12-23-2019 04:37 AM
Please consult the Vivado Synthesis guide, UG901, Chapter 4.
There you have Verilog code snippets for BRAM inference.
Consider giving "Kudos" if you like my answer. Please mark my post "Accept as solution" if my answer has solved your problem
Asking for solutions to problems via PM will be ignored.
12-23-2019 05:34 AM - edited 12-23-2019 05:36 AM
I deal with several problems involved in implementing RAM in my beginners tutorial. In general, I proposed the following rules to help make certain inference happens like it should:
always @(posedge i_clk) if (write) ram[write_addr] <= write_value; always @(posedge i_clk) if (read) read_value <= ram[read_addr];
always @(posedge i_clk) if (i_reset) begin // This will not infer a block RAM--block RAM cannot be re-initialized for(i=0; i<ramsize; i=i+1) ram <= 0; end else if (write) ram[write_addr] <= write_value
// Don't do this if you want to infer RAM always @(posedge i_clk) if (A) value <= ram[addr_a]; else if (B) value <= something_else; else if (C) value <= ram[addr_b]; else if (D) // logic continues
// Many synthesizers will turn this into FFs always @(posedge i_clk) if (write_enable) begin B <= // some logic; C <= // something else ram[addr] <= value; end
always @(posedge i_clk) if (write_enable) begin if (en) ram[write_addr][15:8] <= write_value[15:8]; if (en) ram[write_addr][ 7:0] <= write_value[7:0]; end
// Write-through capability // ---- Not Verilog spec compliant! always @(posedge i_clk) begin if (write_enable) mem[addr] <= write_value; read_value <= mem[addr]; end
always @(*) read_value = ram[read_address];This is a *really useful* capability, and one I really like
So, it's not so much how you define the array that causes it to be placed into block RAM, but rather how you use it that determines whether or not it gets placed into block RAM in the first place.
Also, you need to be aware that not all hardware architectures are the same. Block RAM inference is limited by the hardware architecture. So while reading from a RAM asynchronously is (pleasantly) supported on a Xilinx device (for example), not all architectures have this capability.
P.S. Regarding the two-dimensional memory inference ... depending on how you set that up, a multiply would be required to implement it and most tools are designed so as to let you (the designer) control all pipelining--so you won't find that implemented in general.