FPGA片内ROM读写测试实验


前言

FPGA 本身是 SRAM 架构的,断电之后程序就会消失,那么如何利用 FPGA 实现一个 ROM 呢,我们可以利用 FPGA 内部的 RAM 资源实现 ROM,但这不是真正意义上的 ROM,而是每次上电都会把初始化的值先写入 RAM。Vivado 软件中提供了 ROM 的 IP 核 , 我们只需通过 IP 核例化一个 ROM,根据 ROM 的读时序来读取 ROM 中存储的数据。本节将介绍如何使用 FPGA 内部的 ROM 以及程序对该 ROM 的数据读操作。该实验与 FPGA 片内 RAM 读写测试实验操作类似,可以参考一下。


一、准备 ROM 初始化文件

对于 ROM,我们需要提前准备好数据,这样在 FPGA 实际运行时,就可以直接读取 ROM 中预存好的数据了。Xilinx FPGA 的片内 ROM 支持初始化数据配置,我这里创建一个名为 “rom_init.coe” 的 ROM 初始化文件,后面会用得到。

将下面的内容拷贝进去:

MEMORY_INITIALIZATION_RADIX=16;        //表示ROM内容的数据格式是16进制
MEMORY_INITIALIZATION_VECTOR= 
11,
22,
33,
44,
55,
66,
77,
88,
99,
aa,
bb,
cc,
dd,
ee,
ff,
00,
a1,
a2,
a3,
a4,
a5,
a6,
a7,
a8,
b1,
b2,
b3,
b4,
b5,
b6,
b7,
b8;       //每个数据后面用逗号或者空格或者换行符隔开,最后一个数据后面加分号

ROM 初始化文件的内容格式比较简单,其中第 1 行为定义的数据格式,第 3 行到第 34 行是这个 32*8bit 大小ROM的初始化数据,每行数字后面用逗号,最后一行数字结束时用分号。

二、创建及配置工程

1、创建工程

新建一个 rom_test 的工程
在这里插入图片描述
将刚刚的 rom_init.coe 文件放到当前工程目录中
在这里插入图片描述

2、添加 ROM IP核

①、 点击下图中 IP Catalog ,在右侧弹出的界面中搜索 rom ,找到 Block Memory Generator,双击打开。
在这里插入图片描述
②、Basic 选项栏按照下图进行配置
在这里插入图片描述
③、Port A Option 选项栏按照下图进行配置
在这里插入图片描述
把 Primitives Output Register 取消勾选,其功能是在输出数据上加寄存器,这可以有效改善时序 ,但读出的数据会落后地址两个周期,因此在很多情况下,不用这项功能,保持读出的数据落后地址一个周期即可。

④、在 Other Options 下勾选 Load Init File,然后点击 Browse 查找第一步中创建好的文件 rom_init.coe,并点击 OK
在这里插入图片描述
⑤、在弹出的对话框中点击 Generate 就可以生成 ROM IP。
在这里插入图片描述

3、添加 ILA IP 核

①、点击左侧 PROJECT MANAGER 栏 –> IP Catalog 或者菜单栏下 Window –> IP Catalog 然后在右侧出现的 IP Catalog 窗口下搜索 ILA,双击选择 Debug 下的 ILA 进行 IP 配置操作步骤如下图所示
在这里插入图片描述
②、General Option 添加两个探针去采集我们读的地址和数据,采样数据的深度我们设置大一些,如下图所示
在这里插入图片描述
③、Probe_Ports(0…7) 中PROBE0 用来采集 5 位地址,PROBE1 用来采集 8 位数据,并点击 OK,如下图所示
在这里插入图片描述
④、点击 OK,再点击 Generate,生成 ILA IP

三、程序编写

1、新建测试程序

新建 rom_test.v 源文件并将下面的程序块拷贝过去
rom_test.v

`timescale 1ns / 1ps

module rom_test(
	input sys_clk,	//50MHz时钟
	input rst_n		//复位,低电平有效
    );

wire [7:0] rom_data;	  //ROM读出数据
reg	 [4:0] rom_addr;      //ROM输入地址 

//产生ROM地址读取数据
always @ (posedge sys_clk or negedge rst_n)
begin
    if(!rst_n)
        rom_addr <= 10'd0;
    else
        rom_addr <= rom_addr+1'b1;
end        
//实例化ROM
rom_ip rom_ip_inst
(
    .clka   (sys_clk),      //inoput clka
    .addra  (rom_addr),      //input [4:0] addra
    .douta  (rom_data)       //output [7:0] douta
);
//实例化逻辑分析仪
ila_0 ila_m0
(
    .clk    (sys_clk),
    .probe0 (rom_addr),
	.probe1 (rom_data)
);

endmodule

在这里插入图片描述

2、新建仿真文件

新建 vtf_rom_tb.v 仿真文件并将下面的程序块拷贝过去
vtf_rom_tb.v

`timescale 1ns / 1ps

module vtf_rom_tb;
// Inputs
reg sys_clk;
reg rst_n;

// Instantiate the Unit Under Test (UUT)
rom_test uut (
	.sys_clk	(sys_clk), 		
	.rst_n		(rst_n)
);

initial 
begin
	// Initialize Inputs
	sys_clk = 0;
	rst_n = 0;

	// Wait 100 ns for global reset to finish
	#100;
      rst_n = 1;       

 end

always #10 sys_clk = ~ sys_clk;   //20ns一个周期,产生50MHz时钟源
   
endmodule

在这里插入图片描述

四、进行仿真

1、点击 Run Simulation -> Run Behavioral Simulation,进行仿真
在这里插入图片描述
2、将 ROM 里面地址和数据信号拖拽进观察窗口
在这里插入图片描述3、点击 Run for 200us,可以看到如下图仿真波形

在这里插入图片描述
可以看到地址 0 对应数据 0x11,地址 1 对应于数据 0x22 …,与我们之前的 “rom_init.coe” 的 ROM 初始化文件一致

五、下载到 FPGA

1、引脚约束及时序约束

rst_n -> T11
clk -> U18

新建引脚约束文件 rom.xdc,将下面语句拷贝过去并保存

set_property PACKAGE_PIN T11 [get_ports rst_n]
set_property IOSTANDARD LVCMOS33 [get_ports rst_n]
set_property PACKAGE_PIN U18 [get_ports sys_clk]
set_property IOSTANDARD LVCMOS33 [get_ports sys_clk]

create_clock -period 20.000 -name sys_clk -waveform {
    
    0.000 10.000} [get_ports sys_clk]

在这里插入图片描述
2、生成比特文件
点击 “Generate Bitstream”,直接生成 bit 文件
在这里插入图片描述
3、下载程序
连接上 JTAG 以及电源线,将板子上电,下载程序
在这里插入图片描述
4、逻辑分析仪分析波形
以 10 进制方式查看读取的内存及数据,设置触发条件为 “rom 地址为 0”,可以看到地址 0 的数据为 0x11,rom 地址 31 时的数据为 0xb8,可见满足了预期结果。
在这里插入图片描述

六、资源自取

FPGA片内ROM测试实验


我的qq:2442391036,欢迎交流!


猜你喜欢

转载自blog.csdn.net/qq_41839588/article/details/133429286
ROM