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.0
No CommentsBe the first to comment