单指令周期CPU---转移指令的实现

指令周期CPU---转移指令的实现
在之前实现的基础上继续增加了14条(实际上是12条)简单算术操作指令(jr、jalr、j、jar、b、bal、beq、bgez、bgezal、bgtz、blez、bltz、bltzal、bne)
之前操作的传送门:
指令介绍
跳转指令:jr、jalr、j、jar
分⽀指令b、bal、beq、bgez、bgezal、bgtz、blez、bltz、bltzal、bne
跳转指令
指令格式:
- jr(功能码为6’b001000):⽤法:jr rs,作⽤:pc <- rs 将地址为rs的通⽤寄存器的值赋给寄存器PC,作为新的指令地址
- jalr(功能码为6’b001001):⽤法:jalr rs 或者 jalr rd,rs 作⽤:rd <- return_address,pc <- rs,将地址为rs的通⽤寄存器的值赋给寄存器PC,作为新的指令地址,同时将跳转指令后⾯第2条指令的地址作为返回地址保存到地址为rd的通⽤寄存器,如果没有在指令中指明rd,那么默认将返回地址保存到寄存器$31
- j(指令码为6’b000010):⽤法:j target,作⽤:pc <- (pc+4)[31,28]||target||’00’,转移到新的指令地址,其中新地址的低28位是target左移两位后的值,新指令地址⾼4位是后⼀指令的⾼四位
**因为处理器按照字节寻址,⼆指令存储器每个地址是⼀个32bit字,所以要给指令中的⽴即数乘4,即左移两位**
jal(指令码为6’b000011):⽤法:jal target,作⽤:pc <- (pc+4)[31,28]||target||’00’,转移到新的指令地址,其中新地址的低28位是target左移两位后的值,新指令地址⾼4位是后⼀指令的⾼四位,jal指令要将跳转指令后⾯的⼀条指令地址(pc+4)写⼊$31寄存器
分⽀指令
指令格式:
- 由指令格式可以看出:
beq、b、bgtz、blez、bne这5条指令可以直接依据指令中的指令码进⾏判断是哪⼀条指令,bltz、bltzal、bgez、bgezal、bal这5条指令指令码相同,依据指令中16\~20bit的值进⼀步判断是哪⼀条指令
所有分⽀指令的第0\~15bit存储的都是offset,如果发⽣转移,那么将offset左移2位,并符号扩展⾄32位
转移⽬标地址 = (signed_extend)(offset||'00')+(pc+4)
- beq(指令码为6’b000100):⽤法:beq rs,rt,offset,作⽤:if rs = rt then branch,将地址为rs的通⽤寄存器的值与地址为rt的通⽤寄存器的值进⾏⽐较,如果相等,则发⽣转移
- b(指令码为6’b000100,且16\~25bit为0):⽤法:b offset,作⽤:⽆条件转移,即beq指令的rs,rt都为0时的情况,实现时不需要特意实现b指令,只需要实现beq即可
- bgtz(指令码为6’b000111):⽤法:bgtz rs,offset,作⽤:if rs > 0 then branch
- blez(指令码6’b000110):⽤法:blez rs,offset,作⽤:if rs <= 0 then branch
- bne(指令码6’b000101):⽤法:bne rs,rt,offset,作⽤:if rs != rt then branch
- bltz(指令码为REGIMM,且第16\~20bit为5’b00000):⽤法:bltz rs,offset,作⽤:if rs < 0 then branch
- * bltzal(指令码为REGIMM,且第16\~20bit为5’b10000):⽤法:bltzal rs,offset,作⽤:if rs < 0 then branch,并且将指令后⾯的指令地址作为返回地址,保存到通⽤寄存器$31*
- bgez(指令码为REGIMM,且第16\~20bit为5’b00001):⽤法:bgez rs,offset,作⽤:if rs >= 0 then branch
- bgezal(指令码为REGIMM,且第16\~20bit为5’b10001):⽤法:bgezal rs,offset,作⽤:if rs >= 0 then branch,并且将指令后⾯的指令地址作为返回地址,保存到通⽤寄存器$31
- bal(指令码为REGIMM,且第21\~25bit为0,第16\~20bit为5’b10001):⽤法:bal offset,作⽤:⽆条件转移,并且将指令后⾯的指令地址作为返回地址,保存到通⽤寄存器$31,bal是bgezal指令的特殊情况,即bgezal指令的rs为0,不⽤特意实现这个指令
修改系统结构
增加了PC和ID模块的两个接⼝,⽤来表⽰是否跳转和跳转的指令地址,也增加了ID模块和EX模块的⼀个借⼝,⽤来表⽰将要保存的指令地址
新型化粪池
代码修改
1. 增加宏定义
`define Branch 1'b1            //发⽣转移
电镀前处理
`define NotBranch 1'b0          //不发⽣转移
`define EXE_J  6'b000010        //指令J的功能码
`define EXE_JAL  6'b000011      //指令JAL的功能码冰鞋座
`define EXE_JALR  6'b001001    //指令JALR的功能码
`define EXE_JR  6'b001000      //指令JR的功能码
`define EXE_BEQ  6'b000100      //指令BEQ的指令码
`define EXE_BGEZ  5'b00001      //指令BGEZ第16~20bit
`define EXE_BGEZAL  5'b10001    //指令BGEZAL第16~20bit
`define EXE_BGTZ  6'b000111    //指令BGTZ的指令码
`define EXE_BLEZ  6'b000110    //指令BLEZ的指令码
`define EXE_BLTZ  5'b00000      //指令BLTZ第16~20bit
`define EXE_BLTZAL  5'b10000    //指令BLTZAL第16~20bit
韩先良`define EXE_BNE  6'b000101      //指令BNE的指令码
`define EXE_REGIMM_INST 6'b000001  //REGIMM类的指令码
`define EXE_J_OP  8'b01001111
`define EXE_JAL_OP  8'b01010000
`define EXE_JALR_OP  8'b00001001
`define EXE_JR_OP  8'b00001000
`define EXE_BEQ_OP  8'b01010001
`define EXE_BGEZ_OP  8'b01000001
`define EXE_BGEZAL_OP  8'b01001011
`define EXE_BGTZ_OP  8'b01010100
`define EXE_BLEZ_OP  8'b01010011
`define EXE_BLTZ_OP  8'b01000000
`define EXE_BLTZAL_OP  8'b01001010
tz15`define EXE_BNE_OP  8'b01010010
2. 修改取指阶段PC 阶段
增加了两个输⼊接⼝:⽤来接收从译码阶段ID模块传来的信息
branch_flag_i:⽤来标识是否发⽣转移
branch_target_address_i:转移到的⽬标地址
3. 修改译码阶段ID 模块
根据指令的指令码和功能码,以及指令有关bit位的特点来判断是哪⼀条指令
always @ (posedge clk) begin
if  (ce == `ChipDisable) begin
pc <= 32'h00000000;
end  else  if (stall[0] == `NoStop) begin
if (branch_flag_i == `Branch) begin
pc <= branch_target_address_i;
end  else  begin
pc <= pc + 4'h4;
end
end
end
wire[`RegBus] pc_plus_4;
wire[`RegBus] imm_sll2_signedext ;
assign pc_plus_4 = pc_i +4;
assign imm_sll2_signedext = {{14{inst_i[15]}}, inst_i[15:0], 2'b00 };
...
`EXE_JR: begin
wreg_o <= `WriteDisable ;
aluop_o <= `EXE_JR_OP ;
alusel_o <= `EXE_RES_JUMP_BRANCH ;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
link_addr_o <= `ZeroWord ;
branch_target_address_o <= reg1_o ;
单元测试流程
branch_flag_o <= `Branch ;
instvalid <= `InstValid ;
end
`EXE_JALR: begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_JALR_OP;
alusel_o <= `EXE_RES_JUMP_BRANCH;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
if(inst_i[15:11] == 5'b00000)begin //如果没有指定保存寄存器,则默认保存到$31            wd_o <= 5'b11111;
end
else begin
wd_o <= inst_i[15:11];
end
link_addr_o <= pc_plus_4;
branch_target_address_o <= reg1_o;
branch_flag_o <= `Branch;
instvalid <= `InstValid;
end
...
`EXE_J:        begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_J_OP;
alusel_o <= `EXE_RES_JUMP_BRANCH;
reg1_read_o <= 1'b0;
reg2_read_o <= 1'b0;
link_addr_o <= `ZeroWord;
branch_target_address_o <= {pc_plus_4[31:28], inst_i[25:0], 2'b00};
branch_flag_o <= `Branch;
instvalid <= `InstValid;
end
`EXE_JAL:          begin
wreg_o <= `WriteEnable;
aluop_o <= `EXE_JAL_OP;
alusel_o <= `EXE_RES_JUMP_BRANCH;
reg1_read_o <= 1'b0;
reg2_read_o <= 1'b0;
wd_o <= 5'b11111;
link_addr_o <= pc_plus_4 ;
branch_target_address_o <= {pc_plus_4[31:28], inst_i[25:0], 2'b00};
branch_flag_o <= `Branch;
instvalid <= `InstValid;
end
`EXE_BEQ:          begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_BEQ_OP;
alusel_o <= `EXE_RES_JUMP_BRANCH;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
if(reg1_o == reg2_o) begin
branch_target_address_o <= pc_plus_4 + imm_sll2_signedext;
branch_flag_o <= `Branch;
end
end
`EXE_BGTZ:          begin
wreg_o <= `WriteDisable;
aluop_o <= `EXE_BGTZ_OP;
alusel_o <= `EXE_RES_JUMP_BRANCH;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
instvalid <= `InstValid;
if((reg1_o[31] == 1'b0) && (reg1_o != `ZeroWord)) begin
branch_target_address_o <= pc_plus_4 + imm_sll2_signedext;
branch_flag_o <= `Branch;
end
end

本文发布于:2024-09-21 20:50:17,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/3/344518.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:指令   地址   阶段   保存   作为   返回   模块
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议