aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--atk16_fpga/cu.v100
-rw-r--r--atk16_fpga/cu_tb.gtkw18
-rw-r--r--atk16_fpga/cu_tb.v228
-rw-r--r--atk16_fpga/ice40hx8k-evb.pcf6
-rw-r--r--atk16_fpga/top.v8
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;