目录
引言
致谢
指令说明
逻辑指令
and、or、xor、nor
andi、xori
lui
移位指令
sll、sllv、sra、srav、srl、srlv
空指令
nop、ssnop、sync、pref
指令实现
宏定义添加
指令译码模块修改
指令执行模块修改
功能验证
逻辑运算
验证代码
仿真波形
移位运算
验证代码
仿真波形
随章节进度继续推进,本章继续实现逻辑、移位、空指令等其他操作指令。
感谢书籍《自己动手写CPU》及其作者雷思磊。一并感谢开源精神。
指令格式:
该4条指令均属于 R 类型指令,且指令码均为 6‘b000000 即MIPS32 ISA 中定义的 SPECIAL 类。另外,指令的 6~10位均为0,需要依据指令中的 低 6 位 判断功能类型。
指令格式:
这两条指令都是 I 类型指令。根据指令码的 高 6 位 ,可以判断指令的功能。
此处的指令用法再一次证实了,书本所写的 ori 指令用法格式有误:
指令格式:
根据指令码的高6位即可判断功能是否为 lui ,指令用法:
指令格式:
此6条指令均属于 R 指令类型,且指令码均为 6'b000000。属于 SPECIAL 类,需要根据指令码的 低6位判断其功能。
此6条指令均属于 R 指令类型,且指令码均为 6'b000000。属于 SPECIAL 类,
仅供参考:
// |------------------------------ ================================== ------------------------------
// |============================== MIPS32 CPU SYSTEM ALL MACRO DEFINE ==============================
// |------------------------------ ================================== ------------------------------
// |Create Date : 2022-12-06
// |Finish Date : 2022-
// |Edited by : Xu Y. B. (CSDN USER NAME :在路上,正出发)
// |Reference : 《自己动手写CPU》——第4章
// |
// |
// |------------------------------------------------------------------------------------------------
// |---------------------------------------- Change History ----------------------------------------
// |Date:2022-12-09
// |Who :Xu Y. B.
// |What:增加如下指令宏定义:
// | and、or、xor、nor
// | andi、xori
// | lui
// | sll、sllv、sra、srav.、srl、srlv
// | nop、ssnop、sync、pref
// | 以及相应的ALU操作功能宏定义
// |-------------------------------------- 系统级全局宏定义 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 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 // and
`define DEF_ISTC_OR 6'b100101 // or
`define DEF_ISTC_XOR 6'b100110 // xor
`define DEF_ISTC_NOR 6'b100111 // nor
`define DEF_ISTC_ANDI 6'b001100 // andi
`define DEF_ISTC_ORI 6'b001101 // ori
`define DEF_ISTC_XORI 6'b001110 // xori
`define DEF_ISTC_LUI 6'b001111 // lui
`define DEF_ISTC_SLL 6'b000000 // sll
`define DEF_ISTC_SLLV 6'b000100 // sllv
`define DEF_ISTC_SRL 6'b000010 // srl
`define DEF_ISTC_SRLV 6'b000110 // srlv
`define DEF_ISTC_SRA 6'b000011 // sra
`define DEF_ISTC_SRAV 6'b000111 // srav
`define DEF_ISTC_SYNC 6'b001111 // sync
`define DEF_ISTC_PREF 6'b110011 // pref
`define DEF_ISTC_SPEC 6'b000000 // SPECIAL 类指令码
`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_NOP_OPR 8'd0
// | ALU 选择
`define DEF_ALU_SEL_LOGIC 3'b001
`define DEF_ALU_SEL_NOP 3'b000
// | 操作数
`define DEF_SRC_OPR_DATA_BUS 31:0
`define DEF_IMM_DATA_BUS 15:0
// |-------------------------------------- 指令存储器宏定义 --------------------------------------
// |------------------------------------------------------------------------------------------------
`define DEF_ISTC_ADDR_BUS 31:0 // 地址线总线
`define DEF_ISTC_DATA_BUS 31:0 // 数据线总线
`define DEF_ISTC_CACH_DEPTH 2**17-1 // 缓存深度/地址最大值
`define DEF_ISTC_ADDR_WIDTH_ACTUAL 17 // 实际使用的缓存地址线宽度
// |-------------------------------------- 通用寄存器宏定义 --------------------------------------
// |------------------------------------------------------------------------------------------------
`define DEF_GPR_ADDR_WIDTH 5 // 通用寄存器地址位宽(32个)
`define DEF_GPR_DATA_WIDTH 32 // 通用寄存器数据位宽
`define DEF_GPR_NUM 32 // 通用寄存器数目
`define DEF_GPR_ADDR_NOP 5'd0 // 空操作 GPR 地址
编程思路参考书本,我的代码仅供参考:
// |------------------------------ ================================== ------------------------------
// |============================== 指令-译码模块 ==============================
// |------------------------------ ================================== ------------------------------
// |Create Date : 2022-12-07
// |Finish Date : 2022-12-07
// |Edited by : Xu Y. B. (CSDN USER NAME :在路上,正出发)
// |Reference : 《自己动手写CPU》
// |
// |
// |------------------------------------------------------------------------------------------------
// |---------------------------------------- Change History ----------------------------------------
// |Date:2022-12-08
// |Who :Xu Y. B.
// |What:修复流水线数据相关的问题(第 2、3类问题)
// | 思路参考《自己动手写CPU》5.2节
// | 增加模块端口:Line 48 - 54
// | 增加条件分支:Line 141 - 148 、171 - 178
// |Date:2022-12-09
// |Who :Xu Y. B.
// |What:增加逻辑、移位指令的译码功能
`include "MIPS_SYS_DEFINES.v"
`timescale 1ns / 1ps
module ID_MDL(
// |-------------------------------------- 输入输出端口声明 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 时钟、复位
input I_CPU_CLK,
input I_CPU_RSTN,
// | 指令
input [`DEF_ISTC_DATA_BUS] I_ISTC,
// | GPR读写控制
output reg O_GPR_RD_EN_A,
output reg [`DEF_GPR_ADDR_WIDTH-1:0] O_GPR_RD_ADDR_A,
input [`DEF_GPR_DATA_WIDTH-1:0] I_GPR_RD_DATA_A,
output reg O_GPR_RD_EN_B,
output reg [`DEF_GPR_ADDR_WIDTH-1:0] O_GPR_RD_ADDR_B,
input [`DEF_GPR_DATA_WIDTH-1:0] I_GPR_RD_DATA_B,
// | 译码输出相关 对接 ALU 运算单元
// output reg [`DEF_ALU_SEL_BUS] O_ALU_SEL,
output reg [`DEF_ALU_OPR_BUS] O_ALU_OP_TYPE,
output reg [`DEF_SRC_OPR_DATA_BUS] O_SRC_OPR_DATA_A,
output reg [`DEF_SRC_OPR_DATA_BUS] O_SRC_OPR_DATA_B,
output reg O_DST_GPR_WR_EN,
output reg [`DEF_GPR_ADDR_WIDTH-1:0] O_DST_GPR_WR_ADDR,
// | 为解决数据相关问题/读写冲突问题 引入的端口
// 来自执行模块
input I_DST_GPR_WR_EN_FROM_EXE_MDL,
input [`DEF_GPR_ADDR_WIDTH-1:0] I_DST_GPR_WR_ADDR_FROM_EXE_MDL,
input [`DEF_GPR_DATA_WIDTH-1:0] I_DST_GPR_WR_DATA_FROM_EXE_MDL,
// 来自访存模块
input I_DST_GPR_WR_EN_FROM_MEM_ACS_MDL,
input [`DEF_GPR_ADDR_WIDTH-1:0] I_DST_GPR_WR_ADDR_FROM_MEM_ACS_MDL,
input [`DEF_GPR_DATA_WIDTH-1:0] I_DST_GPR_WR_DATA_FROM_MEM_ACS_MDL
);
// |-------------------------------------- 模块内部信号声明 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 指令分解相关
wire [5:0] W_ISTC_TYPE; // 指令码
wire [`DEF_GPR_ADDR_WIDTH-1:0] W_SRC_GPR_ADDR;
wire [`DEF_GPR_ADDR_WIDTH-1:0] W_DST_GPR_ADDR;
wire [`DEF_IMM_DATA_BUS] W_ISTC_IMM_DATA;
wire [4:0] W_ISTC_15_11_BIT;
wire [4:0] W_ISTC_10_6_BIT;
wire [5:0] W_ISTC_5_0_BIT;
// | 32位立即数
reg [31:0] R_IMM_DATA_32BIT;
// | 指令有效信号
reg R_ISTC_VAL;
// |-------------------------------------- 模块内部逻辑设计 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 指令分解相关
assign W_ISTC_TYPE = I_ISTC[31:26];// 指令码
assign W_SRC_GPR_ADDR = I_ISTC[25:21];
assign W_DST_GPR_ADDR = I_ISTC[20:16];
assign W_ISTC_IMM_DATA = I_ISTC[15:0] ;
assign W_ISTC_15_11_BIT = I_ISTC[15:11];
assign W_ISTC_10_6_BIT = I_ISTC[10:6];
assign W_ISTC_5_0_BIT = I_ISTC[5:0];
// | 指令译码
always @ (posedge I_CPU_CLK)
begin
if(~I_CPU_RSTN)
begin
O_GPR_RD_EN_A <= 1'b0;
O_GPR_RD_ADDR_A <= `DEF_GPR_ADDR_NOP;
O_GPR_RD_EN_B <= 1'b0;
O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP;
O_ALU_OP_TYPE <= `DEF_ALU_NOP_OPR;
// O_ALU_SEL <= `DEF_ALU_SEL_NOP;
O_DST_GPR_WR_EN <= 1'b0;
O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP;
R_ISTC_VAL <= 1'b0;
R_IMM_DATA_32BIT <= 32'd0;
end
else
begin
case(W_ISTC_TYPE)
`DEF_ISTC_SPEC://SPECIAL 类 指令
begin
case(W_ISTC_10_6_BIT)
5'd0:
begin
case(W_ISTC_5_0_BIT)
`DEF_ISTC_AND:
begin
O_GPR_RD_EN_A <= 1'b1;
O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR;
O_GPR_RD_EN_B <= 1'b1;
O_GPR_RD_ADDR_B <= W_DST_GPR_ADDR;
O_ALU_OP_TYPE <= `DEF_ALU_AND_OPR;
// O_ALU_SEL <= `DEF_ALU_SEL_NOP;
O_DST_GPR_WR_EN <= 1'b1;
O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;
R_ISTC_VAL <= 1'b1;
R_IMM_DATA_32BIT <= 32'd0;
end
`DEF_ISTC_OR:
begin
O_GPR_RD_EN_A <= 1'b1;
O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR;
O_GPR_RD_EN_B <= 1'b1;
O_GPR_RD_ADDR_B <= W_DST_GPR_ADDR;
O_ALU_OP_TYPE <= `DEF_ALU_OR_OPR;
// O_ALU_SEL <= `DEF_ALU_SEL_NOP;
O_DST_GPR_WR_EN <= 1'b1;
O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;
R_ISTC_VAL <= 1'b1;
R_IMM_DATA_32BIT <= 32'd0;
end
`DEF_ISTC_XOR:
begin
O_GPR_RD_EN_A <= 1'b1;
O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR;
O_GPR_RD_EN_B <= 1'b1;
O_GPR_RD_ADDR_B <= W_DST_GPR_ADDR;
O_ALU_OP_TYPE <= `DEF_ALU_XOR_OPR;
// O_ALU_SEL <= `DEF_ALU_SEL_NOP;
O_DST_GPR_WR_EN <= 1'b1;
O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;
R_ISTC_VAL <= 1'b1;
R_IMM_DATA_32BIT <= 32'd0;
end
`DEF_ISTC_NOR:
begin
O_GPR_RD_EN_A <= 1'b1;
O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR;
O_GPR_RD_EN_B <= 1'b1;
O_GPR_RD_ADDR_B <= W_DST_GPR_ADDR;
O_ALU_OP_TYPE <= `DEF_ALU_NOR_OPR;
// O_ALU_SEL <= `DEF_ALU_SEL_NOP;
O_DST_GPR_WR_EN <= 1'b1;
O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;
R_ISTC_VAL <= 1'b1;
R_IMM_DATA_32BIT <= 32'd0;
end
`DEF_ISTC_SLLV:
begin
O_GPR_RD_EN_A <= 1'b1;
O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR;
O_GPR_RD_EN_B <= 1'b1;
O_GPR_RD_ADDR_B <= W_DST_GPR_ADDR;
O_ALU_OP_TYPE <= `DEF_ALU_SLL_OPR;
// O_ALU_SEL <= `DEF_ALU_SEL_NOP;
O_DST_GPR_WR_EN <= 1'b1;
O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;
R_ISTC_VAL <= 1'b1;
R_IMM_DATA_32BIT <= 32'd0;
end
`DEF_ISTC_SRLV:
begin
O_GPR_RD_EN_A <= 1'b1;
O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR;
O_GPR_RD_EN_B <= 1'b1;
O_GPR_RD_ADDR_B <= W_DST_GPR_ADDR;
O_ALU_OP_TYPE <= `DEF_ALU_SRL_OPR;
// O_ALU_SEL <= `DEF_ALU_SEL_NOP;
O_DST_GPR_WR_EN <= 1'b1;
O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;
R_ISTC_VAL <= 1'b1;
R_IMM_DATA_32BIT <= 32'd0;
end
`DEF_ISTC_SRAV:
begin
O_GPR_RD_EN_A <= 1'b1;
O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR;
O_GPR_RD_EN_B <= 1'b1;
O_GPR_RD_ADDR_B <= W_DST_GPR_ADDR;
O_ALU_OP_TYPE <= `DEF_ALU_SRA_OPR;
// O_ALU_SEL <= `DEF_ALU_SEL_NOP;
O_DST_GPR_WR_EN <= 1'b1;
O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;
R_ISTC_VAL <= 1'b1;
R_IMM_DATA_32BIT <= 32'd0;
end
`DEF_ISTC_SYNC:
begin
O_GPR_RD_EN_A <= 1'b0;
O_GPR_RD_ADDR_A <= `DEF_GPR_ADDR_NOP;
O_GPR_RD_EN_B <= 1'b1;
O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP;
O_ALU_OP_TYPE <= `DEF_ALU_NOP_OPR;
// O_ALU_SEL <= `DEF_ALU_SEL_NOP;
O_DST_GPR_WR_EN <= 1'b0;
O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP;
R_ISTC_VAL <= 1'b1;
R_IMM_DATA_32BIT <= 32'd0;
end
default:
begin
O_GPR_RD_EN_A <= 1'b0;
O_GPR_RD_ADDR_A <= `DEF_GPR_ADDR_NOP;
O_GPR_RD_EN_B <= 1'b0;
O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP;
O_ALU_OP_TYPE <= `DEF_ALU_NOP_OPR;
// O_ALU_SEL <= `DEF_ALU_SEL_NOP;
O_DST_GPR_WR_EN <= 1'b0;
O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP;
R_ISTC_VAL <= 1'b0;
R_IMM_DATA_32BIT <= 32'd0;
end
endcase
end
default:
begin
O_GPR_RD_EN_A <= 1'b0;
O_GPR_RD_ADDR_A <= `DEF_GPR_ADDR_NOP;
O_GPR_RD_EN_B <= 1'b0;
O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP;
O_ALU_OP_TYPE <= `DEF_ALU_NOP_OPR;
// O_ALU_SEL <= `DEF_ALU_SEL_NOP;
O_DST_GPR_WR_EN <= 1'b0;
O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP;
R_ISTC_VAL <= 1'b0;
R_IMM_DATA_32BIT <= 32'd0;
end
endcase
end
`DEF_ISTC_ORI:// ori指令
begin
O_GPR_RD_EN_A <= 1'b1;
O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR;
O_GPR_RD_EN_B <= 1'b0;
O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP;
O_ALU_OP_TYPE <= `DEF_ALU_OR_OPR;
// O_ALU_SEL <= `DEF_ALU_SEL_LOGIC;
O_DST_GPR_WR_EN <= 1'b1;
O_DST_GPR_WR_ADDR <= W_DST_GPR_ADDR;
R_ISTC_VAL <= 1'b1;
R_IMM_DATA_32BIT <= {16'd0,W_ISTC_IMM_DATA};
end
`DEF_ISTC_ANDI:
begin
O_GPR_RD_EN_A <= 1'b1;
O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR;
O_GPR_RD_EN_B <= 1'b0;
O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP;
O_ALU_OP_TYPE <= `DEF_ALU_AND_OPR;
// O_ALU_SEL <= `DEF_ALU_SEL_LOGIC;
O_DST_GPR_WR_EN <= 1'b1;
O_DST_GPR_WR_ADDR <= W_DST_GPR_ADDR;
R_ISTC_VAL <= 1'b1;
R_IMM_DATA_32BIT <= {16'd0,W_ISTC_IMM_DATA};
end
`DEF_ISTC_XORI:
begin
O_GPR_RD_EN_A <= 1'b1;
O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR;
O_GPR_RD_EN_B <= 1'b0;
O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP;
O_ALU_OP_TYPE <= `DEF_ALU_XOR_OPR;
// O_ALU_SEL <= `DEF_ALU_SEL_LOGIC;
O_DST_GPR_WR_EN <= 1'b1;
O_DST_GPR_WR_ADDR <= W_DST_GPR_ADDR;
R_ISTC_VAL <= 1'b1;
R_IMM_DATA_32BIT <= {16'd0,W_ISTC_IMM_DATA};
end
`DEF_ISTC_LUI:
begin
O_GPR_RD_EN_A <= 1'b1;
O_GPR_RD_ADDR_A <= W_SRC_GPR_ADDR;
O_GPR_RD_EN_B <= 1'b0;
O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP;
O_ALU_OP_TYPE <= `DEF_ALU_OR_OPR;
// O_ALU_SEL <= `DEF_ALU_SEL_LOGIC;
O_DST_GPR_WR_EN <= 1'b1;
O_DST_GPR_WR_ADDR <= W_DST_GPR_ADDR;
R_ISTC_VAL <= 1'b1;
R_IMM_DATA_32BIT <= {W_ISTC_IMM_DATA,16'd0};
end
`DEF_ISTC_PREF:
begin
O_GPR_RD_EN_A <= 1'b0;
O_GPR_RD_ADDR_A <= `DEF_GPR_ADDR_NOP;
O_GPR_RD_EN_B <= 1'b0;
O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP;
O_ALU_OP_TYPE <= `DEF_ALU_NOP_OPR;
// O_ALU_SEL <= `DEF_ALU_SEL_LOGIC;
O_DST_GPR_WR_EN <= 1'b0;
O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP;
R_ISTC_VAL <= 1'b1;
R_IMM_DATA_32BIT <= 32'd0;
end
default:
begin
O_GPR_RD_EN_A <= 1'b0;
O_GPR_RD_ADDR_A <= `DEF_GPR_ADDR_NOP;
O_GPR_RD_EN_B <= 1'b0;
O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP;
O_ALU_OP_TYPE <= `DEF_ALU_NOP_OPR;
// O_ALU_SEL <= `DEF_ALU_SEL_NOP;
O_DST_GPR_WR_EN <= 1'b0;
O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP;
R_ISTC_VAL <= 1'b0;
R_IMM_DATA_32BIT <= 32'd0;
end
endcase
if(I_ISTC[31:21] == 11'd0)
begin
case(W_ISTC_5_0_BIT)
`DEF_ISTC_SLL:
begin
O_GPR_RD_EN_A <= 1'b0;
O_GPR_RD_ADDR_A <= `DEF_GPR_ADDR_NOP;
O_GPR_RD_EN_B <= 1'b1;
O_GPR_RD_ADDR_B <= W_DST_GPR_ADDR;
O_ALU_OP_TYPE <= `DEF_ALU_SLL_OPR;
// O_ALU_SEL <= `DEF_ALU_SEL_LOGIC;
O_DST_GPR_WR_EN <= 1'b1;
O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;
R_ISTC_VAL <= 1'b1;
R_IMM_DATA_32BIT <= {27'd0,W_ISTC_10_6_BIT};
end
`DEF_ISTC_SRL:
begin
O_GPR_RD_EN_A <= 1'b0;
O_GPR_RD_ADDR_A <= `DEF_GPR_ADDR_NOP;
O_GPR_RD_EN_B <= 1'b1;
O_GPR_RD_ADDR_B <= W_DST_GPR_ADDR;
O_ALU_OP_TYPE <= `DEF_ALU_SRL_OPR;
// O_ALU_SEL <= `DEF_ALU_SEL_LOGIC;
O_DST_GPR_WR_EN <= 1'b1;
O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;
R_ISTC_VAL <= 1'b1;
R_IMM_DATA_32BIT <= {27'd0,W_ISTC_10_6_BIT};
end
`DEF_ISTC_SRA:
begin
O_GPR_RD_EN_A <= 1'b0;
O_GPR_RD_ADDR_A <= `DEF_GPR_ADDR_NOP;
O_GPR_RD_EN_B <= 1'b1;
O_GPR_RD_ADDR_B <= W_DST_GPR_ADDR;
O_ALU_OP_TYPE <= `DEF_ALU_SRA_OPR;
// O_ALU_SEL <= `DEF_ALU_SEL_LOGIC;
O_DST_GPR_WR_EN <= 1'b1;
O_DST_GPR_WR_ADDR <= W_ISTC_15_11_BIT;
R_ISTC_VAL <= 1'b1;
R_IMM_DATA_32BIT <= {27'd0,W_ISTC_10_6_BIT};
end
default:
begin
O_GPR_RD_EN_A <= 1'b0;
O_GPR_RD_ADDR_A <= `DEF_GPR_ADDR_NOP;
O_GPR_RD_EN_B <= 1'b0;
O_GPR_RD_ADDR_B <= `DEF_GPR_ADDR_NOP;
O_ALU_OP_TYPE <= `DEF_ALU_NOP_OPR;
// O_ALU_SEL <= `DEF_ALU_SEL_NOP;
O_DST_GPR_WR_EN <= 1'b0;
O_DST_GPR_WR_ADDR <= `DEF_GPR_ADDR_NOP;
R_ISTC_VAL <= 1'b0;
R_IMM_DATA_32BIT <= 32'd0;
end
endcase
end
end
end
// | 数据输出
always @ (posedge I_CPU_CLK)
begin
if(~I_CPU_RSTN)
begin
O_SRC_OPR_DATA_A <= `DEF_ZERO_WORD;
end
else if(I_DST_GPR_WR_EN_FROM_EXE_MDL && O_GPR_RD_EN_A && (O_GPR_RD_ADDR_A == I_DST_GPR_WR_ADDR_FROM_EXE_MDL))
begin
O_SRC_OPR_DATA_A <= I_DST_GPR_WR_DATA_FROM_EXE_MDL;
end
else if(I_DST_GPR_WR_EN_FROM_MEM_ACS_MDL && O_GPR_RD_EN_A && (O_GPR_RD_ADDR_A == I_DST_GPR_WR_ADDR_FROM_MEM_ACS_MDL))
begin
O_SRC_OPR_DATA_A <= I_DST_GPR_WR_DATA_FROM_MEM_ACS_MDL;
end
else if(O_GPR_RD_EN_A)
begin
O_SRC_OPR_DATA_A <= I_GPR_RD_DATA_A;
end
else if(~O_GPR_RD_EN_A)
begin
O_SRC_OPR_DATA_A <= R_IMM_DATA_32BIT;
end
else
begin
O_SRC_OPR_DATA_A <= `DEF_ZERO_WORD;
end
end
always @ (posedge I_CPU_CLK)
begin
if(~I_CPU_RSTN)
begin
O_SRC_OPR_DATA_B <= `DEF_ZERO_WORD;
end
else if(I_DST_GPR_WR_EN_FROM_EXE_MDL && O_GPR_RD_EN_B && (O_GPR_RD_ADDR_B == I_DST_GPR_WR_ADDR_FROM_EXE_MDL))
begin
O_SRC_OPR_DATA_B <= I_DST_GPR_WR_DATA_FROM_EXE_MDL;
end
else if(I_DST_GPR_WR_EN_FROM_MEM_ACS_MDL && O_GPR_RD_EN_B && (O_GPR_RD_ADDR_B == I_DST_GPR_WR_ADDR_FROM_MEM_ACS_MDL))
begin
O_SRC_OPR_DATA_B <= I_DST_GPR_WR_DATA_FROM_MEM_ACS_MDL;
end
else if(O_GPR_RD_EN_B)
begin
O_SRC_OPR_DATA_B <= I_GPR_RD_DATA_B;
end
else if(~O_GPR_RD_EN_B)
begin
O_SRC_OPR_DATA_B <= R_IMM_DATA_32BIT;
end
else
begin
O_SRC_OPR_DATA_B <= `DEF_ZERO_WORD;
end
end
endmodule
编程思路参考书本,我的代码仅供参考:
// |------------------------------ ================================== ------------------------------
// |============================== 指令-执行模块 ==============================
// |------------------------------ ================================== ------------------------------
// |Create Date : 2022-12-07
// |Finish Date : 2022-12-07
// |Edited by : Xu Y. B. (CSDN USER NAME :在路上,正出发)
// |Reference : 《自己动手写CPU》
// |
// |
// |------------------------------------------------------------------------------------------------
// |---------------------------------------- Change History ----------------------------------------
// |Date:2022-12-08
// |Who :Xu Y. B.
// |What:修复流水线数据相关的问题(第 2、3类问题)
// | 增加模块端口:Line 42 - 44
// | 两部分输出区别:组合逻辑输出和时序逻辑输出
// | 代码变动行编号:Line 73、77、84、88、103、111、115、116
// |Date:2022-12-09
// |Who :Xu Y. B.
// |What:增加逻辑、移位运算执行功能。
`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,
// | 输出
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
);
// |-------------------------------------- 模块内部信号声明 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | 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;
// |-------------------------------------- 模块内部逻辑设计 --------------------------------------
// |------------------------------------------------------------------------------------------------
// | I_ALU_OP_TYPE 打拍对齐时序
always @ (posedge I_CPU_CLK)
begin
if(~I_CPU_RSTN)
begin
R_I_ALU_OP_TYPE <= 0;
end
else
begin
R_I_ALU_OP_TYPE <= I_ALU_OP_TYPE;
end
end
// | 计算单元
// 组合逻辑
always @ (*)
begin
if(~I_CPU_RSTN)
begin
O_DST_GPR_WR_DATA_2_ID_MDL = `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;
end
`DEF_ALU_AND_OPR:
begin
O_DST_GPR_WR_DATA_2_ID_MDL = I_SRC_OPR_DATA_A & I_SRC_OPR_DATA_B;
end
`DEF_ALU_XOR_OPR:
begin
O_DST_GPR_WR_DATA_2_ID_MDL = I_SRC_OPR_DATA_A ^ I_SRC_OPR_DATA_B;
end
`DEF_ALU_NOR_OPR:
begin
O_DST_GPR_WR_DATA_2_ID_MDL = ~(I_SRC_OPR_DATA_A | I_SRC_OPR_DATA_B);
end
`DEF_ALU_SLL_OPR:
begin
O_DST_GPR_WR_DATA_2_ID_MDL = I_SRC_OPR_DATA_B << I_SRC_OPR_DATA_A;
end
`DEF_ALU_SRL_OPR:
begin
O_DST_GPR_WR_DATA_2_ID_MDL = I_SRC_OPR_DATA_B >> I_SRC_OPR_DATA_A;
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);
end
default:
begin
O_DST_GPR_WR_DATA_2_ID_MDL = `DEF_ZERO_WORD;
end
endcase
end
end
// | 写操作打拍
always @ (posedge I_CPU_CLK)
begin
if(~I_CPU_RSTN)
begin
O_DST_GPR_WR_EN <= 1'b0;
O_DST_GPR_WR_ADDR <= 5'd0;
R_I_DST_GPR_WR_EN <= 1'b0;
R_I_DST_GPR_WR_ADDR <= 5'd0;
O_DST_GPR_WR_DATA <= `DEF_ZERO_WORD;
end
else
begin
R_I_DST_GPR_WR_EN <= I_DST_GPR_WR_EN;
R_I_DST_GPR_WR_ADDR <= I_DST_GPR_WR_ADDR;
O_DST_GPR_WR_EN <= R_I_DST_GPR_WR_EN;
O_DST_GPR_WR_ADDR <= R_I_DST_GPR_WR_ADDR;
O_DST_GPR_WR_DATA <= O_DST_GPR_WR_DATA_2_ID_MDL;
end
end
assign O_DST_GPR_WR_EN_2_ID_MDL = R_I_DST_GPR_WR_EN ;
assign O_DST_GPR_WR_ADDR_2_ID_MDL = R_I_DST_GPR_WR_ADDR;
endmodule
此处参考书本的验证代码:
.org 0x0
.global _start
.set noat
_start:
lui $1,0x0101
ori $1,$1,0x0101
ori $2,$1,0x1100
or $1,$1,$2
andi $3,$1,0x00FE
and $1,$3,$1
xori $4,$1,0xFF00
xor $1,$4,$1
nor $1,$4,$1
.org 0x0
.global _start
.set noat
_start:
lui $2,0x0404
ori $2,$2,0x0404
ori $7,$0,0x7
ori $5,$0,0x5
ori $8,$0,0x8
sync
sll $2,$2,8
sllv $2,$2,$7
srl $2,$2,8
srlv $2,$2,$5
nop
ssnop
sll $2,$2,19
ssnop
sra $2,$2,16
srav $2,$2,$8