[Verilog] カウンタ作成とありがちなバグ

Verilog HDL ネタは、講義とかで使われるようなのを書くとアクセスアップしたりするんだろうか。どんなのがいいかわからないけど。

今回は、カウンタ回路でありがちかもしれないバグの話。

カウント範囲の変更

0~max_count のカウンタ生成で次のような場合、致命的なバグがあります。

reg [15:0] count;
// max_count は 入力値など
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
count <= 0; // リセット
end
else if (count == max_count) begin
count <= 0; // カウンタ最大値の場合、0 にリセット
end
else begin
count <= count + 1;
end
end
view raw

gistfile1.v

hosted with ❤ by GitHub

max_count でカウンタの範囲を変更できるようにしていますが、count == max_count 時にカウンタ値リセットをしているので、max_count を大きい値から小さい値に変更したとき、例えば count = 100 のとき max_count = 50 に変えると count の値が bit 幅 MAX まで振り切ってしまいます。

count >= max_count のような条件にするか、ダウンカウンタを使えば上記のようなバグは通常発生しません。

always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
count <= max_count; // 初期値をカウンタ最大値にする
end
else if (count == 0) begin
count <= max_count; // count = 0 でリセット
end
else begin
count <= count 1;
end
end
view raw

gistfile1.v

hosted with ❤ by GitHub

また、ダウンカウンタを使うと「100~0、50~0 の組み合わせで、リセット時以外1ずつしか変化しない」ということも簡単です(アップカウンタは max_count の値を変えた時に、max_count 以外のカウンタ値から 0 にリセットされる場合がある)。

ダウンカウンタの方が、回路規模が小さくなるという話も。

カウンタの有効・無効

普通は、ずっと動いているカウンタを作ることは少なく(意味もなく動いていると電力も喰うし)、動作が有効の条件を付けます。

reg enable;
always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
count <= max_count;
end
else if (enable) begin // enable = 1'b1 の時のみカウント動作
else if (count == 0) begin
count <= max_count;
end
else begin
count <= count 1;
end
end
end
view raw

gistfile1.v

hosted with ❤ by GitHub

この enable の条件もよく考えていないとバグることがよく(?)あります。例えば次のように start と finish 信号によってカウント開始・終了を制御している場合、どうでしょう。

always @(posedge clk or negedge rst_n) begin
if (~rst_n) begin
enable <= 1'b0;
end
else if (start) begin
enable <= 1'b1;
end
else if (finish) begin
enable <= 1'b0;
end
end
view raw

gistfile1.v

hosted with ❤ by GitHub

この場合、start と finish が同時に 1 のとき問題ない動作なのか確認が必要です。普通に使っていると start → finish の順で 1 になるけど、start・finish が同時に 1 になる場合もあり考慮されていないと、カウンタが止まっていてほしいときに動き続けることになりかねません。

スポンサーリンク

シェアする

  • このエントリーをはてなブックマークに追加

フォローする

スポンサーリンク