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




目录

引言

致谢

指令说明

add、addu、sub、subu、slt、sltu

addi、addiu、slti、sltiu

clo、clz

multu、mult、mul

设计

宏定义

译码模块

指令执行模块

仿真

仿真程序

仿真结果

1月5日回答评论区疑问



引言

随章节进度继续推进,本章继续实现 算术运算 指令等其他操作指令。

本篇文章主要实现简单算术操作指令,一共有15条指令。

致谢

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


指令说明

add、addu、sub、subu、slt、sltu

此 6 条指令都是 R 型指令,指令码均为 6'd0 ,都属 SPECIAL 类。此外 6 ~ 10位均为 0 。可根据 低 6 位 判断指令功能。

指令格式:

 指令用法说明:

addi、addiu、slti、sltiu

该4条指令都是 I 型指令,指令格式:

 指令用法:

clo、clz

此两条指令属于 R 型指令。指令码均为 6'b011100,MIPS32 的 ISA 中表示 SPECIAL2 类。此外,10~6位 为0,需要依靠 低六位 判定指令功能。

指令格式:

 指令用法:

multu、mult、mul

此 3 条指令都是 R型指令。其中 mul 属SPECIAL2类,mult和multu属SPECIAL类。

指令格式:

 指令用法:

设计

此处仅对有改动的模块,给出源码。

宏定义

// |------------------------------ ================================== ------------------------------
// |============================== 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操作功能宏定义

// |--------------------------------------  系统级全局宏定义  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 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_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_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:增加简单算术运算指令的译码功能

`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	reg [`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

    );
// |--------------------------------------  模块内部信号声明  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 指令分解相关
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;



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

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

// | 指令译码 
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;

		O_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;

								O_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;

								O_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;

								O_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;

								O_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;

								O_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;

								O_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;

								O_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;

								O_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;

								O_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;

								O_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;

								O_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;

								O_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;

								O_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;

								O_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;

								O_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;

								O_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;

								O_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;

								O_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;

								O_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;

								O_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;

								O_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;

								O_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														
							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;

								O_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;

						O_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;

						O_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;

						O_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;

						O_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
					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;

						O_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;

				O_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;

				O_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;

				O_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;

				O_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;

				O_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;

				O_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;

				O_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;

				O_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;

				O_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;

				O_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(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;

					O_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;

					O_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;

					O_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;

					O_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:增加简单算数运算执行功能

`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

    );
// |--------------------------------------  模块内部信号声明  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 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;

// |--------------------------------------  模块内部逻辑设计  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | I_ALU_OP_TYPE 打拍对齐时序
always @ (posedge I_CPU_CLK)
begin
	if(~I_CPU_RSTN)
	begin
		R_I_ALU_OP_TYPE <= 0;
	end
	else
	begin
		R_I_ALU_OP_TYPE <= 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						
			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
		O_HILO_WR_EN <= R_O_HILO_WR_EN;
		O_HI 		 <= R_O_HI 		;
		O_LO 		 <= R_O_LO 		;		
	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
		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
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; 
endmodule

仿真

仿真程序

此处参考书本。

.org 0x0 		
.global _start 	
.set noat		

_start:

ori $1,$0,0x8000
sll $1,$1,16
ori $1,$1,0x0010

ori $2,$0,0x8000
sll $2,$2,16
ori $2,$2,0x0001

ori $3,$0,0x0000
addu $3,$2,$1
ori $3,$0,0x0000
add $2,$2,$1

sub $3,$1,$3
subu $3,$3,$2

addi $3,$3,2
ori $3,$0,0x0000
addiu $3,$3,0x8000

or $1,$0,0xFFFF
sll $1,$1,16
slt $2,$1,$0
sltu $2,$1,$0
slti $2,$1,0x8000
sltiu $2,$1,0x8000

lui $1,0x0000
clo $2,$1
clz $2,$1

lui $1,0xFFFF
ori $1,$1,0xFFFF
clz $2,$1
clo $2,$1

lui $1,0xA100
clz $2,$1
clo $2,$1

lui $1,0x1100
clz $2,$1
clo $2,$1


ori $1,$0,0xFFFF
sll $1,$1,16
ori $1,$1,0xFFFB
ori $2,$0,6
mul $3,$1,$2

mult $1,$2
multu $1,$2
nop
nop

仿真结果

具体细节可以自行仿真查看。 


1月5日回答评论区疑问

昨天收到一位读者的评论,内容如下:

 对此疑问我的解释是:

1、直接将源操作数赋值给定义的有符号wire型信号,是可以实现有符号数运算的,不需要取补码,如果不是赋值给有符号的信号,则需要先对原始信号取补码,再做有符号运算。

2、这个其实也很好理解,直接复制给有符号的信号后,有符号的信号参与运算,verilog的解释器自动会按照有符号数据计算的规则进行解释和综合。

3、实在想不明白的话,那就用实践来检验,写一个testbench就能很好说明问题。

这里我写了一个简单的testbench:

// 测试有符号数赋值

`timescale 1ns / 1ps

module TB_SIGNED_CAL();

reg 	[15:0]			R_CNT1;
reg 	[15:0]			R_CNT2;
reg 					R_CLK;
// 源操作数直接赋值
wire 	signed [15:0]	W_R_CNT1_SIGNED = R_CNT1;
wire 	signed [15:0]	W_R_CNT2_SIGNED = R_CNT2;
wire 	signed [15:0]	W_CNT1_ADD_CNT2 = W_R_CNT1_SIGNED + W_R_CNT2_SIGNED;
wire 	signed [15:0]	W_CNT1_SUB_CNT2 = W_R_CNT1_SIGNED - W_R_CNT2_SIGNED;
// 源操作数取补码后赋值
wire 	signed [15:0]	W_R_CNT1_SIGNED_2 = (~R_CNT1) + 1'b1;
wire 	signed [15:0]	W_R_CNT2_SIGNED_2 = (~R_CNT2) + 1'b1;
wire 	signed [15:0]	W_CNT1_ADD_CNT2_2 = W_R_CNT1_SIGNED_2 + W_R_CNT2_SIGNED_2;
wire 	signed [15:0]	W_CNT1_SUB_CNT2_2 = W_R_CNT1_SIGNED_2 - W_R_CNT2_SIGNED_2;

initial R_CLK = 1'b0;
always #10 R_CLK = ~R_CLK;

initial
begin
	R_CNT1 = 0;
	R_CNT2 = 0;
	@(posedge R_CLK)
	R_CNT1 <= 16'd10;
	R_CNT2 <= -16'd20;
	@(posedge R_CLK)
	R_CNT1 <= -16'd10;
	R_CNT2 <= -16'd20;
	@(posedge R_CLK)
	R_CNT1 <= 16'd10;
	R_CNT2 <= 16'd20;
	@(posedge R_CLK)
	R_CNT1 <= 16'd100;
	R_CNT2 <= -16'd200;
	@(posedge R_CLK)
	R_CNT1 <= -16'd100;
	R_CNT2 <= -16'd20;
	@(posedge R_CLK)
	R_CNT1 <= 16'd110;
	R_CNT2 <= -16'd20;
	$finish;	 
end
endmodule

仿真结果:

 仿真表明,直接将源操作数赋值给有符号信号,然后用被赋值的有符号信号作相应的有符号运算是没问题的,相反如果将源操作数取补码后再赋值给有符号信号,进而再做有符号运算时,结果就出现问题了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

在路上-正出发

哈哈,多少是个心意

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

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

打赏作者

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

抵扣说明:

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

余额充值