ハードウェア記述言語と検証
always @(*) begin
sum = sum + in;
end入力inを足し続ける累算器のつもりで、上のように書いた。この記述の問題と直し方の組み合わせとして正しいものはどれか。
- A問題はなく、inが変わるたびにsumにinを1回ずつ足す回路が合成される
- Bセンシティビティリストに書き漏れがあり、シミュレーションと合成の結果が食い違う。@(in)と書き直す
- C加算器の出力がフリップフロップを通らずに自分の入力に戻り、値が定まらない。always @(posedge clk)の中でsum <= sum + in;と書き、クロックごとに1回ずつ足す
答えと解説を見る
正解:C. 加算器の出力がフリップフロップを通らずに自分の入力に戻り、値が定まらない。always @(posedge clk)の中でsum <= sum + in;と書き、クロックごとに1回ずつ足す
always @(*)は組み合わせ回路を表すので、この記述は「sumを入力とする加算器の出力を、そのままsumにつなぐ」回路になります。フリップフロップがないため、加算器の出力が変わると入力も変わり、値が回り続けて定まらない組み合わせループになります。静的タイミング解析でも扱えず、多くのLintツールや論理合成ツールが警告やエラーを出します。値を積み上げる回路では、クロックの立ち上がりで1回ずつ値を更新するフリップフロップを入れます。always @(posedge clk)の中でノンブロッキング代入を使い、リセットで初期値も決めます。
- A. クロックがないので「1回ずつ」足す区切りがなく、累算器にはなりません。
- B. @(*)は読んでいるsumとinを自動で含むので、書き漏れはありません。@(in)にしてもループは残ります。
- C. 正しい。帰還の途中にフリップフロップを入れます。