杭电计算机组成原理实验RISC-V 实验 实现运算及传送指令的CPU设计实验 实现访存指令的CPU设计实验 实现转移指令的CPU设计实验

本文详细介绍了在已有的RISC-V CPU实验基础上,如何新增beq、jal、jalr指令,涉及数据通路设计、系统结构调整、有限状态机控制及指令集扩展。实验过程包括模块设计、代码实现、仿真验证和问题解决,旨在提升对RISC-V指令理解和CPU设计能力。
摘要由CSDN通过智能技术生成

杭电计算机组成原理实验RISC-V 实验 实现运算及传送指令的CPU设计实验 实现访存指令的CPU设计实验 实现转移指令的CPU设计实验

一、实验目的与要求

1、 实验目的:

a) 掌握RISC-V的转移指令的数据通路设计,掌握指令流和数据流的控制方法

b) 学习依据新增指令,修改多周期CPU的系统结构的方法,具备链接各模块构建整机的能力。

c) 掌握基于有限状态机,实现控制单元的设计方法。

d) 在实现RISC-V的R型和I型运算类指令,U型传送类指令,访存指令的基础上,进一步实现转移类指令beq,jal,jalr真的功能。

2、 实验要求:

本次实验内容:在前述构建并实现了运算类指令(R型和I型)、转移指令(U型lui指令)、访存指令(I型和S型)的RISC-V CPU基础上,新增三条转移类指令beq、jal、jalr;首先在实验8基础上,添加CP0寄存器、相对转移的地址加法器和PC写入的多路选择器,并与各个逻辑模块正确链接;然后修改寄存器堆的写入数据多路选择器、修改二级译码及控制单元,实现新的目标指令集功能;最后,编写测试程序,检查CPU是否能正确执行基于新目标集的程序。

二、实验设计与程序代码

1、 模块设计说明

(描述整个实验的设计方案,分几个模块,各模块的功能,各模块之间的连接关系,可附图)

实验除了顶层模块之外还有十一个模块,分别为指令的存取,指令放入到IR,ID1对指令的处理,ID2对ID1处理后的数据进行分析,分析出现在的指令的类型,ALU部分为数据的计算,同时还包括了判断B或者imm32,显示数据模块为数码管模块,对数码管进行显示,暂存器模块是为了A,B的赋值,以及对PC,PC0,W_DATA的赋值,CU模块是包含有限自动机,对不同的状态进行转移,数据获得模块,主要是为了查看相关的数据,对不同的数据进行选择。DM模块是存储器模块,主要是为了存储获取,写入相关的数据。

2、 实验程序源代码及注释等

(实验各个模块的代码,包含功能注释)

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date:    15:57:20 06/04/2021 
// Design Name: 
// Module Name:    main 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//
module main(
	input clk,clk_n,clk_25M,
	input [3:0] SW,
	output [3:0] AN,
	output [7:0] seg,
	output ZF,SF,CF,OF
    );


wire [31:0] PC,PC0,IR,inst_Code,A,B,F,R_Addr_A,R_Addr_B,W_Data,imm32,MDR;
wire IR_Write,Reg_Write,rs2_imm_s,PC0_write,Mem_Write,PC_Write;
wire [1:0] PC_s,w_data_s;
wire [4:0] rs1,rs2,rd;
wire [6:0] opcode;
wire [2:0] funct3;
wire [6:0] funct7;
wire [3:0] ALU_OP,ALU_OP_o;
wire IS_R,IS_IMM,IS_LUI,IS_LW,IS_SW,IS_BEQ,IS_JAL,IS_JALR;
wire [31:0] shownum;
IM myIM(clk,PC[7:2],inst_Code);//指令集
Get_Order myGet_Order(IR_Write,PC_Write,PC0_Write,PC_s,inst_Code,imm32,F,clk,clk_n,PC,IR,PC0);//获得指令
ID1 myID1(IR,rs1,rs2,rd,imm32,opcode,funct3,funct7);//ID1对指令进行处理
ID2 myID2(opcode,funct3,funct7,IS_R,IS_IMM,IS_LUI,IS_LW,IS_SW,IS_BEQ,IS_JAL,IS_JALR,ALU_OP);//ID2对指令处理
ALU myALU(A,B,imm32,clk,rs2_imm_s,ALU_OP_o,F,ZF,SF,CF,OF);//ALU部分
ShowNum myShowNum(clk_25M,shownum,seg,AN);//显示数据
DataInput myDataInput(clk,rd,clk_n,Reg_Write,rs1,rs2,W_Data,R_Addr_A,R_Addr_B);
ABInput myABInput(clk,R_Addr_A,R_Addr_B,imm32,F,MDR,PC,w_data_s,rs2_imm_s,A,B,W_Data);
CU myCU(clk,clk_n,IS_R,IS_IMM,IS_LUI,IS_LW,IS_SW,IS_BEQ,IS_JAL,IS_JALR,ZF,ALU_OP,PC_Write,PC0_Write,IR_Write,Reg_Write,Mem_Write,rs2_imm_s,w_data_s,PC_s,ALU_OP_o);
getShowNum mygetShowNum(PC,IR,W_Data,A,B,F,MDR,PC0,rd,imm32,rs1,rs2,SW,shownum);
DM myDM(clk,Mem_Write,F[7:2],B,MDR);
endmodule

module getShowNum(
input [31:0] PC,inst,W_Data,A,B,F,MDR,PC0,rd,imm32,rs1,rs2,
input [3:0] sw,
output reg [31:0] shownum
	);
	
always@(*)
begin
	case(sw)
		0:begin shownum=PC; end
		1:begin shownum=inst; end
		2:begin shownum=W_Data; end
		3:begin shownum=A; end
		4:begin shownum=B; end
		5:begin shownum=F; end
		6:begin shownum=MDR; end
		7:begin shownum=PC0; end
		8:begin shownum=rd; end
		9:begin shownum=imm32; end
		10:begin shownum=rs1; end
		11:begin shownum=rs2; end
		default:
			shownum=0;
	endcase
end

endmodule


module CU(
input clk,reset,IS_R,IS_IMM,IS_LUI,IS_LW,IS_SW,IS_BEQ,IS_JAL,IS_JALR,
input ZF,
input [3:0] ALU_OP,
output reg PC_Write,PC0_Write,IR_Write,Reg_Write,
output wire Mem_Write,
output reg rs2_imm_s,
output reg [1:0] w_data_s,PC_s,
output reg [3:0] ALU_OP_o
	);

reg [3:0] ST,Next_ST;

initial
begin
	ST=0;
end

assign Mem_Write=(Next_ST==4'b1010);

always@(posedge clk or posedge reset)
begin
	if(reset) ST<=0;
	else ST<=Next_ST;
end

always@(*)
begin
	case(ST)
		4'b0000:begin Next_ST=4'b0001; end
		4'b0001: 
		begin
			if(IS_LUI) Next_ST=4'b0110;
			else if(IS_R||IS_IMM||IS_LW||IS_SW||IS_JALR||IS_BEQ) Next_ST=4'b0010;
			else if(IS_JAL) Next_ST=4'b1011;
		end
		4'b0010:
		begin
			if(IS_R) Next_ST=4'b0011;
			else if(IS_IMM) Next_ST=4'b0101;
			else if(IS_LW||IS_SW||IS_JALR) Next_ST=4'b0111;
			else if(IS_BEQ) Next_ST=4'b1101;
		end
		4'b0011:begin Next_ST=4'b0100; end
		4'b0100:begin Next_ST=4'b0001; end
		4'b0101:begin Next_ST=4'b0100; end
		4'b0110:begin Next_ST=4'b0001; end
		4'b0111:
		begin 
			if(IS_LW) Next_ST=4'b1000;
			else if(IS_SW) Next_ST=4'b1010;
			else if(IS_JALR) Next_ST=4'b1100;
		end
		4'b1000:begin Next_ST=4'b1001; end
		4'b1001:begin Next_ST=4'b1010; end
		4'b1010:begin Next_ST=4'b0001; end
		4'b1011:begin Next_ST=4'b0001; end
		4'b1100:begin Next_ST=4'b0001; end
		4'b1101:begin Next_ST=4'b1110; end
		4'b1110:begin Next_ST=4'b0001; end
		default: Next_ST=4'b0001;
	endcase
end


always@(posedge clk or posedge reset)
begin
	if(reset)begin PC_Write<=0;PC0_Write<=0;IR_Write<=0;Reg_Write<=0;ALU_OP_o<=0;rs2_imm_s<=0;w_data_s<=0;PC_s<=0;end
	else
	begin
		case(Next_ST)
			4'b0001:begin PC_Write<=1;PC0_Write<=1;IR_Write<=1;Reg_Write<=0;ALU_OP_o<=0;rs2_imm_s<=0;w_data_s<=0;PC_s<=0;end
			4'b0010:begin PC_Write<=0;PC0_Write<=0;IR_Write<=0;Reg_Write<=0;ALU_OP_o<=0;rs2_imm_s<=0;w_data_s<=0;PC_s<=0;end
			4'b0011:begin PC_Write<=0;PC0_Write<=0;IR_Write<=0;Reg_Write<=0;ALU_OP_o<=ALU_OP;rs2_imm_s<=0;w_data_s<=0;PC_s<=0;end
			4'b0100:begin PC_Write<=0;PC0_Write<=0;IR_Write<=0;Reg_Write<=1;ALU_OP_o<=0;rs2_imm_s<=0;w_data_s<=0;PC_s<=0;end
			4'b0101:begin PC_Write<=0;PC0_Write<=0;IR_Write<=0;Reg_Write<=0;ALU_OP_o<=ALU_OP;rs2_imm_s<=1;w_data_s<=0;PC_s<=0;end
			4'b0110:begin PC_Write<=0;PC0_Write<=0;IR_Write<=0;Reg_Write<=1;ALU_OP_o<=0;rs2_imm_s<=0;w_data_s<=1;PC_s<=0;end
			4'b0111:begin PC_Write<=0;PC0_Write<=0;IR_Write<=0;Reg_Write<=0;ALU_OP_o<=0;rs2_imm_s<=1;w_data_s<=0;PC_s<=0;end
			4'b1000:begin PC_Write<=0;PC0_Write<=0;IR_Write<=0;Reg_Write<=0;ALU_OP_o<=0;rs2_imm_s<=0;w_data_s<=0;PC_s<=0;end
			4'b1001:begin PC_Write<=0;PC0_Write<=0;IR_Write<=0;Reg_Write<=1;ALU_OP_o<=0;rs2_imm_s<=0;w_data_s<=2;PC_s<=0;end
			4'b1010:begin PC_Write<=0;PC0_Write<=0;IR_Write<=0;Reg_Write<=0;ALU_OP_o<=0;rs2_imm_s<=0;w_data_s<=0;PC_s<=0;end
			4'b1011:begin PC_Write<=1;PC0_Write<=0;IR_Write<=0;Reg_Write<=1;ALU_OP_o<=0;rs2_imm_s<=0;w_data_s<=3;PC_s<=1;end
			4'b1100:begin PC_Write<=1;PC0_Write<=0;IR_Write<=0;Reg_Write<=1;ALU_OP_o<=0;rs2_imm_s<=0;w_data_s<=3;PC_s<=2;end
			4'b1101:begin PC_Write<=0;PC0_Write<=0;IR_Write<=0;Reg_Write<=0;ALU_OP_o<=8;rs2_imm_s<=0;w_data_s<=0;PC_s<=0;end
			4'b1110:begin PC_Write<=ZF;PC0_Write<=0;IR_Write<=0;Reg_Write<=0;ALU_OP_o<=0;rs2_imm_s<=0;w_data_s<=0;PC_s<=1;end
		endcase
	end

end
	
	
endmodule



module ID2(
	input [6:0] opcode,
	input [2:0] funct3,
	input [6:0] funct7,
	output reg IS_R,IS_IMM,IS_LUI,IS_LW,IS_SW,IS_BEQ,IS_JAL,IS_JALR,
	output reg [3:0] ALU_OP
	);
always@(*)
begin
	case(opcode)
		7'b0110011://R
		begin IS_R=1;IS_IMM=0;IS_LUI=0;IS_LW=0;IS_SW=0;IS_BEQ=0;IS_JAL=0;IS_JALR=0;ALU_OP={funct7[5],funct3}; end
		7'b0010011://I
		begin IS_R=0;IS_IMM=1;IS_LUI=0;IS_LW=0;IS_SW=0;IS_BEQ=0;IS_JAL=0;IS_JALR=0;ALU_OP=(funct3==3'b101)?{funct7[5],funct3}:{1'b0,funct3};end
		7'b0110111://U
		begin IS_R=0;IS_IMM=0;IS_LUI=1;IS_LW=0;IS_SW=0;IS_BEQ=0;IS_JAL=0;IS_JALR=0;ALU_OP=0;end
		7'b0000011://IW
		begin IS_R=0;IS_IMM=0;IS_LUI=0;IS_LW=1;IS_SW=0;IS_BEQ=0;IS_JAL=0;IS_JALR=0;ALU_OP=0;end
		7'b0100011://SW
		begin IS_R=0;IS_IMM=0;IS_LUI=0;IS_LW=0;IS_SW=1;IS_BEQ=0;IS_JAL=0;IS_JALR=0;ALU_OP=0;end
		7'b1100011://B
		begin IS_R=0;IS_IMM=0;IS_LUI=0;IS_LW=0;IS_SW=0;IS_BEQ=1;IS_JAL=0;IS_JALR=0;ALU_OP=0;end
		7'b1101111://Jal
		begin IS_R=0;IS_IMM=0;IS_LUI=0;IS_LW=0;IS_SW=0;IS_BEQ=0;IS_JAL=1;IS_JALR=0;ALU_OP=0;end
		7'b1100111://Jalr
		begin IS_R=0;IS_IMM=0;IS_LUI=0;IS_LW=0;IS_SW=0;IS_BEQ=0;IS_JAL=0;IS_JALR=1;ALU_OP=0;end
		default: 
		begin IS_R=0;IS_IMM=0;IS_LUI=0;IS_LW=0;IS_SW=0;IS_BEQ=0;IS_JAL=0;IS_JALR=1;ALU_OP=0;end
	endcase

end
	
	
endmodule

module ID1(
	input [31:0] inst,
	output reg [4:0] rs1,rs2,rd,
	output reg [31:0] imm32,
	output reg [6:0] opcode,
	output reg [2:0] funct3,
	output reg [6:0] funct7
	);

	reg [5:0] I_fmt;
	
	always@(*)
	begin
		opcode=inst[6:0];
		rs1=inst[19:15];
		rs2=inst[24:20];
		rd=inst[11:7];
		funct3=inst[14:12];
		funct7=inst[31:25];
		
		
		case(opcode)
			7'b0110011: I_fmt=6'b000001;//R
			7'b0010011: I_fmt=6'b100000;//I
			7'b0000011: I_fmt=6'b100000;//L和I型一致
			7'b0100011: I_fmt=6'b010000;//S
			7'b1100011: I_fmt=6'b001000;//B
			7'b0110111: I_fmt=6'b000100;//U
			7'b1101111: I_fmt=6'b000010;//Jal
			7'b1100111: I_fmt=6'b100000;//Jalr和I一致
			default: 
				I_fmt=0;
		endcase
		case(I_fmt)
			6'b000001: imm32=0;//R
			6'b100000: 
			begin
				if(funct3==3'b101||3'b001) imm32={{27{1'b0}},inst[24:20]};
				else imm32={{20{inst[31]}},inst[31:20]};//I
				
			end
			6'b010000: imm32={{20{inst[31]}},inst[31:25],inst[11:7]};//S
			6'b001000: imm32={{20{inst[31]}},inst[7],inst[30:25],inst[11:8],1'b0};//B
			6'b000100: imm32={inst[31:12],{12{1'b0}}};//U
			6'b000010: imm32={{12{inst[31]}},inst[19:12],inst[20],inst[30:21],1'b0};//J1,I2
			default: 
				imm32=0;
		endcase
		
		
		
	end
endmodule


module Get_Order(
	input IR_Write,PC_Write,PC0_Write,
	input [1:0] PC_s,
	input [31:0] inst_Code,imm32,F,
	input clk,reset,
	output reg [31:0] PC,IR,PC0
	);
	initial
	begin
		PC=0;
	end
	always@(negedge clk or posedge reset)
	begin
		if(reset)
		begin
			PC<=0;
			IR<=0;
		end
		else
		begin
			if(IR_Write==1)
			begin
				IR<=inst_Code;
			end
			if(PC_Write==1)
			begin
				if(PC_s==0)	PC<=PC+4;
				else if(PC_s==1) PC<=PC0+imm32;
				else if(PC_s==2) PC<=F;
			end
			if(PC0_Write==1)
			begin
				PC0<=PC;
			end
		end
	end
endmodule


module ABInput(//暂存器AB  W_Data进行赋值模块
	input clk_RR,
	input [31:0] R_DataA,R_DataB,
	input [31:0] imm32,F,MDR,PC,
	input [1:0]w_data_s,
	input rs2_imm_s,
	output reg [31:0] A,B,W_Data
	);
	always@(negedge clk_RR)
	begin
		A<=R_DataA;
		B<=R_DataB;
	end
		
	always@(*)
	begin
		if(w_data_s==0) begin W_Data=F; end
		else if(w_data_s==1) begin W_Data=imm32; end
		else if(w_data_s==2) begin W_Data=MDR; end
		else if(w_data_s==3) begin W_Data=PC;end
	end
		
		
endmodule



module DataInput(//暂存器堆的重置清零和R_Addr_A,R_Addr_B,的赋值
	input wire clk,
	input wire [4:0] W_Addr,
	input wire reset,reg_Write,
	input wire [4:0] R_Addr_A,R_Addr_B,
	input wire [31:0] W_Data,
	output reg [31:0] R_DataA,R_DataB
	);
	reg [31:0] regs [31:0];
	
	initial
	begin
		regs[0]=0;
		regs[1]=1;
		regs[2]=2;
		regs[3]=3;
		regs[4]=4;
		regs[5]=5;
		regs[6]=6;
		regs[7]=7;
		regs[8]=8;
		regs[9]=9;
		regs[10]=10;
		regs[11]=11;
		regs[12]=12;
		regs[13]=13;
		regs[14]=14;
		regs[15]=15;
		regs[16]=16;
		regs[17]=17;
		regs[18]=18;
		regs[19]=19;
		regs[20]=20;
		regs[21]=21;
		regs[22]=22;
		regs[23]=23;
		regs[24]=24;
		regs[25]=25;
		regs[26]=26;
		regs[27]=27;
		regs[28]=28;
		regs[29]=29;
		regs[30]=30;
		regs[31]=31;
	end
	
	always@(negedge clk or posedge reset)
	begin
		if(reset)
		begin
			regs[0]<=0;
			regs[1]<=1;
			regs[2]<=2;
			regs[3]<=3;
			regs[4]<=4;
			regs[5]<=5;
			regs[6]<=6;
			regs[7]<=7;
			regs[8]<=8;
			regs[9]<=9;
			regs[10]<=10;
			regs[11]<=11;
			regs[12]<=12;
			regs[13]<=13;
			regs[14]<=14;
			regs[15]<=15;
			regs[16]<=16;
			regs[17]<=17;
			regs[18]<=18;
			regs[19]<=19;
			regs[20]<=20;
			regs[21]<=21;
			regs[22]<=22;
			regs[23]<=23;
			regs[24]<=24;
			regs[25]<=25;
			regs[26]<=26;
			regs[27]<=27;
			regs[28]<=28;
			regs[29]<=29;
			regs[30]<=30;
			regs[31]<=31;
		end
		else
		begin
			if(reg_Write==1'b1)
			begin
				if(W_Addr!=0)
				begin
					regs[W_Addr]<=W_Data;
				end
			end
		end
	end
	
	always@(*)
	begin
		R_DataA=regs[R_Addr_A];
		R_DataB=regs[R_Addr_B];
	end
	
endmodule

module ALU(//ALU的计算模块
	input [31:0] A,B,imm32,
	input clk_F,
	input rs2_imm_s,
	input [3:0] ALU_OP,
	output reg [31:0] F,
	output reg ZF,SF,CF,OF
	);
	reg F32;
	reg ZF_O,SF_O,CF_O,OF_O;
	always@(negedge clk_F)
	begin
		if(rs2_imm_s==0)
		begin
			case(ALU_OP)
			4'b0000:begin {F32,F}=A+B;end
			4'b0001:begin F=A<<B;end
			4'b0010:begin F=($signed(A)<$signed(B))?1:0;end
			4'b0011:begin F=(A<B)?1'b1 : 1'b0;end
			4'b0100:begin F=A^B;end
			4'b0101:begin F=A>>B;end
			4'b0110:begin F=A|B;end
			4'b0111:begin F=A&B;end
			4'b1000:begin {F32,F}=A-B;F32=~F32; end
			4'b1101:begin F=($signed(A))>>>B;end
			endcase
			ZF=(F>0)?1'b0:1'b1;
			SF=F[31];
			CF=F32;
			OF=A[31]^B[31]^F[31]^F32;
		end
		else
		begin
			case(ALU_OP)
			4'b0000:begin {F32,F}=A+imm32;end
			4'b0001:begin F=A<<imm32;end
			4'b0010:begin F=($signed(A)<$signed(imm32))?1:0;end
			4'b0011:begin F=(A<imm32)?1'b1 : 1'b0;end
			4'b0100:begin F=A^imm32;end
			4'b0101:begin F=A>>imm32;end
			4'b0110:begin F=A|imm32;end
			4'b0111:begin F=A&imm32;end
			4'b1000:begin {F32,F}=A-imm32;F32=~F32; end
			4'b1101:begin F=($signed(A))>>>imm32;end
			endcase
			ZF=(F>0)?1'b0:1'b1;
			SF=F[31];
			CF=F32;
			OF=A[31]^B[31]^F[31]^F32;
		end
	end
	

endmodule



module ShowNum(//数码管模块用于显示数据
	input clk_25M,
	input [31:0] F,
	output reg [7:0]seg,
	output reg [3:0]AN
	);
	parameter count=10000;
	reg [31:0] clk_num;
	reg [3:0] digit;
	reg [2:0] which;
	
	initial
	begin
		clk_num=0;
		which=0;
		digit=0;
	end
	
	always@(posedge clk_25M)
	begin
		if(clk_num<count)
		begin clk_num<=clk_num+1;end
		else
		begin 
			clk_num<=0;
			which<=which+3'b001;
			case(which)
				0: begin digit<=F[3:0];end
				1: begin digit<=F[7:4];end
				2: begin digit<=F[11:8];end
				3: begin digit<=F[15:12];end
				4: begin digit<=F[19:16];end
				5: begin digit<=F[23:20];end
				6: begin digit<=F[27:24];end
				7: begin digit<=F[31:28];end
			endcase
		end
	end

	
	always@(digit,which)
	begin
		case(which)
			1: begin AN=4'b1111;end
			2: begin AN=4'b1110;end
			3: begin AN=4'b1101;end
			4: begin AN=4'b1100;end
			5: begin AN=4'b1011;end
			6: begin AN=4'b1010;end
			7: begin AN=4'b1001;end
			0: begin AN=4'b1000;end
			default:AN=4'bzzzz;
		endcase
		case(digit)
				0:seg[7:0]=8'b00000011;
				1:seg[7:0]=8'b10011111;
				2:seg[7:0]=8'b00100101;
				3:seg[7:0]=8'b00001101;
				4:seg[7:0]=8'b10011001;
				5:seg[7:0]=8'b01001001;
				6:seg[7:0]=8'b01000001;
				7:seg[7:0]=8'b00011111;
				8:seg[7:0]=8'b00000001;
				9:seg[7:0]=8'b00001001;	
				10:seg[7:0]=8'b00010001;
				11:seg[7:0]=8'b11000001;
				12:seg[7:0]=8'b01100011;
				13:seg[7:0]=8'b10000101;
				14:seg[7:0]=8'b01100001;
				15:seg[7:0]=8'b01110001;
				default:seg[7:0]=8'b11111111;
		endcase
	end
endmodule

三、实验仿真

1、 仿真代码

(含仿真源代码、仿真验证方案)

`timescale 1ns / 1ps


// Company: 
// Engineer:
//
// Create Date:   22:20:29 06/18/2021
// Design Name:   main
// Module Name:   D:/ShuZiDianLu/example/exam9.1/test1.v
// Project Name:  exam9.1
// Target Device:  
// Tool versions:  
// Description: 
//
// Verilog Test Fixture created by ISE for module: main
//
// Dependencies:
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 


module test1;

	// Inputs
	reg clk;
	reg clk_n;
	reg clk_25M;
	reg [3:0] SW;

	// Outputs
	wire [3:0] AN;
	wire [7:0] seg;
	wire ZF;
	wire SF;
	wire CF;
	wire OF;

	// Instantiate the Unit Under Test (UUT)
	main uut (
		.clk(clk), 
		.clk_n(clk_n), 
		.clk_25M(clk_25M), 
		.SW(SW), 
		.AN(AN), 
		.seg(seg), 
		.ZF(ZF), 
		.SF(SF), 
		.CF(CF), 
		.OF(OF)
	);

	initial begin
		// Initialize Inputs
		clk = 0;
		clk_n = 0;
		clk_25M = 0;
		SW = 0;

		// Wait 100 ns for global reset to finish
		#100;
        
		// Add stimulus here
		
	end
	
	initial begin
		forever #1000 clk=~clk;	
	end
   initial begin
		forever #1 clk_25M=~clk_25M;	
	end

2、 仿真波形
(运行仿真时,波形截图)
在这里插入图片描述

3、 仿真结果分析
(对仿真波形进行分析)
仿真波形基本符合实验要求

四、电路图
(开发工具中显示的电路模块图)
在这里插入图片描述

五、引脚配置

(引脚约束文件的内容,描述主要配置情况)



NET "AN[3]" LOC = L21;
NET "AN[2]" LOC = M22;
NET "AN[1]" LOC = M21;
NET "AN[0]" LOC = N22;
NET "seg[7]" LOC = H19;
NET "seg[6]" LOC = G20;
NET "seg[5]" LOC = J22;
NET "seg[4]" LOC = K22;
NET "seg[3]" LOC = K21;
NET "seg[2]" LOC = H20;
NET "seg[1]" LOC = H22;
NET "seg[0]" LOC = J21;
NET "SW[3]" LOC = T3;
NET "SW[2]" LOC = U3;
NET "SW[1]" LOC = T4;
NET "SW[0]" LOC = V3;
NET "ZF" LOC = R1;
NET "SF" LOC = P2;
NET "CF" LOC = P1;
NET "OF" LOC = N2;
NET "clk" LOC = R4;
NET "clk_25M" LOC = H4;
NET "clk_n" LOC = AA4;

#PlanAhead Generated IO constraints 

NET "AN[3]" IOSTANDARD = LVCMOS18;
NET "AN[2]" IOSTANDARD = LVCMOS18;
NET "AN[1]" IOSTANDARD = LVCMOS18;
NET "AN[0]" IOSTANDARD = LVCMOS18;
NET "seg[7]" IOSTANDARD = LVCMOS18;
NET "seg[6]" IOSTANDARD = LVCMOS18;
NET "seg[5]" IOSTANDARD = LVCMOS18;
NET "seg[4]" IOSTANDARD = LVCMOS18;
NET "seg[3]" IOSTANDARD = LVCMOS18;
NET "seg[2]" IOSTANDARD = LVCMOS18;
NET "seg[1]" IOSTANDARD = LVCMOS18;
NET "seg[0]" IOSTANDARD = LVCMOS18;
NET "SW[3]" IOSTANDARD = LVCMOS18;
NET "SW[2]" IOSTANDARD = LVCMOS18;
NET "SW[1]" IOSTANDARD = LVCMOS18;
NET "SW[0]" IOSTANDARD = LVCMOS18;
NET "clk" IOSTANDARD = LVCMOS18;
NET "clk_25M" IOSTANDARD = LVCMOS18;
NET "clk_n" IOSTANDARD = LVCMOS18;
NET "OF" IOSTANDARD = LVCMOS18;
NET "SF" IOSTANDARD = LVCMOS18;
NET "ZF" IOSTANDARD = LVCMOS18;
NET "CF" IOSTANDARD = LVCMOS18;
NET "SW[3]" PULLDOWN;
NET "SW[2]" PULLDOWN;
NET "SW[1]" PULLDOWN;
NET "SW[0]" PULLDOWN;
NET "clk_25M" PULLDOWN;
NET "clk" PULLDOWN;
NET "clk_n" PULLDOWN;

六、思考与探索

1、 实验结果记录:

实验8实验结果记录表

序号PCIR汇编指令预期执行结果指令clk数W_DataMDR
1001000f93li t6,16t6=1640x100x10
24000fad03lw s10,0(t6)S10=0x1140x110x11
38004fad83lw s11,4(t6)S11=0x2240x220x22
4C01bfa023sw s11,0(t6)Mem[4]=0x2240x22
51001afa223sw s10,4(t6)Mem[5]=0x1140x11
614000fad03lw s10,0(t6)S10=0x2240x220x22
718004fad83lw s11,4(t6)S11=0x1140x110x11
81c01bd0e33add t3,s10,s11t3=0x3340x33
92001c02823sw t3,16(zero)t3=0x3340x33
102401002e83lw t4,16(zero)t4=0x3340x330x33
112887600093li ra,22ra=0xFFFF_F87640xFFFF_F876
122c00400113li sp,4sp=0x0000_000440x0000_0004
1330002081b3add gp,ra,spgp=0xFFFF_F87A40xFFFF_F87A
143440208233sub tp,ra,sptp=0xFFFF_F87240xFFFF_F872
1538002092b3sll t0,ra,spt0=0xFFFF_876040xFFFF_8760
163c0020d333srl t1,ra,spt1=0x0FFF_FF8740x0FFF_FF87
17404020d3b3sra t2,ra,spt2=0xFFFF_FF8740xFFFF_FF87
18440020a433slt s0,ra,sps0=0x0000_000140x0000_0001
19480020b4b3sltu s1,ra,sps1=0x0000_000040x0000_0000
204c0062f533and a0,t0,t1s0=0x0FFF_870040x0FFF_8700
21500062e5b3or a1,t0,t1a1=0xFFFF_FFE740xFFFF_FFE7
22540062c633xor a2,t0,t1a2=0xF000_78E740xF000_78E7
2358800006b7lui a3,0x80000a3=0x8000_000020x8000_0000
245cfff68713addi a4,a3,-1a4=0x7FFF_FFFF40x7FFF_FFFF
256012370793addi a5,a4,291a5=0x8000_012240x8000_0122
266400379813slli a6,a5,0x3a6=0x0000_091040x0000_0910
27680037d893srli a7,a5,0x3a7=0x1000_002440x1000_0024
286c4037d913srai s2,a5,0x3s2=0xF000_002440xF000_0024
2970fff92993slti s3,s2,-1s3=0x0000_000140x0000_0001
3074fff93a13sltiu s4,s2,-1s4=0x0000_000140x0000_0001
317800192a93slti s5,s2,1s5=0x0000_000140x0000_0001
327c00193b13seqz s6,s2s6=0x0000_000040x0000_0000
33800ff67b93andi s7,a2,255s7=0x0000_00E740x0000_00E7
34840ff66b93ori s7,a2,255s7=0xF000_78FF40xF000_78FF —
358800010c37lui s8,0x10s8=0x0001_000020x0001_0000
368cfffc0c13addi s8,s8,-1s8=0x0000_FFFF40x0000_FFFF
3790fffc4c93not s9,s8s9=0xFFFF_000040xFFFF_0000

表11.1 实验9实验结果记录表

序号PCIR汇编指令执行结果下条指令地址
1001000513li a0,16a0=1600306593
2400306593ori a1,zero,3a1=303004613
3803004613xori a2,zero,48a2=48008000ef
4C008000efJal ra,14PC=14000502b3
514000502b3add t0,a0,zerot0=160005e333
6180005e333or t1,a1,zeroa1=3000073b3
71c000073b3and t2,zero,zerot2=00002ae03
8200002ae03lw t3,0(t0)t3=401c383b3
92401c383b3add t2,t2,t3t2=400428293
102800428293addi t0,t0,4t0=20fff30313
112cfff30313addi t1,t1,-1t1=200030463
123000030463beqz t1,38 0fedff06f
1334fedff06fj 20 PC=200002ae03
14200002ae03lw t3,0(t0)t3=501c383b3
152401c383b3add t2,t2,t3t2=900428293
162800428293addi t0,t0,4 t100030463
183000030463beqz t1,38 0fedff06f
1934fedff06fj 20 PC=200002ae03
20200002ae03lw t3,0(t0)t3=601c383b3
212401c383b3add t2,t2,t3t2=f00428293
222800428293addi t0,t0,4t0=28fff30313
232cfff30313addi t1,t1,-1t1=000030463
243000030463beqz t1,38 100762023
253800762023sw t2,0(a2)mem©=f00008067
263c00008067Ret00062403
271000062403lw s0,0(a2)s0=f----

2、 实验结论:

(分析实验结果,给出实验结论)
实验结果基本符合实验的要求,同时对照数据值发现符合DM提前放进进去的数据值,说明sw和lw没有问题,同时跳转指令也符合要求,则说明beq、jal、jalr也符合要求。

3、 问题与解决方案:

问题:实验中间发现了很多奇怪的问题,比如跳转不对,数据不对,数码管位移这一系列的问题。
解决方案:通过反复实验和查找数据,发现一部分错误在于没有必要的代码,还有一部分代码问题在于写代码时间过长,导致除了代码的前后差异过大,从而也会造成差异。

4、 思考题:

a) 可以执行三条转移指令,测试例子可以查看实验记录结果

代码如下:
00000000 <main>:
   0:   01000513                li      a0,16
   4:   00306593                ori     a1,zero,3
   8:   03004613                xori    a2,zero,48
   c:   008000ef                jal     ra,14 <BankSum>
  10:   00062403                lw      s0,0(a2)

00000014 <BankSum>:
  14:   000502b3                add     t0,a0,zero
  18:   0005e333                or      t1,a1,zero
  1c:   000073b3                and     t2,zero,zero

00000020 <L>:
  20:   0002ae03                lw      t3,0(t0)
  24:   01c383b3                add     t2,t2,t3
  28:   00428293                addi    t0,t0,4
  2c:   fff30313                addi    t1,t1,-1
  30:   00030463                beqz    t1,38 <exit>
  34:   fedff06f                j       20 <L>

00000038 <exit>:
  38:   00762023                sw      t2,0(a2)
  3c:   00008067                ret

b) 分析j的指令1111 1110 1101 1111 1111 0000 0110 1111 发现这是opcode 为jar的类型,所以为jal。因为jal是20位的立即数,而jalr只有12位立即数,则需要压缩,同时jalr主要是为了rs1+imm32->PC则需要将PC的数值放入到rs1中。所以rd和rs1需要一致,综合得到jalr指令为:1011 1111 0110 0000 1000 0000 1110 0111。

c) 可以,但是这里存在的问题在于需要添加一条PC和imm32的加法器,同时在选择w_data_s的时候需要添加更多的选择,所以CU部分也需要添加相应的状态才可以实现。

d) 判断转移条件只需要是ZF=0即可,其他的判断条件其实只需要在原来的基础上加上非即可。

e) 问题很多,找老师,跑板子,查数据解决。

评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值