一、简介
RAM(Random Access Memory):即随机访问存储器,它可以随时把数据写入任一指定地址的存储单元,也可以随时从任一指定地址中读出数据,其读写速度是由时钟频率决定的。RAM主要用来存放程序及程序执行过程中产生的中间数据、运算结果等。
二、实验任务
本节的实验任务是使用Vivado软件生成一个单端口的RAM并对其进行读写操作,然后通过仿真观察波形是否正确,最后通过在线调试工具对实验结果进行验证。如:将RAM设置的深度和宽度分别为32和8进行读写测试。
三、创建单端口RAM IP核
1.波形图
2.在vivado中创建工程
在ip目录找到ram下的 Block Memory
配置好后点OK
3.编写代码
ram_rw模块
module ram_rw(
input clk,
input rst_n,
input [7:0] ram_rd_data, //RAM读出的数据
output reg ram_en, //RAM使能信号,高电平有效
output ram_we, //RAM写使能 1:写 0:读
output reg [4:0] ram_addr, //RAM读写地址
output reg [7:0] ram_wr_data //RAM写入的数据
);
reg [5:0] rw_cnt;
assign ram_we = (rw_cnt <= 6'd31 && ram_en == 1'b1) ? 1'b1 : 1'b0;
//对RAM使能信后赋值,结束复位后拉高
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
ram_en <= 1'b0;
else
ram_en <= 1'b1;
end
//对re_cnt进行赋值,变化范围0~63
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
rw_cnt <= 6'b0;
else if(ram_en && rw_cnt == 6'd63)
rw_cnt <= 6'b0;
else if(ram_en)
rw_cnt <= rw_cnt + 6'b1;
else
rw_cnt <= 6'b0;
end
//对RAM地址进行赋值,地址0~31
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
ram_addr <= 5'b0;
else if(ram_en && ram_addr == 5'd31)
ram_addr <= 5'b0;
else if(ram_en)
ram_addr <= ram_addr + 5'b1;
else
ram_addr <= 5'b0;
end
//对RAM写数据进行赋值,在WE拉高期间地址0~31
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
ram_wr_data <= 8'b0;
else if(ram_we && ram_wr_data < 8'd31)
ram_wr_data <= ram_wr_data + 8'b1;
else
ram_wr_data <= 8'b0;
end
endmodule
顶层模块
module ip_1port_ram(
input sys_clk,
input sys_rst_n
);
wire [7:0] ram_rd_data ;
wire ram_en;
wire ram_we;
wire [4:0] ram_addr;
wire [7:0] ram_wr_data;
ram_rw u_ram_rw(
.clk (sys_clk ),
.rst_n (sys_rst_n),
.ram_rd_data (ram_rd_data ),
.ram_en (ram_en ),
.ram_we (ram_we ),
.ram_addr (ram_addr ),
.ram_wr_data (ram_wr_data )
);
blk_mem_gen_0 u_blk_mem_gen_0(
.clka (sys_clk),
.ena (ram_en),
.wea (ram_we),
.addra (ram_addr),
.dina (ram_wr_data),
.douta (ram_rd_data)
);
endmodule
4.仿真验证
编写tb文件
`timescale 1ns/1ns //仿真单位/仿真精度
module tb_ip_1port_ram();
parameter CLK_PERIOD = 20;
reg sys_clk; //周期20ns
reg sys_rst_n;
initial begin
sys_clk <= 1'b0;
sys_rst_n <= 1'b0;
#200
sys_rst_n <= 1'b1;
end
always #(CLK_PERIOD/2) sys_clk = ~sys_clk;
ip_1port_ram u_ip_1port_ram(
.sys_clk (sys_clk ),
.sys_rst_n (sys_rst_n)
);
endmodule
在design sources中添加例化代码和tb文件
运行功能仿真后
5.联合仿真
vivado编译仿真库
在vivado中运行仿真之后自动同步到modulesim中
输出波形与预计波形相同。
四、下载验证
生成约束文件。
编译出现问题
原因是顶层模块里没有输出端口定义,所以需要在线调试助手。
在网表里面添加Set Up Debug
保存后重新编译,再连接开发板。
可以看出与预计波形相符。