自己动手写CPU_step5_移动指令

news2024/11/25 2:01:25

移动操作指令

`define EXE_MOVN        6'b001011   //不等于0转移   if rt != 0 then rs -> rd
`define EXE_MOVZ        6'b001010   //等于0转移     if rt == 0 then rs -> rd
`define EXE_MFHI        6'b010000   //  hi -> rd
`define EXE_MFLO        6'b010010   //  lo -> rd
`define EXE_MTHI        6'b010001   //  rs -> hi
`define EXE_MTLO        6'b010011   //  rs -> lo

这些指令都是R型指令,即指令类型由FUNC字段决定,而OP操作码字段全0。

上面的MOVN和MOVZ指令和前篇的R型指令基本一致,只是多了判断条件。

下面的四条指令都涉及HILO寄存器,该寄存器用于保存乘法运算和除法运算的结果。

HILO寄存器实现

//特殊寄存器组,用于存储乘法的高32位和低32位或除法的商和余数
module hilo_reg(
    input                       clk,
    input                       rst,
    //写端口
    input                       hi_wren_i,
    input [`RegDataBus]         hi_reg_i,
    input                       lo_wren_i,
    input [`RegDataBus]         lo_reg_i,
    output reg [`RegDataBus]    hi_reg_o,
    output reg [`RegDataBus]    lo_reg_o
    );
    
    reg [`RegDataBus]   HI;
    reg [`RegDataBus]   LO;

    always @ (posedge clk) begin
        if (rst) begin
            HI      <=  32'd0;
        end else if (hi_wren_i) begin
            HI     <=   hi_reg_i;
        end else begin
            HI      <=  HI;
        end
    end
    
    always @ (posedge clk) begin
        if (rst) begin
            LO      <=  32'd0;
        end else if (lo_wren_i) begin
            LO      <=   lo_reg_i;
        end else begin
            LO      <=  LO;
        end
    end

    always @ (*) begin
        if (rst) begin
            hi_reg_o    <=  32'd0;
        end else if (hi_wren_i) begin
            hi_reg_o    <=  hi_reg_i;
        end else begin
            hi_reg_o    <=  32'd0;
        end
    end
    
    always @ (*) begin
        if (rst) begin
            lo_reg_o    <=  32'd0;
        end else if (lo_wren_i) begin
            lo_reg_o    <=  lo_reg_i;
        end else begin
            lo_reg_o    <=  32'd0;
        end
    end
    
endmodule

该模块的输入与MEM_WB模块相连,输出接到EX模块。


数据相关问题

新加入的指令可能产生数据冲突:

mthi        reg1 => hi        IF        ID        EX        MEM        WB

mthi        reg2 => hi                   IF         ID         EX            MEM        WB

mthi        reg3 => hi                                IF         ID             EX            MEM        WB

mfhi        hi     => rd                                             IF             ID             EX            MEM     WB  如果安正常的执行顺序,mfhi指令的EX阶段使用的hi寄存器值是第一条指令的结果,但是,这和我们实际需要的结果不同,我们需要的hi寄存器值应该是上一条指令产生的结果。所以,这里存在数据冲突,其实和之前译码部分的冲突是一个道理,这里我们也还是使用旁路技术解决这个冲突。即如果需要HILO寄存器的值,先判断有没有MEM阶段来的值,再判断有没有WB阶段来的值,如果都没有的话就是正常获取HILO寄存器的值,也即没有冲突。


EX阶段实现

//执行阶段,根据译码阶段得到的操作码和操作数进行运算,得到结果
module ex(
    input                       rst,
    input [`AluOpBus]           aluop,
    input [`RegDataBus]         reg1,
    input [`RegDataBus]         reg2,
    input                       reg_wb_i,
    input [`RegAddrBus]         reg_wb_addr_i,
    output reg                  reg_wb_o,
    output reg [`RegAddrBus]    reg_wb_addr_o,
    output reg [`RegDataBus]    reg_wb_data,    //写回数据到目的寄存器
    //HILO寄存器
    input [`RegDataBus]         hi_reg_i,       //读取HI寄存器数据
    input [`RegDataBus]         lo_reg_i,       //读取LO寄存器数据
    output reg [`RegDataBus]    hi_reg_o,       //写入HI寄存器数据
    output reg [`RegDataBus]    lo_reg_o,       //写入LO寄存器数据
    output reg                  hi_wren,        //HI寄存器写使能        
    output reg                  lo_wren,        //LO寄存器写使能        
    //  HILO寄存器旁路                          
    input [`RegDataBus]         wb_hi_i,
    input [`RegDataBus]         wb_lo_i,
    input                       wb_hi_wren_i,  //有指令写HI,从写回阶段给出旁路(隔一条指令)
    input                       wb_lo_wren_i,  //有指令写LO,从写回阶段给出旁路(隔一条指令)
    input [`RegDataBus]         mem_hi_i,
    input [`RegDataBus]         mem_lo_i,
    input                       mem_hi_wren_i,  //有指令写HI,从访存阶段给出旁路(上一条指令)
    input                       mem_lo_wren_i  //有指令写LO,从访存阶段给出旁路(上一条指令)
    );

    always @ (*) begin
        if (rst) begin
            reg_wb_o        <= 1'd0;
            reg_wb_addr_o   <= 5'd0;
            reg_wb_data     <= 32'd0;
            hi_reg_o        <= 32'd0;
            lo_reg_o        <= 32'd0;
            hi_wren         <= 1'b0;
            lo_wren         <= 1'b0;
        end else begin
            reg_wb_o        <= reg_wb_i;
            reg_wb_addr_o   <= reg_wb_addr_i;
            reg_wb_data     <= 32'd0;
            hi_wren         <= 1'b0;
            lo_wren         <= 1'b0;
            hi_reg_o        <= 32'd0;
            lo_reg_o        <= 32'd0;
            case (aluop) 
                `EXE_ORI_OP,`EXE_OR_FUNC:       begin
                       reg_wb_data      <=  reg1 | reg2;
                end
                `EXE_ANDI_OP,`EXE_AND_FUNC:     begin
                        reg_wb_data     <=  reg1 & reg2;
                end
                `EXE_XORI_OP,`EXE_XOR_FUNC:     begin
                        reg_wb_data     <=  reg1 ^ reg2;
                end
                `EXE_LUI_OP:                    begin
                        reg_wb_data     <=  {reg2[15:0],reg2[31:16]};
                end
                `EXE_NOR_FUNC:                  begin
                        reg_wb_data     <=  ~(reg1 | reg2);
                end
                `EXE_SLL_FUNC,`EXE_SLLV_FUNC:   begin
                        reg_wb_data     <=  reg2 << reg1[4:0];
                end
                `EXE_SRL_FUNC,`EXE_SRLV_FUNC:   begin
                        reg_wb_data     <=  reg2 >> reg1[4:0];
                end
                `EXE_SRA_FUNC,`EXE_SRAV_FUNC:   begin       //算术移位也可以直接使用>>>
                        reg_wb_data     <=  ({32{reg2[31]}} << (6'd32 - {1'b0,reg1[4:0]})) | reg2 >> reg1[4:0];
                end
                `EXE_MOVN_FUNC,`EXE_MOVZ_FUNC:  begin
                        reg_wb_data     <=  reg1;
                end
                `EXE_MFHI_FUNC:                 begin
                        if (mem_hi_wren_i) begin            //访存阶段数据旁路
                            reg_wb_data     <=  mem_hi_i;
                        end else if (wb_hi_wren_i) begin    //写回阶段数据旁路
                            reg_wb_data     <=  wb_hi_i;
                        end else begin
                            reg_wb_data     <=  hi_reg_i;   //正常读取HI寄存器
                        end
                end
                `EXE_MFLO_FUNC:                 begin
                        if (mem_lo_wren_i) begin            //旁路
                            reg_wb_data     <=  mem_lo_i;
                        end else if (wb_lo_wren_i) begin    //旁路
                            reg_wb_data     <=  wb_lo_i;
                        end else begin                      //正常读取LO寄存器
                            reg_wb_data     <=  lo_reg_i;
                        end
                end
                `EXE_MTHI_FUNC:                 begin
                        hi_wren         <=  1'b1;
                        hi_reg_o        <=  reg1;
                        lo_reg_o        <=  lo_reg_i;
                end
                `EXE_MTLO_FUNC:                 begin
                        lo_wren         <=  1'b1;
                        lo_reg_o        <=  reg1;
                        hi_reg_o        <=  hi_reg_i;
                end
                default:                        begin
                        reg_wb_o        <= 1'd0;
                        reg_wb_addr_o   <= 5'd0;
                        reg_wb_data     <= 32'd0;
                        hi_reg_o        <= 32'd0;
                        lo_reg_o        <= 32'd0;
                        hi_wren         <= 1'b0;
                        lo_wren         <= 1'b0;
                end
            endcase
        end
    end

endmodule

模块修改

在EX_MEM、MEM、MEM_WB模块中添加由对应的HILO寄存器的值和写使能信号传导至HILO寄存器。最后修改顶层模块,将MEM阶段、WB阶段以及HILO寄存器的输出值都连接到EX的输入即可。


仿真结果

本次仿真使用了16条指令:

3c010000:LUI        将立即数低位扩展至reg1        reg1:00000000

3c02ffff:    LUI        将立即数低位扩展至reg2        reg2:ffff0000
3c030505:LUI        将立即数低位扩展至reg3        reg3:05050000
3c040000:LUI        将立即数低位扩展至reg4        reg4:00000000
0041200a:MOVZ   if (reg1==0) reg4 = reg2          reg4:ffff0000
0061200b:MOVN   if (reg1!=0) reg4 = reg3          reg4:ffff0000
0062200b:MOVN   if (reg2!=0) reg4 = reg3           reg4:05050000
0043200a:MOVZ   if (reg3!=0) reg4 = reg2           reg4:05050000
00000011:MTHI     reg0(全0) => hi                        hi:00000000
00400011:MTHI     reg2         => hi                        hi:ffff0000
00600011:MTHI     reg3         => hi                        hi:05050000
00002010:MFHI     hi             => reg4                    reg4:05050000
00600013:MTLO    reg3        => lo                        lo:05050000
00400013:MTLO    reg2        => lo                        lo:ffff0000
00200013:MTLO    reg1        => lo                        lo:00000000
00002012:MFLO    lo            => reg4                    reg4:00000000

上述指令可以测试是否消除数据相关。

仿真结果可知,所有指令的运行结果都与预期的一致。

验证了CPU设计的正确性。

下一步计划实现算数运算指令!

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

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

相关文章

一步迅速了解Spring框架的几个特点

一&#xff0c;特点1&#xff1a;IOC(控制反转) 1&#xff0c;IOC是什么 反转控制”(Inverse of Control) 不是什么技术&#xff0c;而是一种设计思想&#xff0c;就是将原本在程序中手动创建对象的控制权&#xff0c;交由 Spring 框架来管理 2&#xff0c;IOC的作用 IOC 容器…

tensor core实现矩阵乘法的详细解读

之前关于tensor core的介绍可以参考链接添加链接描述 基础的tensor core实现C=AB的代码可以参考下面这段内容: 上面代码的几个注意事项: 首先是加载mma.h头文件,这个是包含wmma模板类的头文件。 其次是设置的WMMA_M=16,WMMA_N=16,WMMA_K=8,这三个参数的表示的意思是,对于…

乐凡三防:工业界的硬核产品——重新定义三防平板的极限

在工业4.0的浪潮中&#xff0c;科技与制造业的深度融合催生了一系列高性能、高耐用的智能产品。乐凡三防平板&#xff0c;作为工业界的新宠&#xff0c;正以其卓越的防护性能和强大的功能&#xff0c;重新定义了三防平板的极限&#xff0c;成为硬核科技的代表。 硬核防护&#…

Marching Cubes 算法三探

Marching Cubes 算法再探 CUDA SamplesMarchingCubesworkflowCodedata structurecomputeIsosurfacelaunch_classifyVoxelclassifyVoxel ThrustScanWrapperlaunch_compactVoxelscompactVoxels launch_generateTriangles2generateTriangles2 improvements 初探再探三探&#xff0…

翻译软件推荐:有道翻译及其他选择!

一款好的翻译软件不仅能帮助我们跨越语言障碍&#xff0c;还能提升我们的工作效率。今天&#xff0c;我将为大家深入介绍几款亲测好用的翻译工具&#xff1a;福昕在线翻译、福昕翻译客户端、海鲸AI翻译以及有道翻译。 福昕在线翻译 链接&#xff1a; https://fanyi.pdf365.cn…

write your own xx-starter【1】

在springboot 中&#xff0c;我们加入例如mybatis-spring-boot-starter&#xff0c;接着在application.yml配置数据库信息&#xff0c;就可以使用mybatis了&#xff0c;无需我们手动进行配置 这就是springboot威力&#xff0c;那么他是如何实现的呢&#xff1f;简单来说类似于…

Java面向接口编程—习题

Java面向接口编程—习题 Java面向接口编程—习题 Java面向接口编程—习题需求实现思路具体步骤1.步骤一:创建接口2.步骤2&#xff1a;创建接口的实现类3.步骤3&#xff1a;创建一个厂商4.步骤四&#xff1a;创建测试类 需求 说明采用面向接口编程思想组装一台计算机计算机的主…

【RabbitMQ工作原理相关】

RabbitMQ如何保证消息不丢失 开启生产者确认机制,确保生产者的消息能到达队列开启持久化功能,确保消息未消费前在队列中不会丢失开启消费者确认机制为auto,由spring确认消息处理成功后完成ack开启消费者失败重试机制,多次重试失败后将消息投递到异常交换机,交由人工处理 Rabb…

Linux Debian12安装Peek录屏软件,录制gif动态图

一、Peek安装 在Debian 12 (codenamed “Bookworm”) 上安装 Peek 录屏软件&#xff0c;可以通过以下步骤进行&#xff1a; 1.打开终端。 2.更新系统的包索引&#xff1a; sudo apt update3.安装 Peek 的依赖项&#xff1a; sudo apt install peek如果你遇到问题&#xff…

【大模型LLMs】文本分块Chunking调研LangChain实战

【大模型LLMs】文本分块Chunking调研&LangChain实战 Chunking策略类型1. 基于规则的文本分块2. 基于语义Embedding分块3. 基于端到端模型的分块4. 基于大模型的分块 Chunking工具使用&#xff08;LangChain&#xff09;1. 固定大小分块&#xff08;字符&token&#xff…

IC-Light还原细节的节点 DetailTransfer使用时报错-comfyui

&#x1f388;问题描述 今天在调试一个工作流节点的时候&#xff0c;遇到一个问题&#xff1a; Error occurred when executing DetailTransfer: The size of tensor a (848) must match the size of tensor b (853) at non-singleton dimension 2 File "F:\ComfyUI-aki\…

Volvo EDI 项目测试流程详解

近期知行帮助多个供应商成功对接Volvo EDI&#xff0c;这些案例中&#xff0c;供应商收到Volvo发来的EDI需求是基本一致的&#xff1a; 传输协议选择OFTP报文标准选择EDIFACT业务单据包括&#xff1a;DELFOR交付预测以及DESADV发货通知 扩展阅读&#xff1a;汽车EDI&#xff…

车规级CAN总线外围电路设计方案

目录 1、共模电感 1.1、电感值 1.2、泄漏电感 1.3、直流电阻 1.4、CMC的模式转换特性 2、终端分立电阻 3、总线电容 4、ESD保护二极管 在汽车领域&#xff0c;电磁兼容性&#xff08;EMC&#xff09;问题一直备受瞩目。相较于传统汽车&#xff0c;新能源汽车的EMC挑战更…

如何使用ssm实现社区智慧养老监护管理平台+vue

TOC ssm270社区智慧养老监护管理平台vue 系统概述 1.1 研究背景 智慧养老是面向居家老人、社区及养老机构的传感网系统与信息平台&#xff0c;并在此基础上提供实时、快捷、高效、低成本的&#xff0c;物联化、互联化、智能化的养老服务。 随着科技进步&#xff0c;新型养…

无法启动此程序,因为计算机中丢失dll,整理了7种解决方法!

当电脑出现“无法启动此程序&#xff0c;因为计算机中丢失dll”的错误弹窗时&#xff0c;这通常意味着系统中的DLL文件出现了缺失或错误。DLL文件是动态链接库文件&#xff0c;它们在软件运行中起着至关重要的作用。 造成dll文件缺失和错误的原因有很多&#xff0c;大部分问题都…

git clone 别人的项目上传到自己的Gitee或者github仓库

git clone别人的项目 git clone https://github.com/wohuweixiya/yft-design.git 进入该项目内&#xff0c;删除原有的.git信息 rm -r .git 初始化.git git init 将本地代码添加到仓库 git add . git commit -m "提交仓库说明" Github上新建一个和这个clone下来…

【快速选择算法】解决TopK问题中前K小的数字问题

目录 1.前言2.题目简介3.求解思路4.示例代码 1.前言 在一个数组中找到这个数组前K小的数字有三种方式&#xff1a; 排序 O(N*logN)堆排序&#xff1a;建立一个k个大小的大堆(如果是找前K大的数字的话用小堆) O(N*logK)快速选择算法&#xff1a;原地交换数字&#xff0c;使得该…

数据结构---单链表(常见的复杂操作)

目录 一、单链表 1.1.查找中间元素 1.2.查找倒数第K个节点 1.3.链表倒置 1.4.冒泡排序 1.5.选择排序 1.6.环&#xff0c;确认有环单链表的环入口和环大小 二、总结 一、单链表 1.1.查找中间元素 定义两个指针&#xff0c;分别指向第一个元素&#xff0c;第一个指针每次向后…

开源的工作流系统突出优点总结

当前&#xff0c;想要实现高效率的办公&#xff0c;可以一起来了解低代码技术平台、开源的工作流系统的相关特点和功能优势。作为较受职场喜爱的平台产品&#xff0c;低代码技术平台拥有可视化才做界面、灵活、好维护操作等多个优势特点&#xff0c;在推动企业流程化办公的过程…

在线生成书法字帖,想练习什么字就练习什么字

有没有想练习一个字的时候发现找不到字帖的情况&#xff0c;现在推荐一款在线生成字帖的网站 可选择对应格子类型&#xff0c;生成你想练习的字 在线生成字帖