https://insoobaik.tistory.com/676
FIFO 구조 및 동작 원리 (1)에 이어서 FIFO 사용에 필요한 Asynchronous, CDC, Metastability, Synchronizer, GrayCounter에 대한 내용을 작성해 볼 것이다.
이전에 말했듯이 SoC 내부는 여러 Clock Domain을 가지고 있다. 서로 다른 Clock Domain이 Data를 주고 받는 것은 Clock Domain Crossing라고 부르고 줄여서 CDC라고 부른다.
CDC
Clock Domain Crossing
서로 다른 클록 도메인 간의 신호 전달을 의미한다.
위 그림과 같이 위 FF은 clk_A 하나의 클럭에 동기화 되어 있기 때문에 각 Domain에 대한 성능이 동일하다. 같은 Clock을 사용하기 때문에 Setup / Hold를 계산하기 용이하다.
하지만 SoC 내부는 아래 그림과 같이 각 Domain마다 서로 다른 Clock을 사용한다. 각 Domain마다 성능이 다르고 요구하는 Clock이 다르기 때문이다.
각 Domain별로 서로 다른 Clock을 사용하여 작업을 수행하는 것은 문제가 되지 않지만 아래 그림과 같이 서로 다른 Clock을 가진 Domain끼리 Data를 주고 받을 때 문제가 발생할 수 있다.
Metastability
Metastability는 디지털 회로에서 발생할 수 있는 불안정한 상태를 말한다. 클록 신호에 동기화된 회로에서 신호가 올바르게 결졍되지 못하고, 일정 시간 동안 중간 상태에 머무는 현상을 의미한다.
위 그림은 Clock이 다른 두개의 Domain이 데이터를 주고 받는 그림이다.
위 그림에서 data 신호가 High에서 Low로 떨어지는 중간에 clk_B의 상승 Edge가 동작하고 있다.
High에서 Low 떨어지는 구간은 신호가 정확히 0, 1이 아니기 때문에 제대로된 신호가 전달되지 않아 dout의 신호처럼 불안정한 신호가 전달될 수 있다.
위 그림의 경우 High에서 Low 떨어지는 순간이였고, 결과적으로 Low 신호를 전달하기 때문에 처음에 의도한 신호가 전달되겠지만
위 그림과 같이 Low에서 High로 신호가 변하는 순간 Clock Edge가 동작하게 되면 High 신호를 유지해야 하지만 Low 신호를 전달하게 되는 경우가 발생할 수 있다.
Synchronizer
위의 Metastability를 해결하기 위한 방법 중 Synchronizer 기술이 있다.
D Flip Flop을 Metastability가 발생하는 구간에 하나 더 추가하는 방법이다.
위 그림과 같이 clk_A에 의해 전달되는 data_A를 전달받는 clk_B Domain의 첫번째 FF는 metastability가 발생할 수 있다.
하지만 metastability가 발생한 data_B 신호는 이내 High 또는 Low 신호로 확정 지어질 것이고, dout의 신호는 항상 High, Low 둘 중 하나의 확실한 신호만 전달 받아 출력하게 된다.
!!!!!!!
* 위 Synchronizer같은 경우 dout을 통해 불안정한 신호가 나오지 않는 부분은 해결되었지만 data_A의 신호가 clk_B보다 짧게 전달될 경우 dout의 신호는 Domain A에서 보낸 신호를 감지하지 못한채 이전 신호를 계속해서 전달할 수 있다.
위 그림에서도 data_A는 2번의 1의 값을 보냈지만 dout에서는 data_A의 High 구간에도 0의 신호를 내보내고 있는 것을 확인할 수 있다
data가 전달되지 않는 상황을 방지하기 위해 Domain A와 Domain B 사이에 전달되는 Data는 Domain B Clock 주기의 1.5배 이상 Pulse를 유지하도록 하면 해결된다.
Pulse를 1.5배 이상 보내게 되면 첫번째 Clock에서는 metastability가 발생할 수 있지만 두번째 Clock에서는 확정된 신호를 전달하여 최종적으로 dout에서는 data_A의 신호를 안정적으로 내보낼 수 있다.
(위 방법은 간단하지만 data 전달 Pulse Width를 조절해줘야 하기 때문에 지켜지기 쉽지 않다. 이를 해결하기 위한 Feedback 방식이 있는데 훨씬 복잡한 방법이기 때문에 추후에 알아보도록 하겠다.)
Asynchronous FIFO / Gray Counter
처음 FIFO 얘기로 돌아가서 결국 FIFO Buffer를 통해 Domain A에서 Domain B에 데이터를 보낼때도 둘의 Clock 속도 다르다.
각 Domain의 Clock 속도에 따라 FIFO Buffer에 데이터가 Write, Read되고, 전달 받는 Domain의 경우 Synchronizer를 사용하여 안정된 신호를 전달하도록 해야 한다.
Synchronizer를 통해 Data를 보내는 것까지 좋지만 Domain A와 Domain B는 각각의 Clock 맞춰 동작하기 때문에 Buffer의 Write, Read의 위치를 나타내는 역할을 하는 Pointer 기능이 필요하다. Write Pointer, Read Pointer의 위치를 지정하게 되면 비동기 상태에서 각 Domain은 Pointer 위치만 보고 Buffer의 Data를 Write, Read하면 된다.
위 그림과 같이 각 Domain은 Pointer Write, Read가 있다. 처음 Write, Read 전부 00 위치를 가르키고 있다.
1. Write 작업이 일어나면 Write Pointer는 01로 이동하고, Read 작업은 일어나지 않았기 때문에 00 위치를 그대로 가르키고 있다.
2. Write 작업과 Read 작업이 둘 다 일어나게 되면 Write Pointer는 10으로 이동하고, Read Pointer는 01로 이동하게 되는 방식으로 Buffer의 위치에 값을 Write하거나 Read하게 된다.
Gray Counter
디지털 세계에서는 일반적으로 Binary(이진)법을 사용하기 때문에 4bit 기준 0000, 0001, 0010, 0011, 0100와 같이 숫자가 커진다. FIFO는 순서가 중요하고 하나씩 순차적으로 Push, Pop이 이루어진다.
그런데 현재 FIFO Buffer는 Clock이 다른 2개의 Domain에서 Data를 Write, Read하고 있다. 이때 0011(3), 0100(4)와 같이 Pointer의 위치가 하나 이동해야 하지만 실제 bit는 3개가 바뀌는 상황이 일어날 때가 있다. 이 때 3개의 비트가 전부 바뀐 상태가 아닌 2개의 비트만 바뀐 상태가 전달되면 0011(3) -> 0000(0)과 같이 순서가 어긋나는 상황이 발생할 수 있다. 이는 순서가 아예 틀어지는 것이기 때문에 기능에 있어서 엄청난 오류를 발생할 수 있다.
이를 해결하기 위한 방법이 Gray Counter 방식이다.
카르노 맵에서도 사용되는 Gray Counter는 디지털 회로 설계에서 주로 사용되는 카운터 유형으로, 다음 상태로 전이할 때 이진수의 한 비트만 변경되는 특성을 가지고 있다.
한 비트씩 전이하기 때문에 전이 과정에서의 오류를 줄이고, 메모리의 임시 데이터가 부정확해지는 현상을 방지할 수 있다.
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
0000 | 0001 | 0011 | 0010 | 0110 | 0111 | 0101 | 0100 | 1100 | 1101 |
위 표와 같이 4bit를 예로 들었을 때 4bit의 숫자가 커질때마다 4bit 중 하나의 비트만 0 -> 1, 1 -> 0으로 변하는 것을 확인할 수 있다.
이러한 방식으로 카운터를 하게 되면 Binary 방식의 카운터에서 3비트가 한번에 바뀌어야 하는 일이 발생하지 않아 pointer data 전달에 있어 안정적이다.
Pointer를 지정하기 위해 FIFO Buffer의 크기만큼의 Counter만 필요하겠지만 FIFO Buffer의 Full과 Empty 상황을 구분하기 위해서 FIFO Buffer + 1 bit의 크기로 만들어야 한다.
FIFO Buffer의 크기와 Counter의 크키가 같을 경우 위 그림과 같이 Write, Read 둘 다 00을 지정하고 있을 때 현재 FIFO가 Full인지 Empty인지 알 수 있는 방법이 없다.
* Gray Code, Binary 사용하여 해결
FIFO Buffer의 크기를 2bit / Counter는 FIFO Buffer 크기 + 1 3bit를 예시로 들겠다. (추가로 Binary 값을 Gary Code로 변환하는 알고리즘을 사용하여 변환해야 한다. -> 시프트 레지스터를 사용하면 간단하게 구현할 수 있다.)
우선 가장 기본적으로 Full, Empty의 기준은 Write, Read Pointer의 위치가 동일할 때 발생한다. 하지만 Pointer 위치가 동일 할 때 Full인지 Empty인지 구분할 수 없는 것이 문제였다. 그 해결 방법을 아래 설명하겠다.
FIFO Buffer의 위치 값은 Counter 값의 하위 2bit를 사용하게 된다.
Counter의 경우 3bit이기 때문에 0~7의 값이 반복되지만 하위 2bit는 위 그림 파란 네모를 보게되면 0~3의 값을 반복하는 것을 확인할 수 있다. (00 01 10 11 -> 00 01 10 11를 반복하기 때문에 해당 FIFO의 순서대로 값을 Write, Read 할 수 있다.)
하지만 Write, Read Pointer의 경우 Data 안정성을 위하여 Binary 값이 아닌 Gray Code 값을 사용하기로 했다.
Gray Code를 사용하기만 하면 문제가 해결되는 것 같지만 추가적인 문제가 하나 더 발생한다.
Binary Code처럼 00 01 10 11 다음 다시 00으로 돌아가는 것이 아닌 별도의 규칙성을 찾아
(1). 0의 Gray Code(000)와 4의 Gray Code(110)가 동일한 위치임을 증명해야 하고,
(2) 위치가 같지만 한바퀴를 돌아 같은 위치인지(Full) / 한바퀴를 돌지 않고 같은 위치인지(Empty)를 구분해야 한다.
위 그림처럼 3bit Counter에서 하위 2bit는 Binary값일 때 Buffer의 주소 값으로 사용되어 00 01 10 11 00 이 순서대로 반복되는 것을 볼 수 있다.
Gray Code의 경우 0 <-> 4 / 1 <-> 5 / 2 <-> 6 / 3 <-> 7 의 값이 메모리상 서로 같은 위치지만 서로 바퀴수가 다른 것을 증명해야 한다.
위 그림의 빨간색 부분처럼 상위 2비트가 서로 반전되어 있는 것을 볼 수 있다.
즉, 상위 2비트가 반전되어 있고, 하위 1 비트가 동일한 경우 같은 위치지만 바퀴 수가 다른 경우인 것을 알 수 있다.
Full = 상위 2비트 반전되어 있지만, 하위 1비트가 동일한 경우
Empty = 상위 2비트도 같고, 하위 1비트도 동일한 경우
위 방식을 통해 FIFO Buffer의 서로 다른 Clock을 Domain이 Pointer를 이용하여 Buffer의 Data를 Write, Read 할 수 있고, Buffer보다 + 1 크기의 Counter를 이용하여 Full, Empty를 구분하여 Data를 Write를 수행, 정지 / Read를 수행 정지 시킬 수 있게 된다.
'Semiconductor, Embedded > 0. Digital, Analog, 회로 이론' 카테고리의 다른 글
AMBA - AXI 이론편 (0) | 2024.09.04 |
---|---|
AMBA - AMBA 이론편 (0) | 2024.09.04 |
FIFO - 구조 및 동작 원리 (1) (0) | 2024.08.20 |
CPU 구조 및 동작 원리 (RISC, Pipeline, Hazard) (2) (1) | 2024.08.15 |
I2C 구조 및 동작 원리 (0) | 2024.08.14 |