グレイコードカウンタ

[] [] []


多ビット信号をCDC転送するとき、変化がランダムではなく順番が決まっているカウンタ値であれば、MUXシンクロナイザより、もっと簡単な方法がある。

通常のバイナリカウンタはカウントアップするとき複数のビットが変化するので、そのまま2FFシンクロナイザでサンプリングすると過渡値を取る可能性があるが、1ビットずつしか変化しないように順番を並び変えたグレイコードカウンタを使えば、そのまま2FFシンクロナイザでサンプリングできる

バイナリ

グレイ

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

0000

0001

0010

0011

0100

0101

0110

0111

1000

1001

1010

1011

1100

1101

1110

1111

0000

0001

0011

0010

0110

0111

0101

0100

1100

1101

1111

1110

1010

1011

1001

1000

ただしグレイコードカウンタをカウントアップする単純なアルゴリズムはないので、バイナリコードでカウントアップしてからグレイコードに変換することになる。

バイナリコードからグレイコードへの変換回路の遅延時間はビット幅に依らない

/* binary to gray */

wire[N-1:0] bin,gray;

assign gray = bin ^ (bin >> 1);

一方、グレイコードからバイナリコードへの変換回路の遅延時間はビット幅に比例して大きくなるので、なるべく使わずに済ませた方がよい。

/* gray to binary */

wire[N-1:0] bin,gray;

genvar i;

generate for(i=0; i<N; i=i+1) begin: gray2bin

  assign bin[i] = ^gray[N-1:i];

end endgenerate

このグレイコードカウンタを使った例はあまり知らないのだが、非同期FIFOを作るときは有効である。(→非同期FIFOの作り方)

なお、1ビットずつしか変化しないカウンタとしては回路が単純なジョンソンカウンタもある。ただし、これはNビットで2Nまでしかカウントできないので、大きいカウント数が必要な場合は不利である。

ジョンソン

0

1

2

3

4

5

6

7

0000

0001

0011

0111

1111

1110

1100

1000

 

/* Johnson counter */

reg[N-1:0] count_reg;

always @(posedge clk or posedge rst) begin

  if(rst)

    count_reg <= {N{1'b0}};

  else if(en)

    count_reg <= {count_reg[N-2:0],~count_reg[N-1]};

end


[] [] []