Dual-port RAM design in Verilog - Time & Space Complexity
We want to understand how the time it takes to read and write memory changes as the size of the memory grows.
How does the design of a dual-port RAM affect the speed when we increase its size?
Analyze the time complexity of the following code snippet.
module dual_port_ram (
input logic clk,
input logic [7:0] addr_a, addr_b,
input logic [7:0] data_in_a, data_in_b,
input logic we_a, we_b,
output logic [7:0] data_out_a, data_out_b
);
logic [7:0] ram [0:255];
always_ff @(posedge clk) begin
if (we_a) ram[addr_a] <= data_in_a;
data_out_a <= ram[addr_a];
if (we_b) ram[addr_b] <= data_in_b;
data_out_b <= ram[addr_b];
end
endmodule
This code models a dual-port RAM with two independent read/write ports working on a 256-byte memory.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Accessing memory array at given addresses for read and write.
- How many times: Each clock cycle, two memory accesses happen independently.
As the memory size grows, each read or write still happens in one step because the address directly selects the memory location.
| Input Size (memory size) | Approx. Operations per cycle |
|---|---|
| 256 | 2 (one read/write per port) |
| 1024 | 2 (still one read/write per port) |
| 4096 | 2 (still one read/write per port) |
Pattern observation: The number of operations per cycle stays the same regardless of memory size.
Time Complexity: O(1)
This means each read or write happens in constant time, no matter how big the memory is.
[X] Wrong: "Accessing larger memory always takes longer because it has more data to search through."
[OK] Correct: In hardware RAM, the address directly selects the memory cell, so access time stays constant regardless of size.
Understanding how hardware memory access time stays constant helps you explain efficient designs and shows you know how hardware differs from software loops.
"What if the RAM was implemented as a large array accessed by a software loop instead of hardware memory? How would the time complexity change?"
Practice
dual-port RAM in hardware design?Solution
Step 1: Understand dual-port RAM functionality
Dual-port RAM has two ports that can access memory independently at the same time.Step 2: Identify the main benefit
This allows simultaneous read/write operations, improving performance.Final Answer:
It allows two independent read/write operations simultaneously. -> Option AQuick Check:
Dual-port RAM = two simultaneous accesses [OK]
- Thinking it reduces memory size
- Assuming it only supports reads
- Believing it slows down RAM
Solution
Step 1: Identify dual-port RAM ports
Dual-port RAM needs separate address, data, and write enable signals for each port.Step 2: Match correct declaration
input clk, input [7:0] addr_a, input [7:0] data_in_a, output [7:0] data_out_a, input we_a, input [7:0] addr_b, input [7:0] data_in_b, output [7:0] data_out_b, input we_b; declares separate addr, data_in, data_out, and we signals for ports A and B, matching dual-port RAM design.Final Answer:
input clk, input [7:0] addr_a, input [7:0] data_in_a, output [7:0] data_out_a, input we_a, input [7:0] addr_b, input [7:0] data_in_b, output [7:0] data_out_b, input we_b; -> Option DQuick Check:
Separate signals per port = input clk, input [7:0] addr_a, input [7:0] data_in_a, output [7:0] data_out_a, input we_a, input [7:0] addr_b, input [7:0] data_in_b, output [7:0] data_out_b, input we_b; [OK]
- Using single address and data signals for both ports
- Missing write enable signals
- Confusing read and write signals
data_out_b after the clock edge if we_b is 0 and addr_b is 3?reg [7:0] ram [0:7]; always @(posedge clk) begin if (we_a) ram[addr_a] <= data_in_a; if (we_b) ram[addr_b] <= data_in_b; data_out_a <= ram[addr_a]; data_out_b <= ram[addr_b]; end
Solution
Step 1: Understand write enable effect
Sincewe_bis 0, no write occurs ataddr_bon this clock edge.Step 2: Determine data_out_b value
data_out_breads the RAM ataddr_b, so it outputs the stored value at address 3 before the clock edge.Final Answer:
The value stored at address 3 before the clock edge. -> Option BQuick Check:
we_b=0 means no write; output = stored value [OK]
- Assuming data_out_b equals data_in_b always
- Thinking output is zero when no write
- Ignoring read operation on clock edge
reg [7:0] ram [0:15]; always @(posedge clk) begin if (we_a) ram[addr_a] <= data_in_a; if (we_b) ram[addr_b] <= data_in_b; data_out_a <= ram[addr_a]; data_out_b <= ram[addr_b]; end assign data_out_a = ram[addr_a];
Solution
Step 1: Check assignments to data_out_a
Data_out_a is assigned inside the always block and also by continuous assign statement, causing conflict.Step 2: Understand Verilog rules
A signal cannot be driven by both procedural and continuous assignments simultaneously.Final Answer:
Conflicting assignments to data_out_a: both procedural and continuous. -> Option AQuick Check:
Signal driven twice = conflict error [OK]
- Ignoring multiple drivers on one signal
- Thinking sensitivity list needs clock and addr
- Misunderstanding RAM size syntax
Solution
Step 1: Define port roles
Port A should only write data, so it needs a write enable and no read output.Step 2: Configure Port B as read-only
Port B should not write, so write enable is never asserted; it only reads data from RAM.Final Answer:
Use write enable only on Port A and never write on Port B; read data only from Port B. -> Option CQuick Check:
Write-only Port A + Read-only Port B = Use write enable only on Port A and never write on Port B; read data only from Port B. [OK]
- Trying to write on both ports
- Disabling clock to control read/write
- Using single write enable for both ports
Ready to prove it?
Pass the test and this pattern moves unknown
