FPGA19 嵌入式RAM之双端口RAM 使用和测试
模块名称: dpram() IP Core
主要功能 :调用内部的资源,实现数据的读/写功能
实验目的 :了解这些芯片专用硬件资源的情况下,将其合理的应用到对应的系统中
FPGA 芯片的内部结构:
RAM,随机存取序列
实验目的及现象:通过串口发送数据到FPGA 中,FPGA接收到数据后将数据存储在双口 ram 的一段连续空间中,通过Quartus 软件提供的In-System Memory Content Editor 工具查看RAM中接收到的数据。当需要时,按下按键0,则FPGA将 RAM中存储的数据通过串口发送出去。
知识点: 1、Altera公司Cyclone lv系列器件的内部结构
2、存储器IP核的使用。
3、In-System Memory Content Editor 内存查看工具的使用。
4、后面实现【串口收发+按键+双口RAM组成的简易系统设计】
实现方式:
1、调用IP核,实现数据的存取
创建IP核
双口RAM配置:
对双口RAM【类似与电脑的内存条空间】的 解释
1、针对上面的结构图,我们可以看到 几个信号线
data[7:0],表示的是即将写入的数据
wraddress [4:0]: 表示的是数据要写入或者说是数据要存入的地址
wren : 表示数据写入使能信号
readdress[4:0] : 表示读取数据的地址
q[7:0 ]: 表示的是读取的该地址的数据。
clk : 时钟
2、如何使用双端口ram模块
① 一个读端口,一个写端口
②两个都是读/写端口
3、内存结构单元的大小
1、使用字节作为一个存取单
2、使用bit作为一个存取单元
ram 配置的类型
对双口RAM【类似与电脑的内存条空间】的解释
1、选择开辟的8bit(我们在上一张配置的结果中选择的是一个字节)的内存大小,这里是选择了 256字节
2、使用不同的数据对应着不同的位宽
理解: 这个的话就类似与整体的数据大小(size)和address的分配的一种对应关系
由上述 256字节来说
假设我们使用 8位数据输入,那么address就是[7:0]的地址
那么,如果在输出端配置的是:
? ① 8位数据输出,即q[7:0] ,那么 rdaddress也是 [7:0]
? ②16位数据输出,即q[15:0],那么 rdaddress就是[6:0]即可
也就是说,输入和输出是不一定都是相匹配的,可以根据自己的需求进行更改。
3、申请内存的分配的结构类型
默认选 auto(自动分配内存), M9K 和LCs的还不太了解。
1、第一个是时钟的配置
①选用单时钟
? ②读和写使用不同的时钟
? ③输入和输出使用不同的时钟
2、是否要创建读使能信号
? 下面的配置主要针对的是大于8位的位宽来进行配置的(暂时不管)
1、是否要使用寄存器(默认选择使用即可)
2、创建一个时钟使能信号(不用)
3、创建一个寄存器清零信号(暂时不用)
本次我们使用的读和写数据使用的是同一个时钟,当我们同时在读和写同一个地址的数据的时候,我们需要认为此时q输出的数据是:
? ① 读取之前的数据
? ② 我不关心是之前的还是当前写入的(本次选用的是下面的方案)
1、如何初始化你的内存(RAM)
? ① 让其保持空白
? ②使用mif文件对内存进行初始化
next
直接finish 。
本实验主要是熟悉和了解ram的使用:
以下是个人总结:
1、了解ram,其实ram就是我们说的内存,但是在我们实现的时候,就是要对内存执行【读/写】两个操作。
我们一般来说,写操作就是将输入写入到指定的地址中,【读】操作就是将存在在某个地址的数据读取出来。
生活实例:
? 这个可以理解为我们图书馆里面的书架,每个格子里面都可以存放书本(注:是任意或者非固定目标的书本),然后每个格子里面也各有标号。当我们需要读取的时候,只要对对应的格子编号,就可以找我我们要的书。
? 这个和ram是类似的,也就是说,地址里面的数据是可以根据自己的想法来改变的。
dpram_tb.v 文件
`timescale 1ns/1ns
`define clk_period 20
module dpram_tb;
reg clock;
reg [7:0]data;
reg [7:0]rdaddress;
reg [7:0]wraddress;
reg wren;
wire [7:0]q;
integer i;
dpram dpram0(
.clock(clock),
.data(data),
.rdaddress(rdaddress),
.wraddress(wraddress),
.wren(wren),
.q(q)
);
initial clock = 1;
always#(`clk_period/2)clock = ~clock;
initial begin
data = 0;
rdaddress = 30;
wraddress = 0;
wren = 0;
#(`clk_period*20 +1 );
for (i=0;i<=15;i=i+1)begin
wren = 1;
data = 255 - i;
wraddress = i;
#`clk_period;
end
wren = 0;
#(`clk_period*20);
for (i=0;i<=15;i=i+1)begin
rdaddress = i;
#`clk_period;
end
#(`clk_period*20);
$stop;
end
endmodule
|