Inferring Block RAM vs. Distributed RAM in XST and Precision
This is a description of how to infer Xilinx FPGA block RAM or distributed RAM through HDL coding style and synthesis attributes/pragmas. Verilog GENERATE is an easy way to choose between the types without digging into the hierarchy. Verilog is the HDL of choice, and the tools are Xilinx XST (ISE 8.1) and Mentor Graphics Precision 2005c.99.
Intro
Sometimes it's desirable to have the ability to control whether an HDL memory block is inferred as a block RAM or distributed RAM easily, such as thru an attribute or parameter. Below is some example Verilog code for a 1Kb x 16 single port RAM (the attribute/pragma for both XST and Precision are present and have no effect on each other):
input Clk; input We; input [9:0] Waddr; input [9:0] Raddr; input [15:0] Din; output [15:0] Dout; //synthesis attribute ram_style of mem is distributed reg [9:0] mem[0:1023]; //pragma attribute mem ram_block FALSE reg [9:0] raddr_reg; always @ (posedge Clk) begin raddr_reg <= Raddr; if (We) begin mem[Waddr] <= Din; end //Dout <= mem[raddr_reg]; //registered read end assign Dout = mem[raddr_reg]; //unregistered read
input Clk; input We; input [9:0] Waddr; input [9:0] Raddr; input [15:0] Din; output [15:0] Dout; //synthesis attribute ram_style of mem is distributed reg [9:0] mem[0:1023]; //pragma attribute mem ram_block FALSE reg [9:0] raddr_reg; always @ (posedge Clk) begin raddr_reg <= Raddr; if (We) begin mem[Waddr] <= Din; end //Dout <= mem[raddr_reg]; //registered read end assign Dout = mem[raddr_reg]; //unregistered read
XST
//synthesis attribute ram_style of mem is distributed (or block)
Xilinx's XST will infer block RAM if the read address is registered inside the module. Setting the ram_style attribute to block or absence of the attribute has no effect. If the read address is not registered or the ram_style attribute is set to distributed, distributed RAM will be inferred. Registering the write data & address or the read output have no effect on block RAM vs. distributed RAM. (Note: the first "s" in synthesis must be lower case.)
Xilinx's XST will infer block RAM if the read address is registered inside the module. Setting the ram_style attribute to block or absence of the attribute has no effect. If the read address is not registered or the ram_style attribute is set to distributed, distributed RAM will be inferred. Registering the write data & address or the read output have no effect on block RAM vs. distributed RAM. (Note: the first "s" in synthesis must be lower case.)
Precision
//pragma attribute mem ram_block FALSE (or TRUE)
Mentor's Precision will infer block RAM if 1) the memory read data is registered, or 2) the read address is registered. Setting the pragma to TRUE or absence of the pragma has no effect. If the above conditions aren't met or the ram_block pragma is set to FALSE, distributed RAM will be inferred. The XST ram_style attribute has no effect in Precision.
Mentor's Precision will infer block RAM if 1) the memory read data is registered, or 2) the read address is registered. Setting the pragma to TRUE or absence of the pragma has no effect. If the above conditions aren't met or the ram_block pragma is set to FALSE, distributed RAM will be inferred. The XST ram_style attribute has no effect in Precision.
Hierarchically controlling the RAM inferrence
The synthesis attributes and pragmas listed above can't be used hierarchically, such as a level up where the RAM is instantiated. However, the Verilog 2001 generate can be used with a parameter (which can be passed down through the hierarchy) to choose between block RAM and distributed RAM. The RAM module is duplicated with the correct attribute or pragma. Here's an example:
parameter blockram = 1; generate if (blockram) begin: blockr //block RAM memb bram ( .Clk (Clk), .... ); end else begin : distr //distributed RAM memd dram ( .Clk (Clk), ... ); end endgenerate