在Quartus 下有许多免费的IPcore可以使用,其中存储器就包括ROM,单口RAM,双口RAM,FIFO等。这些集成功能IPcore功能强大,接口简单,仿真文件齐全,配套的设计案例丰富。充分利用这些IPcore不仅使设计变得简单,性能高,而且稳定可靠。本节内容就从最简单的ROM IPcore的生成,配置及使用介绍开始,逐步把相关的存储器类IPcore介绍给大家。在这篇文章中主要介绍ROM的生成与配置。
ROM (read only memory)只读存储器,也就是掉电信息不丢失。大家可能会有疑问,既然FPGA是基于RAM的架构,FPGA内如何做到掉电信息不丢失的?其实原理很简单,也就是ROM的内容随着FPGA上电配置,一起从外部存储器中将ROM的内容写入的。因此从用户的角度看,的确做到ROM的信息在掉电后信息一直保存的现象。为了使用方便,Quartus 提供ROM的生成与配置向导,ROM的生成步骤如下:
1. 新建测试工程
在learning_course 目录新建文件夹test_rom(c:/learning_course/test_rom),工程名称test_rom,顶层设计实体(top level design entity)的名称为test_rom。器件选择Cyclone 10 LP , 10cl006YE144C8G。EAD tool Settings –>Simulation–>Modelsim-Altera。
2.选取ROM类型
在工程的 IP Catalog区域内Library–>Basic Functions–>On Chip Memory–>ROM:1-PORT,如图1,双击跳出界面如图2。

图1
在图2中IP的文件名称为p1_rom,可以根据命名规则给出名称,这里以p1_rom为例。点击OK. 弹出对话框如图3,

图2
3. 配置ROM参数
在图3中设置如下:
-
- 输出的宽度8bits和深度256 words,这主要映射到左边的图形的输出q的向量宽度(如本例为q[7..0]对应8位宽度)和地址深度(如本例address[7..0] 为256 words).其实在选定芯片的可提供的范围内,宽度和深度是可以任意设定的。这里设定的是工程中ROM的使用情况。
- 选择memory block 的类型,在Cyclone 10 LP 中只有M9K一种类型可以使用,如果选择的器件是其他类型如Arria10系列或Straitix10系列,有更多的类型可以支持,如MLAB,LCs,M144K等。可以选择具体类型(用户定制),也可以选择Auto(自动,由系统根据系统优化进行选择配置)。因此对于Cyclone 10 LP 器件选择Auto 与选择M9K效果相同。这里设定的是每个M9K的配置情况。
- 对于M9K的结构,最佳使用方式是1bit x 9K ,或9 bits x 1K,18bits x 512,36 bits x 256等方式,这样可以把M9K的资源充分利用起来。可以作不同的选择观察左下角资源使用情况( Resource Usage)。
- 时钟的设定,根据需要可以将地址和输出设为同一个时钟,也可以设为不同的时钟,这里设为相同的时钟。点击NEXT,跳出对话框如图4,

图3
图4中的各个设置及问题解释如下:
-
- ROM的输出的数据是否需要寄存器锁存? (这个是可选项)
-
- 只锁存地址(这个是必选项),不锁存数据输出如图4,这样的选择在地址确定后只有地址通道带来的一级延迟,例:读取地址8’h0f到8’h1f的值。
reg [7:0] addr;
wire [7:0] q;
reg [7:0] data;
reg [1:0] rd_st; //状态
always@(posedge clk or posedge rst)
if(rst)
begin
rd_st <= 0;
data <= 0;
addr <= 0;
end
else case(rd_st)
0:
begin
rd_st <= 1;
data <= 0;
addr <= 8'h0f;
end
1:
begin //给状态下,addr==8'h0f
rd_st <= 2;
data <= 0;
addr <= addr + 1;
end
2:
begin //给状态才得到 地址 8'h0f的值。
data <= q;
if(addr == 8'h1f)
begin
rd_st <= 3;
end
else
begin
addr <= addr + 1;
end
end
3:
begin
data <= q;
rd_st <= 0;
end
default: rd_st <= 0;
endcase
从上例可以看出,在状态0给地址addr赋值,在状态1时addr的输出才得到地址值,而ROM有时在clock的驱动下的地址锁存,因此ROM内的地址address的输出也延迟一个时钟才会输出,如果如图4的结构,q端没有寄存器缓冲,逻辑译码可以直接输出。
-
- 如果q端也有寄存器锁存,输出将会再延迟一个时钟输出。

图4
-
- 时钟使能,主要考虑到低功耗模式,如果设计的产品将来会运行在低功耗模式,需要深度睡眠状态,就要添加时钟使能端。当然时钟使能添加后,IPcore的使用也变得相对复杂。
- 选择是否添加异步清零端口aclr,该端口是针对address及输出端q的寄存器而言的,即在添加了异步清零后,可以通过异步清零端口清除寄存器的值。这里没有选择异步清零端口。
- 选择是否创建’rden’端口,如果选择创建该端口,在ROM读取的时候rden必须为高(逻辑1),输出端口q才会更新。如图5,

图5
在图5中点击Next,跳到对话框图6,
4.ROM 的初始化文件
图6中的设置:
-
- 选择包含ROM 的初始内容的文件(memory initial content data file),可以有两种文件被支持,分别是文件扩展名为.mif(memory initialization file)与.hex (Hexadecimal (Intel-format) file)的文件,现在还没有创建对应的文件,可以在工程目录中建立一个空文件,并修改名称为p1_rom.mif, 在图6中通过Browse 按钮找到该文件并选中。
- Allow In-System Memory Content Editor…这个内容在后续章节讲解,这里先选中。
点击Next,跳出图7 对话框。

图 6
图7 提示
-
- 如需正常仿真该IPcore生成的文件,需要 Altera_mf 库。特别是在使用独立的Modelsim进行仿真时。
- 产生时序和资源评估的网表文件。这个主要是在使用第三方EDA综合工具时才用得到。这里都是在Quartus 下综合,因此不选”Generate netlist file”。
- 点击Next ,如图8,

图7
在图8中选择需要的文件,如p1_rom_inst.v,p1_rom_bb.v。

图8
点击Finish , 完成ROM的生成。
关于如何使用ROM和*.mif文件在后续的文章中会继续介绍。