《自己动手写CPU》学习记录(6)——第5章/Part 2

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



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


目录

引言

致谢

指令说明

逻辑指令

and、or、xor、nor

andi、xori

lui

移位指令

sll、sllv、sra、srav、srl、srlv 

空指令

nop、ssnop、sync、pref

指令实现

宏定义添加

指令译码模块修改

指令执行模块修改

功能验证

逻辑运算

验证代码

仿真波形 

移位运算

验证代码

仿真波形



引言

随章节进度继续推进,本章继续实现逻辑、移位、空指令等其他操作指令。

致谢

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


指令说明

逻辑指令

and、or、xor、nor

指令格式:

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

 该4条指令均属于 R 类型指令,且指令码均为 6‘b000000 即MIPS32 ISA 中定义的 SPECIAL 类。另外,指令的 6~10位均为0,需要依据指令中的 低 6 位 判断功能类型。

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

andi、xori

指令格式:

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

 这两条指令都是 I 类型指令。根据指令码的 高 6 位 ,可以判断指令的功能。

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

 此处的指令用法再一次证实了,书本所写的 ori 指令用法格式有误:

lui

指令格式:

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

根据指令码的高6位即可判断功能是否为 lui ,指令用法:

移位指令

sll、sllv、sra、srav、srl、srlv 


指令格式:

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

 此6条指令均属于 R 指令类型,且指令码均为 6'b000000。属于 SPECIAL 类,需要根据指令码的 低6位判断其功能。

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

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

空指令

nop、ssnop、sync、pref
 

 此6条指令均属于 R 指令类型,且指令码均为 6'b000000。属于 SPECIAL 类,

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

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

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

指令实现

宏定义添加

仅供参考:

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


// |--------------------------------------  系统级全局宏定义  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 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			// and
`define 							DEF_ISTC_OR							6'b100101			// or
`define 							DEF_ISTC_XOR						6'b100110			// xor
`define 							DEF_ISTC_NOR						6'b100111			// nor
`define 							DEF_ISTC_ANDI						6'b001100			// andi
`define 							DEF_ISTC_ORI						6'b001101 			// ori
`define 							DEF_ISTC_XORI						6'b001110			// xori
`define 							DEF_ISTC_LUI						6'b001111			// lui

`define 							DEF_ISTC_SLL						6'b000000			// sll
`define 							DEF_ISTC_SLLV						6'b000100			// sllv
`define 							DEF_ISTC_SRL						6'b000010			// srl
`define 							DEF_ISTC_SRLV						6'b000110			// srlv
`define 							DEF_ISTC_SRA						6'b000011			// sra
`define 							DEF_ISTC_SRAV						6'b000111 			// srav

`define 							DEF_ISTC_SYNC						6'b001111 			// sync
`define 							DEF_ISTC_PREF						6'b110011 			// pref
`define 							DEF_ISTC_SPEC						6'b000000 			// SPECIAL 类指令码

`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_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:增加逻辑、移位指令的译码功能

`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
							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:增加逻辑、移位运算执行功能。

`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,
// | 输出 
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


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

// |--------------------------------------  模块内部逻辑设计  --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 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
// | 计算单元
// 组合逻辑
always @ (*)
begin
	if(~I_CPU_RSTN)
	begin
		O_DST_GPR_WR_DATA_2_ID_MDL = `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;
			end
			`DEF_ALU_AND_OPR:
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = I_SRC_OPR_DATA_A & I_SRC_OPR_DATA_B;
			end
			`DEF_ALU_XOR_OPR:
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = I_SRC_OPR_DATA_A ^ I_SRC_OPR_DATA_B;
			end
			`DEF_ALU_NOR_OPR:
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = ~(I_SRC_OPR_DATA_A | I_SRC_OPR_DATA_B);
			end
			`DEF_ALU_SLL_OPR:
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = I_SRC_OPR_DATA_B << I_SRC_OPR_DATA_A;
			end
			`DEF_ALU_SRL_OPR:
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = I_SRC_OPR_DATA_B >> I_SRC_OPR_DATA_A;
			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);
			end
			default:
			begin
				O_DST_GPR_WR_DATA_2_ID_MDL = `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;
		O_DST_GPR_WR_EN <= R_I_DST_GPR_WR_EN;
		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:
lui   $1,0x0101
ori   $1,$1,0x0101
ori   $2,$1,0x1100
or    $1,$1,$2
andi  $3,$1,0x00FE
and   $1,$3,$1
xori  $4,$1,0xFF00
xor   $1,$4,$1
nor   $1,$4,$1

仿真波形 

移位运算

验证代码

.org 0x0 		
.global _start 	
.set noat		

_start:
lui   $2,0x0404
ori   $2,$2,0x0404
ori   $7,$0,0x7
ori   $5,$0,0x5
ori   $8,$0,0x8
sync
sll	  $2,$2,8
sllv  $2,$2,$7
srl   $2,$2,8
srlv  $2,$2,$5
nop
ssnop
sll   $2,$2,19
ssnop
sra   $2,$2,16
srav  $2,$2,$8

仿真波形

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



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