티스토리 뷰

 IDEC 강의 영상을 보고 정리한 내용입니다.

https://www.idec.or.kr/vod/apply/view/?pay=&search_val=CPU&no=273 

 

반도체설계교육센터

강의제목 CPU 설계 및 응용 구분 부산대 / 설계강좌 / 초급/중급 / 이론+실습 강의시간 13시간 열람기간 16일 이용료(일반) 무료 이용료(학생) 무료 강의개요 SoC 설계를 위해서 CPU를 설계하고 응용할

www.idec.or.kr

저번까지 설계한 CPU의 구조이다.

이번엔 ACC와 ALU를 연결하여 MUL연산과 DIV연산을 하도록 하겠다.

 

MUL / DIV

MUL과 DIV는 shift와 add연산을 사용한다.

MUL : shift right(ACC) + add(ALU)

DIV : shift left(ACC) + sub(ALU)

 

MUL

mul 연산 과정은 다음과 같다.

7 X 6 (0111 x 0110)

7 : Multiplicant (BREG)

6 : Multiplier (AL)

 

BREG : BREG

ACC : AH | AL

 

ALU는 AH와 BREG를 연산한다.

 

곱셈 예시

https://www.youtube.com/watch?v=3QHC7LXxKuI 

DIV

div연산 과정은 다음과 같다.

9 X 2 (1001 x 0010)

9 : Dividend (AL)

2 : Divisor (BREG)

 

BREG : BREG

ACC : AH/AL

 

ALU는 AH와 BREG를 연산한다.

 

나눗셈 예시

https://www.youtube.com/watch?v=i-6ZVoxD40Y 

 

제어신호(hs / ls) 분기회로

위의 flow chart에서 분기점에서 ACC의 제어신호를 결정한다.

MUL

: if (al_lsb == 1) -> AH = AH+BREG 

ACC입장에서 hs = 11(data load)

 

DIV

: if ((AH-BREG)>=0) => AH = AH - BREG

ACC입장에서 hs = 11(data load)

 

위의 정보로 회로를 구성하면 다음과 같다.

- DIV나 MUL일 때 MUX가 D1을 이어준다.

- AH값을 갱신할 때 hs=11이 된다.

 

ACC+ALU

ACC + ALU 회로는 다음과 같다.

계산이 완료된 ACC의 값을 내보내는 tri-state-buffer는 다음과 같다.

지금까지 구성한 회로를 모두 모으면 다음과 같다.

 

verilog code

module aluNacc(ah_reset,ah_inen,s_sub,s_and,s_div, s_add,s_mul, clr,acc_oen,clk,breg_in,bus_in,hs,ls,sign_flag,zero_flag,acc_out);
input ah_reset,ah_inen,s_sub,s_and,s_div,s_add, s_mul, 
clr,acc_oen,clk;
input [3:0] breg_in;
input [3:0] bus_in;
input [1:0] hs;
input [1:0] ls;
output sign_flag, zero_flag;
output [7:0] acc_out;
wire [3:0] ah_out, al_out, aluout;
wire c_out;
wire [1:0] acc_hs;
// hs selection
assign acc_hs[1]=(s_mul|s_div)?(s_mul&al_out[0])| (s_div&c_out) : hs[1];
assign acc_hs[0]=(s_mul|s_div)?(s_mul&al_out[0])| (s_div&c_out) : hs[0];
acc u0(ah_reset,clr,clk,bus_in,ah_inen,aluout,carry_flag,acc_hs, 
ls,ah_out,al_out);
// tri-state-buffer
assign acc_out=(acc_oen)?{ah_out, al_out} : 8'bz; //Tri-state buffer
alu u1(s_sub,s_div,ah_out,breg_in,s_and,aluout, c_out,clk,clr,s_add, 
s_mul,al_out[0],sign_flag,carry_flag,zero_flag);
endmodule

 

MUL / DIV simulation

MUL simulation

`timescale 1ns / 1ps
module tb_aluNaccMul;
// Inputs
reg ah_reset, ah_inen;
reg [3:0] bus_in;
reg [1:0] hs;
reg [1:0] ls;
reg s_sub,s_and, s_div;
reg s_add, s_mul, clr, clk,acc_oen;
reg [3:0] breg_in;
// Output
wire sign_flag,zero_flag;
wire [7:0] acc_out;
// Instantiate the UUT
aluNacc UUT (
.ah_reset(ah_reset),.ah_inen(ah_inen), 
.bus_in(bus_in), .hs(hs), 
.ls(ls), .s_sub(s_sub), 
.s_and(s_and), .s_div(s_div), 
.breg_in(breg_in),.s_add(s_add), 
.clr(clr), .s_mul(s_mul), .clk(clk), 
.sign_flag(sign_flag), 
.zero_flag(zero_flag), 
.acc_oen(acc_oen), 
.acc_out(acc_out)
);
always #50 clk = ~clk;
initial begin
ah_reset = 0; ah_inen = 0;
bus_in = 4'b0011; breg_in = 4'b0101;
hs = 0; ls = 0;
s_sub = 0; s_and = 0;
s_div = 0; s_add = 0;
clk = 0; s_mul = 0;
clr = 1; acc_oen = 1;
#100; clr = 0;
#100; ah_inen = 1; hs = 2'b11;
#100; ah_inen = 0; hs = 2'b00;
#100; ls = 2'b11;
#100; ls = 2'b00;
#100; ah_reset = 1;
#100; ah_reset = 0;
#100; hs = 2'b11; s_mul = 1; //T3
#100; hs = 2'b01; ls = 2'b01; s_mul = 0; //T4
#100; hs = 2'b11; ls = 2'b00;s_mul = 1; //T5
#100; hs = 2'b01; ls = 2'b01; s_mul = 0; //T6
#100; hs = 2'b11; ls = 2'b00;s_mul = 1; //T7
#100; hs = 2'b01; ls = 2'b01; s_mul = 0; //T8
#100; hs = 2'b11; ls = 2'b00;s_mul = 1; //T9
#100; hs = 2'b01; ls = 2'b01; s_mul = 0; //T10
#100; hs = 2'b00; ls = 2'b00; //T11
#100;
end
endmodule

- s_mul에 맞춰서 AH 업데이트

- clk에 맞춰서 shift

를 반복하는 모습을 볼 수 있다.

 

DIV simulation

`timescale 1ns / 1ps
module tb_aluNaccDiv;
// Inputs
reg ah_reset, ah_inen;
reg [3:0] bus_in;
reg [1:0] hs;
reg [1:0] ls;
reg s_sub,s_and, s_div;
reg [3:0] breg_in;
reg s_add,clr, s_mul,clk,acc_oen;
// Output
wire sign_flag,zero_flag;
wire [7:0] acc_out;
// Instantiate the UUT
aluNacc UUT (.ah_reset(ah_reset), 
.ah_inen(ah_inen),.bus_in(bus_in), 
.hs(hs), .ls(ls), .s_sub(s_sub), 
.s_and(s_and), .s_div(s_div), 
.breg_in(breg_in),.s_add(s_add), 
.clr(clr), .s_mul(s_mul), .clk(clk), 
.sign_flag(sign_flag), 
.zero_flag(zero_flag), 
.acc_oen(acc_oen), 
.acc_out(acc_out)
);
always #50 clk = ~clk;
initial begin
ah_reset = 0; ah_inen = 0;
bus_in = 4'b1001; breg_in = 4'b0010;
hs = 0; ls = 0;
s_sub = 0; s_and = 0;
s_div = 0; s_add = 0;
clk = 0; s_mul = 0;
clr = 1; acc_oen = 1;
#100; clr = 0;
#100; ah_inen = 1; hs = 2'b11;
#100; ah_inen = 0; hs = 2'b00;
#100; ls = 2'b11;
#100; ls = 2'b00;
#100; ah_reset = 1;
#100; ah_reset = 0;
#100; hs = 2'b10; ls = 2'b10; //T3
#100; hs = 2'b11; ls = 2'b00; s_div = 1;//T4
#100; hs = 2'b10; ls = 2'b10; s_div = 0;//T5
#100; hs = 2'b11; ls = 2'b00; s_div = 1;//T6
#100; hs = 2'b10; ls = 2'b10; s_div = 0;//T7
#100; hs = 2'b11; ls = 2'b00; s_div = 1;//T8
#100; hs = 2'b10; ls = 2'b10;s_div = 0; //T9
#100; hs = 2'b11; ls = 2'b00; s_div = 1;//T10
#100; hs = 2'b00; ls = 2'b10; s_div = 0; //T11
#100; hs = 2'b00; ls = 2'b00;
end
endmodule

- s_div에 맞춰서 AH 업데이트

- clk에 맞춰서 shift

를 반복하는 모습을 볼 수 있다.

9/2로 simulation했을 때 (몫 : 4 / 나머지 : 1)을 확인할 수 있다.

 

결론

ACC와 ALU를 연결하여 mul연산과 div연산을 했다.

다음은 control block을 설계할 것이다.

 

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/06   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30
글 보관함