임베디드 스터디 - Verilog 기초
임베디드 스터디 - Verilog 기초
Verilog
- C 언어 스타일의 문법을 바탕으로 구현되는 HDL(Hardware Description Language)
module키워드를 통해 하드웨어 모듈을 정의- 검증 및 테스트밴치용 코드를 작성할 때는 SystemVerilog를 더 많이 사용한다.
Software VS HDL
- C를 예시로 들어보자. 아래 예시 코드를 통해 소프트웨어와 HDL의 차이점을 확인할 수 있다.
1
2
3
a = 1;
b = 2;
c = a + b;
- C : 각 라인에 해당하는 코드에 대해 컴파일, 빌드 과정을 거쳐 컴퓨터의 프로세서에 명령 입력이 하나씩 수행되어, 최종적으로 변수
c에 해당하는 메모리에a+b에 대한 값이 저장된다. - HDL :
a+b라는 논리회로를 구성하고,a와b를 입력라인에,c를 출력 라인에 연결한다. - 결론 : Verilog와 같은 HDL은 코드를 실행하는 것이 아니라 하드웨어를 구성하는 것이다.
모듈 (Module)
- Verilog의 하드웨어 설계 단위, 하나의 회로 블록
module~endmodule사이에 회로 내용을 작성- 모듈 이름 옆 괄호에 입출력 포트 정의
assign으로 출력 정의
1
2
3
4
5
6
7
8
9
module and_gate (
input wire a,
input wire b,
output wire y
);
assign y = a & b;
endmodule
포트 (Port)
- 포트는 총 3가지 종류가 있다.
- input : 입력 전용
- output : 출력 전용
- inout : 양방향 포트
- inout은 $I^{2}C$ SDA와 같은 통신 버스에 사용된다.
데이터 타입
- wire : 포트 간 연결에 사용된다. 조합논리회로의 출력 포트 정의 시
wire를 사용한다. - reg :
always@()블록에 들어가는 신호.reg는 always 블록에서 대입 가능한 변수이며, 실제 합성 결과(FF or 조합회로)는 sensitivity list가 결정한다
assign vs always @()
- assign : 단순 연결. 조합논리회로 구성에 사용
- always : 순서논리회로, 조합논리회로 구성 가능
Clock Domain Crossing
- 회로를 설계하면서 여러 개의 클럭 신호를 바탕으로 다양한 모듈을 동작시켜야할 수도 있다.
- 2개 이상의 다른 클럭 신호를 바탕으로 구성된 하드웨어를 CDC(Clock Domain Crossing), MCD(Multi Clock Domain)이라 한다.
- 각기 다른 클럭 동작으로 인해, 서로 다른 클럭으로 동작하는 FF의 셋업/홀드 타임 위반이 발생할 수 있다.
메타스태빌리티 (Metastability)
- CDC에서 발생하는 FF 셋업/홀드 타임 위반에 의해, FF에 0도, 1도 아닌 어중간한 데이터가 발생하게되는 상태
- 일정 시간이 지나면 스테이블 상태로 데이터가 변화한다.
- 메타스태빌리티 해결에 동기화 체인(Synchronizer)이라는 직렬 FF 여러 개(2~3개)를 사용한다.
- 1단 FF : 비동기 신호 샘플링 → 셋업/홀드 타임 위반 가능 → 메타스태빌리티 진입 가능
- 2단 FF : 1단 FF가 stable 상태로 수렴할 시간(한 클럭)을 확보 → 안정된 값 샘플링
- CDC에서 메타스태빌리티를 완전히 제거하기는 어렵기에, MTBF(Mean Time Between Failures)를 설계 요구사항 이상으로 구현하는게 목표다.
래치 추론 (Latch Inference)
- 아래 Verilog의
if~else은 모든 조건에 대해 출력이 정의되지 않은 형태로 구성되어 있다.
1
2
3
4
5
reg y;
always @(*) begin
if (sel)
y = a;
end
- 이러한 형태로 코드를 작성하는 경우, 합성기는
sel==0에서 y가 이전 데이터를 유지하도록 래치 회로를 구성한다. 이렇게 의도하지 않은 형태로 합성기가 해석하여 회로를 구성하는 경우를 래치 추론이라 한다.- 합성기의 입장에서 해당 코드에 문법적 오류는 없다.
- 래치 회로는 비동기 회로다. 즉, 타이밍 클로저(Timing Closure) 문제가 발생해 셋업/홀드 타임 위반을 확인할 수가 없다.
- 해결 방법은 각 조건에 대한 출력을 모두 명시해주면 된다.
1
2
3
4
5
6
7
8
9
10
11
// 해결책 1: else 분기 명시
always @(*) begin
if (sel) y = a;
else y = b;
end
// 해결책 2: default 값 선언
always @(*) begin
y = 1'b0; // default
if (sel) y = a;
end
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.