Verilog-2

2023. 3. 9. 13:49Verilog

1. 연산자 (이어서)

산술 연산자의 사용 예

-d10 / 5 // (10의 2의 보수)/5 = (2^32-10)/5
5 / 0 // 5/0 = x
(-7) % (+4) = -3 // 나머지, 왼쪽 오퍼랜드의 부호를 따른다.
(+7) % (-2) = +1
// 정수, 레지스터 연산 예
integer intA;
reg [15:0] regA;
reg signed [15:0] regS;
intA = -5'd12;
regA = intA / 3; // -4, intA는 integer, regA는 65532
regA = -5'd12; // regA는 65524
intA = regA / 3; // 21841
intA = -5'd12 / 3; // 1431655761, -5d'12= 2^32-12
regA = -12 / 3; // -4, -12는 integer 자료형, regA는 65532
regS = -12 / 3; // -4, regS는 signed reg
regS = -4'sd12 / 3; // 1, -4'sd12는 4이므로 4/3=1

이동 연산자

음수인 경우는 산술 오른 쉬프트와 논리 오른 쉬프트와 결과가 다르다는 것에 유의해야 한다. 산술 쉬프트의 경우 쉬프트하고 남은 수들을 모두 부호 비트로 채우게 된다. 

 

관계 연산

관계 연산자는 c언어의 관계 연산자와 동일하게 사용할 수 있다. 

하지만 x(뭔지 알 수 없는값)가 들어간 z와 4'b1000인 x를 비교했을 때는 값을 비교할 수 없기 때문에 알 수없음(x)가 나온다. 

x <=z의 경우도 4'b1000 <= 4'1 xxxx 해서 논리 참이 나올 것 같지만 역시 알 수 없음(x)가 나온다.

 

등가 연산

// X=4'b1010, Y=4'b1101, Z=4'b1xxz, M=4'b1xxz
X == Y // 0 
X == Z // x
M == Z // x 
M === Z // 1

등가 연산자는 각 항의 값이 동일한지를 체크하는 연산자이고, 동일 연산자는 둘이 완전히 동일한지를 비교하는 연산자이다. 따라서 4'b1 xxz == 4'b1 xxz는 값을 비교할 수 없어 x이지만, 4'b1 dxxz === 4'b1 xxz는 참이 나온다. 

 

비트 단위 연산자

만약 서로 비트 수가 다른 경우는 LSB를 기준으로 연산된다. 

4'b1111 & 2b'01

예를들어 위 식을 실행하면 오른쪽 항은 내부적으로 4b'0001로 처리된다. 

 

// X = 4'b1110, Y = 4'b1000, Z = 4'b01xx
~ X // Negation, 결과는 4'b0001
X & Y // Bitwise and, 결과는 4'b1000
X | Y // Bitwise or, 결과는 4'b1110
X ^ Y // Bitwise xor, 결과는 4'b0110
X ^~ Y // Bitwise xnor, 결과는 4'b1001
Y | Z // Bitwise xor, 결과는 4'b11xx
// 비트 단위 연산자의 할당 예
wire [3:0] a, b, c;
assign c = a | b; // 4 비트 단위 연속할당
// 아래 4개의 각 비트 할당문과 동일
assign c[3] = a[3] | b[3];
assign c[2] = a[2] | b[2];
assign c[1] = a[1] | b[1];
assign c[0] = a[0]| b[0];

축소 연산자

축소 연산자는 우측의 모든 비트를 연산하는 연산자이다. 위의 비트 단위 연산자와 생김새는 같지만 사용방법은 다르다. 

 

wire [3:0] a = 4'b0101;
wire x1, x2, y1, y2, y3 ;
// 다음 두 연산의 결과 x1과 x2는 동일
assign x1 = & a; // reduction, 0 & 1 & 0 & 1 = 0
assign x2 = a[3] & a[2] & a[1] & a[0]; // bitwise AND
assign y1 = | a; // 0 | 1 | 0 | 1 = 1
assign y2 = ^ a; // 0 ^ 1 ^ 0 ^ 1 = 0
assign y3 = ^~ a; // ~( 0 ^ 1 ^ 0 ^ 1) = 1

논리 연산자

논리 연산자는 c언어와 완전히 동일하다.

논리 연산자자와 비트 논리 연산자는 c언어와 쓰임이 같은데, 헷갈리지 않도록 유의해야 한다.

 

결합 연산자

// a = 1'b1 b =3'b101 c = 2'b01
assign x1 = { b, c }; // 결과 x1은 5'b10101
assign y1 = { a, b, 4'b0111 }; // 결과 y1은 8'b11010111
assign z1 = { a, b[1:0], c[1] }; // 결과 z1은 4'b1010
// 반복 연산자, { { } } 사용 예
assign x2 = { 8{a} }; // 결과 x2는 8'b1111_1111
assign y2 = { 2{a}, 2{b} }; // 결과 y2는 8'b1110_1101
assign z2 = { 3{a}, b, 2{c} }; // 결과 z2는 10'b11_1101_0101
assign byte = { 4{2'b10} }; // 8'b1010_1010 생성
assign hword = { {8{byte[7]} }, byte }; // 16 비트생성, 부호확장
// 1111_1111_1010_1010

//결합 연산자를 사용한 비트길이 조절
wire [7:0] a, b;
wire [7:0] sum8;
wire [8:0] sum9;
assign sum8 = a + b; // 캐리 버림
assign sum9 = a + b; // sum9[8]에 캐리 저장
assign {cout, sum8} = a + b; // cout에 캐리 저장

//결합 연산자를 사용한 비트 결합
wire a1, b1;
wire [3:0] a4;
wire [7:0] b8, c8, d8;
assign b8 = {a4, a4};
assign c8 = {a1, b1, a4, 2'b10};
assign d8 = {b8[3:0], c8[7:4]};

//결합 연산자를 사용한 이동 연산 구현
wire [7:0] a;
wire [7:0] rot, shl, sha1, sha2;
assign rot = {a[2:0], a[7:3]}; // 3 비트 우 순환 이동
assign shl = {3'b000, a[7:3]}; // 3 비트 우 이동, MSB는 0으로 채움
assign sha1 ={a[7], a[7], a[7], a[7:3]); // 3 비트 우 이동,
// MSB는 부호 비트로 채움, 산술 이동
assign sha2 ={4{a[7]), a[7:4]}; // 4 비트 우 이동, 부호 채움

여러 개의 비트들을 합칠 때 많이 사용하는 결합 연산자이다. 비트를 합쳐 조건에 넣거나 한 번에 초기화할 때 유용하게 사용할 수 있다. 

 

조건 연산자

MUX를 만들 때 사용 가능하다. MUX는 case나 if를 사용해서 합성하거나 조건 연산자를 여러개 사용해서 합성 가능하다. 

연산자의 우선순위

 

역시 c언어와 비슷하다. 

 

2. 인스턴스

모듈 인스턴스

1비트 버퍼를 8비트로 확장시키고 싶을 때는 인스턴스 배열을 이용해 8비트 버퍼로 확장 시킬 수 있다. 

2번째 예제도 8비트 버퍼를 인스턴스 배열을 사용해 32비트 버퍼로 확장시킨 것이다. 

 

프리미티브 인스턴스

instance_name과 array_range는 선택사항이다. 

게이트를 만들 때 맨 앞에 출력이 오는 것을 유의해야한다.

 

3. 시스템 태스크

시뮬레이터를 사용할 때 상황을 지정하기 위한 함수들이다. 

4. 컴파일러 지시어

컴파일러 지시어는 사용자가 컴파일 옵션을 주기 위한 함수이다. C언어의 전처리기와 비슷한 역할을 한다.

주소 사용하는건 timescale인데, 시뮬레이션에서 delay를 줄 때 단위를 결정한다 

 

'Verilog' 카테고리의 다른 글

verilog 9 카운터 실습  (0) 2023.03.15
verilog7  (0) 2023.03.14
verilog 5  (0) 2023.03.13
verilog 3  (0) 2023.03.10
Verilog  (0) 2023.03.08