數字設計---格雷碼與二進位制碼
格雷碼與二進位制碼
格雷碼
格雷碼是一種迴圈二進位制碼或者叫作反射二進位制碼。
格雷碼的特點是從一個數變為相鄰的一個數時,只有一個數據位發生跳變(或者說相鄰的兩個格雷碼之間只有一位不同)。
從圖上可以看出,相鄰的二進位制數會出現多位的變化(比如從15變到0就會有4位的變化),但對於格雷碼來說,相鄰的格雷碼只有一位存在不同。
對於二進位制數計數器來說,如果在跨時鐘域的時候將計數器傳到不同的時鐘域,如果僅採用“打兩拍的方法”,因為有多位數的變化,就可能會導致電路出現亞穩態或者出現毛刺。
由於格雷碼的這種特點,採用格雷碼就可以避免二進位制編碼計數組合電路中出現的亞穩態。格雷碼常用於通訊,FIFO 或者 RAM 地址定址計數器中。
格雷碼與BCD碼的轉換
BCD碼轉格雷碼
對於\(n\)位的二進位制數,可以通過下面的式子轉換為格雷碼
\[gray_{n-1} = bin_{n-1} \] \[gray_i = bin_i \oplus bin_{i+1} \qquad i<n-1 \]即格雷碼的最高位與二進位制數的最高位相同,後面格雷碼的各位等於相應的二進位制碼的對應位與上一位的異或。
從上圖可以看出二進位制碼轉換為格雷碼的具體流程
拿5位二進位制數10110舉例
\(gray[4] = bin[4] = 1\)
\(gray[3] = bin[3] \oplus bin[4] = 1\)
\(gray[2] = bin[2] \oplus bin[3] = 1\)
\(gray[1] = bin[1] \oplus bin[2] =0\)
\(gray[0] = bin[0] \oplus bin[1] =1\)
對於verilog來說,我們可以將二進位制數與他右移一位的數按位相異或來求得gray碼。
module bin_to_gray #(parameter WIDTH = 4) ( input [WIDTH-1:0] bin_in, output [WIDTH-1:0] gray_out ); //================================================================ // ------------------------- MAIN CODE -------------------------- //================================================================ assign gray_out = (bin_in >> 1) ^ bin_in; //右移一位再按位相異或 // gray_out[0] = (bin_in[1]) ^ bin_in[0]; //當然可以分著來,就是沒上面那麼簡潔 // gray_out[1] = (bin_in[2]) ^ bin_in[1]; // gray_out[2] = (bin_in[3]) ^ bin_in[2]; // gray_out[3] = (bin_in[3]) ^ 0 ; endmodule
格雷碼轉BCD碼
對於\(n\)位的格雷碼,可以採用下面的式子轉換為二進位制碼
\(bin_{n-1} = gray_{n-1}\)
\(bin_{i}=gray_{i}\oplus bin_{i+1}\)
即二進位制碼的最高位與格雷碼的最高位相同,剩餘位可以通過將對應位的格雷碼與上一位的二進位制碼相異或求得
還是拿上圖的5位格雷碼10110舉例
\(bin[4] = gray[4]=1\)
\(bin[3]=gray[3] \oplus bin[4] = gray[3] \oplus gray[4] =1\)
\(bin[2] = gray[2] \oplus bin[3] = gray[2] \oplus gray[3] \oplus gray[4] = 0\)
\(bin[1] = gray[1] \oplus bin[2] = gray[1] \oplus gray[2] \oplus gray[3] \oplus gray[4] = 1\)
\(bin[0] = gray[0] \oplus bin[1] = gray[0] \oplus gray[1] \oplus gray[2] \oplus gray[3] \oplus gray[4] = 1\)
從上面的分析可以看出格雷碼轉換為二進位制,對應位的二進位制可以通過求對應位格雷碼及以上所有位的異或求得。
對於verilog實現來說,可以通過將格雷碼右移相應位數,再求所有位的異或來實現上面的效果(求對應位格雷碼及以上所有位的異或)。
module gray_to_bin
#(parameter WIDTH = 4)
(
input [WIDTH-1:0] gray_in,
output reg [WIDTH-1:0] bin_out
);
//===================================================
// ------------------- MAIN CODE -------------------
//===================================================
integer i;
always @(*) begin
for(i=0;i<WIDTH;i=i+1)
bin_out[i] = ^(gray_in >> i);
end
endmodule
參考
(9條訊息) 二進位制與格雷碼互相轉換_耐心的小黑的部落格-CSDN部落格_二進位制轉格雷碼
《硬體架構的藝術》