数字IC前端学习笔记:格雷码(含Verilog实现的二进制格雷码转换器)

 相关文章

数字IC前端学习笔记:LSFR(线性反馈移位寄存器)

数字IC前端学习笔记:跨时钟域信号同步

数字IC前端学习笔记:信号同步和边沿检测

数字IC前端学习笔记:锁存器Latch的综合

数字IC前端学习笔记:FIFO的Verilog实现(一)

数字IC前端学习笔记:FIFO的Verilog实现(二)

数字IC前端学习笔记:仲裁轮询(一)

数字IC前端学习笔记:仲裁轮询(二)

数字IC前端学习笔记:仲裁轮询(三)


目录

1.格雷码编码/解码

2.二进制码转格雷码Verilog实现

3.格雷码转二进制码Verilog实现


1.格雷码编码/解码

        格雷编码在弗兰克·格雷在1953年公布的专利中出现,主要特点是相邻编码值只有一位比特发生改变,下表中给出了三比特和四比特二进制码和对应的格雷码,从图中可以清晰地看到这一特点,而这一特点也使格雷码有十分广泛的应用。

三比特格雷码

十进制编码 二进制编码 格雷编码
0 000 000
1 001 001
2 010 011
3 011 010
4 100 110
5 101 111
6 110 101
7 111 100

四比特格雷码

十进制编码 二进制编码 格雷编码 十进制编码 二进制编码 格雷编码
0 0000 0000 8 1000 1100
1 0001 0001 9 1001 1101
2 0010 0011 10 1010 1111
3 0011 0010 11 1011 1110
4 0100 0110 12 1100 1010
5 0101 0111 13 1101 1011
6 0110 0101 14 1110 1001
7 0111 0100 15 1111 1000

        格雷编码被广泛应用于使用两个不同时钟的异步FIFO(First In First Out,先入先出存储器)中。一般来说,当多位数据穿越时钟域边界时,不能直接使用传统的同步器分别同步各位数据,因为无法保证这些数据会被同时同步,可能会出现较高的错误率。但如果多位数据是使用格雷编码,每次只可能有一比特数据改变,则可以直接同步。

        在异步FIFO中,写地址和读地址指针分别保存在不同的时钟域中,而为了表示FIFO状态,我们需要分别在写时钟域中产生FIFO_full信号,在读时钟域中产生FIFO_rmpty信号,而判断FIFO状态时,需要对比读写指针的值,两个不同时钟域中的值不能直接比较。所以,我们需要先把二进制编码的指针先转换成格雷码,并使格雷编码从一个时钟域穿越到另一个时钟域,然后使用转换公式再把格雷编码转换回二进制码,并与目标时钟域的指针比较。整个同步的过程如下图所示。

       数字IC前端学习笔记:格雷码(含Verilog实现的二进制格雷码转换器)_第1张图片

         我们通过一些真实的案例来深入分析这一过程,然后再看不使用这一转换方法时存在的问题。下面的例子中CLKA时钟域内,一个值从十进制值5变为6,我们来分析一下多位数据的传递过程。 

十进制数值 二进制数值 格雷码值 同步后的二进制值 同步后的十进制值
5 101 111 111 5
6 110 101 111或101 5或6

         在CLKA中,当十进制数从5变成6时,经过同步器后,在目标时钟域变为101或暂时为原来的111(一至两个时钟周期后,依旧会变为101)。可以看出,无论是101还是111,最终的结果都是按先后顺序出现的合法值。

        如果不使用上面的二进制-格雷码相互转换的电路,直接在CLKB时钟域使用同步器,会发生什么呢?下表给出了可能的结果。

十进制数值 二进制数值 同步后的二进制值 同步后的十进制值
5 101 101 5
6 110 101或110或100或111 5或6或4或7

        可以看出,同步后的值可能是旧值101、新值,但也可能变为100或111。因为多位数据是分别进行同步的,无法保证多位信号在同一个时钟沿被采样到,这些独立同步的信号有效值可能出现在不同的时钟沿。

        虽然最终能得到正确值,即最终输出变为。但是在此期间可能会出现违反规则的值。在该例中,出现了两种非法值,如果同时有更多位数据跳变,则可能会产生大量不合法的值,输出端会保留这些值一至两个周期。

        对于FIFO来说,空\满信号是根据指针对比得到的,当出现这些非法值时,FIFO可能会出现错误的空\满信号,导致系统工作错误甚至崩溃。

2.二进制码转格雷码Verilog实现

module binary_to_gray #(parameter PTR = 8)
                       (input [PTR:0]binary_value,
                        output [PTR:0]gray_value);
genvar i;
generate
    for(i = 0;i < PTR;i = i+1) begin
        assign gray_value[i] = binary_value[i] ^ binary_value[i+1];
    end
endgenerate

assign gray_value[PTR] = binary_value[PTR];

endmodule

3.格雷码转二进制码Verilog实现

module gray_to_binary #(parameter PTR = 8)
                       (output [PTR:0]binary_value,
                        input [PTR:0]gray_value);
genvar i;
generate
    for(i = 0;i < PTR;i = i+1) begin
        assign binary_value[i] = binary_value[i+1] ^ gray_value[i];
    end
endgenerate

assign binary_value[PTR] = gray_value[PTR];

endmodule

 以上内容来源于《Verilog高级数字系统设计技术和实例分析》

你可能感兴趣的:(数字IC,前端,学习,fpga开发,Verilog,HDL,数字IC)