이 페이지는 clock domains에 대한 시리즈 3개 중 두 번째 페이지입니다.
범위
이전 페이지 에서 이미 언급했듯이 path가 related clocks의 clock domains를 가로 지르면 logic에서 특별한 처리가 필요하지 않습니다. 그럼에도 불구하고 대상(setup 및 hold)에서 synchronous element 의 타이밍 요구 사항을 보장하기 위해 FPGA 도구가 이 path에서 timing constraints를 적용하는지 확인해야 합니다. 따라서 이 경우는 path가 시간 제한이 있다는 점에서 clock domain crossing이 전혀 없는 것처럼 처리됩니다.
그러나 clocks가 unrelated clocks인 경우 resynchronization logic이 필요합니다. 이 문제를 해결하기 위한 전용 코드가 Verilog (또는 다른 언어)로 되어 있어야 합니다. 이 페이지에서는 이를 수행하는 방법에 대한 기본 사항을 설명합니다.
가능하면 FIFO를 사용하십시오.
탈출 가능성이 있는 사람들에게 유리하게 이 두통을 완전히 피하는 방법부터 시작하는 것이 공정하다고 생각했습니다. 다음은 다음과 같습니다.
FPGA 도구에 의해 생성되는Dual-clock FIFOs는 확실히 clock domains를 가로지르는 가장 안전한 방법입니다. 이것이 가장 보편적인 솔루션이며 이 방법이 널리 사용된다는 사실 자체만으로도 신뢰할 수 있는 이유입니다.
특히, FPGAs를 처음 사용하는 경우 해당 목적을 위해 자신의 design을 약간 변경해야 하는 경우에도 FIFO를 선호하는 충분한 이유가 있습니다. FIFO를 사용하면 목적에 맞게 조정된 logic 보다 약간 더 많은 리소스를 소비할 수 있습니다. 그러나 FIFO의 깊이가 얕은 경우 block RAM은 일반적으로 필요하지 않습니다. 따라서 차이가 반드시 엉망이 될 위험이 있는 것은 아닙니다.
종종 FIFO는 clock domains를 가로지르는 자연스러운 솔루션입니다. 특히 한 기능 장치에서 다른 기능 장치로 data stream이 있을 때 그렇습니다. 하지만 그렇게 자연스러운 것은 아니더라도 logic을 재구성하여 상황에 맞도록 하는 것이 종종 가능합니다. 예를 들어, 한 clock domain 의 logic이 어떤 이벤트에 대해 다른 clock domain 의 logic 에 알려야 하는 경우 메시지 단어를 인코딩하고 얕은 FIFO에 작성하여 이를 수행할 수 있습니다. 이러한 종류의 솔루션은 버그가 발생할 가능성이 낮을 뿐만 아니라 보다 체계적이고 읽기 쉬운 design을 생성할 가능성도 있습니다.
FIFOs를 연결하고 사용하는 방법은 이 페이지 시리즈 에서 광범위하게 논의됩니다.
단일 bit용Resynchronization logic
FIFO가 문제를 해결하지 못한다면 이제 우리의 소매를 걷어붙이고 안전한 clock domain crossing을 위해 resynchronization logic을 구현할 때입니다. 이 페이지의 나머지 부분은 단일 bit의 너비를 가진 신호로 clock domains를 가로지르는 것으로 제한됩니다. 이것은 모든 resynchronization logic의 초석이며 이 겉보기에 단순한 케이스에 대해 할 말이 많습니다.
이 시리즈의 다음 페이지 에서는 아래에 제시된 metastability guard 기술을 기반으로 더 넓은 신호로 clock domains를 가로지르는 방법에 대해 설명합니다.
Metastability
해결책으로 넘어가기 전에 flip-flop 의 timing requirements가 위반될 때 무슨 일이 일어나는지 이해하는 것이 중요합니다. 다시 말해, data input 의 신호가 clock edge전에 tsu가 시작되고 그 뒤에 thold가 끝나는 기간에서 안정적이지 않을 때입니다. 관련 clock edge는 물론 flip-flop의 clock input에 있는 것입니다. 이 clock edge가 data input을 샘플링하게 합니다.
분명히 이 기간 동안 데이터가 변경되면 이 clock edge 이후 flip-flop 의 output은 예측할 수 없습니다. 그러나 그보다 더 나쁘다: flip-flop이 flip-flop의 output에서 합법적인 '0' 또는 '1'을 제시하는 데는 평소보다 상당히 더 오래 걸릴 수 있습니다. flip-flop이 이 두 가지 가능한 값(즉, '0' 또는 '1') 중 하나에서 output을 안정적으로 유지하도록 설계되었지만, timing requirements를 위반하면 flip-flop이 잠시 동안 불안정한 상태를 유지할 수 있습니다. 또는 공식 용어를 사용하면 flip-flop은 metastable입니다.
flip-flop이 도달할 수 있는 불안정한 상황을 묘사하는 데 자주 사용되는 언덕 끝에 공이 서 있는 진부한 이미지를 건너뛰지 않겠습니다.
Metastability는 flip-flop이 결국 무엇을 얻게 되는지에 대한 불확실성보다 훨씬 더 큰 문제입니다. flip-flop의 output이 둘 이상의 대상에 연결된 경우 특히 그렇습니다. '0' 또는 '1'에 착륙하는 데 더 오랜 시간이 걸리기 때문에 신호가 목적지에서 flip-flops 에 대해 너무 늦게 안정될 수 있습니다. 결과적으로 목적지에 있는 일부 flip-flops는 워블링 신호를 '0' 로 수신하고 다른 flip-flops는 '1'로 수신할 수 있습니다. 이 불일치는 logic을 잘못된 상태로 만들 수 있으며 이 상황에서 logic은 black magic 스타일로 작동할 수 있습니다. 따라서 metastability 의 위험에 처한 flip-flop은 두 개 이상의 logic element에 연결해서는 안 됩니다.
metastability를 처리하려면 flip-flop이 안정적인 상태 중 하나로 떨어지는 데 걸리는 시간을 아는 것이 좋습니다. 불행히도 그것에 대한 확실한 답은 없습니다. 공이 언덕 꼭대기에 얼마나 오래 머무를 것인지 묻는 것과 같습니다. 그것은 많은 요인에 달려 있으며 무작위 진동으로 인해 결국 이런 식으로 떨어질 가능성이 있습니다. flip-flop의 metastability와 동일: 전자 회로의 무작위 노이즈 또는 기타 다른 이유로 인해 이 상태에서 벗어날 수 있습니다.
따라서 이론상 flip-flop은 metastability 의 상태로 영원히 남을 수 있지만 실제로는 잠시 후 안정적인 상태 중 하나로 떨어질 것입니다. 이 상태를 유지한 시간은 random variable입니다. 그리고 이 random variable의 동작을 추정하기 위해 많은 실험과 시뮬레이션이 이루어졌습니다. 그러나 동작이 silicon의 제조 기술, 온도, crosstalk 의 소음 수준 등에 따라 달라지기 때문에 이러한 시도 중 어느 것도 실제로 관련이 없습니다.
다시 한 번, flip-flop이 metastability의 상태에서 절대 초과하지 않을 최대 시간을 지정하는 것이 편리했을지라도 그러한 제한은 없습니다. 새로운 제조 공정으로 인해 metastability 상태를 더 빨리 벗어나는 경향이 있는 flip-flops가 만들어지기 때문에 대략적인 수치를 얻는 것조차 불가능합니다.
대신 다음과 같은 방법에 익숙해져야 합니다. clock domains를 unrelated clocks와 함께 사용하면 일부 flip-flop이 design이 견딜 수 있는 시간보다 더 오래 metastability 상태로 남아 있을 가능성이 있으며 그 결과 문제가 발생합니다. 우리가 designers 로 할 수 있는 유일한 일은 이 위험을 줄이는 것입니다. 우리는 기껏해야 사람이 살 수 있는 MTBF (Mean Time Between Failure)를 달성할 수 있습니다.
운 좋게도 정확히 이를 달성할 수 있는 잘 정립된 기술이 있어 다음 주제로 넘어갑니다.
metastability guard
긴 이야기를 짧게 만들기 위해 이전 페이지 의 첫 번째 코드 예제를 다시 살펴보겠습니다. @clk1 및 @clk2가 unrelated clocks인 경우 @foo 에서 안정적인 @bar를 얻기 위한 공통 resynchronization logic은 다음과 같습니다.
reg foo, bar, bar_metaguard;
always @(posedge clk1)
foo <= !foo;
always @(posedge clk2)
begin
bar_metaguard <= foo;
bar <= bar_metaguard;
end
이름에서 알 수 있듯이 @bar_metaguard는 metastability guard입니다. @bar_metaguard를 구현하는 flip-flop 의 타이밍 요구 사항은 @foo를 샘플링하는 동안 가끔 위반됩니다. 따라서 @bar_metaguard는 metastability의 짧은 순간을 가질 수 있습니다. 이 flip-flop은 이 상태에서 빠르게 복구될 것으로 예상되므로 @bar의 setup timing requirement를 충족할 만큼 충분히 빠르게 안정될 것입니다. 따라서 @bar는 @clk2의 clock domain내부에서 안정적으로 사용할 수 있습니다.
이 설명은 부정확하게 들릴 수 있으며 실제로 그렇습니다. metastability에 대한 안전 장치 솔루션이 없기 때문에 위에서 metastability 에 대해 쓴 것과 실제로 모순됩니다. 아래에서 더 자세히 다루겠습니다. 그러나 지금은 위와 같이 metastability guard를 추가하는 일반적인 관행을 고수하고 더 이상 걱정하지 마십시오. 그리고 솔직히 말해서, 나는 이것에 문제가 있는 사람에 대해 들어본 적이 없습니다.
좀 더 안전하게 하고 싶은 분들은 registers를 더 추가하세요. 따라서 이중 metastability guard는 다음과 같이 수행됩니다.
reg foo, bar, bar_metaguard_a, bar_metaguard_b;
always @(posedge clk1)
foo <= !foo;
always @(posedge clk2)
begin
bar_metaguard_a <= foo;
bar_metaguard_b <= bar_metaguard_a;
bar <= bar_metaguard_b;
end
@bar_metaguard_a는 첫 번째 metastability guard입니다. 운이 나쁘면 metastability 상태에 너무 오래 머물러 @bar_metaguard_b의 timing requirements가 침해됩니다. 결과적으로 @bar_metaguard_b는 다음 clock cycle에서 metastability 주기를 갖습니다. 하지만 이번에는 metastability 주기가 짧을 것으로 기대할 수 있습니다. 번개는 한 곳에서 두 번 치지 않는다고 합니다. 그러나 물론 @bar_metaguard_b는 @bar의 timing을 위반할 만큼 충분히 오랫동안 metastability 상태를 유지할 수 있습니다. 하지만 그럴 확률은 얼마나 될까요? 목표는 합리적인 MTBF를 얻는 것임을 기억하십시오.
요약: 단일 bit로 clock domain을 가로지르는 방법에 대한 쿡북 솔루션을 찾고 있다면 바로 여기입니다. 하나의 metastability guard 또는 두 개의 metastability guards가 잘 작동합니다. 절대 실패하지 않는 솔루션을 찾고 있다면 불행히도 이것은 불가능합니다. 그러나 가능한 한 사고의 가능성을 줄이려면 계속 읽으십시오.
metastability의Timing analysis
이제 단일 metastability guard를 사용하여 위의 예제로 돌아가서 @bar_metaguard가 metastability 에서 충분히 빨리 복구된다고 확신한 이유를 물어보겠습니다. 대답은 이미 언급했듯이 확신할 이유가 없다는 것입니다.
그럼에도 불구하고 timing analysis를 조금 만들어 봅시다. @bar_metaguard 와 @bar는 모두 동일한 clock와 동기화됩니다. 이 registers 에 특별히 할당된 timing constraints가 없다고 가정하면 이들 사이의 path는 @clk2의 timing constraint (clock period)에 의해 제한됩니다. 즉, 이 도구는 metastability가 없는 경우 @bar 의 input signal이 합법적인 timing로 샘플링되도록 합니다.
하지만 @bar_metaguard 의 요점은 가끔 metastability가 허용된다는 것입니다. 그래서 timing analysis는 충분하지 않습니다. 실제로 flip-flop이 metastability 상태에서 보내는 시간은 clock-to-output 시간에 추가됩니다. 다시 말해, metastability는 flip-flop 의 output이 평소의 delay보다 늦게 안정되는 것을 의미합니다. 따라서 @bar_metaguard 와 @bar 사이의 path가 거의 0인 slack을 가지고 있다면(즉, propagation delay이 timing을 달성하기에 충분하지만 여유가 없다면), metastability는 path의 총 delay을 허용 한계 위로 끌어올릴 수 있습니다. 이러한 이벤트는 @bar의 input에서 timing violation을 발생시킵니다. 물론 이는 온도, 전압 및 제조 공정에서 최악의 경우에 적용되지만, 그럼에도 불구하고: 해당 도구가 metastability guard의 output 에 일반 timing constraint를 적용한다는 사실은 필요한 timing requirements의 성능을 보장하지 않는다는 것을 의미합니다.
다행히도 이것은 쉽게 고칠 수 있습니다. 또는 개선해야 합니다. 방법은 metastability guards 에서 registers 까지 신뢰할 수 있어야 하는 모든 paths 에 더 단단한 timing constraint를 추가하는 것입니다. 즉, 이러한 paths에서 더 적은 propagation delay을 허용하는 것입니다. propagation delay에 허용되는 시간을 줄임으로써 이 시간은 metastability에서 복구하기 위한 것입니다.
예를 들어 모든 metastability guard registers 에 *_metaguard 접미사가 있는 경우 단일 timing constraint를 작성하여 모든 paths가 안정화를 위해 추가 시간을 갖도록 요구할 수 있습니다. Vivado의 경우 이러한 constraint는 다음과 같이 말합니다.
set_max_delay -from [ get_cells -hier -filter {name=~*_metaguard*} ] 0.75
(set_max_delay은 타이밍 예외 페이지 에 설명되어 있습니다.)
이 timing constraint는 metastability guard 에서 시작하는 모든 path가 목적지에 도달하기 위해 0.75 ns를 갖는다는 것을 의미합니다(이러한 paths는 registers이름의 접미사로 선택됨). 이것은 내가 이것을 시도한 특정 FPGA 에서 timing constraint를 실패하지 않고 얻을 수 있었던 최소 지연입니다(따라서 다른 FPGAs에서는 다를 수 있음). 이 숫자에 도달하는 방법은 도구가 이 constraint를 달성하지 못할 때까지 더 낮은 숫자를 선택하는 것입니다. 이 실패 시 매우 작은 slack (예: 0.2 ns)를 달성하는 데 필요한 만큼 이 숫자를 늘리십시오. 이렇게 하면 도구가 이러한 paths에서 최선을 다할 수 있습니다.
이 set_max_delay command는 0.75ns (1333 MHz)의 clock period를 요청하는 것과 같습니다. 따라서 예를 들어 실제 clock period가 250 MHz (4 ns)인 경우 이 timing constraint를 달성하면 최소 4 – 0.75 = 3.25 ns의 잉여가 발생합니다. 따라서 metastability guards가 3.25 ns까지 metastability 상태에 있는 경우 이 set_max_delay constraint덕분에 timing violation은 발생하지 않습니다.
물론 이것은 전혀 보증하지 않는 것보다 낫지 만 3.25 ns 로 충분합니까? 많은가요? clock domains의 가상 페일세이프 전환을 보장하는 것으로 충분합니까?
이미 말했듯이 이것에 대한 대답은 몇 가지 요인에 달려 있습니다. 발표된 실험에 따르면 내 개인적인 인상은 오늘날 실제로 사용되는 FPGA 에서 flip-flop이 1 ns만큼 metastability 상태로 유지되는 것을 볼 가능성은 극히 낮다는 것입니다. 하지만 이 점에 대해 확실히 말씀드리기는 어렵습니다.
그러나 이 timing constraint를 추가하고 도구가 최선을 다하도록 밀어붙이면 FPGA design을 다른 모든 사람의 상황과 동일하거나 더 나은 상태로 만들 수 있습니다. 따라서 황금률 #4 (don't push your luck)의 정신에 따라 그것이 실패하면 다른 많은 사람들도 불평할 이유가 있을 것이라는 입장을 취하십시오.
timing 에 대한 이 토론의 또 다른 통찰력은 clock의 주파수가 사용되는 FPGA 와 관련하여 높으면 이중 metastability guard가 좋은 생각일 수 있다는 것입니다. 위에서 제안한 추가 timing constraint가 사용되지 않는 경우 특히 그렇습니다. 위에서 언급했듯이 metastability는 path의 slack을 소비합니다. clock period가 작아질수록(주파수가 높아짐) slack이 더 적어지므로 metastability에 대한 추가 시간이 줄어듭니다.
마지막으로, 왜 사실상 모든 사람이 timing에 대한 이 모든 문제를 무시하는지, 그리고 아무도 문제에 대해 불평하지 않는지 물어보겠습니다. 몇 가지 가능한 설명을 제시하겠지만, 이는 단지 추측일 뿐입니다.
따라서 첫 번째 설명은 도구가 metastability guard를 물리적으로 FPGA의 logic fabric 에서 다른 flip-flop에 매우 가깝게 배치할 가능성이 있다는 것입니다. 따라서 이 두 flip-flops 사이의 propagation delay (예: @bar_metaguard ~ @bar)는 어쨌든 해당 FPGA 측면에서 매우 짧습니다. 그러나 위에서 논의한 바와 같이 명시적 timing constraints없이는 이러한 긴밀한 배치가 보장되지 않습니다.
FPGA의 공급업체가 제공하는 공식 FIFOs 내부에서 이러한 종류의 flip-flops 쌍은 종종 동일한 slice에서 발견됩니다. 그럼에도 불구하고 공식 FIFOs는 이 문제를 해결하도록 신뢰할 수 있습니다.
또 다른 것은 FPGAs가 더 빨라지고 더 높은 clock 주파수가 가능해짐에 따라 flip-flops 도 metastability 에서 더 빨리 빠져 나온다는 것입니다. 따라서 metastability 와 propagation delay에서 복구하는 데 걸리는 시간은 여전히 clock의 clock period 보다 훨씬 짧습니다.
따라서 대부분의 사람들이 metastability guard를 추가하고 더 이상 그것에 대해 걱정하지 않는다는 것은 놀라운 일이 아닙니다. 그러나 그것이 constraint추가에 대해 게으른 것에 대한 변명은 아닙니다.
clocks의 주파수 제한
나는 지금까지 clock domain에서 clocks 의 주파수에 대해 많이 말하지 않았습니다. 예를 들어 소스의 clock domain (@clk1)에 있는 clock이 대상의 clock (@clk2)보다 빠르면 어떻게 됩니까?
clocks간에 동기화가 필요하지 않기 때문에 소스의 주파수 자체가 높거나 낮은지는 중요하지 않습니다. 그러나 소스의 신호(@foo)가 너무 빨리 변경되면 대상의 flip-flop이 이 변경을 샘플링하기 전에 앞뒤로 변경될 수 있습니다. 따라서 모든 전환이 대상에서 표시되어야 하는 경우 소스의 clock period는 대상의 clock보다 약간 더 길어야 합니다(즉, 주파수가 더 낮음).
얼마나 더 오래? 별로. 또는 정확한 답변을 주장하는 경우: 그것은 주로 목적지의 timing requirements 또는 flip-flop 에 달려 있습니다. 간단한 계산은 다음과 같습니다(정말 관심이 없다면 건너뛰세요):
이 flip-flop의 input이 flip-flop의 clock edge보다 정확히 tsu 전에 변경되면 적절하게 샘플링되는 직전이므로 다음 clock cycle에서 샘플링해야 합니다. 그렇지 않으면 이 변경이 누락되었을 수 있습니다. 다음 clock cycle 에서 이 변경을 안정적으로 샘플링하려면 input signal이 다음 clock edge후 thold 까지 안정적으로 유지되어야 합니다. 따라서 소스의 clock period는 대상의 clock period 보다 tsu + thold + 2tj만큼 길어야 합니다. tj는 clock period (jitter)의 불확실성입니다. jitter는 두 번 계산되는데, 한 번은 소스의 clock 에 대해, 두 번째는 destination의 clock에 대해 계산됩니다.
따라서 tsu + thold + 2tj 는 소스의 clock에 대해 "약간 더 긴" clock period를 의미했습니다.
metastability guards에 대한 도구 설명
일부 FPGA 도구의 설명서에서는 metastability guards로 사용되는 flip-flops 에 attribute을 추가할 것을 권장합니다. 이것은 도구가 이러한 flip-flops에서 조작하는 것을 방지합니다. 또한 도구가 다음 flip-flop와 동일한 slice 에 metastability guard를 배치하도록 권장하므로 routing은 가능한 한 짧습니다.
예를 들어 Vivado 에는 이름이 ASYNC_REG인 attribute이 있습니다. 따라서 이전과 마찬가지로 모든 metastability guard registers 에 *_metaguard 접미사가 있는 경우 XDC 파일의 이 행은 필요에 따라 attribute을 설정합니다.
set_property ASYNC_REG true [get_cells -hier -filter {name=~*_metaguard*}]
Verilog 코드 내부에 이 attribute을 설정할 수도 있습니다.
그러나 이 attribute은 어떤 차이도 만들지 않을 것입니다. 왜냐하면 도구는 일반적으로 어쨌든 metastability guards를 올바르게 처리하기 때문입니다.
이것으로 이 시리즈 의 두 번째 페이지를 마칩니다. 다음 페이지 는 clock domains를 통해 데이터를 전달하는 기술을 보여줍니다.