ノンブロッキングとブロッキングでFFの動作が変わる話 SystemVerilog

はじめに

FFを作るとき、ノンブロッキング代入とブロッキング代入で多段FFの動作が変わります。

入力を2段のFFで受けて出力する回路でその動作を見ていきます。

ノンブロッキング

nonblocking.sv
module dut(
    input clk,
    input rst_n,
    input din,
    output logic dout
);
    logic dout_d;
    always_ff @(posedge clk, negedge rst_n) begin
        if (!rst_n) begin
            dout_d <= '0;
        end
        else begin
            dout_d <= din;
        end
    end
    always_ff @(posedge clk, negedge rst_n) begin
        if (!rst_n) begin
            dout <= '0;
        end
        else begin
            dout <= dout_d;
        end
    end
endmodule

ブロッキング

blocking.sv
module dut(
    input clk,
    input rst_n,
    input din,
    output logic dout
);
    logic dout_d;
    always_ff @(posedge clk, negedge rst_n) begin
        if (!rst_n) begin
            dout_d = '0;
        end
        else begin
            dout_d = din;
        end
    end
    always_ff @(posedge clk, negedge rst_n) begin
        if (!rst_n) begin
            dout = '0;
        end
        else begin
            dout = dout_d;
        end
    end
endmodule

シミュレーションを実行する

以下のテストベンチを用意して、それぞれシミュレーションしてみます。

tb.sv
module top;
    initial begin
        $dumpfile("wave.vcd");
        $dumpvars(0, top);
    end

    bit clk = 0;
    bit rst_n = 0;
    always #5 clk = ~clk;

    initial begin
        #10 rst_n = 1;
        #200 $finish;
    end

    bit din = 0;
    always @(posedge clk)
        din <= ~din;

    dut#(
    ) i_dut(
        .clk(clk),
        .rst_n(rst_n),
        .din(din),
        .dout()
    );
endmodule
波形

ノンブロッキング代入のFFはクロック毎に値をラッチしていますが、

ブロッキング代入のFFは1段目と2段目が同時に遷移しています。

ノンブロッキング
ブロッキング

考察

ノンブロッキング代入では右辺から左辺に同時に値が代入されますが、ブロッキング代入では同時ではなくなります。

1段目、2段目のalways文は同時に起動しますが、それぞれのブロッキング代入が評価されるタイミングは言語仕様で決まっていないのでしょうか。

コメント

タイトルとURLをコピーしました