Xilinx RAM IP核的使用
背景
RAM和ROM也是类似的,由于这也是常用的IP核,所有完全有必要在这里记录一下,以后用到了实际后,再补充到实际工程中。随机存储器(RAM),它可以随时从任一指定地址读出数据,也可以随时把数据写入任何指定的存储单元,且读写的速度与存储单元在存储芯片的位置无关。RAM主要用来存放程序及程序执行过程中产生的中间数据、运算结果等。RAM按照存储单元的工作原理可以分为静态RAM和动态RAM,也就是常说的SRAM和DRAM。
SRAM速度非常快,是目前读写最快的存储设备,比如CPU的一级缓冲,二级缓冲。而计算机内存就是DRAM,比SRAM便宜。这里要说明的是,DRAM与SRAM相比较速度慢,但是它与ROM相比较速度还是很快的。
RAM IP核同ROM IP核一样,xilinx也提供了两种:一种是单端口的RAM IP,另一种是双端口的RAM IP。
IP核之RAM的配置
在这个页面中,有3个可供修改的标签“option output resisters”(可选输出寄存器)的“portA”(端口A)、“memory Initialization”(存储器初始化)和“File Remaining Memory Locations”(填补剩余的内存位置)。
在“port A”(端口A)栏有两个可修改项:
“register port A output of memory primitives”:表示源于的输出端口A处增加寄存器级。
“Register port A output of memory core”:表示在IP核的输出端口A处增加寄存器级。
在“memory Initialization”(存储器初始化)栏中,我们可以载入coe文件对ROM IP核进行初始化。在“Fiie Remaining Memory Locations”(填补剩余的内存位置)栏中,我们可以将剩余内存填充上我们指定的数值。
在这个页面中,有2个可供修改的标签,“power estimate options”(功耗估计选项)的“output reset options”(输出复位选项)的“port A”(端口A)可以选择是否添加一个“RSTA”引脚。“output reset valure(Hex)”设置复位输出值(十六进制)。
创建好了RAM 后,进行例化。
代码:
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 09:44:24 05/23/2019
// Design Name:
// Module Name: RAM_top
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//下述功能描述了写入一个地址为0~511的地址,从512~1023 不写入数据
//
module RAM_top(
input clk,
input rst,
output reg ram_en, //RAM IP核的使能信号
output reg wren, //RAM IP核的写使能信号
//RAM IP核的地址信号
output reg [7 : 0] wrdata, //RAM IP核的写数据信号
output [7 : 0] rddata //RAM IP核的读数据信号
//用来产生地址和数据的计数器
);
reg [8 : 0] addr=0;
reg [7 : 0] time_cnt=0;
always @ (posedge clk or negedge rst)
begin
if(!rst)
time_cnt<=0;
else if(time_cnt=='d1023)
time_cnt<=1'd0;
else
time_cnt<=time_cnt+1;
end
//用来产生RAM IP核的写使能信号
always @ (posedge clk or negedge rst)
begin
if(!rst)
wren<=0;
else if (time_cnt<='d511)
wren<=1'b1;
else
wren<=0;
end
//用来产生RAM IP核的地址信号
always @ (posedge clk or negedge rst)
begin
if(!rst)
addr<=0;
else if (time_cnt<='d511)
addr<=time_cnt;
else
addr<=time_cnt-'d512;
end
//用来产生RAM IP核的写数据信号
always @ (posedge clk or negedge rst)
begin
if(!rst)
wrdata<=0;
else if (time_cnt<='d511)
wrdata<=time_cnt;
else
wrdata<=wrdata;
end
//例化RAM模块
RAM_IP RAM_IP_inst(
.clka(clk), //50M时钟输入
.wea(wren), //写使能信号
.addra(addr), //地址信号
.dina(wrdata), //写数据信号
.douta(rddata) //读数据信号
);
endmodule
下面来说一下该代码主要实现了什么功能,该代码主要实现了先往RAM IP核中的0 ~ 511地址写入0 ~511 数据,每个地址对应一个数据,比如0地址对应0数据,1地址对应1数据,以此类推。写完了512个数据之后,读数据时,我们需要将写使能拉低,而ram_en信号在操作RAM的过程中需要一直拉高。(虽然在这里,我们没有设置ranm_en)。再写完512个数据后,然后进行读数据,此时,输入一个地址,读取一个对应地址的数据,此时将wren保持为低,这样就没法写入数据,只能读取数据了。给一个地址,读取一个对应地址的数据。
仿真
采用modelsim SE 10.4 进行仿真,一看上去波形正确。
我们放大来看看,也可以看到,在地址为0,读取数据为0,然后地址为1,读取数据为1.以此类推。
note:仿真失败的,要注意添加ISE的库到modelsim中,或者编译库文件,再调用modelsim。
https://blog.csdn.net/ciscomonkey/article/details/90343303
工程链接:
https://download.csdn.net/download/ciscomonkey/11199757