RTL to GDS: 1. RTL Design, Verilog coding style

RTL to GDS: 1. RTL Design, Verilog coding style
Photo by Pankaj Patel / Unsplash

1부: Implementation의 시작 (Front-end Bridge)

서문: RTL 코드가 실리콘이 되기까지, 그 첫 번째 관문

현대 반도체 설계, 특히 수십억 개의 트랜지스터가 집적되는 SoC(System on Chip) 설계 과정에서 'RTL 코딩'은 거대한 여정의 시작점에 불과합니다. 학부나 석사 과정에서 Verilog HDL을 처음 접할 때 가장 흔히 범하는 오해는 "Testbench 시뮬레이션에서 파형(Waveform)이 의도대로 나오면 설계가 끝났다"고 믿는 것입니다.

하지만 시뮬레이션 환경은 물리적 제약이 존재하지 않는, Ideal 논리 세계입니다.

처음 디지털 공학을 배우고, Verilog Hardware Description Language를 배우는 대학생들은, "나 이제 칩 설계 할 줄 알아!"라고 생각합니다. 그러나 대학원에 가서 Tape out을 하면서 반도체의 깊은 심연에 들어가게 되죠.

실제 반도체는 아래와 같은 회로가 엄청나게 많이 들어가게 됩니다.

그런 회로들이 엄청나게 많이 들어가고,

실제로 생산된 반도체 위에서 전자가 움직이며 동작하는 칩을 만들기 위해서는 Timing, Power, Noise, Area 그리고 Variation이라는 가혹한 물리적 현실을 극복해야 합니다.

이 글 'Implementation의 시작 (Front-end Bridge)'에서는 RTL 코드가 Synthesis Tool에 입력되기 전과 후 단계에 대해 이야기합니다.

Verilog coding style: 합성이 가능한 코드인가?

설계 흐름의 첫 번째 관문에 배우는 것은 Verilog coding style 입니다.

반도체 설계는 매우 복잡한데, 칩 제조에 $10,000,000 USD 이상 사용되고, 제조된 후에 수정할 방법이 없습니다. 그래서 "양산이 가능한, 매우 안전한 방식의 Hardware coding이 필요합니다."


1. 하드웨어의 본질: "코드가 아니라 회로다"

학생들은 Verilog를 C언어 같은 프로그래밍 언어로 착각합니다. 하지만 양산용 설계의 철칙은 다음과 같습니다.

  • Physics의 이해: 전자는 이동하는 데 시간이 걸립니다(Gate Delay + Net delay). 시뮬레이션은 '0'의 시간으로 계산하지만, 실제 실리콘에서는, 온도와 전압에 따라 이 시간이 변합니다.
  • 단순함의 미학: 현란한 문법은 시뮬레이션용일 뿐입니다. 실제 칩은 Combination + Sequential logic의 조합일 뿐임을 명심해야 합니다.
  • 엄청 잘 만들어도 Silicon Failure가 발생합니다. 쉽게 만들지 않으면, 원인 디버그도 안됩니다.

2. Sequential Logic (FF) 설계 규칙

Flip-flop은 칩의 뼈대입니다. 가장 보수적이고 표준적인 구조만 허용합니다. 물론 아래 약속들을 안 지켜도, 실제로 칩 생산 가능합니다.

그렇지만 대기업에서는 수율을 아주 조금이라도 올리기 위해, Silicon failure가 발생하면 빠르게 분석하기 위해 매우 엄격한 coding style을 갖고 있습니다.

  • Clock/Reset 약속:
    • Positive Edge Clock: 셀 라이브러리의 기본이므로 posedge clk만 사용합니다. 한 칩 안에 negedge clk를 섞는 것은 추천하지 않습니다.
      • 칩이 나오기 전, 모든 신호가 제시간에 도착하는지 계산(Static Timing Analysis)해야 합니다. posedgenegedge를 섞어 쓰면 'Half-cycle path'가 생기는데, 이는 타이밍 마진을 절반으로 줄여버립니다.
      • 클럭의 High 구간과 Low 구간이 정확히 50:50이 아니면(Jitter/Skew), posedgenegedge 가 섞이는 구간에서 Noise 문제가 날 확률이 높습니다.
      • 실제로 대기업에서는 이것보다 더 엄격한 기준을 갖고 설계합니다. 초고속 통신 Block들을 제외하고, 대부분의 System ICposedge로 설계합니다.
    • Asynchronous Reset: 리셋은 비동기로 하되, 가능하면 negedge를 사용합니다.
      • 많은 파운드리의 라이브러리 셀들이 Active-Low 비동기 리셋에 최적화되어 있습니다.
      • 확실한 초기화: 칩에 전원이 들어오는 순간(Power-up), 클럭이 아직 안정화되지 않은 상태에서도 칩을 안전한 'IDLE' 상태로 강제 고정하기 위해 비동기 리셋을 선호합니다.
    • No Gating: 클럭 라인에 직접 논리 게이트(AND, OR)를 달지 말고, Foundry에서 가이드하는 ICG를 사용하세요.
      • Glitch 지옥: 일반 AND 게이트로 클럭을 껐다 켰다 하면, 짧은 노이즈가 발생할 수 있습니다. 이게 플립플롭에 들어가면 데이터가 깨지고, 칩은 '원인 불명의 동작 멈춤' 상태가 됩니다.
      • 파운드리 공인: ICG 셀은 파운드리에서 "이건 Glitch에서 훨씬 안전하다"라고 보증한 전용 부품입니다. 대기업에서는 클럭 라인에 일반 로직 게이트가 하나라도 섞여 있으면 'Lint Error'로 처리해 설계를 반려합니다.

표준 구문 준수:Verilog

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) 
        data_q <= 8'd0;
    else 
        data_q <= next_data;
end

3. Combinational Logic: reg보다는 wire

보내주신 글에서 가장 강조하는 부분입니다. always @(*) 블록 내에서 reg를 사용하여 조합 회로를 설계하는 방식을 경계해야 합니다.

일반적인 디지털 회로 설계에서는 Latch를 사용하지 않고, Flip flop을 사용합니다.

  • 위험성: always @(*) 블록에서 조건문(if, case) 처리가 미흡하면 의도치 않은 Latch가 생성됩니다. 시뮬레이션에선 돌아가도 실제 양산 시 특정 온도에서 동작이 멈추는 원인이 됩니다.
  • 안전한 대안: 가급적 assignwire를 사용한 연속 할당문을 사용하세요.
    • Bad (Avoid): always @(*) 내에서 reg로 조합 회로 설계 (Latch 위험)
    • Good (Safe): assign out = (cond) ? a : b; (물리적 회로가 명확히 보임)

4. FSM(상태 머신) 설계의 정석

양산용 FSM은 '현란한 case문'이 아니라 '명확한 신호 분리'가 핵심입니다.

  • 상태 전이와 출력 로직의 분리:
    • State Register: always 블록 (Sequential)
    • Next State Logic: assign 문 (Combinational)
    • Output Logic: assign 문 (Combinational)

5. 실수를 방지하는 디테일

  • 비트 폭 일치: 10'd5를 리셋할 때 9'd0으로 쓰는 실수를 절대 하지 마세요. 툴이 대충 맞춰주길 기대하는 순간 양산은 실패합니다.
  • Default 값의 함정: "안 해도 되겠지"라는 생각은 버려야 합니다. 모든 case문에는 default를, 모든 if문에는 else를 작성하여 회로의 모든 경로를 확정(Deterministic)지어야 합니다.

책 추천: Verilog coding style for mass production

다시 말하지만, Verilog coding style 안 지켜도 생산 가능합니다. 근데 수율 조금이라도 올리고, 양산 실패 가능성 조금이라도 낮추고, 실패하면 원인을 조금이라도 더 쉽게 찾고자 대기업들이 이런 규칙을 적용하는 것입니다.

  1. Reuse Methodology Manual (RMM): 제일 유명한 책
  2. STARC Design Style Guide: 일본 반도체 뿐만 아니라, 한국의 반도체 대기업들의 일본 유학 엔지니어들이 이 책으로 Verilog coding style 규칙을 많이 만들었다고 들었습니다.
  3. Verilog의 대가 Cliff Cummings의 발표 논문들.

다음은 RTL Linting입니다. 소프트웨어 개발에서의 Lint가 단순한 문법 오류나 스타일을 체크하는 수준이라면, 하드웨어 설계에서의 Linting은 "이 코드가 실제 회로로 변환 가능한가?"를 묻는 생존의 문제입니다.

Simulator는 문법적으로 허용되지만 실제 하드웨어로는 구현 불가능하거나, 구현되더라도 치명적인 불량을 유발하는 코드를 너그럽게 받아들입니다. 이러한 '시뮬레이션과 합성 간의 불일치(Simulation-Synthesis Mismatch)'를 잡아내는 것이 RTL Lint의 핵심 목표입니다.1

1.1 Synthesizability: 시뮬레이션과 물리적 구현의 괴리

합성 툴(예: Synopsys Design Compiler)은 RTL 코드를 읽어 들여 이를 GTECH(Generic Technology)라 불리는 툴 내부의 추상적 논리 게이트로 변환합니다. 이 과정에서 가장 빈번하게 발생하는 문제는 설계자의 의도와 다르게 하드웨어가 해석되는 경우입니다.

1.1.1 Latch Inference: 의도치 않은 메모리 소자의 위험성

디지털 회로 설계의 금기 중 하나는 'Inferred Latch'의 생성입니다. Combinational Logic를 기술할 때, if 문이나 case 문에서 모든 가능한 조건에 대해 출력 값을 명시하지 않으면, 합성 툴은 조건이 명시되지 않은 상황에서 이전 값을 Hold해야 한다고 판단합니다. 조합 회로는 스스로 값을 저장할 수 없으므로, 툴은 데이터를 저장하기 위해 Transparent Latch를 강제로 삽입합니다.

왜 Latch를 안 쓰려고 하는가?

  1. STA(Static Timing Analysis)의 복잡성 증가: Flip-flop은 Clock edge에서만 데이터가 넘어가므로 타이밍 분석이 명확합니다. 반면, Latch는 Clock이 Transparent window 내내 입력 변화가 출력으로 전달되는 Time Borrowing 특성을 가집니다. 이는 타이밍 경로 분석을 매우 복잡하게 만들며, 툴이 Setup/Hold 시간을 정확히 계산하기 어렵게 하여 Timing Closure를 방해합니다.
  2. DFT(Design for Test) coverage 하락: 양산 테스트를 위한 Scan Chain 삽입 시, 래치는 제어 및 관측이 어려워 test pattern 생성을 방해하고 Fault Coverage을 떨어뜨립니다.
  3. Glitch Propagation: Latch의 Enable 신호가 Glitch에 노출될 경우, 의도치 않은 데이터가 저장되어 기능 오류를 유발할 수 있습니다.

해결책: Defensive Coding Style

가장 확실한 예방책은 모든 always_comb (SystemVerilog) 또는 always @(*) (Verilog) 블록의 최상단에 Default Assignment을 할당하는 것입니다. 이렇게 하면 조건문에서 특정 경로가 누락되더라도 기본값이 할당되므로 값을 유지할 필요가 없어 래치가 생성되지 않습니다.

Example1: enable이 0일 때 data_out에 대한 정의가 없어 Latch가 생성됨

always @(*) begin
    if (enable) 
        data_out = data_in;
end

Example2: 블록 진입 시 0으로 초기화하므로, if문을 타지 않아도 값이 결정됨 -> 조합 논리(MUX)로 합성

always_comb begin
  data_out = 1'b0; // Default Assignment
  if (enable)
    data_out = data_in;
end


또한, case 문을 사용할 때도 default 구문을 반드시 포함하여 정의되지 않은 상태를 방지해야 합니다. default 구문이 없으면 툴은 case 조건에 해당하지 않는 입력이 들어올 때 이전 값을 유지하려 하여 래치를 생성합니다.

1.1.2 Full Case와 Parallel Case의 함정: "The Evil Twins"

Verilog 설계 역사에서 가장 논쟁적이고 위험한 주제 중 하나는 // synopsys full_case parallel_case와 같은 Sytnehssis Pragma의 사용입니다. 저명한 Verilog 전문가 Clifford Cummings는 이를 "The Evil Twins of Verilog Synthesis"라고 명명하며 그 위험성을 경고했습니다.

이런걸 잘 사용하면, 코드가 좀 짧아지긴 하는데, 저도 사용하지 않는 스타일입니다. 그냥 Synthesis Pragma라는게 있다는 정도만 배우셔도 됩니다.

보통은 대학교 연구실에도 작은 Verilog coding style이 있습니다.

스타트업에도 있고, 대기업으로 갈 수록 더 강력한 Verilog coding style이 있고, 해당 coding style을 검사하는 Checker도 있습니다.

다음 글에서 RTL Lint에 대해 알아보겠습니다.

Enjoyed this article?

Get deep-dive semiconductor analysis and career insights delivered weekly. Free forever — no paywall, no upsell. Funded by sponsorships with a strict editorial firewall (Editorial Standards).

Work with me

Consulting · Collaboration · Support

Paid 1:1 technical consulting, speaker invitations, collaboration proposals, or just want to say thanks — all welcome.

View options →
VLSI Korea Free forever · No paywall · Weekly semiconductor insights from practicing engineers
Support