Question

Which code is better in writing a RAM?

  1. assigning data_out inside always block:

    module memory(
        output reg [7:0] data_out,
        input [7:0] address,
        input [7:0] data_in, 
        input write_enable,
        input clk
    );
        reg [7:0] memory [0:255];
    
        always @(posedge clk) begin
            if (write_enable) begin
                memory[address] <= data_in;
            end
            data_out <= memory[address];
        end
    
    endmodule
    
  2. assigning data_out using assign statement:

    module memory(
        output [7:0] data_out,
        input [7:0] address,
        input [7:0] data_in, 
        input write_enable,
        input clk
    );
        reg [7:0] memory [0:255];
    
        always @(posedge clk) begin
            if (write_enable) begin
                memory[address] <= data_in;
            end
        end
    
        assign data_out = memory[address];
    
    endmodule
    

Any recommendations?

Was it helpful?

Solution

It depends on your requirements.

  1. This registers your memory output. If you are synthesizing this to gates, you will have 16 more flip-flops than in case 2. That means you use a little more area. It also means your output will have less propagation delay relative to the clock than case 2. Furthermore, the output data will not be available until the next clock cycle.

  2. Your output data will be available within the same clock cycle as it was written, albeit with longer propagation delay relative to the clock.

You need to decide which to use based on your requirements.

A third option is to use a generated RAM, which is a hard macro. This should have area, power and possibly timing advantages over both case 1 and 2.

OTHER TIPS

to add to toolic's answer - if you use the asynchronous read method (case 2), it won't map to a RAM block in an FPGA, as the RAM blocks in all the major architectures I'm aware of have a synchronous read.

Both forms are valid, depending on the type of pipelining you want. I always recommend following the Xilinx RAM coding guidelines -- it's a good way to ensure that the code synthesizes into proper FGPA constructs.

For example, your example 1 would synthesize into into Xilinx BRAM (i.e., dedicated Block Ram), since it is synchronous read, and your example 2 would synthesize into Xilinx Distributed Ram (since it is asynchronous read).

See the coding guidelines in Xilinx document UG901 (Vivado Design Suite User Guide), in the RAM HDL Coding Techniques section. It also has a good description of the difference between synchronous read and asynchronous read for RAMs.

In the second program, there would be compilation error as we can not 'Assign' a value to 'Reg'. It will give an error saying: 'Register is illegal in left-hand side of continuous assignment'

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top