[write your own CPU] implementation of loading and storing instructions

target

Modify the sopc that has been tested before, add data RAM for it, test the implementation of general loading instructions, and add special loading and storage instructions.
This paper discusses the load related problems caused by loading instructions, gives the solution of OpenMIPS, and verifies the solution effect.

Load storage instruction description

31-2625-2120-1615-0useagefunction
LB(100000)basertoffsetlb rt,offset(base)Read a byte from the address specified in memory, then expand the symbol to 32 bits and save it to the general register with address rt
LBU(100100)basertoffsetlbu rt,offset(base)Ibid., signed to unsigned
LH(100001)basertoffsetlh rt,offset(base)Read one and a half words from the load address specified in memory, then expand the symbol to 32 bits and save it to the general register with address rt. The instruction requires the address of the lowest order to be 0
LHU(100101)basertoffsetlhu rt,offset(base)Ibid., signed to unsigned
LW(100011)basertoffsetlw rt,offset(base)Read a word from the load address specified in the memory and save it to the general register with address rt. the instruction has address alignment requirements, and the lowest two bits of the load address are required to be 00

Load address = signed_extended(offset) + GPR[base]
Firstly, the 16 bit offset symbol is extended to 32 bits, and then added to the value of the general register with address base to obtain the load address

Storage instruction description

31-2625-2120-1615-0useagefunction
SB(101000)basertoffsetsb rt,offset(base)Stores the lowest byte of the general-purpose register with address rt to the specified address in memory
SH(101001)basertoffsetsh rt,offset(base)Store the lowest two bytes of the general-purpose register with address rt to the specified address in memory. The instruction has address alignment requirements, which requires that the lowest bit of the calculated storage address is 0
SW(101011)basertoffsetsw rt,offset(base)Stores the value of the general-purpose register with address rt to the specified address in memory. This instruction has address alignment requirements. It requires that the lowest two digits of the calculated storage address be 00

Storage address = signed_extended(offset) + GPR[base]
The 16 bit offset symbol is extended to 32 bits, and then added to the value of the general register with address base to obtain the storage address

Load store instruction usage example

Addressing by byte, in the big end mode, the high order of data is saved in the low address of memory, and the low order of data is saved in the high address of memory.
Use the sb instruction to store 0x81 data at 0x50, and the high bit of the data is stored in the low address of the memory.

Use the sh instruction to store 0x8281 at 0x54. The low order of the data is saved in the high address.

Use the sw instruction to store 0x84838281 at 0x58

Next, use the load instruction

  • Use lbu to load a byte at 0x58. The read byte is 0x84, and the unsigned extension is 0x00000084 to 32 bits.
  • Use lb to load a byte from 0x58. The read byte is 0x84, and the signed byte is extended to 32 bits 0xffff84.
  • Use lhu to load one and a half words from 0x58. The read bytes are half words (in 32-bit Cpu, one word is 4 bytes, and half words are 2 bytes). The read byte is 0x8483. The unsigned extension to 32 bits is 0x00008483
  • Use lh to load a half word from 0x5a and read 2 bytes. The read byte is 0x8281. The instruction has address alignment requirements. The minimum bit of the loaded address is 0, which is 1 at this time, which does not meet the requirements.

Loading instruction lwl,lwr description

31-2625-2120-1615-0useagefunction
LWL(100010)basertoffsetlwl rt,offset(base)Load the most significant part of a word from the load address specified in memory, without address alignment requirements.
LWR(100110)basertoffsetlwr rt,offset(base)Load the least significant part of a word from the load address specified in memory. There is no address alignment requirement.

lwl calculation method:

Here is the effect in big end mode
Loading address loadaddr = signed_extended(offset)+GPR[base]
n = loadaddr[1:0]
loadaddr_align = loadaddr - n;
The lwl instruction functions from the address loadaddr_ Load a word and 4 bytes at align. Save the lowest 4-n bytes of the word to the high-order of the general-purpose register with address rt and keep the low order unchanged.
lwl $1,5($0) rt = $1

lwr calculation method:

Loading address loadaddr = signed_extended(offset)+GPR[base]
n = loadaddr[1:0]
loaddr_align =loadaddr - n;
The lwr instruction functions from the address loadaddr_ Load a word and 4 bytes at align. Save the highest n+1 bytes of the word to the low bit of the general register with address rt and keep the high bit unchanged.

The combination of LWL and LWR instructions can load a word with a non aligned address, and only two instructions are needed

Description of stored instructions

31-2625-2120-1615-0useagefunction
SWL(101010)basertoffsetswl rt,offset(base)Store the high-order part of the general-purpose register with the address rt into the address specified in the memory. The last two bits of the storage address determine which bytes of the rt general-purpose register to be stored. The swl instruction has no alignment requirements for the storage instruction (store the maximum 4-n bytes of the general-purpose register with the address rt into storeaddr)
SWR(101110)basertoffsetswr rt,offset(base)Non aligned instructions, stored to the right. Store the low-order part of the general-purpose register with address rt to the specified address in memory. The last two bits of the storage address determine which bytes of the general-purpose register with address rt are to be stored (store the lowest n+1 bytes of the general-purpose register with address rt to storeaddr)

storeaddr =signed_extended(offset) + GPR[base]
n=storeaddr[1:0]
storeaddr_align=storeaddr-n
It is the same except that the load is changed to storage.

Implementation of loading and storing instructions

The loading instruction is decoded in the decoding stage to obtain the operation type and sub operation type, as well as the data to be stored. These information are transmitted to the execution stage, and then sent to the memory access stage. The memory access stage sets the access signal to the data memory RAM according to these information. The data read from RAM needs to be aligned and adjusted according to the type of loading instruction and loading address, and the adjusted result is written into the destination register as the final result.

Modification of data flow diagram

Compared with before, the access to data memory RAM is added in the memory access stage. At the same time, the data written to the destination register may be the result of the execution stage or the data loaded from RAM in the memory access stage. Therefore, add a selector in the memory access stage to select.

Modification of system structure

Modification of code module

Decoding stage

id.v

The decoding phase ID increases the output signal inst_o instruction in the decoding stage, the value will be passed to the execution stage, and the ex module uses the value of the signal (instruction in the decoding stage) to calculate the loading and storage address mem_addr_o.

`include "define.v"
module id(

	input wire										rst,
	input wire[`InstAddrBus]			pc_i,
	input wire[`InstBus]          inst_i,

	input wire[`RegBus]           reg1_data_i,
	input wire[`RegBus]           reg2_data_i,
	input wire is_in_delayslot_i,//Whether it is in the delay slot instruction

	//Information sent to regfile
	output reg                    reg1_read_o,
	output reg                    reg2_read_o,     
	output reg[`RegAddrBus]       reg1_addr_o,
	output reg[`RegAddrBus]       reg2_addr_o, 	      
	
	//Information sent to the execution phase
	output reg[`AluOpBus]         aluop_o,
	output reg[`AluSelBus]        alusel_o,
	output reg[`RegBus]           reg1_o,
	output reg[`RegBus]           reg2_o,
	output reg[`RegAddrBus]       wd_o,
	output reg                    wreg_o,
	
	
	//The result of an instruction in execution
	input wire ex_wreg_i,
  input wire[`RegBus] ex_wdata_i,
	input wire[`RegAddrBus] ex_wd_i,
	input wire[`AluOpBus] ex_aluop_i,
	//The operation result of the instruction in the memory access stage
	input wire mem_wreg_i,
	input wire[`RegBus] mem_wdata_i,
	input wire[`RegAddrBus] mem_wd_i,
	output wire stallreq,
	output reg next_inst_in_delayslot_o,//Is the next instruction a delay slot
	
	output reg branch_flag_o,//Whether transfer occurs
	output reg[`RegBus] branch_target_address_o,//Destination address of transfer to
	output reg[`RegBus] link_addr_o,//Return address of the transfer instruction to be saved
	output reg is_in_delayslot_o,//Whether the currently decoded instruction is in the delay slot
	output wire[`RegBus] inst_o //Newly added output interface
);

  wire[5:0] op = inst_i[31:26];
  wire[4:0] op2 = inst_i[10:6];
  wire[5:0] op3 = inst_i[5:0];
  wire[4:0] op4 = inst_i[20:16];
  
  wire[`RegBus] pc_plus_8;//Save the address of the second instruction after the instruction in the current decoding stage
  wire[`RegBus] pc_plus_4;//Save the instruction address immediately following the instruction in the current decoding stage
  
  wire[`RegBus] imm_sll2_signedext;//The offset in the corresponding branch instruction is shifted to the left by two bits, and then the symbol is extended to the value of 32 bits
  
  
  reg[`RegBus]	imm;
  reg instvalid;
  
  assign stallreq = `NoStop;//This signal will be assigned a value when loading and storing instructions are realized
  
  assign imm_sll2_signedext = {{14{inst_i[15]}},inst_i[15:0],2'b00};
  //imm_sll2_signedext shifts the offset in the corresponding branch instruction by two bits to the left, and then extends the symbol to the value of 32 bits
  
 assign pc_plus_8 = pc_i+8;
 assign pc_plus_4 = pc_i+4;
 
 assign stallreq = `NoStop;
 assign inst_o = inst_i;//Instructions in decoding stage
	always @ (*) begin	
		if (rst == `RstEnable) begin
			aluop_o <= `EXE_NOP_OP;
			alusel_o <= `EXE_RES_NOP;//nop
			wd_o <= `NOPRegAddr;
			wreg_o <= `WriteDisable;
			instvalid <= `InstValid;
			reg1_read_o <= 1'b0;
			reg2_read_o <= 1'b0;
			reg1_addr_o <= `NOPRegAddr;
			reg2_addr_o <= `NOPRegAddr;
			imm <= 32'h0;		
			link_addr_o <= `ZeroWord;//Return address of the transfer instruction to be saved
			branch_target_address_o <= `ZeroWord;//Destination address of transfer to
			branch_flag_o <= `NotBranch;//No transfer
			next_inst_in_delayslot_o <= `NotInDelaySlot;//Is the next instruction in the delay slot	
	  end else begin //Initialize first
			aluop_o <= `EXE_NOP_OP;
			alusel_o <= `EXE_RES_NOP;
			wd_o <= inst_i[15:11];
			wreg_o <= `WriteDisable;
			instvalid <= `InstInvalid;	   
			reg1_read_o <= 1'b0;
			reg2_read_o <= 1'b0;
			reg1_addr_o <= inst_i[25:21];//rs
			reg2_addr_o <= inst_i[20:16];//rt
			imm <= `ZeroWord;		
			link_addr_o <= `ZeroWord;
			branch_target_address_o <= `ZeroWord;
			branch_flag_o <= `NotBranch;
			next_inst_in_delayslot_o <= `NotInDelaySlot; 	
		case (op)//Instruction code
		  	`EXE_SPECIAL_INST: begin //The instruction code is SPECIAL
		  		case(op2)//Function code
		  			5'b00000: begin
		  				case(op3) //Determine which instruction is based on the function code
								`EXE_OR: begin //or R-type instruction rs|rt - > Rd
									wreg_o <= `WriteEnable;
									aluop_o <= `EXE_OR_OP;
									alusel_o <= `EXE_RES_LOGIC;
									reg1_read_o <= 1'b1;
									reg2_read_o <= 1'b1;
									instvalid <= `InstValid;
								end
								`EXE_AND:begin
									wreg_o <= `WriteEnable;
									aluop_o <= `EXE_AND_OP;//R rs&rt ->rd
									alusel_o <=  `EXE_RES_LOGIC;
									reg1_read_o <= 1'b1;
									reg2_read_o <= 1'b1;
									instvalid <= `InstValid;
								end
								`EXE_XOR:begin
									wreg_o <= `WriteEnable;
									aluop_o <= `EXE_XOR_OP;// R rs^rt ->rd
									alusel_o <= `EXE_RES_LOGIC;
									reg1_read_o <= 1'b1;
									reg2_read_o <= 1'b1;
									instvalid <= `InstValid;
								end
								`EXE_NOR:begin
									wreg_o <= `WriteEnable;
									aluop_o <= `EXE_NOR_OP;// R rs~|rt ->rd
									alusel_o <= `EXE_RES_LOGIC;
									reg1_read_o <= 1'b1;
									reg2_read_o <= 1'b1;
									instvalid <= `InstValid;
								end
								`EXE_SLLV:begin
									wreg_o <= `WriteEnable;
									aluop_o <= `EXE_SLL_OP; 
									alusel_o <= `EXE_RES_SHIFT;
									reg1_read_o <= 1'b1;
									reg2_read_o <= 1'b1;
									instvalid <= `InstValid;
								end
								`EXE_SRLV:begin
									wreg_o <= `WriteEnable;
									aluop_o <= `EXE_SRLV_OP;
									alusel_o <= `EXE_RES_SHIFT;
									reg1_read_o <= 1'b1;
									reg2_read_o <= 1'b1;
									instvalid <= `InstValid;
								end
								`EXE_SRAV:begin
									wreg_o <= `WriteEnable;
									aluop_o <= `EXE_SRAV_OP;
									alusel_o <= `EXE_RES_SHIFT;
									reg1_read_o <= 1'b1;
									reg2_read_o <= 1'b1;
									instvalid <= `InstValid;
								end
								`EXE_SYNC:begin
									wreg_o <= `WriteEnable;
									aluop_o <= `EXE_NOP_OP;
									alusel_o <= `EXE_RES_NOP;
									reg1_read_o <= 1'b0;
									reg2_read_o <= 1'b1;
									instvalid <= `InstValid;
								end
								`EXE_MFHI:begin//Assign the value of the special register hi to the register with address rd
									wreg_o <= `WriteEnable;
									aluop_o <= `EXE_MFHI_OP;
									alusel_o <= `EXE_RES_MOVE;
									reg1_read_o <= 1'b0;
									reg2_read_o <= 1'b0;
									instvalid <= `InstValid;
								end
								`EXE_MFLO:begin
									wreg_o <= `WriteEnable;
									aluop_o <= `EXE_MFLO_OP;
									alusel_o <= `EXE_RES_MOVE;
									reg1_read_o <= 1'b0;
									reg2_read_o <= 1'b0;
									instvalid <= `InstValid;
								end
								`EXE_MTHI:begin//Hi < - RS write special register
									wreg_o <= `WriteEnable;
									aluop_o <= `EXE_MTHI_OP;
									alusel_o <= `EXE_RES_MOVE;
									reg1_read_o <= 1'b1;
									reg2_read_o <= 1'b0;
									instvalid <= `InstValid;
								end
								`EXE_MTLO:begin //Lo < - RS write special register
									wreg_o <= `WriteEnable;
									aluop_o <= `EXE_MTLO_OP;
									reg1_read_o <= 1'b1;//rs
									reg2_read_o <= 1'b0;
									instvalid <= `InstValid;
								end
								`EXE_MOVN:begin//Judge if the value of rt register is not 0, assign the value of rs to rd, otherwise the value of rd remains unchanged
									//wreg_o <= `WriteEnable;
									aluop_o <= `EXE_MOVN_OP;
									alusel_o <= `EXE_RES_MOVE;
									reg1_read_o <= 1'b1;
									reg2_read_o <= 1'b1;
									instvalid <= `InstValid;
									//reg2_ The value of O is the value of the register with address rt
									if(reg2_o != `ZeroWord)begin
									wreg_o <= `WriteEnable;
									end else begin
									wreg_o <= `WriteDisable;
									end
								end
								`EXE_MOVZ:begin //Judge if the value of rt register is 0, assign the value of rs to rd, otherwise the value of rd remains unchanged
									aluop_o <= `EXE_MOVZ_OP;
									alusel_o <= `EXE_RES_MOVE;
									reg1_read_o <= 1'b1;
									reg2_read_o <= 1'b1;
									instvalid <= `InstValid;
									if(reg2_o == `ZeroWord)begin
									wreg_o <= `WriteEnable;
									end else begin
									wreg_o <= `WriteDisable;
									end 
								end
								`EXE_SLT:begin//slt instruction Rd < - (RS < RT)
									wreg_o <= `WriteEnable;
									aluop_o <= `EXE_SLT_OP;
									alusel_o <= `EXE_RES_ARITHMETIC;
									reg1_read_o <= 1'b1;
									reg2_read_o <= 1'b1;
									instvalid <= `InstValid;
								end
								`EXE_SLTU:begin //sltu instruction
									wreg_o <= `WriteEnable;
									aluop_o <= `EXE_SLTU_OP;
									alusel_o <= `EXE_RES_ARITHMETIC;
									reg1_read_o <= 1'b1;
									reg2_read_o <= 1'b1;
									instvalid <= `InstValid;
								end
								`EXE_ADD:begin//rd<-rs+rt
									wreg_o <= `WriteEnable;
									aluop_o <= `EXE_ADD_OP;
									alusel_o <= `EXE_RES_ARITHMETIC;
									reg1_read_o <= 1'b1;
									reg2_read_o <= 1'b1;
									instvalid <= `InstValid;
								end
								`EXE_ADDU:begin
									wreg_o <= `WriteEnable;
									aluop_o <= `EXE_ADDU_OP;
									alusel_o <= `EXE_RES_ARITHMETIC;
									reg1_read_o <= 1'b1;
									reg2_read_o <= 1'b1;
									instvalid <= `InstValid;
								end
								`EXE_SUB:begin
									wreg_o <= `WriteEnable;
									aluop_o <= `EXE_SUB_OP;
									alusel_o <= `EXE_RES_ARITHMETIC;
									reg1_read_o <= 1'b1;
									reg2_read_o <= 1'b1;
									instvalid <= `InstValid;
								end
								`EXE_SUBU:begin
									wreg_o <= `WriteEnable;
									aluop_o <= `EXE_SUBU_OP;
									alusel_o <= `EXE_RES_ARITHMETIC;
									reg1_read_o <= 1'b1;
									reg2_read_o <= 1'b1;
									instvalid <= `InstValid;
								end
								`EXE_MULT:begin
									wreg_o <= `WriteEnable;
									aluop_o <= `EXE_MULT_OP;
									reg1_read_o <= 1'b1;
									reg2_read_o <= 1'b1;
									instvalid <= `InstValid;
								end
								`EXE_MULTU:begin
									wreg_o <= `WriteEnable;
									aluop_o <= `EXE_MULTU_OP;
									reg1_read_o <= 1'b1;
									reg2_read_o <= 1'b1;
									instvalid <= `InstValid;
								end 	
								`EXE_DIV:begin
									wreg_o <= `WriteDisable;
									aluop_o <= `EXE_DIV_OP;
									reg1_read_o <= 1'b1;
									reg2_read_o <= 1'b1;
									instvalid <= `InstValid;
								end
								`EXE_DIVU:begin
									wreg_o <= `WriteDisable;
									aluop_o <= `EXE_DIVU_OP;
									reg1_read_o <= 1'b1;
									reg2_read_o <= 1'b1;
									instvalid <= `InstValid;
								end
								`EXE_JR:begin
									wreg_o <= `WriteDisable;
									aluop_o <= `EXE_JR_OP;
									alusel_o <= `EXE_RES_JUMP_BRANCH;
									reg1_read_o <= 1'b1;//The rs register needs to be used
									reg2_read_o <= 1'b0;
									wd_o <= inst_i[15:11];
									link_addr_o <= pc_plus_8;//Return address
									branch_target_address_o <= reg1_o;//Destination address of transfer to
									branch_flag_o <= `Branch;//Whether transfer occurs
									next_inst_in_delayslot_o <= `InDelaySlot;//The next instruction is not in the delay slot
									instvalid <= `InstValid;
								end
								`EXE_JALR:begin
									wreg_o <= `WriteEnable;
									aluop_o <= `EXE_JALR_OP;
									alusel_o <= `EXE_RES_JUMP_BRANCH;
									reg1_read_o <= 1'b1;
									reg2_read_o <= 1'b0;
									wd_o <= inst_i[15:11];
									link_addr_o <= pc_plus_8;
									branch_target_address_o <= reg1_o;
									branch_flag_o <= `Branch;
									next_inst_in_delayslot_o <= `InDelaySlot;
									instvalid <= `InstValid;
								end
								default:begin
								end
								endcase
								end
								
								
								
		  					default:begin
									//aluop_o <= `EXE_NOP_OP;
									//alusel_o <= `EXE_RES_OP;
									//wd_o <= `NOPRegAddr;
									//wreg_o <= `WriteDisable;
									//instvalid <= `InstValid;
									//reg1_read_o <= `ReadDisable;
									//reg2_read_o <= `ReadDisable;
									//reg1_addr_o <= inst_i[25:21];
									//reg2_addr_o <= inst_i[20:16];
		  					end
		  				endcase//op3
		  			end	// 5'b00000
					`EXE_J:begin
						wreg_o <= `WriteDisable;//Whether to write to the destination register in the decoding stage
						aluop_o <= `EXE_J_OP;
						alusel_o <= `EXE_RES_JUMP_BRANCH;
						reg1_read_o <= 1'b0;
						reg2_read_o <= 1'b0;
						link_addr_o <= `ZeroWord;
						branch_flag_o <= `Branch;
						next_inst_in_delayslot_o <= `InDelaySlot;
						instvalid <= `InstValid;
						branch_target_address_o <= {pc_plus_4[31:28],inst_i[25:0],2'b00};//Address of transfer destination
					end
					`EXE_JAL:begin
						wreg_o <= `WriteEnable;
						aluop_o <= `EXE_JAL_OP;
						alusel_o <= `EXE_RES_JUMP_BRANCH;
						reg1_read_o <= 1'b0;
						reg2_read_o <= 1'b0;
						wd_o <= 5'b11111;//Address register $1 of destination register to write
						link_addr_o <= pc_plus_8;//Return address of the transfer instruction to be saved
						branch_flag_o <= `Branch;//Flag of transfer occurrence
						next_inst_in_delayslot_o <= `InDelaySlot;
						instvalid <= `InstValid;
						branch_target_address_o <= {pc_plus_4[31:28],inst_i[25:0],2'b00};
					end
					`EXE_BEQ:begin
						wreg_o <= `WriteDisable;
						aluop_o <= `EXE_BEQ_OP;
						alusel_o <= `EXE_RES_JUMP_BRANCH;
						reg1_read_o <= 1'b1;//Need to compare rs and rt 
						reg2_read_o <= 1'b1;
						instvalid <= `InstValid;
						if(reg1_o == reg2_o)begin //If the value of rs is reg1_ The value of O and rd is reg2_o equal transfer
							branch_target_address_o <= pc_plus_4 + imm_sll2_signedext;
							branch_flag_o <= `Branch;
							next_inst_in_delayslot_o <= `InDelaySlot;
						end
					end
					`EXE_BGTZ:begin
						wreg_o <= `WriteDisable;
						aluop_o <= `EXE_BGTZ_OP;
						alusel_o <= `EXE_RES_JUMP_BRANCH;
						reg1_read_o <= 1'b1;//rs
						reg2_read_o <= 1'b0;
						instvalid <= `InstValid;
						if((reg1_o[31] == 1'b0)&&(reg1_o != `ZeroWord))begin
							branch_target_address_o <= pc_plus_4 + imm_sll2_signedext;
							branch_flag_o <= `Branch;
							next_inst_in_delayslot_o <= `InDelaySlot;
						end
					end
					`EXE_BLEZ:begin
						wreg_o <= `WriteDisable;//Whether to write to the destination register in the decoding stage
						aluop_o <= `EXE_BLEZ_OP;
						alusel_o <= `EXE_RES_JUMP_BRANCH;
						reg1_read_o <= 1'b1;
						reg2_read_o <= 1'b0;
						instvalid <= `InstValid;
						if((reg1_o[31] == 1'b1)&&(reg1_o != `ZeroWord))begin
							branch_target_address_o <= pc_plus_4 + imm_sll2_signedext;
							branch_flag_o <= `Branch;
							next_inst_in_delayslot_o <= `InDelaySlot;
						end
					end
					`EXE_BNE:begin
						wreg_o <= `WriteDisable;
						aluop_o <= `EXE_BNE_OP;
						alusel_o <= `EXE_RES_JUMP_BRANCH;
						reg1_read_o <= 1'b1;
						reg2_read_o <= 1'b1;
						instvalid <= `InstValid;
						if(reg1_o != reg2_o)begin
							branch_target_address_o <= pc_plus_4+imm_sll2_signedext;
							branch_flag_o <= `Branch;
							next_inst_in_delayslot_o <= `InDelaySlot;
						end
					end
					`EXE_REGIMM_INST:begin
						case(op4)
							`EXE_BLTZAL:begin//bltzal
								wreg_o <= `WriteEnable;
								aluop_o <= `EXE_BGEZAL_OP;
								alusel_o <= `EXE_RES_JUMP_BRANCH;
								reg1_read_o <= 1'b1;
								reg2_read_o <= 1'b0;
								link_addr_o <= pc_plus_8;
								wd_o <= 5'b11111;
								instvalid <= `InstValid;
								if(reg1_o[31] == 1'b1) begin//reg1_o<0
									branch_target_address_o <= pc_plus_4+imm_sll2_signedext;
									branch_flag_o <= `Branch;
									next_inst_in_delayslot_o <= `InDelaySlot;
								end
							end
							`EXE_BLTZ:begin//bltz
								wreg_o <= `WriteDisable;
								aluop_o <= `EXE_BGEZAL_OP;
								alusel_o <= `EXE_RES_JUMP_BRANCH;
								reg1_read_o <= 1'b1;
								reg2_read_o <= 1'b0;
								instvalid <= `InstValid;
								if(reg1_o[31] == 1'b1)begin
									branch_target_address_o <= pc_plus_4 + imm_sll2_signedext;
									branch_flag_o <= `Branch;
									next_inst_in_delayslot_o <= `InDelaySlot;
								end
							end
							`EXE_BGEZ:begin//bgez
								wreg_o <= `WriteDisable;
								aluop_o <= `EXE_BGEZ_OP;
								alusel_o <= `EXE_RES_JUMP_BRANCH;
								reg1_read_o <= 1'b1;
								reg2_read_o <= 1'b0;
								instvalid <= `InstValid;
								if(reg1_o[31] == 1'b0)begin//The value of rs is greater than or equal to 0
									branch_target_address_o <= pc_plus_4 + imm_sll2_signedext;
									branch_flag_o <= `Branch;
									next_inst_in_delayslot_o <= `InDelaySlot;
								end
							end
							`EXE_BGEZAL:begin//bgezal
								wreg_o <= `WriteEnable;
								aluop_o <= `EXE_BGEZAL_OP;
								alusel_o <= `EXE_RES_JUMP_BRANCH;
								reg1_read_o <= 1'b1;
								reg2_read_o <= 1'b0;
								link_addr_o <= pc_plus_8;
								wd_o <= 5'b11111;
								instvalid <= `InstValid;
								if(reg1_o[31] == 1'b0)begin
									branch_target_address_o <= pc_plus_4 + imm_sll2_signedext;
									branch_flag_o <= `Branch;
									next_inst_in_delayslot_o <= `InDelaySlot;
								end
							end
					default:begin
				end
				endcase		// op2	
			end	
		  	`EXE_ORI:begin                        //ORI instruction
		  		wreg_o <= `WriteEnable;		
		  		aluop_o <= `EXE_OR_OP;
		  		alusel_o <= `EXE_RES_LOGIC; 
		  		reg1_read_o <= 1'b1;
		  		reg2_read_o <= 1'b0;	  	
					imm <= {16'h0, inst_i[15:0]};	//Immediate 0 extension
					wd_o <= inst_i[20:16]; // Read rt address
					instvalid <= `InstValid;	
		  	end 
		  	`EXE_ANDI:begin //andi
		  		wreg_o <= `WriteEnable;
		  		aluop_o <= `EXE_AND_OP;
		  		alusel_o <= `EXE_RES_LOGIC;
		  		reg1_read_o <= 1'b1;
		  		reg2_read_o <= 1'b0;
		  		imm <= {16'h0,inst_i[15:0]};
		  		wd_o <= inst_i[20:16];//rt
		  		instvalid = `InstValid;
		  	end
		  	`EXE_XORI:begin//xori
		  		wreg_o <= `WriteEnable;
		  		aluop_o <= `EXE_XOR_OP;
		  		alusel_o <= `EXE_RES_LOGIC;
		  		reg1_read_o <= 1'b1;
		  		reg2_read_o <= 1'b0;
		  		imm <= {16'h0,inst_i[15:0]};
		  		wd_o <= inst_i[20:16];
		  		instvalid = `InstValid;		
		  	end
		  	`EXE_LUI:begin//lui
		  		wreg_o <= `WriteEnable;//Notice the typographical errors in the book
		  		aluop_o <= `EXE_OR_OP;
		  		alusel_o <= `EXE_RES_LOGIC;
		  		reg1_read_o <= 1'b1;
		  		reg2_read_o <= 1'b0;
		  		imm <= {inst_i[15:0],16'h0};	
		  		wd_o <= inst_i[20:16];
		  		instvalid <= `InstValid;
		  	end
		  	/*`EXE_PREF:	begin//pref
		  		wreg_o <= `WriteDisable;
		  		aluop_o <= `EXE_NOP_OP;
		  		alusel_o <= `EXE_RES_NOP;
		  		reg1_read_o <= 1'b0;
		  		reg2_read_o <= 1'b0;
		  		instvalid <= 	`InstValid;
		  	end	*/	
		  	`EXE_SLTI:begin //slti   rt <- (rs < (sign_extended)immediate)
		  		wreg_o <= `WriteEnable;
		  		aluop_o <= `EXE_SLT_OP;
		  		alusel_o <= `EXE_RES_ARITHMETIC;
		  		reg1_read_o <= 1'b1;
		  		reg2_read_o <= 1'b0;
		  		imm <= {{16{inst_i[15]}},inst_i[15:0]};
		  		wd_o <= inst_i[20:16];
		  		instvalid <= `InstValid;
		  	end
		  	`EXE_SLTIU:begin
		  		wreg_o <= `WriteEnable;
		  		aluop_o <= `EXE_SLTU_OP;
		  		alusel_o <= `EXE_RES_ARITHMETIC;
		  		reg1_read_o <= 1'b1;
		  		reg2_read_o <= 1'b0;
		  		imm <= {{16{inst_i[15]}},inst_i[15:0]};
		  		wd_o <= inst_i[20:16];
		  		instvalid <= `InstValid;
		  	end
		  	`EXE_ADDI:begin
		  		wreg_o <= `WriteEnable;
		  		aluop_o <= `EXE_ADDI_OP;
		  		alusel_o <= `EXE_RES_ARITHMETIC;
		  		reg1_read_o <= 1'b1;
		  		reg2_read_o <= 1'b0;
		  		imm <= {{16{inst_i[15]}},inst_i[15:0]};
		  		wd_o <= inst_i[20:16];
		  		instvalid <= `InstValid;
		  	end
		  	`EXE_ADDIU:begin
		  		wreg_o <= `WriteEnable;
		  		aluop_o <= `EXE_ADDIU_OP;
		  		alusel_o <= `EXE_RES_ARITHMETIC;
		  		reg1_read_o <= 1'b1;
		  		reg2_read_o <= 1'b0;
		  		imm <= {{16{inst_i[15]}},inst_i[15:0]};
		  		wd_o <= inst_i[20:16];
		  		instvalid <= `InstValid;
		  	end		
		  	`EXE_LB:begin//Write the loading result to the destination register
		  		wreg_o <= `WriteEnable;
		  		aluop_o <= `EXE_LB_OP;
		  		alusel_o <= `EXE_RES_LOAD_STORE;
		  		reg1_read_o <= 1'b1;//Calculating the load destination address requires the register value with address base
		  		reg2_read_o <= 1'b0;
		  		wd_o <= inst_i[20:16];//Destination register address
		  		instvalid <= `InstValid;
		  	end
		  	`EXE_LBU:begin
		  		wreg_o <= `WriteEnable;
		  		aluop_o <= `EXE_LBU_OP;
		  		alusel_o <= `EXE_RES_LOAD_STORE;
		  		reg1_read_o <= 1'b1;
		  		reg2_read_o <= 1'b0;
		  		wd_o <= inst_i[20:16];
		  		instvalid <= `InstValid;
		  	end
		  	`EXE_LH:begin
		  		wreg_o <= `WriteEnable;
		  		aluop_o <= `EXE_LH_OP;
		  		alusel_o <= `EXE_RES_LOAD_STORE;
		  		reg1_read_o <= 1'b1;
		  		reg2_read_o <= 1'b0;
		  		wd_o <= inst_i[20:16];
		  		instvalid <= `InstValid;
		  	end
		  	`EXE_LHU:begin
		  		wreg_o <= `WriteEnable;
		  		aluop_o <= `EXE_LHU_OP;
		  		alusel_o <= `EXE_RES_LOAD_STORE;
		  		reg1_read_o <= 1'b1;
		  		reg2_read_o <= 1'b0;
		  		wd_o <= inst_i[20:16];
		  		instvalid <= `InstValid;
		  	end
		  	`EXE_LW:begin
		  		wreg_o <= `WriteEnable;
		  		aluop_o <= `EXE_LW_OP;
		  		alusel_o <= `EXE_RES_LOAD_STORE;
		  		reg1_read_o <= 1'b1;
		  		reg2_read_o <= 1'b0;
		  		wd_o <= inst_i[20:16];
		  		instvalid <= `InstValid;
		  	end
		  	`EXE_LWL:begin//The loading result to the left needs to be written to the destination register [20:16]
		  		wreg_o <= `WriteEnable;
		  		aluop_o <= `EXE_LWL_OP;
		  		alusel_o <= `EXE_RES_LOAD_STORE;
		  		reg1_read_o <= 1'b1;
		  		reg2_read_o <= 1'b1;
		  		wd_o <= inst_i[20:16];
		  		instvalid <= `InstValid;
		  	end
		  	`EXE_LWR:begin//Load right
		  		wreg_o <= `WriteEnable;
		  		aluop_o <= `EXE_LWR_OP;
		  		alusel_o <= `EXE_RES_LOAD_STORE;
		  		reg1_read_o <= 1'b1;
		  		reg2_read_o <= 1'b1;
		  		wd_o <= inst_i[20:16];
		  		instvalid <= `InstValid;
		  	end
		  	`EXE_SB:begin //There is no need to write a general register to calculate the value of the register whose address is base that needs to be used to store the target address
		  		wreg_o <= `WriteDisable;
		  		aluop_o <= `EXE_SB_OP;
		  		reg1_read_o <= 1'b1; //[25:21] reg1_addr_o ======> base
		  		reg2_read_o <= 1'b1;
		  		instvalid <= `InstValid;
		  		alusel_o <= `EXE_RES_LOAD_STORE;
		  	end
		  	`EXE_SH:begin
		  		wreg_o <= `WriteDisable;
		  		aluop_o <= `EXE_SH_OP;
		  		reg1_read_o <= 1'b1;
		  		reg2_read_o <= 1'b1;
		  		instvalid <= `InstValid;
		  		alusel_o <= `EXE_RES_LOAD_STORE;
		  	end
		  	`EXE_SW:begin
		  		wreg_o <= `WriteDisable;
		  		aluop_o <= `EXE_SW_OP;
		  		reg1_read_o <= 1'b1;
		  		reg2_read_o <= 1'b1;
		  		instvalid <= `InstValid;
		  		alusel_o <= `EXE_RES_LOAD_STORE;
		  	end
		  	`EXE_SWL:begin
		  		wreg_o <= `WriteDisable;
		  		aluop_o <= `EXE_SWL_OP;
		  		reg1_read_o <= 1'b1;
		  		reg2_read_o <= 1'b1;
		  		instvalid <= `InstValid;
		  		alusel_o <= `EXE_RES_LOAD_STORE;
		  	end
		  	`EXE_SWR:begin
		  		wreg_o <= `WriteDisable;
		  		aluop_o <= `EXE_SWR_OP;
		  		reg1_read_o <= 1'b1;
		  		reg2_read_o <= 1'b1;
		  		instvalid <= `InstValid;
		  		alusel_o <= `EXE_RES_LOAD_STORE;
		  	end
		  	`EXE_SPECIAL2_INST:begin//(op)
				case(op3)
					`EXE_CLZ:begin
		  				wreg_o <= `WriteEnable;
		  				aluop_o <= `EXE_CLZ_OP;
		  				alusel_o <= `EXE_RES_ARITHMETIC;
		  				reg1_read_o <= 1'b1;
		  				reg2_read_o <= 1'b0;
		  				instvalid <= `InstValid;
		  			end
					`EXE_CLO:begin
		  				wreg_o <= `WriteEnable;
		  				aluop_o <= `EXE_CLO_OP;
		  				alusel_o <= `EXE_RES_ARITHMETIC;
		  				reg1_read_o <= 1'b1;
		  				reg2_read_o <= 1'b0;
		  				instvalid <= `InstValid;
		  			end
					`EXE_MUL:begin
		  				wreg_o <= `WriteEnable;
		  				aluop_o <= `EXE_MUL_OP;
		  				alusel_o <= `EXE_RES_MUL;
		  				reg1_read_o <= 1'b1;
		  				reg2_read_o <= 1'b1;
		  				instvalid <= `InstValid;
		  			end
					`EXE_MADD:begin 
		  				wreg_o <= `WriteDisable;
		  				aluop_o <= `EXE_MADD_OP;
		  				alusel_o <= `EXE_RES_MUL;
		  				reg1_read_o <= 1'b1;
		  				reg2_read_o <= 1'b1;
		  				instvalid <= `InstValid;
		  			end
					`EXE_MADDU:begin
		  				wreg_o <= `WriteDisable;
		  				aluop_o <= `EXE_MADDU_OP;
		  			  alusel_o <= `EXE_RES_MUL;
		  				reg1_read_o <= 1'b1;
		  				reg2_read_o <= 1'b1;
		  				instvalid <= `InstValid;
		  			end
					`EXE_MSUB:begin
		  				wreg_o <= `WriteDisable;
		  				aluop_o <= `EXE_MSUB_OP;
		  				alusel_o <= `EXE_RES_MUL;
		  				reg1_read_o <= 1'b1;
		  				reg2_read_o <= 1'b1;
		  				instvalid <= `InstValid;
		  			end
					`EXE_MSUBU:begin
		  				wreg_o <= `WriteDisable;
		  				aluop_o <= `EXE_MSUBU_OP;
		  				alusel_o <= `EXE_RES_MUL;
		  				reg1_read_o <= 1'b1;
		  				reg2_read_o <= 1'b1;
		  				instvalid <= `InstValid;
		  			end
					default:begin
					 end
				endcase //EXE_SPECIAL_INST2 case
			end				 
		    default:begin
		    end
		endcase		  //case op		
		if(inst_i[31:21] == 11'b00000000000)begin //sll,srl,sra
		  	if(op3 == `EXE_SLL) begin
		  		wreg_o <= `WriteEnable;
		  		aluop_o <= `EXE_SLL_OP;
		  		alusel_o <= `EXE_RES_SHIFT;
		  		reg1_read_o <= 1'b0;
		  		reg2_read_o <= 1'b1;
		  		imm[4:0] <= inst_i[10:6];
		  		wd_o <= inst_i[15:11];
		  		instvalid <= `InstValid;
		  	end else if(op3 == `EXE_SRL)begin
		  		wreg_o <= `WriteEnable;
		  		aluop_o <= `EXE_SRL_OP;
		  		alusel_o <= `EXE_RES_SHIFT;
		  		reg1_read_o <= 1'b0;
		  		reg2_read_o <= 1'b1;
		  		imm[4:0] <= inst_i[10:6];
		  		wd_o <= inst_i[15:11];
		  		instvalid <= `InstValid;
		  	end else if(op3 == `EXE_SRA) begin
		  		wreg_o <= `WriteEnable;
		  		aluop_o <= `EXE_SRA_OP;
		  		alusel_o <= `EXE_RES_SHIFT;
		  		reg1_read_o <= 1'b0;
		  		reg2_read_o <= 1'b1;
		  		imm[4:0] <= inst_i[10:6];
		  		wd_o <= inst_i[15:11];
		  		instvalid <= `InstValid;
		  	end
//endcase
		  	//end
		end       //if
	end 
end        //always
	
/*       Data push forward
 Give reg1_o two cases are added in the assignment process
1:If the register to be read by Regfile module reading port 1 is the destination register to be written in the execution stage, the result of the execution stage is directly transferred to ex_wdata_i as reg1_ Value of O
2:If the register to be read by Regfile module reading port 1 is the destination register to be written in the memory access stage, the result of the memory access stage is directly mem_wdata_i as reg1_ Value of O*/
	always @ (*) begin
		if(rst == `RstEnable) begin
			reg1_o <= `ZeroWord;		
		end else if((reg1_read_o == 1'b1) && (ex_wreg_i == 1'b1) 
								&& (ex_wd_i == reg1_addr_o)) begin
			reg1_o <= ex_wdata_i; 
		end else if((reg1_read_o == 1'b1) && (mem_wreg_i == 1'b1) 
								&& (mem_wd_i == reg1_addr_o)) begin
			reg1_o <= mem_wdata_i; 			
	  end else if(reg1_read_o == 1'b1) begin
	  	reg1_o <= reg1_data_i;
	  end else if(reg1_read_o == 1'b0) begin
	  	reg1_o <= imm;
	  end else begin
	    reg1_o <= `ZeroWord;
	  end
	end
	
	always @ (*) begin
		if(rst == `RstEnable) begin
			reg2_o <= `ZeroWord;
		end else if((reg2_read_o == 1'b1) && (ex_wreg_i == 1'b1) 
								&& (ex_wd_i == reg2_addr_o)) begin
			reg2_o <= ex_wdata_i; 
		end else if((reg2_read_o == 1'b1) && (mem_wreg_i == 1'b1) 
								&& (mem_wd_i == reg2_addr_o)) begin
			reg2_o <= mem_wdata_i;			
	  end else if(reg2_read_o == 1'b1) begin
	  	reg2_o <= reg2_data_i;
	  end else if(reg2_read_o == 1'b0) begin
	  	reg2_o <= imm;
	  end else begin
	    reg2_o <= `ZeroWord;
	  end
	end


//Output variable is_in_delayslot_o indicates whether the instruction in the current decoding stage is a delay slot instruction
always @ (*)begin
	if(rst == `RstEnable)begin
		is_in_delayslot_o <= `NotInDelaySlot;
	end else begin
		//Directly equal to is_in_delayslot_i
		is_in_delayslot_o <= is_in_delayslot_i;
	end
end

endmodule


id_ex.v

`include "define.v"
//At the rising edge of the clock cycle, the result of the decoding stage is passed to the execution stage*/
module id_ex(

	input	wire										clk,
	input wire										rst,

	
	//Information transmitted from decoding stage
	input wire[`AluOpBus]         id_aluop,
	input wire[`AluSelBus]        id_alusel,
	input wire[`RegBus]           id_reg1,
	input wire[`RegBus]           id_reg2,
	input wire[`RegAddrBus]       id_wd,
	input wire                    id_wreg,
	
	//Information from control module
	input wire[5:0] stall	,
	input wire[`RegBus] id_link_address,
	input wire id_is_in_delayslot,
	input wire next_inst_in_delayslot_i,
	
	input wire[`RegBus] id_inst, //The instruction that the signal from the id module is currently in the decoding stage
	
	
	
	
	//Information passed to the execution phase
	output reg[`AluOpBus]         ex_aluop,
	output reg[`AluSelBus]        ex_alusel,
	output reg[`RegBus]           ex_reg1,
	output reg[`RegBus]           ex_reg2,
	output reg[`RegAddrBus]       ex_wd,
	output reg                    ex_wreg,
	
	output reg[`RegBus] ex_link_address,
	output reg ex_is_in_delayslot,
	output reg is_in_delayslot_o,
	output reg[`RegBus] ex_inst //The instruction passed to the ex module that is currently in the execution phase
	
);


	always @ (posedge clk) begin
		if (rst == `RstEnable) begin
			ex_aluop <= `EXE_NOP_OP;
			ex_alusel <= `EXE_RES_NOP;
			ex_reg1 <= `ZeroWord;
			ex_reg2 <= `ZeroWord;
			ex_wd <= `NOPRegAddr;
			ex_wreg <= `WriteDisable;
			ex_link_address <= `ZeroWord;
			ex_is_in_delayslot <= `NotInDelaySlot;
			ex_inst <= `ZeroWord;
		end else if(stall[2] == `Stop && stall[3] == `NoStop)begin//Execute stop memory access continue
			ex_aluop <= `EXE_NOP_OP;
			ex_alusel <= `EXE_RES_NOP;
			ex_reg1 <= `ZeroWord;
			ex_reg2 <= `ZeroWord;
			ex_wd <= `NOPRegAddr;
			ex_wreg <= `WriteDisable;
			ex_link_address <= `ZeroWord;
			ex_is_in_delayslot <= `NotInDelaySlot;
			ex_inst <= `ZeroWord;
		end else if(stall[2] == `NoStop)begin//Execution continues
			ex_aluop <= id_aluop;
			ex_alusel <= id_alusel;
			ex_reg1 <= id_reg1;
			ex_reg2 <= id_reg2;
			ex_wd <= id_wd;
			ex_wreg <= id_wreg;
			ex_link_address <= id_link_address;
			ex_is_in_delayslot <= id_is_in_delayslot;
			ex_inst <= id_inst;
			is_in_delayslot_o <= next_inst_in_delayslot_i;
		/*end else begin		
			ex_aluop <= id_aluop;
			ex_alusel <= id_alusel;
			ex_reg1 <= id_reg1;
			ex_reg2 <= id_reg2;
			ex_wd <= id_wd;
			ex_wreg <= id_wreg;		
		end*/
	end
	end
	
endmodule
	

Execution module

ex.v

`include "define.v"
//ex.v execution module
module ex(
//Information sent from decoding stage to execution stage
input wire[`AluOpBus] aluop_i,
input wire[`AluSelBus] alusel_i,
input wire[`RegBus] reg1_i,
input wire[`RegBus] reg2_i,
input wire[`RegAddrBus] wd_i,
input wire wreg_i,
input wire rst,
//HILO module gives the value of hi and lo registers
input wire[`RegBus] hi_i,
input wire[`RegBus] lo_i,
//Whether the instruction in the write back phase should write hi and lo is used to detect the data related problems caused by hi and lo registers
input wire[`RegBus] wb_hi_i,
input wire[`RegBus] wb_lo_i,
input wire wb_whilo_i,
//Whether the instruction in the memory access stage should write hi and lo is used to detect the data related problems caused by hi and lo registers
input wire[`RegBus] mem_hi_i,
input wire[`RegBus] mem_lo_i,
input wire mem_whilo_i,

//Added input port
input wire[`DoubleRegBus] hilo_temp_i,//Save multiplication results
input wire[1:0] cnt_i,//Which cycle is in the implementation phase

//Add input from division module
input wire[`DoubleRegBus] div_result_i,
input wire div_ready_i,

//The return address to be saved for the branch instruction in the execution stage
input wire[`RegBus] link_address_i,

//Whether the instruction in the current execution stage is in the delay slot
input wire is_in_delayslot_i,

//New input port inst_i. Its value is the instruction currently in execution
input wire[`RegBus] inst_i,//Instructions currently in execution

//Write operation request of instruction in execution phase to lo and hi registers
output reg[`RegBus] hi_o,
output reg[`RegBus] lo_o,
output reg whilo_o,

//Results of execution
output reg[`RegAddrBus] wd_o,
output reg wreg_o,
output reg[`RegBus] wdata_o,
output reg stallreq,

output reg[`DoubleRegBus] hilo_temp_o,
output reg[1:0] cnt_o,

//Output added to division module
output reg[`RegBus] div_opdata1_o,
output reg[`RegBus] div_opdata2_o,
output reg div_start_o,
output reg signed_div_o,


//output reg is_in_delayslot_o,
//The following new output interfaces are prepared for loading and storing instructions
output wire[`AluOpBus] aluop_o, //Subtype to be operated on during execution
output wire[`RegBus] mem_addr_o,//Load the memory address corresponding to the storage instruction
output wire[`RegBus] reg2_o//Store the data to be stored by the instruction, or the address of the destination register to be loaded by the LWL and LWR instructions
);
//Save the result of logical operation
reg[`RegBus] logicout;
//Save the result of the shift operation
reg[`RegBus] shiftres;
//Save the results of the move operation
reg[`RegBus] moveres;
//Save the latest values of hi and lo registers
reg[`RegBus] HI;
reg[`RegBus] LO;
//Is the pipeline suspended due to division
reg stallreq_for_div;
/***********************Chapter 7 new definitions of some variables***********************/
wire ov_sum;//Save overflow
wire reg1_eq_reg2;//Is the first operand equal to the second operand
wire reg1_lt_reg2;//Is the first operand less than the second operand
reg[`RegBus] arithmeticres;//Save the result of arithmetic operation
reg[`DoubleRegBus] mulres;//Save the result of multiplication
wire[`RegBus] reg2_i_mux;//Save the input second operand reg2_ Complement of I
wire[`RegBus] reg1_i_not;//Save the first operand entered reg1_i take the inverse value
wire[`RegBus] result_sum;//Save addition results
wire[`RegBus] opdata1_mult;//Multiplicand in multiplication operation
wire[`RegBus] opdata2_mult;//Multiplier in multiplication operation
wire[`DoubleRegBus] hilo_temp;//Temporarily save the multiplication result with a width of 64 bits
reg [`DoubleRegBus] hilo_temp1;
reg stallreq_for_madd_msub;
//aluop_o will be passed to the storage access stage, which will be used to determine the loading and storage types
assign aluop_o = aluop_i;
//mem_addr_o will be passed to the memory access stage, which is the memory address corresponding to the loading and storage instructions. Here reg1_i is the value of the general-purpose register with address base in the loading and storage instruction
//By calculating mem_addr_o. Understand why the ID module adds an output interface Inst in the decoding stage_ o
assign mem_addr_o = reg1_i + {{16{inst_i[15]}},inst_i[15:0]};
//reg2_i is the data to be stored by the storage instruction, or the original value of the destination register to be loaded by the LWL and LWR instructions, which is passed through reg2_o interface transfer to memory access stage
assign reg2_o = reg2_i;
/*******************************************************************
**            Paragraph 1: according to aluop_ The operator type indicated by I**
*******************************************************************/
always @ (*) 
begin//1
	if(rst == `RstEnable)
	begin//2
		logicout <= `ZeroWord;
	end//2
	else
	begin//3
		case(aluop_i)//4
			`EXE_OR_OP:begin//5 logical or
				logicout <= reg1_i|reg2_i;
			end 
			`EXE_AND_OP: begin //Logic and
				logicout <= reg1_i&reg2_i;
			end
			`EXE_NOR_OP:begin //Logical or not
				logicout <= ~(reg1_i|reg2_i);
			end
			`EXE_XOR_OP:begin //Logical XOR
				logicout <= reg1_i^reg2_i;
			end
			default:begin//6
				logicout <= `ZeroWord;
			end//6
		endcase//4
	end//3
end//1
always @ (*) begin
	if(rst == `RstEnable)begin
		shiftres <= `ZeroWord;
	end else begin
		case(aluop_i)
			`EXE_SLL_OP:begin //Logical shift left
				shiftres <= reg2_i << reg1_i[4:0];
			end
			`EXE_SRL_OP:begin //Logical shift right
				shiftres <= reg2_i >> reg1_i[4:0];
			end
			`EXE_SRA_OP:begin//Arithmetic shift right 1
				shiftres <= ({32{reg2_i[31]}}<<(6'd32-{1'b0,reg1_i[4:0]})) |/*rt Shift sa bit to the right*/ reg2_i>>reg1_i[4:0];
			end
			default:begin
			 shiftres <= `ZeroWord;
		end
	endcase
end
end
	
/******************************************************************
****The third paragraph: get the latest value of hi and lo registers. Here we need to solve the problems related to data****
******************************************************************/
always @ (*)begin
	if(rst == `RstEnable) begin
		{HI,LO} <= {`ZeroWord,`ZeroWord};
	end else if(mem_whilo_i == `WriteEnable)begin
		{HI,LO} <= {mem_hi_i,mem_lo_i};//The instructions in the memory access stage shall be written to hi and lo registers
	end else if(wb_whilo_i == `WriteEnable)begin
		{HI,LO} <= {wb_hi_i,wb_lo_i};//The instruction in the write back phase should write hi and lo registers
end
end
/*******************************************************************
******************Section 4: MFHI,MFLO,MOVN,MOVZ instructions********************
*******************************************************************/
always @ (*) begin
	if(rst == `RstEnable) begin
		moveres <= `ZeroWord;
	end else begin
		moveres <= `ZeroWord;
		case(aluop_i)
			`EXE_MFHI_OP:begin
				//rd<-hi
				moveres <= HI;//The value of HI is the result of the move operation
			end
			`EXE_MFLO_OP:begin
				//rd<-lo
				moveres <= LO;
			end
			`EXE_MOVN_OP:begin
				//rd<-rs
				moveres <= reg1_i;
			end
			`EXE_MOVZ_OP:begin
				//rd<-rs
				moveres <= reg1_i;
			end
			default:begin
			end
		endcase
	end
end
/***************************************************************
*******For mthi and mtlo instructions, you need to give while_ o,hi_ o,lo_ Value of O*******
***************************************************************/                 
always @ (*)begin
	if(rst == `RstEnable) begin
		whilo_o <= `WriteDisable;
		hi_o <= `ZeroWord;
		lo_o <= `ZeroWord;
	end else if(aluop_i == `EXE_MTHI_OP)begin
		whilo_o <= `WriteEnable;
		hi_o <= reg1_i;
		lo_o <= LO;//Write HI register, so LO remains unchanged
	end else if(aluop_i == `EXE_MTLO_OP)begin
		whilo_o <= `WriteEnable;
		hi_o <= HI;
		lo_o <= reg1_i;
	end else begin
		whilo_o <= `WriteDisable;
		hi_o <= `ZeroWord;
		lo_o <= `ZeroWord;
	end
end
//end
//endmodule
/*************************************************************
******************Paragraph 5: calculate the values of the following five variables******************
*************************************************************/
/*(1)If it is subtraction or signed comparison, reg2_i_mux equals the second operand reg2_ Complement of I,
Otherwise reg2_i_mux is equal to the second operand reg2_i*/
assign reg2_i_mux = ((aluop_i == `EXE_SUB_OP)||(aluop_i == `EXE_SUBU_OP)||(aluop_i == `EXE_SLT_OP))?(~reg2_i)+1:reg2_i;
/*(2)There are three situations:
A:If it is an addition operation, reg2_i_mux is the second operand reg2_i. So result_sum is the result of addition
B:In case of subtraction, reg2_i_mux is the second operand reg2_i's complement, so result_sum is the result of subtraction
C:If it is a signed comparison operation, reg2_i_mux is the second operand reg2_i's complement, so result_sum is subtraction
 For the result of the operation, you can judge whether the result of subtraction is less than 0, and then judge the first operand reg1_ Is I less than the second operand reg2_i*/
assign result_sum = reg1_i + reg2_i_mux;
/*(3)Calculate whether the overflow occurs. When the addition instruction add and addi and the subtraction instruction sub are executed, it is necessary to judge whether the overflow occurs when one of the following two conditions is met
A:reg1_i Is a positive number, reg2_i_mux is positive, but the sum of the two is negative
B:reg1_i Negative, reg2_i_mux is negative, but the sum of the two is positive*/
//I don't understand this. I understand it on March 10, 2022
assign ov_sum = ((!reg1_i[31] && !reg2_i_mux[31]) && result_sum[31])||((reg1_i[31] && reg2_i_mux[31])&&(!result_sum[31]));
/*(4)There are two ways to calculate whether operand 1 is less than operand 2:
A:aluop_i Is EXE_SLT_OP stands for signed comparison operation
1.reg1_i Negative, reg2_i is a positive number, obviously reg1_i is less than reg2_i
2.reg1_i Positive, reg2_i is a positive number and reg1_i minus reg2_ When the value of I is less than 0(result_sum is negative), reg1_i is less than reg2_i
3.reg1_i Negative, reg2_i is negative and reg1_i minus reg2_ When the value of I is less than 0(result_sum is negative), reg1_i is less than reg2_i
B:When comparing unsigned numbers, the comparison operator is directly used to compare reg1_i and reg2_i*/
assign reg1_lt_reg2 = ((aluop_i == `EXE_SLT_OP))?((reg1_i[31]&&!reg2_i[31])||(!reg1_i[31]&&!reg2_i[31]&&result_sum[31])||(reg1_i[31]&&reg2_i[31]&&result_sum[31])):(reg1_i<reg2_i);
//(5) The operand 1 is inversely assigned to reg1 bit by bit_ i_ not
assign reg1_i_not = ~reg1_i;
/*****************************************************************
*****Paragraph 6: assign value to arithmetics variable according to different arithmetic operation types*******
*****************************************************************/
always @ (*) begin
	if(rst == `RstEnable)begin
		arithmeticres <= `ZeroWord;
	end else begin
		case(aluop_i) //Select operation type
			`EXE_SLT_OP,`EXE_SLTU_OP:begin
				arithmeticres <= reg1_lt_reg2;//Comparison operation
			end
			`EXE_ADD_OP,`EXE_ADDU_OP,`EXE_ADDI_OP,`EXE_ADDIU_OP:begin
				arithmeticres <= result_sum;//Addition operation
			end
			`EXE_SUB_OP,`EXE_SUBU_OP:begin
				arithmeticres <= result_sum;//Subtraction operation
			end
			`EXE_CLZ_OP:begin //Count operation clz 
				arithmeticres <= reg1_i[31]?0:reg1_i[30]?1:
												 reg1_i[29]?2:reg1_i[28]?3:
												 reg1_i[27]?4:reg1_i[26]?5:
												 reg1_i[25]?6:reg1_i[24]?7:
												 reg1_i[23]?8:reg1_i[22]?9:
												 reg1_i[21]?10:reg1_i[20]?11:
												 reg1_i[19]?12:reg1_i[18]?13:
												 reg1_i[17]?14:reg1_i[16]?15:
												 reg1_i[15]?16:reg1_i[14]?17:
												 reg1_i[13]?18:reg1_i[12]?19:
												 reg1_i[11]?20:reg1_i[10]?21:
												 reg1_i[9]?22:reg1_i[8]?23:
												 reg1_i[7]?24:reg1_i[6]?25:
												 reg1_i[5]?26:reg1_i[4]?27:
												 reg1_i[3]?28:reg1_i[2]?29:
												 reg1_i[1]?20:reg1_i[0]?31:32;
												end
			`EXE_CLO_OP:begin //Counting operation clo
				arithmeticres <= (reg1_i_not[31]?0:
													reg1_i_not[30]?1:
													reg1_i_not[29]?2:
													reg1_i_not[28]?3:
													reg1_i_not[27]?4:
													reg1_i_not[26]?5:
													reg1_i_not[25]?6:
													reg1_i_not[24]?7:
													reg1_i_not[23]?8:
													reg1_i_not[22]?9:
													reg1_i_not[21]?10:
													reg1_i_not[20]?11:
													reg1_i_not[19]?12:
													reg1_i_not[18]?13:
													reg1_i_not[17]?14:
													reg1_i_not[16]?15:
													reg1_i_not[15]?16:
													reg1_i_not[14]?17:
													reg1_i_not[13]?18:
													reg1_i_not[12]?19:
													reg1_i_not[11]?20:
													reg1_i_not[10]?21:
													reg1_i_not[9]?22:
													reg1_i_not[8]?23:
													reg1_i_not[7]?24:
													reg1_i_not[6]?25:
													reg1_i_not[5]?26:
													reg1_i_not[4]?27:
													reg1_i_not[3]?28:
													reg1_i_not[2]?29:
													reg1_i_not[1]?30:
													reg1_i_not[0]?31:32);
												end
												default:begin
													arithmeticres <= `ZeroWord;
												end
											endcase
										end
									end 
/*****************************************************************
************************Paragraph 7: multiplication***********************
*****************************************************************/
/*(1)The multiplicand instructions MADD and MSUB that obtain the multiplication operation are signed multiplication if the first operand reg1_i is a negative number
 Then take reg1_ The complement of I is the multiplicand, on the contrary, reg1 is used directly_ I is the multiplicand. If it is a signed multiplication and the multiplicand is negative, the complement is taken*/
assign opdata1_mult = (((aluop_i == `EXE_MUL_OP)||(aluop_i == `EXE_MULT_OP)||(aluop_i == `EXE_MADD_OP)||(aluop_i == `EXE_MSUB_OP))&&(reg1_i[31] == 1'b1)) ? (~reg1_i+1):reg1_i;
//(2) Obtain the multiplier of the multiplication operation. If it is a signed multiplication and the multiplier is negative, take the complement
assign opdata2_mult = (((aluop_i == `EXE_MUL_OP)||(aluop_i == `EXE_MULT_OP)||(aluop_i == `EXE_MADD_OP)||(aluop_i == `EXE_MSUB_OP))&&(reg2_i[31] == 1'b1)) ? (~reg2_i+1):reg2_i;
//(3) Get the temporary multiplication result and save it in the variable Hilo_ In temp
assign hilo_temp = opdata1_mult * opdata2_mult;
/*(4)The temporary multiplication result is corrected, and the final multiplication result is saved in the variable mulres. There are mainly the following two points
A:If it is signed multiplication instruction mult and mul, the temporary multiplication result needs to be corrected as follows:
A1:If both the multiplicand and the multiplier are positive and negative, Hilo is required for the temporary multiplication result_ Temp finds the complement and assigns it to mulres as the final multiplication result
A2:If the multiplicand has the same sign as the multiplier, then Hilo_ The value of temp is assigned to the variable mulres as the final multiplication result
B:If it is an unsigned multiplication instruction multu, then Hilo_ The value of temp is assigned to the variable mulres as the final multiplication result
*/
always @ (*) begin//1
	if(rst == `RstEnable) begin//2
		mulres <= {`ZeroWord,`ZeroWord};
	end/*2*/ else if((aluop_i == `EXE_MULT_OP)||(aluop_i == `EXE_MUL_OP)||(aluop_i == `EXE_MADD_OP)||(aluop_i == `EXE_MSUB_OP))begin//3
		if(reg1_i[31]^reg2_i[31] == 1'b1)begin//4 the multiplicand and multiplier are positive and negative
			mulres <= ~hilo_temp+1;
		end/*4*/ else begin//5 the multiplicand and multiplier have the same sign
			mulres <= hilo_temp;
		end//5
		end/*3*/ else begin//6 unsigned multiplication
			mulres <= hilo_temp;
		end//6
	end//1
/*****************************************************************
****************Paragraph 8: determine the data to be written to the destination register*****************
*****************************************************************/
always @ (*)begin
	wd_o <= wd_i;
	//If it is an add,addi,sub,subi instruction and overflow occurs, set wreg_o is WriteEnable, indicating that the destination register is not written
	if(((aluop_i == `EXE_ADD_OP)||(aluop_i == `EXE_ADDI_OP)||(aluop_i == `EXE_SUB_OP))&&(ov_sum == 1'b1))begin
		wreg_o <= `WriteDisable;
	end else begin
		wreg_o <= wreg_i;
	end
	case(alusel_i)
		`EXE_RES_LOGIC:begin
			wdata_o <= logicout;
		end
		`EXE_RES_SHIFT:begin
			wdata_o <= shiftres;
		end
		`EXE_RES_MOVE:begin
			wdata_o <= moveres;
		end
		`EXE_RES_ARITHMETIC:begin//Simple arithmetic operation instructions other than multiplication
			wdata_o <= arithmeticres;
		end
		`EXE_RES_MUL:begin//Multiplication instruction mul
			wdata_o <= mulres[31:0];
		end
		`EXE_RES_JUMP_BRANCH:begin
			wdata_o <= link_address_i;
		end
		default:begin
			wdata_o <= `ZeroWord;
		end
	endcase
end//always

/****************************************************************
********************Paragraph 10: multiplication and accumulation, multiplication and subtraction************************
****************************************************************/
//MADD MADDU MSUB MSUBU instruction
always @ (*) begin
	if(rst == `RstEnable) begin
		hilo_temp_o <= {`ZeroWord,`ZeroWord};
		cnt_o <= 2'b00;
		stallreq_for_madd_msub <= `NoStop;
	end else begin
		case(aluop_i)
			`EXE_MADD_OP,`EXE_MADDU_OP:begin
				if(cnt_i == 2'b00) begin //Execute the first clock cycle
					hilo_temp_o <= mulres;//At this time, the multiplication result mulres is passed through the interface hilo_temp_o output to EX/MEM module for use in the next clock cycle
					cnt_o <= 2'b01;
					hilo_temp1 <= {`ZeroWord,`ZeroWord};
					stallreq_for_madd_msub <= `Stop;//Multiply accumulate instruction requests pipeline pause
					
				end else if(cnt_i == 2'b01) begin//Execute the second clock cycle
					hilo_temp_o <= {`ZeroWord,`ZeroWord};
					cnt_o <= 2'b10;
					hilo_temp1 <= hilo_temp_i+{HI,LO}; //hilo_temp_i is the multiplication result of the last clock cycle
					stallreq_for_madd_msub <= `NoStop;//When the execution of multiply accumulate instruction ends, the pipeline pause is no longer requested
				end
			end
			`EXE_MSUB_OP,`EXE_MSUBU_OP:begin
				if(cnt_i == 2'b00) begin
					hilo_temp_o <= ~mulres+1;
					cnt_o <= 2'b01;
					stallreq_for_madd_msub <= `Stop;
				end else if(cnt_i == 2'b01) begin
					hilo_temp_o <= {`ZeroWord,`ZeroWord};
					cnt_o <= 2'b10;
					hilo_temp1 <= hilo_temp_i +{HI,LO};
					stallreq_for_madd_msub <= `NoStop;
				end
			end
			default:begin
				hilo_temp_o <= {`ZeroWord,`ZeroWord};
				cnt_o <= 2'b00;
				stallreq_for_madd_msub <= `NoStop;
			end
		endcase
	end
end
/****************************************************************
******Paragraph 12: output DIV module control information and obtain the results given by DIV module*********
****************************************************************/
always @ (*) begin
	if(rst == `RstEnable)begin
		stallreq_for_div <= `NoStop;
		div_opdata1_o <= `ZeroWord;
		div_opdata2_o <= `ZeroWord;
		div_start_o <= `DivStop;
		signed_div_o <= 1'b0;
	end else begin
		stallreq_for_div <= `NoStop;
		div_opdata1_o <= `ZeroWord;
		div_opdata2_o <= `ZeroWord;
		div_start_o <= `DivStop;
		signed_div_o <= 1'b0;
		case(aluop_i)
			`EXE_DIV_OP:begin
				if(div_ready_i == `DivResultNotReady) begin
					div_opdata1_o <= reg1_i;//Divisor
					div_opdata2_o <= reg2_i;//Divisor
					div_start_o <= `DivStart;//Start division
					signed_div_o <= 1'b1;//Signed Division
					stallreq_for_div <= `Stop;//Request pipeline pause
				end else if(div_ready_i == `DivResultReady) begin
					div_opdata1_o <= reg1_i;
					div_opdata2_o <= reg2_i;
					div_start_o <= `DivStop;//End Division
					signed_div_o <= 1'b1;
					stallreq_for_div <= `NoStop;//Pipeline pause is no longer requested
				end else begin
					div_opdata1_o <= `ZeroWord;
					div_opdata2_o <= `ZeroWord;
					div_start_o <= `DivStop;
					signed_div_o <= 1'b0;
					stallreq_for_div <= `NoStop;
				end
			end
			`EXE_DIVU_OP:begin
				if(div_ready_i == `DivResultNotReady) begin
					div_opdata1_o <= reg1_i;
					div_opdata2_o <= reg2_i;
					div_start_o <= `DivStart;
					signed_div_o <= 1'b0;//Unsigned Division
					stallreq_for_div <= `Stop;
				end else if(div_ready_i == `DivResultReady) begin
					div_opdata1_o <= reg1_i;
					div_opdata2_o <= reg2_i;
					div_start_o <= `DivStop;
					signed_div_o <= 1'b0;
					stallreq_for_div <= `NoStop;
				end else begin
					div_opdata1_o <= `ZeroWord;
					div_opdata2_o <= `ZeroWord;
					div_start_o <= `DivStop;
					signed_div_o <= 1'b0;
					stallreq_for_div <= `NoStop;
				end
			end
			default:begin
			end
		endcase
	end
end
			
/****************************************************************
*********************Paragraph 11: suspension of assembly lines*************************
****************************************************************/
//At present, only multiply accumulate and multiply subtract instructions will cause pipeline pause, so stallreq=stallreq_for_madd_msub
always @ (*) begin
	stallreq = stallreq_for_madd_msub || stallreq_for_div;
end
/****************************************************************
****************Paragraph 9: determine (modify) the operation information of hi and lo registers*********
****************************************************************/
always @ (*)begin
	if(rst == `RstEnable) begin
		whilo_o <= `WriteDisable;
		hi_o <= `ZeroWord;
		lo_o <= `ZeroWord;
	end else if((aluop_i == `EXE_MULT_OP)||(aluop_i == `EXE_MULTU_OP))begin //mult,multu instruction
		whilo_o <= `WriteEnable;
		hi_o <= mulres[63:32];
		lo_o <= mulres[31:0];
	end else if(aluop_i == `EXE_MTHI_OP)begin
		whilo_o <= `WriteEnable;
		hi_o <= reg1_i;
		lo_o <= LO;//Write HI register, so LO remains unchanged
	end else if(aluop_i == `EXE_MTLO_OP)begin
		whilo_o <= `WriteEnable;
		hi_o <= HI;
		lo_o <= reg1_i;
	end else if((aluop_i == `EXE_MSUB_OP)||(aluop_i == `EXE_MSUBU_OP))begin
		whilo_o <= `WriteEnable;
		hi_o <= hilo_temp1[63:32];
		lo_o <= hilo_temp1[31:0];
	end else if((aluop_i == `EXE_MADD_OP)||(aluop_i == `EXE_MADDU_OP))begin
		whilo_o <= `WriteEnable;
		hi_o <= hilo_temp1[63:32];
		lo_o <= hilo_temp1[31:0];
	end else if((aluop_i == `EXE_DIV_OP)||(aluop_i == `EXE_DIVU_OP))begin
		whilo_o <= `WriteEnable;
		hi_o <= div_result_i[63:32];
		lo_o <= div_result_i[31:0];
	end else begin
		whilo_o <= `WriteDisable;
		hi_o <= `ZeroWord;
		lo_o <= `ZeroWord;
	end 
		
end

endmodule

ex_mem.v

`include "define.v"
module ex_mem(

	input	wire										clk,
	input wire										rst,
	
	//Information from control module
	input wire[5:0] stall,
	
	
	//Information from execution phase	
	input wire[`RegAddrBus]       ex_wd,
	input wire                    ex_wreg,
	input wire[`RegBus]					 ex_wdata, 	
	input wire[`RegBus]           ex_hi,
	input wire[`RegBus]           ex_lo,
	input wire                    ex_whilo, 
	//Input interface added for loading and storing instructions
	input wire[`AluOpBus] ex_aluop, //Subtype to be operated on during execution
	input wire[`RegBus] ex_mem_addr,//The memory address corresponding to the loading and storage instructions in the execution stage
	input wire[`RegBus] ex_reg2,//The execution stage stores the data to be stored by the instruction, or the original value of the destination register to be written by the LWL and LWR instructions

	
	//Added input interface
	input wire[`DoubleRegBus] hilo_i,
	input wire[1:0] cnt_i,
	//input wire[5:0] stall,
	//Information sent to the storage access stage
	output reg[`RegAddrBus]      mem_wd,
	output reg                   mem_wreg,
	output reg[`RegBus]					 mem_wdata,
	output reg[`RegBus]          mem_hi,
	output reg[`RegBus]          mem_lo,
	output reg                   mem_whilo	,
	
	//Added output port
	output reg[`DoubleRegBus] hilo_o,
	output reg[1:0] cnt_o,
	
	//Output interface added for loading and storing instructions
	output reg[`AluOpBus] mem_aluop,//The subtype of the instruction to be operated in the memory access stage
	output reg[`RegBus] mem_mem_addr,//The memory address corresponding to the loading and storage instructions in the memory access stage
	output reg[`RegBus] mem_reg2//The memory access stage stores the data to be stored by the instruction, or the original value of the destination register to be written by LWL and LWR
	
);

/*When the pipeline execution phase is suspended, the signal Hilo is input_ I through output interface hilo_o send out,
Input signal cnt_i via output interface cnt_o send out. The rest of the time, hilo_o = 0,cnt_o is also 0.*/
	always @ (posedge clk) begin
		if(rst == `RstEnable) begin
			mem_wd <= `NOPRegAddr;
			mem_wreg <= `WriteDisable;
		  mem_wdata <= `ZeroWord;	
		  mem_hi <= `ZeroWord;
		  mem_lo <= `ZeroWord;
		  mem_whilo <= `WriteDisable;	
		  hilo_o <= {`ZeroWord,`ZeroWord};
		  cnt_o <= 2'b00;	  
		  mem_aluop <= `EXE_NOP_OP;
		  mem_mem_addr <= `ZeroWord;
		  mem_reg2 <= `ZeroWord;
		end else if(stall[3] == `Stop && stall[4] == `NoStop)begin
			mem_wd <= `NOPRegAddr;
			mem_wreg <= `WriteDisable;
			mem_wdata <= `ZeroWord;
			mem_hi <= `ZeroWord;
			mem_lo <= `ZeroWord;
			mem_whilo <= `WriteDisable;
			hilo_o <= hilo_i;
			cnt_o <= cnt_i;
			mem_aluop <= `EXE_NOP_OP;
			mem_mem_addr <= `ZeroWord;
			mem_reg2 <= `ZeroWord;
		end else if(stall[3] == `NoStop)begin
			mem_wd <= ex_wd;
			mem_wreg <= ex_wreg;
			mem_wdata <= ex_wdata;	
			mem_hi <= ex_hi;
			mem_lo <= ex_lo;
			mem_whilo <= ex_whilo;	
			hilo_o <= {`ZeroWord,`ZeroWord};
			cnt_o <= 2'b00;
			mem_aluop <= ex_aluop;
			mem_mem_addr <= ex_mem_addr;
			mem_reg2 <= ex_reg2;
		end else begin
			hilo_o <= hilo_i;
			cnt_o <= cnt_i;				
		end    //if
	end      //always
			

endmodule

Memory access module

mem.v

`include "define.v"
//mem.v storage access
//The results of the input execution phase are directly used as the output
module mem(
input wire rst,
input wire clk,
//Information from execution phase
input wire[`RegAddrBus] wd_i,
input wire wreg_i,
input wire[`RegBus] wdata_i,
input wire[`RegBus] hi_i,
input wire[`RegBus] lo_i,
input wire whilo_i,

//Add an interface, information from the memory access stage, and add an access interface to the data memory RAM
input wire [`AluOpBus]aluop_i, //The subtype of the operation to be performed by the instruction in the memory access stage
input wire [`RegBus] mem_addr_i,//The memory address corresponding to the loading and storage instruction in the memory access stage
input wire [`RegBus] reg2_i,

//New interface information from external data memory RAM
input wire[`RegBus] mem_data_i,//Data read from ram
//Results of the deposit access phase
output reg[`RegAddrBus] wd_o,
output reg wreg_o,
output reg[`RegBus] wdata_o,
output reg[`RegBus] hi_o,
output reg[`RegBus] lo_o,
output reg whilo_o,

//Add an interface to send the information to the external data memory RAM
output reg[`RegBus] mem_addr_o,//ram address to access
output wire mem_we_o,//Is it a write operation? Is it a write operation
output reg[3:0] mem_sel_o,//Byte select signal
output reg[`RegBus] mem_data_o,//Address to write to data store
output reg mem_ce_o//Data memory enable signal
);
wire[`RegBus] zero32;
reg mem_we;
assign mem_we_o = mem_we;//Read and write signals of external data memory ram
assign zero32 = `ZeroWord;
always @ (*)
begin
	if(rst == `RstEnable)
	begin
	wd_o <= `NOPRegAddr;
	wreg_o <= `WriteDisable;
	wdata_o <= `ZeroWord;
	hi_o <= `ZeroWord;
	lo_o <= `ZeroWord;
	whilo_o <= `WriteDisable;
	mem_addr_o <= `ZeroWord;
	mem_we <= `WriteDisable;
	mem_sel_o <= 4'b0000;
	mem_data_o <= `ZeroWord;
	mem_ce_o <= `ChipDisable;
end
else 
begin
	wd_o <= wd_i;
	wreg_o <= wreg_i;
	wdata_o <= wdata_i;
	hi_o <= hi_i;
	lo_o <= lo_i;
	whilo_o <= whilo_i;
	mem_we <= `WriteDisable;
	mem_addr_o <= `ZeroWord;
	mem_sel_o <= 4'b1111;
	mem_ce_o <= `ChipDisable;
	case(aluop_i)//Subtype of operation to be performed in memory access stage
		`EXE_LB_OP:begin //Read a byte, expand unsigned to 32 bits, and save it in the register with address rt
			mem_addr_o <= mem_addr_i;
			mem_we <= `WriteDisable;
			mem_ce_o <= `ChipEnable;
			case(mem_addr_i[1:0])//The last two digits of the ram address to be accessed
				2'b00:begin //Read data memory ram at 0x mem_ addr_ Bytes at I [1:0]
					wdata_o <={{24{mem_data_i[31]}},mem_data_i[31:24]}; //Highest position
					mem_sel_o <= 4'b1000;//0x0
				end
				2'b01:begin
					wdata_o <= {{24{mem_data_i[23]}},mem_data_i[23:16]};//Secondary high
					mem_sel_o <= 4'b0100;//0x1
				end
				2'b10:begin
					wdata_o <= {{24{mem_data_i[15]}},mem_data_i[15:8]};
					mem_sel_o <= 4'b0010;//0x2
				end
				2'b11:begin
					wdata_o <= {{24{mem_data_i[7]}},mem_data_i[7:0]};
					mem_sel_o <= 4'b0001; //0x3
				end
				default:begin
					wdata_o <= `ZeroWord;
				end
			endcase
		end
		`EXE_LBU_OP:begin
			mem_addr_o <= mem_addr_i;
			mem_we <= `WriteDisable;
			mem_ce_o <= `ChipEnable;
			case(mem_addr_i[1:0])
				2'b00:begin
					wdata_o <= {{24{1'b0}},mem_data_i[31:24]};
					mem_sel_o <= 4'b1000;
				end
				2'b01:begin
					wdata_o <= {{24{1'b0}},mem_data_i[23:16]};
					mem_sel_o <= 4'b0100;
				end
				2'b10:begin
					wdata_o <= {{24{1'b0}},mem_data_i[15:8]};
					mem_sel_o <= 4'b0010;
				end
				2'b11:begin
					wdata_o <= {{24{1'b0}},mem_data_i[7:0]};
					mem_sel_o <= 4'b0001;
				end
				default:begin
					wdata_o <= `ZeroWord;
				end
			endcase
		end
		`EXE_LH_OP:begin //Read half word 2 bytes
			mem_addr_o <= mem_addr_i;
			mem_we <= `WriteDisable;
			mem_ce_o <= `ChipEnable;
			case(mem_addr_i[1:0])
				2'b00:begin
					wdata_o <= {{16{mem_data_i[31]}},mem_data_i[31:16]};//Read the lowest 8 bits
					mem_sel_o <= 4'b1100;//Read 2 bytes from 0x0
				end
				2'b10:begin
					wdata_o <= {{16{mem_data_i[15]}},mem_data_i[15:0]};
					mem_sel_o <= 0011;
				end
				default:begin
					wdata_o <= `ZeroWord;
				end
			endcase
		end
		`EXE_LHU_OP:begin
			mem_addr_o <= mem_addr_i;
			mem_we <= `WriteDisable;
			mem_ce_o <= `ChipEnable;
			case(mem_addr_i[1:0])
				2'b00:begin
					wdata_o <= {{16{1'b0}},mem_data_i[31:16]};
					mem_sel_o <= 4'b1100;
				end
				2'b10:begin
					wdata_o <= {{16{1'b0}},mem_data_i[15:0]};
					mem_sel_o <= 4'b0011;
				end
				default:begin
				wdata_o <= `ZeroWord;
			end
		endcase
	end
	`EXE_LW_OP:begin //Load a word
		mem_addr_o <= {mem_addr_i[31:2],2'b00};
		mem_we <= `WriteDisable;
		mem_sel_o <= 4'b1111;
		mem_ce_o <= `ChipEnable;
		wdata_o <= mem_data_i;
	end
	`EXE_LWL_OP:begin //Loading the most significant part of a word from the specified address in memory allows non aligned loading
		mem_addr_o <= {mem_addr_i[31:2],2'b00};
		mem_we <= `WriteDisable;
		mem_sel_o <= 4'b1111;
		mem_ce_o <= `ChipEnable;
		case(mem_addr_i[1:0])//The slave address is mem_ addr_ Load a word at O and save the lowest 4-n bytes of the word to the high and low bits of the rt register
			2'b00:begin
				wdata_o <= mem_data_i[31:0];//32-bit (4-0) * 8
			end
			2'b01:begin
				wdata_o <= {mem_data_i[23:0],reg2_i[7:0]};//24 bits (4-1) * 8
			end
			2'b10:begin
				wdata_o <= {mem_data_i[15:0],reg2_i[15:0]};//16 bits (4-2) * 8
			end
			2'b11:begin
				wdata_o <= {mem_data_i[7:0],reg2_i[23:0]};//8 bits (4-3) * 8
			end
			default:begin
				wdata_o <= `ZeroWord;
			end
		endcase
	end
	`EXE_LWR_OP:begin
		mem_addr_o <= {mem_addr_i[31:2],2'b00};
		mem_we <= `WriteDisable;
		mem_sel_o <= 4'b1111;
		mem_ce_o <= `ChipEnable;
		case(mem_addr_i[1:0])
			2'b00:begin
				wdata_o <= {reg2_i[31:8],mem_data_i[31:24]};//Save 8 bits in low order
			end
			2'b01:begin
				wdata_o <= {reg2_i[31:16],mem_data_i[31:16]};//Save 16 bits in low order
			end
			2'b10:begin
				wdata_o <= {reg2_i[31:24],mem_data_i[31:8]};//Save the upper 24 bits in the lower order
			end
			2'b11:begin
				wdata_o <= mem_data_i;
			end
			default:begin
				wdata_o <= `ZeroWord;
			end
		endcase
	end
	`EXE_SB_OP:begin//Stores the lowest byte of the general-purpose register with address rt to the specified address in memory
		mem_addr_o <= mem_addr_i;
		mem_we <= `WriteEnable;
		mem_data_o <= {reg2_i[7:0],reg2_i[7:0],reg2_i[7:0],reg2_i[7:0]};
		mem_ce_o <= `ChipEnable;
		case(mem_addr_i[1:0])//The high bit of data is stored in the low address of memory
			2'b00:begin
				mem_sel_o <= 4'b1000;
			end
			2'b01:begin
				mem_sel_o <= 4'b0100;
			end
			2'b10:begin
				mem_sel_o <= 4'b0010;
			end
			2'b11:begin
				mem_sel_o <= 4'b0001;
			end
			default:begin
				mem_sel_o <= 4'b0000;
			end
		endcase
	end
	`EXE_SH_OP:begin//Store the lowest two bytes of the general-purpose register with address rt, and save the low order 2 to the high address
		mem_addr_o <= mem_addr_i;
		mem_we <= `WriteEnable;
		mem_data_o <= {reg2_i[15:0],reg2_i[15:0]};
		mem_ce_o <= `ChipEnable;
		case(mem_addr_i[1:0])
			2'b00:begin
				mem_sel_o <= 4'b1100;
			end
			2'b10:begin
				mem_sel_o <= 4'b0011;
			end
			default:begin
				mem_sel_o <= `ZeroWord;
			end
		endcase
	end
	`EXE_SW_OP:begin
		mem_addr_o <= mem_addr_i;
		mem_we <= `WriteEnable;
		mem_ce_o <= `ChipEnable;
		mem_sel_o <= 4'b1111;
	end
	/*Store the high-order part of the general-purpose register with address rt to the address specified in memory,
	The last two bits of the storage address determine which bytes of the rt general register to store,
	swl Instruction has no alignment requirements for stored instructions
	Store the maximum 4-n bytes of the general-purpose register with address rt in storeaddr*/
	`EXE_SWL_OP:begin//The non aligned storage instruction stores the high-order part of the general-purpose register with address rt to the left at the specified address in memory
		//The last two bits of the storage address determine which bytes of the rt general-purpose register to store
		mem_addr_o <= {mem_addr_i[31:2],2'b00};
		mem_we <= `WriteEnable;
		mem_ce_o <= `ChipEnable;
		case(mem_addr_i[1:0])//Determines which bytes of the rt general register are stored
			2'b00:begin
				mem_sel_o <= 4'b1111;
				mem_data_o <= reg2_i;
			end
			2'b01:begin
				mem_sel_o <= 4'b0111;
				mem_data_o <= {zero32[7:0],reg2_i[31:8]};//Store up to 4-1 bytes (24 bits) in storeaddr
			end
			2'b10:begin
				mem_sel_o <= 4'b0011;//16bits 
				mem_data_o <= {zero32[15:0],reg2_i[31:16]};
			end
			2'b11:begin
				mem_sel_o <= 4'b0001;
				mem_data_o <= {zero32[23:0],reg2_i[31:24]};
			end
			default:begin
				mem_sel_o <= 4'b000;
			end
		endcase
	end
	`EXE_SWR_OP:begin
		mem_addr_o <= {mem_addr_i[31:2],2'b00};
		mem_we <= `WriteEnable;
		mem_ce_o <= `ChipEnable;
		case(mem_addr_i[1:0])
			2'b00:begin
				mem_sel_o <= 4'b1000;
				mem_data_o <= {reg2_i[7:0],zero32[23:0]};
			end
			2'b01:begin
				mem_sel_o <= 4'b1100;
				mem_data_o <= {reg2_i[15:0],zero32[15:0]};
			end
			2'b10:begin
				mem_sel_o <= 4'b1110;
				mem_data_o <= {reg2_i[23:0],zero32[7:0]};
			end
			2'b11:begin
				mem_sel_o <= 4'b1111;
				mem_data_o <= reg2_i[31:0];
			end
			default:begin
				mem_sel_o <= `ZeroWord;
			end
		endcase
	end
	default:begin
	end
endcase

end
end
endmodule

Instantiation (must be wrong every time!!!)

openmips.v

`include "define.v"

module openmips(

	input	wire										clk,
	input wire										rst,
	
 
	input wire[`RegBus]           rom_data_i,
	output wire[`RegBus]           rom_addr_o,
	output wire                    rom_ce_o,
	
  //Connect data memory data_ram
	input wire[`RegBus]           ram_data_i,
	output wire[`RegBus]           ram_addr_o,
	output wire[`RegBus]           ram_data_o,
	output wire                    ram_we_o,
	output wire[3:0]               ram_sel_o,
	output wire[3:0]               ram_ce_o
	
);

	wire[`InstAddrBus] pc;
	wire[`InstAddrBus] id_pc_i;
	wire[`InstBus] id_inst_i;
	
	//Connect the output of ID module in decoding stage with the input of ID/EX module
	wire[`AluOpBus] id_aluop_o;
	wire[`AluSelBus] id_alusel_o;
	wire[`RegBus] id_reg1_o;
	wire[`RegBus] id_reg2_o;
	wire id_wreg_o;
	wire[`RegAddrBus] id_wd_o;
	wire id_is_in_delayslot_o;
  wire[`RegBus] id_link_address_o;	
  wire[`RegBus] id_inst_o;
	
	//Connect the output of ID/EX module with the input of EX module in execution stage
	wire[`AluOpBus] ex_aluop_i;
	wire[`AluSelBus] ex_alusel_i;
	wire[`RegBus] ex_reg1_i;
	wire[`RegBus] ex_reg2_i;
	wire ex_wreg_i;
	wire[`RegAddrBus] ex_wd_i;
	wire ex_is_in_delayslot_i;	
  wire[`RegBus] ex_link_address_i;	
  wire[`RegBus] ex_inst_i;
	
	//Connect the output of the execution stage EX module with the input of the EX/MEM module
	wire ex_wreg_o;
	wire[`RegAddrBus] ex_wd_o;
	wire[`RegBus] ex_wdata_o;
	wire[`RegBus] ex_hi_o;
	wire[`RegBus] ex_lo_o;
	wire ex_whilo_o;
	wire[`AluOpBus] ex_aluop_o;
	wire[`RegBus] ex_mem_addr_o;
	wire[`RegBus] ex_reg1_o;
	wire[`RegBus] ex_reg2_o;	

	//Connect the output of EX/MEM module with the input of MEM module in memory access stage
	wire mem_wreg_i;
	wire[`RegAddrBus] mem_wd_i;
	wire[`RegBus] mem_wdata_i;
	wire[`RegBus] mem_hi_i;
	wire[`RegBus] mem_lo_i;
	wire mem_whilo_i;		
	wire[`AluOpBus] mem_aluop_i;
	wire[`RegBus] mem_mem_addr_i;
	wire[`RegBus] mem_reg1_i;
	wire[`RegBus] mem_reg2_i;		

	//Connect the output of MEM module and the input of MEM/WB module in memory access stage
	wire mem_wreg_o;
	wire[`RegAddrBus] mem_wd_o;
	wire[`RegBus] mem_wdata_o;
	wire[`RegBus] mem_hi_o;
	wire[`RegBus] mem_lo_o;
	wire mem_whilo_o;		
	
	//Connect the output of the MEM/WB module with the input of the write back phase	
	wire wb_wreg_i;
	wire[`RegAddrBus] wb_wd_i;
	wire[`RegBus] wb_wdata_i;
	wire[`RegBus] wb_hi_i;
	wire[`RegBus] wb_lo_i;
	wire wb_whilo_i;	
	
	//Connection between Regfile and general register decoding module
  wire reg1_read;
  wire reg2_read;
  wire[`RegBus] reg1_data;
  wire[`RegBus] reg2_data;
  wire[`RegAddrBus] reg1_addr;
  wire[`RegAddrBus] reg2_addr;

	//Connect the output of the execution stage and hilo module and read the HI and LO registers
	wire[`RegBus] 	hi;
	wire[`RegBus]   lo;

  //Connect execution phase and ex_reg module for multi cycle MADD, MADDU, MSUB, MSUBU instructions
	wire[`DoubleRegBus] hilo_temp_o;
	wire[1:0] cnt_o;
	
	wire[`DoubleRegBus] hilo_temp_i;
	wire[1:0] cnt_i;

	wire[`DoubleRegBus] div_result;
	wire div_ready;
	wire[`RegBus] div_opdata1;
	wire[`RegBus] div_opdata2;
	wire div_start;
	wire div_annul;
	wire signed_div;

	wire is_in_delayslot_i;
	wire is_in_delayslot_o;
	wire next_inst_in_delayslot_o;
	wire id_branch_flag_o;
	wire[`RegBus] branch_target_address;

	wire[5:0] stall;
	wire stallreq_from_id;	
	wire stallreq_from_ex;
  
  //pc_reg instantiation
	pc_reg pc_reg0(
		.clk(clk),
		.rst(rst),
		.stall(stall),
		.branch_flag_i(id_branch_flag_o),
		.branch_target_address_i(branch_target_address),		
		.pc(pc),
		.ce(rom_ce_o)		
			
	);
	
  assign rom_addr_o = pc;

  //IF/ID modularization
	if_id if_id0(
		.clk(clk),
		.rst(rst),
		.stall(stall),
		.if_pc(pc),
		.if_inst(rom_data_i),
		.id_pc(id_pc_i),
		.id_inst(id_inst_i)      	
	);
	
	//Decoding phase ID module
	id id0(
		.rst(rst),
		.pc_i(id_pc_i),
		.inst_i(id_inst_i),

  	.ex_aluop_i(ex_aluop_o),

		.reg1_data_i(reg1_data),
		.reg2_data_i(reg2_data),

	  //The destination register information to be written by the instruction in the execution phase
		.ex_wreg_i(ex_wreg_o),
		.ex_wdata_i(ex_wdata_o),
		.ex_wd_i(ex_wd_o),

	  //The destination register information to be written by the instruction in the memory access stage
		.mem_wreg_i(mem_wreg_o),
		.mem_wdata_i(mem_wdata_o),
		.mem_wd_i(mem_wd_o),

	  .is_in_delayslot_i(is_in_delayslot_i),

		//Information sent to regfile
		.reg1_read_o(reg1_read),
		.reg2_read_o(reg2_read), 	  

		.reg1_addr_o(reg1_addr),
		.reg2_addr_o(reg2_addr), 
	  
		//Information sent to ID/EX module
		.aluop_o(id_aluop_o),
		.alusel_o(id_alusel_o),
		.reg1_o(id_reg1_o),
		.reg2_o(id_reg2_o),
		.wd_o(id_wd_o),
		.wreg_o(id_wreg_o),
		.inst_o(id_inst_o),

	 	.next_inst_in_delayslot_o(next_inst_in_delayslot_o),	
		.branch_flag_o(id_branch_flag_o),
		.branch_target_address_o(branch_target_address),       
		.link_addr_o(id_link_address_o),
		
		.is_in_delayslot_o(id_is_in_delayslot_o),
		
		.stallreq(stallreq_from_id)		
	);

  //Regfile instantiation of general register
	regfile regfile1(
		.clk (clk),
		.rst (rst),
		.we	(wb_wreg_i),
		.waddr (wb_wd_i),
		.wdata (wb_wdata_i),
		.re1 (reg1_read),
		.raddr1 (reg1_addr),
		.rdata1 (reg1_data),
		.re2 (reg2_read),
		.raddr2 (reg2_addr),
		.rdata2 (reg2_data)
	);

	//ID/EX module
	id_ex id_ex0(
		.clk(clk),
		.rst(rst),
		
		.stall(stall),
		
		//Information transmitted from ID module of decoding stage
		.id_aluop(id_aluop_o),
		.id_alusel(id_alusel_o),
		.id_reg1(id_reg1_o),
		.id_reg2(id_reg2_o),
		.id_wd(id_wd_o),
		.id_wreg(id_wreg_o),
		.id_link_address(id_link_address_o),
		.id_is_in_delayslot(id_is_in_delayslot_o),
		.next_inst_in_delayslot_i(next_inst_in_delayslot_o),		
		.id_inst(id_inst_o),		
	
		//Information passed to the execution stage EX module
		.ex_aluop(ex_aluop_i),
		.ex_alusel(ex_alusel_i),
		.ex_reg1(ex_reg1_i),
		.ex_reg2(ex_reg2_i),
		.ex_wd(ex_wd_i),
		.ex_wreg(ex_wreg_i),
		.ex_link_address(ex_link_address_i),
  	.ex_is_in_delayslot(ex_is_in_delayslot_i),
		.is_in_delayslot_o(is_in_delayslot_i),
		.ex_inst(ex_inst_i)		
	);		
	
	//EX module
	ex ex0(
		.rst(rst),
	
		//Information sent to the execution stage EX module
		.aluop_i(ex_aluop_i),
		.alusel_i(ex_alusel_i),
		.reg1_i(ex_reg1_i),
		.reg2_i(ex_reg2_i),
		.wd_i(ex_wd_i),
		.wreg_i(ex_wreg_i),
		.hi_i(hi),
		.lo_i(lo),
		.inst_i(ex_inst_i),

	  .wb_hi_i(wb_hi_i),
	  .wb_lo_i(wb_lo_i),
	  .wb_whilo_i(wb_whilo_i),
	  .mem_hi_i(mem_hi_o),
	  .mem_lo_i(mem_lo_o),
	  .mem_whilo_i(mem_whilo_o),

	  .hilo_temp_i(hilo_temp_i),
	  .cnt_i(cnt_i),

		.div_result_i(div_result),
		.div_ready_i(div_ready), 

	  .link_address_i(ex_link_address_i),
		.is_in_delayslot_i(ex_is_in_delayslot_i),	  
			  
	  //EX module output to EX/MEM module information
		.wd_o(ex_wd_o),
		.wreg_o(ex_wreg_o),
		.wdata_o(ex_wdata_o),

		.hi_o(ex_hi_o),
		.lo_o(ex_lo_o),
		.whilo_o(ex_whilo_o),

		.hilo_temp_o(hilo_temp_o),
		.cnt_o(cnt_o),

		.div_opdata1_o(div_opdata1),
		.div_opdata2_o(div_opdata2),
		.div_start_o(div_start),
		.signed_div_o(signed_div),	

		.aluop_o(ex_aluop_o),
		.mem_addr_o(ex_mem_addr_o),
		.reg2_o(ex_reg2_o),
		
		.stallreq(stallreq_from_ex)     				
		
	);

  //EX/MEM module
  ex_mem ex_mem0(
		.clk(clk),
		.rst(rst),
	  
	  .stall(stall),
	  
		//Information from execution stage EX module	
		.ex_wd(ex_wd_o),
		.ex_wreg(ex_wreg_o),
		.ex_wdata(ex_wdata_o),
		.ex_hi(ex_hi_o),
		.ex_lo(ex_lo_o),
		.ex_whilo(ex_whilo_o),		

  	.ex_aluop(ex_aluop_o),
		.ex_mem_addr(ex_mem_addr_o),
		.ex_reg2(ex_reg2_o),			

		.hilo_i(hilo_temp_o),
		.cnt_i(cnt_o),	

		//Information sent to MEM module in memory access stage
		.mem_wd(mem_wd_i),
		.mem_wreg(mem_wreg_i),
		.mem_wdata(mem_wdata_i),
		.mem_hi(mem_hi_i),
		.mem_lo(mem_lo_i),
		.mem_whilo(mem_whilo_i),

  	.mem_aluop(mem_aluop_i),
		.mem_mem_addr(mem_mem_addr_i),
		.mem_reg2(mem_reg2_i),
				
		.hilo_o(hilo_temp_i),
		.cnt_o(cnt_i)
						       	
	);
	
  //MEM module instantiation
	mem mem0(
		.rst(rst),
	
		//Information from EX/MEM module	
		.wd_i(mem_wd_i),
		.wreg_i(mem_wreg_i),
		.wdata_i(mem_wdata_i),
		.hi_i(mem_hi_i),
		.lo_i(mem_lo_i),
		.whilo_i(mem_whilo_i),		

  	.aluop_i(mem_aluop_i),
		.mem_addr_i(mem_mem_addr_i),
		.reg2_i(mem_reg2_i),
	
		//Information from memory
		.mem_data_i(ram_data_i),
	  
		//Information sent to MEM/WB module
		.wd_o(mem_wd_o),
		.wreg_o(mem_wreg_o),
		.wdata_o(mem_wdata_o),
		.hi_o(mem_hi_o),
		.lo_o(mem_lo_o),
		.whilo_o(mem_whilo_o),
		
		//Information sent to memory
		.mem_addr_o(ram_addr_o),
		.mem_we_o(ram_we_o),
		.mem_sel_o(ram_sel_o),
		.mem_data_o(ram_data_o),
		.mem_ce_o(ram_ce_o)		
	);

  //MEM/WB module
	mem_wb mem_wb0(
		.clk(clk),
		.rst(rst),

    .stall(stall),

		//Information from MEM module in memory access stage	
		.mem_wd(mem_wd_o),
		.mem_wreg(mem_wreg_o),
		.mem_wdata(mem_wdata_o),
		.mem_hi(mem_hi_o),
		.mem_lo(mem_lo_o),
		.mem_whilo(mem_whilo_o),		
	
		//Information sent to write back phase
		.wb_wd(wb_wd_i),
		.wb_wreg(wb_wreg_i),
		.wb_wdata(wb_wdata_i),
		.wb_hi(wb_hi_i),
		.wb_lo(wb_lo_i),
		.wb_whilo(wb_whilo_i)		
									       	
	);

	hilo_reg hilo_reg0(
		.clk(clk),
		.rst(rst),
	
		//Write port
		.we(wb_whilo_i),
		.hi_i(wb_hi_i),
		.lo_i(wb_lo_i),
	
		//Read port 1
		.hi_o(hi),
		.lo_o(lo)	
	);
	
	ctrl ctrl0(
		.rst(rst),
	
		.stallreq_from_id(stallreq_from_id),
	
  	//Pause request from execution phase
		.stallreq_from_ex(stallreq_from_ex),

		.stall(stall)       	
	);

	div div0(
		.clk(clk),
		.rst(rst),
	
		.signed_div_i(signed_div),
		.opdata1_i(div_opdata1),
		.opdata2_i(div_opdata2),
		.start_i(div_start),
		.annul_i(1'b0),
	
		.result_o(div_result),
		.ready_o(div_ready)
	);

endmodule
                                                                                                                                                 

openmips_min_sopc.v

`include "define.v"
//openmips_min_sopc.v
module openmips_min_sopc(
input wire clk,
input wire rst
);
//Connection instruction memory
wire[`InstAddrBus] inst_addr;
wire[`InstBus] inst;
wire rom_ce;
//Connecting external data storage
wire mem_we_i;
wire [`RegBus]mem_addr_i;
wire [`RegBus]mem_data_i;
wire [`RegBus]mem_data_o;
wire[3:0] mem_sel_i;
wire mem_ce_i;
//Instantiation processor
openmips openmips0(
	.clk(clk),
		.rst(rst),
	
		.rom_addr_o(inst_addr),
		.rom_data_i(inst),
		.rom_ce_o(rom_ce),

		.ram_we_o(mem_we_i),
		.ram_addr_o(mem_addr_i),
		.ram_sel_o(mem_sel_i),
		.ram_data_o(mem_data_i),
		.ram_data_i(mem_data_o),
		.ram_ce_o(mem_ce_i)		
	
);
//Instantiated instruction memory
inst_rom inst_rom0(
	.ce(rom_ce),	
	.inst(inst), 
	.addr(inst_addr)
);
//Instantiated external data memory RAM
data_ram data_ram0(
	.clk(clk),
		.we(mem_we_i),
		.addr(mem_addr_i),
		.sel(mem_sel_i),
		.data_i(mem_data_i),
		.data_o(mem_data_o),
		.ce(mem_ce_i)
);
endmodule

test data

inst_rom.S

   .org 0x0
   .set noat
   .set noreorder
   .set nomacro
   .global _start
_start:
   ori  $3,$0,0xeeff
   sb   $3,0x3($0)       # [0x3] = 0xff
   srl  $3,$3,8
   sb   $3,0x2($0)       # [0x2] = 0xee
   ori  $3,$0,0xccdd
   sb   $3,0x1($0)       # [0x1] = 0xdd
   srl  $3,$3,8
   sb   $3,0x0($0)       # [0x0] = 0xcc
   lb   $1,0x3($0)       # $1 = 0xffffffff
   lbu  $1,0x2($0)       # $1 = 0x000000ee
   nop

   ori  $3,$0,0xaabb
   sh   $3,0x4($0)       # [0x4] = 0xaa, [0x5] = 0xbb
   lhu  $1,0x4($0)       # $1 = 0x0000aabb
   lh   $1,0x4($0)       # $1 = 0xffffaabb
 
   ori  $3,$0,0x8899
   sh   $3,0x6($0)       # [0x6] = 0x88, [0x7] = 0x99
   lh   $1,0x6($0)       # $1 = 0xffff8899
   lhu  $1,0x6($0)       # $1 = 0x00008899

   ori  $3,$0,0x4455
   sll  $3,$3,0x10
   ori  $3,$3,0x6677     
   sw   $3,0x8($0)       # [0x8] = 0x44, [0x9]= 0x55, [0xa]= 0x66, [0xb] = 0x77
   lw   $1,0x8($0)       # $1 = 0x44556677

   lwl  $1, 0x5($0)      # $1 = 0xbb889977
   lwr  $1, 0x8($0)      # $1 = 0xbb889944

   nop
   swr  $1, 0x2($0)      # [0x0] = 0x88, [0x1] = 0x99, [0x2]= 0x44, [0x3] = 0xff
   swl  $1, 0x7($0)      # [0x4] = 0xaa, [0x5] = 0xbb, [0x6] = 0x88, [0x7] = 0x44

   lw   $1, 0x0($0)      # $1 = 0x889944ff
   lw   $1, 0x4($0)      # $1 = 0xaabb8844
    
_loop:
   j _loop
   nop

inst_rom.data

3403eeff
a0030003
00031a02
a0030002
3403ccdd
a0030001
00031a02
a0030000
80010003
90010002
00000000
3403aabb
a4030004
94010004
84010004
34038899
a4030006
84010006
94010006
34034455
00031c00
34636677
ac030008
8c010008
88010005
98010008
00000000
b8010002
a8010007
8c010000
8c010004
0800001f
00000000

Results (changes in reg1 and reg3) $1 and $3




The detailed design may open another article...

Tags: Verilog FPGA

Posted by goodtimeassured on Mon, 18 Apr 2022 22:49:06 +0930