RTL设计(2)- 双口RAM

双口RAM简介

单口只有一组数据线与地址线,因此读写不能同时进行;双口有两组数据线与地址线,读写可同时进行。

双口RAM是在一个存储器上具有两套完全独立的数据线、地址线和读写控制线,并允许两个独立的系统同时异步地对该存储器进行随机性读写访问的存储器。

双口RAM可用于提高RAM的吞吐率,适用于实时的数据缓存。

双口RAM实例

以下程序实现一种双口RAM,其中一个口只写,另一个口只读。读和写可同时异步地进行。

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

运行结果

vcs -R dualram.v tb_dualram.v

在这里插入图片描述
由于使用寄存器输出,读数据会有1个周期的延迟。

猜你喜欢

转载自blog.csdn.net/meng1506789/article/details/110909889