【FPGA/verilog -入门学习9】verilog基于查找表的8位格雷码转换

发布时间:2023年12月17日

本文参考: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文件 ,原语例化时,数据生成之前,要足够厂的以上的延时,才能正常输出数据

异常数据:

文章来源:https://blog.csdn.net/cengqiu4314/article/details/134931650
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。