1.7 Pipe Register
파이프 레지스터(pipe register)는 컴퓨터 아키텍처에서 파이프라인(pipeline) 구조를 구성하는 레지스터이다. 파이프 레지스터는 Pipeline stage 간의 데이터 흐름을 제어하고, 각 스테이지에서 수행되는 동작의 결과를 일시적으로 저장하는 역할을 한다.
파이프 레지스터는 주로 명령어가 프로세서의 다양한 단계를 거치면서 실행되는 동안 발생하는 지연을 최소화하기 위해 사용된다. 각 스테이지는 한 번에 하나의 명령어를 처리하며, 다음 명령어는 이전 명령어가 다음 스테이지로 이동할 때까지 현재 스테이지에 머무르게 됩니다.
이러한 파이프 레지스터는 CPU의 성능을 향상시키기 위해 사용되며, 파이프라인의 깊이와 관련이 있다. 파이프라인이 더 깊으면 명령어의 처리 속도는 빨라질 수 있지만, 파이프라인 깊이가 깊을수록 지연이 증가한다. 이번에 설계한 processor의 파이프 개수는 총 4개로 5단계 pipeline으로 진행한다.
1.7.1 IF_ID Regster
IF_ID Regster 동작 설명
IF_ID Register에서는 IF stage에서 넘어온 Program Counter값과 Instruction을 저장하는 레지스터다. 리셋 신호(rst) 혹은 IF_Flush신호가 들어오면 모든 값을 0으로 변환시켜준다. PC와 Inst값은 매 클락 prev_IF_PC, prev_IF_inst라는 레지스터에 추가적으로 저장되고 있으며 Stall이 일어날 경우 다음 신호에서 prev의 값이 대신 사용된다. 기본적으로는 Hazard Detection Unit으로부터 IF_ID_Write 신호가 상시 전달되고 있으며 Hazard 가 일어나 IF_ID_Write 신호가 꺼지면 prev_IF_PC, prev_IF_inst 값이 출력으로 대신 연결된다.
module IFtoID_Register ( input wire clk, rst, input wire [31:0] IF_PC, IF_inst, input wire IF_ID_Write, IF_Flush, output reg [31:0] ID_PC, ID_inst); reg [31:0] prev_IF_PC; //이전 값 저장 reg [31:0] prev_IF_inst; //이전 값 저장 always @ (posedge clk or posedge rst or posedge IF_Flush) begin if (rst || IF_Flush) begin ID_PC <= 0; ID_inst <= 0; prev_IF_PC <= 0; //이전 값 저장 prev_IF_inst <= 0; end else begin if(IF_ID_Write) begin ID_PC <= IF_PC; ID_inst <= IF_inst; end else begin ID_PC <= prev_IF_PC; ID_inst <= prev_IF_inst; end prev_IF_PC <= IF_PC; prev_IF_inst <= IF_inst; end end endmodule |
1.7.2 ID_EX Regster
ID_EX Regster 동작 설명
ID_EX Register에서는 ID stage에서 넘어온 Decode된 instruction 값(ID_ReadData1, ID_ReadData2, ID_Rs, ID_Rt)이 전달되어 저장된다. 추가로 Control signal에서 전달된 3stage, 4stage, 5stage에서 사용될 Control 신호들도 저장된다. 매 클락 신호(clk)가 올라갈 때 작동하며, 리셋 신호(rst)가 들어오면 모든 값이 0으로 변경한다.
module IDtoEX_Register( input wire clk, input wire rst, //input from ID_Stage input wire [31:0] ID_ReadData1, ID_ReadData2, input wire [31:0] ID_Imm, input wire [4:0] ID_Rs, ID_Rt, ID_Rd, input wire [5:0] funct, //input from Control input wire [1:0] ALUOp, input wire ALUSrc, RegDst, MemRead, MemWrite, RegWrite, MemtoReg, // outputs to EX_Stage output reg [31:0] IDtoEX_ReadData1,IDtoEX_ReadData2, // Read Data from Register File output reg [31:0] IDtoEX_Imm, // Sign extended immediate value output reg [4:0] IDtoEX_Rt, IDtoEX_Rd, // Destination Register // Control unit to use in 3 stage output reg [1:0] EX_ALUOp, output reg EX_ALUSrc, output reg EX_RegDst, // outputs to Forwarding unit output reg [4:0] Forwarding_Rs, // outputs to ALU control output reg [5:0] ALUcontrol_funct, // Function code // outputs to next pipe output reg IDtoEX_MemRead, IDtoEX_MemWrite, // stage 4?????? ?????? output reg IDtoEX_RegWrite, IDtoEX_MemtoReg // stage 5?????? ?????? ); always @ (posedge clk or posedge rst) begin if (rst) begin IDtoEX_ReadData1 <= 0; IDtoEX_ReadData2 <= 0; IDtoEX_Imm <= 0; IDtoEX_Rt <= 0; IDtoEX_Rd <= 0; Forwarding_Rs <= 0; ALUcontrol_funct <= 0; EX_ALUOp <= 0; EX_ALUSrc <= 0; EX_RegDst <= 0; IDtoEX_MemRead <= 0; IDtoEX_MemWrite <= 0; IDtoEX_RegWrite <= 0; IDtoEX_MemtoReg <= 0; end else begin IDtoEX_ReadData1 <= ID_ReadData1; IDtoEX_ReadData2 <= ID_ReadData2; IDtoEX_Imm <= ID_Imm; IDtoEX_Rt <= ID_Rt; IDtoEX_Rd <= ID_Rd; EX_ALUOp <= ALUOp; EX_ALUSrc <= ALUSrc; EX_RegDst <= RegDst; Forwarding_Rs <= ID_Rs; ALUcontrol_funct <= funct; IDtoEX_MemRead <= MemRead; IDtoEX_MemWrite <= MemWrite; IDtoEX_RegWrite <= RegWrite; IDtoEX_MemtoReg <= MemtoReg; end end endmodule |
1.7.3 EX_MEM Regster
EX_MEM Regster 동작 설명
EX_MEM Register에서는 EX stage에서 구한 계산의 결과값, Register의 목적지, Stage 4와 Stage 5에서 사용할 Control signal 등이 저장되어이 있는 파이프 레지스터다. ID_EX Register와 마찬가지로 매 클락 신호(clk)가 올라갈 때 작동하며, 리셋 신호(rst)가 들어오면 모든 값이 0으로 변경한다.
module EXtoMEM_Register( input wire clk, rst, // datapath input input wire [31:0] EX_ALUresult, input wire [31:0] EX_ReadData2, input wire [4:0] EX_RegDest, // control input // MEM input wire EX_MemRead, input wire EX_MemWrite, // WB input wire EX_MemtoReg, input wire EX_RegWrite, // datapath output output reg [31:0] EXtoMEM_ALUresult, output reg [31:0] EXtoMEM_ReadData2, output reg [4:0] EXtoMEM_RegDest, // control output output reg MEM_MemRead, output reg MEM_MemWrite, // WB output reg MEM_MemtoReg, output reg MEM_RegWrite ); always @(posedge clk or posedge rst) begin if(rst) begin // datapath EXtoMEM_ALUresult <= 0; EXtoMEM_ReadData2 <= 0; EXtoMEM_RegDest <= 0; // control MEM_MemRead <= 0; MEM_MemWrite <= 0; MEM_MemtoReg <= 0; MEM_RegWrite <= 0; end else begin // datapath EXtoMEM_ALUresult <= EX_ALUresult; EXtoMEM_ReadData2 <= EX_ReadData2; EXtoMEM_RegDest <= EX_RegDest; // control MEM_MemRead <= EX_MemRead; MEM_MemWrite <= EX_MemWrite; MEM_MemtoReg <= EX_MemtoReg; MEM_RegWrite <= EX_RegWrite; end end endmodule |
1.7.4 MEM_WB Regster
MEM_WB Regster 동작 설명
MEM_WB Register에서는 lw instruction이 들어왔을 때 Data Memory를 통해 읽은 Data 값, ALU를 통해 나온 계산의 결과 값, 새롭게 쓰여질 레지스터의 주소 및 WB 레지스터에서 사용되는 Control signal에 대한 정보를 저장한다. 해당 레지스터도 마찬가지로 클락 신호(clk)와 리셋 신호(rst)에 따라 값이 0으로 갱신되거나, 이전 stage에서 값을 받아온다.
module MEMtoWB_Register ( input clk, rst, // datapath input input wire [31:0] MEM_ReadData, input wire [31:0] MEM_ALU_result, input wire [4:0] MEM_RegDest, // control input input wire MEM_MemtoReg, input wire MEM_RegWrite, // datapath output output reg [31:0] MEMtoWB_ReadData, output reg [31:0] MEMtoWB_ALU_result, output reg [4:0] MEMtoWB_RegDest, // control output output reg MEMtoWB_MemtoReg, output reg MEMtoWB_RegWrite ); always @(posedge clk) begin // datapath MEMtoWB_ReadData <= MEM_ReadData; MEMtoWB_ALU_result <= MEM_ALU_result; MEMtoWB_RegDest <= MEM_RegDest; // control MEMtoWB_MemtoReg <= MEM_MemtoReg; MEMtoWB_RegWrite <= MEM_RegWrite; end endmodule |
1.8 Control
Control unit 동작 설명
Control Unit은 ID stage에서 Opcode를 받아 각 instruction에 맞는 Control Signal을 보내주는 역할을 한다. 해당 Processor에서는 총 9가지의 Control Signal 곧 ALUSrc, RegDst, ALUOp, MemRead, MemWrite, RegWrite, MemtoReg, Branch, IF_Flush를 사용한다.
ALUSrc는 Sign-extended Unit을 통해 넘어온 값과, Register File의 Output ReadData2로부터 나온 값 중 어떤 값을 ALU에서 계산하게 할 지를 결정한다.
RegDst는 instruction의 [20:16]bit와 [15:11]bit 중에서 목적지를 결정한다.
ALUOp는 ALU Control을 통해 add, sub, and, or, nor 중 어떤 계산을 해야할지를 결정한다. 이는 ALU 부분에 더욱 자세히 기술되어 있다.
MemRead는 Data Memory가 받은 주소값을 통해 데이터를 읽을 수 있도록 하는 신호로 lw instruction에서 사용한다.
MemWrite는 Data Memory에 값을 갱신하게 하는 신호로 sw instruction에서 사용한다.
Branch는 Beq instruction을 통해 Program Counter의 값을 이동시킬 때 사용하는 신호이다.
IF_Flush는 Hazard가 발생한 경우, IF_ID Register의 값을 0으로 만들어 Stall이 일어나게 한다.
각 instruction에 따른 Control signal 값은 다음 표와 같다.
Instruction | Opcode | Control signal |
lw | 100011 | ALUSrc = 1'b1; MemRead = 1'b1; RegWrite = 1'b1; |
sw | 101011 | ALUSrc = 1'b1; MemWrite = 1'b1; |
beq | 000100 | ALUOp = 1'b1; Branch = 1’b1; (branch_equal이 1이면) IF_Flush = 1'b1; (Branch가 1이면) MemtoReg = 1'b1; |
addi | 001000 | ALUSrc = 1'b1; ALUOp = 2'b10; RegWrite = 1'b1; MemtoReg = 1'b1; |
R-type | 000000 | ALUOp = 2'b10; RegDst = 1'b1; RegWrite = 1'b1; MemtoReg = 1'b1; |
쓰여있지 않은 값들은 0이다.
beq instruction의 경우 두 값이 같아야 주소값의 이동이 일어나므로 먼저 두 값이 같은지 여부를 받고 같을 때에만 Branch Signal이 켜진다. 또한 Branch가 켜지면 값을 Stall 시킬 수 있도록 IF_Flush에 값을 준다.
module Control( input wire rst, input wire hazard_detected, input wire [5:0] opcode, input wire branch_equal, input wire [31:0] IF_PC, output reg [1:0] ALUOp, output reg ALUSrc, RegDst, output reg MemRead, MemWrite, output reg RegWrite, MemtoReg, output reg Branch, output reg IF_Flush ); always @* begin ALUSrc = 1'b0; RegDst = 1'b0; ALUOp = 2'b00; MemRead = 1'b0; MemWrite = 1'b0; RegWrite = 1'b0; MemtoReg = 1'b0; Branch = 1'b0; IF_Flush = 1'b0; if(!hazard_detected && !rst && !(IF_PC == 4)) begin case(opcode) 6'b100011 : begin // LW instruction ALUSrc = 1'b1; MemRead = 1'b1; RegWrite = 1'b1; //MemtoReg = 1'b1; end 6'b101011 : begin // SW instrtuction ALUSrc = 1'b1; MemWrite = 1'b1; end 6'b001000 : begin // Addi instruction ALUSrc = 1'b1; ALUOp = 2'b10; RegWrite = 1'b1; MemtoReg = 1'b1; end 6'b000100 : begin // BEQ instruction ALUOp = 1'b1; Branch = (branch_equal == 1); MemtoReg = 1'b1; if(Branch) begin IF_Flush = 1'b1; end End 6'b000000 : begin // R-type instruction ALUOp = 2'b10; RegDst = 1'b1; RegWrite = 1'b1; MemtoReg = 1'b1; end default : begin ALUSrc = 1'b0; RegDst = 1'b0; ALUOp = 2'b00; MemRead = 1'b0; MemWrite = 1'b0; RegWrite = 1'b0; MemtoReg = 1'b0; Branch = 1'b0; IF_Flush = 1'b0; end endcase end end endmodule |
'전공 이야기 > Digital System Design' 카테고리의 다른 글
#7 MIPS Pipeline Processor Design (5) - I/O, Constraints (1) | 2023.12.26 |
---|---|
#6 MIPS Pipeline Processor Design (4) - Hazard, Top module (0) | 2023.12.26 |
#4 MIPS Pipeline Processor Design (2) - ID, EX, MEM, WB (1) | 2023.12.26 |
#3 MIPS Pipeline Processor Design (1) - IF Stage, Sub Unit (0) | 2023.12.26 |
#2 Verilog (0) | 2023.12.24 |