동기
ISE 의 합성 도구(synthesizer)(xst)가 생성하는 리포트의 맨 아래쯤에는 최대 주파수가 무엇인지, 가장 느린 경로(path)의 개요가 무엇인지 함께 적혀 있다. 이는 특히 특정 모듈을 최적화하려고 할 때 꽤 유용한 기능이다. 그런데 Vivado 로 합성한 뒤에는 이런 수치가 제공되지 않는다. 아마 Xilinx 쪽에서 이 "최대 주파수"라는 개념이 오해를 불러일으킬 수 있다고 판단했기 때문일 것이다. 그렇다면 그들에게는 그럴 만한 두 가지 이유가 있었다.
- 첫째, "최대 주파수"라는 것은 실제로 존재하지 않는다. 도구는 타이밍 제약 조건(timing constraints)을 보고 그에 맞춰 최선을 다할 뿐이다. 간단히 말하면, 특정 주파수를 요구하지 않으면 그 주파수를 얻지 못할 수도 있다.
- 둘째, 일반적인 설계에는 서로 다른 주파수를 가진 클럭이 많다. 가장 느린 경로가 애초에 느린 클럭에 속한 경로일 수도 있다.
그렇더라도 전체 구현(implementation)이라는 고난의 길을 떠나기 전에 현재 상황이 어느 정도인지 가늠해 보는 것이 유용할 때가 있다.
Vivado 에서 하는 방법
무엇보다 먼저: 기대하는 바에 맞게 타이밍 제약 조건을 설정하라. 아니면 최소한 어느 클럭이 중요하고 어느 클럭은 느려도 되는지가 분명히 드러나도록 설정하라. 그런 다음 설계를 합성(synthesis)한다.
합성이 성공적으로 끝나면 합성된 설계를 연다(왼쪽 막대에서 "Open Synthesized Design"을 클릭하거나 Tcl 명령어 "open_run synth_1"을 사용).
Tcl 창에 다음 명령을 입력한다.
report_timing_summary -file mytiming.rpt
그러면 합성 후 전체 타이밍 리포트가 mytiming.rpt 파일에 기록된다. "report_timing_summary"만 입력하면 콘솔에 출력된다.
왼쪽 막대의 "Synthesized Design" 아래에 "Report Timing Summary" 옵션도 있지만, GUI 환경에서 이 리포트로부터 필요한 정보를 얻기는 쉽지 않다고 생각한다.
리포트 읽는 법
규칙 #1: 합성 리포트는 어디까지나 대략적인 추정치에 불과하다. 배선 지연(routing delay)은 추정값일 뿐이다. 실제 구현에서는 어차피 성공할 타이밍을 실패로 보고할 수도 있고, 반대로 실제 구현이 크게 실패할 타이밍을 문제없다고 말할 수도 있다(특히 FPGA 의 로직 사용률이 100%에 가까울 때 그렇다).
이제 실제로 해 보자. 가장 먼저 살펴볼 것은 Clock Summary와 Intra Clock Table이다. 여기서 Vivado 가 각 클럭에 어떤 이름을 붙였는지 파악한다. 예를 들어,
------------------------------------------------------------------------------------------------
| Clock Summary
| -------------
------------------------------------------------------------------------------------------------
Clock Waveform(ns) Period(ns) Frequency(MHz)
----- ------------ ---------- --------------
clk_fpga_1 {0.000 5.000} 10.000 100.000
gclk {0.000 4.000} 8.000 125.000
audio_mclk_OBUF {0.000 41.667} 83.333 12.000
clk_fb {0.000 20.000} 40.000 25.000
vga_clk_ins/clk_fb {0.000 20.000} 40.000 25.000
vga_clk_ins/clkout0 {0.000 1.538} 3.077 325.000
vga_clk_ins/clkout1 {0.000 7.692} 15.385 65.000
vga_clk_ins/clkout2 {0.000 7.692} 15.385 65.000
------------------------------------------------------------------------------------------------
| Intra Clock Table
| -----------------
------------------------------------------------------------------------------------------------
Clock WNS(ns) TNS(ns) TNS Failing Endpoints TNS Total Endpoints WHS(ns) THS(ns) THS Failing Endpoints THS Total Endpoints WPWS(ns) TPWS(ns) TPWS Failing Endpoints TPWS Total Endpoints
----- ------- ------- --------------------- ------------------- ------- ------- --------------------- ------------------- -------- -------- ---------------------- --------------------
clk_fpga_1 3.791 0.000 0 12474 0.135 0.000 0 12474 3.750 0.000 0 5021
gclk 6.751 0.000 0 2
audio_mclk_OBUF 76.667 0.000 0 1
clk_fb 12.633 0.000 0 2
vga_clk_ins/clk_fb 38.751 0.000 0 2
vga_clk_ins/clkout0 1.410 0.000 0 10
vga_clk_ins/clkout1 10.747 0.000 0 215 -0.029 -0.229 8 215 6.712 0.000 0 195
vga_clk_ins/clkout2 3.990 0.000 0 415 0.135 0.000 0 415 7.192 0.000 0 211
Clock Summary에 나열된 클럭 주파수(타이밍 제약 조건에서 파생된 값)만으로는 클럭과 이름을 매칭하기 어렵다면, Intra Clock Table에 있는 각 클럭의 TNS Total Endpoints를 보면 어떤 클럭이 어떤 것인지 구분하는 데 도움이 된다. 관심 있는 클럭의 이름을 찾았다면 그 이름을 리포트 파일에서 검색하여 다음과 같은 내용을 찾는다.
Max Delay Paths -------------------------------------------------------------------------------------- Slack (MET) : 3.791ns (required time - arrival time) Source: xillybus_ins/xillybus_core_ins/unitw_1_ins/unitw_1_offset_limit_1/C (rising edge-triggered cell FDRE clocked by clk_fpga_1 {rise@0.000ns fall@5.000ns period=10.000ns}) Destination: xillybus_ins/xillybus_core_ins/unitw_1_ins/unitw_1_end_offset_0/D (rising edge-triggered cell FDRE clocked by clk_fpga_1 {rise@0.000ns fall@5.000ns period=10.000ns}) Path Group: clk_fpga_1 Path Type: Setup (Max at Slow Process Corner) Requirement: 10.000ns (clk_fpga_1 rise@10.000ns - clk_fpga_1 rise@0.000ns) Data Path Delay: 6.077ns (logic 2.346ns (38.605%) route 3.731ns (61.395%)) Logic Levels: 8 (CARRY4=3 LUT3=1 LUT4=1 LUT6=3) Clock Path Skew: -0.040ns (DCD - SCD + CPR) Destination Clock Delay (DCD): 0.851ns = ( 10.851 - 10.000 ) Source Clock Delay (SCD): 0.901ns Clock Pessimism Removal (CPR): 0.010ns Clock Uncertainty: 0.154ns ((TSJ^2 + TIJ^2)^1/2 + DJ) / 2 + PE Total System Jitter (TSJ): 0.071ns Total Input Jitter (TIJ): 0.300ns Discrete Jitter (DJ): 0.000ns Phase Error (PE): 0.000ns Location Delay type Incr(ns) Path(ns) Netlist Resource(s) ------------------------------------------------------------------- ------------------- (clock clk_fpga_1 rise edge) 0.000 0.000 r PS7 0.000 0.000 r xillybus_ins/system_i/vivado_system_i/processing_system7_0/inst/PS7_i/FCLKCLK[1] net (fo=1, unplaced) 0.000 0.000 xillybus_ins/system_i/vivado_system_i/processing_system7_0/inst/n_707_PS7_i BUFG (Prop_bufg_I_O) 0.101 0.101 r xillybus_ins/system_i/vivado_system_i/processing_system7_0/inst/buffer_fclk_clk_1.FCLK_CLK_1_BUFG/O net (fo=5023, unplaced) 0.800 0.901 xillybus_ins/xillybus_core_ins/bus_clk_w r xillybus_ins/xillybus_core_ins/unitw_1_ins/unitw_1_offset_limit_1/C ------------------------------------------------------------------- ------------------- FDRE (Prop_fdre_C_Q) 0.496 1.397 f xillybus_ins/xillybus_core_ins/unitw_1_ins/unitw_1_offset_limit_1/Q net (fo=5, unplaced) 0.834 2.231 xillybus_ins/xillybus_core_ins/unitw_1_ins/unitw_1_offset_limit[1] LUT4 (Prop_lut4_I0_O) 0.289 2.520 r xillybus_ins/xillybus_core_ins/unitw_1_ins/Mcompar_n0037_lutdi/O net (fo=1, unplaced) 0.000 2.520 xillybus_ins/xillybus_core_ins/unitw_1_ins/Mcompar_n0037_lutdi CARRY4 (Prop_carry4_DI[0]_CO[3]) 0.553 3.073 r xillybus_ins/xillybus_core_ins/unitw_1_ins/Mcompar_n0037_cy[0]_CARRY4/CO[3] net (fo=1, unplaced) 0.000 3.073 xillybus_ins/xillybus_core_ins/unitw_1_ins/Mcompar_n0037_cy[3] CARRY4 (Prop_carry4_CI_CO[3]) 0.114 3.187 r xillybus_ins/xillybus_core_ins/unitw_1_ins/Mcompar_n0037_cy[4]_CARRY4/CO[3] net (fo=3, unplaced) 0.936 4.123 xillybus_ins/xillybus_core_ins/unitw_1_ins/Mcompar_n0037_cy[7] LUT6 (Prop_lut6_I4_O) 0.124 4.247 f xillybus_ins/xillybus_core_ins/unitw_1_ins/unitw_1_wr_request_condition/O net (fo=7, unplaced) 0.480 4.727 xillybus_ins/xillybus_core_ins/unitw_1_ins/unitw_1_wr_request_condition LUT3 (Prop_lut3_I2_O) 0.124 4.851 r xillybus_ins/xillybus_core_ins/unitw_1_ins/unitw_1_flush_condition_unitw_1_wr_request_condition_AND_179_o3_lut/O net (fo=1, unplaced) 0.000 4.851 xillybus_ins/xillybus_core_ins/unitw_1_ins/unitw_1_flush_condition_unitw_1_wr_request_condition_AND_179_o3_lut CARRY4 (Prop_carry4_S[2]_CO[3]) 0.398 5.249 f xillybus_ins/xillybus_core_ins/unitw_1_ins/unitw_1_flush_condition_unitw_1_wr_request_condition_AND_179_o2_cy_CARRY4/CO[3] net (fo=21, unplaced) 0.979 6.228 xillybus_ins/xillybus_core_ins/unitw_1_ins/unitw_1_flush_condition_unitw_1_wr_request_condition_AND_179_o LUT6 (Prop_lut6_I5_O) 0.124 6.352 r xillybus_ins/xillybus_core_ins/unitw_1_ins/_n03401/O net (fo=15, unplaced) 0.502 6.854 xillybus_ins/xillybus_core_ins/unitw_1_ins/_n0340 LUT6 (Prop_lut6_I5_O) 0.124 6.978 r xillybus_ins/xillybus_core_ins/unitw_1_ins/unitw_1_end_offset_0_rstpot/O net (fo=1, unplaced) 0.000 6.978 xillybus_ins/xillybus_core_ins/unitw_1_ins/unitw_1_end_offset_0_rstpot FDRE r xillybus_ins/xillybus_core_ins/unitw_1_ins/unitw_1_end_offset_0/D ------------------------------------------------------------------- ------------------- (clock clk_fpga_1 rise edge) 10.000 10.000 r PS7 0.000 10.000 r xillybus_ins/system_i/vivado_system_i/processing_system7_0/inst/PS7_i/FCLKCLK[1] net (fo=1, unplaced) 0.000 10.000 xillybus_ins/system_i/vivado_system_i/processing_system7_0/inst/n_707_PS7_i BUFG (Prop_bufg_I_O) 0.091 10.091 r xillybus_ins/system_i/vivado_system_i/processing_system7_0/inst/buffer_fclk_clk_1.FCLK_CLK_1_BUFG/O net (fo=5023, unplaced) 0.760 10.851 xillybus_ins/xillybus_core_ins/bus_clk_w r xillybus_ins/xillybus_core_ins/unitw_1_ins/unitw_1_end_offset_0/C clock pessimism 0.010 10.861 clock uncertainty -0.154 10.707 FDRE (Setup_fdre_C_D) 0.062 10.769 xillybus_ins/xillybus_core_ins/unitw_1_ins/unitw_1_end_offset_0 ------------------------------------------------------------------- required time 10.769 arrival time -6.978 ------------------------------------------------------------------- slack 3.791
이 텍스트는 다소 지저분해 보이지만, 핵심 요소들은 빨간색으로 표시되어 있다.
어떤 결론을 내리기 전에, 지금 보고 있는 부분이 올바른지 확인하자.
- Max Delay Paths 섹션이어야 한다. Minimum paths 섹션은 홀드 타임 위반(hold time violation)을 찾는 데 유용할 뿐, 최대 주파수와는 관계가 없다.
- 올바른 클럭이어야 한다. 위 예에서는 clk_fpga_1이 그것이다. Requirement 행에는 이 클럭에 주어진 제약 조건(10ns = 100MHz)이 나와 있을 뿐 아니라, 이 경로가 clk_fpga_1의 한 상승 엣지에서 다음 상승 엣지까지 이어지는 경로라는 사실도 나와 있다.
확인이 끝났으면 이제 결과를 보자. 요구 시간(requirement)은 10ns였고, 슬랙(slack)은 3.791ns였다(양수라는 점에 유의). 이는 클럭 주기를 3.791ns만큼 더 짧게 요구해도 문제없었다는 뜻이다. 따라서 요구할 수 있었던 클럭 주기는 10 - 3.791 = 6.209ns, 즉 약 161MHz가 된다.
그러므로 clk_fpga_1의 "최대 클럭" 질문에 대한 짧은 답은 161MHz이다. 다만 이 수치는 제약 조건이 바뀌면 달라질 수 있다는 점을 기억하라.
마지막으로 한 가지. Data Path Delay를 보면 이 최악 경로(worst path)가 왜 느리거나 빠른지 알 수 있다. 지연 중 얼마나 많은 부분이 로직(logic)에서 발생했고, 얼마나 많은 부분이 (추정된) 배선 지연(route delay)에서 발생했는지가 드러난다. 바로 뒤에 이어지는 상세 지연 리포트도 마찬가지다. 더 자세한 리포트가 필요하다면 타이밍 리포트를 요청할 때 "-nworst" 플래그를 사용하여 최악 경로를 여러 개 나열해 보라. 타이밍 문제를 해결하는 데 도움이 될 수 있다.