Why and How to Draw RTL Diagrams
Intro
설계를 할 때 그림을 그리는 것은 중요합니다. 건축/토목, 자동차, 소프트웨어 아키텍처 등 다양한 공학 분야에서는 그림을 통해 설계합니다. 디지털 회로 설계 역시 마찬가지입니다. 회로를 설계할 때 글보다는 시각 언어를 사용하는 게 효과적입니다.
그런데 회로를 설계할 때 표현하는 방식이 다양합니다. 예를 들어 adder만 하더라도 아래와 같이 다양한 방식으로 표현됩니다.
또한 설계도의 추상화 수준 또한 여러 가지입니다. 디지털 설계 관련 책들을 보면 아래와 같이 gate level에서부터 register-transfer level, block level까지 다양한 수준의 회로도가 나옵니다.
이렇게 회로를 표현하는 방식이 다양하니 처음 설계를 시작하면 내가 설계하는 회로를 어떻게 표현해야 할까 고민이 됩니다. 이번 글에서는 디지털 시스템에서 사용되는 회로도의 추상화 수준과 필요한 기호들을 정리하겠습니다.
디지털 회로의 추상화 수준
디지털 회로와 관련된 자료들을 보다 보면 다양한 종류의 회로도가 나옵니다. 게이트 레벨의 회로, RTL 회로, 블록 다이어그램 등이 있죠. 각 회로도를 보면 아래와 같습니다.
게이트 레벨 회로
모든 것들이 논리 게이트로 표현되어 있습니다. Adder, flip-flop 등 comb logic과 ff들이 모두 논리 게이트로 표현되어 있죠. 디지털 회로 교과서들의 앞부분에 나오는 회로들이 게이트 레벨 회로들입니다. 게이트 레벨 회로는 RTL 설계에서 큰 의미가 없습니다. 어차피 합성 컴파일러가 최적화하는 과정에서 마음대로 바꿀 테니까요. 열심히 adder 회로를 논리 게이트로 그려봤자 HDL에서는 단순히 ‘+’ 기호로 표현될 것이고, 이것이 논리 게이트로 어떻게 구현될지는 합성 컴파일러가 할 일입니다. 타이밍이나 synthesis constraints 등에 따라 다르게 합성됩니다.
물론 내가 설계한 회로가 논리 게이트로 어떻게 구현될지 예상해 보는 것은 중요하고, 알아야 합니다. 이런 것들을 알아야 여러 아키텍처 중에서 면적이나 소비 전력에 최적화된 것을 고를 수 있겠죠. 그러나 회로를 그릴 때 논리 게이트 수준으로 표현하는 것은 RTL 설계에서는 지나치게 불필요한 과정이라 생각합니다.
RTL 회로
Register-transfer level에서는 모든 것이 comb logic과 register들의 조합으로 표현됩니다. 게이트로 표현되어 있던 것들이 추상화되어있죠. adder, multiplexer, register들이 논리 게이트로 표현되지 않고 기호들로 표현됩니다.
RTL에서 제대로 회로를 설계했다면 코딩은 굉장히 간단합니다. 설계한 회로를 그대로 코드로 옮겨 적으면 코딩이 끝나니까요. 생각할 거 없이 선들은 wire로 옮겨 적고, comb logic 쭉 쓰고 레지스터 쭉 쓰면 코딩이 끝납니다. RTL 설계를 잘하기 위해서는 RTL에서 내가 어떤 디지털 회로를 구현할지 그려보고 연습하는 것이 중요합니다.
블록 다이어그램
RTL보다 한 번 더 추상화되어 있습니다. 여기서는 시스템이 모듈들의 조합으로 표현됩니다. 여기서 모듈이라 함은 보통 조합 회로와 레지스터가 합쳐진 특정 기능을 수행하는 하드웨어 블록을 의미합니다. 전체 구조를 그려보고 시스템의 구조를 구체화하는 과정에서 필요합니다.
그러나 블록 다이어그램만 그려놓고 RTL 코딩을 하기에는 부족합니다. 충분히 숙련된 엔지니어라면 간단한 모듈 정도는 RTL에서 설계하지 않아도 머릿속에 대충 떠오를 테지만 초보자가 블록 다이어그램만 그려놓고 코딩하는 것은 설계하지 않고 바로 구현하는 것과 마찬가지죠. 설계하는 역량을 키우기 위해서는 RTL에서 회로도를 그려보는 게 중요합니다.
RTL 기호
Wires
선으로 표시하되, 1bit이 아닌 경우 /
표시와 함께 bitwidth를 적어줍니다.
Combinational Logics
다양한 표현 방식들이 존재합니다. 보통 사각형, 원, ALU 기호(V) 등 다양한 방식들이 사용됩니다. ANSI/IEEE Std. 91-1984와 같은 표준 그래픽 기호들도 있고, 경우에 따라 특정 로직들은 특수한 기호를 사용하는 경우가 있습니다. 예를 들어 mux나 demux 같은 경우는 사다리꼴 기호를 사용합니다. shift 로직을 기울어진 직사각형으로 표현하는 경우도 있지만 널리 쓰이는 표현은 아닌 듯합니다.
아래는 제가 선호하는 표현 방식입니다. 저는 간단한 로직(+, -, *, …)들은 원으로, 조금 복잡한 로직은 사각형으로 표현하는 것을 선호하고, mux와 demux는 사다리꼴을 사용합니다. 이 부분은 정답이 없으니 원하는 스타일을 정해서 사용하시면 될 것 같습니다.
참고로, 구름 모양을 사용하는 경우도 있습니다. 보통 구체적인 연산이 정해진 경우가 아니라 그냥 모종의 comb logic을 의미할 때 사용하는 경우가 많습니다. 설계하는 과정에서 아직 잘 모르는 부분은 구름으로 표시해놓을 수 있습니다.
Registers (flip-flops)
플립플롭은 아래와 같이 표현합니다. 사각형에 클럭 신호 입력 기호 >
가 추가된 게 특징입니다.
필요한 기능에 따라 enable이 있을 수도 있고, reset이 없을 수도 있고, 여러 변형이 있습니다. 레지스터도 보통 플립플롭과 같은 기호를 사용합니다.
SRAM(BRAM)
Synchronous SRAM(ASIC)이나 BRAM(FPGA)를 사용하는 경우 레지스터와 같은 기호를 사용하되, 필요한 신호들을 추가하여 사용하면 될 듯합니다.
Leave a comment