FPGAから出力するクロックの位相、FPGAから出力するクロックの位相2、FPGA出力クロックの解析でFPGAから他のデバイスへクロック供給について考察?(そんな良いもんじゃないという話もあるが)したが、結局外部フィードバックをするとDCMへのクロック入力遅延とフィードバック入力遅延が合わずにFPGA外部に出力するクロックの位相が入力クロックと合わずに困ることがあった。
やはり外部フィードバックはやめて内部フィードバックで行くことにした。これだと遅延が計算できる。ディフォルトだとクロックパスは遅延をキャンセルするように自動調整されるので出力用DDRレジスタと出力パッドの遅延分だけキャンセルすればよいようだ。実際に計算して設定してみたら動作したので、書いてみたいと思う。
FPGA FAQからヒントを得てフィードバックを使用しないでFPGAからクロックを出力する方法を試してみた。図1にFPGA出力クロック生成回路を示す。
以前の回路はクロック出力から出力したクロックをフィードバック入力から入力して入力クロックに出力クロックの位相を合わせる予定だったが、FPGA内のクロック入力パスとフィードバック入力パスの遅延が合わないので位相が合わなくなっていた。
今回はDCMのフィードバックはチップ内で行う。その代わり、フィードバックでキャンセルできないデータパス遅延(DDRレジスタと出力パッドの遅延、Tdatapath)はタイミングアナライザから割り出した遅延分をDCMの位相シフトで保障することで0ディレイを保証する。
DDRレジスタのFF0とFF1までのクロックパス(Tclkpath)の遅延の差が0.2ns程度あるようだが、より早いFF1の方で遅延を計算する。実際にタイミングアナライザで算出したPPC_CLK_OUTのクロックパス、データパスの遅延を図2に示す。
図2でデータパス遅延とクロックパス遅延を足して実力係数(0.82)を掛けた遅延値をDCMの位相シフトで戻せば入力クロックと出力クロックは0ディレイになるはずである。戻すべき位相シフト値をTphとして下の式より計算する。
・PPC_CLK
Tph = (Tclkpath + Tdatapath) × 0.82 = (1.546 + (-0.378)) × 0.82 = 0.958ns
位相シフト値はクロックの周期をTとすると (Tph/T)×256 = (0.958/15)×256 = 16
PPC_CLKの位相シフト値は12(SDRAM_CLK0を位相0とするため)なので実際の位相シフト量は以下の値になる。
実際の位相シフト量 12 – 16 = -4
・SDRAM_CLK0
Tph = (Tclkpath + Tdatapath) × 0.82 = (1.551 + (-0.379)) × 0.82 = 0.961ns
位相シフト値はクロックの周期をTとすると (Tph/T)×256 = (0.961/15)×256 = 16
SDRAM_CLK0の位相シフト値は0(SDRAM_CLK0を位相0とするため)なので実際の位相シフト量は以下の値になる。
実際の位相シフト量 0 – 16 = -16
・SDRAM_CLK1
Tph = (Tclkpath + Tdatapath) × 0.82 = (1.527 + (-0.373)) × 0.82 = 0.946ns
位相シフト値はクロックの周期をTとすると (Tph/T)×256 = (0.946/15)×256 = 16
SDRAM_CLK1の位相シフト値は6(SDRAM_CLK0を位相0とするため)なので実際の位相シフト量は以下の値になる。
実際の位相シフト量 6 – 16 = -10
実際に位相を測定して計算値とどのくらいの誤差があるか調べてみた。やり方は今まで同様にテストポイントに各クロックをFPGA EditorのProbe機能を使用して接続してオシロスコープでPCIXクロックからの位相差を測定するという手順で行った。各クロックのテストポイントまでの遅延をタイミングアナライザで測定して実力係数をかけ実力値を求める。実力値にディフォルトでの位相シフト分を上乗せして実測値と比べてみた。それが表1だ。
5.の最終算出値と6.のオシロスコープによる実測値があまり違わないので、私はこの方式が良いだろうと判断した。
<教訓>
FPGAからフードバック入力でフィードバックして出力クロックの位相を合わせようとする場合にクロック入力とフィードバック入力はFPGAダイの近くに配置する。クロック入力がダイの上、フィードバック入力がダイの下というように配置すると双方の配線遅延の差が大きくなって出力クロックの位相の狂いが大きくなる。
やはり外部フィードバックはやめて内部フィードバックで行くことにした。これだと遅延が計算できる。ディフォルトだとクロックパスは遅延をキャンセルするように自動調整されるので出力用DDRレジスタと出力パッドの遅延分だけキャンセルすればよいようだ。実際に計算して設定してみたら動作したので、書いてみたいと思う。
FPGA FAQからヒントを得てフィードバックを使用しないでFPGAからクロックを出力する方法を試してみた。図1にFPGA出力クロック生成回路を示す。
以前の回路はクロック出力から出力したクロックをフィードバック入力から入力して入力クロックに出力クロックの位相を合わせる予定だったが、FPGA内のクロック入力パスとフィードバック入力パスの遅延が合わないので位相が合わなくなっていた。
今回はDCMのフィードバックはチップ内で行う。その代わり、フィードバックでキャンセルできないデータパス遅延(DDRレジスタと出力パッドの遅延、Tdatapath)はタイミングアナライザから割り出した遅延分をDCMの位相シフトで保障することで0ディレイを保証する。
DDRレジスタのFF0とFF1までのクロックパス(Tclkpath)の遅延の差が0.2ns程度あるようだが、より早いFF1の方で遅延を計算する。実際にタイミングアナライザで算出したPPC_CLK_OUTのクロックパス、データパスの遅延を図2に示す。
図2でデータパス遅延とクロックパス遅延を足して実力係数(0.82)を掛けた遅延値をDCMの位相シフトで戻せば入力クロックと出力クロックは0ディレイになるはずである。戻すべき位相シフト値をTphとして下の式より計算する。
・PPC_CLK
Tph = (Tclkpath + Tdatapath) × 0.82 = (1.546 + (-0.378)) × 0.82 = 0.958ns
位相シフト値はクロックの周期をTとすると (Tph/T)×256 = (0.958/15)×256 = 16
PPC_CLKの位相シフト値は12(SDRAM_CLK0を位相0とするため)なので実際の位相シフト量は以下の値になる。
実際の位相シフト量 12 – 16 = -4
・SDRAM_CLK0
Tph = (Tclkpath + Tdatapath) × 0.82 = (1.551 + (-0.379)) × 0.82 = 0.961ns
位相シフト値はクロックの周期をTとすると (Tph/T)×256 = (0.961/15)×256 = 16
SDRAM_CLK0の位相シフト値は0(SDRAM_CLK0を位相0とするため)なので実際の位相シフト量は以下の値になる。
実際の位相シフト量 0 – 16 = -16
・SDRAM_CLK1
Tph = (Tclkpath + Tdatapath) × 0.82 = (1.527 + (-0.373)) × 0.82 = 0.946ns
位相シフト値はクロックの周期をTとすると (Tph/T)×256 = (0.946/15)×256 = 16
SDRAM_CLK1の位相シフト値は6(SDRAM_CLK0を位相0とするため)なので実際の位相シフト量は以下の値になる。
実際の位相シフト量 6 – 16 = -10
実際に位相を測定して計算値とどのくらいの誤差があるか調べてみた。やり方は今まで同様にテストポイントに各クロックをFPGA EditorのProbe機能を使用して接続してオシロスコープでPCIXクロックからの位相差を測定するという手順で行った。各クロックのテストポイントまでの遅延をタイミングアナライザで測定して実力係数をかけ実力値を求める。実力値にディフォルトでの位相シフト分を上乗せして実測値と比べてみた。それが表1だ。
5.の最終算出値と6.のオシロスコープによる実測値があまり違わないので、私はこの方式が良いだろうと判断した。
<教訓>
FPGAからフードバック入力でフィードバックして出力クロックの位相を合わせようとする場合にクロック入力とフィードバック入力はFPGAダイの近くに配置する。クロック入力がダイの上、フィードバック入力がダイの下というように配置すると双方の配線遅延の差が大きくなって出力クロックの位相の狂いが大きくなる。