0

ハンドシェイクのように交互に実行される 2 つの always ブロックを含む単純な Verilog コードを設計したいと考えています。2 つのブロック (block_A と block_B) を制御するために、do_A と do_B の 2 つのフラグを使用したいと考えています。期待される結果は ABABAB でなければなりません... 次のコードを修正する方法はありますか? 私を助けてくれてありがとう。

    module tb;
    reg clock, reset, do_A, do_B;

    initial begin clock = 0; reset = 0; #50; reset = 150; #50; reset = 0; end
    always #50 clock = ~clock;

    always @(posedge clock) begin: block_A
        if (reset) do_B <= 0;
        else if (do_A) begin
            do_B <= 0;
            $display("A");
        end 
    end

    always @(posedge clock) begin:block_B
        if (reset) do_A <= 1;
        else if (do_B) begin
            do_A <= 0;
            $display("B");
        end 
    end
endmodule

Vesiliy に感謝します。次のコードは、望ましい結果を得るためにうまく機能します。

always @(posedge clock) begin: Block_A
        if (reset) do_B = 0;
        else if (do_A) begin
            do_B = 0;
            $display("A");
        end 
        else do_B <= 1;
    end

    always @(posedge clock) begin:Block_B
        if (reset) do_A = 1;
        else if (do_B) begin
            do_A = 1;
            $display("B");
        end 
        else do_A <= 0;

奇妙に思えますが、うまく機能します。

4

1 に答える 1

3

まずreset = 150;見た目がおかしい(タイプミス?)。ただし、このコンテキストでは機能します。

最初のシーケンシャルに別のタイプミスがありalwaysます-あなたが(一見)書くつもりだったのは次のとおりです。

else if (do_A) begin
    do_B <= 1;
    $display("A");
end 

elseただし、ここでの主な問題は、シーケンシャルalwaysブロックに (デフォルトの) 句がないことだと思います。

このブロックを見てください (例):

always @(posedge clock) begin:block_B
    if (reset) do_A <= 1;
    else if (do_B) begin
        do_A <= 0;
        $display("B");
    end 
end

リセット後、デアサートされましたdo_A = 1。次に、以前のタイプミスを修正したと仮定すると、do_Bは 1 にdo_Aなり、0 になります。この状態に達した後は、do_Aすべてをリセットするまで 0 でスタックします。

次の追加でこれを修正する必要があります (最初のalwaysブロックでも同じです)。

always @(posedge clock) begin:block_B
    if (reset) do_A <= 1;
    else if (do_B) begin
        do_A <= 0;
        $display("B");
    end
    else do_A <= 1; 
end

上記の修正を行ったコードは機能すると思いますが、この機能を説明する正しい方法は、2 つの状態を持つ (単純な) ステートマシンを実装することです。ググってください。

于 2013-07-01T06:22:35.180 に答える