2

For HDL design I'm currently developing for a zynq SoC, I need to invert a clock signal because of a swapped differential pair on board level.

Using "NOT" to invert adds a LUT in the path and as such introduces skew of at least 500ps between the inverted one and the original one (which is also put on an other differential output. And this is too much in our case.

Is there a way to invert a clock signal so that the skew between the original and the inverted copy is minimal?

I have found a possible solution using the ODDR primitive but this seems more like a workaround than a solution.

Thanks in advance.

Thomas
  • 23
  • 4
  • Is constraining the skew and just having synthesis do its job inserting extra delay on the original signal a possibility? – DonFusili Jul 24 '18 at 12:53
  • Can you implement a zero-delay buffer using a PLL resource? – Spehro Pefhany Jul 24 '18 at 14:50
  • @DonFusili It might be a possibility, so far I have never tried something like that. I will investigate and get back to you. – Thomas Jul 25 '18 at 09:05
  • @SpehroPefhany Using a PLL resource is probably out of the question since it is already the output of a PLL. Although it is possible to invert it by setting the phase to 180. The phase is already controlled dynamically and should be kept that way. I will investigate and get back to you. – Thomas Jul 25 '18 at 09:05
  • @Thomas changing the phase 180 degrees and keeping it dynamically controlled are not mutually exclusive. – DonFusili Jul 25 '18 at 14:02
  • I assume you already figured out a solution, but just wanted to remark: doesn't a negation of a signal (through LUT-based logic) necessarily introduce the possibility of glitches in the transitions? Several other answers/comments seem to suggest that it will work (and they only point out that it is an invonvenient/convoluted solution); seems to me that it cannot work. Am I missing something? – Cal-linux Mar 26 '20 at 14:54

2 Answers2

2

With Xilinx devices, using an ODDR is actually the recommended way to output a clock signal on a pin, especially if you have tight timing constraints. Do this for both clk and clk180, and both will have the same, repeatable timing. It is not a workaround at all.

See comment on the Xilinx forum here by a Xilinx Engineer:

ODDR keeps the duty cycle and provides the best possible path. No routing of clock on any interconnect, clock remains on the global clock resources where they belong.

It's also mentioned in the Xilinx 7-Series Select IO user guide, page 128, section "OLOGIC Resources" > "Clock Forwarding":

Output DDR can forward a copy of the clock to the output. This is useful for propagating a clock and DDR data with identical delays, and for multiple clock generation

You could play around with balancing LUT delays with other LUTs, ODELAY, and constraints, but this will not approach the simplicity or timing predictability of the ODDR method.

scary_jeff
  • 1,977
  • 8
  • 11
0

You could try to add the same delay to both outputs. The trick is to introduce logic which can not be optimized away but adds a LUT delay.

You are probably familiar with using EXOR gates to conditionally invert a signal.

I would add an EXOR function to both output ports. One EXOR's "control" signal is high the other is not. The control signal into each EXOR gate must be such that it could change. e.g. a register which you can write a one or zero to. You never will do that but the synthesis tools does not know so it has to keep the EXOR gate. It can't optimize it away.


Yesterday I tried to prevent logic from being optimised away using various Xilinx constraints but failed. In the end I used the certain-to-work-method I described above but I used an input pin to make that the non-inverting LUT is not optimised away:

//
// Same delay path for o1 and o2 
// where o2 = ~o1
//
module keep (
   input  clk,
   input  reset_n,
   input  never_changes, // Always low 
   output o1,o2
  );

reg [1:0] count;

   // Some (arbitrary) test registers
   always @(posedge clk or negedge reset_n)
   begin
      if (!reset_n)
        count <= 2'b0;
      else
        count <= count + 2'b01;
   end  

/* 
   This did not work:   
   XOR2 X1(.I0(count[1]),.I1(1'b0),.O(o1));
   // synthesis attribute optimize of X1 is off
   XOR2 X2(.I0(count[1]),.I1(1'b1),.O(o2));
   // synthesis attribute optimize of X2 is off
 */
 // This can't fail: Note that never_changes should be low
   assign o1 = never_changes ^ count[1];
   assign o2 = ~count[1];

endmodule   

This is the result of the outputs after place & route: enter image description here

Oldfart
  • 14,212
  • 2
  • 15
  • 41
  • I was also thinking something like adding a LUT to the non-inverted signals path but could not figure out any way to introduce one. It might be tricky to keep the synth tool from optimizing it away. I will try and report back. Thanks! – Thomas Jul 25 '18 at 09:08
  • This will work, but seems like an obfuscated workaround when the Zynq SoC has ODelay primitives. – DonFusili Jul 25 '18 at 10:57
  • The attribute to use in your code above would be `keep`, not `optimize`. – scary_jeff Aug 01 '18 at 08:46