디지털 시스템 설계(3)
Module Verilog HDL 프로그램의 기본 구조 대소문자 구별 Statement terminator로 semicolon을 사용 Timing specification은 시뮬레이션을 위해서 사용
Module의 구성요소
Port 선언 포트 리스트 포트 타입 포트 선언 모듈에 사용되는 포트 이름의 list input : 입력 포트 예 : module mux_latch(y_out, sel_a, sel_b, data_a, data_b); 포트 타입 input : 입력 포트 output : 출력 포트 inout : 입•출력 포트 포트 선언 포트 리스트에 나열된 포트명의 타입을 결정하는 과정을 의미 <port type> <port_name>; 예 input sel_a, sel_b, data_a, data_b; output y_out; input [3:0] a; output [3:0] a, b;
Port 선언 포트선언시의 일반적 표현방법 i_[port_name] o_[port_name] RHS(Right-Hand Side argument)로 사용 o_[port_name] “o_” 현재 포트의 이름이 출력 포트임을 의미 LHS(Left-Hand Side argument)로 사용 LHS, RHS의 규칙을 따르지 않을경우 합성 이후 네트(net)가 연결되어 있지 않는 플로팅(floating) 상태가 되고, 레이아웃(Layout)시 GND(Ground, 접지 전압, 0V 또는 VDD(동작 전압)로 강제로 할당되므로 주의 b_[port_name] “b_” 현재 포트의 이름이 입출력 양방향(bi-directional) 포트임을 의미 RHS, LHS에 사용가능 버스의 선언은 down-ward로 기술 예 : [BIT_WIDTH-1:0]
데이터 형태 물리적 데이터 형태 논리값의 종류 추상적 데이터 형태 Integer, real, time 등
데이터 형태 변수선언(데이터 형태 선언) 종류 constant reg : register (latch 또는 flip-flop) 일시적으로 데이터를 저장하는 변수를 의미 하드웨어 레지스터를 의미하지는 않는다 always, initial 문 등에서 사용 예 : reg alu_reg; reg [7:0] alu_reg; wire : net (배선) 값 저장 불가능 assign 문에서 사용 예 : wire adder_out; wire [15:0] adder_out, mult_out; constant 파라미터를 이용하여 변수 값을 사용할 때
데이터 형 수 표현 Sized 또는 unsized 형식의 수 표현 가능 Sized 형식의 수 표현 형식 : <size>’<base format><number> 예 : 3’b010 //3의 prefix는 수의 size를 의미 Unsized 형식의 수 표현 Base format이 없는 경우는 default로 decimal을 의미 Size가 없는 경우는 default로 32-bit의 수를 의미 예 : 321 //32-bit을 갖는 decimal number 321을 의미 Base format Decimal : ‘d 또는 ‘D Hexadecimal : ‘h 또는 ‘H Binary : ‘b 또는 ‘B Octal : ‘o 또는 ‘O
데이터 형 수 표현 음수의 표현 수의 확장 법칙 <size> 앞에 – 부호를 위치하여 표현 예 : -8’d3 //3의 2의 보수 형태로 저장된 8bit의 음수 틀린 예 : 4’d-2 수의 확장 법칙 MSB가 0, X, 또는 Z 인 경우 각 각 MSB가 0, X, Z가 되도록 확장 예 : 3’b01 = 3’b001, 3’bx1 = 3’bxx1 , 3’bz = 3’bzzz MSB가 1인 경우 MSB를 0으로 채우는 방향으로 확장 예 : 3’b1 = 3’b001
데이터 형 수 표현
연산자 Binary 연산자의 종류 (예) (예) 어떤 operand bit이 x값을 가지면 전체 연산 A = 4’b0011, B = 4’b0100, D = 6, E =4 일때 A * B = 4’b1100 D / E = 1 //Truncates any fractional part A + B = 4’b0111 B – A = 4’b0001 13 % 3 = 1 (예) 어떤 operand bit이 x값을 가지면 전체 연산 결과는 x 이다. in1 = 4’b101x, in2 = 4’b1010 일 때 Sum = in1 + in 2; //sum은 4’bx -7 % 2 = -1 //첫 번째 operand의 부호 7 % -2 = 1 //첫 번째 operand의 부호
연산자 관계 연산자 (예) ain = 3’b010, bin = 3’b100, cin = 3’b111, din = 3’b01z, ein = 3’b01x일 때 ain > bin 은 false(1’b0) 의 결과 ain < bin 은 ture(1’b1)의 결과 ain >= bin 은 unknown(1’bx)의 결과 ain <= ein은 unknown(1’bx)의 결과
연산자 논리 연산자 (예) A = 3 ; B = 0; A && B //Evaluates to 0. Equivalent to (logical 1 && logical 0) A || B //Evaluates to 1. Equivalent to (logical 1 && logical 0) !A //Evaluates to 0. Equivalent to not(logical 1) !B //Evaluates to 1. Equivalent to not(logical 0) A = 2’b0x ; B = 2’b10; A && B //Evaluates to x. Equivalent to (x && logical 1) (a == 2) && (b == 3) //Evaluates to 1 if both a == 2 and b==3 are true
연산자 Bitwise 연산자 만일 두 operand의 길이가 다르면 짧은 길이의 operand가 0으로 left-extend (예) X = 4’b1010, Y = 4’b1101, Z = 4’b10x1일 때 ~X //Result is 4’b0101 X & Y //Result is 4’b1000 X | Y //Result is 4’b1111 X ^ Y //Result is 4’b0111 X ^~ Y //Result is 4’b1000 X & Z //Result is 4’b10x0
연산자 Unary Reduction 연산자 vector를 하나의 bit로 줄이는 연산을 수행한다. X 또는 Z는 연산자에 따라서 unknown일 수도 있고 known일 수도 있다. (예) ain = 5’b10101, bin = 4’b0011, cin = 3’bz00, din = 3’bx011일 때 &ain //Result is 1’b0 ~&ain //Result is 1’b1 |cin //Result is 1’bx &din //Result is 1’b0
연산자 Equality 연산자 case equality와 case inequality를 제외하고 operand에 X 나 Z를 포함하면 결과는 unknown (예) A = 4, B = 3, X = 4’b1010, Y = 4’b1101, Z = 4’b1xxz, M = 4’b1xxz, N = 4’b1xxx일 때 A == B //Result is logical 0 X != Y //Result is logical 1 X == Z //Result is x Z == M //Result is logical 1(all bits match, including x and z) Z == N //Result is logical 0(least significant bit does not match) M != N //Result is logical 1
연산자 기타 연산자
Multi Bit 선언 신호 선언 [MSB:LSB] 한 비트의 선택 여러 신호를 하나의 신호로 할당 Input [7:0] abus; reg [15:8] add; 한 비트의 선택 assign abc = abus[5] ; assign abus[5] = abc ; 여러 신호를 하나의 신호로 할당 assign abcd[15:0] = {abus[7:0],add[15:8]} ;
Array Register 형은 array로 선언 가능 Bit 선택이나 부분 선택 Reg [15:0] mem [0:255]; mem은 16bit * 256word, 512 byte의 메모리 resister 배열은 bit 선택과 부분 선택 불가 반드시 word 단위의 액세스 Bit 선택이나 부분 선택 일시적인 net 신호를 이용 Ex) wire [15:0] temp; assign temp = mem [100];
기술방법(Description) 구조적 기술방법(Structural description) Explicit structural description Primitive 또는 라이브러리 셀의 instance 및 연결을 통한 기술 Implicit structural description Continuous assignment를 통한 기술 동작 기술 방법(Behavioral description) 회로의 동작을 기술함으로 설계하는 방법 대표적으로 initial, always behavior를 사용 Procedural block 과 procedural statement로 구성
기술방법 Explicit description Implicit description module 8bit_or_gate(y, a, b); input [7:0]a, b; output y; or G1(y, a, b); endmodule module 8bit_or_gate(y, a, b); input [7:0]a, b; output y; or8bit(y, a, b); endmodule Primitive를 이용한 기술 라이브러리를 이용한 기술 module 8bit_or_gate(y, a, b); input [7:0]a, b; output y; assign y = a | b; endmodule
Primitives Predetermined Primitives
Module Instantiation Port connection의 2가지 방법 Connecting by ordered list Connecting ports by name
Module Instantiation Connecting ports by name
Assign Assign Wire에 값을 가하고 update 하기 위해 사용 LHS (Left Hand Side)의 데이터 타입은 항상 net data type이여야 한다 Always active RHS (Right Hand Side)의 어느 한 operand라도 변화하면, expression은 실행되고 LHS 값은 즉시 update 된다 RHS의 데이터 타입은 net, register, function call등 어떤 것이어도 상관 없다
Procedural Blocks Procedure의 정의 sequential 하게 동작하는 코드 부분을 의미 procedural statement procedure안에 존재하는 statement 예를 들어, 2-to-1 MUX의 경우
Initial Block 시뮬레이션을 위한 초기화, 모니터링, waveform의 기술시에 주로 사용된다 시뮬레이션 타임 0에서 시작하여 오직 1번만 실행된다 하나의 initial block이 여러 개의 behavioral statement를 가질 경우 begin ~ end로 group 되어야 한다 독립적인 initial block은 서로 concurrent 하다 Initial block 내부의 statement들은 sequential 하게 동작한다 initial block은 중첩될 수 없다 synthesis 되지 않는다
Initial Block module TestBench; reg a, b, c, d Initial #20 $finish; Initial a = 1’b0; Initial Begin b = 1’b1; #5 c = 1’b0; #10 d = 1’b0; End Initial #20 $finish; endmodule
Always Block(Level-Senssitive Circuit) 논리조합회로(Level-Sensitive Circuit)와 논리순차회로(Edge Sensitive Circuit) 에서 사용가능 논리조합회로에는 Blocking Assignment(=)만을 사용 always @([Senstitivity_list]) begin . end
Always Block(Edge-Senssitive Circuit) 논리순차회로에는 non-Blocking Assignment(<=)만을 사용 Edge Contition posedge negedge Edge Condition 은 최소 1개 최대 3개까지 기술 always @ ( Edge condition [signal] or Edge condition [signal] or…) begin ... end
Always Block(Edge-Senssitive Circuit)
Always Block(Edge-Senssitive Circuit)
Always Block(Edge-Senssitive Circuit)
Blocking vs. Non-Blocking Assignment Symbol Blocking Assignment = Combination Logic Circuit Non-Block Assignment <= Sequential Logic Circuit(always statement를 사용) Blocking Assignment = 한 always 블록 내에서 ';'로 끝나는 각 구문이 연속적인(continuo us) 할당이 발생하여 맨 마지막에 할당된 값을 가지게 된다. 또한 블로킹 할당은 신호의 중복 할당을 허용한다. 클럭 엣지에서 Unit Delay 존재하지 않는다. Non-Blocking Assignment <= 한 always 블록 내에서 ';'로 끝나는 각 구문이 동시적인(concurr ent) 할당이 발생된다. 또한 논블로킹 할당은 중복 할당을 허용하 지 않는다. 클럭 엣지에서 Unit Delay 존재한다.
Blocking vs. Non-Blocking
Blocking vs. Non-Blocking
Initial vs Always
Procedural Statement if-else statement TOP에서 BOTTOM으로 조건 평가 실시 모든 조건이 false이면 else에 관계되는 statement를 실행 E.g. 4-to-1 mux module mux4_1(out, in, sel); output out; input [3:0] in; input [1:0] sel; reg out; wire [3:0] in; wire [1:0] sel; always @(in or sel) if (sel == 0) out = in[0]; else if (sel == 1) out = in[1]; else if (sel == 2) out = in[2]; else out = in[3]; endmodule if(<condition1>) sequence of statement(s) else if(<condition2>) …… else sequence of statements(s)
Procedural Statement case statement if else와 같이 조건 평가에 의한 statement의 실행 모든 가능한 조건이 고려되어야 함 default : 기술되지 않은 모든 가능한 조건에 해당 중첩 될 수 있다 expression의 결과와 condition의 bit 수가 같지 않을 때는 MSB부터 0 fill 한다 E.g. 4-to-1 mux module mux4_1(out, in, sel); output out; input [3:0] in; input [1:0] sel; reg out; wire [3:0] in; wire [1:0] sel; always @(in or sel) case (sel) 0: out = in[0]; 1: out = in[1]; 2: out = in[2]; 3: out = in[3]; endcase endmodule case (expression) <condition1>: sequence of statement(s) <condition2>: … default : endcase
Procedural Statement For loop의 시작에서 일단 한번 statement를 실행하고 expression이 참일때만 계속 loop를 실행 module count(Y, start); output [3:0] Y; input start; reg [3:0] Y; wire start; integer i; initial Y = 0; always @(posedge start) for (i = 0; i < 3; i = i + 1) #10 Y = Y + 1; endmodule
Verilog HDL Module 구조 예 Module Add_half_1(sum, c_out, a, b); input a, b; output sum, c_out; wire c_out_bar; xor(sum, a, b); nand(c_out_bar, a, b); not(c_out, c_out_bar); endmodule 모듈 선언 포트 선언 데이터 타입 선언 회로 동작기술 Predefined primitive 를 사용하여 instantiation
Verilog HDL Module Add_half_2(sum, c_out, a, b); input a, b; output sum, c_out; wire c_out_bar; assign {c_out, sum} = a + b; endmodule 회로 동작기술 Continuous assignment 구문사용
Verilog HDL Module Add_full(sum, c_out, a, b); input a, b, c_in; output sum, c_out; wire w1, w2, w3; add_half_1 M1 (w1, s2, a, b); add_half_2 M2 (sum, w3, s1, c_in); or(c_out, w2, s3); endmodule 기존에 설계한 half_adder를 이용한 Structural description module instantiation 사용 (parent module / child module) module instantiation시 반드시 module instance name이 들어가야 함 (primitive instantiation시는 optional)
Verilog HDL Module full_adder(sum, carry_out, in1, in2, carry_in); input in1, in2, carry_in; output sum, carry_out; reg sum, carryout; always @(in1 or in2)begin {carry_out, sum} = in1+in2+carryin; end endmodule sumHA = a ^ b c_outHA = ab sumFA = (a + b) ^ c_in c_outFA = (a + b) c_in + abc_in Half_adder의 결과를 sum을 연산자 +, c_out를 연산자 &로 치환하면 sumFA = (a + b) + c_in c_outFA = a&b | a&b&c_in