HDL(Hardware Description Language)
- 반도체 및 전자설계 사업에서 전자 시스템을 모델링하기 위한 언어
- VHDL과 verilog HDL이 IEEE의 표준 HDL로 지정됨
- 디지털 시스템의 모델링, 일부 아닐로그 회로에서 사용
기능:
- 시물레이션 (sumulation)
- 서류화 (documentation)
- 합성 (synthesis)
언어 특성
- 동시성 (concurrent)
- 병렬성 (parallel)
- 추상화 (abstraction)
C언어와 매우 유사함
- 절차형 및 순차형 실행은 동일
- if else문(절차형에서 사용), case, for loop문 등을 사용
- 연산자: 논리(&,|,^), 산술(+,-,*,/), 비교(<,>,==)
차이점
- 동시성(concurrent): 대표적으로 always문
- 병렬성(parallel)
구조적 (Structural) 모델링: 코드길이의 간소화와 가독성이 좋음
- 논리 게이트, 플립플롭 등을 사용한 연결도 표현
- 기존 설계한 회로를 포함한 네트리스트(netlist) 사용
Dataflow 모델링
- 시간 개념이 없음(Clk의 영향을 받지 않음)
- Data 입력에 의해서 출력값 결정
- 대표적으로 assign 문
- 조합회로에 이용(and, or, not)
동작적(behavioral) 모델링
- if~else, case, while, for 등과 같은 구문 사용
- 인간의 사고에 가장 근접한 표현
if(a!=b) = 1bit;
else y = 1^b0
둘은 같은 동작이지만 가독성은 동작적 모델링이 더 좋음
- 시뮬레이션 (simulation) : full set
- 문서화 (documentation) : full set
- 합성( synthesis) : subset
- Library : system 함수
설계흐름도와 추상화 레벨
Verliog 문법
Half Adder 설계
진리표
논리식
S = x xor y
CO = x and y
Half Adder 모듈 정의
회로도
모듈구조
-> TestBench의 경우, Port_list가 없음
Half Adder 구조적 모델링
Half Adder Dataflow 모델링
- bitwise 연산의 경우, bit별로 연산을 진행함
ex)
wire[3:0] y,a,b;
assign y = a & b;
위와 코드가 같다면 a & b연산을 bit 별로 진행 즉, 4번의 and 연산을 진행한다.
- always의 경우, 조건에 맞을 경우, 항상 실행
- begin end는 2줄 이상 코딩할 경우, 필수로 들어가야 됨
- 연산자를 이용하지 않고 switch-case 문을 사용 -> Mapping 형식으로 코딩 -> 랜덤코드를 생성할 경우, Mapping 형식이 좋음
테스트 벤치
Stimulus Generation:
DUT: 작성한 코드
Response Monitor: 출력에 대한 반응
timescale의 앞에 시간에 맞춰서 sclae됨
reg는 주로 입력용
wire는 주로 출력용
시뮬레이션을 보기위해 $stop을 사용함
`timescale 1ns/1ps
- 컴파일러 지시어(directive)
- time 변수에 대한 시간 단위 설정
- time_unit/time_precision
- 사용 가능한 단위
-> s(second), ms(millisecond),
-> us(microsecond), ns(nanosecond),
-> ps(picosecond), fs(femtosecond)
-> initial begin ~ end
- 절차형 블록문
- reg 변수에 시간적으로 변하는 신호 생성
- 필요에 따라 원하는 파형의 순차적생성
- 시뮬레이션의 시작에서 한번 실행
- 시간 값은 누적 증가
// DUT 인스턴스
HA_b U1 (.x(x), .y(y), .co(cout), .s(sum) );
- HA_B 모듈의 포트에 신호연결
$finish;
- 시뮬레이터 실행 종료
- 시스템 task 함수
- $stop, $monitor, $display, $write 등
-> Half Adder의 경우, Carry 입력(올림값)이 없음 -> 이것을 보완한 것이 Full Adder
Verilog 어휘 규칙
Case sensitive
여백(white space)
- 빈칸(blank, space), 탭(tab), 줄바꿈, EOF
- 어휘 토큰들을 분리하기 위해 사용되는 경우를 제외하고는 무시
- 공백(blank)과 탭은 문자열에서는 의미 있게 취급
주석(comment)
- HDL 소스코드의 설명을 위해 사용되며, 컴파일과정에서 무시됨
- 단일 라인 주석문; // 로 시작되어 해당 라인의 끝까지
- 블록 주석문; / ~ / 로 표시, 여러 줄에 사용가능
- 블록 주석문은 내포(nested)될 수 없음
연산자(operator)
식별자(identifier)
- 객체에 고유 이름을 지정하기 위해 사용
- 대소문자 구별하여 인식
- 가독성을 위해 밑줄 사용 가능
- 단순 식별자: 일련의 문자, 숫자, 기호 $, 밑줄 등으로 구성
-> 첫번째 문자는 문자( a~z 및 A~Z ) 혹은 밑줄( _ )만 사용 가능
- 확장 식별자(escaped identifier);
-> \ (back slash)로 시작되며, 여백(빈칸, 탭, 줄바꿈) 등으로 끝남
-> 프린트 가능한 ASCII 문자들을 식별자에 포함시키는 수단을 제공
키워드(keyword)
- Verilog 구성 요소를 정의하기 위해 미리 정의된 식별자
- 확장문자가 포함된 키워드는 키워드로 인식되지 않음
Verilog 예약어
Verilog 논리값
0: Zero, Low, False
1: One, High, True
Z: High Impedence
X: Unknown, Uninitialized
논리 강도
Strength level이 높을 수록 강도(우선 순위)가 높다
정수표현
- 정수형(integer)
-> 10진수 'd
-> 2진수 'b
-> 8진수 'o
-> 16진수 'h
ex) 4'hC == 4'b1100 == 4'd12 == 4'o14
실수표현
문자열
- ""사이의 문자열
- unsigned 정수형으로 취급됨
- reg형 변수이며, 문자열 내의 문자 수에 8을 곱한 크기의 비트 폭을 가짐
모듈구성
- 설계의 기본단위
always 내부의 출력값은 register형으로 선언으로 해주어야한다.
일반적인 경우, wire로 선언되는데 이는 netlist형이므로 register형의 출력을 쓰기 위해서는 반드시 선언이 필요하다
모듈의 정의
암시적 내부연결: 모듈내부에서 사용되는 이름과 밖에서 보이는 모듈이 같은 것
명시적 내부 연결: 밖에서 사용되는 이름과 모듈 내부에서 사용되는 이름이 다른 경우
-> 주로 Bus 형식으로 연결할 때 사용
Module Item
- Module Port 선언은 반드시 되어야함
- data type 경우, 모두 입력이 wire인 경우, 생략가능
- 기술순서와 무관하기 때문에 위에서 사용되는 구문을 아래서 선언해도 문제가 없음
포트선언
ex)
parameter-> 변수를 여러 형식으로 대체
Data type
net
- 설계 부분의 사이에서 물리적인 연결을 만들 때 사용하는 개념
- net는 net의 구동자(driver)의 값과 strength level이나 혹은 net의
capacitance, 혹은 그 자신의 값을 가지지 않은 것을 그대로 반영
- 한 개의 net를 구동하는 여러 개의 구동자가 있을 경우에는 최종값을 결
정하는 resolution 함수 필요
variable type
- 프로그래밍 데이터의 임시적 저장소로 사용되므로 레지스터(register) 데이터형이라고도 한다.
-> 하지만 reg가 항상 저장의 의미를 가지지 않는다.
-> Clk가 있을 경우에만 Flip-Flop으로 만들어짐
-> always내에서 쓰일 경우에는 wire(단순 gate)의 역할을 한다
- initial 블록, always 블록, 태스크나 function과 같은 프로시듀어의 내부에
서만 값을 할당받을 수 있다.
- 논리값만 저장할 수 있으며 논리 strength는 저장할 수 없다.
- 변수는 시뮬레이션의 시작에는 비초기화(un-initialized)되고, 값이 할당
되기 전까지는 논리 X의 값을 유지한다.
Data type 선언
ex) reg[8:0] t_mem[0:127] -> 8 bit의 t_mem이 128개가 만들어진 배열
- net_type [size] #(delay) net_name [array_size]에서 #delay는 배선에서 발생하는 지연을 의미
레지스터형
- 프로시듀어 블록내 절차형 할당에서 좌변 변수로 사용
- 할당과 할당 사이의 값을 유지
- reg 변수가 하드웨어적인 저장장소를 의미하는 것은 아님
ex)
-> reg [7:0] A[0:3][0:15]; 8bit 변수가 4개가 있으며, 그 4개의 8bit 변수는 16묶음이 있는 것
-> reg clk = 0, rst = 1; 값은 시뮬레이션을 위해 값을 주는 것
reg type이 저장소로 쓰이는 경우와 쓰이지 않는 경우
q <= d;
q = d;
net형
- 어떤 소자의 출력에 의해 구동되는 신호
- 입력(input) 포트나 입출력 포트로 선언되는 신호
- 연속할당문의 좌변(LHS, Left Hand Side) 신호로 사용
- 연속할당문의 우변(RHS, Right Hand Side) 구동자가 연결되지 않으면 default 값인 high-impedance(z) 값이 됨.
- default 자료형 : 1 비트의 wire
- default 초기값 : z, 단 trireg는 x
모듈의 신호연결
- I/O port를 사용할 경우, Input이 동시에 Output이 되는 경우를 방지해야한다
-> I/O Port는 오직 wire만 사용가능
ex)
net 선언의 진리표
그외의 데이터형
ex)
백터형
-
net나 reg 형의 다중 비트 선언
-
선언 형식
-
동일한 데이터의 1차원 혹은 2차원 정의
-
벡터는 단일 객체이나 배열은 다중객체(object)
-
배열로 선언될 수 있는 데이터 : reg, net, integer, time
-
선언형식
-
배열 전체 또는 일부분은 단일 할당문에 의해 값을 할당 받을 수 없으며
또한 수식에 사용될 수 없다.
-> 배열을 구성하는 요소에만 단일 할당문으로 값을 할당받을 수 있다.
ex)
-
전체 배열에 쓰는 것이 불가능하다
-
다중 배열에서 memb[1] = 0; 이런식으로 사용불가
-> 정확한 위치를 표기해줘야함 ex)memb[1][0] = 0;
Verilog 연산자
- 일반적인 논리 쉬프트이 경우, 음수, 또는 양수의 부호를 나타내는 MSB가 바뀌는 문제가 있음
- 산술 쉬프트의 경우, 부호bit(MSB)를 계속해서 패딩해줌
-> 부호가 없는 unsigned에서는 논리 shift처럼 동작(패딩 X)
-> reduction의 경우, 우측에 있는 모든 bit를 한번에 연산함