本文参考:FPGA杂记5——格雷码转换设计-CSDN博客
1,什么是查表法,做什么用,有什么好处
查找表(Look-Up-Table)
查找表,简单说,就是一个预先存储好结果的数据表
通过访问这张预先存储好结果的数据表,可以快速的获取不同输入的输出结果
查找表可以免去运算的过程,尤其对于复杂的运算更是可以大大减少运算开销和运行时间
2,怎么使用
1,Xilinx的COE文件用于对ROM做初始化赋值
2,memory_initialization_radix 后是数据格式,COE文件中的数据格式可以是2(Binary),10(Decimal)或者16(Hex)。
memory_initialization_vector 后是初始化数据。
memory_initialization_radix=16;
memory_initialization_vector=
0000,
……
ffff;
ROM初始化COE文件
COE文件制作以及使用ROM流程:
打开vivado工程文件点击IP Catalog选择生成ROM(以Block Memory Generator为例)
将打开的ROM的Memory Type改成Single Port ROM
在Port A Options里面将位宽与数据个数改成相应的数据,同时使能always
在Other Options中导入COE文件,这里由于没有COE文件可以在线创建一个即可
然后点击OK会弹出一个generate的窗口直接生成即可
回到vivado界面的Sources里面的IP Sources中查看你所配置IP的Instantiation Template中的原语 .veo 文件,并将原语用于你所设计的verilog代码中
这里要注意一下,只要在IP中勾选了Primitives Output Register,那么就意味着你会延时两个时钟周期输出数据,在Summary中也可查看
Primitives Output Register
原语输出寄存器
复制原语的例化代码
//----------- Begin Cut here for INSTANTIATION Template ---// INST_TAG
blk_mem_gen_0 your_instance_name (
.clka(clka), // input wire clka
.addra(addra), // input wire [7 : 0] addra
.douta(douta) // output wire [7 : 0] douta
);
添加编译路径
3,设计代码vlg_design
/
/*需求:使用查表法实现8位二进制格雷码输出@input:i_clk,i_rst_n,i_en,i_data,@output: o_vld,o_gray*/
/
`timescale 1ns/1ps
module vlg_design(input i_clk, input i_rst_n,input i_en,input[7:0] i_data,output o_vld, //有效信号output[7:0] o_gray);//
//o_vld是i_en两个时钟周期的延时
reg[1:0] r_vld;always@(posedge i_clk)if(!i_rst_n) r_vld <= 'b00;else r_vld <= {r_vld[0],i_en};assign o_vld = r_vld[1];//IP ROM_LUT
blk_mem_gen_0 uut_blk_mem_gen_0 (.clka(i_clk), // input wire clka.addra(i_data), // input wire [7 : 0] addra.douta(o_gray) // output wire [7 : 0] douta
);
endmodule
4,测试代码 testbench_top
`timescale 1ns/1ps
module testbench_top();//参数定义`define CLK_PERIORD 20 //接口申明
reg i_clk;
reg i_rst_n;
reg i_en;
reg[7:0] i_data;
wire o_vld; //有效信号
wire[7:0] o_gray;vlg_design vlg_design_inst (.i_clk(i_clk),.i_rst_n(i_rst_n),.i_en(i_en),.i_data(i_data),.o_vld(o_vld),.o_gray(o_gray) ); integer i;
//产生initial begin
i_en <= 0;
i_clk <= 0;
i_rst_n <= 0;
i_data <= 0;
#200; //这里时间太短,输出会有失败
i_rst_n <= 1;end
always #(`CLK_PERIORD/2) i_clk = ~i_clk;
//产生激励
initial begin@(posedge i_clk);@(posedge i_rst_n); i_en <= 1;@(posedge i_clk); for (i = 0;i <= 255;i = i+1) begini_data <= i_data + 1;@(posedge i_clk);end@(posedge i_clk);i_en <= 0;#2000;$stop;
end//实时显示
always@(posedge i_clk) beginif(o_vld) $display("%b",o_gray);else ;
endendmodule
5,仿真结果
问题发现:
使用ROM初始化COE文件 ,原语例化时,数据生成之前,要足够厂的以上的延时,才能正常输出数据
异常数据: