synth_gatemate: Add block RAM cascade support
authorPatrick Urban <patrick.urban@web.de>
Wed, 10 Nov 2021 15:18:13 +0000 (16:18 +0100)
committerMarcelina Koƛcielnicka <mwk@0x04.net>
Sat, 13 Nov 2021 20:53:25 +0000 (21:53 +0100)
* 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
techlibs/gatemate/cells_sim.v

index b7f0ff73e83d900fd97ed9ca1aaa9de4a219293e..2e5e1a5ccf43252f88b18f7f708bf87a511d03a4 100644 (file)
@@ -50,19 +50,13 @@ module \$__CC_BRAM_20K_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1
        wire [15:0] ADDRA = {A1ADDR, 7'b0};\r
        wire [15:0] ADDRB = {B1ADDR, 7'b0};\r
 \r
-       localparam INIT_CHUNK_SIZE = (CFG_DBITS <= 2) ? 256 : 320;\r
+       localparam INIT_CHUNK_SIZE = 320;\r
 \r
        function [319:0] permute_init;\r
                input [INIT_CHUNK_SIZE-1:0] chunk;\r
                integer i;\r
                begin\r
-                       if (CFG_DBITS <= 2) begin\r
-                               for (i = 0; i < 64; i = i + 1) begin\r
-                                       permute_init[i * 5 +: 5] = {1'b0, chunk[i * 4 +: 4]};\r
-                               end\r
-                       end else begin\r
-                               permute_init = chunk;\r
-                       end\r
+                       permute_init = chunk;\r
                end\r
        endfunction\r
 \r
@@ -133,19 +127,13 @@ module \$__CC_BRAM_40K_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1
        wire [15:0] ADDRA = {A1ADDR, 7'b0};\r
        wire [15:0] ADDRB = {B1ADDR, 7'b0};\r
 \r
-       localparam INIT_CHUNK_SIZE = (CFG_DBITS <= 2) ? 256 : 320;\r
+       localparam INIT_CHUNK_SIZE = 320;\r
 \r
        function [319:0] permute_init;\r
                input [INIT_CHUNK_SIZE-1:0] chunk;\r
                integer i;\r
                begin\r
-                       if (CFG_DBITS <= 2) begin\r
-                               for (i = 0; i < 64; i = i + 1) begin\r
-                                       permute_init[i * 5 +: 5] = {1'b0, chunk[i * 4 +: 4]};\r
-                               end\r
-                       end else begin\r
-                               permute_init = chunk;\r
-                       end\r
+                       permute_init = chunk;\r
                end\r
        endfunction\r
 \r
@@ -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),\r
                .A_CLK(CLK2),\r
                .B_CLK(CLK3),\r
-               .A_EN(|A1EN),\r
+               .A_EN(1'b1),\r
                .B_EN(B1EN),\r
                .A_WE(|A1EN),\r
                .B_WE(1'b0),\r
@@ -440,7 +428,7 @@ module \$__CC_BRAM_CASCADE (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1
        wire A_CAS, B_CAS;\r
 \r
        // unconnected signals\r
-       wire [39:0] A_UP_DO, A_LO_DO, B_LO_DO;\r
+       wire [39:0] A_UP_DO;\r
        wire A_ECC_1B_ERR, B_ECC_1B_ERR, A_ECC_2B_ERR, B_ECC_2B_ERR;\r
 \r
        localparam INIT_CHUNK_SIZE = 256;\r
@@ -462,7 +450,7 @@ module \$__CC_BRAM_CASCADE (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1
                        `undef INIT_UPPER\r
                        .LOC("UNPLACED"),\r
                        .CAS("UPPER"),\r
-                       .A_RD_WIDTH(0), .B_RD_WIDTH(CFG_DBITS),\r
+                       .A_RD_WIDTH(CFG_DBITS), .B_RD_WIDTH(0),\r
                        .A_WR_WIDTH(CFG_DBITS), .B_WR_WIDTH(0),\r
                        .RAM_MODE("TDP"),\r
                        .A_WR_MODE("NO_CHANGE"), .B_WR_MODE("NO_CHANGE"),\r
@@ -474,8 +462,8 @@ module \$__CC_BRAM_CASCADE (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1
                ) upper_cell (\r
                        .A_CI(A_CAS),\r
                        .B_CI(B_CAS),\r
-                       .A_DO(A_UP_DO),\r
-                       .B_DO(B1DATA),\r
+                       .A_DO(B1DATA),\r
+                       .B_DO(A_UP_DO),\r
                        .A_ECC_1B_ERR(A_ECC_1B_ERR),\r
                        .B_ECC_1B_ERR(B_ECC_1B_ERR),\r
                        .A_ECC_2B_ERR(A_ECC_2B_ERR),\r
@@ -500,7 +488,7 @@ module \$__CC_BRAM_CASCADE (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1
                        `undef INIT_LOWER\r
                        .LOC("UNPLACED"),\r
                        .CAS("LOWER"),\r
-                       .A_RD_WIDTH(0), .B_RD_WIDTH(CFG_DBITS),\r
+                       .A_RD_WIDTH(CFG_DBITS), .B_RD_WIDTH(0),\r
                        .A_WR_WIDTH(CFG_DBITS), .B_WR_WIDTH(0),\r
                        .RAM_MODE("TDP"),\r
                        .A_WR_MODE("NO_CHANGE"), .B_WR_MODE("NO_CHANGE"),\r
@@ -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),\r
                        .A_ECC_EN(1'b0), .B_ECC_EN(1'b0)\r
                ) lower_cell (\r
-                       .A_CI(1'b1),\r
+                       .A_CI(),\r
                        .B_CI(),\r
                        .A_CO(A_CAS),\r
                        .B_CO(B_CAS),\r
index 90b795d9d38415cf16e567b1487dc83209b86ea1..1c7e40680abeb24625d0aa06dc212a085af3fd0b 100644 (file)
@@ -666,41 +666,11 @@ module CC_BRAM_20K (
        generate\r
                if (RAM_MODE == "SDP") begin\r
                        // Port A (write)\r
-                       if (A_WR_WIDTH <= 1) begin\r
-                               assign addra = A_ADDR[15:7] + (A_ADDR[15:7]/4);\r
-                       end\r
-                       else if (A_WR_WIDTH <= 2) begin\r
-                               assign addra = A_ADDR[15:7]*2 + (A_ADDR[15:7]/2);\r
-                       end\r
-                       else if (A_WR_WIDTH <= 5) begin\r
-                               assign addra = A_ADDR[15:7]*5;\r
-                       end\r
-                       else if (A_WR_WIDTH <= 10) begin\r
-                               assign addra = A_ADDR[15:7]*10;\r
-                       end\r
-                       else if (A_WR_WIDTH <= 20) begin\r
-                               assign addra = A_ADDR[15:7]*20;\r
-                       end\r
-                       else if (A_WR_WIDTH <= 40) begin\r
+                       if (A_WR_WIDTH == 40) begin\r
                                assign addra = A_ADDR[15:7]*40;\r
                        end\r
                        // Port B (read)\r
-                       if (B_RD_WIDTH <= 1) begin\r
-                               assign addrb = B_ADDR[15:7] + (B_ADDR[15:7]/4);\r
-                       end\r
-                       else if (B_RD_WIDTH <= 2) begin\r
-                               assign addrb = B_ADDR[15:7]*2 + (B_ADDR[15:7]/2);\r
-                       end\r
-                       else if (B_RD_WIDTH <= 5) begin\r
-                               assign addrb = B_ADDR[15:7]*5;\r
-                       end\r
-                       else if (B_RD_WIDTH <= 10) begin\r
-                               assign addrb = B_ADDR[15:7]*10;\r
-                       end\r
-                       else if (B_RD_WIDTH <= 20) begin\r
-                               assign addrb = B_ADDR[15:7]*20;\r
-                       end\r
-                       else if (B_RD_WIDTH <= 40) begin\r
+                       if (B_RD_WIDTH == 40) begin\r
                                assign addrb = B_ADDR[15:7]*40;\r
                        end\r
                end\r
@@ -849,8 +819,8 @@ module CC_BRAM_40K (
        output B_ECC_1B_ERR,\r
        output A_ECC_2B_ERR,\r
        output B_ECC_2B_ERR,\r
-       output A_CO,\r
-       output B_CO,\r
+       output reg A_CO = 0,\r
+       output reg B_CO = 0,\r
        (* clkbuf_sink *)\r
        input A_CLK,\r
        (* clkbuf_sink *)\r
@@ -1065,6 +1035,14 @@ module CC_BRAM_40K (
                        $display("ERROR: Port B width of 80 bits is only supported in SDP mode.");\r
                        $finish();\r
                end\r
+               if (((CAS == "UPPER") || (CAS == "LOWER")) && (WIDTH_MODE_A > 1)) begin\r
+                       $display("ERROR: Port A cascade mode only supported in 1 bit mode.");\r
+                       $finish();\r
+               end\r
+               if (((CAS == "UPPER") || (CAS == "LOWER")) && (WIDTH_MODE_B > 1)) begin\r
+                       $display("ERROR: Port B cascade mode only supported in 1 bit mode.");\r
+                       $finish();\r
+               end\r
                if ((WIDTH_MODE_A != 80) && (WIDTH_MODE_A != 40) && (WIDTH_MODE_A != 20) && (WIDTH_MODE_A != 10) &&\r
                        (WIDTH_MODE_A != 5)  && (WIDTH_MODE_A != 2)  && (WIDTH_MODE_A != 1) && (WIDTH_MODE_A != 0)) begin\r
                        $display("ERROR: Illegal %s Port A width configuration %d.", RAM_MODE, WIDTH_MODE_A);\r
@@ -1075,10 +1053,6 @@ module CC_BRAM_40K (
                        $display("ERROR: Illegal %s Port B width configuration %d.", RAM_MODE, WIDTH_MODE_B);\r
                        $finish();\r
                end\r
-               if (CAS != "NONE") begin\r
-                       $display("WARNING: Cascade simulation model not yet supported.");\r
-                       $finish();\r
-               end\r
                if ((CAS != "NONE") && ((WIDTH_MODE_A > 1) || (WIDTH_MODE_B > 1))) begin\r
                        $display("ERROR: Cascade feature only supported in 1 bit data width mode.");\r
                        $finish();\r
@@ -1235,47 +1209,11 @@ module CC_BRAM_40K (
        generate\r
                if (RAM_MODE == "SDP") begin\r
                        // Port A (write)\r
-                       if (A_WR_WIDTH <= 1) begin\r
-                               assign addra = A_ADDR[15:7] + (A_ADDR[15:7]/4);\r
-                       end\r
-                       else if (A_WR_WIDTH <= 2) begin\r
-                               assign addra = A_ADDR[15:7]*2 + (A_ADDR[15:7]/2);\r
-                       end\r
-                       else if (A_WR_WIDTH <= 5) begin\r
-                               assign addra = A_ADDR[15:7]*5;\r
-                       end\r
-                       else if (A_WR_WIDTH <= 10) begin\r
-                               assign addra = A_ADDR[15:7]*10;\r
-                       end\r
-                       else if (A_WR_WIDTH <= 20) begin\r
-                               assign addra = A_ADDR[15:7]*20;\r
-                       end\r
-                       else if (A_WR_WIDTH <= 40) begin\r
-                               assign addra = A_ADDR[15:7]*40;\r
-                       end\r
-                       else if (A_WR_WIDTH <= 80) begin\r
+                        if (A_WR_WIDTH == 80) begin\r
                                assign addra = A_ADDR[15:7]*80;\r
                        end\r
                        // Port B (read)\r
-                       if (B_RD_WIDTH <= 1) begin\r
-                               assign addrb = B_ADDR[15:7] + (B_ADDR[15:7]/4);\r
-                       end\r
-                       else if (B_RD_WIDTH <= 2) begin\r
-                               assign addrb = B_ADDR[15:7]*2 + (B_ADDR[15:7]/2);\r
-                       end\r
-                       else if (B_RD_WIDTH <= 5) begin\r
-                               assign addrb = B_ADDR[15:7]*5;\r
-                       end\r
-                       else if (B_RD_WIDTH <= 10) begin\r
-                               assign addrb = B_ADDR[15:7]*10;\r
-                       end\r
-                       else if (B_RD_WIDTH <= 20) begin\r
-                               assign addrb = B_ADDR[15:7]*20;\r
-                       end\r
-                       else if (B_RD_WIDTH <= 40) begin\r
-                               assign addrb = B_ADDR[15:7]*40;\r
-                       end\r
-                       else if (B_RD_WIDTH <= 80) begin\r
+                       if (B_RD_WIDTH == 80) begin\r
                                assign addrb = B_ADDR[15:7]*80;\r
                        end\r
                end\r
@@ -1354,22 +1292,66 @@ module CC_BRAM_40K (
                        end\r
                end\r
                else if (RAM_MODE == "TDP") begin\r
+                       // {A,B}_ADDR[0]=0 selects lower, {A,B}_ADDR[0]=1 selects upper cascade memory\r
+                       wire upper_sel_a = ((CAS == "UPPER") && (A_ADDR[0] == 1));\r
+                       wire lower_sel_a = ((CAS == "LOWER") && (A_ADDR[0] == 0));\r
+                       wire upper_sel_b = ((CAS == "UPPER") && (B_ADDR[0] == 1));\r
+                       wire lower_sel_b = ((CAS == "LOWER") && (B_ADDR[0] == 0));\r
+\r
+                       reg dumm;\r
+\r
+                       // Cascade output port A\r
+                       always @(*)\r
+                       begin\r
+                               if ((A_WR_MODE == "NO_CHANGE") && lower_sel_a) begin\r
+                                       A_CO = memory[addra];\r
+                               end\r
+                               else if ((A_WR_MODE == "WRITE_THROUGH") && lower_sel_a) begin\r
+                                       A_CO = ((wea && A_BM[0]) ? (A_DI[0]) : (memory[addra]));\r
+                               end\r
+                       end\r
+\r
+                       // Cascade output port B\r
+                       always @(*)\r
+                       begin\r
+                               if ((B_WR_MODE == "NO_CHANGE") && lower_sel_b) begin\r
+                                       B_CO = memory[addrb];\r
+                               end\r
+                               else if ((B_WR_MODE == "WRITE_THROUGH") && lower_sel_b) begin\r
+                                       B_CO = ((web && B_BM[0]) ? (B_DI[0]) : (memory[addrb]));\r
+                               end\r
+                       end\r
+\r
                        // TDP port A\r
                        always @(posedge clka)\r
                        begin\r
                                for (i=0; i < WIDTH_MODE_A; i=i+1) begin\r
-                                       if (ena && wea && A_BM[i]) memory[addra+i] <= A_DI[i];\r
+                                       if (upper_sel_a || lower_sel_a || (CAS == "NONE")) begin\r
+                                               if (ena && wea && A_BM[i])\r
+                                                       memory[addra+i] <= A_DI[i];\r
+                                       end\r
 \r
                                        if (A_WR_MODE == "NO_CHANGE") begin\r
-                                               if (ena && !wea) A_DO_out[i] <= memory[addra+i];\r
+                                               if (ena && !wea) begin\r
+                                                       if (CAS == "UPPER") begin\r
+                                                               A_DO_out[i] <= ((A_ADDR[0] == 1) ? (memory[addra+i]) : (A_CI));\r
+                                                       end\r
+                                                       else if (CAS == "NONE") begin\r
+                                                               A_DO_out[i] <= memory[addra+i];\r
+                                                       end\r
+                                               end\r
                                        end\r
                                        else if (A_WR_MODE == "WRITE_THROUGH") begin\r
                                                if (ena) begin\r
-                                                       if (wea && A_BM[i]) begin\r
-                                                               A_DO_out[i] <= A_DI[i];\r
+                                                       if (CAS == "UPPER") begin\r
+                                                               if (A_ADDR[0] == 1) begin\r
+                                                                       A_DO_out[i] <= ((wea && A_BM[i]) ? (A_DI[i]) : (memory[addra+i]));\r
+                                                               end else begin\r
+                                                                       A_DO_out[i] <= A_CI;\r
+                                                               end\r
                                                        end\r
-                                                       else begin\r
-                                                               A_DO_out[i] <= memory[addra+i];\r
+                                                       else if (CAS == "NONE") begin\r
+                                                               A_DO_out[i] <= ((wea && A_BM[i]) ? (A_DI[i]) : (memory[addra+i]));\r
                                                        end\r
                                                end\r
                                        end\r
@@ -1379,18 +1361,32 @@ module CC_BRAM_40K (
                        always @(posedge clkb)\r
                        begin\r
                                for (i=0; i < WIDTH_MODE_B; i=i+1) begin\r
-                                       if (enb && web && B_BM[i]) memory[addrb+i] <= B_DI[i];\r
+                                       if (upper_sel_b || lower_sel_b || (CAS == "NONE")) begin\r
+                                               if (enb && web && B_BM[i])\r
+                                                       memory[addrb+i] <= B_DI[i];\r
+                                       end\r
 \r
                                        if (B_WR_MODE == "NO_CHANGE") begin\r
-                                               if (enb && !web) B_DO_out[i] <= memory[addrb+i];\r
+                                               if (enb && !web) begin\r
+                                                       if (CAS == "UPPER") begin\r
+                                                               B_DO_out[i] <= ((B_ADDR[0] == 1) ? (memory[addrb+i]) : (B_CI));\r
+                                                       end\r
+                                                       else if (CAS == "NONE") begin\r
+                                                               B_DO_out[i] <= memory[addrb+i];\r
+                                                       end\r
+                                               end\r
                                        end\r
                                        else if (B_WR_MODE == "WRITE_THROUGH") begin\r
                                                if (enb) begin\r
-                                                       if (web && B_BM[i]) begin\r
-                                                               B_DO_out[i] <= B_DI[i];\r
+                                                       if (CAS == "UPPER") begin\r
+                                                               if (B_ADDR[0] == 1) begin\r
+                                                                       B_DO_out[i] <= ((web && B_BM[i]) ? (B_DI[i]) : (memory[addrb+i]));\r
+                                                               end else begin\r
+                                                                       B_DO_out[i] <= B_CI;\r
+                                                               end\r
                                                        end\r
-                                                       else begin\r
-                                                               B_DO_out[i] <= memory[addrb+i];\r
+                                                       else if (CAS == "NONE") begin\r
+                                                               B_DO_out[i] <= ((web && B_BM[i]) ? (B_DI[i]) : (memory[addrb+i]));\r
                                                        end\r
                                                end\r
                                        end\r
@@ -1419,5 +1415,5 @@ module CC_BRAM_40K (
                else begin\r
                        assign B_DO = B_DO_out;\r
                end\r
-   endgenerate\r
+       endgenerate\r
 endmodule\r