ID阶段(Instruction Decode)
ID阶段对指令进行解码并生成必要的信号。数据的直通、Load冒险的检测,分支的判定都在这个阶段进行
各模块和端口定义:
1.指令解码器 decoder:
/********** IF/ID pipeline register **********/
input wire [`WordAddrBus] if_pc, // Program counter
input wire [`WordDataBus] if_insn, // Instruction
input wire if_en, // Enable pipeline data
/********** GPR interface **********/
input wire [`WordDataBus] gpr_rd_data_0, // Read data 0
input wire [`WordDataBus] gpr_rd_data_1, // Read data 1
output wire [`RegAddrBus] gpr_rd_addr_0, // Read address 0
output wire [`RegAddrBus] gpr_rd_addr_1, // Read address 1
/********** Forwarding **********/
// Forwarding form ID stage
input wire id_en, // Enable pipeline data
input wire [`RegAddrBus] id_dst_addr, // Write address
input wire id_gpr_we_, // Write enable
input wire [`MemOpBus] id_mem_op, // Memory operation
// Forwarding form EX stage
input wire ex_en, // Enable pipeline data
input wire [`RegAddrBus] ex_dst_addr, // Write address
input wire ex_gpr_we_, // Write enable
input wire [`WordDataBus] ex_fwd_data, // Forwarding data
// Forwarding form MEM stage
input wire [`WordDataBus] mem_fwd_data, // Forwarding data
/********** Control register interface **********/
input wire [`CpuExeModeBus] exe_mode, // Execution mode
input wire [`WordDataBus] creg_rd_data, // Read data
output wire [`RegAddrBus] creg_rd_addr, // Read address
/********** Decode result **********/
output reg [`AluOpBus] alu_op, // ALU operation
output reg [`WordDataBus] alu_in_0, // ALU input 0
output reg [`WordDataBus] alu_in_1, // ALU input 1
output reg [`WordAddrBus] br_addr, // Branch address
output reg br_taken, // Branch taken
output reg br_flag, // Brach flag
output reg [`MemOpBus] mem_op, // Memory operation
output wire [`WordDataBus] mem_wr_data, // Data to write to memory
output reg [`CtrlOpBus] ctrl_op, // Control operation
output reg [`RegAddrBus] dst_addr, // GPR write address
output reg gpr_we_, // GPR write enable
output reg [`IsaExpBus] exp_code, // Exception code
output reg ld_hazard // Load hazard
2.ID阶段寄存器 id_reg
/********** Clock & Reset **********/
input wire clk,
input wire reset,
/********** Decode result **********/
input wire [`AluOpBus] alu_op, // ALU operation 位宽4位
input wire [`WordDataBus] alu_in_0, // ALU input 0 ALU输入0 位宽32
input wire [`WordDataBus] alu_in_1, // ALU input 1 ALU输入1 位宽32
input wire br_flag, // Branch flag 分支符号位
input wire [`MemOpBus] mem_op, // Memory operation 位宽2
input wire [`WordDataBus] mem_wr_data, // Data to write to memory 32
input wire [`CtrlOpBus] ctrl_op, // Control operation 2
input wire [`RegAddrBus] dst_addr, // GPR write address 5
input wire gpr_we_, // GPR register write enable
input wire [`IsaExpBus] exp_code, // Exception code 3
/********** Pipeline control signal **********/
input wire stall, // Stall
input wire flush, // Flush
/********** IF/ID pipeline register **********/
input wire [`WordAddrBus] if_pc, // Program counter
input wire if_en, // Enable pipeline data
/********** ID/EX pipeline register **********/
output reg [`WordAddrBus] id_pc, // Program counter
output reg id_en, // Enable pipeline data
output reg [`AluOpBus] id_alu_op, // ALU operation
output reg [`WordDataBus] id_alu_in_0, // ALU input 0
output reg [`WordDataBus] id_alu_in_1, // ALU input 1
output reg id_br_flag, // Branch flag
output reg [`MemOpBus] id_mem_op, // Memory operation
output reg [`WordDataBus] id_mem_wr_data, // Data to write to memory
output reg [`CtrlOpBus] id_ctrl_op, // Control operation
output reg [`RegAddrBus] id_dst_addr, // GPR write address
output reg id_gpr_we_, // GPR register write enable
output reg [`IsaExpBus] id_exp_code // Exception code
3.top模块id_stage:
/********** Clock & Reset **********/
input wire clk,
input wire reset,
/********** GPR interface **********/
input wire [`WordDataBus] gpr_rd_data_0, // Read data 0
input wire [`WordDataBus] gpr_rd_data_1, // Read data 1
output wire [`RegAddrBus] gpr_rd_addr_0, // Read Address 0
output wire [`RegAddrBus] gpr_rd_addr_1, // Read Address 1
/********** Forwarding **********/
// Forwarding from EX stage
input wire ex_en, // Enable pipeline data
input wire [`WordDataBus] ex_fwd_data, // Forwarding data
input wire [`RegAddrBus] ex_dst_addr, // Write address
input wire ex_gpr_we_, // Write enable
// Forwarding from MEM stage
input wire [`WordDataBus] mem_fwd_data, // Forwarding
/********** Control register interface **********/
input wire [`CpuExeModeBus] exe_mode, // Execution mode
input wire [`WordDataBus] creg_rd_data, // Read data
output wire [`RegAddrBus] creg_rd_addr, // Read address
/********** Pipeline control signal **********/
input wire stall,
input wire flush,
output wire [`WordAddrBus] br_addr, // Branch address
output wire br_taken, // Branch taken
output wire ld_hazard, // Load hazard
/********** IF/ID pipeline register **********/
input wire [`WordAddrBus] if_pc, // Program counter
input wire [`WordDataBus] if_insn, // Instruction
input wire if_en, // Enable pipeline data
/********** ID/EX pipeline register **********/
output wire [`WordAddrBus] id_pc, // Program counter
output wire id_en, // Enable pipeline data
output wire [`AluOpBus] id_alu_op, // ALU operation
output wire [`WordDataBus] id_alu_in_0, // ALU input 0
output wire [`WordDataBus] id_alu_in_1, // ALU input 1
output wire id_br_flag, // Branch flag
output wire [`MemOpBus] id_mem_op, // Memory opeartion
output wire [`WordDataBus] id_mem_wr_data, // Data to write to memory
output wire [`CtrlOpBus] id_ctrl_op, // Control operation
output wire [`RegAddrBus] id_dst_addr, // GPR write address
output wire id_gpr_we_, // GPR write enable
output wire [`IsaExpBus] id_exp_code // Exception code
4.gpr:
//时钟和复位
input wire clk,
input wire reset,
/********** 读端口0 **********/
input wire [`RegAddrBus] rd_addr_0, // Read address 位宽5
output wire [`WordDataBus] rd_data_0, // Read data 位宽32
/********** 读端口1 **********/
input wire [`RegAddrBus] rd_addr_1, // Read address 位宽5
output wire [`WordDataBus] rd_data_1, // Read data 位宽32
/********** 写端口 **********/
input wire we_, // Write enable 位宽1
input wire [`RegAddrBus] wr_addr, // Write address 位宽5
input wire [`WordDataBus] wr_data // Write data 位宽32
);
1.指令解码器
指令解码器从输入的指令码中分解各个指令字段(从IF阶段拿出的指令),生成地址、数据和控制等信号。数据的直通、Load冒险检测、分支的判断也在这个模块实现。
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2022/01/29 21:41:13
// Design Name:
// Module Name: decoder
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
// Instruction decoder
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
/********** Global header **********/
`include "nettype.vh"
`include "global_config.vh"
`include "stddef.vh"
/********** Local header **********/
`include "isa.vh"
`include "cpu.vh"
module decoder(
/********** IF/ID pipeline register **********/
input wire [`WordAddrBus] if_pc, // Program counter
input wire [`WordDataBus] if_insn, // Instruction
input wire if_en, // Enable pipeline data
/********** GPR interface **********/
input wire [`WordDataBus] gpr_rd_data_0, // Read data 0
input wire [`WordDataBus] gpr_rd_data_1, // Read data 1
output wire [`RegAddrBus] gpr_rd_addr_0, // Read address 0
output wire [`RegAddrBus] gpr_rd_addr_1, // Read address 1
/********** Forwarding **********/
// Forwarding form ID stage
input wire id_en, // Enable pipeline data
input wire [`RegAddrBus] id_dst_addr, // Write address
input wire id_gpr_we_, // Write enable
input wire [`MemOpBus] id_mem_op, // Memory operation
// Forwarding form EX stage
input wire ex_en, // Enable pipeline data
input wire [`RegAddrBus] ex_dst_addr, // Write address
input wire ex_gpr_we_, // Write enable
input wire [`WordDataBus] ex_fwd_data, // Forwarding data
// Forwarding form MEM stage
input wire [`WordDataBus] mem_fwd_data, // Forwarding data
/********** Control register interface **********/
input wire [`CpuExeModeBus] exe_mode, // Execution mode
input wire [`WordDataBus] creg_rd_data, // Read data
output wire [`RegAddrBus] creg_rd_addr, // Read address
/********** Decode result **********/
output reg [`AluOpBus] alu_op, // ALU operation
output reg [`WordDataBus] alu_in_0, // ALU input 0
output reg [`WordDataBus] alu_in_1, // ALU input 1
output reg [`WordAddrBus] br_addr, // Branch address
output reg br_taken, // Branch taken
output reg br_flag, // Brach flag
output reg [`MemOpBus] mem_op, // Memory operation
output wire [`WordDataBus] mem_wr_data, // Data to write to memory
output reg [`CtrlOpBus] ctrl_op, // Control operation
output reg [`RegAddrBus] dst_addr, // GPR write address
output reg gpr_we_, // GPR write enable
output reg [`IsaExpBus] exp_code, // Exception code
output reg ld_hazard // Load hazard
);
/********** Instruction field **********/
// `define IsaOpLoc 31:26 // Opcode location
//`define IsaOpBus 5:0 // Opcode bus
wire [`IsaOpBus] op = if_insn[`IsaOpLoc]; // Opcode 指令前六位取出
//`define IsaRaAddrLoc 25:21// Register Ra location
//`define IsaRegAddrBus 4:0 // Register address bus
wire [`RegAddrBus] ra_addr = if_insn[`IsaRaAddrLoc]; // Ra address
//$display("ra_addr=%b",ra_addr);
//`define IsaRbAddrLoc 20:16 // Register Rb location
wire [`RegAddrBus] rb_addr = if_insn[`IsaRbAddrLoc]; // Rb address
//`define IsaRcAddrLoc 15:11 // Register Rc location
wire [`RegAddrBus] rc_addr = if_insn[`IsaRcAddrLoc]; // Rc address
//`define IsaImmLoc 15:0
//`define IsaImmBus 15:0
wire [`IsaImmBus] imm = if_insn[`IsaImmLoc]; // Immediate
/********** Immediate **********/
// Sign extension
//`define ISA_IMM_MSB 15 // Immediate MSB
//`define WordDataBus 31:0 // Data bus
//`define ISA_EXT_W 16
wire [`WordDataBus] imm_s = {{`ISA_EXT_W{imm[`ISA_IMM_MSB]}}, imm}; //16位立即数扩展到32位
// Zero extension
wire [`WordDataBus] imm_u = {{`ISA_EXT_W{1'b0}}, imm};
/********** Register read address **********/
assign gpr_rd_addr_0 = ra_addr; // GPR read address 0
assign gpr_rd_addr_1 = rb_addr; // GPR read address 1
assign creg_rd_addr = ra_addr; // Control register read address
/********** Control register read data **********/
//`define WordDataBus 31:0 // Data bus
reg [`WordDataBus] ra_data; // Unsigned Ra
wire signed [`WordDataBus] s_ra_data = $signed(ra_data); // Signed Ra
reg [`WordDataBus] rb_data; // Unsigned Rb
wire signed [`WordDataBus] s_rb_data = $signed(rb_data); // Signed Rb
assign mem_wr_data = rb_data; // Data to write to memory
/********** Address **********/
//`define WordAddrBus 29:0 // Address bus
//`define WORD_ADDR_MSB 29 // Most significant bit
//`define WordAddrLoc 31:2 // Word address location
//jr_target为字编址, ra_data为字节编址,所以选取ra_data的高30位
wire [`WordAddrBus] ret_addr = if_pc + 1'b1; // Return address
wire [`WordAddrBus] br_target = if_pc + imm_s[`WORD_ADDR_MSB:0]; // Branch address
wire [`WordAddrBus] jr_target = ra_data[`WordAddrLoc]; // Jump address
/********** Forwarding **********/
always @(*) begin
$display("op=%b",op);
$display("ra_addr=%b",ra_addr);
$display("rb_addr=%b",rb_addr);
$display("rc_addr=%b",rc_addr);
/* Ra register */
if ((id_en == `ENABLE) && (id_gpr_we_ == `ENABLE_) &&
(id_dst_addr == ra_addr)) begin
ra_data = ex_fwd_data; // Forwarding from EX stage
end else if ((ex_en == `ENABLE) && (ex_gpr_we_ == `ENABLE_) &&
(ex_dst_addr == ra_addr)) begin
ra_data = mem_fwd_data; // Forwarding from MEM stage
end else begin
ra_data = gpr_rd_data_0; // Read from register file
$display("ra_data=%b",ra_data);
end
/* Rb register */
if ((id_en == `ENABLE) && (id_gpr_we_ == `ENABLE_) &&
(id_dst_addr == rb_addr)) begin
rb_data = ex_fwd_data; // Forwarding from EX stage
end else if ((ex_en == `ENABLE) && (ex_gpr_we_ == `ENABLE_) &&
(ex_dst_addr == rb_addr)) begin
rb_data = mem_fwd_data; // Forwarding from MEM stage
end else begin
rb_data = gpr_rd_data_1; // Read from register file
$display("rb_data=%b",rb_data);
end
end
/********** Load hazard detection **********/
//`define MEM_OP_LDW 2'h1 // Read word
always @(*) begin
if ((id_en == `ENABLE) && (id_mem_op == `MEM_OP_LDW) &&
((id_dst_addr == ra_addr) || (id_dst_addr == rb_addr))) begin
ld_hazard = `ENABLE; // Load hazard
end else begin
ld_hazard = `DISABLE; // No hazard
end
end
/********** Decode instruction **********/
always @(*) begin
/* Default value */
alu_op = `ALU_OP_NOP; //ALU操作
alu_in_0 = ra_data; //ALU输入0
alu_in_1 = rb_data; //ALU输入1
br_taken = `DISABLE; //分支成立
br_flag = `DISABLE; //分支标志位
br_addr = {`WORD_ADDR_W{1'b0}}; //分支地址
mem_op = `MEM_OP_NOP; //内存操作
ctrl_op = `CTRL_OP_NOP; //控制操作
dst_addr = rb_addr; //通用寄存器写入地址
gpr_we_ = `DISABLE_; //通用寄存器写入有效
exp_code = `ISA_EXP_NO_EXP; //异常代码
//`define ISA_EXP_NO_EXP 3'h0 // No exception
/*
`define ALU_OP_NOP 4'h0 // No Operation
`define ALU_OP_AND 4'h1 // AND
`define ALU_OP_OR 4'h2 // OR
`define ALU_OP_XOR 4'h3 // XOR
`define ALU_OP_ADDS 4'h4 // Signed ADD
`define ALU_OP_ADDU 4'h5 // Unsigned ADD
`define ALU_OP_SUBS 4'h6 // Signed SUB
`define ALU_OP_SUBU 4'h7 // Unsigned SUB
`define ALU_OP_SHRL 4'h8 // Shift right
`define ALU_OP_SHLL 4'h9 // Shift left
*/
/* Opcode */
if (if_en == `ENABLE) begin //流水线数据有效
case (op)
/* Logical operation 逻辑运算指令*/
`ISA_OP_ANDR : begin //寄存器间的逻辑与
alu_op = `ALU_OP_AND; //ALU操作
dst_addr = rc_addr; //通用寄存器写入地址
gpr_we_ = `ENABLE_; //通用寄存器写入有效
end
`ISA_OP_ANDI : begin //寄存器与立即数的逻辑与
alu_op = `ALU_OP_AND;
alu_in_1 = imm_u;
gpr_we_ = `ENABLE_;
end
`ISA_OP_ORR : begin //寄存器之间的逻辑或
alu_op = `ALU_OP_OR;
dst_addr = rc_addr;
gpr_we_ = `ENABLE_;
end
`ISA_OP_ORI : begin //寄存器与立即数的逻辑或
alu_op = `ALU_OP_OR;
alu_in_1 = imm_u;
gpr_we_ = `ENABLE_;
end
`ISA_OP_XORR : begin //寄存器间的逻辑异或
alu_op = `ALU_OP_XOR;
dst_addr = rc_addr;
gpr_we_ = `ENABLE_;
end
`ISA_OP_XORI : begin
alu_op = `ALU_OP_XOR; //寄存器与立即数的逻辑异或
alu_in_1 = imm_u;
gpr_we_ = `ENABLE_;
end
/* Arithmetic operation 算术运算指令*/
`ISA_OP_ADDSR : begin //寄存器间的有符号运算
alu_op = `ALU_OP_ADDS;
dst_addr = rc_addr;
gpr_we_ = `ENABLE_;
$display("alu_op=%b",alu_op);
$display("dst_addr=%b",dst_addr);
$display("gpr_we_=%b",gpr_we_);
end
`ISA_OP_ADDSI : begin //寄存器与立即数之间的有符号运算
alu_op = `ALU_OP_ADDS;
alu_in_1 = imm_s;
gpr_we_ = `ENABLE_;
end
`ISA_OP_ADDUR : begin //寄存器间的无符号运算
alu_op = `ALU_OP_ADDU;
dst_addr = rc_addr;
gpr_we_ = `ENABLE_;
end
`ISA_OP_ADDUI : begin //寄存器与立即数之间的无符号运算
alu_op = `ALU_OP_ADDU;
alu_in_1 = imm_s;
gpr_we_ = `ENABLE_;
end
`ISA_OP_SUBSR : begin //寄存器间的有符号减法
alu_op = `ALU_OP_SUBS;
dst_addr = rc_addr;
gpr_we_ = `ENABLE_;
end
`ISA_OP_SUBUR : begin //寄存器的无符号减法
alu_op = `ALU_OP_SUBU;
dst_addr = rc_addr;
gpr_we_ = `ENABLE_;
end
/* Shift 移位指令*/
`ISA_OP_SHRLR : begin //寄存器的逻辑右移
alu_op = `ALU_OP_SHRL;
dst_addr = rc_addr;
gpr_we_ = `ENABLE_;
end
`ISA_OP_SHRLI : begin //寄存器与立即数间的逻辑右移
alu_op = `ALU_OP_SHRL;
alu_in_1 = imm_u;
gpr_we_ = `ENABLE_;
end
`ISA_OP_SHLLR : begin //寄存器间的逻辑左移
alu_op = `ALU_OP_SHLL;
dst_addr = rc_addr;
gpr_we_ = `ENABLE_;
end
`ISA_OP_SHLLI : begin //寄存器与立即数间的逻辑左移
alu_op = `ALU_OP_SHLL;
alu_in_1 = imm_u;
gpr_we_ = `ENABLE_;
end
/* Branch 分支指令*/
`ISA_OP_BE : begin // Signed compare registers(Ra == Rb)
br_addr = br_target;
br_taken = (ra_data == rb_data) ? `ENABLE : `DISABLE;
br_flag = `ENABLE;
end
`ISA_OP_BNE : begin // Signed compare registers(Ra != Rb)
br_addr = br_target;
br_taken = (ra_data != rb_data) ? `ENABLE : `DISABLE;
br_flag = `ENABLE;
end
`ISA_OP_BSGT : begin // Signed compare registers(Ra < Rb)
br_addr = br_target;
br_taken = (s_ra_data < s_rb_data) ? `ENABLE : `DISABLE;
br_flag = `ENABLE;
end
`ISA_OP_BUGT : begin // Unsigned compare registers(Ra < Rb)
br_addr = br_target;
br_taken = (ra_data < rb_data) ? `ENABLE : `DISABLE;
br_flag = `ENABLE;
end
`ISA_OP_JMP : begin // Jump
br_addr = jr_target;
br_taken = `ENABLE;
br_flag = `ENABLE;
end
`ISA_OP_CALL : begin // Call
alu_in_0 = {ret_addr, {`BYTE_OFFSET_W{1'b0}}};
br_addr = jr_target;
br_taken = `ENABLE;
br_flag = `ENABLE;
dst_addr = `REG_ADDR_W'd31;//CALL指令返回地址写入31号寄存器
gpr_we_ = `ENABLE_;
end
/* Memory access 内存访问指令 */
`ISA_OP_LDW : begin // Load word字读取,从内存读取一个字数据存入寄存器中
alu_op = `ALU_OP_ADDU;
alu_in_1 = imm_s;
mem_op = `MEM_OP_LDW;
gpr_we_ = `ENABLE_;
end
`ISA_OP_STW : begin // Store word 字写入。寄存器中的一个字写入内存中
alu_op = `ALU_OP_ADDU;
alu_in_1 = imm_s;
mem_op = `MEM_OP_STW;
end
/* System call 特殊指令解码*/
`ISA_OP_TRAP : begin // Trap
exp_code = `ISA_EXP_TRAP;
end
//define ISA_EXP_TRAP 3'h5 // Trap
/* Privilege 特权指令解码 */
/*
// Opcode
`define CTRL_OP_NOP 2'h0 // No Operation
`define CTRL_OP_WRCR 2'h1 // Write to control register
`define CTRL_OP_EXRT 2'h2 // Restore from exception
*/
`ISA_OP_RDCR : begin // Read control register 读取控制寄存器
if (exe_mode == `CPU_KERNEL_MODE) begin
alu_in_0 = creg_rd_data;
gpr_we_ = `ENABLE_;
end else begin
exp_code = `ISA_EXP_PRV_VIO;
end
end
`ISA_OP_WRCR : begin // Write control register 写入控制寄存器
if (exe_mode == `CPU_KERNEL_MODE) begin
ctrl_op = `CTRL_OP_WRCR;
end else begin
exp_code = `ISA_EXP_PRV_VIO;
end
end
`ISA_OP_EXRT : begin // Restore from exception 从异常恢复
if (exe_mode == `CPU_KERNEL_MODE) begin
ctrl_op = `CTRL_OP_EXRT;
end else begin
exp_code = `ISA_EXP_PRV_VIO;
end
end
/* Other instructions 其他指令 */
default : begin // Undefined instruction 未定义指令处理
exp_code = `ISA_EXP_UNDEF_INSN;
end
endcase
end
end
endmodule
2.ID阶段流水线寄存器
主要实现将解码结果输出。
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2022/01/28 10:07:04
// Design Name:
// Module Name: id_reg
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
// ID stage pipeline register
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
/********** Global header **********/
`include "nettype.vh"
`include "global_config.vh"
`include "stddef.vh"
/********** Local header **********/
`include "isa.vh"
`include "cpu.vh"
module id_reg(
/********** Clock & Reset **********/
input wire clk,
input wire reset,
/********** Decode result **********/
input wire [`AluOpBus] alu_op, // ALU operation 位宽4位
input wire [`WordDataBus] alu_in_0, // ALU input 0 ALU输入0 位宽32
input wire [`WordDataBus] alu_in_1, // ALU input 1 ALU输入1 位宽32
input wire br_flag, // Branch flag 分支符号位
input wire [`MemOpBus] mem_op, // Memory operation 位宽2
input wire [`WordDataBus] mem_wr_data, // Data to write to memory 32
input wire [`CtrlOpBus] ctrl_op, // Control operation 2
input wire [`RegAddrBus] dst_addr, // GPR write address 5
input wire gpr_we_, // GPR register write enable
input wire [`IsaExpBus] exp_code, // Exception code 3
/********** Pipeline control signal **********/
input wire stall, // Stall
input wire flush, // Flush
/********** IF/ID pipeline register **********/
input wire [`WordAddrBus] if_pc, // Program counter
input wire if_en, // Enable pipeline data
/********** ID/EX pipeline register **********/
output reg [`WordAddrBus] id_pc, // Program counter
output reg id_en, // Enable pipeline data
output reg [`AluOpBus] id_alu_op, // ALU operation
output reg [`WordDataBus] id_alu_in_0, // ALU input 0
output reg [`WordDataBus] id_alu_in_1, // ALU input 1
output reg id_br_flag, // Branch flag
output reg [`MemOpBus] id_mem_op, // Memory operation
output reg [`WordDataBus] id_mem_wr_data, // Data to write to memory
output reg [`CtrlOpBus] id_ctrl_op, // Control operation
output reg [`RegAddrBus] id_dst_addr, // GPR write address
output reg id_gpr_we_, // GPR register write enable
output reg [`IsaExpBus] id_exp_code // Exception code
);
/********** Pipeline register **********/
always @(posedge clk or `RESET_EDGE reset) begin
if (reset == `RESET_ENABLE) begin
/* Asynchronous Reset */
id_pc <= #1 `WORD_ADDR_W'h0;
id_en <= #1 `DISABLE;
id_alu_op <= #1 `ALU_OP_NOP;
id_alu_in_0 <= #1 `WORD_DATA_W'h0;
id_alu_in_1 <= #1 `WORD_DATA_W'h0;
id_br_flag <= #1 `DISABLE;
id_mem_op <= #1 `MEM_OP_NOP;
id_mem_wr_data <= #1 `WORD_DATA_W'h0;
id_ctrl_op <= #1 `CTRL_OP_NOP;
id_dst_addr <= #1 `REG_ADDR_W'd0;
id_gpr_we_ <= #1 `DISABLE_;
id_exp_code <= #1 `ISA_EXP_NO_EXP;
end
else begin
/* Update pipeline register */
if (stall == `DISABLE) begin
if (flush == `ENABLE) begin // Flush
id_pc <= #1 `WORD_ADDR_W'h0;
id_en <= #1 `DISABLE;
id_alu_op <= #1 `ALU_OP_NOP;
id_alu_in_0 <= #1 `WORD_DATA_W'h0;
id_alu_in_1 <= #1 `WORD_DATA_W'h0;
id_br_flag <= #1 `DISABLE;
id_mem_op <= #1 `MEM_OP_NOP;
id_mem_wr_data <= #1 `WORD_DATA_W'h0;
id_ctrl_op <= #1 `CTRL_OP_NOP;
id_dst_addr <= #1 `REG_ADDR_W'd0;
id_gpr_we_ <= #1 `DISABLE_;
id_exp_code <= #1 `ISA_EXP_NO_EXP;
end else begin
id_pc <= #1 if_pc;
id_en <= #1 if_en;
id_alu_op <= #1 alu_op;
id_alu_in_0 <= #1 alu_in_0;
id_alu_in_1 <= #1 alu_in_1;
id_br_flag <= #1 br_flag;
id_mem_op <= #1 mem_op;
id_mem_wr_data <= #1 mem_wr_data;
id_ctrl_op <= #1 ctrl_op;
id_dst_addr <= #1 dst_addr;
id_gpr_we_ <= #1 gpr_we_;
id_exp_code <= #1 exp_code;
end
end
end
end
endmodule
3.top模块(连接各模块)
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2022/02/02 16:21:32
// Design Name:
// Module Name: id_stage
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
// ID stage --TOP顶层模块
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
/********** Global header **********/
`include "nettype.vh"
`include "global_config.vh"
`include "stddef.vh"
/********** Local header **********/
`include "isa.vh"
`include "cpu.vh"
module id_stage(
/********** Clock & Reset **********/
input wire clk,
input wire reset,
/********** GPR interface **********/
input wire [`WordDataBus] gpr_rd_data_0, // Read data 0
input wire [`WordDataBus] gpr_rd_data_1, // Read data 1
output wire [`RegAddrBus] gpr_rd_addr_0, // Read Address 0
output wire [`RegAddrBus] gpr_rd_addr_1, // Read Address 1
/********** Forwarding **********/
// Forwarding from EX stage
input wire ex_en, // Enable pipeline data
input wire [`WordDataBus] ex_fwd_data, // Forwarding data
input wire [`RegAddrBus] ex_dst_addr, // Write address
input wire ex_gpr_we_, // Write enable
// Forwarding from MEM stage
input wire [`WordDataBus] mem_fwd_data, // Forwarding
/********** Control register interface **********/
input wire [`CpuExeModeBus] exe_mode, // Execution mode
input wire [`WordDataBus] creg_rd_data, // Read data
output wire [`RegAddrBus] creg_rd_addr, // Read address
/********** Pipeline control signal **********/
input wire stall,
input wire flush,
output wire [`WordAddrBus] br_addr, // Branch address
output wire br_taken, // Branch taken
output wire ld_hazard, // Load hazard
/********** IF/ID pipeline register **********/
input wire [`WordAddrBus] if_pc, // Program counter
input wire [`WordDataBus] if_insn, // Instruction
input wire if_en, // Enable pipeline data
/********** ID/EX pipeline register **********/
output wire [`WordAddrBus] id_pc, // Program counter
output wire id_en, // Enable pipeline data
output wire [`AluOpBus] id_alu_op, // ALU operation
output wire [`WordDataBus] id_alu_in_0, // ALU input 0
output wire [`WordDataBus] id_alu_in_1, // ALU input 1
output wire id_br_flag, // Branch flag
output wire [`MemOpBus] id_mem_op, // Memory opeartion
output wire [`WordDataBus] id_mem_wr_data, // Data to write to memory
output wire [`CtrlOpBus] id_ctrl_op, // Control operation
output wire [`RegAddrBus] id_dst_addr, // GPR write address
output wire id_gpr_we_, // GPR write enable
output wire [`IsaExpBus] id_exp_code // Exception code
);
wire [`AluOpBus] alu_op; // ALU operation
wire [`WordDataBus] alu_in_0; // ALU input 0
wire [`WordDataBus] alu_in_1; // ALU input 1
wire br_flag; // Branch flag
wire [`MemOpBus] mem_op; // Memory operation
wire [`WordDataBus] mem_wr_data; // Data to write to memory
wire [`CtrlOpBus] ctrl_op; // Control operation
wire [`RegAddrBus] dst_addr; // GPR write address
wire gpr_we_; // GPR write enable
wire [`IsaExpBus] exp_code; // Exception code
/********** Decoder **********/
decoder decoder (
/********** IF/ID pipeline register **********/
.if_pc (if_pc), // Program counter
.if_insn (if_insn), // Instruction
.if_en (if_en), // Enable pipeline data
/********** GPR interface **********/
.gpr_rd_data_0 (gpr_rd_data_0), // Read data 0
.gpr_rd_data_1 (gpr_rd_data_1), // Read data 1
.gpr_rd_addr_0 (gpr_rd_addr_0), // Read address 0
.gpr_rd_addr_1 (gpr_rd_addr_1), // Read address 1
/********** Forwarding **********/
// Forwarding form ID stage
.id_en (id_en),
.id_dst_addr (id_dst_addr),
.id_gpr_we_ (id_gpr_we_),
.id_mem_op (id_mem_op),
// Forwarding form EX stage
.ex_en (ex_en),
.ex_fwd_data (ex_fwd_data),
.ex_dst_addr (ex_dst_addr),
.ex_gpr_we_ (ex_gpr_we_),
// Forwarding form MEM stage
.mem_fwd_data (mem_fwd_data),
/********** Control register interface **********/
.exe_mode (exe_mode),
.creg_rd_data (creg_rd_data),
.creg_rd_addr (creg_rd_addr),
/********** Decode signal **********/
.alu_op (alu_op),
.alu_in_0 (alu_in_0),
.alu_in_1 (alu_in_1),
.br_addr (br_addr),
.br_taken (br_taken),
.br_flag (br_flag),
.mem_op (mem_op),
.mem_wr_data (mem_wr_data),
.ctrl_op (ctrl_op),
.dst_addr (dst_addr),
.gpr_we_ (gpr_we_),
.exp_code (exp_code),
.ld_hazard (ld_hazard)
);
/********** Pipeline register **********/
id_reg id_reg (
/********** Clock & Reset **********/
.clk (clk),
.reset (reset),
/********** Decode result **********/
.alu_op (alu_op),
.alu_in_0 (alu_in_0),
.alu_in_1 (alu_in_1),
.br_flag (br_flag),
.mem_op (mem_op),
.mem_wr_data (mem_wr_data),
.ctrl_op (ctrl_op),
.dst_addr (dst_addr),
.gpr_we_ (gpr_we_),
.exp_code (exp_code),
/********** Pipeline control signal **********/
.stall (stall),
.flush (flush),
/********** IF/ID pipeline register **********/
.if_pc (if_pc),
.if_en (if_en),
/********** ID/EX pipeline register **********/
.id_pc (id_pc),
.id_en (id_en),
.id_alu_op (id_alu_op),
.id_alu_in_0 (id_alu_in_0),
.id_alu_in_1 (id_alu_in_1),
.id_br_flag (id_br_flag),
.id_mem_op (id_mem_op),
.id_mem_wr_data (id_mem_wr_data),
.id_ctrl_op (id_ctrl_op),
.id_dst_addr (id_dst_addr),
.id_gpr_we_ (id_gpr_we_),
.id_exp_code (id_exp_code)
);
endmodule
4.gpr寄存器
之前的实验已经构建过此模块,这边用于测试时,实现将要执行数据的取出。
模块指向下图寄存器堆,主要连接端口是指令解码器中gpr_rd_addr_0、gpr_rd_addr_1、gpr_rd_data_0、gpr_rd_data_1

代码如下:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2022/01/24 18:08:00
// Design Name:
// Module Name: gpr
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies: General purpose register (GPR)
// 通用寄存器,两个读取端口,一个写入端口
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
/********** Global header **********/
`include "nettype.vh"
`include "global_config.vh"
`include "stddef.vh"
/********** Local header **********/
`include "cpu.vh"
module gpr(
//时钟和复位
input wire clk,
input wire reset,
/********** 读端口0 **********/
input wire [`RegAddrBus] rd_addr_0, // Read address 位宽5
output wire [`WordDataBus] rd_data_0, // Read data 位宽32
/********** 读端口1 **********/
input wire [`RegAddrBus] rd_addr_1, // Read address 位宽5
output wire [`WordDataBus] rd_data_1, // Read data 位宽32
/********** 写端口 **********/
input wire we_, // Write enable 位宽1
input wire [`RegAddrBus] wr_addr, // Write address 位宽5
input wire [`WordDataBus] wr_data // Write data 位宽32
);
/********** Internal signal **********/
reg [`WordDataBus] gpr [`REG_NUM-1:0]; // Register array 32*32
integer i; //初始化用迭代器,位宽32
//读取端口0
assign rd_data_0 =((we_==`ENABLE)&&(wr_addr==rd_addr_0))?
wr_data:gpr[rd_addr_0];
//读取端口1
assign rd_data_1 =((we_==`ENABLE)&&(wr_addr==rd_addr_1))?
wr_data:gpr[rd_addr_1];
//异步复位
always @(posedge clk or `RESET_EDGE reset)
begin
if(reset==`RESET_ENABLE)
begin
for (i=0;i<`REG_NUM;i=i+1)
//`define REG_NUM 32
begin
//`define WORD_DATA_W 32
gpr[i] <= #1 `WORD_DATA_W'h0;
end
end
else
begin
if(we_==`ENABLE_)
begin
gpr[wr_addr]<= #1 wr_data;
$display("写入gpr");
$display("gpr[%b]=%b",wr_addr,wr_data);
end
end
end
endmodule
5.测试模块(testbench)
测试思路:
在从IF/ID寄存器中拿到对应的指令,对指令进行处理,实现译码操作。
这边指令使用ADDSR寄存器间的有符号运算进行测试
将gpr【0】作为 alu0(即ra)
将gpr【1】作为 alu1(即rb)
将gpr【2】作为 dst_addr(即rc)

1.先将gpr中对应的位置写入数据
2.输入IF/ID寄存器的if_insn 指令
3.运算数据地址指向gpr中,gpr将发送对应数据
4.得到的数据发送到decoder中,进行解码操作
5.解码结果将放入ID/EX寄存器中,进行输出。
代码如下:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2022/02/09 11:18:15
// Design Name:
// Module Name: id_test
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
/********** Global header **********/
`include "nettype.vh"
`include "global_config.vh"
`include "stddef.vh"
/********** Local header **********/
`include "isa.vh"
`include "cpu.vh"
module id_test(
);
//端口定义
/********** Clock & Reset **********/
reg clk;
reg reset;
/********** GPR interface **********/
wire [`WordDataBus] gpr_rd_data_0; // Read data 0
wire [`WordDataBus] gpr_rd_data_1; // Read data 1
wire [`RegAddrBus] gpr_rd_addr_0; // Read Address 0
wire [`RegAddrBus] gpr_rd_addr_1; // Read Address 1
reg we_; // Write enable 位宽1
reg [`RegAddrBus] wr_addr; // Write address 位宽5
reg [`WordDataBus] wr_data; // Write data 位宽32
/********** Forwarding **********/
// Forwarding from EX stage
reg ex_en; // Enable pipeline data
reg [`WordDataBus] ex_fwd_data; // Forwarding data
reg [`RegAddrBus] ex_dst_addr; // Write address
reg ex_gpr_we_; // Write enable
// Forwarding from MEM stage
reg [`WordDataBus] mem_fwd_data; // Forwarding
/********** Control register interface **********/
reg [`CpuExeModeBus] exe_mode; // Execution mode
reg [`WordDataBus] creg_rd_data; // Read data
wire [`RegAddrBus] creg_rd_addr; // Read address
/********** Pipeline control signal **********/
reg stall;
reg flush;
wire [`WordAddrBus] br_addr; // Branch address
wire br_taken; // Branch taken
wire ld_hazard; // Load hazard
/********** IF/ID pipeline register **********/
reg [`WordAddrBus] if_pc; // Program counter
reg [`WordDataBus] if_insn; // Instruction
reg if_en; // Enable pipeline data
/********** ID/EX pipeline register **********/
wire [`WordAddrBus] id_pc; // Program counter
wire id_en; // Enable pipeline data
wire [`AluOpBus] id_alu_op; // ALU operation
wire [`WordDataBus] id_alu_in_0; // ALU reg 0
wire [`WordDataBus] id_alu_in_1; // ALU reg 1
wire id_br_flag; // Branch flag
wire [`MemOpBus] id_mem_op; // Memory opeartion
wire [`WordDataBus] id_mem_wr_data; // Data to write to memory
wire [`CtrlOpBus] id_ctrl_op; // Control operation
wire [`RegAddrBus] id_dst_addr; // GPR write address
wire id_gpr_we_; // GPR write enable
wire [`IsaExpBus] id_exp_code; // Exception code
wire [`AluOpBus] alu_op; // ALU operation
wire [`WordDataBus] alu_in_0; // ALU input 0
wire [`WordDataBus] alu_in_1; // ALU input 1
wire br_flag; // Branch flag
wire [`MemOpBus] mem_op; // Memory operation
wire [`WordDataBus] mem_wr_data; // Data to write to memory
wire [`CtrlOpBus] ctrl_op; // Control operation
wire [`RegAddrBus] dst_addr; // GPR write address
wire gpr_we_; // GPR write enable
wire [`IsaExpBus] exp_code; // Exception code
integer i;
parameter STEP=100;
always#(STEP/2)begin
clk<=~clk;
end
//实例化
/********** Decoder **********/
decoder decoder (
/********** IF/ID pipeline register **********/
.if_pc (if_pc), // Program counter
.if_insn (if_insn), // Instruction
.if_en (if_en), // Enable pipeline data
/********** GPR interface **********/
.gpr_rd_data_0 (gpr_rd_data_0), // Read data 0
.gpr_rd_data_1 (gpr_rd_data_1), // Read data 1
.gpr_rd_addr_0 (gpr_rd_addr_0), // Read address 0
.gpr_rd_addr_1 (gpr_rd_addr_1), // Read address 1
/********** Forwarding **********/
// Forwarding form ID stage
.id_en (id_en),
.id_dst_addr (id_dst_addr),
.id_gpr_we_ (id_gpr_we_),
.id_mem_op (id_mem_op),
// Forwarding form EX stage
.ex_en (ex_en),
.ex_fwd_data (ex_fwd_data),
.ex_dst_addr (ex_dst_addr),
.ex_gpr_we_ (ex_gpr_we_),
// Forwarding form MEM stage
.mem_fwd_data (mem_fwd_data),
/********** Control register interface **********/
.exe_mode (exe_mode),
.creg_rd_data (creg_rd_data),
.creg_rd_addr (creg_rd_addr),
/********** Decode signal **********/
.alu_op (alu_op),
.alu_in_0 (alu_in_0),
.alu_in_1 (alu_in_1),
.br_addr (br_addr),
.br_taken (br_taken),
.br_flag (br_flag),
.mem_op (mem_op),
.mem_wr_data (mem_wr_data),
.ctrl_op (ctrl_op),
.dst_addr (dst_addr),
.gpr_we_ (gpr_we_),
.exp_code (exp_code),
.ld_hazard (ld_hazard)
);
/********** Pipeline register **********/
id_reg id_reg (
/********** Clock & Reset **********/
.clk (clk),
.reset (reset),
/********** Decode result **********/
.alu_op (alu_op),
.alu_in_0 (alu_in_0),
.alu_in_1 (alu_in_1),
.br_flag (br_flag),
.mem_op (mem_op),
.mem_wr_data (mem_wr_data),
.ctrl_op (ctrl_op),
.dst_addr (dst_addr),
.gpr_we_ (gpr_we_),
.exp_code (exp_code),
/********** Pipeline control signal **********/
.stall (stall),
.flush (flush),
/********** IF/ID pipeline register **********/
.if_pc (if_pc),
.if_en (if_en),
/********** ID/EX pipeline register **********/
.id_pc (id_pc),
.id_en (id_en),
.id_alu_op (id_alu_op),
.id_alu_in_0 (id_alu_in_0),
.id_alu_in_1 (id_alu_in_1),
.id_br_flag (id_br_flag),
.id_mem_op (id_mem_op),
.id_mem_wr_data (id_mem_wr_data),
.id_ctrl_op (id_ctrl_op),
.id_dst_addr (id_dst_addr),
.id_gpr_we_ (id_gpr_we_),
.id_exp_code (id_exp_code)
);
/*****gpr实例化***************/
gpr gpr(
.clk(clk),
.reset(reset),
.rd_addr_0(gpr_rd_addr_0),
.rd_addr_1(gpr_rd_addr_1),
.rd_data_0(gpr_rd_data_0),
.rd_data_1(gpr_rd_data_1),
.we_(we_),
.wr_addr( wr_addr),
.wr_data( wr_data)
);
//测试
assign id_en=`ENABLE_;
initial begin
#10 begin
clk<=1;
reset<=`RESET_ENABLE;
end
#(STEP*3/4)
#STEP begin
reset<=`RESET_DISABLE;
#STEP
we_<=`ENABLE_;
wr_addr<=5'b00000;
wr_data<=32'd10;
#STEP
we_<=`ENABLE_;
wr_addr<=5'b00001;
wr_data<=32'd20;
#STEP
we_<=`DISABLE_;
if_en<=`ENABLE;
if_insn<={{`ISA_OP_ADDSR},{5'b00000},{5'b00001},{5'b00010},{11{1'b0}}};
#STEP
stall <= `DISABLE;
end
#STEP
$finish;
end
endmodule
测试结果:
1.数据10写入gpr【0】


2.数据20写入gpr【1】


3.输入if指令if_insn<={{`ISA_OP_ADDSR},{5’b00000},{5’b00001},{5’b00010},{11{1’b0}}};
进行解码:
指令为ADDSR,
ra地址为0,对应gpr【0】。
rb地址为1,对应gpr【1】。
rc地址为2.对应gpr【2】。
将ra数据加上rb数据,结果存入rc中
这边定义了alu中指令编号为4(即0100):
`define ALU_OP_ADDS 4'h4 // Signed ADD

4.将对应的解码结果输入到ID/EX寄存器中,并且output
仿真结束。

2184

被折叠的 条评论
为什么被折叠?



