본문 바로가기
개발 Tools/Verilog HDL

Verilog HDL 연산자 ( 산술 연산자, 비트 연산자, 논리 연산자, 축약 연산자, 등가 연산자, 시프트 연산자, 결합 연산자, 반복 연산자 )

by 전컴반 2022. 2. 9.
반응형
산술 연산자

 

예를 보는 게 더 이해가 쉽다.

 

// a = 4'b0011;  (== 3)
// b = 4'b0100;  (== 4)
// d = 6;
// e = 4;


a * b  // 4'b1100  (== 12), 10진수 값으로 곱한다
d / e  // 1, 소수점 이하는 버림
a + b  // 4'b0111, 비트 연산
b - a  // 4'b0001


13 % 3  // 1, 나머지 연산 값
16 % 4  // 0, 나머지 연산 값
-7 % 2  // -1, 첫번째 값의 부호와 일치해야 한다
7 % -2  // 1, 첫번째 값의 부호와 일치해야 한다

 

더하기 ( + )와 빼기 ( - )는 비트로 더하든 10진수로 더하든 똑같다.

 

나누기 ( / )와 나머지 ( % ) 연산자는 두 번째 피연산자가 0인 경우 결괏값은 x인 unknown값이다.

이유는 분모에 0이 들어가면 무한대가 되기 때문이다.

 

추가적으로 나머지 ( % ) 연산자의 부호는 첫 번째 연산자의 부호를 따른다.

무슨말이냐 하면 위에서 예를 보면,

-7 % 2는 부호 제외하고 보면, 나머지가 1이지만 첫 번째 연산자의 값이 ' - '라 -1이 된다. 

좀 더 보자면, -7 = 2 * -3 - 1으로 표현할 수 있고, 2 * -4 + 1로 표현할 수도 있다.

즉, -1이냐 +1이냐의 차이인데 첫 번째 연산자의 값이 음수라 -1을 결괏값으로 취한다.

 

논리 연산자 

 

참 아니면 거짓만 나온다. 0이 아니면 다 참이다. 0만 거짓이다. 1248도 참이고 -124도 참이다

 

&& = and 연산

|| = or 연산

! = not 연산 

 

// a = -3;  (참)
// b = 0;  (거짓)

a && b  // 0, 참 && 거짓 = 거짓
a || b  // 1, 참 || 거짓 = 참
!a  // 0, !참 = 거짓

 

비트 연산

 

위에서 본 논리 연산과 잘 구분해야 한다.

 

& = 비트의 and 연산

| = 비트의 or 연산

~ = 모든 비트를 반전 시킴

^  = 비트의 XOR

~^ =  비트의 XNOR

 

// a = 1010  (참)
// b = 1111  (참)

a && b  // 1, 참 && 참 = 참
a & b  //4'b1010, 각각의 비트끼리 연산을 수행

 

축약 연산자

 

위에사 잘 구분했는데 또 헷갈리게 축약 연산자가 있다.

축약 연산자는 단항 연산자로 하나의 피연산자에 사용된다.

하나하나의 비트 연산을 수행한다. 사용의 이유는 아래와 같다 축약 연산자의 이름처럼 축약하여 사용할 수 있기 때문이다.

 

&

~&

|

~|

^

~^가 있다.

 

&4'b0110  // 0 & 1 & 1 & 0 == 0
~&4'b0110  // ~(0 & 1 & 1 & 0) == 1


// 아래는 같은 연산이다.
parity = ^cnt[7:0];
parity = ^cnt[7]^cnt[6]^cnt[5]^cnt[4]^cnt[3]^cnt[2]^cnt[1]^cnt[0];

 

등가 연산자

 

흔히들 알고 있는 기본적으로 ==,!=가 있으나 추가적으로 ===,!== 가 있다. 

차이점은 x, z를 포함하냐 하지 않냐의 차이에 있다.

 

 ==와 !=는 논리 값인 x, z를 표함 하지 않는 연산자이다.  그러나 결과는 x가 될 수 있다

===는 x, z를 포함하여 일치를 판단한다. !==도 x, z를 포함하여 불일치를 판단한다.

 

 

시프트 연산자

 

논리 시프트 (<<, >>)는 빈자리에 0을 채운다

산술 시프트 (<<<. >>>)는  왼쪽 시프트 <<<는 0을 채우지만 >>>는 빈자리에 MSB를 채운다.

 

// a = 4'b1100;

b = a >> 1;  // 4'b0110
b = a << 1;  // 4'b1000
b = a << 2;  // 4'b0000

 

결합 연산자

 

중요한 연산자이다.

중괄호 {}를 이용하여 2개 이상의 값들을 결합한다. 하나의 나열이라고 볼 수도 있다.

 

// a = 1'b'1;
// b = 2'b00;
// c = 2'b10;
// d = 3'b110;

y = {b, c};  // 4'b0010, 2비트 +2비트에다 00과 10을 결합한 값
y = {a, b, c, d};  // 8'b1_00_10_110  
y = {a, 3'b001};  // 4'b1_001, 자세히 나열 {a, 1'b0, 1'b0, 1'b1}
y = {b[0], c[1]};  // 2'b01

// 반대 작업도 가능
// in_reg = 10'b1_0111_01_010;

{a[1], b[3:0], c[1:0], d[5:3]} = in_reg[9:0];

// a[1] = 1'b1
// b[3:0] = 4'b0111
// c[1:0] = 2'b01
// d[5:3] = 3'b010

 

여러 정보들을 하나로 묶는 작업이다. 반대로 여러 정보를 하나하나 분배할 수도 있다. 만약 같은 진수가 아니라면 진수의 통일을 하여 수행된다. ( + index는 왼쪽에서부터 시작된다. 예, c [1] = 1, c [0] = 0)

 

추가적으로 봐야 할 것이 있다. 아래 예를 보자,

 

// a = 1101
// b = 1001

{carry, sum[3:0]} = a[3:0] + b[3:0];

 

위의 연산은 4비트 덧셈이다. 하지만 1101과 1001을 더하면 carry가 발생한다. 그래서 5비트 연산으로 이루어진다.

 

회로적으로 보자,

아래의 회선을 나눠야 한다면 어떻게 작성할까? 결합 연산자를 이용하여 간편하게 작성할 수 있다. 

숫자를 지정하여 나눌 수도 있지만 결합 연산자를 이용하면 [31:16] 까지는 bus_hi에, 나머지는 bus_lo에 들어간다.

 

assign {bus_hi[15:0], bus_lo[15:0]} = bus[31:0];

// 위와 같은 동작
assign bus_hi[15:0] = bus[31:16];
assign bus_lo[15:0] = bus[15:0];

 

반복 연산자

 

중괄호 2개를 이용하여 나타낸다. 즉, {{}} 를 이용하여 {a {b}} 와 같은 형태로 사용한다. b를 a번 반복한다는 의미다.

주의해야 할 점은 {}의 수를 잘 맞춰야 한다. 

 

// a = 1'b1;
// b = 2'b00;
// c = 2'b10;

y = { {4{a}} };  // 4'b1111, 1이 4개
y = { {4{a}}, {2{b}} }  //8'b1111_0000, 1이 4개, 00이 2개 

// 아래 코드는 같다
x = { w, w, w, w} 
x = { {4{w}} }  // 끝에 있는{}는 결합연산자

 

a의 값이 1인데 4번 반복하라니 위와 같은 값이 나오고

두 번째의 경우에는 먼저 1을 4번 반복하고, 00을 2번 반복하고 결합을 한 것이다.

 

회로적 예를 들어보자, 여러 표현 방법이 있을 것이다. 4가지 정도로 알아보자

 

// 방법 1
assign y[7] = a;
assign y[6] = a;
assign y[5] = b;
assign y[4] = b;
assign y[3] = b;
assign y[2] = 1'b1;
assign y[1] = 1'b1;
assign y[0] = 1'b1;


// 방법 2
assign y[7:6] = {2{a}};
assign y[5:3] = {3{b}};
assign y[2:0] = {3{1'b1}};

// 방법 3
assign y[7:0] = { a, a, b, b, b, 1'b1, 1'b1, 1'b1 }


// 방법 4
assign y[7:0] = { {2{a}}, {3{b}}, {3{1'b1}} }

 

방법 1은 가장 기본적인 생각이다.

방법 2는 중복을 이용하여 작성한 것이다.

방법 3은 결합을 이용하여 작성한 것이다.

방법 4는 중복과 결합을 이용하여 작성한 것이다. 

 

제일 좋은 것은 방법 4처럼 짜는 것이다. 즉 반복은 결합과 사용하면 더 좋은 코드를 만들어 낼 수 있다.

 

조건 연산자

 

프로그래밍 언어에서의 조건 연산자와 똑같다. 주로 여러 개의 입력 중에 하나만 출력하는 mux로 사용한다.  

표현 방법은 아래와 같다.

결과 = 조건 ? (참일 경우) : (거짓일 경우);

 

 

 

 

반응형

댓글