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
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
.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
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
`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
) 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
`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
.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
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
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
$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
$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
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
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
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
else begin\r
assign B_DO = B_DO_out;\r
end\r
- endgenerate\r
+ endgenerate\r
endmodule\r