0
0
Verilogprogramming~5 mins

Single-port RAM design in Verilog

Choose your learning style9 modes available
Introduction

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.

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

endmodule
This 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

endmodule
Sample 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
endmodule
OutputSuccess
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.