实验目的

  • 熟悉并掌握 MIPS 计算机中寄存器堆的原理和设计方法
  • 理解源操作数/目的操作数的概念

实验环境

  • Vivado 集成开发环境

MIPS寄存器

  • 寄存器R0的值恒为0

模块接口设计

1个写端口和2个读端口

名称 宽度 方向 描述
clk 1 IN 时钟信号
raddr1 5 IN 寄存器堆读地址1
rdata1 32 OUT 寄存器堆返回数据1
raddr2 5 IN 寄存器堆读地址2
rdata2 32 OUT 寄存器堆返回数据2
we 1 IN 寄存器堆写使能
waddr 5 IN 寄存器堆写地址
wdata 32 IN 寄存器堆写数据

寄存器堆(regfile)实现了32个32位通用寄存器。

  • 可以同时进行两个寄存器的读操作和一个寄存器的写操作。
  • 写:写使能信号(we)为1时写有效,为0时无效。(write enable
  • 读:读操作可以同时读两个寄存器。
  • 同时对同一个寄存器进行读写时,读的数据为旧的数据。
  • 读写均为同步。
  • 0号寄存器恒为0。

设计代码

`define REG_DATA_WIDTH 31:0
`define REG_NUM 31:0
`define REG_ADDR_WIDTH 4:0
`define REG_ADDR_BIT 5 // 地址线宽
`define REG_DATA_BIT 32 // 数据线宽
module regfile(
input clk,
input [`REG_ADDR_WIDTH] raddr1,
input [`REG_ADDR_WIDTH] raddr2,
input we, // 写使能
input [`REG_ADDR_WIDTH] waddr, // 写地址
input [`REG_DATA_WIDTH] wdata, // 写数据
output reg [`REG_DATA_WIDTH] rdata1,
output reg [`REG_DATA_WIDTH] rdata2
); // 数组表示寄存器堆
reg [`REG_DATA_WIDTH] mips_regfile [`REG_NUM]; // 读1
always @(posedge clk) begin
if (raddr1 == {`REG_ADDR_BIT{1'b0}}) begin
rdata1 <= {`REG_DATA_BIT{1'b0}};
end
else begin
rdata1 <= mips_regfile[raddr1];
end
end
// 读2
always @(posedge clk) begin
if (raddr2 == {`REG_ADDR_BIT{1'b0}}) begin
rdata2 <= {`REG_DATA_BIT{1'b0}};
end
else begin
rdata2 <= mips_regfile[raddr2];
end
end
// 写
always @(posedge clk) begin
if (we == 1'b1 ) begin
if (waddr == {`REG_ADDR_BIT{1'b0}}) begin
mips_regfile[0] <= {`REG_DATA_BIT{1'b0}};
end
else begin
mips_regfile[waddr] <= wdata;
end
end
else begin
mips_regfile[0] <= {`REG_DATA_BIT{1'b0}};
end
end endmodule

测试

测试代码

`timescale 1ns / 1ps

`define REG_DATA_WIDTH 31:0
`define REG_NUM 31:0
`define REG_ADDR_WIDTH 4:0
`define REG_ADDR_BIT 5
`define REG_DATA_BIT 32
module sim();
reg clk;
reg [`REG_ADDR_WIDTH] raddr1;
reg [`REG_ADDR_WIDTH] raddr2;
reg we; // 写使能
reg [`REG_ADDR_WIDTH] waddr; // 写地址
reg [`REG_DATA_WIDTH] wdata; // 写数据
wire [`REG_DATA_WIDTH] rdata1;
wire [`REG_DATA_WIDTH] rdata2; integer i;
regfile u0 (
.clk(clk),
.raddr1(raddr1),
.raddr2(raddr2),
.we(we),
.waddr(waddr),
.wdata(wdata),
.rdata1(rdata1),
.rdata2(rdata2)
);
initial begin
clk = 1;
forever begin
#10 clk = ~clk;
end
end initial begin
raddr1 = `REG_ADDR_BIT'd0;
raddr2 = `REG_ADDR_BIT'd0;
we = 1'b0;
waddr = `REG_ADDR_BIT'd0;
wdata = `REG_DATA_BIT'd0; // 写数据
#100
we = 1'b1;
wdata = `REG_DATA_BIT'hFF;
for (i = 0; i < `REG_DATA_BIT; i = i + 1) begin
waddr = i;
wdata = wdata + `REG_DATA_BIT'h100;
#20;
end
// 读数据
we = 1'b0; for (i = 0; i < `REG_DATA_BIT; i = i + 1) begin
raddr1 = i;
raddr2 = `REG_DATA_BIT - raddr1 - 1;
#20;
end // 读写相同
// 读到的数据是旧数据
we = 1'b1;
wdata = `REG_DATA_BIT'h100;
for (i = 0; i < `REG_DATA_BIT; i = i + 1) begin
raddr1 = i;
raddr2 = i;
waddr = i;
wdata = wdata - `REG_DATA_BIT'h1;
#20;
end we = 1'b0;
#100 $finish; end
endmodule

测试波形

写数据:

从 0号寄存器开始到 31号寄存器,分别写入 01ff到 20ff。

读数据:

读地址 1和读地址 2分别读寄存器值,0号寄存器读得值为 0。其余寄存器读值正确。

结果分析

先进行写数据测试,从 0号寄存器开始到 31号寄存器,分别写入 01ff20ff。然后进行读数据测试,发现 0号寄存器值为 0,其余寄存器的值符合预期。当同时写和读,即写地址和读地址相同,且写使能时,发现读到的数据为旧数据,而写入的数据不会冲突。

MIPS寄存器堆的更多相关文章

  1. 自己动手写CPU——寄存器堆、数据存储器(基于FPGA与Verilog)

    上一篇写的是基本的设计方案,由于考研复习很忙,不知道下一次什么时候才能打开博客,今天就再写一篇.写一写CPU中涉及到RAM的部件,如寄存器堆.数据存储器等. 大家应该在大一刚接触到计算机的时候就知道R ...

  2. 【CPU微架构设计】分布式多端口(4写2读)寄存器堆设计

    寄存器堆(Register File)是微处理的关键部件之一.寄存器堆往往具有多个读写端口,其中写端口往往与多个处理单元相对应.传统的方法是使用集中式寄存器堆,即一个集中式寄存器堆匹配N个处理单元.随 ...

  3. 手写一个简易的多周期 MIPS CPU

    一点前言 多周期 CPU 相比单周期 CPU 以及流水线 CPU 实现来说其实写起来要麻烦那么一些,但是相对于流水线 CPU 和单周期 CPU 而言,多周期 CPU 除了能提升主频之外似乎并没有什么卵 ...

  4. MIPS指令 MIPS架构

    华中科技大学 - 计算机组成原理 华中科技大学 - 计算机硬件系统设计 Microprocessor without Interlocked Pipleline Stages 无内部互锁流水级的微处理 ...

  5. MIPS 汇编指令学习

    MIPS 寄存器 MIPS comes with 32 general purpose registers named $0. . . $31Registers also have symbolic ...

  6. uvm_reg_file——寄存器模型(十四)

    有了uvm_reg_field, uvm_reg, uvm_block, 也许我们需要跟大的uvm_file,这就是传说中的寄存器堆. // // CLASS: uvm_reg_file // Reg ...

  7. iot漏洞mips汇编基础

    1 基础概念 MIPS(Microprocessor without Interlocked Piped Stages architecture),是一种采取精简指令集(RISC)的处理架构,由MIP ...

  8. verilog实现16位五级流水线的CPU带Hazard冲突处理

    verilog实现16位五级流水线的CPU带Hazard冲突处理 该文是基于博主之前一篇博客http://www.cnblogs.com/wsine/p/4292869.html所增加的Hazard处 ...

  9. OpenRisc-47-or1200的WB模块分析

    引言 “善妖善老,善始善终”,说的是无论什么事情要从有头有尾,别三分钟热度. 对于or1200的流水线来说,MA阶段是最后一个阶段,也是整条流水线的收尾阶段,负责战场的清扫工作.比如,把运算指令的运算 ...

  10. OpenRisc-44-or1200的pipeline整体分析

    引言 我们在前面分析了ORPSoC,or1200_top,和or1200_cpu的整体架构,在最近,我们也分析了or1200的pipeline(流水线)中的两级,EX级和IF级. 但是,我们还没有从宏 ...

随机推荐

  1. jmeter跨线程组引用变量的3种方法

    利用BeanShell后置处理程序将参数设置为全局变量,用于跨线程传参(注:1.把提取变量的线程组放到引用变量的线程组前2.在测试计划中勾选"独立运行每个线程组") 方法1(jme ...

  2. 【使用git之旅】

    前言 在学习各种语言的时候我总喜欢把例子改成有自己想法并且有趣的程序, 但是时间一长,我发现在本地管理很麻烦,于是乎想到了github和gitee, 然后昨晚一时兴起,就开始了学习,开个博客记录一下我 ...

  3. 一篇文章告诉你什么是Java内存模型

    在上篇 并发编程Bug起源:可见性.有序性和原子性问题,介绍了操作系统为了提示运行速度,做了各种优化,同时也带来数据的并发问题, 定义 在单线程系统中,代码按照顺序从上往下顺序执行,执行不会出现问题. ...

  4. 使用openlayers扩展插件ol-ext设置地图指定区域高亮

    最近要实现一个从底图向上发光的功能,着实纠结了好久,起初像是使用polygon 颜色透明度来实现,但毕竟底图不亮,增加图层效果不理想呀 一.ui设计是这样 二.绘制面 为底图增加一个MultiPoly ...

  5. C# decimal double 获取一组数字 小数点后最多有几位

    有一组数字,想判断一组数字中最多的有几位小数,乘以10的指定幂,转为整数,此处教大家一个高级的写法,拒接无脑for循环 decimal: decimal[] numbers = new decimal ...

  6. 【IntelliJ】添加javaweb、tomcat语法支持

    默认情况下:idea不支持javaweb的语法 但,我们的期望是: 解决方法:配置tomcat如下: (假设你已经配置好了tomcat)接下来: 1.打开[项目结构(快捷键:Ctrl + Shift ...

  7. 从源码级剖析Java类加载原理

    相信大多数熟悉Java的研发工程师,都知道Java类加载原理:Java中的类是由类加载器采用双亲委派机制进行加载.其中,Java核心库中实现了三种类型的类加载器,它们分别是:引导类加载器Bootstr ...

  8. 1. Mybatis 简介

    1. Mybatis历史 MyBatis最初是Apache的一个开源项目iBatis, 2010年6月这个项目由Apache Software Foundation迁移到了Google Code.随着 ...

  9. 曾经辛苦造的轮子,现在能否用 ChatGPT 替代呢?

    上一篇文章 我在 vscode 插件里接入了 ChatGPT,解决了代码变量命名的难题 中,展示了如何在 vscode 插件中使用 ChatGPT 解决代码变量命名的问题.vscode 插件市场中有很 ...

  10. 一次与 ChatGPT 的 .NET 面试问答

    以常用问题来面试机器人,机器人是否能够合格 1. 您能描述一下您曾经在.NET项目中集成硬件设备的经历吗?这个过程是怎样的,您面临了哪些挑战? GPT 回答:当我在.NET项目中集成硬件设备时,我首先 ...