目录
引言
致谢
流水线暂停
指令说明
madd、maddu、msub、msubu
设计
宏定义文件
程序计数器模块
译码模块
执行模块
访存模块
HI LO 寄存器模块
通用寄存器模块
流水线控制模块
程序ROM
MIPS32顶层
MIPS32 SOPC
仿真
仿真程序
TESTBENCH
仿真结果
随章节进度继续推进,本章继续实现 流水线暂停、复杂算术运算(包括乘累加等) 指令等其他操作指令。
本篇文章主要实现简单算术操作指令,一共有15条指令。
感谢书籍《自己动手写CPU》及其作者雷思磊。一并感谢开源精神。
复杂算术运算,包括乘累加、乘累减、除法等算术运算。这些运算在单个时钟周期不能完成,至少需要 2 个时钟周期。因此在此类指令未执行完毕时,流水线不然能取下一条指令。
MIPS32的暂停机制:
增加流水线控制模块:
按照此思路,修改相应模块即可。此处代码和后续的乘加乘减指令一并实现后给出,并验证。
该 4 条指令均属于 SPECIAL2 类型指令。第 15~6位 为0,可根据低六位判断功能。
指令格式:
指令用法:
此处给出所有设计模块以及仿真模块源码,方便读者阅读,查看逻辑。
// |------------------------------ ================================== ------------------------------
// |============================== 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操作功能宏定义
// |-------------------------------------- 系统级全局宏定义 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 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-06
// |Finish Date : 2022-12-06
// |Edited by : Xu Y. B. (CSDN USER NAME :在路上,正出发)
// |Reference : 《自己动手写CPU》
// |
// |
// |------------------------------------------------------------------------------------------------
// |---------------------------------------- Change History ----------------------------------------
// |Date:2022-12-15
// |Who :Xu Y. B.
// |What:增加流水线指令暂停功能
`include "MIPS_SYS_DEFINES.v"
`timescale 1ns / 1ps
module PC_REG_MDL(
// |-------------------------------------- 输入输出端口声明 --------------------------------------
// |------------------------------------------------------------------------------------------------
input I_CPU_CLK,
input I_CPU_RSTN,
input I_PC_PAUSE,
output reg [`DEF_ISTC_ADDR_BUS] O_PC,
output reg O_ISTC_ROM_CE
);
// |-------------------------------------- 模块内部逻辑设计 --------------------------------------
// |------------------------------------------------------------------------------------------------
// CE
always @ (posedge I_CPU_CLK)
begin
if(~I_CPU_RSTN)
begin
O_ISTC_ROM_CE <= `DEF_CHIP_DIS;
end
else
begin
O_ISTC_ROM_CE <= `DEF_CHIP_EN;
end
end
// PC
always @ (posedge I_CPU_CLK)
begin
if((~I_CPU_RSTN) || (O_ISTC_ROM_CE == `DEF_CHIP_DIS))
begin
O_PC <= 32'd0;
end
else if(~I_PC_PAUSE)
begin
O_PC <= O_PC + 32'd4;
end
else
begin
O_PC <= O_PC ;
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类问题)
// | 思路参考《自己动手写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步算术运算指令的译码功能
`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
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
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步算数运算执行功能
`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;//位宽可能存在冗余
// |-------------------------------------- 模块内部逻辑设计 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 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
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,`DEF_ALU_DIV_OPR,`DEF_ALU_DIVU_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
default:
begin
O_PAUSE_REQ = 1'b0;
end
endcase
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,`DEF_ALU_DIV_OPR,`DEF_ALU_DIVU_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
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-14
// |Who :Xu Y. B.
// |What:增加流水线指令暂停模块
`include "MIPS_SYS_DEFINES.v"
`timescale 1ns / 1ps
module MEM_ACS_MDL(
// |-------------------------------------- 输入输出端口声明 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 时钟、复位
input I_CPU_CLK,
input I_CPU_RSTN,
// | 前接指令执行模块输出
input I_DST_GPR_WR_EN,
input [`DEF_GPR_ADDR_WIDTH-1:0] I_DST_GPR_WR_ADDR,
input [`DEF_GPR_DATA_WIDTH-1:0] I_DST_GPR_WR_DATA,
// | 后接写回模块
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,
input [`DEF_GPR_DATA_WIDTH-1:0] I_HI,
input [`DEF_GPR_DATA_WIDTH-1:0] I_LO,
input I_HILO_WR_EN,
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
);
// |-------------------------------------- 模块内部逻辑设计 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 目的寄存器写操作传递/打拍
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;
O_DST_GPR_WR_DATA <= 32'd0;
O_HI <= 32'd0;
O_LO <= 32'd0;
O_HILO_WR_EN <= 1'b0;
end
else
begin
if(!I_PAUSE_ACK[3])
begin
O_DST_GPR_WR_EN <= I_DST_GPR_WR_EN ;
O_DST_GPR_WR_ADDR <= I_DST_GPR_WR_ADDR;
O_DST_GPR_WR_DATA <= I_DST_GPR_WR_DATA;
O_HI <= I_HI ;
O_LO <= I_LO ;
O_HILO_WR_EN <= I_HILO_WR_EN;
end
else
begin
O_DST_GPR_WR_EN <= 1'b0;
O_DST_GPR_WR_ADDR <= 5'd0;
O_DST_GPR_WR_DATA <= 32'd0;
O_HI <= 32'd0;
O_LO <= 32'd0;
O_HILO_WR_EN <= 1'b0;
end
end
end
endmodule
// |------------------------------ ================================== ------------------------------
// |============================== 指令-译码模块 ==============================
// |------------------------------ ================================== ------------------------------
// |Create Date : 2022-12-10
// |Finish Date : 2022-12-10
// |Edited by : Xu Y. B. (CSDN USER NAME :在路上,正出发)
// |Reference : 《自己动手写CPU》
// |
// |
// |------------------------------------------------------------------------------------------------
// |---------------------------------------- Change History ----------------------------------------
// |Date:
// |Who :
// |What:
`include "MIPS_SYS_DEFINES.v"
`timescale 1ns / 1ps
module HI_LO_REG_MDL(
// |-------------------------------------- 输入输出端口声明 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 时钟、复位
input I_CPU_CLK,
input I_CPU_RSTN,
input I_HILO_WR_EN,
input [`DEF_GPR_DATA_WIDTH-1:0] I_HI,
input [`DEF_GPR_DATA_WIDTH-1:0] I_LO,
output reg [`DEF_GPR_DATA_WIDTH-1:0] O_HI,
output reg [`DEF_GPR_DATA_WIDTH-1:0] O_LO
);
// |-------------------------------------- 模块内部逻辑设计 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 寄存
always @ (posedge I_CPU_CLK)
begin
if(~I_CPU_RSTN)
begin
O_HI <= `DEF_ZERO_WORD;
O_LO <= `DEF_ZERO_WORD;
end
else if(I_HILO_WR_EN)
begin
O_HI <= I_HI;
O_LO <= I_LO;
end
else
begin
O_HI <= O_HI;
O_LO <= O_LO;
end
end
endmodule
// |------------------------------ ================================== ------------------------------
// |============================== 取指-译码接口模块 ==============================
// |------------------------------ ================================== ------------------------------
// |Create Date : 2022-12-06
// |Finish Date : 2022-12-06
// |Edited by : Xu Y. B. (CSDN USER NAME :在路上,正出发)
// |Reference : 《自己动手写CPU》
// |
// |
// |------------------------------------------------------------------------------------------------
// |---------------------------------------- Change History ----------------------------------------
// |Date:2022-12-
// |Who :Xu Y. B.
// |What:
`include "MIPS_SYS_DEFINES.v"
`timescale 1ns / 1ps
module GPR_WR_RD_MDL(
// |-------------------------------------- 输入输出端口声明 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 时钟、复位
input I_CPU_CLK,
input I_CPU_RSTN,
// | 写
input I_GPR_WR_EN,
input [`DEF_GPR_ADDR_WIDTH-1:0] I_GPR_WR_ADDR,
input [`DEF_GPR_DATA_WIDTH-1:0] I_GPR_WR_DATA,
// |读
input I_GPR_RD_EN_A,
input [`DEF_GPR_ADDR_WIDTH-1:0] I_GPR_RD_ADDR_A,
output reg [`DEF_GPR_DATA_WIDTH-1:0] O_GPR_RD_DATA_A,
input I_GPR_RD_EN_B,
input [`DEF_GPR_ADDR_WIDTH-1:0] I_GPR_RD_ADDR_B,
output reg [`DEF_GPR_DATA_WIDTH-1:0] O_GPR_RD_DATA_B
);
// |-------------------------------------- GPR-寄存器组定义 --------------------------------------
// |------------------------------------------------------------------------------------------------
reg [`DEF_GPR_DATA_WIDTH-1:0] R_GPR [`DEF_GPR_NUM-1:0];
// |-------------------------------------- GPR-寄存器初始化 --------------------------------------
// |------------------------------------------------------------------------------------------------
initial $readmemh("D:/VIVADO_WORK_SPACE/CPU_MIPS32/DATA_FILE/GPR_INIT.txt",R_GPR);
// |-------------------------------------- GPR-寄存器写操作 --------------------------------------
// |------------------------------------------------------------------------------------------------
always @ (posedge I_CPU_CLK)
begin
if(I_CPU_RSTN)
begin
if(I_GPR_WR_EN && I_GPR_WR_ADDR != `DEF_GPR_ADDR_WIDTH'd0)
begin
R_GPR[I_GPR_WR_ADDR] <= I_GPR_WR_DATA;
end
end
end
// |-------------------------------------- PORT A 读操作 --------------------------------------
// |------------------------------------------------------------------------------------------------
always @ (*)
begin
if(~I_CPU_RSTN)
begin
O_GPR_RD_DATA_A = `DEF_ZERO_WORD;
end
else if(I_GPR_WR_EN && I_GPR_RD_EN_A && (I_GPR_RD_ADDR_A == I_GPR_WR_ADDR))
begin
O_GPR_RD_DATA_A = I_GPR_WR_DATA;
end
else if(I_GPR_RD_EN_A)
begin
O_GPR_RD_DATA_A = R_GPR[I_GPR_RD_ADDR_A];
end
else
begin
O_GPR_RD_DATA_A = `DEF_ZERO_WORD;
end
end
// |-------------------------------------- PORT B 读操作 --------------------------------------
// |------------------------------------------------------------------------------------------------
always @ (*)
begin
if(~I_CPU_RSTN)
begin
O_GPR_RD_DATA_B = `DEF_ZERO_WORD;
end
else if(I_GPR_WR_EN && I_GPR_RD_EN_B && (I_GPR_RD_ADDR_B == I_GPR_WR_ADDR))
begin
O_GPR_RD_DATA_B = I_GPR_WR_DATA;
end
else if(I_GPR_RD_EN_B)
begin
O_GPR_RD_DATA_B = R_GPR[I_GPR_RD_ADDR_B];
end
else
begin
O_GPR_RD_DATA_B = `DEF_ZERO_WORD;
end
end
endmodule
// |------------------------------ ================================== ------------------------------
// |============================== 指令-执行模块 ==============================
// |------------------------------ ================================== ------------------------------
// |Create Date : 2022-12-12
// |Finish Date : 2022-12-12
// |Edited by : Xu Y. B. (CSDN USER NAME :在路上,正出发)
// |Reference : 《自己动手写CPU》
// |
// |
// |------------------------------------------------------------------------------------------------
// |---------------------------------------- Change History ----------------------------------------
// |Date:2022-12-12
// |Who :Xu Y. B.
// |What:
module PIPE_LINE_CTRL_MDL(
// |-------------------------------------- 输入输出端口声明 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 时钟、复位
input I_CPU_CLK,
input I_CPU_RSTN,
input I_PAUSE_REQ_FROM_ID_MDL,
input I_PAUSE_REQ_FROM_EXE_MDL,
output reg [4:0] O_PAUSE_ACK
// O_PAUSE_ACK[0] ——> PC_REG_MDL
// O_PAUSE_ACK[1] ——> ID_MDL
// O_PAUSE_ACK[2] ——> EXE_MDL
// O_PAUSE_ACK[3] ——> MEM_ACS_MDL
// O_PAUSE_ACK[4] ——> HI_LO_REG_MDL
);
// always @ (posedge I_CPU_CLK)
always @ (*)
begin
if(~I_CPU_RSTN)
begin
O_PAUSE_ACK <= 5'd0;
end
else if(I_PAUSE_REQ_FROM_EXE_MDL)
begin
O_PAUSE_ACK <= 5'b0_0_1_1_1;
end
else if(I_PAUSE_REQ_FROM_ID_MDL)
begin
O_PAUSE_ACK <= 5'b0_0_0_1_1;
end
else
begin
O_PAUSE_ACK <= 5'd0;
end
end
endmodule
// |------------------------------ ================================== ------------------------------
// |============================== 程序计数寄存器模块 ==============================
// |------------------------------ ================================== ------------------------------
// |Create Date : 2022-12-08
// |Finish Date : 2022-12-08
// |Edited by : Xu Y. B. (CSDN USER NAME :在路上,正出发)
// |Reference : 《自己动手写CPU》
// |
// |
// |------------------------------------------------------------------------------------------------
// |---------------------------------------- Change History ----------------------------------------
// |Date:2022-12-
// |Who :Xu Y. B.
// |What:
`include "MIPS_SYS_DEFINES.v"
`timescale 1ns / 1ps
module ROM_ISTC_MDL(
// |-------------------------------------- 输入输出端口声明 --------------------------------------
// |------------------------------------------------------------------------------------------------
input I_CPU_CLK,
input I_CPU_RSTN,
input I_RD_EN,
input [`DEF_ISTC_ADDR_BUS] I_RD_ADDR,
output reg [`DEF_ISTC_DATA_BUS] O_ISTC
);
// |-------------------------------------- 模块内部信号声明 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | ROM空间开辟
reg [`DEF_ISTC_DATA_BUS] R_ROM_DATA [`DEF_ISTC_CACH_DEPTH:0];
// |-------------------------------------- 模块内部逻辑设计 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | ROM初始化
initial $readmemh("D:/Ubuntu_Win_Share/My_MIPS32/TEST/ISTC_ROM.data",R_ROM_DATA);
// | 数据读取
always @ (posedge I_CPU_CLK)
begin
if(~I_CPU_RSTN)
begin
O_ISTC <= `DEF_ZERO_WORD;
end
else
begin
if(I_RD_EN)
begin
O_ISTC <= R_ROM_DATA[I_RD_ADDR[`DEF_ISTC_ADDR_WIDTH_ACTUAL+1:2]];
end
else
begin
O_ISTC <= `DEF_ZERO_WORD;
end
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类问题)
// | 顶层文件配合改动
`include "MIPS_SYS_DEFINES.v"
`timescale 1ns / 1ps
module TOP_MIPS32(
// |-------------------------------------- 输入输出端口声明 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 时钟、复位
input I_CPU_CLK,
input I_CPU_RSTN,
// | 指令取
input [`DEF_ISTC_DATA_BUS] I_ISTC_FROM_ROM,
output [`DEF_ISTC_ADDR_BUS] O_ISTC_ADDR_2_ROM,
// | 指令存储器使能
output O_ISTC_ROM_CE
);
// |-------------------------------------- 模块内部信号声明 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | PC_REG_MDL 输出
wire [`DEF_ISTC_ADDR_BUS] W_PC;
// | IF_ID_MDL 输出
wire [`DEF_ISTC_ADDR_BUS] W_ID_ADDR;
wire [`DEF_ISTC_DATA_BUS] W_ID_DATA;
// ID_MDL 端口信号(GPR相关)
wire W_GPR_RD_EN_A;
(*DONT_TOUCH = "TRUE"*)
wire [`DEF_GPR_ADDR_WIDTH-1:0] W_GPR_RD_ADDR_A;
wire [`DEF_GPR_DATA_WIDTH-1:0] W_GPR_RD_DATA_A;
wire W_GPR_RD_EN_B;
(*DONT_TOUCH = "TRUE"*)
wire [`DEF_GPR_ADDR_WIDTH-1:0] W_GPR_RD_ADDR_B;
wire [`DEF_GPR_DATA_WIDTH-1:0] W_GPR_RD_DATA_B;
// ID_MDL 端口信号(EXE 相关)
wire [`DEF_ALU_OPR_BUS] W_ALU_OP_TYPE;
wire [`DEF_SRC_OPR_DATA_BUS] W_SRC_OPR_DATA_A;
wire [`DEF_SRC_OPR_DATA_BUS] W_SRC_OPR_DATA_B;
// GPR_WR_RD_MDL 写操作端口(EXE 相关)
wire W_DST_GPR_WR_EN_EXE_MDL_IN;
wire [`DEF_GPR_ADDR_WIDTH-1:0] W_DST_GPR_WR_ADDR_EXE_MDL_IN;
// GPR_WR_RD_MDL 写操作端口(MEM 相关)
wire W_DST_GPR_WR_EN_MEM_MDL_IN;
wire [`DEF_GPR_ADDR_WIDTH-1:0] W_DST_GPR_WR_ADDR_MEM_MDL_IN;
wire [`DEF_GPR_DATA_WIDTH-1:0] W_DST_GPR_WR_DATA_MEM_MDL_IN;
// GPR_WR_RD_MDL 写操作端口(GPR 相关)
wire W_DST_GPR_WR_EN_GPR_MDL_IN;
wire [`DEF_GPR_ADDR_WIDTH-1:0] W_DST_GPR_WR_ADDR_GPR_MDL_IN;
wire [`DEF_GPR_DATA_WIDTH-1:0] W_DST_GPR_WR_DATA_GPR_MDL_IN;
// | 为解决数据相关问题/读写冲突问题 引入的端口
// 来自执行模块
wire W_DST_GPR_WR_EN_GPR_MDL_IN_FROM_EXE_MDL ;
wire [`DEF_GPR_ADDR_WIDTH-1:0] W_DST_GPR_WR_ADDR_GPR_MDL_IN_FROM_EXE_MDL;
wire [`DEF_GPR_DATA_WIDTH-1:0] W_DST_GPR_WR_DATA_GPR_MDL_IN_FROM_EXE_MDL;
// | HI_LO_REG_MDL 端口
wire W_HILO_WR_EN;
wire [`DEF_GPR_DATA_WIDTH-1:0] W_HI;
wire [`DEF_GPR_DATA_WIDTH-1:0] W_LO;
wire [`DEF_GPR_DATA_WIDTH-1:0] W_O_HI;
wire [`DEF_GPR_DATA_WIDTH-1:0] W_O_LO;
wire W_O_EXE_HILO_WR_EN;
wire [`DEF_GPR_DATA_WIDTH-1:0] W_O_EXE_HI;
wire [`DEF_GPR_DATA_WIDTH-1:0] W_O_EXE_LO;
// | PIPE_LINE_CTRL_MDL 端口
wire W_PAUSE_REQ_FROM_ID_MDL;
wire W_PAUSE_REQ_FROM_EXE_MDL;
wire [4:0] W_PAUSE_ACK;
// |-------------------------------------- 模块内部逻辑设计 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 输出
assign O_ISTC_ADDR_2_ROM = W_PC;
// |-------------------------------------- 子模块例化 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 程序计数器模块
PC_REG_MDL INST_PC_REG_MDL
(
.I_CPU_CLK (I_CPU_CLK),
.I_CPU_RSTN (I_CPU_RSTN),
.I_PC_PAUSE (W_PAUSE_ACK[0]),
.O_PC (W_PC),
.O_ISTC_ROM_CE (O_ISTC_ROM_CE)
);
// | 译码模块例化
ID_MDL INST_ID_MDL
(
.I_CPU_CLK (I_CPU_CLK),
.I_CPU_RSTN (I_CPU_RSTN),
.I_ISTC (I_ISTC_FROM_ROM),
.O_GPR_RD_EN_A (W_GPR_RD_EN_A),
.O_GPR_RD_ADDR_A (W_GPR_RD_ADDR_A),
.I_GPR_RD_DATA_A (W_GPR_RD_DATA_A),
.O_GPR_RD_EN_B (W_GPR_RD_EN_B),
.O_GPR_RD_ADDR_B (W_GPR_RD_ADDR_B),
.I_GPR_RD_DATA_B (W_GPR_RD_DATA_B),
.O_ALU_OP_TYPE (W_ALU_OP_TYPE),
.O_SRC_OPR_DATA_A (W_SRC_OPR_DATA_A),
.O_SRC_OPR_DATA_B (W_SRC_OPR_DATA_B),
.O_DST_GPR_WR_EN (W_DST_GPR_WR_EN_EXE_MDL_IN),
.O_DST_GPR_WR_ADDR (W_DST_GPR_WR_ADDR_EXE_MDL_IN),
// | 为解决数据相关问题/读写冲突问题 引入的端口
// 来自执行模块
.I_DST_GPR_WR_EN_FROM_EXE_MDL (W_DST_GPR_WR_EN_GPR_MDL_IN_FROM_EXE_MDL ),
.I_DST_GPR_WR_ADDR_FROM_EXE_MDL (W_DST_GPR_WR_ADDR_GPR_MDL_IN_FROM_EXE_MDL),
.I_DST_GPR_WR_DATA_FROM_EXE_MDL (W_DST_GPR_WR_DATA_GPR_MDL_IN_FROM_EXE_MDL),
// 来自访存模块
.I_DST_GPR_WR_EN_FROM_MEM_ACS_MDL (W_DST_GPR_WR_EN_MEM_MDL_IN ),
.I_DST_GPR_WR_ADDR_FROM_MEM_ACS_MDL (W_DST_GPR_WR_ADDR_MEM_MDL_IN),
.I_DST_GPR_WR_DATA_FROM_MEM_ACS_MDL (W_DST_GPR_WR_DATA_MEM_MDL_IN),
.I_PAUSE_ACK(W_PAUSE_ACK),
.O_PAUSE_REQ(W_PAUSE_REQ_FROM_ID_MDL)
);
// | 通用寄存器模块例化
GPR_WR_RD_MDL INST_GPR_WR_RD_MDL
(
.I_CPU_CLK (I_CPU_CLK),
.I_CPU_RSTN (I_CPU_RSTN),
.I_GPR_WR_EN (W_DST_GPR_WR_EN_GPR_MDL_IN),
.I_GPR_WR_ADDR (W_DST_GPR_WR_ADDR_GPR_MDL_IN),
.I_GPR_WR_DATA (W_DST_GPR_WR_DATA_GPR_MDL_IN),
.I_GPR_RD_EN_A (W_GPR_RD_EN_A),
.I_GPR_RD_ADDR_A (W_GPR_RD_ADDR_A),
.O_GPR_RD_DATA_A (W_GPR_RD_DATA_A),
.I_GPR_RD_EN_B (W_GPR_RD_EN_B),
.I_GPR_RD_ADDR_B (W_GPR_RD_ADDR_B),
.O_GPR_RD_DATA_B (W_GPR_RD_DATA_B)
);
// | 执行模块例化
EXE_MDL INST_EXE_MDL
(
.I_CPU_CLK (I_CPU_CLK),
.I_CPU_RSTN (I_CPU_RSTN),
.I_ALU_OP_TYPE (W_ALU_OP_TYPE),
.I_SRC_OPR_DATA_A (W_SRC_OPR_DATA_A),
.I_SRC_OPR_DATA_B (W_SRC_OPR_DATA_B),
.I_DST_GPR_WR_EN (W_DST_GPR_WR_EN_EXE_MDL_IN),
.I_DST_GPR_WR_ADDR (W_DST_GPR_WR_ADDR_EXE_MDL_IN),
.I_HI(W_O_HI),
.I_LO(W_O_LO),
.I_HI_FROM_MEM_ACS_MDL (W_O_EXE_HI),
.I_LO_FROM_MEM_ACS_MDL (W_O_EXE_LO),
.I_WR_EN_FROM_MEM_ACS_MDL (W_O_EXE_HILO_WR_EN),
.I_HI_FROM_HI_LO_REG_MDL (W_HI),
.I_LO_FROM_HI_LO_REG_MDL (W_LO),
.I_WR_EN_FROM_HI_LO_REG_MDL (W_HILO_WR_EN),
.O_DST_GPR_WR_EN (W_DST_GPR_WR_EN_MEM_MDL_IN ),
.O_DST_GPR_WR_ADDR (W_DST_GPR_WR_ADDR_MEM_MDL_IN),
.O_DST_GPR_WR_DATA (W_DST_GPR_WR_DATA_MEM_MDL_IN),
// | 为解决数据相关问题/读写冲突问题 引入的端口
// 送至指令译码模块
.O_DST_GPR_WR_EN_2_ID_MDL (W_DST_GPR_WR_EN_GPR_MDL_IN_FROM_EXE_MDL ),
.O_DST_GPR_WR_ADDR_2_ID_MDL (W_DST_GPR_WR_ADDR_GPR_MDL_IN_FROM_EXE_MDL),
.O_DST_GPR_WR_DATA_2_ID_MDL (W_DST_GPR_WR_DATA_GPR_MDL_IN_FROM_EXE_MDL),
.O_HI(W_O_EXE_HI),
.O_LO(W_O_EXE_LO),
.O_HILO_WR_EN(W_O_EXE_HILO_WR_EN),
.I_PAUSE_ACK(W_PAUSE_ACK),
.O_PAUSE_REQ(W_PAUSE_REQ_FROM_EXE_MDL)
);
// | 存储器存取模块例化
MEM_ACS_MDL INST_MEM_ACS_MDL
(
.I_CPU_CLK (I_CPU_CLK),
.I_CPU_RSTN (I_CPU_RSTN),
.I_DST_GPR_WR_EN (W_DST_GPR_WR_EN_MEM_MDL_IN ),
.I_DST_GPR_WR_ADDR (W_DST_GPR_WR_ADDR_MEM_MDL_IN),
.I_DST_GPR_WR_DATA (W_DST_GPR_WR_DATA_MEM_MDL_IN),
.O_DST_GPR_WR_EN (W_DST_GPR_WR_EN_GPR_MDL_IN ),
.O_DST_GPR_WR_ADDR (W_DST_GPR_WR_ADDR_GPR_MDL_IN),
.O_DST_GPR_WR_DATA (W_DST_GPR_WR_DATA_GPR_MDL_IN),
.I_HI (W_O_EXE_HI),
.I_LO (W_O_EXE_LO),
.I_HILO_WR_EN (W_O_EXE_HILO_WR_EN),
.O_HI (W_HI),
.O_LO (W_LO),
.O_HILO_WR_EN (W_HILO_WR_EN),
.I_PAUSE_ACK(W_PAUSE_ACK)
// .O_PAUSE_REQ()
);
// | HI LO 寄存器例化
HI_LO_REG_MDL INST_HI_LO_REG_MDL
(
.I_CPU_CLK (I_CPU_CLK),
.I_CPU_RSTN (I_CPU_RSTN),
.I_HILO_WR_EN (W_HILO_WR_EN),
.I_HI (W_HI),
.I_LO (W_LO),
.O_HI (W_O_HI),
.O_LO (W_O_LO)
);
// | PIPE_LINE_CTRL_MDL 模块例化
PIPE_LINE_CTRL_MDL INST_PIPE_LINE_CTRL_MDL
(
.I_CPU_CLK (I_CPU_CLK),
.I_CPU_RSTN (I_CPU_RSTN),
.I_PAUSE_REQ_FROM_ID_MDL (W_PAUSE_REQ_FROM_ID_MDL),
.I_PAUSE_REQ_FROM_EXE_MDL (W_PAUSE_REQ_FROM_EXE_MDL),
.O_PAUSE_ACK (W_PAUSE_ACK)
);
endmodule
// |------------------------------ ================================== ------------------------------
// |============================== MIPS32 SOPC 系统 ==============================
// |------------------------------ ================================== ------------------------------
// |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-
// |Who :Xu Y. B.
// |What:
`include "MIPS_SYS_DEFINES.v"
`timescale 1ns / 1ps
module TOP_MIPS32_SOPC(
// |-------------------------------------- 输入输出端口声明 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 时钟、复位
input I_CPU_CLK,
input I_CPU_RSTN
);
// |-------------------------------------- 模块内部信号声明 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | TOP_MIPS32 模块端口
// | 指令取
wire [`DEF_ISTC_DATA_BUS] W_ISTC_FROM_ROM;
wire [`DEF_ISTC_ADDR_BUS] W_ISTC_ADDR_2_ROM;
// | 指令存储器使能
wire W_ISTC_ROM_CE;
// |-------------------------------------- 子模块例化 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 处理器模块
TOP_MIPS32 INST_TOP_MIPS32
(
.I_CPU_CLK (I_CPU_CLK),
.I_CPU_RSTN (I_CPU_RSTN),
.I_ISTC_FROM_ROM (W_ISTC_FROM_ROM),
.O_ISTC_ADDR_2_ROM (W_ISTC_ADDR_2_ROM),
.O_ISTC_ROM_CE (W_ISTC_ROM_CE)
);
// | 指令存储模块
ROM_ISTC_MDL INST_ROM_ISTC_MDL
(
.I_CPU_CLK (I_CPU_CLK),
.I_CPU_RSTN (I_CPU_RSTN),
.I_RD_EN (W_ISTC_ROM_CE),
.I_RD_ADDR (W_ISTC_ADDR_2_ROM),
.O_ISTC (W_ISTC_FROM_ROM)
);
endmodule
.org 0x0
.global _start
.set noat
_start:
ori $1,$0,0xFFFF
sll $1,$1,16
ori $1,$1,0xFFFB
ori $2,$0,6
mult $1,$2
madd $1,$2
nop
maddu $1,$2
msub $1,$2
nop
msubu $1,$2
madd $1,$2
maddu $1,$2
nop
msub $1,$2
msubu $1,$2
madd $1,$2
maddu $1,$2
nop
madd $1,$2
maddu $1,$2
msub $1,$2
msubu $1,$2
madd $1,$2
nop
// |------------------------------ ================================== ------------------------------
// |============================== 顶层模块仿真平台 ==============================
// |------------------------------ ================================== ------------------------------
// |Create Date : 2022-12-08
// |Finish Date : 2022-12-08
// |Edited by : Xu Y. B. (CSDN USER NAME :在路上,正出发)
// |Reference : 《自己动手写CPU》
// |
// |
// |------------------------------------------------------------------------------------------------
// |---------------------------------------- Change History ----------------------------------------
// |Date:2022-12-
// |Who :Xu Y. B.
// |What:
`timescale 1ns / 1ps
`define CLK_PERIOD 20
module TB_TOP_MIPS32();
reg I_CPU_CLK;
reg I_CPU_RSTN;
// 产生时钟
initial I_CPU_CLK = 0;
always #(`CLK_PERIOD/2) I_CPU_CLK = ~I_CPU_CLK;
// 产生复位
initial
begin
I_CPU_RSTN <= 0;
#(`CLK_PERIOD*3);
@(posedge I_CPU_CLK);
I_CPU_RSTN <= 1;
#(`CLK_PERIOD*50);
$finish;
end
// 顶层例化
TOP_MIPS32_SOPC INST_TOP_MIPS32_SOPC
(.I_CPU_CLK(I_CPU_CLK),
.I_CPU_RSTN(I_CPU_RSTN)
);
endmodule
欢迎交流~~~~~