Đồ án cấu trúc máy tính và vi xử lý báo cáo lab 4 BÁO CÁO LAB 4 ĐỒ ÁN CẤU TRÚC MÁY TÍNH DESIGN A MIPS PIPELINED CPU Thiết kế bộ xử lý MIPS pipelined bao gồm các lệnh: LW, SW, J, JR, BNE, XORI, ADD, SUB và SLT. Các lệnh đều được xử lý hoàn tất trong 1 chu kỳ lệnh. Thiết kế dựa trên các module có sẵn SingleCycle regfife, alu, instrmem và datamem.
Trang 1BÁO CÁO LAB 4
ĐỒ ÁN CẤU TRÚC MÁY TÍNH
DESIGN A MIPS PIPELINED CPU
Trang 2Phần 1: Giới thiệu về bộ xử lý MIPS PIPELINED
1.1 Yêu cầu:
Thiết kế bộ xử lý MIPS pipelined bao gồm các lệnh: LW, SW, J, JR, BNE, XORI, ADD, SUB và SLT
Các lệnh đều được xử lý hoàn tất trong 1 chu kỳ lệnh
Thiết kế dựa trên các module có sẵn SingleCycle regfife, alu, instrmem và datamem
Datapath cần có thêm các khối Fowarding, Hazard detection unit và Control Hazard
để điều chỉnh những hazard về data và control bằng cách forwarding, stalling và nhậndạng sớm các lệnh branch, jump để tránh tổn hao trong trường hợp branch taken
Trong cơ chế pipeline có trường hợp lệnh kế tiếp không thể thực hiện trong chu kỳ kếtiếp Hazard (xung đột)
Tồn tại 3 loại hazard:
- Xung đột cấu trúc : một tài nguyên được yêu cầu nhưng bận
- Xung đột về dữ liệu: đợi lệnh trước hoàn tất nhiệm vụ đọc/ghi dữ liệu
- Xung đột điều khiển: Quyết định bước tiếp theo phụ thuộc vào lệnh trước đó
1.2 Thực hiện:
Thực hiện datapath pineline:
Dựa trên single datapath đã thực hiện ở lab trước, bài lab này, ta sẽ tách một lệnh thành 5 giai đoạn để thực hiện pipeline, điều đó có nghĩa là 5 lệnh sẽ được thực hiện trong một chu
kì Ta gọi 5 giai đoạn của pipelined datapath như sau:
IF: Nhận lệnh từ Instruction Memory
ID: Giải mã lệnh và đọc thanh ghi
EX: Thực hiện tính toán
MEM: Truy cập bộ nhớ dữ liệu
WB: Ghi kết quả vào thanh ghi file
Trang 3Để các lệnh có thể sử dụng chung các phần của datapath thì ta cần các thanh ghi thêm vào
để lưu trữ dữ liệu sau mỗi giai đoạn thực hiện Các thanh ghi đươc đặt tên theo thứ tự từ trái sang phải của datapath như sau: IF/ID, ID/EX, EX/MEM, MEM/WB
Đối với tín hiệu điều khiển, có thể được chia thành 5 nhóm như sau:
IF :
- PCSrc: dùng để chọn nguồn cho PC
- PCWrite: cho phép ghi vào PC
- IF/ID.Write: Cho phép ghi vào thanh ghi pipeline IF/ID
ID: Jump, JumpReg, ALUSrc, SignExtend, Opcode, Funct
EX: ALUOp, Funct, MemWrite, …
MEM: MemRead, MemWrite
WB: RegWrite, MemToReg
Ngoài ra, ta còn phải thiết kế thêm các khối điều khiển Forward để xử lý data hazard, Hazard Detection Unit để xử lý structural hazard
Trang 4 Các tín hiệu điều khiển và giá trị tương ứng trong từng câu lệnh được cho trong bảng dưới.
Từ bảng trạng thái, sử dụng các cổng logic AND và OR, ta lập được các tín hiệu ra từ
6 bit Opcode
Trang 5Main Control
RegDst ALUSrc Jump MemToReg Branch RegWrite MemRead JumpReg ALUop Memwrite Aluscr Regwrite
Instruction [31:26]
Instruction [5:0]
Khối điều khiển trung tâm, có nhiệm vụ giải mã lệnh dựa trên 6-bit Opcode và 6-bit function của câu lệnh thành các tín hiệu điều khiển đến các khối khác trong bộ xử lý MIPS
Các tín hiệu điều khiển và giá trị tương ứng trong từng câu lệnh được cho trong bảng dưới
Từ bảng trạng thái, sử dụng các cổng logic AND và OR, ta lập được các tín hiệu ra từ
6 bit Opcode
Trang 6 Sơ đồ khối:
Ngõ vào bộ Control gồm có 6-bit Opcode và 6-bit Function
Các lệnh format R: ADD, SUB, SLT có chung các tín hiệu điều khiển ra Riêng lệnh
JR có 1 tín hiệu khác là: JumpReg Do đó cần thiết kế riêng khối điều khiển cho lệnh JR
Các lệnh khác phân biệt với nhau bởi Opcode nên không cần dựa vào các bit function
để điều khiển
2.2.2 Các thanh ghi pipeline
Các thanh ghi pipeline được xây dựng gồm các tín hiệu vào là các data cần lưu trữ của giai đoạn trước, và tín hiệu ra sẽ được đọc ở chu kì kế tiếp Để việc đọc và ghi được thực hiện đồng bộ, thì các thanh ghi cần có thêm các xung clock
Trang 72.2.2 Khối Forwarding
Data hazard xảy ra khi kết quả của lệnh trước là giá trị thanh ghi rs hoặc rt của lệnh kề sau
và sau nó Kết quả chỉ được ghi lại ở giai đoạn WB, trong khi việc đọc thanh ghi của lệnh sau sẽ được đọc ở giai đoạn ID, lúc này kết quả mới chưa được cập nhật
Thực tế thì kết quả đã được tính toán xong ở giai đoạn EX và kết quả sẽ được lưu vào thanh ghi EX/MEM và MEM/WB ngay sau đó, do đó mà ta có thể giải quyết hazard này bằng cách forward kết quả từ thanh ghi EX/MEM hoặc MEM/WB đưa vào ngõ vào của ALU Riêng đối với trường hợp rd là thanh ghi 0 thì ta không cần phải forward giá trị về trước
Ta xét các điều kiện xảy ra hazard như sau:
Trang 8Các ngõ ra ForwardA, ForwardB để lựa chọn giá trị thích hợp để đưa vào khối ALU Do đó
ta cần phải thêm vào trước ALU các bộ MUX để lựa chọn ngõ vào cho ALU cho các trường hợp sau:
- ForwardA, ForwardB = 00: giá trị rs, rt được đọc từ thanh ghi ID/EX
- ForwardA, ForwardB = 01: giá trị rs, rt được đọc từ thanh ghi EX/MEM
- ForwardA, ForwardB = 10: giá trị rs, rt được đọc từ thanh ghi MEM/WB
2.2.3 Khối Hazard Detection unit:
- Đối với lệnh load thì dữ liệu chính xác sẽ được đọc ở giai đoạn MEM, chậm hơn 1 chu kì đối với các lệnh R Format Do đó mà để giải quyết hazard ta cần phải thêm khối Hazard detection unit ở giai đoạn ID để thêm vào một stall giữa lệnh load và cáclệnh có sử dụng kết quả của nó sau đó
Việc stall đơn giản là thiết lập các tín hiệu điều khiển ở giai đoạn ID = 0 , các tín hiệu điều khiển 0 này sẽ trôi qua các thanh ghi pipeline và các giai đoạn sau đó sẽ không làm gì cả Đối với PC và thanh ghi IF/ID ta chỉ cần duy trì cho nó không đổi, tức PC vẫn thực hiện gọi và đọc lại lệnh trước đó
Trang 9Do đó khối Hazard detection unit cần có :
- Ngõ vào là IDEX_MemRead để xác định lệnh LOAD vì chỉ có lệnh Load là có tín hiệu MemRead=1
- Giá trị ra là PCWrite,IFIDWrite,ControlWrite để đưa tới điều khiển các thanh ghi PC,IFID không đổi ControlWrite dùng để điều khiển bộ MUX sau khối Control để lựa chọn ngõ ra là tín hiệu Control hay là các tín hiệu 0 đối với trường hợp có stall giải quyết hazard
Từ đó xây dựng khối Hazard detection unit như sau:
2.2.4 Khối Control Hazard:
Đối với lệnh Branch và Jump thì việc xác định lệnh kế tiếp có phải địa chỉ lệnh nhay hay không phải đợi tới giai đoạn MEM Giải pháp là giả sử lệnh Branch sẽ được không được
Trang 10taken và tiếp tục thực hiện lệnh kế tiếp Nếu lệnh Branch taken thì các lệnh được gọi và giải
mã sẽ bị bỏ đi và thực hiện tiếp địa chi nhảy
Để giảm bớt các lệnh bị xóa khi Branch taken, ta sẽ di chuyển việc tính toán điều kiện và địachỉ nhảy lên giai đoạn ID Khối Control hazard sẽ kiểm tra các giá trị thanh ghi rd1, rd2 được đọc ở giai đoạn ID có bằng nhau không, và kiểm tra ID_op =5d tức là lệnh BNE Giá trị ra của khối Control hazard là các tín hiệu ID_PCBR,IF_Flush Tín hiệu ID_PCBR dùng
để điều khiển MUXPCBR, IF_Flush dùng để xóa các lệnh trong thanh ghi IF/ID nếu lệnh branch taken
Trang 11*======================================================*/
module Pipeline(clk, reset);
input clk, reset;
wire [1:0]ID_ALUOp, EX_ALUCtrl, EX_ALUOp, MEM_Command;
wire [1:0]ForwardA, ForwardB, WB_Command;
wire [3:0]EX_Command, MEM_In_Command;
wire [4:0]ID_Rs, ID_Rt, ID_Rd, WB_Rd, MEM_Rd;
wire [4:0]EX_Rs, EX_Rt, EX_Rd, EX_WriteRegister;
wire [5:0]ID_Opcode, ID_Funct, EX_Funct;
wire [6:0]ID_Cmd, ID_Command, EX_In_Command;
wire [31:0]IF_InputPC, IF_PC_4, BranchOut, IF_OutputPC;
wire [31:0]IF_Instruction, ID_PC_4, ID_Instruction;
wire [31:0]ID_ReadDataA, ID_ReadData2;
wire [31:0]ID_immZero32, ID_immSign32, ID_Extend32;
wire [31:0]ID_ReadDataB, ID_Shift_BNE, ID_PC_BNE;
wire [31:0]ID_Shift_Jump, ID_PC_Branch;
wire [31:0]EX_ReadData1, EX_ReadData2, WB_WriteData;
wire [31:0]EX_ALU_DataA, EX_ALU_DataB, MEM_ALU_Result;
wire [31:0]EX_ALU_Result, MEM_WriteData;
wire [31:0]MEM_ReadData, WB_ReadData, WB_ALU_Result, EX_ALU_Data2;
/* =================== First pipeline stage: IF ============================ *//* Multiplexer input PC */
mux32_2to1 IF_Mux(IF_InputPC, PCSrc, IF_PC_4, BranchOut);
/* Program counter */
PC_Register IF_PC(IF_OutputPC, IF_InputPC, reset, clk, PCWrite);
/* Read from instruction memory */
instrmem IF_InstrMem(IF_Instruction, IF_OutputPC);
Trang 12/* Increment PC: PC + 4 */
ADD_ALU IF_Adder(IF_PC_4, IF_CarryOut, IF_Zero, IF_Overflow, IF_Negative, IF_OutputPC, 32'h04, 1'b0);
/* Pipeline stage IF/ID */
Stage_IF_ID IF_Stage(IF_ID_Write, IF_Flush, IF_PC_4, clk, reset,
IF_Instruction, ID_PC_4, ID_Instruction);
/* ================== Second pipeline stage: ID =========================== */
assign ID_Rs[4:0] = ID_Instruction[25:21];
assign ID_Rt[4:0] = ID_Instruction[20:16];
assign ID_Rd[4:0] = ID_Instruction[15:11];
assign ID_Opcode[5:0] = ID_Instruction[31:26];
assign ID_Funct[5:0] = ID_Instruction[5:0];
/* MIPS Controller */
MIPS_Control ID_Control1(IF_Flush, ID_Flush, ID_RegDst, PCSrc, ID_MemRead,
ID_MemToReg, ID_ALUOp, ID_Rs_Rt_nEqual,
ID_MemWrite, ID_ALUSrc, ID_RegWrite, ID_Jump, ID_JumpReg, ID_SignExtend, ID_Opcode, ID_Funct);
/* Register file */
regfile ID_RegFile(ID_ReadDataA, ID_ReadData2, WB_WriteData, ID_Rs, ID_Rt, WB_Rd, WB_RegWrite, WB_clk);
/* Sign & zero extend */
UnsignExtend_32bit ID_Extend0(ID_immZero32, ID_Instruction[15:0]);
SignExtend_32bit ID_Extend1(ID_immSign32, ID_Instruction[15:0]);
mux32_2to1 ID_Extend2(ID_Extend32, ID_SignExtend, ID_immZero32, ID_immSign32);
Trang 13/* ALUSrc bit */
mux32_2to1 ID_Mux02(ID_ReadDataB, ID_ALUSrc, ID_ReadData2, ID_Extend32);
/* Compare for BNE: ReadData1 vs ReadData2 */
Compare_Register32 ID_Compare1(ID_Rs_Rt_nEqual, ID_ReadDataA, ID_ReadData2);
/* Shift left 2: BNE */
Shift_Left32 ID_Shift1(ID_Shift_BNE, ID_Extend32);
/* Increment PC(BNE): PC + 4 + 16-bit */
ADD_ALU ID_Adder(ID_PC_BNE, ID_CarryOut, ID_Zero, ID_Overflow, ID_Negative,
ID_Shift_BNE, ID_PC_4, 1'b0);
/* Shift left 26: Jump */
Shift_Left26 ID_Shift2(ID_Shift_Jump[27:0], ID_Instruction[25:0]);
Assign ID_Shift_Jump[31:28] = ID_PC_4[31:28];
/* Multiplexer: BNE vs Jump */
mux32_2to1 ID_Mux03(ID_PC_Branch, ID_Jump, ID_PC_BNE, ID_Shift_Jump);
/* Multiplexer: Branch vs JR */
mux32_2to1 ID_Mux05(BranchOut, ID_JumpReg, ID_PC_Branch, ID_ReadDataA);
/* Stall & Flush */
assign ID_Cmd[6:0] = {ID_RegDst, ID_ALUOp[1:0], ID_MemWrite, ID_MemRead,
ID_MemToReg, ID_RegWrite};
or #50 ID_Stall(Stall_True, ID_EX_Stall, ID_Flush);
mux7_2to1 ID_Mux04(ID_Command, Stall_True, ID_Cmd[6:0], 7'h00);
/* Pipeline stage ID-EX */
Trang 14Stage_ID_EX ID_Stage(EX_In_Command, EX_Rs, EX_Rt, EX_Rd,
EX_Funct, EX_ReadData1, EX_ReadData2,
clk, reset, ID_Command, ID_Rs, ID_Rt,
ID_Rd, ID_Funct, ID_ReadDataA, ID_ReadDataB);
/* Hazard Detection Unit */
assign EX_MemRead = EX_In_Command[2];
Hazard_Detection Control2(PCWrite, IF_ID_Write, ID_EX_Stall, reset, ID_Rs, ID_Rt, EX_Rt, EX_MemRead);
/* ================ Third pipeline stage: EX ============================= */
/* Multiplexer for data input ALU */
mux32_4to1 EX_Mux05(EX_ALU_DataA, ForwardA[1:0], EX_ReadData1, WB_WriteData, MEM_ALU_Result, 32'h00);
mux32_4to1 EX_Mux06(EX_ALU_Data2, ForwardB[1:0], EX_ReadData2, MEM_ALU_Result, WB_WriteData, 32'h00);
/* Except: Store Word instruction */
assign EX_MemWrite = EX_In_Command[3];
mux32_2to1 EX_Mux07(EX_ALU_DataB, EX_MemWrite, EX_ALU_Data2, EX_ReadData2);
/* Multiplexer for Wrire Back register */
assign EX_RegDst = EX_In_Command[6];
mux5_2to1 EX_Mux08(EX_WriteRegister, EX_RegDst, EX_Rt, EX_Rd);
/* ALU Control */
assign EX_ALUOp[1:0] = EX_In_Command[5:4];
ALU_Control EX_ControlA(EX_ALUCtrl, EX_ALUOp[1:0], EX_Funct[5:0]);
/* Main ALU */
Trang 15alu EX_ControlB(EX_ALU_Result, EX_CarryOut, EX_Zero, EX_Overflow, EX_Negative, EX_ALU_DataA, EX_ALU_DataB, EX_ALUCtrl);
/* Forwarding Unit */
Forwarding_Unit Forward(ForwardA, ForwardB, EX_Rs, EX_Rt, WB_Rd, MEM_Rd,
MEM_RegWrite, WB_RegWrite);
/* Pipeline stage EX-MEM */
assign EX_Command[3:0] = EX_In_Command[3:0];
Stage_EX_MEM EX_Stage(MEM_In_Command, MEM_Rd, MEM_ALU_Result,
MEM_WriteData,
MEM_clk, clk, reset,
EX_Command, EX_WriteRegister, EX_ALU_Result, EX_ALU_Data2);
/* ================ Fourth pipeline stage: MEM ======================== */
/* Data memory */
assign MEM_RegWrite = MEM_In_Command[0];
assign MEM_MemRead = MEM_In_Command[2];
assign MEM_MemWrite = MEM_In_Command[3];
datamem MEM_DataMem(MEM_ReadData, MEM_ALU_Result, MEM_WriteData,
MEM_MemWrite, MEM_clk);
assign MEM_Command[1:0] = MEM_In_Command[1:0];
Stage_MEM_WB WB_Stage(WB_Command, WB_ReadData, WB_ALU_Result, WB_Rd,
WB_clk, clk, reset, MEM_Command[1:0], MEM_ReadData, MEM_ALU_Result, MEM_Rd);
/* ================== Fifth pipeline stage: WB ============================ */
Trang 16/* Muxtiplexer: Write back data */
assign WB_MemToReg = WB_Command[1];
assign WB_RegWrite = WB_Command[0];
mux32_2to1 WB_Mux01(WB_WriteData, WB_MemToReg, WB_ALU_Result, WB_ReadData);endmodule
input ID_EX_MemRead, reset;
input [4:0] IF_ID_Rt, IF_ID_Rs, ID_EX_Rt;
output PCWrite, IF_ID_Write, ID_EX_Stall;
/* if(ID_EX_MemRead == 1) and ((ID_EX_Rt == IF_ID_Rt) or (ID_EX_Rt == IF_ID_Rs))
then:
• Force all control outputs to 0
• Prevent PC from changing
• Prevent IF/ID from changing
*/
Compare_Register05 hazard1(n1, ID_EX_Rt, IF_ID_Rt);
Compare_Register05 hazard2(n2, ID_EX_Rt, IF_ID_Rs);
or #50 hazard3(reg_equal, n1, n2);
buf #150 hazard4(d_MemRead, ID_EX_MemRead);
and #50 hazard5(hazard_true, reg_equal, d_MemRead);
buf #50 hazard6(ID_EX_Stall, hazard_true);
not #50 hazard7(IF_ID_Write, hazard_true);
not #50 hazard8(PCWrite, hazard_true);
endmodule
Trang 17/* ===========================================================
* =============== Forwarding unit ===============================
* ===========================================================*/
module Forwarding_Unit(ForwardA, ForwardB, ID_EX_Rs, ID_EX_Rt, MEM_WB_Rd,
EX_MEM_Rd, EX_MEM_RegWrite, MEM_WB_RegWrite);
input MEM_WB_RegWrite, EX_MEM_RegWrite;
input [4:0] ID_EX_Rs, ID_EX_Rt;
input [4:0] EX_MEM_Rd, MEM_WB_Rd;
output [1:0] ForwardA, ForwardB;
Compare_Register05 forwardA1(A1, EX_MEM_Rd, 5'h00);
Compare_Register05 forwardA2(A2, ID_EX_Rs, EX_MEM_Rd);
Compare_Register05 forwardA3(A3, ID_EX_Rt, EX_MEM_Rd);
not #50 forwardA4(A4, A1);
and #50 forwardA5(ForwardA[1], A2, A4, EX_MEM_RegWrite);
and #50 forwardA6(ForwardB[0], A3, A4, EX_MEM_RegWrite);
/* Forward from MEM/WB registers
If (MEM_WB.RegWrite)
and If (MEM_WB.Rd != 0)
Trang 18and If (ID_EX.Rt == MEM_WB.Rd)
*/
Compare_Register05 forwardB1(B1, MEM_WB_Rd, 5'h00);
Compare_Register05 forwardB2(B2, ID_EX_Rs, MEM_WB_Rd);
Compare_Register05 forwardB3(B3, ID_EX_Rt, MEM_WB_Rd);
not #50 forwardB4(B4, B1);
and #50 forwardB5(ForwardA[0], B2, B4, MEM_WB_RegWrite);
and #50 forwardB6(ForwardB[1], B3, B4, MEM_WB_RegWrite);
endmodule
/* =============================================================
* ================== Pipeline 1st Stage: IF/ID =========================
* =============================================================*/
module Stage_IF_ID(IF_ID_Write, IF_Flush, Input_PC_4, clk, reset,
Input_InstrMem, Output_PC_4, Output_InstrMem);
Register_Control32 Register_1(Output_PC_4, clk, IF_ID_Write, reset, IF_Flush, Input_PC_4);
/* Output Instruction memory */
Register_Control32 Register_2(Output_InstrMem, clk, IF_ID_Write, reset, IF_Flush,
Trang 19module Stage_ID_EX(Output_WB_M_EX, Output_Rs, Output_Rt, Output_Rd,
Output_Funct, Output_ReadData1, Output_ReadData2,
clk, reset,
Input_WB_M_EX, Input_Rs, Input_Rt, Input_Rd,
Input_Funct, Input_ReadData1, Input_ReadData2);
output [31:0]Output_ReadData1, Output_ReadData2;
/* Control signals: WB - Mem - EX */
Register_NonControl07 Register1(Output_WB_M_EX, clk, reset, Input_WB_M_EX);