AI智能
改变未来

Parwan处理器架构简述

目录导航

  • 前言:
  • 写作目的:
  • 文章内容:
  • 开始之前:
  • 正文:
    • 1.Parwan处理器架构是什么?
    • 2.Parwan处理器架构的基本概况
    • 3.Parwan处理器架构的内存管理
    • 4.Parwan处理器架构的指令集
    • 5.Parwan处理器架构的内部结构
    • 6.Parwan处理器架构内部各器件的详解
    • 逻辑处理部分:
    • 内存管理部分:
    • 控制部分:
    • 总线部分:
  • 7.Parwan处理器架构部分指令执行过程的简要概述
    • 1.典型的取指令第一字节操作的概述
    • 2.取指令第二字节以Full Address形式的直接寻址法找到数据送到DBUS上的操作概述
    • 3.取指令第二字节以Full Address形式的间接寻址法找到数据送到DBUS上的操作概述
    • 4.将DBUS上的数据和AC中数据进行某操作并送到AC中的操作
    • 5.将AC中数据以Full Address形式的直接寻址法写回内存中的操作
    • 6.跳转至DBUS上的直接寻址形式地址的操作
    • 7.PC_OFFSET中偏移地址写到Page Address形式的直接寻址的子程序开头的操作
  • 8.Parwan处理器架构的控制状态机
    • S1:准备取数据(指令)
    • S2:取数据(指令)
    • S3:执行单字节指令(包含一部分的取值准备)
    • S4:双字节指令的初步执行
    • S5:间接寻址指令间接寻址过程的执行
    • S6:直接寻址指令的执行
    • S7:jsr指令前半部分的执行
    • S8:jsr指令的后半部分
    • S9:分支跳转指令的执行
  • 9.一些额外的提醒
  • 10.参考资料
  • 严禁未经本人允许的转载和引用到任何实验报告/大作业/论文/文章中。
    当然小段的合理的借鉴是可以的。

    前言:

    写作目的:

    这玩意很冷门?是的,就是很冷门。冷门到中文互联网上基本找不到有关资料,但是呢,西电人还是要用啊。
    在西安电子科技大学计算机科学与技术学院(我还是喜欢叫软件学院)的嵌入式方向必修课FPGA技术中,沈老师用了这种架构来作为教学工具,讲解了如何用HDL描述一个较为复杂的硬件结构。在最后完成大作业的时候,很多同学可能会遇到“找不到资料”,“PPT看不懂”等困难,我写这篇长文也算是造福后来的学弟学妹们吧。
    文章修改自我的大作业报告,删去了一些代码以及实验仿真部分。

    文章内容:

    这篇文章并不包括任何的代码,只是从较为顶层的角度简述了整个Parwan处理器是怎么运作的,并举了一些例子。
    当然,第九部分的图片会使用VHDL综合后的NGC网表图,因为我觉得这样能好理解一点。
    由于对MarkDown使用不熟练,很多表格都是在Word中绘制然后截图贴上的,请谅解。
    错别字可能很多。

    开始之前:

    开始之前,我假定您是一位合格的大三学生,这意味着您学过数字电路和基本的计算机组成原理。我希望您理解以下名词的大概含义:

    • D触发器
    • 总线
    • 内存
    • 内存页
    • 寻址方式
    • 指令集
    • ALU(算术逻辑单元)
    • 寄存器
    • PC(程序计数器)
    • 状态机

    大概理解就好,这些名词我也会在后文稍作简述。
    我们先简要回顾一下我们之前学习的内容,我们可能觉得“操作系统”已经够底层了,“写汇编”已经底层到不能再底层了。但是,我们某些时候可能需要关注更底层的东西,比如CPU内部的架构,指令流水线,分支推测,内存设计或者某个Port的状态或者PCB板的布局。去考虑什么推挽开漏,上拉下拉,某个电容怎样怎样等玩意。
    计算机组成课上讲的什么微命令等东西,教学时几乎是作为黑箱讲的,只了解到什么微指令译码等东西。确实,要深入讲是较为麻烦的,哪怕8086也是个挺复杂的CISC的CPU。很多同学就会很好奇“PC OUT ;AR IN”到底底层怎么处理啊?希望能通过读一读文章,理解一下RISC的硬件解码是如何构建和运行的。
    本文尽量不谈微操作,微指令之类的东西,这些概念通常是CISC特有的,CISC本质上到了最后也是要进行硬件解码的,不过再说就超出本文范围了。
    这次的Parwan处理器架构就是介于计算机科学和电子工程之间的东西,简单(相比于真正的现代处理器来说,这玩意只是60年前水平的玩具),但体现了很多思想。不过我们不能一一去了解了,这篇文章从较为顶层的层面去讨论整个Parwan架构,读完后有兴趣的甚至可以自己用点元件组一个。

    正文:

    1.Parwan处理器架构是什么?

    Parwan处理器是一种简易冯诺依曼式RISC处理器架构,最初是国外某校大四学生的课程设计。

    Parwan本意为“帕尔旺省”,又作Panvan,是阿富汗中部的一个省份。

    2.Parwan处理器架构的基本概况

    Parwan处理器中,用户可完全控制的寄存器只有一个,就是AC(累加寄存器),除此之外,用户需要存储的数据均必须放置于内存中。

    Parwan处理器字长为8位,也就意味着AC的容量仅有8BIT,数据总线的宽度也只有8BIT,但是,由于其特殊的设计,地址总线可以达到12BIT,也就是说,Parwan处理器最多能支持4KByte的内存容量。

    Parwan处理器的指令寻址方式支持直接寻址(Directled Addressing)和间接寻址(Indirected Addressing),具体细节将在后文详述。

    Parwan处理器的指令分为单字节指令和双字节指令,可以大致分为17条,不过由于寻址方式的不同,部分指令还可以细分,对于处理器的控制部分和指令译码来说,共有23种指令。

    由于地址为12位但是字长只有8位,Parwan处理器在设计时针对部分指令的寻址范围进行了约束,branch等分支指令,或者jsr等子程序进入指令,其寻址范围限制在256Byte内。关于Parwan的内存管理机制将在后文详述。

    3.Parwan处理器架构的内存管理

    如上文所述,Parwan处理器地址总线宽度为12BIT,这也就意味着在进行寻址时,只靠一个字节是无法进行准确定位的。为此,Parwan处理器采用了分页式的内存管理机制。

    Parwan处理器最多支持4Kbyte的内存,这4Kbyte内存被分为16个256Byte的页(Page)。

    对于一个内存单元的准确描述,需要4位的页号和8位的偏移地址(Offset)。

    对于寻址范围有限制的指令,如各类branch分支指令,jsr子程序进入指令等,其寻址方式为直接将第二个字节的8位解释为偏移地址,而页号则使用该条指令第二个字节在内存中位于的页号,即直接从PC中取来页号。这样就能拼凑为12位地址,从而定位内存单元。

    以上只能进行页内寻址的寻址方式被称作Page Address

    而对于必须进行精确定位的指令,如jmp直接跳转指令和STA,LDA等指令,这些指令的第一个字节的低4位也被用来编码内存地址,此时,指令第一个字节的低4位作为页号,第二个字节8位作为偏移地址,共同进行寻址。

    这些需要精确定位的指令,通常也支持间接寻址,对于间接寻址,指令第一个字节的低4位作为页号,第二个字节8位作为偏移地址,组成12位全地址,用这12位地址找到某内存单元,再用这内存单元内的8位数据作为偏移地址,和之前的页号一起,找到真正要寻找的内存单元。可见,间接寻址的地址存放单元和数据存放单元必须在同一页面内。

    以上需要第一字节和第二字节共同拼凑作为作为地址的寻址方式称作Full Address

    4.Parwan处理器架构的指令集

    Parwan处理器架构采用自创的指令集,如上文所述,共有23条指令,不过对于顶层用户,只需要理解为17种指令。

    指令如下:

    其中[loc]表示以直接/间接寻址的方式得到loc地址存储内容

    对于以上指令,其二进制编码如下:

    注:BIT4位在支持间接寻址的指令内,’1’代表间接寻址,’0’代表直接寻址,其余指令无此意义。


    如上文内存管理部分所述,这些指令的寻址方式存在区别:部分指令的寻址方式仅局限于页内,部分指令的第一个字节的低4位也被用来编码地址。这些都是在汇编器设计中需要注意的

    对于以上指令的执行过程,顶层开发者可以不详细了解,但是jsr指令的设计是和Parwan处理器架构支持的子程序结构密切相关得,再次说明如下:

    由于Parwan处理器架构不支持cpu层面的堆栈处理,所以在进入子程序时必须保存返回地址。

    Parwan处理器架构支持的子程序格式必须如下:

    jsr指令的第二字节为需要进入的子程序的第一字节。

    在执行jsr指令时,会首先将当前PC的值写入子程序的第一字节(此时PC的值就是jsr后下一条指令的地址)

    然后将PC置为子程序第一字节的值+1,这样等到下一指令周期时,就会进入子程序执行对应代码段

    当子程序执行完成后,导数第二字节的JMP指令会使用倒数第一字节间接寻址到子程序第一字节,然后跳转到第一字节所记录的返回地址

    等到下一指令周期时,就能退出子程序,从jsr进入点的下一条指令处开始执行。

    子程序内部可以跨页(JMP寻址方式为Full
    Address),但是起始字节和子程序调用入口必须在同一页。

    5.Parwan处理器架构的内部结构

    如图所示,Parwan处理器架构不是很复杂,但是理解起来还是要花上点时间。·

    Parwan处理器内部可以大致分为以下部分:

    • 逻辑处理部分
    • 内存地址管理部分
    • 控制部分
    • 总线部分

    逻辑处理部分主要由**算术逻辑单元(ALU),累加寄存器(AC),移位单元(SHU),状态寄存器(SR)**组成

    内存管理部分主要由**程序计数器页寄存器(PC_PAGE),程序计数器偏移寄存器(PC_OFFSET),内存地址寄存器页寄存器(MAR_PAGE),内存地址寄存器偏移寄存器(MAR_OFFSET)**组成

    控制部分主要由控制状态机(CONTROLLER),指令寄存器(IR),和31根控制线组成

    总线部分主要有外部数据总线(DATABUS),外部地址总线(ADBUS),内部数据总线(DBUS),内部总线(OBUS),内部页地址总线(MAR_PAGE_BUS),内部偏移地址总线(MAR_OFFSET_BUS)

    6.Parwan处理器架构内部各器件的详解

    逻辑处理部分:

    ALU:ALU是用于算数和逻辑运算的器件,可以执行加减,以及and,not逻辑,ALU共有两个8位主输入口a和b,一个8位主输出口alu_out,一个4位状态输入口,和一个4位状态输出口alu_flags。

    a口连接DBUS,b口连接AC寄存器,状态输入口连接SR,主输出口alu_out和状态输出口连接SHU。

    ALU有6根控制线,分别是ALU_AND,ALU_NOT,ALU_A,ALU_B,ALU_ADD,ALU_SUB。如字面意义,分别为控制ALU执行不同功能或者直接输出某输入口值的控制信号。

    SHU:SHU是用于移位处理的器件,可以执行左右移位操作。SHU共有4位8位各一个输入口和4位8位各一个输出口。

    输入口接收ALU输出信号的4位状态(flags)和8位输出结果,其中状态保持不变,直接从4位状态输出口直抵SR,而8位数据则在进行相应操作相应操作后被送至OBUS。

    SHU共有两根控制线,分别是ARITH_SHIFT_LEFT,ARITH_SHIFT_RIGHT,用于控制左移右移,如果两条控制线均为’0’,则不进行任何移位操作。

    SR:SR寄存器用于对ALU输出的状态(flags)进行存储,ALU输出的状态共有4位,分别是:V,C,Z,N。

    V:为1时代表发生溢出。

    C:为1时代表加法运算产生了进位或者减法运算不产生借位。

    Z:为1时代表结果为0。

    N:为1式代表结果为负数。

    SR的4位输入口连接SHU的状态输出口,输出口则连接至控制状态机和ALU。

    SR有两条控制线:LOAD_SR和CM_CARRY_SR,分别是从SHU的4位状态输出口载入SR的值和将SR的C位置’1’。

    AC:AC本身含义为算数寄存器,它是Parwan处理器中唯一的一个用户可全部控制的寄存器。AC寄存器有一个8位输入口和一个8位输出口ac_out,输入口连接OBUS,输出口连接ALU的b_side输入口。

    AC寄存器有两条控制线:LOAD_AC和ZERO_AC,前者用于从OBUS上载入值到AC,后者用于将AC清零。

    内存管理部分:

    PC:PC作为程序计数器,记录着下一条要执行指令的地址。PC分为两部分4位的PC_PAGE和8位的PC_OFFSET,如上文所述,PC_PAGE用于存储下一条指令的页号,PC_OFFSET用于存储偏移量。

    PC_PAGE的输入口连接至MAR_PAGE的输出口,PC_OFFSET的输入口连接至MAR_OFFSET的输出口。

    PC共有三个输出口(pc_out),PC_PAGE的输出口连接至MAE_PAGE_BUS,PC_OFFSET的输出口连接至MAR_OFFSET_BUS和DBUS。以上三个连接均为由控制线控制的选通连接。其中,PC_OFFSET到DBUS的连接,是为了jsr指令中需要保存子程序入口下一条的地址这个功能而设计的。

    PC共有四条控制线,分别为LOAD_PAGE_PC,LOAD_OFFSET_PC,INCREMENT_PC,和RESET_PC。作用分别为从MAR_PAGE_BUS/MAR_OFFSET_BUS处载入PC对应部分的值以及PC值+1和清零PC。

    MAR:MAR的作用是和ADBUS地址总线直接相连,用作从内存中读取数据的地址寄存。MAR和PC一样,也分为4位的MAR_PAGE和8位的MAR_OFFSET两部分,分别存储页号和偏移地址。

    MAR_PAGE和MAR_OFFSET的输入口分别连接在MAR_PAGE_BUS和MAR_OFFSET_BUS上,输出口,即mar_out,分别连接到PC_PAGE和PC_OFFSET上。同时两个输出口也合并为12位线,以选通方式链接到ADBUS上,用于和内存交互时到地址总线的地址输出。

    可见,MAR的输出连接至PC的输入,这就意味着对于各种跳转指令,跳转时跳转的地址都会先到MAR,再到PC。

    MAR部分有两根控制线,LOAD_PAGE_MAR和LOAD_OFFSET_MAR,含义是从MAR_PAGE_BUS和MAR_OFFSET_BUS上载入对应的值。

    控制部分:

    IR:IR作为指令寄存器,用于存储读取到指令的第一个字节。

    IR的8位输入口连接OBUS,8位输出口连接控制状态机,8位输出口的低4位也以选通的方式连接到了MAR_PAGE_BUS。很显然,指令第一个字节的低4位在进行Full Address寻址时存储着地址的页号,所以也需要连接至内存管理部分。

    IR有一根控制线LOAD_IR,含义是从OBUS上载入8位指令。

    控制状态机:31根控制信号线的源泉(另外一根INTERRUPT中断信号线来自于外部),是一个9状态的FSM。通过状态迁移来控制指令的执行,通常,一个指令周期对应几个状态,指令周期中取指,取操作数,执行,回写等部分也都分别对应一个或多个状态。状态控制机的详细介绍放在后文介绍。

    控制状态机有两部分输入来源,8位来自IR,4位来自SR的状态输出。

    状态控制机有31根控制信号线,INTERRUPT信号线来自于外部,为’1’时会将整个处理器初始化,READ_MEM和WRITE_MEM为内存读写控制线,连接至内存。其余28根控制信号线连接至各个组件以及选通连线。

    总线部分:

    ADBUS:ADBUS为外部地址总线,12BIT,用于处理器和内存直接的地址交互,线宽12BIT。一头以选通形式连接至MAR,另一头连接至内存。

    ADBUS共有一根控制线MAR_ON_ADBUS,为’1’时单向联通MAR的12位输出口到ADBUS。

    DATABUS:DATABUS为外部数据总线,8BIT,用于处理器和内存的数据交互,一头以选通形式连接DBUS,一头连接内存。

    DATABUS有1根控制线,为DBUS_ON_DATABUS,控制DBUS到DATABUS的单向连通。

    DBUS:DBUS为内部数据总线,用于处理器内部的数据交互,宽8BIT。

    DBUS和ALU的a_side直接连接,单向选择连通至MAR_OFFSET_BUS同时也被OBUS和PC_OFFSET的输出口单向选择连通。

    DBUS有3根控制线:PC_OFFSET_ON_DBUS,控制PC_OFFSET的输出口单向连通至DBUS,OBUS_ON_DBUS,控制OBUS到DBUS的单向连通,以及DATABUS_ON_DBUS,控制DATABUS到DBUS的单向连通。

    OBUS:OBUS是内部总线,本意为OUTPUTBUS(ALU的输出总线)。宽8BIT,连接了SHU,ALU和IR,用于指令的读取以及AC的输入。

    OBUS直接连接了SHU的输出以及AC,IR的输入。并以选通形式单向连通到DBUS。

    DBUS没有控制线。

    MAR_PAGE_BUS:MAR_PAGE_BUS是内部地址总线中的页总线,直接连通至MAR_PAGE,并以选通形式被IR的低4位和PC_PAGE的输出单向连通。

    MAR_PAGE_BUS有两条控制线,PC_ON_MAR_PAGE_BUS控制PC_PAGE到MAR_PAGE_BUS的单向连通,IR_ON_MAR_PAGE_BUS控制IR低4位到MAR_PAGE_BUS的单向连通。

    MAR_OFFSET_BUS:MAR_OFFSET_BUS是内部地址总线中的偏移地址总线,直接连通到MAR_OFFSET,并以选通形式被PC_OFFSET的输出和DBUS单向连通。

    MAR_OFFSET_BUS有两条控制线,PC_ON_MAR_OFFSET_BUS控制PC_OFFSET到MAR_OFFSET_BUS的单向连通,DBUS_ON_MAR_PAGE_BUS控制DBUS到MAR_OFFSET_BUS的单向连通。

    7.Parwan处理器架构部分指令执行过程的简要概述

    注意:概述部分不涉及控制状态机的状态以及状态迁移和内部电路,仅为功能性叙述,部分信号不严格遵守时序,很多顺序表述的语句实际上是并行的。

    如果需要了解具体哪些步骤并行,哪些步骤被划分为一个周期,请参考后续状态机部分,或者有关原理图或HDL代码。

    1.典型的取指令第一字节操作的概述

    前置:PC中已经存储了这个指令周期需要执行的指令的地址

    发出PC_PAGE_ON_MARPAGE_BUS信号和PC_OFFSET_ON_MAR_OFFSET_PAGE信号,使得PC中的值充斥MAR_BUS

    发出LOAD_MAR_PAGE信号和LOAD_MAR_OFFSET信号,使得MAR载入MAR_BUS的值

    发出MAR_ON_ADBUS指令,使得MAR中12位地址充斥ADBUS

    发出READ_MEM指令,使得内存读取ADBUS地址对应的8位数据,使之充斥DATABUS

    发出DATABUS_ON_DBUS信号,使DATABUS中的值充斥DBUS

    发出ALU_A指令,使得ALU的a_side从DBUS上读取8位数据,然后直接输出到alu_out

    这时这8位数据经过SHU,但SHU未接到指令,所以不作任何处理,直接输出到OBUS。

    发出LOAD_IR指令,IR从OBUS读取8位数据。

    发出INCREMENT _PC信号,使PC+1

    此时IR读取到了指令的第一字节。接下来就是控制状态机进行后续控制了。

    2.取指令第二字节以Full Address形式的直接寻址法找到数据送到DBUS上的操作概述

    前置:此时已经通过控制状态机对指令的译码知道了要取指令第二字节

    发出IR_ON_MARPAGE_BUS信号,使得指令第一个字节的低4位(页号)充斥MAR_PAGE_BUS

    发出PC_OFFSET_ON_MAR_OFFSET_PAGE信号,使得PC_OFFSET中的值充斥MAR_OFFSET_BUS

    发出LOAD_MAR_PAGE信号和LOAD_MAR_OFFSET信号,使得MAR载入MAR_BUS的值

    发出MAR_ON_ADBUS指令,使得MAR中12位地址充斥ADBUS

    发出READ_MEM指令,使得内存读取ADBUS地址对应的8位数据,使之充斥DATABUS

    发出DATABUS_ON_DBUS信号,使DATABUS中的值充斥DBUS

    发出INCREMENT _PC信号,使PC+1

    3.取指令第二字节以Full Address形式的间接寻址法找到数据送到DBUS上的操作概述

    前置:此时已经通过控制状态机对指令的译码知道了要取指令第二字节

    发出IR_ON_MARPAGE_BUS信号,使得指令第一个字节的低4位(页号)充斥MAR_PAGE_BUS

    发出PC_OFFSET_ON_MAR_OFFSET_PAGE信号,使得PC_OFFSET中的值充斥MAR_OFFSET_BUS

    发出LOAD_MAR_PAGE信号和LOAD_MAR_OFFSET信号,使得MAR载入MAR_BUS的值

    发出MAR_ON_ADBUS指令,使得MAR中12位地址充斥ADBUS

    发出READ_MEM指令,使得内存读取ADBUS地址对应的8位数据,使之充斥DATABUS

    发出DATABUS_ON_DBUS信号,使DATABUS中的值充斥DBUS

    发出INCREMENT _PC信号,使PC+1

    发出DBUS_ON_MAR_OFFSET_BUS信号,使得8位数据充斥MAR_OFFSET_BUS

    发出LOAD_MAR信号,使得MAR_BUS的12位数据进入MAR

    注意,此处具体执行操作需要结合处理器实际设计来决定,如果MAR_PAGE_BUS是锁存器之类结构来实现,其保存了上一次的4位页号,可以直接载入到MAR_PAGE,如果采用其它方式实现,视情况需要再次让IR中的低4位页号输送到MAR_PAGE_BUS。

    发出MAR_ON_ADBUS信号,使地址充斥ADBUS

    发出READ_MEM信号,读取内存到DATABUS

    发出DATABUS_ON_DBUS信号,读取到DBUS

    4.将DBUS上的数据和AC中数据进行某操作并送到AC中的操作

    前置:DBUS上充斥着需要的8位数据

    发出ALU_AND或ALU_ADD或ALU_SUB信号,a_side(DBUS)和b_side(AC)中的数据进行运算后输送到alu_out,又经过什么也不做的SHU,到达OBUS。

    发出LOAD_AC指令,使OBUS上数据载入AC

    5.将AC中数据以Full Address形式的直接寻址法写回内存中的操作

    前置:DBUS上充斥写回地址

    发出DBUS_ON_MAR_OFFSET_BUS信号,使得MAR_OFFSET_BUS充斥8位偏移地址

    发出IR_ON_MAR_PAGE_BUS信号,使得IR中低4位页号充斥MAR_PAGE_BUS

    发出LOAD_MAR_PAGE和LOAD_MAR_OFFSET信号,使得MAR载入地址

    发出MAR_ON_ADBUS信号,使得地址总线充斥12位地址

    发出ALU_B信号,使得AC中的8位数据经ALU和SHU输出到OBUS

    发出OBUS_ON_DBUS信号,数据充斥DBUS

    发出DBUS_ON_DATABUS,数据总线充斥数据

    发出WRITE_MEM信号,写内存

    6.跳转至DBUS上的直接寻址形式地址的操作

    前置:DBUS上充斥着需要跳转的8位偏移地址

    发出DBUS_ON_MAR_OFFSET_BUS信号,地址充斥MAR_OFFSET_BUS

    发出LOAD_MAR_OFFSET,地址载入到MAR_OFFSET

    发出LOAD_PC_OFFSET,MAR_OFFSET中8位偏移地址会被载入到PC_OFFSET中

    这时的PC就是需要跳转的地址了

    如果是jmp指令,则需要将IR的低4位页号也经过MAR_PAGE_BUS和MAR_PAGE送到PC_PAGE中去。

    7.PC_OFFSET中偏移地址写到Page Address形式的直接寻址的子程序开头的操作

    前置:MAR中存储着12位子程序首地址

    发出PC_OFFSET_ON_DBUS信号,是的PC_OFFSET成的值充斥DBUS

    发出DBUS_ON_DATABUS信号,数据充斥DATABUS

    发出MAR_ON_ADBUS信号,12位地址充斥ADBUS

    发出WRITE_MEM信号,写内存

    之后跳转到子程序,只需要将MAR中的偏移地址送到PC_OFFSET中就好了

    再次强调,以上叙述不严格遵守时序,很多操作实际是并行的。如果需要了解具体哪些步骤并行,哪些步骤被划分为一个周期,请参考后续状态机部分,或者有关原理图或HDL代码。

    8.Parwan处理器架构的控制状态机

    状态迁移图如下:

    各个状态均是由触发器实现,状态机原理图总览

    对于这张图片,我们能看到:

    每一个“状态”实际上是一个触发器,此处我们可以采用D触发器

    回顾一下数字电路中D触发器(D
    FLIP_FLOP),可以总结出以下的真值表:

    上图和下表均讨论的是上升沿触发的D触发器
    FLIP_FLOP或者DELAY FLIP_DLOP。

    在CLK触发时,D端的输入值会被装入,接着在下一次触发装入前,整个触发器的内部状态都会保持在装入时的状态,Q端也会输出上次装入的D值。

    D触发器的组合可以制作出各种状态机,具体的可以参考数电课本之类的资料,在此不赘述。

    观察原理图,每个状态对应的D触发器,在’1’状态时我们视为当前状态激活。

    对于每个D触发器的输入端D,我们可以认为是“输入’1’则迁移到该状态”,对于输出端Q,在该状态被激活时则会输出’1’。

    在某一状态时需要做的事,会被连接到状态对应D触发器的Q端,包括各种控制信号线以及状态迁移。

    对于某些状态,比如状态1,会有很多条迁移路径能到达状态1。结合迁移图,我们可以知道状态1能从状态1,状态6,状态8,状态9迁移而来。所以,其D端为各个状态Q端的OR关系。

    各个状态的详解:

    我们必须明确一点:Parwan处理器架构中控制部分的各个状态,并不能完整的映射到我们直觉中的指令周期的各个步骤。比如,S1是“开始准备取内存数据”,对于一些指令,取值的第一个状态就是S1,但是呢,对于一些单字节指令,在取下一个指令的时候S3会代劳S1的部分工作。

    下面,我将介绍各个状态的详细流程,并且举出一些指令执行的例子。

    S1:准备取数据(指令)

    S1也是系统的初始化状态,在遇到interrupt时也会迁移到该状态

    该状态的迁移信号来自自己以及S6,S8,S9。用OR关系连接。

    在该状态时,会发出

    PC_ON_MAR_PAGE_BUS,PC_ON_MAR_OFFSET_BUS,LOAD_PAGE_MAR,LOAD_OFFSET_MAR。

    以上四个控制信号会将PC中的页号和偏移地址载入MAR中。

    interrupt控制信号来源于外部,在S1状态时,如果interrupt信号为0,则状态在下个周期会迁移到S2,如果interrupt信号为1,则会发出RESET_PC控制信号重置PC为000000000000,并且下个周期迁移到S1自身。

    S2:取数据(指令)

    S2为取指的后半段,

    该状态的迁移信号来自S1,S3和S6,用OR逻辑连接。

    S2状态时会发出

    MAR_ON_ADBUS,READ_MEM,DATABUS_ON_DBUS,ALU_A,LOAD_IR,INCREMENT_PC信号

    这些信号会从内存读取一个字节,并沿着DATABUS-》DBUS-》ALU-》OBUS的顺序送入IR。

    S2状态执行后会转入S3状态。

    S3:执行单字节指令(包含一部分的取值准备)

    S2为单字节指令的执行阶段,执行后也会完成取指令的前半部分(S1状态)。这也意味着对于单字节指令,S1->S2->S3->S2这样的顺序就可以完成一个指令周期的全部操作并且取到下一个指令。

    S3状态的迁移信号来自S2。

    S2状态时会发出

    PC_ON_MAR_PAGE_BUS,PC_ON_MAR_OFFSET_BUS,LOAD_PAGE_MAR,LOAD_OFFSET_MAR信号,这些信号和S1控制信号一样的,是为了完成代替S1状态的取值前半部分工作。

    同时,根据指令的不同,其余信号也会发出。

    参考指令集,可见指令第一个字节高4位为1110即代表的单字节指令的身份,如果不是1110,并且当前状态为S3,那么下一个状态就会迁移到S4状态。

    如果是1110,并且当前状态为S3,那么就会迁移到S2状态,并且根据指令低4位发出对应单字节指令的控制信号,比如我要把AC清零,那么我就需要判断“后四位为0001”,然后输出ZERO_AC=’1’就好了,我们也是这么做的。

    再举个例子,我要把AC置位,但是处理器里边并没有全部置’1’的信号线啊,那么我就需要使能ZERO_AC,ALU_B,ALU_NOT,LOAD_AC那么我就能通过先清零AC,然后取反再送入的方式使其为全’1’。

    综上,核心思想就是对每一种指令都将其转化为一系列控制线的开关,然后找到共性,进行逻辑设计。

    S3状态下,如果判断是单字节指令,那么就会在执行后转移到S2状态,再进行取指的后半部分。

    S4:双字节指令的初步执行

    注:一下的一般直接,间接寻址指令指除了jsr和各种BRANCH的其余指令。

    经由S3状态,所有的双字节指令(第一个字节高4位不是1110)都会导致状态迁移到S4。在S4状态,将进行双字节指令的分类和初步处理。

    S4状态会发出

    MAR_ON_ADBUS,READ_MEM_DATABUS_ON_DBUS_DBUS_ON_MAR_OFFSET_BUS,LOAD_OFFSET_MAR,和INCREMENT_PC

    信号。

    这些信号和S3中的“取指前半部分”的控制信号一道,构成了读取下一字节到DBUS的功能,此时,我们还不知道这是直接寻址还是间接寻址或者跳转指令,但是此处,我们还是将DBUS上的第二字节装入了MAR的OFFSET偏移地址部分。这样,不管是BRANCH,JMP,JSR或者间接寻址的指令,都可以在接下来的状态中直接使用MAR_OFFSET中的地址偏移量。

    除此之外,在指令第一字节的7,6位不为”11”时,该指令为一般的直接间接寻址指令,会触发IR_ON_MAR_PAGE_BUS和LOAD_PAGE_MAR信号,是的指令第一字节低4位的页号也能装入到MAR中,构成完整的地址。

    同样,根据指令种类不同,会触发不同的下一状态。一般的直接寻址指令会迁移到状态S6,一般的间接寻址指令会迁移到状态S5。而jsr指令会迁移到S7,BRANCH指令迁移到状态S9。

    S5:间接寻址指令间接寻址过程的执行

    状态S5由状态S4迁移而来,用于执行间接寻址指令的间接寻址过程。

    S4状态会发出

    MAR_ON_ADBUS,READ_MEM,DATABUS_ON_DBUS,DBUS_ON_MAR_OFFSET_BUS,LOAD_OFFSET_MAR

    信号。

    这些信号完成了之前S4进行的取数操作的后半,并且将新的偏移地址(取来的数据)送入了MAR_OFFSET,以便S6直接使用。

    S5执行后会转移到S6状态。

    S6:直接寻址指令的执行

    S6不仅是直接寻址指令的执行,也作为间接寻址指令执行的后半部分,毕竟间接寻址就是两次直接寻址嘛。S6来源于S4和S5状态,两者之间OR连接。


    S6状态会根据指令的类型发出对应的控制信号,jm代表jmp简单跳转,st代表STA指令,而rd代表需要读取内存数据,然后和AC中数据经由ALU运算后放到AC的指令。

    各种指令的控制信号相信大家都可以容易的理解。在S6之后会回归初始状态S1。

    S7:jsr指令前半部分的执行

    S7状态实现了将入口地址写入子程序第一个字节的目标,该状态来源于S4状态。

    该状态发出

    MAR_ON_ADBUS,PC_OFFSET_ON_DBUS,DBUS_ON_DATABUS,WRITE_MEM,LOAD_OFFSET_PC信号。

    这些信号完成了对子程序第一字节处写入当前PC中OFFSET偏移地址的操作,并且从MAR载入了PC(此时MAR就是S4中读取的第二字节,也就是子程序第一个字节的地址)。

    状态S7的下一个状态的S8。

    S8:jsr指令的后半部分

    最简单的一个状态,来自S7,转移到S1,只是把S7中取得的PC值+1,因为子程序真正的第一跳指令是从第二个字节开始的。经过S8后才能准确的进入子程序,然后从S1开始取指……

    S9:分支跳转指令的执行

    S9为四种分支跳转指令的处理,来自S4,迁移到S1。

    对于S9,只需要通过IR中的低4位判断指令的类型,再根据SR中的四位标识位来确定是否跳转,如果确认跳转,则和S8一样,给PC载入S4中已经装入MAR的第二字节就好。

    注:上图的status3-0其实就是SR的VCZN四个标识位。

    下面,总结控制状态机的9个状态,如果仔细阅读以上详解,就会发现有的状态描述不是很准确,这也是没办法的事情。毕竟经典的几个周期在Parwan架构设计中有的被分散到里几个状态。

    9.一些额外的提醒

    大家可能已经适应了“高级语言”的思维方式,想到逻辑,必然是顺序选择和循环,还有函数,面向对象,多线程等东西。但我们必须注意:实际上我们是在和一堆有实体的元件打交道。

    有一个较为常见的问题:“某个状态,给某条控制线置’1’,那么为啥不用置’0’啊?”。

    可能大家习惯了用C语言等高级语言去写STM32或者51单片机,对于某个GPIO,置’1’后就得清’0’。但是我们这里关注的是更底层的东西。实际上,不管是我们用HDL写然后综合,或者我们自己去搞个面包板鼓弄,每一根控制线都是很多个信号“或”的关系,如果在FPGA里就是个LUT(可以理解为真值表)。


    如上图,显而易见,Increment_PC控制线就是个LUT,里边就是三根线或,这三根线其实就是S2,S4,S8三个状态对应的D触发器的Q口。如果该状态结束了,那么随着下一个CLK的上升沿到来,对应D触发器的Q口就会为’0’,显然控制线就会清零了。

    所以说,在看较为底层设计的时候,要抛开高级语言的思维方式,从布尔逻辑和时序电路的角度去考虑问题。

    10.参考资料

    西安电子科技大学 计算机科学与技术学院(软件学院)沈沛意 张亮 老师的PPT。(80%的图片来源于PPT截图,剩余图片为原创)

    Github 上的 Grifk93用户的Parwan_Proccesor A VHDL implementation 项目。
    (这个项目大家可以参考下,VHDL写的,不过注释是西班牙文(有的词语建议用印尼文翻译,更准确),但是很多词语看看基本形态就能想到对应的英语词汇,项目有点小错误,而且有些地方不够完美。不过参考足够了。)

    其它互联网资料。(实话,几乎没有。)

    赞(0) 打赏
    未经允许不得转载:爱站程序员基地 » Parwan处理器架构简述