Verilog HDL ネタは、講義とかで使われるようなのを書くとアクセスアップしたりするんだろうか。どんなのがいいかわからないけど。
今回は、カウンタ回路でありがちかもしれないバグの話。
カウント範囲の変更
0~max_count のカウンタ生成で次のような場合、致命的なバグがあります。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
max_count でカウンタの範囲を変更できるようにしていますが、count == max_count 時にカウンタ値リセットをしているので、max_count を大きい値から小さい値に変更したとき、例えば count = 100 のとき max_count = 50 に変えると count の値が bit 幅 MAX まで振り切ってしまいます。
count >= max_count のような条件にするか、ダウンカウンタを使えば上記のようなバグは通常発生しません。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
また、ダウンカウンタを使うと「100~0、50~0 の組み合わせで、リセット時以外1ずつしか変化しない」ということも簡単です(アップカウンタは max_count の値を変えた時に、max_count 以外のカウンタ値から 0 にリセットされる場合がある)。
ダウンカウンタの方が、回路規模が小さくなるという話も。
カウンタの有効・無効
普通は、ずっと動いているカウンタを作ることは少なく(意味もなく動いていると電力も喰うし)、動作が有効の条件を付けます。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
この enable の条件もよく考えていないとバグることがよく(?)あります。例えば次のように start と finish 信号によってカウント開始・終了を制御している場合、どうでしょう。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
この場合、start と finish が同時に 1 のとき問題ない動作なのか確認が必要です。普通に使っていると start → finish の順で 1 になるけど、start・finish が同時に 1 になる場合もあり考慮されていないと、カウンタが止まっていてほしいときに動き続けることになりかねません。