강의

멘토링

커뮤니티

인프런 커뮤니티 질문&답변

rnjstns0721님의 프로필 이미지
rnjstns0721

작성한 질문수

디지털 회로설계 실무 : Computer Architecture 와 SoC 프로토콜 Digital IP 설계하기

아두이노 좀 다뤄보셨나요? Chip-to-Chip 통신을 위한 Serial Interface : I2C + SPI 통신 Protocol 설계하기

I2C SCL_Synched, SDA_Synched 질문

작성

·

29

0

image.png

안녕하세요 코드를 보다 의문점이 들어서 질문 드립니다. input으로 들어오는 SCL 을 그대로 사용하는게 아니라 3단 F/F을 통해 slave 쪽의 clk에 맞춰서 SCL_posedge, SCL_negedge를 사용함으로써 동기화를 하여 Slave의 메인 clk에 맞춰 데이터를 채갈 수 있도록 하는 것은 이해했습니다! 근데 SCL_posedge 및 SCL_negedge 의 경우 '안정화 된' [2:1] 세번째, 두번째 F/F의 결과를 보고 posedge 및 negedge를 출력하기에 SCL은 안정화 된 값을 가지는 것을 이해하엿으나

SDA_synched의 경우 [2:0] 총 3개의 F/F 에 대해 AND 를 취한 결과를 사용하고 있습니다. 이렇게 하게 되면 만약 최악의 경우

SCL_posedge가 '1'이 되었을때

data_in 에다가 SDA_synched의 값을 넣어야 하는데

SCL_posedge가 1이됨과 동시에 SDA_syncehd[2], SDA_syncehd[1] 이 모두 1이고 SDA_synched[0] 이 0에서 1로 바뀌는 중이라면 결국 data_in에 무엇을 저장해야 할 지 몰라서 meta stable 한 상태에 빠질것이라고 생각됩니다.

이를 방지하려면,

wire SDA_synched = SDASynch[2] & SDASynch[1] 로 선언해서 사용해야 하는 것 아닌가요?? 감사합니다.

답변 1

0

안녕하세요, 답변 남겨드립니다.

 

1. 이 코드에서 값이 언제 / 어떻게 보이는지

핵심 포인트 하나만 잡고 가면 됩니다:

always @(posedge clk)
    SCLSynch <= {SCLSynch[1:0], SCL};

always @(posedge clk)
    SDASynch <= {SDASynch[1:0], SDA};

여기서 <=논블로킹 할당이라서,

  • posedge clk 순간에

    • 레지스터 내부 값은 새 값으로 캡처되지만,

    • 클럭에서 조합논리(wire) 가 보는 값은 직전 클럭에 있던 값입니다.

즉,

  • SCL_posedge 는 “직전 클럭까지의 SCLSynch[2:1]”을 보고 계산되고,

  • SDA_synched 도 “직전 클럭까지의 SDASynch[2:0]”을 보고 계산됩니다.

  • 그리고 상태머신이나 data_in 레지스터는 그 두 신호를 보고 같은 posedge clk 에서 동작합니다.

그래서 질문하신 것처럼

“SCL_posedge가 1이 되는 바로 그 순간 SDASynch[0]이 0→1로 바뀌는 중이라서 둘이 섞여서 메타가 되는 것 아닌가요?”

라는 상황은 시간축 상으로 동시에 관측되지 않습니다.

  • SCL_posedge == 1 이라는 사실은 “한 클럭 이전까지 이미 결정돼 있던 SCLSynch[2:1]의 패턴” 때문이고,

  • 이번 클럭에서 막 metastable 이 되는 건 SCLSynchSDASynch의 “새 값”인데,

  • 그 “새 값”은 다음 클럭에서야 SCL_posedge / SDA_synched 계산에 쓰입니다.


2. metastability 자체는 어디서 생기고 어떻게 처리되나

진짜 메타가 생길 수 있는 곳은 여기뿐입니다:

always @(posedge clk)
    SDASynch[0] <= SDA;   // 비동기 입력을 첫 FF가 샘플링
  • SDA가 clk의 setup/hold 타이밍 근처에서 바뀌면 SDASynch[0]은 metastable 이 될 수 있습니다.

  • 하지만 한 클럭 주기 동안 시간이 지나면서 대부분 0 또는 1로 수렴하고,

  • 다음 클럭에서 SDASynch[1]가 그 값을 받고, 또 그 다음 클럭에서 SDASynch[2]가 받습니다.

그래서:

  • “아날로그적으로 애매한 중간값”이 조합로직을 타고 data_in까지 그대로 퍼지는 구조는 아니고,

  • 결국은 0 또는 1로 결정된 값만 논리 AND에 들어갑니다.

  • 문제가 될 수 있는 건 “언제 샘플링했느냐(타이밍)”이지,
    data_in이 ‘메타 상태 그 자체’를 받는 건 아닙니다.

3단 동기화 체인을 쓰는 이유는

  • metastability가 다음 스테이지까지 살아남을 확률을 쭉 떨어뜨리고,

  • 동시에 아주 짧은 글리치/스파이크도 여러 클럭 동안 반복되지 못하게 해서
    노이즈 필터 역할도 하려는 겁니다.


3. SCL_posedge 의 타이밍을 말로 풀어보기

SCL이 실제 버스에서 0에서 1로 올라갔다고 생각해봅시다.

SCLSynch는 매 클럭마다 오른쪽에서 SCL을 하나씩 밀어넣는 구조라서,
클럭이 지날 때마다 대략 이런 식으로 변합니다 (숫자 대신 말로 설명):

  1. 처음에는 SCLSynch가 예를 들어 000 이었다고 합시다. (SCL도 0)

  2. 버스에서 SCL이 1로 바뀐다.

  3. 다음 clk 엣지에서 SCLSynch001 이 된다.
    이때 상위 두 비트는 00 이므로 SCL_posedge는 아직 0.

  4. 그 다음 clk 엣지에서 SCLSynch011 이 된다.
    이제 상위 두 비트 2:101 패턴이므로, 이 클럭에서 SCL_posedge가 1이 된다.

  5. 또 한 번 지나면 SCLSynch111 이 되고, 상위 두 비트는 11 이므로 다시 SCL_posedge는 0.

즉:

  • 실제 SCL이 1이 된 뒤, 최소 두 번의 clk를 거쳐야만 SCL_posedge가 1로 올라옵니다.

  • I²C 규격상 SDA는 SCL rising 전에 어느 정도 setup time을 가져야 하기 때문에,
    내부 clk 기준으로 보면 우리가 데이터를 샘플하는 시점(SCL_posedge==1)에는 SDA가 굉장히 오래 전에 이미 안정적이었어야 합니다.


4. SDA_synched = [2] & [1] & [0] 이 의미하는 것

SDA도 똑같은 식으로 밀어 넣습니다.

SDA가 0에서 1로 바뀌었다고 해볼게요.

  1. 처음에는 SDASynch000.

  2. SDA가 1로 바뀐다.

  3. 첫 번째 clk 이후: 001.
    세 비트 AND는 아직 0.

  4. 두 번째 clk 이후: 011.
    세 비트 AND는 아직 0.

  5. 세 번째 clk 이후: 111.
    이때 비로소 세 비트 AND가 1이 된다.

즉,

  • SDASynch[2] & SDASynch[1] & SDASynch[0] 이 1이 되려면
    SDA가 최소 3클럭 동안 연속으로 1 이어야 합니다.

질문에서 제안하신

wire SDA_synched = SDASynch[2] & SDASynch[1];

로 바꾸면,

  • SDA가 1로 바뀌고 2클럭 연속 1일 때 1이 됩니다.

  • 그러니까 한 클럭 더 빨리 반응하는 대신, 필터링은 조금 약해집니다.

metastability 관점에서는

  • 둘 다 “이전 클럭까지의 레지스터 값”을 보기 때문에

  • 어떤 쪽도 “막 메타가 된 비트와 조합돼서 알 수 없는 상태로 가는” 위험성은 비슷합니다.

  • 차이는 “몇 클럭 연속 같은 값이어야 신뢰하겠냐” 라는 필터 강도입니다.


5. SCL_posedge 와 SDA_synched 을 같이 쓰는 순간

일반적인 슬레이브 수신부는 보통 이렇게 씁니다:

always @(posedge clk) begin
    if (SCL_posedge)
        data_in <= {data_in[6:0], SDA_synched};
end

이때도

  • SCL_posedgeSDA_synched 모두
    이번 클럭에서 갱신되기 “직전”의 SCLSynch/SDASynch 값에 의해 결정됩니다.

  • 이번 클럭에서 막 metastable 이 된 SDASynch[0]의 상태는
    아직 SDA_synched 계산에 사용되지 않습니다.
    그건 다음 클럭에서야 반영됩니다.

그래서 “SCL_posedge==1 이 되는 그 클럭에서 SDA_synched AND 안에 metastable 비트가 끼어들어 와서 data_in이 메타 상태로 가는” 시나리오는
설계 구조상 성립하지 않습니다.

rnjstns0721님의 프로필 이미지
rnjstns0721
질문자

친절한답변 덕분에 이해가 갔습니다. 감사합니다!!

rnjstns0721님의 프로필 이미지
rnjstns0721

작성한 질문수

질문하기