Description
I am declaring sufficiently large arrays in my design and expecting these memories to be implemented using BRAMs. I have tried using various synthesis directives to force the tool to utilize BRAMs, but these memories are mapped to LRAMs instead. How do I direct Synplify Pro to infer BRAMs instead of LRAMs on Speedster7t FPGAs when none of my synthesis directives to use BRAMs are being respected?
Answer
To understand why this is happening, we should first take a look at the architectures of these different memory modules in the Speedster7t architecture. The architectures of the memory modules can be seen below.
Figure: LRAM (ACX_LRAM2K_SDP) Block Diagram
Figure: BRAM (ACX_BRAM72K_SDP) Block Diagram
As seen above, the read operation on the LRAM has an asynchronous data path. However, in the BRAM, the read and write operations are synchronized to their respective clocks. The BRAM read output must be registered for at least one clock cycle. Therefore, when inferring BRAMs via memory array declaration, it is important to ensure that the write and read paths are synchronized to their respective clocks.
Setting an initial value in the output port declaration forces Synplify Pro to infer LRAMs. The initial value in the port declaration implies an asynchronous read, which forces the inference of an LRAM. For example, the code below infers LRAMs:
reg [DATA_WIDTH - 1:0] mem_array [DEPTH];
reg [DATA_WIDTH - 1:0] data_output = 0; //forces LRAM to be synthesized because of initial value declaration
always @ (posedge clk)
begin
if (write_enable == 1'b1)
mem_array[write_address] <= data_input;
end
always @ (posedge clk)
begin
if (read_enable == 1'b1)
data_output <= mem_array[read_address] ;
end
A combinatorial read in the memory module also infers LRAMs since this read is an asynchronous operation. The read operation below also infers LRAMs:
always_comb data_output <= mem_array[read_address];
Structuring the memory module with synchronous, or registered, read and write operations without setting an initial value on the data output declaration infers BRAMs.
CDATA[reg [DATA_WIDTH - 1:0] mem_array [DEPTH];
reg [DATA_WIDTH - 1:0] data_output;
always @ (posedge clk)
begin
if (write_enable == 1'b1)
mem_array[write_address] <= data_input;
end
always @ (posedge clk) begin
if (read_enable == 1'b1)
data_output <= mem_array[read_address] ;
end