diff options
| -rw-r--r-- | atk16_fpga/.gitignore | 3 | ||||
| -rw-r--r-- | atk16_fpga/alu_gtkw_translate_sel.txt | 8 | ||||
| -rw-r--r-- | atk16_fpga/alu_tb.gtkw | 54 | ||||
| -rw-r--r-- | atk16_fpga/alu_tb.v | 26 | ||||
| -rw-r--r-- | atk16_fpga/bram.v | 37 | ||||
| -rw-r--r-- | atk16_fpga/cu.v | 201 | ||||
| -rw-r--r-- | atk16_fpga/cu_tb.gtkw | 77 | ||||
| -rw-r--r-- | atk16_fpga/cu_tb.v | 77 | ||||
| -rw-r--r-- | atk16_fpga/mem_fsm.v | 67 | ||||
| -rw-r--r-- | atk16_fpga/mem_fsm_tb.gtkw | 32 | ||||
| -rw-r--r-- | atk16_fpga/mem_fsm_tb.v | 82 | ||||
| -rw-r--r-- | atk16_fpga/top.v | 18 |
12 files changed, 659 insertions, 23 deletions
diff --git a/atk16_fpga/.gitignore b/atk16_fpga/.gitignore index 5b8789e..c09389c 100644 --- a/atk16_fpga/.gitignore +++ b/atk16_fpga/.gitignore @@ -1,6 +1,9 @@ *.dblite *.out *.vcd +*.rpt +*.svg +*.dot hardware.bin hardware.json hardware.asc diff --git a/atk16_fpga/alu_gtkw_translate_sel.txt b/atk16_fpga/alu_gtkw_translate_sel.txt new file mode 100644 index 0000000..ac71a28 --- /dev/null +++ b/atk16_fpga/alu_gtkw_translate_sel.txt @@ -0,0 +1,8 @@ +0 ADD +1 MINUS +2 AND +3 OR +4 XOR +5 SHL +6 SHR +7 SAR diff --git a/atk16_fpga/alu_tb.gtkw b/atk16_fpga/alu_tb.gtkw new file mode 100644 index 0000000..0ef8322 --- /dev/null +++ b/atk16_fpga/alu_tb.gtkw @@ -0,0 +1,54 @@ +[*] +[*] GTKWave Analyzer v3.4.0 (w)1999-2022 BSI +[*] Tue Dec 24 12:08:19 2024 +[*] +[dumpfile] "/Users/jantuomi/Projects/Personal/ATK16/atk16_fpga/alu_tb.vcd" +[dumpfile_mtime] "Tue Dec 24 11:56:07 2024" +[dumpfile_size] 1623 +[savefile] "/Users/jantuomi/Projects/Personal/ATK16/atk16_fpga/alu_tb.gtkw" +[timestart] 0 +[size] 1280 600 +[pos] -1 -1 +*-17.259954 120300 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 +[markername] DD +[markername] EE +[markername] FF +[markername] GG +[markername] HH +[markername] II +[markername] JJ +[markername] KK +[markername] LL +[markername] MM +[markername] NN +[markername] OO +[markername] PP +[markername] QQ +[markername] RR +[markername] SS +[markername] TT +[markername] UU +[markername] VV +[markername] WW +[markername] XX +[markername] YY +[markername] ZZ +[treeopen] alu_tb. +[sst_width] 240 +[signals_width] 170 +[sst_expanded] 1 +[sst_vpaned_height] 159 +@2025 +^1 /Users/jantuomi/Projects/Personal/ATK16/atk16_fpga/alu_gtkw_translate_sel.txt +alu_tb.dut.sel[2:0] +@420 +alu_tb.dut.a[15:0] +alu_tb.dut.b[15:0] +alu_tb.dut.result[15:0] +@28 +alu_tb.dut.flags[3:0] +[pattern_trace] 1 +[pattern_trace] 0 diff --git a/atk16_fpga/alu_tb.v b/atk16_fpga/alu_tb.v index 7569e2d..559e23b 100644 --- a/atk16_fpga/alu_tb.v +++ b/atk16_fpga/alu_tb.v @@ -11,11 +11,11 @@ `define SAR 3'd7 `define TESTCASE(ma, msel, mb, mexpected, mflags) \ - sel <= `msel; \ - a <= ma; \ - b <= mb; \ + sel = `msel; \ + a = ma; \ + b = mb; \ #5 if (result != $unsigned(mexpected) || flags !== mflags) begin \ - failed <= 1; \ + 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)); \ @@ -44,20 +44,20 @@ module alu_tb(); reg failed; initial begin - failed <= 0; + 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'd10, PLUS, 16'd20, 16'd30, 4'b0000) + `TESTCASE(-16'd1, PLUS, 16'd1, 16'd0, 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'd30, MINUS, 16'd30, 16'd0, 4'b0001) + `TESTCASE(16'd30, MINUS, 16'd40, -16'd10, 4'b1010) + `TESTCASE(16'h7fff, MINUS, 16'h7fff, 16'd0, 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, AND, 16'b101, 16'b100, 4'b0000) + `TESTCASE(16'b110, OR, 16'b101, 16'b111, 4'b0000) + `TESTCASE(16'b110, XOR, 16'b101, 16'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) diff --git a/atk16_fpga/bram.v b/atk16_fpga/bram.v new file mode 100644 index 0000000..c814c67 --- /dev/null +++ b/atk16_fpga/bram.v @@ -0,0 +1,37 @@ +`default_nettype none + +/* + * Copyright 2020 Brian O'Dell + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +module bram ( + input clk, + input [15:0] addr, + input cs_n, + input wr_n, + input rd_n, + input [15:0] bram_data_in, + output reg [15:0] bram_data_out +); + + reg [15:0] mem [16'hEFFF:0]; + + always @(posedge clk) + if (cs_n == 1'b0) begin + if (wr_n == 1'b0) mem[addr] <= bram_data_in; + if (rd_n == 1'b0) bram_data_out <= mem[addr]; + end + endmodule diff --git a/atk16_fpga/cu.v b/atk16_fpga/cu.v new file mode 100644 index 0000000..915ce8e --- /dev/null +++ b/atk16_fpga/cu.v @@ -0,0 +1,201 @@ +`default_nettype none + +`define PH_RESET 3'd0 +`define PH_FETCH 3'd1 +`define PH_DECODE 3'd2 +`define PH_EXECUTE 3'd3 + +`define FL_CARRY 2'd3 +`define FL_OVERFLOW 2'd2 +`define FL_NEGATIVE 2'd1 +`define FL_ZERO 2'd0 + +// Legend: +// T = target register select +// L = left operand register select +// R = right operand register select +// I = immediate operand +// S = ALU operation select +// A = absolute (1) / relative (0) addressing +// D = direct (1) / indirect (0) load +// M = immediate mode (1) / register mode (0) + +// ALR (arithmetic-logic, register) +// 0000 TTTL LLRR RSSS +`define OP_ALR 4'b0000 +// ALI (arithmetic-logic, immediate) +// 0001 TTTL LLII ISSS +`define OP_ALI 4'b0001 +// LDR (load by register) +// 0010 TTTR RRXX XXAD +`define OP_LDR 4'b0010 +// STR (store to memory) +// 0011 XXXL LLRR RMAD +`define OP_STR 4'b0011 +// LDI (load by immediate) +// 0100 TTTD IIII IIII +`define OP_LDI 4'b0100 + +module cu( + input wire clk, + input wire rst +); + reg [2:0] alu_sel; + reg [15:0] alu_a; + reg [15:0] alu_b; + wire [15:0] alu_result; + wire [3:0] alu_flags; + reg [15:0] regbank [0:7]; + reg [15:0] decoded_tmp; + reg [2:0] phase = `PH_RESET; + reg [15:0] pc; + reg [15:0] ir; + + reg [15:0] mem_addr; + reg [15:0] mem_data_in; + reg mem_read_en, mem_write_en; + wire mem_done; + wire [15:0] mem_data_out; + mem_fsm mem_fsm_inst( + .clk(clk), + .addr(mem_addr), + .data_in(mem_data_in), + .read_en(mem_read_en), + .write_en(mem_write_en), + .data_out(mem_data_out), + .done(mem_done) + ); + + alu alu_inst( + .sel(alu_sel), + .a(alu_a), + .b(alu_b), + .result(alu_result), + .flags(alu_flags) + ); + + // Named reg wires for debugging purposes + wire [15:0] ra, rb, rc, rd, re, rf, rg, rh; + assign ra = regbank[0]; + assign rb = regbank[1]; + assign rc = regbank[2]; + assign rd = regbank[3]; + assign re = regbank[4]; + assign rf = regbank[5]; + assign rg = regbank[6]; + assign rh = regbank[7]; + + integer i; + always @(posedge clk or posedge rst) begin + // Handle reset button + if (rst) begin + phase <= `PH_RESET; + end + + else if (phase == `PH_RESET) begin + phase <= `PH_FETCH; + + pc <= 16'd0; + mem_read_en <= 0; + mem_write_en <= 0; + + for (i = 0; i < 8; i = i + 1) begin + regbank[i] <= 16'd0; + end + end + + // Fetch stage + else if (phase == `PH_FETCH) begin + mem_read_en <= 1; + mem_write_en <= 0; + mem_addr <= pc; + + if (mem_done) begin + mem_read_en <= 0; + mem_write_en <= 0; + ir <= mem_data_out; + phase <= `PH_DECODE; + pc <= pc + 16'd1; + end + end + + // Decode stage + else if (phase == `PH_DECODE) begin + phase <= `PH_EXECUTE; + + case (ir[15:12]) + `OP_ALR: begin + alu_sel <= ir[2:0]; // select ALU operation + alu_a <= regbank[ir[8:6]]; // read operand A + alu_b <= regbank[ir[5:3]]; // read operand B + end + `OP_ALI: begin + alu_sel <= ir[2:0]; // select ALU operation + alu_a <= regbank[ir[8:6]]; // read operand A + alu_b <= ir[5:3]; // read immediate operand + end + `OP_LDR: begin + // set target reg value to address, dereference in execute phase + if (ir[1] == 1 && ir[0] == 1) // addressing mode: absolute, direct + decoded_tmp <= regbank[ir[8:6]]; + else if (ir[1] == 0 && ir[0] == 1) // addressing mode: pc relative, direct + decoded_tmp <= regbank[ir[8:6]] + pc - 1; + /*else if (ir[1] == 1 && ir[0] == 0) begin // addressing mode: absolute, indirect + bram_wr <= 0; + bram_rd <= 1; + bram_addr <= regbank[ir[8:6]]; + decoded_tmp <= bram_data_out; + end + else if (ir[1] == 0 && ir[0] == 0) begin // addressing mode: pc relative, indirect + bram_wr <= 0; + bram_rd <= 1; + bram_addr <= regbank[ir[8:6]] + pc - 1; + decoded_tmp <= bram_data_out; + end*/ + end + `OP_STR: begin + // ir[2] = M = immediate mode (1) / register mode (0) + // ir[1] = A = absolute (1) / relative (0) addressing + // ir[0] = D = direct (1) / indirect (0) load + // TODO + end + default: begin + `ifdef __SYNTHESIS__ + $fatal(1, "decode: unhandled opcode %04b", ir[15:12]); + `endif + end + endcase + end + + // Execute stage + else if (phase == `PH_EXECUTE) begin + case (ir[15:12]) + `OP_ALR, `OP_ALI: begin + regbank[ir[11:9]] <= alu_result; // write result + phase <= `PH_FETCH; + end + `OP_LDR: begin + //$display("ir[11:9] %d, reg val: %d, mem_data_out: %d, mem_done: %d\n", ir[11:9], regbank[ir[11:9]], mem_data_out, mem_done); + mem_read_en <= 1; + mem_write_en <= 0; + mem_addr <= decoded_tmp; + + if (mem_done) begin + regbank[ir[11:9]] <= mem_data_out; // dereference address + mem_read_en <= 0; + mem_write_en <= 0; + phase <= `PH_FETCH; + end + end + `OP_STR: begin + // TODO + end + default: begin + `ifdef __SYNTHESIS__ + $fatal(1, "execute: unhandled opcode %04b", ir[15:12]); + `endif + end + endcase + end + end +endmodule diff --git a/atk16_fpga/cu_tb.gtkw b/atk16_fpga/cu_tb.gtkw new file mode 100644 index 0000000..b297fcc --- /dev/null +++ b/atk16_fpga/cu_tb.gtkw @@ -0,0 +1,77 @@ +[*] +[*] GTKWave Analyzer v3.4.0 (w)1999-2022 BSI +[*] Thu Dec 26 10:23:44 2024 +[*] +[dumpfile] "/Users/jantuomi/Projects/Personal/ATK16/atk16_fpga/cu_tb.vcd" +[dumpfile_mtime] "Thu Dec 26 10:23:28 2024" +[dumpfile_size] 3558 +[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 +[markername] AA +[markername] BB +[markername] CC +[markername] DD +[markername] EE +[markername] FF +[markername] GG +[markername] HH +[markername] II +[markername] JJ +[markername] KK +[markername] LL +[markername] MM +[markername] NN +[markername] OO +[markername] PP +[markername] QQ +[markername] RR +[markername] SS +[markername] TT +[markername] UU +[markername] VV +[markername] WW +[markername] XX +[markername] YY +[markername] ZZ +[treeopen] cu_tb. +[treeopen] cu_tb.dut. +[sst_width] 240 +[signals_width] 325 +[sst_expanded] 1 +[sst_vpaned_height] 317 +@28 +cu_tb.dut.clk +cu_tb.dut.rst +@25 +cu_tb.dut.phase[2:0] +@22 +cu_tb.dut.pc[15:0] +@28 +cu_tb.dut.ir[15:0] +@420 +cu_tb.dut.alu_a[15:0] +cu_tb.dut.alu_b[15:0] +cu_tb.dut.alu_sel[2:0] +cu_tb.dut.alu_result[15:0] +@28 +cu_tb.dut.alu_flags[3:0] +@22 +cu_tb.dut.ra[15:0] +cu_tb.dut.rb[15:0] +cu_tb.dut.rc[15:0] +cu_tb.dut.rd[15:0] +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 new file mode 100644 index 0000000..18a9a37 --- /dev/null +++ b/atk16_fpga/cu_tb.v @@ -0,0 +1,77 @@ +`default_nettype none +`define DUMPSTR(x) `"x.vcd`" +`timescale 10 ns / 100 ps + +module cu_tb(); + + reg clk, rst; + + cu dut( + .clk(clk), + .rst(rst) + ); + + // Clock generation + always #5 clk = ~clk; // 100 MHz clock + + reg failed; + initial begin + failed = 0; + $dumpfile(`DUMPSTR(`VCD_OUTPUT)); + $dumpvars(0, cu_tb); + + clk = 0; + rst = 0; + + #10 // Wait for reset phase to finish + + // test ALR + dut.regbank[0] = 16'd10; + dut.regbank[1] = 16'd20; + dut.mem_fsm_inst.bram_inst.mem[0] = { 4'b0000, 3'd2, 3'd0, 3'd1, 3'd0 }; // ALR RC, RA, RB, S=PLUS + + #200 if (dut.regbank[2] == 16'd30) begin + $display("\033[0;32m[PASS]\033[0m ALR ok"); + end else begin + $display("\033[0;31m[FAIL]\033[0m ALR not working, target reg contains %04h", dut.regbank[2]); + failed = 1; + end + rst = 1; #10 rst = 0; #10 + + // test LDR, absolute addressing + dut.mem_fsm_inst.bram_inst.mem[16'd100] = 16'hffff; + dut.regbank[1] = 16'd100; + dut.mem_fsm_inst.bram_inst.mem[16'd0] = { 4'b0010, 3'd0, 3'd1, 4'd0, 1'd1, 1'd1 }; // LDR RA, RB, absolute, direct + + #200 if (dut.regbank[0] == 16'hffff) begin + $display("\033[0;32m[PASS]\033[0m LDR absolute ok"); + end else begin + $display("\033[0;31m[FAIL]\033[0m LDR absolute not working, target reg contains %04h", dut.regbank[0]); + failed = 1; + end + rst = 1; #10 rst = 0; #10 + + // test LDR, relative addressing + dut.mem_fsm_inst.bram_inst.mem[16'd10] = 16'hffff; + dut.regbank[1] = 16'd10; + dut.mem_fsm_inst.bram_inst.mem[16'd0] = { 4'b0010, 3'd0, 3'd1, 4'd0, 1'd0, 1'd1 }; // LDR RA, RB, relative, direct + + #200 if (dut.regbank[0] == 16'hffff) begin + $display("\033[0;32m[PASS]\033[0m LDR relative ok"); + end else begin + $display("\033[0;31m[FAIL]\033[0m LDR relative not working, target reg contains %04h", dut.regbank[0]); + failed = 1; + end + rst = 1; #10 rst = 0; #10 + + #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/mem_fsm.v b/atk16_fpga/mem_fsm.v new file mode 100644 index 0000000..d5419c5 --- /dev/null +++ b/atk16_fpga/mem_fsm.v @@ -0,0 +1,67 @@ +`default_nettype none + +`define ST_IDLE 3'd0 +`define ST_READ1 3'd1 +`define ST_READ2 3'd2 +`define ST_WRITE1 3'd4 +`define ST_WRITE2 3'd5 +`define ST_END 3'd7 + +module mem_fsm( + input clk, + input [15:0] addr, + input [15:0] data_in, + input read_en, + input write_en, + + output wire [15:0] data_out, + output reg done +); + reg wr, rd; + reg [15:0] bram_addr; + reg [2:0] state = 0; + bram bram_inst( + .clk(clk), + .addr(bram_addr), + .cs_n(0), + .wr_n(~wr), + .rd_n(~rd), + .bram_data_in(data_in), + .bram_data_out(data_out) + ); + + always @(posedge clk) begin + case (state) + `ST_IDLE: begin + done <= 0; + if (~done && read_en) begin + state <= `ST_READ1; + bram_addr <= addr; + rd <= 1; + wr <= 0; + end + else if (~done && write_en) begin + state <= `ST_WRITE1; + bram_addr <= addr; + rd <= 0; + wr <= 1; + end + end + `ST_READ1: begin + state <= `ST_READ2; + end + `ST_READ2: begin + state <= `ST_IDLE; + done <= 1; + end + `ST_WRITE1: begin + state <= `ST_WRITE2; + end + `ST_WRITE2: begin + state <= `ST_IDLE; + done <= 1; + end + endcase + end + +endmodule diff --git a/atk16_fpga/mem_fsm_tb.gtkw b/atk16_fpga/mem_fsm_tb.gtkw new file mode 100644 index 0000000..6e8015a --- /dev/null +++ b/atk16_fpga/mem_fsm_tb.gtkw @@ -0,0 +1,32 @@ +[*] +[*] GTKWave Analyzer v3.4.0 (w)1999-2022 BSI +[*] Thu Dec 26 11:58:12 2024 +[*] +[dumpfile] "/Users/jantuomi/Projects/Personal/ATK16/atk16_fpga/mem_fsm_tb.vcd" +[dumpfile_mtime] "Thu Dec 26 11:57:15 2024" +[dumpfile_size] 1302 +[savefile] "/Users/jantuomi/Projects/Personal/ATK16/atk16_fpga/mem_fsm_tb.gtkw" +[timestart] 0 +[size] 1280 600 +[pos] -1 -1 +*-16.373917 -1 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 +[treeopen] mem_fsm_tb. +[treeopen] mem_fsm_tb.dut. +[sst_width] 240 +[signals_width] 144 +[sst_expanded] 1 +[sst_vpaned_height] 159 +@28 +mem_fsm_tb.clk +mem_fsm_tb.start_read +mem_fsm_tb.start_write +@22 +mem_fsm_tb.addr[15:0] +mem_fsm_tb.data_in[15:0] +mem_fsm_tb.data_out[15:0] +@28 +mem_fsm_tb.done +@29 +mem_fsm_tb.dut.state[2:0] +[pattern_trace] 1 +[pattern_trace] 0 diff --git a/atk16_fpga/mem_fsm_tb.v b/atk16_fpga/mem_fsm_tb.v new file mode 100644 index 0000000..5c5029c --- /dev/null +++ b/atk16_fpga/mem_fsm_tb.v @@ -0,0 +1,82 @@ +`default_nettype none +`define DUMPSTR(x) `"x.vcd`" +`timescale 10 ns / 100 ps + +module mem_fsm_tb(); + + reg clk, rst, start_read, start_write; + reg [15:0] addr, data_in; + wire done; + wire [15:0] data_out; + + mem_fsm dut( + .clk(clk), + .addr(addr), + .data_in(data_in), + .start_read(start_read), + .start_write(start_write), + .data_out(data_out), + .done(done) + ); + + // Clock generation + always #5 clk = ~clk; // 100 MHz clock + + reg failed; + initial begin + failed = 0; + $dumpfile(`DUMPSTR(`VCD_OUTPUT)); + $dumpvars(0, mem_fsm_tb); + + clk = 0; + rst = 0; + start_read = 0; + start_write = 0; + #10 + + // test read + dut.bram_inst.mem[0] = 16'hffff; + addr = 16'd0; + start_read = 1; + start_write = 0; + + #40 + if (data_out == 16'hffff && done == 1) begin + $display("\033[0;32m[PASS]\033[0m Read: data is available and done is 1 as expected"); + end else begin + $display("\033[0;31m[FAIL]\033[0m Read: done is %d (expected 1), data is %04h (expected ffff)", done, data_out); + failed = 1; + end + + start_read = 0; + start_write = 0; + #10 + + // test write + addr = 16'd1; + data_in = 16'hffff; + start_read = 0; + start_write = 1; + + #40 + if (dut.bram_inst.mem[1] == 16'hffff && done == 1) begin + $display("\033[0;32m[PASS]\033[0m Write: data is available and done is 1 as expected"); + end else begin + $display("\033[0;31m[FAIL]\033[0m Write: done is %d (expected 0), data is %04h (expected FFFF)", done, data_out); + failed = 1; + end + + start_read = 0; + start_write = 0; + + #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/top.v b/atk16_fpga/top.v index c456b31..386d6e3 100644 --- a/atk16_fpga/top.v +++ b/atk16_fpga/top.v @@ -1,18 +1,16 @@ +`default_nettype none + module top( input wire SYSCLK, + input wire BUT1, 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) + cu cu_inst( + .clk(SYSCLK), + .rst(BUT1) ); + assign LED1 = BUT1; + endmodule |
