FPGA学习系列:16. rom控制器设计

描述

设计背景:

    ROM是只读存储器(Read-Only Memory)的简称,是一种只能读出事先所存数据的固态半导体存储器。其特性是一旦储存资料就无法再将之改变或删除。通常用在不需经常变更资料的电子或电脑系统中,并且资料不会因为电源关闭而消失。

    ROM是由英文Read only Memory的首字母构成的,意为只读存储器。顾名思义,就是这样的存储器只能读,不能像RAM一样可以随时读和写。它只允许在生产出来之后有一次写的机会,数据一旦写入则不可更改。它另外一个特点是存储器掉电后里面的数据不丢失,可以存放成百上千年。此类存储器多用来存放固件,比如计算机启动的引导程序,手机、MP3、MP4、数码相机等一些电子产品的相应的程序代码。

设计原理: 

    我们的设计是读ROM的数据,然后读到最后一个数据的时候,然后又从最后的地址往回读数据,来实现循环读数。

    首先我们先创建一个.mif文件,然后给对应的地址中写如数据,然后设计一个IP核,之后通过读ROM的地址,来读出ROM中存在的数据,具体的操作如下面的操作。      

                FPGA

    下一步,建立一个深度256,位宽为8的 .mif。

    FPGA

    FPGA

    然后在第一个地址右键。

                FPGA

                填写开始地址以及结束地址,我们给每一位的地址位写上和地址一样的数据,那么就是数据从0开始,步进为1,如下,然后然后完成,保存。

    FPGA

    FPGA

    这样我们写好我们.mif文件,然后进行下面的步骤。

    FPGA

    FPGA

    FPGA

    FPGA

    选择我们所选的硬件描述语言,我们都是verilog HDL,然后选择我们文件生成的路径,下一步。

    设置我们的输出的位宽,和深度,我们的深度256,位宽8,下一步。

    FPGA

    去掉输出是否有寄存器的对勾,如果选了输出会晚一拍,因为加了一个输出寄存器。

    FPGA

    然后出现下面的界面,点击FPGA,选择我们生成的.mif文件,添加进来,然后下一步,下一步完成。

    FPGA

    FPGA

设计架构图:

FPGA

设计代码:

顶层模块

0 module rom(clk,rst_n,data);

1  input clk;

2  input rst_n;

4  output [7:0] data;

6  wire [7:0]address;

8  rom_r rom_r (   //例化ROM控制器模块

9    .clk(clk),

10   .rst_n(rst_n),

11   .address(address)

12   );

13

14 my_rom my_rom_inst (       //例化IP核模块

15  .address ( address ),

16  .clock ( clk ),

17  .q ( data )

18 );

19

20 endmodule 

设计模块

0 module rom_r(clk,rst_n,address);

2  input clk;

3  input rst_n;

5  output reg [7:0] address;

7  reg [1:0] state;

8  always @(posedge clk or negedge rst_n)

9   if(!rst_n)

10   begin

11    address <= 1'b0;

12    state <= 1'b0;

13   end

14  else

15   begin

16    case (state)

17      0:begin

18        if(address < 255)    //判断地址

19         begin

20          address <= address + 1'b1; //地址激增

21         end

22        else

23         begin

24          if(address == 255)    //判断是否读完

25           begin

26            address <= address - 1'b1; 

27            state <= 1;

28           end

29          

30         end

31       end

32      1:begin

33        if(address > 0)  //读完就跳转一状态后让地址减1

34         begin

35          address <= address - 1'b1;

36         end

37        else

38         begin

39          address <= address + 1'b1;

40          state <= 0;

41         end

42       end

43      default : state <= 0;

44    endcase

45   end

46 endmodule 

测试模块

0 `timescale 1ns/1ps

2 module rom_tb();

4  reg clk;

5  reg rst_n;

7  wire [7:0] data;

9  initial begin

10   clk = 1'b1;

11   rst_n = 1'b0;

12

13   #100.1 rst_n = 1'b1;

14

15   #20000 $stop;   //20000NS后停止仿真

16

17  end

18

19  always #10 clk = ~clk;   //产生50M时钟

20

21 rom rom_dut (      //例化顶层模块

22   .clk(clk),

23   .rst_n(rst_n),

24   .data(data)

25   );

26 endmodule 

仿真图:

    仿真中我们可以看到和我们的设计一样,我们先从0地址读数据,当读到最后一个数后,然后返回来从最后一个地址开始读数。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分