异常相关指令的实现

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我们使用术语自陷(trap)来指当被一个异常条件引起的事件发生在一个 RISC-V 的线程里的时候,同步地把控制权传输给管理员环境
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

`include "defines.v"

module pc_reg(

	input  wire					   clk,
	input  wire					   rst,
	//来自控制模块的信息
	input wire[5:0]            stall,
	input wire                 flush,		//流水线清除信号
	input wire[`RegBus]        new_pc,		//异常处理例程入口地址
	
	//来自译码阶段的信息
	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 begin
			if(flush == 1'b1) begin	//输入信号为1表示异常发生,将从CTRL模块给出的异常
				pc <= new_pc;			//处理例程入口地址new_pc处取值执行
			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	
	end
	
endmodule

在这里插入图片描述

`include "defines.v"

module if_id(
	input wire clk,
	input wire rst,
	input wire [`InstBus] 		if_inst,	//InstBus为ROM数据宽度,同样为31:0
	input wire[`InstAddrBus]	if_pc  ,	//ROM地址总线宽度 31:0
	
	//来自控制模块的信息	
	input wire[5:0]            stall,
	input wire                 flush,	
	
	output reg [`InstBus] 		id_inst,
	output reg[`InstAddrBus]   id_pc  
	
);

	//复位有效 输出为32位的0;否则则寄存传递来的取指指令地址和指令
	//1.当stall[1]为stop,stall[2]为nostop,表示取指阶段暂停,译码阶段继续
	//  使用空指令作为下一个周期进入译码阶段的指令
	//2.当stall[1]为nostop,取指阶段继续,取得的指令进入译码阶段
	//3.其余情况,保持不变
	always @ (posedge clk) begin
		if (rst == `RstEnable) begin
			id_pc   <= `ZeroWord;
			id_inst <= `ZeroWord;
		end
		else if(flush == 1'b1 ) begin	//发生异常 清除流水线
			id_pc   <= `ZeroWord;
			id_inst <= `ZeroWord;					
		end	
		else if(stall[1] == `Stop && stall[2] == `NoStop) begin
			id_pc   <= `ZeroWord;
			id_inst <= `ZeroWord;	
	   end 
	   else if(stall[1] == `NoStop) begin
		  id_pc   <= if_pc;
		  id_inst <= if_inst;
		end
	end
			
endmodule

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

`include "defines.v"

module id_ex(

	input wire					  clk,
	input wire					  rst,
	input wire                flush,			//流水线消除信号

	//从译码阶段传递的信息
	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[`RegBus]         id_current_inst_address,	//译码阶段指令地址
	input wire[31:0]            id_excepttype,				//译码阶段异常信息
	
	//当前处于译码阶段的指令
	input wire[`RegBus]         id_inst,	
	
	//来自控制模块的
	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,		//当前译码阶段的指令是否位于延迟槽
	output reg[31:0]            ex_excepttype,			//译码阶段收集到的异常信息
	output reg[`RegBus]         ex_current_inst_address,//执行阶段指令地址	
	//当前处于执行阶段的指令
	output reg[`RegBus]         ex_inst
	
);
	//打一拍传过去
	//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;
			ex_inst <= `ZeroWord;
		   ex_excepttype <= `ZeroWord;
	      ex_current_inst_address <= `ZeroWord;
		end
		else if(flush == 1'b1 ) begin	//清除流水线
			ex_aluop <= `EXE_NOP_OP;
			ex_alusel <= `EXE_RES_NOP;
			ex_reg1 <= `ZeroWord;
			ex_reg2 <= `ZeroWord;
			ex_wd <= `NOPRegAddr;
			ex_wreg <= `WriteDisable;
			ex_excepttype <= `ZeroWord;
			ex_link_address <= `ZeroWord;
			ex_inst <= `ZeroWord;
			ex_is_in_delayslot <= `NotInDelaySlot;
	      ex_current_inst_address <= `ZeroWord;	
	      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;	
			ex_inst <= `ZeroWord;
		   ex_excepttype <= `ZeroWord;
	      ex_current_inst_address <= `ZeroWord;		
		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;	
			ex_inst <= id_inst;
			ex_excepttype <= id_excepttype;
	      ex_current_inst_address <= id_current_inst_address;	
		end
	end
	
endmodule

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

`include "defines.v"

module ex_mem(

	input wire					     clk,
	input wire					     rst,
	
	//来自控制模块的信息
	input wire[5:0]				  stall,
	input wire                   flush,

  //为实现加载、访存指令而添加
   input wire[`AluOpBus]        ex_aluop,		//执行阶段的指令要进行的运算的子类型
	input wire[`RegBus]          ex_mem_addr,	//执行阶段的加载、存储指令对应的存储器地址
	input wire[`RegBus]          ex_reg2,		//执行阶段的存储指令要存储的数据或lwl/lwr要加载到的目的段寄存器原始值
	
	//来自执行阶段的信息	
	input wire[`RegAddrBus]      ex_wd,
	input wire                   ex_wreg,
	input wire[`RegBus]			  ex_wdata, 	
	input wire[`RegBus]          ex_hi,      
	input wire[`RegBus]          ex_lo,      
	input wire                   ex_whilo,
	
	//协处理器
	input wire                   ex_cp0_reg_we,
	input wire[4:0]              ex_cp0_reg_write_addr,
	input wire[`RegBus]          ex_cp0_reg_data,

	//乘累
	input wire[`DoubleRegBus]    hilo_i,	
	input wire[1:0]              cnt_i,

   input wire[31:0]             ex_excepttype,				//译码执行收集的异常信息
	input wire                   ex_is_in_delayslot,
	input wire[`RegBus]          ex_current_inst_address,	
	
	//送到访存阶段的信息
	output reg[`RegAddrBus]      mem_wd,
	output reg                   mem_wreg,
	output reg[`RegBus]			  mem_wdata,
	output reg[`RegBus]          mem_hi,     
	output reg[`RegBus]          mem_lo,     
	output reg                   mem_whilo,
	
   //为实现加载、访存指令而添加
   output reg[`AluOpBus]        mem_aluop,	//访存阶段的指令要进行的运算的子类型
	output reg[`RegBus]          mem_mem_addr,//访存阶段的加载、存储指令对应的存储器地址
	output reg[`RegBus]          mem_reg2,		//访存阶段的存储指令要存储的数据或lwl/lwr要加载到的目的段寄存器原始值

	output reg                   mem_cp0_reg_we,
	output reg[4:0]              mem_cp0_reg_write_addr,
	output reg[`RegBus]          mem_cp0_reg_data,
	
	output reg[31:0]             mem_excepttype,
   output reg                   mem_is_in_delayslot,
	output reg[`RegBus]          mem_current_inst_address,
	
	//乘累
	output reg[`DoubleRegBus]    hilo_o,
	output reg[1:0]              cnt_o	
);
	//1.当stall[3]为stop,stall[4]为nostop,表示执行阶段暂停,访存阶段继续
	//  使用空指令作为下一个周期进入访存阶段的指令
	//2.当stall[3]为nostop,执行阶段继续,执行后的指令进入访存阶段
	//3.其余情况,保持不变
	always @ (posedge clk) begin
		if(rst == `RstEnable) begin
			mem_wd    <= `NOPRegAddr;
			mem_wreg  <= `WriteDisable;
		   mem_wdata <= `ZeroWord;	
		   mem_hi 	 <= `ZeroWord;
		   mem_lo 	 <= `ZeroWord;
		   mem_whilo <= `WriteDisable;		
	      hilo_o 	 <= {`ZeroWord, `ZeroWord};
			cnt_o 	 <= 2'b00;
		  	mem_aluop <= `EXE_NOP_OP;
			mem_mem_addr <= `ZeroWord;
			mem_reg2 <= `ZeroWord;
			mem_cp0_reg_we <= `WriteDisable;
			mem_cp0_reg_write_addr <= 5'b00000;
			mem_cp0_reg_data <= `ZeroWord;
			mem_excepttype <= `ZeroWord;
			mem_is_in_delayslot <= `NotInDelaySlot;
			mem_current_inst_address <= `ZeroWord;
		end 
		else if(flush == 1'b1 ) begin
			mem_wd <= `NOPRegAddr;
			mem_wreg <= `WriteDisable;
		   mem_wdata <= `ZeroWord;
		   mem_hi <= `ZeroWord;
		   mem_lo <= `ZeroWord;
		   mem_whilo <= `WriteDisable;
			mem_aluop <= `EXE_NOP_OP;
			mem_mem_addr <= `ZeroWord;
			mem_reg2 <= `ZeroWord;
			mem_cp0_reg_we <= `WriteDisable;
			mem_cp0_reg_write_addr <= 5'b00000;
			mem_cp0_reg_data <= `ZeroWord;
			mem_excepttype <= `ZeroWord;
			mem_is_in_delayslot <= `NotInDelaySlot;
			mem_current_inst_address <= `ZeroWord;
			hilo_o <= {`ZeroWord, `ZeroWord};
			cnt_o <= 2'b00;	    	    				
		end
		else if(stall[3] == `Stop && stall[4] == `NoStop) begin
			mem_wd 	 <= `NOPRegAddr;
			mem_wreg  <= `WriteDisable;
		   mem_wdata <= `ZeroWord;
		   mem_hi 	 <= `ZeroWord;
		   mem_lo 	 <= `ZeroWord;
		   mem_whilo <= `WriteDisable;
	      hilo_o 	 <= hilo_i;
			cnt_o 	 <= cnt_i;
			mem_aluop <= `EXE_NOP_OP;
			mem_mem_addr <= `ZeroWord;
			mem_reg2 <= `ZeroWord;
			mem_cp0_reg_we <= `WriteDisable;
			mem_cp0_reg_write_addr <= 5'b00000;
			mem_cp0_reg_data <= `ZeroWord;
			mem_excepttype <= `ZeroWord;
			mem_is_in_delayslot <= `NotInDelaySlot;
			mem_current_inst_address <= `ZeroWord;			
		end 
		else if(stall[3] == `NoStop) begin
			mem_wd 	 <= ex_wd;
			mem_wreg  <= ex_wreg;
			mem_wdata <= ex_wdata;	
			mem_hi 	 <= ex_hi;
			mem_lo 	 <= ex_lo;
			mem_whilo <= ex_whilo;	
	      hilo_o 	 <= {`ZeroWord, `ZeroWord};
			cnt_o 	 <= 2'b00;
		  	mem_aluop <= ex_aluop;
			mem_mem_addr <= ex_mem_addr;
			mem_reg2 <= ex_reg2;
			mem_cp0_reg_we <= ex_cp0_reg_we;
			mem_cp0_reg_write_addr <= ex_cp0_reg_write_addr;
			mem_cp0_reg_data <= ex_cp0_reg_data;
			mem_excepttype <= ex_excepttype;
			mem_is_in_delayslot <= ex_is_in_delayslot;
			mem_current_inst_address <= ex_current_inst_address;	
		end 
		else begin
	      hilo_o 	 <= hilo_i;
			cnt_o 	 <= cnt_i;											
		end  
	end       
			
endmodule

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

`include "defines.v"

module mem_wb(

	input	wire				  			clk,
	input wire				      	rst,
	
  //来自控制模块的信息
	input wire[5:0]               stall,
	input wire                    flush,
	
	//来自访存阶段的信息	
	input wire[`RegAddrBus]       mem_wd,
	input wire                    mem_wreg,
	input wire[`RegBus]			 	mem_wdata,
	input wire[`RegBus]           mem_hi,
	input wire[`RegBus]           mem_lo,
	input wire                    mem_whilo,

	input wire                    mem_LLbit_we,		//访存阶段指令是否要写LLbit
	input wire                    mem_LLbit_value,	//值
	
	input wire                    mem_cp0_reg_we,
	input wire[4:0]               mem_cp0_reg_write_addr,
	input wire[`RegBus]           mem_cp0_reg_data,	

	//送到回写阶段的信息
	output reg[`RegAddrBus]       wb_wd,
	output reg                    wb_wreg,
	output reg[`RegBus]			   wb_wdata,
	output reg[`RegBus]           wb_hi,
	output reg[`RegBus]           wb_lo,
	output reg                    wb_whilo,
	
	output reg                    wb_LLbit_we,		//回写阶段的指令是否要写LLbit
	output reg                    wb_LLbit_value,	//值
	
	output reg                    wb_cp0_reg_we,
	output reg[4:0]               wb_cp0_reg_write_addr,
	output reg[`RegBus]           wb_cp0_reg_data
	
);
	//1.当stall[4]为stop,stall[5]为nostop,表示访存阶段暂停,回写阶段继续
	//  使用空指令作为下一个周期进入回写阶段的指令
	//2.当stall[4]为nostop,访存阶段继续,访存后的指令进入回写阶段
	//3.其余情况,保持不变
	always @ (posedge clk) begin
		if(rst == `RstEnable) begin
			wb_wd <= `NOPRegAddr;
			wb_wreg <= `WriteDisable;
		   wb_wdata <= `ZeroWord;	
		   wb_hi <= `ZeroWord;
		   wb_lo <= `ZeroWord;
		   wb_whilo <= `WriteDisable;
			wb_LLbit_we <= 1'b0;
		   wb_LLbit_value <= 1'b0;
			wb_cp0_reg_we <= `WriteDisable;
			wb_cp0_reg_write_addr <= 5'b00000;
			wb_cp0_reg_data <= `ZeroWord;	
		end
		else if(flush == 1'b1 ) begin
			wb_wd <= `NOPRegAddr;
			wb_wreg <= `WriteDisable;
		   wb_wdata <= `ZeroWord;
		   wb_hi <= `ZeroWord;
		   wb_lo <= `ZeroWord;
		   wb_whilo <= `WriteDisable;
		   wb_LLbit_we <= 1'b0;
		   wb_LLbit_value <= 1'b0;	
			wb_cp0_reg_we <= `WriteDisable;
			wb_cp0_reg_write_addr <= 5'b00000;
			wb_cp0_reg_data <= `ZeroWord;				  				  	  	
		end	
		else if(stall[4] == `Stop && stall[5] == `NoStop) begin
			wb_wd <= `NOPRegAddr;
			wb_wreg <= `WriteDisable;
		   wb_wdata <= `ZeroWord;
		   wb_hi <= `ZeroWord;
		   wb_lo <= `ZeroWord;
		   wb_whilo <= `WriteDisable;	
		   wb_LLbit_we <= 1'b0;
		   wb_LLbit_value <= 1'b0;
			wb_cp0_reg_we <= `WriteDisable;
			wb_cp0_reg_write_addr <= 5'b00000;
			wb_cp0_reg_data <= `ZeroWord;			
		end 
		else if(stall[4] == `NoStop) begin	//判断访存阶段是否暂停
			wb_wd <= mem_wd;
			wb_wreg <= mem_wreg;
			wb_wdata <= mem_wdata;
			wb_hi <= mem_hi;
			wb_lo <= mem_lo;
			wb_whilo <= mem_whilo;
		   wb_LLbit_we <= mem_LLbit_we;
		   wb_LLbit_value <= mem_LLbit_value;
			wb_cp0_reg_we <= mem_cp0_reg_we;
			wb_cp0_reg_write_addr <= mem_cp0_reg_write_addr;
			wb_cp0_reg_data <= mem_cp0_reg_data;			
		end   
	end      
			
endmodule

在这里插入图片描述

`include "defines.v"

module cp0_reg(

	input	wire							clk,
	input wire							rst,
	
	
	input wire                    we_i,			//是否要写CP0的寄存器
	input wire[4:0]               waddr_i,		//要写寄存器的地址
	input wire[4:0]               raddr_i,		//要读取寄存器的地址
	input wire[`RegBus]           data_i,		//要写入的数据
	input wire[31:0]              excepttype_i,	
	input wire[5:0]               int_i,		//6个外部硬件中断的输入
	input wire[`RegBus]           current_inst_addr_i,
	input wire                    is_in_delayslot_i,
	
	//相关寄存器的值
	output reg[`RegBus]       	   data_o,		//读出的值
	output reg[`RegBus]           count_o,		
	output reg[`RegBus]           compare_o,	
	output reg[`RegBus]           status_o,	
	output reg[`RegBus]           cause_o,		
	output reg[`RegBus]           epc_o,
	output reg[`RegBus]           config_o,
	output reg[`RegBus]           prid_o,
	
	//是否有定时中断发生
	output reg                    timer_int_o    
	
);

	//第一段:对CP0中寄存器的写操作
	always @ (posedge clk) begin
		if(rst == `RstEnable) begin
			count_o   <= `ZeroWord;	
			compare_o <= `ZeroWord;	
			
			//status寄存器的CU为0001,表示协处理器CP0存在
			status_o  <= 32'b00010000000000000000000000000000;
			cause_o   <= `ZeroWord;
			epc_o 	 <= `ZeroWord;
			
			//config寄存器的BE为1,表示Big-Endian;MT为00,表示没有MMU
			config_o <= 32'b00000000000000001000000000000000;
			
			//制作者是L,对应的是0x48,类型是0x1,基本类型,版本号是1.0	
			prid_o <= 32'b00000000010011000000000100000010;
			timer_int_o <= `InterruptNotAssert;
		end 
		
		else begin
			count_o <= count_o + 1 ;	//每个时钟周期自加1
			cause_o[15:10] <= int_i;	//cause[15:11]保存外部中断声明
			
			//当comepare不为0且count值为compare时
			//将输出信号timer_int_o置为1,表示时钟中断发生
			if(compare_o != `ZeroWord && count_o == compare_o) begin
				timer_int_o <= `InterruptAssert;
			end
					
			if(we_i == `WriteEnable) 	begin
				case (waddr_i) 
					`CP0_REG_COUNT:		begin	//写count寄存器
						count_o <= data_i;
					end
					`CP0_REG_COMPARE:		begin	//写compare寄存器
						compare_o <= data_i;
						timer_int_o <= `InterruptNotAssert;
					end
					`CP0_REG_STATUS:	begin		//写state寄存器
						status_o <= data_i;
					end
					`CP0_REG_EPC:	begin			//写EPC寄存器
						epc_o <= data_i;
					end
					`CP0_REG_CAUSE:	begin		//写cause寄存器
					  //cause寄存器只有IP[1:0]、IV、WP字段是可写的
						cause_o[9:8] <= data_i[9:8];
						cause_o[23]  <= data_i[23];
						cause_o[22]  <= data_i[22];
					end					
				endcase  
			end
			
			case (excepttype_i)
				32'h00000001:		begin		//外部中断
					if(is_in_delayslot_i == `InDelaySlot ) begin
						epc_o <= current_inst_addr_i - 4 ;
						cause_o[31] <= 1'b1;
					end else begin
					  epc_o <= current_inst_addr_i;
					  cause_o[31] <= 1'b0;
					end
					status_o[1] <= 1'b1;
					cause_o[6:2] <= 5'b00000;
					
				end
				32'h00000008:		begin		//syscall
					if(status_o[1] == 1'b0) begin
						if(is_in_delayslot_i == `InDelaySlot ) begin
							epc_o <= current_inst_addr_i - 4 ;
							cause_o[31] <= 1'b1;
						end else begin
					  	epc_o <= current_inst_addr_i;
					  	cause_o[31] <= 1'b0;
						end
					end
					status_o[1] <= 1'b1;
					cause_o[6:2] <= 5'b01000;			
				end
				32'h0000000a:		begin		//无效指令
					if(status_o[1] == 1'b0) begin
						if(is_in_delayslot_i == `InDelaySlot ) begin
							epc_o <= current_inst_addr_i - 4 ;
							cause_o[31] <= 1'b1;
						end else begin
					  	epc_o <= current_inst_addr_i;
					  	cause_o[31] <= 1'b0;
						end
					end
					status_o[1] <= 1'b1;
					cause_o[6:2] <= 5'b01010;					
				end
				32'h0000000d:		begin		//自陷异常
					if(status_o[1] == 1'b0) begin
						if(is_in_delayslot_i == `InDelaySlot ) begin
							epc_o <= current_inst_addr_i - 4 ;
							cause_o[31] <= 1'b1;
						end else begin
					  	epc_o <= current_inst_addr_i;
					  	cause_o[31] <= 1'b0;
						end
					end
					status_o[1] <= 1'b1;
					cause_o[6:2] <= 5'b01101;					
				end
				32'h0000000c:		begin		//溢出异常
					if(status_o[1] == 1'b0) begin
						if(is_in_delayslot_i == `InDelaySlot ) begin
							epc_o <= current_inst_addr_i - 4 ;
							cause_o[31] <= 1'b1;
						end else begin
					  	epc_o <= current_inst_addr_i;
					  	cause_o[31] <= 1'b0;
						end
					end
					status_o[1] <= 1'b1;
					cause_o[6:2] <= 5'b01100;					
				end				
				32'h0000000e:   begin		//eret
					status_o[1] <= 1'b0;
				end
				default:				begin
				end
			endcase	
					
		end   
	end      
	
	//第二段:对cp0寄存器的读操作
	always @ (*) begin
		if(rst == `RstEnable) begin
			data_o <= `ZeroWord;
		end 
		else begin
				case (raddr_i) 
					`CP0_REG_COUNT:	begin
						data_o <= count_o ;
					end
					`CP0_REG_COMPARE:	begin
						data_o <= compare_o ;
					end
					`CP0_REG_STATUS:	begin
						data_o <= status_o ;
					end
					`CP0_REG_CAUSE:	begin
						data_o <= cause_o ;
					end
					`CP0_REG_EPC:	begin
						data_o <= epc_o ;
					end
					`CP0_REG_PrId:	begin
						data_o <= prid_o ;
					end
					`CP0_REG_CONFIG:	begin
						data_o <= config_o ;
					end	
					default: 	begin
					end			
				endcase  	
		end    
	end      
endmodule

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

`include "defines.v"

module ctrl(

	input wire						  rst,
	input wire[31:0]             excepttype_i,
	input wire[`RegBus]          cp0_epc_i,			//epc最新值
	input wire                   stallreq_from_id,
	input wire                   stallreq_from_ex,
	
	output reg[`RegBus]          new_pc,
	output reg                   flush,
	output reg[5:0]              stall       
	
);

	always @ (*) begin
		if(rst == `RstEnable) begin
			stall <= 6'b000000;
			flush <= 1'b0;
			new_pc <= `ZeroWord;
		end 
		else if(excepttype_i != `ZeroWord) begin	//不为0 表示发生异常
		   flush <= 1'b1;
		   stall <= 6'b000000;
			case (excepttype_i)
				32'h00000001:		begin   //interrupt
					new_pc <= 32'h00000020;
				end
				32'h00000008:		begin   //syscall
					new_pc <= 32'h00000040;
				end
				32'h0000000a:		begin   //inst_invalid
					new_pc <= 32'h00000040;
				end
				32'h0000000d:		begin   //trap
					new_pc <= 32'h00000040;
				end
				32'h0000000c:		begin   //ov
					new_pc <= 32'h00000040;
				end
				32'h0000000e:		begin   //eret
					new_pc <= cp0_epc_i;
				end
				default	: begin
				end
			endcase 						
		end 
		else if(stallreq_from_ex == `Stop) begin
			stall <= 6'b001111;
			flush <= 1'b0;		
		end 
		else if(stallreq_from_id == `Stop) begin
			stall <= 6'b000111;	
			flush <= 1'b0;		
		end 
		else begin
			stall <= 6'b000000;
			flush <= 1'b0;
			new_pc <= `ZeroWord;		
		end   
	end         
			
endmodule

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Designing with Low-Level Primitives Chapter 2. Primitive Reference Primitives ................................................................................................................................................ 2–1 ALT_INBUF ...................................................................................................................................... 2–1 ALT_OUTBUF .................................................................................................................................. 2–3 ALT_OUTBUF_TRI .......................................................................................................................... 2–6 ALT_IOBUF ....................................................................................................................................... 2–8 ALT_INBUF_DIFF ......................................................................................................................... 2–11 ALT_OUTBUF_DIFF ..................................................................................................................... 2–13 ALT_OUTBUF_TRI_DIFF ............................................................................................................. 2–14 ALT_IOBUF_DIFF .......................................................................................................................... 2–19 ALT_BIDIR_DIFF ........................................................................................................................... 2–22 ALT_BIDIR_BUF ............................................................................................................................ 2–25 LCELL .............................................................................................................................................. 2–27 DFF ................................................................................................................................................... 2–28 CARRY and CARRY_SUM ........................................................................................................... 2–29 CASCADE ....................................................................................................................................... 2–30 LUT_INPUT .................................................................................................................................... 2–31 LUT_OUTPUT ................................................................................................................................ 2–32

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值