Vivado에서 Implementation을 돌렸는데, WNS (Worst Negative Slack)가 음수로 Design Timing Summary에 빨간색 숫자가 떴습니다.
이때 FPGA 엔지니어는 “설계가 잘못됐나?” 하고 코드를 수정하려 합니다. 하지만 이런 경우, 대부분의 문제는 Constraints (제약 조건) 파일에 있습니다. 물리적으로 1 clock 안에 도달할 수 없는 경로를 억지로 검사하느라 에러가 난 것일 수 있기 때문입니다.
이번 글에서는 timing error를 없애는 가장 강력한 두 가지 방법인 False Path와 Multicycle Path의 정확한 설정법과 주의사항에 대해 설명해보겠습니다.
1. Timing Constraints가 왜 필요한가?
Vivado의 타이밍 분석기(STA)는 기본적으로 “모든 레지스터 간의 데이터 전송은 1 clock 주기 안에 끝나야 한다”고 가정합니다.
하지만 실제 회로에는 예외가 존재합니다.
- CDC (Clock Domain Crossing): 서로 다른 clock끼리는 타이밍을 맞출 수 없습니다. (검사 불가능)
- 느린 신호: 100MHz 클럭을 쓰지만, 특정 제어 신호는 2~3 clock에 한 번씩만 변한다면? 굳이 1 clock 안에 도착하라고 닥달할 필요가 없습니다.
이런 예외 상황을 xdc (Xilinx Design Constraints) 파일에 명시해주지 않으면, vivado tool은 불가능한 숙제를 풀다가 Timing Violation을 뱉어냅니다.
2. False Path: “이 길은 검사하지 마”
False Path는 타이밍 분석에서 완전히 제외시키는 명령어입니다. 주로 서로 관련 없는 비동기 clock 간의 경로(CDC)나, 동작 중에 절대 활성화될 일이 없는 경로에 사용합니다.
2.1. 언제 쓰는가?
- CDC (Clock Domain Crossing):
clk_A도메인에서clk_B도메인으로 넘어가는 신호. (반드시 2-FF Synchronizer 등으로 회로적으로 처리된 상태여야 함) - Asynchronous Reset: 비동기 리셋 핀에서 레지스터로 가는 경로.
- Configuration Signals: 부팅 시 한 번 세팅되고 변하지 않는 모드 설정 핀들.
2.2. XDC 명령어 문법 (Tcl)
가장 많이 쓰는 패턴입니다. Vivado Tcl Console이나 xdc 파일에 입력하면 됩니다.
① 클럭 간의 관계 끊기 (가장 흔함)
# clk_a에서 clk_b로 가는 모든 경로는 무시해라
set_false_path -from [get_clocks clk_a] -to [get_clocks clk_b]
# 반대 방향도 무시 (양방향 CDC인 경우)
set_false_path -from [get_clocks clk_b] -to [get_clocks clk_a]② 특정 핀 무시하기 (Reset 등)
# 'sys_rst_n' 포트에서 시작되는 모든 경로는 무시
set_false_path -from [get_ports sys_rst_n]⚠️ 주의사항:
set_false_path는 매우 강력합니다. 실수로 유효한 데이터 경로(Valid Path)에 이걸 걸어버리면, 툴은 타이밍 검사를 포기하고 맘대로 배치합니다. 결과적으로 칩이 랜덤하게 오동작하는 최악의 버그를 만듭니다. 반드시 CDC 회로(Synchronizer)가 있는 곳에만 적용하세요.
3. Multicycle Path: “천천히 가도 돼”
Multicycle Path는 데이터가 도착하는 데 1 clock 이상(N Cycle) 걸려도 된다고 허락해 주는 것입니다.
3.1. 언제 쓰는가?
- Enable 기반 로직: 100MHz clock을 쓰지만,
enable신호가 4 clock마다 한 번씩 켜져서 데이터가 이동하는 경우. - 복잡한 연산기: 곱셈이나 나눗셈처럼 조합 회로 딜레이가 커서 1 clock 안에 계산이 안 되지만, 파이프라인 설계를 통해 2~3 clock 뒤에 결과를 가져가도 되는 경우.
3.2. 핵심 함정: Hold Time (N-1의 법칙)
이 부분이 시니어의 노하우입니다. 많은 분들이 Setup만 늘려주고 안심하는데, 그러면 Hold Violation이 터집니다.
- 기본 동작: Setup 검사는 1주기(Default), Hold 검사는 0주기(같은 엣지)에서 수행합니다.
- Setup을 2로 늘리면: 툴은 Setup 여유가 생겼으니 데이터를 최대한 천천히 보내려고 합니다.
- 문제 발생: 데이터가 너무 늦게 출발해서, Hold 검사 기준(0주기)을 침범할 수 있습니다.
- 해결책: Setup을
N으로 늘렸으면, Hold 검사 기준도N-1만큼 뒤로 밀어줘야 합니다.
3.3. XDC 명령어 문법 (Tcl)
Setup N주기, Hold N-1주기 설정
예를 들어, cpu_core에서 mem_ctrl로 가는 경로가 3 clock 여유가 있다고 가정합시다.
# 1. Setup을 3주기로 완화 (기본값 1 -> 3)
set_multicycle_path -setup 3 -from [get_pins cpu_core/reg_out] -to [get_pins mem_ctrl/reg_in]
# 2. Hold를 2주기(3-1) 뒤로 이동 (필수!)
set_multicycle_path -hold 2 -from [get_pins cpu_core/reg_out] -to [get_pins mem_ctrl/reg_in]💡 요약 공식:
- Setup = N
- Hold = N – 1
4. 실전 가이드: Vivado에서 적용하는 순서
타이밍 에러를 보고 Constraints를 작성하는 흐름입니다.
- Timing Report 확인:
- Vivado Implementation 완료 후
Open Implemented Design. Report Timing Summary클릭.- Intra-Clock Paths 에러인가? -> 로직이 너무 긴 것임. (파이프라인 추가 필요 or Multicycle 고려)
- Inter-Clock Paths 에러인가? -> CDC일 확률 99%. (False Path 고려)
- Vivado Implementation 완료 후
- 경로 분석:
- Failing Path를 더블 클릭하여
Path Properties를 봅니다. - Start Point와 End Point가 서로 다른 클럭 도메인인지 확인합니다.
- 중간에 Synchronizer(2-FF)가 있는지 회로도(
Schematic)에서 확인합니다.
- Failing Path를 더블 클릭하여
- XDC 작성:
- 안전하다고 판단되면
.xdc파일에 위에서 배운set_false_path또는set_multicycle_path를 추가합니다.
- 안전하다고 판단되면
- Re-run:
- Implementation을 다시 돌립니다. WNS가 양수(Positive)로 바뀌었는지 확인합니다.
5. 마치며: 제약 조건은 마법이 아니다
초보 엔지니어는 타이밍 에러가 나면 무조건 False Path를 걸어서 에러를 지우고 싶어 합니다. 이것은 눈을 가리고 운전하는 것과 같습니다.
- 회로적으로 안전한가? (CDC 처리 확인)
- 정말 느려도 되는가? (설계 의도 확인)
이 두 가지가 확인되었을 때만 Constraints를 사용해야 합니다. 정확하게 적용된 Constraints는 여러분의 퇴근 시간을 앞당겨주는 최고의 도구입니다.
참고: xilinx