2022 buaa CO P6

by psfott

设计概述

  1. 设计说明

    • 支持指令:
      add, sub, and, or, slt, sltu, lui
      addi, andi, ori
      lb, lh, lw, sb, sh, sw
      mult, multu, div, divu, mfhi, mflo, mthi, mtlo
      beq, bne, jal, jr
    • 处理器为五级流水线设计
  2. 遇到的bug:
    • 偷懒没写宏,把4’b1111写成了1111
    • 没有仔细研究课程组给的tb,sb和sh的实现机制没有搞懂

工程模块

  • 在P5的基础上增加了三个模块,分别为E_MDU,M_BE,M_DE

E_MDU(乘除模块)

信号名 方向 位宽 描述
clk I 1 时钟信号
reset I 1 异步复位信号
srcA I 32 参与乘除运算的第一个值
srcB I 32 参与乘除运算的第二个值
MDUop I 4 乘除模块控制信号
Dout O 32 运算结果
busy O 1 busy信号(改阻塞)
  • 乘除模块行为约定如下:

    • 我们假定乘除法部件的执行乘法的时间为 5 个时钟周期,执行除法的时间为 10 个时钟周期(包含写入内部的 HI 和 LO 寄存器)
    • 自 Start 信号有效后的第 1 个 clock 上升沿开始,乘除法部件开始执行运算,同时将 Busy 置位为 1。
    • 在运算结果保存到 HI 寄存器和 LO 寄存器后,Busy 位清除为 0。
    • 当 Busy 信号或 Start 信号为 1 时,mult, multu, div, divu, mfhi, mflo, mthi, mtlo 等乘除法相关的指令均被阻塞在 D 流水级。
    • 数据写入 HI 寄存器或 LO 寄存器,均只需 1 个时钟周期。
  • 具体代码实现:只要想明白时钟周期的控制其实蛮容易的,特别注意$signed
    if(cycle == 0) beginif(mtlo) lo <= srcA;if(mthi) hi <= srcA;if(mult) beginBusy <= 1;cycle <= 5;{temp_hi,temp_lo} <= $signed(srcA) * $signed(srcB);endif(multu) beginBusy <= 1;cycle <= 5;{temp_hi,temp_lo} <= srcA * srcB;endif(div) beginBusy <= 1;cycle <= 10;temp_lo <= $signed(srcA) / $signed(srcB);temp_hi <= $signed(srcA) % $signed(srcB);endif(divu) beginBusy <= 1;cycle <= 10;temp_lo <= srcA / srcB;temp_hi <= srcA % srcB;endendelse if(cycle == 1) begincycle <= 0;Busy <= 0;hi <= temp_hi;lo <= temp_lo; end else begincycle <= cycle - 1;end

M_BE(字节扩展模块)

信号名 方向 位宽 描述
DMWr I 1 写DM使能信号
DMType I 3 DM字节扩展选择信号
A I 32 32位待写入地址
byteen O 4 字节使能信号
  • 结合课程组所给tb,新增字节扩展模块计算byteen,用于扩展sw、sh、sb指令
    always @(*) beginif(DMWr) begincase(DMTYpe)3'b010 : beginif(A[1:0] == 2'b00)      byteen = 4'b0001;else if(A[1:0] == 2'b01) byteen = 4'b0010;else if(A[1:0] == 2'b10) byteen = 4'b0100;else                     byteen = 4'b1000; end //sb3'b100 : beginif(A[1] == 1'b0) byteen = 4'b0011;else byteen = 4'b1100;end //sh3'b000 : beginbyteen = 4'b1111;end //swdefault : byteen = 4'b0000;endcaseendelse beginbyteen = 4'b0000;endend
  • tips:注意官方tb的写法如下:
if (m_data_byteen[3]) fixed_wdata[31:24] = m_data_wdata[31:24];
if (m_data_byteen[2]) fixed_wdata[23:16] = m_data_wdata[23:16];
if (m_data_byteen[1]) fixed_wdata[15: 8] = m_data_wdata[15: 8];
if (m_data_byteen[0]) fixed_wdata[7 : 0] = m_data_wdata[7 : 0];

所以传入的待写入DM的数据应该有所修改

assign m_data_wdata = (byteen_M == 4'b1100) ? {M_WD[15:0],{16{1'b0}}} :(byteen_M == 4'b0010) ? {{16{1'b0}},M_WD[7:0],{8{1'b0}}} :(byteen_M == 4'b0100) ? {{8{1'b0}},M_WD[7:0],{16{1'b0}}} :(byteen_M == 4'b1000) ? {M_WD[7:0],{24{1'b0}}} :M_WD;

M_DE(数据扩展模块)

信号名 方向 位宽 描述
A I 32 32位地址
DMTYpe I 3 数据扩展控制码
Din I 32 输入的32位待扩展数据
Dout O 32 扩展后的32位数据
  • 该模块用于扩展lw,lh,lhu,lb,lbu指令
  • Din直接接m_data_rdata
  • 具体实现(推荐用宏,笔者懒惰了就把初稿粘在这里)
  always @(*) begincase(DMTYpe)3'b000 : beginDout = Din;end //lw3'b011 : beginif(A[1] == 1'b0) Dout = {{16{1'b0}},Din[15:0]};else Dout = {{16{1'b0}},Din[31:16]};end //lhu3'b100 : beginif(A[1] == 1'b0) Dout = {{16{Din[15]}},Din[15:0]};else Dout = {{16{Din[31]}},Din[31:16]};end //lh3'b001 : beginif(A[1:0] == 2'b00) Dout = {{24{1'b0}},Din[7:0]};else if(A[1:0] == 2'b01) Dout = {{24{1'b0}},Din[15:8]};else if(A[1:0] == 2'b10) Dout = {{24{1'b0}},Din[23:16]};else Dout = {{24{1'b0}},Din[31:24]};end //lbu3'b010 : beginif(A[1:0] == 2'b00) Dout = {{24{Din[7]}},Din[7:0]};else if(A[1:0] == 2'b01) Dout = {{24{Din[15]}},Din[15:8]};else if(A[1:0] == 2'b10) Dout = {{24{Din[23]}},Din[23:16]};else Dout = {{24{Din[31]}},Din[31:24]};end //lbendcaseend

阻塞与转发

  • 转发:

    • MDU计算会产生结果M_MO,可以用mux与M_AO合并传入M_reg
    • 转发通路与P5相似
  • 阻塞:
    • 新增指令类型:mt(写HI/LO寄存器),mf(读HI/LO寄存器),md(乘除计算指令)
    • if(mt || md) Tuse_rs = 2’d1;
    • if(md) Tuse_rt = 2’d1;
    • if(mf) Tnew_D = 2’d2;
    • 乘除计算时要阻塞:wire Stall_md = (MDUop_D != 4’b0000) && (busy_E);

测试方案:

  1. 测试新增计算指令(注意addi是sign_extend):
34001ec2
3401123a
340225fb
3403220d
34040930
34051566
340621cd
34070ebc
34081ea8
34091278
340a1e24
340b0e6e
340c05e2
340d2134
340e23ab
340f145f
34102042
34111e1c
34121f59
34131098
34141466
3415072a
3416038f
341724f0
34180b08
34191f60
341a19f6
341b23e9
341c0f36
341d1796
341e105e
341f021b
00668825
00000000
3639633f
00000000
03396820
00000000
00000000
35ae1f1e
00000000
35c82f70
00000000
01084022
21ee0240
01082025
00000000
3058037e
0084d020
31a003dd
035a8020
02100019
0294a82a
02b54024
2316025a
3500b156
372d2471
35b13568
323a01cf
00000000
0231001a
0339c825
0339402b
00000000
350847b4
00000000
350fe133
01ef0019
02520018
00000000
00000000
3643b4d3
00000000
2070001a
3463ce4c
00636822
35acdfcb
00000000
3583209f
00000000
3472ec79
3645fd8c
3c170390
00000000
00a55820
016b3825
34e6d3bc
00c65025
35d301d6
00000000
014af824
3c03007a
37fce9ae
00000000
00000000
378c5cde
018c1820
00000000
00631824
0063702b
00000000
01ceb025
00000000
36d588b0
00000000
36ab1e6e
34260332
016b1022
31250339
0042102a
34590819
00000000
0339001b
321901c0
00000000
00f26820
00000000
00000000
35a88752
3508690c
00000000
3514735e
3c18012c
3685a13b
00002812
34b3926f
00000000
36783694
3713f608
2232038a
00000000
367149c2
3c00001d
00000000
0231b824
00000000
00000000
02f78820
00000000
363f6726
03ff5824
00000000
00000000
016ba822
00000000
36bebd8b
00000000
37ccfe84
366d014b
018c0022
33fb0172
3c0c01b4
3671f767
3630bd82
23d00251
02107020
00000000
00000000
35d71f6f
35d700f0
0000c810
0339d02a
00000000
00000000
2276001d
35bb0466
03600011
039cd022
00000812
343cb2b2
00000000
22b60230
3787d3f5
00000000
00000000
00e00011
014a0018
00000000
00000000
36bf02f6
37f57ff1
30180291
3c1c00ee
02b5b820
02f72020
00000012
01600011
00c6d824
00000000
00000000
0000c012
0318c025
371f465f
03ff1822
00000000
35370231
0063a02a
00000000
3698a1f7
00000000
20a301e2
03180019
00000000
36969de9
203502e4
02d64022
00000000
35118801
00000000
322f02ec
3634b2d7
0294e820
00000000
37b7a8a0
221f01d9
00000000
02f76824
01ad982b
00000000
00000000
36743150
02946820
00000000
35bd3726
03bd0018
2200017f
3534d76c
3c1c01e9
3c060336
0294e02a
22c2010b
379a2509
374fb240
00000000
  1. 测试存储指令
34001ec2
3401123a
340225fb
3403220d
34040930
34051566
340621cd
34070ebc
34081ea8
34091278
340a1e24
340b0e6e
340c05e2
340d2134
340e23ab
340f145f
34102042
34111e1c
34121f59
34131098
34141466
3415072a
3416038f
341724f0
34180b08
34191f60
341a19f6
341b23e9
341c0f36
341d1796
341e105e
341f021b
a0410000
a0420001
a0430002
  1. 测试跳转指令
    //···

思考题:

  1. 为什么需要有单独的乘除法部件而不是整合进 ALU?为何需要有独立的 HI、LO 寄存器?
  • 如果乘法部件整合到ALU中,那么在乘除法运算延迟的过程中,其他指令因为无法使用ALU而无法继续执行。而且可能超32位,ALU会产生溢出。而单独的乘除法部件可以保证在运算延迟的过程中,其他无关指令仍然可以正常访问ALU并执行,提高执行速度。
  • HI和LO寄存器是只与乘除法有关的用于存放结果的两个寄存器。由高内聚,低耦合原则,应该让其独立
  1. 真实的流水线 CPU 是如何使用实现乘除法的?请查阅相关资料进行简单说明。
  • 乘法:
    首先CPU会初始化三个通用寄存器用来存放被乘数,乘数,部分积的二进制数,部分积寄存器初始化为0!
    然后在判断乘数寄存器的低位是低电平还是高电平(0/1)!
    如果为0则将乘数寄存器右移一位,同时将部分积寄存器也右移一位,在位移时遵循计算机位移规则,乘数寄存器低位溢出的一位丢弃,部分积寄存器低位溢出的一位填充到乘数寄存器的高位,同时部分积寄存器高位补0!
    如果为1则将部分积寄存器加上被乘数寄存器,在进移位操作。
    当所有乘数位处理完成后部分积寄存器做高位乘数寄存器做低位就是最终乘法结果!
  • 除法:
    首先CPU会初始化三个寄存器,用来存放被除数,除数,部分商!余数(被除数与除数比较的结果)放到被除数的有效高位上!
    CPU做除法时和做除法时是相反的,乘法是右移,除法是左移,乘法做的是加法,除法做的是减法。
    首先CPU会把被除数bit位与除数bit位对齐,然后在让对齐的被除数与除数比较(双符号位判断)。
    这里说一下什么是双符号位判断:
    比如01-10=11(前面的1是符号位) 1-2=-1 计算机通过符号位和后一位的bit位来判断大于和小于,那么01-10=11 就说明01小于10,如果得数为01就代表大于,如果得数为00代表等于。
    如果得数大于或等于则将比较的结果放到被除数的有效高位上然后在商寄存器上商:1 并向后多看一位
    (上商就是将商的最低位左移1位腾出商寄存器最低位上新的商)
    如果得数小于则上商:0 并向后多看一位
    然后循环做以上操作当所有的被除数都处理完后,商做结果被除数里面的值就是余数!
  1. 请结合自己的实现分析,你是如何处理 Busy 信号带来的周期阻塞的?
  • 在HCU模块新增一个stall_md信号,如果busy为高电平stall_md置一
  1. 请问采用字节使能信号的方式处理写指令有什么好处?(提示:从清晰性、统一性等角度考虑)
  • 清晰性:当处理器执行 sb、sh 指令时,只要对地址的后两位进行解读,产生相应的 m_data_byteen 信号,就可以“通知” Testbench 中的 DM 该写入哪些字节,非常的清晰。
  • 统一性:统一了三种写指令的处理流程
  1. 请思考,我们在按字节读和按字节写时,实际从 DM 获得的数据和向 DM 写入的数据是否是一字节?在什么情况下我们按字节读和按字节写的效率会高于按字读和按字写呢?
  • 否,是一个字
  1. 为了对抗复杂性你采取了哪些抽象和规范手段?这些手段在译码和处理数据冲突的时候有什么样的特点与帮助?
  • 在MCU模块里我根据指令之间控制信号的相似性将指令分为一下几种类型:

    • calc_r
    • calc_i
    • load
    • store
    • branch
    • md
    • mt
    • mf
  • 所以在数据通路、转发、阻塞时都可以复用这些代码
  1. 在本实验中你遇到了哪些不同指令类型组合产生的冲突?你又是如何解决的?相应的测试样例是什么样的?
  • 指令分类之后,冲突类型和P5几乎一样,除去乘除指令。更改了乘除指令的Tuse和Tnew就好
  1. 如果你是手动构造的样例,请说明构造策略,说明你的测试程序如何保证覆盖了所有需要测试的情况;如果你是完全随机生成的测试样例,请思考完全随机的测试程序有何不足之处;如果你在生成测试样例时采用了特殊的策略,比如构造连续数据冒险序列,请你描述一下你使用的策略如何结合了随机性达到强测的效果。
  • 我是手动构造样例的
  • 主要是测试不同指令类型之间的冲突(需要阻塞 + 转发的情况),再和课程组给的mars对拍

附录:

  1. 我的课上题目:

2022 buaa CO P6(Verilog实现流水线CPU(plus))相关推荐

  1. Verilog流水线CPU设计(超详细)

    上篇:Verilog单周期CPU设计(超详细) 本篇完整工程下载链接,已于19.12.17更新 实验 流水线CPU 一.设计目的与要求 1.1 实验内容 1.2 实验要求 1.3 实验创新 二.课程设 ...

  2. 流水线cpu —Verilog HDL

    一.准备工作 先看看书(<计算机原理与设计 Verilog HDL版>),搞懂一点原理.然后照着书上的代码写一写(用8.4的就可以了,不用8.6的). 注意mux2x32,mux4,cla ...

  3. 基于MIPS32的流水线CPU设计与实现(verilog)

    文章目录 1.实验内容 2.实验要求 3. 实验难点 4. 模块详细分析 4.1 取指令部分(IF) 4.1.1 PCAdd4 4.1.2 PC 寄存器的设计与实现 4.1.3 指令存储器的设计与实现 ...

  4. BUAA(2021秋)计算机硬件基础(软件学院计组)P4——用Logisim实现流水线CPU(含测试数据供自测)

    计算机硬件基础(软件学院计组)P4--用Logisim实现流水线CPU 目录 计算机硬件基础(软件学院计组)P4--用Logisim实现流水线CPU 实验内容 实验要求 提交要求 题解 前言及其预备知 ...

  5. MIPS32的流水线CPU测试代码(verilog)

    在流水线CPU的实验过程中,发现有以下注意的地方: 1.PC寄存器和IF/ID寄存器需连接stall输入信号. 2.IF/ID寄存器和ID/EX寄存器需连接condep输入信号. 3.寄存器堆在时钟周 ...

  6. verilog搭建单周期CPU与流水线CPU

    目录 实现功能与搭建环境介绍 单周期CPU 整体框图 具体代码 顶层模块 取值 译码 执行 访存 写回 流水线CPU 整体框图 前置知识及思路探讨 如何让流水线流起来~ Hazard_detect模块 ...

  7. (Verilog)多周期CPU设计

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

  8. 北航2021届计组 -- 流水线CPU

    北航2021届计组流水线CPU设计 文章目录 北航2021届计组流水线CPU设计 一.设计想法 1.1 我的CPU的整体架构 1.2 从单周期到流水线 1.2.1 修改原单周期CPU 1.2.2 流水 ...

  9. 手搓单周期、流水线CPU

    实验指导书连接实验概述 - 计算机设计与实践(2022夏季) | 哈工大(深圳) (gitee.io) 实现的18条指令如下: [注释:(r)表示寄存器r的值,Mem[addr]表示地址为addr的存 ...

最新文章

  1. 读自动驾驶激光雷达物体检测技术(Lidar Obstacle Detection)(1):Stream PCD流式载入激光点云数据
  2. muduo之EventLoop
  3. Windows 平台下解决httpd.exe: syntax error on line 39
  4. java自动化测试报告_Java自动化测试框架-10 - TestNG之测试结果篇(详细教程)
  5. [2021.1.27多校省选模拟10]跑步(线段树合并)
  6. oracle erp 操作手册,OracleERP操作手册
  7. 各厂家服务器存储默认登录信息
  8. 【MySQL源码】01 MySQL源码总述
  9. 扫描到pc服务器位置,打印机s2520 扫描到PC服务器之通讯录怎么设置
  10. windows各版本序列号集合
  11. memory exhausted mysql 42000 1064
  12. 创宇猎幽斩获“2022年网络安全优秀创新成果大赛”三等奖!
  13. 每个程序员都应该读的非编程书
  14. lamp环境实战操作建立完全属于自己的博客站点
  15. python镜像安装是什么意思_通过PyPI镜像安装Python包
  16. 国培南通之行的感悟——(其一)
  17. centos mysql ssh连接,使用SSH隧道连接MYSQL
  18. 职业价值观免费免登陆直接在线测试
  19. 用RVIZ2显示毫米波雷达点云
  20. python编程入门指南明日科技pdf-零基础学Python PDF 全彩影印版

热门文章

  1. CodeForces 891E Lust(生成函数)
  2. Masonry的使用,动画,出现问题解决等
  3. Ubuntu18.04配置双网卡上网
  4. kds官方android客户端,电子厨打设置(KDS/ADS)
  5. 912 计算机考研专业课,2019清华大学计算机考研912考试教材如何选择?
  6. python计算一元二次方程a=2.b=3c=1_Python1日一练03-一元二次方程的计算
  7. 2022-2028年中国植物蛋白饮品行业市场全景调研及战略咨询研究报告
  8. mybatis-plus进阶教程!超详细使用方法解析!
  9. 前端鼠标触碰实现遮罩方法
  10. 宝塔接php支付,支付宝免签约辅助AlipaySupervisor宝塔面板使用教程