只读储存器ROM IP核的调取及应用

写在前面的话

在项目设计中,我们通常需要使用一些固定的数据。如果是使用单片机,那么在数据量比较大的情况下,这些数据就必须存储在外挂的存储芯片中。那么,使用FPGA呢?在数据量不是特别大的情况下,我们可以将这些数据存储到FPGA片内的存储器中,这样既节约了板级成本,又可以保证数据不容易受到外界干扰。那么本节,梦翼师兄和大家一起学习FPGA只读存储器IP核-ROM的设计。

项目需求

设计一个ROM控制器,该控制器负责输出0-255递增的地址数据,将此地址总线连接到ROM地址输入端,查看ROM输出的数据是否正确

操作步骤

由于ROM是只读存储器也就是说我们不能对其内部写入外部数据那么我们就需要创建一个ROM的数据初始化文件mif文件(mif文件用来存放初始数据)

定义位宽和深度(这里我们选择位宽为8位,深度为256

填充数据(在这里我们用软件自带的一种的填充数据的方式,填充上0255,大家自己在项目中应用的时候,应该填充上自己所需要的初始值)。

mif文件建立成功(地址从0255,数据从0开始,每次增加1,所以此时的mif文件中存放的是0255)。

在右侧的IP核搜索的编辑区,输入rom,在菜单栏找到并双击rom(在这里我们使用单端口的rom,双端口的rom,自己感兴趣的话,可以自己调用试一试)。

选择语言类型Verilog,同时为该IP核命名,然后点击【OK】

进入rom的设置向导,设置深度和字节的宽度(rom的深度和字节宽度必须要和建立的mif文件保持一致),然后点击【NEXT

 

把输出端口的寄存器去掉(如果不去掉的话,就会使输出延迟一拍。这里我们不需要延迟这一拍,所以去掉),然后点击【NEXT

进入如下界面,点击【browse···】(找到我们之前建立的mif文件,添加进来),点击【NEXT】

 

一直点击【NEXT】,直到出现如下界面,把my_rom_inst.v选择上,然后点击【finish】(完成rom的设置)

 顶层架构设计

 Rom是只读存储器,需要我们指定地址,它才能输出对应地址的数据。

模块功能介绍

模块名

功能描述

Rom_control

ROM控制模块,产生递增的地址信号

My_rom

ROM存储器IP核

Rom

系统顶层模块,负责子模块级联

端口和内部连线描述


顶层模块端口介绍

端口名

端口说明

Clk

系统时钟输入

Rst_n

系统复位

q

数据输出

系统内部连线介绍

连线名

连线说明

addr

Rom_control产生的地址信号

代码解释

Rom_control模块的代码

/****************************************************          

*   Engineer        :   梦翼师兄

*   QQ               :   761664056

*   The module function:  输出有效地址

*****************************************************/

01  module rom_control (

02                              clk,        //系统时钟输入

03                              rst_n,  //系统复位

04                              addr        //地址输出

05                          );

06      // 系统输入

07      input clk;      //系统时钟输入

08      input rst_n;    //系统复位

09      

10      output reg [7:0] addr;  //地址输出

11      

12      // 产生地址电路

13      always @ (posedge clk or negedge rst_n)

14          begin

15              if (!rst_n)

16              addr <= 0; // 复位的时候地址是0

17              else

18                  if (addr < 255) // 让地址在0255循环

19                      addr <= addr + 1;

20                  else    

21                      addr <= 0;

22          end

23

24  endmodule 

本模块只是产生了有效的地址信号,让地址信号在0到255之间循环,用于rom的输入,遍历rom全部存储空间,验证rom是否能够正确地输出对应地址的数据。 

Rom模块代码

/****************************************************          

*   Engineer        :   梦翼师兄

*   QQ               :   761664056

*   The module function:  顶层连接

*****************************************************/

01  module rom (

02                  clk,        //系统时钟输入

03                  rst_n,  //系统复位

04                  q           //有效数据输出

05              );

06      //系统输入

07      input clk;          //系统时钟输入

08      input rst_n;        //系统复位

09      //系统输出

10      output [7:0] q; //有效数据输出

11      //定义中间连线

12      wire [7:0] addr; //定义地址信号

13      //实例化rom_control

14      rom_control rom_control (

15                                              .clk(clk),      //系统时钟输入

16                                              .rst_n(rst_n), //系统复位

17                                              .addr(addr)     //地址输出

18                                          );

19      //IP--rom的调用

20      my_rom  my_rom_inst (

21                                  .address ( addr ),      // 地址输入

22                                  .clock ( clk ),         // 时钟输入

23                                  .q ( q )                 //有效数据输出

24                              );

25

26  endmodule 

本模块只是用于做连接,没有任何的逻辑。编写完可综合代码之后,查看RTL视图如下:

 RTL视图可以看出,代码综合以后得到的电路和我们设计的系统框图一致,接下来,编写测试代码如下:

/****************************************************          

*   Engineer        :   梦翼师兄

*   QQ               :   761664056

*   The module function:  顶层测试

*****************************************************/

01   `timescale 1ns/1ps //时间单位和精度定义

02   module rom_tb;

03   

04      //系统输入

05      reg clk;            //系统时钟输入

06      reg rst_n;      //系统复位

07      //系统输出

08      wire [7:0] q;   //有效数据输出

09      

10      initial begin

11          clk = 1;

12          rst_n = 0;

13          # 200.1

14          rst_n = 1;

15      end

16      

17      always # 10 clk = ~clk;  //50MHz时钟

18   

19      rom rom (

20                      .clk(clk),      //系统时钟输入

21                      .rst_n(rst_n),  //系统复位

22                      .q(q)           //有效数据输出

23                  );

24   

25   endmodule 

 仿真分析

当复位信号拉高以后,addr(地址)开始发生变化,qrom的输出)开始输出有效数据,并且是每一拍都会输出一个有效数据。地址和数据之间存在一拍的延迟是由于rom内部结构导致的。

在地址循环的同时,对应地址的有效数据也循环输出,证明我们的ip核使用正确。

原文地址:https://www.cnblogs.com/mengyi1989/p/11515982.html