同期/非同期リセットでの生成回路の違い(1)

同期リセット、非同期リセットについては太古の昔に次のように定義されていた。

  • Alteraは非同期リセット推奨
  • Xilinxは同期リセット推奨

とくにXilinxは同期リセットのほうが合成に都合がいいとされていた。

それで、今現状はどうなんだろう?と試してみることにした。

対象のRTL

対象のコードは次のように7入力で6つのANDと1つのORを1出力する回路です。

    DOUT <= DIN0 | (DIN1 & DIN2 & DIN3 & DIN4 & DIN5 & DIN6);

このコードで試しているのはXilinxのUltraScale+で合成をかけているからです。

UltraScale+は6入力LUTなので6つのANDで1つのLUTが使われますが他の1つのORとリセットがどうなるか?というところが確認ポイントです。

次の5つのケースを試してみました。

  • ケース0:リセットなし
  • ケース1:非同期リセット
  • ケース2:同期リセット
  • ケース3:同期リセット
  • ケース4:非同期リセット

ケース0のRTL

このケースはリセットされない回路です。

I/Oは直接ピンに接続します。

`default_nettype none
`timescale 1ns/1ps

module fftest0
(
    input wire RST_N,
    input wire CLK,

    input wire DIN0,
    input wire DIN1,
    input wire DIN2,
    input wire DIN3,
    input wire DIN4,
    input wire DIN5,
    input wire DIN6,

    output reg DOUT
);

always @(posedge CLK) begin
    DOUT <= DIN0 | (DIN1 & DIN2 & DIN3 & DIN4 & DIN5 & DIN6);
end

endmodule

`default_nettype wire

このケースはリセットがないので単純にLUTが2つ使われて構成されるはずです。

![]()

ケース1のRTL

ケース1は非同期リセットです。

`default_nettype none
`timescale 1ns/1ps

module fftest1
(
    input wire RST_N,
    input wire CLK,

    input wire DIN0,
    input wire DIN1,
    input wire DIN2,
    input wire DIN3,
    input wire DIN4,
    input wire DIN5,
    input wire DIN6,

    output reg DOUT
);

always @(posedge CLK or negedge RST_N) begin
    if(!RST_N) begin
        DOUT <= 0;
    end else begin
        DOUT <= DIN0 | (DIN1 & DIN2 & DIN3 & DIN4 & DIN5 & DIN6);
    end
end

endmodule

`default_nettype wire

記述上はCLKRST_Nの変化点で回路が動くように作ったものです。

![]()

ケース2のRTL

ケース2は同期リセットです。

`default_nettype none
`timescale 1ns/1ps

module fftest2
(
    input wire RST_N,
    input wire CLK,

    input wire DIN0,
    input wire DIN1,
    input wire DIN2,
    input wire DIN3,
    input wire DIN4,
    input wire DIN5,
    input wire DIN6,

    output reg DOUT
);

reg CLK_RST_N;

always @(posedge CLK) begin
    CLK_RST_N <= RST_N;
end

always @(posedge CLK) begin
    if(!CLK_RST_N) begin
        DOUT <= 0;
    end else begin
        DOUT <= DIN0 | (DIN1 & DIN2 & DIN3 & DIN4 & DIN5 & DIN6);
    end
end

endmodule

`default_nettype wire

入力したRST_Nを明示的にCLKで叩き直して回路に適用しています。

![]()

ケース3のRTL

ケース3も同期リセットです。

`default_nettype none
`timescale 1ns/1ps

module fftest3
(
    input wire RST_N,
    input wire CLK,

    input wire DIN0,
    input wire DIN1,
    input wire DIN2,
    input wire DIN3,
    input wire DIN4,
    input wire DIN5,
    input wire DIN6,

    output reg DOUT
);

always @(posedge CLK) begin
    if(!RST_N) begin
        DOUT <= 0;
    end else begin
        DOUT <= DIN0 | (DIN1 & DIN2 & DIN3 & DIN4 & DIN5 & DIN6);
    end
end

endmodule

`default_nettype wire

ケース2と違うところはRST_Nを明示的にCLKで叩いていないところです。

しかし、回路はCLKの変化点でのみ動作するので同期リセット回路を想定した記述です。

ケース4のRTL

ケース4は非同期リセットです。

`default_nettype none
`timescale 1ns/1ps

module fftest4
(
    input wire RST_N,
    input wire CLK,

    input wire DIN0,
    input wire DIN1,
    input wire DIN2,
    input wire DIN3,
    input wire DIN4,
    input wire DIN5,
    input wire DIN6,

    output reg DOUT
);

reg CLK_RST_N;
always @(posedge CLK) begin
    CLK_RST_N <= RST_N;
end

always @(posedge CLK or negedge CLK_RST_N) begin
    if(!CLK_RST_N) begin
        DOUT <= 0;
    end else begin
        DOUT <= DIN0 | (DIN1 & DIN2 & DIN3 & DIN4 & DIN5 & DIN6);
    end
end

endmodule

`default_nettype wire

RST_NCLKで叩き直しているので同期リセットのように見えますが回路はCLK_RST_Nの変化点でリセットされるように記述しているので同期リセットに見せかけた非同期リセットが想定です。

配置配線結果

配置配線の結果は次のようになりました。

ケース0 ケース1 ケース2 ケース3 ケース4
同期/非同期 なし 非同期 同期 同期 非同期
LUT 2 3 3 3 3
FF 1 1 2 1 2
IO 9 10 10 10 10
BUFG 1 1 1 1 1

I/Oはリセットなし以外は10本なので間違いありません。

LUTはケース1〜ケース4で変わりません。

FFはケース1とケース3が1個でケース2とケース4が2個です。

FFが1個のときはDOUTのFFのみ構成されています。

FFが2個のときはDOUTRST_NのFFが構成されて2個になっています。

write: 2020/06/29/ 00:00:00