0 实验要求

实验整体框架已给出,任务主要包括:

  • 数据窗口的添加(可选,我添加了)
  • 立即数生成错误修改(老师主动设置错误,修改见代码)
  • 三端口寄存器模块的添加(这与此前的三端口略有不同,注意重点查看RegisterFile模块的实现)

1 源代码

`default_nettype none
// --------------------------------------------------------------------
// 单周期 RISC-V CPU 模块
// --------------------------------------------------------------------
module CPU#(parameter DATAWIDTH = 32,parameter ADDRWIDTH = 32)
(input  wire iCPU_Reset,input  wire iCPU_Clk,// 指令存储器接口output wire [ADDRWIDTH-1:0] oIM_Addr,   //指令存储器地址input  wire [DATAWIDTH-1:0] iIM_Data,   //指令存储器数据// 数据存储器接口input  wire [DATAWIDTH-1:0] iReadData,  //数据存储器读数据output wire [DATAWIDTH-1:0] oWriteData, //数据存储器写数据output wire [ADDRWIDTH-1:0] oAB,        //数据存储器地址output wire oWR,                        //数据存储器写使能// 连接调试器的信号output wire [ADDRWIDTH-1:0] oCurrent_PC,output wire oFetch,input  wire iScanClk,input  wire iScanIn,output wire oScanOut,input  wire [1:0] iScanCtrl
);/** The input port is replaced with an internal signal **/wire   clk   = iCPU_Clk;wire   reset = iCPU_Reset;// Instruction partslogic [31:0] pc, nextPC;logic [31:0] instruction; // instruction codeassign nextPC = pc + 4;   /*-TODO 目前仅支持PC+4,增加分支指令时需修改 -*/// PCDataReg #(32) pcreg(.iD(nextPC), .oQ(pc), .Clk(clk), .Reset(reset), .Load(1'b1));assign oIM_Addr = pc;         // 连接指令存储器的地址端口assign instruction = iIM_Data;// 连接指令存储器的数据端口// Instruction decodelogic [6:0] opcode;logic [2:0] funct3;logic [6:0] funct7;logic [4:0] ra1,ra2,wa;assign funct7 = instruction[31:25];assign ra2    = instruction[24:20];assign ra1    = instruction[19:15]; assign funct3 = instruction[14:12];assign wa     = instruction[11:7];assign opcode = instruction[6:0];// Control unitlogic cRegWrite;logic [4:0] cImm_type;  //{J,U,B,S,I}Controller controller(.iOpcode(opcode),.iFunct3(funct3),/*-TODO 随着指令的增加,相应添加端口信号 -*/.oRegWrite(cRegWrite),.oImm_type(cImm_type));// Immediate data generation logic [31:0] immData;ImmGen  immGen(.iInstruction(instruction[31:7]), .iImm_type(cImm_type), .oImmediate(immData));// Register filelogic [31:0] regWriteData, regReadData1, regReadData2;RegisterFile #(32) regFile(.Clk(clk), .iWE(cRegWrite), .iWA(wa), .iWD(regWriteData), .iRA1(ra1), .oRD1(regReadData1),.iRA2(ra2), .oRD2(regReadData2));assign regWriteData = aluOut; /*-目前仅支持将ALU运算结果写入寄存器堆,TODO:增加Load类指令时需修改 -*/// ALUlogic [31:0] aluOut;assign aluOut = regReadData1 + immData; /*-目前仅支持加立即数运算,TODO:需用自己设计的ALU模块代替 -*//*-TODO 连接数据存储器 -*///---------------------- 送给调试器的变量 ------------------------////送给调试器的观察信号,需要与虚拟面板的信号框相对应struct packed{/*-TODO 在这里添加观察信号的类型 -*/logic RegWrite;               //对应虚拟元件WS1logic [4:0] ImmType;          //对应虚拟元件WS0}ws; always_comb begin/*-【注意】添加观察信号类型后须关联相应变量!-*/ws.RegWrite = cRegWrite;      //对应虚拟元件WS1ws.ImmType = cImm_type;       //对应虚拟元件WS0end        //送给调试器的观察变量,需要与虚拟面板的数据框相对应struct packed{/*-TODO 在这里添加观察数据的类型 -*/    logic [11:0] imm12;    logic [31:0] aluOut;       //对应虚拟元件WD8logic [31:0] immData;      //对应虚拟元件WD7logic [31:0] regReadData1; //对应虚拟元件WD6logic [4:0]  ra2;          //对应虚拟元件WD5,5位logic [4:0]  ra1;          //对应虚拟元件WD4,5位logic [4:0]  wa;           //对应虚拟元件WD3,5位logic [31:0] instruction;  //对应虚拟元件WD2        logic [31:0] pc;           //对应虚拟元件WD1logic [31:0] nextPC;       //对应虚拟元件WD0}wd;always_comb begin/*-【注意】添加观察数据类型后须关联相应变量!-*/  wd.imm12        = instruction[31:20];      wd.aluOut       = aluOut;       //对应虚拟元件WD8wd.immData      = immData;      //对应虚拟元件WD7wd.regReadData1 = regReadData1; //对应虚拟元件WD6wd.ra2          = ra2;          //对应虚拟元件WD5,5位wd.ra1          = ra1;          //对应虚拟元件WD4,5位wd.wa           = wa;           //对应虚拟元件WD3,5位wd.instruction  = instruction;  //对应虚拟元件WD2wd.pc           = pc;           //对应虚拟元件WD1wd.nextPC       = nextPC;       //对应虚拟元件WD0 end// 调试器部分,请勿修改!WatchChain #(.DATAWIDTH($bits(ws)+$bits(wd))) WatchChain_inst(.DataIn({ws,wd}), .ScanIn(iScanIn), .ScanOut(oScanOut), .ShiftDR(iScanCtrl[1]), .CaptureDR(iScanCtrl[0]), .TCK(iScanClk));assign oCurrent_PC = pc;assign oFetch = 1'b1;endmodule// --------------------------------------------------------------------
// Controller模块
// --------------------------------------------------------------------
module Controller(input  logic [6:0] iOpcode,input  logic [2:0] iFunct3,/*- TODO:扩充指令时在这里增加端口 -*/output logic oRegWrite,   output logic [4:0] oImm_type   //对应五种类型:{J,U,B,S,I}
);always_comb begin/*- TODO:扩充指令时需修改 ...... -*/if (iOpcode==7'b0010011 && iFunct3==3'b000) beginoImm_type = 5'b00001;oRegWrite = 1'b1;endelse beginoImm_type = 5'b00000;oRegWrite = 1'b0;    end
end
endmodule// --------------------------------------------------------------------
// 立即数生成模块
// --------------------------------------------------------------------
module ImmGen( //立即数生成input  logic [4:0]  iImm_type,   //{J,U,B,S,I}input  logic [31:7] iInstruction,output logic [31:0] oImmediate
);
/*- TODO:增加其他类型的立即数需修改。目前只有I型,所以并未区分Imm_type -*/
assign oImmediate = {{20{iInstruction[31]}}, iInstruction[31:20]};
/*- 符号扩展为32位立即数。【注意】上面的代码注入了一个错误,这里已修改
原始错误:assign oImmediate = {{20{iInstruction[31]}}, iInstruction[30:20]}; -*/endmodule// --------------------------------------------------------------------
// 三端口寄存器堆模块
// --------------------------------------------------------------------
module RegisterFile#(parameter DATAWIDTH = 32,parameter ADDRWIDTH = 5)
(input  logic  Clk,input  logic  iWE,input  logic  [4:0] iWA, iRA1, iRA2,input  logic  [31:0] iWD,output logic  [31:0] oRD1, oRD2
);
/*- TODO:...  -*/
localparam MEMDEPTH = 1<<ADDRWIDTH;
logic [DATAWIDTH-1:0] mem[0:MEMDEPTH-1];always_ff @(posedge Clk)
begin if(iWE)if(iWA!={ADDRWIDTH{1'b0}})mem[iWA] <= iWD;
endassign oRD1 = mem[iRA1];
assign oRD2 = mem[iRA2];
endmodule// --------------------------------------------------------------------
// DataReg模块
// --------------------------------------------------------------------
module DataReg
#(parameter N = 4)
(   output reg [N-1:0] oQ,input wire [N-1:0] iD,input wire Clk,input wire Load,input wire Reset
);
always @(posedge Clk or posedge Reset)
beginif (Reset)oQ <= 0; else if (Load)oQ <= iD;
end
endmodule

2 添加数据窗口

代码中我加了数据观察窗口

所以验证前把这个数据窗口加了,不添加会影响后续指令类型判断

3 运行测试

将编译后的rbf文件上传至远程FPGA,接着输入测试指令

点击复位按钮,可看到当前第一条指令06400293(addi x5,x0,100)执行状态

此时,从RD1从RA1端口00即x0寄存器(默认为0)读出值00000000,立即数为instruction[31:20] 0000_0110_0100即064h,扩展为32位对应00000064,相加结果为00000000+00000064=00000064

然后,将运算结果00000064传到WD,并写入寄存器地址wa 00101即WA端口显示的x5寄存器

控制器模块(见下图)根据opcode和funct3判断指令类型(JUBSI)是I型指令,显示00001

接着,点击微单步,执行下一条指令FFF28313(addi  x6,x5,-1),可以发现RD1是从RA1显示的x5寄存器读值00000064(上一条指令已写入),立即数为-1,补码显示FFFFFFFF,运算结果为00000063,并把结果写入WA显示的x6寄存器

具体各端口值得分析可以参照第一条指令分析过程,将指令写成32位进行分析

再次微单步执行下一条指令00030393(addi x7,x6,0),执行状态如下

具体各端口值得分析可以参照第一条指令分析过程,将指令写成32位进行分析

整个运行记录如下:

最后,后面的实验你该尝试尽量自己分析解决了

RISC-V:实现ADDI指令相关推荐

  1. 计组学习笔记2(RISC v版)

    指令集解释 (规定:R[r]表示通用寄存器r的内容,M[addr]表示存储单元addr的内容,SEXT[imm]表示对imm进行符号扩展,ZEXT[imm]表示对imm进行零扩展) 整数运算类 -U型 ...

  2. RISC V (RV32+RV64) 架构 整体介绍

    文章目录 riscv 市场 芯片介绍 软件介绍 开发板介绍 PC介绍 riscv 架构 编程模型(指令集/寄存器/ABI/SBI) 运行状态 指令集 寄存器 riscv32和riscv64两者的区别 ...

  3. 安装Ubuntu RISC V toolchain失败(网速、git配置原因)

    git获取大容量工程出错:RPC failed: curl GnuTLS recv error : Decryption has failed. error: RPC failed; curl 56 ...

  4. MIPS指令集处理器设计(支持64条汇编指令)

    一.题目背景和意义 二.国内外研究现状 (略) 三.MIPS指令集处理器设计与实现 (一).MIPS指令集功能性梳理 1.MIPS指令集架构 (1).mips基础指令集格式总结 MIPS是(Micro ...

  5. RISC-V 指令学习笔记(基于CH32V103)

    文章目录 RISC-V 指令学习笔记(基于CH32V103) 一.指令结构分类 二.寄存器功能 三.加载存储指令 四.算数运算指令 五.移位指令 六.逻辑操作指令 七.跳转指令 7.1 条件跳转 7. ...

  6. verilog实现多周期处理器之——(六)简单算数操作指令的实现

    实现的指令说明 这里解释有符号扩展与无符号扩展,有符号数扩展符号位.也就是1,无符号数扩展0.也就是在前面补满零或1 R-型指令 加减比较指令 add.addu.sub.sub.slt.sltu 这6 ...

  7. 从零开始的RISCV架构CPU设计(2)-CISC与RISC

    系列文章目录 上一节:从零开始的RISCV架构CPU设计(1)-CPU开源资料说明 文章目录 系列文章目录 前言 一.什么是CISC 二.什么是RISC 三.CISC与RISC 3.1 指令集实现架构 ...

  8. 【计组复习(二)指令】

    考点概述:1.指令设计原则:2.RISC.CISC:3.寻址方式(重点):4.子函数调用:5.链接. 存储程序概念:多种类型的指令和数据均以数字形式存储于存储器中. 硬件设计四条基本原则 1.简单源于 ...

  9. 体系结构实验(3)—— 指令流水的分析

    文章目录 Chp3 Lab: Analysis of Instruction Execution Pipelining a. b. c. Chp3 Lab: Analysis of Instructi ...

最新文章

  1. Tensorflow快餐教程(8) - 深度学习简史
  2. 创建带有关联的 XML 架构的 XML 文件 从 XML 文件创建 XML 架构
  3. wiki维基百科上logo中字母的意思是什么?
  4. Solaris RAID 换盘/替换坏盘
  5. 深入sql server中的事务
  6. 运用贪心思想解决跳跃游戏
  7. python argparse模块详解_python中argparse模块用法实例详解
  8. dst发育筛查有意义吗_岱岳区妇幼保健院眼耳鼻喉科成功引进双目视力筛查仪
  9. oracle里的or 短路么,Oracle CASE短路不能分组工作
  10. 数据结构(C语言版)
  11. PHP字符串函数ucfirst( 将字符串的首字母转换为大写)
  12. 手机浏览器查看控制台
  13. linux远程连接命令
  14. 打工人息息相关的个税计算
  15. UE4 Sequence学习
  16. 分布式数据库同步系统之Otter
  17. DSRC通信协议标准
  18. java素数对算法_Java版本 质数(也叫素数)算法
  19. HCIE证书真的有用吗?
  20. 如何把计算机颜色调正常,怎样调电脑屏幕亮度和颜色,电脑屏幕颜色调回正常...

热门文章

  1. 7-14 电话聊天狂人 (25分) 【map】
  2. 女人最该记得的100本书的100句话
  3. Google 真的抄百度了吗?
  4. ubuntu不小心忘记开机密码
  5. kafka完整集群安装
  6. AndroidStudio检测不到模拟器的解决方案(百试不爽)
  7. 地方门户类网站建设解决方案
  8. 语音识别发展史与入门书籍简介
  9. java编程官方教程_Java编程入门官方教程
  10. 行为瘫痪(paralysis)、心流和可能的自我