06-21-2019 01:56 PM
I'm having trouble bringing up a SATA transceiver on an UltraScale+ MPSoC.I can't get the CPLL to lock. The reference clock input is on MGTREFCLK1. In the Transceiver Wizard, I'm using the GTH-SATA preset, with a line rate of 3 Gbps (targeting SATA II). The refernece clock frequency on the MGTREFCLK1 is 150 MHz. (I can change the refernece clock frequency if needed, but I cannot put it on different pins.) I have a free-running 50 MHz clock connected to drpclk_in and cplllockdetclk_in.
I have connected the MGTREFCLK1 signal through:
IBUFDS_GTE4 ibufds_gtrefclk1_inst ( .O ( gtrefclk1 ), .ODIV2 ( ), .CEB ( 1'b0 ), .I ( REF_CLK_P_IN ), .IB ( REF_CLK_N_IN ) );
I have cpllrefclksel_in tied to 3'b010. No matter what I try, cplllock_out is always 0. I'm not sure what I'm doing wrong.
I have verified that the clock is reaching the pins. To test that, I temporarily took out the transceiver, took the output from ODIV2 of the IBUFDS_GTE4, put it through a BUFG_GT, and then put it through a "normal" MMCM PLL. That PLL was able to lock, so I have confiednce that the clock signal is arriving at the pins.
Going back to the transceiver, in the transceiver wizard's Physical Resources tab, I have selected GTHE4_CHANNEL_X1Y12, with the TX REFCLK source (CPLL) and RX REFCLK source (CPLL) both set to MGTREFCLK1. The physical resources for this line are Bank 230, data pins D1, D2, E3, E4, which look right. The MGTREFCLK1 pins for that channel should be B9 and B10. (The FPGA part is xczu6cg-ffvb1156-1L-i.)
The code generated by the transcevier wizard is setting the CPLL multipliers/dividers to M=1, N1=5, N2=4, D=2. That corresponds to a CPLL VCO and line rate of both 3 GHz. That is the line rate I requested, and as far as I can tell, that is within range of the CPL: with a divider of 2, the data sheet says the line rate should be in the range 2 - 4.25 GHz for the -1 speed grade.
In my design, the free-running 50 MHz clock is generated from the Zynq's pl_clk0 output. That means that it is not active at power-up, but it is active before bitstream configuration, so that should "appear" free-running to the FPGA fabric. The 150 MHz reference clock is not free-running; it is generated by an external clock chip, which is not active until it is programmed by other logic in my design. I wait until that clock signal is stable and the transceiver's gtpowergood_out is high before asserting and releasing gtwiz_reset_all_in.
I have also tried enabling the CPLL calibration block. I set INCLUDE_CPLL_CAL to 2, re-generated the course, and then examined the source to verify that the values it set to the three calibration signals match what I expect from the CPLL settings I listed above.
Am I missing something obvious? Why isn't my CPLL locking? Any help would be appreciated.
06-24-2019 02:32 AM
if a single ref clock is used, you can connect CPLLREFCLKSEL port to 3'b001 and GTREFCLK0 port in RTL. Put the correct pin number for the MGTREFCLK1P/N. our implemenation tool will connect it properly for you.
You can refer to below comments from UG576 pg32.
Similarly, Figure 2-5 shows the detailed view of the reference clock multiplexer structure
within a single GTHE3/4_CHANNEL primitive. The CPLLREFCLKSEL port is required when
multiple reference clock sources are connected to this multiplexer. A single reference clock
is most commonly used. In this case, connect the reference clock to the GTREFCLK0 port
and tie the CPLLREFCLKSEL port to 3'b001. The Xilinx software tools will handle the
complexity of the multiplexers and associated routing.
06-24-2019 08:45 AM
That doesn't seem to have helped. I removed the gtrefclk1_in and cpllrefclksel_in signals from the wizard and connected the output of my IBUFDS_GTE4 to gtrefclk0_in. When I view the schematic after implementation, I can verify that the IBUFDS_GTE4 now connects to MGTREFCLK0 on the GTHE4_CHANNEL_PRIM_INST generated by the wizard, and that CPLLREFCLKSEL is tied to 001. I still get gtpowergood_out=1 but cplllock_out = 0. Asserting/releasing cpllreset_in did not help; neither did gtwiz_reset_all_in.
06-24-2019 09:00 AM
You ARE working with the example design? The connections won't be in question if your example design simulation works correctly. I would hold the CPLL in power down or reset until there is a reference clock present.
06-24-2019 12:03 PM
I honestly hadn't tried to simulate it. I'm trying to adapt a design that worked on a Kintex-7. I have now created a simple test bench that just contains the transceiver and two clocks: the 50 MHz freeclk and the 150 MHz differential MGTREFCLK. In simulation, both clocks are free-running. The CPLL fails to lock. That means I must be doing something wrong, but I'm not sure what.
In the transceiver wizard, under Structural Options, when selecting which things to put in the core versus the example design, I have everything set to "Core" except for "Include simple receiver user clocking network in the". Instead of using the example design for that component, I am trying to reproduce what I had done with the Kitnex design: I am driving rxusrclk_in and rxusrclk2_in with txusrclk_out and txusrclk2_out, and gtwiz_userclk_rx_active_in with gtwiz_userclk_tx_active_out.
The fact that this is the one part of the design for which I am not using the example design suggests what I am doing is incorrect. The third-party SATA protocol stack we're using is designed to run off a single clock, generated by the transceiver. In the Series 7 wizard, there was an option to set the RXUSRCLK source to TXOUTCLK. I don't see an equivalent option in the UltraScale+ transceiver wizard; the above was my attempt to replicate the same.
In the simulation, I see rxpmaresetdone and txpmaresetdone go high at 200ns, but low again at 240ns. At 222 ns, I see a few pulses of txusrclk, then txusrclk_active goes high, but txusrclk stops toggling at 238ns. That seems strange. txusrclk_active_out stays high even though txusrclk is no longer toggling.
Would it help if I attached my simulation project here? It contains my just configuration of the IP core and minimal test bench.
06-24-2019 12:57 PM
I think I might see what I'm doing wrong. If I want to drive txusrclk and rxusrclk from the same source, I should: 1) export txoutclk from the IP block, 2) put it through a BUFG_GT, and then 3) use that to drive both txusrclk and rxusrclk inputs. Is that the correct approach?
06-24-2019 03:08 PM
I've taken another look, and what I just described should be the effect of the way I have things configured: the Tx user clocking network generated in the core inserts a pair of BUFG_GT's in front of txuserclk and txuserclk2. I then connect those to rxuserclk and rxuserclk2.
I tried simulating the example project generated from the IP core. It also fails to achieve CPLL lock.
07-02-2019 03:02 PM
I have the transceiver coming up now. I think the problem was with the "userclk_active" signals. Given how I'm using the clocks, these must not be asserted until txpmaresetdone_out is high. However, it's not sufficient to just set rx_userclk_active_in to txpmaresetdone_out, because that signal goes high soon after the transceiver powers up even if you have not requested a reset through gtwiz_reset_all_in.
The CPLL now locks in both simulation and hardware.
10-09-2019 08:00 AM
It's been a while. I'll see if I can recall what went wrong. My situation my not exactly match yours. In my design, I wanted to use txoutclk_out as the user clocks for both txusrclk_in and rxusrclk_in. The gtwiz_userclk_tx_active_in and gtwiz_userclk_rx_active_in must be held low until txpmaresetdone_out is high (because that indicates that txoutclk_out is stable). However, the transceiver goes through its startup routine at power-up even if you have gtwiz_reset_all_in held high, which means you'll see the various "done" signals go high. Then, once you release gtwiz_reset_all_in, it will go through the startup routine again. I found I needed to make sure I held gtwiz_userclk_tx_active_in and gtwiz_userclk_rx_active_in low until *after* I had asserted and then de-asserted gtwiz_reset_all_in, and then subsequently txpmaresetdone_out had gone high.
Another mistake I made early on was with the gtwiz_reset_clk_freerun_in signal. The signal name is confusing. It is not a reset signal; it is the free-running clock input. It is necessary for the transceiver to function, and it should be free-running with respect to the transceiver (i.e. you can't use any of the transceiver's output clocks for it).
Those were the two things I needed to change to make my design work. Do create and run the simulated example project from the IP core. I found it useful in figuring out what the various reset and done signals were doing when. You have to run the simulation for a while: with a line rate of 3 Gbps, the simulation had to run for nearly 1.3 ms (that's milliseconds, not microseconds) before all of the done signals asserted. txoutclk_out didn't appear until about 600 us, and it wasn't stable until about 820 us.