【读书笔记】RISC存储程序机的电路设计(3)

简介: 【读书笔记】RISC存储程序机的电路设计(3)

前言

想写的东西太多,所以就拆成几份了,哈哈哈哈,完整目录:

 

【读书笔记】RISC存储程序机的电路设计(1)

【读书笔记】RISC存储程序机的电路设计(2)

【读书笔记】RISC存储程序机的电路设计(3)

【读书笔记】RISC存储程序机的电路设计(4)

【读书笔记】RISC存储程序机的电路设计(5)

【读书笔记】RISC存储程序机的电路设计(6)

 

实际上就是多水几篇好啦,毕竟这么长使劲没写了~~~~~又水了4行!

前面呢把Processor、Controller和Memory总体概述了下,要继续展开Controller呢,就必须要先把指令集看一下。

当然了,开始前还是把结构图放下:

指令集

RSIC处理器由mem中的指令序列控制运转,因此整体设计(主要是Controller的设计)是和指令集紧密联系的;

该处理器支持短指令和长指令两种,短指令为8bit,长指令为16bit;

短指令的格式为:

操作标志 源src 目的dst
0 0 1 0 0 1 1 1

 

长指令的格式为:

操作标志 源src 目的dst
0 1 1 0 0 0 1 0
地址
0 0 1 1 0 0 1 0

 

操作码

指令包括如下:

指令 操作码 操作 示意
NOP 0000 不进行任何操作
ADD 0001 源和目的寄存器中的值相加,存入目的寄存器 dst = src + dst
AND 0011 源和目的按位取与,存入目的寄存器 dst = src & dst
NOT 0100 源寄存器内容取反,存入目的寄存器 dst = ~src
SUB 0010 目的减源寄存器后存入目的寄存器 dst = dst - src
RD 0101 从长指令第二字节指定的存储单元中取出操作数,写入到目的寄存器 dst = mem[addr]
WR 0110 将源寄存器值写入到指定存储单元 mem[addr] = src
BR 0111 将第二字节指定地址中的内容写入PC,实现指令跳转 PC = mem[addr]
BRZ 1000 当zero_flag有效时,将第二字节指定地址中的内容写入PC,实现指令跳转 PC = mem[addr]
HALT 1111 停止执行,直到复位

 

指令是如何被处理的呢?

当外部复位有效后,PC归零开始读取mem中的第一条指令。如果为短指令,那么指令被读入IR同时PC自加1。IR中的指令确定了ALU进行什么操作以及通路如何传递信息。

而长指令需要再多一拍来读取第二个8bit信息,两拍读取到完整指令后才能确定最后如何处理数据。

说起来还是比较乱的,不如我们用例子一个指令一个指令的来看。

指令解析

指令解析的过程就是Controller的编码过程,对于每一个指令,Controller需要将其拆解为具体的电路行为,不妨称之为微指令吧。

ADD/SUB/AND

1.在复位后电路必须是处于idle状态的,那么定义一个状态为S_idle,当处于S_idle时直接默认跳转到下一个状态S_fet1即可;

2.处于S_fet1时,我们需要去取指了,那么需要如何操作呢?

  • Sel_PC:Mux_1选择当前PC的输出到Bus_1总线,这个值就是我们要取得指令的地址;
  • Sel_Bus_1:Mux_2选择Bus_1,也就是说把PC值加载到Bus_2上来了;
  • Load_Add_R:把Bus_2总线上的数据写入到Add_R寄存器中,时序逻辑当拍拉高,下拍完成写入;

OK,在S_fet1中完成了把PC的值写入到了Add_R这一操作,那么下一个状态自然就时根据这一地址把内容从mem中读出来到IR了,因此默认进入S_fet2;

3.S_fet2状态下,目的是将mem中的内容读出,注意处于S_fet2时,mem的地址线已经稳定为Add_R的值了也就是PC所指定的地址,那么只需要把此时mem的值加载到Bus_2总线上就可以了;

  • Sel_mem:Bus_2选择mem的输出数据,即把mem[Add_R]值加载到Bus_2总线上;
  • Load_IR:将Bus_2上的值写入到IR内,实现了取值的功能;
  • Inc_PC:取值完成了,PC先自加1,无论是长指令还是短指令,下一个要取的位置都在下一个Byte,除非解析出了跳转,那就一会跳一下好了;

取值第一个Byte后,肯定要进行译码操作,即使这是一个长指令那也需要译码才能知道;

4.S_dec状态下进行译码,此时IR内的指令已经稳定,opcode = IR.data_out[8 -1:4]为操作码,假设现在确认了操作码为ADD,那么需要进行一下操作:

  • Sel_R0/1/2/3:根据IR.data_out[4 -1:2]获取源寄存器标志,把对应的通用寄存器加载到Bus_1总线上;
  • Sel_Bus_1:将Bus_1总线的值加载到Bus_2总线上,只有到了Bus_2总线才能加载到Processor内的其他模块上;
  • Load_Reg_Y:将Bus_2总线的值加载到Reg_Y中,前面提到过,两个数相加减啥的,必须得先拿出来一个数放在Reg_Y中暂存下,下一拍再去拿另外一个数才行;

这三个操作同时开启后,Reg_Y上升沿就可以采到R0(或者R1/2/3)的值了,下一拍Reg_Y的值稳定,可以进行运算了,那么进入S_ex1状态;

5.S_ex1状态下,进行一下几个操作:

  • Sel_R0/1/2/3:根据IR.data_out[2 -1:0]获取目的寄存器标志,把对应的通用寄存器加载到Bus_1总线上;
  • ALU自动获取了Bus_1总线的值和Reg_Y的值以及操作符opcode = IR.data_out[8 -1:4],当拍即进行了加法操作,结果为ALU的输出值;
  • Sel_ALU:书上是没有这一操作的,但是显然不把ALU的值加载到Bus_2上,后面如何写入到dst寄存器中呢,因此我认为需要这一操作;
  • Load_R0/1/2/3:根据IR.data_out[2 -1:0],将Bus_2的数据写入到对应的目的寄存器中;
  • Load_Reg_Z:把ALU的另外一个输出zero_flag写入到Reg_Z中;

好的,完成了这一步实际上ADD指令的处理就完成了,那么下一步实际上就是跳转回S_fet1继续取下一个指令;

ADD/SUB/AND的操作实际上是一模一样的,都是需要S_fet1 -> S_fet2 -> S_dec -> S_ex1 -> S_fet1这样一个流程采完成取值-译码-执行的流程。

最后再把结构图放一下,梳理下数据流即可:


相关文章
|
存储
【读书笔记】RISC存储程序机的电路设计(1)
【读书笔记】RISC存储程序机的电路设计(1)
176 1
【读书笔记】RISC存储程序机的电路设计(1)
|
存储
【读书笔记】RISC存储程序机的电路设计(2)
【读书笔记】RISC存储程序机的电路设计(2)
186 0
【读书笔记】RISC存储程序机的电路设计(2)
|
存储 索引
【读书笔记】RISC存储程序机的电路设计(4)
【读书笔记】RISC存储程序机的电路设计(4)
201 0
【读书笔记】RISC存储程序机的电路设计(4)
|
存储 安全 C#
一起谈.NET技术,《Effective C#中文版:改善C#程序的50种方法》读书笔记
  从去年找工作以来,都没什么时间写博客[找工作的体会:建议以后有自己开公司的IT人一定要找IT专业人员做HR,好多公司的HR并不能真正发掘人才,他们形成了太多的偏见,如在学校期间学不了什么东西、只看学校有多少奖励等。
1175 0
|
存储 安全 C#
《Effective C#中文版:改善C#程序的50种方法》“.NET技术”读书笔记
  从去年找工作以来,都没什么时间写博客[找工作的体会:建议以后有自己开公司的IT人一定要找IT专业人员做HR,好多公司的HR并不能真正发掘人才,他们形成了太多的偏见,如在学校期间学不了什么东西、只看学校有多少奖励等。
1385 0
|
算法 UED
软件 = 程序 + 软件工程(构建之法读书笔记一)
  在我正式开始阅读这本书之前,我对于软件工程这个词汇的概念还是模糊的,认为它只是停留在是一门学科,一个专业,或者是一大堆硬生生的理论知识,然而当我读完构建之法这本书的推荐序和第一,第二版前言开始,我就深刻意识到我之前对于软件工程的肤浅认识是多么错误。
1009 0
|
C语言 编译器 程序员
以C语言为例的程序性能优化 --《深入理解计算机系统》第五章读书笔记
  其实大多数的编译器本身就能提供一些简单的优化,比如gcc就能通过使用 -O2 或者 -O3 的选项来优化程序。但编译器的优化始终也是有限,因为它必须小心翼翼保证优化过程不对程序的功能有改动。故而程序员本身应该对程序有优化意识。
1167 0
|
数据库 C#
【读书笔记】用反射+抽象工程模式实现多数据库的访问程序
  今天在上传代码的同时试着写点东西,请大家指教,哈!反射简单说起来就是 Assembly.Load(" 程序集名称").CreateInstance("命名空间.类名称")获取一个“类名称"的对象(使用时添加using System.Reflection命名空间)。
734 0
|
存储 安全 编译器
[笔记]读书笔记 C++设计新思维《一》基于策略的类设计(下)
[笔记]读书笔记 C++设计新思维《一》基于策略的类设计(下)