③ 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
引脚名称 Imm_ex[31:0] Sa_ex[31:0] RsAddr_ex[4:0] RtAddr_ex[4:0] RdAddr_ex[4:0] RsData_ex[31:0] RtData_ex[31:0] RegWriteData_wb[31:0] ALUResult_mem[31:0] RegWriteAddr_wb[4:0] RegWriteAddr_mem[4:0] RegWrite_wb RegWrite_mem RegWriteAddr_ex[4:0] ALUResult_ex[31:0] MemWriteData_ex[31:0] ALU_A[31:0] ALU_B[31:0] 方向 说 明 立即数 移位位数 Rs寄存器地址,即Instruction_id[25:21] Rt寄存器地址,即Instruction_id[20:16] Rd寄存器地址,即Instruction_id[15:11] Rs寄存器数据 Rt寄存器数据 写入寄存器的数据 ALU输出数据 寄存器的写地址 寄存器写允许信号 寄存器的写地址 ALU运算结果 寄存器的回写数据 ALU操作数,测试时使用 Input Output
(1) ALU子模块的设计
ALU是提供CPU基本运算能力的重要电路。ALU执行何种运算,由控制单元中的ALU控制器输出的ALUCode信号决定。ALU功能见下表: ALUCode ALUResult alu_add = 5'b00000 A+B alu_and = 5'b00001 A&B alu_xor = 5'b00010 A^B alu_or = 5'b00011 A|B alu_nor = 5'b00100 ~(A|B) alu_sub = 5'b00101 A-B alu_andi= 5'b00110 A&{16'b0,B[15:0]} alu_xori= 5'b00111 A^{16'b0,B[15:0]} alu_ori = 5'b01000 A|{16'b0,B[15:0]} alu_sll = 5'b10000 B<>A alu_sra = 5'b10010 B>>>A alu_slt = 5'b10011 A
17
图3.16 ALU的基本结构
a) 加、减电路的设计考虑
减法、比较(SLT、SLTI)及部分分支指令(BEQ、BNE)均可用加法器和必要的辅助电路来实现。图3.16中的Binvert信号控制加减运算:
Binvert=~(ALUCode==alu_add)
对ALU来说,它的两个操作数输入时都已经是补码形式,当要完成两个操作数的减法时,即A补-B补,可将减法转换为加法,利用加法器来实现:
?A补-B补= A补+(-B补)= A补+(B补)补= A补+(B补)反+1 加法器完成的功能为:
sum=A+B^{32{Binvert}}+Binvert
当Binvert=0时,sum=A+B^0+0= A+B;
当Binvert=1时,sum=A+B^{32’b1}+1= A-B;(B^{32’b1}即对B按位取反) 即可完成加减运算。
由于32位加法器的运算速度影响着CPU频率的高低,因此设计一个高速加法器尤
18
为重要,本实验采用lab7中介绍的32位进位选择加法器。 b) 比较电路的设计考虑
对于比较运算,如果最高为不同,即A[31]≠B[31],则根据A[31]、B[31]决定比较结果,但应注意有符号数和无符号数比较运算的区别。
①在有符号数比较SLT运算中,判断A
若A、B符号相同,A-B为负:(A[31]~^B[31]) && sum[31] 则
SLTResult=(A[31]&&(~B[31])) ||( (A[31]~^B[31]) && sum[31])
②在无符号数比较SLT运算中,判断A
若A、B最高位相同,A-B为负:(A[31]~^B[31]) && sum[31] 则
SLTResult=((~A[31] )&&B[31]) ||( (A[31]~^B[31]) && sum[31])
c) 算术右移运算电路的设计考虑
Verilog HDL的算术右移的运算符为“<<<”。要实现算术右移应注意,被移位的对象必须定义为reg类型,但是在SRA指令,被移位的对象操作数B为输入信号,不能定义为reg类型,因此必须引入reg类型中间变量B_reg,相应的Verilog HDL语句为:
reg signed [31:0] B_reg; always @(B) begin
B_reg = B; end
引入reg类型的中间变量B_reg后,就可对B_reg进行算术右移操作。 d) 逻辑运算
与、或、或非、异或、逻辑移位等运算较为简单,只是要注意一点,ANDI、XORI、ORI三条指令的立即数为16位无符号数,应“0扩展”为32位无符号数,在运算的同时完成“0扩展”。如:ADDI指令的运算为A&{16’b0,B[15:0]}。
(2) 转发电路Forwarding的设计 操作数A和B由数据选择器决定,数据选择器的地址信号即为ForwardA和ForwardB。其含义如下表: 说明 操作数A来自寄存器堆 操作数A来自二阶数据相关的转发数据 操作数A来自一阶数据相关的转发数据 操作数B来自寄存器堆 操作数B来自二阶数据相关的转发数据 操作数B来自一阶数据相关的转发数据 由前面介绍的一、二阶数据相关判断条件,不难得到:
ForwardA[0]=RegWrite_wb&&(RegWriteAddr_wb!=0) &&(RegWriteAddr_mem!=RsAddr_ex) &&(RegWriteAddr_wb==RsAddr_ex); ForwardA[1]=RegWrite_mem&&(RegWriteAddr_mem!=0) &&(RegWriteAddr_mem==RsAddr_ex);
19
地址 ForwardA=00 ForwardA=01 ForwardA=10 ForwardB=00 ForwardB=01 ForwardB=10 操作数来源 RsData_ex RegWriteData_wb ALUresult_mem RtData_ex RegWriteData_wb ALUresult_mem
ForwardB[0]=RegWrite_wb&&(RegWriteAddr_wb!=0) &&(RegWriteAddr_mem!=RtAddr_ex) &&(RegWriteAddr_wb==RtAddr_ex); ForwardB[1]=RegWrite_mem&&(RegWriteAddr_mem!=0) &&(RegWriteAddr_mem==RtAddr_ex);
5. 存储器访问MEM模块的设计
数据存储器利用Xilinx Core Generator实现。考虑到FPGA的资源,数据存储器可设计为容量各为26×32bit单端口RAM。
由于MIPS系统的32位字地址由4 个字节组成,根据“对齐限制”要求字地址必须是4的倍数,也就是说字地址的低两位必须是0,所以字地址的低两位不接入电路。故我们设计的数据RAM的地址应该接的信号是ALUResult_mem[7:2]。
由于VIRTEXII PRO只能产生带寄存器的内核RAM,所以存储器输出绕过MEM/WB流水线寄存器,直接接入WB级的数据选择器。图3.17与图3.18中的虚线就是表示这种含义.
20