在开篇中我们对RISC-V及其SoC软核工程进行了简单介绍,现在来介绍取指模块:

tinyriscv这个SoC工程的内核cpu部分,采用经典的三级流水线结构进行设计,即大家所熟知的:取值—>译码—>执行三级流水线。

另外,在最后一个章节中会上传额外添加详细注释的工程代码,完全开源,如有需要可自行下载。

目录

0 RISC-V SoC注解系列文章目录

1. CPU结构解析

2. 取值结构注解

2.1 pc_reg.v(时序逻辑电路)

2.2. if_id.v(时序逻辑电路)

2.3 rom.v


0 RISC-V SoC注解系列文章目录

零、RISC-V SoC软核笔记详解——前言

一、RISC-V SoC内核注解——取指

二、RISC-V SoC内核注解——译码

三、RISC-V SoC内核注解——执行

四、RISC-V SoC内核注解——除法(试商法)

五、RISC-V SoC内核注解——中断

六、RISC-V SoC内核注解——通用寄存器

七、RISC-V SoC内核注解——总线

八、RISC-V SoC外设注解——GPIO

九、RISC-V SoC外设注解——SPI接口

十、RISC-V SoC外设注解——timer定时器

十一、RISC-V SoC外设注解——UART模块(终篇)

1. CPU结构解析

在注解工程中的“取指”代码之前,先回顾一下CPU执行指令的简略过程(以三级流水线为例):

CPU内部主要由:

  1. 寄存器(Register):多种寄存器各司其职,有程序计数器(即程序指针PC,Program Counter),用来记录要执行的指令的地址;指令寄存器,用来暂存指令内容;数据寄存器,一般为通用寄存器,用来保存指令执行过程中临时存放的寄存器操作数和中间(或最终)的操作结果。
  2. 控制单元(Control):以流水线的方式对指令进行取指,译码,执行,并且发出为完成每条指令所要执行的各个操作的控制信号。
  3. 算术逻辑运算单元(ALU,Arithmetic Logic Unit):用来执行定点或浮点算术运算操作、移位操作以及逻辑操作,也可执行地址运算和转换。

以上三部分组成。

那程序在CPU中是怎么执行的呢?程序执行过程中涉及到的组件在这个tinyriscv工程中是怎么对应的呢?

简化的CPU执行程序的过程如下:

        程序编译器编译后生成二进制指令码,烧写程序即烧写程序对应的二进制指令码,烧写程序到硬件系统中后,这些二进制指令码就保存在系统的硬盘中,当你打开一个程序的时候,就把对应的指令码+数据加载到了内存里,其中指令部分被随后加载到了CPU的缓存里面,然后CPU根据程序计数器,即程序指针PC指向的缓存地址,把存储的指令从缓存取到指令寄存器里面保存,这里是取指;你取过来的指令,是由操作码和地址码组成的,分别表示执行什么操作和对谁操作,但是这些指令需要控制单元里面的一个叫做译码器的东西来分析,分析这些取来的指令码到底是什么意思,然后根据分析出来的内容指定下一步的行动计划:去哪里找什么部件执行什么操作,这是译码。 随后数据寄存器把数据从内存里面加载到算术逻辑单元,进行运算,并把结果传回数据寄存器,这就是执行

以上就是三级流水线CPU的执行过程。在此过程中涉及到的组件与这个tinyriscv工程的对应关系如下:

        程序:嵌入式代码,如C代码;

        编译器:gnu工具链;

        硬件系统:嵌入此工程所编写的SoC软核的硬件平台,如FPGA;

        硬盘:可以是上述FPGA板卡的板载flash,烧写代码时,可以将程序烧写固化在flash中,这样板卡掉电后,程序还会存在于flash中,在下次上电后,可从flash中读取;

        内存:工程中对应rom.v外设,工程中提供的代码烧写方式是直接烧录在rom中的,板卡掉电后rom中的数据会丢失,需要重新烧写代码;

        缓存:此工程比较简洁,没有使用缓存结构,将代码烧写进内存rom中后,cpu内核直接与rom进行通信,从rom中取出指令码,省去了缓存这一层级;

        程序指针PC本质上是一个32bit的寄存器,用于存放指令的地址,在工程的pc_reg.v文件中定义为reg[`InstAddrBus] pc_o;

        指令寄存器:存放根据程序指针PC取出的32bit指令码,在工程中定义为inst_i;


2. 取值结构注解

回到tinyriscv工程中,首先看这个RISC-V内核的取指部分:涉及到pc_reg.v、if_id.v、rom.v等模块:

取指模块的整体框图如下所示:

取指模块的详细介绍如下:

2.1 pc_reg.v(时序逻辑电路)

主要功能为:对指令存储器的地址信号,进行复位、跳转、暂停、地址递增等操作,即是对指令的地址进行处理,用于产生PC寄存器的值,该值会被用作指令存储器的地址信号,用来从rom中读取指令内容;

pc_reg模块有3个主要输入,分别是:跳转标志jump_flag_i,跳转地址jump_addr_i,和流水线暂停标志hold_flag_i,这三个输入信号从crtl.v模块接入,还有1个由jtag调试模块接入的复位标志jtag_reset_flag_i,用于jtag下载调试。

1个输出信号pc_o,即输出指令的地址,输出给总线,通过总线将指令寄存器的地址信号送入ROM,之后可从ROM中,把具体的指令给if_id模块。

2.2. if_id.v(时序逻辑电路)

主要功能为:取指,并将从rom中读取的指令打一拍后送到译码模块,即将取指数据(三级流水的第一级)打一拍,送入下一级(译码)。

此处插播一条内容:为什么CPU内核运行,要有流水线操作,比如此处的三级流水(取指----译码----执行)?

答案播报(以下播报内容引用源代码作者的博客):

这与数字电路中的时序有关,用以下这个模型为例:

其中对时序影响最大的是上图中的组合逻辑电路。所以要避免时序问题,最简单的方法减小组合逻辑电路的延时。组合逻辑电路里的串联级数越多延时就越大,实在没办法减小串联级数时,可以采用流水线的方式将这些级数用触发器隔开。要设计处理器的话,流水线是绕不开的。当然你也可以抬杠说:”用状态机也可以实现处理器啊,不一定要用流水线。采用流水线设计方式,不但可以提高处理器的工作频率,还可以提高处理器的效率。但是流水线并不是越长越好,流水线越长要使用的资源就越多、面积就越大。在设计一款处理器之前,首先要确定好所设计的处理器要达到什么样的性能(或者说主频最高是多少),所使用的资源的上限是多少,功耗范围是多少。如果一味地追求性能而不考虑资源和功耗的话,那么所设计出来的处理器估计就只能用来玩玩,或者做做学术研究。tinyriscv采用的是三级流水线,即取指、译码和执行,设计的目标就是要对标ARM的Cortex-M3系列处理器。(播报结束)

输入信号:

  1. 指令内容inst_i,从rom.v中读取得地址,读取地址是组合逻辑;
  2. 指令地址inst_addr_i,从pc_reg.v模块接入,向下一级流水译,即码模块传递;
  3. 流水线暂停标志hold_flag_i,信号位宽为3bit,从ctrl.v模块传入,根据不同的暂停信号,选择是否暂停整条流水线;
  4. 外设中断输入信号int_flag_i,由time.v模块传入,用于定时器中断发生时,暂停主程序流水线,转而执行中断操作。

输出信号:

  1. 外设中断输入的输出信号int_flag_o, 如果复位或者暂停流水线信号无效,则外设(timer)中断输入信号int_flag_i被打一拍后送到clint.v模块(clint.v模块是中断管理模块,后续会讲到);
  2. 指令内容inst_o,如果复位或者暂停流水线信号无效,则将由rom输入的指令内容inst_i打一拍输出到id.v译码模块和clint.v模块;
  3. 指令地址inst_addr_o, 如果复位或者暂停流水线信号无效,则指令地址inst_addr_i被打一拍,输出到id.v译码模块和clint.v模块;

若流水线暂停信号hold_flag_i有效,需要冲刷流水线,则设置inst_i、inst_addr_i、int_flag_i为默认值(32'h00000001、32‘d0、8'h0),然后传递给下一级模块。

2.3 rom.v

要功能为:存储烧写的指令码,并根据PC寄存器的值向外输出指令码;

 reg[`MemBus] _rom[0:`RomNum - 1];

定义一个32*4096的二维数组,作为存储数据的空间。即存储32bit的指令码,最多可以存储4096条指令码,4096这个维度即指令码对应的地址。

在数据存入和读出的过程中:

    always @ (posedge clk) beginif (we_i == `WriteEnable) begin_rom[addr_i[31:2]] <= data_i;endend

注意到_rom的地址索引为addr_i[31:2]即指令地址addr_i的高30位,这是为什么呢?

在计算机体系结构中,一个字节可以存储8bit数据,而内存空间映射的地址,一个地址对应一个8bit数据,即一个字节的数据;一条32bit的指令码,由4个字节组成,在内存空间中占用4个地址,这也是为什么在pc_reg.v模块中,pc的值每次累加4'h4的原因:

else beginpc_o <= pc_o + 4'h4;end

但是在rom中,定义的_rom存储空间是32*4096的,4096这个维度是32bit指令码的索引,即地址,结构如下:

_rom中一个地址对应的是32bit数据,所以实际映射地址的4个地址的数据(4*8bit)对应_rom数组存储结构中1个地址的数据(32bit),但是_rom中的数据又是紧凑存储的,而pc程序指针数值上是以4为间隔递增,即pc值的低2位pc[1:0]是以4为周期变化,不能直接作为rom的索引地址,而pc[1:0]由0加4,对应32bit数据,pc[31:2]也递增1表示,与_rom索引变化一致,所以使用pc地址的高30位作为rom的指令索引地址。

另外,在实际移植到FPGA的过程中,需要注意所用FPGA芯片的资源容量,适当的调整这个二维数组的大小。

一、RISC-V SoC内核——取指 代码讲解相关推荐

  1. 五、RISC-V SoC内核——中断 代码讲解

    tinyriscv这个SoC工程的内核cpu部分,采用经典的三级流水线结构进行设计,即大家所熟知的:取值->译码->执行三级流水线. 另外,在最后一个章节中会上传额外添加详细注释的工程代码 ...

  2. 七、RISC-V SoC内核——总线 代码讲解

    上一篇博文中注释了通用寄存器reg.v模块,现在来介绍总线模块rib.v: 另外,在最后一个章节中会上传额外添加详细注释的工程代码,完全开源,如有需要可自行下载. (这个RIB总线协议为工程原作者自定 ...

  3. 二、RISC-V SoC内核注解——译码 代码讲解

    tinyriscv这个SoC工程的内核cpu部分,采用经典的三级流水线结构进行设计,即大家所熟知的:取值->译码->执行三级流水线. 另外,在最后一个章节中会上传额外添加详细注释的工程代码 ...

  4. 十、RISC-V SoC外设——timer定时器 代码讲解

    上一篇博文中注释了SPI外设模块,现在来介绍timer定时器模块. 另外,在最后一个章节中会上传额外添加详细注释的工程代码,完全开源,如有需要可自行下载. 目录 0 RISC-V SoC注解系列文章目 ...

  5. 零、RISC-V SoC软核代码笔记详解——前言

    目录 0 RISC-V SoC注解系列文章目录 1 前言(手绘RISC-V SoC内核RTL试图): 2. 开源工程tinyriscv使用教程: 3. 开源工程tinyriscv下载地址: 4. 开源 ...

  6. tx2 fpga pcie无法读写_Cyclone V SOC(ARM+FPGA)开发文档_之开发流程详解

    双击可查看大图(手动狗头) 目录 Altera Cyclone V soc开发文档 之软硬件开发 1 Cyclone V开发流程介绍 5 专业术语 5 Cyclone V软件开发介绍 6 U-BOOT ...

  7. ubuntu arm qt_Cyclone V SOC(ARM+FPGA)开发文档_之开发流程详解

    双击可查看大图(手动狗头) 目录 Altera Cyclone V soc开发文档 之软硬件开发 1 Cyclone V开发流程介绍 5 专业术语 5 Cyclone V软件开发介绍 6 U-BOOT ...

  8. (2021) 18 [代码讲解] 可执行文件

    (2021) 18 [代码讲解] 可执行文件 南京大学操作系统课蒋炎岩老师网络课程笔记. 视频:https://www.bilibili.com/video/BV1HN41197Ko?p=18 讲义: ...

  9. 『HTML5实现人工智能』小游戏《井字棋》发布,据说IQ上200才能赢【算法代码讲解+资源打包下载】...

    一,什么是TicTacToe(井字棋) 本游戏为在下用lufylegend开发的第二款小游戏.此游戏是大家想必大家小时候都玩过,因为玩它很简单,只需要一张草稿纸和一只笔就能开始游戏,所以广受儿童欢迎. ...

最新文章

  1. 多核分布式队列的实现:“偷”与“自私”的运用(4)
  2. 用于HTTP加密浏览的TW2.0插件
  3. 【深度学习】腹部CT的肝脏肿瘤分割的探索
  4. 长期价值三重进阶,同程艺龙加速“破局”OTA
  5. SQL重复记录查询(转载)
  6. 软件工程--第三章--需求分析
  7. Docker~从Dockerfile到Container的过程
  8. 服务器网站链接ip限制,apache服务器对同一IP地址的连接限制
  9. 1*2*...*1000的末尾有多少个0?(Java实现)
  10. linux下的 lib文件的学习思考
  11. CSS基础——CSS 列表和表单【学习笔记】
  12. Report Builder:SRW包
  13. Android API 级别
  14. ffplay不能直播red5上的直播流问题解决
  15. 算法:Evaluate Reverse Polish Notation(逆波兰表达式求值)
  16. font-family 各字体一览表
  17. mac安装旺旺启动台找不到_如何正确安装和卸载Mac软件?
  18. 用c语言编程,统计大写字母,小写字母,数字,其他字符的个数,用C语言:输入一行字符,不超过50个,统计出其中英文大写字母,小写字母,数字,空格以及其他字符个数...
  19. RESTful理解与实践
  20. SAP 固定资产主数据

热门文章

  1. ECharts:echarts-wordcloud词云图
  2. Leetcode-SQL学习计划-SQL入门-584:寻找用户推荐人
  3. Google 和 Meta 正在接受欧盟和英国反垄断监管机构对”Jedi Blue”的调查
  4. OpenCV - 自动纠正图片的文字倾斜
  5. 游戏原画设计HTML5模板是一款适合网页游戏原画设计作品展示的HTML5网站模板。
  6. Python 的主要应用领域有哪些?
  7. 相遇周期 HDU - 1713
  8. 机器学习—— SVM分类垃圾短信
  9. 【React】二.JSX
  10. KWD-035-SNS-C2-H-1 R162232320标准钢质滚珠滑块