<< 디지탈 회로에서의 크럭 skew 문제 >>

아주 기본적인 내용이지만 디지탈 회로에서 클럭이 어떻게 사용되는지 아주 기본적인 사항을 잘 모르고 계신 분들이 가끔 보이더군요. (물론 대부분의 사람들은 알고 있지만, 옛날에 공부를 하신 분들이나 젊은 사람들 중에도 실무에 관심이 없이 공부한 사람들은 잘 모르는 것 같습니다.) 이런 내용을 설명해야 하는 상황이 여러 번 있었기 때문에 이곳에 글로 올려 둡니다. 도움이 되시길..
디지탈 회로는 일반적으로 아래의 그림과 같이 modeling할 수 있습니다.(원래는 state machine을 설명할 때 쓰는 그림이지만 모든 디지탈 회로의 원리와 같습니다.)



<그림1. 디지탈 회로>(그림이 뜰 때까지 시간이 걸릴 수 있습니다.)


디지탈 회로는 외부와의 사이에 입력신호와 출력신호가 있습니다. 조합회로 글자 그대로 AND-OR 등 조합을 나타내고 (입력에 따라 출력이 따라서 바뀝니다.약간의 시간지연과 함께), 레지스터들은 모든 '값을 저장하고 있는' -레지스터, 래치 .. 카운터들이나 state 값들도 모두 register들입니다.- 것들을 말합니다. 그리고 클럭이 0에서 1로 올라가는 순간에 각 레지스터들은 자신의 입력에 준비되어 있는 값에 따라 출력값을 바꾸게 됩니다. 단 모든 레지스터들의 클럭입력은 모두 동시에 올라가고 내려간다고 가정합니다.(아주 중요함!! 올라가는 순간의 시간적인 차이가 너무 작아서 무시할 정도라는 것입니다. 만약 이 올라가는 시간이 레지스터마다 서로 조금씩 다르다고 하면 skew가 있다고 말합니다. 올라가는 시점이 비틀어졌다, 어긋났다 그런 뜻이지요.) 매번 클럭이 tic 할 때(0에서 1로 올라갈 때) 이 레지스터들의 값이 바뀌게 되는데 각 레지스터들의 클럭이 튄 후의 값들은 클럭이 튀기 전의 입력신호와 레지스터 값에 의해 정해집니다. 그러니까 레지스터들의 next 값은 레지스터들의 current 값과 입력신호들의 current 값에 의해 정해집니다. 많은 경우에 자기 자신의 현재값이 자신의 다음값을 결정하는데 사용되기도 합니다.
그러니까 현재의 레지스터값들과 입력신호들의 값에 따라 계산된 결과에 의해 모든 레지스터 입력신호에 어떤 값이 계산되어 준비된 상태에 있다가 클럭이 한 번 튀면 그 값들이 레지스터에 새로 저장되고 그러면 모든 레지스터의 값들이 변했으므로 그 변화의 여파가 그 때의 새로운 입력신호와 함께 다시 combinational logic을 거쳐서 어느 정도 짧은 시간(gate delay + wire delay : 보통 클럭 주기보다는 짧아야 합니다.)이 지나면 다시 모든 레지스터들의 입력에 update되어 대기하고 있게 되고, 다시 다음 클럭이 튀면 모든 레지스터가 새로운 값으로 바뀌고, 다시 그 변화가 조합회로를 거쳐서 레지스터 입력에 변화로 나타나고,.. 다시 클럭이 튀고,.. 이런 식으로 레지스터의 값들이 바뀌는 것입니다. 물론 입력신호도 클럭에 맞춰서 바뀌는 것입니다. 출력신호는 레지스터에서 곧바로 나갈 수도 있고 또는 입력신호와 레지스터의 조합으로 출력신호가 만들어질 수도 있으며 그냥 입력신호들의 조합으로만 만들어질 수도 있습니다. (여기서 레지스터로 쳐서 만든 신호는 glitch가 없는 신호가 됩니다. 조합회로의 출력은 당연히 glitch가 있지만 같은 클럭에 연결된 레지스터 사이에 주고 받는 경우에는 glitch가 있더라도 클럭 edge직전까지는 settle되어 안정된 값에 머무르게 되므로 문제가 없습니다. 단!! 어떤 레지스터의 asynch reset이나 set으로 사용될 신호는 glitch가 있으면 안되겠지요? 또는 다른 클럭에 동기되어 오는 신호를 곧바로 조합회로에 시간지연에 의해 false 값이 쳐지게(registered) 되어 문제가 발생하기 때문에 특별한 처리가 필요합니다. 보통 클럭 경계에서는 registere된 신호를 주고 받아야 하고 받는 쪽에서는 synchronize한 후 사용하거나 flag등을 통한 handshaking, 또는 천이검출 등을 통해 정보를 주고 받습니다.)
보통 디지탈 하드웨어 설계를 할 때는 "각 레지스터들이 현재의 값과 입력신호에 따라 어떤 값들로 바뀌어야 하는가"를 기술해(describe)주는 식으로 정의해 주게 됩니다. 그러니까 RTL(Register Transfer Level) 이라는 말은 여기서 나온 것이지요. 거의 99%의 설계가 이런 RTL로 이루어집니다. 최근에는 behavioral compiler라는 것이 있어서 첫번째 클럭에 이렇게 하고 다음 클럭에 이렇게하고 .. 하고 기술해 줄 수도 있지만 거의 사용되지 않고 있습니다.
그럼 여기서 이상한 질문이 나오는 경우가 있습니다. -- 제가 이 글을 쓰는 이유입니다.
레지스터의 값들이 바뀌는데 그 값들이 바뀌고 있는데 그 값을 클럭으로 치게 되면 위험하지 않습니까? 그 값이 클럭의 rising edge의 앞과 뒤에서 유지되고 있어야 하는데 rising edge의 바로 뒤에 각 레지스터의 입력값이 바뀌게 되는데도 문제가 없습니까? 라는 질문입니다. 어떤 사람은 이런 것이 불안해서 negative edge로 한 번 쳐 주고 난 후에 rising edge로 치도록 해 두기도 합니다. 그러나 일반적으로 디지탈 회로에서 앞아서 설명한 대로 클럭이 동시에 올라간다고 보기 때문에 그런 걱정은 하지 않아도 됩니다. 그 바뀐 영향이 레지스터 입력에 도착했을 때는 이미 클럭의 rising edge가 지나간 다음이지요. ASIC이건 FPGA건 이 클럭이 skew가 없도록 하는 것은 보장이 되어 있습니다. 이 클럭은 보통신호가 아니고 아주 특별하게 처리됩니다. ASIC의 경우에는 layout하는 엔지니어가 아주 높은 fan-out에서도 skew가 없도록 클럭을 배치해 주고요--물론 CAD software를 써서 하는데 BCT(balanced clock tree)라는 방식으로 clock을 배치해 줍니다. FPGA의 경우에는 특별히 클럭 network가 몇 개 준비되어 있고 이 network을 클럭으로 사용해야 합니다.
만약 clock에 skew가 있으면 어떻게 될까요? 예를 들어 설명하겠습니다.



<그림 2> clock skew가 있을 때의 문제(그림이 뜰 때까지 시간이 걸릴 수 있습니다.)

위의 그림에서 보듯이 처음에 각 F/F(flip-flop)의 값이 A,B,C와 같이 있었다고 합시다. 만약 모든 F/F에 들어가는 클럭이 동시에 올라간다고 하면 클럭이 한 번 튀었을 때 새로운 값은 한칸씩 shift되어 있어야 합니다. 그런데 만약 위의 그림에서 두번째 F/F에 들어가는 클럭신호만 약간 늦게 들어갔다고 합시다. (보통 wire의 delay나 fan-out차이로 그런 일이 벌어질 수 있습니다. 앞에서 설명한 대로 ASIC이나 FPGA 내부의 진짜 클럭은 그런 문제가 없도록 보장이 됩니다.) 이런 상황에서는 f1의 값은 클럭이 오면 자신의 입력값인 B로 되어야 하지만 자신의 입력값을 제공하는 F/F f0의 값이 약간 앞서서 A로 되어 버리기 때문에 새로 바뀐 값 A를 치게 되어 결국 A,B,C가 되지 않고 A,A,C가 되어 버립니다. 이렇게 skew가 있으면 아주 기본적인 것 조차 동작하지 않습니다. 생각해 보시면 알겠지만 어떤 레지스터의 값을 다른 레지스터가 받는다고 했을 때 '받는' 레지스터의 클럭이 '보내는' 레지스터의 클럭보다 늦으면 이 문제가 발생합니다. 차라리 레지스터 사이의 combinational logic이나 wire에서 delay가 어느 정도 있으면 (받는 레지스터의 setup 타임보다 큰 값으로) 이 문제가 차라리 없어지게 됩니다.(ASIC을 만들 때 chip의 공정이 제대로 이루어졌는지 확인하는 Scan Test를 할 때 이렇게 클럭의 위상관계가 확실하지 않을 경우에는 clock domain boundary마다 자동적으로 data lock up latch를 삽입하여 이런 문제를 없앱니다. 실제 설계에도 사용할 수 있는 방법이구요.)
이런 skew문제는 보통 chip속에서는 벌어지지 않고(clock은 너무 기본이기 때문에) PCB기판에서 벌어지게 됩니다. 왜냐하면 clock신호가 칩속으로 들어가거나 칩속에서 나올 때 delay에 의해 이런 skew 문제가 생기기 때문입니다. 앞에 설명한 대로 한쪽에서 어떤 클럭으로 데이타를 쳐서 보냈는데 받는 쪽 클럭이 시간지연에 의해 오히려 늦게 오기 때문에 발생합니다. 데이타도 같은 만큼 지연되는 경우에는 문제가 없지만 데이타와 클럭의 순서가 바뀔 정도로 지연이 되면 문제가 되는 것입니다. 또 한 칩에서 다른 칩으로 일방적으로 주는 관계라면 또 문제가 간단해집니다(트랜시버와 프레임 처리칩 사이같이). 이런 경우는 약간 시간지연만 추가해 주거나 클럭을 뒤집어서 받거나 하면 되지요(클럭을 뒤집어서 받는 것 조차도 주어진 클럭 주기의 절반밖에 사용하지 않으고, 즉 timing margin을 반이나 깍아 먹으면서 동작시키는 것이기 때문에 고속으로 가면 쓸 수 없습니다.)
그러나 같은 클럭을 기준으로 신호를 서로 주고 받는 관계에 있어서는(UTOPIA 인터페이스같이) 가는 신호와 오는 신호 양쪽에 대해서 문제가 발생하지 않도록 배려해야 합니다. 처음부터 칩이 잘 만들어지고(클럭과 그 클럭으로 동기되어 나가거나 들어오는 데이타가 있을 때는 데이타의 지연이 클럭의 지연보다 충분히 크도록), PCB에서 클럭 배선에 skew가 없도록 하는 것이 가장 중요합니다. 아예 이런 것을 고려해서 center에서만 치도록 보드를 만들어도 됩니다만 속도가 올라가면 함부로 쓸 수 없는 방법이고 또 클럭만 동시에 올라가도록 해주면 되는데 굳이 center에서 치도록 보드를 만드는 것도 낭비가 될 수 있겠지요.