-
Notifications
You must be signed in to change notification settings - Fork 164
Open
Description
I tried to synthesize a module in Vivado, but I found that the synthesis result of BRAM2BE is not as expected.
As shown in the code, the synthesis results are compared below.
module test_bram_syn(
input clk,
input [7:0] ADDRA,
input [7:0] ADDRB,
input [15:0] DIA,
input [15:0] DIB,
input [1:0] WEA,
input ENA,
input ENB,
output [15:0] DOA,
output [15:0] DOB
);
wire [1:0] WEB;
assign WEB = 2'b11;
BRAM2BE #(.PIPELINED(1'd0),
.ADDR_WIDTH(32'd8),
.DATA_WIDTH(32'd16),
.CHUNKSIZE(32'd8),
.WE_WIDTH(32'd2),
.MEMSIZE(9'd256)) axil_bram_inst_1_bram_inst_memory(.CLKA(clk),
.CLKB(clk),
.ADDRA(ADDRA),
.ADDRB(ADDRB),
.DIA(DIA),
.DIB(DIB),
.WEA(WEA),
.WEB(WEB),
.ENA(ENA),
.ENB(ENB),
.DOA(DOA),
.DOB(DOB));
endmodule
Using original BRAM2BE.v from https://github.com/B-Lang-org/bsc/blob/main/src/Verilog.Vivado/BRAM2BE.v
Using modified BRAM2BE.v which references:
- Vivado Design Suite User Guide: Synthesis (UG901)
-- Byte Write Enable—True Dual Port with Byte-Wide Write Enable (Verilog)
`ifdef BSV_ASSIGNMENT_DELAY
`else
`define BSV_ASSIGNMENT_DELAY
`endif
// Dual-Ported BRAM (WRITE FIRST) with byte enables
module BRAM2BE(CLKA,
ENA,
WEA,
ADDRA,
DIA,
DOA,
CLKB,
ENB,
WEB,
ADDRB,
DIB,
DOB
);
parameter PIPELINED = 0;
parameter ADDR_WIDTH = 1;
parameter DATA_WIDTH = 1;
parameter CHUNKSIZE = 1;
parameter WE_WIDTH = 1;
parameter MEMSIZE = 1;
input CLKA;
input ENA;
input [WE_WIDTH-1:0] WEA;
input [ADDR_WIDTH-1:0] ADDRA;
input [DATA_WIDTH-1:0] DIA;
output [DATA_WIDTH-1:0] DOA;
input CLKB;
input ENB;
input [WE_WIDTH-1:0] WEB;
input [ADDR_WIDTH-1:0] ADDRB;
input [DATA_WIDTH-1:0] DIB;
output [DATA_WIDTH-1:0] DOB;
(* RAM_STYLE = "BLOCK" *)
reg [DATA_WIDTH-1:0] RAM[0:MEMSIZE-1] /* synthesis syn_ramstyle="no_rw_check" */ ;
reg [DATA_WIDTH-1:0] DOA_R;
reg [DATA_WIDTH-1:0] DOA_R2;
reg [DATA_WIDTH-1:0] DOB_R;
reg [DATA_WIDTH-1:0] DOB_R2;
`ifdef BSV_NO_INITIAL_BLOCKS
`else
// synopsys translate_off
integer i;
initial
begin : init_block
for (i = 0; i < MEMSIZE; i = i + 1) begin
RAM[i] = { ((DATA_WIDTH+1)/2) { 2'b10 } };
end
DOA_R = { ((DATA_WIDTH+1)/2) { 2'b10 } };
DOA_R2 = { ((DATA_WIDTH+1)/2) { 2'b10 } };
DOB_R = { ((DATA_WIDTH+1)/2) { 2'b10 } };
DOB_R2 = { ((DATA_WIDTH+1)/2) { 2'b10 } };
end
// synopsys translate_on
`endif // !`ifdef BSV_NO_INITIAL_BLOCKS
// PORT A
integer j;
always @(posedge CLKA) begin
if (ENA) begin
for(j = 0; j < WE_WIDTH; j = j + 1) begin: porta_we
if (WEA[j]) begin
RAM[ADDRA][j*CHUNKSIZE+:CHUNKSIZE] = `BSV_ASSIGNMENT_DELAY DIA[j*CHUNKSIZE+:CHUNKSIZE];
end
end
DOA_R = `BSV_ASSIGNMENT_DELAY RAM[ADDRA];
end
end
// PORT B
integer k;
always @(posedge CLKB) begin
if (ENB) begin
for(k = 0; k < WE_WIDTH; k = k + 1) begin: portb_we
if (WEB[k]) begin
RAM[ADDRB][k*CHUNKSIZE+:CHUNKSIZE] = `BSV_ASSIGNMENT_DELAY DIB[k*CHUNKSIZE+:CHUNKSIZE];
end
end
DOB_R = `BSV_ASSIGNMENT_DELAY RAM[ADDRB];
end
end
// Output drivers
always @(posedge CLKA) begin
DOA_R2 <= `BSV_ASSIGNMENT_DELAY DOA_R;
end
always @(posedge CLKB) begin
DOB_R2 <= `BSV_ASSIGNMENT_DELAY DOB_R;
end
assign DOA = (PIPELINED) ? DOA_R2 : DOA_R;
assign DOB = (PIPELINED) ? DOB_R2 : DOB_R;
endmodule // BRAM2BE
When the DATA_WIDTH is set to 16 and the WE_WIDTH is set to 2, the WE mapping on RAMB18E2 should be 'b11, but the result is only 'b1.
As a consequence, bits[15:8] cannot be written into the memory.
Strangely, when the DATA_WIDTH is set to 24, this problem does not occur.
Metadata
Metadata
Assignees
Labels
No labels