Knowledge Base Article
Why output register cannot be enabled when inferred RAM depth is larger than 2048?
Description
Due to limitation with the Quartus® Prime Pro Edition software, the output register in M20K cannot be enabled when inferred RAM depth is large than 2048.
Resolution
To work around this problem in the Quartus Prime Pro Edition software, use the template below to enable output register for inferred RAM.
module ram_template #(
parameter DATA_WIDTH=8,
parameter ADDR_WIDTH=12,
parameter SPLIT_RAM_INTO_SUB_BLOCKS=1
)
(
input [(DATA_WIDTH-1):0] data,
input [(ADDR_WIDTH-1):0] read_addr, write_addr,
input we, read_clock, write_clock,
output reg [(DATA_WIDTH-1):0] q
);
localparam MAX_ADDR_BITS = 11;
localparam SPLIT_RAM = (ADDR_WIDTH > MAX_ADDR_BITS) ? SPLIT_RAM_INTO_SUB_BLOCKS : 0;
localparam SPLIT_ADDR_BITS = SPLIT_RAM ? (ADDR_WIDTH - MAX_ADDR_BITS) : 1;
localparam NUM_RAM_SUB_BLOCKS = SPLIT_RAM ? (1 << SPLIT_ADDR_BITS) : 1;
wire [(DATA_WIDTH-1):0] ram_out;
reg [(SPLIT_ADDR_BITS-1):0] read_addr_reg0, read_addr_reg1;
wire [(NUM_RAM_SUB_BLOCKS-1):0][(DATA_WIDTH-1):0] ram_out_channels;
wire [(NUM_RAM_SUB_BLOCKS-1):0] we_channels;
genvar i;
generate
if (SPLIT_RAM) begin
always @(posedge read_clock) begin
read_addr_reg0 <= read_addr[(ADDR_WIDTH-1):(ADDR_WIDTH-SPLIT_ADDR_BITS)];
read_addr_reg1 <= read_addr_reg0;
end
for (i=0; i<NUM_RAM_SUB_BLOCKS; i=i+1) begin : SUB_RAM_BLOCKS
ram_template_sub_ram_block #(
.DATA_WIDTH(DATA_WIDTH),
.ADDR_WIDTH(MAX_ADDR_BITS)
) sub_ram_block (
.data(data),
.read_addr(read_addr[MAX_ADDR_BITS-1:0]),
.write_addr(write_addr[MAX_ADDR_BITS-1:0]),
.we(we_channels[i]),
.read_clock(read_clock),
.write_clock(write_clock),
.q(ram_out_channels[i])
);
end
assign we_channels = {NUM_RAM_SUB_BLOCKS{we}} & (1 << write_addr[(ADDR_WIDTH-1):(ADDR_WIDTH-SPLIT_ADDR_BITS)]);
assign ram_out = ram_out_channels[read_addr_reg0];
end
else begin
ram_template_sub_ram_block #(
.DATA_WIDTH(DATA_WIDTH),
.ADDR_WIDTH(ADDR_WIDTH)
) sub_ram_block (
.data(data),
.read_addr(read_addr),
.write_addr(write_addr),
.we(we),
.read_clock(read_clock),
.write_clock(write_clock),
.q(ram_out)
);
end
endgenerate
always @(posedge read_clock) begin
q <= ram_out;
end
endmodule
module ram_template_sub_ram_block #(
parameter DATA_WIDTH=8,
parameter ADDR_WIDTH=12
)
(
input [(DATA_WIDTH-1):0] data,
input [(ADDR_WIDTH-1):0] read_addr, write_addr,
input we, read_clock, write_clock,
output reg [(DATA_WIDTH-1):0] q
);
reg [(ADDR_WIDTH-1):0] read_addr_reg;
// Declare the RAM variable
reg [DATA_WIDTH-1:0] ram[2**ADDR_WIDTH-1:0];
always @ (posedge write_clock)
begin
// Write
if (we)
ram[write_addr] <= data;
end
always @ (posedge read_clock)
begin
// Read
read_addr_reg <= read_addr;
q <= ram[read_addr_reg];
end
endmodule
Updated 9 days ago
Version 2.0No CommentsBe the first to comment