01signal.com

일렉트로닉 엑소시즘(Electronic Exorcism): FPGA가 빙의된 것처럼 행동하는 이유

이상해지기 시작할 때

FPGA는 일반적으로 매우 믿음직한 부품입니다. 그러나 다른 기술이 다 그렇듯, 잘못 사용하면 제대로 동작하지 않습니다.

안타깝게도 FPGA 설계 툴은 우리 인간이 실수하지 않도록 안내해 주는 데는 별로 도움이 되지 않습니다. 그래서 결과가 신뢰할 수 없고 예측 불가능해지기 십상입니다. 더 정확히 말하면, FPGA 툴은 특정 설계 관행을 따랐을 때만 안정적인 동작을 보장하며, 우리가 뭘 하고 있는지 알고 있다는 가정을 깔고 있습니다. 소스 코드에 오류가 있으면 실행 파일 생성을 거부하는 소프트웨어 컴파일러와 달리, FPGA 툴은 이렇게 말합니다. “자, 여기 비트스트림(bitstream)이 있습니다. 원하면 써 보세요. 아, 참고로 경고가 200개쯤 있습니다. 경고 #143번이 무슨 뜻인지 이해할 수 있다면, 고쳐야 할 심각한 문제가 있다는 사실도 이해하게 될 겁니다.”

FPGA로 작업하는 사람들이, 전자 제품에 어떤 마법의 힘이 들린 것 같고 아무것도 이치에 맞지 않는다고 느끼는 일은 드물지 않습니다. 완전히 무관해 보이는 변경 때문에 문제가 생겼다가 사라지기도 하고, 합리적인 설명이 눈앞에 없습니다. 제대로 교육받은 엔지니어들조차 이런 이상한 동작을 어떻게든 설명하려고 FPGA에 관한 터무니없는 이론을 받아들이곤 합니다.

이것이 바로 ‘블랙 매직 모드(Black Magic Mode)’입니다. 이성적인 사람들이 문제에 합리적인 설명이 있다는 믿음을 멈추고, 대신 자신의 경험에 기반한 해결책을 찾기 시작하는 상황입니다. FPGA가 정말 차가울 때만 모든 게 잘 동작한다? 좋습니다. 큰 방열판을 달면 됩니다. 문제가 특정 보드에서만 생기고 다른 보드에서는 안 생긴다? 알겠습니다. 보드를 하나하나 테스트해서 안 되는 것은 버리면 됩니다. 이런 식입니다.

어떤 모습인가

다음은 엔지니어들을 비이성적으로 만들 수 있는 문제들의 일부 목록입니다. 항상 “모든 게 잘 동작하는데, 그런데…” 식으로 시작합니다.

이런 상황에는 전자 제품 자체에 결함이 있고 데이터시트가 약속한 대로 동작하지 않는다는 믿음이 따라오곤 합니다. 거대한 회사가 불량 부품을 유통한다는 음모론도 드물지 않습니다.

그러니 이것은 단순한 버그가 아닙니다. 물론 버그도 사람을 미치게 만들 수 있습니다. 그래도 버그는 어느 정도 재현성이 있고, 에어컨 때문에 나타났다 사라지지는 않습니다. 소프트웨어 엔지니어가 버그를 PC 자체 탓으로 돌리는 말을 들어 본 적이 없습니다(극히 드물게 실제로 그런 경우도 있지만). 반면 FPGA 설계의 실수는 확실히 하드웨어 레벨에서 오작동을 일으킬 수 있습니다. 거기서 세상 전체를 탓하는 단계까지는 한 걸음도 안 걸립니다.

논리적인 설명이 있습니다. 정말입니다.

그리고 손이 닿을 만한 곳에 있습니다. 반드시 쉽다는 뜻은 아닙니다.

이 분야에서 꽤 오랫동안 프리랜서로 일하면서 가끔 이런 상황을 고쳐 왔습니다. 저를 믿으세요. 극히 드문 경우를 제외하면 FPGA는 정상이고, 문제는 아마 비트스트림에 있을 것입니다.

나쁜 소식은 FPGA 설계에 결함이 하나 이상인 경우가 꽤 흔하고, 그 결함들이 눈에 보이는 문제의 원인일 수 있다는 점입니다. 따라서 고쳐야 할 것이 많을 수 있습니다. ‘거의 동작하는 FPGA 설계’를 고쳐 달라는 요청을 받은 적이 꽤 있습니다. 그럴 때마다 ‘이 작은 문제’를 빨리 고칠 수 있으리라는 비현실적인 기대와 마주하게 됩니다. 설계를 안정화한다는 것은 눈에 띄는 진전 없이 많은 작업을 해야 함을 뜻하는 경우가 많습니다.

어느 쪽이든 선택의 여지가 없습니다. 이 페이지에서는 전자 제품에 귀신이 들린 것처럼 보이는 현상의 가능한 원인들을 나열하면서, 합리적인 사고를 되찾는 데 도움을 드리고자 합니다.

물론 애초에 이런 상황을 피하는 것이 가장 좋습니다. 다른 페이지에 정리해 둔 골든 룰(Golden Rules)을 따르는 것이 좋은 시작입니다.

무엇이 이상해지게 만드는가

음, 짧게 답하면 FPGA 설계에 뭔가 잘못되어 있다는 뜻입니다. 그런 경우 원칙적으로 두 가지 가능성이 있습니다. 비교적 운이 좋은 가능성은 FPGA가 하려는 일에서 분명하고 지속적인 오작동이 나타나는 경우입니다. 소프트웨어 버그와 같아서, 찾아서 고치고, 고친 뒤 잘 동작하는지 확인하면 끝입니다.

덜 운이 좋은 가능성은 FPGA가 동작하긴 하는데, 그게 대부분 행운 덕분인 경우입니다. 그래서 어떤 조건이 바뀌면 FPGA가 갑자기 제대로 동작하지 않다가, 다시 정상으로 돌아오기도 합니다. 왜 이런 일이 생길까요?

핵심은 이렇습니다. FPGA도 전자 제품이므로 제조 과정에서 부정확함이 있습니다. 더 중요한 것은, 실리콘의 온도가 변하면 트랜지스터가 상태를 바꾸는 속도도 변하고, 로직 패브릭(logic fabric) 위에서 신호가 전파되는 속도도 변한다는 점입니다. 공급 전압의 변화도 FPGA 내부에서 일이 얼마나 빨리 일어나는지에 영향을 줍니다.

따라서 FPGA가 조금 더 따뜻해지거나 차가워지면, 신호가 클록에 비해 플립플롭에 아주 조금 늦게 또는 조금 일찍 도착할 수 있습니다. 이 차이만으로 플립플롭이 샘플링(sampling)해야 할 신호를 놓치거나, 평소에는 놓쳤던 신호를 샘플링할 수도 있습니다. 칩에서 인접한(그리고 무관해 보이는) 로직이 덜 활발하거나 더 활발해짐에 따라 실리콘이 국부적으로 뜨거워지는 것만으로도 이런 일이 생길 수 있습니다.

마찬가지로 FPGA에도 제조 공정의 부정확성이 있습니다. 공장에서 나오는 모든 FPGA는 사양과 일치하는지 검증하는 테스트를 통과하지만, 어떤 FPGA는 다른 것보다 실리콘이 더 빠를 수 있습니다. 그래서 제대로 만들어지지 않은 로직 설계가 한 FPGA에서는 동작하고 다른 FPGA에서는 동작하지 않을 수 있습니다.

이런 무작위 변수들은 로직 패브릭 위의 작은 구성 요소들이 상태를 바꾸는 에 영향을 줍니다. 그 타이밍 차이가 완벽히 동작하는 결과와 대참사 사이의 차이를 만들 수 있습니다. 따라서 제조 공정과 온도, 전압의 아주 작은 오차도 눈에 보이는 차이를 만들어 낼 수 있습니다.

그렇다면 FPGA는 어떻게 신뢰할 수 있을까요? FPGA 설계가 올바르게 되었다면 FPGA 툴이 모든 것이 정의된 대로 항상 동작하도록 보장합니다. 좀 더 정확히 말하면, 제조 테스트를 통과하고 데이터시트의 요구사항에 맞게 사용되는 FPGA라면 모두 동작하도록 보장합니다. 이 말은 결국 주변 온도(필요 시 냉각 포함)와 FPGA 핀에 공급되는 전압을 올바르게 유지한다는 뜻으로 귀결됩니다.

그러나 요구되는 FPGA 설계 관행을 따르지 않으면 툴도 정상적인 동작을 보장하지 않습니다. 즉, 차이가 없어야 할 변수들이 결정적이 되어, 전혀 중요하지 않아야 할 것들에 따라 보드 전체가 멈췄다가 다시 동작하기도 합니다. 이상하게 변하는 데에 한계가 없습니다.

지겹도록 반복해서 말하는 것 같지만, 여기 몇 가지 예가 있습니다.

몇 번이고 반복해서 말할 가치가 있습니다. FPGA 설계를 제대로 하면 이런 일은 절대 일어나지 않습니다. 적어도 극히 드뭅니다. 데이터시트를 읽고 그대로 따르고 FPGA도 올바르게 사용하면 전자 제품이 얼마나 믿음직한지 아는 사람은 거의 없습니다.

하지만 이 페이지를 읽고 계신 분들에게는 이 훈계가 이미 늦었을지도 모릅니다. 문제는 이미 생겼으니까요. 그래서 제 경험을 바탕으로, 빙의된 것처럼 보이는 FPGA에서 흔히 발견되는 원인 몇 가지를 정리했습니다. 이런 문제를 겪고 계시다면 그중 하나일 가능성이 높습니다.

원인 #1: 타이밍

FPGA 툴은 주어진 타이밍 제약 조건(timing constraints)을 달성함으로써 FPGA의 안정적인 동작을 상당 부분 보장합니다. 이것이 사용자와 툴 사이의 거래입니다. 사용자가 타이밍 요구사항을 정확히 표현하면, 툴은 FPGA가 허용된 온도·전압 범위 안에서 동작하는 한, 사용하는 어떤 FPGA에서든 그 요구사항이 달성되도록 보장합니다.

타이밍 제약 조건이 단 하나뿐인 경우도 드물지 않습니다. 그 하나는 대개 기준 클록(reference clock)의 주파수입니다. 이것만으로 충분할 수도 있지만, 다른 설계에서 그 한 줄을 그냥 복사해 왔는데 “어, 동작하네” 정도의 상태라면 검토할 이유가 충분합니다.

사실 이것은 전반적으로 타이밍을 올바르게 처리하는 문제입니다. 가장 노련한 FPGA 설계자에게도 쉬운 일이 아닙니다. 설계 안의 모든 신호 경로(path)가, 경로 끝의 플립플롭이 항상 신호를 올바르게 받도록 보장하는 제약 조건에 의해 관리되는지 확인하는 일을 뜻합니다. 제약이 필요 없는 경로는 예외로 하고요.

그러므로 가장 먼저 확인할 것은 설계가 타이밍 제약 조건을 달성했는지입니다. 정말 기초적이지만, 대부분의 FPGA 툴은 제약 조건을 달성하지 못했어도 일단 비트스트림을 만들어 주기 때문에 FPGA 초보자가 이 단순한 실수에 빠질 수 있습니다.

다음으로 타이밍 제약 조건을 검토하세요. 이런 점검을 다루는 별도 페이지가 있습니다. 간단히 줄이면, 타이밍 제약 조건이 정확히 무엇을 의미하는지 이해하고 있나요? 그 의미가 정말 그래야 하는 것과 일치하나요? 필터 조건으로 특정 경로만 선별하는 제약 조건이 있다면, 그 제약 조건이 정말 올바른 경로에 적용되고 있나요?

그리고 타이밍 리포트도 주의 깊게 읽어야 합니다. 다시 한번 말하지만, 별도 페이지에서 이 주제를 자세히 다룹니다.

또 하나 살펴볼 것은 클록 도메인(clock domain) 간 크로싱(clock domain crossing)입니다. 각 클록과 관련된 로직이 어떤 것인지 주의를 기울이지 않아서, 신호가 한 클록 도메인에서 다른 클록 도메인으로 안전하지 않게 건너가고 있지는 않은가요? 클록 도메인 간 크로싱은 FPGA 툴이 만든 FIFO로만 이루어지나요? 아니라면, 그 크로싱이 안전하고 올바르게 구현되어 있나요?

원인 #2: 부적절한 리셋

리셋과 무관해 보일 수 있지만, 로직의 초기 상태가 보장되지 않으면 흑마법 같은 동작으로 이어질 가능성이 매우 높습니다.

규칙은 간단합니다. 리셋과 로직의 초기 구동에 대해 진지하게 고민하지 않았다면, 아마 잘못했을 확률이 높습니다.

특히 다음 예를 보십시오.

   always @(posedge clk or negedge resetn)
     if (!resetn)
       the_reg <= 0;
     else
       the_reg <= [ ... ] ;

리셋을 이렇게 쓰는 방식이 전부라면, 즉 @resetn이 비활성화(이 예에서는 하이로 변함)될 때 어떤 일이 일어나는지 명시적으로 처리하지 않는다면, 이 페이지를 꼭 보시기 바랍니다.

어느 쪽이든, 리셋이 있어야 할 곳에 리셋이 있고 제 역할을 제대로 수행하는지 확인하는 것이 좋습니다. 그 의미에 대해서는 관련 짧은 연재 페이지들에서 다룹니다.

원인 #3: 클록 처리

클록 품질은 디지털 설계에서 가장 과소평가된 주제일 것입니다. 흔히 “그래, 하이에서 로우로 바뀌고 다시 돌아오네. 그럼 이걸 클록으로 쓰자” 같은 식이지요.

FPGA 로직에 사용하는 클록은 안정적이고 충분히 낮은 지터(jitter) 성능을 가져야 합니다. 그에 못지않게 중요한 것은 FPGA까지의 클록 물리적 연결이 안정적이고 확실해야 한다는 점입니다.

이런 문장을 예로 들어 보겠습니다.

always @(posedge clk)

이런 문장에서 @clk 자리에는 무엇이 오든 아주 주의를 기울여 다뤄야 합니다. 이상적으로는 전용 클록 생성 부품(오실레이터)에서 나온 클록이어야 하며, 그래야 안정적이고 지터가 낮습니다. 일반적으로는 이 외부 클록을 로직에 직접 연결하기보다 PLL의 기준 클록으로 사용하는 것이 좋습니다. PLL이 클록의 주파수를 바꾸지 않더라도 마찬가지입니다.

이유는 PLL을 사용하면 PLL의 잠금(Lock) 감지 출력을 모니터링할 수 있기 때문입니다. 따라서 이 클록에 의존하는 로직은 PLL이 잠기지 않았을 때 리셋 상태로 잡아둘 수 있습니다. 이렇게 하면 기준 클록이 불안정할 때(특히 전원을 켠 직후) 문제가 생길 가능성이 크게 줄어듭니다.

PLL은 문제를 일으키는 장치로 오해받기도 합니다. PLL이 간헐적으로 잠금을 잃어 원인 모를 리셋이 걸리는데, 이를 ‘고치겠다’고 PLL을 제거하고 외부 클록을 로직에 직접 연결하면 모든 게 잘 동작하는 것처럼 보일 수 있습니다. 이런 경우라면 기준 클록에 문제가 있을 확률이 높습니다. 이 상황에서 PLL을 제거해도 문제가 해결되는 것이 아니라, 문제를 로직 패브릭 안으로 밀어 넣어 흑마법 상황을 일으킬 가능성이 높습니다.

지금까지는 전용 오실레이터의 클록, 즉 비교적 쉬운 경우를 다뤘습니다. 다른 소스는 더 골칫거리입니다. 프로세서나 프로세서 주변장치가 만든 클록은 정말 필요한 경우가 아니면 조심해서 사용해야 합니다. 그런 클록은 프로세서 때문에 순간적으로 멈추거나, 때때로 비정상적인 파형을 만들 수 있습니다. 소프트웨어가 관련 하드웨어 레지스터에 쓰는 동작 때문에 그럴 수 있는데, 그 쓰기 동작은 무관한 작업의 일부일 수 있습니다. 이런 짧은 사건은 오실로스코프로 클록을 살펴볼 때 보이지 않을 수 있지만, 그럼에도 이상한 오작동을 일으킵니다.

또 다른 흔한 문제 원인은 소스 동기 클록(source-synchronous clock)을 제대로 처리하지 못하는 것입니다. 다시 말해, 외부 부품이 클록 신호와 하나 이상의 데이터 신호를 함께 공급해서 데이터가 그 클록에 동기화되는 경우입니다. 보통 데이터 신호는 클록의 상승 에지에서만(또는 하강 에지에서만) 값이 바뀔 수 있습니다.

흔하기는 하지만 상당히 위험한 방법은 그런 소스 동기 클록을 FPGA 내부의 애플리케이션 로직에 직접 연결하는 것입니다. 여기서 문제가 되는 부분은, 소스 동기 클록이 연속 클록으로 쓰일 의도가 아닌 경우가 많아서 순간적으로 멈추거나 가짜 펄스가 나올 수 있다는 점입니다.

또 다른 가능한 문제는 소스 동기 인터페이스가 물리적 커넥터를 통해 FPGA에 연결되는 경우가 많다는 점입니다. 예를 들어 데이터 소스가 카메라이고 카메라가 케이블로 메인 보드에 연결되는 경우입니다. 커넥터는 보통 신뢰할 만하지만, 진동 때문에 물리적 접촉이 1ns만 끊겨도 클록 신호에 비정상적인 펄스가 발생할 수 있습니다. 물론 데이터 신호에서도 그럴 수 있지만, 특히 데이터 소스가 카메라인 경우에는 그 영향이 덜 중요합니다. 하지만 그런 클록 신호를 애플리케이션 로직에 직접 연결했다면, 1ns 길이의 펄스 하나로 충분히 큰 혼란이 생길 수 있습니다.

따라서 클록과 데이터 신호가 함께 오는 소스 동기 인터페이스에서는, 클록과 데이터를 모두 일반 신호로 취급하는 것이 가장 좋은 해결책입니다. 즉, 소스 동기 클록과 데이터 신호를 모두 안정적이고 안전한 훨씬 빠른 클록으로 플립플롭에서 샘플링합니다. 가능하면 I/O 핀에 인접한 전용 플립플롭을 사용하는 것이 좋습니다.

소스 동기 클록이 로우에서 하이로 바뀌면, 이 신호를 샘플링하는 플립플롭의 출력도 로우에서 하이로 바뀝니다. 따라서 동기 로직(synchronous logic)은 이 플립플롭의 출력이 로우에서 하이로 바뀐다는 단순한 사실로 소스 동기 클록의 상승 에지를 감지할 수 있습니다. 물론 이 로직은 더 빠르고 안정적인 클록을 기준으로 동작합니다. 이런 상승 에지가 감지되면 데이터가 유효하다고 표시합니다. 다시 말해, 데이터 입력 값이 들어 있는 플립플롭들의 출력이 유효 데이터로 표시됩니다.

클록 신호에 무슨 일이 생기든 FPGA 로직이 계속 안전한 클록에 의존한다는 점이 01 신호 샘플링(01-signal sampling) 방식의 분명한 장점입니다. 소스 동기 클록이 엉뚱하게 변하면, 에지를 감지하는 로직이 적절히 대응해야 합니다.

이 기법은 소스 동기 클록 주파수가 상대적으로 낮을 때 사용할 수 있습니다. FPGA 속도와 DDR 샘플링 사용 여부에 따라 보통 최대 200~300MHz 정도입니다.

더 빠른 소스에서는 소스의 클록을 PLL에 공급하고, PLL의 출력을 애플리케이션 로직에 사용하는 것이 선호되는 해결책입니다. 앞서 말했듯이, PLL이 잠기지 않았다고 알리면 로직을 리셋해야 합니다. 이것은 다른 이유에서도 올바른 해결책일 가능성이 높습니다. 방금 제안한 01 신호 샘플링 방식으로는 감당하기 어려울 정도로 주파수가 높다면, 제대로 샘플링하는 유일한 방법은 클록의 위상 편이(phase shifting)로 타이밍을 맞추는 것일 가능성이 높습니다. 즉, 샘플링되는 신호에 오류가 감지되지 않을 때까지 로직이 타이밍을 자동으로 조정합니다. 이 기법은 어차피 PLL을 필요로 합니다.

원인 #4: RTL 설계 규칙 위반

합성용으로 작성하는 Verilog 코드(또는 VHDL)는 몇 가지 엄격한 규칙을 따라야 합니다. 특히 RTL(Register Transfer Level) 패러다임을 따라야 합니다. 무엇보다 메모리와 같은 성격의 로직 요소(예: 플립플롭)는 클록 에지에서만 값이 변해야 합니다. 유일한 예외는 비동기 리셋(asynchronous reset)이며, 이 역시 아무 신호나 될 수 없습니다.

합성기(synthesizer)가 이런 규칙을 위반하는 Verilog 코드를 만나면, 보통은 협조적으로 동작하려고 시뮬레이션에서 보여 주는 것과 같지 않을 수 있는 로직을 만듭니다. 또 다른 가능성은 합성 결과가 대개는 기대대로 동작하지만, 무작위로 실패할 수 있다는 것입니다.

예를 들어, 0부터 14까지 세는 카운터를 위한 다음 잘못된 설계를 보십시오.

reg [3:0] counter;
wire      reset_cnt;

assign reset_cnt = (counter == 15); // This is so wrong!

always @(posedge clk or posedge reset_cnt)
  if (reset_cnt)
    counter <= 0;
  else
    counter <= counter + 1;

@reset_cnt를 비동기 리셋으로 사용한 것이 끔찍한 실수입니다.

하지만 먼저 시뮬레이션에서 어떻게 동작하는지 설명하겠습니다. @counter는 @clk의 상승 에지마다 값을 올립니다. 그런데 @counter가 15에 도달하면 @reset_cnt가 ‘1’이 되고 @counter를 비동기로 0으로 리셋합니다. 따라서 @clk로 @counter를 샘플링하면 기대한 대로 0부터 14까지의 값이 보입니다.

하지만 하드웨어에서는 이렇게 동작하지 않을 수 있습니다. 문제는 @reset_cnt가 @counter의 조합 함수라는 점입니다. @counter가 7에서 8로 바뀔 때, @reset_cnt를 계산하는 로직은 @counter 값을 순간적으로 15로 볼 수 있습니다. 7은 2진수 0111이고 8은 1000으로 인코딩되기 때문입니다. 따라서 @reset_cnt를 계산하는 로직까지 비트 3의 전파 지연이 가장 짧다면, 이 신호는 순간적으로 ‘1’이 될 수 있습니다. 그 결과 @counter는 어떤 때는 0부터 14까지 세고, 어떤 때는 0부터 7까지만 셀 수 있습니다. 온도와 그 외 무관한 요소들이 어떤 결과가 나타나는지에 영향을 줄 수 있습니다.

하지만 이 예가 왜 잘못됐는지에 대한 설명은 크게 단순화한 것입니다. 툴은 조합 로직(combinatorial logic)을 가장 창의적인 방식으로 구현할 자유가 있으므로, 클록 에지 사이에는 사실상 어떤 일이든 일어날 수 있습니다. 툴이 보장하는 유일한 것은, 목적지 플립플롭의 타이밍 요구사항(셋업 타임과 홀드 타임)에 맞춰 신호가 안정적으로 유지된다는 점입니다.

따라서 RTL 설계 규칙을 엄격히 지키지 않으면, 이상한 일이 얼마든지 일어날 수 있습니다.

원인 #5: 온도와 전원 공급

흔한 원인은 아니고 확인도 쉬운 편입니다. 그럼에도 온도와 전원 공급은 묘한 문제의 근본 원인이 될 수 있습니다.

당연하게도 실리콘 온도가 허용 범위를 벗어나면 아무것도 정상 동작을 보장받을 수 없습니다. 가장 흔한 원인은 방열 설계 부족으로 인한 과열, 또는 먼지로 막힌 팬입니다.

전원 공급 장치는 여러 이유로 불량 출력을 만들 수 있습니다. 오실로스코프로 간단히 확인하면 전압이 규격 범위 안에 있는지 알 수 있습니다. 다만 전압은 모든 순간에 그 범위 안에 있어야 한다는 점을 기억하세요. 평균 전압이 맞는 것만으로는 부족합니다. 스위칭 전원이 항상 만드는 노이즈나 가끔 발생하는 스파이크도 허용 한계를 넘으면 안 됩니다.

1μs 길이의 스파이크는 무해해 보일 수 있지만, FPGA 내부에서는 수십에서 수백 클록 사이클에 해당합니다. 따라서 FPGA에 잘못된 전압이 공급되는 길고 의미 있는 시간입니다. 가능하면 FPGA 가까이에 있는 디커플링 커패시터에서 전압을 측정해서 실제로 도달하는 전압을 확인하세요. 그리고 오실로스코프 트리거를 전압 상한과 하한에 설정하고, 그 값에 오실로스코프가 반응하지 않는지도 확인하세요. 짧은 스파이크는 오실로스코프 화면에서 발견하기 쉽지 않지만, 트리거가 잡아 줍니다.

때로는 전원 공급 문제가 보드 설계 불량의 직접적인 결과입니다. 많은 전원 공급 모듈에는 종종 간과되는 최소 전류 요구사항이 있습니다. 이 최소 전류를 흘려 주지 않으면 전원 공급 모듈이 불안정해져서 규격에 맞지 않는 전압을 만들거나, 더 심하면 간헐적으로 발진할 수도 있습니다.

또 다른 흔한 실수는 전압 레귤레이터가 필요한 자리에 스위칭 전원을 사용하는 것입니다. 특히 지터가 낮은 클록 오실레이터는 매우 깨끗한 입력 전원을 요구합니다. 그런 오실레이터에 노이즈가 많은 전원을 공급하면 그 노이즈가 클록 출력의 지터로 그대로 나타납니다. 기가비트 트랜시버(예: PCIe, USB 3.x, 광통신 등)가 이 클록을 사용한다면 데이터 링크가 불안정해지는 경우가 많습니다.

마찬가지로, DDR 메모리가 설계에 포함되면 기준 전압(reference voltage) 전원이 필요합니다. 이 전압은 FPGA와 DDR 메모리가 두 부품 사이의 배선에서 ‘0’과 ‘1’을 판별하는 전압 임계값으로 사용합니다. 이 기준 전압을 스위칭 전원으로 만들면, 전원 노이즈 때문에 FPGA와 DDR 메모리 사이에 오류 없이 데이터를 전송하기가 어려워지거나 아예 불가능해질 수 있습니다.

원인 #6: 농담이세요?

때로는 흑마법 상황의 원인이 너무 커서, 어떻게 그게 동작했는지 궁금할 정도인 결함입니다. 예를 들어 PCB의 배선이 해당 FPGA 핀과 완전히 끊어져 있는데도, 누화(crosstalk)나 기생 커패시턴스 덕분에 올바른 신호가 FPGA에 도달하는 경우입니다.

이런 일은 특히 클록에서 자주 생깁니다. 클록은 보드 전체에 배선되는 경우가 많고, 주기 신호라서 FPGA까지 제법 잘 전달되어 정상처럼 보일 가능성이 높기 때문입니다.

그러니 오실로스코프를 들고 모든 클록을 FPGA에 최대한 가까운 지점에서 확인하세요. 클록에 AC 커플링 커패시터가 있다면 그곳도 좋은 확인 지점입니다. 특히 커패시터가 빠져 있다는 사실을 발견하게 될 수도 있습니다.

원인 #7: 평범한 버그

좀 더 정확히 말하면, 설계가 애초에 동작하도록 만들어진 적이 없는 경우입니다. 어느 시점에도 누군가 앉아서 ‘로직이 제 역할을 한다는 것을 어떻게 보장할 것인가’를 고민하지 않았습니다. 대신 시뮬레이션과 하드웨어를 오가며 시행착오로 코드를 조금씩 써 내려갔습니다. 모든 게 잘 동작해 보이는 순간 그 과정이 끝났지만, 코드를 보면 어떻게 동작했는지가 기적처럼 보입니다. 그 작은 문제를 고치려고 수없이 패치를 가했기 때문에, 무슨 일이 일어나는지 따라가는 것조차 불가능하고 변경은 더 말할 나위도 없습니다.

이 원인을 마지막에 둔 이유는, 이것은 사실 흑마법 같은 동작이 아니기 때문입니다. 그냥 아주 짜증 나는 버그입니다. 그럼에도 불구하고 FPGA 프로젝트가 좌초되는 가장 흔한 원인이기도 합니다.

그래도 FPGA 탓이라고 생각한다면

가끔은 여러분 잘못이 아닐 수도 있습니다. FPGA 자체나 벤더의 소프트웨어에 버그가 있을 수 있습니다. 이런 경우는 사람들이 FPGA 벤더를 탓하는 것보다 훨씬 드물지만, 드물게 실제로 그럴 때가 있습니다.

남을 탓하고 싶은 유혹은 자연스럽습니다. 그러니 스스로를 위해 부탁드립니다. 아래 두 가지 중 하나(또는 둘 다)를 갖고 있지 않다면, 이 퇴마 작업을 ‘FPGA 탓’으로 끝내지 마세요.

이런 증거 없이 어떻게든 문제를 우회해서 마무리했다면, 나중에 같은 문제를 다시 만날 가능성이 높습니다.

FPGA 자체의 버그를 겪은 가장 좋은 예는 오래전 Xilinx Virtex-4의 하드웨어 FIFO에서였습니다. 즉, FIFO의 제어 로직이 로직 패브릭이 아니라 실리콘에 직접 구현된 듀얼 클록 FIFO였습니다.

그 FIFO를 통과하는 데이터 흐름은 가끔 멈추곤 했습니다. 조사해 보니, FIFO가 한동안 정상적으로 동작한 다음 empty(비어 있음) 신호와 full(가득 참) 신호를 동시에 활성화한 채로 유지하고 있었습니다. FIFO가 리셋 상태에 있었다면 이런 상태도 가능하지만, 당시에는 리셋 상태가 아니었습니다. 그래서 제가 관측하는 신호가 정말 정확한지 확인하고 나서, ‘FPGA의 FIFO에 버그가 있다’는 결론으로 이 사건을 마무리했습니다. 그리고 그 뒤로는 로직 패브릭에 구현된 FIFO를 사용했습니다.

몇 달 후, 저는 이 FIFO들에 대한 정오표 기록을 발견했습니다. 문제를 미리 알지 못했다면 이해하지 못했을 내용이었습니다. 하지만 설명을 아주 주의 깊게 읽고 나서, 그 기록이 제 관측을 확인해 준다고 결론 내릴 수 있었습니다.

그 사례는 FPGA 버그가 ‘내 잘못이 아니다’라고 선언해도 되려면 얼마나 명확해야 하는지를 보여 주는 예시일 뿐입니다.

요약

FPGA가 자연 법칙을 거스르는 것처럼 보이면 상식에서 벗어난 설명을 받아들이고 싶어집니다. 그렇지만 합리적인 설명을 찾는 것이 중요하며, 아주 자주 초능력 없이도 찾을 수 있습니다.

원인을 쫓는 일은 설계 전체를 철저히 검토해야 할 수도 있는데, 그 자체가 나쁜 일은 아닙니다. 그런 추적이 답답하게 느껴질 수는 있어도 설계 품질에 크게 기여할 수 있습니다.

이 페이지는 영어 원문을 기계 번역한 것입니다. 의문이 드는 부분이 있으면 원문을 참조하시기 바랍니다.
Copyright © 2021-2026. All rights reserved. (dcc38493)