引言

  不知道你是否和我有过同样的感受,《计算机组成原理》这门学科学起来如此的艰难:一节课下来,教室黑板上留下了满满的 “足迹”,看上去也挺简单的,不就是 0 和 1 嘛。但这些看起来简简单单的 0 1 码却成为了我当时学习路上的绊脚石。源码、反码、补码等等等等,各种的码制转换令我一头雾水,我曾一度怀疑这就是计算机干的活儿吗?

  随着后面慢慢了解《计算机组成原理》后,我愿称计算机为世界上最麻烦的电子产品。也形象的将计算机描述为一套有电源、有身体、有框架,但就是没有思想的空壳儿。这时候,我们的人类社会才萌生了许许多多“ 利用 ”它们的主人—程序“ 猿 ”。

  程序员就是要为计算机这个富有 ” 聪明 “潜质的伙伴编写一套一套的 “程序” ,告诉它们应该去做什么亦或是怎么去做。正是由于它们能吃苦、不怕累的精神再加上完美程序的契合,我们的生活质量得以大幅度提升。



  即使你不是计算机专业的学生,相信对于CPU你也有所了解。正所谓CPU(Central Processing Unit),也就是中央处理器。负责解释计算机指令以及处理计算机软件中的数据。中央处理器主要包含控制器、运算器两部分,其中还包括cache以及实现它们之间信息互换的数据、总线。

  可千万别小看这个不起眼的 “小东西” ,它可是程序执行、机器正常运转必不可少的元器件。作为电子计算机三大核心部件(CPU、内存、I/O设备)之一的CPU,在计算机体系结构中承载着控制调配硬件资源、执行通用运算等重要职责。下面我们来了解较为简单的单周期CPU功能指令。


上机实验

分析实现单周期CPU的14条指令计算结果,比较理论与实践结果的正确性。

Addi:

  分析第一个周期,指令地址为041008,在程序测试段中,可以看到,本条指令为addi,那么现在开始检验指令addi的实现过程:指令addi的功能是rt←rs + (sign-extend)immediate; immediate符号扩展再参加“加”运算。

  首先找到rs在本周期中存放的源操作数地址,rs=00;然后在Objects中添加immediate组件,找到立即数的值,immediate=8;最后进入ALU分析计算结果,在ALU的代码文件中有两个引脚,ALUSrcA和ALUSrcB,它们在第一个周期中的值分别是0和1,则A端口进行ReadData1,B端口进行extend,计算结果为result=8,指令执行正确,可以实现数据相加功能。

Ori:



  分析第二个周期,指令地址为40020002,在程序测试段中,可以看到,本条指令为ori,那么现在开始检验指令ori的实现过程:指令ori的功能是rt←rs | (zero-extend)immediate; immediate符号扩展再参加“或”运算。寄存器源操作数地址:rs=0,immediate=2;

进行zero-extend后,值为2



进行“或”运算,ALU两个引脚输入端口值为



计算结果为

指令计算结果无误,指令运行正常。

Add:



  分析第三个周期,指令地址为0411800,在程序测试段中,可以看到,本条指令为add,那么现在开始检验指令add的实现过程:指令add的功能是rd←rs + rt。源操作数地址:rs=2,rt=1;ALU两个引脚值都是0,读寄存器中的值,此时存入结果为03,程序运行正常,功能实现。

Sub:

  分析第四个周期,指令地址为08622800,在程序测试段中,可以看到,本条指令为sub,那么现在开始检验指令sub的实现过程:指令sub的功能是rd←rs - rt。源操作数地址:rs=3,rt=2;ALU两个引脚值皆为0,程序读取寄存器中的值,此时存入结果为5,程序运行正常,功能完好。

and:



  分析第五个周期,指令地址为44a22000,在程序测试段中,可以看到,本条指令为and,那么现在开始检验指令and的实现过程:指令and的功能是rd←rs & rt;(逻辑与运算)。源操作数寄存器地址:rs=5,rt=2;ALU引脚值为0,读取ALU计算结果为00000000,分别对源操作数5和2转为2进制为:0101、0010按位与后值为0,结果吻合,该单元工作正常,功能实现。

or:



  分析第六个周期,指令地址为48824000,在程序测试段中,可以看到,本条指令为or,那么现在开始检验指令or的实现过程:指令or的功能是rd←rs | rt;(逻辑或运算)。源操作数寄存器地址:rs=04,rt=02;ALU双引脚值为0,读取寄存器堆中的值,可以看到存放真值为0和2(取最后结果)。读取值为2。

  分别对源操作数4和2转为2进制并按位或后值为2,与程序运行结果吻合,该单元工作正常,功能实现。

sll:

  分析第七个周期,指令地址为60084040,在程序测试段中,可以看到,本条指令为sll,那么现在开始检验指令sll的实现过程:指令sll的功能是rd<-rt<<(zero-extend)sa,左移sa位 ,(zero-extend)sa。源操作数寄存器地址:rt=08 ,寻求真值,移位数sa=1,程序运行后 。在二进制数据计算中,左移一位就相当于乘以2,故程序结果正确,该单元工作正常。

bne:

  分析第八个周期,指令地址为c501fffe,在程序测试段中,可以看到,本条指令为bne,那么现在开始检验指令bne的实现过程:指令bne的功能是:if(rs!=rt) pc←pc + 4 + (sign-extend)immediate <<2 else pc ←pc + 4【与beq不同:不等时转移,相等时顺序执行。】在寄存器堆中找到源操作数地址,寻得真值,找寻计算结果,结果吻合,单元工作正常。

slti:



  分析第九个周期,指令地址为6c460008,在程序测试段中,可以看到,本条指令为slti,那么现在开始检验指令slti的实现过程:指令slti的功能是:if (rs <(sign-extend)immediate) rt =1 else rt=0,源操作数地址找到后,对立即数进行sign-extend,然后判断是否满足if()中的给定条件,程序结果完整无误,本单元工作正常。

beq:



  第14个周期中,指令地址为c0e1fffe,在程序测试段中,可以看到,本条指令为beq,那么现在开始检验指令beq的实现过程:指令beq的功能是:if(rs=rt) pc←pc + 4 + (sign-extend)immediate <<2 else pc ←pc + 4,immediate是从PC+4地址开始和转移到的指令之间指令条数。

  immediate符号扩展之后左移2位再相加。左移2位是由于跳转到的指令地址肯定是4的倍数(每条指令占4个字节),最低两位是“00”,因此将immediate放进指令码中的时候,已经右移两位,这与上文 “指令之间指令条数”相契合。运算结果符合事实,单元工作正常。

sw:



  第19个周期中,指令地址为98220004,在程序测试段中,可以看到,本条指令为sw,那么现在开始检验指令sw的实现过程:指令sw的功能是:memory[rs+ (sign-extend)immediate]←rt;immediate符号扩展再相加。

  将rt寄存器的内容保存到rs寄存器内容和立即数符号扩展后的数相加作为地址的内存单元中。同样的依次找到源操作数在寄存器中的值,进入ALU运算后,检验结果,过程图展示如下,结果无误,单元功能实现完好。

lw:



  第20个周期中,指令地址为9c290004,在程序测试段中,可以看到,本条指令为lw,那么现在开始检验指令lw的实现过程:指令lw的功能是:rt ← memory[rs + (sign-extend)immediate];immediate符号扩展再相加。

  读取rs寄存器内容和立即数符号扩展后的数相加作为地址的内存单元中的数,然后保存到rt寄存器中。同样的依次找到源操作数在寄存器中的值,进入ALU运算后,检验结果,过程图展示如下,结果无误,单元功能实现完好。

j:

  第21个周期中,指令地址为e0000010,在程序测试段中,可以看到,本条指令为j,那么现在开始检验指令j的实现过程:指令j的功能是:pc <-{(pc+4)[31..28],addr[27..2],2{0}},无条件跳转。

  由于MIPS32的指令代码长度占4个字节,所以指令地址二进制数最低2位均为0,将指令地址放进指令代码中时,可省掉!这样,除了最高6位操作码外,还有26位可用于存放地址,事实上,可存放28位地址了,剩下最高4位由pc+4最高4位拼接上。指令验证过程如下,最后结论为:单元工作正常,功能实现完好。

halt:



  第22个周期中,指令地址为fc000000,在程序测试段中,可以看到,本条指令为Halt,那么现在开始检验指令Halt的实现过程:指令Halt的功能是:停机;不改变PC的值,PC保持不变。从仿真后的波形图中,可以清晰看到,波形图在本指令后,电平恒定,不再发生变化,所以本指令功能实现,模块单元工作正常。

总结

  深刻了解了一个简单单周期CPU的设计方法,无论是复杂亦或是简单的系统,最好的办法就是采用分层和模块化的设计方法。在众多信号状态中,首先从最高层开始梳理逻辑,划分模块,进而到每个模块的内部核心处继续划分,这样就避免了在信号条件变动很多的情况下不能够清晰的理清的问题。

  硬件设施的不足让人感觉整个课程在“云端”,讲授的内容不能很好的和现有知识的应用契合,虽然第一次接触VerilogHDL硬件描述语言,但是这门语言的思想和我所学的C++语言使用了同样的逻辑架构,采用了自顶向下、分而治之的思想逐步剖析,正所谓“大厦的建立绝非一朝一夕”,采用“分步”的设计思想完成最终单周期CPU的设计与实现。

  有些许遗憾的是未能在硬件上实现,如果能在开发板上烧写程序,接触到实物,应该能有更为深刻的理解,在模块调用使用端口绑定时,有一个小技巧:勿完全按照顺序赋值;因为这样的方法可以尽量减少程序出错的概率,而对于我们后期检查源文件时也无需完全分辨每一个参数的值,减少工作量。

  维基百科、谷歌学术是非常不错的平台。

Vivado实战—单周期CPU指令分析的更多相关文章

  1. 使用logisim搭建单周期CPU与添加指令

    使用logisim搭建单周期CPU与添加指令 搭建 总设计 借用高老板的图,我们只需要分别做出PC.NPC.IM.RF.EXT.ALU.DM.Controller模块即可,再按图连线,最后进行控制信号 ...

  2. 单周期CPU设计

    终于有点时间了,恰好多周期的设计也已经完成,其实只想写写多周期的,无奈单周期补上才好,哈哈哈~ —————+—————黄金分割线—————+————— 首先要理解什么叫单周期CPU(与后面多周期CPU ...

  3. 为什么现在使用多周期CPU,而单周期CPU被弃用?

    最初设计的CPU结构简单,内部不复杂.之所以制造它是为了让机器自动跑程序,算数. 早期CPU都是单周期的,人们没考虑那么多,性能啥的.就让CPU每个时钟周期跑一个指令,这些时钟周期等长.这样下来,有的 ...

  4. 使用Verilog搭建一个单周期CPU

    使用Verilog搭建一个单周期CPU 搭建篇 总体结构 其实跟使用logisim搭建CPU基本一致,甚至更简单,因为完全可以照着logisim的电路图来写,各个模块和模块间的连接在logisim中非 ...

  5. 单周期CPU设计的理论基础

    写在前面:本博客内容为本人老师原创,严禁任何形式的转载!本博客只允许放在博客园(.cnblogs.com),如果您在其他网站看到这篇博文,请通过下面这个唯一的合法链接转到原文! 本博客全网唯一合法UR ...

  6. 单周期cpu设计代码解读

    目录 写在前面 单周期cpu设计代码讲解 概念回顾 Verilog代码讲解 写在前面 欢迎转载,转载请说明出处. 单周期cpu设计代码讲解 概念回顾 一.电子计算机的部件 分为:中央处理器(cpu). ...

  7. P4-verilog实现mips单周期CPU

    最近对学习的掌控可能出现了问题,左支右绌,p2挂了,p2.p3.p4.p5每周在计组花的连续时间少了很多,学习到的东西也少了很多,流水线都还没真正开始写,和别人比落后了一大截,随笔自然就荒废了,我得尽 ...

  8. 单周期CPU

    一个时钟周期执行一条指令的过程理解(单周期CPU): https://blog.csdn.net/a201577F0546/article/details/84726912 单周期CPU指的是一条指令 ...

  9. Verilog单周期CPU(未完待续)

    单周期CPU:指令周期=CPU周期 Top模块作为数据通路 运算器中有ALU,通路寄存器(R1.R2.R3.R4),数据缓冲寄存器(鉴于书上的运算器只有R0)........... 此为ALU和通用寄 ...

随机推荐

  1. Scrapy 爬虫框架学习笔记(未完,持续更新)

    Scrapy 爬虫框架 Scrapy 是一个用 Python 写的 Crawler Framework .它使用 Twisted 这个异步网络库来处理网络通信. Scrapy 框架的主要架构 根据它官 ...

  2. ASM入网小助手卸载

    目录 ASM小助手卸载 写在前的 卸载 解除U盘禁用 写在后的 ASM小助手卸载 写在前的 有些公司内网的上网认证是用的ASM小助手,不过有时候用自己电脑接入公司内网可能会主动下载到ASM入网小助手的 ...

  3. (Opencv06)绘制轮廓函数

    (Opencv06)绘制轮廓函数 cv2.drawContours(image, contours, contourIdx, color, thickness) img: 指在哪副图像上绘制轮廓 会改 ...

  4. 深入刨析tomcat 之---第14篇 对应19章,使用manager管理 web应用

    writedby 张艳涛 第19章讲的是管理程序,当一个tomcat启动的时候,能通过远程浏览器能访问tomcat,启动web应用,关闭web应用,查看web应用 怎么实现的呢? 在webapp 文件 ...

  5. SQL Server常用的几个存储过程

    1. sp_helptext 查看一些数据库对象的定义,比如存储过程.函数.试图等. 2. sp_who或者sp_who2 查看SQL Server数据库会话信息.比如是否被阻塞.

  6. 痞子衡嵌入式:嵌入式Cortex-M中断向量表原理及其重定向方法

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是Cortex-M中断向量表原理及其重定向方法. 接着前文 <嵌入式Cortex-M裸机环境下临界区保护的三种实现> 继续聊, ...

  7. Netty 源码分析系列(二)Netty 架构设计

    前言 上一篇文章,我们对 Netty做了一个基本的概述,知道什么是Netty以及Netty的简单应用. Netty 源码分析系列(一)Netty 概述 本篇文章我们就来说说Netty的架构设计,解密高 ...

  8. SQL遍历日期

    IF OBJECT_ID(N'tempdb..#temp', N'U') IS NOT NULL BEGIN DROP TABLE #temp;--临时表删除 END --创建临时表 CREATE T ...

  9. ORACLE ORA-00933: SQL 命令未正确结束,

    这个错误害我花了一天时间排查,最后原来是因为结束符,这种语句不能是分号,将分号即可执行成功. MERGE INTO MO_TRADE_COUNT_DAY A USING ( SELECT MAX(fl ...

  10. js--class类、super和estends关键词的学习笔记

    前言 JavaScript 语言在ES6中引入了 class 这一个关键字,在学习面试的中,经常会遇到面试官问到谈一下你对 ES6 中class的认识,同时我们的代码中如何去使用这个关键字,使用这个关 ...