Quartus: The importance of derive_pll_clocks in the SDC file

This post was written by eli on September 5, 2018
Posted Under: Altera,FPGA

Introduction

Whenever a PLL is used in a design to generate one clock from another, it’s quite common to expect the timing tools to figure out the frequencies and timing relations between the different clocks.

With Intel’s Quartus tools, this isn’t the case by default. A derive_pll_clocks command is required in the SDC constraints file for this happen. And indeed, this command appears in virtually any SDC file that is generated automatically by the tools.

But here’s the scary thing: If derive_pll_clocks is omitted, one would expect that the PLL’s output clocks would not be timed at all, and that the relevant paths would be listed as unconstrained. Unfortunately, it’s different: As shown below, timing calculations are made for these paths, but with wrong figures. So one might get the impression that the timing constraints were met and all is fine, but in fact nothing is assured.

An example

Let’s say that the FPGA has an oscillator input of 48 MHz (hence a period of 20.833 ns), from which a PLL generates a 240 MHz clock (with a period of 4.166 ns).

First let’s take a simple, properly written, SDC file going:

create_clock -name root_clk -period 20.833 [get_ports {osc_clock}]

derive_pll_clocks
derive_clock_uncertainty

Note that the derive_pll_clocks command is there.

Now let’s look at the timing report for a path between two registers, which are clocked by the derived clock. The only interesting part is marked with red:

+-------------------------------------------------------------------------------------------------------------------------------------------------+
; Data Arrival Path                                                                                                                               ;
+---------+----------+----+------+--------+------------------------+------------------------------------------------------------------------------+
; Total   ; Incr     ; RF ; Type ; Fanout ; Location               ; Element                                                                      ;
+---------+----------+----+------+--------+------------------------+------------------------------------------------------------------------------+
; 0.000   ; 0.000    ;    ;      ;        ;                        ; launch edge time                                                             ;
; 4.937   ; 4.937    ;    ;      ;        ;                        ; clock path                                                                   ;
;   0.000 ;   0.000  ;    ;      ;        ;                        ; source latency                                                               ;
;   0.000 ;   0.000  ;    ;      ; 1      ; PIN_B12                ; osc_clock                                                                    ;
;   0.000 ;   0.000  ; RR ; IC   ; 1      ; IOIBUF_X19_Y29_N8      ; osc_clock~input|i                                                            ;
;   0.667 ;   0.667  ; RR ; CELL ; 2      ; IOIBUF_X19_Y29_N8      ; osc_clock~input|o                                                            ;
;   2.833 ;   2.166  ; RR ; IC   ; 1      ; PLL_3                  ; clkrst_ins|altpll_component|auto_generated|pll1|inclk[0]                     ;
;   1.119 ;   -1.714 ; RR ; COMP ; 1      ; PLL_3                  ; clkrst_ins|altpll_component|auto_generated|pll1|observablevcoout             ;
;   1.119 ;   0.000  ; RR ; CELL ; 1      ; PLL_3                  ; clkrst_ins|altpll_component|auto_generated|pll1|clk[0]                       ;
;   3.274 ;   2.155  ; RR ; IC   ; 1      ; CLKCTRL_G13            ; clkrst_ins|altpll_component|auto_generated|wire_pll1_clk[0]~clkctrl|inclk[0] ;
;   3.274 ;   0.000  ; RR ; CELL ; 8      ; CLKCTRL_G13            ; clkrst_ins|altpll_component|auto_generated|wire_pll1_clk[0]~clkctrl|outclk   ;
;   4.336 ;   1.062  ; RR ; IC   ; 1      ; FF_X40_Y24_N27         ; clkrst_ins|main_state[0]|clk                                                 ;
;   4.937 ;   0.601  ; RR ; CELL ; 1      ; FF_X40_Y24_N27         ; clkrst:clkrst_ins|main_state[0]                                              ;
; 6.774   ; 1.837    ;    ;      ;        ;                        ; data path                                                                    ;
;   5.169 ;   0.232  ;    ; uTco ; 1      ; FF_X40_Y24_N27         ; clkrst:clkrst_ins|main_state[0]                                              ;
;   5.169 ;   0.000  ; FF ; CELL ; 5      ; FF_X40_Y24_N27         ; clkrst_ins|main_state[0]|q                                                   ;
;   5.591 ;   0.422  ; FF ; IC   ; 1      ; LCCOMB_X40_Y24_N24     ; clkrst_ins|Equal1~0|dataa                                                    ;
;   6.002 ;   0.411  ; FR ; CELL ; 1      ; LCCOMB_X40_Y24_N24     ; clkrst_ins|Equal1~0|combout                                                  ;
;   6.370 ;   0.368  ; RR ; IC   ; 1      ; DDIOOUTCELL_X41_Y24_N4 ; clkrst_ins|the_register|d                                                    ;
;   6.774 ;   0.404  ; RR ; CELL ; 1      ; DDIOOUTCELL_X41_Y24_N4 ; clkrst:clkrst_ins|the_register                                               ;
+---------+----------+----+------+--------+------------------------+------------------------------------------------------------------------------+

+-------------------------------------------------------------------------------------------------------------------------------------------------+
; Data Required Path                                                                                                                              ;
+---------+----------+----+------+--------+------------------------+------------------------------------------------------------------------------+
; Total   ; Incr     ; RF ; Type ; Fanout ; Location               ; Element                                                                      ;
+---------+----------+----+------+--------+------------------------+------------------------------------------------------------------------------+
; 4.166   ; 4.166    ;    ;      ;        ;                        ; latch edge time                                                              ;
; 9.005   ; 4.839    ;    ;      ;        ;                        ; clock path                                                                   ;
;   4.166 ;   0.000  ;    ;      ;        ;                        ; source latency                                                               ;
;   4.166 ;   0.000  ;    ;      ; 1      ; PIN_B12                ; osc_clock                                                                    ;
;   4.166 ;   0.000  ; RR ; IC   ; 1      ; IOIBUF_X19_Y29_N8      ; osc_clock~input|i                                                            ;
;   4.833 ;   0.667  ; RR ; CELL ; 2      ; IOIBUF_X19_Y29_N8      ; osc_clock~input|o                                                            ;
;   6.912 ;   2.079  ; RR ; IC   ; 1      ; PLL_3                  ; clkrst_ins|altpll_component|auto_generated|pll1|inclk[0]                     ;
;   5.119 ;   -1.793 ; RR ; COMP ; 1      ; PLL_3                  ; clkrst_ins|altpll_component|auto_generated|pll1|observablevcoout             ;
;   5.119 ;   0.000  ; RR ; CELL ; 1      ; PLL_3                  ; clkrst_ins|altpll_component|auto_generated|pll1|clk[0]                       ;
;   7.187 ;   2.068  ; RR ; IC   ; 1      ; CLKCTRL_G13            ; clkrst_ins|altpll_component|auto_generated|wire_pll1_clk[0]~clkctrl|inclk[0] ;
;   7.187 ;   0.000  ; RR ; CELL ; 8      ; CLKCTRL_G13            ; clkrst_ins|altpll_component|auto_generated|wire_pll1_clk[0]~clkctrl|outclk   ;
;   8.199 ;   1.012  ; RR ; IC   ; 1      ; DDIOOUTCELL_X41_Y24_N4 ; clkrst_ins|the_register|clk                                                  ;
;   8.736 ;   0.537  ; RR ; CELL ; 1      ; DDIOOUTCELL_X41_Y24_N4 ; clkrst:clkrst_ins|the_register                                               ;
;   9.005 ;   0.269  ;    ;      ;        ;                        ; clock pessimism removed                                                      ;
; 8.985   ; -0.020   ;    ;      ;        ;                        ; clock uncertainty                                                            ;
; 8.890   ; -0.095   ;    ; uTsu ; 1      ; DDIOOUTCELL_X41_Y24_N4 ; clkrst:clkrst_ins|the_register                                               ;
+---------+----------+----+------+--------+------------------------+------------------------------------------------------------------------------+

Aside from all the mumbo-jumbo, there’s the “latch edge time” line, which is the time of the edge of the clock that will propagate through the clock network and become the latching clock on the receiving register. As this is the case of a plain register-to-register path, both clocked with the rising edge of the same clock, the “latch edge time” is simply the clock’s period. Indeed 4.166 ns. So far so good.

But then disaster

Let’s see what happens if the derive_pll_clocks command is omitted. In other words, the SDC file reads:

create_clock -name root_clk -period 20.833 [get_ports {osc_clock}]

derive_clock_uncertainty

For exactly the same path, the timing report reads:

+-------------------------------------------------------------------------------------------------------------------------------------------------+
; Data Arrival Path                                                                                                                               ;
+---------+----------+----+------+--------+------------------------+------------------------------------------------------------------------------+
; Total   ; Incr     ; RF ; Type ; Fanout ; Location               ; Element                                                                      ;
+---------+----------+----+------+--------+------------------------+------------------------------------------------------------------------------+
; 0.000   ; 0.000    ;    ;      ;        ;                        ; launch edge time                                                             ;
; 4.937   ; 4.937    ;    ;      ;        ;                        ; clock path                                                                   ;
;   0.000 ;   0.000  ;    ;      ;        ;                        ; source latency                                                               ;
;   0.000 ;   0.000  ;    ;      ; 1      ; PIN_B12                ; osc_clock                                                                    ;
;   0.000 ;   0.000  ; RR ; IC   ; 1      ; IOIBUF_X19_Y29_N8      ; osc_clock~input|i                                                            ;
;   0.667 ;   0.667  ; RR ; CELL ; 2      ; IOIBUF_X19_Y29_N8      ; osc_clock~input|o                                                            ;
;   2.833 ;   2.166  ; RR ; IC   ; 1      ; PLL_3                  ; clkrst_ins|altpll_component|auto_generated|pll1|inclk[0]                     ;
;   1.119 ;   -1.714 ; RR ; COMP ; 1      ; PLL_3                  ; clkrst_ins|altpll_component|auto_generated|pll1|observablevcoout             ;
;   1.119 ;   0.000  ; RR ; CELL ; 1      ; PLL_3                  ; clkrst_ins|altpll_component|auto_generated|pll1|clk[0]                       ;
;   3.274 ;   2.155  ; RR ; IC   ; 1      ; CLKCTRL_G13            ; clkrst_ins|altpll_component|auto_generated|wire_pll1_clk[0]~clkctrl|inclk[0] ;
;   3.274 ;   0.000  ; RR ; CELL ; 8      ; CLKCTRL_G13            ; clkrst_ins|altpll_component|auto_generated|wire_pll1_clk[0]~clkctrl|outclk   ;
;   4.336 ;   1.062  ; RR ; IC   ; 1      ; FF_X40_Y24_N19         ; clkrst_ins|main_state[0]|clk                                                 ;
;   4.937 ;   0.601  ; RR ; CELL ; 1      ; FF_X40_Y24_N19         ; clkrst:clkrst_ins|main_state[0]                                              ;
; 6.765   ; 1.828    ;    ;      ;        ;                        ; data path                                                                    ;
;   5.169 ;   0.232  ;    ; uTco ; 1      ; FF_X40_Y24_N19         ; clkrst:clkrst_ins|main_state[0]                                              ;
;   5.169 ;   0.000  ; FF ; CELL ; 5      ; FF_X40_Y24_N19         ; clkrst_ins|main_state[0]|q                                                   ;
;   5.583 ;   0.414  ; FF ; IC   ; 1      ; LCCOMB_X40_Y24_N24     ; clkrst_ins|Equal1~0|datab                                                    ;
;   5.994 ;   0.411  ; FR ; CELL ; 1      ; LCCOMB_X40_Y24_N24     ; clkrst_ins|Equal1~0|combout                                                  ;
;   6.361 ;   0.367  ; RR ; IC   ; 1      ; DDIOOUTCELL_X41_Y24_N4 ; clkrst_ins|the_register|d                                                    ;
;   6.765 ;   0.404  ; RR ; CELL ; 1      ; DDIOOUTCELL_X41_Y24_N4 ; clkrst:clkrst_ins|the_register                                               ;
+---------+----------+----+------+--------+------------------------+------------------------------------------------------------------------------+

+--------------------------------------------------------------------------------------------------------------------------------------------------+
; Data Required Path                                                                                                                               ;
+----------+----------+----+------+--------+------------------------+------------------------------------------------------------------------------+
; Total    ; Incr     ; RF ; Type ; Fanout ; Location               ; Element                                                                      ;
+----------+----------+----+------+--------+------------------------+------------------------------------------------------------------------------+
; 20.833   ; 20.833   ;    ;      ;        ;                        ; latch edge time                                                              ;
; 25.672   ; 4.839    ;    ;      ;        ;                        ; clock path                                                                   ;
;   20.833 ;   0.000  ;    ;      ;        ;                        ; source latency                                                               ;
;   20.833 ;   0.000  ;    ;      ; 1      ; PIN_B12                ; osc_clock                                                                    ;
;   20.833 ;   0.000  ; RR ; IC   ; 1      ; IOIBUF_X19_Y29_N8      ; osc_clock~input|i                                                            ;
;   21.500 ;   0.667  ; RR ; CELL ; 2      ; IOIBUF_X19_Y29_N8      ; osc_clock~input|o                                                            ;
;   23.579 ;   2.079  ; RR ; IC   ; 1      ; PLL_3                  ; clkrst_ins|altpll_component|auto_generated|pll1|inclk[0]                     ;
;   21.786 ;   -1.793 ; RR ; COMP ; 1      ; PLL_3                  ; clkrst_ins|altpll_component|auto_generated|pll1|observablevcoout             ;
;   21.786 ;   0.000  ; RR ; CELL ; 1      ; PLL_3                  ; clkrst_ins|altpll_component|auto_generated|pll1|clk[0]                       ;
;   23.855 ;   2.069  ; RR ; IC   ; 1      ; CLKCTRL_G13            ; clkrst_ins|altpll_component|auto_generated|wire_pll1_clk[0]~clkctrl|inclk[0] ;
;   23.855 ;   0.000  ; RR ; CELL ; 8      ; CLKCTRL_G13            ; clkrst_ins|altpll_component|auto_generated|wire_pll1_clk[0]~clkctrl|outclk   ;
;   24.867 ;   1.012  ; RR ; IC   ; 1      ; DDIOOUTCELL_X41_Y24_N4 ; clkrst_ins|the_register|clk                                                  ;
;   25.404 ;   0.537  ; RR ; CELL ; 1      ; DDIOOUTCELL_X41_Y24_N4 ; clkrst:clkrst_ins|the_register                                               ;
;   25.672 ;   0.268  ;    ;      ;        ;                        ; clock pessimism removed                                                      ;
; 25.572   ; -0.100   ;    ;      ;        ;                        ; clock uncertainty                                                            ;
; 25.477   ; -0.095   ;    ; uTsu ; 1      ; DDIOOUTCELL_X41_Y24_N4 ; clkrst:clkrst_ins|the_register                                               ;
+----------+----------+----+------+--------+------------------------+------------------------------------------------------------------------------+

So it’s exactly the same analysis, only assuming that the clock period is 20.833 ns (note the “latch edge time” again). Note that the analysis traverses the PLL, but simply ignores the fact that the PLL’s output has another frequency. It’s as if the tools were saying: You forgot the derive_pll_clocks constraint? No problem. We’ll play as if the PLL’s input clock went right through it.

Frankly, I can’t think about a single case where this behavior would make sense. Either don’t calculate the timing of paths of the derived clock, or do it correctly. But just throwing in the original clock’s period? These incorrectly constrained paths don’t appear in the unconstrained path summary, nor is there any other indication that the timing is horribly wrong.

To the tools’ defense, the timing analysis produces warnings on this matter, but none at a Critical level, so it’s easy to miss them in the sea of warnings that FPGA tools always generate.

Bottom line

  • Make sure your design has the derive_pll_clocks command if you have a PLL involved (unless you’ve added explicit constraints for the derived clocks)
  • Be sure to generate a timing report, to read and understand it.
  • Always test your constraints by requiring impossible values, and verify that the failing paths are calculated correctly

Add a Comment

required, use real name
required, will not be published
optional, your blog address