本文参考: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) begin
i_data <= i_data + 1;
@(posedge i_clk);
end
@(posedge i_clk);
i_en <= 0;
#2000;
$stop;
end
//实时显示
always@(posedge i_clk) begin
if(o_vld) $display("%b",o_gray);
else ;
end
endmodule
5,仿真结果
问题发现:
使用ROM初始化COE文件 ,原语例化时,数据生成之前,要足够厂的以上的延时,才能正常输出数据
异常数据: