MIPS流水线CPU的verilog实现 - 图文 联系客服

发布时间 : 星期日 文章MIPS流水线CPU的verilog实现 - 图文更新完毕开始阅读c9f71522ed630b1c59eeb52e

八种指令类型中J_tpye、JR_tpye及Branch类型指令没有使用ALU;其他使用ALU的指令类型中LW、SW、R_type1和I_type均采用的rs作为ALU第一操作数,只有R_type2的第一操作数采用的是0扩展的sa,所以:

ALUSrcA_id= R_type2 ⑦ ALUSrcB

决定ALU第二操作数来源。当ALUSrcB=0时,ALU第二操作数B。当ALUSrcB=1时,ALU第二操作数来源于符号扩展的16位Imm。

八种指令类型中J_tpye、JR_tpye及Branch类型指令没有使用ALU。其他使用ALU的指令类型中R_type1和R_type2 采用rt作为ALU第二操作数,而LW、SW、I_type的第二操作数采用的是符号扩展的立即数Imm段,所以:

ALUSrcB_id= LW || SW || I_type ⑧ PCSource

决定写入PC寄存器的来源。PCSource由JR_tpye 、J_tpye及Z决定:即:PCSource={JR, J, Z}

?PCSource=000时, 写入值为下一条指令的地址PC+4; ?PCSource=001时, 写入值为Branch指令的分支地址; ?PCSource=010时,写入值为J指令的跳转地址; ?PCSource=100时,写入值为JR指令的跳转地址。

⑨ ALUCode

决定ALU的功能,由指令中的op段、rt段和funct段决定。功能表如下: op BEQ_op BNE_op BGEZ_op BGTZ_op BLEZ_op BLTZ_op R_type_op funct ×××××× ×××××× ×××××× ×××××× ×××××× ×××××× ADD_funct ADDU_funct AND_funct XOR_funct OR_funct NOR_funct SUB_funct SUBU_funct SLT_funct SLTU_funct SLL_funct SLLV_funct SRL_funct SRLV_funct SRA_funct SRAV_funct rt ×××××× ×××××× 5'd1 5'd0 5'd0 5'd0 ×××××× ×××××× ×××××× ×××××× ×××××× ×××××× ×××××× ×××××× ×××××× ×××××× ×××××× ×××××× ×××××× ×××××× ×××××× ×××××× 运算 Z=(A==B) Z=~(A==B) Z=(A≥0) Z=(A>0) Z=(A≤0) Z=(A<0) 加 与 异或 或 或非 减 A>A B>>>A ALUCode 5'd10 5'd11 5'd12 5'd13 5'd14 5'd15 5'd0 5'd1 5'd2 5'd3 5'd4 5'd5 5'd19 5'd20 5'd16 5'd17 5'd18 13

op ADDI_op ADDIU_op ANDI_op XORI_op ORI_op SLTI_op SLTIU_op SW_op LW_op funct ×××××× ×××××× ×××××× ×××××× ×××××× ×××××× ×××××× ×××××× ×××××× rt ×××××× ×××××× ×××××× ×××××× ×××××× ×××××× ×××××× ×××××× ×××××× 运算 加 与 异或 或 A

Zero检测电路主要用于判断Branch指令的分支条件是否成立,其中BEQ、BNE两个操作数为RsData与RtData,而BGEZ、BGTZ、BLEZ和BLTZ指令则为RsData与常数0比较,所以输出信号Z的表达式为:

RsData[31] || ~ (| RsData[31: 0]) ; ALUCode=alu _blez RsData[31] ; ALUCode=alu _bltz ~ RsData[31] && (| RsData[31: 0]) ; ALUCode=alu _bgtz Z= ~ RsData[31]; ALUCode=alu _bgez

| ( RsData[31: 0] ^ RtData[31: 0]) ; ALUCode=alu_bne & ( RsData[31: 0] ~^ RtData[31: 0] ); ALUCode=alu_beq 0; ALUCode=OTHER

(3) 寄存器堆(Registers)的设计 寄存器堆由32个32位寄存器组成,这些寄存器通过寄存器号进行读写存取。寄存器堆的原理框图如图3.13所示。因为读取寄存器不会更改其内容,故只需提供寄存号即可读出该寄存器内容。读取端口采用数据选择器即可实现读取功能。应注意“0”号寄存器为常数0.

14

对于往寄存器里写数据,需要目标寄存器号(WriteRegister)、待写入数据(WriteData)、写允许信号(RegWrite)三个变量。图3.13中5位二进制译码器完成地址译码,其输出控制目标寄存器的写使能信号EN,决定将数据WriteData写入哪个寄存器。

在流水线CPU设计中,寄存器堆设计还应解决三阶数据相关的数据转发问题。当满足三阶数据相关条件时,寄存器具有Read after Write的特性。为实现该功能,在寄存器堆的基础上加一转发电路。如图3.14所示。图中转发检测电路的输出表达式为

RsSel=RegWrite_wb&&(~(RegWriteAddr_wb==0))&&(RegWriteAddr_wb==RsAddr_id) RtSel=RegWrite_wb&&(~(RegWriteAddr_wb==0))&&(RegWriteAddr_wb==RtAddr_id)

(4) 冒险检测功能(Hazard Deterctor)的设计 由前面分析可知,冒险成立的条件为:

① 上一条指令是LW指令,即MemRead_ex=1;

② 在EX级的LW指令与在ID级的指令读写的是同一个寄存器,即

RegWriteAddr_ex=RsAddr_id 或 RegWriteAddr_ex=RtAddr_id 解决冒险的方法为:

① 插入一个流水线气泡Stall清空ID/EX寄存器并且阻塞流水线ID级、IF级流水线,

有:

Stall=((RegWriteAddr_ex==RsAddr_id)||

(RegWriteAddr_ex==RtAddr_id))&&MemRead_ex

② 保持PC寄存器和IF/ID流水线寄存器不变,有:

PC_IFWrite=~Stall

(5) 其它单元电路的设计

① Branch指令分支地址的计算电路:

BranchAddr=NextPC_id+(sign-extend(Imm_id)<<2)

② JR指令跳转地址的计算电路:

JRAddr=RsData_id

15

③ J指令跳转地址的计算电路:

Jaddr={NextPC_id[31:28],IR_id[25:0],2’b00}

④ 符号扩展的方法—针对有符号数

?? 如果最高位(即符号位)是0,则要扩展的高位用0补齐;如果最高位是1,则用1补齐。

?? 例: 8位的+1,表示为二进制为00000001,扩展成16位的话,符号扩展为

0000000000000001;8位的-1,表示成二进制为11111111,扩展成16位的话,符号扩展为1111111111111111 。

⑤ 0扩展的方法—针对无符号数 ?? 要扩展的高位用0补齐。

?? 例:16位二进制0xFFFF(无符号数65535), 0扩展成32位为0x0000FFFF (无符号数65535) 。

4. 执行模块EX的设计

执行模块主要有ALU子模块、转发电路Forwarding以及若干数据选择器组成。这行模块的接口信息如下表所示: 引脚名称 RegDst_ex ALUCode_ex[4:0] ALUSrcA_ex ALUSrcB_ex

方向 Input 说 明 决定Register回写时采用的地址(rt/rd) 决定ALU采用何种运算 决定ALU的A操作数的来源(rs/Sa) 决定ALU的B操作数的来源(rt/Imm) 16