目录
引言
随章节进度继续推进,本章继续实现 32位整数除法 指令等其他操作指令。
致谢
感谢书籍《自己动手写CPU》及其作者雷思磊。一并感谢开源精神。
除法指令
div、divu
该两条指令均为 SPECIAL ,第6~15位为 0 。需要根据低六位判断功能。
指令用法:
试商法设计思路
思路详述
在整数除法中,
商的位宽和被除数一致,余数的位宽与除数一致。
需要的步骤数等于被除数位宽。
以6位被除数 除以 3位除数为例,说明:
长除法 101101 / 110 :
除法模块设计
// |------------------------------ ================================== ------------------------------
// |============================== 顶层模块仿真平台 ==============================
// |------------------------------ ================================== ------------------------------
// |Create Date : 2022-12-15
// |Finish Date : 2022-12-15
// |Edited by : Xu Y. B. (CSDN USER NAME :在路上,正出发)
// |Reference : 《自己动手写CPU》
// |
// |
// |------------------------------------------------------------------------------------------------
// |---------------------------------------- Change History ----------------------------------------
// |Date:2022-12-15
// |Who :Xu Y. B.
// |What:实现32位整数除法 _OPR_DATA_A / _OPR_DATA_B
`timescale 1ns / 1ps
module DIV_OPR_MDL(
// |-------------------------------------- 输入输出端口声明 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 时钟、复位
input I_CPU_CLK,
input I_CPU_RSTN,
input I_DIV_TYPE, // 1:有符号除法,0:无符号除法 电平信号
input [31:0] I_OPR_DATA_A,
input [31:0] I_OPR_DATA_B,
input I_OPR_EN,//电平信号 需要与数据同步
input I_OPR_CANCEL,//脉冲信号 取消除法运算
output reg O_RES_VAL,
output reg [63:0] O_RES
);
// |-------------------------------------- 模块内部参数声明 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 状态编码
localparam LP_ST_IDLE = 3'b001;
localparam LP_ST_ZERO = 3'b010;
localparam LP_ST_WORK = 3'b100;
// |-------------------------------------- 模块内部信号声明 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 状态信号
reg [2:0] R_STATE;
// | 计数器
reg [5:0] R_CNT;
// | 操作数
reg [31:0] R_OPR_A;
reg [31:0] R_OPR_B;
reg [64:0] R_DIVIDEND;
reg [31:0] R_DIVISOR;
wire [32:0] W_DIV_TMP;
// |-------------------------------------- 模块内部逻辑设计 --------------------------------------
// |------------------------------------------------------------------------------------------------
assign W_DIV_TMP = {1'b0,R_DIVIDEND[63:32]} - {1'b0,R_DIVISOR};
// | 状态机
always @ (posedge I_CPU_CLK)
begin
if(~I_CPU_RSTN)
begin
R_STATE <= LP_ST_IDLE;
R_CNT <= 6'd0;
O_RES_VAL <= 1'b0;
O_RES <= 64'd0;
R_OPR_A <= 32'd0;
R_OPR_B <= 32'd0;
R_DIVIDEND<= 65'd0;
R_DIVISOR <= 32'd0;
end
else
begin
case(R_STATE)
LP_ST_IDLE:
begin
R_CNT <= 6'd0;
O_RES_VAL <= 1'b0;
O_RES <= 64'd0;
R_DIVIDEND<= 65'd0;
R_DIVISOR <= 32'd0;
if(I_OPR_EN & !I_OPR_CANCEL)
begin
if(I_OPR_DATA_B == 32'd0)
begin
R_STATE <= LP_ST_ZERO;
R_OPR_A <= 32'd0;
R_OPR_B <= 32'd0;
end
else
begin
R_STATE <= LP_ST_WORK;
if(I_DIV_TYPE)
begin
if(I_OPR_DATA_A[31])
begin
R_OPR_A <= ~I_OPR_DATA_A + 1;
end
else
begin
R_OPR_A <= I_OPR_DATA_A;
end
if(I_OPR_DATA_B[31])
begin
R_OPR_B <= ~I_OPR_DATA_B + 1;
end
else
begin
R_OPR_B <= I_OPR_DATA_B;
end
end
else
begin
R_OPR_A <= I_OPR_DATA_A;
R_OPR_B <= I_OPR_DATA_B;
end
end
end
else
begin
R_STATE <= LP_ST_IDLE;
R_OPR_A <= 32'd0;
R_OPR_B <= 32'd0;
end
end
LP_ST_ZERO:
begin
O_RES_VAL <= 1'b1;
O_RES <= 64'd0;
R_STATE <= LP_ST_IDLE;
R_CNT <= 6'd0;
R_DIVIDEND<= 65'd0;
R_DIVISOR <= 32'd0;
end
LP_ST_WORK:
begin
if(!I_OPR_CANCEL)
begin
if(R_CNT == 6'd0)
begin
R_DIVIDEND[32:1] <= R_OPR_A;
R_DIVISOR <= R_OPR_B;
R_STATE <= LP_ST_WORK;
R_CNT <= R_CNT + 1;
end
else if(R_CNT == 6'd33)
begin
if(I_DIV_TYPE && ((I_OPR_DATA_A[31] ^ I_OPR_DATA_B[31]) == 1'b1))
begin
R_DIVIDEND[31:0] <= (~R_DIVIDEND[31:0]) + 1;
end
if(I_DIV_TYPE && ((I_OPR_DATA_A[31] ^ R_DIVIDEND[64]) == 1'b1))
begin
R_DIVIDEND[64:33] <= (~R_DIVIDEND[64:33]) + 1;
end
R_STATE <= LP_ST_WORK;
R_CNT <= R_CNT + 1;
end
else if(R_CNT == 6'd34)
begin
O_RES_VAL <= 1'b1;
O_RES <= {R_DIVIDEND[64:33] , R_DIVIDEND[31:0]};
R_STATE <= LP_ST_IDLE;
R_CNT <= 32'd0;
end
else
begin
if(W_DIV_TMP[32])
begin
R_DIVIDEND <= {R_DIVIDEND[63:0] , 1'b0};
end
else
begin
R_DIVIDEND <= {W_DIV_TMP[31:0] , R_DIVIDEND[31:0] , 1'b1};
end
R_CNT <= R_CNT + 1;
R_STATE <= LP_ST_WORK;
end
end
else
begin
R_STATE <= LP_ST_IDLE;
end
end
default:
begin
R_STATE <= LP_ST_IDLE;
end
endcase
end
end
endmodule
除法模块仿真
TEST BENCH
// |------------------------------ ================================== ------------------------------
// |============================== 顶层模块仿真平台 ==============================
// |------------------------------ ================================== ------------------------------
// |Create Date : 2022-12-15
// |Finish Date : 2022-12-15
// |Edited by : Xu Y. B. (CSDN USER NAME :在路上,正出发)
// |Reference : 《自己动手写CPU》
// |
// |
// |------------------------------------------------------------------------------------------------
// |---------------------------------------- Change History ----------------------------------------
// |Date:2022-12-15
// |Who :Xu Y. B.
// |What:
`timescale 1ns / 1ps
module TB_DIV_OPR_MDL();
// |-------------------------------------- 输入输出端口声明 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 时钟、复位
reg I_CPU_CLK;
reg I_CPU_RSTN;
reg I_DIV_TYPE; // 1:有符号除法,0:无符号除法
reg [31:0] I_OPR_DATA_A;
reg [31:0] I_OPR_DATA_B;
reg I_OPR_EN;//电平信号 需要与数据同步
reg I_OPR_CANCEL;//脉冲信号 取消除法运算
wire O_RES_VAL;
wire [63:0] O_RES;
// | 产生激励
initial I_CPU_CLK = 1'b0;
always #10 I_CPU_CLK = ~I_CPU_CLK;
initial
begin
I_CPU_RSTN = 1'b0;
I_DIV_TYPE = 1'b0;
I_OPR_DATA_A = 32'd0;
I_OPR_DATA_B = 32'd0;
I_OPR_EN = 1'b0;
I_OPR_CANCEL = 1'b0;
#55;
I_CPU_RSTN = 1'b1;
#35;
// 有符号数除法
@(posedge I_CPU_CLK)// 正数 / 正数
I_OPR_EN <= 1'b1;
I_DIV_TYPE <= 1'b1;
I_OPR_DATA_A <= 32'd13;
I_OPR_DATA_B <= 32'd2;
@(negedge O_RES_VAL);
@(posedge I_CPU_CLK)// 正数 / 负数
I_OPR_EN <= 1'b1;
I_DIV_TYPE <= 1'b1;
I_OPR_DATA_A <= 32'd13;
I_OPR_DATA_B <= -32'd2;
@(negedge O_RES_VAL);
@(posedge I_CPU_CLK)// 负数 / 负数
I_OPR_EN <= 1'b1;
I_DIV_TYPE <= 1'b1;
I_OPR_DATA_A <= -32'd13;
I_OPR_DATA_B <= -32'd2;
@(negedge O_RES_VAL);
@(posedge I_CPU_CLK)// 负数 / 正数
I_OPR_EN <= 1'b1;
I_DIV_TYPE <= 1'b1;
I_OPR_DATA_A <= -32'd13;
I_OPR_DATA_B <= 32'd2;
// 无符号数除法
@(negedge O_RES_VAL);
@(posedge I_CPU_CLK)// 正数 / 正数
I_OPR_EN <= 1'b1;
I_DIV_TYPE <= 1'b0;
I_OPR_DATA_A <= 32'd100;
I_OPR_DATA_B <= 32'd2;
// 无符号数除法
@(negedge O_RES_VAL);
@(posedge I_CPU_CLK)// 正数 / 正数
I_OPR_EN <= 1'b1;
I_DIV_TYPE <= 1'b0;
I_OPR_DATA_A <= 32'd200;
I_OPR_DATA_B <= 32'd25;
// 无符号数除法
@(negedge O_RES_VAL);
@(posedge I_CPU_CLK)// 正数 / 正数
I_OPR_EN <= 1'b1;
I_DIV_TYPE <= 1'b0;
I_OPR_DATA_A <= 32'd1200;
I_OPR_DATA_B <= 32'd300;
@(negedge O_RES_VAL);
@(posedge I_CPU_CLK)// 中间终止
I_OPR_EN <= 1'b1;
I_DIV_TYPE <= 1'b0;
I_OPR_DATA_A <= -32'd13;
I_OPR_DATA_B <= 32'd2;
#(10*20);
@(posedge I_CPU_CLK);
I_OPR_CANCEL <= 1'b1;
#(10*20);
$finish;
end
// | 模块例化
DIV_OPR_MDL INST_DIV_OPR_MDL
(
.I_CPU_CLK (I_CPU_CLK),
.I_CPU_RSTN (I_CPU_RSTN),
.I_DIV_TYPE (I_DIV_TYPE),
.I_OPR_DATA_A (I_OPR_DATA_A),
.I_OPR_DATA_B (I_OPR_DATA_B),
.I_OPR_EN (I_OPR_EN),
.I_OPR_CANCEL (I_OPR_CANCEL),
.O_RES_VAL (O_RES_VAL),
.O_RES (O_RES)
);
endmodule
仿真结果
除法运算加入指令集
此处仅给出有改动模块的源码:
宏定义
// |------------------------------ ================================== ------------------------------
// |============================== 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操作功能宏定义
// |Date:2022-12-14
// |Who :Xu Y. B.
// |What:增加如下指令宏定义:
// | madd、maddu、msub、msubu
// | 以及相应的ALU操作功能宏定义
// |Date:2022-12-16
// |Who :Xu Y. B.
// |What:增加如下指令宏定义:
// | div、divu
// | 以及相应的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_MADD 6'b000000
`define DEF_ISTC_MADDU 6'b000001
`define DEF_ISTC_MSUB 6'b000100
`define DEF_ISTC_MSUBU 6'b000101
`define DEF_ISTC_DIV 6'b011010
`define DEF_ISTC_DIVU 6'b011011
`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_MADD_OPR 8'b10100110
`define DEF_ALU_MADDU_OPR 8'b10101000
`define DEF_ALU_MSUB_OPR 8'b10101010
`define DEF_ALU_MSUBU_OPR 8'b10101011
`define DEF_ALU_DIV_OPR 8'b00011010
`define DEF_ALU_DIVU_OPR 8'b00011011
`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:增加简单算术运算指令的译码功能
// |Date:2022-12-14
// |Who :Xu Y. B.
// |What:增加2步算术运算指令的译码功能
// |Date:2022-12-16
// |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 [`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,
// 流水线暂停
input [4:0] I_PAUSE_ACK,//待优化
output O_PAUSE_REQ
);
// |-------------------------------------- 模块内部信号声明 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 指令分解相关
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;
// 配合流水线暂停功能
wire [`DEF_ISTC_DATA_BUS] W_I_ISTC;
reg [`DEF_ALU_OPR_BUS] R_ALU_OP_TYPE;
reg [1:0] R_PAUSE_REQ;
// |-------------------------------------- 模块内部逻辑设计 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 指令分解相关
assign W_ISTC_TYPE = W_I_ISTC[31:26];// 指令码
assign W_SRC_GPR_ADDR = W_I_ISTC[25:21];
assign W_DST_GPR_ADDR = W_I_ISTC[20:16];
assign W_ISTC_IMM_DATA = W_I_ISTC[15:0] ;
assign W_ISTC_15_11_BIT = W_I_ISTC[15:11];
assign W_ISTC_10_6_BIT = W_I_ISTC[10:6];
assign W_ISTC_5_0_BIT = W_I_ISTC[5:0];
assign O_PAUSE_REQ = R_PAUSE_REQ[0] & (~R_PAUSE_REQ[1]);
// 下面两句故意设置为 锁存器,以满足功能需求
assign W_I_ISTC = (!I_PAUSE_ACK[1]) ? I_ISTC:W_I_ISTC;
assign O_ALU_OP_TYPE = (!I_PAUSE_ACK[1]) ? R_ALU_OP_TYPE:O_ALU_OP_TYPE;
always @ (posedge I_CPU_CLK)
begin
if(~I_CPU_RSTN)
begin
R_PAUSE_REQ <= 2'b00;
end
else if(W_ISTC_TYPE == `DEF_ISTC_SPEC2)
begin
R_PAUSE_REQ[1] <= R_PAUSE_REQ[0];
case(W_ISTC_5_0_BIT)
`DEF_ISTC_MADD,`DEF_ISTC_MADDU,`DEF_ISTC_MSUB,`DEF_ISTC_MSUBU:
begin
R_PAUSE_REQ[0] <= 1'b1;
end
default:
begin
R_PAUSE_REQ[0] <= R_PAUSE_REQ[0];
end
endcase
end
else if(W_ISTC_TYPE == `DEF_ISTC_SPEC)
begin
R_PAUSE_REQ[1] <= R_PAUSE_REQ[0];
case(W_ISTC_5_0_BIT)
`DEF_ISTC_DIVU,`DEF_ISTC_DIV:
begin
R_PAUSE_REQ[0] <= 1'b1;
end
default:
begin
R_PAUSE_REQ[0] <= R_PAUSE_REQ[0];
end
endcase
end
else
begin
R_PAUSE_REQ[0] <= R_PAUSE_REQ[0];
R_PAUSE_REQ[1] <= R_PAUSE_REQ[0];
end
end
// | 指令译码
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;
R_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;
R_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;
R_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;
R_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;
R_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;
R_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;
R_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;
R_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;
R_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;
R_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;
R_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;
R_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;
R_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;
R_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;
R_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;
R_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;
R_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;
R_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;
R_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;
R_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;
R_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;
R_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;
R_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
`DEF_ISTC_DIV :
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;
R_ALU_OP_TYPE <= `DEF_ALU_DIV_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_DIVU :
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;
R_ALU_OP_TYPE <= `DEF_ALU_DIVU_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;
R_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;
R_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;
R_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;
R_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;
R_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
`DEF_ISTC_MADD:
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;
R_ALU_OP_TYPE <= `DEF_ALU_MADD_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_MADDU:
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;
R_ALU_OP_TYPE <= `DEF_ALU_MADDU_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_MSUB :
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;
R_ALU_OP_TYPE <= `DEF_ALU_MSUB_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_MSUBU:
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;
R_ALU_OP_TYPE <= `DEF_ALU_MSUBU_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;
R_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;
R_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;
R_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;
R_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;
R_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;
R_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;
R_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;
R_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;
R_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;
R_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;
R_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(W_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;
R_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;
R_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;
R_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;
R_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:增加简单算术运算执行功能
// |Date:2022-12-14
// |Who :Xu Y. B.
// |What:增加2步算术运算执行功能
// |Date:2022-12-16
// |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,
// 流水线暂停
input [4:0] I_PAUSE_ACK,//待优化
output reg O_PAUSE_REQ
);
// |-------------------------------------- 模块内部信号声明 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 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;
// 暂存 乘加、乘减 的中间运算结果
reg [63:0] R_MID_RES_MULT;
// 2步运算指令计数器
reg [1:0] R_2STEP_ISTC_CNT;//位宽可能存在冗余
// 除法运算
wire W_DIV_RES_VAL;
wire [63:0] W_DIV_RES;
reg R_DIV_TYPE;
reg [31:0] R_OPR_DATA_A;
reg [31:0] R_OPR_DATA_B;
reg R_OPR_EN;
reg R_OPR_CANCEL;
reg R_PAUSE_REQ;
reg R_R_DIV_TYPE;
// |-------------------------------------- 模块内部逻辑设计 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | I_ALU_OP_TYPE 打拍对齐时序
always @ (posedge I_CPU_CLK)
begin
if(~I_CPU_RSTN)
begin
R_I_ALU_OP_TYPE <= 0;
end
else if(!I_PAUSE_ACK[2])
begin
R_I_ALU_OP_TYPE <= I_ALU_OP_TYPE;
end
else
begin
R_I_ALU_OP_TYPE <= R_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
`DEF_ALU_MADD_OPR ,`DEF_ALU_MADDU_OPR:
begin
O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD;
if(R_2STEP_ISTC_CNT == 1)
begin
R_O_HILO_WR_EN = 1'b1;
{R_O_HI,R_O_LO} = {R_HI[31],R_HI,R_LO} + {R_MID_RES_MULT[63],R_MID_RES_MULT};
end
else
begin
R_O_HILO_WR_EN = 1'b0;
R_O_HI = `DEF_ZERO_WORD;
R_O_LO = `DEF_ZERO_WORD;
end
end
`DEF_ALU_MSUB_OPR ,`DEF_ALU_MSUBU_OPR:
begin
O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD;
if(R_2STEP_ISTC_CNT == 1)
begin
R_O_HILO_WR_EN = 1'b1;
{R_O_HI,R_O_LO} = {R_HI[31],R_HI,R_LO} - {R_MID_RES_MULT[63],R_MID_RES_MULT};
end
else
begin
R_O_HILO_WR_EN = 1'b0;
R_O_HI = `DEF_ZERO_WORD;
R_O_LO = `DEF_ZERO_WORD;
end
end
`DEF_ALU_DIV_OPR,`DEF_ALU_DIVU_OPR :
begin
O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD;
if(W_DIV_RES_VAL)
begin
R_O_HILO_WR_EN = 1'b1;
{R_O_HI,R_O_LO} = W_DIV_RES;
end
else
begin
R_O_HILO_WR_EN = 1'b0;
R_O_HI = `DEF_ZERO_WORD;
R_O_LO = `DEF_ZERO_WORD;
end
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
if(!I_PAUSE_ACK[2])
begin
O_HILO_WR_EN <= R_O_HILO_WR_EN;
O_HI <= R_O_HI ;
O_LO <= R_O_LO ;
end
else
begin
O_HILO_WR_EN <= 1'b0;
O_HI <= 32'd0;
O_LO <= 32'd0;
end
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
if(!I_PAUSE_ACK[2])
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
else
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
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;
always @ (*)
begin
if(~I_CPU_RSTN)
begin
O_PAUSE_REQ = 1'b0;
end
else
begin
case(R_I_ALU_OP_TYPE)
`DEF_ALU_MADD_OPR,`DEF_ALU_MADDU_OPR,`DEF_ALU_MSUB_OPR,`DEF_ALU_MSUBU_OPR:
begin
if(R_2STEP_ISTC_CNT == 0)
begin
O_PAUSE_REQ = 1'b1;
end
else if(R_2STEP_ISTC_CNT == 1)
begin
O_PAUSE_REQ = 1'b0;
end
else
begin
O_PAUSE_REQ = 1'b1;
end
end
`DEF_ALU_DIV_OPR,`DEF_ALU_DIVU_OPR:
begin
if(W_DIV_RES_VAL)
begin
O_PAUSE_REQ = 1'b0;
end
else
begin
O_PAUSE_REQ = 1'b1;
end
end
default:
begin
O_PAUSE_REQ = O_PAUSE_REQ;//锁存器
end
endcase
end
end
always @ (posedge I_CPU_CLK)
begin
if(~I_CPU_RSTN)
begin
R_PAUSE_REQ <= 1'b0;
end
else
begin
R_PAUSE_REQ <= O_PAUSE_REQ;
end
end
always @ (posedge I_CPU_CLK)
begin
if(~I_CPU_RSTN)
begin
R_2STEP_ISTC_CNT <= 2'd0;
end
else
begin
case(R_I_ALU_OP_TYPE)
`DEF_ALU_MADD_OPR,`DEF_ALU_MADDU_OPR,`DEF_ALU_MSUB_OPR,`DEF_ALU_MSUBU_OPR:
begin
if(R_2STEP_ISTC_CNT == 1)
begin
R_2STEP_ISTC_CNT <= 2'd0;
end
else
begin
R_2STEP_ISTC_CNT <= R_2STEP_ISTC_CNT + 1;
end
end
default:
begin
R_2STEP_ISTC_CNT <= 2'd0;
end
endcase
end
end
always @ (posedge I_CPU_CLK)
begin
if(~I_CPU_RSTN)
begin
R_MID_RES_MULT <= 64'd0;
end
else
begin
case(R_I_ALU_OP_TYPE)
`DEF_ALU_MADD_OPR,`DEF_ALU_MADDU_OPR,`DEF_ALU_MSUB_OPR,`DEF_ALU_MSUBU_OPR,`DEF_ALU_DIV_OPR,`DEF_ALU_DIVU_OPR:
begin
if(R_2STEP_ISTC_CNT == 0)
begin
if(R_I_ALU_OP_TYPE == `DEF_ALU_MADD_OPR || R_I_ALU_OP_TYPE == `DEF_ALU_MSUB_OPR)
begin
R_MID_RES_MULT <= W_I_SRC_OPR_DATA_A_SIGNED * W_I_SRC_OPR_DATA_B_SIGNED;
end
else if(R_I_ALU_OP_TYPE == `DEF_ALU_MADDU_OPR || R_I_ALU_OP_TYPE == `DEF_ALU_MSUBU_OPR)
begin
R_MID_RES_MULT <= I_SRC_OPR_DATA_A * I_SRC_OPR_DATA_B;
end
else
begin
R_MID_RES_MULT <= R_MID_RES_MULT;
end
end
else
begin
R_MID_RES_MULT <= R_MID_RES_MULT;
end
end
default:
begin
R_MID_RES_MULT <= 64'd0;
end
endcase
end
end
// | 除法运算控制
always @ (posedge I_CPU_CLK)
begin
if(~I_CPU_RSTN)
begin
R_DIV_TYPE <= 1'b0;
R_OPR_DATA_A <= 32'd0;
R_OPR_DATA_B <= 32'd0;
R_OPR_EN <= 1'b0;
R_OPR_CANCEL <= 1'b0;
end
else
begin
case(R_I_ALU_OP_TYPE)
`DEF_ALU_DIV_OPR:
begin
if(!(R_PAUSE_REQ&O_PAUSE_REQ))
begin
R_DIV_TYPE <= 1'b1;
R_OPR_DATA_A <= I_SRC_OPR_DATA_A;
R_OPR_DATA_B <= I_SRC_OPR_DATA_B;
R_OPR_EN <= 1'b1;
end
else
begin
R_OPR_EN <= R_OPR_EN;
R_DIV_TYPE <= R_DIV_TYPE;
R_OPR_DATA_A <= R_OPR_DATA_A;
R_OPR_DATA_B <= R_OPR_DATA_B;
end
R_OPR_CANCEL <= 1'b0;
end
`DEF_ALU_DIVU_OPR:
begin
if(!(R_PAUSE_REQ&O_PAUSE_REQ))
begin
R_DIV_TYPE <= 1'b0;
R_OPR_DATA_A <= I_SRC_OPR_DATA_A;
R_OPR_DATA_B <= I_SRC_OPR_DATA_B;
R_OPR_EN <= 1'b1;
end
else
begin
R_OPR_EN <= R_OPR_EN;
R_DIV_TYPE <= R_DIV_TYPE;
R_OPR_DATA_A <= R_OPR_DATA_A;
R_OPR_DATA_B <= R_OPR_DATA_B;
end
R_OPR_CANCEL <= 1'b0;
end
default:
begin
if(W_DIV_RES_VAL)
begin
R_OPR_EN <= 1'b0;
R_DIV_TYPE <= 1'b0;
R_OPR_DATA_A <= 32'd0;
R_OPR_DATA_B <= 32'd0;
end
else
begin
R_OPR_EN <= R_OPR_EN;
R_DIV_TYPE <= R_DIV_TYPE;
R_OPR_DATA_A <= R_OPR_DATA_A;
R_OPR_DATA_B <= R_OPR_DATA_B;
end
R_OPR_CANCEL <= 1'b0;
end
endcase
end
end
always @ (posedge I_CPU_CLK)
begin
if(~I_CPU_RSTN)
begin
R_R_DIV_TYPE <= 1'b0;
end
else
begin
R_R_DIV_TYPE <= R_DIV_TYPE;
end
end
// |-------------------------------------- 模块内部例化 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 除法运算模块
DIV_OPR_MDL INST_DIV_OPR_MDL
(
.I_CPU_CLK (I_CPU_CLK),
.I_CPU_RSTN (I_CPU_RSTN),
.I_DIV_TYPE (R_DIV_TYPE),
.I_OPR_DATA_A (R_OPR_DATA_A),
.I_OPR_DATA_B (R_OPR_DATA_B),
.I_OPR_EN (R_DIV_TYPE ^ R_R_DIV_TYPE),
.I_OPR_CANCEL (R_OPR_CANCEL),
.O_RES_VAL (W_DIV_RES_VAL),
.O_RES (W_DIV_RES)
);
endmodule
测试
测试程序
.org 0x0
.global _start
.set noat
_start:
ori $1,$0,0xFFFF
sll $1,$1,16
ori $1,$1,0xFFF1
ori $2,$0,0x4
ori $3,$0,0xFFFF
sll $3,$3,16
ori $3,$3,0xFFF2
ori $4,$0,0x5
ori $5,$0,0xFFFF
sll $5,$5,16
ori $5,$5,0xFFF3
ori $6,$0,0x6
ori $7,$0,0xFFFF
sll $7,$7,16
ori $7,$7,0xFFF4
ori $8,$0,0x7
div $zero,$1,$2
divu $zero,$3,$4
div $zero,$5,$6
divu $zero,$7,$8
测试结果
更细节的时序可根据源码自行仿真。若有问题,可以留言相告~~