使用quartusⅡ调用ROM或RAM IP核
ROM IP核的使用
常常用来实现从快速时钟域到慢速时钟域的处理或慢速时钟域到快速时钟域的处理。对于一些数据可以先不发出,先把它存储起来,等到了一定的数目再发出。ROM只能读出数据,不能写入数据。在进行ip核名命的时候一定要注意规范 比如我们数据的存储宽度为8位,存储深度为256 则命名的名字为rom_8_256,rom是要进行初始化的,常常使用hex文件或mif文件对ROM进行初始化
IP核的调用过程
调用IP核
step1
单时钟和双时钟的意思分别为输入和输出是否使用同一个时钟
step2
一般都在输出端增加一个寄存器这样可以让驱动ROMIP核的时钟频率更高一些,也让时钟频率更稳定
ROM初始化
先在文件窗口下新建一个hex文件(new 下面的Memory文件第一个),然后对其赋值,然后保存,保存核ROM IP核同一个目录下,取得名字也要和ROM IP核的名字一样,保存完之后,然后将这个文件加载进来,如果文件名是黑色说明加载成功了,否则就说明加载出了问题,然后next。除了这种方法还可以建一个mif文件,用来初始化,采用mif文件的好处就是可以利用matlabd对mif文件初始化
这个altera_mf就是我们仿真的时候要调用的库(这个库文件就需要从安装目录下的ip核目录下拷贝出来),如果直接使用do文件或modelsim进行仿真的时候,就需要把这个库文件放在仿真目录下,进行编译
点击产生例化的文件
仿真
在仿真的时候要注意把hex文件放在sim的文件夹下,这是因为在ip核的rom_8_256.v文件中读取hex文件的地址默认的是tb文件的那个根目录,或者我们可以打开rom_8_256.v文件,将读取hex的地址变为我们存放hex文件的地址,这样就不会出现无法读取hex文件的警告了。
仿真结果如下:
可以看到,对于要输出的数据具有两个节拍的时延,这就是因为输出端添加了寄存器的结果。
这时未加寄存器的结果,可以看到未加寄存器的话输出只有1个延时
module ex_ipcore(
input wire sclk,
output wire oclk1,
output wire oclk2,
output reg [1:0] cnt,
output wire [7:0] odata,
output wire locked
);
reg [7:0] raddr=0;
reg [1:0] cnt1=0;
always @(posedge oclk1)
begin
cnt1 <= cnt1 + 1'b1;
cnt <= cnt1;
end
always @(posedge oclk1)
raddr <= raddr + 1'b1;
pll1 pll1_inst (
.inclk0 ( sclk ),
.c0 ( oclk1 ),
.c1 ( oclk2 ),
.locked ( locked )
);
rom_8_256 rom_8_256_inst (
.address ( raddr ),
.clock ( oclk1 ),
.q ( odata )
);
endmodule
测试文件
`timescale 1ns/1ns
module tb_ex_ipcore;
reg sclk;
wire oclk1,oclk2,locked,cnt;
initial
begin
sclk = 0;
//cnt = 0;
end
always #10 sclk = ~sclk;
ex_ipcore ex_ipcore_inst(
.sclk(sclk),
.oclk1(oclk1),
.oclk2(oclk2),
.locked(locked),
.cnt(cnt)
);
endmodule
do文件
quit -sim
.main clear
vlib ./work
vmap work ./work
vlog -work work ./tb_ex_ipcore.v
vlog -work work ./altera_lib/*.v
vlog -work work ./../design/*.v
vlog -work work ./../quartus_prj/ipcore_dir/pll1.v
vlog -work work ./../quartus_prj/ipcore_dir/rom_8_256.v
vsim -voptargs=+acc work.tb_ex_ipcore
add wave tb_ex_ipcore/ex_ipcore_inst/*
run 1000ns