信じられないかもしれませんが、問題は実際にはテストベンチにあります。これは、VHDL シミュレーション モデルの動作に関係しています。
VHDL は通常、同期ハードウェア設計に使用されます。つまり、立ち上がりエッジでサンプリングし、立ち下がりエッジで出力を設定するフリップフロップを使用して、読み取りと書き込みの間に競合状態が発生しないようにします。しかし、VHDL では、このマスター/スレーブ ロジックは実際には反対のクロック エッジを使用してシミュレートされません。
プロセスを検討する
process (clock) begin
if rising_edge(clock) then
a <= b;
end if;
end process;
シミュレーション タイムステップの開始時に、clock
がちょうど上昇した場合、if
が実行されます。次に、割り当てa <= b
が実行されます。これにより、すぐに割り当てが行われるわけではありませんが、タイムステップの終わりに割り当てをスケジュールします。
すべてのプロセスが実行された後、すべてのスケジュールされた割り当てが行われます。a
これは、次のタイムステップまでプロセスが の新しい値を「認識」しないことを意味します。
Time a b Actions
Start of ts 1 '0' '1' a <= '1' is scheduled
End of ts 1 '1' '0' a <= '1' is executed
Start of ts 2 '1' '0' a <= '0' is scheduled
End of ts 2 '0' '1' a <= '0' is executed
したがって、波形ビューアーを見ると、a
明らかにクロックの立ち上がりエッジに設定されており、b
1 クロック サイクル遅れて続いていることがわかります。これが発生する原因となる割り当ての中間スケジューリングは表示されません。
もちろん、実際には「タイムステップの終わり」はなく、信号の実際の変化はa
、フリップフロップのスレーブ部分がトリガーしたとき、つまり負のエッジで発生します。(おそらく、VHDL が負のエッジを使用する方が混乱しにくいかもしれませんが、まあ、これが機能する方法です)。
ラッチ コードの 2 つのテストベンチを次に示します。
最初に、波形ビューアを見ると、説明したとおりにlwe
表示されます-1クロックサイクル遅れているように見えます-しかし、実際には、設定されている非ブロッキング割り当てで遅延が発生していますcounter
-したがって、立ち上がりエッジが発生し、we
実際にはまだ新しい値がありません。そして 2 番目では、そのような遅延は見られません。立ち上がりエッジで正確にその時lwe
の値に設定されます。we
Verilog の関連トピックについては、Verilog 合成でのノンブロッキング代入、キルするコーディング スタイルを参照してください。