06-20-2019 08:28 AM
I've got some code implementing a module and a delay line. The module outputs a differential clock to the delay line and the delay line output goes back in the module.The clock sent to the delay line can be changed by the module and it can loop the delay line ouput to its input :
from delay_line --> IBUFDS --> |
| BUFGCTRL --> ODDR --> OBUFDS --> output to delay line
master_clock --> IBUFDS --> |
The delay line introduce a delay from 3ns to 13ns. The master clock runs at 200MHz. In the design, the BUFGCTRL is made to change the output clock just after a pulse of the master_clock.
I can't simulate properly the design. When I try to close the loop on itself, in Vivado's simulator the BUFGCTRL ouput is OK, the ODDR output is OK but the OBUFDS output is red. So shortly after (since it is a loop), the IBUFDS receives a red input and the "undefined" value is propagated everywhere. (I've attached a screenshot)
There is something i must be missing.
Here is some of the code :
input mstr_clk_p, input mstr_clk_n, input dlyc_out_p, input dlyc_out_n, output dlyc_din_p, output dlyc_din_n, // dlyline_clk : from delay_line in --> IBUFDS --> to BUFGCTRL //------------------------------------------------------------------- IBUFDS // IBUFDS is used to transform the differential clock signal to a clock signal #( .IOSTANDARD("LVDS_25")) dlyline_out_clk_ibufgds (.I(dlyc_out_p), .IB(dlyc_out_n), .O(dline_clk_i)); // delay_line in IBUFDS --> | // mstr_clk : in --> IBUFDS --> | BUFGCTRL --> ODDR --> OBUFDS --> out to delay line //----------------------------------------------------------------------------------- IBUFDS // IBUFDS is used to transform the differential clock signal to a clock signal #(.IOSTANDARD("LVDS_25")) mstr_clk_ibufgds (.I(mstr_clk_p), .IB(mstr_clk_n), .O(mstr_clk_i)); BUFG mstr_clk_bufg (.I(mstr_clk_i), .O(master_clk)); // BUFG to send clock to logic BUFGCTRL dline_clk_sel ( // BUFGCTRL is configured as an asynchronous MUX for the MUX to switch immediatly without waitin for switching conditions (see ug572 v1.8) .O(dline_clk_mux), // Clock output to ODDR .CE0(1'b1), // Clock enable input for I0, always on .CE1(1'b1), // Clock enable input for I1, always on .I0(mstr_clk_i), // Primary clock: master clock .I1(dline_clk_i), // Secondary clock: delay line clock looped .IGNORE0(1'b1), // Clock ignore input for I0, always on .IGNORE1(1'b1), // Clock ignore input for I1, always on .S0(~mux_sel_dly_2d), // Clock select for I0: if mux_sel_dly is low, master clock is sent to delay line .S1(mux_sel_dly_2d )); // Clock select for I1: if mux_sel_dly is high, delay line clock is looped (auto-oscillation) ODDRE1 dly_line_clk_oddr ( // ODDR is used to output a clock cleanly .Q(dlyc_clock_oddr), // Output to OBUFDS .C(dline_clk_mux), // Clock input from BUFGCTRL .D1(1'b1), // Value on D1 is output on rising edge of C .D2(1'b0), // Value on D2 is output on falling edge of C .SR(1'b0)); // Set/reset not used OBUFDS // OBUFDS is used to transform the clock signal to a differential clock signal #(.IOSTANDARD("LVDS_25")) dly_cout (.O(dlyc_din_p), .OB(dlyc_din_n), .I(dlyc_clock_oddr));
06-20-2019 06:09 PM
Correct me if I misunderstand it, but isnt' OBUFDS supposed to drive output port only? How can it feedback to the delay line?
06-21-2019 01:41 AM
Sorry I wasn't clear enough, the delay line is external to the FPGA. That's why I use IBUFDS and OBUFDS.
06-21-2019 02:06 AM
Hi @mathieu_paccot ,
Could you provide the testbench? Do you define the mux_sel_dly_1d ?I don't see it in your code.
06-21-2019 02:57 AM
The test is simple: from the beginning, the mux_sel_dly_2d wire is low so the BUFGCTRL ouput its I0 input. Then the mux_sel_dly_2d signal goes up for the BUFGCTRL to output its I1 input.
// BUFGCTRL control logic always @(negedge master_clk or negedge reset_fpga_b) // using negedge of master_clk so that a last pulse of master_clock went through the BUFGCTRL before commuting if (~reset_fpga_b) begin mux_sel_dly_1d <= 1'b0; mux_sel_dly_2d <= 1'b0; end else begin mux_sel_dly_1d <= mux_sel_dly; // double resync for mux_sel_dly signal mux_sel_dly_2d <= mux_sel_dly_1d; // for clock domain crossing end
The mux_sel_dly wire is double registered because it is coming from another clock domain.
06-23-2019 08:28 PM
Is it behavioral simulaiton or timing simulation?
Can you add the primitive level OBUFDS input & output signals to wave, and observe how they change?
06-24-2019 03:17 AM
The OBUFDS primitive input signal is : dlyc_clock_oddr
and the OBUFDS primitive output signals are : dlyc_din_p, dlyc_din_n
They are already on the waveform, they are the last 3 signals.
We can see, and this is the weird thing in that simulation, that the OBUFDS outputs become red BEFORE its input (i.e. the ODDR output).
06-24-2019 05:59 PM
I mean finding the primitive instance in the Scope window, selecting it, and adding the input/output ports shown in the Objects window to wave. e.g. <ODDR instance>.Q
As asked before, is it a behavioral or timing simulation?
06-25-2019 08:54 AM
The primitive instance doesn't appear in the Scope window. In fact there isn't any instance of primitive (BUFG, IBUFDS, ODDR, etc.) in the scope windows...
It is a behavioral simulation.
06-25-2019 06:10 PM
You may change the elaboration option xsim.elaborate.debug_level to 'all' in Simulation Settings. This allows you to view primitives.
If possible, could you share the test case for a look?
06-28-2019 12:16 AM
Ok I changed the settings and relaunched the simulation, I will get back to you with the new waves.
Sorry it's not possible to share the test case as usual... ;-)
06-28-2019 01:08 AM
My take on that is your problems start to appear at dlc_din_p/n and coincident with the transition in mux_sel_dly_2d shortly after the dline_clk_mux rise transition. I would think some setup/hold limits are not respected.
06-28-2019 01:39 AM
06-28-2019 01:46 AM
It looks like a pulse swallow issue, but not should not happen in behavioral simulation.
From the OBUFDS.v,
bufif0 (O, I, GTS);
notif0 (OB, I, GTS);
GTS is driven to '0' after 100 ns. I cannot figure out why the output is 'x'.
Can you please cross check in 3rd party simulator like Questasim and see if the behavior is the same?
06-28-2019 02:18 AM
I tried using a BUFGMUX instead of a BUFGCTRL like described in the ug572 (v1.8, p21 to 24) but it was the same.
As said in the doc, in the BUFGMUX config, the S signal must met setup time requirement or else a glitch can happen but in my case it was not just a glitch.
In the current BUFGMUX_CTRL config, the doc says that "the setup/hold time on S is for determining whether the output passes an extra pulse of the previously selected clock before switching".
What bothers me most is that OBUFDS outputs are the first to go red in the simulation even though its input is still green. If the BUFGCTRL was not used properly I would expect the BUFGCTRL output to go red before the other primitives' outputs