实验3:CUP的译码ID阶段实现
ID阶段(Instruction Decode)
ID阶段对指令进行解码并生成必要的信号。数据的直通、Load冒险的检测,分支的判定都在这个阶段进行
各模块和端口定义:
1.指令解码器 decoder:/********** IF/ID pipeline register **********/input wire [`WordAddrBus] if_pc, // Program counterinput wire [`WordDataBus] if_insn, // Instructioninput wire if_en, // Enable pipeline data/********** GPR interface **********/input wire [`WordDataBus] gpr_rd_data_0, // Read data 0input wire [`WordDataBus] gpr_rd_data_1, // Read data 1output wire [`RegAddrBus] gpr_rd_addr_0, // Read address 0output wire [`RegAddrBus] gpr_rd_addr_1, // Read address 1/********** Forwarding **********/// Forwarding form ID stageinput wire id_en, // Enable pipeline datainput wire [`RegAddrBus] id_dst_addr, // Write addressinput wire id_gpr_we_, // Write enableinput wire [`MemOpBus] id_mem_op, // Memory operation// Forwarding form EX stageinput wire ex_en, // Enable pipeline datainput wire [`RegAddrBus] ex_dst_addr, // Write addressinput wire ex_gpr_we_, // Write enableinput wire [`WordDataBus] ex_fwd_data, // Forwarding data// Forwarding form MEM stageinput wire [`WordDataBus] mem_fwd_data, // Forwarding data/********** Control register interface **********/input wire [`CpuExeModeBus] exe_mode, // Execution modeinput wire [`WordDataBus] creg_rd_data, // Read dataoutput wire [`RegAddrBus] creg_rd_addr, // Read address/********** Decode result **********/output reg [`AluOpBus] alu_op, // ALU operationoutput reg [`WordDataBus] alu_in_0, // ALU input 0output reg [`WordDataBus] alu_in_1, // ALU input 1output reg [`WordAddrBus] br_addr, // Branch addressoutput reg br_taken, // Branch takenoutput reg br_flag, // Brach flagoutput reg [`MemOpBus] mem_op, // Memory operationoutput wire [`WordDataBus] mem_wr_data, // Data to write to memoryoutput reg [`CtrlOpBus] ctrl_op, // Control operationoutput reg [`RegAddrBus] dst_addr, // GPR write addressoutput reg gpr_we_, // GPR write enableoutput reg [`IsaExpBus] exp_code, // Exception codeoutput reg ld_hazard // Load hazard2.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 位宽32input wire [`WordDataBus] alu_in_1, // ALU input 1 ALU输入1 位宽32input wire br_flag, // Branch flag 分支符号位input wire [`MemOpBus] mem_op, // Memory operation 位宽2input wire [`WordDataBus] mem_wr_data, // Data to write to memory 32input wire [`CtrlOpBus] ctrl_op, // Control operation 2 input wire [`RegAddrBus] dst_addr, // GPR write address 5input wire gpr_we_, // GPR register write enable input wire [`IsaExpBus] exp_code, // Exception code 3/********** Pipeline control signal **********/input wire stall, // Stallinput wire flush, // Flush/********** IF/ID pipeline register **********/input wire [`WordAddrBus] if_pc, // Program counterinput wire if_en, // Enable pipeline data/********** ID/EX pipeline register **********/output reg [`WordAddrBus] id_pc, // Program counteroutput reg id_en, // Enable pipeline dataoutput reg [`AluOpBus] id_alu_op, // ALU operationoutput reg [`WordDataBus] id_alu_in_0, // ALU input 0output reg [`WordDataBus] id_alu_in_1, // ALU input 1output reg id_br_flag, // Branch flagoutput reg [`MemOpBus] id_mem_op, // Memory operationoutput reg [`WordDataBus] id_mem_wr_data, // Data to write to memoryoutput reg [`CtrlOpBus] id_ctrl_op, // Control operationoutput reg [`RegAddrBus] id_dst_addr, // GPR write addressoutput reg id_gpr_we_, // GPR register write enableoutput reg [`IsaExpBus] id_exp_code // Exception code3.top模块id_stage:/********** Clock & Reset **********/input wire clk,input wire reset,/********** GPR interface **********/input wire [`WordDataBus] gpr_rd_data_0, // Read data 0input wire [`WordDataBus] gpr_rd_data_1, // Read data 1output wire [`RegAddrBus] gpr_rd_addr_0, // Read Address 0output wire [`RegAddrBus] gpr_rd_addr_1, // Read Address 1/********** Forwarding **********/// Forwarding from EX stageinput wire ex_en, // Enable pipeline datainput wire [`WordDataBus] ex_fwd_data, // Forwarding datainput wire [`RegAddrBus] ex_dst_addr, // Write addressinput wire ex_gpr_we_, // Write enable// Forwarding from MEM stageinput wire [`WordDataBus] mem_fwd_data, // Forwarding/********** Control register interface **********/input wire [`CpuExeModeBus] exe_mode, // Execution modeinput wire [`WordDataBus] creg_rd_data, // Read dataoutput wire [`RegAddrBus] creg_rd_addr, // Read address/********** Pipeline control signal **********/input wire stall, input wire flush, output wire [`WordAddrBus] br_addr, // Branch addressoutput wire br_taken, // Branch takenoutput wire ld_hazard, // Load hazard/********** IF/ID pipeline register **********/input wire [`WordAddrBus] if_pc, // Program counterinput wire [`WordDataBus] if_insn, // Instructioninput wire if_en, // Enable pipeline data/********** ID/EX pipeline register **********/output wire [`WordAddrBus] id_pc, // Program counteroutput wire id_en, // Enable pipeline dataoutput wire [`AluOpBus] id_alu_op, // ALU operationoutput wire [`WordDataBus] id_alu_in_0, // ALU input 0output wire [`WordDataBus] id_alu_in_1, // ALU input 1output wire id_br_flag, // Branch flagoutput wire [`MemOpBus] id_mem_op, // Memory opeartionoutput wire [`WordDataBus] id_mem_wr_data, // Data to write to memoryoutput wire [`CtrlOpBus] id_ctrl_op, // Control operationoutput wire [`RegAddrBus] id_dst_addr, // GPR write addressoutput wire id_gpr_we_, // GPR write enableoutput wire [`IsaExpBus] id_exp_code // Exception code4.gpr://时钟和复位input wire clk,input wire reset,/********** 读端口0 **********/input wire [`RegAddrBus] rd_addr_0, // Read address 位宽5output wire [`WordDataBus] rd_data_0, // Read data 位宽32/********** 读端口1 **********/input wire [`RegAddrBus] rd_addr_1, // Read address 位宽5output wire [`WordDataBus] rd_data_1, // Read data 位宽32/********** 写端口 **********/input wire we_, // Write enable 位宽1input wire [`RegAddrBus] wr_addr, // Write address 位宽5input 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 counterinput wire [`WordDataBus] if_insn, // Instructioninput wire if_en, // Enable pipeline data/********** GPR interface **********/input wire [`WordDataBus] gpr_rd_data_0, // Read data 0input wire [`WordDataBus] gpr_rd_data_1, // Read data 1output wire [`RegAddrBus] gpr_rd_addr_0, // Read address 0output wire [`RegAddrBus] gpr_rd_addr_1, // Read address 1/********** Forwarding **********/// Forwarding form ID stageinput wire id_en, // Enable pipeline datainput wire [`RegAddrBus] id_dst_addr, // Write addressinput wire id_gpr_we_, // Write enableinput wire [`MemOpBus] id_mem_op, // Memory operation// Forwarding form EX stageinput wire ex_en, // Enable pipeline datainput wire [`RegAddrBus] ex_dst_addr, // Write addressinput wire ex_gpr_we_, // Write enableinput wire [`WordDataBus] ex_fwd_data, // Forwarding data// Forwarding form MEM stageinput wire [`WordDataBus] mem_fwd_data, // Forwarding data/********** Control register interface **********/input wire [`CpuExeModeBus] exe_mode, // Execution modeinput wire [`WordDataBus] creg_rd_data, // Read dataoutput wire [`RegAddrBus] creg_rd_addr, // Read address/********** Decode result **********/output reg [`AluOpBus] alu_op, // ALU operationoutput reg [`WordDataBus] alu_in_0, // ALU input 0output reg [`WordDataBus] alu_in_1, // ALU input 1output reg [`WordAddrBus] br_addr, // Branch addressoutput reg br_taken, // Branch takenoutput reg br_flag, // Brach flagoutput reg [`MemOpBus] mem_op, // Memory operationoutput wire [`WordDataBus] mem_wr_data, // Data to write to memoryoutput reg [`CtrlOpBus] ctrl_op, // Control operationoutput reg [`RegAddrBus] dst_addr, // GPR write addressoutput reg gpr_we_, // GPR write enableoutput reg [`IsaExpBus] exp_code, // Exception codeoutput reg ld_hazard // Load hazard);/********** Instruction field **********/// `define IsaOpLoc 31:26 // Opcode location//`define IsaOpBus 5:0 // Opcode buswire [`IsaOpBus] op = if_insn[`IsaOpLoc]; // Opcode 指令前六位取出//`define IsaRaAddrLoc 25:21// Register Ra location//`define IsaRegAddrBus 4:0 // Register address buswire [`RegAddrBus] ra_addr = if_insn[`IsaRaAddrLoc]; // Ra address//$display("ra_addr=%b",ra_addr);//`define IsaRbAddrLoc 20:16 // Register Rb locationwire [`RegAddrBus] rb_addr = if_insn[`IsaRbAddrLoc]; // Rb address//`define IsaRcAddrLoc 15:11 // Register Rc locationwire [`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 16wire [`WordDataBus] imm_s = {{`ISA_EXT_W{imm[`ISA_IMM_MSB]}}, imm}; //16位立即数扩展到32位// Zero extensionwire [`WordDataBus] imm_u = {{`ISA_EXT_W{1'b0}}, imm};/********** Register read address **********/assign gpr_rd_addr_0 = ra_addr; // GPR read address 0assign gpr_rd_addr_1 = rb_addr; // GPR read address 1assign creg_rd_addr = ra_addr; // Control register read address/********** Control register read data **********///`define WordDataBus 31:0 // Data busreg [`WordDataBus] ra_data; // Unsigned Rawire signed [`WordDataBus] s_ra_data = $signed(ra_data); // Signed Rareg [`WordDataBus] rb_data; // Unsigned Rbwire signed [`WordDataBus] s_rb_data = $signed(rb_data); // Signed Rbassign 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 addresswire [`WordAddrBus] br_target = if_pc + imm_s[`WORD_ADDR_MSB:0]; // Branch addresswire [`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)) beginra_data = ex_fwd_data; // Forwarding from EX stageend else if ((ex_en == `ENABLE) && (ex_gpr_we_ == `ENABLE_) && (ex_dst_addr == ra_addr)) beginra_data = mem_fwd_data; // Forwarding from MEM stageend else beginra_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)) beginrb_data = ex_fwd_data; // Forwarding from EX stageend else if ((ex_en == `ENABLE) && (ex_gpr_we_ == `ENABLE_) && (ex_dst_addr == rb_addr)) beginrb_data = mem_fwd_data; // Forwarding from MEM stageend else beginrb_data = gpr_rd_data_1; // Read from register file$display("rb_data=%b",rb_data);endend /********** Load hazard detection **********///`define MEM_OP_LDW 2'h1 // Read wordalways @(*) beginif ((id_en == `ENABLE) && (id_mem_op == `MEM_OP_LDW) &&((id_dst_addr == ra_addr) || (id_dst_addr == rb_addr))) beginld_hazard = `ENABLE; // Load hazardend else beginld_hazard = `DISABLE; // No hazardendend/********** Decode instruction **********/always @(*) begin/* Default value */alu_op = `ALU_OP_NOP; //ALU操作alu_in_0 = ra_data; //ALU输入0alu_in_1 = rb_data; //ALU输入1br_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 // Jumpbr_addr = jr_target;br_taken = `ENABLE;br_flag = `ENABLE;end`ISA_OP_CALL : begin // Callalu_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 // Trapexp_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) beginalu_in_0 = creg_rd_data;gpr_we_ = `ENABLE_;end else beginexp_code = `ISA_EXP_PRV_VIO;endend`ISA_OP_WRCR : begin // Write control register 写入控制寄存器if (exe_mode == `CPU_KERNEL_MODE) begin ctrl_op = `CTRL_OP_WRCR;end else beginexp_code = `ISA_EXP_PRV_VIO;endend`ISA_OP_EXRT : begin // Restore from exception 从异常恢复if (exe_mode == `CPU_KERNEL_MODE) beginctrl_op = `CTRL_OP_EXRT;end else beginexp_code = `ISA_EXP_PRV_VIO;endend/* Other instructions 其他指令 */default : begin // Undefined instruction 未定义指令处理exp_code = `ISA_EXP_UNDEF_INSN;endendcaseendendendmodule
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 位宽32input wire [`WordDataBus] alu_in_1, // ALU input 1 ALU输入1 位宽32input wire br_flag, // Branch flag 分支符号位input wire [`MemOpBus] mem_op, // Memory operation 位宽2input wire [`WordDataBus] mem_wr_data, // Data to write to memory 32input wire [`CtrlOpBus] ctrl_op, // Control operation 2 input wire [`RegAddrBus] dst_addr, // GPR write address 5input wire gpr_we_, // GPR register write enable input wire [`IsaExpBus] exp_code, // Exception code 3/********** Pipeline control signal **********/input wire stall, // Stallinput wire flush, // Flush/********** IF/ID pipeline register **********/input wire [`WordAddrBus] if_pc, // Program counterinput wire if_en, // Enable pipeline data/********** ID/EX pipeline register **********/output reg [`WordAddrBus] id_pc, // Program counteroutput reg id_en, // Enable pipeline dataoutput reg [`AluOpBus] id_alu_op, // ALU operationoutput reg [`WordDataBus] id_alu_in_0, // ALU input 0output reg [`WordDataBus] id_alu_in_1, // ALU input 1output reg id_br_flag, // Branch flagoutput reg [`MemOpBus] id_mem_op, // Memory operationoutput reg [`WordDataBus] id_mem_wr_data, // Data to write to memoryoutput reg [`CtrlOpBus] id_ctrl_op, // Control operationoutput reg [`RegAddrBus] id_dst_addr, // GPR write addressoutput reg id_gpr_we_, // GPR register write enableoutput reg [`IsaExpBus] id_exp_code // Exception code);/********** Pipeline register **********/always @(posedge clk or `RESET_EDGE reset) beginif (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;endelse begin/* Update pipeline register */if (stall == `DISABLE) begin if (flush == `ENABLE) begin // Flushid_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 endend
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 0input wire [`WordDataBus] gpr_rd_data_1, // Read data 1output wire [`RegAddrBus] gpr_rd_addr_0, // Read Address 0output wire [`RegAddrBus] gpr_rd_addr_1, // Read Address 1/********** Forwarding **********/// Forwarding from EX stageinput wire ex_en, // Enable pipeline datainput wire [`WordDataBus] ex_fwd_data, // Forwarding datainput wire [`RegAddrBus] ex_dst_addr, // Write addressinput wire ex_gpr_we_, // Write enable// Forwarding from MEM stageinput wire [`WordDataBus] mem_fwd_data, // Forwarding/********** Control register interface **********/input wire [`CpuExeModeBus] exe_mode, // Execution modeinput wire [`WordDataBus] creg_rd_data, // Read dataoutput wire [`RegAddrBus] creg_rd_addr, // Read address/********** Pipeline control signal **********/input wire stall, input wire flush, output wire [`WordAddrBus] br_addr, // Branch addressoutput wire br_taken, // Branch takenoutput wire ld_hazard, // Load hazard/********** IF/ID pipeline register **********/input wire [`WordAddrBus] if_pc, // Program counterinput wire [`WordDataBus] if_insn, // Instructioninput wire if_en, // Enable pipeline data/********** ID/EX pipeline register **********/output wire [`WordAddrBus] id_pc, // Program counteroutput wire id_en, // Enable pipeline dataoutput wire [`AluOpBus] id_alu_op, // ALU operationoutput wire [`WordDataBus] id_alu_in_0, // ALU input 0output wire [`WordDataBus] id_alu_in_1, // ALU input 1output wire id_br_flag, // Branch flagoutput wire [`MemOpBus] id_mem_op, // Memory opeartionoutput wire [`WordDataBus] id_mem_wr_data, // Data to write to memoryoutput wire [`CtrlOpBus] id_ctrl_op, // Control operationoutput wire [`RegAddrBus] id_dst_addr, // GPR write addressoutput wire id_gpr_we_, // GPR write enableoutput wire [`IsaExpBus] id_exp_code // Exception code);wire [`AluOpBus] alu_op; // ALU operationwire [`WordDataBus] alu_in_0; // ALU input 0wire [`WordDataBus] alu_in_1; // ALU input 1wire br_flag; // Branch flagwire [`MemOpBus] mem_op; // Memory operationwire [`WordDataBus] mem_wr_data; // Data to write to memorywire [`CtrlOpBus] ctrl_op; // Control operationwire [`RegAddrBus] dst_addr; // GPR write addresswire gpr_we_; // GPR write enablewire [`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 位宽5output wire [`WordDataBus] rd_data_0, // Read data 位宽32/********** 读端口1 **********/input wire [`RegAddrBus] rd_addr_1, // Read address 位宽5output wire [`WordDataBus] rd_data_1, // Read data 位宽32/********** 写端口 **********/input wire we_, // Write enable 位宽1input wire [`RegAddrBus] wr_addr, // Write address 位宽5input wire [`WordDataBus] wr_data // Write data 位宽32);/********** Internal signal **********/reg [`WordDataBus] gpr [`REG_NUM-1:0]; // Register array 32*32integer i; //初始化用迭代器,位宽32//读取端口0assign rd_data_0 =((we_==`ENABLE)&&(wr_addr==rd_addr_0))?wr_data:gpr[rd_addr_0];//读取端口1assign rd_data_1 =((we_==`ENABLE)&&(wr_addr==rd_addr_1))?wr_data:gpr[rd_addr_1]; //异步复位always @(posedge clk or `RESET_EDGE reset)beginif(reset==`RESET_ENABLE)beginfor (i=0;i<`REG_NUM;i=i+1)//`define REG_NUM 32begin//`define WORD_DATA_W 32gpr[i] <= #1 `WORD_DATA_W'h0;endendelsebeginif(we_==`ENABLE_)begingpr[wr_addr]<= #1 wr_data;$display("写入gpr");$display("gpr[%b]=%b",wr_addr,wr_data);endend 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 0wire [`WordDataBus] gpr_rd_data_1; // Read data 1wire [`RegAddrBus] gpr_rd_addr_0; // Read Address 0wire [`RegAddrBus] gpr_rd_addr_1; // Read Address 1reg we_; // Write enable 位宽1reg [`RegAddrBus] wr_addr; // Write address 位宽5reg [`WordDataBus] wr_data; // Write data 位宽32/********** Forwarding **********/// Forwarding from EX stagereg ex_en; // Enable pipeline datareg [`WordDataBus] ex_fwd_data; // Forwarding datareg [`RegAddrBus] ex_dst_addr; // Write addressreg ex_gpr_we_; // Write enable// Forwarding from MEM stagereg [`WordDataBus] mem_fwd_data; // Forwarding/********** Control register interface **********/reg [`CpuExeModeBus] exe_mode; // Execution modereg [`WordDataBus] creg_rd_data; // Read datawire [`RegAddrBus] creg_rd_addr; // Read address/********** Pipeline control signal **********/reg stall; reg flush; wire [`WordAddrBus] br_addr; // Branch addresswire br_taken; // Branch takenwire ld_hazard; // Load hazard/********** IF/ID pipeline register **********/reg [`WordAddrBus] if_pc; // Program counterreg [`WordDataBus] if_insn; // Instructionreg if_en; // Enable pipeline data/********** ID/EX pipeline register **********/wire [`WordAddrBus] id_pc; // Program counterwire id_en; // Enable pipeline datawire [`AluOpBus] id_alu_op; // ALU operationwire [`WordDataBus] id_alu_in_0; // ALU reg 0wire [`WordDataBus] id_alu_in_1; // ALU reg 1wire id_br_flag; // Branch flagwire [`MemOpBus] id_mem_op; // Memory opeartionwire [`WordDataBus] id_mem_wr_data; // Data to write to memorywire [`CtrlOpBus] id_ctrl_op; // Control operationwire [`RegAddrBus] id_dst_addr; // GPR write addresswire id_gpr_we_; // GPR write enablewire [`IsaExpBus] id_exp_code; // Exception codewire [`AluOpBus] alu_op; // ALU operationwire [`WordDataBus] alu_in_0; // ALU input 0wire [`WordDataBus] alu_in_1; // ALU input 1wire br_flag; // Branch flagwire [`MemOpBus] mem_op; // Memory operationwire [`WordDataBus] mem_wr_data; // Data to write to memorywire [`CtrlOpBus] ctrl_op; // Control operationwire [`RegAddrBus] dst_addr; // GPR write addresswire gpr_we_; // GPR write enablewire [`IsaExpBus] exp_code; // Exception codeinteger i;parameter STEP=100;always#(STEP/2)beginclk<=~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 beginclk<=1;reset<=`RESET_ENABLE;end#(STEP*3/4)#STEP beginreset<=`RESET_DISABLE;#STEPwe_<=`ENABLE_;wr_addr<=5'b00000;wr_data<=32'd10;#STEPwe_<=`ENABLE_;wr_addr<=5'b00001;wr_data<=32'd20;#STEPwe_<=`DISABLE_;if_en<=`ENABLE;if_insn<={{`ISA_OP_ADDSR},{5'b00000},{5'b00001},{5'b00010},{11{1'b0}}};#STEPstall <= `DISABLE;end#STEP$finish;endendmodule
测试结果:
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
仿真结束。
实验3:CUP的译码ID阶段实现相关推荐
- 微型计算机系统实验总结(学习性实验:IO地址译码,可编程并行接口8255,交通灯控制实验 + 自主设计实验:汽车信号灯控制系统,电风扇控制器,洗衣机控制系统,霓虹灯,电梯控制系统)
实验配套软件: https://download.csdn.net/download/qq_39932172/11221584 实验指导用书: 教师版: https://download.csdn.n ...
- CUMT矿大----电路与数字系统实验四 计数、译码、显示的HDL设计
软件:Quartus II 9.0 (64-Bit) AHDL语言 看完觉得不错的点个赞呗╰(*°▽°*)╯不要白嫖啊 一.60进制计数器(静态显示) 分频模块(输入时钟40MHZ) subde ...
- 计算机体系结构-体系结构基础与流水线原理
计算机体系结构:体系结构基础与流水线原理 计算机体系结构:量化设计与分析一书以RISC-V为例介绍计算机体系结构.介绍体系结构的基本知识和流水线原理.笔记内容为原书的第一章,附录A.B.C. 第一章 ...
- 实验6:CUP的控制模块实现CPU全部模块连接
1.CPU控制模块 cpu控制模块进行对保存CPU状态的控制寄存器进行管理,并且对流水线进行控制 cpu控制模块中设有设置和保存CPU状态的控制寄存器 主要处理流水线刷新延迟.程序中断等异常. 这一模 ...
- 计算机组成原理 控制冒险,电子科大-系统结构实验-解决控制冒险.docx
电子科大-系统结构实验-解决控制冒险 实验报告课程名称:计算机系统结构实验学 院:计算机科学与工程学院专 业:计算机科学与技术指导教师:好老师学生姓名:爱学习的大哥哥2014666666666实验成绩 ...
- 【中山大学计算机组成原理实验】单周期CPU设计与实现
实验一 : 单周期CPU设计与实现 一. 实验目的 (1) 掌握单周期CPU数据通路图的构成.原理及其设计方法: (2) 掌握单周期CPU的实现方法,代码实现方法: (3) 认识和掌握指令与CPU的关 ...
- 计算机组成原理实验2---单周期CPU
实验目的 实验内容 设计一个单周期CPU,该CPU至少能实现以下指令功能操作. 必须写一段测试用的汇编程序,而且必须包含所要求的所有指令,slti指令必须检查两种情况:"小于"和& ...
- 计算机组成原理实验单周期处理,计算机组成原理实验实验报告-单周期cpu设计...
计算机组成原理实验实验报告-单周期cpu设计 (16页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 19.90 积分 计算机组成原理实验计算机组成原理实验 ...
- [省级大创项目]教育类APP的探索和实践——大学物理实验助手APP开发
立项依据(项目背景及研究现状500字以内) 通过网上问卷等形式做了前期调研,网上问卷由问卷星提供技术支持,共有348份答卷,问卷链接为很抱歉,此问卷(12931895)已暂停,不能填写!. (1)通过 ...
最新文章
- 正则式高人谈解答正则式的心得
- How to change the status of Prepayment invoice
- maven 版本号插件_测试Maven版本插件自动递增版本号
- mysql和web文件夹_Linux使用记录---自动备份MySQL和web文件夹到windows共享路径
- 阿里云再发两款混合云一体机 ,企业全面上云就像上车一样简单
- npm ERR! Please try running this command again as root/Administrator.
- I2C总线串行串行输入输出结构
- 当浙江“十万企业上云“遇见中国软件生态大会
- Tensor Flow量化里representative_dataset参数是什么意思?
- 萌新学习笔记之线性表
- Ubuntu 15.04 或更新版 更新源/Ubuntu 15.04 Vivid Vervet更新源已可用
- 用 python 写了一个随机任务抽取器
- 2020年专业408的算法题
- uc缓存分段视频合并
- 逻辑思维训练题:切西瓜之一共切10刀,最多能将西瓜切成多少块?
- 珠海网站建设需要多少钱?
- 详谈ByteArrayOutputStream的用法
- Whitelabel Error Page 的原因
- 「Hudi系列」Hudi查询写入常见问题汇总
- MSC Marc英文界面汉化