グレイコードカウンタ
多ビット信号をCDC転送するとき、変化がランダムではなく順番が決まっているカウンタ値であれば、MUXシンクロナイザより、もっと簡単な方法がある。
通常のバイナリカウンタはカウントアップするとき複数のビットが変化するので、そのまま2FFシンクロナイザでサンプリングすると過渡値を取る可能性があるが、1ビットずつしか変化しないように順番を並び変えたグレイコードカウンタを使えば、そのまま2FFシンクロナイザでサンプリングできる。
n |
バイナリ |
グレイ |
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までしかカウントできないので、大きいカウント数が必要な場合は不利である。
n |
ジョンソン |
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 |