异步简单双口RAM的实现
程序员文章站
2024-02-22 22:57:22
...
RAM的分类
RAM,随机存取存储器,有单口和双口之分,单口RAM只有一个数据线和地址线,不能同时进行读取操作,双口RAM有读和写两个地址线和数据线。因此双口RAM使用要比单口RAM广泛。
双口RAM有真双口和简单双口之分,真双口有两个读端口和两个写端口,简单双口只有一个读端口和一个写端口,一般读写要求不高时,简单双口RAM就能满足我们的需求。另外根据时钟的不同,RAM还有同步异步之分,同步RAM是指读写采用同一个时钟,异步RAM是指读写的时钟不同。
异步简单双口RAM的实现
实现的双口RAM的功能是:建立一个宽度为8bit深度为8的RAM,然后把0-7写入,并在尚未完全写完时就开始读取数据,最终全部读出。程序如下:
module single_dualram(
input wire clk1,//写时钟
input wire clk2,//读时钟
input wire we,//写使能
input wire rd,//读使能
input wire [2:0] we_addr,//写地址
input wire [2:0] rd_addr,//读地址
input wire [7:0] datain,//写数据
output reg [7:0] dataout//读数据
);
reg [7:0]mem[7:0];
always @(posedge clk1) begin
if (we == 1'b1) begin
mem[we_addr] <= datain;
end
end
always @(posedge clk2) begin
if (rd == 1'b1) begin
dataout <= mem[rd_addr];
end
end
endmodule
testbench模块:
`timescale 1ns/1ns
module tb_single_dualram();
reg clk1,clk2;
reg we,rd;
reg [7:0] we_addr,rd_addr;
reg [7:0] datain;
wire[7:0] dataout;
initial begin
clk1 = 0;
clk2 = 0;
we = 0;
rd = 0;
we_addr = 0;
rd_addr = 0;
datain = 0;
end
always #10 clk1 = ~clk1;
always #10 clk2 = ~clk2;
initial begin
#25
we = 1;
#50
rd = 1;
#100
we = 0;
end
initial begin
#20
repeat(7)
#20
begin
we_addr = we_addr +1;
datain = datain + 1;
end
end
initial begin
#75
repeat(7)
#20
begin
rd_addr = rd_addr +1;
end
end
initial
#240
rd = 0;
single_dualram inst_single_dualram(
.clk1 (clk1),
.clk2 (clk2),
.we (we),
.rd (rd),
.we_addr (we_addr),
.rd_addr (rd_addr),
.datain (datain),
.dataout (dataout)
);
endmodule
波形图如下,可以看到效果达到预期:
在modelesim中检查存储器信息,可以发现已经将0-7存入RAM,如下图所示: