在此感谢 特权同学,接下来写到的FPGA杂记基本上源于他的B站讲解视频,同时这是他的淘宝商铺链接,感兴趣的同学也可以在B站中看到他更多的一些视频学习资料,一起学习一起成长

1. 显示和监视任务

1.1 显示任务 $display 以及 $write

两者的语法结构大概都是:任务名(“可选字符串+格式”,信号列表)

  • 任务名包括$displayb(二进制)、 $displayh(十六进制)、 $displayo(八进制)以及 $write的其他任务名
  • 可选字符串+格式包括%h(16进制输出)、%c(ASCII输出)、%b(二进制输出)、%s(字符串输出)、%t(以当前时间格式输出显示)等等
  • display和write的区别在于display输出后会自动换行

%0d,加个0会使得输出的数据前面的零或者空格删掉(一般发生在输出要求位数大于实际输出位数的情况下)例如,32位的数据以十进制显示为65,用显示任务不加0的结果是:____(空格)65,但若是要求为%0d,那么输出结果就是65

1.2 监视任务$monitor

$monitor任务在声明后默认开启,只有在其运行期间调用系统任务 $monitoroff 则会关闭监视任务知道系统再次调用系统任务 $monitoron后将重新开启监视

以上两种主要在testbench中调用任务,方便在测试中验证自己的设计、逻辑功能的实现

2. 4位格雷码计数器设计

2.1 设计实现

设计目标:以1S为一个计数周期(注意不是系统时钟),计数值从0一直往上叠加,并将计数值不断转换成格雷码输出

`timescale 1ns/1ps
module vlg_design(input i_clk,  //时钟为50MHz,20nsinput i_rst_n,output[3:0] o_gray);
/
//1s定时计数
localparam  TIMER_1S_MAX_CNT = 32'd1_000_000_000/20;  //50MHZ的时钟在1s内的最大周期数,1S标志位reg[31:0] r_cnt;always @(posedge i_clk)if(!i_rst_n) r_cnt <= 'b0;else if(r_cnt < (TIMER_1S_MAX_CNT - 1))  r_cnt <= r_cnt + 'b1;else r_cnt <= 'b0;//
//1s计数器
reg[3:0] r_second;always @(posedge i_clk)if(!i_rst_n) r_second <= 'b0;else if(r_cnt == (TIMER_1S_MAX_CNT-1)) r_second <= r_second + 'b1;else ;/
//r_second译码为格雷码输出
reg[3:0] r_gray;always @(posedge i_clk)    if(!i_rst_n) r_gray <= 'b0;else begincase(r_second)4'b0000: r_gray <= 4'b0000;4'b0001: r_gray <= 4'b0001;4'b0010: r_gray <= 4'b0011;4'b0011: r_gray <= 4'b0010;4'b0100: r_gray <= 4'b0110;4'b0101: r_gray <= 4'b0111;4'b0110: r_gray <= 4'b0101;4'b0111: r_gray <= 4'b0100;4'b1000: r_gray <= 4'b1100;4'b1001: r_gray <= 4'b1101;4'b1010: r_gray <= 4'b1111;4'b1011: r_gray <= 4'b1110;4'b1100: r_gray <= 4'b1010;4'b1101: r_gray <= 4'b1011;4'b1110: r_gray <= 4'b1001;4'b1111: r_gray <= 4'b1000;default: ;endcase
endassign o_gray = r_gray; endmodule

看整个运行过程,各部分都会定义一个寄存器暂时储存输出结果,最后再进行赋值操作

2.2 测试脚本testbench

`timescale 1ns/1ps
module testbench_top();

//参数定义
`define CLK_PERIORD        20      //时钟周期设置为20ns(50MHz)
//接口申明
reg clk;
reg rst_n;
wire[3:0] o_gray;
//对被测试的设计进行例化
vlg_design      uut_vlg_design(.i_clk(clk),.i_rst_n(rst_n),.o_gray(o_gray));
//复位和时钟产生
//时钟和复位初始化、复位产生
initial beginclk <= 0;rst_n <= 0;#1000;rst_n <= 1;
end//时钟产生
always #(`CLK_PERIORD/2) clk = ~clk;
//测试激励产生
integer i;
initial begin@(posedge rst_n); //等待复位完成$monitor("o_gray is %b at %0dns",o_gray,$time);$stop;
endendmodule

2.3 测试结果

3. 基于查找表的8位格雷码转换

3.1 查找表LUT

查找表是相当于预先存储好结果的数据表,免去了运算过程,从另外一种角度来说相当于ROM。我们接下来利用IP的ROM加入查找表,通过VIVADO创建出ROM的初始化COE文件用于存放LUT的数据

3.2 ROM初始化COE文件

COE文件用于对ROM作初始化赋值,具体格式如下

 memory_initialization_radix = 位数(数据格式);memory_initialization_vector = 初始化数据;    //查找表数据

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中也可查看

3.3 设计代码.v

`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

3.4 测试脚本

`timescale 1ns/1ps
module testbench_top();

//参数定义
`define CLK_PERIORD        20      //时钟周期设置为20ns(50MHz)
//接口申明
reg clk;
reg rst_n;
reg i_en;
reg[7:0] i_data;
wire o_vld;
wire[7:0] o_gray;
//对被测试的设计进行例化
vlg_design      uut_vlg_design(.i_clk(clk),.i_rst_n(rst_n),.i_en(i_en),.i_data(i_data),.o_vld(o_vld),.o_gray(o_gray));
//复位和时钟产生
//时钟和复位初始化、复位产生
initial beginclk <= 0;rst_n <= 0;#1000;rst_n <= 1;
end
//时钟产生
always #(`CLK_PERIORD/2) clk = ~clk;
//测试激励产生
initial begini_en <= 'b0;i_data <= 'b0;@(posedge rst_n); //等待复位完成@(posedge clk);i_en <= 'b1;i_data <= 'b0;@(posedge clk);repeat(255) begin   //循环叠加256次i_data <= i_data + 1;@(posedge clk);endi_en <= 'b0;i_data <= 'b0;#1000;$stop;
end//
//实时显示
always@(posedge clk) beginif(o_vld) $display("%b",o_gray);else ;
endendmodule

4. 格雷码转换的快速算法

4.1 算法介绍

  • 二进制码(自然数)的最高位是MSB,最低位是0
  • 二进制码的MSB位直接赋值给格雷码的MSB位
  • 对于次高位(MSB-1)位到最低位0,使用二进制码相邻位异或的方式获取格雷码
    • 若二进制码字的第i位与第i+1位相同,则第 i 位的格雷码为0
    • 若二进制码字的第i位与第i+1位不同,则第 i 位的格雷码为1

举个例子:4位的二进制码1010转换格雷码(不通过LUT,直接通过RTL实现)

位数 操作 按位输出格雷码
Bit3 取MSB位 1
Bit2 1 xor 0 1
Bit1 0 xor 1 1
Bit0 1 xor 0 1

最终输出结果:1111

4.2 模块设计

`timescale 1ns/1ps
module vlg_design #(parameter MSB = 7)     //参数定义(input i_clk,input i_rst_n,input i_en,input[MSB:0] i_data,output reg o_vld,output reg[MSB:0] o_gray);always @(posedge i_clk) if(!i_rst_n) o_vld <= 'b0;else o_vld <= i_en;
//快速转换设计
always @(posedge i_clk)o_gray[MSB] <= i_data[MSB];genvar i;
generatefor(i=MSB-1;i>=0;i=i-1) beginalways @(posedge i_clk) begino_gray[i] <= i_data[i] ^ i_data[i+1];endend
endgenerateendmodule

4.3 测试脚本

`timescale 1ns/1ps
module testbench_top();

//参数定义
`define CLK_PERIORD        10      //时钟周期设置为10ns(100MHz)
parameter GRAY_MSB = 7;            //定义参数
//接口申明
reg clk;
reg rst_n;
reg i_en;
reg[GRAY_MSB:0] i_data;
wire o_vld;
wire[GRAY_MSB:0] o_gray;
//对被测试的设计进行例化
vlg_design #(.MSB(GRAY_MSB))uut_vlg_design(.i_clk(clk),.i_rst_n(rst_n),.i_en(i_en),.i_data(i_data),.o_vld(o_vld),.o_gray(o_gray));
//复位和时钟产生
//时钟和复位初始化、复位产生
initial beginclk <= 0;rst_n <= 0;#1000;rst_n <= 1;
end
//时钟产生
always #(`CLK_PERIORD/2) clk = ~clk;
//测试激励产生
initial begini_en <= 'b0;i_data <= 'b0;$display("The value of GRAY_MSB is %0d",GRAY_MSB);       @(posedge rst_n);      //等待复位完成@(posedge clk);i_en <= 'b1;i_data <= 'b0;repeat(2**(GRAY_MSB+1)-1) begin            //一共有(MSB+1)位,相当于计数值最大为2^(MSB+1)-1@(posedge clk);i_en <= 'b1;i_data <= i_data + 1;end@(posedge clk);i_en <='b0;$stop;
endalways @(posedge clk)if(o_vld) $display("%b",o_gray);else ;endmodule

4.4 测试结果

脚本显示(modelsim):
测试波形:

FPGA杂记5——格雷码转换设计相关推荐

  1. (45)FPGA面试题格雷码特点及其应用

    1.1 FPGA面试题格雷码特点及其应用 1.1.1 本节目录 1)本节目录: 2)本节引言: 3)FPGA简介: 4)FPGA面试题格雷码特点及其应用: 5)结束语. 1.1.2 本节引言 &quo ...

  2. 格雷码转换成二进制c语言程序,格雷码与二进制的转换程序

    /* 格雷码与二进制的转换程序 * 本程序采用递推的方法进行推导,可以转换0~2147483647之间的数(1~31位) * 推导方式如下(以三位格雷码为例): * 序号 格雷码 格雷码实值 二进制码 ...

  3. FPGA异步时钟域处理之格雷码转换

    0 本章目录 1)时钟域定义 2)为什么要做跨时钟域的处理? 3)FPGA简介 4)结束语 1 时钟域定义 所谓时钟域,就是同一个时钟驱动的区域.单一时钟域是FPGA的基本组成部分,但是随着设计规模扩 ...

  4. 【verilog】 异步FIFO设计(格雷码转换,跨时钟域)

    功能图 空满判别 顶层 子模块 测试 功能图 空满判别 对FIFO的空满判断采用地址位扩展的方法 waddr=raddr,fifo为空 waddr[最高bit]≠raddr[最高bit],waddr[ ...

  5. 【菜鸟C++学习杂记】ASCII码转换和显示

    笔者今年刚考上华东某高校的计算机研究生,本科虽是计算机学院,但期间主攻C#和Unity游戏开发,研究生属于小跨到计算机科学与技术,目前在进行硕导给的假期期间学习C++的任务,此类杂记主要记录下编码过程 ...

  6. 数字电路基础知识——格雷码和二进制码的转换的算法和Verilog实现

    数字电路基础知识--格雷码和二进制码的转换的算法和Verilog实现 关于数字电路中的码制问题在这篇博客中已经做了详细分析, 数字电路基础知识--数字IC中的进制问题(原码,反码,补码以及各进制的转换 ...

  7. 异步FIFO的设计详解(格雷码计数+两级DFF同步)

    文章目录 一.异步FIFO介绍 1.1.空满判断 1.2.跨时钟域问题 1.3.格雷码转换 1.4.格雷码计数器 二.代码code 一.异步FIFO介绍   FIFO有同步和异步两种,同步即读写时钟相 ...

  8. 【基础知识】~ 进制转换、补码、格雷码、BCD码、独热码

    1. 进制转换 1.1 十进制 to 二进制 正整数转二进制:除二取余,然后倒序排列,高位补零. 负整数转二进制:先是将对应的正整数转换成二进制后,对二进制取反,然后对结果再加一. 小数转二进制:对小 ...

  9. 关于格雷码的规律、转换

    发现数电书中对于格雷码并没有很好地解释,这里保留下来所理解的知识供自己日后查看.这里主要说明排列规律和转换. 格雷码特点: 任意两个相邻的代码只有一位二进制数不同.并且首尾相连,属于循环码(这里我发现 ...

  10. C语言学习:二进制码与格雷码的转换

    格雷码,又叫循环二进制码或反射二进制码,格雷码是我们在工程中常会遇到的一种编码方式,它的基本的特点就是任意两个相邻的代码只有一位二进制数不同. 格雷码的基本特点就是任意两个相邻的代码只有一位二进制数不 ...

最新文章

  1. 老男孩Python全栈开发(92天全)视频教程 自学笔记20
  2. Spring 注解配置
  3. 硬核!手写一个优先队列
  4. shell批量监控网站状态码
  5. Windows下python虚拟环境pip依旧使用全局pip的解决办法
  6. Model compatibility cannot be checked because the database does not contain model metadata
  7. 学python对数学要求高吗_人工智能的小男孩 大专学历的人没有数学基础想学习python技术未来能往大数据或人工智能方向进行职业发展吗?...
  8. kafka简介(大数据技术)
  9. 剑指offer之链表中环的入口结点
  10. Adobe Edge Animate 1.0 概述
  11. MFC 消息映射表和虚函数实现消息映射到底谁的效率高
  12. xpath提取目录下所有标签内的内容,递归 //text()
  13. Web渗透测试实战——(2.1)Metasploit 6.0初步
  14. mpp格式文用什么软件打开
  15. 蔬菜出口流程 |外贸流程
  16. 题解 洛谷P2142 高精度减法
  17. MatlabR2018aWin 安装教程 (附文件)
  18. 计算机英语邓广慧,地方高校理工类大学生专业英语教学改革探讨
  19. 冰盾ARP防火墙V1.0 Build 80122
  20. DDR从channel/rank/chip/bank/row/col/cell,DDR/GDDR/HBM

热门文章

  1. oracle查询创建视图语句
  2. 数据来看吃热狗王校长的微博究竟有多火!
  3. 外贸业务员常用询盘报价邮件模板
  4. PTA 7-6 2048游戏模拟(1)--单行向左移动叠加
  5. 计算机基础是五笔吗,计算机基础 五笔一.ppt
  6. webstorm设置中文界面
  7. hive窗口函数总结
  8. 西北农林科技大学研究生学位论文“参考文献”著录规则
  9. 学籍管理系统mysql实训报告_学生学籍管理系统数据库设计
  10. 富文本编辑器内容存储至Mysql