
14–5 = 1110–0101
Change 5(0101) by using 2’s Complement
0101-> 1010+1 -> 1011
14–5=1110+1011, carry=1

12–7 = 1100–0111 = 1100+1001= 0101, carry =1
Change B by adding NOT, and put Carry 1 to make 2’s complement

When CTR is 1, XOR gate make B invert for 2’s complement. (act as Subtractor)
When CTR is 0, this circuit act as Adder

when A<B , result is minus, like 10–12=-2
put the NOT gate and AND gate

Sum = A ⊕ B ⊕ Cin
Cout = (A & B) | (A & Cin) | (B & Cin)
module full_adder(
input a, b, cin,
output sum, cout);
assign sum = a^b^cin;
assign cout = (a & b) | (b & cin) | (a & cin);
endmodule
module ripple_carry_adder_subtractor (
input [3:0] A, B,
input CTRL,
output [3:0] S, Cout);
wire [3:0] Bc; // Bc = B complement
assign Bc = B ^ {4{CTRL}};
full_adder fa0(A[0], Bc[0], CTRL, S[0], Cout[0]);
full_adder fa1(A[1], Bc[1], Cout[0], S[1], Cout[1]);
full_adder fa2(A[2], Bc[2], Cout[1], S[2], Cout[2]);
full_adder fa3(A[3], Bc[3], Cout[2], S[3], Cout[3]);
endmodule
Bc = B ^ {4{CTRL}}; 이거를 풀어서 쓰면 아래와 같다
assign Bc[0] = B[0] ^ CTRL;
assign Bc[1] = B[1] ^ CTRL;
assign Bc[2] = B[2] ^ CTRL;
assign Bc[3] = B[3] ^ CTRL;
이런 식으로 캐리가 Ripple(흘러가는) 구조가 되기 때문에
→ 이름이 “Ripple Carry Adder” 입니다.
자리(g) full_adder 입력 설명
g=1 A[1], Bc[1], Cout[0] 이전 자리의 캐리(Cout[0])를 입력으로 받음
g=2 A[2], Bc[2], Cout[1] Cout[1]을 입력으로 받음
g=3 A[3], Bc[3], Cout[2] Cout[2]을 입력으로 받음
이건 각 비트마다 B를 반전시킬지 말지를 정하는 코드
따라서 Bc[g]는 덧셈일 때는 그냥 B,뺄셈일 때는 반전된 B 값
그리고 첫 자리의 cin이 1이므로 결과적으로 A + (~B) + 1이 되어 A - B 가 됨.
┌───────────────┐
A[0] ───► │ │
B[0] ─►XOR──► full_adder fa0│──► Cout[0]
CTRL ───────► (Cin = CTRL) │
└───────────────┘
│
▼
┌───────────────┐
A[1] ───► │ full_adder fa1│──► Cout[1]
B[1] ─►XOR──► (Cin = Cout[0])│
└───────────────┘
│
▼
┌───────────────┐
A[2] ───► │ full_adder fa2│──► Cout[2]
B[2] ─►XOR──► (Cin = Cout[1])│
└───────────────┘
│
▼
┌───────────────┐
A[3] ───► │ full_adder fa3│──► Cout[3]
B[3] ─►XOR──► (Cin = Cout[2])│
└───────────────┘
Testbench
module RCAS_TB;
wire [3:0] S, Cout;
reg [3:0] A, B;
reg ctrl;
//DUT (Device Under Test) 연결
ripple_carry_adder_subtractor rcas(A, B, ctrl, S, Cout);
initial begin //initial 블록은 시뮬레이션이 시작될 때 한 번만 실행됨.
$monitor("CTRL=%b: A = %b, B = %b --> S = %b, Cout[3] = %b", ctrl, A, B, S, Cout[3]);
ctrl = 0;
A = 1; B = 0;
#3 A = 2; B = 4;
#3 A = 4'hb; B = 4'h6; //16진수 11, 16진수 6
#3 A = 5; B = 3;
ctrl = 1;
A = 1; B = 0;
#3 A = 2; B = 4;
#3 A = 4'hb; B = 4'h6;
#3 A = 5; B = 3;
#3 $finish;
end
initial begin
$dumpfile("waves.vcd");
$dumpvars;
end
endmodule
$monitor — 콘솔에 결과 출력
$dumpfile, $dumpvars — 파형 파일 저장
시뮬레이터가 파형(waveform) 파일을 저장하게 하는 명령
"waves.vcd"라는 파일에 시간에 따른 신호 변화를 저장

ALL ABOUT ELECTRONICS 4-bit Adder and Subtractor Circuit Explained https://youtu.be/J7gPUP0aRug?si=3Kagk_--fqSdvPkT
VLSI Verify, https://vlsiverify.com/verilog/verilog-codes/4-bit-adder-subtractor/