クロックで数が増える回路
カウンターは、クロックが1回刻まれるたびに、数を1つ増やす回路です。時計も、信号機も、走行距離の表示も、クロックの刻みで状態が変わります。
クロックの立ち上がりの瞬間にだけ値が変わる、という決まりが、順序回路の核心です。
このレッスンのゴール
メモ
クロックの立ち上がりで数が変わるカウンターを記述できる。
重要な言葉
| ことば | いみ |
|---|---|
| クロック | 0と1を一定の間隔で繰り返す信号 |
| 立ち上がりエッジ | クロックが0から1に変わる瞬間 |
| フリップフロップ | 立ち上がりで1ビットを覚える部品 |
| 同期リセット | 次の立ち上がりで、値を0に戻す仕組み |
| 順序回路 | 過去の値を覚えて、出力を決める回路 |
学生が入力するセルは、このプレビューでは空白です。
順序回路は前の値を覚える
これまでの回路は、入力が変われば、すぐ出力が変わりました。カウンターは違います。前の数を覚えていて、それに1を足します。
覚える部品がフリップフロップです。クロックが0から1に変わる立ち上がりエッジの瞬間に、1ビットを取り込みます。次の立ち上がりまで、値は変わりません。
4ビットのカウンター
module counter(input clk, input rst, output reg [3:0] q);
always @(posedge clk)
if (rst) q <= 4'd0;
else q <= q + 4'd1;
endmodule
always の行を読む
always @(posedge clk) は、clk の立ち上がりのたびに、下の文を実行するという意味です。q <= ... は、立ち上がりのあとに q を更新します。
4'd0 は、4ビットの10進数の0です。rst が1なら q は0に、そうでなければ1増えます。
同期リセットは次の刻みで効く
rst を1にしたら、q はすぐ0になるでしょうか。このカウンターでは、ならないはずです。リセットも、立ち上がりのときに調べられます。
下の Run は、ラボの counter.v に、刻みを1回ずつ与えます。刻みの前後で q を表示して、確かめましょう。
ラボのフォルダに入る
cd ~/hdlここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
テストベンチを書く
printf 'module edge_tb;\n reg clk = 0, rst = 1;\n wire [3:0] q;\n counter dut(.clk(clk), .rst(rst), .q(q));\n initial begin\n #1 $display("start q=%%0d", q);\n #1 clk = 1;\n #1 $display("edge 1 q=%%0d (rst was 1)", q);\n rst = 0; #1 $display("rst=0 q=%%0d", q);\n #1 clk = 0; #1 clk = 1;\n #1 $display("edge 2 q=%%0d", q);\n #1 clk = 0; #1 clk = 1;\n #1 $display("edge 3 q=%%0d", q);\n rst = 1; #1 $display("rst=1 q=%%0d", q);\n #1 clk = 0; #1 clk = 1;\n #1 $display("edge 4 q=%%0d", q);\n end\nendmodule\n' > /tmp/edge_tb.vここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
回路とテストベンチを準備
iverilog -o /tmp/edge counter.v /tmp/edge_tb.vここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
刻みごとの q を見る
vvp /tmp/edgeここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
4ビットは15の次に0へ戻る
4ビットで表せる最大の数は15です。15に1を足すと、5ビット目が必要になりますが、q は4ビットしかありません。そのため、0に戻ります。
下の表は、13から数えたときの q です。Python で同じ動きを確かめてみましょう。
13から数えたカウンター
| 刻み | q(10進数) | q(2進数) |
|---|---|---|
| 1 | 13 | 1101 |
| 2 | 14 | 1110 |
| 3 | 15 | 1111 |
| 4 | 0 | 0000 |
| 5 | 1 | 0001 |
学生が入力するセルは、このプレビューでは空白です。
Python で真似する
# 4ビットのカウンターを、Python で真似します。
q = 13
for edge in range(5):
print("刻み", edge + 1, "q =", q)
# 15 の次は 16 ではなく 0 に戻ります。
q = (q + 1) % 16
# q の最初の値を 0 に変えて、もう一度実行しましょう。
よくある間違い
注意
rst を1にした瞬間に、q が0になると思いがちです。同期リセットは、次の立ち上がりまで待ちます。それまで q は前の値のままです。先の Run でも、rst を1にしたとき、q は2のままでした。
さらに挑戦: 割り算のカウンター
課題が通ったら、LIMIT を6に変えて、0から5まで数えるカウンターにしましょう。時計の「分」の下の桁は、10で0に戻ります。
LIMIT を10にして、run(8, [[0,1],[0,1],[0,1]]) が何になるか、先に予想してから確かめましょう。