読者です 読者をやめる 読者になる 読者になる

GTX のクロック

GTX のクロック。Zynq では 4つの GTX がひとつのかたまりになって、PLL が個々についている。加えて qpll なるものが1個ありこれ全部の GTX に供給される。
1.485MHz と 1.485MHz/1.001 の2つを供給して、TX では切り替えられるようにする。RX は qpll をつかって 1.485MHz を供給。どういう仕組みになっているのか知らないけど (PLL と CDC の細かい話まで把握していない)、とにかくここまでやってあげると 1.485GHz (メガじゃないよ) の差動信号で外に出るわけだ(TX)。あるいは 1.485MHz/1.001 で外に出ていく。
IBERT をつかってなんちゃってアイパターン(?)を見ると、一回外に出て折り返しているけどかなりうまく動いている。ほんとにこんなにきれいなのか?ソフト的にみているのだと思うけど、ちゃんと実測してみたい。とくに光で折り返してみたい。
さて、RX の場合、リファレンスが 1.485MHz なのに、あら不思議、1.485MHz と 1.485MHz/1.001 のどちらでも認識できる。その上、自動的にどちらをつかっているかまでわかる。CDC すげー。っていうかアナログ的な CDC とか PLL をもうちょい理解しないといけない気がするぞ。> 自分
で、結局、RX は2つのうちどっちかわからないクロックが出てくる。
さて、Zynq の場合、このクロックで AR が出てます。
AR# 64351 - Vivado 制約 - ギガビット トランシーバー (GT) の出力クロックの制約設定方法
強烈な AR で、「7 シリーズ デバイスの場合は、GT 入力クロックから出力クロックまでのタイミング アークがないため」「自動クロック伝搬がサポートされていません。」だってよ。
道理で ila でいろいろみようとおもったらクロックがないわけだ。
最初はなくてもなんとかなってたんだけど(いやそれじゃだめでしょ)、ちょっと複雑になると、動いたり動かなかったりし始めた。やっぱり、当たり前だけど、ちゃんと create_clock の定義をしないといけない。
というわけでこんな感じで定義。

create_clock -period 6.666 -name clk_sdi_tx_0 [get_pins design_1_i/omni_7series_gtx_0/inst/u_x7gtx_channel_wrapper_0/u_x7gtx_channel_0/gt0_x7gtx_wrapper_i/gtxe2_i/TXOUTCLK]
create_clock -period 6.666 -name clk_sdi_rx_1 [get_pins design_1_i/omni_7series_gtx_0/inst/u_x7gtx_channel_wrapper_0/u_x7gtx_channel_1/gt0_x7gtx_wrapper_i/gtxe2_i/RXOUTCLK]

6.666 ns なので 150MHz 超えてます。最初、1.485MHz と 1.485MHz/1.001 の MUX かと思ったのだけど、よーく考えたら、それはリファレンスクロックであって、RX の場合、CDC で復元されたクロックだ。う~ん。この2つをうまく分離するのか?などと最初は悩んだのだけど、いろいろ見てみての結論は、結局、このクロックというのは合成や実装に使われるわけで、実際のクロックを定義しているわけではない。1.485MHz と 1.485MHz/1.001 なんてのはもうおおよそ同じなわけだ。なので、ざっくりと 6.666ns でいいわけ。な~んだ。

ところが、これだけじゃ終わらない。PS から 150MHzと50MHz (fpga0 と fpga2 という名称のクロックになった)があり、こいつらと上記の tx0 とか rx0 のクロック間が複雑に入り組んでいる。単純に create_clock しただけだと、合成で inter clock 間のタイミングがエラーになる(timing report とか clock 間の遅延をレポートで見る)。

これをちまちまと set_max_delay で設定する。結構大変。

再度合成。inter clock 間のタイミングエラーはゼロになる。やった!!。intra が残るけど、これは使っていないピンだったりして、インプリメント時に消えることがわかっている。

デザインでは VDMA を使う。ソフトを見ると SG (Scatter Gather?) が使えそうに見えるけど、これは後方互換。VDMA 6.0 からは使えなくなった。バッファ切り替えしろということか?VDMA 6.0 は AXIS の IF をつかう。TLAST に line の終わりを示して TUSER (これはARM の AXIS的には自由に拡張して使える)を1ビット使い、先頭の line の先頭に1クロックだけアサートするようなプロトコルになっている。
tuser の代わりに fsync も使えるが、これはどういうわけか負論理。
あるいは none という選択肢もある。とりあえずこれつかっておけば、VDMA としてメモリに書く。境界が変になるけど。

クロック周りはちゃんと考えて設定しないと Vivado ががんばってタイミングを合わせようとして、合成が一晩かかってもおわらないということがありました。つまり FIFO で切れているところはどっちがどっちの clock domain かちゃんと考えないとダメ。まぁ当たり前なんだけど、似たような名前になっているので紛らわしい。

なんだかんだで、やっと前に進める。