01signal.com

타이밍 제약 조건이 올바른지 검증하기

이 페이지는 타이밍(timing)에 관한 연재 글 모음의 마지막 페이지입니다. 지금까지의 페이지에서는 타이밍 계산의 이론을 설명하고, 몇 가지 타이밍 제약 조건(timing constraints)을 작성하는 방법을 보여 주었으며, 타이밍 클로저(Timing Closure)의 원리도 논의했습니다.

서론

FPGA 개발 방식은 흔히 기능을 추가하고, 동작하지 않는 부분을 고치고, 다시 반복하는 식입니다. 그러다 보면 잠재적으로는 잘못되었지만 당장 눈에 보이는 문제를 일으키지 않는 설계 부분을 소홀히 하기 쉽습니다.

FPGA 설계가 타이밍 제약 조건을 잘못 적용했거나 설사 그 제약 조건을 달성하지 못했더라도 완벽하게 동작할 수 있다는 점을 이해하는 것이 매우 중요합니다. 타이밍 제약 조건의 올바른 사용은 FPGA의 안정적이고 정확한 동작을 보장하는 핵심 요소 중 하나입니다. 그런데 이런 주제를 소홀히 한다고 해서 반드시 즉시 실패가 나타나는 것은 아닙니다. 오히려 부적절한 타이밍은 매우 혼란스러운 간헐적 오동작으로 이어질 수 있습니다.

이 페이지는 이 타이밍 제약 조건 연재에서 제안한 여러 내용을 요약하고 다시 강조합니다. 목적은 부적절한 타이밍 때문에 생긴 문제를 찾을 때 염두에 두어야 할 주제들을 부각하는 것입니다. 평소에도 이런 주제들을 가끔씩 점검하는 지혜를 갖추면 좋겠지만, 실제로는 대부분 뭔가 마법처럼 보이는 문제를 해결하려다 이 글을 찾게 됩니다.

타이밍 리포트를 읽으세요

모든 FPGA 설계 툴은 타이밍 리포트를 생성합니다. 리포트를 여는 가장 흔한 이유는 툴이 타이밍 제약 조건을 달성하지 못했을 때입니다. 리포트에서 실패한 경로(path)를 찾고, 그 경로에 대해 무엇을 할 수 있는지 파악할 수 있습니다.

그러나 타이밍 리포트를 살펴봐야 하는 못지않게 중요한 이유가 하나 더 있습니다. 바로 타이밍 제약 조건이 툴에서 의도한 대로 해석되고, 그래서 제대로 적용되는지 확인하는 것입니다. 특히 새 타이밍 제약 조건을 추가한 뒤에는 이런 점검을 가끔 해 주는 것이 좋은 습관입니다.

FPGA 설계 툴마다 리포트의 구조와 형식이 다르기 때문에, 각 리포트의 모든 부분이 정확히 무엇을 뜻하는지 일일이 설명하는 것은 현실적으로 어렵습니다. 따라서 이 페이지에서는 모든 툴에 공통으로 적용되는 원리를 설명합니다. 여러분이 사용하는 툴의 타이밍 리포트 형식과 기능에 대해서는 시간을 내어 익혀 두는 것이 좋습니다.

타이밍 리포트 점검에서 얻을 수 있는 또 다른 이점은, 로직을 잘못 사용한 부분이 드러날 수 있다는 것입니다. 예를 들어 설계에 비동기 로직을 잘못 사용했거나, 타이밍 제약 조건을 적용할 수 없는 클록에 의존하는 부분이 있다면, 이것이 타이밍 리포트에서 드러날 수 있습니다. 그러한 로직에는 타이밍 제약 조건을 적용하는 것이 불가능하므로, 제약 조건이 없는 경로(unconstrained path)로 나타날 수 있기 때문입니다.

한편, 설계에 포함된 IP는 여러분이 제공하는 제약 조건 위에 툴이 추가로 적용하는 자체 타이밍 제약 조건을 갖는 경우가 많다는 점도 언급할 가치가 있습니다. 이러한 제약 조건과 관련된 경로를 일일이 점검할 필요는 대개 없지만, 그런 경로들이 타이밍 리포트를 상당히 무겁게 만들 수는 있습니다.

제약 조건이 없는 내부 경로

이 논의에서 동기 요소(synchronous element)란 플립플롭, 블록 RAM, 시프트 레지스터, 또는 클록의 상승 엣지나 하강 엣지에서 데이터 입력을 샘플링하거나 데이터 출력을 바꾸는 기타 로직 요소를 뜻합니다.

동기 요소의 데이터 출력에서 다른 동기 요소의 데이터 입력으로 가는 모든 경로에는 반드시 타이밍이 적용되어야 합니다. 즉 타이밍 제약 조건의 적용을 받아야 합니다. 유일한 예외는 목적지 동기 요소에서 타이밍 위반 가능성을 적절히 처리한 경우, 즉 무관한 클록 도메인(unrelated clock domain)처럼 처리한 경우입니다.

다시 말해, 어떤 동기 요소로 가는 경로는 그곳에 명시적인 재동기화 메커니즘이 있어서 툴이 입력 신호를 예측 가능한 방식으로 샘플링하는 책임을 지지 않아도 된다는 점을 보완하지 않는 한, 반드시 타이밍 제약 조건을 적용받아야 합니다.

때로는 기준 클록을 정의하는 한 줄짜리 타이밍 제약 조건만으로 충분하고 나머지는 FPGA 툴이 처리합니다. 어떤 경우에는 그 이상이 필요합니다. 정말 나쁜 경우에는 일부 내부 경로가 실수로 제약 조건 없이 남을 수 있습니다. 여기에는 여러 가능한 이유가 있습니다. 그중 일부는 다음과 같습니다.

FPGA 설계 툴은 타이밍 제약 조건이 적용되지 않은 경로, 즉 제약 조건이 없는 경로를 나열하는 타이밍 리포트를 만드는 기능을 지원합니다. 원칙적으로 이 목록은 비어 있어야 합니다. 제약 조건이 필요 없는 경로는 타이밍 제약 조건 파일에서 명시적으로 가짜 경로(false path)로 정의되어야 합니다. 그러한 제약 조건은 어차피 타이밍이 적용되지 않았던 경로에 기능적으로 아무 변화도 주지 않지만, 타이밍 리포트에서 제약 조건이 없는 경로 목록을 비워 두는 것을 가능하게 합니다. 이렇게 하면 의도치 않게 빠진 경로를 쉽게 발견할 수 있습니다. 게다가 이 목록의 경로 수가 제한되어 있으므로, 무해한 경로들이 대신 나열되면 절대 이 목록에 있으면 안 되는 경로가 숨어 있을 수 있습니다.

안타깝게도 일부 타이밍 리포트에서는 제약 조건이 없는 경로 섹션에 타이밍 제약 조건을 적용할 이유가 없는 경로도 포함될 수 있습니다. 예를 들어 클록 버퍼 출력에서 다른 클록 자원 입력으로 가는 경로가 그렇습니다. 그 결과 타이밍 리포트는 아주 많은 경로를 제약 조건 없는 경로로 나열하지만, 그것은 전혀 문제가 아닙니다. 이 때문에 리포트만으로 상황을 추론하기가 조금 더 어려워지지만, 실제로 큰 문제는 아닙니다. 그런 경로들은 보통 플립플롭의 데이터 입력이나 다른 동기 요소에서 끝나는 경로와 별도로 나열되기 때문입니다. 결국 리포트를 주의 깊게 읽고 각 경로 그룹이 무엇을 의미하는지 유의하는 것이 관건입니다.

기본으로 생성되는 타이밍 리포트에는 이 정보가 충분히 들어 있지 않을 때가 있습니다. 제대로 된 FPGA 설계 툴이라면 제약 조건이 없는 경로를 나열하는 주문형 타이밍 리포트를 만들 수 있고, 각 그룹에 얼마나 많은 경로를 나열할지도 선택할 수 있습니다(관련 목록은 완전히 비어 있어야 하므로 10개면 충분한 값입니다).

클록 도메인 사이의 경로

출발지와 목적지에서 서로 다른 클록에 동기되는 내부 경로는, 그 클록들이 관련 클록(related clocks)이라면(더 정확히는 로직이 그렇게 간주한다면) 타이밍 제약 조건을 적용해야 합니다. 그렇지 않다면 적용해서는 안 됩니다. 불필요한 제약은 고품질 라우팅 자원을 낭비하고 타이밍 제약 조건 달성 실패를 일으킬 수 있기 때문입니다. 관련 클록과 무관한 클록(unrelated clocks)에 대해서는 이 페이지를 참조하세요.

각 툴은 클록 쌍을 관련 클록으로 간주할지 여부를 자동으로 결정하는 고유한 방식을 가집니다. 타이밍 제약 조건 파일에서 SDC 문법을 사용하는 툴(예: Vivado와 Quartus)은 관련 클록 그룹과 무관한 클록 그룹을 정의할 수 있는 set_clock_groups 명령을 제공합니다. 이 문제에서 툴을 안내하는 다른 방법도 있습니다. 특히 가짜 경로(false path) 타이밍 제약 조건을 통한 방법이 있습니다.

그렇다면 툴이 어떤 클록들을 관련 클록으로 보는지, 그렇지 않은지 어떻게 확인할 수 있을까요? 안타깝게도 툴마다 방식이 다릅니다. 예를 들어 Vivado에는 Clock Interaction Report가 있으며, 클록 쌍별 상황을 색상 다이어그램으로 보여 줍니다.

그 대신, 특정 경로 그룹으로 제한된 맞춤형 타이밍 리포트를 만들어 이 문제를 조사할 수도 있습니다. 관련된 클록에 따라 경로를 선택할 수 있습니다. 한 클록에 동기되는 로직 요소에서 시작하여 다른 클록에서 끝나는 경로를 선택하면 됩니다. 또한 클록 도메인 크로싱(clock domain crossing)이 일어나는 것으로 알려진 경로 그룹을 특별히 살펴보는 것도 도움이 될 수 있습니다.

어렵겠지만, 툴이 어떤 클록 도메인 크로싱에 제약 조건을 적용하고 있는지, 그리고 그것이 올바른지 종합적으로 검토하는 것은 매우 중요합니다. 동시에 로직 설계에 필요한 곳에 재동기화 로직이 있는지 검토할 기회이기도 합니다. 어떤 신호에 어떤 클록이 사용되는지 혼동하면 안전하지 않은 클록 도메인 크로싱이 생기기 쉽습니다.

이 검토를 할 때는 각 클록의 성격을 염두에 두는 것이 중요합니다. 예를 들어 서로 다른 오실레이터에서 나온 두 클록이 의도된 주파수는 같고, 그래서 타이밍 제약 조건 파일에서도 비슷하게 정의되어 있다면, 툴이 그 클록들을 잘못 관련 클록으로 간주하여 한 클록에서 다른 클록으로 지나가는 경로의 타이밍을 계산할 수 있습니다. 두 클록 사이의 위상 관계는 전혀 보장되지 않으므로, 그러한 경로에 제약 조건을 적용하는 것은 무의미합니다. 불필요한 타이밍 제약 조건 자체는 툴이 타이밍을 달성하기 어렵게 만들 뿐이라 무해할 수 있습니다. 진짜 문제는 타이밍 리포트가 우리를 속여 그 클록들이 실제로 관련 클록이라고 믿게 만들 수 있다는 점입니다. 그래서 제약 조건과 타이밍 리포트만 보면 두 클록 사이의 경로가 (타이밍 위반으로부터 보호할 필요가 없는) 안전한 경로처럼 보일 수 있습니다. 그러나 실제로는 그렇지 않습니다. 두 클록은 주파수가 대략 같다는 것 말고는 공통점이 전혀 없습니다. 이런 종류의 실수를 피하는 유일한 방법은 각 클록이 어떻게 생성되는지 이해하는 것입니다.

제약 조건이 없는 외부 경로

I/O 핀에서 시작하거나 I/O 핀에서 끝나는 경로에는 항상 타이밍 제약 조건을 적용해야 합니다. 이를 수행하는 방법은 별도 페이지에서 설명합니다. 유일한 예외는 클록 입력 핀과 특수한 인터페이스를 가진 핀입니다. 예를 들어 기가비트 트랜시버, FPGA 실리콘 위의 하드웨어 프로세서에 직접 연결되는 핀 등이 그렇습니다. 인터페이스가 아주 느리다면 타이밍 제약 조건을 정의하지 않은 것이 용서될 수도 있습니다. 예를 들어 LED, 푸시버튼, I2C 배선 같은 경우입니다. 그러나 그러한 핀에는 가짜 경로(false path) 제약 조건을 지정하는 것이 훨씬 좋습니다. 타이밍 리포트에서 제약 조건이 없는 I/O 핀 목록을 비워 둘 수 있기 때문입니다.

외부 경로에 타이밍 제약 조건을 적용하는 것이 무의미해 보일 때가 많습니다. 예를 들어 여러 출력 핀이 모두 같은 클록에 동기되고, 그 핀들이 동시에 토글된다는 사실만으로 올바른 타이밍이 보장된다고 생각하는 경우입니다. 이런 동시 토글을 구현하는 일반적인 방법은 IOB 레지스터(IOB register)를 사용하는 것입니다. 이 플립플롭은 가능한 최상의 clock-to-output 지연과 출력 핀 사이에서 놀라울 정도로 낮은 스큐(skew)를 제공합니다.

그런데 이것은 출력 핀에 타이밍 제약 조건이 왜 중요한지 보여 주는 좋은 예입니다. 타이밍 제약 조건을 엄격하게 유지하면 핀 사이의 낮은 스큐가 보장됩니다. IOB 레지스터를 사용할 때, 엄격한 타이밍 제약 조건은 툴이 이 플립플롭을 사용하도록 강제하는 방법이 될 수 있습니다. 또는 툴이 그렇게 하지 않으면 무시되지 않도록 하는 방법이기도 합니다. 툴이 플립플롭을 원하는 위치에 배치하지 않으면 타이밍이 실패하기 때문입니다.

비슷한 이유로 입력 핀에도 엄격한 타이밍 제약 조건을 적용해야 합니다.

여러 핀 사이의 낮은 스큐를 얻기 위해 타이밍 제약 조건을 사용할 때는, 리포트에 나타나는 슬랙(slack)이 거의 0이 될 때까지 제약 조건을 조이는 것만으로는 부족합니다. 더 엄격한 타이밍을 요구하면 실제로 제약 조건 달성이 실패하는지 확인해야 합니다. I/O 신호 경로에는 선택적인 지연 라인이 포함될 수 있고, 툴이 직관에 반하는 방식으로 그 지연 라인을 활용할 수 있기 때문입니다. 예를 들어 Intel FPGA의 Quartus는 타이밍 여유가 남으면 입력 경로에 지연을 추가할 수 있습니다. 툴이 이런 선택을 하는 것은 바라지 않던 일이거나 예상하지 못한 일일 수 있습니다.

잘못된 가짜 경로와 지나치게 완화된 타이밍

때로는 타이밍 제약 조건이 적용되기는 하는데 너무 관대할 때가 있습니다. 이 경우 관련 경로에 타이밍이 적용되기는 하지만 요구사항이 잘못되었으므로, 발견하기가 훨씬 어렵습니다.

이런 종류의 실수에는 여러 가능한 이유가 있습니다. 그중 일부는 다음과 같습니다.

이런 종류의 문제를 찾아내는 간단한 방법은 없습니다. 타이밍 리포트를 처음부터 끝까지 주의 깊게 읽는 것은 분명 좋은 생각이지만, 리포트가 각 그룹에 10개의 경로를 표시한다고 해서 문제가 있는 경로가 우연히 그 목록에 나타난다는 보장은 없습니다. 표시되는 경로 수가 아무리 많아도 마찬가지입니다.

또 다른 접근 방식은 작성된 타이밍 제약 조건 자체를 검토하는 것입니다. SDC 제약 조건은 Tcl로 작성되므로, 제약 조건 파일에서 로직 요소를 선택하는 표현식("from"과 "to")을 Tcl 표현식으로 평가하고 그 끝점 목록을 훑어볼 수 있습니다.

예를 들어 Vivado .xdc 파일에 다음 줄이 있다면,

set_false_path -to [ get_pins -hier -filter {name =~ */pclk_i1_bufgctrl.pclk_i1/S*} ]

구현된 설계(implemented design)를 열고 false path가 적용되는 목적지들을 나열할 수 있습니다.

puts [join [ get_pins -hier -filter {name =~ */pclk_i1_bufgctrl.pclk_i1/S*} ] "\n" ]

Tcl 명령("puts"와 "join")을 사용하면 각 요소가 별도의 행에 나열되므로 출력이 길어도 쉽게 읽을 수 있습니다.

이런 식으로 제약 조건을 검토하는 것은 중요하지만, 실제로 머리를 써야 하는 일이라 역시 어렵습니다.

요약

툴이 다양한 경로에 올바른 타이밍 한계를 적용하도록 하는 것은 까다로운 작업입니다. 타이밍 제약 조건 문장이 정확히 무엇을 의미하는지 아는 것과, 타이밍 리포트를 확인하는 방법을 아는 것이 결합되어야 실수를 발견할 가능성이 높아집니다.

무엇보다도, 특히 설계가 잘 동작하는 것처럼 보일 때 설계를 반복해서 점검하는 자기 훈련이 중요합니다.

이 페이지는 영어 원문을 기계 번역한 것입니다. 의문이 드는 부분이 있으면 원문을 참조하시기 바랍니다.
Copyright © 2021-2026. All rights reserved. (dcc38493)