RTL 설계 직무 면접 가이드 시즌 2: Reset, FIFO, Formal, STA
시즌 1에서 다룬 주제에 이어 reset 해제, 동기식과 비동기식 FIFO, formal property, STA 제약 조건을 설계 판단 중심으로 정리합니다.
RTL 면접 시즌 2에서는 코드 문법보다 설계의 경계 조건을 설명하는 연습을 해보자. reset을 어떻게 풀어야 하는지, FIFO가 가득 찬 사이클에 읽기와 쓰기가 겹치면 어떻게 되는지, assertion이 무엇을 증명하는지, 타이밍 예외를 언제 둘 수 있는지가 자주 이어지는 질문이다.
시즌 1 면접 가이드는 STA 기본, CDC, AXI 파이프라이닝, 합성 코딩, 저전력을 다뤘다. 이번 글은 그 설명을 반복하기보다 reset, FIFO, formal 검증, 제약 파일처럼 설계 의도를 구체적으로 말해야 하는 주제를 이어서 정리한다.
1. Reset 해제는 왜 동기화해야 하나
Q1. 비동기 reset을 사용하는 회로에서 reset을 해제할 때 어떤 점을 확인해야 하나요?
💡 답변의 핵심
비동기 reset은 클럭이 멈춰 있거나 아직 안정되지 않은 동안에도 회로를 초기 상태로 만들 수 있다. 하지만 reset 해제 시점이 클럭 에지와 가까우면 플립플롭의 recovery/removal 조건을 위반할 수 있다. 따라서 비동기 reset을 사용하는 설계에서는 assertion과 deassertion을 구분해 설명해야 한다.
흔히 쓰는 구조는 reset을 비동기로 assert하고, 각 클럭 도메인에서 동기화기를 거쳐 deassert하는 방식이다. 이렇게 하면 reset은 빠르게 전달하면서도 각 도메인의 상태 레지스터는 해당 클럭에 맞춰 reset에서 벗어날 수 있다. 클럭 도메인이 여러 개라면 각 도메인에 맞는 reset 해제 동기화가 필요하다.
외부 reset
├── 비동기 assert → 도메인 A reset 해제 동기화기 → 도메인 A 로직
└── 비동기 assert → 도메인 B reset 해제 동기화기 → 도메인 B 로직
🛠️ 꼬리 질문: 모든 레지스터를 reset해야 하나요?
항상 그런 것은 아니다. reset 대상은 블록의 초기 동작 계약과 구현 구조에 맞춰 정한다. 제어 상태와 valid 비트는 초기화가 필요할 수 있지만, 큰 데이터 배열은 모든 비트를 reset하는 대신 유효 상태를 초기화하거나 초기화 시퀀스로 처리할 수 있다. 메모리 매크로가 지원하는 reset 방식과 합성 결과도 함께 확인해야 한다.
면접에서는 "reset은 무조건 비동기" 또는 "모든 플롭을 reset"처럼 단정하기보다 다음을 짚으면 좋다.
- reset을 받는 클럭 도메인과 reset 해제 시점
- reset 해제 중 출력과 인터페이스가 어떤 값을 보여야 하는지
- reset된 블록과 reset되지 않은 블록 사이의 handshake
- reset synchronizer가 합성 및 배치 단계에서 의도대로 보존되는지
2. FIFO의 full과 empty는 어떻게 정의하나
Q2. FIFO가 full 또는 empty인 사이클에 read와 write 요청이 함께 들어오면 어떻게 처리해야 하나요?
💡 답변의 핵심
먼저 인터페이스에서 실제로 수락된 요청을 정의한다. 예를 들어 write_accept = write_req && !full, read_accept = read_req && !empty라면 점유량은 다음과 같이 변한다.
| 수락된 동작 | 점유량 변화 |
|---|---|
| write만 수락 | 1 증가 |
| read만 수락 | 1 감소 |
| read와 write 모두 수락 | 변화 없음 |
| 둘 다 수락되지 않음 | 변화 없음 |
동시에 read와 write가 수락되면 기존 데이터 하나가 빠지고 새 데이터 하나가 들어오므로 점유량은 유지된다. 하지만 FIFO가 full인 사이클의 동시 read/write를 허용할지는 인터페이스 계약에 따라 달라진다. 위 예시처럼 !full 조건으로 write를 막으면 같은 사이클에 read가 있어도 새 write는 수락되지 않는다. 반대로 같은 사이클의 read를 고려해 write를 허용하려면 full 판정과 메모리 동작을 그 의미에 맞게 설계해야 한다.
empty 상태의 동시 read/write도 계약을 정해야 한다. 위 예시처럼 !empty 조건으로 read를 막으면 write만 수락되고 새 데이터는 이후 사이클부터 읽힌다. empty일 때 입력 데이터를 바로 출력으로 전달하는 fall-through 동작을 지원하려면 bypass 경로와 handshake 동작을 별도로 정의해야 한다.
🧭 꼬리 질문: 동기식 FIFO와 비동기식 FIFO의 차이는 무엇인가요?
동기식 FIFO는 읽기와 쓰기가 같은 클럭 도메인에서 진행되므로 포인터와 점유량을 하나의 클럭 기준으로 관리할 수 있다. 비동기식 FIFO는 읽기와 쓰기가 서로 다른 클럭 도메인에서 진행되므로 각 측의 포인터를 상대 도메인에 안전하게 전달하는 구조가 필요하다.
비동기식 FIFO에서는 보통 포인터를 Gray code로 표현하고 동기화기를 거쳐 반대편에 전달한다. Gray code는 인접한 포인터 값 사이에서 한 비트만 바뀌게 해 다중 비트 포인터 전환 중 여러 비트가 서로 다른 시점에 샘플링될 위험을 줄인다. 데이터 버스 자체를 비트마다 2-FF 동기화하는 방식과는 다르다. FIFO의 데이터 저장소는 양쪽 도메인이 정해진 프로토콜에 따라 접근하고, 포인터와 상태 정보를 도메인 간 전달한다.
Gray code를 썼다는 사실만으로 물리적 구현 검토가 끝나는 것은 아니다. 포인터 비트의 배선 skew와 타이밍 제약, reset 이후 포인터 초기화, full/empty flag의 도메인별 동작을 확인해야 한다. 특히 full/empty 경계에서 read와 write가 동시에 들어오는 경우는 설계한 인터페이스 계약을 테스트와 assertion에 반영해야 한다.
3. Formal 검증은 시뮬레이션을 어떻게 보완하나
Q3. 시뮬레이션 테스트가 통과했는데도 formal 검증을 하는 이유는 무엇인가요?
💡 답변의 핵심
시뮬레이션은 선택한 입력 시나리오를 실행해 결과를 확인한다. Formal 검증은 설계의 입력과 상태에 제약을 두고, 지정한 property가 가능한 상태 전이에서 성립하는지 도구가 탐색한다. 둘은 대체 관계가 아니라 서로 다른 방식으로 설계의 결함을 찾는다.
예를 들어 ready/valid 인터페이스에서 송신자가 valid를 올렸는데 수신자가 ready를 내린 상태라면, 전송이 수락될 때까지 valid와 데이터가 유지되어야 한다는 조건을 property로 표현할 수 있다.
property hold_payload_while_stalled;
@(posedge clk) disable iff (!rst_n)
valid && !ready |=> valid && $stable(data);
endproperty
assert property (hold_payload_while_stalled);
이 property는 한 사이클 정체된 뒤에도 다음 샘플에서 valid와 data가 유지되는지 확인한다. 실제 설계에서는 reset 의미, handshake 규칙, 인터페이스의 허용 지연을 포함해 property를 검토해야 한다.
⚠️ 꼬리 질문: assertion이 통과하면 설계가 완전히 맞다는 뜻인가요?
아니다. property가 요구사항을 제대로 표현해야 하고, 환경 가정도 실제 시스템과 맞아야 한다. 가정이 지나치게 강하면 문제가 생기는 입력을 차단해 assertion이 통과할 수 있다. 반대로 필요한 가정이 빠지면 현실에서는 발생하지 않는 동작까지 검사할 수 있다.
Formal 결과를 설명할 때는 다음을 구분하면 좋다.
- Assertion: 설계가 만족해야 하는 조건
- Assumption: 검증 환경이 지켜야 하는 입력 조건
- Cover: 특정 상태나 시나리오에 도달 가능한지 보는 목표
- Bounded check: 정해진 깊이까지 반례가 있는지 탐색
- Proof: 설정한 모델과 가정 아래 property가 성립하는지 확인
도구와 설정에 따라 지원하는 property와 증명 범위가 다르다. 예를 들어 SymbiYosys 문서는 bounded 및 unbounded safety 검증, cover, liveness 검증 흐름을 구분해 설명한다. 면접에서는 "formal로 전부 증명했다"고 뭉뚱그리기보다 어떤 property를 어떤 가정과 범위에서 확인했는지 말하는 편이 정확하다.
4. 타이밍 예외는 언제 적용하나
Q4. setup violation이 있는 경로에 false_path를 걸면 해결된 것인가요?
💡 답변의 핵심
아니다. false_path는 해당 경로를 특정 타이밍 분석에서 제외하는 제약이지, 회로의 동작이나 지연을 고치는 명령이 아니다. 실제 기능 경로를 잘못 제외하면 타이밍 위반이 보고서에서 사라질 뿐, 실리콘에서의 동작 위험은 남는다.
타이밍 예외를 넣기 전에는 먼저 경로의 시작점과 끝점, 클럭 관계, 기능상 데이터가 샘플링되는 조건을 확인해야 한다. 예외를 적용한 뒤에는 의도한 경로만 선택됐는지, 예외가 다른 경로까지 넓게 퍼지지 않았는지 보고서로 확인한다.
면접에서 설명할 때는 다음 항목을 짚을 수 있다.
- primary clock과 generated clock이 올바르게 정의됐는가
- 입력 및 출력 지연이 외부 인터페이스 요구사항과 연결돼 있는가
- 비동기 clock group이나 CDC 경로를 어떤 기준으로 제외했는가
- multicycle path의 setup과 hold 관계를 함께 검증했는가
- unconstrained path와 예외 적용 경로를 별도 보고서에서 확인했는가
CDC 경로를 동기식 setup 분석에서 제외하더라도 CDC 구조 검증은 별도로 필요하다. 타이밍 예외가 CDC 안전성을 증명하지는 않는다. 반대로 Gray code 포인터처럼 비동기 FIFO에서 사용되는 신호는 일반적인 동기식 경로와 다른 물리 제약이 필요할 수 있으므로, 사용 중인 FPGA 또는 ASIC 툴의 CDC와 타이밍 제약 가이드를 함께 확인해야 한다.
면접 답변을 설계 조건으로 연결하기
시즌 2의 네 주제는 정답 하나를 외우는 것보다 입력 조건과 경계 동작을 어떻게 정의하는지가 중요하다. reset은 도메인별 해제 시점을, FIFO는 수락된 동작과 full/empty 경계를, formal은 property와 가정을, STA는 예외 적용 근거와 보고서 범위를 설명해야 한다.
답변할 때는 먼저 동작 계약을 말하고, 정상 조건과 경계 조건을 나눈 다음, 검증 방법을 덧붙여 보자. 실제 프로젝트 경험이나 수치를 확인하지 못했다면 경험담으로 만들지 않고 설계 원리와 검증 관점으로 설명하면 된다.
관련 주제의 기본 질문은 RTL 설계 직무 면접 가이드 시즌 1에서 이어서 볼 수 있다.