杭电计算机组成原理实验RISC-V 实验 取指令及指令译码实验

一、实验目的与要求

1、 实验目的:

a) 掌握指令存储器、PC与IR的设计方法

b) 掌握CPU取指令操作与指令译码的方法和过程,掌握指令译码器的设计方法

c) 理解RISC-V立即数的生成与扩展方法,掌握立即数拼接与扩展器的设计

2、 实验要求:

首先设计一个64 X 32位的只读存储器作为指令存储器;然后设计程序计数器PC和指令存储器IR,实现取指令操作,设计一个指令译码器和一个立即数拼接与扩展器,完成指令译码操作。

二、实验设计与程序代码

1、 模块设计说明

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

2、 实验程序源代码及注释等
(实验各个模块的代码,包含功能注释)

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date:    00:13:16 05/25/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 Ir_Write,
	input PC_Write,
	input clk_im,
	input clk_n,
	input clk_25M,
	output [4:0] rs1,rs2,rd,
	output [3:0] AN,
	output [7:0] seg,
	output [6:0] opcode,
	output [2:0] funct3,
	output [6:0] funct7
    );
	wire [31:0] IR;
	wire [31:0] inst;
	wire [31:0] imm32;
	wire [31:0] PC;
	Get_Order myGet_Order(Ir_Write,PC_Write,IR,clk_im,clk_n,PC,inst);
	IDI myIDI(inst,rs1,rs2,rd,imm32,opcode,funct3,funct7);
	ShowNum myShowNum(clk_25M,imm32,seg,AN);//这个模块主要是相关数据显示模块
	IM myIM(clk_im,PC[7:2],IR);
	
	
endmodule





module Get_Order(
	input IR_Write,
	input PC_Write,
	input [31:0] IR,
	input clk_im,
	input clk_n,
	output reg [31:0] PC,
	output reg [31:0] inst
	);

	
	initial
	begin
		PC=0;
	end
	always@(posedge clk_im or posedge clk_n)
	begin
		if(IR_Write==1)
		begin
			inst<=IR;
			PC<=PC+4;
		end
		else if(clk_n==1)
		begin
			PC<=0;
		end
	end
	


endmodule



module IDI(
	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'b0010011: I_fmt=6'b1000000;//I1
			7'b0000011: I_fmt=6'b1000000;//I2
			7'b0100011: I_fmt=6'b0100000;//S
			7'b1100011: I_fmt=6'b0010000;//B
			7'b0110111: I_fmt=6'b0001000;//U
			7'b0010111:	I_fmt=6'b0001000;//U
			7'b1101111: I_fmt=6'b0000100;//J1
			7'b1100111: I_fmt=6'b0000100;//J2
			7'b0110011: I_fmt=6'b0000010;//R
			default: 
				I_fmt=0;
		endcase
		case(I_fmt)
			6'b0000010: imm32=0;
			6'b1000000: imm32={{20{inst[31]}},inst[31:20]};//I1.I2
			6'b1000000: imm32={{20{inst[31]}},inst[31:25],inst[11:7]};//S
			6'b0010000: imm32={{20{inst[31]}},inst[7],inst[30:25],inst[11:8],1'b0};//B
			6'b0001000: imm32={inst[31:12],{12{1'b0}}};//U
			6'b0000100: imm32={{12{inst[31]}},inst[19:12],inst[20],inst[30:21],1'b0};//J1,I2
			default: 
				imm32=0;
		endcase
		
		
		
	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:   00:21:34 06/03/2021
// Design Name:   main
// Module Name:   D:/ShuZiDianLu/example/PCIR/test.v
// Project Name:  PCIR
// Target Device:  
// Tool versions:  
// Description: 
//
// Verilog Test Fixture created by ISE for module: main
//
// Dependencies:
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 


module test;

	// Inputs
	reg Ir_Write;
	reg PC_Write;
	reg clk_im;
	reg clk_n;
	reg clk_25M;

	// Outputs
	wire [4:0] rs1;
	wire [4:0] rs2;
	wire [4:0] rd;
	wire [3:0] AN;
	wire [7:0] seg;
	wire [6:0] opcode;
	wire [2:0] funct3;
	wire [6:0] funct7;

	// Instantiate the Unit Under Test (UUT)
	main uut (
		.Ir_Write(Ir_Write), 
		.PC_Write(PC_Write), 
		.clk_im(clk_im), 
		.clk_n(clk_n), 
		.clk_25M(clk_25M), 
		.rs1(rs1), 
		.rs2(rs2), 
		.rd(rd), 
		.AN(AN), 
		.seg(seg), 
		.opcode(opcode), 
		.funct3(funct3), 
		.funct7(funct7)
	);

	initial begin
		// Initialize Inputs
		Ir_Write = 0;
		PC_Write = 0;
		clk_im = 0;
		clk_n = 0;
		clk_25M = 0;

		// Wait 100 ns for global reset to finish
		#100;
        
		// Add stimulus here
		Ir_Write=1;
		PC_Write=1;
		#100
		clk_im = 1;
		#20
		clk_im = 0;
		#100
		clk_im = 1;
		#20
		clk_im = 0;
		#100
		clk_im = 1;
		#20
		clk_im = 0;
		#100
		clk_im = 1;
		#20
		clk_im = 0;
		#100
		clk_im = 1;
		#20
		clk_im = 0;
		#100
		clk_im = 1;
		#20
		clk_im = 0;
		#100
		clk_im = 1;
		#20
		clk_im = 0;
		#100
		clk_im = 1;
		#20
		clk_im = 0;
	end
	
	initial begin
		forever #1 clk_25M=~clk_25M;	
	end
      
endmodule

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[0]" LOC = J21;
NET "seg[1]" LOC = H22;


NET "AN[3]" IOSTANDARD = LVCMOS18;
NET "AN[2]" IOSTANDARD = LVCMOS18;
NET "AN[1]" IOSTANDARD = LVCMOS18;
NET "AN[0]" IOSTANDARD = LVCMOS18;
NET "funct3[2]" IOSTANDARD = LVCMOS18;
NET "funct3[1]" IOSTANDARD = LVCMOS18;
NET "funct3[0]" IOSTANDARD = LVCMOS18;
NET "funct7[6]" IOSTANDARD = LVCMOS18;
NET "funct7[5]" IOSTANDARD = LVCMOS18;
NET "funct7[4]" IOSTANDARD = LVCMOS18;
NET "funct7[3]" IOSTANDARD = LVCMOS18;
NET "funct7[2]" IOSTANDARD = LVCMOS18;
NET "funct7[1]" IOSTANDARD = LVCMOS18;
NET "funct7[0]" IOSTANDARD = LVCMOS18;
NET "opcode[6]" IOSTANDARD = LVCMOS18;
NET "opcode[5]" IOSTANDARD = LVCMOS18;
NET "opcode[4]" IOSTANDARD = LVCMOS18;
NET "opcode[3]" IOSTANDARD = LVCMOS18;
NET "opcode[2]" IOSTANDARD = LVCMOS18;
NET "opcode[1]" IOSTANDARD = LVCMOS18;
NET "opcode[0]" IOSTANDARD = LVCMOS18;
NET "rd[4]" IOSTANDARD = LVCMOS18;
NET "rd[3]" IOSTANDARD = LVCMOS18;
NET "rd[2]" IOSTANDARD = LVCMOS18;
NET "rd[1]" IOSTANDARD = LVCMOS18;
NET "rd[0]" IOSTANDARD = LVCMOS18;
NET "rs1[4]" IOSTANDARD = LVCMOS18;
NET "rs1[3]" IOSTANDARD = LVCMOS18;
NET "rs1[2]" IOSTANDARD = LVCMOS18;
NET "rs1[1]" IOSTANDARD = LVCMOS18;
NET "rs1[0]" IOSTANDARD = LVCMOS18;
NET "rs2[4]" IOSTANDARD = LVCMOS18;
NET "rs2[3]" IOSTANDARD = LVCMOS18;
NET "rs2[2]" IOSTANDARD = LVCMOS18;
NET "rs2[1]" IOSTANDARD = LVCMOS18;
NET "rs2[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 "clk_im" IOSTANDARD = LVCMOS18;
NET "clk_n" IOSTANDARD = LVCMOS18;
NET "clk_25M" IOSTANDARD = LVCMOS18;
NET "Ir_Write" IOSTANDARD = LVCMOS18;
NET "PC_Write" IOSTANDARD = LVCMOS18;


NET "clk_25M" LOC = H4;
NET "clk_im" LOC = R4;
NET "clk_n" LOC = AA4;
NET "Ir_Write" LOC = T3;
NET "PC_Write" LOC = U3;


NET "clk_25M" PULLDOWN;
NET "clk_im" PULLDOWN;
NET "Ir_Write" PULLDOWN;
NET "clk_n" PULLDOWN;
NET "PC_Write" PULLDOWN;

#PlanAhead Generated physical constraints 

NET "opcode[0]" LOC = J4;
NET "opcode[1]" LOC = L4;
NET "opcode[2]" LOC = N4;
NET "opcode[3]" LOC = H3;
NET "opcode[4]" LOC = K3;
NET "opcode[5]" LOC = M3;
NET "opcode[6]" LOC = N3;
NET "rd[0]" LOC = B2;
NET "rd[1]" LOC = B1;
NET "rd[2]" LOC = D1;
NET "rd[3]" LOC = E2;
NET "rd[4]" LOC = F1;
NET "funct3[0]" LOC = G2;
NET "funct3[1]" LOC = H2;
NET "funct3[2]" LOC = J1;
NET "rs1[0]" LOC = K1;
NET "rs1[1]" LOC = G4;
NET "rs1[3]" LOC = G3;
NET "rs1[4]" LOC = L3;
NET "rs1[2]" LOC = K4;
NET "rs2[0]" LOC = A1;
NET "rs2[1]" LOC = D2;
NET "rs2[2]" LOC = E1;
NET "rs2[3]" LOC = G1;
NET "rs2[4]" LOC = J2;
NET "funct7[0]" LOC = L1;
NET "funct7[1]" LOC = M2;
NET "funct7[2]" LOC = M1;
NET "funct7[3]" LOC = N2;
NET "funct7[4]" LOC = P1;
NET "funct7[5]" LOC = P2;
NET "funct7[6]" LOC = R1;

六、思考与探索

1、 实验结果记录:

(实验操作的过程及结果记录)
实验6实验结果记录表
PC IR COE文件中指令代码 汇编指令 立即数imm32 解析字段是否正确
00000000 000002b3 000002b3 add 00000000 对
00000004 00000333 00000333 add 00000000 对
00000008 00a00393 00a00393 li 0000000A 对
000000C 04032e03 04032e03 lw 00000040 对
00000010 01c282b3 01c282b3 add 00000000 对
00000014 00430313 00430313 addi 00000004 对

2、 实验结论:

(分析实验结果,给出实验结论)
实验符合要求

3、 问题与解决方案:

(整个实验过程中发生了什么问题?你是如何解决的。)
问题存在但已经解决

4、 思考题:

a) 先读的是0号单元的数据,因为是先取数据再PC+4

b) 可以

c) 可能出现抖动,所以需要按的更慢点

d) 学习了很多,获得了很多

  • 11
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
RISC-V是一种基于开源架构的指令集,其指令集架构简单、规范且可扩展,非常适合教育和研究领域。在RISC-V中,指令译码是非常重要的一步,其作用是将指令从二进制形式翻译成计算机能够理解的操作。 这里简单介绍一下RISC-V指令译码器设计实验的流程: 1. 首先,根据RISC-V指令集规范,确定需要支持的指令类型和指令格式。RISC-V指令集中包含了常见的指令类型,如算术指令、逻辑指令、分支指令等,每种指令类型都有其特定的操作码和寄存器操作数等信息。 2. 在确定了需要支持的指令类型和指令格式后,可以开始设计译码器。译码器的主要功能是将二进制形式的指令转换为相应的操作,并将操作所需的寄存器地址等信息提取出来。在RISC-V指令集中,每个指令类型都有其特定的操作码,因此可以通过解析操作码来确定指令类型,并根据指令类型提取操作所需的寄存器地址等信息。 3. 接下来,可以开始进行译码器的Verilog设计。在设计过程中,需要考虑各种指令类型的特点和译码器的逻辑结构,以确保译码器能够正确地解析每一个指令。此外,还需要根据实际情况添加一些特殊的功能,如异常处理、中断处理等。 4. 设计完成后,需要进行仿真测试和验证。使用Verilog仿真工具对译码器进行功能测试,检查其是否能够正确地解析所有支持的指令,并且能够正确地提取操作所需的寄存器地址等信息。如果存在问题,需要进行调试和修改,直到译码器能够正确地工作为止。 5. 最后,将译码器集成到RISC-V处理器中,并进行系统级测试和验证。在测试过程中,需要使用各种测试程序和工具来验证处理器的性能和可靠性,以确保其能够满足实际应用的需求。 总之,RISC-V指令译码器设计是一个非常重要的实验,可以帮助学生深入了解计算机体系结构和指令集架构的相关知识,同时也可以提高学生的设计和实现能力。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值