Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
14 years ago

Verilog - how to write parameterized RAM that infers a RAM block?

Does anyone know a way to write a RAM in Verilog with parameterized width and byte enables that causes Quartus to infer a RAM block?

Since Altera seems to be strongly discouraging direct use of altsyncram by removing all documentation, I am trying to find a way to directly code RAM. I do not need special features like initialization from a file, but i do need basic parameterization.

I have written a simple test which instantiates two RAM blocks. This first is inferred correctly but is not parmetrized. The second is properly parametrized but is not inferred. For the second, Quartus outputs the following:

Info (276007): RAM logic "ram2:m2|ram" is uninferred due to asynchronous read logic

Any solutions or ideas to try would be greatly appreciated.

** edit for clarification

Quartus does infer an altsyncram megafunction from the second RAM instantiation, but uses lcell registers instead of a RAM block.

** /edit


// top level, just instantiate two test cases
module ram_test#(
    parameter data_width = 32,
    parameter addr_width = 6,
    parameter bena_width = data_width / 8 
) (
    input clk,
    input  addr,
    input wena1,
    input wena2,
    input  wdata,
    input  bena,
    output  q1,
    output  q2
);
    ram1# (.data_width(data_width), .addr_width(addr_width)
    ) m1 (.clk(clk), .addr(addr), .wena(wena1), .wdata(wdata), .bena(bena),
            .q(q1)
    );
    ram2# (.data_width(data_width), .addr_width(addr_width)
    ) m2 (.clk(clk), .addr(addr), .wena(wena2), .wdata(wdata), .bena(bena),
            .q(q2)
    );
endmodule
//---------------------------------------------------------------------------
// Hard coded width, infers correctly
//---------------------------------------------------------------------------
module ram1# (
    parameter data_width = 32,  // works only for 32 bit
    parameter addr_width = 10,
    parameter bena_width = data_width / 8 
) (
    input clk,
    input  addr,
    input wena,
    input  wdata,
    input  bena,
    output reg  q
);
    localparam numwords = 2**addr_width;
    reg  ram ;
    always_ff@(posedge clk) begin
        if(wena) begin
            if(bena) ram <= wdata;
            if(bena) ram <= wdata;
            if(bena) ram <= wdata;
            if(bena) ram <= wdata;
        end
        q <= ram;
    end
endmodule
//---------------------------------------------------------------------------
// Parameterized width, does not infer a RAM block
//---------------------------------------------------------------------------
module ram2# (
    parameter data_width = 32,  // can be any multiple of 8
    parameter addr_width = 10,
    parameter bena_width = data_width / 8
) (
    input clk,
    input  addr,
    input wena,
    input  wdata,
    input  bena,
    output reg  q
);
    localparam numwords = 2**addr_width;
    reg  ram ;
    // create full write enable bit mask
    wire  wmask;
    genvar bytelane;
    generate
        for(bytelane=0; bytelane < bena_width; bytelane++) begin : lpbl
            assign wmask = wena ? {8{bena}} : 8'b0;
        end
    endgenerate
    // RAM
    always_ff@(posedge clk) begin
        ram <= (wmask & wdata) | (~wmask & ram);
        q <= ram;
    end
endmodule

20 Replies