diff options
| -rw-r--r-- | atk16_fpga/.gitignore | 6 | ||||
| -rw-r--r-- | atk16_fpga/alu.v | 35 | ||||
| -rw-r--r-- | atk16_fpga/alu_tb.v | 73 | ||||
| -rw-r--r-- | atk16_fpga/apio.ini | 3 | ||||
| -rw-r--r-- | atk16_fpga/ice40hx8k-evb.pcf | 70 | ||||
| -rw-r--r-- | atk16_fpga/top.v | 18 |
6 files changed, 205 insertions, 0 deletions
diff --git a/atk16_fpga/.gitignore b/atk16_fpga/.gitignore new file mode 100644 index 0000000..5b8789e --- /dev/null +++ b/atk16_fpga/.gitignore @@ -0,0 +1,6 @@ +*.dblite +*.out +*.vcd +hardware.bin +hardware.json +hardware.asc diff --git a/atk16_fpga/alu.v b/atk16_fpga/alu.v new file mode 100644 index 0000000..ea78328 --- /dev/null +++ b/atk16_fpga/alu.v @@ -0,0 +1,35 @@ +`default_nettype none + +module alu ( + input wire [2:0] sel, + input wire [15:0] a, + input wire [15:0] b, + output reg [15:0] result, + output reg [3:0] flags // { carry, overflow, negative, zero } +); + always @(*) begin + flags[2] = 0; + flags[3] = 0; + + case (sel) + 3'd0: begin + {flags[3], result} = a + b; // compute carry and result + flags[2] = (a[15] == b[15] && result[15] != a[15]); // compute overflow + end + 3'd1: begin + {flags[3], result} = a - b; // compute carry and result + flags[2] = (a[15] != b[15] && result[15] != a[15]); // compute overflow + end + 3'd2: result = a & b; + 3'd3: result = a | b; + 3'd4: result = a ^ b; + 3'd5: result = a << b; + 3'd6: result = a >> b; + 3'd7: result = $signed(a) >>> b; + endcase + + flags[1] = ($signed(result) < 0); + flags[0] = (result == 0); + end + +endmodule diff --git a/atk16_fpga/alu_tb.v b/atk16_fpga/alu_tb.v new file mode 100644 index 0000000..7569e2d --- /dev/null +++ b/atk16_fpga/alu_tb.v @@ -0,0 +1,73 @@ +`default_nettype none +`define DUMPSTR(x) `"x.vcd`" + +`define PLUS 3'd0 +`define MINUS 3'd1 +`define AND 3'd2 +`define OR 3'd3 +`define XOR 3'd4 +`define SHL 3'd5 +`define SHR 3'd6 +`define SAR 3'd7 + +`define TESTCASE(ma, msel, mb, mexpected, mflags) \ + sel <= `msel; \ + a <= ma; \ + b <= mb; \ + #5 if (result != $unsigned(mexpected) || flags !== mflags) begin \ + failed <= 1; \ + $write("\033[0;31m[FAIL]\033[0m "); \ + $display("%d msel %0d = %0d, flags %04b", a, b, result, flags); \ + $display("_ expected result %0d", $unsigned(mexpected)); \ + $display("_ expected flags %04b", mflags); \ + end \ + else begin \ + $write("\033[0;32m[PASS]\033[0m "); \ + $display("%d msel %0d = %0d, flags %04b", a, b, result, flags); \ + end + +`timescale 10 ns / 100 ps +module alu_tb(); + + reg [2:0] sel; + reg [15:0] a, b; + wire [15:0] result; + wire [3:0] flags; + + alu dut ( + .sel(sel), + .a(a), + .b(b), + .result(result), + .flags(flags) + ); + + reg failed; + initial begin + failed <= 0; + $dumpfile(`DUMPSTR(`VCD_OUTPUT)); + $dumpvars(0, alu_tb); + + `TESTCASE(10, PLUS, 20, 30, 4'b0000) + `TESTCASE(-1, PLUS, 1, 0, 4'b1001) + `TESTCASE(16'h7fff, PLUS, 16'h7fff, 16'hfffe, 4'b0110) + `TESTCASE(30, MINUS, 30, 0, 4'b0001) + `TESTCASE(30, MINUS, 40, -16'd10, 4'b1010) + `TESTCASE(16'h7fff, MINUS, 16'h7fff, 0, 4'b0001) + `TESTCASE(16'h8000, MINUS, 16'h1, 16'h7fff, 4'b0100) + `TESTCASE(3'b110, AND, 3'b101, 3'b100, 4'b0000) + `TESTCASE(3'b110, OR, 3'b101, 3'b111, 4'b0000) + `TESTCASE(3'b110, XOR, 3'b101, 3'b011, 4'b0000) + `TESTCASE(16'b110, SHL, 16'd3, 16'b110000, 4'b0000) + `TESTCASE(16'b1100_0000_0000_0000, SHR, 16'd3, 16'b0001_1000_0000_0000, 4'b0000) + `TESTCASE(16'b1100_0000_0000_0000, SAR, 16'd3, 16'b1111_1000_0000_0000, 4'b0010) + + #5 + if (failed) begin + $display("🛑 \033[0;31mTest suite failed\033[0m"); + $fatal(1); + end else + $display("✅ \033[0;32mTest suite passed\033[0m"); + $finish; + end +endmodule diff --git a/atk16_fpga/apio.ini b/atk16_fpga/apio.ini new file mode 100644 index 0000000..c205966 --- /dev/null +++ b/atk16_fpga/apio.ini @@ -0,0 +1,3 @@ +[env] +board = iCE40-HX8K-EVB +top-module = top diff --git a/atk16_fpga/ice40hx8k-evb.pcf b/atk16_fpga/ice40hx8k-evb.pcf new file mode 100644 index 0000000..540987f --- /dev/null +++ b/atk16_fpga/ice40hx8k-evb.pcf @@ -0,0 +1,70 @@ +# Whenever possible, pin names have been taken from the official schematic +# <https://github.com/OLIMEX/iCE40HX8K-EVB/blob/master/HARDWARE/REV-B/iCE40HX8K-EVB_Rev_B.pdf> + +# Clock +set_io -nowarn SYSCLK J3 # GBIN6 + +# LEDs +set_io -nowarn LED1 M12 +set_io -nowarn LED2 R16 + +# Buttons +set_io -nowarn BUT1 K11 +set_io -nowarn BUT2 P13 + +# SPI Flash +set_io -nowarn CDONE M10 +set_io -nowarn CRESET N11 +set_io -nowarn SDO P12 +set_io -nowarn SDI P11 +set_io -nowarn SCK R11 +set_io -nowarn SS_B R12 + +# Programming connector +set_io -nowarn RxD L11 +set_io -nowarn TxD T16 + +# SRAM +set_io -nowarn SRAM_CS T6 +set_io -nowarn SRAM_OE L9 +set_io -nowarn SRAM_WE T7 +set_io -nowarn SA[0] N6 +set_io -nowarn SA[1] T1 +set_io -nowarn SA[2] P4 +set_io -nowarn SA[3] R2 +set_io -nowarn SA[4] N5 +set_io -nowarn SA[5] T2 +set_io -nowarn SA[6] P5 +set_io -nowarn SA[7] R3 +set_io -nowarn SA[8] R5 +set_io -nowarn SA[9] T3 +set_io -nowarn SA[10] R4 +set_io -nowarn SA[11] M7 +set_io -nowarn SA[12] N7 +set_io -nowarn SA[13] P6 +set_io -nowarn SA[14] M8 +set_io -nowarn SA[15] T5 +set_io -nowarn SA[16] R6 +set_io -nowarn SA[17] P8 +set_io -nowarn SD[0] T8 +set_io -nowarn SD[1] P7 +set_io -nowarn SD[2] N9 +set_io -nowarn SD[3] T9 +set_io -nowarn SD[4] M9 +set_io -nowarn SD[5] R9 +set_io -nowarn SD[6] K9 +set_io -nowarn SD[7] P9 +set_io -nowarn SD[8] R10 +set_io -nowarn SD[9] L10 +set_io -nowarn SD[10] P10 +set_io -nowarn SD[11] N10 +set_io -nowarn SD[12] T10 +set_io -nowarn SD[13] T11 +set_io -nowarn SD[14] T15 +set_io -nowarn SD[15] T14 + +# JTAG +set_io -nowarn TDI R14 +set_io -nowarn TMS R15 +set_io -nowarn TCK P14 +set_io -nowarn TDO P15 diff --git a/atk16_fpga/top.v b/atk16_fpga/top.v new file mode 100644 index 0000000..c456b31 --- /dev/null +++ b/atk16_fpga/top.v @@ -0,0 +1,18 @@ +module top( + input wire SYSCLK, + output wire LED1 +); + + assign LED1 = SYSCLK; + + wire [15:0] result; + wire [3:0] flags; + alu alu_inst( + .sel(3'd0), + .a(16'd0), + .b(16'd0), + .result(result), + .flags(flags) + ); + +endmodule |
