FFのリセット
FFのリセットは負論理の非同期リセットを使うのが一般的だが、FPGAファミリやブロックによっては必ずしもそうなっていない。
FF |
ブロックの図 |
Intel |
Xilinx |
Logicブロック のFF (*1) |
|
非同期リセット(*2) 正/負論理 リセット値0/1 |
非同期/同期リセット 正/負論理(*3) リセット値0/1 |
IOブロック のFF |
|
||
DSPブロック のFF |
|
非同期リセット 正/負論理 リセット値0 |
同期リセット 正/負論理(*3) リセット値0 |
RAMブロック のFF |
|
||
(*1)LogicブロックのFFはLAB,Slice単位でリセットラインを共有している (*2)同期リセットはLUTを使ってD入力とANDをとる回路に合成される。 (*3)Spartan6,7seriesのFFのリセット端子は正論理になっており、 RTLを負論理で書くとLogicブロックのLUTでリセットを反転した回路に合成される。 |
◇
そこで、どのFPGAファミリでも使えるRTL記述するには次のようにするとよい。
(1) 原則、FFは正論理の非同期リセットにする
これはSpartan6,7seriesが正論理で、その他は正負どちらでもよいので、正論理の方に合わせておけばよいという意図である。もっとも既存のRTL記述を負論理から正論理に書きなおすのは大変なので、書きなおし量とのトレードオフになる。
// 正論理の非同期リセット always @(posedge clk or posedge rst) begin if(rst) d_reg <= 8'd0; else ... end |
◇
(2) ただし、DSPブロックのFFとRAMブロックの出力FFにはリセットを付けない
これはIntelが非同期リセットでXilinxが同期リセットなので、どちらでも使えるようにするにはリセットなしにするしかないからである。
RAMの出力FFはリセット解除したらすぐRAMの出力値に変わってしまうので、リセットを付けても付けなくても大差ない。
DSPのFFは前段のリセット値が伝搬するように、リセット期間を数クロック確保すれば問題ないが、シミュレーション上はFFの初期値が不定値xになるので、不定値のフィードバックループは作らないように注意した方がよい。
// 乗算器のFFにリセットは付けない always @(posedge clk) begin a_reg <= ain; b_reg <= bin; p_reg <= a_reg * b_reg; end ↑ assign ain = p_reg + cin; のような不定値のフィードバックループ を作らないように注意 |
// RAMの出力FFにリセットは付けない always @(posedge clk) begin if(we) ram[addr] <= din; // write port dout <= ram[addr]; // read port dout_reg <= dout; // 出力FF end |