Merge pull request #266 from antmicro/k6n10f_dsp_tests Equivalence checks for qlf_k6n10f DSP tests
diff --git a/Makefile_test.common b/Makefile_test.common index db3cc3c..ca6ec18 100644 --- a/Makefile_test.common +++ b/Makefile_test.common
@@ -95,6 +95,47 @@ endef +define test_post_synth_sim_tpl = +$(1): $(1)/ok + @printf "Test %-18s \e[32mPASSED\e[0m @ %s\n" $(1) $(CURDIR); + +$(1)/ok: $(1)/synth + @make -C $(1)/sim sim; \ + if [ $$$$? -ne 0 ]; then \ + printf "Test %-18s \e[31;1mFAILED\e[0m @ %s\n" $(1) $(CURDIR); \ + false; \ + else \ + touch $$@; \ + true; \ + fi + +$(1)/synth: $(1)/$$(notdir $(1).v) + @set +e; \ + cd $(1); \ + echo "source $(TEST_UTILS)" > run-$$(notdir $(1)).tcl ;\ + echo "source $$(notdir $(1)).tcl" >> run-$$(notdir $(1)).tcl ;\ + DESIGN_TOP=$$(notdir $(1)) TEST_OUTPUT_PREFIX=./ \ + yosys -c "run-$$(notdir $(1)).tcl" -q -q -l $$(notdir $(1)).log; \ + RETVAL=$$$$?; \ + rm -f run-$$(notdir $(1)).tcl; \ + if [ ! -z "$$($(1)_negative)" ] && [ $$($(1)_negative) -eq 1 ]; then \ + if [ $$$$RETVAL -ne 0 ]; then \ + printf "Negative test %-20s \e[32mPASSED\e[0m @ %s\n" $(1) $(CURDIR); \ + true; \ + else \ + printf "Negative test %-20s \e[31;1mFAILED\e[0m @ %s\n" $(1) $(CURDIR); \ + false; \ + fi \ + else \ + if [ $$$$RETVAL -ne 0 ]; then \ + echo "Unexpected runtime error"; \ + printf "Test %-20s \e[31;1mFAILED\e[0m @ %s\n" $(1) $(CURDIR); \ + false; \ + fi \ + fi + +endef + define unit_test_tpl = $(1): $(1)/$(1).test @$$< @@ -109,7 +150,7 @@ diff_test = diff $(1)/$(1).golden.$(2) $(1)/$(1).$(2) -all: $(TESTS) $(SIM_TESTS) $(UNIT_TESTS) +all: $(TESTS) $(SIM_TESTS) $(POST_SYNTH_SIM_TESTS) $(UNIT_TESTS) $(GTEST_DIR)/build/lib/libgtest.a $(GTEST_DIR)/build/lib/libgtest_main.a: @mkdir -p $(GTEST_DIR)/build @@ -121,10 +162,12 @@ $(foreach test,$(TESTS),$(eval $(call test_tpl,$(test)))) $(foreach test,$(SIM_TESTS),$(eval $(call test_sim_tpl,$(test)))) +$(foreach test,$(POST_SYNTH_SIM_TESTS),$(eval $(call test_post_synth_sim_tpl,$(test)))) $(foreach test,$(UNIT_TESTS),$(eval $(call unit_test_tpl,$(test)))) clean: @rm -rf $(foreach test,$(TESTS),$(test)/$(test).sdc $(test)/$(test)_[0-9].sdc $(test)/$(test).txt $(test)/$(test).eblif $(test)/$(test).json) @rm -rf $(foreach test,$(SIM_TESTS),$(test)/*.vvp $(test)/*.vcd) + @rm -rf $(foreach test,$(POST_SYNTH_SIM_TESTS),$(test)/sim/*.vvp $(test)/sim/*.vcd $(test)/sim/*post_synth.v) @rm -rf $(foreach test,$(UNIT_TESTS),$(test)/$(test).test.o $(test)/$(test).test.d $(test)/$(test).test) @find . -name "ok" -or -name "*.log" | xargs rm -rf
diff --git a/ql-qlf-plugin/qlf_k6n10f/TDP18Kx18_FIFO.v b/ql-qlf-plugin/qlf_k6n10f/TDP18Kx18_FIFO.v index bec428b..696c2a7 100644 --- a/ql-qlf-plugin/qlf_k6n10f/TDP18Kx18_FIFO.v +++ b/ql-qlf-plugin/qlf_k6n10f/TDP18Kx18_FIFO.v
@@ -34,13 +34,8 @@ FWM, OVERRUN, FLUSH, + RAM_ID, FMODE, - SYNC_FIFO, - POWERDN, - SLEEP, - PROTECT, - UPAF, - UPAE, PL_INIT, PL_ENA, PL_WEN, @@ -48,9 +43,15 @@ PL_CLK, PL_ADDR, PL_DATA_IN, - PL_DATA_OUT, - RAM_ID + PL_DATA_OUT ); + parameter SYNC_FIFO = 1'b0; + parameter POWERDN = 1'b0; + parameter SLEEP = 1'b0; + parameter PROTECT = 1'b0; + parameter UPAF = 11'b0; + parameter UPAE = 11'b0; + input wire [2:0] RMODE_A; input wire [2:0] RMODE_B; input wire [2:0] WMODE_A; @@ -80,13 +81,8 @@ output wire FWM; output wire OVERRUN; input wire FLUSH; + input wire [15:0] RAM_ID; input wire FMODE; - input wire SYNC_FIFO; - input wire POWERDN; - input wire SLEEP; - input wire PROTECT; - input wire [10:0] UPAF; - input wire [10:0] UPAE; input PL_INIT; input PL_ENA; input PL_WEN; @@ -95,7 +91,6 @@ input [31:0] PL_ADDR; input [17:0] PL_DATA_IN; output reg [17:0] PL_DATA_OUT; - input [15:0] RAM_ID; reg [17:0] wmsk_a; reg [17:0] wmsk_b; wire [8:0] addr_a;
diff --git a/ql-qlf-plugin/qlf_k6n10f/brams.txt b/ql-qlf-plugin/qlf_k6n10f/brams.txt index 1664603..b8ba985 100644 --- a/ql-qlf-plugin/qlf_k6n10f/brams.txt +++ b/ql-qlf-plugin/qlf_k6n10f/brams.txt
@@ -1,4 +1,3 @@ - bram $__QLF_FACTOR_BRAM36_TDP init 1 abits 10 @a10d36 @@ -13,51 +12,21 @@ dbits 2 @a14d2 abits 15 @a15d1 dbits 1 @a15d1 - groups 2 - ports 1 1 - wrmode 0 1 - enable 1 4 @a10d36 - enable 1 2 @a11d18 - enable 1 1 @a12d9 @a13d4 @a14d2 @a15d1 - transp 0 0 - clocks 2 3 - clkpol 2 3 -endbram - -bram $__QLF_FACTOR_BRAM18_TDP - init 1 - abits 10 @a10d18 - dbits 18 @a10d18 - abits 11 @a11d9 - dbits 9 @a11d9 - abits 12 @a12d4 - dbits 4 @a12d4 - abits 13 @a13d2 - dbits 2 @a13d2 - abits 14 @a14d1 - dbits 1 @a14d1 - groups 2 - ports 1 1 - wrmode 0 1 - enable 1 2 @a10d18 - enable 1 1 @a11d9 @a12d4 @a13d2 @a14d1 - transp 0 0 - clocks 2 3 - clkpol 2 3 + groups 4 + ports 1 1 1 1 + wrmode 0 1 0 1 + enable 1 4 1 4 @a10d36 + enable 1 2 1 2 @a11d18 + enable 1 1 1 1 @a12d9 @a13d4 @a14d2 @a15d1 + transp 0 0 0 0 + clocks 1 1 2 2 + clkpol 1 1 1 1 endbram match $__QLF_FACTOR_BRAM36_TDP - min bits 128 - min efficiency 2 - shuffle_enable B - make_transp - or_next_if_better -endmatch - -match $__QLF_FACTOR_BRAM18_TDP - min bits 128 - min efficiency 2 + max dbits 36 + max abits 15 shuffle_enable B make_transp endmatch
diff --git a/ql-qlf-plugin/qlf_k6n10f/brams_map.v b/ql-qlf-plugin/qlf_k6n10f/brams_map.v index be0b230..59fbdd7 100644 --- a/ql-qlf-plugin/qlf_k6n10f/brams_map.v +++ b/ql-qlf-plugin/qlf_k6n10f/brams_map.v
@@ -6,17 +6,25 @@ // // SPDX-License-Identifier:ISC -module \$__QLF_FACTOR_BRAM36_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); +`define MODE_36 3'b111 // 36 or 32-bit +`define MODE_18 3'b110 // 18 or 16-bit +`define MODE_9 3'b101 // 9 or 8-bit +`define MODE_4 3'b100 // 4-bit +`define MODE_2 3'b010 // 32-bit +`define MODE_1 3'b001 // 32-bit + +module \$__QLF_FACTOR_BRAM36_TDP (A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN, C1ADDR, C1DATA, C1EN, CLK1, CLK2, D1ADDR, D1DATA, D1EN); parameter CFG_ABITS = 10; parameter CFG_DBITS = 36; parameter CFG_ENABLE_B = 4; + parameter CFG_ENABLE_D = 4; parameter CLKPOL2 = 1; parameter CLKPOL3 = 1; parameter [36863:0] INIT = 36864'bx; + input CLK1; input CLK2; - input CLK3; input [CFG_ABITS-1:0] A1ADDR; output [CFG_DBITS-1:0] A1DATA; @@ -26,106 +34,226 @@ input [CFG_DBITS-1:0] B1DATA; input [CFG_ENABLE_B-1:0] B1EN; - wire [14:0] A1ADDR_15; - wire [14:0] B1ADDR_15; - //wire [7:0] B1EN_8 = //B1EN; + input [CFG_ABITS-1:0] C1ADDR; + output [CFG_DBITS-1:0] C1DATA; + input C1EN; - wire [3:0] DIP, DOP; - wire [31:0] DI, DO; + input [CFG_ABITS-1:0] D1ADDR; + input [CFG_DBITS-1:0] D1DATA; + input [CFG_ENABLE_B-1:0] D1EN; - wire [31:0] DOBDO; - wire [3:0] DOPBDOP; + wire FLUSH1; + wire FLUSH2; + wire SPLIT; + wire [15:0] RAM_ID; - //wire [2:0] WRITEDATAWIDTHB; - //wire [2:0] READDATAWIDTHA; - assign A1DATA = { DOP[3], DO[31:24], DOP[2], DO[23:16], DOP[1], DO[15: 8], DOP[0], DO[ 7: 0] }; - assign { DIP[3], DI[31:24], DIP[2], DI[23:16], DIP[1], DI[15: 8], DIP[0], DI[ 7: 0] } = B1DATA; + wire PL_INIT_i; + wire PL_ENA_i; + wire PL_REN_i; + wire PL_CLK_i; + wire [1:0] PL_WEN_i; + wire [23:0] PL_ADDR_i; + wire [35:0] PL_DATA_i; + reg PL_INIT_o; + reg PL_ENA_o; + reg PL_REN_o; + reg PL_CLK_o; + reg [1:0] PL_WEN_o; + reg [23:0] PL_ADDR_o; + wire [35:0] PL_DATA_o; - assign A1ADDR_15[14:CFG_ABITS] = 0; - assign A1ADDR_15[CFG_ABITS-1:0] = A1ADDR; - assign B1ADDR_15[14:CFG_ABITS] = 0; - assign B1ADDR_15[CFG_ABITS-1:0] = B1ADDR; + wire [14:CFG_ABITS] A1ADDR_CMPL = {15-CFG_ABITS{1'b0}}; + wire [14:CFG_ABITS] B1ADDR_CMPL = {15-CFG_ABITS{1'b0}}; + wire [14:CFG_ABITS] C1ADDR_CMPL = {15-CFG_ABITS{1'b0}}; + wire [14:CFG_ABITS] D1ADDR_CMPL = {15-CFG_ABITS{1'b0}}; - /*if (CFG_DBITS == 1) begin - assign WRITEDATAWIDTHB = 3'b000; - assign READDATAWIDTHA = 3'b000; - end else if (CFG_DBITS == 2) begin - assign WRITEDATAWIDTHB = 3'b001; - assign READDATAWIDTHA = 3'b001; - end else if (CFG_DBITS > 2 && CFG_DBITS <= 4) begin - assign WRITEDATAWIDTHB = 3'b010; - assign READDATAWIDTHA = 3'b010; - end else if (CFG_DBITS > 4 && CFG_DBITS <= 9) begin - assign WRITEDATAWIDTHB = 3'b011; - assign READDATAWIDTHA = 3'b011; - end else if (CFG_DBITS > 9 && CFG_DBITS <= 18) begin - assign WRITEDATAWIDTHB = 3'b100; - assign READDATAWIDTHA = 3'b100; - end else if (CFG_DBITS > 18 && CFG_DBITS <= 36) begin - assign WRITEDATAWIDTHB = 3'b101; - assign READDATAWIDTHA = 3'b101; - end*/ - generate if (CFG_DBITS > 8) begin - TDP_BRAM36 #( - //`include "brams_init_36.vh" - .READ_WIDTH_A(CFG_DBITS), - .READ_WIDTH_B(CFG_DBITS), - .WRITE_WIDTH_A(CFG_DBITS), - .WRITE_WIDTH_B(CFG_DBITS), - ) _TECHMAP_REPLACE_ ( - .WRITEDATAA(32'hFFFFFFFF), - .WRITEDATAAP(4'hF), - .READDATAA(DO[31:0]), - .READDATAAP(DOP[3:0]), - .ADDRA(A1ADDR_15), - .CLOCKA(CLK2), - .READENABLEA(A1EN), - .WRITEENABLEA(1'b0), - .BYTEENABLEA(4'b0), - //.WRITEDATAWIDTHA(3'b0), - //.READDATAWIDTHA(READDATAWIDTHA), + wire [14:0] A1ADDR_TOTAL = {A1ADDR_CMPL, A1ADDR}; + wire [14:0] B1ADDR_TOTAL = {B1ADDR_CMPL, B1ADDR}; + wire [14:0] C1ADDR_TOTAL = {C1ADDR_CMPL, C1ADDR}; + wire [14:0] D1ADDR_TOTAL = {D1ADDR_CMPL, D1ADDR}; - .WRITEDATAB(DI), - .WRITEDATABP(DIP), - .READDATAB(DOBDO), - .READDATABP(DOPBDOP), - .ADDRB(B1ADDR_15), - .CLOCKB(CLK3), - .READENABLEA(1'b0), - .WRITEENABLEB(1'b1), - .BYTEENABLEB(B1EN) - //.WRITEDATAWIDTHB(WRITEDATAWIDTHB), - //.READDATAWIDTHB(3'b0) - ); - end else begin - TDP_BRAM36 #( - //`include "brams_init_32.vh" - ) _TECHMAP_REPLACE_ ( - .WRITEDATAA(32'hFFFFFFFF), - .WRITEDATAAP(4'hF), - .READDATAA(DO[31:0]), - .READDATAAP(DOP[3:0]), - .ADDRA(A1ADDR_15), - .CLOCKA(CLK2), - .READENABLEA(A1EN), - .WRITEENABLEA(1'b0), - .BYTEENABLEA(4'b0), - //.WRITEDATAWIDTHA(3'b0), - //.READDATAWIDTHA(READDATAWIDTHA), + wire [35:CFG_DBITS] A1DATA_CMPL; + wire [35:CFG_DBITS] C1DATA_CMPL; - .WRITEDATAB(DI), - .WRITEDATABP(DIP), - .READDATAB(DOBDO), - .READDATABP(DOPBDOP), - .ADDRB(B1ADDR_15), - .CLOCKB(CLK3), - .READENABLEB(1'b0), - .WRITEENABLEB(1'b1), - .BYTEENABLEB(B1EN) - //.WRITEDATAWIDTHB(WRITEDATAWIDTHB), - //.READDATAWIDTHB(3'b0) - ); - end endgenerate + wire [35:0] A1DATA_TOTAL = {A1DATA_CMPL, A1DATA}; + wire [35:0] C1DATA_TOTAL = {C1DATA_CMPL, C1DATA}; + + wire [14:0] PORT_A_ADDR; + wire [14:0] PORT_B_ADDR; + + case (CFG_DBITS) + 1: begin + assign PORT_A_ADDR = A1EN ? A1ADDR_TOTAL : (B1EN ? B1ADDR_TOTAL : 15'd0); + assign PORT_B_ADDR = C1EN ? C1ADDR_TOTAL : (D1EN ? D1ADDR_TOTAL : 15'd0); + defparam _TECHMAP_REPLACE_.WMODE_A1_i = `MODE_1; + defparam _TECHMAP_REPLACE_.WMODE_A2_i = `MODE_1; + defparam _TECHMAP_REPLACE_.RMODE_A1_i = `MODE_1; + defparam _TECHMAP_REPLACE_.RMODE_A2_i = `MODE_1; + defparam _TECHMAP_REPLACE_.WMODE_B1_i = `MODE_1; + defparam _TECHMAP_REPLACE_.WMODE_B2_i = `MODE_1; + defparam _TECHMAP_REPLACE_.RMODE_B1_i = `MODE_1; + defparam _TECHMAP_REPLACE_.RMODE_B2_i = `MODE_1; + end + + 2: begin + assign PORT_A_ADDR = A1EN ? (A1ADDR_TOTAL << 1) : (B1EN ? (B1ADDR_TOTAL << 1) : 15'd0); + assign PORT_B_ADDR = C1EN ? (C1ADDR_TOTAL << 1) : (D1EN ? (D1ADDR_TOTAL << 1) : 15'd0); + defparam _TECHMAP_REPLACE_.WMODE_A1_i = `MODE_2; + defparam _TECHMAP_REPLACE_.WMODE_A2_i = `MODE_2; + defparam _TECHMAP_REPLACE_.RMODE_A1_i = `MODE_2; + defparam _TECHMAP_REPLACE_.RMODE_A2_i = `MODE_2; + defparam _TECHMAP_REPLACE_.WMODE_B1_i = `MODE_2; + defparam _TECHMAP_REPLACE_.WMODE_B2_i = `MODE_2; + defparam _TECHMAP_REPLACE_.RMODE_B1_i = `MODE_2; + defparam _TECHMAP_REPLACE_.RMODE_B2_i = `MODE_2; + end + + 4: begin + assign PORT_A_ADDR = A1EN ? (A1ADDR_TOTAL << 5) : (B1EN ? (B1ADDR_TOTAL << 5) : 15'd0); + assign PORT_B_ADDR = C1EN ? (C1ADDR_TOTAL << 5) : (D1EN ? (D1ADDR_TOTAL << 5) : 15'd0); + defparam _TECHMAP_REPLACE_.WMODE_A1_i = `MODE_4; + defparam _TECHMAP_REPLACE_.WMODE_A2_i = `MODE_4; + defparam _TECHMAP_REPLACE_.RMODE_A1_i = `MODE_4; + defparam _TECHMAP_REPLACE_.RMODE_A2_i = `MODE_4; + defparam _TECHMAP_REPLACE_.WMODE_B1_i = `MODE_4; + defparam _TECHMAP_REPLACE_.WMODE_B2_i = `MODE_4; + defparam _TECHMAP_REPLACE_.RMODE_B1_i = `MODE_4; + defparam _TECHMAP_REPLACE_.RMODE_B2_i = `MODE_4; + end + + 8, 9: begin + assign PORT_A_ADDR = A1EN ? (A1ADDR_TOTAL << 3) : (B1EN ? (B1ADDR_TOTAL << 3) : 15'd0); + assign PORT_B_ADDR = C1EN ? (C1ADDR_TOTAL << 3) : (D1EN ? (D1ADDR_TOTAL << 3) : 15'd0); + defparam _TECHMAP_REPLACE_.WMODE_A1_i = `MODE_9; + defparam _TECHMAP_REPLACE_.WMODE_A2_i = `MODE_9; + defparam _TECHMAP_REPLACE_.RMODE_A1_i = `MODE_9; + defparam _TECHMAP_REPLACE_.RMODE_A2_i = `MODE_9; + defparam _TECHMAP_REPLACE_.WMODE_B1_i = `MODE_9; + defparam _TECHMAP_REPLACE_.WMODE_B2_i = `MODE_9; + defparam _TECHMAP_REPLACE_.RMODE_B1_i = `MODE_9; + defparam _TECHMAP_REPLACE_.RMODE_B2_i = `MODE_9; + end + + 16, 18: begin + assign PORT_A_ADDR = A1EN ? (A1ADDR_TOTAL << 4) : (B1EN ? (B1ADDR_TOTAL << 4) : 15'd0); + assign PORT_B_ADDR = C1EN ? (C1ADDR_TOTAL << 4) : (D1EN ? (D1ADDR_TOTAL << 4) : 15'd0); + defparam _TECHMAP_REPLACE_.WMODE_A1_i = `MODE_18; + defparam _TECHMAP_REPLACE_.WMODE_A2_i = `MODE_18; + defparam _TECHMAP_REPLACE_.RMODE_A1_i = `MODE_18; + defparam _TECHMAP_REPLACE_.RMODE_A2_i = `MODE_18; + defparam _TECHMAP_REPLACE_.WMODE_B1_i = `MODE_18; + defparam _TECHMAP_REPLACE_.WMODE_B2_i = `MODE_18; + defparam _TECHMAP_REPLACE_.RMODE_B1_i = `MODE_18; + defparam _TECHMAP_REPLACE_.RMODE_B2_i = `MODE_18; + end + + 32, 36: begin + assign PORT_A_ADDR = A1EN ? (A1ADDR_TOTAL << 5) : (B1EN ? (B1ADDR_TOTAL << 5) : 15'd0); + assign PORT_B_ADDR = C1EN ? (C1ADDR_TOTAL << 5) : (D1EN ? (D1ADDR_TOTAL << 5) : 15'd0); + defparam _TECHMAP_REPLACE_.WMODE_A1_i = `MODE_36; + defparam _TECHMAP_REPLACE_.WMODE_A2_i = `MODE_36; + defparam _TECHMAP_REPLACE_.RMODE_A1_i = `MODE_36; + defparam _TECHMAP_REPLACE_.RMODE_A2_i = `MODE_36; + defparam _TECHMAP_REPLACE_.WMODE_B1_i = `MODE_36; + defparam _TECHMAP_REPLACE_.WMODE_B2_i = `MODE_36; + defparam _TECHMAP_REPLACE_.RMODE_B1_i = `MODE_36; + defparam _TECHMAP_REPLACE_.RMODE_B2_i = `MODE_36; + end + default: begin + assign PORT_A_ADDR = A1EN ? A1ADDR_TOTAL : (B1EN ? B1ADDR_TOTAL : 15'd0); + assign PORT_B_ADDR = C1EN ? C1ADDR_TOTAL : (D1EN ? D1ADDR_TOTAL : 15'd0); + defparam _TECHMAP_REPLACE_.WMODE_A1_i = `MODE_36; + defparam _TECHMAP_REPLACE_.WMODE_A2_i = `MODE_36; + defparam _TECHMAP_REPLACE_.RMODE_A1_i = `MODE_36; + defparam _TECHMAP_REPLACE_.RMODE_A2_i = `MODE_36; + defparam _TECHMAP_REPLACE_.WMODE_B1_i = `MODE_36; + defparam _TECHMAP_REPLACE_.WMODE_B2_i = `MODE_36; + defparam _TECHMAP_REPLACE_.RMODE_B1_i = `MODE_36; + defparam _TECHMAP_REPLACE_.RMODE_B2_i = `MODE_36; + end + endcase + + + assign SPLIT = 1'b0; + assign FLUSH1 = 1'b0; + assign FLUSH2 = 1'b0; + assign RAM_ID = 16'b0; + + assign PL_INIT_i = 1'b0; + assign PL_ENA_i = 1'b0; + assign PL_REN_i = 1'b0; + assign PL_CLK_i = 1'b0; + assign PL_WEN_i = 2'b0; + assign PL_ADDR_i = 24'b0; + assign PL_DATA_i = 36'b0; + + TDP_BRAM36 #( + .UPAE1_i(12'd10), + .UPAF1_i(12'd10), + .UPAE2_i(12'd10), + .UPAF2_i(12'd10), + .SYNC_FIFO1_i(1'b0), + .SYNC_FIFO2_i(1'b0), + .FMODE1_i(1'b0), + .FMODE2_i(1'b0), + .POWERDN1_i(1'b0), + .POWERDN2_i(1'b0), + .SLEEP1_i(1'b0), + .SLEEP2_i(1'b0), + .PROTECT1_i(1'b0), + .PROTECT2_i(1'b0), + .SPLIT_i(1'b0) + ) _TECHMAP_REPLACE_ ( + .WDATA_A1_i(B1DATA[17:0]), + .WDATA_A2_i(B1DATA[35:18]), + .RDATA_A1_o(A1DATA_TOTAL[17:0]), + .RDATA_A2_o(A1DATA_TOTAL[35:18]), + .ADDR_A1_i(PORT_A_ADDR), + .ADDR_A2_i(PORT_A_ADDR), + .CLK_A1_i(CLK1), + .CLK_A2_i(CLK1), + .REN_A1_i(A1EN), + .REN_A2_i(A1EN), + .WEN_A1_i(B1EN[0]), + .WEN_A2_i(B1EN[0]), + .BE_A1_i({B1EN[1],B1EN[0]}), + .BE_A2_i({B1EN[3],B1EN[2]}), + + .WDATA_B1_i(D1DATA[17:0]), + .WDATA_B2_i(D1DATA[35:18]), + .RDATA_B1_o(C1DATA_TOTAL[17:0]), + .RDATA_B2_o(C1DATA_TOTAL[35:18]), + .ADDR_B1_i(PORT_B_ADDR), + .ADDR_B2_i(PORT_B_ADDR), + .CLK_B1_i(CLK2), + .CLK_B2_i(CLK2), + .REN_B1_i(C1EN), + .REN_B2_i(C1EN), + .WEN_B1_i(D1EN[0]), + .WEN_B2_i(D1EN[0]), + .BE_B1_i({D1EN[1],D1EN[0]}), + .BE_B2_i({D1EN[3],D1EN[2]}), + + .FLUSH1_i(FLUSH1), + .FLUSH2_i(FLUSH2), + .RAM_ID_i(RAM_ID), + + .PL_INIT_i(PL_INIT_i), + .PL_ENA_i(PL_ENA_i), + .PL_WEN_i(PL_WEN_i), + .PL_REN_i(PL_REN_i), + .PL_CLK_i(PL_CLK_i), + .PL_ADDR_i(PL_ADDR_i), + .PL_DATA_i(PL_DATA_i), + .PL_INIT_o(PL_INIT_o), + .PL_ENA_o(PL_ENA_o), + .PL_WEN_o(PL_WEN_o), + .PL_REN_o(PL_REN_o), + .PL_CLK_o(PL_CLK_o), + .PL_ADDR_o(), + .PL_DATA_o(PL_DATA_o) + + ); endmodule // ------------------------------------------------------------------------
diff --git a/ql-qlf-plugin/qlf_k6n10f/cells_sim.v b/ql-qlf-plugin/qlf_k6n10f/cells_sim.v index ad84b3f..6dac58b 100644 --- a/ql-qlf-plugin/qlf_k6n10f/cells_sim.v +++ b/ql-qlf-plugin/qlf_k6n10f/cells_sim.v
@@ -503,17 +503,6 @@ RDATA_A1_o, RDATA_B1_o, FLUSH1_i, - SYNC_FIFO1_i, - RMODE_A1_i, - RMODE_B1_i, - WMODE_A1_i, - WMODE_B1_i, - FMODE1_i, - POWERDN1_i, - SLEEP1_i, - PROTECT1_i, - UPAE1_i, - UPAF1_i, WEN_A2_i, WEN_B2_i, REN_A2_i, @@ -529,18 +518,6 @@ RDATA_A2_o, RDATA_B2_o, FLUSH2_i, - SYNC_FIFO2_i, - RMODE_A2_i, - RMODE_B2_i, - WMODE_A2_i, - WMODE_B2_i, - FMODE2_i, - POWERDN2_i, - SLEEP2_i, - PROTECT2_i, - UPAE2_i, - UPAF2_i, - SPLIT_i, RAM_ID_i, PL_INIT_i, PL_ENA_i, @@ -557,6 +534,32 @@ PL_ADDR_o, PL_DATA_o ); + parameter SYNC_FIFO1_i = 1'b0; + parameter RMODE_A1_i = 3'b0; + parameter RMODE_B1_i = 3'b0; + parameter WMODE_A1_i = 3'b0; + parameter WMODE_B1_i = 3'b0; + parameter FMODE1_i = 1'b0; + parameter POWERDN1_i = 1'b0; + parameter SLEEP1_i = 1'b0; + parameter PROTECT1_i = 1'b0; + parameter UPAE1_i = 12'b0; + parameter UPAF1_i = 12'b0; + + parameter SYNC_FIFO2_i = 1'b0; + parameter RMODE_A2_i = 3'b0; + parameter RMODE_B2_i = 3'b0; + parameter WMODE_A2_i = 3'b0; + parameter WMODE_B2_i = 3'b0; + parameter FMODE2_i = 1'b0; + parameter POWERDN2_i = 1'b0; + parameter SLEEP2_i = 1'b0; + parameter PROTECT2_i = 1'b0; + parameter UPAE2_i = 12'b0; + parameter UPAF2_i = 12'b0; + + parameter SPLIT_i = 1'b0; + parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000; parameter INITP_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000; parameter INITP_02 = 256'h0000000000000000000000000000000000000000000000000000000000000000; @@ -719,17 +722,6 @@ output reg [17:0] RDATA_A1_o; output reg [17:0] RDATA_B1_o; input wire FLUSH1_i; - input wire SYNC_FIFO1_i; - input wire [2:0] RMODE_A1_i; - input wire [2:0] RMODE_B1_i; - input wire [2:0] WMODE_A1_i; - input wire [2:0] WMODE_B1_i; - input wire FMODE1_i; - input wire POWERDN1_i; - input wire SLEEP1_i; - input wire PROTECT1_i; - input wire [11:0] UPAE1_i; - input wire [11:0] UPAF1_i; input wire WEN_A2_i; input wire WEN_B2_i; input wire REN_A2_i; @@ -747,19 +739,7 @@ output reg [17:0] RDATA_A2_o; output reg [17:0] RDATA_B2_o; input wire FLUSH2_i; - input wire SYNC_FIFO2_i; - input wire [2:0] RMODE_A2_i; - input wire [2:0] RMODE_B2_i; - input wire [2:0] WMODE_A2_i; - input wire [2:0] WMODE_B2_i; - input wire FMODE2_i; - input wire POWERDN2_i; - input wire SLEEP2_i; - input wire PROTECT2_i; - input wire [10:0] UPAE2_i; - input wire [10:0] UPAF2_i; - input SPLIT_i; - input [15:0] RAM_ID_i; + input wire [15:0] RAM_ID_i; input wire PL_INIT_i; input wire PL_ENA_i; input wire PL_REN_i; @@ -990,29 +970,27 @@ end endcase end - always @(*) - case (SPLIT_i) - 0: begin - ram_rmode_a1 = (RMODE_A1_i == MODE_36 ? MODE_18 : RMODE_A1_i); - ram_rmode_a2 = (RMODE_A1_i == MODE_36 ? MODE_18 : RMODE_A1_i); - ram_wmode_a1 = (WMODE_A1_i == MODE_36 ? MODE_18 : (FMODE1_i ? MODE_18 : WMODE_A1_i)); - ram_wmode_a2 = (WMODE_A1_i == MODE_36 ? MODE_18 : (FMODE1_i ? MODE_18 : WMODE_A1_i)); - ram_rmode_b1 = (RMODE_B1_i == MODE_36 ? MODE_18 : (FMODE1_i ? MODE_18 : RMODE_B1_i)); - ram_rmode_b2 = (RMODE_B1_i == MODE_36 ? MODE_18 : (FMODE1_i ? MODE_18 : RMODE_B1_i)); - ram_wmode_b1 = (WMODE_B1_i == MODE_36 ? MODE_18 : WMODE_B1_i); - ram_wmode_b2 = (WMODE_B1_i == MODE_36 ? MODE_18 : WMODE_B1_i); - end - 1: begin - ram_rmode_a1 = (RMODE_A1_i == MODE_36 ? MODE_18 : RMODE_A1_i); - ram_rmode_a2 = (RMODE_A2_i == MODE_36 ? MODE_18 : RMODE_A2_i); - ram_wmode_a1 = (WMODE_A1_i == MODE_36 ? MODE_18 : WMODE_A1_i); - ram_wmode_a2 = (WMODE_A2_i == MODE_36 ? MODE_18 : WMODE_A2_i); - ram_rmode_b1 = (RMODE_B1_i == MODE_36 ? MODE_18 : RMODE_B1_i); - ram_rmode_b2 = (RMODE_B2_i == MODE_36 ? MODE_18 : RMODE_B2_i); - ram_wmode_b1 = (WMODE_B1_i == MODE_36 ? MODE_18 : WMODE_B1_i); - ram_wmode_b2 = (WMODE_B2_i == MODE_36 ? MODE_18 : WMODE_B2_i); - end - endcase + always @(posedge CLK_A1_i or posedge CLK_B1_i or posedge CLK_A2_i or posedge CLK_B2_i) begin + if (!SPLIT_i) begin + ram_rmode_a1 <= (RMODE_A1_i == MODE_36 ? MODE_18 : RMODE_A1_i); + ram_rmode_a2 <= (RMODE_A1_i == MODE_36 ? MODE_18 : RMODE_A1_i); + ram_wmode_a1 <= (WMODE_A1_i == MODE_36 ? MODE_18 : (FMODE1_i ? MODE_18 : WMODE_A1_i)); + ram_wmode_a2 <= (WMODE_A1_i == MODE_36 ? MODE_18 : (FMODE1_i ? MODE_18 : WMODE_A1_i)); + ram_rmode_b1 <= (RMODE_B1_i == MODE_36 ? MODE_18 : (FMODE1_i ? MODE_18 : RMODE_B1_i)); + ram_rmode_b2 <= (RMODE_B1_i == MODE_36 ? MODE_18 : (FMODE1_i ? MODE_18 : RMODE_B1_i)); + ram_wmode_b1 <= (WMODE_B1_i == MODE_36 ? MODE_18 : WMODE_B1_i); + ram_wmode_b2 <= (WMODE_B1_i == MODE_36 ? MODE_18 : WMODE_B1_i); + end else begin + ram_rmode_a1 <= (RMODE_A1_i == MODE_36 ? MODE_18 : RMODE_A1_i); + ram_rmode_a2 <= (RMODE_A2_i == MODE_36 ? MODE_18 : RMODE_A2_i); + ram_wmode_a1 <= (WMODE_A1_i == MODE_36 ? MODE_18 : WMODE_A1_i); + ram_wmode_a2 <= (WMODE_A2_i == MODE_36 ? MODE_18 : WMODE_A2_i); + ram_rmode_b1 <= (RMODE_B1_i == MODE_36 ? MODE_18 : RMODE_B1_i); + ram_rmode_b2 <= (RMODE_B2_i == MODE_36 ? MODE_18 : RMODE_B2_i); + ram_wmode_b1 <= (WMODE_B1_i == MODE_36 ? MODE_18 : WMODE_B1_i); + ram_wmode_b2 <= (WMODE_B2_i == MODE_36 ? MODE_18 : WMODE_B2_i); + end + end always @(*) begin : FIFO_READ_SEL case (RMODE_B1_i) MODE_36: fifo_rdata = {ram_rdata_b2[17:16], ram_rdata_b1[17:16], ram_rdata_b2[15:0], ram_rdata_b1[15:0]}; @@ -1115,19 +1093,24 @@ end always @(posedge CLK_A1_i) laddr_a1 <= ADDR_A1_i; always @(posedge CLK_B1_i) laddr_b1 <= ADDR_B1_i; - always @(*) begin - case (WMODE_A1_i) - default: fifo_wmode = 2'b00; - MODE_36: fifo_wmode = 2'b00; - MODE_18: fifo_wmode = 2'b01; - MODE_9: fifo_wmode = 2'b10; - endcase - case (RMODE_B1_i) - default: fifo_rmode = 2'b00; - MODE_36: fifo_rmode = 2'b00; - MODE_18: fifo_rmode = 2'b01; - MODE_9: fifo_rmode = 2'b10; - endcase + always @(posedge CLK_A1_i or posedge CLK_B1_i or posedge CLK_A2_i or posedge CLK_B2_i) begin + if (WMODE_A1_i == MODE_36) + fifo_wmode = 2'b00; + else if (WMODE_A1_i == MODE_18) + fifo_wmode = 2'b01; + else if (WMODE_A1_i == MODE_9) + fifo_wmode = 2'b10; + else + fifo_wmode = 2'b00; + + if (RMODE_B1_i == MODE_36) + fifo_rmode = 2'b00; + else if (RMODE_B1_i == MODE_18) + fifo_rmode = 2'b01; + else if (RMODE_B1_i == MODE_9) + fifo_rmode = 2'b10; + else + fifo_rmode = 2'b00; end fifo_ctl #( .ADDR_WIDTH(12), @@ -1150,7 +1133,14 @@ .upaf(UPAF1_i), .upae(UPAE1_i) ); - TDP18K_FIFO u1( + TDP18K_FIFO #( + .UPAF(UPAF1_i[10:0]), + .UPAE(UPAE1_i[10:0]), + .SYNC_FIFO(SYNC_FIFO1_i), + .POWERDN(POWERDN1_i), + .SLEEP(SLEEP1_i), + .PROTECT(PROTECT1_i) + )u1( .RMODE_A(ram_rmode_a1), .RMODE_B(ram_rmode_b1), .WMODE_A(ram_wmode_a1), @@ -1178,13 +1168,8 @@ .FWM(FWM1), .OVERRUN(OVERRUN1), .FLUSH(FLUSH1_i), + .RAM_ID({RAM_ID_i}), .FMODE(ram_fmode1), - .UPAF(UPAF1_i[10:0]), - .UPAE(UPAE1_i[10:0]), - .SYNC_FIFO(SYNC_FIFO1_i), - .POWERDN(POWERDN1_i), - .SLEEP(SLEEP1_i), - .PROTECT(PROTECT1_i), .PL_INIT(PL_INIT_i), .PL_ENA(PL_ENA_i), .PL_WEN(PL_WEN_i[0]), @@ -1192,10 +1177,16 @@ .PL_CLK(PL_CLK_i), .PL_ADDR(PL_ADDR_i), .PL_DATA_IN({PL_DATA_i[33:32], PL_DATA_i[15:0]}), - .PL_DATA_OUT(pl_dout0), - .RAM_ID({RAM_ID_i}) + .PL_DATA_OUT(pl_dout0) ); - TDP18K_FIFO u2( + TDP18K_FIFO #( + .UPAF(UPAF2_i[10:0]), + .UPAE(UPAE2_i[10:0]), + .SYNC_FIFO(SYNC_FIFO2_i), + .POWERDN(POWERDN2_i), + .SLEEP(SLEEP2_i), + .PROTECT(PROTECT2_i) + )u2( .RMODE_A(ram_rmode_a2), .RMODE_B(ram_rmode_b2), .WMODE_A(ram_wmode_a2), @@ -1223,13 +1214,8 @@ .FWM(FWM2), .OVERRUN(OVERRUN2), .FLUSH(FLUSH2_i), + .RAM_ID({RAM_ID_i}), .FMODE(ram_fmode2), - .UPAF(UPAF2_i), - .UPAE(UPAE2_i), - .SYNC_FIFO(SYNC_FIFO2_i), - .POWERDN(POWERDN2_i), - .SLEEP(SLEEP2_i), - .PROTECT(PROTECT2_i), .PL_INIT(PL_INIT_i), .PL_ENA(PL_ENA_i), .PL_WEN(PL_WEN_i[1]), @@ -1237,8 +1223,7 @@ .PL_CLK(PL_CLK_i), .PL_ADDR(PL_ADDR_i), .PL_DATA_IN({PL_DATA_i[35:34], PL_DATA_i[31:16]}), - .PL_DATA_OUT(pl_dout1), - .RAM_ID(RAM_ID_i) + .PL_DATA_OUT(pl_dout1) ); always @(*) begin if (RAM_ID_i == PL_ADDR_i[31:16])
diff --git a/ql-qlf-plugin/tests/Makefile b/ql-qlf-plugin/tests/Makefile index 77938e3..21b68b6 100644 --- a/ql-qlf-plugin/tests/Makefile +++ b/ql-qlf-plugin/tests/Makefile
@@ -23,7 +23,7 @@ pp3_bram \ qlf_k6n10f/dsp_mult \ qlf_k6n10f/dsp_simd \ - qlf_k6n10f/dsp_macc + qlf_k6n10f/dsp_macc \ # qlf_k6n10_bram \ SIM_TESTS = \ @@ -31,6 +31,10 @@ qlf_k6n10f/sim_dsp_mult_r \ qlf_k6n10f/sim_dsp_fir +# Those tests perform synthesis and simulation of synthesis results +POST_SYNTH_SIM_TESTS = \ + qlf_k6n10f/bram_tdp + include $(shell pwd)/../../Makefile_test.common consts_verify = true
diff --git a/ql-qlf-plugin/tests/qlf_k6n10f/bram_tdp/bram_tdp.tcl b/ql-qlf-plugin/tests/qlf_k6n10f/bram_tdp/bram_tdp.tcl new file mode 100644 index 0000000..f3a5349 --- /dev/null +++ b/ql-qlf-plugin/tests/qlf_k6n10f/bram_tdp/bram_tdp.tcl
@@ -0,0 +1,50 @@ +yosys -import + +if { [info procs ql-qlf-k6n10f] == {} } { plugin -i ql-qlf } +yosys -import ; + +read_verilog $::env(DESIGN_TOP).v +design -save bram_tdp + +select BRAM_TDP_32x512 +select * +synth_quicklogic -family qlf_k6n10f -top BRAM_TDP_32x512 +opt_expr -undriven +opt_clean +stat +write_verilog sim/bram_tdp_32x512_post_synth.v +select -assert-count 1 t:TDP_BRAM36 + +select -clear +design -load bram_tdp +select BRAM_TDP_16x1024 +select * +synth_quicklogic -family qlf_k6n10f -top BRAM_TDP_16x1024 +opt_expr -undriven +opt_clean +stat +write_verilog sim/bram_tdp_16x1024_post_synth.v +select -assert-count 1 t:TDP_BRAM36 + +select -clear +design -load bram_tdp +select BRAM_TDP_8x2048 +select * +synth_quicklogic -family qlf_k6n10f -top BRAM_TDP_8x2048 +opt_expr -undriven +opt_clean +stat +write_verilog sim/bram_tdp_8x2048_post_synth.v +select -assert-count 1 t:TDP_BRAM36 + +select -clear +design -load bram_tdp +select BRAM_TDP_4x4096 +select * +synth_quicklogic -family qlf_k6n10f -top BRAM_TDP_4x4096 +opt_expr -undriven +opt_clean +stat +write_verilog sim/bram_tdp_4x4096_post_synth.v +select -assert-count 1 t:TDP_BRAM36 +
diff --git a/ql-qlf-plugin/tests/qlf_k6n10f/bram_tdp/bram_tdp.v b/ql-qlf-plugin/tests/qlf_k6n10f/bram_tdp/bram_tdp.v new file mode 100644 index 0000000..3486fa2 --- /dev/null +++ b/ql-qlf-plugin/tests/qlf_k6n10f/bram_tdp/bram_tdp.v
@@ -0,0 +1,284 @@ +// Copyright (C) 2022 The SymbiFlow Authors. +// +// Use of this source code is governed by a ISC-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/ISC +// +// SPDX-License-Identifier:ISC + +module BRAM_TDP #(parameter AWIDTH = 9, +parameter DWIDTH = 32)( + clk_a, + rce_a, + ra_a, + rq_a, + wce_a, + wa_a, + wd_a, + + clk_b, + rce_b, + ra_b, + rq_b, + wce_b, + wa_b, + wd_b +); + + input clk_a; + input rce_a; + input [AWIDTH-1:0] ra_a; + output reg [DWIDTH-1:0] rq_a; + input wce_a; + input [AWIDTH-1:0] wa_a; + input [DWIDTH-1:0] wd_a; + + input clk_b; + input rce_b; + input [AWIDTH-1:0] ra_b; + output reg [DWIDTH-1:0] rq_b; + input wce_b; + input [AWIDTH-1:0] wa_b; + input [DWIDTH-1:0] wd_b; + + reg [DWIDTH-1:0] memory[0:(1<<AWIDTH)-1]; + + always @(posedge clk_a) begin + if (rce_a) + rq_a <= memory[ra_a]; + + if (wce_a) + memory[wa_a] <= wd_a; + end + + always @(posedge clk_b) begin + if (rce_b) + rq_b <= memory[ra_b]; + + if (wce_b) + memory[wa_b] <= wd_b; + end + + integer i; + initial + begin + for(i = 0; i < (1<<AWIDTH)-1; i = i + 1) + memory[i] = 0; + end + +endmodule + +module BRAM_TDP_32x512( + clk_a, + rce_a, + ra_a, + rq_a, + wce_a, + wa_a, + wd_a, + + clk_b, + rce_b, + ra_b, + rq_b, + wce_b, + wa_b, + wd_b +); + +parameter AWIDTH = 9; +parameter DWIDTH = 32; + + input clk_a; + input rce_a; + input [AWIDTH-1:0] ra_a; + output [DWIDTH-1:0] rq_a; + input wce_a; + input [AWIDTH-1:0] wa_a; + input [DWIDTH-1:0] wd_a; + input clk_b; + input rce_b; + input [AWIDTH-1:0] ra_b; + output [DWIDTH-1:0] rq_b; + input wce_b; + input [AWIDTH-1:0] wa_b; + input [DWIDTH-1:0] wd_b; + +BRAM_TDP #(.AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) + BRAM_TDP_32x512 (.clk_a(clk_a), + .rce_a(rce_a), + .ra_a(ra_a), + .rq_a(rq_a), + .wce_a(wce_a), + .wa_a(wa_a), + .wd_a(wd_a), + .clk_b(clk_b), + .rce_b(rce_b), + .ra_b(ra_b), + .rq_b(rq_b), + .wce_b(wce_b), + .wa_b(wa_b), + .wd_b(wd_b)); + +endmodule + +module BRAM_TDP_16x1024( + clk_a, + rce_a, + ra_a, + rq_a, + wce_a, + wa_a, + wd_a, + clk_b, + rce_b, + ra_b, + rq_b, + wce_b, + wa_b, + wd_b +); + +parameter AWIDTH = 10; +parameter DWIDTH = 16; + + input clk_a; + input rce_a; + input [AWIDTH-1:0] ra_a; + output [DWIDTH-1:0] rq_a; + input wce_a; + input [AWIDTH-1:0] wa_a; + input [DWIDTH-1:0] wd_a; + + input clk_b; + input rce_b; + input [AWIDTH-1:0] ra_b; + output [DWIDTH-1:0] rq_b; + input wce_b; + input [AWIDTH-1:0] wa_b; + input [DWIDTH-1:0] wd_b; + +BRAM_TDP #(.AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) + BRAM_TDP_16x1024 (.clk_a(clk_a), + .rce_a(rce_a), + .ra_a(ra_a), + .rq_a(rq_a), + .wce_a(wce_a), + .wa_a(wa_a), + .wd_a(wd_a), + .clk_b(clk_b), + .rce_b(rce_b), + .ra_b(ra_b), + .rq_b(rq_b), + .wce_b(wce_b), + .wa_b(wa_b), + .wd_b(wd_b)); +endmodule + +module BRAM_TDP_8x2048( + clk_a, + rce_a, + ra_a, + rq_a, + wce_a, + wa_a, + wd_a, + + clk_b, + rce_b, + ra_b, + rq_b, + wce_b, + wa_b, + wd_b +); + +parameter AWIDTH = 11; +parameter DWIDTH = 8; + + input clk_a; + input rce_a; + input [AWIDTH-1:0] ra_a; + output [DWIDTH-1:0] rq_a; + input wce_a; + input [AWIDTH-1:0] wa_a; + input [DWIDTH-1:0] wd_a; + + input clk_b; + input rce_b; + input [AWIDTH-1:0] ra_b; + output [DWIDTH-1:0] rq_b; + input wce_b; + input [AWIDTH-1:0] wa_b; + input [DWIDTH-1:0] wd_b; + +BRAM_TDP #(.AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) + BRAM_TDP_8x2048 (.clk_a(clk_a), + .rce_a(rce_a), + .ra_a(ra_a), + .rq_a(rq_a), + .wce_a(wce_a), + .wa_a(wa_a), + .wd_a(wd_a), + .clk_b(clk_b), + .rce_b(rce_b), + .ra_b(ra_b), + .rq_b(rq_b), + .wce_b(wce_b), + .wa_b(wa_b), + .wd_b(wd_b)); +endmodule + +module BRAM_TDP_4x4096( + clk_a, + rce_a, + ra_a, + rq_a, + wce_a, + wa_a, + wd_a, + + clk_b, + rce_b, + ra_b, + rq_b, + wce_b, + wa_b, + wd_b +); + +parameter AWIDTH = 12; +parameter DWIDTH = 4; + + input clk_a; + input rce_a; + input [AWIDTH-1:0] ra_a; + output [DWIDTH-1:0] rq_a; + input wce_a; + input [AWIDTH-1:0] wa_a; + input [DWIDTH-1:0] wd_a; + + input clk_b; + input rce_b; + input [AWIDTH-1:0] ra_b; + output [DWIDTH-1:0] rq_b; + input wce_b; + input [AWIDTH-1:0] wa_b; + input [DWIDTH-1:0] wd_b; + +BRAM_TDP #(.AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) + BRAM_TDP_4x4096 (.clk_a(clk_a), + .rce_a(rce_a), + .ra_a(ra_a), + .rq_a(rq_a), + .wce_a(wce_a), + .wa_a(wa_a), + .wd_a(wd_a), + .clk_b(clk_b), + .rce_b(rce_b), + .ra_b(ra_b), + .rq_b(rq_b), + .wce_b(wce_b), + .wa_b(wa_b), + .wd_b(wd_b)); +endmodule
diff --git a/ql-qlf-plugin/tests/qlf_k6n10f/bram_tdp/sim/Makefile b/ql-qlf-plugin/tests/qlf_k6n10f/bram_tdp/sim/Makefile new file mode 100644 index 0000000..06b45cc --- /dev/null +++ b/ql-qlf-plugin/tests/qlf_k6n10f/bram_tdp/sim/Makefile
@@ -0,0 +1,35 @@ +# Copyright (C) 2022 The SymbiFlow Authors. +# +# Use of this source code is governed by a ISC-style +# license that can be found in the LICENSE file or at +# https://opensource.org/licenses/ISC +# +# SPDX-License-Identifier:ISC + +TESTBENCH = bram_tdp_tb.v +POST_SYNTH = bram_tdp_32x512_post_synth bram_tdp_16x1024_post_synth bram_tdp_8x2048_post_synth bram_tdp_4x4096_post_synth +ADDR_WIDTH = 9 10 11 12 +DATA_WIDTH = 32 16 8 4 +TOP = BRAM_TDP_32x512 BRAM_TDP_16x1024 BRAM_TDP_8x2048 BRAM_TDP_4x4096 +TEST_CASES = $(seq 0 3) +ADDR_DEFINES = $(foreach awidth, $(ADDR_WIDTH),-DADDR_WIDTH="$(awidth)") +DATA_DEFINES = $(foreach dwidth, $(DATA_WIDTH),-DDATA_WIDTH="$(dwidth)") +TOP_DEFINES = $(foreach top, $(TOP),-DTOP="$(top)") +VCD_DEFINES = $(foreach vcd, $(POST_SYNTH),-DVCD="$(vcd).vcd") + +SIM_LIBS = $(shell find ../../../../qlf_k6n10f -name "*.v" -not -name "*_map.v") + +define simulate_post_synth + @iverilog -vvvv -g2005 $(word $(1),$(ADDR_DEFINES)) $(word $(1),$(DATA_DEFINES)) $(word $(1),$(TOP_DEFINES)) $(word $(1),$(VCD_DEFINES)) -o $(word $(1),$(POST_SYNTH)).vvp $(word $(1),$(POST_SYNTH)).v $(SIM_LIBS) $(TESTBENCH) > $(word $(1),$(POST_SYNTH)).vvp.log 2>&1 + @vvp -vvvv $(word $(1),$(POST_SYNTH)).vvp > $(word $(1),$(POST_SYNTH)).vcd.log 2>&1 +endef + +define clean_post_synth_sim + @rm -rf $(word $(1),$(POST_SYNTH)).vcd $(word $(1),$(POST_SYNTH)).vvp $(word $(1),$(POST_SYNTH)).vvp.log $(word $(1),$(POST_SYNTH)).vcd.log +endef + +sim: + $(call simulate_post_synth,1) + $(call simulate_post_synth,2) + $(call simulate_post_synth,3) + $(call simulate_post_synth,4)
diff --git a/ql-qlf-plugin/tests/qlf_k6n10f/bram_tdp/sim/bram_tdp_tb.v b/ql-qlf-plugin/tests/qlf_k6n10f/bram_tdp/sim/bram_tdp_tb.v new file mode 100644 index 0000000..90cbf4e --- /dev/null +++ b/ql-qlf-plugin/tests/qlf_k6n10f/bram_tdp/sim/bram_tdp_tb.v
@@ -0,0 +1,227 @@ +// Copyright (C) 2022 The SymbiFlow Authors. +// +// Use of this source code is governed by a ISC-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/ISC +// +// SPDX-License-Identifier:ISC + +`timescale 1ns/1ps + +`define STRINGIFY(x) `"x`" + +module TB; + localparam PERIOD = 50; + localparam ADDR_INCR = 1; + + reg clk_a; + reg rce_a; + reg [`ADDR_WIDTH-1:0] ra_a; + wire [`DATA_WIDTH-1:0] rq_a; + reg wce_a; + reg [`ADDR_WIDTH-1:0] wa_a; + reg [`DATA_WIDTH-1:0] wd_a; + + reg clk_b; + reg rce_b; + reg [`ADDR_WIDTH-1:0] ra_b; + wire [`DATA_WIDTH-1:0] rq_b; + reg wce_b; + reg [`ADDR_WIDTH-1:0] wa_b; + reg [`DATA_WIDTH-1:0] wd_b; + + + initial clk_a = 0; + initial clk_b = 0; + initial ra_a = 0; + initial ra_b = 0; + initial rce_a = 0; + initial rce_b = 0; + initial forever #(PERIOD / 2.0) clk_a = ~clk_a; + initial begin + #(PERIOD / 4.0); + forever #(PERIOD / 2.0) clk_b = ~clk_b; + end + initial begin + $dumpfile(`STRINGIFY(`VCD)); + $dumpvars; + end + + integer a; + integer b; + + reg done_a; + reg done_b; + initial done_a = 1'b0; + initial done_b = 1'b0; + wire done_sim = done_a & done_b; + + reg [`DATA_WIDTH-1:0] expected_a; + reg [`DATA_WIDTH-1:0] expected_b; + + always @(posedge clk_a) begin + expected_a <= (a | (a << 20) | 20'h55000) & {`DATA_WIDTH{1'b1}}; + end + always @(posedge clk_b) begin + expected_b <= (b | (b << 20) | 20'h55000) & {`DATA_WIDTH{1'b1}}; + end + + wire error_a = a != 0 ? rq_a !== expected_a : 0; + wire error_b = b != (1<<`ADDR_WIDTH) / 2 ? rq_b !== expected_b : 0; + + integer error_a_cnt = 0; + integer error_b_cnt = 0; + + always @ (posedge clk_a) + begin + if (error_a) + error_a_cnt <= error_a_cnt + 1'b1; + end + always @ (posedge clk_b) + begin + if (error_b) + error_b_cnt <= error_b_cnt + 1'b1; + end + // PORT A + initial #(1) begin + // Write data + for (a = 0; a < (1<<`ADDR_WIDTH) / 2; a = a + ADDR_INCR) begin + @(negedge clk_a) begin + wa_a = a; + wd_a = a | (a << 20) | 20'h55000; + wce_a = 1; + end + @(posedge clk_a) begin + #(PERIOD/10) wce_a = 0; + end + end + // Read data + for (a = 0; a < (1<<`ADDR_WIDTH) / 2; a = a + ADDR_INCR) begin + @(negedge clk_a) begin + ra_a = a; + rce_a = 1; + end + @(posedge clk_a) begin + #(PERIOD/10) rce_a = 0; + if ( rq_a !== expected_a) begin + $display("%d: PORT A: FAIL: mismatch act=%x exp=%x at %x", $time, rq_a, expected_a, a); + end else begin + $display("%d: PORT A: OK: act=%x exp=%x at %x", $time, rq_a, expected_a, a); + end + end + end + done_a = 1'b1; + end + + // PORT B + initial #(1) begin + // Write data + for (b = (1<<`ADDR_WIDTH) / 2; b < (1<<`ADDR_WIDTH); b = b + ADDR_INCR) begin + @(negedge clk_b) begin + wa_b = b; + wd_b = b | (b << 20) | 20'h55000; + wce_b = 1; + end + @(posedge clk_b) begin + #(PERIOD/10) wce_b = 0; + end + end + // Read data + for (b = (1<<`ADDR_WIDTH) / 2; b < (1<<`ADDR_WIDTH); b = b + ADDR_INCR) begin + @(negedge clk_b) begin + ra_b = b; + rce_b = 1; + end + @(posedge clk_b) begin + #(PERIOD/10) rce_b = 0; + if ( rq_b !== expected_b) begin + $display("%d: PORT B: FAIL: mismatch act=%x exp=%x at %x", $time, rq_b, expected_b, b); + end else begin + $display("%d: PORT B: OK: act=%x exp=%x at %x", $time, rq_b, expected_b, b); + end + end + end + done_b = 1'b1; + end + + // Scan for simulation finish + always @(posedge clk_a, posedge clk_b) begin + if (done_sim) + $finish_and_return( (error_a_cnt == 0 & error_b_cnt == 0) ? 0 : -1 ); + end + + case (`STRINGIFY(`TOP)) + "BRAM_TDP_32x512": begin + BRAM_TDP_32x512 #() bram ( + .clk_a(clk_a), + .rce_a(rce_a), + .ra_a(ra_a), + .rq_a(rq_a), + .wce_a(wce_a), + .wa_a(wa_a), + .wd_a(wd_a), + .clk_b(clk_b), + .rce_b(rce_b), + .ra_b(ra_b), + .rq_b(rq_b), + .wce_b(wce_b), + .wa_b(wa_b), + .wd_b(wd_b) + ); + end + "BRAM_TDP_16x1024": begin + BRAM_TDP_16x1024 #() bram ( + .clk_a(clk_a), + .rce_a(rce_a), + .ra_a(ra_a), + .rq_a(rq_a), + .wce_a(wce_a), + .wa_a(wa_a), + .wd_a(wd_a), + .clk_b(clk_b), + .rce_b(rce_b), + .ra_b(ra_b), + .rq_b(rq_b), + .wce_b(wce_b), + .wa_b(wa_b), + .wd_b(wd_b) + ); + end + "BRAM_TDP_8x2048": begin + BRAM_TDP_8x2048 #() bram ( + .clk_a(clk_a), + .rce_a(rce_a), + .ra_a(ra_a), + .rq_a(rq_a), + .wce_a(wce_a), + .wa_a(wa_a), + .wd_a(wd_a), + .clk_b(clk_b), + .rce_b(rce_b), + .ra_b(ra_b), + .rq_b(rq_b), + .wce_b(wce_b), + .wa_b(wa_b), + .wd_b(wd_b) + ); + end + "BRAM_TDP_4x4096": begin + BRAM_TDP_4x4096 #() bram ( + .clk_a(clk_a), + .rce_a(rce_a), + .ra_a(ra_a), + .rq_a(rq_a), + .wce_a(wce_a), + .wa_a(wa_a), + .wd_a(wd_a), + .clk_b(clk_b), + .rce_b(rce_b), + .ra_b(ra_b), + .rq_b(rq_b), + .wce_b(wce_b), + .wa_b(wa_b), + .wd_b(wd_b) + ); + end + endcase +endmodule