真双口RAM IP的使用
1 IP的例化
第一个配置界面:
Block Memory Gnerator一共可以产生5种不同类型的内存空间,
其中block RAM有三种:单口RAM、简化双口RAM和真双口RAM。
单口RAM只有一个端口(A端口),可以对A端口进行读写。
简化双口RAM有两个端口(A和B端口),但是A端口只能进行写入操作,不能进行读出操作,而B端口则只能进行读出操作,不能进行写入操作。
真双口RAM有两个端口(A和B端口),A和B端口都能进行读写操作。

第二个配置界面:
Operating Mode(操作模式)一共有三种:Write First,Read First,No Change。
在Write First模式中,在一个时钟周期里,写入内存单元的数据被同步输出到输出数据总线上;
在Read First模式中,在一个时钟周期里,写入到内存单元的数据是当前输入数据总线上的数据,
而输出到输出数据总线上的数据则是上一个时钟周期存储在内存单元中的数据。
细节可参考PG058的49到50页4。Enable Port Type设置为Always Enabled,一直使能端口A。

第三个配置界面:

其他窗口保持默认。

2 源代码
2.1 顶层文件
```cpp
`timescale 1ns / 1ps
/*
注意点:
(1)Block Memory Gnerator一共可以产生5种不同类型的内存空间,
其中block RAM有三种:单口RAM、简化双口RAM和真双口RAM[4]。
单口RAM只有一个端口(A端口),可以对A端口进行读写。
简化双口RAM有两个端口(A和B端口),但是A端口只能进行写入操作,不能进行读出操作,而B端口则只能进行读出操作,不能进行写入操作。
真双口RAM有两个端口(A和B端口),A和B端口都能进行读写操作
(2)Operating Mode(操作模式)一共有三种:Write First,Read First,No Change。
在Write First模式中,在一个时钟周期里,写入内存单元的数据被同步输出到输出数据总线上;
在Read First模式中,在一个时钟周期里,写入到内存单元的数据是当前输入数据总线上的数据,
而输出到输出数
##据总线上的数据则是上一个时钟周期存储在内存单元中的数据。
细节可参考PG058的49到50页4。Enable Port Type设置为Always Enabled,一直使能端口A。
*/
module True_TwoPort_RAM(
input clk,
input rst_n,
input trig //RAM工作信号
);
/*模块功能:
count=0到99,RAM不工作
count=100到199,RAM写数据
count=200到299,RAM不工作
count=300到399,RAM读数据
count=其他值,RAM不工作
*/
reg RAM_en ; // RAM 使能信号
reg wea ; // wea=1,RAM写数据; wea=0,RAM读数据。
reg [15:0] addr ; // RAM的读写地址
reg [15:0] Write_Data ; // RAM写入数据
reg [15:0] count ;
always @ (posedge clk)
begin
if(!rst_n)
begin
RAM_en <=1'b0;// RAM 使能信号
wea <=1'b0;
addr <=16'd0;
Write_Data <=16'd0;
count <=16'd0;
end
else
if(trig==1'b1)
begin
count <= count + 1'd1;
if( count<10'd100 ) //count=0到99,RAM不工作
begin
RAM_en <= 1'b0; // RAM 使能信号
wea <= 1'b0; // wea=1,RAM写数据; wea=0,RAM读数据。
end
else if( (count >=10'd100) && (count < 10'd200))//count=100到199,RAM写数据
begin
RAM_en <= 1'b1; // RAM 使能信号
wea <= 1'b1; // wea=1,RAM写数据; wea=0,RAM读数据。
addr <= addr + 10'd1;
Write_Data <= Write_Data + 1'd1;
end
else if( (count >=10'd200) && (count < 10'd300) ) // count=200到299,RAM不工作
begin
RAM_en <= 1'b0; //RAM IP不工作
wea <= 1'b0; // wea=1,RAM写数据; wea=0,RAM读数据。
addr <= 10'd0; //地址清零
Write_Data <= 128'd0; //数据清零
end
else if((count >=10'd300) && (count < 10'd400) )//count=300到399,RAM读数据
begin
RAM_en <= 1'b1;
wea <= 1'b0; // wea=1,RAM写数据; wea=0,RAM读数据。
addr <= addr + 10'd1;
end
else //count=其他值,RAM不工作
begin
RAM_en <= 1'b0; //RAM IP不工作
count <= count; //
end
end
else
begin
RAM_en <=RAM_en ;// RAM 使能信号
wea <=wea ;
addr <=addr ;
Write_Data <=Write_Data;
count <=count ;
end
end
// ena:RAM IP 使能信号 ,ena=1,RAM IP工作
// wea:wea=1,写数据;wea=0,读数据。
wire[15:0] Read_Data ; // RAM读出数据
True_TwoPort_RAM_ip Inst_True_TwoPort_RAM_ip (
.clka (clk ), // input wire clka
.ena (RAM_en ), // input wire ena RAM IP 使能信号
.wea (wea ), // input [0 : 0] wea=1,写数据;wea=0,读数据。
.addra (addr ), // input [15 : 0] addra
.dina (Write_Data ), // input [15 : 0] dina
.douta (Read_Data ), // output [15 : 0] douta
.clkb(clk), // input wire clkb
.enb(), // input wire enb
.web(), // input wire [0 : 0] web
.addrb(), // input wire [9 : 0] addrb
.dinb(), // input wire [127 : 0] dinb
.doutb() // output wire [127 : 0] doutb
);
endmodule
2.2 testbench文件
`timescale 1ns / 1ps
module sim_top;
//input
reg clk;
reg rst_n;
reg trig;
True_TwoPort_RAM Inst_True_TwoPort_RAM(
.clk (clk ),
.rst_n (rst_n ),
.trig (trig )
);
// 初始化
initial
begin
//初始化输入
clk<=1'b0;
rst_n<=1'b0;
trig<=1'b0;
#20;
rst_n<=1'b1;
trig<=1'b1;
end
// create clock;
always #5 clk=~clk;//10ns一个周期,clk的频率为100M
endmodule
3 仿真结果

4万+

被折叠的 条评论
为什么被折叠?



