본문 바로가기

회로/디지털

[Verilog] signed, unsigned 사칙연산 - adder, multiplier, subtractor, divider (덧셈기, 곱셈기, 뺄셈기, 나눗셈기)

반응형


※ Verilog 2001 기준

 

일반적으로 직접 덧셈, 뺄셈, 곱셈, 나눗셈 로직을 구현하지 않는 이상, 합성 툴이 자동으로 로직을 구현합니다. 속도와 면적을 바꾸고 싶다면, 합성 툴 메뉴얼을 확인해야 하며, 필요할 경우 직접 로직 구현해야 합니다.

 

● Adder (덧셈기)

 

x 비트와 y 비트를 더하면 x + y 둘중 큰 비트수 더하기 1개의 비트 수가 출력되어야 합니다.

더하기 1은 carry 비트가 추가 되는 것으로 더하다 보면, 5 + 9 = 14와 같이 한 자리씩 더하더라도 결과는 두자리가 나올 수 있기 때문입니다.  (3 비트 + 5 비트 = 6 비트)

 

1. unsigned = unsigned + unsigned

가장 신경 쓰이지 않는 덧셈기입니다.

양수 더하기 양수는 양수. ( 2 + 3 = 5 )

 

예제

module unsigned_adder (

input    [3:0]    a,

input    [3:0]    b,

output  [4:0]    sum

);

assign    sum = a + b;

endmodule

 

 

2. signed = signed + signed

정수 더하기 정수 는 정수, 2 + (-3) = -1

 

예제

module signed_adder (

input    signed    [3:0]    a,

input    signed    [3:0]    b,

output  signed    [4:0]    sum

);

assign    sum = a + b;

endmodule

 

 

3. signed + unsigned ???

정수 + 양수 = ???

(-5) + 9 = 4

1 0 1 1 (-5)    -> signed

+    1 0 0 1 (9)    -> unsigned

------------------

    1 0 1 0 0 (-12)    -> signed

 

예제

module signed_adder (

input    signed    [3:0]    a,

input                  [3:0]    b,

output  signed    [4:0]    sum

);

assign    sum = a + b;

endmodule

 

이대로 된다면 문제가 큽니다.

그래서 signed연산에 끼어 있는 unsigned는 자기 신분을 분명히 할 필요가 있습니다.

양수는 양의 정수 이기 때문에 sign bit에 '0'을 붙여 줍니다.

 

1 1 0 1 1 (-5)    -> signed

+    0 1 0 0 1 (9)    -> unsigned

------------------

0 0 1 0 0 (4)    -> signed

 

예제

module signed_adder (

input    signed    [3:0]    a,

input                  [3:0]    b,

output  signed    [4:0]    sum

);

assign    sum = a + {1'b0, b};

endmodule

 

● Multiplier (곱셈기)

 

덧셈기와 거의 비슷합니다. 출력 비트수는 x 비트와 y비트를 곱하면 x + y 비트입니다.

 

1. signed + unsigned

 

예제

module signed_adder (

input    signed    [5:0]    a,

input                  [3:0]    b,

output  signed    [9:0]    sum

);

assign    sum = a * {1'b0, b};

endmodule

 

● 기타 : Subtractor(뺄셈기), Divider(나눗셈기)

 

뺄셈기는 덧셈기에 음수를 더하는 형태로 구현됩니다. 그래서 덧셈기라고 보면 됩니다.

나눗셈기는 2의 N승으로 나눌 때는 N비트 쉬프트 동작으로 구현합니다. 2(2^1)로 나누면 오른쪽 한 비트 쉬프트, 4(2^2)로 나누면 두번, 8(2^3)로 나누면 세번하면 간단히 구현할 수 있다. 하지만 이외의 경우는 잘 사용하지 않습니다. (속도와 면적 문제로...)

 

verilog 에서 사칙연산은 단독으로 있을 때는 그나마 이렇게 이해 되지만, 곱셈, 덧셈등이 섞여 있는 경우(대부분 이렇죠)는 출력 비트수와 signed, unsigned 를 계속 따지면서 설계하여야 합니다.

 

 

반응형