片内RAM读写测试实验
概念
RAM是FPGA中常用的基础模块,可广泛用于缓存数据的情况,同样它也是 ROM,FIFO 的基础。
官方已经提供了RAM的IP核进行例化即可。
读写时序(具体还是要看官方资料):
过程
- 创建工程
- 在ip catalog里面搜索ram,选择Block Memory Generator,双击并进行设置即可。
代码
向RAM端口A写入一串连续数据,只写一次,并从端口B读出。
`timescale 1ns / 1ps
//
module ram_test(
input sys_clk_p, //system clock 200Mhz on board
input sys_clk_n, //system clock 200Mhz on board
input rst_n //复位信号,低电平有效
);
//-----------------------------------------------------------
reg [8:0] w_addr; //RAM PORTA写地址
reg [15:0] w_data; //RAM PORTA写数据
reg wea; //RAM PORTA使能
reg [8:0] r_addr; //RAM PORTB读地址
wire [15:0] r_data; //RAM PORTB读数据
wire clk ;
IBUFDS IBUFDS_inst (
.O(clk), // Buffer output
.I(sys_clk_p), // Diff_p buffer input (connect directly to top-level port)
.IB(sys_clk_n) // Diff_n buffer input (connect directly to top-level port)
);
//产生RAM PORTB读地址
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
r_addr <= 9'd0;
else if (|w_addr) //w_addr位或,不等于0
r_addr <= r_addr+1'b1;
else
r_addr <= 9'd0;
end
//产生RAM PORTA写使能信号
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
wea <= 1'b0;
else
begin
if(&w_addr) //w_addr的bit位全为1,共写入512个数据,写入完成
wea <= 1'b0;
else
wea <= 1'b1; //ram写使能
end
end
//产生RAM PORTA写入的地址及数据
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
w_addr <= 9'd0;
w_data <= 16'd1;
end
else
begin
if(wea) //ram写使能有效
begin
if (&w_addr) //w_addr的bit位全为1,共写入512个数据,写入完成
begin
w_addr <= w_addr ; //将地址和数据的值保持住,只写一次RAM
w_data <= w_data ;
end
else
begin
w_addr <= w_addr + 1'b1;
w_data <= w_data + 1'b1;
end
end
end
end
//实例化RAM
ram_ip ram_ip_inst (
.clka (clk ), // input clka
.wea (wea ), // input [0 : 0] wea
.addra (w_addr ), // input [8 : 0] addra
.dina (w_data ), // input [15 : 0] dina
.clkb (clk ), // input clkb
.addrb (r_addr ), // input [8 : 0] addrb
.doutb (r_data ) // output [15 : 0] doutb
);
//实例化ila逻辑分析仪
ila_0 ila_0_inst (
.clk (clk ),
.probe0 (r_data ),
.probe1 (r_addr )
);
endmodule
`timescale 1ns / 1ps
//
module vtf_ram_test;
// Inputs
reg sys_clk_p;
reg rst_n ;
wire sys_clk_n;
ram_test uut(
.sys_clk_p(sys_clk_p),
.sys_clk_n(sys_clk_n),
.rst_n(rst_n)
);
initial
begin
// Initialize Inputs
sys_clk_p = 0;
rst_n = 0;
// Wait for global reset to finish
#1000;
rst_n = 1;
end
//Create clock
always #2.5 sys_clk_p = ~ sys_clk_p; assign sys_clk_n = ~sys_clk_p ;
endmodule
仿真
在线仿真
仿真的话,可以把写入的值和读出的值均抓出来。
上板验证
代码中只抓取了读取数据的端口,通过读取数据验证是否正确。
总结
通过控制ram的时钟,地址,数据,使能端口,根据读取和写入时序进行数据的读取。
参考资料
- https://docs.xilinx.com/v/u/en-US/pg058-blk-mem-gen