Skip to content

Unexpected BRAM2BE synthesis results in Vivado 2022.2 #777

@ChienTeLi

Description

@ChienTeLi

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

Image
Image

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

Image

Image

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

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions