杭电计算机组成原理实验RISC-V 实验 寄存器堆与运算器设计实验实验报告

杭电计算机组成原理实验RISC-V 实验 寄存器堆与运算器设计实验实验报告

一、实验目的与要求

1、 实验目的:

a) 学习寄存器堆的结构传送原理,掌握三端寄存器堆的设计方法

b) 掌握运算器的结构与工作原理,能将寄存器堆与暂存器ALU进行正确连接,构成运算器

2、 实验要求:首先设计一个RVI321指令集架构的寄存器堆(32*32),然后将其与前述实验中的暂存器A、B、F和ALU进行链接,构成一个完整的运算器。

二、实验设计与程序代码

1、 模块设计说明

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

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

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

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date:    23:38:21 05/07/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 wire clk_WB,reg_Write,
	input wire [4:0] R_Addr_A,R_Addr_B,W_Addr,
	input wire [3:0] ALU_OP,
	input wire clk_F,res_n,
	input wire clk_RR,
	input wire clk_25M,
	output wire ZF,SF,CF,OF,
	output wire [3:0] AN,
	output wire [7:0] seg
	);
	wire [31:0] R_DataA,R_DataB,W_Data,R_DataF;
	wire [31:0] A,B;
	wire [31:0] F;

	
DataInput mydatainput(res_n,W_Addr,clk_WB,reg_Write,R_Addr_A,R_Addr_B,F,R_DataA,R_DataB);//寄存器堆的区块
	ALU myalu(A,B,clk_F,ALU_OP,R_DataF,ZF,SF,CF,OF);//ALU计算的模块
	ShowNum myShowNum(clk_25M,F,seg,AN);//数码管显示的模块
	ABIPUT myabinput(clk_RR,R_DataA,R_DataB,R_DataF,A,B,F);//AB暂存器赋值模块
	
	
endmodule

module ABIPUT(//暂存器AB进行赋值模块
	input clk_RR,
	input [31:0] R_DataA,R_DataB,R_DataF,
	output reg [31:0] A,B,F
	);
	always@(posedge clk_RR)
		begin
			A<=R_DataA;
			B<=R_DataB;
		end
	always@(*)
	begin
		F<=R_DataF;
	end
endmodule

module DataInput(//暂存器堆的重置清零和R_Addr_A,R_Addr_B,的赋值
	input wire res_n,
	input wire [4:0] W_Addr,
	input wire clk_Regs,reg_Write,
	input wire [4:0] R_Addr_A,R_Addr_B,
	input wire [31:0] F,
	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]=32'b10000000000000000000000000000000;
		regs[31]=32'b01111111111111111111111111111111;
	end
	
	always@(posedge clk_Regs or posedge res_n)
	begin
		if(res_n)
		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]<=32'b10000000000000000000000000000000;
			regs[31]<=32'b01111111111111111111111111111111;
		end
		else
		begin
			if(reg_Write==1'b1)
			begin
				if(W_Addr!=0)
				begin
					regs[W_Addr]<=F;
				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,
	input clk_F,
	input [3:0] ALU_OP,
	output reg [31:0] F,
	output reg ZF,SF,CF,OF
	);
	reg F32;
	always@(posedge clk_F)
	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'b1001: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

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)
			0: begin AN=4'b1111;end
			1: begin AN=4'b1110;end
			2: begin AN=4'b1101;end
			3: begin AN=4'b1100;end
			4: begin AN=4'b1011;end
			5: begin AN=4'b1010;end
			6: begin AN=4'b1001;end
			7: 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
	end
	initial begin
		res_n=1;
		#100
		R_Addr_A=8;
		R_Addr_B=8;
		#100
		clk_RR=1;
		ALU_OP=0;
		#100
		clk_F=1;
		
		
		#100
		R_Addr_A=8;
		R_Addr_B=8;
		#100
		clk_RR=1;
		ALU_OP=6;
		#100
		clk_F=1;
		
	end
		
      
endmodule

1、 仿真波形

(运行仿真时,波形截图)

在这里插入图片描述

2、 仿真结果分析

(对仿真波形进行分析)
主要是验证寄存器堆里面的存取以及赋值和运算模块的验证

四、电路图

(开发工具中显示的电路模块图)

在这里插入图片描述

五、引脚配置

(引脚约束文件的内容,描述主要配置情况)
NET “clk_F” CLOCK_DEDICATED_ROUTE = FALSE;
NET “clk_WB” CLOCK_DEDICATED_ROUTE = FALSE;
#PlanAhead Generated physical constraints

NET “ALU_OP[3]” LOC = T3;
NET “ALU_OP[2]” LOC = U3;
NET “ALU_OP[1]” LOC = T4;
NET “ALU_OP[0]” LOC = V3;
NET “AN[3]” LOC = L21;
NET “AN[2]” LOC = M22;
NET “AN[1]” LOC = M21;
NET “AN[0]” LOC = N22;
NET “R_Addr_A[4]” LOC = V4;
NET “R_Addr_A[3]” LOC = W4;
NET “R_Addr_A[2]” LOC = Y4;
NET “R_Addr_A[1]” LOC = Y6;
NET “R_Addr_A[0]” LOC = W7;
NET “R_Addr_B[4]” LOC = Y8;
NET “R_Addr_B[3]” LOC = Y7;
NET “R_Addr_B[2]” LOC = T1;
NET “R_Addr_B[1]” LOC = U1;
NET “R_Addr_B[0]” LOC = U2;
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 “W_Addr[4]” LOC = W1;
NET “W_Addr[3]” LOC = W2;
NET “W_Addr[2]” LOC = Y1;
NET “W_Addr[1]” LOC = AA1;
NET “W_Addr[0]” LOC = V2;
NET “clk_RR” LOC = R4;
NET “clk_F” LOC = AA4;
NET “reg_Write” LOC = AB8;
NET “clk_WB” LOC = AB6;
NET “res_n” LOC = T5;
NET “ZF” LOC = R1;
NET “SF” LOC = P2;
NET “CF” LOC = P1;
NET “OF” LOC = N2;
NET “clk_25M” LOC = H4;

#PlanAhead Generated IO constraints

NET “ALU_OP[3]” IOSTANDARD = LVCMOS18;
NET “ALU_OP[2]” IOSTANDARD = LVCMOS18;
NET “ALU_OP[1]” IOSTANDARD = LVCMOS18;
NET “ALU_OP[0]” IOSTANDARD = LVCMOS18;
NET “AN[3]” IOSTANDARD = LVCMOS18;
NET “AN[2]” IOSTANDARD = LVCMOS18;
NET “AN[1]” IOSTANDARD = LVCMOS18;
NET “AN[0]” IOSTANDARD = LVCMOS18;
NET “R_Addr_A[4]” IOSTANDARD = LVCMOS18;
NET “R_Addr_A[3]” IOSTANDARD = LVCMOS18;
NET “R_Addr_A[2]” IOSTANDARD = LVCMOS18;
NET “R_Addr_A[1]” IOSTANDARD = LVCMOS18;
NET “R_Addr_A[0]” IOSTANDARD = LVCMOS18;
NET “R_Addr_B[4]” IOSTANDARD = LVCMOS18;
NET “R_Addr_B[3]” IOSTANDARD = LVCMOS18;
NET “R_Addr_B[2]” IOSTANDARD = LVCMOS18;
NET “R_Addr_B[1]” IOSTANDARD = LVCMOS18;
NET “R_Addr_B[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 “W_Addr[0]” IOSTANDARD = LVCMOS18;
NET “W_Addr[1]” IOSTANDARD = LVCMOS18;
NET “W_Addr[2]” IOSTANDARD = LVCMOS18;
NET “W_Addr[3]” IOSTANDARD = LVCMOS18;
NET “W_Addr[4]” IOSTANDARD = LVCMOS18;
NET “CF” IOSTANDARD = LVCMOS18;
NET “clk_25M” IOSTANDARD = LVCMOS18;
NET “clk_WB” IOSTANDARD = LVCMOS18;
NET “clk_RR” IOSTANDARD = LVCMOS18;
NET “clk_F” IOSTANDARD = LVCMOS18;
NET “OF” IOSTANDARD = LVCMOS18;
NET “reg_Write” IOSTANDARD = LVCMOS18;
NET “res_n” IOSTANDARD = LVCMOS18;
NET “SF” IOSTANDARD = LVCMOS18;
NET “ZF” IOSTANDARD = LVCMOS18;
NET “ALU_OP[3]” PULLDOWN;
NET “ALU_OP[2]” PULLDOWN;
NET “ALU_OP[1]” PULLDOWN;
NET “ALU_OP[0]” PULLDOWN;
NET “R_Addr_A[4]” PULLDOWN;
NET “R_Addr_A[3]” PULLDOWN;
NET “R_Addr_A[2]” PULLDOWN;
NET “R_Addr_A[1]” PULLDOWN;
NET “R_Addr_A[0]” PULLDOWN;
NET “R_Addr_B[4]” PULLDOWN;
NET “R_Addr_B[3]” PULLDOWN;
NET “R_Addr_B[2]” PULLDOWN;
NET “R_Addr_B[1]” PULLDOWN;
NET “R_Addr_B[0]” PULLDOWN;
NET “W_Addr[4]” PULLDOWN;
NET “W_Addr[3]” PULLDOWN;
NET “W_Addr[2]” PULLDOWN;
NET “W_Addr[1]” PULLDOWN;
NET “W_Addr[0]” PULLDOWN;
NET “clk_25M” PULLDOWN;
NET “clk_F” PULLDOWN;
NET “clk_RR” PULLDOWN;
NET “clk_WB” PULLDOWN;
NET “reg_Write” PULLDOWN;
NET “res_n” PULLDOWN;

六、思考与探索

1、实验结果记录:

先将reg[FFFFFFFFH]和reg[FFFFFFFEH]相加,再存入reg[1]中,最后对reg[1]与reg[1]相加得到FFFFFFFEH,则实验成功。
(实验操作的过程及结果记录)

2、实验结论:

本实验主要是为了寄存器堆的实现,我们发现寄存器堆的实现需要很多接口的输入和输出。同时也需要很多的时间去验收。
(分析实验结果,给出实验结论)

3、问题与解决方案:

本次实验的书写中我们主要发现问题还是分布在各个模块的关联性上面,同时没有满足相关的模块的逻辑顺序。
解决方案:具体读文件的顺序同时更多了解里面的实验原理。
(整个实验过程中发生了什么问题?你是如何解决的。)

4、思考题:

a) 寄存器堆的判断写入成功,通过写入的寄存器和零号寄存器单元进行加法来计算判断是否写入成功(零号寄寄存器永远为0)

b) ALU_OP可以为一个部分,CLK_A和CLK_B为一个部分,clk_write为一个部分,这三个部分可以分开写。那么一共只需要10个开关。

c) 不能,因为clk_RR是将寄存器堆模块的数据打入到寄存器模块中,clk_F是将寄存器模块的A,B计算出F放入到寄存器模块中,而clk_WB是将寄存器的F打入到寄存器堆当中,这其中功能不同,所以不能合并。

d) 可以将寄存器堆设置一个使能控制,表示单一输出,那么则只需要一个输出接口了,同时还可以加上一个相关的立即数存入B中,再进行后续的计算。

e) 在这个寄存器堆设计实验中,这个实验理解起来稍微困难,起初已经写好了代码,进行了仿真,出现了波形,但是后来老师要求读操作和写操作输出了不同的数据,在不同的单元。于是我就把仿真代码改了一下,将W_Data,W_Addr等数据做了修改。这个实验也就成功了。通过做这个寄存器堆设计实验,我对寄存器堆的读写操作有了一个新的认识和理解了。也对ISE这个软件的运用更加熟练,对寄存器堆这个概念也有了更深层次的理解,增长了我的只是,强化了我的实践能力以及思考能力。这次实验收获巨大。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值