注册 登录
电子工程世界-论坛 返回首页 EEWORLD首页 频道 EE大学堂 下载中心 Datasheet 专题
lhlhualin的个人空间 https://home.eeworld.com.cn/space-uid-342671.html [收藏] [复制] [分享] [RSS]
日志

gray 计数器

已有 1370 次阅读2012-2-26 14:26 |

格雷码(Gray code)是由贝尔实验室的Frank Gray在1940年提出,用于在PCM(Pusle Code Modulation)方法传送讯号时防止出错,并于1953年三月十七日取得美国专利。格雷码是一个数列集合,相邻两数间只有一个位元改变,为无权数码,且格雷码的顺序不是唯一的。

直接排列

以二进制为0值的格雷码为第零项,第一项改变最右边的位元,第二项改变右起第一个为1的位元的左边位元,第三、四项方法同第一、二项,如此反覆,即可排列出n个位元的格雷码。

 二进制码->格雷码(编码):从最右边一位起,依次将每一位与左边一位异或(XOR),作为对应格雷码该位的值,最左边一位不变(相当于左边是0);

格雷码-〉二进制码(解码):从左边第二位起,将每位与左边一位解码后的值异或,作为该位解码后的值(最左边一位依然不变).

  数学(计算机)描述:

  原码:p[n:0];格雷码:c[n:0](n∈N);编码:c=G(p);解码:p=F(c);

  书写时按从左向右标号依次减小,即MSB->LSB,编解码也按此顺序进行

  编码:

  ...................c[n]=p[n],

  ...................c[i]=p[i] XOR p[i+1] (iN,n-1i0)

  解码:

  ...................p[n]=c[n],

  ...................P[i]=c[i] XOR p[i+1] (iN, n-1i0)。   //注意

二进制数转格雷码

(假设以二进制为0的值做为格雷码的0)

格雷码第n位 = 二进制码第(n+1)位+二进制码第n位。不必理会进制。

Verilog 代码:gray=(binary>>1)^binary;

格雷码转二进制数

二进制码第n位 = 二进制码第(n+1)位+格雷码第n位。因为二进制码和格雷码皆有相同位数,所以二进制码可从最高位的左边位元取0,以进行计算。

verilog 代码://------假设 reg [n-1] gray,binary;

integer i;

for(i=0;i<=n-1;i=i+1)

binary[i]=

^(gray>>i)//gray移位后,自身按位异或

^(gray>>i)//第一次看到这样的用法,特意查了下verilog语法

 
 
方法一
代码:
module gray
#(parameter N=5)
(
input clk,
input rst_n,
output reg [N-1:0] gray_cnt_out
);
reg [N-1:0] cnt;
reg [N-1:0] temp;
integer i;
always @ (posedge clk ,negedge rst_n)
begin
if(!rst_n)
cnt <= 5'd0;
else
cnt <= cnt +1'b1;
end
always @(cnt)
begin
temp[N-1] = cnt[N-1];
for(i=1; i<=N-1;i=i+1)
temp[i-1] = cnt[i-1]^cnt[i];
end
//   此处for循环综合会展开  不推荐这种写法
 
always @ (posedge clk ,negedge rst_n)
begin
if(!rst_n)
gray_cnt_out<=1'b0;
else
gray_cnt_out<=temp;
end
endmodule
备注:在实际工程中,Gray码计数器广泛应用于跨时钟域设计,他用于将计数器的计数值从A时钟域传递给B时钟域。由于信号的传播延时,而且CLKA和CLKB没有固定的相位关系,CLKA_cnt的输出不能同时到达CLKB,如果用二进制计数器,则可能出现毛刺,从而导致设计错误;而如果采样Gray码计数器,根据Gray的特性,则可以有效地避免这个问题。
 
方法2:(只有一个寄存器的gray计数器)
代码:
module gray_counter
(
    input iclk,
    input irst_n,
    input ivalid,
    output reg [3:0] gray
);
  
wire [3:0] bin_counter;
wire [3:0] gray_counter;
   
reg  [3:0] G2B_counter;
  
// convert gray to  bin;
always@(*)
begin
    G2B_counter[3] = gray[3];
    G2B_counter[2] = gray[2] ^ G2B_counter[3];
    G2B_counter[1] = gray[1] ^ G2B_counter[2];
    G2B_counter[0] = gray[0] ^ G2B_counter[1];
end
  
//binary counter increased by one
assign bin_counter = bin_counter +ivalid;
  
//convert bin to gray 
assign gray_counter = (bin_counter >>1) ^ bin_counter;
//理解该处的电路结构
  
always@(posedge iclk or negedge irst_n)
begin
    if(!irst_n)
    begin
        gray <= 4'b0;
    end
    else
    begin
        gray <= gray_counter;
    end
end
  
endmodule
 
//  为码
always @(gray) begin
  for (i=0; i<`WIDTH; i=i+1)
   bin[i] = ^(gray>>i);   // Gray码到二进制码转换
  bnext = bin + 1;
  gnext = (bnext>>1) ^ bnext;   // 二进制码到Gray码转换
 end
 
方法3(提高频率,增加寄存器,减少组合逻辑)
module graycounter
(
    input iclk,
    input irst_n,
    input ivalid,
    output     [ADDSIZE-1 : 0]  bin,
    output reg [ADDSIZE : 0]  gray
);
  
parameter ADDSIZE = 4;
  
wire[ADDSIZE : 0] binnext;
wire[ADDSIZE : 0] graynext;
reg[ADDSIZE : 0] bin_o;
  
assign binnext = bin_o + ivalid;
  
assign graynext = (binnext >>1) ^ binnext;
  
assign bin = bin_o[ADDSIZE-1 : 0];
  
always@(posedge iclk or negedge irst_n )
if(!irst_n)
    {bin_o, gray} <= 0;
else
    {bin_o, gray} <= {binnext, graynext};
  
endmodule
评论 (0 个评论)

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 注册

热门文章