Verilog HDL Summury by 강석태 2006 년 3 월 1
Module module < 모듈이름 >(< 포트리스트 >) < 모듈내용 > endmodule C 언어의함수 (Function) 와같은개념. 대소문자구분. 예약어는소문자로만쓴다. 이름은영문자, 숫자, 언더바 (_) 만허용한다. 문장의끝은항상세미콜론 (;) 으로끝난다. end~ 로시작하는예약어에는 ; 이붙지않는다. 하나의 File은하나의 module만포함시킨다. 파일이름은 module의이름과동일하게한다. 2
Module 모듈선언예제 module Adder (X, Y, C, S); input X, Y; // 입력포트선언 output C, S; // 출력포트선언 wire C, S; // 레지스터, 와이어선언 assign C = X & Y; // 모듈내용 assign S = X ^ Y; endmodule 3
기초문법 begin ~ end initial, if, case, always 등을사용할때블록을지정할때사용한다. C 언어에서 { } 와같은개념이다. 주석 // : 한줄을 comment 처리할때사용. /* ~ */ : 여러줄을 comment 처리할때사용. 수표현 < 비트폭 > < 진수 >< 값 > : 8 hfb < 진수 > : b - 2 진수, d - 10 진수, h - 16 진수 음수는 2 complememt 사용 언더바 (_) : 가독성을좋게함. (2 b1100_0101) 4
기초문법 벡터 (Vector) 멀티비트 (Multi-bits) 또는버스 (bus) 라고도한다. 예약어 [MSB:LSB] 이름 예약어 : input, output, reg, wire input [3:0] A, B; input [7:0] ABUS; wire [2:0] status; assign C = ABUS[7]; assign D = ABUS[0]; wire [3:0] H_digit; assign H_digit = ABUS[7:4]; 5
테스트벤치 (Testbench) 정의 시뮬레이션을위한모듈이다. 설계한 DUT 를검증하기위한목적으로사용한다. DUT 를내포하고있으며 DUT 의입력값을생성하고, 출력값을관찰한다. < 테스트벤치 > 입력신호생성 검증대상 DUT 출력신호관찰 6
테스트벤치 시스템기능연산자 테스트벤치에서만사용한다. $ 기호로시작한다. $stop 시뮬레이션정지 $finish 시뮬레이션끝 $time 현재시뮬레이션시간을얻는다. $monitor, $display 특정값을디스플레이할때사용한다. Initial begin #300; $finish; end 7
테스트벤치 `timescale 문 `timescale < 테스트벤치스텝단위 >/< 시뮬레이션스텝단위 > ex) `timescale 1ns/1ps 테스트벤치상단에서시간단위를지정해준다. 문장의끝에세미콜론이붙지않는다. 테스트벤치스텝단위는시간지연등을사용할때의단위이다. 예를들어 `timescale 1ns/1ps 로선언을하였을경우테스트벤치에서 #30의의미는 30ns를의미한다. 시뮬레이션스텝단위는시뮬레이션후 timing diagram 에서보여지는시간의 resolution 을결정한다. 8
테스트벤치 initial 문 순차적으로한번만실행시킬때사용된다. 테스트벤치에서만사용이가능하다. 시간지연 initial 문과함께사용하여 DUT 의입력값을생성할수있다. initial begin // 30[ns] 동안X의값을1로유지시킨다. X = 1; #30; end 9
데이터형 (Data Type) wire 논리적인기능이나행동없이단순한선을의미. 물리적인 wire를의미. 게이트나모듈간의입력과출력을연결할때사용. wire로선언된 signal은 assign 문에서만사용가능하다. reg 순차회로에서사용할때에는플립플롭이된다. reg로선언된 signal은 always 문에서만사용가능하다 테스트벤치에서는 initial 문에서사용한다. 새로운이벤트가발생하기전까지기존의값을유지한다. 10
데이터형 (Data Type) parameter 상수를정의할때사용한다. parameter WIDTH = 32; parameter LENGTH = 8'h16; parameter MASK = 4'b1010; 11
연산자 산술연산자 + 덧셈 비트연산자! 비트 NOT - 뺄셈 & 비트 AND * 곱셈 비트 OR 관계연산자 == 같다 ^ 비트 XOR!= 같지않다 시프트연산자 >> 오른쪽 shift < 작다 << 왼쪽 shift <= 작거나같다 그외연산자? : 조건연산자 > 크다 { } 결합연산자 >= 크거나같다 논리연산자 && 논리 AND 논리 OR! 논리 NOT 12
연산자 조건연산자의예제 assign Y = (A>B)? A : B; A 가 B 보다크면 Y 에 A 값을할당, 그렇지않으면 B 를할당. 결합연산자의예제 assign Y[7:0] = {A[3:0], B[3:0]}; 4비트짜리 A,B를결합하여 8비트짜리 Y를만든다. Y의 MSB 자리에 A, LSB 자리에 B가들어간다. A가 4 ha 이고, B가 4 he이라면 Y의값은 8 hae 가된다. 13
조건문 (if 문 ) if 문 항상 always 문안에서만사용이가능하다. 문장이 2줄이상이되는경우는 begin ~ end로묶어준다. C 언어에서의 if ~ else 문과같다. if(< 조건식 >) 문장 1 else 문장 2 조건식이참이면문장1을실행하고, 거짓이면문장2를실행한다. else if를사용하여조건을추가할수도있다. 14
조건문 (case 문 ) case 문 항상 always 문안에서만사용이가능하다. 각항의문장이 2줄이상인경우는 begin ~ end로묶어준다. C 언어에서의 switch ~ case 문과같다. case( 판정식 ) 항1 : 문장1; 항2 : 문장2;... default : 문장N; 판정식이항1과같으면문장 1을수행, 항2와같으면문장 2를수행, 모든항과같지않으면 default의문장n을수행한다. endcase 15
조합회로 assign 문 조합회로에서값을할당할때사용한다. assign 문으로값을받는 signal 은 wire 로선언되어야한다. assign 문은 = 기호를사용한다. ex) wire [7:0] Y; assign Y = A + B; 16
조합회로 조합회로의 always 문 조합회로에서특정조건문을사용하고자할때 always 문을쓴다. always 문으로값을받는 signal 은 reg 로선언되어야한다. 하나의 signal 을 2 개이상의 always 문에서값을바꾸어서는안된다. if 문, case 문사용할때 else 또는 default 문장을절대로빠뜨리지않아야한다. 17
조합회로 조합회로 always 문예제 (1) always @ (< 이벤트리스트 >) begin.. end 이벤트리스트에는 always 문이동작하기위해필요한 signal 이모두포함되어야한다. 이벤트리스트를쉽게구분하는방법은 = 을중심으로우측항에있는 signal 과 if 문또는 case 문의조건에사용되는 signal 을포함시키면된다. 18
조합회로 조합회로 always 문예제 (2) always @ (A or B) begin if(a>b) Y = A; else Y = B; end always @ (alpha or beta or A or B) begin if(alpha < beta) Y = A; else Y = B; end 19
조합회로 조합회로 always 문예제 (3) wire [3:0] DEC; reg [3:0] Y; always @ (DEC) begin case(dec) 4'h1 : Y = 4'b0001; 4'h2 : Y = 4'b0010; 4'h4 : Y = 4'b0100; 4'h8 : Y = 4'b1000; default : Y = 4'b0000; endcase end 20
조합회로 조합회로설계시주의할점 Feedback 무한루프발생금지. assign 문, always 문동일 A = A + 1; // 에러 A[1] = A[0] & x; A[2] = A[1] & A[0]; 해결 이문장은 Tool 에따라서허용이되는경우도있다. 그러나가급적이와같은문장은사용하지않도록한다. 순차회로로변경한다. (A <= A + 1) 조합회로의경우는 signal 이름을분리하여사용한다. Ex> A1 = A0 & x; A2 = A1 & A0; 21
순차회로 순차회로의 always 문 (1) 순차회로의구현은반드시 always 문을사용. always 문에서값을할당받는 signal 은 reg 로선언한다. always 문에서이벤트리스트에는 clock 과 reset 만사용한다. 순차회로에서는논 블락킹대입문 ( <= ) 을사용한다. "<=" 의특징은 begin ~ end 블록의여러문장들이동시에수행된다는것이다. 22
순차회로 순차회로의 always 문 (2) reset 의동작은가능한 negative edge(negedge) 를사용한다. always 문에서사용하는 reg 는플립플롭이기때문에반드시 reset 이필요하다. always 문내의시작은항상 reset 동작을수행하도록한다. 하나의 module 에서여러개의 always 문이사용가능하다. 이때주의할점은같은레지스터를서로다른 always 문에서값을할당하면안된다는것이다. 23
순차회로 순차회로의 always 문예제 always @ (posedge clock or negedge reset) begin if(!reset) //reset 시작, low active Y <= 0; // "<=" 사용 else begin if(a>b) Y <= A; else Y <= B; end end 24
순차회로 always 문사용시주의할점.(1) 클럭검출의에지에벡터의인덱스는사용할수없다. always @ (posedge CLK[1]) // 에러 리셋조건에는벡터의비트는사용할수없다. always @ (posedge CLK or negedge RESET_BUS) // 에러 if(!reset_bus[1]) // 에러 리셋조건에복잡한수식을사용할수없다. always @ (posedge CLK or negedge RESET) if(reset == (1-1)) // 에러 25
순차회로 always 문사용시주의할점.(2) 리셋조건에 RESET 이외의신호를추가로사용할수없다. always @ (posedge CLK or negedge RESET) if(!reset zero_init) // 에러 하나의 if문이 always 문블록의처음에있어야한다. always @ (posedge CLK or negedge RESET) A <= 3; // 에러 if(!reset) 26
조합회로 & 순차회로 문법구분. 조합회로 : assign 문, always 문, = 사용 순차회로 : always 문, <= 사용 데이터타입 assign 문 : wire 선언 always 문 : reg 선언 27
Module 의 Port Mapping 모듈의호출 (1) C 언어에서 main() 함수에서다른함수를호출하는개념과같다. 테스트벤치에검증하기위한 DUT 를포함시킬때사용된다. 테스트벤치또는특정모듈에서호출되는모듈을 Sub module이라한다. Sub module을호출할때에는항상 instance 명을사용한다. Ex> module tb_test();... test test_inst(< 포트리스트 >); //DUT 호출 endmodule 28
Module 의 Port Mapping 모듈의호출 (2) instance 명이모듈의이름과동일하여도된다. ( 모듈을한번만호출할때가능 ) 하나의모듈을설계한후이모듈을여러번불러서사용해야할경우에유용하다. 동일한모듈을여러번호출할때마다 instance 명을달리해야한다. Ex> module tb_test();... test test_inst0(< 포트리스트 >);... test test_inst1(< 포트리스트 >); endmodule 29
Module 의 Port Mapping 모듈의입출력 모듈의포트리스트는입력과출력의순서는상관없다. ( 일반적으로입력을먼저쓰고, 출력을나중에쓰도록한다.) 입출력데이터가멀티비트인경우는다음과같이쓴다. input [3:0] A; output [7:0] B; input 신호를모듈내에서값을변경할수없다. output으로정의된신호들은모두 reg 또는 wire로재정의해주어야한다. output 신호는현재모듈에서값을생성해주어야하기때문이다. 30
Module 의 Port Mapping 모듈의입출력예제 module test(a, B, X, Y); input [2:0] A; input B; output [2:0] X, Y; wire [2:0] X; reg [2:0] Y; assign X = A + 3'd1; always @ (A or B) begin if(b == 1) Y = A + 3'd2; else Y = A + 3'd3; end endmodule 31
Module 의 Port Mapping 모듈의내부신호 모듈내에서값을저장할필요가있거나모듈과모듈간에값을연결할필요가있을때생성한다. always 문을사용하여값을생성할필요가있을때에는 reg 선언을하여사용한다. assign 문을사용하여값을생성하거나, 서로다른두개의 sub module 간에값을연결할때에는 wire 선언을하여사용한다. 32
Module 의 Port Mapping 모듈의내부신호예제 (1) module test(reset, clock, A, B, Z); input reset, clock; input [2:0] A, B; output [3:0] Z; wire [3:0] Z; wire [2:0] Y; reg [3:0] add_value; always @ (posedge clock or negedge reset) begin if(!reset) add_value <= 0; else add_value <= A +B; end endmodule sub_mod sub_mod0(a, B, Y); sub_mod sub_mod1(y,add_value,z); 33
Module 의 Port Mapping 모듈의내부신호예제 (2) sub_mod 라는모듈은 2 개의입력을받아서 2 신호의차를출력한다. 여기서는 sub_mod 라는모듈을 2 번호출하였다. add_value 라는레지스터는 test 모듈의입력 A, B 의합을저장한다. Y 라는 wire 는 sub_mod0 의출력을받아서 sub_mod1 의입력으로연결하는데사용하였다. Z 는 output 신호이며, sub_mod1 의출력을받아서 output 으로연결한것이다. 34
Module 의 Port Mapping 모듈의포트 Mapping 방법 직접 Mapping 모듈과모듈간에포트의위치를정확하게 1 대 1 로연결하는방법. 각포트들의순서가매우중요하다. 참조 Mapping 모듈과모듈간에포트의이름을찾아서연결하는방법. 포트의순서는중요하지않으며이름만정확하게참조하면된다..< 서브모듈의포트이름 >(< 현재모듈의포트이름 >), 프로그래머의실수에의한신호의오동작을줄여준다. 35
Module 의 Port Mapping 직접 Mapping 예제 module Mother(I,J,K); input [2:0] I,J; output [2:0] K; wire [2:0] K; wire [2:0] X, Y; sub_mod sub_mod0(i, J, X); sub_mod sub_mod1(j, I, Y); assign K = X + Y; endmodule sub_mod 라는모듈을 2번호출. sub_mod0의입력은 I,J. 출력은 X. sub_mod1에입력은 J,I 출력은 Y. sub_mod의기능이 2개의입력신호를순서대로뺄셈을한다고했을때수식은다음과같다. sub_mod0 : X = I - J; sub_mod1 : Y = J - I; 입 출력의순서가매우중요하다. 36
Module 의 Port Mapping 참조 Mapping 예제 module Mother(I,J,K); input [2:0] I,J; output [2:0] K; wire [2:0] K; wire [2:0] X, Y; sub_mod sub_mod0(.a(i),.b(j),.o(x) ); sub_mod sub_mod1(.a(j),.b(i),.o(y) ); assign K = X + Y; endmodule sub_mod의포트는 A, B, O sub_mod0에서는 A와 I, B와 J, O와 X가서로연결되었다. sub_mod0(.b(j),.a(i),.o(x) ); 좌측의 sub_mod0와 A, B의순서가바뀌었지만, 포트의연결은 A-I, B-J로연결됨으로좌측과같다. 37
Module 의 Port Mapping 서브모듈의연결예제 module top(i,j,c_in, carry, sum); input [2:0] i, j; input c_in; output [2:0] sum; output carry; wire [2:0] sum; wire carry; wire w1, w2, w3; wire s0, s1; FA FA0(.x(i[0]),.y(j[0]),.c_in(c_in),.c_out(w1),.sum(s0) ); FA FA1(.x(i[1]),.y(j[1]),.c_in(w1),.c_out(w2),.sum(s1) ); FA FA2(.x(i[2]),.y(j[2]),.c_in(w2),.c_out(w3),.sum(s2) ); assign carry = w3; assign sum[2:0] = {s2, s1, s0}; endmodule 38
- The End - 39