《自己动手写CPU》学习记录(10)——第7章/Part 3




目录

引言

致谢

除法指令

div、divu

 试商法设计思路

思路详述

除法模块设计

除法模块仿真

TEST BENCH

仿真结果

除法运算加入指令集

宏定义

译码模块

执行模块

测试

测试程序

测试结果


引言

随章节进度继续推进,本章继续实现 32位整数除法 指令等其他操作指令。

致谢

感谢书籍《自己动手写CPU》及其作者雷思磊。一并感谢开源精神。



除法指令

div、divu

该两条指令均为 SPECIAL ,第6~15位为 0 。需要根据低六位判断功能。

 指令用法:

 试商法设计思路

思路详述

在整数除法中,

商的位宽和被除数一致,余数的位宽与除数一致。

需要的步骤数等于被除数位宽。 

以6位被除数 除以 3位除数为例,说明:

长除法 101101 / 110 :

除法模块设计

// |------------------------------ ================================== ------------------------------
// |============================== 		    顶层模块仿真平台  	      ==============================
// |------------------------------ ================================== ------------------------------
// |Create Date : 2022-12-15
// |Finish Date : 2022-12-15
// |Edited by   : Xu Y. B. (CSDN USER NAME :在路上,正出发)
// |Reference   : 《自己动手写CPU》
// |
// |
// |------------------------------------------------------------------------------------------------
// |---------------------------------------- Change History ----------------------------------------
// |Date:2022-12-15
// |Who :Xu Y. B.
// |What:实现32位整数除法 _OPR_DATA_A / _OPR_DATA_B


`timescale 1ns / 1ps

module DIV_OPR_MDL(

// |--------------------------------------  输入输出端口声明  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 时钟、复位
input 															I_CPU_CLK,
input 															I_CPU_RSTN,

input 															I_DIV_TYPE, // 1:有符号除法,0:无符号除法 电平信号

input 		[31:0]												I_OPR_DATA_A,
input   	[31:0]												I_OPR_DATA_B,

input															I_OPR_EN,//电平信号 需要与数据同步
input 															I_OPR_CANCEL,//脉冲信号 取消除法运算

output 	reg														O_RES_VAL,
output 	reg	[63:0]												O_RES

    );
// |--------------------------------------  模块内部参数声明  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 状态编码
localparam 			LP_ST_IDLE				=					3'b001;
localparam 			LP_ST_ZERO				=					3'b010;
localparam 			LP_ST_WORK				=					3'b100;



// |--------------------------------------  模块内部信号声明  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 状态信号
reg			[2:0]												R_STATE;
// | 计数器
reg 		[5:0]												R_CNT;
// | 操作数
reg         [31:0]												R_OPR_A;
reg         [31:0]												R_OPR_B;
reg   		[64:0]												R_DIVIDEND;
reg         [31:0]												R_DIVISOR;
wire 		[32:0]												W_DIV_TMP;


// |--------------------------------------  模块内部逻辑设计  --------------------------------------
// |------------------------------------------------------------------------------------------------
assign 		W_DIV_TMP			=		{1'b0,R_DIVIDEND[63:32]} - {1'b0,R_DIVISOR};

// | 状态机
always @ (posedge I_CPU_CLK)
begin
	if(~I_CPU_RSTN)
	begin
		R_STATE   <= LP_ST_IDLE;
		R_CNT     <= 6'd0;
		O_RES_VAL <= 1'b0;
		O_RES     <= 64'd0;
		R_OPR_A   <= 32'd0;
		R_OPR_B   <= 32'd0;
		R_DIVIDEND<= 65'd0;
		R_DIVISOR <= 32'd0;
	end
	else
	begin
		case(R_STATE)
			LP_ST_IDLE:
			begin
				R_CNT     <= 6'd0;
				O_RES_VAL <= 1'b0;
				O_RES     <= 64'd0;
				R_DIVIDEND<= 65'd0;
				R_DIVISOR <= 32'd0;

				if(I_OPR_EN & !I_OPR_CANCEL)
				begin
					if(I_OPR_DATA_B == 32'd0)
					begin
						R_STATE <= LP_ST_ZERO;
						R_OPR_A   <= 32'd0;
						R_OPR_B   <= 32'd0;
					end
					else
					begin
						R_STATE <= LP_ST_WORK;

						if(I_DIV_TYPE)
						begin
							if(I_OPR_DATA_A[31])
							begin
								R_OPR_A   <= ~I_OPR_DATA_A + 1;
							end
							else
							begin
								R_OPR_A   <= I_OPR_DATA_A;
							end

							if(I_OPR_DATA_B[31])
							begin
								R_OPR_B   <= ~I_OPR_DATA_B + 1;
							end
							else
							begin
								R_OPR_B   <= I_OPR_DATA_B;
							end
						end
						else
						begin
							R_OPR_A   <= I_OPR_DATA_A;
							R_OPR_B   <= I_OPR_DATA_B;							
						end
					end
				end
				else
				begin
					R_STATE <= LP_ST_IDLE;
					R_OPR_A   <= 32'd0;
					R_OPR_B   <= 32'd0;
				end
			end
			LP_ST_ZERO:
			begin
				O_RES_VAL <= 1'b1;
				O_RES     <= 64'd0;
				R_STATE   <= LP_ST_IDLE;
				R_CNT     <= 6'd0;
				R_DIVIDEND<= 65'd0;
				R_DIVISOR <= 32'd0;
			end
			LP_ST_WORK:
			begin
				if(!I_OPR_CANCEL)
				begin
					if(R_CNT == 6'd0)
					begin
						R_DIVIDEND[32:1] <= R_OPR_A;
						R_DIVISOR        <= R_OPR_B;
						R_STATE          <= LP_ST_WORK;
						R_CNT 			 <= R_CNT + 1;
					end
					else if(R_CNT == 6'd33)
					begin
						if(I_DIV_TYPE && ((I_OPR_DATA_A[31] ^ I_OPR_DATA_B[31]) == 1'b1))
						begin
							R_DIVIDEND[31:0] <= (~R_DIVIDEND[31:0]) + 1;
						end

						if(I_DIV_TYPE && ((I_OPR_DATA_A[31] ^ R_DIVIDEND[64]) == 1'b1))
						begin
							R_DIVIDEND[64:33] <= (~R_DIVIDEND[64:33]) + 1;
						end

						R_STATE <= LP_ST_WORK;
						R_CNT   <= R_CNT + 1;
					end
					else if(R_CNT == 6'd34)
					begin
						O_RES_VAL <= 1'b1;
						O_RES     <= {R_DIVIDEND[64:33] , R_DIVIDEND[31:0]};
						R_STATE   <= LP_ST_IDLE;
						R_CNT     <= 32'd0;
					end
					else
					begin
						if(W_DIV_TMP[32])
						begin
							R_DIVIDEND <= {R_DIVIDEND[63:0] , 1'b0};
						end
						else
						begin
							R_DIVIDEND <= {W_DIV_TMP[31:0] , R_DIVIDEND[31:0] , 1'b1};
						end

						R_CNT <= R_CNT + 1;
						R_STATE <= LP_ST_WORK;
					end
				end
				else
				begin
					R_STATE <= LP_ST_IDLE;
				end
			end
			default:
			begin
				R_STATE <= LP_ST_IDLE;
			end
		endcase
	end
end


endmodule

除法模块仿真

TEST BENCH

// |------------------------------ ================================== ------------------------------
// |============================== 		    顶层模块仿真平台  	      ==============================
// |------------------------------ ================================== ------------------------------
// |Create Date : 2022-12-15
// |Finish Date : 2022-12-15
// |Edited by   : Xu Y. B. (CSDN USER NAME :在路上,正出发)
// |Reference   : 《自己动手写CPU》
// |
// |
// |------------------------------------------------------------------------------------------------
// |---------------------------------------- Change History ----------------------------------------
// |Date:2022-12-15
// |Who :Xu Y. B.
// |What:

`timescale 1ns / 1ps


module TB_DIV_OPR_MDL();

// |--------------------------------------  输入输出端口声明  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 时钟、复位
reg 															I_CPU_CLK;
reg 															I_CPU_RSTN;

reg 															I_DIV_TYPE; // 1:有符号除法,0:无符号除法

reg 		[31:0]												I_OPR_DATA_A;
reg   		[31:0]												I_OPR_DATA_B;

reg																I_OPR_EN;//电平信号 需要与数据同步
reg 															I_OPR_CANCEL;//脉冲信号 取消除法运算

wire															O_RES_VAL;
wire		[63:0]												O_RES;

// | 产生激励
initial I_CPU_CLK = 1'b0;
always #10 I_CPU_CLK = ~I_CPU_CLK;

initial
begin
	I_CPU_RSTN 	 = 1'b0;
	I_DIV_TYPE 	 = 1'b0;
	I_OPR_DATA_A = 32'd0;
	I_OPR_DATA_B = 32'd0;
	I_OPR_EN     = 1'b0;
	I_OPR_CANCEL = 1'b0;
	#55;
	I_CPU_RSTN   = 1'b1;
	#35;
	// 有符号数除法
	@(posedge I_CPU_CLK)//  正数 / 正数
	I_OPR_EN     <= 1'b1;
	I_DIV_TYPE   <= 1'b1;
	I_OPR_DATA_A <= 32'd13;
	I_OPR_DATA_B <= 32'd2;

	@(negedge O_RES_VAL);
	@(posedge I_CPU_CLK)//  正数 / 负数
	I_OPR_EN     <= 1'b1;
	I_DIV_TYPE   <= 1'b1;
	I_OPR_DATA_A <= 32'd13;
	I_OPR_DATA_B <= -32'd2;

	@(negedge O_RES_VAL);
	@(posedge I_CPU_CLK)//  负数 / 负数
	I_OPR_EN     <= 1'b1;
	I_DIV_TYPE   <= 1'b1;
	I_OPR_DATA_A <= -32'd13;
	I_OPR_DATA_B <= -32'd2;

	@(negedge O_RES_VAL);
	@(posedge I_CPU_CLK)//  负数 / 正数
	I_OPR_EN     <= 1'b1;
	I_DIV_TYPE   <= 1'b1;
	I_OPR_DATA_A <= -32'd13;
	I_OPR_DATA_B <= 32'd2;

	// 无符号数除法
	@(negedge O_RES_VAL);
	@(posedge I_CPU_CLK)//  正数 / 正数
	I_OPR_EN     <= 1'b1;
	I_DIV_TYPE   <= 1'b0;
	I_OPR_DATA_A <= 32'd100;
	I_OPR_DATA_B <= 32'd2;

	// 无符号数除法
	@(negedge O_RES_VAL);
	@(posedge I_CPU_CLK)//  正数 / 正数
	I_OPR_EN     <= 1'b1;
	I_DIV_TYPE   <= 1'b0;
	I_OPR_DATA_A <= 32'd200;
	I_OPR_DATA_B <= 32'd25;

	// 无符号数除法
	@(negedge O_RES_VAL);
	@(posedge I_CPU_CLK)//  正数 / 正数
	I_OPR_EN     <= 1'b1;
	I_DIV_TYPE   <= 1'b0;
	I_OPR_DATA_A <= 32'd1200;
	I_OPR_DATA_B <= 32'd300;

	@(negedge O_RES_VAL);
	@(posedge I_CPU_CLK)//  中间终止
	I_OPR_EN     <= 1'b1;
	I_DIV_TYPE   <= 1'b0;
	I_OPR_DATA_A <= -32'd13;
	I_OPR_DATA_B <= 32'd2;
	#(10*20);
	@(posedge I_CPU_CLK);
	I_OPR_CANCEL <= 1'b1;
	#(10*20);
	$finish;
end
// | 模块例化
	DIV_OPR_MDL INST_DIV_OPR_MDL
		(
			.I_CPU_CLK    (I_CPU_CLK),
			.I_CPU_RSTN   (I_CPU_RSTN),
			.I_DIV_TYPE   (I_DIV_TYPE),
			.I_OPR_DATA_A (I_OPR_DATA_A),
			.I_OPR_DATA_B (I_OPR_DATA_B),
			.I_OPR_EN     (I_OPR_EN),
			.I_OPR_CANCEL (I_OPR_CANCEL),
			.O_RES_VAL    (O_RES_VAL),
			.O_RES        (O_RES)
		);



endmodule

仿真结果

除法运算加入指令集

此处仅给出有改动模块的源码:

宏定义

// |------------------------------ ================================== ------------------------------
// |============================== MIPS32 CPU SYSTEM ALL MACRO DEFINE ==============================
// |------------------------------ ================================== ------------------------------
// |Create Date : 2022-12-06
// |Finish Date : 2022-
// |Edited by   : Xu Y. B. (CSDN USER NAME :在路上,正出发)
// |Reference   : 《自己动手写CPU》——第4章
// |
// |
// |------------------------------------------------------------------------------------------------
// |---------------------------------------- Change History ----------------------------------------
// |Date:2022-12-09
// |Who :Xu Y. B.
// |What:增加如下指令宏定义:
// |	 and、or、xor、nor
// |	 andi、xori
// |	 lui
// |	 sll、sllv、sra、srav.、srl、srlv 
// |	 nop、ssnop、sync、pref
// |	 以及相应的ALU操作功能宏定义
// |Date:2022-12-10
// |Who :Xu Y. B.
// |What:增加如下指令宏定义:
// |	 movz、movn、mfhi、mthi、mfhi、mflo 
// |	 以及相应的ALU操作功能宏定义
// |Date:2022-12-12
// |Who :Xu Y. B.
// |What:增加如下指令宏定义:
// |	 add、addu、sub、subu、slt、sltu、addi、addiu、slti、sltiu、clo、clz、multu、mult、mul
// |	 以及相应的ALU操作功能宏定义
// |Date:2022-12-14
// |Who :Xu Y. B.
// |What:增加如下指令宏定义:
// |	 madd、maddu、msub、msubu
// |	 以及相应的ALU操作功能宏定义
// |Date:2022-12-16
// |Who :Xu Y. B.
// |What:增加如下指令宏定义:
// |	 div、divu
// |	 以及相应的ALU操作功能宏定义

// |--------------------------------------  系统级全局宏定义  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 0字
`define 							DEF_ZERO_WORD						32'd0				// 0字

// | 关于译码
`define 							DEF_ALU_OPR_BUS						7:0					// 译码输出 O_ALU_OPR 总线
`define 							DEF_ALU_SEL_BUS 					2:0					// 译码输出 O_ALU_SEL 总线

// | 逻辑 0 1
`define 							DEF_LOG_TRUE						1'b1				// 逻辑 真
`define 							DEF_LOG_FALSE						1'b0				// 逻辑 假

// | 芯片使能
`define 							DEF_CHIP_EN							1'b1				// 芯片使能
`define 							DEF_CHIP_DIS						1'b0				// 芯片不使能



// |--------------------------------------  指令相关的宏定义  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 指令、功能码
`define 							DEF_ISTC_AND						6'b100100			
`define 							DEF_ISTC_OR							6'b100101			
`define 							DEF_ISTC_XOR						6'b100110			
`define 							DEF_ISTC_NOR						6'b100111			
`define 							DEF_ISTC_ANDI						6'b001100			
`define 							DEF_ISTC_ORI						6'b001101 			
`define 							DEF_ISTC_XORI						6'b001110			
`define 							DEF_ISTC_LUI						6'b001111			

`define 							DEF_ISTC_SLL						6'b000000			
`define 							DEF_ISTC_SLLV						6'b000100			
`define 							DEF_ISTC_SRL						6'b000010			
`define 							DEF_ISTC_SRLV						6'b000110			
`define 							DEF_ISTC_SRA						6'b000011			
`define 							DEF_ISTC_SRAV						6'b000111 			

`define 							DEF_ISTC_SYNC						6'b001111 			
`define 							DEF_ISTC_PREF						6'b110011 			
`define 							DEF_ISTC_SPEC						6'b000000 			// SPECIAL  类指令码
`define 							DEF_ISTC_SPEC2						6'b011100 			// SPECIAL2 类指令码

`define 							DEF_ISTC_MOVZ  						6'b001010
`define 							DEF_ISTC_MOVN  						6'b001011
`define 							DEF_ISTC_MFHI  						6'b010000
`define 							DEF_ISTC_MTHI  						6'b010001
`define 							DEF_ISTC_MFLO  						6'b010010
`define 							DEF_ISTC_MTLO  						6'b010011

`define 							DEF_ISTC_SLT  						6'b101010
`define 							DEF_ISTC_SLTU  						6'b101011
`define 							DEF_ISTC_SLTI  						6'b001010
`define 							DEF_ISTC_SLTIU  					6'b001011   
`define 							DEF_ISTC_ADD  						6'b100000
`define 							DEF_ISTC_ADDU   					6'b100001
`define 							DEF_ISTC_SUB    					6'b100010
`define 							DEF_ISTC_SUBU   					6'b100011
`define 							DEF_ISTC_ADDI   					6'b001000
`define 							DEF_ISTC_ADDIU  					6'b001001
`define 							DEF_ISTC_CLZ    					6'b100000
`define 							DEF_ISTC_CLO    					6'b100001

`define 							DEF_ISTC_MULT   					6'b011000
`define 							DEF_ISTC_MULTU  					6'b011001
`define 							DEF_ISTC_MUL    					6'b000010
`define 							DEF_ISTC_MADD   					6'b000000
`define 							DEF_ISTC_MADDU  					6'b000001
`define 							DEF_ISTC_MSUB   					6'b000100
`define 							DEF_ISTC_MSUBU  					6'b000101
`define 							DEF_ISTC_DIV    					6'b011010
`define 							DEF_ISTC_DIVU   					6'b011011

`define 							DEF_ISTC_NOP						6'b000000			// nop
// | ALU操作码
`define 							DEF_ALU_OR_OPR						8'b00100101			
`define 							DEF_ALU_AND_OPR						8'b00100100			
`define 							DEF_ALU_XOR_OPR						8'b00100110			
`define 							DEF_ALU_NOR_OPR						8'b00100111			

`define 							DEF_ALU_SLL_OPR						8'b01111100			
`define 							DEF_ALU_SRL_OPR						8'b00000010			
`define 							DEF_ALU_SRA_OPR						8'b00000011	

`define 							DEF_ALU_MOVZ_OPR  					8'b00001010
`define 							DEF_ALU_MOVN_OPR  					8'b00001011
`define 							DEF_ALU_MFHI_OPR  					8'b00010000
`define 							DEF_ALU_MTHI_OPR  					8'b00010001
`define 							DEF_ALU_MFLO_OPR  					8'b00010010
`define 							DEF_ALU_MTLO_OPR  					8'b00010011	

`define 							DEF_ALU_SLT_OPR    					8'b00101010
`define 							DEF_ALU_SLTU_OPR   					8'b00101011
`define 							DEF_ALU_SLTI_OPR   					8'b01010111
`define 							DEF_ALU_SLTIU_OPR  					8'b01011000   
`define 							DEF_ALU_ADD_OPR    					8'b00100000
`define 							DEF_ALU_ADDU_OPR   					8'b00100001
`define 							DEF_ALU_SUB_OPR    					8'b00100010
`define 							DEF_ALU_SUBU_OPR   					8'b00100011
`define 							DEF_ALU_ADDI_OPR   					8'b01010101
`define 							DEF_ALU_ADDIU_OPR  					8'b01010110
`define 							DEF_ALU_CLZ_OPR    					8'b10110000
`define 							DEF_ALU_CLO_OPR    					8'b10110001

`define 							DEF_ALU_MULT_OPR   					8'b00011000
`define 							DEF_ALU_MULTU_OPR  					8'b00011001
`define 							DEF_ALU_MUL_OPR    					8'b10101001

`define 							DEF_ALU_MADD_OPR   					8'b10100110
`define 							DEF_ALU_MADDU_OPR   				8'b10101000
`define 							DEF_ALU_MSUB_OPR   					8'b10101010
`define 							DEF_ALU_MSUBU_OPR   				8'b10101011
`define 							DEF_ALU_DIV_OPR   					8'b00011010
`define 							DEF_ALU_DIVU_OPR   					8'b00011011


`define 							DEF_ALU_NOP_OPR						8'd0				

// | ALU 选择
// `define 							DEF_ALU_SEL_LOGIC					3'b001
// `define 							DEF_ALU_SEL_NOP						3'b000				

// | 操作数
`define 							DEF_SRC_OPR_DATA_BUS				31:0
`define 							DEF_IMM_DATA_BUS					15:0


// |--------------------------------------  指令存储器宏定义  --------------------------------------
// |------------------------------------------------------------------------------------------------
`define 							DEF_ISTC_ADDR_BUS					31:0				// 地址线总线
`define 							DEF_ISTC_DATA_BUS 					31:0				// 数据线总线
`define 							DEF_ISTC_CACH_DEPTH					2**17-1				// 缓存深度/地址最大值
`define 							DEF_ISTC_ADDR_WIDTH_ACTUAL			17					// 实际使用的缓存地址线宽度



// |--------------------------------------  通用寄存器宏定义  --------------------------------------
// |------------------------------------------------------------------------------------------------
`define 							DEF_GPR_ADDR_WIDTH					5					// 通用寄存器地址位宽(32个)
`define 							DEF_GPR_DATA_WIDTH					32					// 通用寄存器数据位宽
`define 							DEF_GPR_NUM							32					// 通用寄存器数目
`define 							DEF_GPR_ADDR_NOP					5'd0				// 空操作 GPR 地址

译码模块

// |------------------------------ ================================== ------------------------------
// |============================== 		     指令-译码模块  	      ==============================
// |------------------------------ ================================== ------------------------------
// |Create Date : 2022-12-07
// |Finish Date : 2022-12-07
// |Edited by   : Xu Y. B. (CSDN USER NAME :在路上,正出发)
// |Reference   : 《自己动手写CPU》
// |
// |
// |------------------------------------------------------------------------------------------------
// |---------------------------------------- Change History ----------------------------------------
// |Date:2022-12-08
// |Who :Xu Y. B.
// |What:修复流水线数据相关的问题(第 2、3类问题)
// |	 思路参考《自己动手写CPU》5.2节
// |	 增加模块端口:Line 48 - 54
// |	 增加条件分支:Line 141 - 148 、171 - 178
// |Date:2022-12-09
// |Who :Xu Y. B.
// |What:增加逻辑、移位指令的译码功能
// |Date:2022-12-11
// |Who :Xu Y. B.
// |What:增加移动指令的译码功能
// |Date:2022-12-12
// |Who :Xu Y. B.
// |What:增加简单算术运算指令的译码功能
// |Date:2022-12-14
// |Who :Xu Y. B.
// |What:增加2步算术运算指令的译码功能
// |Date:2022-12-16
// |Who :Xu Y. B.
// |What:增加除法算术运算指令的译码功能

`include "MIPS_SYS_DEFINES.v"
`timescale 1ns / 1ps


module ID_MDL(

// |--------------------------------------  输入输出端口声明  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 时钟、复位
input 															I_CPU_CLK,
input 															I_CPU_RSTN,
// | 指令
input 		[`DEF_ISTC_DATA_BUS]								I_ISTC,
// | GPR读写控制
output 	reg														O_GPR_RD_EN_A,
output	reg	[`DEF_GPR_ADDR_WIDTH-1:0]							O_GPR_RD_ADDR_A,
input 		[`DEF_GPR_DATA_WIDTH-1:0]							I_GPR_RD_DATA_A,
output  reg														O_GPR_RD_EN_B,
output  reg	[`DEF_GPR_ADDR_WIDTH-1:0]							O_GPR_RD_ADDR_B,
input 		[`DEF_GPR_DATA_WIDTH-1:0]							I_GPR_RD_DATA_B,
// | 译码输出相关 对接 ALU 运算单元
// output  reg [`DEF_ALU_SEL_BUS]									O_ALU_SEL,
output		[`DEF_ALU_OPR_BUS]									O_ALU_OP_TYPE,
output  reg	[`DEF_SRC_OPR_DATA_BUS]								O_SRC_OPR_DATA_A,
output  reg	[`DEF_SRC_OPR_DATA_BUS]								O_SRC_OPR_DATA_B,

output  reg 													O_DST_GPR_WR_EN,
output  reg [`DEF_GPR_ADDR_WIDTH-1:0]							O_DST_GPR_WR_ADDR,
// | 为解决数据相关问题/读写冲突问题 引入的端口
// 来自执行模块
input 															I_DST_GPR_WR_EN_FROM_EXE_MDL, 
input 		[`DEF_GPR_ADDR_WIDTH-1:0]							I_DST_GPR_WR_ADDR_FROM_EXE_MDL,
input    	[`DEF_GPR_DATA_WIDTH-1:0]							I_DST_GPR_WR_DATA_FROM_EXE_MDL,
// 来自访存模块
input 															I_DST_GPR_WR_EN_FROM_MEM_ACS_MDL, 
input 		[`DEF_GPR_ADDR_WIDTH-1:0]							I_DST_GPR_WR_ADDR_FROM_MEM_ACS_MDL,
input   	[`DEF_GPR_DATA_WIDTH-1:0]							I_DST_GPR_WR_DATA_FROM_MEM_ACS_MDL,
// 流水线暂停
input 		[4:0]												I_PAUSE_ACK,//待优化
output 															O_PAUSE_REQ





    );
// |--------------------------------------  模块内部信号声明  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 指令分解相关
wire		[5:0]												W_ISTC_TYPE;	// 指令码
wire		[`DEF_GPR_ADDR_WIDTH-1:0]							W_SRC_GPR_ADDR; 
wire 		[`DEF_GPR_ADDR_WIDTH-1:0]							W_DST_GPR_ADDR;
wire		[`DEF_IMM_DATA_BUS]									W_ISTC_IMM_DATA;

wire		[4:0]												W_ISTC_15_11_BIT;
wire		[4:0]												W_ISTC_10_6_BIT;
wire		[5:0]												W_ISTC_5_0_BIT;


// | 32位立即数
reg			[31:0]												R_IMM_DATA_32BIT;

// | 指令有效信号
reg																R_ISTC_VAL;

// 配合流水线暂停功能
wire 		[`DEF_ISTC_DATA_BUS]								W_I_ISTC;

reg 		[`DEF_ALU_OPR_BUS]									R_ALU_OP_TYPE;

reg 		[1:0]												R_PAUSE_REQ;


// |--------------------------------------  模块内部逻辑设计  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 指令分解相关
assign 		W_ISTC_TYPE			=		W_I_ISTC[31:26];// 指令码
assign 		W_SRC_GPR_ADDR  	=       W_I_ISTC[25:21];
assign		W_DST_GPR_ADDR  	=       W_I_ISTC[20:16];
assign 		W_ISTC_IMM_DATA		=		W_I_ISTC[15:0] ;

assign 		W_ISTC_15_11_BIT	=		W_I_ISTC[15:11];
assign		W_ISTC_10_6_BIT		=		W_I_ISTC[10:6];
assign 		W_ISTC_5_0_BIT		=		W_I_ISTC[5:0];

assign      O_PAUSE_REQ			=		R_PAUSE_REQ[0] & (~R_PAUSE_REQ[1]);

// 下面两句故意设置为 锁存器,以满足功能需求
assign 		W_I_ISTC			=		(!I_PAUSE_ACK[1]) ? I_ISTC:W_I_ISTC;
assign 		O_ALU_OP_TYPE 		=		(!I_PAUSE_ACK[1]) ? R_ALU_OP_TYPE:O_ALU_OP_TYPE;


always @ (posedge I_CPU_CLK)
begin
	if(~I_CPU_RSTN)
	begin
		R_PAUSE_REQ <= 2'b00;
	end
	else if(W_ISTC_TYPE == `DEF_ISTC_SPEC2)
	begin
		R_PAUSE_REQ[1] <= R_PAUSE_REQ[0];
		case(W_ISTC_5_0_BIT)
			`DEF_ISTC_MADD,`DEF_ISTC_MADDU,`DEF_ISTC_MSUB,`DEF_ISTC_MSUBU:
			begin
				R_PAUSE_REQ[0] <= 1'b1;
			end
			default:
			begin
				R_PAUSE_REQ[0] <= R_PAUSE_REQ[0];
			end
		endcase
	end
	else if(W_ISTC_TYPE == `DEF_ISTC_SPEC)
	begin
		R_PAUSE_REQ[1] <= R_PAUSE_REQ[0];
		case(W_ISTC_5_0_BIT)
		`DEF_ISTC_DIVU,`DEF_ISTC_DIV:
			begin
				R_PAUSE_REQ[0] <= 1'b1;
			end
			default:
			begin
				R_PAUSE_REQ[0] <= R_PAUSE_REQ[0];
			end
		endcase
	end
	else
	begin
		R_PAUSE_REQ[0] <= R_PAUSE_REQ[0];
		R_PAUSE_REQ[1] <= R_PAUSE_REQ[0];
	end
end

// | 指令译码 
always @ (posedge I_CPU_CLK)
begin
	if(~I_CPU_RSTN)
	begin
		O_GPR_RD_EN_A	  <= 1'b0;
		O_GPR_RD_ADDR_A   <= `DEF_GPR_ADDR_NOP;
		O_GPR_RD_EN_B	  <= 1'b0;
		O_GPR_RD_ADDR_B	  <= `DEF_GPR_ADDR_NOP;

		R_ALU_OP_TYPE     <= `DEF_ALU_NOP_OPR;
		// O_ALU_SEL         <= `DEF_ALU_SEL_NOP;
		O_DST_GPR_WR_EN   <= 1'b0;
		O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP;
		
		R_ISTC_VAL		  <= 1'b0;
		R_IMM_DATA_32BIT  <= 32'd0;
	end
	else
	begin
		case(W_ISTC_TYPE)
			`DEF_ISTC_SPEC://SPECIAL 类 指令
			begin
				case(W_ISTC_10_6_BIT)
					5'd0:
					begin
						case(W_ISTC_5_0_BIT)
							`DEF_ISTC_AND:
							begin
								O_GPR_RD_EN_A	  <= 1'b1;
								O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
								O_GPR_RD_EN_B	  <= 1'b1;
								O_GPR_RD_ADDR_B	  <= W_DST_GPR_ADDR;

								R_ALU_OP_TYPE     <= `DEF_ALU_AND_OPR;
								// O_ALU_SEL         <= `DEF_ALU_SEL_NOP;
								O_DST_GPR_WR_EN   <= 1'b1;
								O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;
		
								R_ISTC_VAL		  <= 1'b1;
								R_IMM_DATA_32BIT  <= 32'd0;
							end
							`DEF_ISTC_OR:
							begin
								O_GPR_RD_EN_A	  <= 1'b1;
								O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
								O_GPR_RD_EN_B	  <= 1'b1;
								O_GPR_RD_ADDR_B	  <= W_DST_GPR_ADDR;

								R_ALU_OP_TYPE     <= `DEF_ALU_OR_OPR;
								// O_ALU_SEL         <= `DEF_ALU_SEL_NOP;
								O_DST_GPR_WR_EN   <= 1'b1;
								O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;
		
								R_ISTC_VAL		  <= 1'b1;
								R_IMM_DATA_32BIT  <= 32'd0;
							end
							`DEF_ISTC_XOR:
							begin
								O_GPR_RD_EN_A	  <= 1'b1;
								O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
								O_GPR_RD_EN_B	  <= 1'b1;
								O_GPR_RD_ADDR_B	  <= W_DST_GPR_ADDR;

								R_ALU_OP_TYPE     <= `DEF_ALU_XOR_OPR;
								// O_ALU_SEL         <= `DEF_ALU_SEL_NOP;
								O_DST_GPR_WR_EN   <= 1'b1;
								O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;
		
								R_ISTC_VAL		  <= 1'b1;
								R_IMM_DATA_32BIT  <= 32'd0;
							end
							`DEF_ISTC_NOR:
							begin
								O_GPR_RD_EN_A	  <= 1'b1;
								O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
								O_GPR_RD_EN_B	  <= 1'b1;
								O_GPR_RD_ADDR_B	  <= W_DST_GPR_ADDR;

								R_ALU_OP_TYPE     <= `DEF_ALU_NOR_OPR;
								// O_ALU_SEL         <= `DEF_ALU_SEL_NOP;
								O_DST_GPR_WR_EN   <= 1'b1;
								O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;
		
								R_ISTC_VAL		  <= 1'b1;
								R_IMM_DATA_32BIT  <= 32'd0;
							end
							`DEF_ISTC_SLLV:
							begin
								O_GPR_RD_EN_A	  <= 1'b1;
								O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
								O_GPR_RD_EN_B	  <= 1'b1;
								O_GPR_RD_ADDR_B	  <= W_DST_GPR_ADDR;

								R_ALU_OP_TYPE     <= `DEF_ALU_SLL_OPR;
								// O_ALU_SEL         <= `DEF_ALU_SEL_NOP;
								O_DST_GPR_WR_EN   <= 1'b1;
								O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;
		
								R_ISTC_VAL		  <= 1'b1;
								R_IMM_DATA_32BIT  <= 32'd0;
							end
							`DEF_ISTC_SRLV:
							begin
								O_GPR_RD_EN_A	  <= 1'b1;
								O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
								O_GPR_RD_EN_B	  <= 1'b1;
								O_GPR_RD_ADDR_B	  <= W_DST_GPR_ADDR;

								R_ALU_OP_TYPE     <= `DEF_ALU_SRL_OPR;
								// O_ALU_SEL         <= `DEF_ALU_SEL_NOP;
								O_DST_GPR_WR_EN   <= 1'b1;
								O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;
		
								R_ISTC_VAL		  <= 1'b1;
								R_IMM_DATA_32BIT  <= 32'd0;
							end
							`DEF_ISTC_SRAV:
							begin
								O_GPR_RD_EN_A	  <= 1'b1;
								O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
								O_GPR_RD_EN_B	  <= 1'b1;
								O_GPR_RD_ADDR_B	  <= W_DST_GPR_ADDR;

								R_ALU_OP_TYPE     <= `DEF_ALU_SRA_OPR;
								// O_ALU_SEL         <= `DEF_ALU_SEL_NOP;
								O_DST_GPR_WR_EN   <= 1'b1;
								O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;
		
								R_ISTC_VAL		  <= 1'b1;
								R_IMM_DATA_32BIT  <= 32'd0;
							end
							`DEF_ISTC_SYNC:
							begin
								O_GPR_RD_EN_A	  <= 1'b0;
								O_GPR_RD_ADDR_A   <= `DEF_GPR_ADDR_NOP;
								O_GPR_RD_EN_B	  <= 1'b1;
								O_GPR_RD_ADDR_B	  <= `DEF_GPR_ADDR_NOP;

								R_ALU_OP_TYPE     <= `DEF_ALU_NOP_OPR;
								// O_ALU_SEL         <= `DEF_ALU_SEL_NOP;
								O_DST_GPR_WR_EN   <= 1'b0;
								O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP;
		
								R_ISTC_VAL		  <= 1'b1;
								R_IMM_DATA_32BIT  <= 32'd0;
							end
							`DEF_ISTC_MOVZ:
							begin
								O_GPR_RD_EN_A     <= 1'b1;
								O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
								O_GPR_RD_EN_B     <= 1'b1;
								O_GPR_RD_ADDR_B   <= W_DST_GPR_ADDR;

								R_ALU_OP_TYPE     <= `DEF_ALU_MOVZ_OPR;
								// 写使能此处后置于 执行模块 判断赋值
								// if(I_GPR_RD_DATA_B == `DEF_ZERO_WORD)
								// begin
								// 	O_DST_GPR_WR_EN   <= 1'b1;
								// end
								// else
								// begin
								// 	O_DST_GPR_WR_EN   <= 1'b0;
								// end

								O_DST_GPR_WR_EN   <= 1'b0;
								O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;

								R_ISTC_VAL 		  <= 1'b1;
								R_IMM_DATA_32BIT  <= 32'd0;
							end
							`DEF_ISTC_MOVN:
							begin
								O_GPR_RD_EN_A     <= 1'b1;
								O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
								O_GPR_RD_EN_B     <= 1'b1;
								O_GPR_RD_ADDR_B   <= W_DST_GPR_ADDR;

								R_ALU_OP_TYPE     <= `DEF_ALU_MOVN_OPR;
								// 写使能此处后置于 执行模块 判断赋值
								// if(I_GPR_RD_DATA_B != `DEF_ZERO_WORD)
								// begin
								// 	O_DST_GPR_WR_EN   <= 1'b1;
								// end
								// else
								// begin
								// 	O_DST_GPR_WR_EN   <= 1'b0;
								// end

								O_DST_GPR_WR_EN   <= 1'b0;
								O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;

								R_ISTC_VAL 		  <= 1'b1;
								R_IMM_DATA_32BIT  <= 32'd0;
							end
							`DEF_ISTC_MFHI:
							begin
								O_GPR_RD_EN_A     <= 1'b0;
								O_GPR_RD_ADDR_A   <= `DEF_GPR_ADDR_NOP;
								O_GPR_RD_EN_B     <= 1'b0;
								O_GPR_RD_ADDR_B   <= `DEF_GPR_ADDR_NOP;

								R_ALU_OP_TYPE     <= `DEF_ALU_MFHI_OPR;
								O_DST_GPR_WR_EN   <= 1'b1;
								O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;

								R_ISTC_VAL 		  <= 1'b1;
								R_IMM_DATA_32BIT  <= 32'd0;
							end
							`DEF_ISTC_MTHI:
							begin
								O_GPR_RD_EN_A     <= 1'b1;
								O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
								O_GPR_RD_EN_B     <= 1'b0;
								O_GPR_RD_ADDR_B   <= `DEF_GPR_ADDR_NOP;

								R_ALU_OP_TYPE     <= `DEF_ALU_MTHI_OPR;
								O_DST_GPR_WR_EN   <= 1'b0;
								O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP;

								R_ISTC_VAL 		  <= 1'b1;
								R_IMM_DATA_32BIT  <= 32'd0;
							end
							`DEF_ISTC_MFLO:
							begin
								O_GPR_RD_EN_A     <= 1'b0;
								O_GPR_RD_ADDR_A   <= `DEF_GPR_ADDR_NOP;
								O_GPR_RD_EN_B     <= 1'b0;
								O_GPR_RD_ADDR_B   <= `DEF_GPR_ADDR_NOP;

								R_ALU_OP_TYPE     <= `DEF_ALU_MFLO_OPR;
								O_DST_GPR_WR_EN   <= 1'b1;
								O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;

								R_ISTC_VAL 		  <= 1'b1;
								R_IMM_DATA_32BIT  <= 32'd0;
							end
							`DEF_ISTC_MTLO:
							begin
								O_GPR_RD_EN_A     <= 1'b1;
								O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
								O_GPR_RD_EN_B     <= 1'b0;
								O_GPR_RD_ADDR_B   <= `DEF_GPR_ADDR_NOP;

								R_ALU_OP_TYPE     <= `DEF_ALU_MTLO_OPR;
								O_DST_GPR_WR_EN   <= 1'b0;
								O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP;

								R_ISTC_VAL 		  <= 1'b1;
								R_IMM_DATA_32BIT  <= 32'd0;
							end
							`DEF_ISTC_ADD  :
							begin
								O_GPR_RD_EN_A     <= 1'b1;
								O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
								O_GPR_RD_EN_B     <= 1'b1;
								O_GPR_RD_ADDR_B   <= W_DST_GPR_ADDR;

								R_ALU_OP_TYPE     <= `DEF_ALU_ADD_OPR;
								O_DST_GPR_WR_EN   <= 1'b1;
								O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;

								R_ISTC_VAL 		  <= 1'b1;
								R_IMM_DATA_32BIT  <= 32'd0;
							end
							`DEF_ISTC_ADDU :
							begin
								O_GPR_RD_EN_A     <= 1'b1;
								O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
								O_GPR_RD_EN_B     <= 1'b1;
								O_GPR_RD_ADDR_B   <= W_DST_GPR_ADDR;

								R_ALU_OP_TYPE     <= `DEF_ALU_ADDU_OPR;
								O_DST_GPR_WR_EN   <= 1'b1;
								O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;

								R_ISTC_VAL 		  <= 1'b1;
								R_IMM_DATA_32BIT  <= 32'd0;
							end
							`DEF_ISTC_SUB  :
							begin
								O_GPR_RD_EN_A     <= 1'b1;
								O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
								O_GPR_RD_EN_B     <= 1'b1;
								O_GPR_RD_ADDR_B   <= W_DST_GPR_ADDR;

								R_ALU_OP_TYPE     <= `DEF_ALU_SUB_OPR;
								O_DST_GPR_WR_EN   <= 1'b1;
								O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;

								R_ISTC_VAL 		  <= 1'b1;
								R_IMM_DATA_32BIT  <= 32'd0;
							end
							`DEF_ISTC_SUBU :
							begin
								O_GPR_RD_EN_A     <= 1'b1;
								O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
								O_GPR_RD_EN_B     <= 1'b1;
								O_GPR_RD_ADDR_B   <= W_DST_GPR_ADDR;

								R_ALU_OP_TYPE     <= `DEF_ALU_SUBU_OPR;
								O_DST_GPR_WR_EN   <= 1'b1;
								O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;

								R_ISTC_VAL 		  <= 1'b1;
								R_IMM_DATA_32BIT  <= 32'd0;
							end
							`DEF_ISTC_SLT  :
							begin
								O_GPR_RD_EN_A     <= 1'b1;
								O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
								O_GPR_RD_EN_B     <= 1'b1;
								O_GPR_RD_ADDR_B   <= W_DST_GPR_ADDR;

								R_ALU_OP_TYPE     <= `DEF_ALU_SLT_OPR;
								O_DST_GPR_WR_EN   <= 1'b1;
								O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;

								R_ISTC_VAL 		  <= 1'b1;
								R_IMM_DATA_32BIT  <= 32'd0;
							end
							`DEF_ISTC_SLTU :
							begin
								O_GPR_RD_EN_A     <= 1'b1;
								O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
								O_GPR_RD_EN_B     <= 1'b1;
								O_GPR_RD_ADDR_B   <= W_DST_GPR_ADDR;

								R_ALU_OP_TYPE     <= `DEF_ALU_SLTU_OPR;
								O_DST_GPR_WR_EN   <= 1'b1;
								O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;

								R_ISTC_VAL 		  <= 1'b1;
								R_IMM_DATA_32BIT  <= 32'd0;
							end
							`DEF_ISTC_MULT :
							begin
								O_GPR_RD_EN_A     <= 1'b1;
								O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
								O_GPR_RD_EN_B     <= 1'b1;
								O_GPR_RD_ADDR_B   <= W_DST_GPR_ADDR;

								R_ALU_OP_TYPE     <= `DEF_ALU_MULT_OPR;
								O_DST_GPR_WR_EN   <= 1'b0;
								O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP;

								R_ISTC_VAL 		  <= 1'b1;
								R_IMM_DATA_32BIT  <= 32'd0;
							end 
							`DEF_ISTC_MULTU:
							begin
								O_GPR_RD_EN_A     <= 1'b1;
								O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
								O_GPR_RD_EN_B     <= 1'b1;
								O_GPR_RD_ADDR_B   <= W_DST_GPR_ADDR;

								R_ALU_OP_TYPE     <= `DEF_ALU_MULTU_OPR;
								O_DST_GPR_WR_EN   <= 1'b0;
								O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP;

								R_ISTC_VAL 		  <= 1'b1;
								R_IMM_DATA_32BIT  <= 32'd0;
							end
							`DEF_ISTC_DIV  :
							begin
								O_GPR_RD_EN_A     <= 1'b1;
								O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
								O_GPR_RD_EN_B     <= 1'b1;
								O_GPR_RD_ADDR_B   <= W_DST_GPR_ADDR;

								R_ALU_OP_TYPE     <= `DEF_ALU_DIV_OPR;
								O_DST_GPR_WR_EN   <= 1'b0;
								O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP;

								R_ISTC_VAL 		  <= 1'b1;
								R_IMM_DATA_32BIT  <= 32'd0;
							end
							`DEF_ISTC_DIVU :
							begin
								O_GPR_RD_EN_A     <= 1'b1;
								O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
								O_GPR_RD_EN_B     <= 1'b1;
								O_GPR_RD_ADDR_B   <= W_DST_GPR_ADDR;

								R_ALU_OP_TYPE     <= `DEF_ALU_DIVU_OPR;
								O_DST_GPR_WR_EN   <= 1'b0;
								O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP;

								R_ISTC_VAL 		  <= 1'b1;
								R_IMM_DATA_32BIT  <= 32'd0;
							end													
							default:
							begin
								O_GPR_RD_EN_A	  <= 1'b0;
								O_GPR_RD_ADDR_A   <= `DEF_GPR_ADDR_NOP;
								O_GPR_RD_EN_B	  <= 1'b0;
								O_GPR_RD_ADDR_B	  <= `DEF_GPR_ADDR_NOP;

								R_ALU_OP_TYPE     <= `DEF_ALU_NOP_OPR;
								// O_ALU_SEL         <= `DEF_ALU_SEL_NOP;
								O_DST_GPR_WR_EN   <= 1'b0;
								O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP;
		
								R_ISTC_VAL		  <= 1'b0;
								R_IMM_DATA_32BIT  <= 32'd0;
							end
						endcase
					end
					default:
					begin
						O_GPR_RD_EN_A	  <= 1'b0;
						O_GPR_RD_ADDR_A   <= `DEF_GPR_ADDR_NOP;
						O_GPR_RD_EN_B	  <= 1'b0;
						O_GPR_RD_ADDR_B	  <= `DEF_GPR_ADDR_NOP;

						R_ALU_OP_TYPE     <= `DEF_ALU_NOP_OPR;
						// O_ALU_SEL         <= `DEF_ALU_SEL_NOP;
						O_DST_GPR_WR_EN   <= 1'b0;
						O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP;
		
						R_ISTC_VAL		  <= 1'b0;
						R_IMM_DATA_32BIT  <= 32'd0;
					end
				endcase
			end
			`DEF_ISTC_SPEC2:
			begin
				case(W_ISTC_5_0_BIT)
					`DEF_ISTC_CLZ:
					begin
						O_GPR_RD_EN_A	  <= 1'b1;
						O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
						O_GPR_RD_EN_B	  <= 1'b0;
						O_GPR_RD_ADDR_B	  <= `DEF_GPR_ADDR_NOP;

						R_ALU_OP_TYPE     <= `DEF_ALU_CLZ_OPR;
						// O_ALU_SEL         <= `DEF_ALU_SEL_NOP;
						O_DST_GPR_WR_EN   <= 1'b1;
						O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;
		
						R_ISTC_VAL		  <= 1'b1;
						R_IMM_DATA_32BIT  <= 32'd0;
					end
					`DEF_ISTC_CLO:
					begin
						O_GPR_RD_EN_A	  <= 1'b1;
						O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
						O_GPR_RD_EN_B	  <= 1'b0;
						O_GPR_RD_ADDR_B	  <= `DEF_GPR_ADDR_NOP;

						R_ALU_OP_TYPE     <= `DEF_ALU_CLO_OPR;
						// O_ALU_SEL         <= `DEF_ALU_SEL_NOP;
						O_DST_GPR_WR_EN   <= 1'b1;
						O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;
		
						R_ISTC_VAL		  <= 1'b1;
						R_IMM_DATA_32BIT  <= 32'd0;
					end
					`DEF_ISTC_MUL:
					begin
						O_GPR_RD_EN_A	  <= 1'b1;
						O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
						O_GPR_RD_EN_B	  <= 1'b1;
						O_GPR_RD_ADDR_B	  <= W_DST_GPR_ADDR;

						R_ALU_OP_TYPE     <= `DEF_ALU_MUL_OPR;
						// O_ALU_SEL         <= `DEF_ALU_SEL_NOP;
						O_DST_GPR_WR_EN   <= 1'b1;
						O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;
		
						R_ISTC_VAL		  <= 1'b1;
						R_IMM_DATA_32BIT  <= 32'd0;
					end
					`DEF_ISTC_MADD:
					begin
						O_GPR_RD_EN_A     <= 1'b1;
						O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
						O_GPR_RD_EN_B     <= 1'b1;
						O_GPR_RD_ADDR_B   <= W_DST_GPR_ADDR;

						R_ALU_OP_TYPE     <= `DEF_ALU_MADD_OPR;
						O_DST_GPR_WR_EN   <= 1'b0;
						O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP;

						R_ISTC_VAL 		  <= 1'b1;
						R_IMM_DATA_32BIT  <= 32'd0;
					end
					`DEF_ISTC_MADDU:
					begin
						O_GPR_RD_EN_A     <= 1'b1;
						O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
						O_GPR_RD_EN_B     <= 1'b1;
						O_GPR_RD_ADDR_B   <= W_DST_GPR_ADDR;

						R_ALU_OP_TYPE     <= `DEF_ALU_MADDU_OPR;
						O_DST_GPR_WR_EN   <= 1'b0;
						O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP;

						R_ISTC_VAL 		  <= 1'b1;
						R_IMM_DATA_32BIT  <= 32'd0;						
					end
					`DEF_ISTC_MSUB :
					begin
						O_GPR_RD_EN_A     <= 1'b1;
						O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
						O_GPR_RD_EN_B     <= 1'b1;
						O_GPR_RD_ADDR_B   <= W_DST_GPR_ADDR;

						R_ALU_OP_TYPE     <= `DEF_ALU_MSUB_OPR;
						O_DST_GPR_WR_EN   <= 1'b0;
						O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP;

						R_ISTC_VAL 		  <= 1'b1;
						R_IMM_DATA_32BIT  <= 32'd0;						
					end
					`DEF_ISTC_MSUBU:
					begin
						O_GPR_RD_EN_A     <= 1'b1;
						O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
						O_GPR_RD_EN_B     <= 1'b1;
						O_GPR_RD_ADDR_B   <= W_DST_GPR_ADDR;

						R_ALU_OP_TYPE     <= `DEF_ALU_MSUBU_OPR;
						O_DST_GPR_WR_EN   <= 1'b0;
						O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP;

						R_ISTC_VAL 		  <= 1'b1;
						R_IMM_DATA_32BIT  <= 32'd0;						
					end
					default:
					begin
						O_GPR_RD_EN_A	  <= 1'b0;
						O_GPR_RD_ADDR_A   <= `DEF_GPR_ADDR_NOP;
						O_GPR_RD_EN_B	  <= 1'b0;
						O_GPR_RD_ADDR_B	  <= `DEF_GPR_ADDR_NOP;

						R_ALU_OP_TYPE     <= `DEF_ALU_NOP_OPR;
						// O_ALU_SEL         <= `DEF_ALU_SEL_NOP;
						O_DST_GPR_WR_EN   <= 1'b0;
						O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP;
		
						R_ISTC_VAL		  <= 1'b0;
						R_IMM_DATA_32BIT  <= 32'd0;
					end
				endcase
			end
			`DEF_ISTC_ORI:// ori指令
			begin
				O_GPR_RD_EN_A	  <= 1'b1;
				O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
				O_GPR_RD_EN_B	  <= 1'b0;
				O_GPR_RD_ADDR_B	  <= `DEF_GPR_ADDR_NOP;

				R_ALU_OP_TYPE     <= `DEF_ALU_OR_OPR;
				// O_ALU_SEL         <= `DEF_ALU_SEL_LOGIC;
				O_DST_GPR_WR_EN   <= 1'b1;
				O_DST_GPR_WR_ADDR <= W_DST_GPR_ADDR;

				R_ISTC_VAL		  <= 1'b1;
				R_IMM_DATA_32BIT  <= {16'd0,W_ISTC_IMM_DATA};
			end
			`DEF_ISTC_ANDI:
			begin
				O_GPR_RD_EN_A	  <= 1'b1;
				O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
				O_GPR_RD_EN_B	  <= 1'b0;
				O_GPR_RD_ADDR_B	  <= `DEF_GPR_ADDR_NOP;

				R_ALU_OP_TYPE     <= `DEF_ALU_AND_OPR;
				// O_ALU_SEL         <= `DEF_ALU_SEL_LOGIC;
				O_DST_GPR_WR_EN   <= 1'b1;
				O_DST_GPR_WR_ADDR <= W_DST_GPR_ADDR;

				R_ISTC_VAL		  <= 1'b1;
				R_IMM_DATA_32BIT  <= {16'd0,W_ISTC_IMM_DATA};
			end
			`DEF_ISTC_XORI:
			begin
				O_GPR_RD_EN_A	  <= 1'b1;
				O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
				O_GPR_RD_EN_B	  <= 1'b0;
				O_GPR_RD_ADDR_B	  <= `DEF_GPR_ADDR_NOP;

				R_ALU_OP_TYPE     <= `DEF_ALU_XOR_OPR;
				// O_ALU_SEL         <= `DEF_ALU_SEL_LOGIC;
				O_DST_GPR_WR_EN   <= 1'b1;
				O_DST_GPR_WR_ADDR <= W_DST_GPR_ADDR;

				R_ISTC_VAL		  <= 1'b1;
				R_IMM_DATA_32BIT  <= {16'd0,W_ISTC_IMM_DATA};
			end
			`DEF_ISTC_LUI:
			begin
				O_GPR_RD_EN_A	  <= 1'b1;
				O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
				O_GPR_RD_EN_B	  <= 1'b0;
				O_GPR_RD_ADDR_B	  <= `DEF_GPR_ADDR_NOP;

				R_ALU_OP_TYPE     <= `DEF_ALU_OR_OPR;
				// O_ALU_SEL         <= `DEF_ALU_SEL_LOGIC;
				O_DST_GPR_WR_EN   <= 1'b1;
				O_DST_GPR_WR_ADDR <= W_DST_GPR_ADDR;

				R_ISTC_VAL		  <= 1'b1;
				R_IMM_DATA_32BIT  <= {W_ISTC_IMM_DATA,16'd0};
			end
			`DEF_ISTC_PREF:
			begin
				O_GPR_RD_EN_A	  <= 1'b0;
				O_GPR_RD_ADDR_A   <= `DEF_GPR_ADDR_NOP;
				O_GPR_RD_EN_B	  <= 1'b0;
				O_GPR_RD_ADDR_B	  <= `DEF_GPR_ADDR_NOP;

				R_ALU_OP_TYPE     <= `DEF_ALU_NOP_OPR;
				// O_ALU_SEL         <= `DEF_ALU_SEL_LOGIC;
				O_DST_GPR_WR_EN   <= 1'b0;
				O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP;

				R_ISTC_VAL		  <= 1'b1;
				R_IMM_DATA_32BIT  <= 32'd0;
			end
			`DEF_ISTC_ADDI :
			begin
				O_GPR_RD_EN_A	  <= 1'b1;
				O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
				O_GPR_RD_EN_B	  <= 1'b0;
				O_GPR_RD_ADDR_B	  <= `DEF_GPR_ADDR_NOP;

				R_ALU_OP_TYPE     <= `DEF_ALU_ADDI_OPR;
				// O_ALU_SEL         <= `DEF_ALU_SEL_LOGIC;
				O_DST_GPR_WR_EN   <= 1'b1;
				O_DST_GPR_WR_ADDR <= W_DST_GPR_ADDR;

				R_ISTC_VAL		  <= 1'b1;
				R_IMM_DATA_32BIT  <= {{16{W_ISTC_IMM_DATA[15]}},W_ISTC_IMM_DATA};
			end
			`DEF_ISTC_ADDIU:
			begin
				O_GPR_RD_EN_A	  <= 1'b1;
				O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
				O_GPR_RD_EN_B	  <= 1'b0;
				O_GPR_RD_ADDR_B	  <= `DEF_GPR_ADDR_NOP;

				R_ALU_OP_TYPE     <= `DEF_ALU_ADDIU_OPR;
				// O_ALU_SEL         <= `DEF_ALU_SEL_LOGIC;
				O_DST_GPR_WR_EN   <= 1'b1;
				O_DST_GPR_WR_ADDR <= W_DST_GPR_ADDR;

				R_ISTC_VAL		  <= 1'b1;
				R_IMM_DATA_32BIT  <= {{16{W_ISTC_IMM_DATA[15]}},W_ISTC_IMM_DATA};
			end
			`DEF_ISTC_SLTI :
			begin
				O_GPR_RD_EN_A	  <= 1'b1;
				O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
				O_GPR_RD_EN_B	  <= 1'b0;
				O_GPR_RD_ADDR_B	  <= `DEF_GPR_ADDR_NOP;

				R_ALU_OP_TYPE     <= `DEF_ALU_SLTI_OPR;
				// O_ALU_SEL         <= `DEF_ALU_SEL_LOGIC;
				O_DST_GPR_WR_EN   <= 1'b1;
				O_DST_GPR_WR_ADDR <= W_DST_GPR_ADDR;

				R_ISTC_VAL		  <= 1'b1;
				R_IMM_DATA_32BIT  <= {{16{W_ISTC_IMM_DATA[15]}},W_ISTC_IMM_DATA};
			end
			`DEF_ISTC_SLTIU:
			begin
				O_GPR_RD_EN_A	  <= 1'b1;
				O_GPR_RD_ADDR_A   <= W_SRC_GPR_ADDR;
				O_GPR_RD_EN_B	  <= 1'b0;
				O_GPR_RD_ADDR_B	  <= `DEF_GPR_ADDR_NOP;

				R_ALU_OP_TYPE     <= `DEF_ALU_SLTIU_OPR;
				// O_ALU_SEL         <= `DEF_ALU_SEL_LOGIC;
				O_DST_GPR_WR_EN   <= 1'b1;
				O_DST_GPR_WR_ADDR <= W_DST_GPR_ADDR;

				R_ISTC_VAL		  <= 1'b1;
				R_IMM_DATA_32BIT  <= {{16{W_ISTC_IMM_DATA[15]}},W_ISTC_IMM_DATA};
			end
			default:
			begin
				O_GPR_RD_EN_A	  <= 1'b0;
				O_GPR_RD_ADDR_A   <= `DEF_GPR_ADDR_NOP;
				O_GPR_RD_EN_B	  <= 1'b0;
				O_GPR_RD_ADDR_B	  <= `DEF_GPR_ADDR_NOP;

				R_ALU_OP_TYPE     <= `DEF_ALU_NOP_OPR;
				// O_ALU_SEL         <= `DEF_ALU_SEL_NOP;
				O_DST_GPR_WR_EN   <= 1'b0;
				O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP;
		
				R_ISTC_VAL		  <= 1'b0;
				R_IMM_DATA_32BIT  <= 32'd0;
			end
		endcase

		if(W_I_ISTC[31:21] == 11'd0)
		begin
			case(W_ISTC_5_0_BIT)
				`DEF_ISTC_SLL:
				begin
					O_GPR_RD_EN_A	  <= 1'b0;
					O_GPR_RD_ADDR_A   <= `DEF_GPR_ADDR_NOP;
					O_GPR_RD_EN_B	  <= 1'b1;
					O_GPR_RD_ADDR_B	  <= W_DST_GPR_ADDR;

					R_ALU_OP_TYPE     <= `DEF_ALU_SLL_OPR;
					// O_ALU_SEL         <= `DEF_ALU_SEL_LOGIC;
					O_DST_GPR_WR_EN   <= 1'b1;
					O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;

					R_ISTC_VAL		  <= 1'b1;
					R_IMM_DATA_32BIT  <= {27'd0,W_ISTC_10_6_BIT};
				end
				`DEF_ISTC_SRL:
				begin
					O_GPR_RD_EN_A	  <= 1'b0;
					O_GPR_RD_ADDR_A   <= `DEF_GPR_ADDR_NOP;
					O_GPR_RD_EN_B	  <= 1'b1;
					O_GPR_RD_ADDR_B	  <= W_DST_GPR_ADDR;

					R_ALU_OP_TYPE     <= `DEF_ALU_SRL_OPR;
					// O_ALU_SEL         <= `DEF_ALU_SEL_LOGIC;
					O_DST_GPR_WR_EN   <= 1'b1;
					O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;

					R_ISTC_VAL		  <= 1'b1;
					R_IMM_DATA_32BIT  <= {27'd0,W_ISTC_10_6_BIT};
				end
				`DEF_ISTC_SRA:
				begin
					O_GPR_RD_EN_A	  <= 1'b0;
					O_GPR_RD_ADDR_A   <= `DEF_GPR_ADDR_NOP;
					O_GPR_RD_EN_B	  <= 1'b1;
					O_GPR_RD_ADDR_B	  <= W_DST_GPR_ADDR;

					R_ALU_OP_TYPE     <= `DEF_ALU_SRA_OPR;
					// O_ALU_SEL         <= `DEF_ALU_SEL_LOGIC;
					O_DST_GPR_WR_EN   <= 1'b1;
					O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;

					R_ISTC_VAL		  <= 1'b1;
					R_IMM_DATA_32BIT  <= {27'd0,W_ISTC_10_6_BIT};
				end
				default:
				begin
					O_GPR_RD_EN_A	  <= 1'b0;
					O_GPR_RD_ADDR_A   <= `DEF_GPR_ADDR_NOP;
					O_GPR_RD_EN_B	  <= 1'b0;
					O_GPR_RD_ADDR_B	  <= `DEF_GPR_ADDR_NOP;

					R_ALU_OP_TYPE     <= `DEF_ALU_NOP_OPR;
					// O_ALU_SEL         <= `DEF_ALU_SEL_NOP;
					O_DST_GPR_WR_EN   <= 1'b0;
					O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP;
			
					R_ISTC_VAL		  <= 1'b0;
					R_IMM_DATA_32BIT  <= 32'd0;
				end
			endcase
		end
	end
end

// | 数据输出
always @ (posedge I_CPU_CLK)
begin
	if(~I_CPU_RSTN)
	begin
		O_SRC_OPR_DATA_A <= `DEF_ZERO_WORD;
	end
	else if(I_DST_GPR_WR_EN_FROM_EXE_MDL && O_GPR_RD_EN_A && (O_GPR_RD_ADDR_A == I_DST_GPR_WR_ADDR_FROM_EXE_MDL))
	begin
		O_SRC_OPR_DATA_A <= I_DST_GPR_WR_DATA_FROM_EXE_MDL;
	end
	else if(I_DST_GPR_WR_EN_FROM_MEM_ACS_MDL && O_GPR_RD_EN_A && (O_GPR_RD_ADDR_A == I_DST_GPR_WR_ADDR_FROM_MEM_ACS_MDL))
	begin
		O_SRC_OPR_DATA_A <= I_DST_GPR_WR_DATA_FROM_MEM_ACS_MDL;
	end
	else if(O_GPR_RD_EN_A)
	begin
		O_SRC_OPR_DATA_A <= I_GPR_RD_DATA_A;
	end
	else if(~O_GPR_RD_EN_A)
	begin
		O_SRC_OPR_DATA_A <= R_IMM_DATA_32BIT;
	end
	else
	begin
		O_SRC_OPR_DATA_A <= `DEF_ZERO_WORD;
	end
end


always @ (posedge I_CPU_CLK)
begin
	if(~I_CPU_RSTN)
	begin
		O_SRC_OPR_DATA_B <= `DEF_ZERO_WORD;
	end
	else if(I_DST_GPR_WR_EN_FROM_EXE_MDL && O_GPR_RD_EN_B && (O_GPR_RD_ADDR_B == I_DST_GPR_WR_ADDR_FROM_EXE_MDL))
	begin
		O_SRC_OPR_DATA_B <= I_DST_GPR_WR_DATA_FROM_EXE_MDL;
	end
	else if(I_DST_GPR_WR_EN_FROM_MEM_ACS_MDL && O_GPR_RD_EN_B && (O_GPR_RD_ADDR_B == I_DST_GPR_WR_ADDR_FROM_MEM_ACS_MDL))
	begin
		O_SRC_OPR_DATA_B <= I_DST_GPR_WR_DATA_FROM_MEM_ACS_MDL;
	end
	else if(O_GPR_RD_EN_B)
	begin
		O_SRC_OPR_DATA_B <= I_GPR_RD_DATA_B;
	end
	else if(~O_GPR_RD_EN_B)
	begin
		O_SRC_OPR_DATA_B <= R_IMM_DATA_32BIT;
	end
	else
	begin
		O_SRC_OPR_DATA_B <= `DEF_ZERO_WORD;
	end
end


endmodule

执行模块

// |------------------------------ ================================== ------------------------------
// |============================== 		     指令-执行模块  	      ==============================
// |------------------------------ ================================== ------------------------------
// |Create Date : 2022-12-07
// |Finish Date : 2022-12-07
// |Edited by   : Xu Y. B. (CSDN USER NAME :在路上,正出发)
// |Reference   : 《自己动手写CPU》
// |
// |
// |------------------------------------------------------------------------------------------------
// |---------------------------------------- Change History ----------------------------------------
// |Date:2022-12-08
// |Who :Xu Y. B.
// |What:修复流水线数据相关的问题(第 2、3类问题)
// |	 增加模块端口:Line 42 - 44
// |	 两部分输出区别:组合逻辑输出和时序逻辑输出
// |	 代码变动行编号:Line 73、77、84、88、103、111、115、116
// |Date:2022-12-09
// |Who :Xu Y. B.
// |What:增加逻辑、移位运算执行功能
// |Date:2022-12-11
// |Who :Xu Y. B.
// |What:增加移动运算执行功能
// |Date:2022-12-12
// |Who :Xu Y. B.
// |What:增加简单算术运算执行功能
// |Date:2022-12-14
// |Who :Xu Y. B.
// |What:增加2步算术运算执行功能
// |Date:2022-12-16
// |Who :Xu Y. B.
// |What:增加除法算术运算执行功能

`include "MIPS_SYS_DEFINES.v"
`timescale 1ns / 1ps

module EXE_MDL(

// |--------------------------------------  输入输出端口声明  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 时钟、复位
input 															I_CPU_CLK,
input 															I_CPU_RSTN,
// | 操作指令
// input		[`DEF_ALU_SEL_BUS]									I_ALU_SEL,		
input 		[`DEF_ALU_OPR_BUS]									I_ALU_OP_TYPE,	
// | 源操作数
input 		[`DEF_SRC_OPR_DATA_BUS]								I_SRC_OPR_DATA_A,
input 		[`DEF_SRC_OPR_DATA_BUS]								I_SRC_OPR_DATA_B,
// | 目的寄存器写
input 															I_DST_GPR_WR_EN,
input 		[`DEF_GPR_ADDR_WIDTH-1:0]							I_DST_GPR_WR_ADDR,

// | HI LO 寄存器
// | HI_LO_REG_MDL 的输出
input		[`DEF_GPR_DATA_WIDTH-1:0]							I_HI,
input		[`DEF_GPR_DATA_WIDTH-1:0]							I_LO,
// | MEM_ACS_MDL 输出
input		[`DEF_GPR_DATA_WIDTH-1:0]							I_HI_FROM_MEM_ACS_MDL,
input		[`DEF_GPR_DATA_WIDTH-1:0]							I_LO_FROM_MEM_ACS_MDL,
input 															I_WR_EN_FROM_MEM_ACS_MDL,
// | HI_LO_REG_MDL 的输入
input		[`DEF_GPR_DATA_WIDTH-1:0]							I_HI_FROM_HI_LO_REG_MDL,
input		[`DEF_GPR_DATA_WIDTH-1:0]							I_LO_FROM_HI_LO_REG_MDL,
input 															I_WR_EN_FROM_HI_LO_REG_MDL,


// | 输出 
output 	reg														O_DST_GPR_WR_EN,   
output 	reg	[`DEF_GPR_ADDR_WIDTH-1:0]							O_DST_GPR_WR_ADDR, 
output  reg [`DEF_GPR_DATA_WIDTH-1:0]							O_DST_GPR_WR_DATA,
// 反馈至 译码模块
output 															O_DST_GPR_WR_EN_2_ID_MDL,   
output 		[`DEF_GPR_ADDR_WIDTH-1:0]							O_DST_GPR_WR_ADDR_2_ID_MDL, 
output  reg [`DEF_GPR_DATA_WIDTH-1:0]							O_DST_GPR_WR_DATA_2_ID_MDL,

// 寄存器输出
output	reg	[`DEF_GPR_DATA_WIDTH-1:0]							O_HI,
output	reg	[`DEF_GPR_DATA_WIDTH-1:0]							O_LO,
output 	reg														O_HILO_WR_EN,

// 流水线暂停
input 		[4:0]												I_PAUSE_ACK,//待优化
output 	reg														O_PAUSE_REQ


    );
// |--------------------------------------  模块内部信号声明  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | I_ALU_OP_TYPE 打拍
reg 		[`DEF_ALU_OPR_BUS]									R_I_ALU_OP_TYPE;
reg         													R_I_DST_GPR_WR_EN;
reg         [`DEF_GPR_ADDR_WIDTH-1:0]							R_I_DST_GPR_WR_ADDR;

reg 		[`DEF_GPR_DATA_WIDTH-1:0]							R_HI;
reg 		[`DEF_GPR_DATA_WIDTH-1:0]							R_LO; 	
// 组合逻辑输出
reg 		[`DEF_GPR_DATA_WIDTH-1:0]							R_O_HI;
reg 		[`DEF_GPR_DATA_WIDTH-1:0]							R_O_LO;
reg 															R_O_HILO_WR_EN;

wire signed	[`DEF_SRC_OPR_DATA_BUS]								W_I_SRC_OPR_DATA_A_SIGNED;
wire signed	[`DEF_SRC_OPR_DATA_BUS]								W_I_SRC_OPR_DATA_B_SIGNED;	
wire signed [`DEF_SRC_OPR_DATA_BUS]								W_A_ADD_B_SIGNED;
wire signed [`DEF_SRC_OPR_DATA_BUS]								W_A_SUB_B_SIGNED;
wire 															W_OVER_FLOW_FLAG;

// reg         [31:0]												W_MUL_RES_H32;
// 暂存 乘加、乘减 的中间运算结果
reg 		[63:0]												R_MID_RES_MULT;
// 2步运算指令计数器
reg         [1:0]												R_2STEP_ISTC_CNT;//位宽可能存在冗余

// 除法运算
wire													        W_DIV_RES_VAL;
wire [63:0]												        W_DIV_RES;
reg 													        R_DIV_TYPE;
reg [31:0]												        R_OPR_DATA_A;
reg [31:0]												        R_OPR_DATA_B;
reg 													        R_OPR_EN;
reg 													        R_OPR_CANCEL;

reg 															R_PAUSE_REQ;
reg 															R_R_DIV_TYPE;

// |--------------------------------------  模块内部逻辑设计  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | I_ALU_OP_TYPE 打拍对齐时序
always @ (posedge I_CPU_CLK)
begin
	if(~I_CPU_RSTN)
	begin
		R_I_ALU_OP_TYPE <= 0;
	end
	else if(!I_PAUSE_ACK[2])
	begin
		R_I_ALU_OP_TYPE <= I_ALU_OP_TYPE;
	end
	else
	begin
		R_I_ALU_OP_TYPE <= R_I_ALU_OP_TYPE;
	end
end
// | 判断选择最新的 HI LO 
always @ (*)
begin
	if(~I_CPU_RSTN)
	begin
		R_HI = `DEF_ZERO_WORD;
		R_LO = `DEF_ZERO_WORD;
	end
	else if(I_WR_EN_FROM_MEM_ACS_MDL)
	begin
		R_HI = I_HI_FROM_MEM_ACS_MDL;
		R_LO = I_LO_FROM_MEM_ACS_MDL;
	end
	else if(I_WR_EN_FROM_HI_LO_REG_MDL)
	begin
		R_HI = I_HI_FROM_HI_LO_REG_MDL;
		R_LO = I_LO_FROM_HI_LO_REG_MDL;
	end
	else
	begin
		R_HI = I_HI;
		R_LO = I_LO;
	end
end
// | 操作数有符号形式
assign W_I_SRC_OPR_DATA_A_SIGNED = I_SRC_OPR_DATA_A;
assign W_I_SRC_OPR_DATA_B_SIGNED = I_SRC_OPR_DATA_B;
assign W_A_ADD_B_SIGNED          = W_I_SRC_OPR_DATA_A_SIGNED + W_I_SRC_OPR_DATA_B_SIGNED;
assign W_A_SUB_B_SIGNED          = W_I_SRC_OPR_DATA_A_SIGNED - W_I_SRC_OPR_DATA_B_SIGNED;
assign W_OVER_FLOW_FLAG 		 = (!W_I_SRC_OPR_DATA_A_SIGNED[31] && !W_I_SRC_OPR_DATA_B_SIGNED[31] && W_A_ADD_B_SIGNED[31])
								   ||
								   ( W_I_SRC_OPR_DATA_A_SIGNED[31] &&  W_I_SRC_OPR_DATA_B_SIGNED[31] && !W_A_ADD_B_SIGNED[31]);
// | 计算单元
// 组合逻辑
always @ (*)
begin
	if(~I_CPU_RSTN)
	begin
		O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD;

		R_O_HILO_WR_EN			   = 1'b0;
		R_O_HI 					   = `DEF_ZERO_WORD;
		R_O_LO 					   = `DEF_ZERO_WORD;
	end
	else
	begin
		case(R_I_ALU_OP_TYPE)
			`DEF_ALU_OR_OPR:
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = I_SRC_OPR_DATA_A | I_SRC_OPR_DATA_B;

				R_O_HILO_WR_EN			   = 1'b0;
				R_O_HI 					   = `DEF_ZERO_WORD;
				R_O_LO 					   = `DEF_ZERO_WORD;
			end
			`DEF_ALU_AND_OPR:
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = I_SRC_OPR_DATA_A & I_SRC_OPR_DATA_B;

				R_O_HILO_WR_EN			   = 1'b0;
				R_O_HI 					   = `DEF_ZERO_WORD;
				R_O_LO 					   = `DEF_ZERO_WORD;
			end
			`DEF_ALU_XOR_OPR:
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = I_SRC_OPR_DATA_A ^ I_SRC_OPR_DATA_B;

				R_O_HILO_WR_EN			   = 1'b0;
				R_O_HI 					   = `DEF_ZERO_WORD;
				R_O_LO 					   = `DEF_ZERO_WORD;
			end
			`DEF_ALU_NOR_OPR:
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = ~(I_SRC_OPR_DATA_A | I_SRC_OPR_DATA_B);

				R_O_HILO_WR_EN			   = 1'b0;
				R_O_HI 					   = `DEF_ZERO_WORD;
				R_O_LO 					   = `DEF_ZERO_WORD;
			end
			`DEF_ALU_SLL_OPR:
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = I_SRC_OPR_DATA_B << I_SRC_OPR_DATA_A;

				R_O_HILO_WR_EN			   = 1'b0;
				R_O_HI 					   = `DEF_ZERO_WORD;
				R_O_LO 					   = `DEF_ZERO_WORD;
			end
			`DEF_ALU_SRL_OPR:
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = I_SRC_OPR_DATA_B >> I_SRC_OPR_DATA_A;

				R_O_HILO_WR_EN			   = 1'b0;
				R_O_HI 					   = `DEF_ZERO_WORD;
				R_O_LO 					   = `DEF_ZERO_WORD;
			end
			`DEF_ALU_SRA_OPR:
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = ({32{I_SRC_OPR_DATA_B[31]}} << (6'd32 - I_SRC_OPR_DATA_A[5:0])) | (I_SRC_OPR_DATA_B >> I_SRC_OPR_DATA_A);

				R_O_HILO_WR_EN			   = 1'b0;
				R_O_HI 					   = `DEF_ZERO_WORD;
				R_O_LO 					   = `DEF_ZERO_WORD;
			end
			`DEF_ALU_MOVZ_OPR:
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = I_SRC_OPR_DATA_A;

				R_O_HILO_WR_EN			   = 1'b0;
				R_O_HI 					   = `DEF_ZERO_WORD;
				R_O_LO 					   = `DEF_ZERO_WORD;
			end
			`DEF_ALU_MOVN_OPR:
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = I_SRC_OPR_DATA_A;

				R_O_HILO_WR_EN			   = 1'b0;
				R_O_HI 					   = `DEF_ZERO_WORD;
				R_O_LO 					   = `DEF_ZERO_WORD;
			end
			`DEF_ALU_MFHI_OPR:
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = R_HI;

				R_O_HILO_WR_EN			   = 1'b0;
				R_O_HI 					   = `DEF_ZERO_WORD;
				R_O_LO 					   = `DEF_ZERO_WORD;
			end
			`DEF_ALU_MTHI_OPR:
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD;

				R_O_HILO_WR_EN			   = 1'b1;
				R_O_HI 					   = I_SRC_OPR_DATA_A;
				R_O_LO 					   = R_LO;
			end
			`DEF_ALU_MFLO_OPR:
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = R_LO;

				R_O_HILO_WR_EN			   = 1'b0;
				R_O_HI 					   = `DEF_ZERO_WORD;
				R_O_LO 					   = `DEF_ZERO_WORD;
			end
			`DEF_ALU_MTLO_OPR:
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD;

				R_O_HILO_WR_EN			   = 1'b1;
				R_O_HI 					   = R_HI;
				R_O_LO 					   = I_SRC_OPR_DATA_A;
			end
			`DEF_ALU_SLT_OPR  :
			begin
				if(W_I_SRC_OPR_DATA_A_SIGNED < W_I_SRC_OPR_DATA_B_SIGNED)
				begin
					O_DST_GPR_WR_DATA_2_ID_MDL = 32'd1;
				end
				else
				begin
					O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD;
				end

				R_O_HILO_WR_EN			   = 1'b0;
				R_O_HI 					   = `DEF_ZERO_WORD;
				R_O_LO 					   = `DEF_ZERO_WORD;			
			end
			`DEF_ALU_SLTU_OPR :
			begin
				if(I_SRC_OPR_DATA_A < I_SRC_OPR_DATA_B)
				begin
					O_DST_GPR_WR_DATA_2_ID_MDL = 32'd1;
				end
				else
				begin
					O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD;
				end

				R_O_HILO_WR_EN			   = 1'b0;
				R_O_HI 					   = `DEF_ZERO_WORD;
				R_O_LO 					   = `DEF_ZERO_WORD;				
			end
			`DEF_ALU_SLTI_OPR :
			begin
				if(W_I_SRC_OPR_DATA_A_SIGNED < W_I_SRC_OPR_DATA_B_SIGNED)
				begin
					O_DST_GPR_WR_DATA_2_ID_MDL = 32'd1;
				end
				else
				begin
					O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD;
				end

				R_O_HILO_WR_EN			   = 1'b0;
				R_O_HI 					   = `DEF_ZERO_WORD;
				R_O_LO 					   = `DEF_ZERO_WORD;					
			end
			`DEF_ALU_SLTIU_OPR:
			begin
				if(I_SRC_OPR_DATA_A < I_SRC_OPR_DATA_B)
				begin
					O_DST_GPR_WR_DATA_2_ID_MDL = 32'd1;
				end
				else
				begin
					O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD;
				end

				R_O_HILO_WR_EN			   = 1'b0;
				R_O_HI 					   = `DEF_ZERO_WORD;
				R_O_LO 					   = `DEF_ZERO_WORD;				
			end
			`DEF_ALU_ADD_OPR  :
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = W_A_ADD_B_SIGNED;

				R_O_HILO_WR_EN			   = 1'b0;
				R_O_HI 					   = `DEF_ZERO_WORD;
				R_O_LO 					   = `DEF_ZERO_WORD;				
			end
			`DEF_ALU_ADDU_OPR :
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = W_A_ADD_B_SIGNED;

				R_O_HILO_WR_EN			   = 1'b0;
				R_O_HI 					   = `DEF_ZERO_WORD;
				R_O_LO 					   = `DEF_ZERO_WORD;				
			end
			`DEF_ALU_SUB_OPR  :
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = W_A_SUB_B_SIGNED;

				R_O_HILO_WR_EN			   = 1'b0;
				R_O_HI 					   = `DEF_ZERO_WORD;
				R_O_LO 					   = `DEF_ZERO_WORD;					
			end
			`DEF_ALU_SUBU_OPR :
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = W_A_SUB_B_SIGNED;

				R_O_HILO_WR_EN			   = 1'b0;
				R_O_HI 					   = `DEF_ZERO_WORD;
				R_O_LO 					   = `DEF_ZERO_WORD;				
			end
			`DEF_ALU_ADDI_OPR :
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = W_A_ADD_B_SIGNED;

				R_O_HILO_WR_EN			   = 1'b0;
				R_O_HI 					   = `DEF_ZERO_WORD;
				R_O_LO 					   = `DEF_ZERO_WORD;					
			end
			`DEF_ALU_ADDIU_OPR:
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = W_A_ADD_B_SIGNED;

				R_O_HILO_WR_EN			   = 1'b0;
				R_O_HI 					   = `DEF_ZERO_WORD;
				R_O_LO 					   = `DEF_ZERO_WORD;					
			end
			`DEF_ALU_CLZ_OPR  :
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = I_SRC_OPR_DATA_A[31] ? 0  : I_SRC_OPR_DATA_A[30] ? 1  : I_SRC_OPR_DATA_A[29] ? 2  : I_SRC_OPR_DATA_A[28] ? 3  :
											 I_SRC_OPR_DATA_A[27] ? 4  : I_SRC_OPR_DATA_A[26] ? 5  : I_SRC_OPR_DATA_A[25] ? 6  : I_SRC_OPR_DATA_A[24] ? 7  :
											 I_SRC_OPR_DATA_A[23] ? 8  : I_SRC_OPR_DATA_A[22] ? 9  : I_SRC_OPR_DATA_A[21] ? 10 : I_SRC_OPR_DATA_A[20] ? 11 :
											 I_SRC_OPR_DATA_A[19] ? 12 : I_SRC_OPR_DATA_A[18] ? 13 : I_SRC_OPR_DATA_A[17] ? 14 : I_SRC_OPR_DATA_A[16] ? 15 :
											 I_SRC_OPR_DATA_A[15] ? 16 : I_SRC_OPR_DATA_A[14] ? 17 : I_SRC_OPR_DATA_A[13] ? 18 : I_SRC_OPR_DATA_A[12] ? 19 :
											 I_SRC_OPR_DATA_A[11] ? 20 : I_SRC_OPR_DATA_A[10] ? 21 : I_SRC_OPR_DATA_A[9]  ? 22 : I_SRC_OPR_DATA_A[8]  ? 23 :
											 I_SRC_OPR_DATA_A[7]  ? 24 : I_SRC_OPR_DATA_A[6]  ? 25 : I_SRC_OPR_DATA_A[5]  ? 26 : I_SRC_OPR_DATA_A[4]  ? 27 :
											 I_SRC_OPR_DATA_A[3]  ? 28 : I_SRC_OPR_DATA_A[2]  ? 29 : I_SRC_OPR_DATA_A[1]  ? 30 : I_SRC_OPR_DATA_A[0]  ? 31 : 32;

				R_O_HILO_WR_EN			   = 1'b0;
				R_O_HI 					   = `DEF_ZERO_WORD;
				R_O_LO 					   = `DEF_ZERO_WORD;				
			end
			`DEF_ALU_CLO_OPR  :
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = !I_SRC_OPR_DATA_A[31] ? 0  : !I_SRC_OPR_DATA_A[30] ? 1  : !I_SRC_OPR_DATA_A[29] ? 2  : !I_SRC_OPR_DATA_A[28] ? 3  :
											 !I_SRC_OPR_DATA_A[27] ? 4  : !I_SRC_OPR_DATA_A[26] ? 5  : !I_SRC_OPR_DATA_A[25] ? 6  : !I_SRC_OPR_DATA_A[24] ? 7  :
											 !I_SRC_OPR_DATA_A[23] ? 8  : !I_SRC_OPR_DATA_A[22] ? 9  : !I_SRC_OPR_DATA_A[21] ? 10 : !I_SRC_OPR_DATA_A[20] ? 11 :
											 !I_SRC_OPR_DATA_A[19] ? 12 : !I_SRC_OPR_DATA_A[18] ? 13 : !I_SRC_OPR_DATA_A[17] ? 14 : !I_SRC_OPR_DATA_A[16] ? 15 :
											 !I_SRC_OPR_DATA_A[15] ? 16 : !I_SRC_OPR_DATA_A[14] ? 17 : !I_SRC_OPR_DATA_A[13] ? 18 : !I_SRC_OPR_DATA_A[12] ? 19 :
											 !I_SRC_OPR_DATA_A[11] ? 20 : !I_SRC_OPR_DATA_A[10] ? 21 : !I_SRC_OPR_DATA_A[9]  ? 22 : !I_SRC_OPR_DATA_A[8]  ? 23 :
											 !I_SRC_OPR_DATA_A[7]  ? 24 : !I_SRC_OPR_DATA_A[6]  ? 25 : !I_SRC_OPR_DATA_A[5]  ? 26 : !I_SRC_OPR_DATA_A[4]  ? 27 :
											 !I_SRC_OPR_DATA_A[3]  ? 28 : !I_SRC_OPR_DATA_A[2]  ? 29 : !I_SRC_OPR_DATA_A[1]  ? 30 : !I_SRC_OPR_DATA_A[0]  ? 31 : 32;

				R_O_HILO_WR_EN			   = 1'b0;
				R_O_HI 					   = `DEF_ZERO_WORD;
				R_O_LO 					   = `DEF_ZERO_WORD;				
			end
			`DEF_ALU_MULT_OPR :
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD;

				R_O_HILO_WR_EN			   = 1'b1;
				{R_O_HI,R_O_LO}			   = W_I_SRC_OPR_DATA_A_SIGNED * W_I_SRC_OPR_DATA_B_SIGNED;				
			end
			`DEF_ALU_MULTU_OPR:
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD;

				R_O_HILO_WR_EN			   = 1'b1;
				{R_O_HI,R_O_LO}			   = I_SRC_OPR_DATA_A * I_SRC_OPR_DATA_B;				
			end
			`DEF_ALU_MUL_OPR  :
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = W_I_SRC_OPR_DATA_A_SIGNED * W_I_SRC_OPR_DATA_B_SIGNED;	

				R_O_HILO_WR_EN			   = 1'b0;
				R_O_HI 					   = `DEF_ZERO_WORD;
				R_O_LO 					   = `DEF_ZERO_WORD;			
			end		
			`DEF_ALU_MADD_OPR ,`DEF_ALU_MADDU_OPR:
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD;
				if(R_2STEP_ISTC_CNT == 1)
				begin
					R_O_HILO_WR_EN			   = 1'b1;
					{R_O_HI,R_O_LO}			   = {R_HI[31],R_HI,R_LO} + {R_MID_RES_MULT[63],R_MID_RES_MULT};	
				end
				else
				begin
					R_O_HILO_WR_EN			   = 1'b0;
					R_O_HI 					   = `DEF_ZERO_WORD;
					R_O_LO 					   = `DEF_ZERO_WORD;					
				end
			end
			`DEF_ALU_MSUB_OPR ,`DEF_ALU_MSUBU_OPR:
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD;
				if(R_2STEP_ISTC_CNT == 1)
				begin
					R_O_HILO_WR_EN			   = 1'b1;
					{R_O_HI,R_O_LO}			   = {R_HI[31],R_HI,R_LO} - {R_MID_RES_MULT[63],R_MID_RES_MULT};
				end
				else
				begin
					R_O_HILO_WR_EN			   = 1'b0;
					R_O_HI 					   = `DEF_ZERO_WORD;
					R_O_LO 					   = `DEF_ZERO_WORD;					
				end
			end
			`DEF_ALU_DIV_OPR,`DEF_ALU_DIVU_OPR :
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD;
				if(W_DIV_RES_VAL)
				begin
					R_O_HILO_WR_EN			   = 1'b1;
					{R_O_HI,R_O_LO}			   = W_DIV_RES;					
				end
				else
				begin
					R_O_HILO_WR_EN			   = 1'b0;
					R_O_HI 					   = `DEF_ZERO_WORD;
					R_O_LO 					   = `DEF_ZERO_WORD;					
				end
			end
			default:
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD;

				R_O_HILO_WR_EN			   = 1'b0;
				R_O_HI 					   = `DEF_ZERO_WORD;
				R_O_LO 					   = `DEF_ZERO_WORD;
			end
		endcase
	end
end

// HI LO 寄存输出
always @ (posedge I_CPU_CLK)
begin
	if(~I_CPU_RSTN)
	begin
		O_HILO_WR_EN <= 1'b0;
		O_HI 		 <= 32'd0;
		O_LO 		 <= 32'd0;
	end
	else
	begin
		if(!I_PAUSE_ACK[2])
		begin
			O_HILO_WR_EN <= R_O_HILO_WR_EN;
			O_HI 		 <= R_O_HI 		;
			O_LO 		 <= R_O_LO 		;	
		end	
		else
		begin
			O_HILO_WR_EN <= 1'b0;
			O_HI 		 <= 32'd0;
			O_LO 		 <= 32'd0;			
		end
	end
end

// | 写操作打拍
always @ (posedge I_CPU_CLK)
begin
	if(~I_CPU_RSTN)
	begin
		O_DST_GPR_WR_EN <= 1'b0;
		O_DST_GPR_WR_ADDR <= 5'd0;
		R_I_DST_GPR_WR_EN <= 1'b0;
		R_I_DST_GPR_WR_ADDR <= 5'd0;
		O_DST_GPR_WR_DATA <= `DEF_ZERO_WORD;
	end
	else
	begin
		if(!I_PAUSE_ACK[2])
		begin
			R_I_DST_GPR_WR_EN <= I_DST_GPR_WR_EN;
			R_I_DST_GPR_WR_ADDR <= I_DST_GPR_WR_ADDR;

			if(R_I_ALU_OP_TYPE == `DEF_ALU_MOVZ_OPR) 
			begin
				if(I_SRC_OPR_DATA_B == `DEF_ZERO_WORD)
				begin
					O_DST_GPR_WR_EN   <= 1'b1;
				end
				else
				begin
					O_DST_GPR_WR_EN   <= 1'b0;
				end
			end
			else if(R_I_ALU_OP_TYPE == `DEF_ALU_MOVN_OPR)
			begin
				if(I_SRC_OPR_DATA_B == `DEF_ZERO_WORD)
				begin
					O_DST_GPR_WR_EN   <= 1'b0;
				end
				else
				begin
					O_DST_GPR_WR_EN   <= 1'b1;
				end
			end
			else if((R_I_ALU_OP_TYPE == `DEF_ALU_ADD_OPR || R_I_ALU_OP_TYPE == 	`DEF_ALU_SUB_OPR || R_I_ALU_OP_TYPE == `DEF_ALU_ADDI_OPR) && W_OVER_FLOW_FLAG)
			begin
				O_DST_GPR_WR_EN <= 1'b0;
			end
			else
			begin
				O_DST_GPR_WR_EN <= R_I_DST_GPR_WR_EN;
			end
			O_DST_GPR_WR_ADDR <= R_I_DST_GPR_WR_ADDR;
			O_DST_GPR_WR_DATA <= O_DST_GPR_WR_DATA_2_ID_MDL;
		end
		else
		begin
			O_DST_GPR_WR_EN <= 1'b0;
			O_DST_GPR_WR_ADDR <= 5'd0;
			R_I_DST_GPR_WR_EN <= 1'b0;
			R_I_DST_GPR_WR_ADDR <= 5'd0;
			O_DST_GPR_WR_DATA <= `DEF_ZERO_WORD;			
		end
	end
end

assign O_DST_GPR_WR_EN_2_ID_MDL     =    R_I_DST_GPR_WR_EN  ;   
assign O_DST_GPR_WR_ADDR_2_ID_MDL   =    R_I_DST_GPR_WR_ADDR; 


always @ (*)
begin
	if(~I_CPU_RSTN)
	begin
		O_PAUSE_REQ = 1'b0;
	end
	else
	begin
		case(R_I_ALU_OP_TYPE)
			`DEF_ALU_MADD_OPR,`DEF_ALU_MADDU_OPR,`DEF_ALU_MSUB_OPR,`DEF_ALU_MSUBU_OPR:
			begin
				if(R_2STEP_ISTC_CNT == 0)
				begin
					O_PAUSE_REQ = 1'b1;
				end
				else if(R_2STEP_ISTC_CNT == 1)
				begin
					O_PAUSE_REQ = 1'b0;
				end
				else 
				begin
					O_PAUSE_REQ = 1'b1;
				end
			end
			`DEF_ALU_DIV_OPR,`DEF_ALU_DIVU_OPR:
			begin
				if(W_DIV_RES_VAL)
				begin
					O_PAUSE_REQ = 1'b0;
				end
				else
				begin
					O_PAUSE_REQ = 1'b1;
				end
			end
			default:
			begin
				O_PAUSE_REQ = O_PAUSE_REQ;//锁存器
			end
		endcase
	end
end

always @ (posedge I_CPU_CLK)
begin
	if(~I_CPU_RSTN)
	begin
		R_PAUSE_REQ <= 1'b0;
	end
	else
	begin
		R_PAUSE_REQ <= O_PAUSE_REQ;
	end
end

always @ (posedge I_CPU_CLK)
begin
	if(~I_CPU_RSTN)
	begin
		R_2STEP_ISTC_CNT <= 2'd0;
	end
	else
	begin
		case(R_I_ALU_OP_TYPE)
			`DEF_ALU_MADD_OPR,`DEF_ALU_MADDU_OPR,`DEF_ALU_MSUB_OPR,`DEF_ALU_MSUBU_OPR:
			begin
				if(R_2STEP_ISTC_CNT == 1)
				begin
					R_2STEP_ISTC_CNT <= 2'd0;
				end
				else
				begin
					R_2STEP_ISTC_CNT <= R_2STEP_ISTC_CNT + 1;
				end
			end
			default:
			begin
				R_2STEP_ISTC_CNT <= 2'd0;
			end
		endcase
	end
end

always @ (posedge I_CPU_CLK)
begin
	if(~I_CPU_RSTN)
	begin
		R_MID_RES_MULT <= 64'd0;
	end
	else
	begin
		case(R_I_ALU_OP_TYPE)
			`DEF_ALU_MADD_OPR,`DEF_ALU_MADDU_OPR,`DEF_ALU_MSUB_OPR,`DEF_ALU_MSUBU_OPR,`DEF_ALU_DIV_OPR,`DEF_ALU_DIVU_OPR:
			begin
				if(R_2STEP_ISTC_CNT == 0)
				begin
					if(R_I_ALU_OP_TYPE == `DEF_ALU_MADD_OPR || R_I_ALU_OP_TYPE == `DEF_ALU_MSUB_OPR)
					begin
						R_MID_RES_MULT <= W_I_SRC_OPR_DATA_A_SIGNED * W_I_SRC_OPR_DATA_B_SIGNED;
					end
					else if(R_I_ALU_OP_TYPE == `DEF_ALU_MADDU_OPR || R_I_ALU_OP_TYPE == `DEF_ALU_MSUBU_OPR)
					begin
						R_MID_RES_MULT <= I_SRC_OPR_DATA_A * I_SRC_OPR_DATA_B;
					end
					else
					begin
						R_MID_RES_MULT <= R_MID_RES_MULT;
					end
				end
				else
				begin
					R_MID_RES_MULT <= R_MID_RES_MULT;
				end
			end
			default:
			begin
				R_MID_RES_MULT <= 64'd0;
			end
		endcase
	end
end

// | 除法运算控制
always @ (posedge I_CPU_CLK)
begin
	if(~I_CPU_RSTN)
	begin
		R_DIV_TYPE    <= 1'b0;
		R_OPR_DATA_A  <= 32'd0;
		R_OPR_DATA_B  <= 32'd0;
		R_OPR_EN      <= 1'b0;   
		R_OPR_CANCEL  <= 1'b0;	
	end
	else
	begin
		case(R_I_ALU_OP_TYPE)
			`DEF_ALU_DIV_OPR:
			begin
				if(!(R_PAUSE_REQ&O_PAUSE_REQ))
				begin
					R_DIV_TYPE    <= 1'b1;
					R_OPR_DATA_A  <= I_SRC_OPR_DATA_A;
					R_OPR_DATA_B  <= I_SRC_OPR_DATA_B;
					R_OPR_EN      <= 1'b1;   
				end
				else
				begin
					R_OPR_EN      <= R_OPR_EN;
					R_DIV_TYPE    <= R_DIV_TYPE;
					R_OPR_DATA_A  <= R_OPR_DATA_A;
					R_OPR_DATA_B  <= R_OPR_DATA_B; 					
				end
				R_OPR_CANCEL  <= 1'b0;					
			end
			`DEF_ALU_DIVU_OPR:
			begin
				if(!(R_PAUSE_REQ&O_PAUSE_REQ))
				begin
					R_DIV_TYPE    <= 1'b0;
					R_OPR_DATA_A  <= I_SRC_OPR_DATA_A;
					R_OPR_DATA_B  <= I_SRC_OPR_DATA_B;
					R_OPR_EN      <= 1'b1; 
				end
				else
				begin
					R_OPR_EN      <= R_OPR_EN;
					R_DIV_TYPE    <= R_DIV_TYPE;
					R_OPR_DATA_A  <= R_OPR_DATA_A;
					R_OPR_DATA_B  <= R_OPR_DATA_B; 					
				end
				R_OPR_CANCEL  <= 1'b0;					
			end
			default:
			begin
				if(W_DIV_RES_VAL)
				begin
					R_OPR_EN      <= 1'b0; 
					R_DIV_TYPE    <= 1'b0;
					R_OPR_DATA_A  <= 32'd0;
					R_OPR_DATA_B  <= 32'd0; 
				end
				else
				begin
					R_OPR_EN      <= R_OPR_EN;
					R_DIV_TYPE    <= R_DIV_TYPE;
					R_OPR_DATA_A  <= R_OPR_DATA_A;
					R_OPR_DATA_B  <= R_OPR_DATA_B; 
				end
				R_OPR_CANCEL  <= 1'b0;					
			end
		endcase
	end
end

always @ (posedge I_CPU_CLK)
begin
	if(~I_CPU_RSTN)
	begin
		R_R_DIV_TYPE <= 1'b0;
	end
	else
	begin
		R_R_DIV_TYPE <= R_DIV_TYPE;
	end
end
// |--------------------------------------    模块内部例化    --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 除法运算模块
	DIV_OPR_MDL INST_DIV_OPR_MDL
		(
			.I_CPU_CLK    (I_CPU_CLK),
			.I_CPU_RSTN   (I_CPU_RSTN),
			.I_DIV_TYPE   (R_DIV_TYPE),
			.I_OPR_DATA_A (R_OPR_DATA_A),
			.I_OPR_DATA_B (R_OPR_DATA_B),
			.I_OPR_EN     (R_DIV_TYPE ^ R_R_DIV_TYPE),
			.I_OPR_CANCEL (R_OPR_CANCEL),
			.O_RES_VAL    (W_DIV_RES_VAL),
			.O_RES        (W_DIV_RES)
		);

endmodule

测试

测试程序

.org 0x0 		
.global _start 	
.set noat		

_start:

ori $1,$0,0xFFFF
sll $1,$1,16
ori $1,$1,0xFFF1
ori $2,$0,0x4

ori $3,$0,0xFFFF
sll $3,$3,16
ori $3,$3,0xFFF2
ori $4,$0,0x5

ori $5,$0,0xFFFF
sll $5,$5,16
ori $5,$5,0xFFF3
ori $6,$0,0x6

ori $7,$0,0xFFFF
sll $7,$7,16
ori $7,$7,0xFFF4
ori $8,$0,0x7

div $zero,$1,$2
divu $zero,$3,$4
div $zero,$5,$6
divu $zero,$7,$8

测试结果

 更细节的时序可根据源码自行仿真。若有问题,可以留言相告~~



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

在路上-正出发

哈哈,多少是个心意

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值