Single-port RAM lets you store and read data using one address at a time. It helps save space and is simple to use in hardware designs.
0
0
Single-port RAM design in Verilog
Introduction
When you need a small memory block to store data temporarily in a digital circuit.
When your design only needs to read or write one data item at a time.
When you want to save hardware resources by using one port for both reading and writing.
When building simple processors or controllers that use memory.
When you want to learn how memory works inside digital chips.
Syntax
Verilog
module single_port_ram #( parameter DATA_WIDTH = 8, parameter ADDR_WIDTH = 4 ) ( input wire clk, input wire we, // write enable input wire [ADDR_WIDTH-1:0] addr, input wire [DATA_WIDTH-1:0] din, output reg [DATA_WIDTH-1:0] dout ); // Declare memory array reg [DATA_WIDTH-1:0] ram [0:(1<<ADDR_WIDTH)-1]; always @(posedge clk) begin if (we) begin ram[addr] <= din; // Write data end dout <= ram[addr]; // Read data end endmodule
The clk input controls when data is read or written.
The we signal decides if the memory writes new data or just reads.
Examples
This example shows an 8-bit wide RAM with 16 addresses.
Verilog
module ram_example (
input wire clk,
input wire we,
input wire [3:0] addr,
input wire [7:0] din,
output reg [7:0] dout
);
reg [7:0] ram [0:15];
always @(posedge clk) begin
if (we) ram[addr] <= din;
dout <= ram[addr];
end
endmoduleThis example uses 4-bit data width and 16 addresses.
Verilog
module ram_16x4 (
input wire clk,
input wire we,
input wire [3:0] addr,
input wire [3:0] din,
output reg [3:0] dout
);
reg [3:0] ram [0:15];
always @(posedge clk) begin
if (we) ram[addr] <= din;
dout <= ram[addr];
end
endmoduleSample Program
This testbench writes values to addresses 3 and 7, then reads them back and prints the results. It also reads an address that was never written to show default zero.
Verilog
module testbench();
reg clk = 0;
reg we;
reg [3:0] addr;
reg [7:0] din;
wire [7:0] dout;
// Instantiate RAM
single_port_ram ram (
.clk(clk),
.we(we),
.addr(addr),
.din(din),
.dout(dout)
);
// Clock generation
always #5 clk = ~clk;
initial begin
// Write 42 at address 3
we = 1; addr = 4'd3; din = 8'd42;
#10;
// Write 100 at address 7
addr = 4'd7; din = 8'd100;
#10;
// Stop writing, read address 3
we = 0; addr = 4'd3;
#10;
$display("Read from addr 3: %d", dout);
// Read address 7
addr = 4'd7;
#10;
$display("Read from addr 7: %d", dout);
// Read address 0 (not written, default 0)
addr = 4'd0;
#10;
$display("Read from addr 0: %d", dout);
$finish;
end
endmodule
module single_port_ram (
input wire clk,
input wire we,
input wire [3:0] addr,
input wire [7:0] din,
output reg [7:0] dout
);
reg [7:0] ram [0:15];
always @(posedge clk) begin
if (we) ram[addr] <= din;
dout <= ram[addr];
end
endmoduleOutputSuccess
Important Notes
Reading and writing happen on the clock's rising edge.
If you read an address that was never written, it usually returns zero or unknown depending on your simulator.
Single-port RAM can only read or write one address per clock cycle.
Summary
Single-port RAM stores data with one address line for both reading and writing.
Use a clock and write enable signal to control memory operations.
This design is simple and saves hardware but can only do one operation at a time.