目录
引言
致谢
流水线暂停
指令说明
madd、maddu、msub、msubu
设计
宏定义文件
程序计数器模块
译码模块
执行模块
访存模块
HI LO 寄存器模块
通用寄存器模块
流水线控制模块
程序ROM
MIPS32顶层
MIPS32 SOPC
仿真
仿真程序
TESTBENCH
仿真结果
引言
随章节进度继续推进,本章继续实现 流水线暂停、复杂算术运算(包括乘累加等) 指令等其他操作指令。
本篇文章主要实现简单算术操作指令,一共有15条指令。
致谢
感谢书籍《自己动手写CPU》及其作者雷思磊。一并感谢开源精神。
流水线暂停
复杂算术运算,包括乘累加、乘累减、除法等算术运算。这些运算在单个时钟周期不能完成,至少需要 2 个时钟周期。因此在此类指令未执行完毕时,流水线不然能取下一条指令。
MIPS32的暂停机制:
增加流水线控制模块:
按照此思路,修改相应模块即可。此处代码和后续的乘加乘减指令一并实现后给出,并验证。
指令说明
madd、maddu、msub、msubu
该 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
HI LO 寄存器模块
// |------------------------------ ================================== ------------------------------
// |============================== 指令-译码模块 ==============================
// |------------------------------ ================================== ------------------------------
// |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
程序ROM
// |------------------------------ ================================== ------------------------------
// |============================== 程序计数寄存器模块 ==============================
// |------------------------------ ================================== ------------------------------
// |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
MIPS32顶层
// |------------------------------ ================================== ------------------------------
// |============================== 指令-执行模块 ==============================
// |------------------------------ ================================== ------------------------------
// |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
// |------------------------------ ================================== ------------------------------
// |============================== 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
TESTBENCH
// |------------------------------ ================================== ------------------------------
// |============================== 顶层模块仿真平台 ==============================
// |------------------------------ ================================== ------------------------------
// |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
仿真结果
欢迎交流~~~~~