Verilog HDL 구문
논리 합성용 구문 | assign, if ~ else , case , for , always 대부분의 논리합성 툴에서 게이트 수준 합성을 지원하는 구문들이다. |
Simulation용 구문 | initial , $finish , $fopen 시뮬레이션을 위한 테스트벤치의 작성에 사용되며, 논리합성이 지원되지 않는다. |
Library용 구문 | specify , $width , table 논리합성에 적용되는 셀 라이브러리 설계에 사용되며, 셀의 기능, 지연, 핀 정보 등을 정의하는 데 사용된다. |
Verilog HDL의 모듈 : Verilog는 module을 기본단위로 하여 구성된다.
module : 특정한 목적을 위해 묶어진 변수들과 함수들의 모임이라고 생각하면 쉽고, 하나의 라이브러리 개념
port : 컴퓨터 하드웨어에서는 컴퓨터와 다른 컴퓨터, 장치 사이의 인터페이스 역할을 담당
베릴로그에서 '포트'란 모듈과 모듈을 연결하는 인터페이스의 의미를 지닌다.
instance : 베릴로그에서 모듈과 함께 등장하여 자주 등장하는 용어이다. 이는 객체지향 프로그래밍 언어가 지니는 특성을 알면 쉽게 이해할 수 있다.
하나의 객체 형식을, 즉 틀을 만들고 그 틀로 찍어내는 하나 하나의 객체를 인스턴스라 칭하며 instance(예시)의 개념으로 이해하면 된다.
베릴로그에서 하나의 모듈을 구성할 때, 기존의 다른 모듈 형식을 가져와 같은 기능과 동작을 하는 하나의 객체를 선언하여 이용하는 것을 '하위 모듈을 인스턴스한다'라고 표현한다.
<머리부> 모듈이름과 포트목록들을 지정 module module_name (port_list); <- semicolon <선언부> 포트목록에 나열된 포트들의 방향, 비트 폭, 자료형 및 parameter 선언 등 모듈에서 필요로 하는 것들을 선언 port 선언 reg 선언 wire 선언 parameter 선언 <몸체부> 회로의 기능, 동작, 구조 등을 표현하는 다양한 베릴로그 구문( 위 3가지 구분의 구문 )들로 구성 하위 모듈 호출 always, initial 문 function, task 정의문 assign 문 function, task 호출문 endmodule <- no semicolon |
베릴로그의 몸체에서 이뤄지는 회로 설계 모델링에서는 여러 가지 모델링 방법이 있어서 같은 회로를 출력하는 데에도 다양한 표현 방법이 존재한다.

- 게이트 primitive 이용한 모델링(회로 표현) : 코드를 보면 알 수 있듯이 xor, nand, not의 게이트 프리미티브를 인스턴스하였다. 간단한 예시 > and (wire a, a.b); module half_adder (input a, b, output sum, cout, wire cout_bar) ; xor (sum, a, b); nand (cout_bar, a, b); not (cout, cout_bar); endmodule ![]() |
- 할당문을 이용한 모델링 : 게이트를 게이트로 표현하지 않고 연산으로 표현 ( wire a = a&b; ) module half_adder (input a, b, output sum, cout) ; assign cout = a & b ; assign sum = a ^ b ; endmodule 베릴로그의 연속 할당문은 assign 문으로 표현되며, 할당 기호 =의 좌변의 신호에 우변의 결과 값을 할당한다. |
- 행위적 수준 모델링 : 행위수준 모델링은 조합회로와 순차회로의 모델링에 폭넓게 사용되고 위의 논리식에서는 always 문과 그 내부에 if ~ else 문을 이용하여 반가산기의 기능을 모델링하였다. module half_adder (input a, b, output sum, cout) ; always @ (a or b) begin >> always 구문 @뒤에 조건이 참일 때 실행 if (a == 0 && b == 0) begin >> begin과 end는 c에서 열고 닫는 중괄호와 비슷 sum = 0; cout = 0; end else if (a == 1 && y == b) begin sum = 0; cout = 1; end else begin sum = 1; cout = 0; end end endmodule wire = '선' reg = '레지스터' 라고 우선 생각을 한다. wire는 실제 wire 처럼 단지 어떤 모듈과 모듈을 이어주는 선에 불과하고 reg은 실제로 레지스터처럼 어떤 신호에 영향을 받아 바뀌는 값이라고 생각. 따라서 always문 안에서만 reg값의 변경이 가능하고 wire 값은 그 자체로 변경이 불가능하다. 단지 선을 연결하거나 and나 or등의 모듈로 나온 선을 잇는 것만 가능 |
하위모듈들을 인스턴스하여 이용하는 구조적 모델링 몸체부에서 half_adder U1 (); 으로 반가산기의 기능을 하는 객체를 형성할 수 있다. ![]() |
Verilog 어휘 규칙
어휘 토큰 : 여백 , 주석 , 연산자, 수, 문자열, 식별자, 키워드
여백
- 빈칸, 탭 ,줄바꿈
- 어휘 토큰들을 분리하기 위해 사용되는 경우를 제외하고는 무시
- 공백과 탭은 문자열에서 의미 있게 취급
주석
- 단일라인 // , 블록 주석문 /* */
연산자
- 단항 연산자 2,3항 연산자
수 표현
![]() |
-'d12 : s가 없으니 unsigned인데 앞에 - 가 붙어있는건 부호화 작업을 하라는 것
default 32 bit에 10진수 12표현 하면
00000000 | 00000000 | 00000000 | 00001100 | 이렇게 되는데 부호화 해주면 |
11111111 | 11111111 | 11111111 | 11110011 | 이렇게 되지만 2의보수로 표현하기 때문에 +1 해주면 |
11111111 | 11111111 | 11111111 | 11110100 | 이렇게 되는데 unsigned표현이라 42억~...이 된다 |
-'sd12 : signed표현이고 10진수 표현이니 -12가된다 ( s는 부호의 표현에만 영향을 미친다.)
4'shf : 4비트표현 signed 16진수 f니까 1111이고 2의 보수로는 -1이 된다.
문자열
- 이중 인용 부호(“ ”) 사이에 있는 일련의 문자들
- 단일 라인에 존재해야 하며, 여러 라인에 걸친 문자열은 사용 불가
- 8비트 ASCII 값으로 표현되는 unsigned unsigned 정수형 상수로 취급
- 문자열 변수는 reg형의 변수이며, 문자열 내의 문자 수에 8을 곱한 크기의 비트 폭을 가짐
reg [8*12:1] string_var; initial begin string_var = "Hello world!"; end |
- 특수 문자 앞에 확장 문자를 사용하면 일부 특수 문자를 문자열에 포함시킬 수 있음 ( \n, \t, \\, \" )
식별자
- 객체에 고유의 이름을 지정하기 위해 사용
- 대소문자를 구별하여 인식
- 가독성을 위해 밑줄 사용 가능
- 단순 식별자; 일련의 문자, 숫자, 기호 $, 밑줄 등으로 구성 (첫번째 문자는 숫자와 $ 사용 불가 , 문자나 밑줄만 가능)
- 확장 식별자; \로 시작되며, 여백( 빈칸 , 탭 , 줄바꿈) 등으로 끝이 나며, 프린트 되는 ASCII 문자들을 식별자에 포함시키는 수단을 제공
유효한 식별자의 예 확장 식별자의 예
shiftreg_a busa_index error_condition merge_ab _bus3 n$657 |
\busa+index \-clock \***error-condition*** \net1/\net2 \{a,b} \a*(b+c) |
키워드
- Verilog 구성 요소를 정의하기 위해 미리 정의된 식별자
- 확장문자가 포함된 키워드는 키워드로 인식되지 않음
'study > Logic Circuit' 카테고리의 다른 글
할당문 (0) | 2020.10.25 |
---|---|
게이트 수준 Modeling (0) | 2020.10.10 |
Verilog 연산자 (0) | 2020.10.10 |
Verilog 자료형 (0) | 2020.10.08 |
기본 (0) | 2020.10.07 |