Quartus II/ ModelSim을 이용한 구현 - 4. ALU(Arithmetic Logic Unit), Substractor

2023. 1. 29. 17:08기록지/컴퓨터구조(computer architecture)

4. Substractor, Arithmetic Logic Unit  구현

 

원리

Substractor

대부분의 digital system에서 subtraction을 위하여 감수 (subtrand) two’s complement number(2의 보수)를 취해 더하게 된다. 2의 보수를 구하는 방법은 해당 입력을 invert한 후, 1을 더해주면 된다.

    A – B = A + (-B)

.

 

–B 를  2’s complement number 로 변경한다

 

Arithmetic logic unit

ALU(산술 논리 장치)는 두 숫자의 산술연산과 논리연산을 계산하는 디지털 회로이다.

Flag

ALU 내에서 특정 조건이나 상황이 만족되었을 때, 이를 표시해주는 것을 flag라 한다. 여기에서는 carry, negative, zero, overflow 4개의 flag를 갖는다.

C: Carry = 연산 결과 carry가 발생하는 경우

N: Negative = 연산 결과의 sign bit 1인 경우

Z: Zero = 연산 결과가 0인 경우

V: Overflow = 연산 결과 overflow가 발생하는 경우

 

N-bit ALU의 symbol
Structural Description

 

4-bit CLA to detect overflow
32-bit CLA

 

설계 검증

Top level entity name: alu4

Device family: Cyclone II EP2C70F896C6

logic elements 42 (1%이하)

pin 19 (3%)

 

RTL viewer
wave form

Input combination: a=0000, b=0000, op=000    Output: result=1111

Carry는 없고 MSB 1이므로 negative이고 zero가 아니며 overflow는 발생하지 않았다.

Op=000이므로 결과는 not a 1111이 나옴

Input combination: a=1100, b=0000, op=000    Output: result=0011

Carry는 없고 MSB 0이므로 negative, zero가 아니며 overflow는 발생하지 않았다.

Op=000이므로 결과는 not a 0011이 나옴

Input combination: a=1100, b=0011, op=001    Output: result=1100

Carry는 없고 MSB 1이므로 negative이고 zero가 아니며 overflow는 발생하지 않았다.

Op=001이므로 결과는 not b 1100이 나옴

Input combination: a=0101, b=1001, op=010    Output: result=0001

Carry는 없고 MSB 0이므로 negative, zero가 아니며 overflow는 발생하지 않았다.

Op=010이므로 결과는 a and b 0001이 나옴

Input combination: a=0101, b=1010, op=011    Output: result=1111

Carry는 없고 MSB 1이므로 negative이고 zero가 아니며 overflow는 발생하지 않았다.

Op=011이므로 결과는 a or b 1111이 나옴

Input combination: a=0011, b=0101, op=100    Output: result=0110

Carry는 없고 MSB 0이므로 negative, zero가 아니며 overflow는 발생하지 않았다.

Op=100이므로 결과는 a exclusive or b 0110이 나옴

Input combination: a=0011, b=0101, op=101    Output: result=1001

Carry는 없고 MSB 1이므로 negative이고 zero가 아니며 overflow는 발생하지 않았다.

Op=101이므로 결과는 a exclusive nor b1001이 나옴

이것은 ALU동작과 일치하는 결과가 나왔으므로 위의 input combination은 정상 동작하는 것을 확인할 수 있다.

 

Top level entity name: alu32

Device family: Cyclone II EP2C70F896C6

logic elements 366 (1%이하)

pin 103 (17%)

RTL viewer

 

Wave form (Hexadecimal)

 

module _inv(a,y);
	input a;
	output y;
	assign y=~a;
endmodule

module _nand2(a,b,y);
	input a,b;
	output y;
	assign y=~(a&b);
endmodule

module _and2(a,b,y);
	input a,b;
	output y;
	assign y=a&b;
endmodule

module _or2(a,b,y);
	input a,b;
	output y;
	assign y=a|b;
endmodule

module _xor2(a,b,y);
	input a,b;
	output y;
	
	wire w1,w2,w3,w4;
	
	_inv _inv0(.a(a),.y(w1));
	_inv _inv1(.a(b),.y(w2));
	_and2 _and0(.a(a),.b(w2),.y(w3));
	_and2 _and1(.a(b),.b(w1),.y(w4));
	_or2 _or0(.a(w3),.b(w4),.y(y));
	
endmodule

module _and3(a,b,c,y);
input a,b,c;
output y;
assign y=a&b&c;
endmodule

module _and4(a,b,c,d,y);
input a,b,c,d;
output y;
assign y=a&b&c&d;
endmodule

module _and5(a,b,c,d,e,y);
input a,b,c,d,e;
output y;
assign y=a&b&c&d&e;
endmodule

module _or3(a,b,c,y);
input a,b,c;
output y;
assign y=a|b|c;
endmodule

module _or4(a,b,c,d,y);
input a,b,c,d;
output y;
assign y=a|b|c|d;
endmodule

module _or5(a,b,c,d,e,y);
input a,b,c,d,e;
output y;
assign y=a|b|c|d|e;
endmodule

//4 bits inverter
module _inv_4bits(a,y);
input [3:0] a;
output [3:0] y;
assign y=~a;
endmodule

//4 bits 2-to-1 and gate
module _and2_4bits(a,b,y);
input [3:0] a,b;
output [3:0] y;
assign y=a&b;
endmodule

//4 bits 2-to-1 or gate
module _or2_4bits(a,b,y);
input [3:0] a,b;
output [3:0] y;
assign y=a|b;
endmodule

//4 bits 2-to-1 exclusive or gate
module _xor2_4bits(a,b,y);
input [3:0] a,b;
output [3:0] y;
_xor2 U0_xor2(.a(a[0]), .b(b[0]), .y(y[0]));
_xor2 U1_xor2(.a(a[1]), .b(b[1]), .y(y[1]));
_xor2 U2_xor2(.a(a[2]), .b(b[2]), .y(y[2]));
_xor2 U3_xor2(.a(a[3]), .b(b[3]), .y(y[3]));
endmodule

//4 bits 2-to-1 exclusive nor gate
module _xnor2_4bits(a,b,y);
input [3:0] a,b;
output [3:0] y;
wire [3:0] w0;
_xor2_4bits U0_xor2_4bits(.a(a), .b(b), .y(w0));
_inv_4bits U1_inv_4bits(.a(w0), .y(y));
endmodule

//32 bits inverter
module _inv_32bits(a,y);
input [31:0] a;
output [31:0] y;
assign y=~a;
endmodule

//32 bits 2-to-1 and gate
module _and2_32bits(a,b,y);
input [31:0] a,b;
output [31:0] y;
assign y=a&b;
endmodule

//32 bits 2-to-1 or gate
module _or2_32bits(a,b,y);
input [31:0] a,b;
output [31:0] y;
assign y=a|b;
endmodule

//32 bits exclusive or gate
module _xor2_32bits(a,b,y);
input [31:0] a,b; 
output [31:0] y;
 _xor2_4bits U0_xor2_4bits(.a(a[3:0]), .b(b[3:0]), .y(y[3:0])); 
 _xor2_4bits U1_xor2_4bits(.a(a[7:4]), .b(b[7:4]), .y(y[7:4])); 
 _xor2_4bits U2_xor2_4bits(.a(a[11:8]), .b(b[11:8]), .y(y[11:8])); 
 _xor2_4bits U3_xor2_4bits(.a(a[15:12]), .b(b[15:12]), .y(y[15:12])); 
 _xor2_4bits U4_xor2_4bits(.a(a[19:16]), .b(b[19:16]), .y(y[19:16])); 
 _xor2_4bits U5_xor2_4bits(.a(a[23:20]), .b(b[23:20]), .y(y[23:20])); 
 _xor2_4bits U6_xor2_4bits(.a(a[27:24]), .b(b[27:24]), .y(y[27:24])); 
 _xor2_4bits U7_xor2_4bits(.a(a[31:28]), .b(b[31:28]), .y(y[31:28])); 
 endmodule
 
//32 bits exclusive nor gate
module _xnor2_32bits(a,b,y);
input [31:0] a,b;
output [31:0] y;
_xnor2_4bits U0_xnor2_4bits(.a(a[3:0]), .b(b[3:0]), .y(y[3:0]));
_xnor2_4bits U1_xnor2_4bits(.a(a[7:4]), .b(b[7:4]), .y(y[7:4]));
_xnor2_4bits U2_xnor2_4bits(.a(a[11:8]), .b(b[11:8]), .y(y[11:8]));
_xnor2_4bits U3_xnor2_4bits(.a(a[15:12]), .b(b[15:12]), .y(y[15:12]));
_xnor2_4bits U4_xnor2_4bits(.a(a[19:16]), .b(b[19:16]), .y(y[19:16]));
_xnor2_4bits U5_xnor2_4bits(.a(a[23:20]), .b(b[23:20]), .y(y[23:20]));
_xnor2_4bits U6_xnor2_4bits(.a(a[27:24]), .b(b[27:24]), .y(y[27:24]));
_xnor2_4bits U7_xnor2_4bits(.a(a[31:28]), .b(b[31:28]), .y(y[31:28]));
endmodule


module alu32(a,b,op,result,c,n,z,v);

	input		[31:0] 	a,b;
	input 	[2:0] 	op;
	output 	[31:0] 	result;
	output				c,n,z,v;
	
	wire 		[31:0]	w_not_a,w_not_b,w_and,w_or,w_xor,w_xnor,w_add,w_sub;
	wire 					co_prev_add,co_add,co_prev_sub,co_sub;
	
	_inv_32bits	      U0_inv_32bits      (.a(a),.y(w_not_a));
	_inv_32bits 			U1_inv_32bits		(.a(b),.y(w_not_b));
	_and2_32bits 		U2_and2_32bits		(.a(a),.b(b),.y(w_and));
	_or2_32bits 			U3_or2_32bits		(.a(a),.b(b),.y(w_or));
	_xor2_32bits 		U4_xor2_32bits		(.a(a),.b(b),.y(w_xor));
	_xnor2_32bits 		U5_xnor2_32bits		(.a(a),.b(b),.y(w_xnor));
	cla32_ov 				U6_add				(.a(a),.b(b),.ci(1'b0),.s(w_add),.co_prev(co_prev_add),.co(co_add));
	cla32_ov 				U7_sub				(.a(a),.b(w_not_b),.ci(1'b1),.s(w_sub),.co_prev(co_prev_sub),.co(co_sub));
	mx8_32bits			U8_mx8_32bits		(.a(w_not_a),.b(w_not_b),.c(w_and),.d(w_or),.e(w_xor),.f(w_xnor),.g(w_add),.h(w_sub),.s2(op[2]),.s1(op[1]),.s0(op[0]),.y(result));
	cal_flag32			U9_cal_flags32		(.op(op),.result(result),.co_add(co_add),.co_prev_add(co_prev_add),.co_sub(co_sub),.co_prev_sub(co_prev_sub),.c(c),.n(n),.z(z),.v(v));
	
endmodule

module cal_flag32(op,result,co_add,co_prev_add,co_sub,co_prev_sub,c,n,z,v);

	input 	[2:0] 	op;
	input 	[31:0]	result;
	input 				co_add,co_prev_add, co_sub, co_prev_sub;
	output 				c,n,z,v;
	
	assign c= (op[2:1] != 2'b11)? 1'b0 :((op[0]==1'b0)? co_add:co_sub);
	
	assign n= result[31];
	
	assign z= (result==32'b0) ? 1'b1 : 1'b0;
	
	assign v= (op[2:1] != 2'b11) ? 1'b0 :((op[0]==1'b0)? (co_add^co_prev_add): (co_sub^co_prev_sub));
	
endmodule


module mx8_32bits(a,b,c,d,e,f,g,h,s2,s1,s0,y);

	input 	[31:0] 	a,b,c,d,e,f,g,h;
	input	 				s2,s1,s0;
	output 	[31:0] 	y;
	
	wire 		[31:0]	w0,w1,w2,w3,w4,w5;
	
	mx2_32bits U0_mx2_32bits(.d0(a),.d1(b),.s(s0),.y(w0));
	mx2_32bits U1_mx2_32bits(.d0(c),.d1(d),.s(s0),.y(w1));
	mx2_32bits U2_mx2_32bits(.d0(e),.d1(f),.s(s0),.y(w2));
	mx2_32bits U3_mx2_32bits(.d0(g),.d1(h),.s(s0),.y(w3));
	mx2_32bits U4_mx2_32bits(.d0(w0),.d1(w1),.s(s1),.y(w4));
	mx2_32bits U5_mx2_32bits(.d0(w2),.d1(w3),.s(s1),.y(w5));
	mx2_32bits U6_mx2_32bits(.d0(w4),.d1(w5),.s(s2),.y(y));
	
endmodule

module mx2_32bits(d0,d1,s,y);

	input 	[31:0] 	d0,d1;
	input 				s;
	output 	[31:0]	y;
	
	assign y= (s==1'b0) ? d0 : d1;
	
endmodule

module cla32_ov(a,b,ci,s,co_prev,co);

	input		[31:0]	a,b;
	input		ci;
	output	[31:0]	s;
	output 	co_prev;
	output 	co;
	
	wire c1,c2,c3,c4,c5,c6,c7;
		
	cla4 U0_cla4(.a(a[3:0]),.b(b[3:0]),.ci(ci),.s(s[3:0]),.co(c1));
	cla4 U1_cla4(.a(a[7:4]),.b(b[7:4]),.ci(c1),.s(s[7:4]),.co(c2));
	cla4 U2_cla4(.a(a[11:8]),.b(b[11:8]),.ci(c2),.s(s[11:8]),.co(c3));
	cla4 U3_cla4(.a(a[15:12]),.b(b[15:12]),.ci(c3),.s(s[15:12]),.co(c4));
	cla4 U4_cla4(.a(a[19:16]),.b(b[19:16]),.ci(c4),.s(s[19:16]),.co(c5));
	cla4 U5_cla4(.a(a[23:20]),.b(b[23:20]),.ci(c5),.s(s[23:20]),.co(c6));
	cla4 U6_cla4(.a(a[27:24]),.b(b[27:24]),.ci(c6),.s(s[27:24]),.co(c7));
	cla4_ov U7_cla4_ov(.a(a[31:28]),.b(b[31:28]),.ci(c7),.s(s[31:28]),.c3(co_prev),.co(co));
	
endmodule


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

module alu4(a,b,op,result, c,n,z,v);

	input		[3:0] 	a,b;
	input		[2:0]		op;
	output 	[3:0] 	result;
	output				c,n,z,v;
	
	wire		[3:0] 	w_not_a,w_not_b,w_and,w_or,w_xor,w_xnor,w_add,w_sub;
	wire					c3_add,c0_add,c3_sub,co_sub;
	
	_inv_4bits	      U0_inv_4bits      (.a(a),.y(w_not_a));
	_inv_4bits 			U1_inv_4bits		(.a(b),.y(w_not_b));
	_and2_4bits 		U2_and2_4bits		(.a(a),.b(b),.y(w_and));
	_or2_4bits 			U3_or2_4bits		(.a(a),.b(b),.y(w_or));
	_xor2_4bits 		U4_xor2_4bits		(.a(a),.b(b),.y(w_xor));
	_xnor2_4bits 		U5_xnor2_4bits		(.a(a),.b(b),.y(w_xnor));
	cla4_ov 				U6_add				(.a(a),.b(b),.ci(1'b0),.s(w_add),.c3(c3_add),.co(co_add));
	cla4_ov 				U7_sub				(.a(a),.b(w_not_b),.ci(1'b1),.s(w_sub),.c3(c3_sub),.co(co_sub));
	mx8_4bits			U8_mx8_4bits		(.a(w_not_a),.b(w_not_b),.c(w_and),.d(w_or),.e(w_xor),.f(w_xnor),.g(w_add),.h(w_sub),.s2(op[2]),.s1(op[1]),.s0(op[0]),.y(result));
	cal_flags4			U9_cal_flags4		(.op(op),.result(result),.co_add(co_add),.c3_add(c3_add),.co_sub(co_sub),.c3_sub(c3_sub),.c(c),.n(n),.z(z),.v(v));
	
endmodule


`timescale 1ns/100ps

module tb_alu4;

	reg	[3:0]		tb_a,tb_b;
	reg	[2:0]		tb_op;
	wire	[3:0] 	tb_result;
	wire				tb_c,tb_n,tb_z,tb_v;
	
	alu4 U0_alu4(.a,.b,.op,.result,.c,.n,.z,.v);
	
	initial
	begin
	
endmodule



module cal_flags4(op,result,co_add, c3_add,co_sub,c3_sub,c,n,z,v);

	input		[2:0]	op;
	input 	[3L0] result;
	input 			co_add,c3_add,co_sub,c3_sub;
	output			c,n,z,v;
	
	assign c = (op[2:1] != 2'b11) ?1'b0 : ((op[0]==1'b0) ? co_add : co_sub);
	
	assign n = result[3];
	
	assign z = (result == 4'b0) ? 1'b1 : 1'b0;
	
	assign v = (op[2:1] != 2'b11) ? 1'b0 : ((op[0]==1'b0) ? (co_add^c3_add) : (co_sub^c3_sub));
	
endmodule


module mx8_4bits(a,b,c,d,e,f,g,h,s2,s1,s0,y);

	input		[3:0] a,b,c,d,e,f,g,h;
	input 			s2,s1,s0;
	output	[3:0]	y;
	
	mx8 (.a(a[0]),.b(b[0]),.c(c[0]),.d(d[0]),.e(e[0]),.f(f[0]),.g(g[0]),.h(h[0]),.s2(s2),.s1(s1),.s0(s0),.y(y[0]));
	mx8 (.a(a[1]),.b(b[1]),.c(c[1]),.d(d[1]),.e(e[1]),.f(f[1]),.g(g[1]),.h(h[1]),.s2(s2),.s1(s1),.s0(s0),.y(y[1]));
	mx8 (.a(a[2]),.b(b[2]),.c(c[2]),.d(d[2]),.e(e[2]),.f(f[2]),.g(g[2]),.h(h[2]),.s2(s2),.s1(s1),.s0(s0),.y(y[2]));
	mx8 (.a(a[3]),.b(b[3]),.c(c[3]),.d(d[3]),.e(e[3]),.f(f[3]),.g(g[3]),.h(h[3]),.s2(s2),.s1(s1),.s0(s0),.y(y[3]));
	
endmodule


module mx8(a,b,c,d,e,f,g,h,s2,s1,s0,y);

	input a,b,c,d,e,f,g,h;
	input s2,s1,s0;
	output y;
	
	wire w0,w1,w2,w3,w4,w5;
	
	mx2(.d0(a),.d1(b),.s(s0),.y(w0));
	mx2(.d0(c),.d1(d),.s(s0),.y(w1));
	mx2(.d0(e),.d1(f),.s(s0),.y(w2));
	mx2(.d0(g),.d1(h),.s(s0),.y(w3));
	mx2(.d0(w0),.d1(w1),.s(s1),.y(w4));
	mx2(.d0(w2),.d1(w3),.s(s1),.y(w5));
	mx2(.d0(w4),.d1(w5),.s(s2),.y(y));
	
endmodule


module mx2(d0,d1,s,y);

	input d0,d1;
	input s;
	output y;
	wire sb, w0, w1;
	
	_inv U0_inv(.a(s),.y(sb));
	_nand2(.a(d0),.b(sb),.y(w0));
	_nand2(.a(d1),.b(s),.y(w1));
	_nand2(.a(w0),.b(w1),.y(y));
	
endmodule


 module cla4_ov(a,b,ci,s,c3,co);
 
	input [3:0] a,b;
	input ci;
	output [3:0] s;
	output c3, co;
	
	wire c1,c2;
	fa_v2 U0_fa (.a(a[0]),.b(b[0]),.ci(ci),.s(s[0]));
	fa_v2 U1_fa (.a(a[1]),.b(b[1]),.ci(c1),.s(s[1]));
	fa_v2 U2_fa (.a(a[2]),.b(b[2]),.ci(c2),.s(s[2]));
	fa_v2 U3_fa (.a(a[3]),.b(b[3]),.ci(c3),.s(s[3]));
	clb4 U4_clba (.a(a),.b(b),.ci(ci),.c1(c1),.c2(c2),.c3(c3),.co(co));
	
endmodule
728x90