又见到verilog了,verilog一定要记得初始化和清零啊!!!

1 教程中的设计和测试说明

1.1 基本思路

  • 在 P3,小编已经使用 Logisim 工具设计出了 MIPS 单周期处理器的电路图。在P4,小编要做的是完成从 Logisim 电路到 Verilog 代码的映射。用verilogHDL语言描述单周期CPU电路。

1.2 设计要求

  • 支持的指令集:{addu, subu, ori, lw, sw, beq, lui, jal, jr,nop}

  • 支持同步复位

  • IM和DM的容量有所变化

    • IM容量为32bit*1024字 reg [31:0] IM_ROM [0:1023];

    • DM容量为32bit*1024字 reg [31:0] DM_RAM [0:1023];

  • 顶层文件为mips.v,接口定义如下:

文件 模块接口定义
mips.v module mips(clk,reset); input clk;//clock input reset;//reset

2 基于P3对P4的思考

虽然P4是P3的代码实现,但是我在一些地方对P4进行了优化

在P3上对P4的完善

  • 在每个模块输入端口都添加mux选择器,选择输入什么数据,虽然大部分情况都是输入确定的数据来源,比如说IM_rs进入GRF_A1,IM_rt进入GRF_A2

  • 这么做的好处是,新增加新的指令时如果某个输入端有新的数据来源,可以避免添加新的mux4_1以及新的数据来源选择控制信号造成bug,会比较方便。

  • 添加mux4_1数据选择器仅在模块的输入端,输出端的数据是给输入端使用的,所以无需考虑

先判断是组合逻辑还是时序逻辑

  • 只有PC,GRF写入逻辑,DM写入逻辑是时序逻辑,其余都是组合逻辑

  • GRF输出逻辑和DM的输出逻辑都是组合逻辑

  • 组合逻辑无时无刻都在工作,而时序逻辑是在时钟上沿是改变寄存器的值

3 各模块verilog实现

  • 最后的logisim效果图

3.1 PC

  • PC的主要功能是完成输出当前指令地址。

  • 复位后,PC指向0x0000_3000。此处为第一条指令的地址。

信号名 描述
input clk 时钟信号
input reset 同步复位信号,复位到0x0000_3000
input [31:0] NPC 下一条指令所在IM地址
output reg [31:0] PC 当前指令所在IM地址

3.2 NPC

  • NPC的功能是计算下一条指令所在地址。

信号名 描述
input [15:0] IM_imm16 指令的16位立即数,IM_instr[15:0]
input [25:0] IM_imm26 指令的26位立即数,IM_instr[25:0]
input [31:0] reg_addr 寄存器中保存的32位数据(需要从GRF中读取)
input [31:0] PC 当前指令所在的IM地址
input [2:0] NPCop NPC功能选择控制信号 000:PC+4 001:PC+4+sign_extend(imm16||00) 010:PC[31:28]||imm26||00 011:rs_addr
output reg [31:0] NPC 下一条指令所在的IM地址
output [31:0] PC_4 PC+4的值

3.3 IM

  • IM功能是保存所有指令,并输出当前指令。

信号名 描述
input [31:0] PC 当前指令所在的IM地址
output [31:0] IM_instr 当前指令,为IM_ROM[PC[11:2]]

3.4 GRF

  • 端口定义

信号名 描述
input [31:0] PC 当前指令所在的IM地址
input [4:0] GRF_A1 5位地址输入信号,指定32个寄存器中的一个,将其中存储的数据读出到RD1
input [4:0] GRF_A2 5位地址输入信号,指定32个寄存器中的一个,将其存储的数据读出到RD2
input [4:0] GRF_A3 5位地址输入信号,指定32个寄存器中的一个作为写入的目标寄存器
input [31:0] GRF_WD 32位数据输入信号
input clk 时钟信号
input reset 同步复位信号
input RegWrite 写使能信号
output reg [31:0] GRF_RD1 输出A1指定的寄存器中的32位数据
output reg [31:0] GRF_RD2 输出A2指定的寄存器中的32为数据
  • 功能定义

功能 描述
读出数据 组合逻辑:将GRF_A1和GRF_A2地址所对应的寄存器的值通过GRF_RD1和GRF_RD2读出
写入数据 时序逻辑:当RegWrite为1且时钟上升沿来临时,将GRF_WD的值写入到GRF_A3地址所对应的寄存器中。0号寄存器的值始终为0。
同步复位 当reset为1且时钟上升沿来临时,将所有寄存器的值清零。

3.5 ALU

  • ALU的功能是执行32位加、减、或运算等功能

信号名 描述
input [31:0] ALU_A 输入的第一个32位操作数
input [31:0] ALU_B 输入的第二个32位操作数
input [4:0] ALU_S 补充运算数,一般为shamt
input [2:0] ALUop ALU输出的32位计算结果
output reg [31:0] ALU_C ALU功能选择控制信号 000:ALU_A&ALU_B 001:ALU_A|ALU_B 010:ALU_A+ALU_B 011:ALU_A-ALU_B 100:直接输出ALU_B

3.6 EXT

  • EXT的功能是为位扩展,将16位立即数扩展为32位立即数。

信号名 描述
input [15:0] EXT_imm16 16位立即数输入
input [2:0] EXTop EXT功能选择信号 000:符号扩展 001:zero扩展 010:加载至高位,低位补0
output reg [31:0] EXT_imm32 32位扩展后的立即数输出

3.7 CMP

  • CMP的功能是输出条件比较的结果

信号名 描述
input [31:0] CMP_A 输入的第一位32位比较数
input [31:0] CMP_B 输入的第二位32位比较数
input [3:0] CMPop CMP比较功能选择信号
output reg cmp_sign 1位结果输出 0:不符合判断条件 1:符合判断条件

3.8 DM

  • 端口定义

信号名 描述
input [31:0] PC 当前指令所在的IM地址
input clk 时钟信号
input reset 同步复位信号
imput MemWrite 写入使能信号 0:不可写入DM 1:可写入DM
input [31:0] DM_A DM数据地址
input [31:0] DM_data DM输入的数据
output reg [31:0] DM_out DM输出数据
  • 功能实现

功能 描述
读出数据 组合逻辑:将DM_A地址所对应DM_RAM的值通过DM_out读出
写入数据 时序逻辑:当MemWrite为1且时钟上升沿来临时,将Memdata的值写入到DM_A地址所对应的主存中。
同步复位 当reset为1且时钟上升沿来临时,将所有寄存器DM_RAM的值清零。

3.9 splitter实现

  • 什么是splitter?

  • 在顶层模块对需要splitter的变量进行assign

assign IM_op=IM_instr[31:26];
assign IM_rs=IM_instr[25:21];
assign IM_rt=IM_instr[20:16];
assign IM_rd=IM_instr[15:11];
assign IM_shamt=IM_instr[10:6];
assign IM_func=IM_instr[5:0];

4 控制器实现

控制器实现分为两个部分:AND_Logic和OR_Logic

4.1 学会用宏定义macro

  • 将需要宏定义的部分保存在macro.v中,需要使用的时候,在模块头

`include "macro.v"

4.2 控制信号列表

  • 将控制信号分为三类:

    • 使能信号

      • RegWrite:GRF写使能信号

      • Memwrite:DM写使能信号

    • 数据来源选择信号

      • GRF_A1_Sel:GRF取操作数寄存器地址选择信号

      • GRF_A2_Sel:GRF取操作数寄存器地址选择信号

      • ALU_A_Sel:ALU第一个操作数来源选择信号

      • ALU_B_Sel:ALU第二个操作数来源选择信号

      • ALU_S_Sel:ALU补充操作数来源选择信号

      • CMP_A_Sel:CMP第一个比较数来源选择信号

      • CMP_B_Sel:CMP第二个比较数来源选择信号

      • DM_A_Sel:DM数据地址来源选择信号

      • DM_data_Sel:DM写入数据来源选择信号

      • GRF_WD_Sel:GRF回写数据选择信号

      • GRF_A3_Sel:GRF回写寄存器地址选择信号

    • 模块功能选择信号

      • ALUop:ALU模块功能选择信号

      • EXRop:EXT模块功能选择信号

      • CMPop:CMP模块功能选择信号

      • DMop:DM模块功能选择信号

  • 控制信号具体解释表

信号名 描述
input [5:0]op; instr[31:26]
input [5:0] func; instr[4:0]
input cmp_sign; CMP模块的输出,条件判断信号,用于条件转移类指令
output RegWrite; GRF模块写使能信号(是否向GRF写入数据)0:不能向GRF中写入数据 1:能向GRF中写入数据
output MemWrite; DM模块写使能信号(是否向DM写入数据) 0:不能向DM中写入数据 2:能向DM中写入数据
output [2:0] EXTop; EXT模块功能选择信号(选择哪种扩展) 000:符号扩展 001:0扩展 010:加载立即数至高位,低位补0
output [2:0] ALUop; ALU模块功能选择信号(选择哪种计算) 000:A&B 001:A|B 010:A+B 011:A-B 100:直接输出B
output [3:0] CMPop; CMP模块功能选择信号(选择哪种比较结果) 0000:A==B 0001:A>B 0010:A<B 0011:A!=B 0100:A>=B 0101:A<=B 0110:A==0 0111:A>0 1000:A<0 1001:
output [2:0] NPCop; NPC模块功能选择信号(选择那种跳转)000:PC+4 001:PC+4+sign_ext(IM_imm16||00) 010:PC[31:28]||IM_imm26||00 (jal) 011:GRF[rs_addr] (jr)
output [1:0] DMop; DM模块功能选择信号(选择输出字,字节,半字) 00:字 01:符号扩展字节 10:符号扩展半字
output [1:0] GRF_A1_Sel; 选择GRF的A1的数据来源 00:rs
output [1:0] GRF_A2_Sel; 选择GRF的A2的数据来源 00:rt
output [1:0] GRF_A3_Sel; 选择GRF的A3的数据来源 00:rt 01:rd 10:31(jal)
output [1:0] GRF_WD_Sel; 选择GRF的写入数据WD的数据来源 00:ALU的C 01:DM的输出 10:PC+4 (jal) 11:32‘d0或32’d1
output [1:0] ALU_A_Sel; 选择ALU的操作数A的数据来源 00:GRF的RD1
output [1:0] ALU_B_Sel; 选择ALU的操作数B的数据来源 00:GRF的RD2 01:扩展后的32位立即数
output [1:0] ALU_S_Sel; 选择ALU的补充操作数S的数据来源 00:IM_shamt
output [1:0] CMP_A_Sel; 选择CMP的比较数A的数据来源 00:GRF的RD2 01:扩展后的32位立即数
output [1:0] CMP_B_Sel; 选择CMP的比较数B的数据来源 00:GRF的RD2 01:扩展后的32位立即数
output [1:0] DM_A_Sel; 选择DM数据地址的来源 00:ALU_C
output [1:0] DM_data_Sel; 选择DM输入数据的来源 00:GRF_RD2

5 顶层模块mips的编写

5.1 顶层mips模块是做什么用的呢?

  • 是为了连接各个模块(PC,NPC,IM,),mux选择器,生成完整的数据通路

5.2 顶层mips模块包括哪些部分?

  • wire型信号声明

  • 各个模块实例化

    .模块输入端口名称(输入信号)

 GRF grf(.PC(PC),.GRF_A1(GRF_A1),.GRF_A2(GRF_A2),.GRF_A3(GRF_A3),.GRF_WD(GRF_WD),.clk(clk),.reset(reset),.RegWrite(RegWrite),.GRF_RD1(GRF_RD1),.GRF_RD2(GRF_RD2));
  • 指令splitter

  • 模块输入数据的mux4_1选择器

    mux4_1_32 mux_GRF_WD_Sel(.A(ALU_C),.B(DM_out),.C(PC_4),.Sel(GRF_WD_Sel),.Y(GRF_WD));

5.3 有哪些wire型信号需要在模块中声明?

  • 在我的设计中,我认为是模块、splitter、mux选择器的输出信号

    • NPC,PC,IM,DM,ALU,CMP,GRF模块的output

    • mux多路选择器的output

    • controller模块的output

    • IM_splitter的output

6 具体实现

6.1 如何完善数据通路?

  • 在顶层mips模块中添加新的数据来源

  • 在顶层mips模块中进行运算,比如P3第三题的指令计算字节数中0和1的个数是否相等

  • 在各个模块中根据新的控制信号增加新的功能,alu的新的计算,cmp的新的比较方法

6.2 如何完善控制信号?

  • 在controller模块里修改

7 新指令分类及其侧重点

7.1经过对上机题目的分析,上机考核的指令分为三类:

  • 转移类指令

  • 计算类指令

  • 访存类指令

7.2 转移类指令

7.2.1 条件转移指令

  • 主要为beq,bgez等B类转移指令组成

  • 控制器中NPCop信号生成

if((beq==1'b1||bgez==1'b1)&&(cmp_sign==1'b1))beginNPCop=3'b000;
end

7.2.2 非条件转移指令

  • 主要为jal,jr,jalr这一类J类转移指令组成

  • 控制器中NPCop信号生成(不用判断cmp_sign信号是否有效)

NPCop[2]=1'b0;
NPCop[1]=jr|jal;
NPCop[0]=jr;

7.3 计算类指令

  • 一般涉及到回写步骤,不涉及访存步骤,重点在ALU或者CMP模块增加新的运算操作!!!

7.4 访存类指令

  • 都涉及到访存步骤,可能涉及到回写步骤

8 如何添加一条新指令

  • 在第七点中我将指令分为三类,分析了每个类型的指令的侧重点,但是小编依然觉得,加指令还是要按照常规步骤来,将指令执行的五个步骤都考虑一遍。

8.1 大致思路

  • step1:先根据五个步骤在纸上简略画出数据通路以及确定要添加和修改的控制信号(非常重要!!!)

  • step2:在controller里面添加指令标签

  • step3:添加新指令的控制信号

  • step4:对需要添加新功能的模块进行修改,完善数据通路

8.2 取指令

取指令涉及模块:NPC,IM

取指令要素:

  • 读取IM

  • 计算NPC,更新PC值

需要考虑的控制信号:

  • NPCop

    • 条件转移类指令

    • 非条件转移类指令

8.3 取操作数

取操作数模块:EXT,GRF (GRF是从寄存器堆里取操作数,EXT是将16位offset扩展成操作数)

要素:

  • GRF操作数地址选择 (一般IM_rs对GRF_A1,IM_rt对GRF_A2)

  • 扩展数据来源选择 (一般为IM_imm16)

  • 如何扩展

需要考虑的控制信号:

  • EXTop

  • GRF_A1_Sel

  • GRF_A2_Sel

8.4 执行

执行模块:ALU,CMP

要素:

  • ALU_A的数据来源

  • ALU_B的数据来源

  • ALU执行哪种运算

  • CMP_A的数据来源

  • CMP_B的数据来源

  • CMP执行哪种比较

需要考虑的控制信号:

  • ALUop

  • CMPop

  • ALU_B_Sel

  • ALU_A_Sel

  • CMP_A_Sel

  • CMP_B_Sel

8.5 访存

访存模块:DM

访存,顾名思义,分为两个部分:访和存

访(读出数据) 组合逻辑

要素:

  • 读出数据的地址DM_A

  • 读出什么大小的数据:word?half word?byte?

需要考虑的控制信号:

  • DMop

  • DM_A_Sel

存(写入数据) 时序逻辑

要素:

  • 是否写入

  • 写入数据的地址DM_A

  • 写入数据的来源DM_data

  • 写入多大的数据:word?half word?byte?

需要考虑的控制信号:

  • Memwrite

  • DMop

  • DM_A_Sel

  • DM_data_Sel

8.6 回写

回写模块:GRF

要素:

  • 是否回写

  • 写入寄存器地址选择

  • 写入数据来源选择

需要考虑的控制信号:

  • RegWrite

  • GRF_A3_Sel

  • GRF_WD_Sel

9 如何进行ISE仿真测试?

9.1 生成八进制代码

  • 课上使用魔改MARS,导入新指令class,编写程序

  • 编译后,导出八进制代码到code.text

9.2 编写testbench

  • testbench代码如下

module tb;// Inputsreg clk;reg reset;
​mips uut (.clk(clk), .reset(reset));initial beginclk = 0;reset = 1;#3 reset=0;endalways #5 clk=~clk;
endmodule

9.3 进行ISE仿真

  • 将需要信号添加到波形图中

  • 如何添加除了顶层信号外的其他信号?

  • 进行仿真

  • 看哪些地方?可能会有什么bug?

10 可能出现的bug和小tips

  • 打代码是需要全神贯注,不要敲错数字,比如macro.v中op码和func码

  • 遇到wa该如何检查?

    • 检查数据通路,在顶层mips中检查(主要是)mux选择器的输入信号是否正确(检查连线)

    • 检查控制器模块的控制信号是否都考虑了,是否有遗漏的未修改的控制信号

    • 检查模块内部功能是否完善,需要检查的有ALU,CMP,NPC,EXT,DM模块

  • reg信号在参与计算之前一定要初始化和清零!!!

    • 计数器等reg型变量的清零

always @(*)beginnum=5'd0;//num是计数器,要清零//开始计数
​
end
  • CMP比较器注意是有符号比较,要加$signed()

  • 为了防止多写一个mux选择器代码,尽量都用现成的mux4_1选择器

  • 这次的IM和DM的地址取[11:2],一共十位,IM_ROM和DM_RAM在声明和初始化的时候不要弄错了

  • mux4_1选择器要注意输入信号的位数 分为32位和5位

P4 用verilog描述单周期CPU的学习笔记和总结(基于P3)相关推荐

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

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

  2. (Verilog)单周期CPU设计

    (Verilog)单周期CPU设计 首先是基础资料部分(借用学校资料): 一.实验内容 设计一个单周期CPU,该CPU至少能实现以下指令功能操作.需设计的指令与格式如下: ==> 算术运算指令 ...

  3. 单周期CPU设计【Verilog】

    第一章 单周期CPU的设计原理 1.1 单周期CPU概述 1.2 CPU工作原理 第二章 单周期CPU的设计内容 2.1 指令系统的设计 2.1.1 概述 2.1.2 运算类指令的设计 2.1.3 传 ...

  4. 【计算机组成原理】实验4:单周期CPU(Verilog)中海大

    [计算机组成原理]实验4 使用Verilog语言实现一个单周期CPU,测试平台:Vivado ①部分代码: single_cycle_cpu.v: `timescale 1ns / 1ps`defin ...

  5. 31条指令单周期cpu设计(Verilog)-(十)上代码→顶层模块设计总结

    说在前面 开发环境:Vivado 语言:Verilog cpu框架:Mips 控制器:组合逻辑 设计思路 按照预先设计好的数据通路图将各个模块连接起来 `timescale 1ns / 1ps mod ...

  6. 31条指令单周期cpu设计(Verilog)-(二)总体设计

    目录 31条指令单周期cpu设计(Verilog)-(一)相关软件 31条指令单周期cpu设计(Verilog)-(二)总体设计 31条指令单周期cpu设计(Verilog)-(三)指令分析      ...

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

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

  8. 单周期CPU设计(Verilog)

    2017/06/08: 当时单周期cpu写的比较仓促,没有深入的进行调试,我准备在放假的时候重构一下代码, 然后把博文改进一下,现在实在没有时间,很抱歉~ 不过多周期我有调试过的,所以有需要的可以移步 ...

  9. 单周期CPU——verilog语言实现

    单周期CPU的设计与实现 关于单周期CPU的设计问题,相信各位在课程上也有所学习,以下是个人的一些理解 整个项目的资源下载:这里写链接内容 实验内容 基本要求 PC和寄存器组写状态使用时钟触发,这是必 ...

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

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

最新文章

  1. LANMP框架搭建——源码编译
  2. 字节输入流 InputStream
  3. linux+tomcat+apache
  4. C的无符号数据类型int,short,byte 转为 Java对应的数据long,char,short
  5. 前端学习(1734):前端系列javascript之添加动画
  6. 关于样式表setStyleSheet
  7. gps test free android,GPSTest | F-Droid - Free and Open Source Android App Repository
  8. 【BZOJ1236】KPSUM,记数类问题(乱搞)
  9. MNIST数据集手写数字识别(二)
  10. 手机端仿ios的银行下拉脚本五
  11. C++ 引用计数技术及智能指针的简单实现
  12. 测试一段C代码的执行时间(windows系统和ubuntu系统)
  13. 利用ICMP协议的PING命令获取客户端当前网络质量 by徐文棋
  14. python重装显示already installed_tensorflow安装出现Requirement already satisfied问题,这个是网络问题吗?...
  15. getline 两次回车 解决办法
  16. 软考知识点---20标准化与法律法规
  17. Java: Tomcat到底是干嘛的?
  18. 让人感慨的21个故事
  19. MIPI传输全局流程图
  20. 联想卡在logo界面_联想笔记本开机卡在lenovo画面无法进入桌面

热门文章

  1. 谷歌浏览器安装插件的方法步骤
  2. 局域网内的服务器搭建(VMware)
  3. 软测工具Testbed的使用以及动态测试实例
  4. 为什么SSD目标检测算法对小目标检测的效果不好
  5. v-distpicker
  6. 形式语言与自动机总结笔记
  7. 用PyTorch完成手写数字识别
  8. 从单机到分布式数据库存储系统的演进
  9. Java 动态编译基础学习
  10. Flutter - 微信朋友圈效果实现