设计背景:
ROM是只读存储器(Read-Only Memory)的简称,是一种只能读出事先所存数据的固态半导体存储器。其特性是一旦储存资料就无法再将之改变或删除。通常用在不需经常变更资料的电子或电脑系统中,并且资料不会因为电源关闭而消失。
ROM是由英文Read only Memory的首字母构成的,意为只读存储器。顾名思义,就是这样的存储器只能读,不能像RAM一样可以随时读和写。它只允许在生产出来之后有一次写的机会,数据一旦写入则不可更改。它另外一个特点是存储器掉电后里面的数据不丢失,可以存放成百上千年。此类存储器多用来存放固件,比如计算机启动的引导程序,手机、MP3、MP4、数码相机等一些电子产品的相应的程序代码。
设计原理:
我们的设计是读ROM的数据,然后读到最后一个数据的时候,然后又从最后的地址往回读数据,来实现循环读数。
首先我们先创建一个.mif文件,然后给对应的地址中写如数据,然后设计一个IP核,之后通过读ROM的地址,来读出ROM中存在的数据,具体的操作如下面的操作。
下一步,建立一个深度256,位宽为8的 .mif。
然后在第一个地址右键。
填写开始地址以及结束地址,我们给每一位的地址位写上和地址一样的数据,那么就是数据从0开始,步进为1,如下,然后然后完成,保存。
这样我们写好我们.mif文件,然后进行下面的步骤。
选择我们所选的硬件描述语言,我们都是verilog HDL,然后选择我们文件生成的路径,下一步。
设置我们的输出的位宽,和深度,我们的深度256,位宽8,下一步。
去掉输出是否有寄存器的对勾,如果选了输出会晚一拍,因为加了一个输出寄存器。
然后出现下面的界面,点击,选择我们生成的.mif文件,添加进来,然后下一步,下一步完成。
设计架构图:
设计代码:
顶层模块
0 module rom(clk,rst_n,data);
1 input clk;
2 input rst_n;
3
4 output [7:0] data;
5
6 wire [7:0]address;
7
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);
1
2 input clk;
3 input rst_n;
4
5 output reg [7:0] address;
6
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
1
2 module rom_tb();
3
4 reg clk;
5 reg rst_n;
6
7 wire [7:0] data;
8
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地址读数据,当读到最后一个数后,然后返回来从最后一个地址开始读数。
全部0条评论
快来发表一下你的评论吧 !