转移指令的实现

我理解的是5级流水线中的转移指令前级被跳过
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

`include "defines.v"

module pc_reg(

	input  wire					clk,
	input  wire					rst,
	//来自控制模块的信息
	input wire[5:0]         stall,
	
	//来自译码阶段的信息
	input wire                    branch_flag_i,
	input wire[`RegBus]           branch_target_address_i,
	
	output reg [`InstAddrBus]	pc,	//InstAddrBus为宏定义 31:0 代表ROM的地址总线宽度 输出给ROM的addr
	output reg                 ce		//给到ROM的使能
	
);
	//如果复位,则使能信号ce拉0,否则置1
	always @ (posedge clk) begin
		if (rst == `RstEnable) begin	//复位信号有效 1'b1
			ce <= `ChipDisable;
		end 
		else begin
			ce <= `ChipEnable;
		end
	end
	
	//如果使能信号为低,则指令地址拉0;使能有效,则指令地址自加4'h4
	always @ (posedge clk) begin
		if (ce == `ChipDisable) begin	//芯片禁止宏定义 1'b0
			pc <= 32'h00000000;
		end 
		else if(stall[0] == `NoStop)begin
			if(branch_flag_i == `Branch) begin
				pc <= branch_target_address_i;
			end
			else 
				pc <= pc + 4'h4;	//自加4 字节寻址
		end
	end
	
endmodule

在这里插入图片描述
在这里插入图片描述

module id(
	input wire					      rst,
	input wire[`InstAddrBus]	   pc_i,			//[31:0]
	input wire[`InstBus]          inst_i,		//[31:0] 接收IF/ID模块给的指令
	
	//从regfile里输入的
	input wire[`RegBus]           reg1_data_i,	//[31:0]
	input wire[`RegBus]           reg2_data_i,	//[31:0]

	//处于执行阶段的指令要写入的目的寄存器信息
	input wire					  		ex_wreg_i,		//是否要写
	input wire[`RegBus]			   ex_wdata_i,
	input wire[`RegAddrBus]       ex_wd_i,
	
	//处于访存阶段的指令要写入的目的寄存器信息
	input wire					  		mem_wreg_i,		//是否要写
	input wire[`RegBus]			   mem_wdata_i,
	input wire[`RegAddrBus]       mem_wd_i,
	
	//如果上一条指令是转移指令,那么下一条指令在译码的时候
	//is_in_delayslot为true表示是延迟槽指令,反之为false
	input wire                    is_in_delayslot_i,	
	
	//送到regfile的信息
	output reg                    reg1_read_o,	//使能
	output reg                    reg2_read_o,   //使能  	
	output reg[`RegAddrBus]       reg1_addr_o,	//[4:0]
	output reg[`RegAddrBus]       reg2_addr_o,	//[4:0] 	      
	
	//送到执行阶段的信息
	output reg[`AluOpBus]         aluop_o,		//译码阶段的输出aluop_o的宽度  7:0 运算子类型
	output reg[`AluSelBus]        alusel_o,	//译码阶段的输出alusel_o的宽度 2:0 运算类型
	
	//结果写入寄存器
	output reg[`RegAddrBus]       wd_o,			//[4:0]  要写入的目的寄存器地址
	output reg                    wreg_o,		//是否有要写入的目的寄存器
	
	//这两个是最终输出的操作数
	output reg[`RegBus]           reg1_o,		//[31:0] 源操作数1
	output reg[`RegBus]           reg2_o,		//[31:0] 源操作数2

	output reg                    next_inst_in_delayslot_o,	//下一条进入译码阶段的指令是否在延迟槽
	
	output reg                    branch_flag_o,					//是否发生转移
	output reg[`RegBus]           branch_target_address_o, 	//转移到的目的地址      
	output reg[`RegBus]           link_addr_o,					//转移指令要保存的返回地址
	output reg                    is_in_delayslot_o,			//当前处于译码阶段的指令是否位于延迟槽
	
	output wire                   stallreq
);
	
	//取得指令的指令码,功能码 即分解帧格式
	//对于ori指令只需通过判断第26-31bit的值,即可判断是否是ori指令;对应I类型指令
    wire[5:0] op  = inst_i[31:26];	//op指令段
    wire[4:0] op2 = inst_i[10:6];
    wire[5:0] op3 = inst_i[5:0];
    wire[4:0] op4 = inst_i[20:16];
	 
	//保存指令执行需要的立即数[31:0]
    reg[`RegBus]	imm;
	 
	//指示指令是否有效
    reg instvalid;
	 
	 wire[`RegBus] pc_plus_8;
	 wire[`RegBus] pc_plus_4;
	 wire[`RegBus] imm_sll2_signedext;  
  
    assign pc_plus_8 = pc_i + 8;	//保存当前译码阶段指令后面第2条指令的地址
	 
    assign pc_plus_4 = pc_i +4;	//保存当前译码阶段指令后面第1条指令的地址
	 
	 //对应分支指令中的左移两位,并符号扩展至32位
	 assign imm_sll2_signedext = {{14{inst_i[15]}}, inst_i[15:0], 2'b00 };
	 
	 assign stallreq = `NoStop;

	//译码操作 组合逻辑实时译码
	//确定要读取的寄存器情况、要执行的运算、要写的目的寄存器
	//主要内容:大小运算类型、两个读口、指令有无效、是否要写、写地址、imm
	always @ (*) 	
		if (rst == `RstEnable) begin
			aluop_o  <= `EXE_NOP_OP;	//8'b0000_0000
			alusel_o <= `EXE_RES_NOP;	//3'b000
			wd_o   <= `NOPRegAddr;		//5'b00000
			wreg_o <= `WriteDisable;
			instvalid   <= `InstValid;	//指令有效 
			reg1_read_o <= 1'b0;
			reg2_read_o <= 1'b0;
			reg1_addr_o <= `NOPRegAddr; //5'b00000
			reg2_addr_o <= `NOPRegAddr; //5'b00000
			imm <= `ZeroWord;	
			link_addr_o <= `ZeroWord;
			branch_target_address_o <= `ZeroWord;
			branch_flag_o <= `NotBranch;
			next_inst_in_delayslot_o <= `NotInDelaySlot;		
	  end 
	  else begin
			//以下是非复位且无法判断指令时的默认情况
			aluop_o  <= `EXE_NOP_OP;	//8'b0000_0000
			alusel_o <= `EXE_RES_NOP;	//3'b000
			wd_o   <= inst_i[15:11];	//默认写入地址
			wreg_o <= `WriteDisable;
			instvalid   <= `InstInvalid;	//指令无效  
			reg1_read_o <= 1'b0;
			reg2_read_o <= 1'b0;
			//默认
			reg1_addr_o <= inst_i[25:21];	//rs寄存器 在后续的读端口使能中,如果使能,则默认为读此地址,对应指令		
			reg2_addr_o <= inst_i[20:16];	//rt寄存器 在后续的读端口使能中,如果使能,则默认为读此地址,对应指令
			imm <= `ZeroWord;
			link_addr_o <= `ZeroWord;
			branch_target_address_o <= `ZeroWord;
			branch_flag_o <= `NotBranch;	
			next_inst_in_delayslot_o <= `NotInDelaySlot; 		
		   case (op)
				`EXE_SPECIAL_INST: begin	//op为special 去判断op2
					case (op2)
						5'b00000:			begin	//5-2阶段非0无效 继续判断op3功能码 以此可跟sll区别
							case (op3)			//功能码	操作均是:类型与子类型,写使能、两个读使能、有无效(这几个操作要写入的寄存器就是默认的rd!)
								`EXE_OR:	begin	
									wreg_o <= `WriteEnable;		aluop_o <= `EXE_OR_OP;
									alusel_o <= `EXE_RES_LOGIC; 	
									reg1_read_o <= 1'b1;	reg2_read_o <= 1'b1;
									instvalid <= `InstValid;	
								end  
								`EXE_AND:	begin	
									wreg_o <= `WriteEnable;		aluop_o <= `EXE_AND_OP;
									alusel_o <= `EXE_RES_LOGIC;	  
									reg1_read_o <= 1'b1;	reg2_read_o <= 1'b1;	
									instvalid <= `InstValid;	
								end  	
								`EXE_XOR:	begin	
									wreg_o <= `WriteEnable;		aluop_o <= `EXE_XOR_OP;
									alusel_o <= `EXE_RES_LOGIC;		
									reg1_read_o <= 1'b1;	reg2_read_o <= 1'b1;	
									instvalid <= `InstValid;	
								end  				
								`EXE_NOR:	begin
									wreg_o <= `WriteEnable;		aluop_o <= `EXE_NOR_OP;
									alusel_o <= `EXE_RES_LOGIC;		
									reg1_read_o <= 1'b1;	reg2_read_o <= 1'b1;	
									instvalid <= `InstValid;	
								end 
								`EXE_SLLV: begin
										wreg_o <= `WriteEnable;		aluop_o <= `EXE_SLL_OP;
									alusel_o <= `EXE_RES_SHIFT;		
									reg1_read_o <= 1'b1;	reg2_read_o <= 1'b1;
									instvalid <= `InstValid;	
								end 
								`EXE_SRLV: begin
									wreg_o <= `WriteEnable;		aluop_o <= `EXE_SRL_OP;
									alusel_o <= `EXE_RES_SHIFT;		
									reg1_read_o <= 1'b1;	reg2_read_o <= 1'b1;
									instvalid <= `InstValid;	
								end 					
								`EXE_SRAV: begin
									wreg_o <= `WriteEnable;		aluop_o <= `EXE_SRA_OP;
									alusel_o <= `EXE_RES_SHIFT;		
									reg1_read_o <= 1'b1;	reg2_read_o <= 1'b1;
									instvalid <= `InstValid;			
								end			
								`EXE_SYNC: begin
									wreg_o <= `WriteDisable;		aluop_o <= `EXE_NOP_OP;
									alusel_o <= `EXE_RES_NOP;		
									reg1_read_o <= 1'b0;	reg2_read_o <= 1'b1;
									instvalid <= `InstValid;	
								end

								`EXE_MFHI: begin	//NEW
									wreg_o <= `WriteEnable;		aluop_o <= `EXE_MFHI_OP;
									alusel_o <= `EXE_RES_MOVE;   
									reg1_read_o <= 1'b0;	reg2_read_o <= 1'b0;
									instvalid <= `InstValid;	
								end
								`EXE_MFLO: begin
									wreg_o <= `WriteEnable;		aluop_o <= `EXE_MFLO_OP;
									alusel_o <= `EXE_RES_MOVE;   
									reg1_read_o <= 1'b0;	reg2_read_o <= 1'b0;
									instvalid <= `InstValid;	
								end
								`EXE_MTHI: begin
									wreg_o <= `WriteDisable;		aluop_o <= `EXE_MTHI_OP;
									reg1_read_o <= 1'b1;	reg2_read_o <= 1'b0; 
									instvalid <= `InstValid;	
								end
								`EXE_MTLO: begin
									wreg_o <= `WriteDisable;		aluop_o <= `EXE_MTLO_OP;
									reg1_read_o <= 1'b1;	reg2_read_o <= 1'b0; 
									instvalid <= `InstValid;	
								end
								`EXE_MOVN: begin	
									aluop_o <= `EXE_MOVN_OP;
									alusel_o <= `EXE_RES_MOVE;   
									reg1_read_o <= 1'b1;	reg2_read_o <= 1'b1;
									instvalid <= `InstValid;
								 	if(reg2_o != `ZeroWord) begin
	 									wreg_o <= `WriteEnable;
	 								end 
									else begin
	 									wreg_o <= `WriteDisable;
	 								end
								end
								`EXE_MOVZ: begin	//NEW
									aluop_o <= `EXE_MOVZ_OP;
									alusel_o <= `EXE_RES_MOVE;   
									reg1_read_o <= 1'b1;	reg2_read_o <= 1'b1;
									instvalid <= `InstValid;
								 	if(reg2_o == `ZeroWord) begin
	 									wreg_o <= `WriteEnable;
	 								end 
									else begin
	 									wreg_o <= `WriteDisable;
	 								end		  							
								end
								`EXE_SLT:  begin 
									wreg_o <= `WriteEnable;		aluop_o <= `EXE_SLT_OP;
									alusel_o <= `EXE_RES_ARITHMETIC;		
									reg1_read_o <= 1'b1;	reg2_read_o <= 1'b1;
									instvalid <= `InstValid;	
								end
								`EXE_SLTU: begin
									wreg_o <= `WriteEnable;		aluop_o <= `EXE_SLTU_OP;
									alusel_o <= `EXE_RES_ARITHMETIC;		
									reg1_read_o <= 1'b1;	reg2_read_o <= 1'b1;
									instvalid <= `InstValid;	
								end
								`EXE_ADD:  begin
									wreg_o <= `WriteEnable;		aluop_o <= `EXE_ADD_OP;
									alusel_o <= `EXE_RES_ARITHMETIC;		
									reg1_read_o <= 1'b1;	reg2_read_o <= 1'b1;
									instvalid <= `InstValid;	
								end
								`EXE_ADDU: begin
									wreg_o <= `WriteEnable;		aluop_o <= `EXE_ADDU_OP;
									alusel_o <= `EXE_RES_ARITHMETIC;		
									reg1_read_o <= 1'b1;	reg2_read_o <= 1'b1;
									instvalid <= `InstValid;	
								end
								`EXE_SUB:  begin
									wreg_o <= `WriteEnable;		aluop_o <= `EXE_SUB_OP;
									alusel_o <= `EXE_RES_ARITHMETIC;		
									reg1_read_o <= 1'b1;	reg2_read_o <= 1'b1;
									instvalid <= `InstValid;	
								end
								`EXE_SUBU: begin
									wreg_o <= `WriteEnable;		aluop_o <= `EXE_SUBU_OP;
									alusel_o <= `EXE_RES_ARITHMETIC;		
									reg1_read_o <= 1'b1;	reg2_read_o <= 1'b1;
									instvalid <= `InstValid;	
								end
								`EXE_MULT: begin
									wreg_o <= `WriteDisable;		aluop_o <= `EXE_MULT_OP;
									reg1_read_o <= 1'b1;	reg2_read_o <= 1'b1; 
									instvalid <= `InstValid;	
								end
								`EXE_MULTU: begin
									wreg_o <= `WriteDisable;		aluop_o <= `EXE_MULTU_OP;
									reg1_read_o <= 1'b1;	reg2_read_o <= 1'b1; 
									instvalid <= `InstValid;	
								end 
								
								`EXE_DIV: begin
									wreg_o <= `WriteDisable;		aluop_o <= `EXE_DIV_OP;
									reg1_read_o <= 1'b1;	reg2_read_o <= 1'b1; 
									instvalid <= `InstValid;	
								end
								`EXE_DIVU: begin
									wreg_o <= `WriteDisable;		aluop_o <= `EXE_DIVU_OP;
									reg1_read_o <= 1'b1;	reg2_read_o <= 1'b1; 
									instvalid <= `InstValid;	
								end	
								
								`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;	//这个会返给PC
									branch_flag_o <= `Branch;
									next_inst_in_delayslot_o <= `InDelaySlot;
									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;
									wd_o <= inst_i[15:11];
									link_addr_o <= pc_plus_8;
									branch_target_address_o <= reg1_o;	
									branch_flag_o <= `Branch;
									next_inst_in_delayslot_o <= `InDelaySlot;
									instvalid <= `InstValid;	
								end									
														
								default:	begin
								end
							endcase
						end
						default: begin
						end
					endcase	
				end
				
				//这几个写入的寄存器不同,所以单独赋值wd_o
				`EXE_ORI:	begin           //ORI指令 用立即数和rs计算后写入rt
					alusel_o    <= `EXE_RES_LOGIC;
					aluop_o 	   <= `EXE_OR_OP;
					wreg_o      <= `WriteEnable;
					wd_o        <= inst_i[20:16];	//立即数与rs的结果写入rt
					imm         <= {16'h0,inst_i[15:0]};
					reg1_read_o <= 1'b1;				//要去读一个rs
					reg2_read_o <= 1'b0;
					instvalid 	<= `InstValid;
				end 

				`EXE_ANDI:			begin
					wreg_o <= `WriteEnable;		aluop_o <= `EXE_AND_OP;
					alusel_o <= `EXE_RES_LOGIC;	
					reg1_read_o <= 1'b1;	reg2_read_o <= 1'b0;	  	
					imm <= {16'h0, inst_i[15:0]};		
					wd_o <= inst_i[20:16];		  	
					instvalid <= `InstValid;	
				end
				
				`EXE_XORI:			begin
					wreg_o <= `WriteEnable;		aluop_o <= `EXE_XOR_OP;
					alusel_o <= `EXE_RES_LOGIC;	
					reg1_read_o <= 1'b1;	reg2_read_o <= 1'b0;	  	
					imm <= {16'h0, inst_i[15:0]};		
					wd_o <= inst_i[20:16];		  	
					instvalid <= `InstValid;	
				end
				
				`EXE_LUI:			begin
					wreg_o <= `WriteEnable;		aluop_o <= `EXE_OR_OP;
					alusel_o <= `EXE_RES_LOGIC; 
					reg1_read_o <= 1'b1;	reg2_read_o <= 1'b0;	  	
					imm <= {inst_i[15:0], 16'h0};		
					wd_o <= inst_i[20:16];		  	
					instvalid <= `InstValid;	
				end	
				
				`EXE_PREF:			begin
					wreg_o <= `WriteDisable;		aluop_o <= `EXE_NOP_OP;
					alusel_o <= `EXE_RES_NOP; 
					reg1_read_o <= 1'b0;	reg2_read_o <= 1'b0;	  	  	
					instvalid <= `InstValid;	
				end	

				`EXE_SLTI:			begin
					wreg_o <= `WriteEnable;		aluop_o <= `EXE_SLT_OP;
					alusel_o <= `EXE_RES_ARITHMETIC; 
					reg1_read_o <= 1'b1;	reg2_read_o <= 1'b0;	  	
					imm <= {{16{inst_i[15]}}, inst_i[15:0]};		
					wd_o <= inst_i[20:16];		  	
					instvalid <= `InstValid;	
				end
				
				`EXE_SLTIU:			begin
					wreg_o <= `WriteEnable;		aluop_o <= `EXE_SLTU_OP;
					alusel_o <= `EXE_RES_ARITHMETIC; 
					reg1_read_o <= 1'b1;	reg2_read_o <= 1'b0;	  	
					imm <= {{16{inst_i[15]}}, inst_i[15:0]};		
					wd_o <= inst_i[20:16];		  	
					instvalid <= `InstValid;	
				end
				
				`EXE_ADDI:			begin
		  		wreg_o <= `WriteEnable;		
				aluop_o <= `EXE_ADDI_OP;
		  		alusel_o <= `EXE_RES_ARITHMETIC; 
				reg1_read_o <= 1'b1;	reg2_read_o <= 1'b0;	  	
					imm <= {{16{inst_i[15]}}, inst_i[15:0]};		
					wd_o <= inst_i[20:16];		  	
					instvalid <= `InstValid;	
				end
				
				`EXE_ADDIU:			begin
					wreg_o <= `WriteEnable;		
					aluop_o <= `EXE_ADDIU_OP;
					alusel_o <= `EXE_RES_ARITHMETIC; 
					reg1_read_o <= 1'b1;	reg2_read_o <= 1'b0;	  	
					imm <= {{16{inst_i[15]}}, inst_i[15:0]};		
					wd_o <= inst_i[20:16];		  	
					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;
					next_inst_in_delayslot_o <= `InDelaySlot;		  	
					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;			//$31
					link_addr_o <= pc_plus_8 ;
					branch_target_address_o <= {pc_plus_4[31:28], inst_i[25:0], 2'b00};
					branch_flag_o <= `Branch;
					next_inst_in_delayslot_o <= `InDelaySlot;		  	
					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;
						next_inst_in_delayslot_o <= `InDelaySlot;		  	
					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;
						next_inst_in_delayslot_o <= `InDelaySlot;		  	
					end
				end
				`EXE_BLEZ:			begin
					wreg_o <= `WriteDisable;		aluop_o <= `EXE_BLEZ_OP;
					alusel_o <= `EXE_RES_JUMP_BRANCH; 
					reg1_read_o <= 1'b1;	reg2_read_o <= 1'b0;
					instvalid <= `InstValid;	
					if((reg1_o[31] == 1'b1) || (reg1_o == `ZeroWord)) begin
						branch_target_address_o <= pc_plus_4 + imm_sll2_signedext;
						branch_flag_o <= `Branch;
						next_inst_in_delayslot_o <= `InDelaySlot;		  	
					end
				end
				`EXE_BNE:			begin
					wreg_o <= `WriteDisable;		aluop_o <= `EXE_BLEZ_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;
						next_inst_in_delayslot_o <= `InDelaySlot;		  	
					end
				end
				`EXE_REGIMM_INST:		begin
					case (op4)
						`EXE_BGEZ:	begin
							wreg_o <= `WriteDisable;		aluop_o <= `EXE_BGEZ_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) begin
								branch_target_address_o <= pc_plus_4 + imm_sll2_signedext;
								branch_flag_o <= `Branch;
								next_inst_in_delayslot_o <= `InDelaySlot;		  	
			   			end
						end
						`EXE_BGEZAL:		begin
							wreg_o <= `WriteEnable;		aluop_o <= `EXE_BGEZAL_OP;
							alusel_o <= `EXE_RES_JUMP_BRANCH; 
							reg1_read_o <= 1'b1;	reg2_read_o <= 1'b0;
							link_addr_o <= pc_plus_8; 
							wd_o <= 5'b11111;  	instvalid <= `InstValid;
							if(reg1_o[31] == 1'b0) begin
								branch_target_address_o <= pc_plus_4 + imm_sll2_signedext;
								branch_flag_o <= `Branch;
								next_inst_in_delayslot_o <= `InDelaySlot;
			   			end
						end
						`EXE_BLTZ:		begin
							wreg_o <= `WriteDisable;		aluop_o <= `EXE_BGEZAL_OP;
							alusel_o <= `EXE_RES_JUMP_BRANCH; 
							reg1_read_o <= 1'b1;	reg2_read_o <= 1'b0;
							instvalid <= `InstValid;	
							if(reg1_o[31] == 1'b1) begin
								branch_target_address_o <= pc_plus_4 + imm_sll2_signedext;
								branch_flag_o <= `Branch;
								next_inst_in_delayslot_o <= `InDelaySlot;		  	
			   			end
						end
						`EXE_BLTZAL:		begin
							wreg_o <= `WriteEnable;		aluop_o <= `EXE_BGEZAL_OP;
							alusel_o <= `EXE_RES_JUMP_BRANCH; 
							reg1_read_o <= 1'b1;	reg2_read_o <= 1'b0;
							link_addr_o <= pc_plus_8;	
							wd_o <= 5'b11111; instvalid <= `InstValid;
							if(reg1_o[31] == 1'b1) begin
								branch_target_address_o <= pc_plus_4 + imm_sll2_signedext;
								branch_flag_o <= `Branch;
								next_inst_in_delayslot_o <= `InDelaySlot;
			   			end
						end
						default:	begin
						end
					endcase
				end	
				
				`EXE_SPECIAL2_INST:		begin
					case ( op3 )
						`EXE_CLZ:		begin
							wreg_o <= `WriteEnable;		aluop_o <= `EXE_CLZ_OP;
							alusel_o <= `EXE_RES_ARITHMETIC; reg1_read_o <= 1'b1;	reg2_read_o <= 1'b0;	  	
							instvalid <= `InstValid;	
						end
						`EXE_CLO:		begin
							wreg_o <= `WriteEnable;		aluop_o <= `EXE_CLO_OP;
							alusel_o <= `EXE_RES_ARITHMETIC; reg1_read_o <= 1'b1;	reg2_read_o <= 1'b0;	  	
							instvalid <= `InstValid;	
						end
						`EXE_MUL:		begin
							wreg_o <= `WriteEnable;		aluop_o <= `EXE_MUL_OP;
							alusel_o <= `EXE_RES_MUL; reg1_read_o <= 1'b1;	reg2_read_o <= 1'b1;	
							instvalid <= `InstValid;	  			
						end
						
						`EXE_MADD:		begin
							wreg_o <= `WriteDisable;		aluop_o <= `EXE_MADD_OP;
							alusel_o <= `EXE_RES_MUL; reg1_read_o <= 1'b1;	reg2_read_o <= 1'b1;	  			
							instvalid <= `InstValid;	
						end
						`EXE_MADDU:		begin
							wreg_o <= `WriteDisable;		aluop_o <= `EXE_MADDU_OP;
							alusel_o <= `EXE_RES_MUL; reg1_read_o <= 1'b1;	reg2_read_o <= 1'b1;	  			
							instvalid <= `InstValid;	
						end
						`EXE_MSUB:		begin
							wreg_o <= `WriteDisable;		aluop_o <= `EXE_MSUB_OP;
							alusel_o <= `EXE_RES_MUL; reg1_read_o <= 1'b1;	reg2_read_o <= 1'b1;	  			
							instvalid <= `InstValid;	
						end
						`EXE_MSUBU:		begin
							wreg_o <= `WriteDisable;		aluop_o <= `EXE_MSUBU_OP;
							alusel_o <= `EXE_RES_MUL; reg1_read_o <= 1'b1;	reg2_read_o <= 1'b1;	  			
							instvalid <= `InstValid;	
						end							
						
						
						
						default:;
					endcase      //EXE_SPECIAL_INST2 case
				end				
				default:;			
		  endcase
		  
		  //sll、srl、sra	把移位数给到imm,作为1个源操作数
		  if(inst_i[31:21] == 11'b00000000000) begin	//新的位段判断指令
				if (op3 == `EXE_SLL) begin
					wreg_o <= `WriteEnable;		aluop_o <= `EXE_SLL_OP;
					alusel_o <= `EXE_RES_SHIFT; reg1_read_o <= 1'b0;	reg2_read_o <= 1'b1;	  	
					imm[4:0] <= inst_i[10:6];		wd_o <= inst_i[15:11];
					instvalid <= `InstValid;	
				end 
				else if ( op3 == `EXE_SRL ) begin
					wreg_o <= `WriteEnable;		aluop_o <= `EXE_SRL_OP;
					alusel_o <= `EXE_RES_SHIFT; reg1_read_o <= 1'b0;	reg2_read_o <= 1'b1;	  	
					imm[4:0] <= inst_i[10:6];		wd_o <= inst_i[15:11];
					instvalid <= `InstValid;	
				end 
				else if ( op3 == `EXE_SRA ) begin
					wreg_o <= `WriteEnable;		aluop_o <= `EXE_SRA_OP;
					alusel_o <= `EXE_RES_SHIFT; reg1_read_o <= 1'b0;	reg2_read_o <= 1'b1;	  	
					imm[4:0] <= inst_i[10:6];		wd_o <= inst_i[15:11];
					instvalid <= `InstValid;	
				end
		  end			  
	  
		end       
	       
	
	//确定2个源操作数
	always@(*)
		if(rst == `RstEnable)
			reg1_o <= `ZeroWord;
		else if((reg1_read_o == 1'b1)&&(ex_wreg_i == 1'b1)&&(reg1_addr_o == ex_wd_i))//前堆
			reg1_o <= ex_wdata_i;
		else if((reg1_read_o == 1'b1)&&(mem_wreg_i == 1'b1)&&(reg1_addr_o == mem_wd_i))//前堆
			reg1_o <= mem_wdata_i;		
		else if(reg1_read_o == 1'b1)
			reg1_o <= reg1_data_i;
		else if(reg1_read_o == 1'b0)
			reg1_o <= imm;
		else
			reg1_o <= `ZeroWord;
		
	always@(*)
		if(rst == `RstEnable)
			reg2_o <= `ZeroWord;
		else if((reg2_read_o == 1'b1)&&(ex_wreg_i == 1'b1)&&(reg2_addr_o == ex_wd_i))//前堆
			reg2_o <= ex_wdata_i;
		else if((reg2_read_o == 1'b1)&&(mem_wreg_i == 1'b1)&&(reg2_addr_o == mem_wd_i))//前堆
			reg2_o <= mem_wdata_i;				
		else if(reg2_read_o == 1'b1)
			reg2_o <= reg2_data_i;
		else if(reg2_read_o == 1'b0)
			reg2_o <= imm;
		else
			reg2_o <= `ZeroWord;

endmodule

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

`include "defines.v"

module id_ex(

	input wire					  clk,
	input wire					  rst,

	//从译码阶段传递的信息
	input wire[`AluOpBus]       id_aluop,	//[7:0]
	input wire[`AluSelBus]      id_alusel,	//[2:0]
	input wire[`RegBus]         id_reg1,
	input wire[`RegBus]         id_reg2,
	input wire[`RegAddrBus]     id_wd,
	input wire                  id_wreg,	
	input wire[`RegBus]         id_link_address,	//处于译码阶段的转移指令要保存的返回地址
	input wire                  id_is_in_delayslot,	//当前处于译码阶段的指令是否位于延迟槽
	input wire                  next_inst_in_delayslot_i, //下一条进入译码阶段的指令是否位于延迟槽

	//来自控制模块的
	input wire[5:0]				 stall,

	//传递到执行阶段的
	output reg[`AluOpBus]       ex_aluop,
	output reg[`AluSelBus]      ex_alusel,
	output reg[`RegBus]         ex_reg1,
	output reg[`RegBus]         ex_reg2,
	output reg[`RegAddrBus]     ex_wd,
	output reg                  ex_wreg,
	output reg[`RegBus]         ex_link_address,		//处于执行阶段的转移指令要保存的返回地址
	output reg                  ex_is_in_delayslot,	//当前处于执行阶段的指令是否位于延迟槽
	output reg                  is_in_delayslot_o		//当前译码阶段的指令是否位于延迟槽
	
);
	//打一拍传过去
	//1.当stall[2]为stop,stall[3]为nostop,表示译码阶段暂停,执行阶段继续
	//  使用空指令作为下一个周期进入执行阶段的指令
	//2.当stall[2]为nostop,译码阶段继续,译码后的指令进入执行阶段
	//3.其余情况,保持不变
	always @ (posedge clk) begin
		if (rst == `RstEnable) begin
			ex_aluop  <= `EXE_NOP_OP;
			ex_alusel <= `EXE_RES_NOP;
			ex_reg1   <= `ZeroWord;
			ex_reg2   <= `ZeroWord;
			ex_wd     <= `NOPRegAddr;
			ex_wreg   <= `WriteDisable;
			ex_link_address <= `ZeroWord;
			ex_is_in_delayslot <= `NotInDelaySlot;
			is_in_delayslot_o <= `NotInDelaySlot;
		end 
		else if(stall[2] == `Stop && stall[3] == `NoStop) begin
			ex_aluop  <= `EXE_NOP_OP;
			ex_alusel <= `EXE_RES_NOP;
			ex_reg1 	 <= `ZeroWord;
			ex_reg2   <= `ZeroWord;
			ex_wd 	 <= `NOPRegAddr;
			ex_wreg 	 <= `WriteDisable;
			ex_link_address <= `ZeroWord;
			ex_is_in_delayslot <= `NotInDelaySlot;			
		end 
		else if(stall[2] == `NoStop) begin		
			ex_aluop  <= id_aluop;
			ex_alusel <= id_alusel;
			ex_reg1 	 <= id_reg1;
			ex_reg2 	 <= id_reg2;
			ex_wd 	 <= id_wd;
			ex_wreg   <= id_wreg;	
			ex_link_address <= id_link_address;
			ex_is_in_delayslot <= id_is_in_delayslot;
			is_in_delayslot_o <= next_inst_in_delayslot_i;	
		end
	end
	
endmodule

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值