目录
引言
致谢
指令说明
add、addu、sub、subu、slt、sltu
addi、addiu、slti、sltiu
clo、clz
multu、mult、mul
设计
宏定义
译码模块
指令执行模块
仿真
仿真程序
仿真结果
引言
随章节进度继续推进,本章继续实现 算术运算 指令等其他操作指令。
本篇文章主要实现简单算术操作指令,一共有15条指令。
致谢
感谢书籍《自己动手写CPU》及其作者雷思磊。一并感谢开源精神。
指令说明
add、addu、sub、subu、slt、sltu
此 6 条指令都是 R 型指令,指令码均为 6'd0 ,都属 SPECIAL 类。此外 6 ~ 10位均为 0 。可根据 低 6 位 判断指令功能。
指令格式:
指令用法说明:
addi、addiu、slti、sltiu
该4条指令都是 I 型指令,指令格式:
指令用法:
clo、clz
此两条指令属于 R 型指令。指令码均为 6'b011100,MIPS32 的 ISA 中表示 SPECIAL2 类。此外,10~6位 为0,需要依靠 低六位 判定指令功能。
指令格式:
指令用法:
multu、mult、mul
此 3 条指令都是 R型指令。其中 mul 属SPECIAL2类,mult和multu属SPECIAL类。
指令格式:
指令用法:
设计
此处仅对有改动的模块,给出源码。
宏定义
// |------------------------------ ================================== ------------------------------ // |============================== MIPS32 CPU SYSTEM ALL MACRO DEFINE ============================== // |------------------------------ ================================== ------------------------------ // |Create Date : 2022-12-06 // |Finish Date : 2022- // |Edited by : Xu Y. B. (CSDN USER NAME :在路上,正出发) // |Reference : 《自己动手写CPU》——第4章 // | // | // |------------------------------------------------------------------------------------------------ // |---------------------------------------- Change History ---------------------------------------- // |Date:2022-12-09 // |Who :Xu Y. B. // |What:增加如下指令宏定义: // | and、or、xor、nor // | andi、xori // | lui // | sll、sllv、sra、srav.、srl、srlv // | nop、ssnop、sync、pref // | 以及相应的ALU操作功能宏定义 // |Date:2022-12-10 // |Who :Xu Y. B. // |What:增加如下指令宏定义: // | movz、movn、mfhi、mthi、mfhi、mflo // | 以及相应的ALU操作功能宏定义 // |Date:2022-12-12 // |Who :Xu Y. B. // |What:增加如下指令宏定义: // | add、addu、sub、subu、slt、sltu、addi、addiu、slti、sltiu、clo、clz、multu、mult、mul // | 以及相应的ALU操作功能宏定义 // |-------------------------------------- 系统级全局宏定义 -------------------------------------- // |------------------------------------------------------------------------------------------------ // | 0字 `define DEF_ZERO_WORD 32'd0 // 0字 // | 关于译码 `define DEF_ALU_OPR_BUS 7:0 // 译码输出 O_ALU_OPR 总线 `define DEF_ALU_SEL_BUS 2:0 // 译码输出 O_ALU_SEL 总线 // | 逻辑 0 1 `define DEF_LOG_TRUE 1'b1 // 逻辑 真 `define DEF_LOG_FALSE 1'b0 // 逻辑 假 // | 芯片使能 `define DEF_CHIP_EN 1'b1 // 芯片使能 `define DEF_CHIP_DIS 1'b0 // 芯片不使能 // |-------------------------------------- 指令相关的宏定义 -------------------------------------- // |------------------------------------------------------------------------------------------------ // | 指令、功能码 `define DEF_ISTC_AND 6'b100100 `define DEF_ISTC_OR 6'b100101 `define DEF_ISTC_XOR 6'b100110 `define DEF_ISTC_NOR 6'b100111 `define DEF_ISTC_ANDI 6'b001100 `define DEF_ISTC_ORI 6'b001101 `define DEF_ISTC_XORI 6'b001110 `define DEF_ISTC_LUI 6'b001111 `define DEF_ISTC_SLL 6'b000000 `define DEF_ISTC_SLLV 6'b000100 `define DEF_ISTC_SRL 6'b000010 `define DEF_ISTC_SRLV 6'b000110 `define DEF_ISTC_SRA 6'b000011 `define DEF_ISTC_SRAV 6'b000111 `define DEF_ISTC_SYNC 6'b001111 `define DEF_ISTC_PREF 6'b110011 `define DEF_ISTC_SPEC 6'b000000 // SPECIAL 类指令码 `define DEF_ISTC_SPEC2 6'b011100 // SPECIAL2 类指令码 `define DEF_ISTC_MOVZ 6'b001010 `define DEF_ISTC_MOVN 6'b001011 `define DEF_ISTC_MFHI 6'b010000 `define DEF_ISTC_MTHI 6'b010001 `define DEF_ISTC_MFLO 6'b010010 `define DEF_ISTC_MTLO 6'b010011 `define DEF_ISTC_SLT 6'b101010 `define DEF_ISTC_SLTU 6'b101011 `define DEF_ISTC_SLTI 6'b001010 `define DEF_ISTC_SLTIU 6'b001011 `define DEF_ISTC_ADD 6'b100000 `define DEF_ISTC_ADDU 6'b100001 `define DEF_ISTC_SUB 6'b100010 `define DEF_ISTC_SUBU 6'b100011 `define DEF_ISTC_ADDI 6'b001000 `define DEF_ISTC_ADDIU 6'b001001 `define DEF_ISTC_CLZ 6'b100000 `define DEF_ISTC_CLO 6'b100001 `define DEF_ISTC_MULT 6'b011000 `define DEF_ISTC_MULTU 6'b011001 `define DEF_ISTC_MUL 6'b000010 `define DEF_ISTC_NOP 6'b000000 // nop // | ALU操作码 `define DEF_ALU_OR_OPR 8'b00100101 `define DEF_ALU_AND_OPR 8'b00100100 `define DEF_ALU_XOR_OPR 8'b00100110 `define DEF_ALU_NOR_OPR 8'b00100111 `define DEF_ALU_SLL_OPR 8'b01111100 `define DEF_ALU_SRL_OPR 8'b00000010 `define DEF_ALU_SRA_OPR 8'b00000011 `define DEF_ALU_MOVZ_OPR 8'b00001010 `define DEF_ALU_MOVN_OPR 8'b00001011 `define DEF_ALU_MFHI_OPR 8'b00010000 `define DEF_ALU_MTHI_OPR 8'b00010001 `define DEF_ALU_MFLO_OPR 8'b00010010 `define DEF_ALU_MTLO_OPR 8'b00010011 `define DEF_ALU_SLT_OPR 8'b00101010 `define DEF_ALU_SLTU_OPR 8'b00101011 `define DEF_ALU_SLTI_OPR 8'b01010111 `define DEF_ALU_SLTIU_OPR 8'b01011000 `define DEF_ALU_ADD_OPR 8'b00100000 `define DEF_ALU_ADDU_OPR 8'b00100001 `define DEF_ALU_SUB_OPR 8'b00100010 `define DEF_ALU_SUBU_OPR 8'b00100011 `define DEF_ALU_ADDI_OPR 8'b01010101 `define DEF_ALU_ADDIU_OPR 8'b01010110 `define DEF_ALU_CLZ_OPR 8'b10110000 `define DEF_ALU_CLO_OPR 8'b10110001 `define DEF_ALU_MULT_OPR 8'b00011000 `define DEF_ALU_MULTU_OPR 8'b00011001 `define DEF_ALU_MUL_OPR 8'b10101001 `define DEF_ALU_NOP_OPR 8'd0 // | ALU 选择 // `define DEF_ALU_SEL_LOGIC 3'b001 // `define DEF_ALU_SEL_NOP 3'b000 // | 操作数 `define DEF_SRC_OPR_DATA_BUS 31:0 `define DEF_IMM_DATA_BUS 15:0 // |-------------------------------------- 指令存储器宏定义 -------------------------------------- // |------------------------------------------------------------------------------------------------ `define DEF_ISTC_ADDR_BUS 31:0 // 地址线总线 `define DEF_ISTC_DATA_BUS 31:0 // 数据线总线 `define DEF_ISTC_CACH_DEPTH 2**17-1 // 缓存深度/地址最大值 `define DEF_ISTC_ADDR_WIDTH_ACTUAL 17 // 实际使用的缓存地址线宽度 // |-------------------------------------- 通用寄存器宏定义 -------------------------------------- // |------------------------------------------------------------------------------------------------ `define DEF_GPR_ADDR_WIDTH 5 // 通用寄存器地址位宽(32个) `define DEF_GPR_DATA_WIDTH 32 // 通用寄存器数据位宽 `define DEF_GPR_NUM 32 // 通用寄存器数目 `define DEF_GPR_ADDR_NOP 5'd0 // 空操作 GPR 地址
译码模块
// |------------------------------ ================================== ------------------------------ // |============================== 指令-译码模块 ============================== // |------------------------------ ================================== ------------------------------ // |Create Date : 2022-12-07 // |Finish Date : 2022-12-07 // |Edited by : Xu Y. B. (CSDN USER NAME :在路上,正出发) // |Reference : 《自己动手写CPU》 // | // | // |------------------------------------------------------------------------------------------------ // |---------------------------------------- Change History ---------------------------------------- // |Date:2022-12-08 // |Who :Xu Y. B. // |What:修复流水线数据相关的问题(第 2、3类问题) // | 思路参考《自己动手写CPU》5.2节 // | 增加模块端口:Line 48 - 54 // | 增加条件分支:Line 141 - 148 、171 - 178 // |Date:2022-12-09 // |Who :Xu Y. B. // |What:增加逻辑、移位指令的译码功能 // |Date:2022-12-11 // |Who :Xu Y. B. // |What:增加移动指令的译码功能 // |Date:2022-12-12 // |Who :Xu Y. B. // |What:增加简单算术运算指令的译码功能 `include "MIPS_SYS_DEFINES.v" `timescale 1ns / 1ps module ID_MDL( // |-------------------------------------- 输入输出端口声明 -------------------------------------- // |------------------------------------------------------------------------------------------------ // | 时钟、复位 input I_CPU_CLK, input I_CPU_RSTN, // | 指令 input [`DEF_ISTC_DATA_BUS] I_ISTC, // | GPR读写控制 output reg O_GPR_RD_EN_A, output reg [`DEF_GPR_ADDR_WIDTH-1:0] O_GPR_RD_ADDR_A, input [`DEF_GPR_DATA_WIDTH-1:0] I_GPR_RD_DATA_A, output reg O_GPR_RD_EN_B, output reg [`DEF_GPR_ADDR_WIDTH-1:0] O_GPR_RD_ADDR_B, input [`DEF_GPR_DATA_WIDTH-1:0] I_GPR_RD_DATA_B, // | 译码输出相关 对接 ALU 运算单元 // output reg [`DEF_ALU_SEL_BUS] O_ALU_SEL, output reg [`DEF_ALU_OPR_BUS] O_ALU_OP_TYPE, output reg [`DEF_SRC_OPR_DATA_BUS] O_SRC_OPR_DATA_A, output reg [`DEF_SRC_OPR_DATA_BUS] O_SRC_OPR_DATA_B, output reg O_DST_GPR_WR_EN, output reg [`DEF_GPR_ADDR_WIDTH-1:0] O_DST_GPR_WR_ADDR, // | 为解决数据相关问题/读写冲突问题 引入的端口 // 来自执行模块 input I_DST_GPR_WR_EN_FROM_EXE_MDL, input [`DEF_GPR_ADDR_WIDTH-1:0] I_DST_GPR_WR_ADDR_FROM_EXE_MDL, input [`DEF_GPR_DATA_WIDTH-1:0] I_DST_GPR_WR_DATA_FROM_EXE_MDL, // 来自访存模块 input I_DST_GPR_WR_EN_FROM_MEM_ACS_MDL, input [`DEF_GPR_ADDR_WIDTH-1:0] I_DST_GPR_WR_ADDR_FROM_MEM_ACS_MDL, input [`DEF_GPR_DATA_WIDTH-1:0] I_DST_GPR_WR_DATA_FROM_MEM_ACS_MDL ); // |-------------------------------------- 模块内部信号声明 -------------------------------------- // |------------------------------------------------------------------------------------------------ // | 指令分解相关 wire [5:0] W_ISTC_TYPE; // 指令码 wire [`DEF_GPR_ADDR_WIDTH-1:0] W_SRC_GPR_ADDR; wire [`DEF_GPR_ADDR_WIDTH-1:0] W_DST_GPR_ADDR; wire [`DEF_IMM_DATA_BUS] W_ISTC_IMM_DATA; wire [4:0] W_ISTC_15_11_BIT; wire [4:0] W_ISTC_10_6_BIT; wire [5:0] W_ISTC_5_0_BIT; // | 32位立即数 reg [31:0] R_IMM_DATA_32BIT; // | 指令有效信号 reg R_ISTC_VAL; // |-------------------------------------- 模块内部逻辑设计 -------------------------------------- // |------------------------------------------------------------------------------------------------ // | 指令分解相关 assign W_ISTC_TYPE = I_ISTC[31:26];// 指令码 assign W_SRC_GPR_ADDR = I_ISTC[25:21]; assign W_DST_GPR_ADDR = I_ISTC[20:16]; assign W_ISTC_IMM_DATA = I_ISTC[15:0] ; assign W_ISTC_15_11_BIT = I_ISTC[15:11]; assign W_ISTC_10_6_BIT = I_ISTC[10:6]; assign W_ISTC_5_0_BIT = I_ISTC[5:0]; // | 指令译码 always @ (posedge I_CPU_CLK) begin if(~I_CPU_RSTN) begin O_GPR_RD_EN_A <= 1'b0; O_GPR_RD_ADDR_A <= `DEF_GPR_ADDR_NOP; O_GPR_RD_EN_B <= 1'b0; O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP; O_ALU_OP_TYPE <= `DEF_ALU_NOP_OPR; // O_ALU_SEL <= `DEF_ALU_SEL_NOP; O_DST_GPR_WR_EN <= 1'b0; O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP; R_ISTC_VAL <= 1'b0; R_IMM_DATA_32BIT <= 32'd0; end else begin case(W_ISTC_TYPE) `DEF_ISTC_SPEC://SPECIAL 类 指令 begin case(W_ISTC_10_6_BIT) 5'd0: begin case(W_ISTC_5_0_BIT) `DEF_ISTC_AND: begin O_GPR_RD_EN_A <= 1'b1; O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR; O_GPR_RD_EN_B <= 1'b1; O_GPR_RD_ADDR_B <= W_DST_GPR_ADDR; O_ALU_OP_TYPE <= `DEF_ALU_AND_OPR; // O_ALU_SEL <= `DEF_ALU_SEL_NOP; O_DST_GPR_WR_EN <= 1'b1; O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= 32'd0; end `DEF_ISTC_OR: begin O_GPR_RD_EN_A <= 1'b1; O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR; O_GPR_RD_EN_B <= 1'b1; O_GPR_RD_ADDR_B <= W_DST_GPR_ADDR; O_ALU_OP_TYPE <= `DEF_ALU_OR_OPR; // O_ALU_SEL <= `DEF_ALU_SEL_NOP; O_DST_GPR_WR_EN <= 1'b1; O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= 32'd0; end `DEF_ISTC_XOR: begin O_GPR_RD_EN_A <= 1'b1; O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR; O_GPR_RD_EN_B <= 1'b1; O_GPR_RD_ADDR_B <= W_DST_GPR_ADDR; O_ALU_OP_TYPE <= `DEF_ALU_XOR_OPR; // O_ALU_SEL <= `DEF_ALU_SEL_NOP; O_DST_GPR_WR_EN <= 1'b1; O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= 32'd0; end `DEF_ISTC_NOR: begin O_GPR_RD_EN_A <= 1'b1; O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR; O_GPR_RD_EN_B <= 1'b1; O_GPR_RD_ADDR_B <= W_DST_GPR_ADDR; O_ALU_OP_TYPE <= `DEF_ALU_NOR_OPR; // O_ALU_SEL <= `DEF_ALU_SEL_NOP; O_DST_GPR_WR_EN <= 1'b1; O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= 32'd0; end `DEF_ISTC_SLLV: begin O_GPR_RD_EN_A <= 1'b1; O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR; O_GPR_RD_EN_B <= 1'b1; O_GPR_RD_ADDR_B <= W_DST_GPR_ADDR; O_ALU_OP_TYPE <= `DEF_ALU_SLL_OPR; // O_ALU_SEL <= `DEF_ALU_SEL_NOP; O_DST_GPR_WR_EN <= 1'b1; O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= 32'd0; end `DEF_ISTC_SRLV: begin O_GPR_RD_EN_A <= 1'b1; O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR; O_GPR_RD_EN_B <= 1'b1; O_GPR_RD_ADDR_B <= W_DST_GPR_ADDR; O_ALU_OP_TYPE <= `DEF_ALU_SRL_OPR; // O_ALU_SEL <= `DEF_ALU_SEL_NOP; O_DST_GPR_WR_EN <= 1'b1; O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= 32'd0; end `DEF_ISTC_SRAV: begin O_GPR_RD_EN_A <= 1'b1; O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR; O_GPR_RD_EN_B <= 1'b1; O_GPR_RD_ADDR_B <= W_DST_GPR_ADDR; O_ALU_OP_TYPE <= `DEF_ALU_SRA_OPR; // O_ALU_SEL <= `DEF_ALU_SEL_NOP; O_DST_GPR_WR_EN <= 1'b1; O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= 32'd0; end `DEF_ISTC_SYNC: begin O_GPR_RD_EN_A <= 1'b0; O_GPR_RD_ADDR_A <= `DEF_GPR_ADDR_NOP; O_GPR_RD_EN_B <= 1'b1; O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP; O_ALU_OP_TYPE <= `DEF_ALU_NOP_OPR; // O_ALU_SEL <= `DEF_ALU_SEL_NOP; O_DST_GPR_WR_EN <= 1'b0; O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= 32'd0; end `DEF_ISTC_MOVZ: begin O_GPR_RD_EN_A <= 1'b1; O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR; O_GPR_RD_EN_B <= 1'b1; O_GPR_RD_ADDR_B <= W_DST_GPR_ADDR; O_ALU_OP_TYPE <= `DEF_ALU_MOVZ_OPR; // 写使能此处后置于 执行模块 判断赋值 // if(I_GPR_RD_DATA_B == `DEF_ZERO_WORD) // begin // O_DST_GPR_WR_EN <= 1'b1; // end // else // begin // O_DST_GPR_WR_EN <= 1'b0; // end O_DST_GPR_WR_EN <= 1'b0; O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= 32'd0; end `DEF_ISTC_MOVN: begin O_GPR_RD_EN_A <= 1'b1; O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR; O_GPR_RD_EN_B <= 1'b1; O_GPR_RD_ADDR_B <= W_DST_GPR_ADDR; O_ALU_OP_TYPE <= `DEF_ALU_MOVN_OPR; // 写使能此处后置于 执行模块 判断赋值 // if(I_GPR_RD_DATA_B != `DEF_ZERO_WORD) // begin // O_DST_GPR_WR_EN <= 1'b1; // end // else // begin // O_DST_GPR_WR_EN <= 1'b0; // end O_DST_GPR_WR_EN <= 1'b0; O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= 32'd0; end `DEF_ISTC_MFHI: begin O_GPR_RD_EN_A <= 1'b0; O_GPR_RD_ADDR_A <= `DEF_GPR_ADDR_NOP; O_GPR_RD_EN_B <= 1'b0; O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP; O_ALU_OP_TYPE <= `DEF_ALU_MFHI_OPR; O_DST_GPR_WR_EN <= 1'b1; O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= 32'd0; end `DEF_ISTC_MTHI: begin O_GPR_RD_EN_A <= 1'b1; O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR; O_GPR_RD_EN_B <= 1'b0; O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP; O_ALU_OP_TYPE <= `DEF_ALU_MTHI_OPR; O_DST_GPR_WR_EN <= 1'b0; O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= 32'd0; end `DEF_ISTC_MFLO: begin O_GPR_RD_EN_A <= 1'b0; O_GPR_RD_ADDR_A <= `DEF_GPR_ADDR_NOP; O_GPR_RD_EN_B <= 1'b0; O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP; O_ALU_OP_TYPE <= `DEF_ALU_MFLO_OPR; O_DST_GPR_WR_EN <= 1'b1; O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= 32'd0; end `DEF_ISTC_MTLO: begin O_GPR_RD_EN_A <= 1'b1; O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR; O_GPR_RD_EN_B <= 1'b0; O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP; O_ALU_OP_TYPE <= `DEF_ALU_MTLO_OPR; O_DST_GPR_WR_EN <= 1'b0; O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= 32'd0; end `DEF_ISTC_ADD : begin O_GPR_RD_EN_A <= 1'b1; O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR; O_GPR_RD_EN_B <= 1'b1; O_GPR_RD_ADDR_B <= W_DST_GPR_ADDR; O_ALU_OP_TYPE <= `DEF_ALU_ADD_OPR; O_DST_GPR_WR_EN <= 1'b1; O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= 32'd0; end `DEF_ISTC_ADDU : begin O_GPR_RD_EN_A <= 1'b1; O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR; O_GPR_RD_EN_B <= 1'b1; O_GPR_RD_ADDR_B <= W_DST_GPR_ADDR; O_ALU_OP_TYPE <= `DEF_ALU_ADDU_OPR; O_DST_GPR_WR_EN <= 1'b1; O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= 32'd0; end `DEF_ISTC_SUB : begin O_GPR_RD_EN_A <= 1'b1; O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR; O_GPR_RD_EN_B <= 1'b1; O_GPR_RD_ADDR_B <= W_DST_GPR_ADDR; O_ALU_OP_TYPE <= `DEF_ALU_SUB_OPR; O_DST_GPR_WR_EN <= 1'b1; O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= 32'd0; end `DEF_ISTC_SUBU : begin O_GPR_RD_EN_A <= 1'b1; O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR; O_GPR_RD_EN_B <= 1'b1; O_GPR_RD_ADDR_B <= W_DST_GPR_ADDR; O_ALU_OP_TYPE <= `DEF_ALU_SUBU_OPR; O_DST_GPR_WR_EN <= 1'b1; O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= 32'd0; end `DEF_ISTC_SLT : begin O_GPR_RD_EN_A <= 1'b1; O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR; O_GPR_RD_EN_B <= 1'b1; O_GPR_RD_ADDR_B <= W_DST_GPR_ADDR; O_ALU_OP_TYPE <= `DEF_ALU_SLT_OPR; O_DST_GPR_WR_EN <= 1'b1; O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= 32'd0; end `DEF_ISTC_SLTU : begin O_GPR_RD_EN_A <= 1'b1; O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR; O_GPR_RD_EN_B <= 1'b1; O_GPR_RD_ADDR_B <= W_DST_GPR_ADDR; O_ALU_OP_TYPE <= `DEF_ALU_SLTU_OPR; O_DST_GPR_WR_EN <= 1'b1; O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= 32'd0; end `DEF_ISTC_MULT : begin O_GPR_RD_EN_A <= 1'b1; O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR; O_GPR_RD_EN_B <= 1'b1; O_GPR_RD_ADDR_B <= W_DST_GPR_ADDR; O_ALU_OP_TYPE <= `DEF_ALU_MULT_OPR; O_DST_GPR_WR_EN <= 1'b0; O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= 32'd0; end `DEF_ISTC_MULTU: begin O_GPR_RD_EN_A <= 1'b1; O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR; O_GPR_RD_EN_B <= 1'b1; O_GPR_RD_ADDR_B <= W_DST_GPR_ADDR; O_ALU_OP_TYPE <= `DEF_ALU_MULTU_OPR; O_DST_GPR_WR_EN <= 1'b0; O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= 32'd0; end default: begin O_GPR_RD_EN_A <= 1'b0; O_GPR_RD_ADDR_A <= `DEF_GPR_ADDR_NOP; O_GPR_RD_EN_B <= 1'b0; O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP; O_ALU_OP_TYPE <= `DEF_ALU_NOP_OPR; // O_ALU_SEL <= `DEF_ALU_SEL_NOP; O_DST_GPR_WR_EN <= 1'b0; O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP; R_ISTC_VAL <= 1'b0; R_IMM_DATA_32BIT <= 32'd0; end endcase end default: begin O_GPR_RD_EN_A <= 1'b0; O_GPR_RD_ADDR_A <= `DEF_GPR_ADDR_NOP; O_GPR_RD_EN_B <= 1'b0; O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP; O_ALU_OP_TYPE <= `DEF_ALU_NOP_OPR; // O_ALU_SEL <= `DEF_ALU_SEL_NOP; O_DST_GPR_WR_EN <= 1'b0; O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP; R_ISTC_VAL <= 1'b0; R_IMM_DATA_32BIT <= 32'd0; end endcase end `DEF_ISTC_SPEC2: begin case(W_ISTC_5_0_BIT) `DEF_ISTC_CLZ: begin O_GPR_RD_EN_A <= 1'b1; O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR; O_GPR_RD_EN_B <= 1'b0; O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP; O_ALU_OP_TYPE <= `DEF_ALU_CLZ_OPR; // O_ALU_SEL <= `DEF_ALU_SEL_NOP; O_DST_GPR_WR_EN <= 1'b1; O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= 32'd0; end `DEF_ISTC_CLO: begin O_GPR_RD_EN_A <= 1'b1; O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR; O_GPR_RD_EN_B <= 1'b0; O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP; O_ALU_OP_TYPE <= `DEF_ALU_CLO_OPR; // O_ALU_SEL <= `DEF_ALU_SEL_NOP; O_DST_GPR_WR_EN <= 1'b1; O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= 32'd0; end `DEF_ISTC_MUL: begin O_GPR_RD_EN_A <= 1'b1; O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR; O_GPR_RD_EN_B <= 1'b1; O_GPR_RD_ADDR_B <= W_DST_GPR_ADDR; O_ALU_OP_TYPE <= `DEF_ALU_MUL_OPR; // O_ALU_SEL <= `DEF_ALU_SEL_NOP; O_DST_GPR_WR_EN <= 1'b1; O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= 32'd0; end default: begin O_GPR_RD_EN_A <= 1'b0; O_GPR_RD_ADDR_A <= `DEF_GPR_ADDR_NOP; O_GPR_RD_EN_B <= 1'b0; O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP; O_ALU_OP_TYPE <= `DEF_ALU_NOP_OPR; // O_ALU_SEL <= `DEF_ALU_SEL_NOP; O_DST_GPR_WR_EN <= 1'b0; O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP; R_ISTC_VAL <= 1'b0; R_IMM_DATA_32BIT <= 32'd0; end endcase end `DEF_ISTC_ORI:// ori指令 begin O_GPR_RD_EN_A <= 1'b1; O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR; O_GPR_RD_EN_B <= 1'b0; O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP; O_ALU_OP_TYPE <= `DEF_ALU_OR_OPR; // O_ALU_SEL <= `DEF_ALU_SEL_LOGIC; O_DST_GPR_WR_EN <= 1'b1; O_DST_GPR_WR_ADDR <= W_DST_GPR_ADDR; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= {16'd0,W_ISTC_IMM_DATA}; end `DEF_ISTC_ANDI: begin O_GPR_RD_EN_A <= 1'b1; O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR; O_GPR_RD_EN_B <= 1'b0; O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP; O_ALU_OP_TYPE <= `DEF_ALU_AND_OPR; // O_ALU_SEL <= `DEF_ALU_SEL_LOGIC; O_DST_GPR_WR_EN <= 1'b1; O_DST_GPR_WR_ADDR <= W_DST_GPR_ADDR; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= {16'd0,W_ISTC_IMM_DATA}; end `DEF_ISTC_XORI: begin O_GPR_RD_EN_A <= 1'b1; O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR; O_GPR_RD_EN_B <= 1'b0; O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP; O_ALU_OP_TYPE <= `DEF_ALU_XOR_OPR; // O_ALU_SEL <= `DEF_ALU_SEL_LOGIC; O_DST_GPR_WR_EN <= 1'b1; O_DST_GPR_WR_ADDR <= W_DST_GPR_ADDR; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= {16'd0,W_ISTC_IMM_DATA}; end `DEF_ISTC_LUI: begin O_GPR_RD_EN_A <= 1'b1; O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR; O_GPR_RD_EN_B <= 1'b0; O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP; O_ALU_OP_TYPE <= `DEF_ALU_OR_OPR; // O_ALU_SEL <= `DEF_ALU_SEL_LOGIC; O_DST_GPR_WR_EN <= 1'b1; O_DST_GPR_WR_ADDR <= W_DST_GPR_ADDR; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= {W_ISTC_IMM_DATA,16'd0}; end `DEF_ISTC_PREF: begin O_GPR_RD_EN_A <= 1'b0; O_GPR_RD_ADDR_A <= `DEF_GPR_ADDR_NOP; O_GPR_RD_EN_B <= 1'b0; O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP; O_ALU_OP_TYPE <= `DEF_ALU_NOP_OPR; // O_ALU_SEL <= `DEF_ALU_SEL_LOGIC; O_DST_GPR_WR_EN <= 1'b0; O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= 32'd0; end `DEF_ISTC_ADDI : begin O_GPR_RD_EN_A <= 1'b1; O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR; O_GPR_RD_EN_B <= 1'b0; O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP; O_ALU_OP_TYPE <= `DEF_ALU_ADDI_OPR; // O_ALU_SEL <= `DEF_ALU_SEL_LOGIC; O_DST_GPR_WR_EN <= 1'b1; O_DST_GPR_WR_ADDR <= W_DST_GPR_ADDR; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= {{16{W_ISTC_IMM_DATA[15]}},W_ISTC_IMM_DATA}; end `DEF_ISTC_ADDIU: begin O_GPR_RD_EN_A <= 1'b1; O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR; O_GPR_RD_EN_B <= 1'b0; O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP; O_ALU_OP_TYPE <= `DEF_ALU_ADDIU_OPR; // O_ALU_SEL <= `DEF_ALU_SEL_LOGIC; O_DST_GPR_WR_EN <= 1'b1; O_DST_GPR_WR_ADDR <= W_DST_GPR_ADDR; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= {{16{W_ISTC_IMM_DATA[15]}},W_ISTC_IMM_DATA}; end `DEF_ISTC_SLTI : begin O_GPR_RD_EN_A <= 1'b1; O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR; O_GPR_RD_EN_B <= 1'b0; O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP; O_ALU_OP_TYPE <= `DEF_ALU_SLTI_OPR; // O_ALU_SEL <= `DEF_ALU_SEL_LOGIC; O_DST_GPR_WR_EN <= 1'b1; O_DST_GPR_WR_ADDR <= W_DST_GPR_ADDR; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= {{16{W_ISTC_IMM_DATA[15]}},W_ISTC_IMM_DATA}; end `DEF_ISTC_SLTIU: begin O_GPR_RD_EN_A <= 1'b1; O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR; O_GPR_RD_EN_B <= 1'b0; O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP; O_ALU_OP_TYPE <= `DEF_ALU_SLTIU_OPR; // O_ALU_SEL <= `DEF_ALU_SEL_LOGIC; O_DST_GPR_WR_EN <= 1'b1; O_DST_GPR_WR_ADDR <= W_DST_GPR_ADDR; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= {{16{W_ISTC_IMM_DATA[15]}},W_ISTC_IMM_DATA}; end default: begin O_GPR_RD_EN_A <= 1'b0; O_GPR_RD_ADDR_A <= `DEF_GPR_ADDR_NOP; O_GPR_RD_EN_B <= 1'b0; O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP; O_ALU_OP_TYPE <= `DEF_ALU_NOP_OPR; // O_ALU_SEL <= `DEF_ALU_SEL_NOP; O_DST_GPR_WR_EN <= 1'b0; O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP; R_ISTC_VAL <= 1'b0; R_IMM_DATA_32BIT <= 32'd0; end endcase if(I_ISTC[31:21] == 11'd0) begin case(W_ISTC_5_0_BIT) `DEF_ISTC_SLL: begin O_GPR_RD_EN_A <= 1'b0; O_GPR_RD_ADDR_A <= `DEF_GPR_ADDR_NOP; O_GPR_RD_EN_B <= 1'b1; O_GPR_RD_ADDR_B <= W_DST_GPR_ADDR; O_ALU_OP_TYPE <= `DEF_ALU_SLL_OPR; // O_ALU_SEL <= `DEF_ALU_SEL_LOGIC; O_DST_GPR_WR_EN <= 1'b1; O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= {27'd0,W_ISTC_10_6_BIT}; end `DEF_ISTC_SRL: begin O_GPR_RD_EN_A <= 1'b0; O_GPR_RD_ADDR_A <= `DEF_GPR_ADDR_NOP; O_GPR_RD_EN_B <= 1'b1; O_GPR_RD_ADDR_B <= W_DST_GPR_ADDR; O_ALU_OP_TYPE <= `DEF_ALU_SRL_OPR; // O_ALU_SEL <= `DEF_ALU_SEL_LOGIC; O_DST_GPR_WR_EN <= 1'b1; O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= {27'd0,W_ISTC_10_6_BIT}; end `DEF_ISTC_SRA: begin O_GPR_RD_EN_A <= 1'b0; O_GPR_RD_ADDR_A <= `DEF_GPR_ADDR_NOP; O_GPR_RD_EN_B <= 1'b1; O_GPR_RD_ADDR_B <= W_DST_GPR_ADDR; O_ALU_OP_TYPE <= `DEF_ALU_SRA_OPR; // O_ALU_SEL <= `DEF_ALU_SEL_LOGIC; O_DST_GPR_WR_EN <= 1'b1; O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT; R_ISTC_VAL <= 1'b1; R_IMM_DATA_32BIT <= {27'd0,W_ISTC_10_6_BIT}; end default: begin O_GPR_RD_EN_A <= 1'b0; O_GPR_RD_ADDR_A <= `DEF_GPR_ADDR_NOP; O_GPR_RD_EN_B <= 1'b0; O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP; O_ALU_OP_TYPE <= `DEF_ALU_NOP_OPR; // O_ALU_SEL <= `DEF_ALU_SEL_NOP; O_DST_GPR_WR_EN <= 1'b0; O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP; R_ISTC_VAL <= 1'b0; R_IMM_DATA_32BIT <= 32'd0; end endcase end end end // | 数据输出 always @ (posedge I_CPU_CLK) begin if(~I_CPU_RSTN) begin O_SRC_OPR_DATA_A <= `DEF_ZERO_WORD; end else if(I_DST_GPR_WR_EN_FROM_EXE_MDL && O_GPR_RD_EN_A && (O_GPR_RD_ADDR_A == I_DST_GPR_WR_ADDR_FROM_EXE_MDL)) begin O_SRC_OPR_DATA_A <= I_DST_GPR_WR_DATA_FROM_EXE_MDL; end else if(I_DST_GPR_WR_EN_FROM_MEM_ACS_MDL && O_GPR_RD_EN_A && (O_GPR_RD_ADDR_A == I_DST_GPR_WR_ADDR_FROM_MEM_ACS_MDL)) begin O_SRC_OPR_DATA_A <= I_DST_GPR_WR_DATA_FROM_MEM_ACS_MDL; end else if(O_GPR_RD_EN_A) begin O_SRC_OPR_DATA_A <= I_GPR_RD_DATA_A; end else if(~O_GPR_RD_EN_A) begin O_SRC_OPR_DATA_A <= R_IMM_DATA_32BIT; end else begin O_SRC_OPR_DATA_A <= `DEF_ZERO_WORD; end end always @ (posedge I_CPU_CLK) begin if(~I_CPU_RSTN) begin O_SRC_OPR_DATA_B <= `DEF_ZERO_WORD; end else if(I_DST_GPR_WR_EN_FROM_EXE_MDL && O_GPR_RD_EN_B && (O_GPR_RD_ADDR_B == I_DST_GPR_WR_ADDR_FROM_EXE_MDL)) begin O_SRC_OPR_DATA_B <= I_DST_GPR_WR_DATA_FROM_EXE_MDL; end else if(I_DST_GPR_WR_EN_FROM_MEM_ACS_MDL && O_GPR_RD_EN_B && (O_GPR_RD_ADDR_B == I_DST_GPR_WR_ADDR_FROM_MEM_ACS_MDL)) begin O_SRC_OPR_DATA_B <= I_DST_GPR_WR_DATA_FROM_MEM_ACS_MDL; end else if(O_GPR_RD_EN_B) begin O_SRC_OPR_DATA_B <= I_GPR_RD_DATA_B; end else if(~O_GPR_RD_EN_B) begin O_SRC_OPR_DATA_B <= R_IMM_DATA_32BIT; end else begin O_SRC_OPR_DATA_B <= `DEF_ZERO_WORD; end end endmodule
指令执行模块
// |------------------------------ ================================== ------------------------------ // |============================== 指令-执行模块 ============================== // |------------------------------ ================================== ------------------------------ // |Create Date : 2022-12-07 // |Finish Date : 2022-12-07 // |Edited by : Xu Y. B. (CSDN USER NAME :在路上,正出发) // |Reference : 《自己动手写CPU》 // | // | // |------------------------------------------------------------------------------------------------ // |---------------------------------------- Change History ---------------------------------------- // |Date:2022-12-08 // |Who :Xu Y. B. // |What:修复流水线数据相关的问题(第 2、3类问题) // | 增加模块端口:Line 42 - 44 // | 两部分输出区别:组合逻辑输出和时序逻辑输出 // | 代码变动行编号:Line 73、77、84、88、103、111、115、116 // |Date:2022-12-09 // |Who :Xu Y. B. // |What:增加逻辑、移位运算执行功能 // |Date:2022-12-11 // |Who :Xu Y. B. // |What:增加移动运算执行功能 // |Date:2022-12-12 // |Who :Xu Y. B. // |What:增加简单算数运算执行功能 `include "MIPS_SYS_DEFINES.v" `timescale 1ns / 1ps module EXE_MDL( // |-------------------------------------- 输入输出端口声明 -------------------------------------- // |------------------------------------------------------------------------------------------------ // | 时钟、复位 input I_CPU_CLK, input I_CPU_RSTN, // | 操作指令 // input [`DEF_ALU_SEL_BUS] I_ALU_SEL, input [`DEF_ALU_OPR_BUS] I_ALU_OP_TYPE, // | 源操作数 input [`DEF_SRC_OPR_DATA_BUS] I_SRC_OPR_DATA_A, input [`DEF_SRC_OPR_DATA_BUS] I_SRC_OPR_DATA_B, // | 目的寄存器写 input I_DST_GPR_WR_EN, input [`DEF_GPR_ADDR_WIDTH-1:0] I_DST_GPR_WR_ADDR, // | HI LO 寄存器 // | HI_LO_REG_MDL 的输出 input [`DEF_GPR_DATA_WIDTH-1:0] I_HI, input [`DEF_GPR_DATA_WIDTH-1:0] I_LO, // | MEM_ACS_MDL 输出 input [`DEF_GPR_DATA_WIDTH-1:0] I_HI_FROM_MEM_ACS_MDL, input [`DEF_GPR_DATA_WIDTH-1:0] I_LO_FROM_MEM_ACS_MDL, input I_WR_EN_FROM_MEM_ACS_MDL, // | HI_LO_REG_MDL 的输入 input [`DEF_GPR_DATA_WIDTH-1:0] I_HI_FROM_HI_LO_REG_MDL, input [`DEF_GPR_DATA_WIDTH-1:0] I_LO_FROM_HI_LO_REG_MDL, input I_WR_EN_FROM_HI_LO_REG_MDL, // | 输出 output reg O_DST_GPR_WR_EN, output reg [`DEF_GPR_ADDR_WIDTH-1:0] O_DST_GPR_WR_ADDR, output reg [`DEF_GPR_DATA_WIDTH-1:0] O_DST_GPR_WR_DATA, // 反馈至 译码模块 output O_DST_GPR_WR_EN_2_ID_MDL, output [`DEF_GPR_ADDR_WIDTH-1:0] O_DST_GPR_WR_ADDR_2_ID_MDL, output reg [`DEF_GPR_DATA_WIDTH-1:0] O_DST_GPR_WR_DATA_2_ID_MDL, // 寄存器输出 output reg [`DEF_GPR_DATA_WIDTH-1:0] O_HI, output reg [`DEF_GPR_DATA_WIDTH-1:0] O_LO, output reg O_HILO_WR_EN ); // |-------------------------------------- 模块内部信号声明 -------------------------------------- // |------------------------------------------------------------------------------------------------ // | I_ALU_OP_TYPE 打拍 reg [`DEF_ALU_OPR_BUS] R_I_ALU_OP_TYPE; reg R_I_DST_GPR_WR_EN; reg [`DEF_GPR_ADDR_WIDTH-1:0] R_I_DST_GPR_WR_ADDR; reg [`DEF_GPR_DATA_WIDTH-1:0] R_HI; reg [`DEF_GPR_DATA_WIDTH-1:0] R_LO; // 组合逻辑输出 reg [`DEF_GPR_DATA_WIDTH-1:0] R_O_HI; reg [`DEF_GPR_DATA_WIDTH-1:0] R_O_LO; reg R_O_HILO_WR_EN; wire signed [`DEF_SRC_OPR_DATA_BUS] W_I_SRC_OPR_DATA_A_SIGNED; wire signed [`DEF_SRC_OPR_DATA_BUS] W_I_SRC_OPR_DATA_B_SIGNED; wire signed [`DEF_SRC_OPR_DATA_BUS] W_A_ADD_B_SIGNED; wire signed [`DEF_SRC_OPR_DATA_BUS] W_A_SUB_B_SIGNED; wire W_OVER_FLOW_FLAG; // reg [31:0] W_MUL_RES_H32; // |-------------------------------------- 模块内部逻辑设计 -------------------------------------- // |------------------------------------------------------------------------------------------------ // | I_ALU_OP_TYPE 打拍对齐时序 always @ (posedge I_CPU_CLK) begin if(~I_CPU_RSTN) begin R_I_ALU_OP_TYPE <= 0; end else begin R_I_ALU_OP_TYPE <= I_ALU_OP_TYPE; end end // | 判断选择最新的 HI LO always @ (*) begin if(~I_CPU_RSTN) begin R_HI = `DEF_ZERO_WORD; R_LO = `DEF_ZERO_WORD; end else if(I_WR_EN_FROM_MEM_ACS_MDL) begin R_HI = I_HI_FROM_MEM_ACS_MDL; R_LO = I_LO_FROM_MEM_ACS_MDL; end else if(I_WR_EN_FROM_HI_LO_REG_MDL) begin R_HI = I_HI_FROM_HI_LO_REG_MDL; R_LO = I_LO_FROM_HI_LO_REG_MDL; end else begin R_HI = I_HI; R_LO = I_LO; end end // | 操作数有符号形式 assign W_I_SRC_OPR_DATA_A_SIGNED = I_SRC_OPR_DATA_A; assign W_I_SRC_OPR_DATA_B_SIGNED = I_SRC_OPR_DATA_B; assign W_A_ADD_B_SIGNED = W_I_SRC_OPR_DATA_A_SIGNED + W_I_SRC_OPR_DATA_B_SIGNED; assign W_A_SUB_B_SIGNED = W_I_SRC_OPR_DATA_A_SIGNED - W_I_SRC_OPR_DATA_B_SIGNED; assign W_OVER_FLOW_FLAG = (!W_I_SRC_OPR_DATA_A_SIGNED[31] && !W_I_SRC_OPR_DATA_B_SIGNED[31] && W_A_ADD_B_SIGNED[31]) || ( W_I_SRC_OPR_DATA_A_SIGNED[31] && W_I_SRC_OPR_DATA_B_SIGNED[31] && !W_A_ADD_B_SIGNED[31]); // | 计算单元 // 组合逻辑 always @ (*) begin if(~I_CPU_RSTN) begin O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD; R_O_HILO_WR_EN = 1'b0; R_O_HI = `DEF_ZERO_WORD; R_O_LO = `DEF_ZERO_WORD; end else begin case(R_I_ALU_OP_TYPE) `DEF_ALU_OR_OPR: begin O_DST_GPR_WR_DATA_2_ID_MDL = I_SRC_OPR_DATA_A | I_SRC_OPR_DATA_B; R_O_HILO_WR_EN = 1'b0; R_O_HI = `DEF_ZERO_WORD; R_O_LO = `DEF_ZERO_WORD; end `DEF_ALU_AND_OPR: begin O_DST_GPR_WR_DATA_2_ID_MDL = I_SRC_OPR_DATA_A & I_SRC_OPR_DATA_B; R_O_HILO_WR_EN = 1'b0; R_O_HI = `DEF_ZERO_WORD; R_O_LO = `DEF_ZERO_WORD; end `DEF_ALU_XOR_OPR: begin O_DST_GPR_WR_DATA_2_ID_MDL = I_SRC_OPR_DATA_A ^ I_SRC_OPR_DATA_B; R_O_HILO_WR_EN = 1'b0; R_O_HI = `DEF_ZERO_WORD; R_O_LO = `DEF_ZERO_WORD; end `DEF_ALU_NOR_OPR: begin O_DST_GPR_WR_DATA_2_ID_MDL = ~(I_SRC_OPR_DATA_A | I_SRC_OPR_DATA_B); R_O_HILO_WR_EN = 1'b0; R_O_HI = `DEF_ZERO_WORD; R_O_LO = `DEF_ZERO_WORD; end `DEF_ALU_SLL_OPR: begin O_DST_GPR_WR_DATA_2_ID_MDL = I_SRC_OPR_DATA_B << I_SRC_OPR_DATA_A; R_O_HILO_WR_EN = 1'b0; R_O_HI = `DEF_ZERO_WORD; R_O_LO = `DEF_ZERO_WORD; end `DEF_ALU_SRL_OPR: begin O_DST_GPR_WR_DATA_2_ID_MDL = I_SRC_OPR_DATA_B >> I_SRC_OPR_DATA_A; R_O_HILO_WR_EN = 1'b0; R_O_HI = `DEF_ZERO_WORD; R_O_LO = `DEF_ZERO_WORD; end `DEF_ALU_SRA_OPR: begin O_DST_GPR_WR_DATA_2_ID_MDL = ({32{I_SRC_OPR_DATA_B[31]}} << (6'd32 - I_SRC_OPR_DATA_A[5:0])) | (I_SRC_OPR_DATA_B >> I_SRC_OPR_DATA_A); R_O_HILO_WR_EN = 1'b0; R_O_HI = `DEF_ZERO_WORD; R_O_LO = `DEF_ZERO_WORD; end `DEF_ALU_MOVZ_OPR: begin O_DST_GPR_WR_DATA_2_ID_MDL = I_SRC_OPR_DATA_A; R_O_HILO_WR_EN = 1'b0; R_O_HI = `DEF_ZERO_WORD; R_O_LO = `DEF_ZERO_WORD; end `DEF_ALU_MOVN_OPR: begin O_DST_GPR_WR_DATA_2_ID_MDL = I_SRC_OPR_DATA_A; R_O_HILO_WR_EN = 1'b0; R_O_HI = `DEF_ZERO_WORD; R_O_LO = `DEF_ZERO_WORD; end `DEF_ALU_MFHI_OPR: begin O_DST_GPR_WR_DATA_2_ID_MDL = R_HI; R_O_HILO_WR_EN = 1'b0; R_O_HI = `DEF_ZERO_WORD; R_O_LO = `DEF_ZERO_WORD; end `DEF_ALU_MTHI_OPR: begin O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD; R_O_HILO_WR_EN = 1'b1; R_O_HI = I_SRC_OPR_DATA_A; R_O_LO = R_LO; end `DEF_ALU_MFLO_OPR: begin O_DST_GPR_WR_DATA_2_ID_MDL = R_LO; R_O_HILO_WR_EN = 1'b0; R_O_HI = `DEF_ZERO_WORD; R_O_LO = `DEF_ZERO_WORD; end `DEF_ALU_MTLO_OPR: begin O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD; R_O_HILO_WR_EN = 1'b1; R_O_HI = R_HI; R_O_LO = I_SRC_OPR_DATA_A; end `DEF_ALU_SLT_OPR : begin if(W_I_SRC_OPR_DATA_A_SIGNED < W_I_SRC_OPR_DATA_B_SIGNED) begin O_DST_GPR_WR_DATA_2_ID_MDL = 32'd1; end else begin O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD; end R_O_HILO_WR_EN = 1'b0; R_O_HI = `DEF_ZERO_WORD; R_O_LO = `DEF_ZERO_WORD; end `DEF_ALU_SLTU_OPR : begin if(I_SRC_OPR_DATA_A < I_SRC_OPR_DATA_B) begin O_DST_GPR_WR_DATA_2_ID_MDL = 32'd1; end else begin O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD; end R_O_HILO_WR_EN = 1'b0; R_O_HI = `DEF_ZERO_WORD; R_O_LO = `DEF_ZERO_WORD; end `DEF_ALU_SLTI_OPR : begin if(W_I_SRC_OPR_DATA_A_SIGNED < W_I_SRC_OPR_DATA_B_SIGNED) begin O_DST_GPR_WR_DATA_2_ID_MDL = 32'd1; end else begin O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD; end R_O_HILO_WR_EN = 1'b0; R_O_HI = `DEF_ZERO_WORD; R_O_LO = `DEF_ZERO_WORD; end `DEF_ALU_SLTIU_OPR: begin if(I_SRC_OPR_DATA_A < I_SRC_OPR_DATA_B) begin O_DST_GPR_WR_DATA_2_ID_MDL = 32'd1; end else begin O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD; end R_O_HILO_WR_EN = 1'b0; R_O_HI = `DEF_ZERO_WORD; R_O_LO = `DEF_ZERO_WORD; end `DEF_ALU_ADD_OPR : begin O_DST_GPR_WR_DATA_2_ID_MDL = W_A_ADD_B_SIGNED; R_O_HILO_WR_EN = 1'b0; R_O_HI = `DEF_ZERO_WORD; R_O_LO = `DEF_ZERO_WORD; end `DEF_ALU_ADDU_OPR : begin O_DST_GPR_WR_DATA_2_ID_MDL = W_A_ADD_B_SIGNED; R_O_HILO_WR_EN = 1'b0; R_O_HI = `DEF_ZERO_WORD; R_O_LO = `DEF_ZERO_WORD; end `DEF_ALU_SUB_OPR : begin O_DST_GPR_WR_DATA_2_ID_MDL = W_A_SUB_B_SIGNED; R_O_HILO_WR_EN = 1'b0; R_O_HI = `DEF_ZERO_WORD; R_O_LO = `DEF_ZERO_WORD; end `DEF_ALU_SUBU_OPR : begin O_DST_GPR_WR_DATA_2_ID_MDL = W_A_SUB_B_SIGNED; R_O_HILO_WR_EN = 1'b0; R_O_HI = `DEF_ZERO_WORD; R_O_LO = `DEF_ZERO_WORD; end `DEF_ALU_ADDI_OPR : begin O_DST_GPR_WR_DATA_2_ID_MDL = W_A_ADD_B_SIGNED; R_O_HILO_WR_EN = 1'b0; R_O_HI = `DEF_ZERO_WORD; R_O_LO = `DEF_ZERO_WORD; end `DEF_ALU_ADDIU_OPR: begin O_DST_GPR_WR_DATA_2_ID_MDL = W_A_ADD_B_SIGNED; R_O_HILO_WR_EN = 1'b0; R_O_HI = `DEF_ZERO_WORD; R_O_LO = `DEF_ZERO_WORD; end `DEF_ALU_CLZ_OPR : begin O_DST_GPR_WR_DATA_2_ID_MDL = I_SRC_OPR_DATA_A[31] ? 0 : I_SRC_OPR_DATA_A[30] ? 1 : I_SRC_OPR_DATA_A[29] ? 2 : I_SRC_OPR_DATA_A[28] ? 3 : I_SRC_OPR_DATA_A[27] ? 4 : I_SRC_OPR_DATA_A[26] ? 5 : I_SRC_OPR_DATA_A[25] ? 6 : I_SRC_OPR_DATA_A[24] ? 7 : I_SRC_OPR_DATA_A[23] ? 8 : I_SRC_OPR_DATA_A[22] ? 9 : I_SRC_OPR_DATA_A[21] ? 10 : I_SRC_OPR_DATA_A[20] ? 11 : I_SRC_OPR_DATA_A[19] ? 12 : I_SRC_OPR_DATA_A[18] ? 13 : I_SRC_OPR_DATA_A[17] ? 14 : I_SRC_OPR_DATA_A[16] ? 15 : I_SRC_OPR_DATA_A[15] ? 16 : I_SRC_OPR_DATA_A[14] ? 17 : I_SRC_OPR_DATA_A[13] ? 18 : I_SRC_OPR_DATA_A[12] ? 19 : I_SRC_OPR_DATA_A[11] ? 20 : I_SRC_OPR_DATA_A[10] ? 21 : I_SRC_OPR_DATA_A[9] ? 22 : I_SRC_OPR_DATA_A[8] ? 23 : I_SRC_OPR_DATA_A[7] ? 24 : I_SRC_OPR_DATA_A[6] ? 25 : I_SRC_OPR_DATA_A[5] ? 26 : I_SRC_OPR_DATA_A[4] ? 27 : I_SRC_OPR_DATA_A[3] ? 28 : I_SRC_OPR_DATA_A[2] ? 29 : I_SRC_OPR_DATA_A[1] ? 30 : I_SRC_OPR_DATA_A[0] ? 31 : 32; R_O_HILO_WR_EN = 1'b0; R_O_HI = `DEF_ZERO_WORD; R_O_LO = `DEF_ZERO_WORD; end `DEF_ALU_CLO_OPR : begin O_DST_GPR_WR_DATA_2_ID_MDL = !I_SRC_OPR_DATA_A[31] ? 0 : !I_SRC_OPR_DATA_A[30] ? 1 : !I_SRC_OPR_DATA_A[29] ? 2 : !I_SRC_OPR_DATA_A[28] ? 3 : !I_SRC_OPR_DATA_A[27] ? 4 : !I_SRC_OPR_DATA_A[26] ? 5 : !I_SRC_OPR_DATA_A[25] ? 6 : !I_SRC_OPR_DATA_A[24] ? 7 : !I_SRC_OPR_DATA_A[23] ? 8 : !I_SRC_OPR_DATA_A[22] ? 9 : !I_SRC_OPR_DATA_A[21] ? 10 : !I_SRC_OPR_DATA_A[20] ? 11 : !I_SRC_OPR_DATA_A[19] ? 12 : !I_SRC_OPR_DATA_A[18] ? 13 : !I_SRC_OPR_DATA_A[17] ? 14 : !I_SRC_OPR_DATA_A[16] ? 15 : !I_SRC_OPR_DATA_A[15] ? 16 : !I_SRC_OPR_DATA_A[14] ? 17 : !I_SRC_OPR_DATA_A[13] ? 18 : !I_SRC_OPR_DATA_A[12] ? 19 : !I_SRC_OPR_DATA_A[11] ? 20 : !I_SRC_OPR_DATA_A[10] ? 21 : !I_SRC_OPR_DATA_A[9] ? 22 : !I_SRC_OPR_DATA_A[8] ? 23 : !I_SRC_OPR_DATA_A[7] ? 24 : !I_SRC_OPR_DATA_A[6] ? 25 : !I_SRC_OPR_DATA_A[5] ? 26 : !I_SRC_OPR_DATA_A[4] ? 27 : !I_SRC_OPR_DATA_A[3] ? 28 : !I_SRC_OPR_DATA_A[2] ? 29 : !I_SRC_OPR_DATA_A[1] ? 30 : !I_SRC_OPR_DATA_A[0] ? 31 : 32; R_O_HILO_WR_EN = 1'b0; R_O_HI = `DEF_ZERO_WORD; R_O_LO = `DEF_ZERO_WORD; end `DEF_ALU_MULT_OPR : begin O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD; R_O_HILO_WR_EN = 1'b1; {R_O_HI,R_O_LO} = W_I_SRC_OPR_DATA_A_SIGNED * W_I_SRC_OPR_DATA_B_SIGNED; end `DEF_ALU_MULTU_OPR: begin O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD; R_O_HILO_WR_EN = 1'b1; {R_O_HI,R_O_LO} = I_SRC_OPR_DATA_A * I_SRC_OPR_DATA_B; end `DEF_ALU_MUL_OPR : begin O_DST_GPR_WR_DATA_2_ID_MDL = W_I_SRC_OPR_DATA_A_SIGNED * W_I_SRC_OPR_DATA_B_SIGNED; R_O_HILO_WR_EN = 1'b0; R_O_HI = `DEF_ZERO_WORD; R_O_LO = `DEF_ZERO_WORD; end default: begin O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD; R_O_HILO_WR_EN = 1'b0; R_O_HI = `DEF_ZERO_WORD; R_O_LO = `DEF_ZERO_WORD; end endcase end end // HI LO 寄存输出 always @ (posedge I_CPU_CLK) begin if(~I_CPU_RSTN) begin O_HILO_WR_EN <= 1'b0; O_HI <= 32'd0; O_LO <= 32'd0; end else begin O_HILO_WR_EN <= R_O_HILO_WR_EN; O_HI <= R_O_HI ; O_LO <= R_O_LO ; end end // | 写操作打拍 always @ (posedge I_CPU_CLK) begin if(~I_CPU_RSTN) begin O_DST_GPR_WR_EN <= 1'b0; O_DST_GPR_WR_ADDR <= 5'd0; R_I_DST_GPR_WR_EN <= 1'b0; R_I_DST_GPR_WR_ADDR <= 5'd0; O_DST_GPR_WR_DATA <= `DEF_ZERO_WORD; end else begin R_I_DST_GPR_WR_EN <= I_DST_GPR_WR_EN; R_I_DST_GPR_WR_ADDR <= I_DST_GPR_WR_ADDR; if(R_I_ALU_OP_TYPE == `DEF_ALU_MOVZ_OPR) begin if(I_SRC_OPR_DATA_B == `DEF_ZERO_WORD) begin O_DST_GPR_WR_EN <= 1'b1; end else begin O_DST_GPR_WR_EN <= 1'b0; end end else if(R_I_ALU_OP_TYPE == `DEF_ALU_MOVN_OPR) begin if(I_SRC_OPR_DATA_B == `DEF_ZERO_WORD) begin O_DST_GPR_WR_EN <= 1'b0; end else begin O_DST_GPR_WR_EN <= 1'b1; end end else if((R_I_ALU_OP_TYPE == `DEF_ALU_ADD_OPR || R_I_ALU_OP_TYPE == `DEF_ALU_SUB_OPR || R_I_ALU_OP_TYPE == `DEF_ALU_ADDI_OPR) && W_OVER_FLOW_FLAG) begin O_DST_GPR_WR_EN <= 1'b0; end else begin O_DST_GPR_WR_EN <= R_I_DST_GPR_WR_EN; end O_DST_GPR_WR_ADDR <= R_I_DST_GPR_WR_ADDR; O_DST_GPR_WR_DATA <= O_DST_GPR_WR_DATA_2_ID_MDL; end end assign O_DST_GPR_WR_EN_2_ID_MDL = R_I_DST_GPR_WR_EN ; assign O_DST_GPR_WR_ADDR_2_ID_MDL = R_I_DST_GPR_WR_ADDR; endmodule
仿真
仿真程序
此处参考书本。
.org 0x0
.global _start
.set noat
_start:
ori $1,$0,0x8000
sll $1,$1,16
ori $1,$1,0x0010
ori $2,$0,0x8000
sll $2,$2,16
ori $2,$2,0x0001
ori $3,$0,0x0000
addu $3,$2,$1
ori $3,$0,0x0000
add $2,$2,$1
sub $3,$1,$3
subu $3,$3,$2
addi $3,$3,2
ori $3,$0,0x0000
addiu $3,$3,0x8000
or $1,$0,0xFFFF
sll $1,$1,16
slt $2,$1,$0
sltu $2,$1,$0
slti $2,$1,0x8000
sltiu $2,$1,0x8000
lui $1,0x0000
clo $2,$1
clz $2,$1
lui $1,0xFFFF
ori $1,$1,0xFFFF
clz $2,$1
clo $2,$1
lui $1,0xA100
clz $2,$1
clo $2,$1
lui $1,0x1100
clz $2,$1
clo $2,$1
ori $1,$0,0xFFFF
sll $1,$1,16
ori $1,$1,0xFFFB
ori $2,$0,6
mul $3,$1,$2
mult $1,$2
multu $1,$2
nop
nop
仿真结果
具体细节可以自行仿真查看。