自己动手写CPU_step2_构建SOPC

news2025/1/9 14:16:54

ROM实现指令寄存器

        上一篇中实现的五级流水线需要一个输入,这个输入是指令数据,而指令数据是通过取指阶段的PC控制的,PC会一直循环的取指令。

指令寄存器实现

//指令寄存器
module inst_rom(
    input                       clk,
    input                       rden,
    input [`InstAddrBus]        addr,
    output reg [`InstDataBus]   inst
    );

reg [`InstDataBus]  inst_mem [0:3];
initial $readmemh ( "C:/C_extend/OpenMIPS_CPU_FPGA/inst_rom.data", inst_mem );

always @ (*) begin
    if (rden == 0) begin
        inst <= 32'd0;
    end else begin
        inst <= inst_mem[addr[3:2]];   //PC每加4对应指令寄存器的下一条指令  addr为0时表示第一条指令
    end
end

endmodule

        设计一个inst_rom.data的数据文件,其中存放4条16进制的32位指令,通过PC恰好可以循环遍历这些指令。addr低两位为0因为PC是4的倍数。


流水线顶层设计

//流水线的顶层模块
module openmips(
    input                   clk,
    input                   rst,
    input [`RegDataBus]     rom_data,
    output [`RegAddrBus]    rom_addr,
    output                  rom_rden
    );
    
    pc u_pc(
        .clk            (clk),
        .rst            (rst),
        .pc             (rom_addr),
        .pc_en          (rom_rden)
    );
    wire [`InstAddrBus]     id_pc;
    wire [`InstDataBus]     id_inst;
    if_id u_if_id(
        .clk            (clk),
        .rst            (rst),
        .if_pc          (rom_addr),
        .if_inst        (rom_data),
        .id_pc          (id_pc),
        .id_inst        (id_inst)
    );    
    wire [`RegDataBus]      reg1_data;
    wire [`RegDataBus]      reg2_data;
    wire [`RegAddrBus]      reg1_addr;
    wire [`RegAddrBus]      reg2_addr;
    wire                    reg1_rden;
    wire                    reg2_rden;
    wire [`RegDataBus]      reg1;
    wire [`RegDataBus]      reg2;
    wire                    reg_wb;
    wire [`RegAddrBus]      reg_wb_addr;
    wire [`AluOpBus]        aluop;
    id  u_id(
        .rst            (rst),
        .pc             (id_pc),
        .inst           (id_inst),
        .reg1_data      (reg1_data),
        .reg1_addr      (reg1_addr),
        .reg1_rden      (reg1_rden),
        .reg2_data      (reg2_data),
        .reg2_addr      (reg2_addr),
        .reg2_rden      (reg2_rden),
        .reg1           (reg1),
        .reg2           (reg2),
        .reg_wb         (reg_wb),
        .reg_wb_addr    (reg_wb_addr),
        .aluop          (aluop)
    );
    wire                wr_en;
    wire [`RegAddrBus]  wr_addr;
    wire [`RegDataBus]  wr_data;
    id_reg  u_id_reg(
        .clk            (clk),
        .rst            (rst),
        .reg1_data      (reg1_data),
        .reg1_addr      (reg1_addr),
        .reg1_rden      (reg1_rden),
        .reg2_data      (reg2_data),
        .reg2_addr      (reg2_addr),
        .reg2_rden      (reg2_rden),
        .wr_en          (wr_en),
        .wr_addr        (wr_addr),
        .wr_data        (wr_data)
    );
    wire [`RegDataBus]      ex_reg1;
    wire [`RegDataBus]      ex_reg2;
    wire                    ex_reg_wb;
    wire [`RegAddrBus]      ex_reg_wb_addr;
    wire [`AluOpBus]        ex_aluop;
    id_ex   u_id_ex(
        .clk            (clk),
        .rst            (rst),
        .id_reg1        (reg1),
        .id_reg2        (reg2),
        .id_aluop       (aluop),
        .id_reg_wb      (reg_wb),
        .id_reg_wb_addr (reg_wb_addr),
        .ex_reg1        (ex_reg1),
        .ex_reg2        (ex_reg2),
        .ex_aluop       (ex_aluop),
        .ex_reg_wb      (ex_reg_wb),
        .ex_reg_wb_addr (ex_reg_wb_addr)
    );
    wire                    ex_reg_wb_o;
    wire [`RegAddrBus]      ex_reg_wb_addr_o;
    wire [`RegDataBus]      ex_reg_wb_data_o;
    ex  u_ex(
        .rst            (rst),
        .reg1           (ex_reg1),
        .reg2           (ex_reg2),
        .aluop          (ex_aluop),
        .reg_wb_i       (ex_reg_wb),
        .reg_wb_addr_i  (ex_reg_wb_addr),
        .reg_wb_o       (ex_reg_wb_o),
        .reg_wb_addr_o  (ex_reg_wb_addr_o),
        .reg_wb_data    (ex_reg_wb_data_o)
    );
    wire                    mem_reg_wb;
    wire [`RegAddrBus]      mem_reg_wb_addr;
    wire [`RegDataBus]      mem_reg_wb_data;
    ex_mem u_ex_mem(
        .clk                (clk),
        .rst                (rst),
        .ex_reg_wb          (ex_reg_wb_o),
        .ex_reg_wb_addr     (ex_reg_wb_addr_o),
        .ex_reg_wb_data     (ex_reg_wb_data_o),
        .mem_reg_wb         (mem_reg_wb),
        .mem_reg_wb_addr    (mem_reg_wb_addr),
        .mem_reg_wb_data    (mem_reg_wb_data)
    );
    wire                    mem_reg_wb_o;
    wire [`RegAddrBus]      mem_reg_wb_addr_o;
    wire [`RegDataBus]      mem_reg_wb_data_o;
    mem u_mem(
        .rst                (rst),
        .reg_wb_i           (mem_reg_wb),
        .reg_wb_addr_i      (mem_reg_wb_addr),
        .reg_wb_data_i      (mem_reg_wb_data),
        .reg_wb_o           (mem_reg_wb_o),
        .reg_wb_addr_o      (mem_reg_wb_addr_o),
        .reg_wb_data_o      (mem_reg_wb_data_o)
    );
    mem_wb  u_mem_wb(
        .clk                (clk),
        .rst                (rst),
        .mem_reg_wb         (mem_reg_wb_o),
        .mem_reg_wb_addr    (mem_reg_wb_addr_o),
        .mem_reg_wb_data    (mem_reg_wb_data_o),
        .wb_reg             (wr_en),
        .wb_reg_addr        (wr_addr),
        .wb_reg_data        (wr_data)
    );
endmodule

最小SOPC实现

//基于MIPS五级流水线的最小sopc实现
module openmips_sopc(
    input                   clk,
    input                   rst
    );
    wire            rom_rden;
    wire [4:0]      rom_addr;
    wire [31:0]     rom_data;
    inst_rom inst_rom(
        .clk            (clk),
        .rden           (rom_rden),
        .addr           (rom_addr),
        .inst           (rom_data)  
    );
    openmips openmips(
        .clk            (clk),
        .rst            (rst),
        .rom_data       (rom_data),
        .rom_addr       (rom_addr),
        .rom_rden       (rom_rden)
    );
endmodule

最小SOPC实现之后,就可以开始仿真测试了。

仿真测试

`timescale 1ns / 1ps

module openmips_sopc_tb;

reg     clk;
reg     rst;

initial begin
    clk = 0;
    forever #10 clk = ~clk;     //时钟周期20ns 50MHz
end

initial begin
    rst = 1;
    #200
    rst = 0;
    #1000
    $finish(2);
end

openmips_sopc   u_openmips_sopc(
    .clk        (clk),
    .rst        (rst)
);

endmodule

仿真结果

由图可知,在210ns时,开始了第一次取指令操作pc=0,230ns时开始了第二次的取指令pc=4,同时进行指令1的译码操作,以此类推;在290ns时是指令1的写回阶段,此时的结果是reg1(来源初始寄存器全0)和reg2(来源指令中的立即数)的或运算结果,结果写回指定的地址寄存器;在310ns时,地址为1的寄存器被正确写入了指令1的计算结果。


        至此,CPU中第一条指令ORI设计完成,后续将实现更多指令!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2065381.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C++ Primer Plus习题】2.1

问题: 解答: #include <iostream> using namespace std;int main() {cout << "在下国林!" << endl;cout << "家住天府之国!" << endl;return 0; }运行结果: 考查点: 预处理头文件命名空间main函数c的标准输出和换行字符…

机器学习/数据分析--通俗语言带你入门K-邻近算法(结合案例)

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 前言 机器学习是深度学习和数据分析的基础&#xff0c;接下来将更新常见的机器学习算法注意&#xff1a;在打数学建模比赛中&#xff0c;机器学习用的也很多&a…

初识Linux · yum和vim

目录 前言&#xff1a; 1 yum 1.1 yum是什么&#xff1f; 1.2 Centos的生态和yum的本地配置 1.3 yum的相关操作 2 vim 前言&#xff1a; 我们学习Linux的时候&#xff0c;是有编程语言的基础的&#xff0c;那么呢&#xff0c;我们学习Linux的时候最迫切的就是希望能打印…

Flat Ads:全球金融应用现状与发展趋势深度解析

随着全球数字化进程的加速,金融科技(FinTech)应用正逐渐成为现代生活不可或缺的一部分。从移动银行到数字支付,再到智能理财工具,金融应用正在重新定义传统金融服务的边界,并推动行业的深刻变革。 本篇文章 Flat Ads 将从全球视角出发,深入剖析当前金融应用市场的现状,探讨未来…

开关电源测试系统方案:系统结构功能、特点、测试项目

为了应对开关电源测试中的复杂挑战&#xff0c;我们推出了NSAT-8000系列开关电源ate测试系统&#xff0c;它以其全面的功能和灵活性&#xff0c;适应了电源产品测试场景&#xff0c;解决了测试难题。 开关电源测试系统 NSAT-8000系列之开关电源测试系统适用于AC/DC和DC/DC开关电…

苹果macbook电脑怎么玩《黑神话:悟空》游戏教程来了

火爆全网《黑神话&#xff1a;悟空》是一款基于中国神话故事《西游记》改编的动作角色扮演游戏&#xff0c;它在PC平台上的系统要求已经公布&#xff0c;但目前官方尚未发布Mac版本。不过&#xff0c;Mac用户可以通过使用系统兼容工具如CrossOver来尝试在Mac上运行这款游戏。Cr…

《黑神话:悟空》游戏攻略:第一回合打法教程!

《黑神话&#xff1a;悟空》是一款以西游记为背景的动作角色扮演游戏&#xff0c;玩家在游戏中将面对各式各样的强大敌人和BOSS。在游戏的第一回合中&#xff0c;你将遇到牯护院、灵虚子、幽魂等多个BOSS。以下是详细的BOSS打法攻略&#xff0c;帮助你在战斗中游刃有余。你可以…

Ubuntu22安装MySQL8,并关闭大小写

最近因为设置MySQL不区分大小写踩了很多坑&#xff0c;把解决过程记录下来。 首先我这个是阿里云全新服务器&#xff0c;操作系统&#xff1a;Ubuntu 22.04 64位 连接到服务器后&#xff1a; 1 安装MySQL 1.1 更新软件包 以下命令皆已单独放至代码块内&#xff0c;直接复制…

服务器配置miniconda环境

目录 1. 查看服务器的操作系统2. 查看服务器的cuda版本3. 配置开发环境3.1 安装miniconda3环境3.2 创建虚拟环境3.3 在虚拟环境中安装pytorch3.4 在虚拟环境中安装库 1. 查看服务器的操作系统 执行代码&#xff1a; uname -a发现是Ubuntu 22.04 2. 查看服务器的cuda版本 执…

鸿蒙OS应用开发例题

单选题 第24/60题 自动跳下一题0 在编译构建HAP时&#xff0c;会从HAP模块及依赖的模块中收集资源文件&#xff0c;如果不同模块下的资源文件出现重名冲突 时&#xff0c;会按照优先级进行覆盖&#xff0c;现在有一个HAP依赖了两个HAR,依赖配置如下所示: // oh-package. j…

柔性织物处理 | 山大宋锐老师 | 最新演讲

笔者是清华在读研究生&#xff0c;主要关注人形机器人、具身智能。将持续分享行业前沿动态、学者观点整理、论文阅读笔记、知识学习路线等。欢迎交流 最近听了宋老师的演讲&#xff0c;以下是学习整理。部分图截自直播&#xff0c;若模糊望见谅 演讲信息&#xff1a; 【会议】…

郁李:花语与植物特征的魅力探寻

一、花语的奥秘 郁李的花语丰富多样&#xff0c;其中 “忠实” 代表着坚定不移的忠诚和信任&#xff0c;寓意着一份真挚而深厚的情感&#xff0c;无论外界如何变化&#xff0c;都能保持初心不变。“困难” 这一花语似乎不太讨喜&#xff0c;它可能象征着人生道路上难免会遭遇的…

iOS 通知

iOS 通知分为本地推送和远程推送两类 一. 本地推送使用流程 1. 注册通知 //请求通知权限 UNUserNotificationCenter *center [UNUserNotificationCenter currentNotificationCenter];[center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizati…

Java学习_18_Stream流

文章目录 前言一、不可变集合二、Stream流思想第一步&#xff1a;得到Stream流第二步&#xff1a;Stream流的中间方法Stream流的终结方法 总结 前言 博客仅记录个人学习进度和一些查缺补漏。 学习内容&#xff1a;BV17F411T7Ao 一、不可变集合 不可变集合就是长度和内容都不可…

HTML+CSS浮动和清除浮动的效果及其应用场景举例

一、清除浮动的效果 解释 .container&#xff1a;用于展示浮动和清除浮动效果的容器&#xff0c;具有边框和背景色以便于区分。 .float-box&#xff1a;浮动元素&#xff0c;用不同的背景色标识。 .clearfix&#xff1a;使用伪元素清除浮动的类&#xff0c;应用于第二个容器。 …

【chips】个人笔记系列-SystemVerilog

Title&#xff1a;System Verilog 学习 背景与发展 什么是SV 啥是SystemVerilog&#xff1f; 就是用来专门写验证和测试的 Verilog 升级版——在verilog的基础上加了些C的思想、语法、模块。 为啥要搞出一个SystemVerilog&#xff1f; 设计IC (integrated circuit)时用的是 …

02_TensorFlow2 Eager Execution:让AI编程从‘慢条斯理’变‘急不可耐’的神奇魔法!

1. Eager execution 的特性 即刻执行&#xff08;Eager execution&#xff09;是TensorFlow2.0的新特性&#xff0c;如同python解释器一样&#xff0c;执行即可获得计算结果&#xff0c;不需要手动建立图结构和会话&#xff0c;与python的兼容性更强, 为快速搭建和测试算法模型…

C语言 之 内存函数 memcpy、memmove函数的使用和模拟实现 memset、memcmp函数的使用

文章目录 1.memcpy函数的使用和模拟实现例子&#xff1a;模拟实现: 2.memmove函数的使用和模拟实现例子&#xff1a;模拟实现&#xff1a; 3.memset函数的使用**例子&#xff1a;** 3.memcmp函数的使用例子&#xff1a; 首先 我们要明确下面这些函数之所以被称作内存函数&#…

130-横向移动PTH哈希PTT票据PTK密匙Kerberos

pass the hash &#xff08;哈希传递攻击&#xff0c;简称pth&#xff09;利用lm&#xff08;老版本哈希&#xff09;或ntlm&#xff08;新版本&#xff09;的值进行的渗透测试 pass the ticket &#xff08;票据传递攻击&#xff0c;简称ptt&#xff09;利用的票据凭证TGT进行…

sql手工注入——sqli-labspage第六关到第十关

第六关 一确定攻击点判断闭合方式 跟个双引号引起报错 说明页面有报错语句的位置 http://127.0.0.1/Less-6/?id1%22http://127.0.0.1/Less-6/?id1%22尝试闭合 闭合成功 http://127.0.0.1/Less-6/?id1%22%20--http://127.0.0.1/Less-6/?id1%22%20-- 二.查询数据库名 ht…