네이버 이웃 추가 / GitHub Profile / 카카오톡 채널 추가 / 방명록 / 이용 안내

[Verilog]RCA, CLA Adder, Subtractor

수성컴 | 2025. 12. 02.
[Verilog]RCA, CLA Adder, Subtractor

오늘은 Verilog로 32-bit 덧셈기(가산기, adder)와 뺄셈기(감산기, subtractor)를 구현해 보겠습니다. 덧셈기는 Ripple Carry Adder 방식과 Carry Look-Ahead Adder 방식으로 구현해 보겠습니다.

  • IDE: Intel Quartus 18.1
  • Device: Cyclone V 5CSXFC6D6F31C6(밑에서 6번째)
  • Simulation: ModelSim-Altera, Verilog HDL

목차

1. Ripple Carry Adder
1.1. Half Adder
1.2. Full Adder
1.3. Ripple Carry Adder 구현 방법
1.4. rca32.v
1.5. tb_rca32.v
1.6. RTL View
1.7. RTL Simulation
1.8. Flow Summary

2. Carry Look-Ahead Adder
2.1. Carry Look-Ahead Adder는 무엇인가?
2.2. CLA Adder Delay
2.3. cla32.v
2.4. tb_cla32.v
2.5. RTL View
2.6. RTL Simulation
2.7. Flow Summary

3. Subtractor
3.1. Subtractor 구현 방법
3.2. sub32.v
3.3. tb_sub32.v
3.4. RTL View
3.5. RTL Simulation
3.6. Flow Summary

4. 글 마무리
5. 참고 문헌

1. Ripple Carry Adder

  • Project Name & the name of Top-level: rca32

1.1. Half Adder

Half Adder
Half Adder는 AB를 input으로 하고, S와 \(C_{out}\)을 output으로 합니다.
S는 A와 B의 합이고, \(C_{out}\)은 받아올림(carry out)을 나타냅니다.
Boolean eqation은 아래와 같습니다.
\(S=A \oplus B\)
\(C_{out}=AB\)

1.2. Full Adder

Full Adder Truth Table
Full Adder는 Half Adder에 \(C_{in}\)이 input으로 추가된 형태입니다.
A, B, \(C_{in}\)을 input으로 하고, S와 \(C_{out}\)을 output으로 합니다.
\(C_{in}\)은 carry in으로, 이전 bit에서 받아올림된 것을 더하는 데 사용됩니다.

Full Adder S K-Map
S를 도출하기 위해 Karnaugh Map을 그려 보면
\(\begin{align}
S &= \bar{A} \bar{B} C_{in} + \bar{A} B \overline{C_{in}} + A B C_{in} + A \bar{B} \overline{C_{in}} \\
&= C_{in} (\bar{A} \bar{B} + A B) + \overline{C_{in}}(\bar{A} B + A \bar{B}) \\
&= C_{in} \oplus A \oplus B
\end{align}\)
가 나옵니다.

Full Adder C_out K-Map
\(C_{out}=AB+BC_{in}+AC_{in}\)입니다.

1.3. Ripple Carry Adder 구현 방법

Ripple Carry Adder
Full Adder 1개는 1-bit 덧셈밖에 못하지만 Full Adder를 여러 개 연결하여 Ripple Carry Adder를 만들면 여러 bit 덧셈을 할 수 있습니다.
i번째 bit의 carry out이 i+1번째 bit의 carry in이 됩니다.
사실 LSB(Least Significant Bit)는 Half Adder를 써도 덧셈을 수행할 수 있지만 어차피 Subtractor를 만들 때 LSB의 carry in도 써야 하므로 Full Adder로 만들겠습니다.

1.4. rca32.v

Ripple Carry Adder Block Diagram
32-bit Ripple Carry Adder를 만들어 보겠습니다. Full Adder를 그냥 32개 연달아 작성하려면 힘드니까 rca32, rca16, rca4, fa(Full Adder)로 나누어서 rca4는 fa를 4개 instantiation하고, rca16rca4를 4개 instantiation하고, rca32rca16을 2개 instantiation하겠습니다.

module rca32(a, b, ci, s, co);	//32-bit Ripple Carry Adder
	input [31:0] a, b;	    //operand
	input ci;				//carry in
	output [31:0] s;		//sum
	output co;				//carry out
	wire w0;
	
	rca16 U0_rca16(a[15:0], b[15:0], ci, s[15:0], w0);
	rca16 U1_rca16(a[31:16], b[31:16], w0, s[31:16], co);
endmodule

module fa(a, b, ci, s, co);	//full adder
	input a, b;		//operand
	input ci;		//carry in
	output s;		//sum
	output co;		//carry out
	wire w0, w1, w2;

	assign s=a^b^ci;
	assign co=a&b|a&ci|b&ci;
endmodule

module rca4(a, b, ci, s, co);	//4-bit Ripple Carry Adder
	input [3:0] a, b;	//operand
	input ci;			//carry in
	output [3:0] s;	    //sum
	output co;			//carry out
	wire w0, w1, w2;
	
	fa U0_fa(a[0], b[0], ci, s[0], w0);
	fa U1_fa(a[1], b[1], w0, s[1], w1);
	fa U2_fa(a[2], b[2], w1, s[2], w2);
	fa U3_fa(a[3], b[3], w2, s[3], co);
endmodule

module rca16(a, b, ci, s, co);	//16-bit Ripple Carry Adder
	input [15:0] a, b;	    //operand
	input ci;				//carry in
	output [15:0] s;		//sum
	output co;				//carry out
	wire [3:0] w0, w1, w2;
	
	rca4 U0_rca4(a[3:0], b[3:0], ci, s[3:0], w0);
	rca4 U1_rca4(a[7:4], b[7:4], w0, s[7:4], w1);
	rca4 U2_rca4(a[11:8], b[11:8], w1, s[11:8], w2);
	rca4 U3_rca4(a[15:12], b[15:12], w2, s[15:12], co);
endmodule

1.5. tb_rca32.v

`timescale 1ns/100ps
 
module tb_rca32();
	reg [31:0] a, b;
	reg ci;
	wire [31:0] s;
	wire co;
	
	rca32 dut(a, b, ci, s, co);
	
	initial begin
		a=0; b=0; ci=0; #10;
		if(s==0)	$display("%d+%d=%d, co=%b (when ci=%b)", a, b, s, co, ci);
		else		$display("%d+%d=%d, co=%b failed (when ci=%b)", a, b, s, co, ci);
		
		a=0; b=1; ci=0; #10;
		if(s==1)	$display("%d+%d=%d, co=%b (when ci=%b)", a, b, s, co, ci);
		else		$display("%d+%d=%d, co=%b failed (when ci=%b)", a, b, s, co, ci);
		
		a=1; b=0; ci=0; #10;
		if(s==1)	$display("%d+%d=%d, co=%b (when ci=%b)", a, b, s, co, ci);
		else		$display("%d+%d=%d, co=%b failed (when ci=%b)", a, b, s, co, ci);
		
		a=1; b=1; ci=0; #10;
		if(s==2)	$display("%d+%d=%d, co=%b (when ci=%b)", a, b, s, co, ci);
		else		$display("%d+%d=%d, co=%b failed (when ci=%b)", a, b, s, co, ci);
		
		a=51; b=10; ci=0; #10;
		if(s==61)	$display("%d+%d=%d, co=%b (when ci=%b)", a, b, s, co, ci);
		else		$display("%d+%d=%d, co=%b failed (when ci=%b)", a, b, s, co, ci);
		
		a=5; b=-3; ci=0; #10;
		if(s==2)	$display("%d+%d=%d, co=%b (when ci=%b)", a, b, s, co, ci);
		else		$display("%d+%d=%d, co=%b failed (when ci=%b)", a, b, s, co, ci);
		
		a=-5; b=-3; ci=0; #10;
		if(s==-8)	$display("%d+%d=%d, co=%b (when ci=%b)", a, b, s, co, ci);
		else		$display("%d+%d=%d, co=%b failed (when ci=%b)", a, b, s, co, ci);
		
		a=51; b=-32; ci=0; #10;
		if(s==19)	$display("%d+%d=%d, co=%b (when ci=%b)", a, b, s, co, ci);
		else		$display("%d+%d=%d, co=%b failed (when ci=%b)", a, b, s, co, ci);
		
		a=0; b=0; ci=1; #10;
		if(s==1)	$display("%d+%d=%d, co=%b (when ci=%b)", a, b, s, co, ci);
		else		$display("%d+%d=%d, co=%b failed (when ci=%b)", a, b, s, co, ci);
		
		a=0; b=1; ci=1; #10;
		if(s==2)	$display("%d+%d=%d, co=%b (when ci=%b)", a, b, s, co, ci);
		else		$display("%d+%d=%d, co=%b failed (when ci=%b)", a, b, s, co, ci);
		
		a=1; b=0; ci=1; #10;
		if(s==2)	$display("%d+%d=%d, co=%b (when ci=%b)", a, b, s, co, ci);
		else		$display("%d+%d=%d, co=%b failed (when ci=%b)", a, b, s, co, ci);
		
		a=1; b=1; ci=1; #10;
		if(s==3)	$display("%d+%d=%d, co=%b (when ci=%b)", a, b, s, co, ci);
		else		$display("%d+%d=%d, co=%b failed (when ci=%b)", a, b, s, co, ci);
		
		a=51; b=10; ci=1; #10;
		if(s==62)	$display("%d+%d=%d, co=%b (when ci=%b)", a, b, s, co, ci);
		else		$display("%d+%d=%d, co=%b failed (when ci=%b)", a, b, s, co, ci);
		
		a=5; b=-3; ci=1; #10;
		if(s==3)	$display("%d+%d=%d, co=%b (when ci=%b)", a, b, s, co, ci);
		else		$display("%d+%d=%d, co=%b failed (when ci=%b)", a, b, s, co, ci);
		
		a=-5; b=-3; ci=1; #10;
		if(s==-7)	$display("%d+%d=%d, co=%b (when ci=%b)", a, b, s, co, ci);
		else		$display("%d+%d=%d, co=%b failed (when ci=%b)", a, b, s, co, ci);
		
		a=51; b=-32; ci=1; #10;
		if(s==20)	$display("%d+%d=%d, co=%b (when ci=%b)", a, b, s, co, ci);
		else		$display("%d+%d=%d, co=%b failed (when ci=%b)", a, b, s, co, ci);
	end
endmodule

이번에는 변수를 10진수로 다루는 것이 편할 것 같아서 a와 b를 10진수로 입력하고 콘솔 창에 모든 결과를 띄우도록 했습니다.

[Line 13]
if(s==0) $display(“%d+%d=%d, co=%b (when ci=%b)”, a, b, s, co, ci);
%d는 10진수로, %b는 2진수로 출력합니다.

1.6. RTL View

rca32 RTL View
rca32는 rca16을 2개 instantiation합니다.

rca16 RTL View
rca16은 rca4를 4개 instantiation합니다.

rca4 RTL View
rca4는 fa를 4개 instantiation합니다.

fa RTL View
fa는 AND Gate 3개, OR Gate 1개, XOR Gate 1개로 구성되었습니다.

fa Bubble Pushing
그러나 실제로 회로를 만들 때는 AND와 OR 대신 NAND를 쓰는 것이 더 저렴하기 때문에 Bubble Pushing을 해야 할 것입니다.

1.7. RTL Simulation

rca32 RTL Simulation
어째선지 콘솔 창에 음수가 제대로 뜨지 않지만, 일단 회로 자체는 오류가 없습니다.
Waveform에서 a, b, s는 10진수(decimal)로 표시하도록 설정을 변경해 주었습니다.

1.8. Flow Summary

rca32 Flow Summary
Logic utiliazation은 43, Total registers는 0, Total pins는 98이 나옵니다.

2. Carry Look-Ahead Adder

  • Project Name & the name of Top-level: cla32

2.1. Carry Look-Ahead Adder는 무엇인가?

Ripple Carry Adder는 덧셈을 하기 위해서 그 전 bit의 carry out을 알아야 하기 때문에 속도가 느립니다. Full Adder의 delay를 \(t_{FA}\)라고 하면 N-bit Ripple Carry Adder의 delay는 \(t_{ripple}=Nt_{FA}\)가 됩니다.
이 단점을 보완하고자 쓰는 것이 Carry Look-Ahead(CLA) Adder입니다. CLA block을 나눠서 일정 bit마다 carry만 빠르게 연산하여 delay를 단축합니다.

이를 위하여 generate signal(\(G_i\))과 propagate signal(\(P_i\))을 정의합니다.
\(G_i = A_i B_i\)
\(P_i = A_i + B_i\)

1.2절에서 \(C_{out}=AB+BC_{in}+AC_{in}\)이었으므로
\(\begin{align}
C_i &= A_i B_i + B_i C_{i-1} + A C_{i-1} \\
&= A_i B_i + (A_i + B_i) C_{i-1} \\
&= G_i + P_i C_{i-1}
\end{align}\)
이 됩니다.

i=0을 대입하면
\(C_0 = G_0 + P_0 C_{-1}\)
인데 \(C_{-1}=C_{in}\)입니다.
따라서 \(C_0 = G_0 + P_0 C_{in}\)이 됩니다.

이어서 i에 1부터 3까지 대입하면
\(\begin{align}
C_1 &= G_1 + P_1 C_0 \\
&= G_1 + P_1 (G_0 + P_0 C_{in}) \\
&= G_1 + P_1 G_0 + P_1 P_0 C_{in}
\end{align}\)
\(\begin{align}
C_2 &= G_2 + P_2 C_1 \\
&= G_2 + P_2 (G_1 + P_1 G_0 + P_1 P_0 C_{in}) \\
&= G_2 + P_2 (G_1 + P_1 G_0) + P_2 P_1 P_0 C_{in}
\end{align}\)
\(\begin{align}
C_3 &= G_3 + P_3 C_2 \\
&= G_3 + P_3 (G_2 + P_2 (G_1 + P_1 G_0) + P_2 P_1 P_0 C_{in}) \\
&= G_3 + P_3 (G_2 + P_2 (G_1 + P_1 G_0)) + P_3 P_2 P_1 P_0 C_{in}
\end{align}\)
입니다.

마지막 식에서
\(G_3 + P_3 (G_2 + P_2 (G_1 + P_1 G_0)) = G_{3:0}\),
\(P_3 P_2 P_1 P_0 C_{in} = P_{3:0}\)
으로 치환하겠습니다.

Carry Look-Ahead Adder
회로도로 나타내면 위와 같습니다. 이것만 가지고는 carry만 구할 수 있을 뿐 덧셈 결과를 알 수 없기 때문에 4-bit Ripple Carry Adder를 함께 사용해야 합니다.

2.2. CLA Adder Delay

CLA Delay
CLA Adder Delay는 위의 이미지와 같습니다.

  • \(t_{pg}\): generate and propagate gates의 delay. AND 또는 OR Gate 1개의 delay와 같습니다.
  • \(t_{pg\_block}\): the block generate and propagate gates의 delay. 그러나 \(P_{3:0}\) 쪽은 \(G_{3:0}\) 쪽과 동시 진행되면서 \(P_{3:0}\) 쪽이 \(G_{3:0}\) 쪽보다 빨리 끝나기 때문에, 제가 빨간색으로 표시한 \(G_{3:0}\) 쪽만 생각하시면 됩니다.
  • \(t_{AND\_OR}\): \(C_{in}\)에서 \(C_{out}\)까지 거치는 AND/OR Gate에서 발생하는 delay
  • \(t_{FA}\): Full Adder의 delay

N-bit CLA Adder는 N>16일 때 Ripple Carry Adder보다 훨씬 빨라집니다.

그런데 공식만 봐서는 무슨 말인지 잘 모르겠죠?
32-bit CLA Adder with 4-bit blocks 예제로 살펴보겠습니다.

Compare the delays of a 32-bit ripple-carry adder and a 32-bit carry-lookahead adder with 4-bit blocks. Assume that each two-input gate delay is 100 ps and that a full adder delay is 300 ps.
(출처: David Money Harris, Sarah L. Harris. 2013. Digial Design and Computer Architecture. 2nd Edition. Elsevier Korea L.L.C. Example 5.1(p. 243).)

위의 이미지와 아래의 해설을 함께 보시기 바랍니다.

“two-input gate delay is 100 ps”라는 것은 AND Gate delay와 OR Gate delay가 100ps라는 것입니다.

  • \(t_{pg}=100\textnormal{ps}\)
  • \(t_{pg\_block} = 6 \times 100 \textnormal{ps} = 600 \textnormal{ps}\)
  • \(t_{AND\_OR} = 2 \times 100 \textnormal{ps} = 200 \textnormal{ps}\)
  • \(t_{FA}=300\textnormal{ps}\)

\(\begin{align}
\therefore t_{CLA} &= 100\textnormal{ps} + 600\textnormal{ps} + (32/4-1) \times 200\textnormal{ps} + 4 \times 300\textnormal{ps} \\
&= 3300\textnormal{ps} \\
&= 3.3\textnormal{ns}
\end{align}\)

여기까지 하면 일단 32-bit CLA Adder with 4-bit blocks의 delay는 구한 것입니다.
그런데 예제에서 32-bit Ripple Carry Adder와 비교하라고 했으니 문제를 끝까지 풀어 보면
\(\begin{align}
t_{ripple} &= 32 \times 300 \textnormal{ps} \\
&= 9600 \textnormal{ps} \\
&= 9.6 \textnormal{ns}
\end{align} \\
\therefore t_{CLA} < t_{ripple}\)
이 되겠습니다.

2.3. cla32.v

32-bit CLA Block Diagram
32-bit CLA Adder with 4-bit blocks를 Verilog로 구현하겠습니다.
clb4(4-bit CLA Block)rca4carry를 instantiation합니다.
cla32clb4를 8개 instantiation합니다.

module cla32(a, b, ci, s, co);	//32-bit Carry Look-Ahead Adder
	input [31:0] a, b;	    //operand
	input ci;				//carry in
	output [31:0] s;		//sum
	output co;				//carry out
	wire w0, w1, w2, w3, w4, w5, w6, w7;
	
	clb4 U0_clb4(a[3:0], b[3:0], ci, s[3:0], w0);
	clb4 U1_clb4(a[7:4], b[7:4], w0, s[7:4], w1);
	clb4 U2_clb4(a[11:8], b[11:8], w1, s[11:8], w2);
	clb4 U3_clb4(a[15:12], b[15:12], w2, s[15:12], w3);
	clb4 U4_clb4(a[19:16], b[19:16], w3, s[19:16], w4);
	clb4 U5_clb4(a[23:20], b[23:20], w4, s[23:20], w5);
	clb4 U6_clb4(a[27:24], b[27:24], w5, s[27:24], w6);
	clb4 U7_clb4(a[31:28], b[31:28], w6, s[31:28], co);
endmodule

module fa(a, b, ci, s, co);	//full adder
	input a, b;		//operand
	input ci;		//carry in
	output s;		//sum
	output co;		//carry out
	wire w0, w1, w2;

	assign s=a^b^ci;
	assign co=a&b|a&ci|b&ci;
endmodule

module rca4(a, b, ci, s, co);	//4-bit Ripple Carry Adder
	input [3:0] a, b;	//operand
	input ci;			//carry in
	output [3:0] s;	    //sum
	output co;			//carry out
	wire w0, w1, w2;
	
	fa U0_fa(a[0], b[0], ci, s[0], w0);
	fa U1_fa(a[1], b[1], w0, s[1], w1);
	fa U2_fa(a[2], b[2], w1, s[2], w2);
	fa U3_fa(a[3], b[3], w2, s[3], co);
endmodule

module carry4(a, b, ci, co);	//4-bit Carry Look-Ahead Carry
	input [3:0] a, b;	//operand
	input ci;			//carry in
	output co;			//carry out
	wire [3:0] g, p;
	
	assign g=a&b;
	assign p=a|b;
	
	assign co=g[3]|p[3]&(g[2]|p[2]&(g[1]|p[1]&g[0]))|p[3]&p[2]&p[1]&p[0]&ci;
endmodule

module clb4(a, b, ci, s, co);	//4-bit Carry Look-Ahead Block
	input [3:0] a, b;
	input ci;
	output [3:0] s;
	output co;
	
	rca4 U0_rca4(a, b, ci, s,);
	carry4 U1_carry4(a, b, ci, co);	
endmodule

[Line 49]
rca4 U0_rca4(a, b, ci, s,);
carry out은 CLA로 따로 구하기 때문에 rca4 module에서 co port는 비워 둡니다.

2.4. tb_cla32.v

`timescale 1ns/100ps
 
module tb_cla32();
	reg [31:0] a, b;
	reg ci;
	wire [31:0] s;
	wire co;
	
	cla32 dut(a, b, ci, s, co);
	
	initial begin
		a=0; b=0; ci=0; #10;
		if(s==0)	$display("%d+%d=%d, co=%b (when ci=%b)", a, b, s, co, ci);
		else		$display("%d+%d=%d, co=%b failed (when ci=%b)", a, b, s, co, ci);
		
		a=0; b=1; ci=0; #10;
		if(s==1)	$display("%d+%d=%d, co=%b (when ci=%b)", a, b, s, co, ci);
		else		$display("%d+%d=%d, co=%b failed (when ci=%b)", a, b, s, co, ci);
		
		a=1; b=0; ci=0; #10;
		if(s==1)	$display("%d+%d=%d, co=%b (when ci=%b)", a, b, s, co, ci);
		else		$display("%d+%d=%d, co=%b failed (when ci=%b)", a, b, s, co, ci);
		
		a=1; b=1; ci=0; #10;
		if(s==2)	$display("%d+%d=%d, co=%b (when ci=%b)", a, b, s, co, ci);
		else		$display("%d+%d=%d, co=%b failed (when ci=%b)", a, b, s, co, ci);
		
		a=51; b=10; ci=0; #10;
		if(s==61)	$display("%d+%d=%d, co=%b (when ci=%b)", a, b, s, co, ci);
		else		$display("%d+%d=%d, co=%b failed (when ci=%b)", a, b, s, co, ci);
		
		a=5; b=-3; ci=0; #10;
		if(s==2)	$display("%d+%d=%d, co=%b (when ci=%b)", a, b, s, co, ci);
		else		$display("%d+%d=%d, co=%b failed (when ci=%b)", a, b, s, co, ci);
		
		a=-5; b=-3; ci=0; #10;
		if(s==-8)	$display("%d+%d=%d, co=%b (when ci=%b)", a, b, s, co, ci);
		else		$display("%d+%d=%d, co=%b failed (when ci=%b)", a, b, s, co, ci);
		
		a=51; b=-32; ci=0; #10;
		if(s==19)	$display("%d+%d=%d, co=%b (when ci=%b)", a, b, s, co, ci);
		else		$display("%d+%d=%d, co=%b failed (when ci=%b)", a, b, s, co, ci);
		
		a=0; b=0; ci=1; #10;
		if(s==1)	$display("%d+%d=%d, co=%b (when ci=%b)", a, b, s, co, ci);
		else		$display("%d+%d=%d, co=%b failed (when ci=%b)", a, b, s, co, ci);
		
		a=0; b=1; ci=1; #10;
		if(s==2)	$display("%d+%d=%d, co=%b (when ci=%b)", a, b, s, co, ci);
		else		$display("%d+%d=%d, co=%b failed (when ci=%b)", a, b, s, co, ci);
		
		a=1; b=0; ci=1; #10;
		if(s==2)	$display("%d+%d=%d, co=%b (when ci=%b)", a, b, s, co, ci);
		else		$display("%d+%d=%d, co=%b failed (when ci=%b)", a, b, s, co, ci);
		
		a=1; b=1; ci=1; #10;
		if(s==3)	$display("%d+%d=%d, co=%b (when ci=%b)", a, b, s, co, ci);
		else		$display("%d+%d=%d, co=%b failed (when ci=%b)", a, b, s, co, ci);
		
		a=51; b=10; ci=1; #10;
		if(s==62)	$display("%d+%d=%d, co=%b (when ci=%b)", a, b, s, co, ci);
		else		$display("%d+%d=%d, co=%b failed (when ci=%b)", a, b, s, co, ci);
		
		a=5; b=-3; ci=1; #10;
		if(s==3)	$display("%d+%d=%d, co=%b (when ci=%b)", a, b, s, co, ci);
		else		$display("%d+%d=%d, co=%b failed (when ci=%b)", a, b, s, co, ci);
		
		a=-5; b=-3; ci=1; #10;
		if(s==-7)	$display("%d+%d=%d, co=%b (when ci=%b)", a, b, s, co, ci);
		else		$display("%d+%d=%d, co=%b failed (when ci=%b)", a, b, s, co, ci);
		
		a=51; b=-32; ci=1; #10;
		if(s==20)	$display("%d+%d=%d, co=%b (when ci=%b)", a, b, s, co, ci);
		else		$display("%d+%d=%d, co=%b failed (when ci=%b)", a, b, s, co, ci);
	end
endmodule

사실 1.5절의 tb_rca32.v에서 모듈명만 바꾼 것입니다.

2.5. RTL View

cla32 RTL View
cla32는 clb4를 8개 instantiation합니다.

clb4 RTL View
clb4는 rca4와 carry4를 instantiation합니다.

carry4 RTL View
carry4는 이렇게 생겼습니다.

2.6. RTL Simulation

cla32 RTL Simulation
Waveform에서 a, b, s는 10진수(decimal)로 표시하도록 설정을 변경해 주었습니다.

2.7. Flow Summary

cla32 Flow Summary
Logic utiliazation은 52, Total registers는 0, Total pins는 98이 나옵니다.
Logic utiliazation은 CLA Adder가 Ripple Carry Adder보다 9개 더 많다는 것을 알 수 있습니다.

3. Subtractor

  • Project Name & the name of Top-level: sub32
  • Add file: cla32.v
    • cf) Ripple Carry Subtractor를 만들려면 rca32.v를 추가하세요.

3.1. Subtractor 구현 방법

\(\begin{align}
A-B &= A+(-B) \\
&= A+(\bar{B}+1)
\end{align}\)
라는 점을 이용합니다.

Subtractor
Adder에서 B를 invert하고, carry in에 1을 넣습니다.
Adder는 Ripple Carry Adder, CLA Adder 상관없습니다.

3.2. sub32.v

CLA로 Subtractor를 만들어 보겠습니다.

module sub32(a, b, s, co);	//32-bit Carry Look-Ahead Subtractor
	input [31:0] a, b;	    //operand
	output [31:0] s;		//sum
	output co;				//carry out
	wire b_inv;				//b inverted
	wire w0, w1, w2, w3, w4, w5, w6, w7;
	
	cla32 U0_cla32(a, ~b, 1, s, co);
endmodule

[Line 1]
module sub32(a, b, s, co);
carry in은 1로 고정이기 때문에 sub32의 port에서 빠졌습니다.

[Line 8]
cla32 U0_cla32(a, ~b, 1, s, co);
cla32를 instantiation할 때 ci에는 1을 넣습니다.

3.3. tb_sub32.v

`timescale 1ns/100ps
 
module tb_sub32();
	reg [31:0] a, b;
	wire [31:0] s;
	wire co;
	
	sub32 dut(a, b, s, co);
	
	initial begin
		a=0; b=0; #10;
		if(s==0)	$display("%d-%d=%d, co=%b", a, b, s, co);
		else		$display("%d-%d=%d, co=%b failed", a, b, s, co);
		
		a=0; b=1; #10;
		if(s==-1)	$display("%d-%d=%d, co=%b", a, b, s, co);
		else		$display("%d-%d=%d, co=%b failed", a, b, s, co);
		
		a=1; b=0; #10;
		if(s==1)	$display("%d-%d=%d, co=%b", a, b, s, co);
		else		$display("%d-%d=%d, co=%b failed", a, b, s, co);
		
		a=1; b=1; #10;
		if(s==0)	$display("%d-%d=%d, co=%b", a, b, s, co);
		else		$display("%d-%d=%d, co=%b failed", a, b, s, co);
		
		a=51; b=10; #10;
		if(s==41)	$display("%d-%d=%d, co=%b", a, b, s, co);
		else		$display("%d+%d=%d, co=%b failed", a, b, s, co);
		
		a=5; b=-3; #10;
		if(s==8)	$display("%d-%d=%d, co=%b", a, b, s, co);
		else		$display("%d-%d=%d, co=%b failed", a, b, s, co);
		
		a=-5; b=-3; #10;
		if(s==-2)	$display("%d-%d=%d, co=%b", a, b, s, co);
		else		$display("%d+%d=%d, co=%b failed", a, b, s, co);
		
		a=51; b=-32; #10;
		if(s==83)	$display("%d-%d=%d, co=%b", a, b, s, co);
		else		$display("%d-%d=%d, co=%b failed", a, b, s, co);
	end
endmodule

[Line 8]
sub32 dut(a, b, s, co);
carry in은 1로 고정이기 때문에 sub32의 port에서 빠졌다는 것을 잊지 마세요.

3.4. RTL View

sub32 RTL View
cla32의 ci에는 1이 들어갔습니다.

3.5. RTL Simulation

sub32 RTL Simulation
Waveform에서 a, b, s는 10진수(decimal)로 표시하도록 설정을 변경해 주었습니다.

3.6. Flow Summary

sub32 Flow Summary
Logic utiliazation은 51, Total registers는 0, Total pins는 97이 나옵니다.

4. 글 마무리

제 글을 읽어 주셔서 감사합니다. 다음에 만나요!

5. 참고 문헌

1) David Money Harris, Sarah L. Harris. 2013. Digial Design and Computer Architecture. 2nd Edition. Elsevier Korea L.L.C.