FPGA学习笔记之格雷码、边沿检测、门控时钟
一、格雷码
格雷码的优点主要是进位时只有一位跳变,误码率低。
1、二进制转格雷码
我们观察下表:
二进制码 | 格雷码 |
00 | 00 |
01 | 01 |
10 | 11 |
11 | 10 |
二进制码表示为B[],格雷码表示为G[],则有
G(i) = B(i),i为最高位
G(i-1) = B(i) xor B(i-1),i非最高位
用verilog可以这样写
1 reg [WIDTH-1:0] bin; 2 reg [WIDTH-1:0] gray; 3 parameter WIDTH = 8; 4 always @(posedge clk or negedge rst_n) begin 5 if (!rst) 6 gray <= 8'b0; 7 else 8 gray <= bin^(bin>>1); //左移一位异或,从而最高位不变,次高与最高异或 9 end
2、格雷码转二进制
对照上表,一张图可以理解:
verilog代码可以这样写
reg [WIDTH-1:0] bin; reg [WIDTH-1:0] gray; parameter WIDTH = 8; always @(posedge clk or negedge rst_n) begin if(!rst) bin = 8'b0; else bin = bin^(gray>>1); end
二、边沿检测
输入一个跳变信号,如按键输入、时钟输入,输出指示高电平、低电平或者跳变(双边沿),综合出的电路如下:
基本思想是利用同步时钟控制两个级联的D触发器,待检测信号输入到第一个D触发器的输入端,因为D触发器之间有一个时钟的时间延迟,因此取两个D触发器之间的信号(命名为dly1)和后一个D触发器的输出(命名为dly2),如果时钟是上升的,那么第一个D触发器输出(即dly1)为高电平,第二个为低电平,则(dly1)&(~dly2)为高,指示了上升沿,下降沿类似,双沿我们自然可以想到,任一个边沿信号为高,则输出指示为高,用一个异或门即可解决。实践中,两个D触发器还可能存在误触发,可以增加D触发器的个数,来降低错误。
三、门控时钟
我们知道,时序电路里总会有一个sys_clk,这个clk一般是从外部晶体振荡器引进来的,但是我们也知道世界上没有觉得理想的器件和路径,引入的时钟可能因为晶体各种噪声干扰或者突然“抽风”了一下,导致时钟抖动,这对时序电路来说是致命的。那么,怎么解决这种情况呢???
一种想法是输入时钟sys_clk的同时,给一个时钟使能信号clk_en,两者经过一个&门,这样输出可能会好点
,but真的吗?看下图时序
该有的还是会有,我们可以看到时钟在clk高半周尾部使能的时候,可能产生极短的脉冲(毛刺),不言而喻,这个电路没有达到理想效果。我们改怎么做呢???如题,“门控时钟”就是解决这个的,电路如下
电路时序如下
即相当于clk_en等下一个时钟才作用,没有产生毛刺。