はじめに
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文は同時に起動しますが、それぞれのブロッキング代入が評価されるタイミングは言語仕様で決まっていないのでしょうか。
コメント