類似半加器和全加器,也有半減器和全減器。
半減器只考慮當前兩位二進制數相減,輸出為差以及是否向高位借位,而全減器還要考慮當前位的低位是否曾有借位。它們的真值表如下:
對半減器,diff = x ^y, cin = ~x&y
對全減器,要理解真值表,可以用舉列子的方法得到,比如4’b1000-4b'0001,則第一位對應0 1 0 1 1第二位對應的是0 0 1 1 1
從真值表中,可以得到 diff = x ^ y ^cout, cin = (~x&(y^cout))|(y&cout)
推導過程:diff = ~x&~y&cout + ~x&y&~cout +x&~y&~cout+x&y&cout=~x&(~y&cout+y&~cout)+x&(~y&~cout+y&cout)=~x&(y^cout)+x&~(y^cout)=x^y^cout;
cin = ~x&~y&cout+~x&y&~cout+~x&y&cout+x&y&cout=~x&(~y&cout+~x&~cout)+(~x+x)&y&cout=~x&(y^cout)+y&cout
注意:這兒 +和|都表示或。
半減器的verilog代碼和testbench代碼如下:

module halfsub(x,y,d,cin); input x; input y; output d; output cin; assign d = x^y; assign cin = (~x)&y; endmodule

`timescale 1ns/1ns
`define clock_period 20
module halfsub_tb;
reg x,y;
wire cin; //carryover
wire d;
reg clk;
halfsub halfsub_0(
.x(x),
.y(y),
.d(d),
.cin(cin)
);
initial clk = 0;
always #(`clock_period/2) clk = ~clk;
initial begin
x = 0;
repeat(20)
#(`clock_period) x = $random;
end
initial begin
y = 0;
repeat(20)
#(`clock_period) y = $random;
end
initial begin
#(`clock_period*20)
$stop;
end
endmodule
用rtl viewer,可以看到半減器邏輯圖如下:
半減器功能驗證的波形:
全減器的verilog代碼和testbench代碼如下:

module fullsub(cout,x,y,d,cin);
input cout; // carry out bit, borrowed by its next low bit
input x;
input y;
output d;
output cin;
assign d = x^y^cout;
assign cin = (~x&(y^cout))|(y&cout);
endmodule

`timescale 1ns/1ns
`define clock_period 20
module fullsub_tb;
reg x,y,cout;
wire cin; //carryover
wire d;
reg clk;
fullsub fullsub_0(
.cout(cout),
.x(x),
.y(y),
.d(d),
.cin(cin)
);
initial clk = 0;
always #(`clock_period/2) clk = ~clk;
initial begin
x = 0;
repeat(20)
#(`clock_period) x = $random;
end
initial begin
y = 0;
repeat(20)
#(`clock_period) y = $random;
end
initial begin
cout = 0;
repeat(20)
#(`clock_period) cout = $random;
end
initial begin
#(`clock_period*20)
$stop;
end
endmodule
用rtl viewer,可以看到全減器邏輯圖如下:
全減器的功能驗證波形: