이번 포스트에서는 Verilog에서의 연산자에 대해서 정리해보도록 할게요.

연산자 같은 경우는 설명할 부분이 많지 않아서 모아서 정리해놓고 간간히 필요할 때 찾아 사용해도 좋을 것 같습니다.

 

- 산술 연산자(Arithmetic Operator)

Operator Description
a + b a plus b
a - b a minus b
a * b a muliplied by b
a / b a divided by b
a % b a modulo b
a ** b a to the power by b

산술 연산자는 너무나 잘 알고 있는 부분이죠.

더하기, 빼기, 곱하기, 나누기 이외에 %는 나머지를 구하는 연산자, a**b는 a의 b제곱 연산을 의미합니다.

간단하게 코드를 짜서 결과를 확인해볼까요?

module operator(
  input wire [31:0] a,
  input wire [31:0] b,
  output reg  [63:0] result_add,
  output reg  [63:0] result_sub,
  output reg  [63:0] result_mul,
  output reg  [63:0] result_div,
  output reg  [63:0] result_mod,
  output reg  [63:0] result_pow  
);
  
  always @(*) begin
    result_add = a + b;
    result_sub = a - b;
    result_mul = a * b;
    result_div = a / b;
    result_mod = a % b;
    result_pow = a ** 32'd2;
  end
  
endmodule

위와 같이 코드를 작성해서 Testbench에서 a = 10, b = 4를 넣고 결과를 확인해봅시다.

Result of Arithmetic Operator

결과가 Hex로 표현되어 있는데 add의 결과를 보면 e(10+4 = 14), sub의 결과 6(10-4 = 6), mul의 결과 28(10*4 = 40),
div의 결과 2(10/4의 몫 = 2), mod의 결과 2(10/4의 나머지 2), pow의 결과 64(10^2 = 100)으로 잘 나타나네요.

 

- 관계연산자(Relational Operator)

Operator Description
a < b a less than b
a > b a greater than b
a <= b a less than b or equal to b
a >= b a greater than b or equal to b

관계연산자는 대소비교를 하는 연산자로 조건에서 많이 쓰이게 되는데요.

이 부분은 알던 이상, 이하, 초과, 미만과 동일하게 때문에 따로 Simulation은 없이 넘어가도록 합시다.

 

- 동일 연산자(Equality Operator)

Operator Description
a === b a equal to b, including x and z
a !== b a not equal to b, including x and z
a == b a equal to b, result can be unknown
a != b a not equal to b, result can be unknown

동일 연산자에는 연산자가 세개(===, !==)가 들어가는 것과 두개(==, !=)가 들어가는 것이 나눠져 있는데 

연산자가 세개인 것들은 x, z 상태까지 고려해 동일성 검사를 하기 때문입니다.

여기서 x, z 상태란 x는 unknown으로 어떤 값인지 모르는 상태(확신할 수 없는 상태)이고
z는 High-Impedance로 선이 연결되어 있지 않은 상태 등을 의미합니다.

 

예를 들어 unknow값을 포함한 111x과 111x을 서로 비교할 때,
==은 unknown(x)이 존재하기에 unknown(x)으로 판단하지만 ===은 같다고 판단하게 되는데 정말 그런지 한번 확인해보고 넘어갑시다.

module operator(
  input wire [31:0] a,
  input wire [31:0] b,
  output reg  [63:0] result_equal,
  output reg  [63:0] result_equal_incxz
);
  
  always @(*) begin
    result_equal = (a == b);
    result_equal_incxz = (a === b);
  end
  
endmodule

result_equal은 ==의 결과, result_equal_incxz는 ===의 결과를 출력하도록 하였고 a와 b모두 111x을 넣어봅시다.

Result of Equality Operator

정말 ==은 a, b가 같은지에 대해서 x(unknown) 판정을 내렸고 ===는 같다고 판정했네요!

 

- 논리 연산자(Logical Opeartor)

Operator Description
a && b evaluates to true if a and b are true
a || b evaluates to true if a or b are true
!a converts non-zero value to zero, and vice versa

논리 연산자에서 &&는 AND 연산, ||는 OR 연산, !는 NOT 연산입니다.

이 부분은 따로 확인하지 않아도 당연한 것이니 넘어가겠습니다.

 

- 비트 연산자(Bitwise Operator)

Operator Description
a & b evaluates to true if a and b are true with its corresponding bit
a | b evaluates to true if a or b are true with its corresponding bit
a ^ b evaluates to true if a xor b are true with its corresponding bit

비트 연산자는 논리 연산자와 다르게 비트 단위로 검사를 합니다.

예를 들어 a = 1011, b = 1101이 있다고 했을 때,
Logical AND연산, a && b를 하게되면 a가 0이 아니고 b가 0이 아니니 단순히 1이 나오게 되지만
Bitwise AND연산, a & b를 하게 되면 비트별로 and연산을 진행해서 1001이라는 결과가 나오게 됩니다.

이것도 한번 확인해보고 넘어갈까요?

 

module operator(
  input wire [31:0] a,
  input wire [31:0] b,
  output reg  [63:0] result_and,
  output reg  [63:0] result_and_bit
);
  
  always @(*) begin
    result_and = (a && b);
    result_and_bit = (a & b);
  end
  
endmodule

이와 같이 코드를 구성하고 a=1011, b=1101을 넣어봅시다.

Result of Bitwise Operator

위에서 이야기했던 대로 Logical 연산과 Bitwise 연산의 차이를 확실히 알 수 있습니다.

 

- 이동 연산자(Shift Operator)

Operator Description
<< Logical Shift Left
>> Logical Shift Right
<<< Arithmetic Shift Left
>>> Arithmetic Shift Right

마지막으로 이동연산자입니다.

이동 연산자도 동일 연산자와 비슷하게 2개짜리가 있고 3개짜리가 있네요. 

차이를 보자면 <<, >>, <<<같은 경우에는 Shift가 일어나고 빈자리에 0이 채워지는

반면 >>>의 경우, 빈자리가 MSB의 부호로 채워지게 됩니다.

 

예를 들어, 1011을 Logical Shift Right(>>2)를 하면 0010이 되는데
Arithmetic Shift Right(>>>2)를 하면빈자리가 여기서 MSB인 1로 채워지기 때문에 1110이 되겠네요.

이런 Arithmetic Shift는 보통 Signed Number를 Shift할 때 쓰인다고 합니다.

이것도 한번 확인해보고 이번 포스트는 마치도록 해볼게요!

 

module operator(
  input wire signed [3:0] a,
  output reg  [3:0] result_log_shi,
  output reg  [3:0] result_ari_shi
);
  
  always @(*) begin
    result_log_shi = (a >> 2);
    result_ari_shi = (a >>> 2);
  end
  
endmodule

위와 같이 코드를 작성해서 1011을 오른쪽으로 2번 Logical Shift와 Arithmetic Shift를 해봅시다.

Result of Shift Operator

공부한 대로 Logical Shift 연산시에는 0010, Arithmetic Shift 연산시에는 1110으로 나타나는 것을 확인할 수 있습니다.


출처 : https://www.chipverify.com/verilog/verilog-operators

반응형
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기