RTL design (2)-dual-port RAM

Introduction to dual-port RAM

A single port has only one set of data lines and address lines, so reading and writing cannot be performed at the same time; a dual port has two sets of data lines and address lines, and reading and writing can be performed at the same time.

Dual-port RAM is a memory that has two completely independent data lines, address lines, and read-write control lines on a memory, and allows two independent systems to perform random read and write access to the memory simultaneously and asynchronously.

Dual-port RAM can be used to improve RAM throughput and is suitable for real-time data caching.

Dual-port RAM example

The following program implements a dual-port RAM, one of which is write-only and the other is read-only. Reading and writing can be performed simultaneously and asynchronously.

dualram.v

`timescale 1ns / 1ps

// Company: 
// Engineer: 
// 
// Create Date: 2020/12/08
// Author Name: Sniper
// Module Name: dualram
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 


module dualram
#(
    parameter WIDTH = 32,
    parameter DEPTH = 1024
)
(
    input wr_clk,
    input [$clog2(DEPTH)-1:0] wr_addr,
    input [WIDTH-1:0] wr_data,
    input wr_en,

    input rd_clk,
    input [$clog2(DEPTH)-1:0] rd_addr,
    output reg [WIDTH-1:0] rd_data,
    input rd_en
);

localparam ADDR_WIDTH = $clog2(DEPTH);//$clog2(8)=3; $clog2(9)=4;

reg [WIDTH-1:0] mem[DEPTH-1:0];


always@(posedge wr_clk)
begin
    if(wr_en)
        mem[wr_addr] <= wr_data;
end

always@(posedge rd_clk)
begin
    if(rd_en)
        rd_data <= mem[rd_addr];
end


endmodule

tb_dualram.v

`timescale 1ns / 1ps

// Company:
// Engineer:
//
// Create Date: 2020/12/08
// Author Name: Sniper
// Module Name: tb_dualram
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//


module tb_dualram;

//parameter
parameter WIDTH = 32;
parameter DEPTH = 1024;


//input
reg wr_clk;
reg [$clog2(DEPTH)-1:0] wr_addr;
reg [WIDTH-1:0] wr_data;
reg wr_en;
reg rd_clk;
reg [$clog2(DEPTH)-1:0] rd_addr;
reg rd_en;


//output
wire [WIDTH-1:0] rd_data;

integer i;

initial
begin
    wr_clk = 0;
    wr_addr = 0;
    wr_data[WIDTH-1:0] = 0;
    wr_en = 0;

	#100;


    for(i=0;i<16;i=i+1)
    begin
        @(posedge wr_clk);
        wr_addr <= i;
        wr_data <= i<<4;
        wr_en <= 1;
    end
    @(posedge wr_clk);
    wr_addr <= 0;
    wr_data <= 0;
    wr_en <= 0;


end

integer j;

initial
begin
    rd_clk = 0;
    rd_addr = 0;
    rd_en = 0;

	#100;

    @(posedge wr_clk);


    for(j=0;j<16;j=j+1)
    begin
        @(posedge rd_clk);
        rd_addr <= j;
        rd_en <= 1;
    end
    @(posedge rd_clk);
    rd_addr <= 0;
    rd_en <= 0;


end

//clock
always #5 wr_clk = ~wr_clk;
always #8 rd_clk = ~rd_clk;



//DUT
dualram 
#(
    .WIDTH(WIDTH),
    .DEPTH(DEPTH)
)
DUT
(
    .wr_clk(wr_clk),
    .wr_addr(wr_addr),
    .wr_data(wr_data),
    .wr_en(wr_en),
    .rd_clk(rd_clk),
    .rd_addr(rd_addr),
    .rd_data(rd_data),
    .rd_en(rd_en)
);

initial
begin
  $dumpfile("curve.vcd");
  $dumpvars(0,DUT);
end

initial #1000 $finish;

endmodule

operation result

vcs -R dualram.v tb_dualram.v

Insert picture description here
Due to the use of register output, there will be a 1-cycle delay in reading data.

Guess you like

Origin blog.csdn.net/meng1506789/article/details/110909889
RAM