diff --git a/firmware/rtl/autoapproach/Makefile b/firmware/rtl/autoapproach/Makefile index 6ed7edd..1ddde22 100644 --- a/firmware/rtl/autoapproach/Makefile +++ b/firmware/rtl/autoapproach/Makefile @@ -2,18 +2,18 @@ .PHONY: test clean -test: obj_dir/Vbram_interface +test: obj_dir/Vbram_interface_sim -bram_SRC= bram_interface.v bram_interface_sim.cpp +bram_SRC= bram_interface_sim.v dma_sim.v bram_interface.v bram_interface_sim.cpp -obj_dir/Vbram_interface.mk: $(bram_SRC) +obj_dir/Vbram_interface_sim.mk: $(bram_SRC) verilator --cc --exe -Wall --trace --trace-fst \ -CFLAGS -DWORD_AMNT=2048 \ -CFLAGS -DRAM_WID=32 \ $(bram_SRC) -obj_dir/Vbram_interface: obj_dir/Vbram_interface.mk - cd obj_dir && make -f Vbram_interface.mk - ./obj_dir/Vbram_interface +obj_dir/Vbram_interface_sim: obj_dir/Vbram_interface_sim.mk + cd obj_dir && make -f Vbram_interface_sim.mk + ./obj_dir/Vbram_interface_sim clean: rm -rf obj_dir/ diff --git a/firmware/rtl/autoapproach/bram_interface.v b/firmware/rtl/autoapproach/bram_interface.v index 851e155..8bf64ad 100644 --- a/firmware/rtl/autoapproach/bram_interface.v +++ b/firmware/rtl/autoapproach/bram_interface.v @@ -105,11 +105,4 @@ end else if (!word_next && word_ok) begin word_ok <= 0; end -`ifdef VERILATOR -initial begin - $dumpfile("bram.fst"); - $dumpvars; -end -`endif - endmodule diff --git a/firmware/rtl/autoapproach/bram_interface_sim.cpp b/firmware/rtl/autoapproach/bram_interface_sim.cpp index 068b29e..617bc44 100644 --- a/firmware/rtl/autoapproach/bram_interface_sim.cpp +++ b/firmware/rtl/autoapproach/bram_interface_sim.cpp @@ -4,42 +4,11 @@ #include #include -#include "Vbram_interface.h" +#include "Vbram_interface_sim.h" #include "../testbench.hpp" -TB *tb; -constexpr uint32_t start_addr = 0x12340; std::array ram_refresh_data; - -static void handle_ram() { - static int timer = 0; - constexpr auto TIMER_MAX = 10; - bool flip_flop = false; - - if (tb->mod.ram_read) { - timer++; - if (timer == TIMER_MAX) { - tb->mod.ram_valid = 1; - if (tb->mod.ram_dma_addr < start_addr || - tb->mod.ram_dma_addr >= start_addr + WORD_AMNT*4) { - printf("bad address %x\n", tb->mod.ram_dma_addr); - exit(1); - } - my_assert(tb->mod.ram_dma_addr >= start_addr, "left oob access %x", tb->mod.ram_dma_addr); - my_assert(tb->mod.ram_dma_addr < start_addr + WORD_AMNT*4, "right oob access %x", tb->mod.ram_dma_addr); - my_assert(tb->mod.ram_dma_addr % 2 == 0, "unaligned access %x", tb->mod.ram_dma_addr); - - if (tb->mod.ram_dma_addr % 4 == 0) { - tb->mod.ram_word = ram_refresh_data[(tb->mod.ram_dma_addr - start_addr)/4]& 0xFFFF; - } else { - tb->mod.ram_word = ram_refresh_data[(tb->mod.ram_dma_addr - start_addr)/4] >> 16; - } - } - } else { - tb->mod.ram_valid = 0; - timer = 0; - } -} +TB *tb; static void handle_read_aa(size_t &i) { if (tb->mod.word_ok) { @@ -95,17 +64,18 @@ static void test_aa_read_interrupted() { static void refresh_data() { for (size_t i = 0; i < RAM_WID; i++) { - ram_refresh_data[i] = mask_extend(rand(), 20); + uint32_t val = mask_extend(rand(), 20); + ram_refresh_data[i] = val; + tb->mod.backing_store[i*2] = val & 0xFFFF; + tb->mod.backing_store[i*2+1] = val >> 16; } tb->mod.refresh_start = 1; - tb->mod.start_addr = start_addr; + tb->mod.start_addr = 0x12340; tb->run_clock(); - while (!tb->mod.refresh_finished) { - handle_ram(); + while (!tb->mod.refresh_finished) tb->run_clock(); - } tb->mod.refresh_start = 0; tb->run_clock(); @@ -113,8 +83,11 @@ static void refresh_data() { } int main(int argc, char *argv[]) { + Verilated::commandArgs(argc, argv); Verilated::traceEverOn(true); - tb = new TB(argc, argv); + Verilated::fatalOnError(false); + + tb = new TB(argc, argv); printf("test basic read/write\n"); refresh_data(); diff --git a/firmware/rtl/autoapproach/bram_interface_sim.v b/firmware/rtl/autoapproach/bram_interface_sim.v new file mode 100644 index 0000000..facdc85 --- /dev/null +++ b/firmware/rtl/autoapproach/bram_interface_sim.v @@ -0,0 +1,81 @@ +module bram_interface_sim #( + parameter WORD_WID = 24, + parameter WORD_AMNT_WID = 11, + parameter [WORD_AMNT_WID-1:0] WORD_AMNT = 2047, + parameter RAM_WID = 32, + parameter RAM_WORD_WID = 16, + parameter RAM_REAL_START = 32'h12340, + parameter RAM_CNTR_LEN = 12, + parameter TOTAL_RAM_WORD_MINUS_ONE = 4095, + parameter DELAY_CNTR_LEN = 8, + parameter DELAY_TOTAL = 12, + parameter RAM_WORD_INCR = 2 +) ( + input clk, + + /* autoapproach interface */ + output [WORD_WID-1:0] word, + input word_next, + output word_last, + output word_ok, + input word_rst, + + /* User interface */ + input refresh_start, + input [RAM_WID-1:0] start_addr, + output refresh_finished, + + input[RAM_WORD_WID-1:0] backing_store [TOTAL_RAM_WORD_MINUS_ONE:0] +); + +wire [RAM_WID-1:0] ram_dma_addr; +wire [RAM_WORD_WID-1:0] ram_word; +wire ram_read; +wire ram_valid; + +dma_sim #( + .RAM_WID(RAM_WID), + .RAM_WORD_WID(RAM_WORD_WID), + .RAM_REAL_START(RAM_REAL_START), + .RAM_CNTR_LEN(RAM_CNTR_LEN), + .TOTAL_RAM_WORD_MINUS_ONE(TOTAL_RAM_WORD_MINUS_ONE), + .DELAY_CNTR_LEN(DELAY_CNTR_LEN), + .DELAY_TOTAL(DELAY_TOTAL) +) dma_sim ( + .clk(clk), + .ram_dma_addr(ram_dma_addr), + .ram_word(ram_word), + .ram_read(ram_read), + .ram_valid(ram_valid), + .backing_store(backing_store) +); + +bram_interface #( + .WORD_WID(WORD_WID), + .WORD_AMNT_WID(WORD_AMNT_WID), + .WORD_AMNT(WORD_AMNT), + .RAM_WID(RAM_WID), + .RAM_WORD_WID(RAM_WORD_WID), + .RAM_WORD_INCR(RAM_WORD_INCR) +) bram_interface ( + .clk(clk), + .word(word), + .word_next(word_next), + .word_last(word_last), + .word_ok(word_ok), + .word_rst(word_rst), + .refresh_start(refresh_start), + .start_addr(start_addr), + .refresh_finished(refresh_finished), + .ram_dma_addr(ram_dma_addr), + .ram_word(ram_word), + .ram_read(ram_read), + .ram_valid(ram_valid) +); + +initial begin + $dumpfile("bram.fst"); + $dumpvars(); +end + +endmodule diff --git a/firmware/rtl/autoapproach/dma_sim.v b/firmware/rtl/autoapproach/dma_sim.v new file mode 100644 index 0000000..dce214e --- /dev/null +++ b/firmware/rtl/autoapproach/dma_sim.v @@ -0,0 +1,44 @@ +/* This module is used to simulate direct memory access, where only + * a small amount of memory is valid to read. + */ +module dma_sim #( + parameter RAM_WID = 32, + parameter RAM_WORD_WID = 16, + parameter RAM_REAL_START = 32'h12340, + parameter RAM_CNTR_LEN = 12, + parameter TOTAL_RAM_WORD_MINUS_ONE = 4095, + parameter DELAY_CNTR_LEN = 8, + parameter DELAY_TOTAL = 12 +) ( + input clk, + + /* DMA interface */ + input [RAM_WID-1:0] ram_dma_addr, + output reg [RAM_WORD_WID-1:0] ram_word, + input ram_read, + output reg ram_valid, + + /*- Verilator interface */ + input [RAM_WORD_WID-1:0] backing_store[TOTAL_RAM_WORD_MINUS_ONE:0] +); + +reg [DELAY_CNTR_LEN-1:0] delay_cntr = 0; + +always @ (posedge clk) begin + if (!ram_read) begin + delay_cntr <= 0; + ram_valid <= 0; + end else if (delay_cntr < DELAY_TOTAL) begin + delay_cntr <= delay_cntr + 1; + end else if (!ram_valid) begin + if (ram_dma_addr < RAM_REAL_START || ram_dma_addr > RAM_REAL_START + 2*TOTAL_RAM_WORD_MINUS_ONE) begin + $display("ram_dma_addr %x out of bounds", ram_dma_addr); + $stop(); + end else begin + ram_word <= backing_store[(RAM_CNTR_LEN)'((ram_dma_addr - RAM_REAL_START)/2)]; + ram_valid <= 1; + end + end +end + +endmodule diff --git a/firmware/rtl/testbench.hpp b/firmware/rtl/testbench.hpp index 3f011c2..bc4aa34 100644 --- a/firmware/rtl/testbench.hpp +++ b/firmware/rtl/testbench.hpp @@ -9,12 +9,8 @@ template class TB { public: TOP mod; - VerilatedContext vc; - - TB(int argc, char *argv[], int _bailout = 0) : mod(), bailout(_bailout), vc() { - vc.commandArgs(argc, argv); - vc.traceEverOn(true); + TB(int argc, char *argv[], int _bailout = 0) : mod(), bailout(_bailout) { mod.clk = 0; tick_count = 0; } @@ -26,14 +22,16 @@ template class TB { void run_clock() { mod.clk = !mod.clk; mod.eval(); - vc.timeInc(1); + Verilated::timeInc(1); mod.clk = !mod.clk; mod.eval(); - vc.timeInc(1); + Verilated::timeInc(1); tick_count++; if (bailout > 0 && tick_count >= bailout) exit(1); + if (Verilated::gotError()) + exit(1); } };