单周期RISC-V架构CPU的设计---设计篇

2023-11-13

一、模块设计

本设计采用《计算机组成与设计硬件软件接口risc-v版》中的架构,如下图所示,这是典型的哈佛结构,即指令和数据分开存储,分别放在instr_mem和data_mem中,因为我要考虑后期流水线分解,在信号数据传输过程中按流水线进行设计(但这里还没加入流水线寄存器),以便于后续分解流水级。

该设计目前的版本为CPU_lv0,32位RISC-V架构CPU,实现了RV32I中的37条指令,包含R型、I型、S型、B型、U型、J型,其中就包含了运算指令、跳转指令、立即数扩展指令、访存指令,目前所有指令都已仿真调试通过,具体仿真调试过程参考后续。

目前初代版本的端口命名还不是特别规范,有点混乱,后续会陆续进行调整。。。

该设计一共有9个源文件,每部分作用汇总如下:

源文件

功能作用解释

pc_reg.v

程序计数器的决断模块,决定下一条指令的pc是多少

id.v

译码模块,将取出的指令进行译码,译码信息包含寄存器地址、控制信号、立即数等

reg_file.v

通用寄存器模块,包含了32个32位的通用寄存器,根据译码出的寄存器地址进行读写数据

alu.v

运算模块,执行运算指令的相关操作,加、减等

mem.v

访存模块,根据alu计算出的地址或者reg_file取出的数据进行读写操作

data_mem.v

数据存储器,在访存阶段配合完成读写

wb.v

回写模块,经alu计算出结果或者load数据之后,写回通用寄存器

cpu_lv0.v

顶层模块

define.v

宏定义文件

本人在设计过程中参考的资料如下:

预学习阶段:

【CO001】课程基本信息 计算机组成原理/计算机组成与设计_哔哩哔哩_bilibili

设计学习阶段:

第0期 设计这个干嘛?| 绪论 | RISC-V设计入门指北_哔哩哔哩_bilibili

手把手教你设计RISC-V 处理器 第0期-蓄势待发_哔哩哔哩_bilibili

自行设计阶段:

从零开始写RISC-V处理器 | liangkangnan的博客

从零开始设计RISC-V处理器——单周期处理器的设计_设计并实现单周期处理器,支持包含risc-v rv32i整数指令(lw, sw,add,sub, o_不学无术的小胖子.的博客-CSDN博客

1、pc_reg.v

1.1、功能说明

PC寄存器,又名程序计数器(PC,Program counter),用于存放指令的地址,为了保证程序(在操作系统中理解为进程)能够连续地执行下去,CPU必须具有某些手段来确定下一条指令的地址。当执行一条指令时,首先需要根据PC中存放的指令地址,将指令由内存取到指令寄存器中,此过程称,为“取指令”。与此同时,PC中的地址或自动加4或由转移指针给出下一条指令的地址。此后经过分析指令,执行指令。完成第一条指令的执行,而后根据PC取出第二条指令的地址,如此循环,执行每一条指令。

1.2、整体框图

1.3、接口列表

端口定义如下

module pc_reg (
    input                           clk,
    input                           rst_n,
    
    input                           pcsrc,
    input       [31:0]              pc_i,
    //input       [31:0]              imm,  //imm
    //input       [31:0]              rs1_data,//jalr
    //input                           jump,
    //input                           jump_reg,
    
    output reg  [31:0]              instr,
    output reg  [31:0]              curr_pc
);

端口名称

类型

位宽

说明

clk

input

1

系统时钟输入

rst_n

input

1

系统低有效复位

pcsrc

input

1

pc值源的选择位

pc_i

input

32

经特殊指令跳转之后的pc值

instr

output

32

取出的指令

curr_pc

output

32

当前执行的指令pc值

其中pcsrc是选择位,以选择下一个pc值,为0时选择默认pc+4,为1时选择pc_i,按地址读出指令输出,同时pc也需要输出,因为有一部分指令需要对pc操作。

指令存储器一般为片外rom,需要挂在总线上,现在暂时用reg寄存器代替。

1.4、内部信号说明

端口名称

类型

位宽

说明

instr_mem

reg

32

指令寄存器,存放指令

1.5、关键电路

输出指令地址,地址发送给指令存储器,其中地址有个来源,正常顺序pc+4,pc跳转输入pc_i,由pc_src选择来源,pc_i在输入之前就已经经过pc运算操作了,涉及的指令包括B型指令、jal、jalr、auipc指令。

在作为地址去指令存储器中pc_i读数据时,要将低两位舍去,或者右移两位,原因是指令存储是按字存储,但字节寻址,一条指令4字节,去掉低两位,字节寻址变为子寻址,一次寻址一条指令。

2、id.v

2.1、功能说明

指令译码器(Instruction Decoder,ID) 是控制器中的主要部件之一。因为计算机能且只能执行“指令”,而一串二进制数字传输过来,cpu并不知道要做什么,ID就是告诉cpu要做哪些操作。指令由操作码、地址码、立即数和两个操作字段funct等组成。操作码(opcode)和funct表示要执行的操作性质,即执行什么操作;地址码是操作码执行时的操作对象的地址,立即数是操作的直接对象,操作之前需要对立即数进行相应的预处理及扩展。计算机执行一条指定的指令时,必须首先分析这条指令的操作码是什么,以决定操作的性质和方法,然后才能控制计算机其他各部件协同完成指令表达的功能。这个分析工作由指令译码器来完成。

2.2、整体框图

2.3、接口列表

端口名称

类型

位宽

说明

rst_n

input

1

系统低有效复位

pc_i

input

32

当前执行的指令pc值

instr_i

input

32

取出的指令

rs1_data_i

input

32

从32个通用寄存器中取出的rs1数据

rs2_data_i

input 

32

从32个通用寄存器中取出的rs2数据

pc_o

output

32

当前执行的指令pc值

rs1_addr_o

output

5

源寄存器rs1的取值地址

rs2_addr_o

output

5

源寄存器rs2的取值地址

rd_addr_o

output

5

目的寄存器地址

branch

output

1

控制信号,pc跳转指示信号

memread

output

1

控制信号,访存读使能

memtoreg

output

1

控制信号,写回数据来源选择位

regwrite

output

1

控制信号,通用寄存器(目的寄存器)写使能

memwrite

output

1

控制信号,访存写使能

alusrc

output

1

控制信号,运算源alu_src2操作数选择位(alu_src2)

aluop[1:0]

output

2

控制信号,运算类型选择

imm

output

32

预处理及扩展后的立即数

funct

output

4

功能码 {funct7[5],funct3},用于判断具体指令

opcode_o

output

7

7位操作码

2.4、内部信号说明

端口名称

类型

位宽

说明

opcode

wire

7

不赘述了,看下图。

rd

wire

5

funct3

wire

3

rs1

wire

5

rs2

wire

5

funct7

wire

7

2.5、关键电路

因为在数据通路中后续会使用到pc值,需要将pc也传递进来,然后将输入的指令解码之后得到的通用寄存器的地址,根据地址向寄存器堆reg_file读取数据,同时将写的rd地址传递到下一组合逻辑电路,在写回阶段用到此rd地址。

将7组控制信号输出到下一级进行相关控制,其中各种不同类型的控制信号赋值如下图所示:

信号

R

I

B

J

JR

U

UPC

IL

S

branch

0

0

1

1

1

0

0

0

0

memread

0

0

0

0

0

0

0

1

0

memtoreg

0

0

0

0

0

0

0

1

0

regwrite

1

1

0

1

1

1

1

1

0

memwrite

0

0

0

0

0

0

0

0

1

alusrc

0

1

0

0

0

0

0

1

1

aluop[1:0]

10

10

01

11

11

11

11

00

00

同时在以上各种类型指令中(除了R型指令之外的)生成imm,并扩展成32位,以供后续计算或pc值跳转。其中imm_gen是嵌入在整个模块内部,同控制信号一起生成。

3、alu.v

3.1、功能说明

在计算机系统中,ALU(Arithmetic Logic Unit)是 中央处理器 的主要组成部分,它代表算术逻辑单元,执行算术运算、逻辑运算、移位操作,也可执行地址运算和转换。 它也称为整数单元 (IU,integer unit),它是 CPU 或 GPU 内的逻辑电路,是处理器中执行计算的最后一个组件。其中还包括跳转指令条件判断。

3.2、整体框图

部分主要路径,总体逻辑以代码为准。

3.3、接口列表

端口名称

类型

位宽

说明

pc_i

input

32

当前执行的指令pc值

rs1_data_i

input

32

从32个通用寄存器中取出的rs1数据

rs2_data_i

input

32

从32个通用寄存器中取出的rs2数据

rd_addr_i

input

5

目的寄存器地址

funct

input 

4

功能码 {funct7[5],funct3},用于判断具体指令

imm

input

32

立即数

opcode

input

7

7位操作码

branch

input

1

控制信号,pc跳转指示信号

memread

input

1

控制信号,访存读使能

memtoreg

input 

1

控制信号,写回数据来源选择位

regwrite

input

1

控制信号,通用寄存器(目的寄存器)写使能

memwrite

input

1

控制信号,访存写使能

alusrc

input

1

控制信号,运算源alu_src2操作数选择位(alu_src2)

aluop[1:0]

input

2

控制信号,运算类型选择

branch_sign

output

1

跳转指令的指示信号(跳转条件判定后的标志位)

result

output

32

执行操作的运算结果

rd_addr_o

output

5

目的寄存器地址

branch_o

output

1

---

memread_o

output

1

---

memtoreg_o

output

1

---

regwrite_o

output

1

---

memwrite_o

output

1

---

pc_o

output

32

---

write_data

output

32

访存操作中需要写入的数据

align

output

4

访存指令的对齐指示信号

aluop_o

output

2

---

3.4、内部信号说明

端口名称

类型

位宽

说明

cond_beq

wire

1

beq、bne指令判断是否相等的条件

cond_bge

wire

32

bge、blt指令判断指令是否大于等于的条件(有符号)

cond_bgeu

wire

32

bgeu、bltu指令判断指令是否大于等于的条件(无符号)

alu_src1

wire

32

参与运算的源操作数1

alu_src2

wire

32

参与运算的源操作数2

mask

reg

32

用于执行逻辑右移操作的掩码

3.5、关键电路

前一译码模块的输入进来的除了上述主要的控制信号之外,运算源操作数有三类,rs1_data、rs2_data、imm,其中运算源操作数alusrc1=rs1_data,运算源操作数alu_src2是rs2_data与imm二选一,选择控制位由alusrc决定。

对于跳转类型指令,需要在满足跳转条件才会执行,故而设置了三个条件判断标志位cond_beq、cond_bge、cond_bgeu,当满足跳转指令的对应条件时跳转标志位branch_sign置1,才会触发跳转操作,这里的跳转指令条件就是对rs1_data和rs2_data不等判断或者大小判断。其中注意cond_bge是有符号位的大于等于条件判断位,需要对待判断源操作数调用函数 $signed(rs1_data_i) 。

在执行逻辑操作,逻辑右移时,使用逻辑右移符号>>>不管用,使用$signed(xxx)>>>,也不管用,故而设置一个掩码mask,通过将mask算数左移相应位,再将其与算术右移的结果按位或操作,就可以等效为逻辑右移,这里需要注意mask的具体赋值是怎样的。

如果是访存指令,store指令就需要直接将rs2_data输出到下一级模块写入数据存储器,load和store指令都要输出读写和写入的数据存储器地址给下一级。

4、mem.v

4.1、功能说明

访存指令load和store的访存模块。

4.2、整体框图

4.3、接口列表

端口名称

类型

位宽

说明

clk

input

1

系统时钟输入

rst_n

input

1

系统低有效复位

branch_i

input

1

控制信号,pc跳转指示信号

memread_i

input

1

控制信号,访存读使能

memtoreg_i

input 

1

控制信号,写回数据来源选择位

regwrite_i

input

1

控制信号,通用寄存器(目的寄存器)写使能

memwrite_i

input

1

控制信号,访存写使能

aluop_i

input

2

控制信号,运算类型选择

branch_sign

input

1

跳转指令的指示信号(跳转条件判定后的标志位)

result

input

32

执行操作的运算结果(这里就是访存的地址或者写回数据)

rd_addr_i

input

5

目的寄存器地址

pc_i

input

32

当前执行的指令pc值

write_data

input

32

访存操作中需要写入的数据

align

input

4

访存指令的对齐指示信号

rd_addr_o

output

5

目的寄存器地址

pc_o

output

32

当前执行的指令pc值

pcsrc

output

1

pc值源的选择位

read_data

output

32

从data_mem中读取的数据

rd_data

output

32

经运算得到的写回结果

memtoreg_o

output

1

---

regwrite_o

output

1

---

4.4、内部信号说明

端口名称

类型

位宽

说明

ram_data_o

wire

32

从data_mem中读出的数据

ram_data_i

reg

32

写入data_mem中的数据

4.5、关键电路

这个模块就简单了,根据访存指令的不同类型输出对应的读取数据,和输入对应的写入数据。

其中例化了data_mem数据存储器。

5、wb.v

这个模块更简单了,根据输入的控制信号,regwrite和memtoreg写回数据,按照rd_addr写回对应的通用寄存器。

写回数据有两个来源,数据存储器读出的数据read_data,通用寄存器读出的数据rs1_data+imm(write_data),memtoreg=0时选择write,1选择read_data。 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

单周期RISC-V架构CPU的设计---设计篇 的相关文章

  • 容器的docker-compose怎样写agent.jar配置

    在 Docker Compose 文件中配置 Java Agent 例如 agent jar 的方式与之前的环境变量类似 您可以使用 environment 字段来设置 Java 环境变量 包括 javaagent 参数来指定 Java A
  • 【C++】string使用

    文章目录 1 为什么要学习string类 2 标准库中的string类 2 1了解string类 2 2string类常用的接口 2 2 1 构造和析构相关 2 2 2 迭代器 2 2 3 容量相关 2 2 4 元素访问 元素遍历 元素访问

随机推荐

  • 生命在于学习——未授权访问漏洞

    声明 本篇文章只是用于记载学习笔记 学习交流 不可用作其他违规用途 一 简介 未授权访问可以理解为需要安全配置或权限认证的地址 授权页面存在缺陷 导致其他用户可以直接访问 从而引发重要权限可被操作 数据库 网站目录等敏感信息泄露 目前主要存
  • 静态对象(全局+局部+静态对象成员)

    所有的静态对象 全局对象都于静态存储区分配 关于全局对象 是在main 函数执行前就分配好了的 其实 在main 函数中的显示代码执行之前 会调用一个由编译器生成的 main 函数 而 main 函数会进行所有全局对象的的构造及初始化工作
  • C++ auto遍历无法直接修改map的数据

    对于std map 当使用for auto it myMap 这种范围循环形式时 实际上是使用了const迭代器进行遍历 这意味着你无法通过该迭代器直接修改std map中的值 范围循环使用的是容器的begin 和end 函数返回的迭代器
  • 【数据结构--链表】反转链表

    题目描述 代码实现 Definition for singly linked list struct ListNode int val struct ListNode next struct ListNode reverseList str
  • JavaScript如何调用摄像头

    如何使用浏览器调用摄像头 在JavaScript中使用浏览器调用摄像头会使用到以下方法 navigator getUserMedia video true audio false success error 参数1 是一个对象包含摄像头和麦
  • 二叉树的重构

    二叉树的重构是指给定二叉树的先序遍历 中序遍历 后序遍历中的任意两者 要求恢复二叉树的结构 其中 除非二叉树是真二叉树 即任一节点要么具有两个子节点 要么没有子节点 否则 必须要有中序遍历才能恢复二叉树的结构 先序遍历 中序遍历 后序遍历
  • 寒假培训——简单搜索

    A 捉迷藏1 dfs bfs简单搜索 题目 Title A 捉迷藏1 Time Limit 1s Description 王吉吉和袁坑坑在一个n m大小的房间里捉迷藏 王吉吉躲起来了 现在袁坑坑要去抓他 地图中 W 代表王吉吉 Y 代表袁坑
  • STM32速成笔记—DMA

    文章目录 一 什么是DMA 二 DMA有什么作用 三 STM32的DMA 3 1 DMA请求 3 2 DMA通道 3 3 仲裁器 四 DMA配置 4 1 DMA配置步骤 4 2 DMA结构体成员 五 DMA配置程序 5 1 ADC1初始化程
  • 4行代码计算9999的阶乘

    转载自 http blog csdn net liangbch article details 3230428 本文来源于csdn2001年的一个帖子 题目是有谁可以用四行代码求出1000000的阶乘 见 http topic csdn n
  • MySQL数据库增删改查及安全值守操作

    我在本篇文章中整理了一些MySQL数据库 表 字段的增删改查和安全值守操作的常用语句 以便同学们保存和快捷查询 详细如下 1 用户的查看 创建 删除 以username为Superman password为123123为例 用户的创建cre
  • python模拟登录京东网页

    目标网站 京东网首页登录 目标网址 https www jd com 任务要求 1 导入selenium库 并使用该库驱动Chrom浏览器 完成请求 2 驱动浏览器对象 找到登录按钮 点击 3 在新页面中选择账号登录 4 找到用户名和密码输
  • Ubuntu 安装 Mysql【详细步骤】

    文章目录 主要内容 安装并设置 mysql 安装 mysql 设置 mysql 首次登录数据库 配置远程访问 修改配置文件 mysql 授予权限 重启 mysql 测试远程访问 建立访问连接 workbench 访问 workbench 增
  • [Springboot+Logback]已定义日志路径但仍生成了LOG_PATH_IS_UNDEFIEND文件夹之解决办法

    目录 1 问题描述 2 分析过程 3 解决办法 4 其他 1 问题描述 自己写练习项目的时候 在application yml中定义了logging file path logging file path logs 也在logback sp
  • 松下GF9使用心得

    文章目录 规格参数 关键特征 USB接口充电功能 旋转显示屏 WiFi直连 4K拍摄和后对焦模式 快速指南 机身按键及功能 拍摄模式 屏显信息 拍摄时 回放时 菜单列表 拍摄菜单 动态影像菜单 自定义菜单 设置菜单 回放菜单 核心功能 拍摄
  • Python之struct简介

    一 struct简介 看到struct这么英文单词 大家应该并不陌生 因为c c 中就有struct 在那里struct叫做结构体 在Python中也使用struct 这充分说明了这个struct应该和c c 中的struct有很深的渊源
  • 保姆级教学——集群环境搭建及创建集群

    保姆级教学 集群环境搭建及创建集群 新建虚拟机 一些默认 加载镜像开启虚拟机 在安装位置选择自己目录 然后建立分区 首先添加 挂载点 类型标准分区 文件系统ext4 加载分区 期望给2G 类型标准分区 swap默认 然后剩下47G给 就可以
  • 发布本地Docker镜像到阿里云的Docker Hub

    发布本地Docker镜像到阿里云的Docker Hub 在使用Docker时 有时需要制作自己的Docker镜像 这些镜像可以保存到不同的Docker Hub中 包括Docker官方的和国内的一些Hub 比如阿里云 同时 也可以使用阿里云的
  • 排列组合相关公式讲解(Anm,Cnm等)

    两个性质 1 C n m C n n m 2 C n m C n 1 m C n 1 m 1 编程时可用此递推
  • Python最强学习知识点:面相对象基础语法

    面相对象基础语法 目标 dir 内置函数 定义简单的类 只包含方法 方法中的 self 参数 初始化方法 内置方法和属性 01 dir 内置函数 知道 在 Python 中 对象几乎是无所不在的 我们之前学习的 变量 数据 函数 都是对象
  • 单周期RISC-V架构CPU的设计---设计篇

    目录 一 模块设计 1 pc reg v 1 1 功能说明 1 2 整体框图 1 3 接口列表 1 4 内部信号说明 1 5 关键电路 2 id v 2 1 功能说明 2 2 整体框图 2 3 接口列表 2 4 内部信号说明 2 5 关键电