From 7f12d0ba95d312e1cfc16b6aa4243430c5b60868 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Fri, 1 Dec 2023 17:00:15 +1300 Subject: [PATCH] QLF_TDP36K: more basic tdp/sdp sim tests Adds TDP submodule to generator. Adds shorthand expected signal to testbench (mostly to make it easier when I look at the vcd dump to figure out what I did wrong in tests). --- .../quicklogic/qlf_k6n10f/gen_memories.py | 89 ++++++++++++++++++- tests/arch/quicklogic/qlf_k6n10f/mem_tb.v | 6 +- 2 files changed, 90 insertions(+), 5 deletions(-) diff --git a/tests/arch/quicklogic/qlf_k6n10f/gen_memories.py b/tests/arch/quicklogic/qlf_k6n10f/gen_memories.py index ea750b8ed..e1d77d9df 100644 --- a/tests/arch/quicklogic/qlf_k6n10f/gen_memories.py +++ b/tests/arch/quicklogic/qlf_k6n10f/gen_memories.py @@ -132,6 +132,26 @@ sync_ram_sdp #(\\ );\ """ +sync_ram_tdp_submodule = """\ +sync_ram_tdp #(\\ + .ADDRESS_WIDTH(ADDRESS_WIDTH),\\ + .DATA_WIDTH(DATA_WIDTH)\\ +) uut (\\ + .clk_a(clk),\\ + .clk_b(clk),\\ + .write_enable_a(wce_a),\\ + .write_enable_b(wce_b),\\ + .read_enable_a(rce_a),\\ + .read_enable_b(rce_b),\\ + .addr_a(ra_a),\\ + .addr_b(ra_b),\\ + .read_data_a(rq_a),\\ + .read_data_b(rq_b),\\ + .write_data_a(wd_a),\\ + .write_data_b(wd_b)\\ +);\ +""" + @dataclass class TestClass: params: dict[str, int] @@ -155,20 +175,81 @@ test_val_map = { } sim_tests: list[TestClass] = [ - TestClass( + TestClass( # basic SDP test + # note that the common SDP model reads every cycle, but the testbench + # still uses the rce signal to check read assertions params={"ADDRESS_WIDTH": 10, "DATA_WIDTH": 36}, top="sync_ram_sdp", - assertions=["-assert-count 1 t:TDP36K"], + assertions=[], test_steps=[ {"wce_a": 1, "wa_a": 0x0A, "wd_a": 0xdeadbeef}, {"wce_a": 1, "wa_a": 0xBA, "wd_a": 0x5a5a5a5a}, {"wce_a": 1, "wa_a": 0xFF, "wd_a": 0}, - {"rce_a": 1, "ra_a": 0xA}, + {"rce_a": 1, "ra_a": 0x0A}, {"rq_a": 0xdeadbeef}, {"rce_a": 1, "ra_a": 0xFF}, {"rq_a": 0}, ] ), + TestClass( # SDP read before write + params={"ADDRESS_WIDTH": 4, "DATA_WIDTH": 16}, + top="sync_ram_sdp", + assertions=[], + test_steps=[ + {"wce_a": 1, "wa_a": 0xA, "wd_a": 0x1234}, + {"wce_a": 1, "wa_a": 0xA, "wd_a": 0x5678, "rce_a": 1, "ra_a": 0xA}, + {"rq_a": 0x1234, "rce_a": 1, "ra_a": 0xA}, + {"rq_a": 0x5678}, + ] + ), + TestClass( # basic TDP test + # note that the testbench uses ra and wa, while the common TDP model + # uses a shared address + params={"ADDRESS_WIDTH": 10, "DATA_WIDTH": 36}, + top="sync_ram_tdp", + assertions=[], + test_steps=[ + {"wce_a": 1, "ra_a": 0x0A, "wce_b": 1, "ra_b": 0xBA, + "wd_a": 0xdeadbeef, "wd_b": 0x5a5a5a5a}, + {"wce_a": 1, "ra_a": 0xFF, + "wd_a": 0}, + {"rce_a": 1, "ra_a": 0x0A, "rce_b": 1, "ra_b": 0x0A}, + {"rq_a": 0xdeadbeef, "rq_b": 0xdeadbeef}, + {"rce_a": 1, "ra_a": 0xFF, "rce_b": 1, "ra_b": 0xBA}, + {"rq_a": 0, "rq_b": 0x5a5a5a5a}, + ] + ), + TestClass( # TDP with truncation + params={"ADDRESS_WIDTH": 4, "DATA_WIDTH": 16}, + top="sync_ram_tdp", + assertions=[], + test_steps=[ + {"wce_a": 1, "ra_a": 0x0F, "wce_b": 1, "ra_b": 0xBA, + "wd_a": 0xdeadbeef, "wd_b": 0x5a5a5a5a}, + {"wce_a": 1, "ra_a": 0xFF, + "wd_a": 0}, + {"rce_a": 1, "ra_a": 0x0F, "rce_b": 1, "ra_b": 0x0A}, + {"rq_a": 0, "rq_b": 0x00005a5a}, + ] + ), + TestClass( # TDP read before write + # note that the testbench uses rce and wce, while the common TDP model + # uses a single enable for write, with reads on no write + params={"ADDRESS_WIDTH": 10, "DATA_WIDTH": 36}, + top="sync_ram_tdp", + assertions=[], + test_steps=[ + {"wce_a": 1, "ra_a": 0x0A, "wce_b": 1, "ra_b": 0xBA, + "wd_a": 0xdeadbeef, "wd_b": 0x5a5a5a5a}, + {"wce_a": 1, "ra_a": 0xBA, "rce_b": 1, "ra_b": 0xBA, + "wd_a": 0xa5a5a5a5}, + { "rq_b": 0x5a5a5a5a}, + {"rce_a": 1, "ra_a": 0x0A, "rce_b": 1, "ra_b": 0x0A}, + {"rq_a": 0xdeadbeef, "rq_b": 0xdeadbeef}, + { "rce_b": 1, "ra_b": 0xBA}, + { "rq_b": 0xa5a5a5a5}, + ] + ), ] for (params, top, assertions) in blockram_tests: @@ -225,6 +306,8 @@ for sim_test in sim_tests: if test_steps: if top == "sync_ram_sdp": uut_submodule = sync_ram_sdp_submodule + elif top == "sync_ram_tdp": + uut_submodule = sync_ram_tdp_submodule else: raise NotImplementedError(f"missing submodule header for {top}") mem_test_vector = "" diff --git a/tests/arch/quicklogic/qlf_k6n10f/mem_tb.v b/tests/arch/quicklogic/qlf_k6n10f/mem_tb.v index 93ba2a31a..22ff63642 100644 --- a/tests/arch/quicklogic/qlf_k6n10f/mem_tb.v +++ b/tests/arch/quicklogic/qlf_k6n10f/mem_tb.v @@ -43,6 +43,7 @@ end wire rce_a = rce_a_testvector[i]; wire [ADDRESS_WIDTH-1:0] ra_a = ra_a_testvector[i]; +wire [DATA_WIDTH-1:0] rq_a_e = rq_a_expected[i]; wire [DATA_WIDTH-1:0] rq_a; wire wce_a = wce_a_testvector[i]; @@ -51,6 +52,7 @@ wire [DATA_WIDTH-1:0] wd_a = wd_a_testvector[i]; wire rce_b = rce_b_testvector[i]; wire [ADDRESS_WIDTH-1:0] ra_b = ra_b_testvector[i]; +wire [DATA_WIDTH-1:0] rq_b_e = rq_b_expected[i]; wire [DATA_WIDTH-1:0] rq_b; wire wce_b = wce_b_testvector[i]; @@ -63,9 +65,9 @@ always @(posedge clk) begin if (i < VECTORLEN-1) begin if (i > 0) begin if($past(rce_a)) - assert(rq_a == rq_a_expected[i]); + assert(rq_a == rq_a_e); if($past(rce_b)) - assert(rq_b == rq_b_expected[i]); + assert(rq_b == rq_b_e); end i <= i + 1; end