系统结构框图
代码模块
1. 宏定义defines.v
// 宏定义模块
// *************** 与具体指令有关的宏定义 ***************
`define EXE_MOVN 6'b001011
`define EXE_MOVZ 6'b001010
`define EXE_MFHI 6'b010000
`define EXE_MFLO 6'b010010
`define EXE_MTHI 6'b010001
`define EXE_MTLO 6'b010011
//AluOp 子类型
`define EXE_MOVN_OP 8'b00001011
`define EXE_MOVZ_OP 8'b00001010
`define EXE_MFHI_OP 8'b00010000
`define EXE_MFLO_OP 8'b00010010
`define EXE_MTHI_OP 8'b00010001
`define EXE_MTLO_OP 8'b00010011
//AluSel 类型
`define EXE_RES_MOVE 3'b011 // 移动
2. 译码id
添加新的移动指令MOVN、MOVZ、MFHI、MFLO、MTHI、MTLO的译码分支
// 对指令进行译码,得到最终运算的类型、子类型、源操作数1、源操作数2、要写入的目的寄存器地址信息等
`include "defines.v"
module id (
// 输出到regfile的信息
output reg reg1_read_o, // regfile模块第一个读寄存器端口的读使能信号
output reg reg2_read_o, // regfile模块第二个读寄存器端口的读使能信号
output reg [`RegAddrBus] reg1_addr_o, // regfile模块第一个读寄存器端口的读地址信号
output reg [`RegAddrBus] reg2_addr_o, // regfile模块第二个读寄存器端口的读地址信号
// 送到执行阶段的信息
output reg [`AluOpBus] aluop_o, // 译码阶段的指令要进行的运算的子类型
output reg [`AluSelBus] alusel_o, // 译码阶段的指令要进行的运算的类型
output reg [`RegBus] reg1_o, // 译码阶段的指令要进行的运算的源操作数1
output reg [`RegBus] reg2_o, // 译码阶段的指令要进行的运算的源操作数2
output reg [`RegAddrBus] wd_o, // 译码阶段的指令要写入的目的寄存器地址
output reg wreg_o, // 译码阶段的指令是否有要写入的目的寄存器
input wire rst, // 复位
input wire [`InstAddrBus] pc_i, // 译码阶段指令对应的地址
input wire [`InstBus] inst_i, // 译码阶段的指令
// 读取的regfile的值
input wire [`RegBus] reg1_data_i, // 从regfile输入的第一个读寄存器端口的输出
input wire [`RegBus] reg2_data_i // 从regfile输入的第一个读寄存器端口的输出
);
// 取得指令的指令码,功能码
// 对于ori指令只需通过判断26-31bits的值,即可判断是否是ori指令,6'b00_1101
wire [5:0] op = inst_i[31:26]; // 指令码
wire [4:0] op2 = inst_i[10:6];
wire [5:0] op3 = inst_i[5:0]; // 操作码
wire [4:0] op4 = inst_i[20:16];
// 保存指令执行需要的立即数
reg [`RegBus] imm;
// 指令指示是否有效
reg instvalid;
// ****************************************************************************
// **************************第一阶段:对指令进行译码******************************
// ****************************************************************************
always @ (*) begin
if (rst == `RstEnable) begin
aluop_o <= `EXE_NOP_OP;
alusel_o <= `EXE_RES_NOP;
wd_o <= `NOPRegAddr; // 写入地址赋值为无效
wreg_o <= `WriteDisable; // 没有要写入的目的寄存器
instvalid <= `InstValid; // 指令有效
reg1_read_o <= 1'b0;
reg2_read_o <= 1'b0;
reg1_addr_o <= `NOPRegAddr;
reg2_addr_o <= `NOPRegAddr;
imm <= 32'h0;
end else begin
aluop_o <= `EXE_NOP_OP;
alusel_o <= `EXE_RES_NOP;
wd_o <= inst_i[15:11]; // 默认目的寄存器地址
wreg_o <= `WriteDisable;
instvalid <= `InstValid; // 指令有效
reg1_read_o <= 1'b0;
reg2_read_o <= 1'b0;
reg1_addr_o <= inst_i[25:21]; // 默认通过regfile读端口1读取的寄存器地址,rs,源寄存器地址
reg2_addr_o <= inst_i[20:16]; // 默认通过regfile读端口2读取的寄存器地址,rt,源寄存器地址
imm <= `ZeroWord;
case (op)
`EXE_SPECIAL_INST: begin
case (op2) // [10:6]sa为0
5'b00000: begin
case (op3) // [5:0]func
`EXE_OR: begin // or指令
wreg_o <= `WriteEnable;
aluop_o <= `EXE_OR_OP; // 8'b 0010_0101
alusel_o <= `EXE_RES_LOGIC;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_AND: begin // and指令
wreg_o <= `WriteEnable;
aluop_o <= `EXE_AND_OP; // 8'b 0010_0100
alusel_o <= `EXE_RES_LOGIC;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_XOR: begin // xor指令
wreg_o <= `WriteEnable;
aluop_o <= `EXE_XOR_OP ; // 8'b 0010_0110
alusel_o <= `EXE_RES_LOGIC;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_NOR: begin // nor指令
wreg_o <= `WriteEnable;
aluop_o <= `EXE_NOR_OP; // 8'b 0010_0111
alusel_o <= `EXE_RES_LOGIC;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_SLLV: begin // sllv指令
wreg_o <= `WriteEnable;
aluop_o <= `EXE_SLL_OP; // 8'b 0000_0100
alusel_o <= `EXE_RES_SHIFT;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_SRLV: begin // srlv指令
wreg_o <= `WriteEnable;
aluop_o <= `EXE_SRL_OP; // 8'b 0000_0110
alusel_o <= `EXE_RES_SHIFT;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_SRAV: begin // srav指令
wreg_o <= `WriteEnable;
aluop_o <= `EXE_SRA_OP; // 8'b 0000_0111
alusel_o <= `EXE_RES_SHIFT;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
end
`EXE_MFHI: begin // mfhi rd <- hi
wreg_o <= `WriteEnable;
aluop_o <= `EXE_MFHI_OP;
alusel_o <= `EXE_RES_MOVE;
reg1_read_o <= 1'b0;
reg2_read_o <= 1'b0;
instvalid <= `InstValid;
end
`EXE_MFLO: begin // mflo rd <- lo
wreg_o <= `WriteEnable;
aluop_o <= `EXE_MFLO_OP;
alusel_o <= `EXE_RES_MOVE;
reg1_read_o <= 1'b0;
reg2_read_o <= 1'b0;
instvalid <= `InstValid;
end
`EXE_MTHI: begin // mthi hi <- rs
wreg_o <= `WriteDisable;
aluop_o <= `EXE_MTHI_OP;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
instvalid <= `InstValid;
end
`EXE_MTLO: begin // mtlo lo <- rs
wreg_o <= `WriteDisable;
aluop_o <= `EXE_MTLO_OP;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
instvalid <= `InstValid;
end
`EXE_MOVN: begin // movn rd <- rs
aluop_o <= `EXE_MOVN_OP;
alusel_o <= `EXE_RES_MOVE;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
// reg2_o的值就是地址为rt的通用寄存器的值
if (reg2_o != `ZeroWord) begin
wreg_o <= `WriteEnable;
end else begin
wreg_o <= `WriteDisable;
end
end
`EXE_MOVZ: begin
aluop_o <= `EXE_MOVZ_OP;
alusel_o <= `EXE_RES_MOVE;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b1;
instvalid <= `InstValid;
// reg2_o的值就是地址为rt的通用寄存器的值
if (reg2_o == `ZeroWord) begin
wreg_o <= `WriteEnable;
end else begin
wreg_o <= `WriteDisable;
end
end
default: begin
end
endcase // case (op3)
end
default: begin
end
endcase // case(op2)
end
`EXE_ORI: begin // 依据op的值判断指令是否为ori指令
// ori指令需要将结果写入目的寄存器
wreg_o <= `WriteEnable;
// 运算子类型是逻辑'or'运算
aluop_o <= `EXE_OR_OP;
// 运算类型是逻辑运算
alusel_o <= `EXE_RES_LOGIC;
// 需要通过regfile的读端口1读取寄存器
reg1_read_o <= `WriteEnable;
// 不需要通过regfile的读端口2读取寄存器
reg2_read_o <= `WriteDisable;
// 指令执行需要的立即数,无符号扩展
imm <= {16'h0, inst_i[15:0]};
// 指令执行要写的目的寄存器地址
wd_o <= inst_i[20:16];
// ori指令是有效指令
instvalid <= `InstValid;
end
`EXE_ANDI: begin // andi指令
wreg_o <= `WriteEnable;
aluop_o <= `EXE_AND_OP; // 8'b 0000_1100
alusel_o <= `EXE_RES_LOGIC;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
imm <= {16'h0, inst_i[15:0]};
wd_o <= inst_i[20:16];
instvalid <= `InstValid;
end
`EXE_XORI: begin // xori指令
wreg_o <= `WriteEnable;
aluop_o <= `EXE_XOR_OP; // 8'b 0010_0100
alusel_o <= `EXE_RES_LOGIC;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
imm <= {16'h0, inst_i[15:0]};
wd_o <= inst_i[20:16];
instvalid <= `InstValid;
end
`EXE_LUI: begin // lui指令
wreg_o <= `WriteEnable;
aluop_o <= `EXE_OR_OP; // 8'b 0010_0101
alusel_o <= `EXE_RES_LOGIC;
reg1_read_o <= 1'b1;
reg2_read_o <= 1'b0;
imm <= {inst_i[15:0], 16'h0};
wd_o <= inst_i[20:16];
instvalid <= `InstValid;
end
default: begin
end
endcase // case(op)
if (inst_i[31:21] == 11'b000_0000_0000) begin
if (op3 == `EXE_SLL) begin // sll指令
wreg_o <= `WriteEnable;
aluop_o <= `EXE_SLL_OP; // 8'b 0000_0000
alusel_o <= `EXE_RES_SHIFT;
reg1_read_o <= 1'b0;
reg2_read_o <= 1'b1;
imm[4:0] <= inst_i[10:6];
wd_o <= inst_i[15:11];
instvalid <=`InstValid;
end else if (op3 == `EXE_SRL) begin // srl指令
wreg_o <= `WriteEnable;
aluop_o <= `EXE_SRL_OP; // 8'b 0000_0010
alusel_o <= `EXE_RES_SHIFT;
reg1_read_o <= 1'b0;
reg2_read_o <= 1'b1;
imm[4:0] <= inst_i[10:6];
wd_o <= inst_i[15:11];
instvalid <= `InstValid;
end else if (op3 == `EXE_SRA) begin // sra指令
wreg_o <= `WriteEnable;
aluop_o <= `EXE_SRA_OP; // 8'b 0000_0011
alusel_o <= `EXE_RES_SHIFT;
reg1_read_o <= 1'b0;
reg2_read_o <= 1'b1;
imm <= inst_i[10:6];
wd_o <= inst_i[15:11];
instvalid <= `InstValid;
end
end
end //else
end //always
// ****************************************************************************
// ********************第二阶段:确定进行运算的操作数1 ******************************
// ****************************************************************************
always @ (*) begin
if (rst == `RstEnable) begin
reg1_o <= `ZeroWord;
end else if (reg1_read_o == 1'b1) begin
reg1_o <= reg1_data_i; // regfile读端口1的输出值
end else if (reg1_read_o == 1'b0) begin
reg1_o <= imm; // 立即数
end else begin
reg1_o <= `ZeroWord;
end
end
// ****************************************************************************
// ********************第三阶段:确定进行运算的操作数2 ******************************
// ****************************************************************************
always @ (*) begin
if (rst == `RstEnable) begin
reg2_o <= `ZeroWord;
end else if (reg2_read_o == 1'b1) begin
reg2_o <= reg2_data_i; // regfile读端口2的输出值
end else if (reg2_read_o == 1'b0) begin
reg2_o <= imm; // 立即数
end else begin
reg2_o <= `ZeroWord;
end
end
endmodule
3. 执行ex
为移动指令添加新的执行分支
// 从ID模块得到运算类型alusel_i、运算子类型aluse_i、源操作数reg1_i、源操作数reg2_i、要写入的目的寄存器地址wd_i
// EX模块依据这些数据进行运算
`include "defines.v"
module ex (
// 执行的结果
output reg [`RegAddrBus] wd_o, // 最终要写入的目的寄存器地址
output reg wreg_o, // 最终是否有要写入的目的寄存器
output reg [`RegBus] wdata_o, // 最终要写入目的寄存器的值
// 处于执行阶段的指令对HI、LO寄存器的写操作请求
output reg whilo_o,
output reg [`RegBus] hi_o,
output reg [`RegBus] lo_o,
input wire rst,
// 译码阶段送到执行阶段的信息
input wire [`AluOpBus] aluop_i, // 执行阶段运算子类型
input wire [`AluSelBus] alusel_i, // 执行阶段运算类型
input wire [`RegBus] reg1_i, // 执行阶段源操作数1
input wire [`RegBus] reg2_i, // 执行阶段源操作数2
input wire [`RegAddrBus] wd_i, // 执行阶段要写入的目的寄存器地址
input wire wreg_i, // 执行阶段是否有要写入的目的寄存器
// HILO模块给出的HI、LO寄存器的值
input wire [`RegBus] hi_i, // HILO模块给出的HI寄存器的值
input wire [`RegBus] lo_i // HILO模块给出的LO寄存器的值
);
reg [`RegBus] logicout; // 逻辑运算的结果
reg [`RegBus] shiftres; // 移位运算的结果
reg [`RegBus] moveres; // 移动操作的结果
reg [`RegBus] HI; // 保存HI寄存器的最新值
reg [`RegBus] LO; // 保存LO寄存器的最新值
// ****************************************************************************
// ***************第一阶段:得到最新的HI、LO寄存器的值*********************
// ****************************************************************************
always @ (*) begin
if (rst == `RstEnable) begin
{HI, LO} <= {`ZeroWord, `ZeroWord};
end else begin
{HI, LO} <= {hi_i, lo_i};
end
end
// ****************************************************************************
// ***************第二阶段:依据aluop_i指示的运算子类型进行运算*********************
// ****************************************************************************
// ********** 逻辑运算 **********
always @ (*) begin
if (rst == `RstEnable) begin
logicout <= `ZeroWord;
end else begin
case (aluop_i)
`EXE_OR_OP: begin
logicout <= reg1_i | reg2_i;
end
`EXE_AND_OP: begin
logicout <= reg1_i & reg2_i;
end
`EXE_NOR_OP: begin
logicout <= ~(reg1_i | reg2_i);
end
`EXE_XOR_OP: begin
logicout <= reg1_i ^ reg2_i;
end
default: begin
logicout <= `ZeroWord;
end
endcase // case
end // if
end // always
// ********** 移位运算 **********
always @ (*) begin
if (rst == `RstEnable) begin
shiftres <= `ZeroWord;
end else begin
case (aluop_i)
`EXE_SLL: begin
shiftres <= reg2_i << reg1_i[4:0];
end
`EXE_SRL: begin
shiftres <= reg2_i >> reg1_i[4:0];
end
`EXE_SRA: begin
shiftres <= ({32{reg2_i[31]}} << (6'd32-{1'b0, reg1_i[4:0]})) | reg2_i >> reg1_i[4:0];
end
endcase
end
end
// ********** 进行移位运算 MFHI、MFLO、MOVN、MOVZ **********
always @ (*) begin
if (rst == `RstEnable) begin
moveres <= `ZeroWord;
end else begin
moveres <= `ZeroWord;
case (aluop_i)
`EXE_MFHI_OP: begin
// 如果是mfhi指令,将HI的值作为移动操作的结果 rd <- hi
moveres <= HI;
end
`EXE_MFLO_OP: begin
// 如果是mflo指令,将LO的值作为移动操作的结果 rd <- lo
moveres <= LO;
end
`EXE_MOVZ_OP: begin
// 如果是movz指令,将reg1_i的值作为移动操作的结果 rd <- rs
moveres <= reg1_i;
end
`EXE_MOVN_OP: begin
// 如果是movn指令,将reg1_i的值作为移动操作的结果 rd <- rs
moveres <= reg1_i;
end
endcase
end // else
end
// ****************************************************************************
// **********第三阶段:依据alusel_i指示的运算类型,选择一个运算结果作为最终结果********
// ****************************************************************************
always @ (*) begin
wd_o <= wd_i; // 要写入的目的寄存器地址
wreg_o <= wreg_i; // 是否要写入目的寄存器
case (alusel_i)
`EXE_RES_LOGIC: begin
wdata_o <= logicout; // wdata_o中存放运算结果
end
`EXE_RES_SHIFT: begin
wdata_o <= shiftres;
end
`EXE_RES_MOVE: begin
wdata_o <= moveres;
end
default: begin
wdata_o <= `ZeroWord;
end
endcase // case
end // always
// ****************************************************************************
// ***************************第四阶段:是否需要写HILO寄存器************************
// ****************************************************************************
always @ (*) begin
if (rst == `RstEnable) begin
whilo_o <= `WriteEnable;
hi_o <= `ZeroWord;
lo_o <= `ZeroWord;
end else if (aluop_i == `EXE_MTHI_OP) begin // hi <- rs
whilo_o <= `WriteEnable;
hi_o <= reg1_i;
lo_o <= LO;
end else if (aluop_i == `EXE_MTLO_OP) begin // lo <- rs
whilo_o <= `WriteEnable;
hi_o <= HI;
lo_o <= reg1_i;
end
end
endmodule
4. 特殊寄存器hilo_reg
// HILO寄存器的实现
// 时钟上升沿,复位信号无效,当WriteEnable时,将输入作为HI、LO的新值,并通过hi_o、lo_o输出
`include "defines.v"
module hilo_reg (
input wire clk,
input wire rst,
// 写端口, 来自回写模块
input wire we, // HI、LO寄存器写使能信号
input wire [`RegBus] hi_i, // 要写入HI寄存器的值
input wire [`RegBus] lo_i, // 要写入LO寄存器的值
// 读端口, 传送到执行模块
output reg [`RegBus] hi_o,
output reg [`RegBus] lo_o
);
always @ (posedge clk) begin
if (rst == `RstEnable) begin
hi_o <= `ZeroWord;
lo_o <= `ZeroWord;
end else if (we == `WriteEnable) begin
hi_o <= hi_i;
lo_o <= lo_i;
end
end
endmodule
5. 顶层模块OpenMIPS
增加新端口和新模块的顶层模块
// 顶层模块
`include "defines.v"
module openmips (
output wire [`RegBus] rom_addr_o, // 输出到指令存储器的地址
output wire rom_ce_o, // 指令寄存器使能信号
input wire [`RegBus] rom_data_i, // 从指令寄存器取得的指令
input wire rst,
input wire clk
);
// ****************************************************************************
// **************************第一阶段:物理连线声明******************************
// ****************************************************************************
// 连接ID模块和EX模块输入的变量
wire [`AluOpBus] id_aluop;
wire [`AluSelBus] id_alusel;
wire [`RegBus] id_reg1;
wire [`RegBus] id_reg2;
wire id_wreg;
wire [`RegAddrBus] id_wd;
// 连接译码阶段ID模块和通用寄存器Regfile模块的变量
wire reg1_read;
wire reg2_read;
wire [`RegBus] reg1_data;
wire [`RegBus] reg2_data;
wire [`RegAddrBus] reg1_addr;
wire [`RegAddrBus] reg2_addr;
// 连接EX模块输出和MEM模块的变量
wire [`RegAddrBus] ex_wd;
wire ex_wreg;
wire [`RegBus] ex_wdata;
wire ex_whilo;
wire [`RegBus] ex_hi;
wire [`RegBus] ex_lo;
// 连接MEM模块输出和WB模块的变量
wire [`RegAddrBus] mem_wd;
wire mem_wreg;
wire [`RegBus] mem_wdata;
wire mem_whilo;
wire [`RegBus] mem_hi;
wire [`RegBus] mem_lo;
// 连接WB模块和RegFIle模块输入的变量
wire [`RegAddrBus] wb_wd;
wire wb_wreg;
wire [`RegBus] wb_wdata;
// 连接WB模块和HILO模块的变量
wire wb_whilo;
wire [`RegBus] wb_hi;
wire [`RegBus] wb_lo;
// 连接HILO模块和EX模块的变量
wire [`RegBus] hilo_hi;
wire [`RegBus] hilo_lo;
// ****************************************************************************
// **********************第二阶段:对各个模块进行实例化*****************************
// ****************************************************************************
// pc_reg例化
pc_reg pc_reg0 (
.pc(rom_addr_o), .ce(rom_ce_o),
.clk(clk), .rst(rst)
);
// 译码阶段ID模块例化
id id0 (
// 送到RegFile模块的信息
.reg1_read_o(reg1_read), .reg2_read_o(reg2_read),
.reg1_addr_o(reg1_addr), .reg2_addr_o(reg2_addr),
// 送到EX模块的信息
.aluop_o(id_aluop), .alusel_o(id_alusel),
.reg1_o(id_reg1), .reg2_o(id_reg2),
.wd_o(id_wd), .wreg_o(id_wreg),
.rst(rst), .pc_i(rom_addr_o), .inst_i(rom_data_i),
// 来自RegFile模块的输出
.reg1_data_i(reg1_data), .reg2_data_i(reg2_data)
);
// 通用寄存器Regfile模块例化
regfile regfile0 (
.we(wb_wreg), .waddr(wb_wd), .wdata(wb_wdata),
.re1(reg1_read), .raddr1(reg1_addr), .rdata1(reg1_data),
.re2(reg2_read), .raddr2(reg2_addr), .rdata2(reg2_data),
.clk(clk), .rst(rst)
);
// EX模块例化
ex ex0 (
// 输出到MEM模块的信息
.wd_o(ex_wd), .wreg_o(ex_wreg), .wdata_o(ex_wdata),
.whilo_o(ex_whilo), .hi_o(ex_hi), .lo_o(ex_lo),
.rst(rst),
// 从ID模块传递过来的信息
.aluop_i(id_aluop), .alusel_i(id_alusel),
.reg1_i(id_reg1), .reg2_i(id_reg2),
.wd_i(id_wd), .wreg_i(id_wreg),
// 从HILO模块传递过来的信息
.hi_i(hilo_hi), .lo_i(hilo_lo)
);
// MEM模块例化
mem mem0 (
// 输出到WB模块的信息
.wd_o(mem_wd), .wreg_o(mem_wreg), .wdata_o(mem_wdata),
.whilo_o(mem_whilo), .hi_o(mem_hi), .lo_o(mem_lo),
.rst(rst),
// 从EX模块接收到的信息
.wd_i(ex_wd), .wreg_i(ex_wreg), .wdata_i(ex_wdata),
.whilo_i(ex_whilo), .hi_i(ex_hi), .lo_i(ex_lo)
);
// WB模块例化
wb wb0 (
// 输出的regfile信息
.wd_o(wb_wd), .wreg_o(wb_wreg), .wdata_o(wb_wdata),
// 输出到HILO模块的信息
.whilo_o(wb_whilo), .hi_o(wb_hi), .lo_o(wb_lo),
.rst(rst),
// 从MEM模块接收到的信息
.wd_i(mem_wd), .wreg_i(mem_wreg), .wdata_i(mem_wdata),
.whilo_i(mem_whilo), .hi_i(mem_hi), .lo_i(mem_lo)
);
// 特殊寄存器HILO模块的实例化
hilo_reg hilo_reg0 (
// 输出到EX模块的信息
.hi_o(hilo_hi), .lo_o(hilo_lo),
.rst(rst), .clk(clk),
// 从WB模块接收到的信息
.we(wb_whilo), .hi_i(wb_hi), .lo_i(wb_lo)
);
endmodule
测试模块
仿真波形