《自己动手写CPU》学习记录(7)——第6章



《自己动手写CPU》学习记录(7)——第6章_第1张图片 


目录

引言

致谢

指令说明

数据相关问题

设计

宏定义

译码模块

执行模块

HI LO寄存器

顶层模块

仿真

仿真代码

仿真结果


引言

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

致谢

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



指令说明

MIPS32指令集定义了 6条 移动操作指令:

movn、movz、mfhi、mthi、 mflo、mtlo
指令说明:

《自己动手写CPU》学习记录(7)——第6章_第2张图片

 用法说明:

《自己动手写CPU》学习记录(7)——第6章_第3张图片

 

数据相关问题

示例:

《自己动手写CPU》学习记录(7)——第6章_第4张图片

 

《自己动手写CPU》学习记录(7)——第6章_第5张图片

 

《自己动手写CPU》学习记录(7)——第6章_第6张图片

 

《自己动手写CPU》学习记录(7)——第6章_第7张图片

 

设计

此处仅给出修改模块的代码:

宏定义

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


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

`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							
							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_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
			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:增加移动运算执行功能。

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

// |--------------------------------------  模块内部逻辑设计  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 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
// | 计算单元
// 组合逻辑
always @ (*)
begin
	if(~I_CPU_RSTN)
	begin
		O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD;

		O_HILO_WR_EN			   = 1'b0;
		O_HI 					   = `DEF_ZERO_WORD;
		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;

				O_HILO_WR_EN			   = 1'b0;
				O_HI 					   = `DEF_ZERO_WORD;
				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;

				O_HILO_WR_EN			   = 1'b0;
				O_HI 					   = `DEF_ZERO_WORD;
				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;

				O_HILO_WR_EN			   = 1'b0;
				O_HI 					   = `DEF_ZERO_WORD;
				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);

				O_HILO_WR_EN			   = 1'b0;
				O_HI 					   = `DEF_ZERO_WORD;
				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;

				O_HILO_WR_EN			   = 1'b0;
				O_HI 					   = `DEF_ZERO_WORD;
				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;

				O_HILO_WR_EN			   = 1'b0;
				O_HI 					   = `DEF_ZERO_WORD;
				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);

				O_HILO_WR_EN			   = 1'b0;
				O_HI 					   = `DEF_ZERO_WORD;
				O_LO 					   = `DEF_ZERO_WORD;
			end
			`DEF_ALU_MOVZ_OPR:
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = I_SRC_OPR_DATA_A;

				O_HILO_WR_EN			   = 1'b0;
				O_HI 					   = `DEF_ZERO_WORD;
				O_LO 					   = `DEF_ZERO_WORD;
			end
			`DEF_ALU_MOVN_OPR:
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = I_SRC_OPR_DATA_A;

				O_HILO_WR_EN			   = 1'b0;
				O_HI 					   = `DEF_ZERO_WORD;
				O_LO 					   = `DEF_ZERO_WORD;
			end
			`DEF_ALU_MFHI_OPR:
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = R_HI;

				O_HILO_WR_EN			   = 1'b0;
				O_HI 					   = `DEF_ZERO_WORD;
				O_LO 					   = `DEF_ZERO_WORD;
			end
			`DEF_ALU_MTHI_OPR:
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD;

				O_HILO_WR_EN			   = 1'b1;
				O_HI 					   = I_SRC_OPR_DATA_A;
				O_LO 					   = R_LO;
			end
			`DEF_ALU_MFLO_OPR:
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = R_LO;

				O_HILO_WR_EN			   = 1'b0;
				O_HI 					   = `DEF_ZERO_WORD;
				O_LO 					   = `DEF_ZERO_WORD;
			end
			`DEF_ALU_MTLO_OPR:
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD;

				O_HILO_WR_EN			   = 1'b1;
				O_HI 					   = R_HI;
				O_LO 					   = I_SRC_OPR_DATA_A;
			end			
			default:
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD;

				O_HILO_WR_EN			   = 1'b0;
				O_HI 					   = `DEF_ZERO_WORD;
				O_LO 					   = `DEF_ZERO_WORD;
			end
		endcase
	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
		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

HI LO寄存器

// |------------------------------ ================================== ------------------------------
// |============================== 		     指令-译码模块  	      ==============================
// |------------------------------ ================================== ------------------------------
// |Create Date : 2022-12-10
// |Finish Date : 2022-12-10
// |Edited by   : Xu Y. B. (CSDN USER NAME :在路上,正出发)
// |Reference   : 《自己动手写CPU》
// |
// |
// |------------------------------------------------------------------------------------------------
// |---------------------------------------- Change History ----------------------------------------
// |Date:
// |Who :
// |What:

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

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

input 															I_HILO_WR_EN,
input 			[`DEF_GPR_DATA_WIDTH-1:0]						I_HI,
input			[`DEF_GPR_DATA_WIDTH-1:0]						I_LO,

output	reg		[`DEF_GPR_DATA_WIDTH-1:0]						O_HI,
output	reg		[`DEF_GPR_DATA_WIDTH-1:0]						O_LO

    );

// |--------------------------------------  模块内部逻辑设计  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 寄存
always @ (posedge I_CPU_CLK)
begin
	if(~I_CPU_RSTN)
	begin
		O_HI <= `DEF_ZERO_WORD;
		O_LO <= `DEF_ZERO_WORD;
	end
	else if(I_HILO_WR_EN)
	begin
		O_HI <= I_HI;
		O_LO <= I_LO;
	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类问题)
// |	 顶层文件配合改动


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

module TOP_MIPS32(

// |--------------------------------------  输入输出端口声明  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 时钟、复位
input 															I_CPU_CLK,
input 															I_CPU_RSTN,
// | 指令取
input			[`DEF_ISTC_DATA_BUS]							I_ISTC_FROM_ROM,
output			[`DEF_ISTC_ADDR_BUS]							O_ISTC_ADDR_2_ROM,
// | 指令存储器使能
output															O_ISTC_ROM_CE
    );

// |--------------------------------------  模块内部信号声明  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | PC_REG_MDL 输出
wire			[`DEF_ISTC_ADDR_BUS]							W_PC;
// | IF_ID_MDL 输出
wire 			[`DEF_ISTC_ADDR_BUS] 							W_ID_ADDR;
wire 			[`DEF_ISTC_DATA_BUS] 							W_ID_DATA;
// ID_MDL 端口信号(GPR相关)
wire															W_GPR_RD_EN_A;
(*DONT_TOUCH = "TRUE"*)
wire			[`DEF_GPR_ADDR_WIDTH-1:0]						W_GPR_RD_ADDR_A;
wire			[`DEF_GPR_DATA_WIDTH-1:0]						W_GPR_RD_DATA_A;
wire															W_GPR_RD_EN_B;
(*DONT_TOUCH = "TRUE"*)
wire			[`DEF_GPR_ADDR_WIDTH-1:0]						W_GPR_RD_ADDR_B;
wire 			[`DEF_GPR_DATA_WIDTH-1:0]						W_GPR_RD_DATA_B;
// ID_MDL 端口信号(EXE 相关)
wire			[`DEF_ALU_OPR_BUS]								W_ALU_OP_TYPE;
wire			[`DEF_SRC_OPR_DATA_BUS]							W_SRC_OPR_DATA_A;
wire			[`DEF_SRC_OPR_DATA_BUS]							W_SRC_OPR_DATA_B;
// GPR_WR_RD_MDL 写操作端口(EXE 相关)
wire															W_DST_GPR_WR_EN_EXE_MDL_IN;
wire			[`DEF_GPR_ADDR_WIDTH-1:0]						W_DST_GPR_WR_ADDR_EXE_MDL_IN;
// GPR_WR_RD_MDL 写操作端口(MEM 相关)
wire															W_DST_GPR_WR_EN_MEM_MDL_IN;
wire			[`DEF_GPR_ADDR_WIDTH-1:0]						W_DST_GPR_WR_ADDR_MEM_MDL_IN;
wire			[`DEF_GPR_DATA_WIDTH-1:0]						W_DST_GPR_WR_DATA_MEM_MDL_IN;
// GPR_WR_RD_MDL 写操作端口(GPR 相关)
wire															W_DST_GPR_WR_EN_GPR_MDL_IN;
wire			[`DEF_GPR_ADDR_WIDTH-1:0]						W_DST_GPR_WR_ADDR_GPR_MDL_IN;
wire			[`DEF_GPR_DATA_WIDTH-1:0]						W_DST_GPR_WR_DATA_GPR_MDL_IN;
// | 为解决数据相关问题/读写冲突问题 引入的端口
// 来自执行模块
wire															W_DST_GPR_WR_EN_GPR_MDL_IN_FROM_EXE_MDL  ;
wire			[`DEF_GPR_ADDR_WIDTH-1:0]						W_DST_GPR_WR_ADDR_GPR_MDL_IN_FROM_EXE_MDL;
wire			[`DEF_GPR_DATA_WIDTH-1:0]						W_DST_GPR_WR_DATA_GPR_MDL_IN_FROM_EXE_MDL;
// | HI_LO_REG_MDL 端口
wire 															W_HILO_WR_EN;
wire 			[`DEF_GPR_DATA_WIDTH-1:0]						W_HI;
wire			[`DEF_GPR_DATA_WIDTH-1:0]						W_LO;
wire 			[`DEF_GPR_DATA_WIDTH-1:0]						W_O_HI;
wire			[`DEF_GPR_DATA_WIDTH-1:0]						W_O_LO;
wire 															W_O_EXE_HILO_WR_EN;
wire 			[`DEF_GPR_DATA_WIDTH-1:0]						W_O_EXE_HI;
wire			[`DEF_GPR_DATA_WIDTH-1:0]						W_O_EXE_LO;
// |--------------------------------------  模块内部逻辑设计  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 输出
assign 			O_ISTC_ADDR_2_ROM		=		W_PC;

// |--------------------------------------      子模块例化    --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 程序计数器模块
	PC_REG_MDL INST_PC_REG_MDL
		(
			.I_CPU_CLK     (I_CPU_CLK),
			.I_CPU_RSTN    (I_CPU_RSTN),
			.O_PC          (W_PC),
			.O_ISTC_ROM_CE (O_ISTC_ROM_CE)
		);
// | 译码模块例化
	ID_MDL INST_ID_MDL
		(
			.I_CPU_CLK         (I_CPU_CLK),
			.I_CPU_RSTN        (I_CPU_RSTN),
			.I_ISTC            (I_ISTC_FROM_ROM),

			.O_GPR_RD_EN_A     (W_GPR_RD_EN_A),
			.O_GPR_RD_ADDR_A   (W_GPR_RD_ADDR_A),
			.I_GPR_RD_DATA_A   (W_GPR_RD_DATA_A),
			.O_GPR_RD_EN_B     (W_GPR_RD_EN_B),
			.O_GPR_RD_ADDR_B   (W_GPR_RD_ADDR_B),
			.I_GPR_RD_DATA_B   (W_GPR_RD_DATA_B),

			.O_ALU_OP_TYPE     (W_ALU_OP_TYPE),
			.O_SRC_OPR_DATA_A  (W_SRC_OPR_DATA_A),
			.O_SRC_OPR_DATA_B  (W_SRC_OPR_DATA_B),

			.O_DST_GPR_WR_EN   (W_DST_GPR_WR_EN_EXE_MDL_IN),
			.O_DST_GPR_WR_ADDR (W_DST_GPR_WR_ADDR_EXE_MDL_IN),
			// | 为解决数据相关问题/读写冲突问题 引入的端口
			// 来自执行模块
			.I_DST_GPR_WR_EN_FROM_EXE_MDL       (W_DST_GPR_WR_EN_GPR_MDL_IN_FROM_EXE_MDL  ), 
			.I_DST_GPR_WR_ADDR_FROM_EXE_MDL     (W_DST_GPR_WR_ADDR_GPR_MDL_IN_FROM_EXE_MDL),
			.I_DST_GPR_WR_DATA_FROM_EXE_MDL     (W_DST_GPR_WR_DATA_GPR_MDL_IN_FROM_EXE_MDL),
			// 来自访存模块
			.I_DST_GPR_WR_EN_FROM_MEM_ACS_MDL   (W_DST_GPR_WR_EN_MEM_MDL_IN  ), 
			.I_DST_GPR_WR_ADDR_FROM_MEM_ACS_MDL (W_DST_GPR_WR_ADDR_MEM_MDL_IN),
			.I_DST_GPR_WR_DATA_FROM_MEM_ACS_MDL (W_DST_GPR_WR_DATA_MEM_MDL_IN)			
		);
// | 通用寄存器模块例化
	GPR_WR_RD_MDL INST_GPR_WR_RD_MDL
		(
			.I_CPU_CLK       (I_CPU_CLK),
			.I_CPU_RSTN      (I_CPU_RSTN),

			.I_GPR_WR_EN     (W_DST_GPR_WR_EN_GPR_MDL_IN),
			.I_GPR_WR_ADDR   (W_DST_GPR_WR_ADDR_GPR_MDL_IN),
			.I_GPR_WR_DATA   (W_DST_GPR_WR_DATA_GPR_MDL_IN),

			.I_GPR_RD_EN_A   (W_GPR_RD_EN_A),
			.I_GPR_RD_ADDR_A (W_GPR_RD_ADDR_A),
			.O_GPR_RD_DATA_A (W_GPR_RD_DATA_A),
			.I_GPR_RD_EN_B   (W_GPR_RD_EN_B),
			.I_GPR_RD_ADDR_B (W_GPR_RD_ADDR_B),
			.O_GPR_RD_DATA_B (W_GPR_RD_DATA_B)
		);
// | 执行模块例化
	EXE_MDL INST_EXE_MDL
		(
			.I_CPU_CLK         (I_CPU_CLK),
			.I_CPU_RSTN        (I_CPU_RSTN),

			.I_ALU_OP_TYPE     (W_ALU_OP_TYPE),
			.I_SRC_OPR_DATA_A  (W_SRC_OPR_DATA_A),
			.I_SRC_OPR_DATA_B  (W_SRC_OPR_DATA_B),

			.I_DST_GPR_WR_EN   (W_DST_GPR_WR_EN_EXE_MDL_IN),
			.I_DST_GPR_WR_ADDR (W_DST_GPR_WR_ADDR_EXE_MDL_IN),

			.I_HI(W_O_HI),
			.I_LO(W_O_LO),
			.I_HI_FROM_MEM_ACS_MDL		(W_O_EXE_HI),
			.I_LO_FROM_MEM_ACS_MDL		(W_O_EXE_LO),
			.I_WR_EN_FROM_MEM_ACS_MDL   (W_O_EXE_HILO_WR_EN),
			.I_HI_FROM_HI_LO_REG_MDL	(W_HI),
			.I_LO_FROM_HI_LO_REG_MDL	(W_LO),
			.I_WR_EN_FROM_HI_LO_REG_MDL	(W_HILO_WR_EN),

			.O_DST_GPR_WR_EN   (W_DST_GPR_WR_EN_MEM_MDL_IN  ),
			.O_DST_GPR_WR_ADDR (W_DST_GPR_WR_ADDR_MEM_MDL_IN),
			.O_DST_GPR_WR_DATA (W_DST_GPR_WR_DATA_MEM_MDL_IN),
			// | 为解决数据相关问题/读写冲突问题 引入的端口
			// 送至指令译码模块
			.O_DST_GPR_WR_EN_2_ID_MDL   (W_DST_GPR_WR_EN_GPR_MDL_IN_FROM_EXE_MDL  ),  
			.O_DST_GPR_WR_ADDR_2_ID_MDL (W_DST_GPR_WR_ADDR_GPR_MDL_IN_FROM_EXE_MDL),
			.O_DST_GPR_WR_DATA_2_ID_MDL (W_DST_GPR_WR_DATA_GPR_MDL_IN_FROM_EXE_MDL),

			.O_HI(W_O_EXE_HI),
			.O_LO(W_O_EXE_LO),
			.O_HILO_WR_EN(W_O_EXE_HILO_WR_EN)
		);
// | 存储器存取模块例化
	MEM_ACS_MDL INST_MEM_ACS_MDL
		(
			.I_CPU_CLK         (I_CPU_CLK),
			.I_CPU_RSTN        (I_CPU_RSTN),

			.I_DST_GPR_WR_EN   (W_DST_GPR_WR_EN_MEM_MDL_IN  ),
			.I_DST_GPR_WR_ADDR (W_DST_GPR_WR_ADDR_MEM_MDL_IN),
			.I_DST_GPR_WR_DATA (W_DST_GPR_WR_DATA_MEM_MDL_IN),

			.O_DST_GPR_WR_EN   (W_DST_GPR_WR_EN_GPR_MDL_IN  ),
			.O_DST_GPR_WR_ADDR (W_DST_GPR_WR_ADDR_GPR_MDL_IN),
			.O_DST_GPR_WR_DATA (W_DST_GPR_WR_DATA_GPR_MDL_IN),

			.I_HI				(W_O_EXE_HI),
			.I_LO				(W_O_EXE_LO),
			.I_HILO_WR_EN		(W_O_EXE_HILO_WR_EN),
			
			.O_HI 				(W_HI),
			.O_LO 				(W_LO),
			.O_HILO_WR_EN  		(W_HILO_WR_EN)
		);
// | HI LO 寄存器例化
	HI_LO_REG_MDL INST_HI_LO_REG_MDL
		(
			.I_CPU_CLK    (I_CPU_CLK),
			.I_CPU_RSTN   (I_CPU_RSTN),
			.I_HILO_WR_EN (W_HILO_WR_EN),
			.I_HI         (W_HI),
			.I_LO         (W_LO),
			.O_HI         (W_O_HI),
			.O_LO         (W_O_LO)
		);

endmodule

仿真

仿真代码

此处参考课本示例。

.org 0x0 		
.global _start 	
.set noat		

_start:
lui   $1,0x0000
lui   $2,0xFFFF
lui   $3,0x0505
lui   $4,0x0000

movz $4,$2,$1
movn $4,$3,$1
movn $4,$3,$2
movz $4,$2,$3

mthi $0
mthi $2
mthi $3

mfhi $4

mtlo $3
mtlo $2
mtlo $1

mflo $4

仿真结果

 



你可能感兴趣的:(CPU,MIPS32,IC,Verilog)