加载存储指令的实现

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
一个字节为8位,一个半字为16位,一个字为32位
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
修改ID,主要是增加译码和一个输出inst_o
lwl模块中reg2也需要读!
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

`include "defines.v"

module id_ex(

	input wire					  clk,
	input wire					  rst,

	//从译码阶段传递的信息
	input wire[`AluOpBus]       id_aluop,	//[7:0]
	input wire[`AluSelBus]      id_alusel,	//[2:0]
	input wire[`RegBus]         id_reg1,
	input wire[`RegBus]         id_reg2,
	input wire[`RegAddrBus]     id_wd,
	input wire                  id_wreg,	
	input wire[`RegBus]         id_link_address,	//处于译码阶段的转移指令要保存的返回地址
	input wire                  id_is_in_delayslot,	//当前处于译码阶段的指令是否位于延迟槽
	input wire                  next_inst_in_delayslot_i, //下一条进入译码阶段的指令是否位于延迟槽

	//当前处于译码阶段的指令
	input wire[`RegBus]         id_inst,	
	
	//来自控制模块的
	input wire[5:0]				 stall,

	//传递到执行阶段的
	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
	
);
	//打一拍传过去
	//1.当stall[2]为stop,stall[3]为nostop,表示译码阶段暂停,执行阶段继续
	//  使用空指令作为下一个周期进入执行阶段的指令
	//2.当stall[2]为nostop,译码阶段继续,译码后的指令进入执行阶段
	//3.其余情况,保持不变
	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;
			is_in_delayslot_o <= `NotInDelaySlot;
			ex_inst <= `ZeroWord;
		end 
		else if(stall[2] == `Stop && stall[3] == `NoStop) 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] == `NoStop) 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;	
			ex_link_address <= id_link_address;
			ex_is_in_delayslot <= id_is_in_delayslot;
			is_in_delayslot_o <= next_inst_in_delayslot_i;	
			ex_inst <= id_inst;
		end
	end
	
endmodule

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

`include "defines.v"

module mem(

	input wire						  rst,
	
	//来自执行阶段的信息	
	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,
	
   //
	input wire[`AluOpBus]        aluop_i,		//访存阶段的指令要进行的运算的子类型
	input wire[`RegBus]          mem_addr_i,	//访存阶段加载、存储指令对应的存储器地址
	input wire[`RegBus]          reg2_i,		//访存阶段的存储指令要存储的数据或lwl/lwr要加载到的目的段寄存器原始值

	//来自memory的信息
	input wire[`RegBus]          mem_data_i,	//从数据存储器读取的数据
	
	//送到回写阶段的信息
	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,
	
	//送到memory的信息
	output reg[`RegBus]          mem_addr_o,	//要访问的数据存储器地址
	output wire						  mem_we_o,		//是否写操作
	output reg[3:0]              mem_sel_o,	//字节选择信号
	output reg[`RegBus]          mem_data_o,	//要写入数据存储器的数据
	output reg                   mem_ce_o		//数据存储器使能信号
);

	wire[`RegBus] zero32;
	reg           mem_we;

	assign mem_we_o = mem_we ;	//外部数据存储器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)
			
				`EXE_LB_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{mem_data_i[31]}},mem_data_i[31:24]};
							mem_sel_o <= 4'b1000;
						end
						2'b01:	begin
							wdata_o <= {{24{mem_data_i[23]}},mem_data_i[23:16]};
							mem_sel_o <= 4'b0100;
						end
						2'b10:	begin
							wdata_o <= {{24{mem_data_i[15]}},mem_data_i[15:8]};
							mem_sel_o <= 4'b0010;
						end
						2'b11:	begin
							wdata_o <= {{24{mem_data_i[7]}},mem_data_i[7:0]};
							mem_sel_o <= 4'b0001;
						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
					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]};
							mem_sel_o <= 4'b1100;
						end
						2'b10:	begin
							wdata_o <= {{16{mem_data_i[15]}},mem_data_i[15:0]};
							mem_sel_o <= 4'b0011;
						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
					mem_addr_o <= mem_addr_i;
					mem_we <= `WriteDisable;
					wdata_o <= mem_data_i;
					mem_sel_o <= 4'b1111;
					mem_ce_o <= `ChipEnable;		
				end
				
				`EXE_LWL_OP:		begin
					mem_addr_o <= {mem_addr_i[31:2], 2'b00};	//lwl地址后两位置0
					mem_we <= `WriteDisable;
					mem_sel_o <= 4'b1111;							//lwl读一个字,所以全1
					mem_ce_o <= `ChipEnable;
					case (mem_addr_i[1:0])							//根据后两位与原始值组合 就是只保存高位
						2'b00:	begin
							wdata_o <= mem_data_i[31:0];
						end
						2'b01:	begin
							wdata_o <= {mem_data_i[23:0],reg2_i[7:0]};
						end
						2'b10:	begin
							wdata_o <= {mem_data_i[15:0],reg2_i[15:0]};
						end
						2'b11:	begin
							wdata_o <= {mem_data_i[7:0],reg2_i[23:0]};	
						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]};
						end
						2'b01:	begin
							wdata_o <= {reg2_i[31:16],mem_data_i[31:16]};
						end
						2'b10:	begin
							wdata_o <= {reg2_i[31:24],mem_data_i[31:8]};
						end
						2'b11:	begin
							wdata_o <= mem_data_i;	
						end
						default:	begin
							wdata_o <= `ZeroWord;
						end
					endcase					
				end
				
				`EXE_SB_OP:		begin
					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])
						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
					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 <= 4'b0000;
						end
					endcase						
				end
				
				`EXE_SW_OP:		begin
					mem_addr_o <= mem_addr_i;
					mem_we <= `WriteEnable;
					mem_data_o <= reg2_i;
					mem_sel_o <= 4'b1111;	
					mem_ce_o <= `ChipEnable;		
				end
				
				`EXE_SWL_OP:		begin
					mem_addr_o <= {mem_addr_i[31:2], 2'b00};	//置0 因为swl最多可能向RAM写入一个字
					mem_we <= `WriteEnable;
					mem_ce_o <= `ChipEnable;
					case (mem_addr_i[1:0])							//zero32拿来补0的
						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]};
						end
						2'b10:	begin
							mem_sel_o <= 4'b0011;
							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'b0000;
						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 <= 4'b0000;
						end
					endcase											
				end 
				default:		begin
				end
			endcase				
		end  
	end      
			
endmodule

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

`include "defines.v"

module data_ram(

	input	wire								clk,
	input wire								ce,
	input wire								we,
	input wire[`DataAddrBus]			addr,
	input wire[3:0]						sel,
	input wire[`DataBus]					data_i,	//要写入的数据
	output reg[`DataBus]					data_o
	
);
	//定义四个字节数组  
	//ByteWidth 7:0 字节宽度
	//DataMemNum 131071 RAM大小 单位是字 此处是128K word
	reg[`ByteWidth]  data_mem0[0:`DataMemNum-1];
	reg[`ByteWidth]  data_mem1[0:`DataMemNum-1];
	reg[`ByteWidth]  data_mem2[0:`DataMemNum-1];
	reg[`ByteWidth]  data_mem3[0:`DataMemNum-1];

	//写操作
	//DataMemNumLog2 17 实际使用的地址宽度
	always @ (posedge clk) begin
		if (ce == `ChipDisable) begin
			//data_o <= ZeroWord;
		end 
		else if(we == `WriteEnable) begin
			if (sel[3] == 1'b1) begin
		      data_mem3[addr[`DataMemNumLog2+1:2]] <= data_i[31:24];
		   end
			if (sel[2] == 1'b1) begin
		      data_mem2[addr[`DataMemNumLog2+1:2]] <= data_i[23:16];
		   end
		   if (sel[1] == 1'b1) begin
		      data_mem1[addr[`DataMemNumLog2+1:2]] <= data_i[15:8];
		   end
			if (sel[0] == 1'b1) begin
		      data_mem0[addr[`DataMemNumLog2+1:2]] <= data_i[7:0];
		   end			   	    
		end
	end
	
	//读操作
	always @ (*) begin
		if (ce == `ChipDisable) begin
			data_o <= `ZeroWord;
	   end 
		else if(we == `WriteDisable) begin	//地址仍左移了两位 因为按字节寻址 所以乘4
		   data_o <= {data_mem3[addr[`DataMemNumLog2+1:2]],
		              data_mem2[addr[`DataMemNumLog2+1:2]],
		              data_mem1[addr[`DataMemNumLog2+1:2]],
		              data_mem0[addr[`DataMemNumLog2+1:2]]};
		end 
		else begin
			data_o <= `ZeroWord;
		end
	end		

endmodule

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

`include "defines.v"

module LLbit_reg(

	input	wire							clk,
	input wire							rst,
	
	input wire                    flush,	//是否有异常发生
	
	//写端口
	input wire							LLbit_i,	//要写到LLbit寄存器的值
	input wire                    we,		//是否要写LLbit寄存器
	
	//读端口1
	output reg                    LLbit_o	//LLbit寄存器的值
	
);

	always @ (posedge clk) begin
		if (rst == `RstEnable) begin
			LLbit_o <= 1'b0;
		end 
		else if((flush == 1'b1)) begin	//如果异常发生,设置为0
			LLbit_o <= 1'b0;
		end 
		else if((we == `WriteEnable)) begin
			LLbit_o <= LLbit_i;
		end
	end

endmodule

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

				`EXE_LL_OP:		begin
					mem_addr_o <= mem_addr_i;
					mem_we <= `WriteDisable;
					wdata_o <= mem_data_i;	
					LLbit_we_o <= 1'b1;
					LLbit_value_o <= 1'b1;
					mem_sel_o <= 4'b1111;			
					mem_ce_o <= `ChipEnable;						
				end	

				`EXE_SC_OP:		begin
					if(LLbit == 1'b1) begin
						LLbit_we_o <= 1'b1;
						LLbit_value_o <= 1'b0;
						mem_addr_o <= mem_addr_i;
						mem_we <= `WriteEnable;
						mem_data_o <= reg2_i;
						wdata_o <= 32'b1;
						mem_sel_o <= 4'b1111;		
						mem_ce_o <= `ChipEnable;				
					end 
					else begin
						wdata_o <= 32'b0;
					end
				end

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值