UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

AR# 56457

Vivado Synthesis - Does Vivado Synthesis infer an optimal block RAM when both read address and the output data are registered in the HDL code?

Description

Vivado Synthesis does not infer an optimal block RAM when the true dual port block RAM has the structure as follows:

read address registered + memory-write + o/p registered this should infer block-ram with DOA/DOB set to 1

Vivado Synthesis does not pack the registered read address into the block RAM.

What is the alternate option to get around this issue, such that Vivado Synthesis would infer an optimal block RAM and pack the registered address into the block RAM?

Solution

Following is a sample code wherein Vivado Synthesis does not infer an optimal block RAM:

.module BRAM_inst

#(parameter DATA_WIDTH=32,
    parameter ADDR_WIDTH=10)
    (
     input [(DATA_WIDTH-1):0] data_in,
     input [(ADDR_WIDTH-1):0] read_addr, write_addr,
     input wr_en, clk,
     output reg [(DATA_WIDTH-1):0] data_out
     );

   (* ram_style = "block" *) reg [DATA_WIDTH-1:0] ram[2**ADDR_WIDTH-1:0];
   reg [ADDR_WIDTH-1:0] read_addr_reg;
  
   always @ (posedge clk) begin
      read_addr_reg <= read_addr; 
      if (wr_en) begin
       ram[write_addr] <= data_in;
      end
       data_out <= ram[read_addr_reg];
   end

endmodule

In the above sample code, the registered read address does not get packed into the block RAM. 

To get around this issue, the above HDL code can be rewritten in the following manner such that an optimal block RAM can be inferred:

module BRAM_inst

  #(parameter DATA_WIDTH=32,
    parameter ADDR_WIDTH=10)
    (
     input [(DATA_WIDTH-1):0] data_in,
     input [(ADDR_WIDTH-1):0] read_addr, write_addr,
     input wr_en, clk,
     output [(DATA_WIDTH-1):0] data_out
     );

   (* ram_style = "block" *) reg [DATA_WIDTH-1:0] ram[2**ADDR_WIDTH-1:0];
   reg [ADDR_WIDTH-1:0] read_addr_reg;
   
   always @ (posedge clk) begin
      read_addr_reg <= read_addr; 
      
      if (wr_en) begin
       ram[write_addr] <= data_in;
     end
   end

   assign data_out = ram[read_addr_reg];
  

endmodule

module BRAM_top
  #(parameter DATA_WIDTH=32,
    parameter ADDR_WIDTH=10)
    (
     input [(DATA_WIDTH-1):0] data_in,
     input [(ADDR_WIDTH-1):0] read_addr, write_addr,
     input wr_en, clk,
     output reg [(DATA_WIDTH-1):0] data_out
     );

   wire [DATA_WIDTH-1:0] data_out_tmp;

   BRAM_inst #(.DATA_WIDTH(DATA_WIDTH),.ADDR_WIDTH(ADDR_WIDTH)) chaitanya_ram_inst (
       .data_out   (data_out_tmp),
       .data_in    (data_in),
       .read_addr  (read_addr),
       .write_addr (write_addr),
       .clk        (clk),
       .wr_en      (wr_en));
   
   always @ (posedge clk)
     begin
       data_out <= data_out_tmp;
     end

endmodule

The above modified code has the o/p data pipeline stage moved across different hierarchy.

This structure now infers an optimal block RAM.

This issue should be fixed in a future release of Vivado Synthesis.

AR# 56457
Date Created 06/17/2013
Last Updated 04/16/2014
Status Active
Type Known Issues
Tools
  • Vivado Design Suite