コードの動作シミュレーションを行ったところ、完全に動作しました。結果は予想通り。コードを合成して Spartan 3e FPGA にアップロードし、chipscope を使用して解析しようとすると、結果が期待したものに近くありません。私は間違って何をしましたか? http://pastebin.com/XWMekL7r
2 に答える
問題は、状態レジスタの初期値を設定する行 13 ~ 16 にあります。
reg [OUTPUT_WIDTH-1:0] previousstate = 0;
reg [OUTPUT_WIDTH-1:0] presentstate = 1;
reg [6:0] fib_number_cnt = 1;
reg [OUTPUT_WIDTH-1:0] nextstate = 1;
これは、これらの値を割り当てる「初期」ステートメントを作成するのと同じです。これは合成できません。ハードウェアにはデフォルト値などはありません。デザインを FPGA 内に配置すると、これらのレジスタはすべてランダムな値になります。
代わりに、リセットがハイのときに、常にブロック内でこれらのカウンター/状態を初期化する必要があります。
always @(posedge clk or posedge reset)
if (reset) begin
previousstate <= 0;
presentstate <= 1;
... etc ...
end
フォローアップの質問への回答:
このようなコードを初期化すると、ハードウェアでは何も起こりません。まるで $display ステートメントを挿入したかのように、完全に無視されます。合成ツールはすべてのシミュレーションのみの構成をスキップしますが、通常は何らかの警告を表示します (これはツールによって異なります)。
さて、ブロッキングと非ブロッキングの質問には非常に長い答えが必要です:)。SNUG-2000 からこの論文を紹介しますが、これはおそらくこのテーマに関してこれまでに書かれた最高の論文です。あなたの質問だけでなく、このトピックに関する他の多くの質問にも答えます。その後、シーケンシャル ロジックでブロッキング ステートメントを使用することが悪い習慣と見なされる理由と、ブロッキング ステートメントを使用してもコードが正常に機能する理由を理解できます。
http://cs.haifa.ac.il/courses/verilog/cummings-nonblocking-snug99.pdf
その他の回答:
あなたのようなロジックを作成するための通常の「パターン」は、2 つの always ブロックを持ち、1 つはロジックを定義し、もう 1 つはフロップを定義することです。前者ではブロック ステートメントを使用してロジックを実装し、後者では生成された値をラッチ (またはリセット) します。したがって、次のようなものです。
wire some_input;
// Main logic (use blocking statements)
reg state, next_state;
always @*
if (reset) next_state = 1'b0;
else begin
// your state logic
if (state) next_state = some_input;
else next_state = 1'b0;
end
// Flops (use non-blocking)
always @(posedge clock)
if (reset) state <= 1'b0;
else state <= next_state;
ここでは同期リセットを使用していますが、必要に応じて非同期を使用できます。
行 13 ~ 16 は正しいです。「reg [6:0] fib_number_cnt = 1;」「初期」ステートメントを使用するのと同じではありません。レジスタの初期化方法の詳細については、ザイリンクスの合成ガイドを参照してください。