RAM简介:
RAM 的英文全称是 Random Access Memory,即随机存取存储器, 它可以随时把数据写入任一指定地址的存储单元,也可以随时从任一指定地址中读出数据, 其读写速度是由时钟频率决定的。 RAM 主要用来存放程序及程序执行过程中产生的中间数据、 运算结果等。
RAM分类:
这里我们使用最简单的单端口RAM:
- DINA:RAM 端口 A 写数据信号。
- ADDRA:RAM 端口 A 读写地址信号,对于单端口 RAM 来说,读地址和写地址共用同该地址线。
- WEA:RAM 端口 A 写使能信号,高电平表示向 RAM 中写入数据,低电平表示从 RAM 中读出数据。
- ENA:端口 A 的使能信号,高电平表示使能端口 A,低电平表示端口 A 被禁止,禁止后端口 A 上的读写操作都会变成无效。另外 ENA信号是可选的,当取消该使能信号后, RAM 会一直处于有效状态。
- RSTA:RAM 端口 A 复位信号,可配置成高电平或者低电平复位,该复位信号是一个可选信号。
- REGCEA: RAM 端口 A 输出寄存器使能信号,当 REGCEA 为高电平时, DOUTA 保持最后一次输出的数据, REGCEA
同样是一个可选信号。 - CLKA:RAM 端口 A 的时钟信号
- DOUTA:RAM 端口 A 读出的数据
本次实验的RAM由Vivado里面自带的BRAM生成而来,位宽为8位,深度为32。
实验代码
ram_rw control代码:
module ram_rw(
input wire clk_50m,
input wire rstn,
output wire ram_en, //RAM使能信号
output wire ram_wea, //RAM读写选择
output reg [4:0] ram_addr, //RAM读写地址
output reg [7:0] ram_wr_data, //RAM写数据
input wire [7:0] ram_rd_data //RAM读数据
);
reg [5:0] rw_cnt; //读写控制计数器
//控制RAM使能信号
assign ram_en = rstn;
//rw_cnt 计数范围,在0-31向RAM中写入数据,32-63中读出数据
assign ram_wea = ((rw_cnt <= 6'd31)&&(ram_en ==1'b1))? 1'b1 : 1'b0;
//读写控制计数器,计数范围0-63
always@(posedge clk_50m or negedge rstn) begin
if(!rstn) begin
rw_cnt <= 6'd0;
end
else if(rw_cnt == 6'd63) begin
rw_cnt <= 6'd0;
end
else begin
rw_cnt <= rw_cnt + 6'd1;
end
end
//读写地址
always@(posedge clk_50m or negedge rstn) begin
if(!rstn) begin
ram_addr <= 5'd0;
end
else if(ram_addr == 5'd31) begin
ram_addr <= 5'd0;
end
else begin
ram_addr <= ram_addr + 5'd1;
end
end
//产生写入的数据
always@(posedge clk_50m or negedge rstn) begin
if(!rstn) begin
ram_wr_data <= 8'd63;
end
else if(rw_cnt < 6'd31) begin
ram_wr_data <= ram_wr_data - 8'd1;
end
else begin
ram_wr_data <= 8'd63;
end
end
endmodule
ram_top代码:
module ip_ram(
input wire clk_50m,
input wire rstn
);
wire ram_en; //RAM使能信号
wire ram_wea; //RAM读写选择
wire [4:0] ram_addr; //RAM读写地址
wire [7:0] ram_wr_data; //RAM写数据
wire [7:0] ram_rd_data; //RAM读数据
//ram contral
ram_rw
u_ram_rw (
.clk_50m (clk_50m),
.rstn (rstn),
.ram_en (ram_en), //RAM使能信号
.ram_wea (ram_wea), //RAM读写选择
.ram_addr (ram_addr), //RAM读写地址
.ram_wr_data (ram_wr_data), //RAM写数据
.ram_rd_data (ram_rd_data) //RAM读数据
);
//例化生成的RAM
blk_mem_gen_0
u_blk_mem_gen_0 (
.clka (clk_50m), // input wire clka
.ena (ram_en), // input wire ena
.wea (ram_wea), // input wire [0 : 0] wea
.addra (ram_addr), // input wire [4 : 0] addra
.dina (ram_wr_data), // input wire [7 : 0] dina
.douta (ram_rd_data) // output wire [7 : 0] douta
);
endmodule
Testbench验证代码:
`timescale 1ns / 1ps
module tb_ram();
reg sys_clock;
reg sys_rstn;
always #10 sys_clock = ~sys_clock;
initial begin
sys_clock = 1'b0;
sys_rstn = 1'b0;
#500
sys_rstn = 1'b1;
end
ip_ram
u_ip_ram(
.clk_50m (sys_clock),
.rstn (sys_rstn)
);
endmodule
仿真波形: