5 / 24 · 概念
クロックエッジでのレジスタ転送を読む
現在の状態と次状態を区別し、イネーブルが保持値を維持する様子を追います。
レッスンは無料で読めます。受講登録すると進捗を保存できます。
すべてのレジスタは更新前の状態を読む
まず、サイクル間で保持する必要のある情報を特定します。アキュムレータ、取り込んだオペランド、ループ回数、出力validは状態です。現在のアキュムレータとオペランドの和は組み合わせ値です。変数への代入だけでは記憶の動作は説明できません。値を取り込むイベントを定義してください。
このアキュムレータはenがアサートされた立ち上がりエッジでのみxを加算します。enが低いときは値を保持します。9ビットの中間値で加算を明示し、その下位8ビットを選択することで256を法とする動作を定義します。always_ff内のノンブロッキング代入は、現在のエッジで読んだ値を使って次状態の更新を予約します。複数のレジスタがある場合、このブロックをソフトウェアの即時代入として読むと解釈を誤ります。
logic [7:0] acc;
logic [8:0] next_sum;
assign next_sum = {1'b0, acc} + {1'b0, x};
always_ff @(posedge clk) begin
if (rst) acc <= 8'd0;
else if (en) acc <= next_sum[7:0];
endリセットは同期式で、イネーブルより優先します。enが低いとき順序回路の代入を省略することは、レジスタの保持を意味します。一方、組み合わせ回路の経路で代入を省略すると、意図しないラッチを推論させる可能性があります。組み合わせの次状態論理では、既定値を与えてから特定の条件で上書きします。
| エッジ | rst | en | x | 更新前のacc | 更新後のacc |
|---|---|---|---|---|---|
| 0 | 1 | 1 | 9 | 不定 | 0 |
| 1 | 0 | 1 | 7 | 0 | 7 |
| 2 | 0 | 0 | 100 | 7 | 7 |
| 3 | 0 | 1 | 250 | 7 | 1 |
エッジ2では、入力に見えている100は受け入れられていません。エッジ3では7+250=257を縮小して1になります。後にenをvalid AND readyに置き換える際も、提示と受け入れの区別は不可欠です。
a<=x; b<=a;では、更新前のa=5、x=9なら更新後はa=9、b=5です。bに9を受け取らせるなら、その入力をxに接続します。更新前の状態の列を先に埋め、すべての次状態をまとめて計算してください。これによりデータと制御の1サイクルのずれが見つかります。
自分で考えてみましょう
初期値はa=4、b=0です。入力xは8、その次に12で、各エッジでa<=x; b<=aを実行します。2回目のエッジ後のaとbはいくつですか。
解説を見る
1回目のエッジ後はa=8、b=4です。2回目の後はa=12、b=8です。bの更新には毎回更新前のaを使うため、x=12が1つのエッジで両レジスタを通過することはありません。