1.介绍
- RAM英文全称为Random Access Memory,即随机存取存储器,它可以随时把数据写入任一指定地址的存储单元,也可以随时从任一指定地址中读出数据,其读写速度是由时钟频率决定的 。RAM主要用来存放程序及程序执行过程中产生的中间数据、运行结果等。
2.RAM IP核简介
- Quartus II软件自带的随机存储器IP核分为RAM IP核和ROM IP核。这两种IP核的区别是RAM是一种随机存取存储器,不仅仅可以存储数据,同时支持对存储的数据进行修改;而ROM是一种只读存储器,也就是说,在正常工作时只能读出数据,而不能写入数据。需要注意的是,这两种存储器使用的资源都是FPGA的内部嵌入式RAM块, 只不过ROM IP核只用到了嵌入式RAM块的读数据端口。本章我们主要介绍RAM IP核的使用方法。
- Altera推出的RAM IP核分为两种类型:单端口RAM和双端口RAM。单端口RAM只有一组地址线,这组地址线控制着写数据端口和读数据端口,而双端口RAM具有两组地址线,这两组地址线分别控制着写数据端口和读数据端口。
data:RAM写数据端口
address:RAM读写地址端口,对于单口RAM来说,读地址和写地址共用同一组地址;
wren:写使能信号,高电平有效;
byteena:字节使能控制,该功能屏蔽了输入数据,这样仅写入数据中指定字节,未被写入的字节保留之前写入的值。当写入数据的位宽为16位、18位、32位和36位时,M9K模块将支持字节使能, wren信号以及字节byteena信号一起控制RAM模块的写操作。 byteena信号在RAM IP核创建过程中是可选的,可选择是否使用字节使能控制功能。
addressstall:地址使能控制,当addressstall信号为高电平时,有效地址时钟使能就会保持之前的地址。addressstall信号在RAM IP核创建过程中是可选的,可选择是否使用地址使能控制功能。
clockena:时钟使能控制,高电平有效;
rden:读使能信号,高电平有效;
aclr:异步复位信号,高电平有效;
inclock、outclock:单口RAM端口支持输入与输出时钟模式和单时钟模式。在输入与输出时钟模式下,输入时钟控制存储器模块的所有输入寄存器,其中包括数据、地址、byteena、wren以及rden寄存器;输出时钟控制数据输出寄存器。在单时钟模式下,没有inclock信号与outclock信号,只有一个clock信号, 可以通过单时钟以及时钟使能来控制M9K存储器模块中的所有寄存器。
3.试验任务
使用Altera RAM IP核生成一个单端口的RAM,然后对 RAM进行读写操作,并仿真。
4.硬件设计
5.程序设计
上面页面中,我们取消选中q输出端口,否则读出的数据会多延时一个时钟周期;
- ram_1port模块的端口分别为: address (ram读写地址) 、 clock (ram读写驱动时钟)、data(ram写数据)、rden(ram读使能信号)、wren(ram写使能信号)和q(ram读出的数据) , 其中读地址和写地址都是共用address地址线的。 当我们需要写入数据时,把wren信号拉高的同时,给出地址(address)和写数据(data),数据就会按照指定的地址写入对应的存储单元;当我们需要读数据时,把rden信号拉高,给出地址(address),q(ram读出的数据)就会根据指定的地址输出对应存储单元的数据。
module RAM
(
input sys_clk, //system clock
input sys_rst_n //system reset
);
//wire define
wire ram_wr_en ; //write en
wire ram_rd_en ; //read en
wire [4:0] ram_addr ; //addr
wire [7:0] ram_wr_data ; //
wire [7:0] ram_rd_data ;
ram_rw u_ram_rw(
.sys_clk (sys_clk ),
.sys_rst_n (sys_rst_n ),
.ram_wr_en (ram_wr_en ),
.ram_rd_en (ram_rd_en ),
.ram_addr (ram_addr ),
.ram_wr_data (ram_wr_data ),
.ram_rd_data (ram_rd_data )
);
ip_ram ip_ram_inst(
.clock (sys_clk ),
.address (ram_addr ),
.data (ram_wr_data ),
.rden (ram_rd_en ),
.wren (ram_wr_en ),
.q (ram_rd_data)
);
endmodule
module ram_rw
(
input sys_clk, //系统时钟
input sys_rst_n, //系统复位
output ram_wr_en , //ram写使能
output ram_rd_en , //ram读使能
output reg [4:0] ram_addr , //ram读写地址
output reg [7:0] ram_wr_data, //ram写数据
input [7:0] ram_rd_data //ram读数据
);
reg [5:0] rw_cnt; //读写控制计数器
assign ram_wr_en=((rw_cnt>=6'd0)&&(rw_cnt<=6'd31)) ?1'b1 : 1'b0;
assign ram_rd_en=((rw_cnt>=6'd32)&&(rw_cnt<=6'd63)) ?1'b1 : 1'b0;
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
rw_cnt<=6'd0;
else begin
if(rw_cnt==6'd63)
rw_cnt<=6'd0;
else
rw_cnt<=rw_cnt+1'b1;
end
end
//读写控制器计数范围:0~31 产生ram写使能信号和写数据信号
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
ram_wr_data <= 8'd0;
else if(rw_cnt >= 6'd0 && rw_cnt <= 6'd31)
ram_wr_data <= ram_wr_data + 8'd1;
else
ram_wr_data <= 8'd0;
end
//读写地址信号 范围为0——31
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
ram_addr<=5'd0;
else begin
if(ram_addr==5'd31)
ram_addr<=5'd0;
else
ram_addr<=ram_addr+1'b1;
end
end
endmodule
采用计数0-63 前32个周期写 数据 后32个周期读数据 其中计数和地址的递增一致 通过仿真调试得出结果如下图
上图为写数据 过程 写使能拉高为1 对应的数据写入对应的地址之中
上图对应的读RAM的过程 读使能信号拉高 将地址0-31中数据一次读出 输出是延迟一个 周期读出的!
修改RAM IP中该位置 可进行RAM的在线查看内部存储实际情况 修改完 重新编译下载
上面是调试RAM的方法。