호경

[개인스터디/개인프로젝트] 8-bit 복합 ALU 설계하기 본문

디지털회로설계/SoC,ASIC 설계

[개인스터디/개인프로젝트] 8-bit 복합 ALU 설계하기

rlaghrud1234 2023. 1. 11. 02:58

※시작에 앞서, 해당 내용은 서적 "VHDL과 반도체 회로설계"의 내용을 토대로 작성됐다.

※나는 Verilog HDL 코드로 작성해서 스터디를 진행했다.


1. ALU

A. ALU란?

ALU는 Arithmetic Logic Unit의 약자이고, CPU에서 가장 중요한 산술 연산 회로이다.

대개 ALU는 다음과 같은 산술 회로로 이루어져 있다.

a. Adder

b. Substracter

c. Multiplier

d. Shift Register

 

이번 포스팅에서는 책에서 심화문제로 제시한 8-bit 복합 ALU 설계를 목표로 한다.

 

2. ALU 설계 과정

* 책에서 요구한 8-bit ALU의 스펙

RST CLK CMD D0
0 X X Initialize
1 / 0 A + B
1 / 1 A - B
1 / 2 A * B
1 / 3 HOLD
1 / 4 LSL with 2 bits
1 / 5 ASL with 2 bits
1 / 6 ASR with 2 bits
1 / 7 RSL with 2 bits

A. ALU Top Module Design 및 Timing Diagram 작성

B. Adder / Substractor

초기 예상도는 다음과 같이 했으나, CMD를 8x1 MUX로 묶어주기 위해서 다시 회로를 작성했기 때문에 그림으로 그린 회로도랑은 다르다.

 

다만 회로의 효율성을 위해  단순히 A + B, A - B를 한 것이 아니라,

특히 SUB에서는 B의 2의 보수를 구해서 더해주는 방법을 사용하여 logic을 덜 사용할 수 있는 고급 설계 방법을 사용했다.

 

Adder와 Substractor 모두 테스트벤치를 진행했으나, 코드가 여러번 변경돼 기존에 그렸던 회로만 포스팅하겠다.

C. Multiplier

CPU에서 곱셈 연산을 할 경우, 하위 1/2 byte만을 사용하고, 상위 1/2 byte는 사용하지 않는다.

 

Adder/Substractor와 마찬가지로 Multiplier도 테스트 벤치를 진행했으나, 코드가 여러번 변경돼 기존에 그렸던 회로만 포스팅하겠다.

 

D. Shift Register

초기 예상도는 다음과 같이 했으나, CMD를 8x1 MUX로 묶어주기 위해서 다시 회로를 작성했기 때문에 그림으로 그린 회로도랑은 다르다.

Shift Register는 결합 연산자를 사용하여 설계했다.

 

Adder/Substractor와 마찬가지로 Shift Register도 테스트 벤치를 진행했으나, 코드가 여러번 변경돼 기존에 그렸던 회로만 포스팅하겠다.

 

3. ALU 설계 코드

A. Verilog HDL 코드

//ALU

module Top_ALU(CLK, RST, A, B, CMD, D0);

	input CLK, RST;
	input[7:0] A, B;
	input[7:0] CMD;
	
	output[7:0] D0;
	
	wire[7:0] T_D0;
	
	wire[7:0] ADD_result;
	wire[7:0] SUB_result;
	
	wire[7:0] Multiplier_result;
	
	wire[7:0] LSL_result;
	wire[7:0] ASL_result;
	wire[7:0] ASR_result;
	wire[7:0] RSL_result;
	
	wire[7:0] HOLD_result = T_D0;
	
	assign D0 = T_D0;
	
	ADSB ADSB1(.A(A), .B(B), .CLK(CLK), .RST(RST), .result_ADD(ADD_result), .result_SUB(SUB_result));
	Multiplier Multiplier1(.A(A), .B(B), .CLK(CLK), .RST(RST), .result_mult(Multiplier_result));
	Shift_Reg Shift_Reg1(.A(A), .B(B), .CLK(CLK), .RST(RST), .result_LSL(LSL_result), .result_ASL(ASL_result), .result_ASR(ASR_result), .result_RSL(RSL_result));
	
	Multiplexer_8_1 MUX8_1(.ADD(ADD_result), .SUB(SUB_result), .HOLD(HOLD_result), .MULT(Multiplier_result), .LSL(LSL_result), .ASL(ASL_result), .ASR(ASR_result), .RSL(RSL_result), .CMD(CMD), .D0(T_D0));

endmodule


//Adder, Substractor
module ADSB(A, B, CLK, RST, result_ADD, result_SUB);
	
	input[7:0] A, B;
	input CLK, RST;

	reg[7:0] B_Temp;
	
	output[7:0] result_ADD;
	output[7:0] result_SUB;
	
	reg[7:0] T_result_SUB;
	reg[7:0] T_result_ADD;
	
	assign result_ADD = T_result_ADD;
	assign result_SUB = T_result_SUB;
	
	always@(posedge CLK or negedge RST)
	begin
		if(!RST)
		begin
			T_result_ADD <= 8'b00000000;
			T_result_SUB <= 8'b00000000;
		end
		
		else
		begin
			T_result_ADD <= A + B;
			T_result_SUB <= A + (~B + 1'b1);
		end
	end
	
endmodule


//Multiplier
module Multiplier(A, B, CLK, RST, result_mult);

	input CLK, RST;
	input[7:0] A, B;
	
	output[7:0] result_mult;
	reg[7:0] T_result_mult;
	
	assign result_mult = T_result_mult;
	
	always@(posedge CLK or negedge RST)
	begin
		if(!RST)
		begin
			T_result_mult <= 8'b00000000;
		end
		
		else
		begin
			T_result_mult <= (A[3:0] * B[3:0]);
		end
	end

endmodule 


//Shift Register
module Shift_Reg(A, B, CLK, RST, result_LSL, result_ASL, result_ASR, result_RSL);

	input CLK, RST;
	input[7:0] A, B;
	
	output[7:0] result_LSL;
	output[7:0] result_ASL;
	output[7:0] result_ASR;
	output[7:0] result_RSL;
	
	reg[7:0] T_result_LSL;
	reg[7:0] T_result_ASL;
	reg[7:0] T_result_ASR;
	reg[7:0] T_result_RSL;
	
	assign result_LSL = T_result_LSL;
	assign result_ASL = T_result_ASL;
	assign result_ASR = T_result_ASR;
	assign result_RSL = T_result_RSL;
	
	always@(posedge CLK or negedge RST)
	begin
		if(!RST)
		begin
			T_result_LSL <= 8'b00000000;
			T_result_ASL <= 8'b00000000;
			T_result_ASR <= 8'b00000000;
			T_result_RSL <= 8'b00000000;
		end
		
		else
		begin
			T_result_LSL <= {A[5:0], 1'b0, 1'b0}; //Logic shift left
			T_result_ASL <= {A[5:0], A[0], A[0]}; //Arithmetic shift left
			T_result_ASR <= {A[7], A[7], A[7:2]}; //Arithmetic shift right
			T_result_RSL <= {A[5:0], A[7], A[6]}; //Rotational shift left
		end
	end

endmodule


//8x1 MUX
module Multiplexer_8_1(ADD, SUB, HOLD, MULT, LSL, ASL, ASR, RSL, CMD, D0);

	input[7:0] ADD, SUB, HOLD, MULT, LSL, ASL, ASR, RSL, CMD;
	
	output[7:0] D0;
	reg[7:0] T_D0;
	
	assign D0 = T_D0;
	
	always@(*)
	begin
		case(CMD)
			8'b00000001: T_D0 <= ADD;
			8'b00000010: T_D0 <= SUB;
			8'b00000100: T_D0 <= HOLD;
			8'b00001000: T_D0 <= MULT;
			8'b00010000: T_D0 <= LSL;
			8'b00100000: T_D0 <= ASL;
			8'b01000000: T_D0 <= ASR;
			8'b10000000: T_D0 <= RSL;
		endcase
	end
	
endmodule

B. Test Bench 코드

//Test Bench

module tb_ALU();

	reg CLK, RST;
	reg[7:0] A, B, CMD;
	
	wire[7:0] D0;
	
	Top_ALU uut(
		.CLK(CLK),
		.RST(RST),
		.A(A),
		.B(B),
		.CMD(CMD),
		.D0(D0));
		
	always#(10)
	begin
		CLK = ~CLK;
	end
	
	initial
	begin
		CLK = 0;
		RST = 0;
		CMD = 8'b00000000;
		A = 8'b00000000;
		B = 8'b00000000;
		
		#30; //0.030ns
		RST = 1;
		CMD = 8'b00000001;
		A = 8'b00000001;
		B = 8'b00000010;
		
		#40; //0.070ns
		CMD = 8'b00000010;
		A = 8'b00000011;
		B = 8'b00000001;
		
		#40; //0.110ns
		CMD = 8'b00000100;
		A = 8'b10101010;
		B = 8'b00000000;
		
		#40; //0.150ns
		CMD = 8'b00001000;
		A = 8'b00010010;
		
		#40; //0.190ns
		CMD = 8'b00010000;
		A = 8'b10100001;
		
		#40; //0.230ns
		CMD = 8'b00100000;
		A = 8'b01100010;
		
		#40; //0.270ns
		CMD = 8'b01000000;
		A = 8'b00100110;
		
		#40; //0.310ns
		CMD = 8'b10000000;
		A = 8'b00110101;
	end
	
endmodule

4. ALU 설계 결과

A. Netlist viewer

B. Simulation 검증

 

설계와 검증을 통해 8-bit ALU 스펙을 만족하는 ALU를 설계 완료 했다.

Comments