always
つまり、Verilog ステートメント、
always @(/* condition */)
/* block of code */
満足するblock of code
たびに実行しcondition
ます。このようなalways
ブロックはどのようにハードウェアに実装されますか?
posedge x
かだけx
posedge
。
always
つまり、Verilog ステートメント、
always @(/* condition */)
/* block of code */
満足するblock of code
たびに実行しcondition
ます。このようなalways
ブロックはどのようにハードウェアに実装されますか?
posedge x
かだけx
posedge
。
回答:
まず、すべてのVerilogデザインが合成可能であるとは限らないことに注意してください。通常、ハードウェアで実現される設計では、特定の構成要素のサブセットのみを使用できます。
ポップアップ表示される1つの重要な制限は、すべてのreg
変数は多くても1つのalways
ステートメントでのみ割り当てることができるということです。つまり、reg
はalways
ブロックとの親和性があります。
以下の種類のalways
ブロックが一般的に使用できます。
always @(*) begin
// combinational
end
always @(posedge clk) begin
// sequential
end
前者の場合、は*
、ブロックで使用される信号が変化するたびにブロックを実行する必要があること、または同等に、ブロックを継続的に実行する必要があることを示します。したがって、reg
組み合わせalways
ブロックとの親和性を持つは、組み合わせロジック、つまりゲートを使用して他の信号から計算された信号として実装されます。
always
一方、後者のタイプのブロックと親和性のあるレジスタは、Dフリップフロップの出力であり、Dフリップフロップの立ち上がりエッジでクロックされます。clk
(negedge
使用されている場合は立ち下がりエッジ)。フリップフロップへの入力も、他の信号からの組み合わせロジックで計算されます。
次の、やや工夫された例を考えてみましょう。
reg out, out_n;
always @(*) begin
out_n = !out;
end
always @(posedge clk) begin
out <= !out;
end
ここでout_n
は、最初のalways
ブロックに関連付けられout
、2番目のブロックに関連付けられています。out_n
駆動out_n
および駆動される単一のNOTゲートで実装されますout
(純粋な組み合わせロジックであることに注意してください)。一方、out
からクロックされるフリップフロップによって駆動されますclk
ます。フリップフロップへの入力は、out
(前述のフリップフロップによって駆動される)からのNOTゲートによって再び計算されます。最適化されたシンセサイザは、2つのNOTゲートを組み合わせ、1つのNOTゲートと1つのフリップフロップを使用します。
使用可能なハードウェアに応じて、他のタイプの構成を使用できます。たとえば、フリップフロップに非同期リセットがある場合、次の構成も合成できます。
always @(posedge clk or posedge rst) begin
if (rst)
// reset
else
// sequential
end
*
、ブロック内の信号が変更されるたびに(デザインではなく)ブロックを実行する必要があることを示していると思いました。
あ always
ブロックは、一般に、フリップフロップ、ラッチ、またはマルチプレクサを記述するために使用されます。コードは、フリップフロップ、ラッチ、またはマルチプレクサで実装されます。
FPGAでは、フリップフロップとラッチは通常、より汎用的なレジスタデバイスの2つの異なる構成にすぎません。マルチプレクサは、1つ以上の汎用ロジックエレメント(LUT)から構成されます。
一般に、Verilogでデザインを行うには2つの方法があります。
必要なロジックをゲートとレジスタの観点から視覚化し、Verilogでそれを記述する方法を理解します。FPGAベンダーまたは合成ツールベンダーの合成ガイドブックには、使用する可能性のある最も一般的な構造のボイラープレートが記載されています。
Verilogを記述するだけで、基盤となるハードウェアの外観を気にする必要はありません。ただし、これを行ったとしても、何が合成可能で何が合成不可能かを知る必要があります。そのため、ツールベンダーから提供されたボイラープレートを調べて、アプリケーションに適合させます。
編集
Avakarの回答はあなたの質問に対してはるかに良い回答ですが、これはザイリンクスとアルテラの違いについての興味深い議論に拍車をかけたので、私はそれを削除しません。
言われたように、すべてのブロックが常に合成可能であるとは限りません。合成ツールが受け入れるがシミュレータが生成するものとは異なる結果を生成するいくつかのブロックもあります。
まず機密リストから。通常のルールは、エッジ検出構成のみを含む必要があり(通常、可能な組み合わせの選択には制限があります)、または(*またはsystemverilogのalways_combを使用して)ブロックへの入力として使用されるすべての信号を含む必要があります。前者を組み合わせブロックと呼び、後者を順次またはブロックと呼びます。通常、入力のサブセットのみを組み合わせブロック合成ツールに含めると、無視され、完全なリストが指定されているかのように動作します(シミュレーション/合成の不一致が作成されます)。
2番目のブロックと非ブロックの割り当て。コンビナトリアルブロックでは違いはそれほど重要ではありませんが、シーケンシャルブロックでは非常に重要です。
順次ブロックでは、非ブロック割り当てはレジスタをかなり直接モデル化しますが、ブロック割り当ては変数を設定します(設定と読み取りの順序に応じてレジスタを意味する場合としない場合があります)。原則として、シーケンシャルブロックでブロッキング割り当てを使用する「reg」セットは同じブロックでのみ読み取る必要があり、ブロッキングと非ブロッキング割り当てを同じ「reg」で混在させないでください。
同じアイテムにブロック割り当てと非ブロック割り当てを混在させると、合成エラーが発生する可能性があります。あるブロックでブロックの割り当てを行い、別のブロックでそれを読み取ると、シミュレーション/合成の不一致が発生する可能性があります(異なるシミュレーション実行間で不一致になる可能性もあります)。
これで、コンパイラーがコードをロジックに変換する方法を検討できる基本的なルールができました。
最初のステップは、すべてのループを展開することです。つまり、ループには、合成時に決定できる最大反復回数が必要です。そうしないと、合成エラーが発生します。
次に、ツールはブロックの制御フローを分析し、データフローに変換できます。各変数は1つ以上の信号になります。各ifステートメントまたは同様の構成は、実際に使用される結果セットを選択する1つ以上のマルチプレクサになります。
次に、ツールはいくつかの最適化を試みて適用します。
quartusでは、プロジェクトをビルドした後、「tools-> netlist viewers-> rtl viewer」でこのプロセスの結果を見ることができます。
この構造表現を抽象論理要素で生成した後、ツールは、これらの抽象要素をチップが実際に持つリソースにマッピングします。
block of code
..です