Block Random Access Memory (BRAM) instances serve as critical volatile storage elements within FPGA fabric. Operational timing relies on synchronous clocking to manage internal state transitions. Memory addressing is handled through dedicated address lines, while data modification is permitted only when write-enable signals are asserted. The output port width corresponds directly to the bit-depth configuration of the instantiated core.
Top-Level Implementation
A wrapper module integrates the generated IP file with a control interface. The following Verilog code demonstrates a design where an internal counter drives both the address and data inputs sequentially.
module block_ram_ctrl (
input wire i_clk,
input wire i_rst_n,
output reg [7:0] o_ram_out
);
reg [7:0] addr_reg;
reg [7:0] din_reg;
wire wr_en;
assign wr_en = i_rst_n;
always @(posedge i_clk)
begin
if (!i_rst_n)
begin
addr_reg <= 8'd0;
din_reg <= 8'd0;
end
else if (addr_reg < 8'd63)
begin
addr_reg <= addr_reg + 1'b1;
din_reg <= addr_reg;
end
end
// Instantiate the Quartus RAM IP Core
ram_primitive U_RAM_IP (
.address(addr_reg),
.clock(i_clk),
.data(din_reg),
.wren(wr_en),
.q(o_ram_out)
);
endmodule
This configuration utilizes default settings for the IP generation wizard. The memory addresses increment from zero, writing the index value into the corresponding storage location.
Testbench Configuration
To validate functionality, a stimulus module moniotrs the output q signal during simulation. Clock generation and reset sequencing are controlled here.
`timescale 1ns/1ps
module tb_block_ram_env;
reg i_clk;
reg i_rst_n;
wire [7:0] o_ram_q;
initial begin
i_clk = 1'b0;
i_rst_n = 1'b0;
end
always #5 i_clk = ~i_clk;
initial begin
$monitor("Time: %t, Output: %h", $time, o_ram_q);
#12
i_rst_n = 1'b1;
#4000
$stop;
end
block_ram_ctrl U_test (
.i_clk(i_clk),
.i_rst_n(i_rst_n),
.o_ram_out(o_ram_q)
);
endmodule
The simulation log indicates the expected sequential progression of values:
... 0 q=xx 10 q=00
50 q=0f 60 q=1e
110 q=3d 150 q=5c
200 q=7b 250 q=9a
... ** Note: $stop
Time: 4012 ns
As observed in the initial cycles (around 0-10ns), the output shows undefined 'x' values. This occurs because the wren signal changes asynchronously relative to the clock during the reset phase. This highlights a potential risk in asynchronous control paths where read operations might occur simultaneously with invalid enable states.
Ensuring that write enables follow the system clock edge strictly prevents these metastability issues. While BRAMs are versatile for dynamic data handling, designers should note that Read-Only Memories (ROM) operate similarly but utilize fixed initialization files rather than runtime writes.