01signal.com

데이터가 있는Clock domain crossing

이 페이지는 clock domains에 대한 세 페이지 시리즈의 마지막 페이지입니다.

하나의 bit이 부족할 때

종종 clock domains를 통과하는 데 필요한 신호는 단일 bit이 아니라 데이터 워드입니다. 이 경우의 간단한 솔루션은 이미 제안된 대로 FPGA공급업체에서 제공하는 dual-clock FIFO 입니다. 그러나 때로는 이것이 옵션이 아닙니다. 게다가 누군가는 과거에 그 FIFO를 구현해야 했습니다.

따라서 목표는 vector signal이 다른 clock domain에 올바르게 표시되도록 하는 것입니다. clock domain crossing이 그렇게 쉽지 않은 이유를 설명하기 위해 먼저 clock domain crossing에 대한 순진하고 잘못된 예부터 시작하겠습니다.

reg [7:0] foo, bar, bar_metaguard;

always @(posedge clk1)
  foo <= foo + 1;

always @(posedge clk2)
  begin
    bar_metaguard <= foo; // This will fail sometimes!
    bar <= bar_metaguard;
  end

이것은 이전 페이지 의 간단한 metastability guard 예제와 똑같지만 registers는 8-bit vectors가 고 @foo는 '0' 와 '1'사이를 변경하는 대신 counter 입니다.

왜 이것이 잘못된 것입니까? 문제는 @foo 에서 @bar_metaguard로의 paths 간의 routing delays 의 차이점입니다. 8개의 bits는 각각 다른 delay을 가지고 있습니다. @foo가 변경되면 이러한 bits 의 변경 사항 중 일부는 합법적인 timing 와 함께 @bar_metaguard의 flip-flops에 도착할 수 있고 나머지는 제때 도착하지 않을 수 있습니다.

따라서 @bar_metaguard를 구성하는 8개의 flip-flops 중 어느 것에도 metastability가 없더라도 @foo가 변경되는 상황이 있을 수 있으며, @bar_metaguard 의 bits 중 일부만 새 값을 얻고 나머지는 이전 값으로 유지됩니다. 따라서 @foo가 0xff 에서 0x00로 변경되면 @bar_metaguard 의 다음 값은 무엇이든 될 수 있습니다. 일부 bits는 변경 전 @foo의 값을 얻었고 나머지는 변경 후 bits 값을 얻었기 때문입니다. 이 잘못된 값은 @clk2의 clock cycle 이후 @bar 에서 볼 수 있습니다.

이 문제를 해결하려면 먼저 필요성을 정의해야 합니다. @bar는 항상 유효한 값을 포함해야 합니까, 아니면 때때로 한 clock domain 에서 다른 clock domain 로 정보를 전달하기 위한 것입니까? 이 두 가지 옵션에 대해 별도로 설명하겠습니다.

옵션 1: 연속 샘플링

대상 단어(예제에서@bar )가 다른 clock domain (@foo)에서 단어를 지속적으로 샘플링해야 하고 항상 합법적이고 의미 있는 값을 포함하는 경우 이를 보장하는 방법은 단 한 가지뿐입니다. 위에 표시된 clock domain crossing 에 대해 순진한 방법을 사용하되 @clk1의 각 clock cycle 에서 @foo의 bits 중 하나만 변경(또는 변경 없음)해야 합니다. 즉, vector signal와 함께 metastability guard를 사용하되 동일한 clock cycle에서 여러 bits가 변경될 때 문제가 발생하지 않도록 하십시오.

각 clock cycle에서 하나의 bit 만 변경할 수 있기 때문에 각 변경은 @bar_metaguard에서 샘플링되거나 누락되며 어느 쪽이든 @foo가 가지고 있던 값 중 하나를 반영합니다.

따라서 위의 예에서 @foo가 일반 binary code가 아닌 Gray code를 사용하는 counter 라면 완벽하게 작동합니다. Gray coding 의 본질은 단어가 카운트업될 때마다 bit이 하나만 변경되기 때문에 @bar는 항상 의미 있는 값을 전달하는 것이 보장된다는 것입니다.

하지만 @clk1이 @clk2보다 더 높은 주파수를 갖는다면 어떻게 될까요? @bar가 @foo의 값 중 일부를 건너뛰어도 상관없습니다. 예를 들어 @foo가 Gray code 형식의 카운터인 경우 @bar를 볼 때 일부 계산된 숫자를 건너뛸 수 있습니다. 그러나 @bar 에서 보이는 모든 값은 어느 시점에서 @foo 에서 나타났다는 점에서 정확합니다.

이 방법의 가장 일반적인 용도는 dual-clock FIFOs내부에서 Gray code를 사용하여 두 clock domains간에 FIFO의 RAM 에 있는 주소를 전송하는 데 사용됩니다. FIFO의 쓰기 쪽은 RAM 에 쓴 마지막 단어의 주소를 Gray code로 인코딩합니다. 인코딩된 단어는 단어에 metastability guards를 사용하여 다른 clock domain에 있는 읽기 측으로 전송됩니다. 다른 방향에서도 동일한 방법이 사용됩니다.

각 측은 상대방의 업데이트된 주소( metastability guards지연 후)를 알고 있기 때문에 각 측은 FIFO에 얼마나 많은 요소가 있는지 계산할 수 있으므로 empty 및 full와 같은 신호를 생성할 수 있습니다.

더 빠른 속도로 이벤트 전달

이전 페이지 에서 단일 bit이 있는 metastability guard는 소스 clock domain의 clock 주파수에 제한이 있음을 상기하십시오. 이 bit 의 각 변경 사항이 이벤트에 대해 상대방에게 알리는 방식이라면 이러한 이벤트가 자주 발생하면 수신측에서 이벤트를 놓칠 위험이 있습니다.

해결책은 clock domains에서 Gray code 로 인코딩된 counter를 전달하는 것입니다. 이런 식으로 수신측은 얼마나 많은 이벤트가 발생했는지 알고 있으므로 정보를 잃지 않습니다. 이 counter 의 bits 의 수는 이벤트가 @clk1의 모든 clock cycle 에서 발생하더라도 수신 측에서 여전히 얼마나 많은 이벤트가 발생했는지 추론할 수 있도록 선택됩니다.

따라서 이러한 의미에서 단일 bit보다 vector 로 작업하는 것이 더 쉬울 수 있습니다. 단일 bit이 변경되고 대상의 clock이 더 느리기 때문에 그 사실을 놓치면 결과는 아무 일도 일어나지 않았다는 사실을 놓치는 것입니다. 그러나 clock domains를 통해 올바르게 전송된 단어(예: Gray code)를 사용하면 정보가 손실되지 않습니다.

그리고 하나의 bit이 이 목적에 충분하다면 Gray code counter는 각 이벤트에서 값을 변경하는 단일 비트에 불과합니다. 즉, 단일 bit의 경우 Gray code counter 의 솔루션은 단순 metastability guard와 정확히 동일합니다.

paths의 타이밍에 대한 사소한 설명

이 섹션의 제목에서 알 수 있듯이 다음 섹션으로 건너뛰는 것이 좋습니다.

vector signals용 metastability guard 에 대한 기본 가정이 있습니다. 이러한 paths 의 delays 간 차이는 소스 clock의 clock cycle을 초과하지 않습니다.

이 가정은 특별한 조치를 취하지 않고도 거의 확실하게 충족되지만 여전히 다음 이론적인 예를 살펴보겠습니다. @clk1 의 주파수는 500 MHz가 고 @foo의 paths ~ @bar_metaguard 중 하나는 routing delay 의 1 ns가 있다고 가정해 보겠습니다. 또한 다른 path 에 4 ns의 routing delay이 있다고 가정해 보겠습니다. 물론 발생할 가능성은 극히 낮지만 어떤 일이 발생할 수 있는지 봅시다.

bits 중 하나가 그 가치를 바꾸고, 그 변화가 4 ns의 여정을 시작합니다. 다음 clock cycle, 2 ns 이후에는 다른 bit이 변경되어 1 ns시간 이후에 @bar_metaguard 에 도달합니다. 그러나 그것은 첫 번째 bit이 도착하기 전에 1 ns 입니다. 따라서 @bar_metaguard는 @foo가 가지고 있지 않은 값으로 전체 단어를 샘플링할 수 있습니다.

routing delays는 일반적으로 이 예보다 훨씬 짧기 때문에 실제로는 일어나지 않을 것으로 예상됩니다. 그럼에도 불구하고 이론적으로 모든 routing delay이 가능합니다. 이 가능성을 완전히 없애기 위해 다음과 같은 timing constraint를 사용할 수 있습니다( Vivado 형식으로 작성).

set_max_delay -datapath_only -from [ get_pins -hier -filter {name=~*/C} ] -to [ get_pins -hier -filter {name=~*_metaguard*/D} ] 1.5

이 constraint는 이전 페이지 에서 제공한 set_max_delay 와 유사합니다. 그러나 이전 페이지에서 metastability guard는 "-from" 부분에 있고 여기에서는 "-to" 부분에 있습니다. 따라서 constraints는 동일한 paths에 적용되지 않습니다. 이전 페이지에서 constraint 의 목적은 metastability guard가 metastability에서 복구할 시간을 주는 것이었습니다. 따라서 해당 constraint는 동일한 clock사이의 paths 에 적용됩니다. 반면 위의 constraint는 clock domain crossing 자체와 관련이 있습니다.

따라서 이 constraint는 다르게 작성됩니다. 관련 paths는 unrelated clocks의 clock domains를 연결하므로 이러한 clocks 의 skews 와 이러한 clocks 의 jitters를 고려하는 것은 의미가 없습니다. 이것은 -datapath_only 부분이 말하는 것입니다: clocks가 flip-flops에 도달하는 데 걸리는 시간은 신경쓰지 마십시오. path를 측정하십시오.

이 constraint를 혼란스럽게 만드는 것은 path가 소스 flip-flop의 clock pin 에서 시작하여 대상의 data input pin (D)에서 끝납니다. 따라서 스톱워치는 소스의 flip-flop이 clock을 가져올 때 시작되고 업데이트된 신호가 destination에 도착할 때 종료되며, 이는 setup time을 충족하는 데 필요합니다. 따라서 이 path 에는 양쪽의 타이밍 사양과 요구 사항이 모두 포함되어 있습니다.

이 timing constraint에서와 같이 이러한 모든 paths를 1.5 ns로 제한하면 path가 이 시간 제한을 초과할 수 없으므로 path delays 사이의 skew 도 이 수로 제한됩니다. 따라서 @clk1 에 2 ns의 clock period가 있더라도 paths가 잘못된 순서로 도착하는 것은 불가능합니다. 다시 한 번, 어쨌든 극히 가능성이 희박하지만 이것이 그것을 보장하는 방법입니다.

path ~ metastability guard가 false path constraint (예: set_false_paths 또는 set_clock_groups)의 영향을 받는 경우 set_max_delay은 영향을 미치지 않을 수 있습니다. false path constraint가 우선할 가능성이 높습니다. 따라서 도구가 constraints를 원하는 대로 해석하는지 확인하기 위해 항상 timing report에서 paths를 확인하십시오. timing에 대한 다른 페이지에서 이에 대해 설명합니다.

옵션 #2: register의 비정기적인 업데이트

각 clock cycle 에서 하나의 bit 만 변경할 수 있다는 제한은 종종 너무 제한적입니다. 데이터가 가끔 업데이트되면 다른 기술을 사용할 수 있습니다. 다음 예에서는 @do_update가 여러 clock cycles에서 한 번만 활성화(즉, 값 '1'을 가짐)한다고 가정합니다. 또한 이 register가 @foo 의 값이 @new_value로 업데이트되어야 함을 나타내는 데 사용된다고 가정해 보겠습니다.

reg [7:0] foo, bar;
reg       toggle, toggle_metaguard, toggle_a, toggle_b;
reg       new_value_bar;

always @(posedge clk1)
  if (do_update)
    begin
      foo <= new_value;
      toggle <= !toggle;
    end

always @(posedge clk2)
  begin
    toggle_metaguard <= toggle;
    toggle_a <= toggle_metaguard;
    toggle_b <= toggle_a;

    if (toggle_a != toggle_b)
      bar <= foo; // No metastability guard, because foo is stable
    new_bar <= (toggle_a != toggle_b); // Not necessary, just side info
  end

지금은 @new_bar를 무시하십시오. 나는 나중에 그것에 올 것이다.

작동 방식은 다음과 같습니다. @foo는 @do_update가 활성화된 경우에만 업데이트됩니다. 이 경우 @toggle은 동일한 clock cycle에서 반대 값으로 변경됩니다.

@clk2의 clock domain에서 @toggle_metaguard는 @toggle 의 값을 metastability guard로 가져옵니다. 다음 clock cycle에서 이 값은 @toggle_a로 복사됩니다. 그 후 clock cycle 에서는 @foo 의 값이 @bar로 직접 복사됩니다. 정확히 하나의 clock cycle동안 @toggle_a 와 @toggle_b가 서로 다른 값을 갖기 때문입니다.

@bar 와 @foo가 다른 clock domains 에 있다는 사실은 의미가 없습니다. @foo가 타이밍 요구 사항을 충족하기에 충분한 시간 이상 동안 안정적이기 때문입니다.

내가 왜 그렇게 확신합니까? 이번에는 타당한 이유가 있으며 다음과 같이 진행됩니다. 전체 절차는 @toggle이 변경했기 때문에 @toggle_metaguard가 값을 변경했을 때 시작됩니다. @bar가 동일한 @clk2 주기에서 @foo를 샘플링했다면 안전하지 않았을 것이지만 운이 좋았다면 괜찮았을 것입니다. 그러나 @toggle_metaguard의 새 값이 @toggle_a에 도달할 때까지 @clk2 의 또 다른 clock cycle이 있습니다. 그리고 @bar는 그때도 업데이트되지 않고 @clk2의 다음 clock cycle 에서만 업데이트됩니다.

따라서 @foo가 변경되는 순간부터 @foo가 @bar 에 의해 샘플링될 때까지 일정 기간이 있으며, 이는 @clk2의 clock cycles 두 개 이상에 해당합니다. 모든 flip-flop의 setup time와 비교하면 그것은 영원합니다. 즉, @toggle_metaguard의 이전 페이지에서 와 같이 set_max_delay을 적용하는 것이 합리적입니다. paths 에서 @bar로 동일한 작업을 수행할 수 있습니다. 비록 필요할 가능성은 거의 없지만 방금 언급한 영원성 때문에 그렇습니다.

이 방법의 아킬레스건은 @do_update가 @bar에 의해 샘플링될 때 @foo가 안정적으로 유지되도록 보장할 만큼 충분히 드물게 활성화되어야 한다는 것입니다. 이러한 업데이트 사이의 합리적인 최소 시간은 @clk2의 clock cycles 4개에 해당하는 시간입니다. 따라서 계산은 @clk1 의 clock cycles가 @clk2의 clock cycles 4개에 해당하고 가장 가까운 정수로 반올림하는 것입니다. @clk1이 @clk2 보다 4배 느리거나(또는 더 느리다면), 그것은 전혀 제한이 없습니다. 그렇지 않으면 @do_update가 허용된 것보다 더 자주 활성화되지 않도록 하는 메커니즘이 logic 에 있어야 합니다.

진실은 실제 designs에서 업데이트 속도가 매우 느릴 때 clock domains가 @toggle이 제공하는 종류의 보호 없이 부주의하게 교차되는 경우가 있다는 것입니다. 이렇게 하면 @foo가 @bar 로 계속 복사됩니다. @foo가 오랫동안 한 번 변경되면 @bar가 하나의 clock cycle동안 잘못된 값을 포함할 수 있지만 누가 신경을 쓰겠습니까? 종종 이 실수는 clock domains의 전체 문제를 무시한 결과입니다. 이봐, 작동하기 때문입니다. 그렇지 않을 때까지 가끔 .

조잡하다고 말하면 위의 예에서 @toggle 나 관련 registers 중 어느 것도 재설정되거나 초기 값이 할당되지 않는다는 점에 유의하십시오. synthesizer가 초기 값 0으로 모두 할당할 가능성이 높기 때문에 일반적으로 괜찮습니다. 그리고 이러한 registers가 처음에 동일한 값을 갖지 않더라도 @foo의 불필요한 샘플링이 한 번 발생하고 그 이상은 되지 않습니다. 그럼에도 불구하고 이러한 registers를 재설정 하는 것이 좋습니다.

고급 변형

지금까지 세 가지 간단한 예를 제시했습니다.

이러한 간단한 예는 몇 가지 다른 메커니즘의 기초입니다.

먼저 위의 예에서 @new_bar 에 대해 말하겠다고 약속했습니다. 따라서 @bar가 새로운 값을 가질 때 clock cycle중 하나가 높은 것은 register 일 뿐입니다. 특별한 점은 없지만 @bar 및 @new_bar는 다른 clock domain의 @foo 및 @do_update를 반영합니다. 따라서 이것은 clock domain을 통해 명령과 상태 메시지를 전달하는 방법입니다(가능한 경우 FIFO를 대신 사용해야 한다고 언급한 적이 있습니까?).

마지막 예제의 또 다른 흥미로운 확장은 다음과 같습니다. registers, @foo 및 @bar쌍 대신 dual port RAM을 넣으십시오. 이것은 clock domains를 통해 buffers 의 데이터를 전달하는 방법입니다. @clk1 의 clock domain 에 있는 logic이 RAM에 데이터를 쓰고 얼마 후 이 RAM 의 절반을 채운다고 가정합니다. logic이 RAM의 후반부를 채우면서 @toggle의 값을 변경합니다. 이 register는 위에 표시된 대로 정확히 @clk2의 clock domain 에 복사됩니다. 그러나 예제와 같이 @bar를 업데이트하는 대신 logic은 RAM의 전반부에 있는 데이터를 소비합니다.

이것이 이 간단한 register가 double-buffer 메커니즘을 동기화하는 방법입니다. 한쪽은 RAM 에서 데이터를 읽고 다른 쪽은 이 RAM에서 데이터를 읽습니다. 사실, @toggle 의 역할은 값을 변경하는 것뿐만 아니라 현재 RAM 의 어느 절반에 쓰여지고 있는지 상대방에게 알려줍니다.

그러나 가능하면 FIFO를 사용하는 것이 가장 좋습니다. 이 double-buffer 메커니즘이 매력적으로 들릴 수 있지만 더 나은 대안이 없을 때만 사용해야 합니다. 예를 들어, RAM 의 데이터를 읽는 순서와 데이터를 쓰는 순서가 다른 경우입니다.

요약

결국 이렇습니다. unrelated clocks의 clock domains 간의 전환에는 항상 resynchronization logic이 포함됩니다. 이 resynchronization을 전달하는 데이터 워드는 제한되어 있으므로 하나의 bit 만 소스의 clock (예제에서는@clk1 )의 각 clock cycle 에서 값을 변경할 수 있습니다. 그렇지 않으면 잘못된 데이터가 목적지에 도착할 수 있습니다.

일부 응용 프로그램에서는 이것으로 충분하지만 이 제한이 너무 제한적이면 데이터 자체에 resynchronization logic을 사용하지 않고 vector register가 있는 clock domains 또는 RAM을 통해 데이터를 대신 이동할 수 있습니다. 이것은 데이터의 쓰기 작업과 읽기 작업 사이에 최소한의 시간 간격을 유지하는 logic 덕분에 작동합니다. 이 시간 간격은 데이터 워드가 대상에서 샘플링될 때 안정적인지 확인합니다. 그럼에도 불구하고 이 logic은 clock domain crossing와 동일한 기술을 기반으로 합니다. 따라서 이 솔루션에는 resynchronization logic이 포함되며, 이는 Gray code를 사용하여 한 번에 하나의 bit을 변경하는 것으로 제한됩니다.

따라서 resynchronization logic 와 이 규칙 하나의 bit은 unrelated clocks가 관련될 때 항상 존재합니다. 그것들이 어떻게 적용되느냐의 문제일 뿐입니다.

이 페이지는 영어에서 자동으로 번역됩니다. 불분명한 사항이 있으면 원본 페이지를 참조하십시오.
Copyright © 2021-2024. All rights reserved. (6f913017)