From 0d871b6c49b326315436fd8cdbd50b8d90a2990f Mon Sep 17 00:00:00 2001 From: Patrick Urban Date: Wed, 10 Nov 2021 16:18:13 +0100 Subject: [PATCH] synth_gatemate: Add block RAM cascade support * add simulation model for block RAM cascade in 40K mode * limit 20K_SDP and 40K_SDP to 40 and 80 bits (the only useful configurations) --- techlibs/gatemate/brams_map.v | 34 +++---- techlibs/gatemate/cells_sim.v | 174 +++++++++++++++++----------------- 2 files changed, 96 insertions(+), 112 deletions(-) diff --git a/techlibs/gatemate/brams_map.v b/techlibs/gatemate/brams_map.v index b7f0ff73e..2e5e1a5cc 100644 --- a/techlibs/gatemate/brams_map.v +++ b/techlibs/gatemate/brams_map.v @@ -50,19 +50,13 @@ module \$__CC_BRAM_20K_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1 wire [15:0] ADDRA = {A1ADDR, 7'b0}; wire [15:0] ADDRB = {B1ADDR, 7'b0}; - localparam INIT_CHUNK_SIZE = (CFG_DBITS <= 2) ? 256 : 320; + localparam INIT_CHUNK_SIZE = 320; function [319:0] permute_init; input [INIT_CHUNK_SIZE-1:0] chunk; integer i; begin - if (CFG_DBITS <= 2) begin - for (i = 0; i < 64; i = i + 1) begin - permute_init[i * 5 +: 5] = {1'b0, chunk[i * 4 +: 4]}; - end - end else begin - permute_init = chunk; - end + permute_init = chunk; end endfunction @@ -133,19 +127,13 @@ module \$__CC_BRAM_40K_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1 wire [15:0] ADDRA = {A1ADDR, 7'b0}; wire [15:0] ADDRB = {B1ADDR, 7'b0}; - localparam INIT_CHUNK_SIZE = (CFG_DBITS <= 2) ? 256 : 320; + localparam INIT_CHUNK_SIZE = 320; function [319:0] permute_init; input [INIT_CHUNK_SIZE-1:0] chunk; integer i; begin - if (CFG_DBITS <= 2) begin - for (i = 0; i < 64; i = i + 1) begin - permute_init[i * 5 +: 5] = {1'b0, chunk[i * 4 +: 4]}; - end - end else begin - permute_init = chunk; - end + permute_init = chunk; end endfunction @@ -173,7 +161,7 @@ module \$__CC_BRAM_40K_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1 .B_ECC_2B_ERR(B_ECC_2B_ERR), .A_CLK(CLK2), .B_CLK(CLK3), - .A_EN(|A1EN), + .A_EN(1'b1), .B_EN(B1EN), .A_WE(|A1EN), .B_WE(1'b0), @@ -440,7 +428,7 @@ module \$__CC_BRAM_CASCADE (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1 wire A_CAS, B_CAS; // unconnected signals - wire [39:0] A_UP_DO, A_LO_DO, B_LO_DO; + wire [39:0] A_UP_DO; wire A_ECC_1B_ERR, B_ECC_1B_ERR, A_ECC_2B_ERR, B_ECC_2B_ERR; localparam INIT_CHUNK_SIZE = 256; @@ -462,7 +450,7 @@ module \$__CC_BRAM_CASCADE (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1 `undef INIT_UPPER .LOC("UNPLACED"), .CAS("UPPER"), - .A_RD_WIDTH(0), .B_RD_WIDTH(CFG_DBITS), + .A_RD_WIDTH(CFG_DBITS), .B_RD_WIDTH(0), .A_WR_WIDTH(CFG_DBITS), .B_WR_WIDTH(0), .RAM_MODE("TDP"), .A_WR_MODE("NO_CHANGE"), .B_WR_MODE("NO_CHANGE"), @@ -474,8 +462,8 @@ module \$__CC_BRAM_CASCADE (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1 ) upper_cell ( .A_CI(A_CAS), .B_CI(B_CAS), - .A_DO(A_UP_DO), - .B_DO(B1DATA), + .A_DO(B1DATA), + .B_DO(A_UP_DO), .A_ECC_1B_ERR(A_ECC_1B_ERR), .B_ECC_1B_ERR(B_ECC_1B_ERR), .A_ECC_2B_ERR(A_ECC_2B_ERR), @@ -500,7 +488,7 @@ module \$__CC_BRAM_CASCADE (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1 `undef INIT_LOWER .LOC("UNPLACED"), .CAS("LOWER"), - .A_RD_WIDTH(0), .B_RD_WIDTH(CFG_DBITS), + .A_RD_WIDTH(CFG_DBITS), .B_RD_WIDTH(0), .A_WR_WIDTH(CFG_DBITS), .B_WR_WIDTH(0), .RAM_MODE("TDP"), .A_WR_MODE("NO_CHANGE"), .B_WR_MODE("NO_CHANGE"), @@ -510,7 +498,7 @@ module \$__CC_BRAM_CASCADE (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1 .A_DO_REG(1'b0), .B_DO_REG(1'b0), .A_ECC_EN(1'b0), .B_ECC_EN(1'b0) ) lower_cell ( - .A_CI(1'b1), + .A_CI(), .B_CI(), .A_CO(A_CAS), .B_CO(B_CAS), diff --git a/techlibs/gatemate/cells_sim.v b/techlibs/gatemate/cells_sim.v index 90b795d9d..1c7e40680 100644 --- a/techlibs/gatemate/cells_sim.v +++ b/techlibs/gatemate/cells_sim.v @@ -666,41 +666,11 @@ module CC_BRAM_20K ( generate if (RAM_MODE == "SDP") begin // Port A (write) - if (A_WR_WIDTH <= 1) begin - assign addra = A_ADDR[15:7] + (A_ADDR[15:7]/4); - end - else if (A_WR_WIDTH <= 2) begin - assign addra = A_ADDR[15:7]*2 + (A_ADDR[15:7]/2); - end - else if (A_WR_WIDTH <= 5) begin - assign addra = A_ADDR[15:7]*5; - end - else if (A_WR_WIDTH <= 10) begin - assign addra = A_ADDR[15:7]*10; - end - else if (A_WR_WIDTH <= 20) begin - assign addra = A_ADDR[15:7]*20; - end - else if (A_WR_WIDTH <= 40) begin + if (A_WR_WIDTH == 40) begin assign addra = A_ADDR[15:7]*40; end // Port B (read) - if (B_RD_WIDTH <= 1) begin - assign addrb = B_ADDR[15:7] + (B_ADDR[15:7]/4); - end - else if (B_RD_WIDTH <= 2) begin - assign addrb = B_ADDR[15:7]*2 + (B_ADDR[15:7]/2); - end - else if (B_RD_WIDTH <= 5) begin - assign addrb = B_ADDR[15:7]*5; - end - else if (B_RD_WIDTH <= 10) begin - assign addrb = B_ADDR[15:7]*10; - end - else if (B_RD_WIDTH <= 20) begin - assign addrb = B_ADDR[15:7]*20; - end - else if (B_RD_WIDTH <= 40) begin + if (B_RD_WIDTH == 40) begin assign addrb = B_ADDR[15:7]*40; end end @@ -849,8 +819,8 @@ module CC_BRAM_40K ( output B_ECC_1B_ERR, output A_ECC_2B_ERR, output B_ECC_2B_ERR, - output A_CO, - output B_CO, + output reg A_CO = 0, + output reg B_CO = 0, (* clkbuf_sink *) input A_CLK, (* clkbuf_sink *) @@ -1065,6 +1035,14 @@ module CC_BRAM_40K ( $display("ERROR: Port B width of 80 bits is only supported in SDP mode."); $finish(); end + if (((CAS == "UPPER") || (CAS == "LOWER")) && (WIDTH_MODE_A > 1)) begin + $display("ERROR: Port A cascade mode only supported in 1 bit mode."); + $finish(); + end + if (((CAS == "UPPER") || (CAS == "LOWER")) && (WIDTH_MODE_B > 1)) begin + $display("ERROR: Port B cascade mode only supported in 1 bit mode."); + $finish(); + end if ((WIDTH_MODE_A != 80) && (WIDTH_MODE_A != 40) && (WIDTH_MODE_A != 20) && (WIDTH_MODE_A != 10) && (WIDTH_MODE_A != 5) && (WIDTH_MODE_A != 2) && (WIDTH_MODE_A != 1) && (WIDTH_MODE_A != 0)) begin $display("ERROR: Illegal %s Port A width configuration %d.", RAM_MODE, WIDTH_MODE_A); @@ -1075,10 +1053,6 @@ module CC_BRAM_40K ( $display("ERROR: Illegal %s Port B width configuration %d.", RAM_MODE, WIDTH_MODE_B); $finish(); end - if (CAS != "NONE") begin - $display("WARNING: Cascade simulation model not yet supported."); - $finish(); - end if ((CAS != "NONE") && ((WIDTH_MODE_A > 1) || (WIDTH_MODE_B > 1))) begin $display("ERROR: Cascade feature only supported in 1 bit data width mode."); $finish(); @@ -1235,47 +1209,11 @@ module CC_BRAM_40K ( generate if (RAM_MODE == "SDP") begin // Port A (write) - if (A_WR_WIDTH <= 1) begin - assign addra = A_ADDR[15:7] + (A_ADDR[15:7]/4); - end - else if (A_WR_WIDTH <= 2) begin - assign addra = A_ADDR[15:7]*2 + (A_ADDR[15:7]/2); - end - else if (A_WR_WIDTH <= 5) begin - assign addra = A_ADDR[15:7]*5; - end - else if (A_WR_WIDTH <= 10) begin - assign addra = A_ADDR[15:7]*10; - end - else if (A_WR_WIDTH <= 20) begin - assign addra = A_ADDR[15:7]*20; - end - else if (A_WR_WIDTH <= 40) begin - assign addra = A_ADDR[15:7]*40; - end - else if (A_WR_WIDTH <= 80) begin + if (A_WR_WIDTH == 80) begin assign addra = A_ADDR[15:7]*80; end // Port B (read) - if (B_RD_WIDTH <= 1) begin - assign addrb = B_ADDR[15:7] + (B_ADDR[15:7]/4); - end - else if (B_RD_WIDTH <= 2) begin - assign addrb = B_ADDR[15:7]*2 + (B_ADDR[15:7]/2); - end - else if (B_RD_WIDTH <= 5) begin - assign addrb = B_ADDR[15:7]*5; - end - else if (B_RD_WIDTH <= 10) begin - assign addrb = B_ADDR[15:7]*10; - end - else if (B_RD_WIDTH <= 20) begin - assign addrb = B_ADDR[15:7]*20; - end - else if (B_RD_WIDTH <= 40) begin - assign addrb = B_ADDR[15:7]*40; - end - else if (B_RD_WIDTH <= 80) begin + if (B_RD_WIDTH == 80) begin assign addrb = B_ADDR[15:7]*80; end end @@ -1354,22 +1292,66 @@ module CC_BRAM_40K ( end end else if (RAM_MODE == "TDP") begin + // {A,B}_ADDR[0]=0 selects lower, {A,B}_ADDR[0]=1 selects upper cascade memory + wire upper_sel_a = ((CAS == "UPPER") && (A_ADDR[0] == 1)); + wire lower_sel_a = ((CAS == "LOWER") && (A_ADDR[0] == 0)); + wire upper_sel_b = ((CAS == "UPPER") && (B_ADDR[0] == 1)); + wire lower_sel_b = ((CAS == "LOWER") && (B_ADDR[0] == 0)); + + reg dumm; + + // Cascade output port A + always @(*) + begin + if ((A_WR_MODE == "NO_CHANGE") && lower_sel_a) begin + A_CO = memory[addra]; + end + else if ((A_WR_MODE == "WRITE_THROUGH") && lower_sel_a) begin + A_CO = ((wea && A_BM[0]) ? (A_DI[0]) : (memory[addra])); + end + end + + // Cascade output port B + always @(*) + begin + if ((B_WR_MODE == "NO_CHANGE") && lower_sel_b) begin + B_CO = memory[addrb]; + end + else if ((B_WR_MODE == "WRITE_THROUGH") && lower_sel_b) begin + B_CO = ((web && B_BM[0]) ? (B_DI[0]) : (memory[addrb])); + end + end + // TDP port A always @(posedge clka) begin for (i=0; i < WIDTH_MODE_A; i=i+1) begin - if (ena && wea && A_BM[i]) memory[addra+i] <= A_DI[i]; + if (upper_sel_a || lower_sel_a || (CAS == "NONE")) begin + if (ena && wea && A_BM[i]) + memory[addra+i] <= A_DI[i]; + end if (A_WR_MODE == "NO_CHANGE") begin - if (ena && !wea) A_DO_out[i] <= memory[addra+i]; + if (ena && !wea) begin + if (CAS == "UPPER") begin + A_DO_out[i] <= ((A_ADDR[0] == 1) ? (memory[addra+i]) : (A_CI)); + end + else if (CAS == "NONE") begin + A_DO_out[i] <= memory[addra+i]; + end + end end else if (A_WR_MODE == "WRITE_THROUGH") begin if (ena) begin - if (wea && A_BM[i]) begin - A_DO_out[i] <= A_DI[i]; + if (CAS == "UPPER") begin + if (A_ADDR[0] == 1) begin + A_DO_out[i] <= ((wea && A_BM[i]) ? (A_DI[i]) : (memory[addra+i])); + end else begin + A_DO_out[i] <= A_CI; + end end - else begin - A_DO_out[i] <= memory[addra+i]; + else if (CAS == "NONE") begin + A_DO_out[i] <= ((wea && A_BM[i]) ? (A_DI[i]) : (memory[addra+i])); end end end @@ -1379,18 +1361,32 @@ module CC_BRAM_40K ( always @(posedge clkb) begin for (i=0; i < WIDTH_MODE_B; i=i+1) begin - if (enb && web && B_BM[i]) memory[addrb+i] <= B_DI[i]; + if (upper_sel_b || lower_sel_b || (CAS == "NONE")) begin + if (enb && web && B_BM[i]) + memory[addrb+i] <= B_DI[i]; + end if (B_WR_MODE == "NO_CHANGE") begin - if (enb && !web) B_DO_out[i] <= memory[addrb+i]; + if (enb && !web) begin + if (CAS == "UPPER") begin + B_DO_out[i] <= ((B_ADDR[0] == 1) ? (memory[addrb+i]) : (B_CI)); + end + else if (CAS == "NONE") begin + B_DO_out[i] <= memory[addrb+i]; + end + end end else if (B_WR_MODE == "WRITE_THROUGH") begin if (enb) begin - if (web && B_BM[i]) begin - B_DO_out[i] <= B_DI[i]; + if (CAS == "UPPER") begin + if (B_ADDR[0] == 1) begin + B_DO_out[i] <= ((web && B_BM[i]) ? (B_DI[i]) : (memory[addrb+i])); + end else begin + B_DO_out[i] <= B_CI; + end end - else begin - B_DO_out[i] <= memory[addrb+i]; + else if (CAS == "NONE") begin + B_DO_out[i] <= ((web && B_BM[i]) ? (B_DI[i]) : (memory[addrb+i])); end end end @@ -1419,5 +1415,5 @@ module CC_BRAM_40K ( else begin assign B_DO = B_DO_out; end - endgenerate + endgenerate endmodule -- 2.30.2