一、计算机的组成结构
1.五个组成部件:数据通路,控制器,存储器,输入输出设备
2.处理器(CPU):数据通路 + 控制器
什么是数据通路?
指令执行过程中,数据所经过的路径,包括路径中的部件。它是指令的执行部件
控制器的功能是什么?
对 指令进行译码,生成指令对应的控制信号,控制数据通路的动作。能对执行部件发出控制信号,是指令的控制部件。
二、MIPS指令的执行过程
1.R-type指令
取指、译码+取数、执行、写回
2.I-type指令
立即数运算/逻辑运算指令:取指、译码+取数、执行、写回(寄存器文件)
比较指令:取指、译码+取数、执行(PC更新)
Store指令:取指、译码+取数、执行(计算写回地址)
Load指令:取指、译码+取数、执行(计算读出的地址)、访存、写回(寄存器文件)
3.J-type指令
取指、译码+取数 (PC更新)
三、多周期处理器
主要思想:把指令的执行分成多个阶段,每个阶段在一个时钟周期内完成,
3.1尽量分成大致相等的若干阶段(取指、译码+取数、执行、访存、写回)
3.2规定每个阶段最多完成1次访存或寄存器堆读/写或ALU
3.3时钟周期以最复杂阶段花费时间为准
每步设置存储元件,每部执行结果都在下个时钟开始保存到相应单元
多周期处理器数据通路的代码如下
module MutipleDataPath(
input clk,
input rstn,
input PcWr,
// input IoD,
input PcwrCond,
input MemWr,
input IRWr,
input RegDst,
input RegWr,
input ALUSelA,
input[1:0] ALUSelB,
input BrWr,
input [1:0] PcSource,
input MDRWr,
input MemtoReg,
input ExtOp,
input[3:0] AluOp,
output [31:0] instruction
);
reg [31:0] IR;
reg [31:0] MDR;
reg [31:0] A,B;
reg [31:0] Branch;
reg [31:0] PC;
reg [31:0] PcNext;
wire PCen;
wire [31:0] DA;
reg [31:0] DB;
wire [31:0] zero;
wire overflow;
wire[31:0] ALUResult;
assign instruction = IR;
always@(*) begin
case(PcSource)
2'b00: PcNext = {PC[31:28],IR[25:0],2'b00};
2'b01: PcNext = ALUResult;
2'b10: PcNext = Branch;
2'b11: PcNext = A;
default: PcNext = 32'd0;
endcase
end
assign PCen = PcWr | ((PcwrCond & (&zero)) | (PcwrCond & (~(&zero))));
always @(posedge clk or negedge rstn) begin
if(~rstn)
PC <= 32'd0;
else if(PCen)
PC <= PcNext;
end
wire [31:0] MemAddr;
wire [31:0] RdData1;
wire [31:0] RdData2;
assign MemAddr = ALUResult;
//(IoD)?ALUResult:PC
/*
RamNoDelay Mem(
.clk(clk),
.wen(MemWr),
.WrAddr(MemAddr),
.WrData(B),
.RdAddr(MemAddr),
.RdData(RdData)
);
*/
RamNoDelay Mem(
.clk(clk),
.wen(MemWr),
.WrAddr(MemAddr),
.WrData(B),
.RdAddr1(MemAddr),
.RdAddr2(PC),
.RdData1(RdData1),
.RdData2(RdData2)
);
always@(posedge clk or negedge rstn) begin
if(~rstn)
IR <=32'd0;
else if(IRWr)
IR <= RdData2;
end
always@(posedge clk or negedge rstn) begin
if(~rstn)
MDR<=32'd0;
else if(MDRWr)
MDR <= RdData1;
end
wire [4:0] Rs;
wire [4:0] Rt;
wire [4:0] Rd;
wire [4:0] shift;
wire [15:0] imme;
assign Rs= IR[25:21];
assign Rt= IR[20:16];
assign Rd= IR[15:11];
assign shift=IR[10:6];
assign imme= IR[15:0];
wire [4:0] Rw;
wire [31:0] BusA, BusB;
wire [31:0] Dw;
wire Rwen;
assign Rw=(RegDst)?Rd:Rt;
assign Dw=(MemtoReg)?MDR:ALUResult;
assign Rwen = ~overflow & RegWr;
dflipflop RegisterFile(
.clk(clk),
.Ra(Rs),
.Rb(Rt),
.Rw(Rw), //要写入的目的寄存器的地址
.Wen(Rwen),
.BusA(BusA),
.BusB(BusB),
.BusW(Dw) //要写入的32位数据
);
always@(posedge clk or negedge rstn) begin
if(~rstn)
A <= 32'd0;
else
A <= BusA;
end
always@(posedge clk or negedge rstn) begin
if(~rstn)
B <= 32'd0;
else
B <= BusB;
end
wire [31:0] ExtResult;
assign ExtResult = (ExtOp)? {{16{imme[15]}},imme}:{16'd0,imme};
assign DA= (ALUSelA)?A:PC;
always@(*)begin
case(ALUSelB)
2'b00: DB = B;
2'b01: DB = 3'b100;
2'b10: DB = ExtResult;
2'b11: DB = ExtResult << 2;
endcase
end
alu alu(
.alu_DA(DA),
.alu_DB(DB),
.alu_CTL(AluOp),
.alu_SHIFT(shift),
.alu_ZERO(zero),
.alu_Overflow(overflow),
.alu_DC(ALUResult)
);
always@(posedge clk or negedge rstn) begin
if(~rstn)
Branch <=32'd0;
else if(BrWr)
Branch <= ALUResult;
end
endmodule
module RamNoDelay(
input clk,
input wen,
input [31:0] WrAddr,
input [31:0] WrData,
input [31:0] RdAddr1,
input [31:0] RdAddr2,
output [31:0] RdData1,
output [31:0] RdData2
);
reg [31:0] rom [255:0];
initial begin
$readmemh("F:/work/digital_system_practise/Multiple_data_path/rtl/inst_rom.data",rom);
end
reg [31:0] ram [255:0];
always@(posedge clk)begin
if(wen)
ram[WrAddr] <= WrData;
end
assign RdData1 = ram[RdAddr1];
assign RdData2 = rom[RdAddr2];
endmodule
module dflipflop(
input clk,
input [4:0] Ra,
input [4:0] Rb,
input [4:0] Rw,
input Wen,
output [31:0] BusA,
output [31:0] BusB,
input [31:0] BusW
);
reg [31:0]DataReg[31:0];
always@(posedge clk)
begin
if(Wen & Rw!=5'd0)
DataReg[Rw] <= BusW;
end
assign BusA = (Ra==5'd0)?32'd0:DataReg[Ra];
assign BusB = (Rb==5'd0)?32'd0:DataReg[Rb];
endmodule
module alu(
input [31:0] alu_DA,
input [31:0] alu_DB,
input [3:0] alu_CTL,
input [4:0] alu_SHIFT,
output [31:0] alu_ZERO,
output alu_Overflow,
output reg [31:0] alu_DC
);
/******************general ctr ****************************/
wire SUBctr;
wire SIGctr;
wire Ovctr;
wire [1:0] Opctr;
wire [1:0] Logicctr;
wire [1:0] Shiftctr;
assign SUBctr = ((~alu_CTL[3]) & ~alu_CTL[2] & alu_CTL[1])|(alu_CTL[3] & ~alu_CTL[2]);
assign Opctr = alu_CTL[3:2];
assign Ovctr = (alu_CTL[0] & ~alu_CTL[3] & ~alu_CTL[2])|(alu_CTL[3] & ~alu_CTL[2] & ~alu_CTL[1] & alu_CTL[0]);
assign SIGctr = alu_CTL[0];
assign Logicctr = alu_CTL[1:0];
assign Shiftctr = alu_CTL[1:0];
/*****************logic op****************************/
reg [31:0] logic_result;
always@(*)begin
case(Logicctr)
2'b00:logic_result = alu_DA & alu_DB;
2'b01:logic_result = alu_DA | alu_DB;
2'b10:logic_result = alu_DA ^ alu_DB;
2'b11:logic_result = ~(alu_DA | alu_DB);
endcase
end
/********************shift op****************************/
wire [31:0] shift_result;
Shifter Shifter(
.alu_DB(alu_DB),
.ALUSHIFT(alu_SHIFT),
.Shiftctr(Shiftctr),
.shift_result(shift_result)
);
/************************add sub op*********************************/
wire [31:0] BIT_M,XOR_M;
wire ADD_carry,ADD_OverFlow;
wire [31:0] ADD_result;
wire [31:0] comp_M;
assign BIT_M = {32{SUBctr}};
assign XOR_M = (alu_DB[31] && SUBctr)?{1'b0,alu_DB[30:0]}:BIT_M ^ alu_DB;
assign comp_M = (alu_DB[31] && SUBctr)?XOR_M: XOR_M + SUBctr;
assign alu_Overflow = ADD_OverFlow & Ovctr;
assign {ADD_carry,ADD_result} = alu_DA + comp_M;
assign ADD_OverFlow = (alu_DA[31] && comp_M[31] && !ADD_result[31]) +
(!alu_DA[31] && !comp_M[31] && ADD_result[31]);
assign alu_ZERO = (|ADD_result)?32'h0000_0000:32'hffff_ffff;
/****************************slt op****************************/
wire [31:0] SLT_result;
wire LESS_M1,LESS_M2,LESS_S,SLT_M;
assign LESS_M1 = ADD_carry ^ SUBctr;
assign LESS_M2 = ADD_OverFlow ^ ADD_result[31];
assign LESS_S = (SIGctr == 1'b0)?LESS_M1:LESS_M2;
assign SLT_result = (LESS_S)?32'hffff_ffff:32'h0000_0000;
/****************************ALU_result***************************/
always@(*)
begin
case(Opctr)
2'b00:alu_DC = ADD_result;
2'b01:alu_DC = logic_result;
2'b10:alu_DC = SLT_result;
2'b11:alu_DC = shift_result;
endcase
end
endmodule
module aluControl(
input [5:0] func,
output [3:0] aluOp
);
wire add = (func == 6'b100000);
wire addu = (func == 6'b100001);
wire sub = (func == 6'b100010);
wire subu = (func == 6'b100011);
wire and1 = (func == 6'b100100);
wire or1 = (func == 6'b100101);
wire xor1 = (func == 6'b100110);
wire nor1 = (func == 6'b100111);
wire sltu = (func == 6'b101011);
wire slt = (func == 6'b101010);
wire sll = (func == 6'b000000);
wire srl = (func == 6'b000010);
wire sra = (func == 6'b000011);
assign aluOp = ({4{add}} & 4'b0001) |
({4{addu}} & 4'b0000) |
({4{sub}} & 4'b0011) |
({4{subu}} & 4'b0010) |
({4{and1}} & 4'b0100) |
({4{or1}} & 4'b0101) |
({4{xor1}} & 4'b0110) |
({4{nor1}} & 4'b0111) |
({4{sltu}} & 4'b1000) |
({4{slt}} & 4'b1001) |
({4{sll}} & 4'b1100) |
({4{srl}} & 4'b1101) |
({4{sra}} & 4'b1110);
endmodule
控制器模块的代码下:
module MultipleControl(
input clk,
input rstn,
output PcWr,
//output IoD,
output PcWrCond,
output MemWr,
output IRWr,
output RegDst,
output RegWr,
output reg ALUSelA,
output reg [1:0] ALUSelB,
output BrWr,
output reg [1:0] PcSource,
output MDRWr,
output MemtoReg,
output reg ExtOp,
output reg [3:0] AluOp,
input [31:0] instruction
);
reg [3:0] nstate;
reg [3:0] state;
parameter IFetch = 4'b0000,
RFetch = 4'b0001,
BrFinish = 4'b0010,
Jfinish = 4'b0011,
Jrfinish = 4'b0100,
OriExec = 4'b0101,
OriFinish = 4'b0110,
Rexec = 4'b0111,
RFinish = 4'b1000,
MemAdr = 4'b1001,
swFinish = 4'b1010,
MemFetch = 4'b1011,
lwFinish = 4'b1100;
//wire [3:0] Aluctr;
wire [5:0] op = instruction[31:26];
wire [5:0] func = instruction[5:0];
wire jr = ((op == 6'b000000) && (func == 6'b001000));
wire ori = (op == 6'b001101);
//wire andi = (op == 6'b001100);
wire lw = (op == 6'b100011);
wire sw = (op == 6'b101011);
wire beq = (op == 6'b000100);
wire bne = (op == 6'b000101);
wire j = (op == 6'b000010);
//wire addi = (op == 6'b001000);
wire R_type = (op == 6'b000000);
wire instrl = ori;
wire ls = lw | sw;
always@(*)begin
case(state)
IFetch:nstate = RFetch;
RFetch:if(beq || bne) nstate = BrFinish;
else if(j) nstate = Jfinish;
else if(instrl) nstate = OriExec;
else if(R_type) nstate = Rexec;
else if(ls) nstate = MemAdr;
else if(jr) nstate = Jrfinish;
else nstate = IFetch;
BrFinish: nstate = IFetch;
Jfinish: nstate = IFetch;
Jrfinish: nstate = IFetch;
Rexec:nstate = RFinish;
RFinish:nstate = IFetch;
OriExec:nstate = OriFinish;
OriFinish:nstate = IFetch;
MemAdr: if(lw) nstate = MemFetch;
else nstate = swFinish;
swFinish:nstate = IFetch;
MemFetch:nstate = lwFinish;
lwFinish:nstate = IFetch;
default:nstate = IFetch;
endcase
end
wire [3:0] aluOp1 = ({4{ori}} & 4'b0101);
/* |
({4{andi}} & 4'b0100) |
({4{addi}} & 4'b0001);
*/
wire [3:0]aluOp2;
aluControl aluControl(
.func(func),
.aluOp(aluOp2)
);
assign PcWr = (state == IFetch) | (state == Jfinish) | (state == Jrfinish);
//assign IoD = (state == MemAdr) | (state == swFinish) | (state == MemFetch)|(state == lwFinish);
assign PcWrCond = (state == BrFinish);
assign MemWr = (state == swFinish);
assign IRWr = (state == IFetch);
assign RegDst = (state == Rexec) | (state == RFinish);
assign RegWr = (state == RFinish) | (state == OriFinish) | (state == lwFinish);
assign BrWr = (state == RFetch);
assign MemtoReg = (state == lwFinish);
assign MDRWr = (state == MemFetch);
always@(posedge clk or negedge rstn)begin
if(!rstn)
state <= IFetch;
else
state <= nstate;
end
always@(*)begin
case(state)
IFetch:
begin
ALUSelA = 1'b0; ALUSelB = 2'b01; PcSource = 2'b01; ExtOp = 1'b0; AluOp = 4'b0000;
end
RFetch:
begin
ALUSelA = 1'b0;ALUSelB = 2'b11;PcSource = 2'b01;ExtOp = 1'b1;AluOp = 4'b0000;
end
BrFinish: begin
ALUSelA = 1'b1;ALUSelB = 2'b00;PcSource = 2'b10;ExtOp = 1'b0;AluOp = 4'b0010;
end
Jfinish:
begin
ALUSelA = 1'b0;ALUSelB = 2'b00;PcSource = 2'b00;ExtOp = 1'b0;AluOp = 4'b0000;
end
Jrfinish:
begin
ALUSelA = 1'b0;ALUSelB = 2'b00;PcSource = 2'b11;ExtOp = 1'b0;AluOp = 4'b0000;
end
OriExec:
begin
ALUSelA = 1'b1;ALUSelB = 2'b10;PcSource = 2'b01;ExtOp = 0;AluOp = aluOp1;
end
OriFinish:
begin
ALUSelA = 1'b1;ALUSelB = 2'b10;PcSource = 2'b01;ExtOp = 0;AluOp = aluOp1;
end
Rexec:
begin
ALUSelA = 1'b1;ALUSelB = 2'b00;PcSource = 2'b01;ExtOp = 1'b0;AluOp = aluOp2;
end
RFinish:
begin
ALUSelA = 1'b1;ALUSelB = 2'b00;PcSource = 2'b01;ExtOp = 1'b0;AluOp = aluOp2;
end
MemAdr:
begin
ALUSelA = 1'b1;ALUSelB = 2'b10;PcSource = 2'b01;ExtOp = 1'b1;AluOp = 4'b0000;
end
swFinish:
begin
ALUSelA = 1'b1;ALUSelB = 2'b10;PcSource = 2'b01;ExtOp = 1'b1;AluOp = 4'b0000;
end
MemFetch:
begin
ALUSelA = 1'b1;ALUSelB = 2'b10;PcSource = 2'b01;ExtOp = 1'b1;AluOp = 4'b0000;
end
lwFinish: begin
ALUSelA = 1'b1;ALUSelB = 2'b10;PcSource = 2'b01;ExtOp = 1'b1;AluOp = 4'b0000;
end
default: begin ALUSelA = 1'b0;ALUSelB = 2'b00;PcSource = 2'b01;ExtOp = 1'b0;AluOp = 4'b0000;
end
endcase
end
endmodule
顶层模块如下:
module Multiple_top(
input clk,
input rstn
);
wire PcWr;
//wire IoD;
wire PcWrCond;
wire MemWr;
wire IRWr;
wire RegDst;
wire RegWr;
wire ALUSelA;
wire [1:0] ALUSelB;
wire BrWr;
wire [1:0] PcSource;
wire MDRWr;
wire MemtoReg;
wire ExtOp;
wire [3:0] AluOp;
wire [31:0] instruction;
MultipleControl MultipleControl(
.clk(clk),
.rstn(rstn),
.PcWr(PcWr),
//.IoD(IoD),
.PcWrCond(PcWrCond),
.MemWr(MemWr),
.IRWr(IRWr),
.RegDst(RegDst),
.RegWr(RegWr),
.ALUSelA(ALUSelA),
.ALUSelB(ALUSelB),
.BrWr(BrWr),
.PcSource(PcSource),
.MDRWr(MDRWr),
.MemtoReg(MemtoReg),
.ExtOp(ExtOp),
.AluOp(AluOp),
.instruction(instruction)
);
MutipleDataPath MutipleDataPath(
.clk(clk),
.rstn(rstn),
.PcWr(PcWr),
//.IoD(IoD),
.PcwrCond(PcWrCond),
.MemWr(MemWr),
.IRWr(IRWr),
.RegDst(RegDst),
.RegWr(RegWr),
.ALUSelA(ALUSelA),
.ALUSelB(ALUSelB),
.BrWr(BrWr),
.PcSource(PcSource),
.MDRWr(MDRWr),
.MemtoReg(MemtoReg),
.ExtOp(ExtOp),
.AluOp(AluOp),
.instruction(instruction)
);
endmodule
module Shifter(
input [31:0] alu_DB,
input [4:0] ALUSHIFT,
input [1:0] Shiftctr,
output reg [31:0] shift_result
);
wire [5:0] shift_n;
assign shift_n = 6'd32 - ALUSHIFT;
always@(*)begin
case(Shiftctr)
2'b00: shift_result = alu_DB << ALUSHIFT;
2'b01: shift_result = alu_DB >> ALUSHIFT;
2'b10: shift_result = ({32{alu_DB[31]}} << shift_n) | (alu_DB >> ALUSHIFT);
default: shift_result = alu_DB;
endcase
end
endmodule