计算机组成原理实验【不知道为什么一直在草稿箱里但懒得细看了就直接发了

敬请指正~
延迟语句可仿真不可综合
只能在仿真文件加延迟

单指令ori

赋值运算
指令的运行方式:取指令、执行指令循环
指令周期包含的阶段:
取指令IF
指令译码ID
指令执行EXE
存储器访问MEM【w/sw】
结果写回WB【结果保存到寄存器、存储器中】

IF

取指令两件事:取指令、PC+4
ID←ROM[PC]
PC←PC+4
虽然不是所有指令都是顺序执行【大部分是】,PC默认取下一条指令,如果遇到跳转指令再重新修改PC的值

PC+4拿出来【有一位空出来,默认为0
assign pc4 = pc + 4
IF框图
PC+4在加法器实现:assign pc4 = addr + 4;
pcsource给执行信号默认00 00顺序执行 01 10 11跳转执行
4选一数据选择器,除了默认的顺序执行还有三种跳转情况

ID

A ← RegisterFile[rs]
B ← RegisterFile[rt]
C ← PC+sign_extend(offset)<<2
ID会根据指令产生opcode、func、rs、rd、rt、sa、imm和address信号
CU【控制单元】根据ID提供的opcode、func产生不同的控制信号,这些控制信号会控制寄存器堆、alu和ram执行不同的操作,它们一起协同工作来完成指令的功能。
在这里插入图片描述
OP:alu的运算选择 regWE:要不要写

//ID
module InstrumentDecoder(
	input [31:0] instrument,
	output reg [5:0] pocode,
	output reg [5:0] func,
	output reg[4:0] rs,
	output reg[4:0] rt,
	output reg[4:0] rd,
	output reg[4:0] sa,
	output reg[15:0] immediate,
	output reg[25:0] addr
	);
	always @(*)
	begin
		opcode <= instrument[31:26];	//高六位固定
		rs <= 5'b00000;
		rt <= 5'b00000;
		rd <= 5'b00000;
		sa <= 5'b00000;
		immediate <= 15'b0;
		addr <= 25'b0;

	case(opcode)
		6'b000000:			//R类型
			begin
				func <= instrument[5:0];
				sa <= instrument[10:6];
				rd <= instrument[15:11];
				rt <= instrument[20:16];
				rs <= instrument[25:21];
			end
		6'b001000,			//I类型
		6'b001100,
		6'b001101,
		6'b001110,
		6'b100011,
		6'b101011,
		6'b000100,
		6'b000101,
		6'b001111:		//前面的指令与此条执行相同的操作
			begin
				immediate <= instrument[15:0];
				rt <= instrument[20:16];
				rs <= instrument[25:21];
					$monitor($time,,"rt==%b",rt);
			end
		6'b00010,6'b000011:		//J类型
			begin
				addr <= instrument[25:0];
			end
		default:rs <= 5'b00000;
	endcase
endmodule

//ControlUnit
module controlunit(
	input [5:0] opcode,		//MIPS指令类型
	input [5:0] func,		//MIPS指令功能码
	input z,				//是否为0标志
	output reg[1:0] pcsource,	//pc值得来源
	output reg ram2reg,		//是否将数据从ram中写入寄存器中
	output reg ramWE,		//是否写内存
	output reg [3:0] aluOP,//alu得运算类型
	output reg regWE,		//是否写寄存器
	output reg imm,		//是否产生立即数
	output reg shift,		//是否移位
	output reg isrt,		//目的寄存器地址,=1选择rt,否则选择rd
	output reg sign_ext,	//立即数扩展,=1为符号扩展,否则为0扩展
	output reg jal			//是否调用子程序跳转
	);
	always @(*)
		begin
			//先设置好默认值
			shift <= 1'b0;
			ram2reg <= 1'b0;
			ramWE <= 1'b0;
			imm <= 1'b0;
			isrt <= 1'b0;
			sign_ext <= 1'b0;
			pcsource <= 2'b00;
			aluOP <= 4'b0000;
			jal <= 1'b0;

			case(op)
				6'b000000:
				begin
					case(func)
						6'b100000:
						begin
							aluOP <= 4'b0001;
							regWE <= 1'b1;
						end
						6'b100010:
						begin
							aluOP <= 4'b0010;
							regWE <= 1'b1;
						end
						6'b000010:
						begin
							pcsource <= 2'b11;	//跳转指令
						end
						6'b000011:
						begin
							jal <= 1'b1;		//调用指令
							regWE <= 1'b1;
							pcsource <= 2'b11;
						end

EXE

ALU根据指令的不同做不同得工作
需要提供ALU得两个数据输入端和运算控制端【根据指令得类型来判断op/数据来源】

MEM

只有lw、sw指令进入存储器访问阶段MEM
不管是读内存还是写内存都必须有地址和数据
读内存是数据输出,写内存是数据输入

在这里插入图片描述

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页