PLL_DigitalPLL

PLL_DigitalPLL : A digitally-controlled phase-locked loop (PLL)

A phase-locked loop (PLL) is a feedback system that generates an output clock of which phase is aligned with that of the input clock. In particular, a digitally-controlled PLL is a PLL that uses a digital controller as its loop filter which updates the oscillator phase and frequency in response to the phase error measured by the phase detector. This type of PLL is gaining popularity due to its programmability and robustness against circuit non-idealities.

This digitally-controlled PLL model is composed of a time-to-digital converter (TDC), a digital loop filter, a digitally-controlled oscillator (DCO), and a frequency divider. The TDC detects the timing error between the input clock in and feedback clock fb and produces a 4-bit digital value terr. The digital loop filter then processes this value and adjusts its 12-bit digital output dctrl, controlling the frequency and phase of the DCO output clock out. When a frequency divider with a dividing ratio of N is present in the feedback path, the PLL generates an N-times higher-frequency output clocks out than the input clock in.

Input/Output Terminals

Name I/O Type Description
out output xbit output clock
in input xbit input clock
reset input wire reset signal

Parameters

Name Type Default Description
init_value int 12’b1000_0000_0000 initial frequency code

List of Children Cells

DIV_SyncDividerBy16 : A synchronous divide-by-16 frequency divider
OSC_ExpDCO : A digitally-controlled oscillator (DCO) with an exponential D-to-f characteristic
PLL_DigitalPLL_LoopFilter : A digital loop filter for digitally-controlled PLL
TDC_GatedOscTDC : A gated-oscillator-based time-to-digital converter (TDC)

List of Testbenches

tb_check_lock : A testbench for checking the locking behavior of a PLL
tb_meas_freqstep : A testbench for measuring the frequency step response of a PLL
tb_meas_jhist : A testbench for measuring the jitter histogram of a PLL output clock
tb_meas_jtran : A testbench for measuring the jitter transfer characteristics of a PLL
tb_meas_phasestep : A testbench for measuring the phase step response of a PLL

tb_check_lock : A testbench for checking the locking behavior of a PLL

This testbench checks if a phase-locked loop (PLL) can successfully acquire a lock by simulating its locking transient. The testbench applies a fixed-frequency reference clock to the PLL, of which initial frequency starts from a value far from the desired lock position. The frequency and phase trajectories of the PLL output clock indicate whether the PLL has the capability of acquiring the correct lock when it is started from the said initial condition.

`include "xmodel.h"

module tb_check_lock();	

    parameter real ref_freq = 312.5e6;  // reference frequency

    // variables
    xbit clk_ref;                       // reference clock
    xbit clk_out;                       // output clock
    bit reset;

    // reference clock generator 
    clk_gen     #(.freq(ref_freq)) clk_gen(clk_ref);

    //reset
    initial begin
        reset = 1;
        #(20ns) reset = 0;
    end

    // DUT (device-under-test) digital PLL
    PLL_DigitalPLL  #(.init_value(12'b0010_0000_0000)) DUT (.in(clk_ref), .out(clk_out), .reset(reset));

    // probing
    probe_xbit  probe_ref(clk_ref);
    probe_xbit  probe_out(clk_out);
    probe_freq  probe_freq(clk_out);
    probe_phase #(.freq(ref_freq*16), .phase_wrap(0)) probe_phase(clk_out);
      
endmodule

Simulation Results

Figure. locking transients of the output clock’s frequency and phase.

steady-state waveforms of the input and output clocks

Figure. steady-state waveforms of the input and output clocks.

tb_meas_freqstep : A testbench for measuring the frequency step response of a PLL

This testbench measures the response of a PLL to a step change in its input clock frequency. Once the PLL acquires a lock, the testbench applies a step change in its input clock frequency using the step_gen and freq_to_clk primitives. The responses in the output clock frequency and phase indicate the loop bandwidth and stability of the PLL.

`include "xmodel.h"

module tb_meas_freqstep();	

    parameter real ref_freq = 312.5e6;  // reference clock initial frequency
    parameter real freq_step = 3.125e6; // frequency step amount
    parameter real delay = 1e-6;        // A point to make frequency step

    // variables
    `xbit(clk_ref);                     // reference clock
    `xbit(clk_out);                     // output clock

    bit reset;
    `xreal(freq);                       // frequency with step change

    // frequency step generator
    step_gen     #(.init_value(ref_freq), .change(freq_step), .delay(delay))
                 freq_gen(freq);
            
    // reference clock generaor
    freq_to_clk  clk_ref_gen(.in(freq), .out(clk_ref));

    //reset
    initial begin
        reset = 1;
        #(20ns) reset = 0;
    end

    // DUT (device-under-test) digital PLL
    PLL_DigitalPLL   DUT(.in(clk_ref), .out(clk_out), .reset(reset));

    // probing
    probe_xbit   probe_ref(clk_ref);
    probe_xbit   probe_out(clk_out);
    probe_freq   probe_freq(clk_out);
    probe_freq   probe_ref_freq(clk_ref);
    
endmodule

Simulation Results

frequency step response of the PLL

Figure. frequency step response of the PLL.

tb_meas_jhist : A testbench for measuring the jitter histogram of a PLL output clock

This testbench measures the jitter histogram and phase noise spectrum of the output clock of a phase-locked loop (PLL). The testbench first lets the PLL acquire a lock by applying a fixed-frequency clock input and waiting for the PLL responses to settle. Then it collects the output clock transitions and analyzes the jitter histogram and phase noise spectrum. The jitter histogram shows the probability density function of the clock edge position and the phase noise spectrum shows the frequency content of the jitter or phase noise. The jitter and phase noise of a PLL output clock can be contributed by the noise from the input clock and internal components.

`include "xmodel.h"

module tb_meas_jhist();	

    parameter real freq_ref = 312.5e6;  // reference clock frequency 
    parameter real RJ_rms = 10e-12;     // reference clock random jitter (RMS)
    parameter real t_lock = 1e-6;       // time required for PLL to lock

    xbit clk_ref;                       // reference clock
    xbit clk_out;                       // output clock
    bit reset;
    
    //reset
    initial begin
        reset = 1;
        #(20ns) reset = 0;
    end

    // DUT phase-locked loop
    PLL_DigitalPLL  DUT(.in(clk_ref), .out(clk_out), .reset(reset));

    // reference clock generator
    clk_gen     #(.freq(freq_ref), .RJ_rms(RJ_rms))
                clk_gen(clk_ref);

    // probing
    probe_xbit  #(.start(t_lock)) probe_out(clk_out);

endmodule

Simulation Results

jitter histogram of the PLL output clock

Figure. jitter histogram of the PLL output clock.

phase noise spectrum of the PLL output clock

Figure. phase noise spectrum of the PLL output clock.

tb_meas_jtran : A testbench for measuring the jitter transfer characteristics of a PLL

This testbench measures the jitter transfer characteristics of a phase-locked loop (PLL). The testbench measures the jitter transfer function at each frequency by applying a sinusoidal jitter to the input clock using a clk_gen primitive and measuring the magnitude and phase of the resulting sinusoidal response in the output clock phase. The jtran.py script repeats this measurement while sweeping the sinusoidal jitter frequency and constructs the overall jitter transfer function of the PLL.

`include "xmodel.h"

module tb_meas_jtran();	
	  
    parameter real ref_freq = @ref_freq;    // input clock frequency 
    parameter real SJ_amp = @sj_amp;        // input sinusoidal jitter amplitude in UI
    parameter real SJ_freq = @sj_freq;      // input sinusoidal jitter frequency in Hz
    parameter real t_lock = @t_lock;        // initial simulation time (PLL locking time) 

    // variables
    xbit clk_ref;                           // reference clock
    xbit clk_out;                           // output clock

    bit reset;

    // reference clock generator with sinusoidal jitter
    clk_gen         #(.freq(ref_freq), .SJ_amp(SJ_amp), .SJ_freq(SJ_freq))
                    clk_gen(clk_ref);

    // reset
    initial begin
        reset = 1;
        #(10e-9/`TIME_SCALE) reset = 0;
    end

    // DUT (device-under-test) digital PLL
    PLL_DigitalPLL  DUT(.in(clk_ref), .out(clk_out), .reset(reset));

    // probing
    probe_phase     #(.freq(16*ref_freq), .start(t_lock)) probe_phase(clk_out);

endmodule

Simulation Results

jitter transfer function of the PLL

Figure. jitter transfer function of the PLL.

tb_meas_phasestep : A testbench for measuring the phase step response of a PLL

This testbench measures the response of a PLL to a step change in its input clock phase. Once the PLL acquires a lock, the testbench applies a step change in its input clock phase using the step_gen and phase_to_clk primitives. The responses in the output clock frequency and phase indicate the loop bandwidth and stability of the PLL.

`include "xmodel.h"

module tb_meas_phasestep();	
    
    parameter real ref_freq = 312.5e6;  // reference frequency
    parameter real phase_step = 1.0;    // phase step amount
    parameter real delay = 1.5e-6;      // A point to make phase step

    // variables
    `xbit(clk_ref);                     // reference clock
    `xbit(clk_out);                     // output clock
    bit reset;

    // phase step generator
    `xreal(phase);
    step_gen     #(.init_value(0.0), .change(phase_step), .delay(delay))
                 step_gen(phase);

    // reference clock generator
    phase_to_clk #(.freq(ref_freq)) clk_ref_gen(.in(phase), .out(clk_ref));

    //reset
    initial begin
        reset = 1;
        #(20e-9/`TIME_SCALE) reset = 0;
    end

    // DUT (device-under-test) digital PLL
    PLL_DigitalPLL  DUT (.in(clk_ref), .out(clk_out), .reset(reset));

    // probing
    probe_xbit  probe_ref(clk_ref);
    probe_xbit  probe_out(clk_out);
    probe_freq  probe_freq(clk_out);
    probe_phase #(.freq(16*ref_freq), .phase_wrap(0)) probe_fb_phase(clk_out);
    probe_phase #(.freq(ref_freq), .phase_wrap(0)) probe_ref_phase(clk_ref);

endmodule

Simulation Results

phase step response of the PLL

Figure. phase step response of the PLL.