赞
踩
目录
xilinx提供了两个ip用于生成ROM存储空间。一个是 Distributed Memory Generator,另一个是Block Memory Generator,两者最主要的差别是生成的 Core所占用的 FPGA 资源不一样,从 Distributed Memory Generator 生成的 ROM/RAM Core 占用的资源是 LUT(查找表,查找表本质就是一个小的 RAM);从 Block Memory Generator 生成的 ROM/RAM Core 占用的资源是 Block Memory(嵌入式的硬件 RAM),因此在实际项目中的应用要看具体硬件的情况。通常ROM用于做初始化配置,或者接口验证。本文通过仿真介绍该IP的使用,并创建一个用于接口验证的实际案例,即将ROM中的数据显示到LVDS显示屏上。用以验证LVDS显示时序正常。上述两个IP使用的差别不大,也都不仅能生成ROM,还可以生成双口RAM等,本文只讨论ROM。本文内容参考xilinx官方手册PG058 Block Memory Generator v8.4 product guide。
第一套仿真代码和配置如下,只关注常规接口的时序。
②设置数据位宽是10,存储深度是32,端口使能信号类型设置,一个是一直使能,一个是通过一个ENA信号管脚控制,这里选择 Always Enable。勾选Primitives Output Register,其含义如下图所示,内部的一个寄存器将数据打一拍,性能会更好。关于REGCEA pin复位的是寄存器中的值,而不是ROM中的值,通常也不用。
③第三页 勾选初始化文件,选择Edit将可以手动创建COE文件或者导入准备好的文件,手动设置如下第二张图,16进制的形式初始化了11个数据。设置完成可以validation并且保存。勾选Fill选项指未初始化的数据将初始化成指定位宽。
④第四页,可以看到当前latency=2,指地址线与数据线之间有一个时钟周期的延时。
- `define CLK_PERIOD 20
- module Sim_romip();
- reg clk;
- reg [5:0]addr;
- reg rsta;
- reg ena;
- initial clk = 1;
- always #(`CLK_PERIOD/2) clk = ~clk;
- wire [9:0]sim_rom;
- //第一段仿真代码
- blk_mem_gen_0 rom (
- .clka(clk),
- .addra(addr), // output wire [4 : 0] spo
- .douta(sim_rom) // output wire [9 : 0] qspo
- );
- initial begin
- addr = 0;
- #21;
- #(`CLK_PERIOD*5);
- addr = addr + 1'b1;
- #(`CLK_PERIOD*2);
- addr = addr + 1'b1;
- #`CLK_PERIOD;
- addr = addr + 1'b1;
- #`CLK_PERIOD;
- addr = 10;
- #`CLK_PERIOD;
- addr = 11;
- #`CLK_PERIOD;
- addr = 31;
- #`CLK_PERIOD;
- addr = 32;
- #`CLK_PERIOD;
- addr = 33;
- #(`CLK_PERIOD * 30);
- $stop;
- end

以地址线addr=2举例,t0时刻,addr=2,而地址2对应的数据12在t1-t2时刻才更新,因此在当前配置下,地址线与数据之间有1个时钟周期的延迟,Latency=2,Latentcy 指的是相对于某个时钟起始位的1个或多个时钟后数据才有效。
地址与数据映射是从0开始,也就是地址0对应一个数据,即手动填写的10;由此32的深度中,最后一个数据的地址应该是31。在之前的IP配置中手动填写了11个数据,因此从地址11-31都是填充数据12。如果地址线addr位宽够大,例如此处为6位宽,实际ip接口只有5位宽,因此addr=32时,ip接收低5位为0又显示第一个地址。另外,当未点击填充数据时,未初始化的数据默认为0。
主要是看Core Output Register和Enable Port Type以及RSTA Pin。
其余配置一样,使能ENA管脚,勾选Core output Register,勾选RSTA Pin,并设置复位时端口值为16.
- `define CLK_PERIOD 20
- module Sim_romip();
- reg clk;
- reg [5:0]addr;
- reg rsta;
- reg ena;
- initial clk = 1;
- always #(`CLK_PERIOD/2) clk = ~clk;
- wire [9:0]sim_rom;
- blk_mem_gen_0 your_instance_name (
- .clka(clk), // input wire clka
- .rsta(rsta), // input wire rsta
- .ena(ena), // input wire ena
- .addra(addr), // input wire [4 : 0] addra
- .douta(sim_rom) // output wire [9 : 0] douta
- );
- initial begin
- addr = 0;
- rsta = 1;
- ena = 0;
- #(`CLK_PERIOD*5);
- rsta = 0;
- #21;
- #(`CLK_PERIOD*5);
- ena = 1;
- addr = addr + 1'b1;
- #(`CLK_PERIOD*2);
- addr = addr + 2;
- #`CLK_PERIOD;
- addr = addr + 5;
- #`CLK_PERIOD;
- addr = 10;
- #`CLK_PERIOD;
- addr = 11;
- #`CLK_PERIOD;
- addr = 31;
- #`CLK_PERIOD;
- addr = 32;
- ena = 0;
- #`CLK_PERIOD;
- ena = 1;
- addr = 33;
- #(`CLK_PERIOD * 30);
- $stop;
- end
- endmodule

复位信号是高电平有效,复位器件数据线上数据通过IP配置。注意,此处的值为16进制。
T0时刻,是第一个地址线上数据进入,在t2-t3时刻地址线addr=1的数据0x11才出来,此时的latency=3;此处要正确理解ena的含义,地址线addr=10是打出来的最后一个数据0x20,因为在0x20该出来的时刻(图中椭圆对应的上升沿时刻)ena是有效的。因此当前时刻数据是否有效有两个因素决定,一个是两个周期之前的地址是否正确写入,一个是当前时刻ena数据有效信号是否有效。当二者有一个不满足时,该数据被pass。该结论下图看的更清楚。
① 确认片上资源XC7A35T仅有1.8Mbit,一张图片的大小为1024*600*8=17.57Mbit。因此计划将一张图片的1/12写入到ROM,coe中,据此验证数据流与上位机。
②使用QT生成COE文件,可参考Qt生成ROM IP核使用的COE文件,需要注意的是这里处理的是RGB格式的图像,需要将bits获取的指针强制转换成QRGB类型才能正确获取RGB分量信息。注意这里只能写图片得十二分之一也就是600/12=50行。另外要按照coe文件格式输出。
③依据LVDS接口LCD显示彩图测试,在这个工程中实现了LVDS显示屏显示彩图,并预留了数据接口。修改数据来源即可将rom中的数据打到屏幕上,需要注意的是,由于rom ip地址与数据之间有一个时钟周期的延时,因此应该将数据同步。
④原图与屏幕显示的图对比效果如下,
我的主页https://blog.csdn.net/weixin_40615338?type=blog
END
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。