二進制碼與格雷碼互轉換 verilog


 

格雷碼原理    

    格雷碼是一個叫弗蘭克*格雷的人在1953年發明的,最初用於通信。格雷碼是一種循環二進制碼或者叫作反射二進制碼。格雷碼的特點是從一個數變為相鄰的一個數時,只有一個數據位發生跳變,由於這種特點,就可以避免二進制編碼計數組合電路中出現的亞穩態。格雷碼常用於通信,FIFO或者RAM地址尋址計數器中。

    如二進制計數編碼從0到F的計數過程如下:

    

十進制

二進制

格雷碼

十進制

二進制

格雷碼

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

    當從7變為8時,4位二進制數都發生跳變,這就很可能會發生亞穩態。而采用格雷碼,就可以編碼4位二進制數都同時發生跳變,導致出現的亞穩態,就算出現亞穩態,最多也就一位出現錯誤。

格雷碼轉二進制

格雷碼轉二進制碼的公式,如下所示:

    b[n-1]=g[n-1], b[i]=gray[i]^b[i+1], i=[0,1,...,n-2]

        其運算過程的示意圖如圖2所示(這里以8位的數據位寬為例):

格雷碼轉二進制碼.jpg

           格雷碼轉二進制碼示意圖

        從圖可以看出,除格雷碼的最高位直接賦給二進制碼的最高位外,其他二進制碼位等對應格雷碼位與其高位格雷碼位異或的結果,因此可歸納出一表達式,如下所示(其中“^”表示變量各位異或):

    for(i = 0; i < n-1; i++)
        b[i] = ^(gray >> i);

    觀察上表可知,格雷碼轉二進制是從左邊第二位起,將每位與左邊一位二進制碼的值異或,作為該位二進制碼后的值(最左邊一位依然不變)。

 

module gray_to_bin(

gray_in,

bin_out

);

parameter data_width = 4;

 

input [data_width-1:0] gray_in;

output [data_width-1:0] bin_out;

reg [data_width-1:0] bin_out;

always @(gray_in)

begin

bin_out[3] = gray_in[3];

bin_out[2] = gray_in[2]^bin_out[3];

bin_out[1] = gray_in[1]^bin_out[2];

bin_out[0] = gray_in[0]^bin_out[1];

end

endmodule

 

二進制轉格雷碼

首先給出二進制碼轉格雷碼的公式,如下所示(以下公式中二進制碼和格雷碼都是n位的):

    g[n-1]=b[n-1], g[i]=b[i]^b[i+1], i=[0,1,...,n-2]

        其運算過程的示意圖如圖1所示(這里以8位的數據位寬為例):

二進制碼轉格雷碼.jpg

         二進制碼轉格雷碼示意圖

        從圖可以很輕易的看出,二進制碼右移1位后與本身異或,其結果就是格雷碼。

    從最右邊一位起,依次將每一位與左邊一位異或(XOR),作為對應格雷碼該位的值,最左邊一位不變。

 

 

module bin_to_gray(

bin_in,

gray_out

);

parameter data_width = 4;

 

input [data_width-1:0] bin_in;

output [data_width-1:0] gray_out;

 

assign gray_out = (bin_in >> 1) ^ bin_in;

 

endmodule

 

格雷碼計數器原理

    格雷碼計數器,采用三個模塊進行設計,格雷碼轉二進制、加法器、二進制轉格雷碼。

格雷碼轉二進制將格雷碼轉換為二進制,並將值輸出用於加法器進行加法運算,然后將加法運算結果通過二進制轉格雷碼轉換為格雷碼,最后將格雷碼進行輸出,同時將結果輸出到格雷碼轉二進制作為輸入,形成一個計數功能。

 

頂層設計

module gray_counter(

clk,

reset_n,

// gray_in,

gray_out

);

parameter data_width = 4;

 

input clk;

input reset_n;

// input [data_width-1:0] gray_in;

output [data_width-1:0] gray_out;

 

//格雷碼轉二進制

wire [data_width-1:0] bin_out;

gray_to_bin gray_to_bin_1(

.gray_in (gray_wire),

.bin_out (bin_out)

);

//二進制加一

wire [data_width-1:0] bin_add_wire;

assign bin_add_wire = bin_out + 1'b1;

//二進制轉格雷碼

wire [data_width-1:0] gray_wire;

reg [data_width-1:0] gray_out;

bin_to_gray bin_to_gray_1(

.bin_in (bin_add_wire),

.gray_out (gray_wire)

);

 

always @(posedge clk or negedge reset_n)

begin

if(reset_n == 1'b0)

begin

gray_out <= {data_width{1'b0}};

end

else

begin

gray_out <= gray_wire;

end

end

endmodule


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM