4비트 전가산기란?
Full Adder(FA): 덧셈을 수행하는 데 있어서 캐리(자리 올림수) 입력을 가진 가산기
4-bit의 입력 2개를 더하는 것 외에 c_in이라는 자리 올림수도 같이 더해야 한다.
※ 덧셈 연산이 느려지는 원인
자릿수마다 자리올림수가 계산되어야지만 다음 자릿수 덧셈을 할 수 있기 때문
즉, 자리올림수를 미리 알 수 있다면 덧셈의 계산속도 빠르게 할 수 있다.
자리올림수 예측 가산기란?
Carry Look-ahead Adder(CLA): 자리올림을 위해 이전 결괏값을 기다리지 않음
자리올림을 예측하기 위해 Propagation와 Generation 함수 사용
$P\left ( A,B \right )= A\oplus B$ (XOR 연산)
-> 이전의 결괏값과 상관없이 자리올림이 발생하는지 여부
-> 캐리(carry) 상관없이 sum 출력
(출력으로 전파된다) (값이 0 또는 1의 값을 갖는 것)
$G\left ( A,B \right )= A\cdot B$ (AND 연산)
-> 이전의 결괏값에 따라 자리올림이 발생할 가능성이 있는지 여부
-> 캐리(carry) 생성 (c_out 출력)
(c_out과 관련됨. 자리올림수가 무조건적으로 발생)
생성된 P와 G는 S와 C를 계산할 때 쓰인다.
$S_{i}=P_{i}\oplus C_{i}$
$C_{i+1}=G_{i}+(P_{i}\cdot C_{i})$
자리올림수 3번째 자리에서 C는 다음과 같다.
$C_{3}=G_{2}+(P_{2}\cdot C_{2})$
자리올림수 2번째 자리를 기다리지 않고 진행하기 위해서는 다음과 같이 풀어쓴다.
$C_{3}=G_{2}+(P_{2}\cdot (G_{2}+(P_{1}\cdot C_{1})))$
자리올림수를 순서대로 진행한다면 아래 그림과 같이 진행된다.
(자리올림 C1~C4의 경우를 슬라이드 형식으로 첨부해놨습니다.)
데이터플로우 기술방법으로 가산기를 설계할 것이다. (wire, assign 사용)
testbench 파일은 따로 만들지 않고, rtl 파일만 만들었다.
- 입력: a(4비트), b(4비트), c_in(1비트)
- 출력: c_out(1비트), sum(4비트)
* TestBench
module tb_adder;
reg [3:0] A, B;
reg C_IN;
wire [3:0] SUM;
wire C_OUT;
adder ADD1_4(C_OUT, SUM, A, B, C_IN);
initial
begin
$monitor($time, " A= %b, B= %b, C_IN= %b, --- C_OUT= %b, SUM= %b\n", A, B, C_IN, C_OUT, SUM);
end
initial
begin
A = 4'd0; B = 4'd0; C_IN = 1'b0;
#5 A = 4'd3; B = 4'd4;
#5 A = 4'd2; B = 4'd5;
#5 A = 4'd9; B = 4'd9;
#5 A = 4'd10; B = 4'd15;
#5 A = 4'd10; B = 4'd5; C_IN = 1'b1;
end
$monitor();
시뮬레이션 결과를 보기 쉽게 모니터로 출력하였다.
$monitor는 신호의 값이 변할 때마다 출력한다.
반면 $diplay는 c언어의 printf 함수와 같이 한 번만 출력한다.
* RTL: Full Adder(FA)
module adder ( c_out, sum, a, b, c_in);
input [3:0] a, b; // 4비트 벡터 표현
input c_in; // 1비트 스칼라 표현
output c_out;
output [3:0] sum;
wire c_out;
wire [3:0] sum;
assign {c_out, sum} = a + b + c_in;
endmodule
assign {c_out, sum} = a + b + c_in;
입력 a와 b, c_in을 더하여 c_out과 sum에 입력한다.
덧셈의 결과, 자리올림(carry)이 발생하면 c_out 값 발생
* RTL: Carry Look-ahead Adder(CLA)
module adder ( c_out, sum, a, b, c_in );
input [3:0] a, b;
input c_in;
output c_out;
output [3:0] sum;
wire c_out;
wire [3:0] sum;
// 내부 wire 신호 추가 선언
wire p0,g0, p1,g1, p2,g2, p3,g3;
wire c4, c3, c2, c1;
// propagation
assign p0 = a[0] ^ b[0]; // xor
assign p1 = a[1] ^ b[1];
assign p2 = a[2] ^ b[2];
assign p3 = a[3] ^ b[3];
// generation
assign g0 = a[0] & b[0]; // and
assign g1 = a[1] & b[1];
assign g2 = a[2] & b[2];
assign g3 = a[3] & b[3];
// 첫번째 무조건적인 캐리: g#
// 두번째 sum의 결과인 p1와 뒤에서 올라온 캐리값 g0
// 세번째 현재결과와 입력 자리올림수와의 캐리연산 &
assign c1 = g0 | (p0 & c_in);
assign c2 = g1 | (p1 & g0) | ( p1 & p0 & c_in);
assign c3 = g2 | (p2 & g1) | (p2 & p1 & g0) | (p2 & p1 & p0 & c_in);
assign c4 = g3 | (p3 & g2) | (p3 & p2 & g1) | (p3 & p2 & p1 & g0) | (p3 & p2 & p1 & p0 & c_in);
assign sum[0] = p0 ^ c_in;
assign sum[1] = p1 ^ c1;
assign sum[2] = p2 ^ c2;
assign sum[3] = p3 ^ c3;
assign c_out = c4;
endmodule
각각의 자리올림수 값을 풀어서 쓰면 다음과 같다.
assign c1 = g0 | (p0 & c_in);
///////////////////////////////////////////////////////////////
assign c2 = g1 | (p1 & g0) | ( p1 & p0 & c_in);
assign c2 = g1 | p1 & ( g0 | (p0 & c_in) );
assign c2 = g1 | p1 & c1;
///////////////////////////////////////////////////////////////
assign c3 = g2 | (p2 & g1) | (p2 & p1 & g0) | (p2 & p1 & p0 & c_in);
assign c3 = g2 | p2 & ( g1 | (p1 & g0) | (p1 & p0 & c_in) );
assign c3 = g2 | p2 & c2
///////////////////////////////////////////////////////////////
assign c4 = g3 | (p3 & g2) | (p3 & p2 & g1) | (p3 & p2 & p1 & g0) | (p3 & p2 & p1 & p0 & c_in);
assign c4 = g3 | p3 & ( g2 | (p2 & g1) | (p2 & p1 & g0) | (p2 & p1 & p0 & c_in) );
assign c4 = g3 | p3 & c3
실행 결과
A, B, C_IN을 이진수로 덧셈 연산하면 {C_OUT, SUM}이 출력된다.
// tb_adder.v 코드의 일부분
A = 4'd0; B = 4'd0; C_IN = 1'b0;
#5 A = 4'd3; B = 4'd4;
#5 A = 4'd2; B = 4'd5;
#5 A = 4'd9; B = 4'd9;
#5 A = 4'd10; B = 4'd15;
#5 A = 4'd10; B = 4'd5; C_IN = 1'b1;
0 -- 모두 다 0
5 -- A = 3(0011), B = 4(0100), C_IN=0 --> C_OUT = 0, SUM = 7(0111) {0_0111}
10 -- A = 2(0010), B = 5(0101), C_IN=0 --> C_OUT = 0, SUM = 7(0111) {0_0111}
15 -- A = 9(1001), B = 9(1001), C_IN=0 --> C_OUT = 1, SUM = 18(0010) {1_0010}
20 -- A = 10(1010), B = 15(1111), C_IN=0 --> C_OUT = 1, SUM = 25(1001) {1_1001}
25 -- A = 10(1010), B = 5(0101), C_IN=1 --> C_OUT = 1, SUM = 15(0000) {1_0000}
- 참고 -
Verilog HDL 디지털 설계와 합성의 길잡이 (한국어판)
'Verilog HDL' 카테고리의 다른 글
[순차회로] 교통 신호 제어기 설계하기 (0) | 2021.08.24 |
---|---|
순차회로와 FSM (0) | 2021.08.23 |
[조합회로] 4:1 멀티플렉서 설계하기 (0) | 2021.07.28 |
[ModelSim] Verilog 조합회로 설계 방법 (0) | 2021.07.28 |
[ModelSim] 컴파일 및 시뮬레이션 자동화 방법 (0) | 2021.07.27 |