背景
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
版权声明:本文为CSDN博主「ciscomonkey」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ciscomonkey/article/details/90453592