3. Verilog RAM - Dual Port Async Design
A Dual Port Asynchronous RAM provides two independent ports, each capable of read or write operations. This design supports different clock frequencies for read and write operations.
Features
- Two independent ports: Port 0 and Port 1
- Separate read/write clocks:
wr_clkandrd_clk - Asynchronous reset: Clears all memory
- Parameterized: Configurable DEPTH, WIDTH, ADDR
Supported Operations
- Write to both Port 0 and Port 1 simultaneously
- Read from both Port 0 and Port 1 simultaneously
- Mixed: Read from one port, write to another
Note: To avoid memory contention, ensure different addresses when writing to both ports simultaneously. External arbitration logic should handle this.
Port Description
| Port | Direction | Description |
|---|---|---|
wr_clk | input | Write clock |
rd_clk | input | Read clock |
reset | input | Asynchronous reset |
data_0/1 | inout | Bidirectional data [WIDTH-1:0] |
addr_0/1 | input | Address [ADDR-1:0] |
wr_en_0/1 | input | Write enable per port |
o_en_0/1 | input | Output enable per port |
RTL Implementation
// Module: dp_async_ram.v
// Dual Port Asynchronous RAM with Asynchronous Reset
// Read and Write Clock Frequencies are Different
module dp_async_ram #(
parameter DEPTH = 16,
parameter WIDTH = 8,
parameter ADDR = 4
)(
input wr_clk,
input rd_clk,
input reset,
inout [WIDTH-1:0] data_0, data_1,
input [ADDR-1:0] addr_0, addr_1,
input wr_en_0, wr_en_1,
input o_en_0, o_en_1
);
// Read data registers
reg [WIDTH-1:0] data_0_reg, data_1_reg;
integer i;
// Memory array
reg [WIDTH-1:0] mem [DEPTH-1:0];
// Write Logic (synchronous to wr_clk, async reset)
always @(posedge wr_clk or posedge reset) begin
if (reset) begin
for (i = 0; i < DEPTH; i = i + 1)
mem[i] <= 0;
end
else begin
if (wr_en_0 && !o_en_0)
mem[addr_0] <= data_0;
if (wr_en_1 && !o_en_1)
mem[addr_1] <= data_1;
end
end
// Read Logic - Tristate outputs
assign data_0 = (o_en_0 && !wr_en_0) ? data_0_reg : {WIDTH{1'bz}};
assign data_1 = (o_en_1 && !wr_en_1) ? data_1_reg : {WIDTH{1'bz}};
// Read Logic (synchronous to rd_clk)
always @(posedge rd_clk) begin
if (o_en_0 && !wr_en_0)
data_0_reg <= mem[addr_0];
if (o_en_1 && !wr_en_1)
data_1_reg <= mem[addr_1];
end
endmodule
Architecture
%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#e0f2fe', 'primaryTextColor': '#0f172a', 'primaryBorderColor': '#0066cc', 'lineColor': '#475569', 'secondaryColor': '#f8fafc'}}}%%
flowchart LR
subgraph Port0["Port 0"]
D0[data_0]
A0[addr_0]
WE0[wr_en_0]
OE0[o_en_0]
end
subgraph Port1["Port 1"]
D1[data_1]
A1[addr_1]
WE1[wr_en_1]
OE1[o_en_1]
end
MEM{{Memory Array}}
D0 <--> MEM
D1 <--> MEM
A0 --> MEM
A1 --> MEM
style MEM fill:#d1fae5,stroke:#10b981,stroke-width:2px
This concludes the Verilog RAM series. You now have designs for both single-port and dual-port asynchronous memories!
Comments (0)
Leave a Comment