[RTL] SDC, Timing Constraints 입문

“내 코드는 완벽한데 왜 칩이 동작하지 않을까?”

RTL 시뮬레이션에서는 아무런 문제가 없었는데, 실제 FPGA나 ASIC 합성하면 동작하지 않는 경우가 있습니다. 90% 이상의 확률로 타이밍(Timing) 문제입니다.

합성(Synthesis) 툴이나 P&R(Place & Route) 툴은 기본적으로 ‘최대한 작게(Area)’ 만들려고 노력할 뿐, 여러분이 이 회로를 100MHz로 돌리고 싶은지, 1GHz로 돌리고 싶은지 알지 못합니다. 이때 툴에게 “이 회로는 무조건 이 속도에 맞춰야 해!”라고 명령하는 파일이 바로 SDC (Synopsys Design Constraints)입니다. (Xilinx FPGA에서는 XDC라고 부르지만 문법은 거의 동일합니다.)

오늘은 수백 가지 SDC 명령어 중, 이것 모르면 설계가 불가능한 핵심 4대장을 알아보겠습니다.

1. 심장 박동 정의하기: create_clock

가장 먼저 할 일은 칩의 심장이 얼마나 빨리 뛰는지 정의하는 것입니다. 모든 타이밍 계산의 기준점(Reference)이 됩니다.

# 문법: create_clock -period [주기_ns] -name [클럭이름] [get_ports 포트명]

# 예시: 100MHz (주기 10ns) 클럭을 'sys_clk' 포트에 정의
create_clock -period 10.0 -name clk_100m [get_ports sys_clk]
  • 의미: “이 sys_clk 핀으로 들어오는 신호는 10ns마다 한 번씩 Rising Edge가 발생한다. 툴 너는 모든 로직(F/F 사이의 조합회로)이 10ns 안에 계산을 마치도록 배치해라.”
  • 주의: 주기를 설정할 때는 실제 목표보다 조금 더 타이트하게(예: 10% 여유) 잡는 것이 일반적입니다. (Over-constraining 기법)

2. 외부 세상과의 약속 1: set_input_delay

Delay 설명

초보자가 가장 이해하기 힘들어하는 명령어입니다. “Input Delay면 입력 핀에서 내부까지 들어오는 딜레이인가?”라고 오해하기 쉽지만, 정반대입니다.

이것은 “칩 바깥(External)에서 들어오는 시간”을 의미합니다.

# 문법: set_input_delay -clock [기준클럭] -max [시간_ns] [get_ports 입력핀]

# 예시: 외부 칩에서 6ns를 쓰고 데이터가 도착한다. (주기 10ns 가정)
set_input_delay -clock clk_100m -max 6.0 [get_ports data_in]
Input delay
  • 물리적 상황:
    1. 외부 칩(Sender)의 레지스터가 clock을 받고 데이터를 쏘는 시간 (T_co).
    2. PCB 기판의 배선을 타고 우리 칩까지 오는 시간 (T_trace).
    3. 이 두 시간을 합친 것이 6ns라고 가정합시다.
  • 툴의 해석: “주기가 10ns인데, 밖에서 이미 6ns를 쓰고 들어왔네? 그럼 우리 칩 내부(Internal)에서는 남은 시간인 4ns (10 – 6) 안에 셋업 타임(Setup Time)을 만족시켜야겠군!”
  • 결론: input_delay 값을 크게 잡을수록, 툴은 내부 로직을 더 빨리 동작하도록 쥐어짭니다.

3. 외부 세상과의 약속 2: set_output_delay

반대로 우리 칩이 데이터를 밖으로 보낼 때의 제약 조건입니다. 이것 역시 “칩 바깥(External)에서 필요한 시간”을 의미합니다.

# 문법: set_output_delay -clock [기준클럭] -max [시간_ns] [get_ports 출력핀]

# 예시: 다음 칩이 데이터를 받기 위해 3ns가 필요하다.
set_output_delay -clock clk_100m -max 3.0 [get_ports data_out]
Output delay
  • 물리적 상황:
    1. PCB 배선 지연 (T_trace).
    2. 다음 칩(Receiver)의 셋업 타임 (T_setup).
    3. 이 두 시간을 합친 것이 3ns입니다.
  • 툴의 해석: “주기가 10ns인데, 데이터가 밖으로 나가서 다음 칩이 받을 때까지 3ns의 여유가 있어야 한다고? 그럼 우리 칩 내부에서는 7ns (10 – 3) 안에 데이터를 핀 밖으로 내보내야겠군!”

4. 예외 처리: set_false_path (CDC 처리)

앞서 배운 CDC(Clock Domain Crossing) 글을 기억하시나요? 서로 다른 주파수의 clock 사이(예: 100MHz → 48MHz)로 데이터가 넘어갈 때는 필연적으로 타이밍 위반이 발생합니다.

이때 엔지니어가 2-FF Synchronizer나 FIFO로 안전장치를 해두었다면, 툴에게 “여기는 타이밍 검사 하지 마! 내가 책임질게”라고 말해줘야 합니다. 안 그러면 툴은 불가능한 타이밍을 맞추느라 밤새도록 헛수고를 하게 됩니다.

# 문법: set_false_path -from [시작클럭] -to [도착클럭]

# 예시: clk_a와 clk_b 사이의 모든 경로는 검사 무시
set_false_path -from [get_clocks clk_a] -to [get_clocks clk_b]
set_false_path -from [get_clocks clk_b] -to [get_clocks clk_a]
  • 주의: 실수로 중요한 경로에 False Path를 걸어버리면, 툴이 최적화를 안 해버려서 칩이 죽습니다. 반드시 CDC가 확실한 곳에만 걸어야 합니다.

5. 요약: SDC는 ‘남은 시간 계산기’다

SDC의 핵심은 Data Required Time (목표 시간)과 Data Arrival Time (도착 시간)의 싸움입니다.

  1. create_clock: 전체 파이(전체 시간, 예: 10ns)를 정합니다.
  2. set_input_delay: 파이의 앞부분(입력 전 소요 시간)을 잘라냅니다.
  3. set_output_delay: 파이의 뒷부분(출력 후 필요 시간)을 잘라냅니다.
  4. 나머지: 가운데 남은 조각만 가지고 RTL 로직을 구현해야 합니다.

RTL 설계를 할 때 단순히 기능만 구현하는 것이 아니라, “내 로직이 과연 이 남은 시간(Slack) 안에 동작할 수 있을까?”를 고민하는 것이 바로 SDC를 이해하는 첫걸음입니다.

참고: Synopsys pdf

Similar Posts