diff options
Diffstat (limited to 'atk16_fpga')
| -rw-r--r-- | atk16_fpga/cu.v | 100 | ||||
| -rw-r--r-- | atk16_fpga/cu_tb.gtkw | 18 | ||||
| -rw-r--r-- | atk16_fpga/cu_tb.v | 228 | ||||
| -rw-r--r-- | atk16_fpga/ice40hx8k-evb.pcf | 6 | ||||
| -rw-r--r-- | atk16_fpga/top.v | 8 |
5 files changed, 198 insertions, 162 deletions
diff --git a/atk16_fpga/cu.v b/atk16_fpga/cu.v index 1f8ea60..d6fb7df 100644 --- a/atk16_fpga/cu.v +++ b/atk16_fpga/cu.v @@ -1,9 +1,10 @@ `default_nettype none `define PH_RESET 3'd0 -`define PH_FETCH 3'd1 -`define PH_DECODE 3'd2 -`define PH_EXECUTE 3'd3 +`define PH_CHECK 3'd1 +`define PH_FETCH 3'd2 +`define PH_DECODE 3'd3 +`define PH_EXECUTE 3'd4 `define FL_CARRY 2'd3 `define FL_OVERFLOW 2'd2 @@ -82,7 +83,8 @@ module cu( // interrupts reg [15:0] int_pc; - reg [3:0] int_line_regs; + reg [3:0] last_int_lines; + reg [3:0] int_tmp; // used as temporary variable reg int_en = 1; reg sram_waiting = 0; @@ -112,59 +114,53 @@ module cu( assign rg = regbank[6]; assign rh = regbank[7]; - always @(posedge int_lines[0]) int_line_regs[0] <= int_lines[0]; - always @(posedge int_lines[1]) int_line_regs[1] <= int_lines[1]; - always @(posedge int_lines[2]) int_line_regs[2] <= int_lines[2]; - always @(posedge int_lines[3]) int_line_regs[3] <= int_lines[3]; - integer i; always @(posedge clk or posedge rst) begin + last_int_lines <= int_lines; // Handle reset button if (rst) begin phase <= `PH_RESET; halted <= 0; + // this line is replicated in PH_RESET handling to appease + // yosys async reset analysis + last_int_lines <= 4'b0000; end else if (halted) begin // Do nothing end - else if (int_en && int_line_regs != 4'b00) begin - int_en <= 0; - int_pc <= pc; - casez (int_line_regs) - 4'bzzz1: begin - pc <= 16'h10; - int_line_regs[0] <= 0; - end - 4'bzz1z: begin - pc <= 16'h11; - int_line_regs[1] <= 0; - end - 4'bz1zz: begin - pc <= 16'h12; - int_line_regs[2] <= 0; - end - 4'b1zzz: begin - pc <= 16'h13; - int_line_regs[3] <= 0; - end - endcase - end - else if (phase == `PH_RESET) begin - phase <= `PH_FETCH; + phase <= `PH_CHECK; - pc <= 16'd0; - sram_rd_n <= 1; - sram_wr_n <= 1; + pc <= 16'd0; + sram_rd_n <= 1; + sram_wr_n <= 1; + last_int_lines <= 4'b0000; for (i = 0; i < 8; i = i + 1) begin regbank[i] <= 16'd0; end end + // Check stage (check interrupts) + // Compute rising edges of interrupt lines (0 -> 1) (blocking) + else if (phase == `PH_CHECK) begin + phase <= `PH_FETCH; + + if (int_en && (~last_int_lines & int_lines) != 4'b00) begin + int_en <= 0; + int_pc <= pc; + casez (~last_int_lines & int_lines) + 4'bzzz1: pc <= 16'h10; + 4'bzz1z: pc <= 16'h11; + 4'bz1zz: pc <= 16'h12; + 4'b1zzz: pc <= 16'h13; + endcase + end + end + // Fetch stage else if (phase == `PH_FETCH) begin if (~sram_waiting) begin @@ -290,11 +286,11 @@ module cu( // ir[9:6] = address reg if (ir[11] == 1 && ir[10] == 1) begin // addressing mode: absolute, direct pc <= regbank[ir[9:6]]; - phase <= `PH_FETCH; + phase <= `PH_CHECK; end else if (ir[11] == 0 && ir[10] == 1) begin // addressing mode: pc relative, direct pc <= pc + regbank[ir[9:6]] - 1; - phase <= `PH_FETCH; + phase <= `PH_CHECK; end else if (ir[11] == 1 && ir[10] == 0) begin // addressing mode: absolute, indirect if (~sram_waiting) begin @@ -304,7 +300,7 @@ module cu( end else begin pc <= sram_out; sram_rd_n <= 1; - phase <= `PH_FETCH; + phase <= `PH_CHECK; sram_waiting <= 0; end end @@ -316,7 +312,7 @@ module cu( end else begin pc <= sram_out; sram_rd_n <= 1; - phase <= `PH_FETCH; + phase <= `PH_CHECK; sram_waiting <= 0; end end @@ -327,11 +323,11 @@ module cu( // ir[9:0] = immediate if (ir[11] == 1 && ir[10] == 1) begin // addressing mode: absolute, direct pc <= {6'd0, ir[9:0]}; - phase <= `PH_FETCH; + phase <= `PH_CHECK; end else if (ir[11] == 0 && ir[10] == 1) begin // addressing mode: pc relative, direct pc <= pc + {{6{ir[9]}}, ir[9:0]} - 1; - phase <= `PH_FETCH; + phase <= `PH_CHECK; end else if (ir[11] == 1 && ir[10] == 0) begin // addressing mode: absolute, indirect if (~sram_waiting) begin @@ -341,7 +337,7 @@ module cu( end else begin pc <= sram_out; sram_rd_n <= 1; - phase <= `PH_FETCH; + phase <= `PH_CHECK; sram_waiting <= 0; end end @@ -353,7 +349,7 @@ module cu( end else begin pc <= sram_out; sram_rd_n <= 1; - phase <= `PH_FETCH; + phase <= `PH_CHECK; sram_waiting <= 0; end end @@ -437,12 +433,12 @@ module cu( `OP_LPC: begin // ir[11:9] = target reg regbank[ir[11:9]] <= pc; - phase <= `PH_FETCH; + phase <= `PH_CHECK; end `OP_RTI: begin pc <= int_pc; int_en <= 1; - phase <= `PH_FETCH; + phase <= `PH_CHECK; end `OP_HLT: begin halted <= 1; @@ -460,7 +456,7 @@ module cu( case (ir[15:12]) `OP_ALR, `OP_ALI: begin regbank[ir[11:9]] <= alu_result; // write result - phase <= `PH_FETCH; + phase <= `PH_CHECK; end `OP_LDR: begin if (~sram_waiting) begin @@ -470,7 +466,7 @@ module cu( end else begin regbank[ir[11:9]] <= sram_out; // dereference address sram_rd_n <= 1; - phase <= `PH_FETCH; + phase <= `PH_CHECK; sram_waiting <= 0; end end @@ -482,7 +478,7 @@ module cu( sram_waiting <= 1; end else begin sram_wr_n <= 1; - phase <= `PH_FETCH; + phase <= `PH_CHECK; sram_waiting <= 0; end end @@ -494,7 +490,7 @@ module cu( // decoded_tmp = immediate value that takes absolute/relative to account if (ir[0] == 1) begin // direct regbank[ir[11:9]] <= decoded_tmp; - phase <= `PH_FETCH; + phase <= `PH_CHECK; end else if (ir[0] == 0) begin // indirect if (~sram_waiting) begin @@ -504,7 +500,7 @@ module cu( end else begin regbank[ir[11:9]] <= sram_out; sram_rd_n <= 1; - phase <= `PH_FETCH; + phase <= `PH_CHECK; sram_waiting <= 0; end end @@ -515,7 +511,7 @@ module cu( if ((1 << ir[9:8]) & alu_flags != 4'd0) begin pc <= decoded_tmp; end - phase <= `PH_FETCH; + phase <= `PH_CHECK; end default: begin `ifdef __SYNTHESIS__ diff --git a/atk16_fpga/cu_tb.gtkw b/atk16_fpga/cu_tb.gtkw index b297fcc..57ec3d8 100644 --- a/atk16_fpga/cu_tb.gtkw +++ b/atk16_fpga/cu_tb.gtkw @@ -1,15 +1,15 @@ [*] [*] GTKWave Analyzer v3.4.0 (w)1999-2022 BSI -[*] Thu Dec 26 10:23:44 2024 +[*] Tue Dec 31 07:36:06 2024 [*] [dumpfile] "/Users/jantuomi/Projects/Personal/ATK16/atk16_fpga/cu_tb.vcd" -[dumpfile_mtime] "Thu Dec 26 10:23:28 2024" -[dumpfile_size] 3558 +[dumpfile_mtime] "Tue Dec 31 07:35:29 2024" +[dumpfile_size] 38114 [savefile] "/Users/jantuomi/Projects/Personal/ATK16/atk16_fpga/cu_tb.gtkw" [timestart] 0 [size] 1728 1051 [pos] -1 -1 -*-18.634130 214600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +*-18.634130 1225000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [markername] AA [markername] BB [markername] CC @@ -42,10 +42,12 @@ [signals_width] 325 [sst_expanded] 1 [sst_vpaned_height] 317 +@25 +cu_tb.test_num[31:0] @28 cu_tb.dut.clk cu_tb.dut.rst -@25 +@24 cu_tb.dut.phase[2:0] @22 cu_tb.dut.pc[15:0] @@ -67,11 +69,5 @@ cu_tb.dut.re[15:0] cu_tb.dut.rf[15:0] cu_tb.dut.rg[15:0] cu_tb.dut.rh[15:0] -cu_tb.dut.bram_addr[15:0] -cu_tb.dut.bram_data_in[15:0] -cu_tb.dut.bram_data_out[15:0] -@28 -cu_tb.dut.bram_rd -cu_tb.dut.bram_wr [pattern_trace] 1 [pattern_trace] 0 diff --git a/atk16_fpga/cu_tb.v b/atk16_fpga/cu_tb.v index 8c8ec10..d472ac3 100644 --- a/atk16_fpga/cu_tb.v +++ b/atk16_fpga/cu_tb.v @@ -40,7 +40,8 @@ module cu_tb(); always #5 clk = ~clk; // 100 MHz clock reg failed; - reg [15:0] expected; + reg [15:0] expected, expected2; + reg [31:0] test_num = 0; initial begin failed = 0; $dumpfile(`DUMPSTR(`VCD_OUTPUT)); @@ -62,12 +63,12 @@ module cu_tb(); expected = 16'd30; #200 if (dut.regbank[2] == expected) begin - $display("\033[0;32m[PASS]\033[0m ALR ok"); + $display("\033[0;32m[PASS]\033[0m [%0d] ALR ok", test_num); end else begin - $display("\033[0;31m[FAIL]\033[0m ALR not working, target reg contains %04h, expected %04h", dut.regbank[2], expected); + $display("\033[0;31m[FAIL]\033[0m [%0d] ALR not working, target reg contains %04h, expected %04h", test_num, dut.regbank[2], expected); failed = 1; end - rst = 1; #10 rst = 0; #10 + rst = 1; #10 rst = 0; #10 test_num++; // test ALI dut.regbank[0] = 16'd10; @@ -75,12 +76,12 @@ module cu_tb(); expected = 16'd17; #200 if (dut.regbank[2] == expected) begin - $display("\033[0;32m[PASS]\033[0m ALI ok"); + $display("\033[0;32m[PASS]\033[0m [%0d] ALI ok", test_num); end else begin - $display("\033[0;31m[FAIL]\033[0m ALI not working, target reg contains %04h, expected %04h", dut.regbank[2], expected); + $display("\033[0;31m[FAIL]\033[0m [%0d] ALI not working, target reg contains %04h, expected %04h", test_num, dut.regbank[2], expected); failed = 1; end - rst = 1; #10 rst = 0; #10 + rst = 1; #10 rst = 0; #10 test_num++; // test LDR, absolute addressing sram_inst.mem[16'd100] = 16'hffff; @@ -89,12 +90,12 @@ module cu_tb(); expected = 16'hffff; #200 if (dut.regbank[0] == expected) begin - $display("\033[0;32m[PASS]\033[0m LDR direct absolute ok"); + $display("\033[0;32m[PASS]\033[0m [%0d] LDR direct absolute ok", test_num); end else begin - $display("\033[0;31m[FAIL]\033[0m LDR direct absolute not working, target reg contains %04h, expected %04h", dut.regbank[0], expected); + $display("\033[0;31m[FAIL]\033[0m [%0d] LDR direct absolute not working, target reg contains %04h, expected %04h", test_num, dut.regbank[0], expected); failed = 1; end - rst = 1; #10 rst = 0; #10 + rst = 1; #10 rst = 0; #10 test_num++; // test LDR, relative addressing sram_inst.mem[16'd10] = 16'hffff; @@ -103,12 +104,12 @@ module cu_tb(); expected = 16'hffff; #200 if (dut.regbank[0] == expected) begin - $display("\033[0;32m[PASS]\033[0m LDR direct relative ok"); + $display("\033[0;32m[PASS]\033[0m [%0d] LDR direct relative ok", test_num); end else begin - $display("\033[0;31m[FAIL]\033[0m LDR direct relative not working, target reg contains %04h, expected %04h", dut.regbank[0], expected); + $display("\033[0;31m[FAIL]\033[0m [%0d] LDR direct relative not working, target reg contains %04h, expected %04h", test_num, dut.regbank[0], expected); failed = 1; end - rst = 1; #10 rst = 0; #10 + rst = 1; #10 rst = 0; #10 test_num++; // test LDR, absolute addressing, indirect sram_inst.mem[16'd100] = 16'd200; @@ -118,12 +119,12 @@ module cu_tb(); expected = 16'hffff; #200 if (dut.regbank[0] == expected) begin - $display("\033[0;32m[PASS]\033[0m LDR indirect absolute ok"); + $display("\033[0;32m[PASS]\033[0m [%0d] LDR indirect absolute ok", test_num); end else begin - $display("\033[0;31m[FAIL]\033[0m LDR indirect absolute not working, target reg contains %04h, expected %04h", dut.regbank[0], expected); + $display("\033[0;31m[FAIL]\033[0m [%0d] LDR indirect absolute not working, target reg contains %04h, expected %04h", test_num, dut.regbank[0], expected); failed = 1; end - rst = 1; #10 rst = 0; #10 + rst = 1; #10 rst = 0; #10 test_num++; // test LDR, relative addressing, indirect sram_inst.mem[16'd10] = 16'd20; @@ -133,12 +134,12 @@ module cu_tb(); expected = 16'hffff; #200 if (dut.regbank[0] == expected) begin - $display("\033[0;32m[PASS]\033[0m LDR indirect relative ok"); + $display("\033[0;32m[PASS]\033[0m [%0d] LDR indirect relative ok", test_num); end else begin - $display("\033[0;31m[FAIL]\033[0m LDR indirect relative not working, target reg contains %04h, expected %04h", dut.regbank[0], expected); + $display("\033[0;31m[FAIL]\033[0m [%0d] LDR indirect relative not working, target reg contains %04h, expected %04h", test_num, dut.regbank[0], expected); failed = 1; end - rst = 1; #10 rst = 0; #10 + rst = 1; #10 rst = 0; #10 test_num++; // test STR, absolute addressing, direct dut.regbank[0] = 16'hfafa; @@ -147,12 +148,12 @@ module cu_tb(); expected = 16'hfafa; #200 if (sram_inst.mem[16'd100] == expected) begin - $display("\033[0;32m[PASS]\033[0m STR direct absolute ok"); + $display("\033[0;32m[PASS]\033[0m [%0d] STR direct absolute ok", test_num); end else begin - $display("\033[0;31m[FAIL]\033[0m STR direct absolute not working, memory location contains %04h, expected %04h", sram_inst.mem[16'd100], expected); + $display("\033[0;31m[FAIL]\033[0m [%0d] STR direct absolute not working, memory location contains %04h, expected %04h", test_num, sram_inst.mem[16'd100], expected); failed = 1; end - rst = 1; #10 rst = 0; #10 + rst = 1; #10 rst = 0; #10 test_num++; // test STR, relative addressing, direct dut.regbank[0] = 16'hafaf; @@ -161,12 +162,12 @@ module cu_tb(); expected = 16'hafaf; #200 if (sram_inst.mem[16'd10] == expected) begin - $display("\033[0;32m[PASS]\033[0m STR direct relative ok"); + $display("\033[0;32m[PASS]\033[0m [%0d] STR direct relative ok", test_num); end else begin - $display("\033[0;31m[FAIL]\033[0m STR direct relative not working, memory location contains %04h, expected %04h", sram_inst.mem[16'd10], expected); + $display("\033[0;31m[FAIL]\033[0m [%0d] STR direct relative not working, memory location contains %04h, expected %04h", test_num, sram_inst.mem[16'd10], expected); failed = 1; end - rst = 1; #10 rst = 0; #10 + rst = 1; #10 rst = 0; #10 test_num++; // test STR, absolute addressing, indirect dut.regbank[0] = 16'hfafa; @@ -176,12 +177,12 @@ module cu_tb(); expected = 16'hfafa; #200 if (sram_inst.mem[16'd200] == expected) begin - $display("\033[0;32m[PASS]\033[0m STR indirect absolute ok"); + $display("\033[0;32m[PASS]\033[0m [%0d] STR indirect absolute ok", test_num); end else begin - $display("\033[0;31m[FAIL]\033[0m STR indirect absolute not working, memory location contains %04h, expected %04h", sram_inst.mem[16'd200], expected); + $display("\033[0;31m[FAIL]\033[0m [%0d] STR indirect absolute not working, memory location contains %04h, expected %04h", test_num, sram_inst.mem[16'd200], expected); failed = 1; end - rst = 1; #10 rst = 0; #10 + rst = 1; #10 rst = 0; #10 test_num++; // test STR, relative addressing, indirect dut.regbank[0] = 16'hafaf; @@ -192,24 +193,24 @@ module cu_tb(); expected = 16'hafaf; #200 if (sram_inst.mem[16'd20] == expected) begin - $display("\033[0;32m[PASS]\033[0m STR indirect relative ok"); + $display("\033[0;32m[PASS]\033[0m [%0d] STR indirect relative ok", test_num); end else begin - $display("\033[0;31m[FAIL]\033[0m STR indirect relative not working, memory location contains %04h, expected %04h", sram_inst.mem[16'd20], expected); + $display("\033[0;31m[FAIL]\033[0m [%0d] STR indirect relative not working, memory location contains %04h, expected %04h", test_num, sram_inst.mem[16'd20], expected); failed = 1; end - rst = 1; #10 rst = 0; #10 + rst = 1; #10 rst = 0; #10 test_num++; // test LDI, absolute addressing, direct sram_inst.mem[16'd0] = { 4'b0100, 3'd0, 7'd123, 1'd1, 1'd1 }; // LDI RA, 1, absolute, direct expected = 16'd123; #200 if (dut.regbank[0] == expected) begin - $display("\033[0;32m[PASS]\033[0m LDI direct absolute ok"); + $display("\033[0;32m[PASS]\033[0m [%0d] LDI direct absolute ok", test_num); end else begin - $display("\033[0;31m[FAIL]\033[0m LDI direct absolute not working, target reg contains %04h, expected %04h", dut.regbank[0], expected); + $display("\033[0;31m[FAIL]\033[0m [%0d] LDI direct absolute not working, target reg contains %04h, expected %04h", test_num, dut.regbank[0], expected); failed = 1; end - rst = 1; #10 rst = 0; #10 + rst = 1; #10 rst = 0; #10 test_num++; // test LDI, relative addressing, direct sram_inst.mem[16'd150] = { 4'b0100, 3'd0, -7'd20, 1'd0, 1'd1 }; // LDI RA, 1, relative, direct @@ -217,12 +218,12 @@ module cu_tb(); expected = 16'd130; #200 if (dut.regbank[0] == expected) begin - $display("\033[0;32m[PASS]\033[0m LDI direct relative ok"); + $display("\033[0;32m[PASS]\033[0m [%0d] LDI direct relative ok", test_num); end else begin - $display("\033[0;31m[FAIL]\033[0m LDI direct relative not working, target reg contains %04h, expected %04h", dut.regbank[0], expected); + $display("\033[0;31m[FAIL]\033[0m [%0d] LDI direct relative not working, target reg contains %04h, expected %04h", test_num, dut.regbank[0], expected); failed = 1; end - rst = 1; #10 rst = 0; #10 + rst = 1; #10 rst = 0; #10 test_num++; // test LDI, absolute addressing, indirect sram_inst.mem[16'd0] = { 4'b0100, 3'd0, 7'd50, 1'd1, 1'd0 }; // LDI RA, 1, absolute, indirect @@ -230,12 +231,12 @@ module cu_tb(); expected = 16'd123; #200 if (dut.regbank[0] == expected) begin - $display("\033[0;32m[PASS]\033[0m LDI indirect absolute ok"); + $display("\033[0;32m[PASS]\033[0m [%0d] LDI indirect absolute ok", test_num); end else begin - $display("\033[0;31m[FAIL]\033[0m LDI indirect absolute not working, target reg contains %04h, expected %04h", dut.regbank[0], expected); + $display("\033[0;31m[FAIL]\033[0m [%0d] LDI indirect absolute not working, target reg contains %04h, expected %04h", test_num, dut.regbank[0], expected); failed = 1; end - rst = 1; #10 rst = 0; #10 + rst = 1; #10 rst = 0; #10 test_num++; // test LDI, relative addressing, indirect sram_inst.mem[16'd150] = { 4'b0100, 3'd0, -7'd20, 1'd0, 1'd0 }; // LDI RA, 1, relative, indirect @@ -244,12 +245,12 @@ module cu_tb(); expected = 16'd123; #200 if (dut.regbank[0] == expected) begin - $display("\033[0;32m[PASS]\033[0m LDI indirect relative ok"); + $display("\033[0;32m[PASS]\033[0m [%0d] LDI indirect relative ok", test_num); end else begin - $display("\033[0;31m[FAIL]\033[0m LDI indirect relative not working, target reg contains %04h, expected %04h", dut.regbank[0], expected); + $display("\033[0;31m[FAIL]\033[0m [%0d] LDI indirect relative not working, target reg contains %04h, expected %04h", test_num, dut.regbank[0], expected); failed = 1; end - rst = 1; #10 rst = 0; #10 + rst = 1; #10 rst = 0; #10 test_num++; // test JPR, absolute addressing, direct dut.regbank[0] = 16'd100; @@ -258,12 +259,12 @@ module cu_tb(); expected = 16'd101; // PC ends up at &HLT + 1 #200 if (dut.pc == expected) begin - $display("\033[0;32m[PASS]\033[0m JPR direct absolute ok"); + $display("\033[0;32m[PASS]\033[0m [%0d] JPR direct absolute ok", test_num); end else begin - $display("\033[0;31m[FAIL]\033[0m JPR direct absolute not working, PC contains %04h, expected: %04h", dut.pc, expected); + $display("\033[0;31m[FAIL]\033[0m [%0d] JPR direct absolute not working, PC contains %04h, expected: %04h", test_num, dut.pc, expected); failed = 1; end - rst = 1; #10 rst = 0; #10 + rst = 1; #10 rst = 0; #10 test_num++; // test JPR, relative addressing, direct dut.regbank[0] = 16'd50; @@ -272,12 +273,12 @@ module cu_tb(); expected = 16'd51; // PC ends up at &HLT + 1 #200 if (dut.pc == expected) begin - $display("\033[0;32m[PASS]\033[0m JPR direct relative ok"); + $display("\033[0;32m[PASS]\033[0m [%0d] JPR direct relative ok", test_num); end else begin - $display("\033[0;31m[FAIL]\033[0m JPR direct relative not working, PC contains %04h, expected: %04h", dut.pc, expected); + $display("\033[0;31m[FAIL]\033[0m [%0d] JPR direct relative not working, PC contains %04h, expected: %04h", test_num, dut.pc, expected); failed = 1; end - rst = 1; #10 rst = 0; #10 + rst = 1; #10 rst = 0; #10 test_num++; // test JPR, absolute addressing, indirect dut.regbank[0] = 16'd100; @@ -287,12 +288,12 @@ module cu_tb(); expected = 16'd201; // PC ends up at &HLT + 1 #200 if (dut.pc == expected) begin - $display("\033[0;32m[PASS]\033[0m JPR indirect absolute ok"); + $display("\033[0;32m[PASS]\033[0m [%0d] JPR indirect absolute ok", test_num); end else begin - $display("\033[0;31m[FAIL]\033[0m JPR indirect absolute not working, PC contains %04h, expected: %04h", dut.pc, expected); + $display("\033[0;31m[FAIL]\033[0m [%0d] JPR indirect absolute not working, PC contains %04h, expected: %04h", test_num, dut.pc, expected); failed = 1; end - rst = 1; #10 rst = 0; #10 + rst = 1; #10 rst = 0; #10 test_num++; // test JPR, relative addressing, indirect dut.regbank[0] = 16'd50; @@ -303,12 +304,12 @@ module cu_tb(); expected = 16'd101; // PC ends up at &HLT + 1 #200 if (dut.pc == expected) begin - $display("\033[0;32m[PASS]\033[0m JPR indirect relative ok"); + $display("\033[0;32m[PASS]\033[0m [%0d] JPR indirect relative ok", test_num); end else begin - $display("\033[0;31m[FAIL]\033[0m JPR indirect relative not working, PC contains %04h, expected: %04h", dut.pc, expected); + $display("\033[0;31m[FAIL]\033[0m [%0d] JPR indirect relative not working, PC contains %04h, expected: %04h", test_num, dut.pc, expected); failed = 1; end - rst = 1; #10 rst = 0; #10 + rst = 1; #10 rst = 0; #10 test_num++; // test JPI, absolute addressing, direct sram_inst.mem[16'd0] = { 4'b0110, 1'd1, 1'd1, 10'd123 }; // JPI 123, absolute, direct @@ -316,12 +317,12 @@ module cu_tb(); expected = 16'd124; // PC ends up at &HLT + 1 #200 if (dut.pc == expected) begin - $display("\033[0;32m[PASS]\033[0m JPI direct absolute ok"); + $display("\033[0;32m[PASS]\033[0m [%0d] JPI direct absolute ok", test_num); end else begin - $display("\033[0;31m[FAIL]\033[0m JPI direct absolute not working, PC contains %04h, expected: %04h", dut.pc, expected); + $display("\033[0;31m[FAIL]\033[0m [%0d] JPI direct absolute not working, PC contains %04h, expected: %04h", test_num, dut.pc, expected); failed = 1; end - rst = 1; #10 rst = 0; #10 + rst = 1; #10 rst = 0; #10 test_num++; // test JPI, relative addressing, direct sram_inst.mem[16'd30] = { 4'b0110, 1'd0, 1'd1, -10'd20 }; // JPI -20, relative, direct @@ -330,12 +331,12 @@ module cu_tb(); expected = 16'd11; // PC ends up at &HLT + 1 #200 if (dut.pc == expected) begin - $display("\033[0;32m[PASS]\033[0m JPI direct relative ok"); + $display("\033[0;32m[PASS]\033[0m [%0d] JPI direct relative ok", test_num); end else begin - $display("\033[0;31m[FAIL]\033[0m JPI direct relative not working, PC contains %04h, expected: %04h", dut.pc, expected); + $display("\033[0;31m[FAIL]\033[0m [%0d] JPI direct relative not working, PC contains %04h, expected: %04h", test_num, dut.pc, expected); failed = 1; end - rst = 1; #10 rst = 0; #10 + rst = 1; #10 rst = 0; #10 test_num++; // test JPI, absolute addressing, indirect sram_inst.mem[16'd10] = { 4'b0110, 1'd1, 1'd0, 10'd50 }; // JPI 50, absolute, indirect @@ -345,12 +346,12 @@ module cu_tb(); expected = 16'd124; // PC ends up at &HLT + 1 #200 if (dut.pc == expected) begin - $display("\033[0;32m[PASS]\033[0m JPI indirect absolute ok"); + $display("\033[0;32m[PASS]\033[0m [%0d] JPI indirect absolute ok", test_num); end else begin - $display("\033[0;31m[FAIL]\033[0m JPI indirect absolute not working, PC contains %04h, expected: %04h", dut.pc, expected); + $display("\033[0;31m[FAIL]\033[0m [%0d] JPI indirect absolute not working, PC contains %04h, expected: %04h", test_num, dut.pc, expected); failed = 1; end - rst = 1; #10 rst = 0; #10 + rst = 1; #10 rst = 0; #10 test_num++; // test JPI, relative addressing, indirect sram_inst.mem[16'd30] = { 4'b0110, 1'd0, 1'd0, -10'd20 }; // JPI -20, relative, indirect @@ -360,12 +361,12 @@ module cu_tb(); expected = 16'd51; // PC ends up at &HLT + 1 #200 if (dut.pc == expected) begin - $display("\033[0;32m[PASS]\033[0m JPI indirect relative ok"); + $display("\033[0;32m[PASS]\033[0m [%0d] JPI indirect relative ok", test_num); end else begin - $display("\033[0;31m[FAIL]\033[0m JPI indirect relative not working, PC contains %04h, expected: %04h", dut.pc, expected); + $display("\033[0;31m[FAIL]\033[0m [%0d] JPI indirect relative not working, PC contains %04h, expected: %04h", test_num, dut.pc, expected); failed = 1; end - rst = 1; #10 rst = 0; #10 + rst = 1; #10 rst = 0; #10 test_num++; // test BRR, absolute addressing, direct, true branch dut.regbank[0] = 16'd100; @@ -377,12 +378,12 @@ module cu_tb(); expected = 16'd111; // PC ends up at &HLT + 1 #200 if (dut.pc == expected) begin - $display("\033[0;32m[PASS]\033[0m BRR direct absolute true ok"); + $display("\033[0;32m[PASS]\033[0m [%0d] BRR direct absolute true ok", test_num); end else begin - $display("\033[0;31m[FAIL]\033[0m BRR direct absolute true not working, PC contains %04h, expected: %04h", dut.pc, expected); + $display("\033[0;31m[FAIL]\033[0m [%0d] BRR direct absolute true not working, PC contains %04h, expected: %04h", test_num, dut.pc, expected); failed = 1; end - rst = 1; #10 rst = 0; #10 + rst = 1; #10 rst = 0; #10 test_num++; // test BRR, absolute addressing, direct, false branch dut.regbank[0] = 16'd100; @@ -394,12 +395,12 @@ module cu_tb(); expected = 16'd3; // PC ends up at &HLT + 1 #200 if (dut.pc == expected) begin - $display("\033[0;32m[PASS]\033[0m BRR direct absolute false ok"); + $display("\033[0;32m[PASS]\033[0m [%0d] BRR direct absolute false ok", test_num); end else begin - $display("\033[0;31m[FAIL]\033[0m BRR direct absolute false not working, PC contains %04h, expected: %04h", dut.pc, expected); + $display("\033[0;31m[FAIL]\033[0m [%0d] BRR direct absolute false not working, PC contains %04h, expected: %04h", test_num, dut.pc, expected); failed = 1; end - rst = 1; #10 rst = 0; #10 + rst = 1; #10 rst = 0; #10 test_num++; // test BRR, relative addressing, direct dut.regbank[0] = 16'd100; @@ -412,12 +413,12 @@ module cu_tb(); expected = 16'd121; // PC ends up at &HLT + 1 #200 if (dut.pc == expected) begin - $display("\033[0;32m[PASS]\033[0m BRR direct relative ok"); + $display("\033[0;32m[PASS]\033[0m [%0d] BRR direct relative ok", test_num); end else begin - $display("\033[0;31m[FAIL]\033[0m BRR direct relative not working, PC contains %04h, expected: %04h", dut.pc, expected); + $display("\033[0;31m[FAIL]\033[0m [%0d] BRR direct relative not working, PC contains %04h, expected: %04h", test_num, dut.pc, expected); failed = 1; end - rst = 1; #10 rst = 0; #10 + rst = 1; #10 rst = 0; #10 test_num++; // test BRR, absolute addressing, indirect dut.regbank[0] = 16'd100; @@ -430,12 +431,12 @@ module cu_tb(); expected = 16'd201; // PC ends up at &HLT + 1 #200 if (dut.pc == expected) begin - $display("\033[0;32m[PASS]\033[0m BRR indirect absolute ok"); + $display("\033[0;32m[PASS]\033[0m [%0d] BRR indirect absolute ok", test_num); end else begin - $display("\033[0;31m[FAIL]\033[0m BRR indirect absolute not working, PC contains %04h, expected: %04h", dut.pc, expected); + $display("\033[0;31m[FAIL]\033[0m [%0d] BRR indirect absolute not working, PC contains %04h, expected: %04h", test_num, dut.pc, expected); failed = 1; end - rst = 1; #10 rst = 0; #10 + rst = 1; #10 rst = 0; #10 test_num++; // test BRR, relative addressing, indirect dut.regbank[0] = 16'd100; @@ -449,12 +450,12 @@ module cu_tb(); expected = 16'd131; // PC ends up at &HLT + 1 #200 if (dut.pc == expected) begin - $display("\033[0;32m[PASS]\033[0m BRR indirect relative ok"); + $display("\033[0;32m[PASS]\033[0m [%0d] BRR indirect relative ok", test_num); end else begin - $display("\033[0;31m[FAIL]\033[0m BRR indirect relative not working, PC contains %04h, expected: %04h", dut.pc, expected); + $display("\033[0;31m[FAIL]\033[0m [%0d] BRR indirect relative not working, PC contains %04h, expected: %04h", test_num, dut.pc, expected); failed = 1; end - rst = 1; #10 rst = 0; #10 + rst = 1; #10 rst = 0; #10 test_num++; // test BRI, absolute addressing, direct, true branch dut.regbank[0] = 16'd100; @@ -465,12 +466,12 @@ module cu_tb(); expected = 16'd101; // PC ends up at &HLT + 1 #200 if (dut.pc == expected) begin - $display("\033[0;32m[PASS]\033[0m BRI direct absolute true ok"); + $display("\033[0;32m[PASS]\033[0m [%0d] BRI direct absolute true ok", test_num); end else begin - $display("\033[0;31m[FAIL]\033[0m BRI direct absolute true not working, PC contains %04h, expected: %04h", dut.pc, expected); + $display("\033[0;31m[FAIL]\033[0m [%0d] BRI direct absolute true not working, PC contains %04h, expected: %04h", test_num, dut.pc, expected); failed = 1; end - rst = 1; #10 rst = 0; #10 + rst = 1; #10 rst = 0; #10 test_num++; // test BRI, absolute addressing, direct, false branch dut.regbank[0] = 16'd100; @@ -481,12 +482,12 @@ module cu_tb(); expected = 16'd3; // PC ends up at &HLT + 1 #200 if (dut.pc == expected) begin - $display("\033[0;32m[PASS]\033[0m BRI direct absolute false ok"); + $display("\033[0;32m[PASS]\033[0m [%0d] BRI direct absolute false ok", test_num); end else begin - $display("\033[0;31m[FAIL]\033[0m BRI direct absolute false not working, PC contains %04h, expected: %04h", dut.pc, expected); + $display("\033[0;31m[FAIL]\033[0m [%0d] BRI direct absolute false not working, PC contains %04h, expected: %04h", test_num, dut.pc, expected); failed = 1; end - rst = 1; #10 rst = 0; #10 + rst = 1; #10 rst = 0; #10 test_num++; // test BRI, relative addressing, direct dut.regbank[0] = 16'd100; @@ -498,12 +499,12 @@ module cu_tb(); expected = 16'd21; // PC ends up at &HLT + 1 #200 if (dut.pc == expected) begin - $display("\033[0;32m[PASS]\033[0m BRI direct relative ok"); + $display("\033[0;32m[PASS]\033[0m [%0d] BRI direct relative ok", test_num); end else begin - $display("\033[0;31m[FAIL]\033[0m BRI direct relative not working, PC contains %04h, expected: %04h", dut.pc, expected); + $display("\033[0;31m[FAIL]\033[0m [%0d] BRI direct relative not working, PC contains %04h, expected: %04h", test_num, dut.pc, expected); failed = 1; end - rst = 1; #10 rst = 0; #10 + rst = 1; #10 rst = 0; #10 test_num++; // test BRI, absolute addressing, indirect dut.regbank[0] = 16'd100; @@ -515,12 +516,12 @@ module cu_tb(); expected = 16'd201; // PC ends up at &HLT + 1 #200 if (dut.pc == expected) begin - $display("\033[0;32m[PASS]\033[0m BRI indirect absolute ok"); + $display("\033[0;32m[PASS]\033[0m [%0d] BRI indirect absolute ok", test_num); end else begin - $display("\033[0;31m[FAIL]\033[0m BRI indirect absolute not working, PC contains %04h, expected: %04h", dut.pc, expected); + $display("\033[0;31m[FAIL]\033[0m [%0d] BRI indirect absolute not working, PC contains %04h, expected: %04h", test_num, dut.pc, expected); failed = 1; end - rst = 1; #10 rst = 0; #10 + rst = 1; #10 rst = 0; #10 test_num++; // test BRI, relative addressing, indirect dut.regbank[0] = 16'd100; @@ -533,12 +534,45 @@ module cu_tb(); expected = 16'd131; // PC ends up at &HLT + 1 #200 if (dut.pc == expected) begin - $display("\033[0;32m[PASS]\033[0m BRI indirect relative ok"); + $display("\033[0;32m[PASS]\033[0m [%0d] BRI indirect relative ok", test_num); end else begin - $display("\033[0;31m[FAIL]\033[0m BRI indirect relative not working, PC contains %04h, expected: %04h", dut.pc, expected); + $display("\033[0;31m[FAIL]\033[0m [%0d] BRI indirect relative not working, PC contains %04h, expected: %04h", test_num, dut.pc, expected); failed = 1; end - rst = 1; #10 rst = 0; #10 + rst = 1; #10 rst = 0; #10 test_num++; + + // test interrupt handling + sram_inst.mem[16'd0] = { 4'b0001, 3'b0, 3'b0, 3'b0, 3'b0 }; // NOP (add imm zero) + sram_inst.mem[16'h10] = { 4'b1111, 12'd0 }; // HLT + expected = 16'h11; + expected2 = 16'd0; + #5 + int_lines = 4'b1001; // set interrupts + + #200 if (dut.pc == expected && dut.int_pc == expected2) begin + $display("\033[0;32m[PASS]\033[0m [%0d] interrupt jump ok", test_num); + end else begin + $display("\033[0;31m[FAIL]\033[0m [%0d] interrupt jump not working, PC contains %04h (expected: %04h), int_pc contains %04h (expected: %04h)", test_num, dut.pc, expected, dut.int_pc, expected2); + failed = 1; + end + rst = 1; #10 rst = 0; #10 test_num++; + + // test RTI + dut.int_en = 1'b0; + dut.pc = 16'h10; + dut.int_pc = 16'd1; + sram_inst.mem[16'h10] = { 4'b1010, 12'd0 }; // RTI + sram_inst.mem[16'd1] = { 4'b1111, 12'd0 }; // HLT + expected = 16'd2; // PC ends up at &HLT + 1 + expected2 = 1'b1; + + #200 if (dut.pc == expected && dut.int_en == expected2) begin + $display("\033[0;32m[PASS]\033[0m [%0d] interrupt return ok", test_num); + end else begin + $display("\033[0;31m[FAIL]\033[0m [%0d] interrupt return not working, PC contains %04h (expected: %04h), int_en contains %01b (expected: %01b)", test_num, dut.pc, expected, dut.int_en, expected2); + failed = 1; + end + rst = 1; #10 rst = 0; #10 test_num++; #200 if (failed) begin diff --git a/atk16_fpga/ice40hx8k-evb.pcf b/atk16_fpga/ice40hx8k-evb.pcf index 540987f..eb63e74 100644 --- a/atk16_fpga/ice40hx8k-evb.pcf +++ b/atk16_fpga/ice40hx8k-evb.pcf @@ -68,3 +68,9 @@ set_io -nowarn TDI R14 set_io -nowarn TMS R15 set_io -nowarn TCK P14 set_io -nowarn TDO P15 + +# EXT4 connector +set_io -nowarn INT[0] G15 +set_io -nowarn INT[1] G10 +set_io -nowarn INT[2] F16 +set_io -nowarn INT[3] G11 diff --git a/atk16_fpga/top.v b/atk16_fpga/top.v index 12ac94a..975a7f5 100644 --- a/atk16_fpga/top.v +++ b/atk16_fpga/top.v @@ -9,7 +9,9 @@ module top( output SRAM_OE, // inverted output SRAM_WE, // inverted output [17:0] SA, - inout [15:0] SD + inout [15:0] SD, + + input [3:0] INT ); cu cu_inst( .clk(SYSCLK), @@ -20,7 +22,9 @@ module top( .sram_wr_n(SRAM_WE), .sram_addr(SA[15:0]), .sram_in(SD), - .sram_out(SD) + .sram_out(SD), + + .int_lines(INT) ); assign SA[17:16] = 2'b0; |
