实验目的

  • 熟悉并掌握 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. Vue 新建项目+基本语法

    新建项目: 导入依赖:    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"> ...

  2. Spectre.Console-实现自己的CLI

    引言 最近发现自己喜欢用的 Todo 软件总是差点意思,毕竟每个人的习惯和工作流不太一样,我就想着自己写一个小的Todo 项目,核心的功能是自动记录 Todo 执行过程中消耗的时间(尤其面向程序员), ...

  3. JavaSE线程基础

    1.线程概念 2.线程创建方式 1.继承thread 2.实现runnable runnable使用最多 3.线程的生命周期及线程的状态 新建状态 就绪状态的线程(已获得所有资源,栈堆内存空间),即s ...

  4. hosts文件妙用,提升网站访问速度!

    一.背景 在讲解hosts文件之前,我们先了解下IP地址与域名的关系. 1.IP地址与域名的关系 IP(Internet Protocol)是一种规定互联网中数据传输的协议,每台连接到互联网中的计算机 ...

  5. HttpURLConnection调用webservice,c#、java、python等HTTP调用webservice,简单的webservice调用

    以前调用webservice一般使用axis.axis2先生成java类后,直接引用,多方便.但是有的webservice接口非常的函数,生成的java类非常多,有没有一种非常简化的方法. axis2 ...

  6. 全面解析PCIDSS中的设备访问控制和网络访问控制

    目录 1. 引言 2. 技术原理及概念 3. 实现步骤与流程 4. 应用示例与代码实现讲解 1. 引言 PCI DSS是PCI设备安全标准(PCI DSS)的缩写,是由PCI设备制造商和PCI服务提供 ...

  7. Codeforces Round #771 (Div. 2) A-E

    A 代码 #include <bits/stdc++.h> using namespace std; using ll = long long; int p[507]; bool solv ...

  8. kubernetes(k8s):解决不在同一网段加入集群失败问题

    执行下面命令,将内外网进行映射. iptables -t nat -A OUTPUT -d 10.140.128.121 -j DNAT --to-destination 10.170.129.153 ...

  9. 分享一个Java功能小案例(代码已开源哦)

    工程合集 工程列表 地址预览 B站 抖音

  10. 在VS Code 中调试远程服务器的PHP代码

    背景 对于PHP的调试,一般来说我们用 echo 和 var_dump 就够用了. 有时会碰到要解决复杂的逻辑或需要确认代码的运行顺序,这里用var_dump效率就比较低了,这时建议用断点的方式进行代 ...