Altera_Forum
Honored Contributor
14 years agoVerilog - 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