【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

除了通用计算器负责控制和计算之外,cpu如果需要正常有序地运行,还需要一定地协处理器来帮助完成对应地工作。在mips下面,这样地协处理器称之为cp0。协处理器的工作一般包括这几个方面,

1)处理中断和异常;

2)处理mmu和tlb;

3)处理cache;

4)处理其他cpu的相关属性。

之前我们在谈到乘法和除法的时候,涉及到hi和lo这两个寄存器。其实,cp0的处理方法和他们是差不多的。如果是mf读操作,那么这个动作是在exe阶段完成的;如果是写操作,那么这个动作也是在wb阶段完成的。

1、准备cp0_reg.v

`include "defines.v"module cp0_reg(input  wire                                        clk,input wire                                      rst,input wire                    we_i,input wire[4:0]               waddr_i,input wire[4:0]               raddr_i,input wire[`RegBus]           data_i,// input wire[31:0]              excepttype_i,input wire[5:0]               int_i,
//  input wire[`RegBus]           current_inst_addr_i,
//  input wire                    is_in_delayslot_i,output reg[`RegBus]           data_o,output reg[`RegBus]           count_o,output reg[`RegBus]           compare_o,output reg[`RegBus]           status_o,output reg[`RegBus]           cause_o,output reg[`RegBus]           epc_o,output reg[`RegBus]           config_o,output reg[`RegBus]           prid_o,output reg                   timer_int_o    );always @ (posedge clk) beginif(rst == `RstEnable) begincount_o <= `ZeroWord;compare_o <= `ZeroWord;//status寄存器的CU为0001,表示协处理器CP0存在status_o <= 32'b00010000000000000000000000000000;cause_o <= `ZeroWord;epc_o <= `ZeroWord;//config寄存器的BE为1,表示Big-Endian;MT为00,表示没有MMUconfig_o <= 32'b00000000000000001000000000000000;//制作者是L,对应的是0x48,类型是0x1,基本类型,版本号是1.0prid_o <= 32'b00000000010011000000000100000010;timer_int_o <= `InterruptNotAssert;end else begincount_o <= count_o + 1 ;cause_o[15:10] <= int_i;if(compare_o != `ZeroWord && count_o == compare_o) begintimer_int_o <= `InterruptAssert;endif(we_i == `WriteEnable) begincase (waddr_i) `CP0_REG_COUNT:      begincount_o <= data_i;end`CP0_REG_COMPARE:    begincompare_o <= data_i;//count_o <= `ZeroWord;timer_int_o <= `InterruptNotAssert;end`CP0_REG_STATUS:   beginstatus_o <= data_i;end`CP0_REG_EPC:   beginepc_o <= data_i;end`CP0_REG_CAUSE:    begin//cause寄存器只有IP[1:0]、IV、WP字段是可写的cause_o[9:8] <= data_i[9:8];cause_o[23] <= data_i[23];cause_o[22] <= data_i[22];end                 endcase  //case addr_iendend    //ifend      //alwaysalways @ (*) beginif(rst == `RstEnable) begindata_o <= `ZeroWord;end else begincase (raddr_i) `CP0_REG_COUNT:        begindata_o <= count_o ;end`CP0_REG_COMPARE:   begindata_o <= compare_o ;end`CP0_REG_STATUS:  begindata_o <= status_o ;end`CP0_REG_CAUSE:    begindata_o <= cause_o ;end`CP0_REG_EPC:   begindata_o <= epc_o ;end`CP0_REG_PrId:    begindata_o <= prid_o ;end`CP0_REG_CONFIG: begindata_o <= config_o ;end    default:    beginend            endcase  //case addr_i          end    //ifend      //alwaysendmodule

2、id添加译码

     if(inst_i[31:21] == 11'b01000000000 && inst_i[10:0] == 11'b00000000000) beginaluop_o <= `EXE_MFC0_OP;alusel_o <= `EXE_RES_MOVE;wd_o <= inst_i[20:16];wreg_o <= `WriteEnable;instvalid <= `InstValid;     reg1_read_o <= 1'b0;reg2_read_o <= 1'b0;       end else if(inst_i[31:21] == 11'b01000000100 && inst_i[10:0] == 11'b00000000000) beginaluop_o <= `EXE_MTC0_OP;alusel_o <= `EXE_RES_NOP;wreg_o <= `WriteDisable;instvalid <= `InstValid;      reg1_read_o <= 1'b1;reg1_addr_o <= inst_i[20:16];reg2_read_o <= 1'b0;                  end

3、ex阶段

1)增加数据读取操作

     `EXE_MFC0_OP:      begincp0_reg_read_addr_o <= inst_i[15:11];moveres <= cp0_reg_data_i;if( mem_cp0_reg_we == `WriteEnable &&mem_cp0_reg_write_addr == inst_i[15:11] ) beginmoveres <= mem_cp0_reg_data;end else if( wb_cp0_reg_we == `WriteEnable &&wb_cp0_reg_write_addr == inst_i[15:11] ) beginmoveres <= wb_cp0_reg_data;endend   

看到这里,大家应该对这个代码不陌生了。之前谈到过,所有的寄存器都是在wb之后,才会真正写到寄存器里面的。但是,mfc0的动作是在exe阶段进行的,那么这个时候势必会出现数据读取错误的情况的。所以,解决这个问题最好的办法就是数据预取。id中寄存器预取、ex阶段hi&lo以及mfc预取、mem阶段llbit预取,本质上都是一回事。

2)增加写操作

always @ (*) beginif(rst == `RstEnable) begincp0_reg_write_addr_o <= 5'b00000;cp0_reg_we_o <= `WriteDisable;cp0_reg_data_o <= `ZeroWord;end else if(aluop_i == `EXE_MTC0_OP) begincp0_reg_write_addr_o <= inst_i[15:11];cp0_reg_we_o <= `WriteEnable;cp0_reg_data_o <= reg1_i;end else begincp0_reg_write_addr_o <= 5'b00000;cp0_reg_we_o <= `WriteDisable;cp0_reg_data_o <= `ZeroWord;end             end 

cp0寄存器的写操作是和通用寄存器分开来的。所以这部分代码需要单独用逻辑快来表达。

4、mem阶段

mem阶段对cp0没有什么影响,主要工作就是把之前ex阶段的数据透传下去即可。

       cp0_reg_we_o <= cp0_reg_we_i;cp0_reg_write_addr_o <= cp0_reg_write_addr_i;cp0_reg_data_o <= cp0_reg_data_i;   

5、准备汇编代码测试

   .org 0x0.set noat.set noreorder.set nomacro.global _start
_start:ori $1,$0,0xfmtc0 $1,$11,0x0  #写compare寄存器,开始计时lui $1,0x1000ori $1,$1,0x401mtc0 $1,$12,0x0  #将0x401写如status寄存器mfc0 $2,$12,0x0  #读status寄存器,$2=0x401_loop:j _loopnop

6、将对应的汇编代码翻译成二进制文件

3401000f
40815800
3c011000
34210401
40816000
40026000
08000006
00000000

7、利用iverilog和gtkwave进行波形分析

除了通用的pc、inst这些寄存器、wire之外,还可以把cp0_reg0里面的寄存器拉出来看看。重点看看we_i什么时候为高、写入的waddr_i对不对、和之前给出来的汇编代码能不能对的上。最后就是死循环了,因为mips延迟槽的原因,循环肯定是两个pc地址交替进行的。

cpu设计和实现(协处理器cp0)相关推荐

  1. cpu设计和实现(协处理器hi和lo)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 很多同学可能不了解mips处理器,如果个人想补充一点mips cpu的知识,可以找些书籍资料来读 ...

  2. 单周期十条指令CPU设计与verilog实现(Modelsim)

    目录 一.实验目的 二.实验内容 三.实验原理 1. 规定 2. 原理图 四.实验步骤 1. CPU各部件实现 pc insMem acc alu cu dataMem 2. CPU例化实现 3. 编 ...

  3. Black Hat|英特尔CPU设计漏洞为恶意软件打开后门

    本文讲的是 Black Hat|英特尔CPU设计漏洞为恶意软件打开后门,约二十年前在x86处理器架构中存在一个设计缺陷,这个缺陷可以允许攻击者在低级别的计算机固件中安装恶意软件,而且安全产品无法检测的 ...

  4. 16位计算机cpu电路图,简单16位CPU设计.doc

    简单16位CPU设计 简单16位CPU设计 一.实验内容 完成从指令系统到CPU的设计,编写测试程序,通过运行测试程序对CPU设计进行正确性评定.具体内容包括:典型指令系统(包括运算类.转移类.访存类 ...

  5. 众友科技计算机组成原理,组成原理:采用微程序控制器的模型机CPU设计(10页)-原创力文档...

    课程设计报告 课程名称: 计算机组成原理 设计题目: 采用微程序控制器的模型机 CPU设计 院 系: 班 级: 设 计 者: 学 号: 指导教师: 目 录 课程设计(大作业)报告 1 昆明学院课程设计 ...

  6. 【Computer Organization笔记10】单周期CPU设计:基于7条MIPS指令的数据通路

    本次笔记内容: P19 计算机组成原理(19) P20 计算机组成原理(20) 本节课对应幻灯片: 组成原理24 singlecycle.pptx 基于上节课的7条MIPS指令的数据通路,分别针对7条 ...

  7. 在VIVADO上实现的非常简易的RISC-V CPU设计(来自《Verilog数字系统设计》夏宇闻著)

    在VIVADO上实现的非常简易的RISC-V CPU设计 一.实验要求重述: 1.实验目的 2.实验要求: 二.学习准备: 1.什么cpu? 2.cpu需要具有哪些部件? 3.什么是RISC_CPU? ...

  8. 【中山大学计算机组成原理实验】单周期CPU设计与实现

    实验一 : 单周期CPU设计与实现 一. 实验目的 (1) 掌握单周期CPU数据通路图的构成.原理及其设计方法: (2) 掌握单周期CPU的实现方法,代码实现方法: (3) 认识和掌握指令与CPU的关 ...

  9. (Verilog)多周期CPU设计

    (Verilog)多周期CPU设计 写在前面:在参考别人的博客自己做了一遍单周期cpu后,觉得不是很难,于是自己尝试了做一下多周期cpu,然后被各种bug糊脸...果然,自己尝试和有大佬指路还是有很大 ...

最新文章

  1. 模拟grub损坏及丢失
  2. 国内外优秀的计算机视觉团队汇总|持续更新
  3. SQL字符串操作汇总
  4. node js fork php,Node.js中execFile,spawn,exec和fork简介
  5. 深入理解——亚像素 / sub-pixel、亚像素卷积
  6. android 录音命令,音频延迟  |  Android NDK  |  Android Developers
  7. 随想录(文件系统的第一个用户程序shell)
  8. Linux添加/删除用户和用户组(linux中,添加cvs用户,实质就是添加linux用户。)
  9. android示例程序剖析之记事本,Android实现记事本项目完整实例,附源代码
  10. ERstudio导入mysql脚本生成rtf文档
  11. visual studio安装vsix插件
  12. Java NIO?看这一篇就够了!
  13. 【论文写作】使用overleaf撰写你的会议论文
  14. JavaScript复制内容到剪贴板 1
  15. DV2020T 综合
  16. 【Spring源码】Spring事务原理
  17. 讲座回顾丨5G的全新可能:基于Smart Edge Open和EdgeX构建5G MEC
  18. 计算机专业的单招大学排名,全国单招学校排名 单招哪个学校比较好
  19. 轻松上手写作利器 Markdown:从此文章排版无烦恼
  20. 46家公司面试笔试题

热门文章

  1. HMM模型(Ⅱ)—量化投资
  2. windows 2008 终端服务器配置,Windows Server 2008搭建终端服务器
  3. centos7安装mplayer解码器
  4. audio标签实现网页循环播放背景音乐代码实现
  5. nodejs+vue社区居民自来水务缴费报修管理系统
  6. 一款DCDC稳压开关电源转换器HM1509
  7. 2021/4/24团队设计天梯赛L3题目集及部分题解
  8. 纳米管 SBS接枝多壁碳纳米管(SBS-g-MWNTs)/聚乙烯咔唑共价修饰多壁碳纳米管(MWNT-PVK)/碳纳米管接枝型环氧树脂固化剂(SBS-g-MWNTs/EP)/
  9. Hi3531DV100开发环境的搭建(含交叉编译器的安装及官方SDK安装)
  10. pycharm连接服务器