1.CPU控制模块
cpu控制模块进行对保存CPU状态的控制寄存器进行管理,并且对流水线进行控制
cpu控制模块中设有设置和保存CPU状态的控制寄存器
主要处理流水线刷新延迟、程序中断等异常。
这一模块涉及中断处理、流水线刷新延迟,知识点较杂乱,需要配合相关资料进一步研究。
端口定义:
part8.CPU控制模块
cpu控制模块进行对保存CPU状态的控制寄存器进行管理,并且对流水线进行控制
cpu控制模块中设有设置和保存CPU状态的控制寄存器
ctrl:
/********** Clock & Reset **********/
input wire clk,
input wire reset,
/********** Control register interface **********/
input wire [`RegAddrBus] creg_rd_addr, // Read address
output reg [`WordDataBus] creg_rd_data, // Read data
output reg [`CpuExeModeBus] exe_mode, // Execution mode
/********** Interrupt **********/
input wire [`CPU_IRQ_CH-1:0] irq, // Interrupt request
output reg int_detect, // Interrupt detection
/********** ID/EX pipeline register **********/
input wire [`WordAddrBus] id_pc, // Program counter
/********** MEM/WB pipeline register **********/
input wire [`WordAddrBus] mem_pc, // Program counter
input wire mem_en, // Enable pipeline data
input wire mem_br_flag, // Branch flag
input wire [`CtrlOpBus] mem_ctrl_op, // Control register operation
input wire [`RegAddrBus] mem_dst_addr, // Write address
input wire [`IsaExpBus] mem_exp_code, // Exception code
input wire [`WordDataBus] mem_out, // Processing result
/********** Pipeline control signal **********/
// Pipeline status
input wire if_busy, // IF stage busy
input wire ld_hazard, // Load hazard
input wire mem_busy, // MEM stage busy
// Stall signal
output wire if_stall, // IF stage stall
output wire id_stall, // ID stage stall
output wire ex_stall, // EX stage stall
output wire mem_stall, // MEM stage stall
// Flush signal
output wire if_flush, // IF stage flush
output wire id_flush, // ID stage flush
output wire ex_flush, // EX stage flush
output wire mem_flush, // MEM stage flush
output reg [`WordAddrBus] new_pc // New program counter
cpu整体连接:
cpu:
/********** Clock & Reset **********/
input wire clk, // Clock
input wire clk_, // Clock (180)
input wire reset, // Asynchronous reset
/********** Bus interface **********/
// IF Stage
input wire [`WordDataBus] if_bus_rd_data, // Read data
input wire if_bus_rdy_, // Ready
input wire if_bus_grnt_, // Bus grant
output wire if_bus_req_, // Bus request
output wire [`WordAddrBus] if_bus_addr, // Address
output wire if_bus_as_, // Address strobe
output wire if_bus_rw, // Read/Write
output wire [`WordDataBus] if_bus_wr_data, // Write data
// MEM Stage
input wire [`WordDataBus] mem_bus_rd_data, // Read data
input wire mem_bus_rdy_, // Ready
input wire mem_bus_grnt_, // Bus grant
output wire mem_bus_req_, // Bus reqeuest
output wire [`WordAddrBus] mem_bus_addr, // Address
output wire mem_bus_as_, // Address strobe
output wire mem_bus_rw, // Read/Write
output wire [`WordDataBus] mem_bus_wr_data, // Write data
/********** Interrupt **********/
input wire [`CPU_IRQ_CH-1:0] cpu_irq // Interrupt request
代码如下:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2022/02/04 19:16:52
// Design Name:
// Module Name: ctrl
// 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"
`include "rom.vh"
`include "spm.vh"
module ctrl(
/********** Clock & Reset **********/
input wire clk,
input wire reset,
/********** Control register interface **********/
input wire [`RegAddrBus] creg_rd_addr, // Read address
output reg [`WordDataBus] creg_rd_data, // Read data
output reg [`CpuExeModeBus] exe_mode, // Execution mode
/********** Interrupt **********/
input wire [`CPU_IRQ_CH-1:0] irq, // Interrupt request
output reg int_detect, // Interrupt detection
/********** ID/EX pipeline register **********/
input wire [`WordAddrBus] id_pc, // Program counter
/********** MEM/WB pipeline register **********/
input wire [`WordAddrBus] mem_pc, // Program counter
input wire mem_en, // Enable pipeline data
input wire mem_br_flag, // Branch flag
input wire [`CtrlOpBus] mem_ctrl_op, // Control register operation
input wire [`RegAddrBus] mem_dst_addr, // Write address
input wire [`IsaExpBus] mem_exp_code, // Exception code
input wire [`WordDataBus] mem_out, // Processing result
/********** Pipeline control signal **********/
// Pipeline status
input wire if_busy, // IF stage busy
input wire ld_hazard, // Load hazard
input wire mem_busy, // MEM stage busy
// Stall signal
output wire if_stall, // IF stage stall
output wire id_stall, // ID stage stall
output wire ex_stall, // EX stage stall
output wire mem_stall, // MEM stage stall
// Flush signal
output wire if_flush, // IF stage flush
output wire id_flush, // ID stage flush
output wire ex_flush, // EX stage flush
output wire mem_flush, // MEM stage flush
output reg [`WordAddrBus] new_pc // New program counter
);
/********** Control register **********/
reg int_en; // #0 : Interrupt enable
reg [`CpuExeModeBus] pre_exe_mode; // #1 : Execution mode
reg pre_int_en; // #2 : Interrupt enable
reg [`WordAddrBus] epc; // #3 : Exception program counter
reg [`WordAddrBus] exp_vector; // #4 : Exception vector
reg [`IsaExpBus] exp_code; // #5 : Exception code
reg dly_flag; // #6 : Delay slot flag
reg [`CPU_IRQ_CH-1:0] mask; // #7 : Interrupt mask
/********** Internal signal **********/
reg [`WordAddrBus] pre_pc; // Previous program counter
reg br_flag; // Branch flag
/********** Pipeline control signal **********/
// Stall signal
wire stall = if_busy | mem_busy;
assign if_stall = stall | ld_hazard;
assign id_stall = stall;
assign ex_stall = stall;
assign mem_stall = stall;
// Flush signal
reg flush;
assign if_flush = flush;
assign id_flush = flush | ld_hazard;
assign ex_flush = flush;
assign mem_flush = flush;
/********** Pipeline flush control **********/
always @(*) begin
/* Default value */
new_pc = `WORD_ADDR_W'h0;
flush = `DISABLE;
/* Pipeline flush */
if (mem_en == `ENABLE) begin // Enable pipeline data
if (mem_exp_code != `ISA_EXP_NO_EXP) begin // Exception happed
new_pc = exp_vector;
flush = `ENABLE;
end else if (mem_ctrl_op == `CTRL_OP_EXRT) begin // EXRT instruction
new_pc = epc;
flush = `ENABLE;
end else if (mem_ctrl_op == `CTRL_OP_WRCR) begin // WRCR instruction
new_pc = mem_pc;
flush = `ENABLE;
end
end
end
/********** Interrupt detection **********/
always @(*) begin
if ((int_en == `ENABLE) && ((|((~mask) & irq)) == `ENABLE)) begin
int_detect = `ENABLE;
end else begin
int_detect = `DISABLE;
end
end
/********** Read access **********/
always @(*) begin
case (creg_rd_addr)
`CREG_ADDR_STATUS : begin // #0:Status
creg_rd_data = {{`WORD_DATA_W-2{1'b0}}, int_en, exe_mode};
end
`CREG_ADDR_PRE_STATUS : begin // #1: Status before exception happened
creg_rd_data = {{`WORD_DATA_W-2{1'b0}},
pre_int_en, pre_exe_mode};
end
`CREG_ADDR_PC : begin // #2: Program counter
creg_rd_data = {id_pc, `BYTE_OFFSET_W'h0};
end
`CREG_ADDR_EPC : begin // #3: Exception program counter
creg_rd_data = {epc, `BYTE_OFFSET_W'h0};
end
`CREG_ADDR_EXP_VECTOR : begin // #4: Exception vector
creg_rd_data = {exp_vector, `BYTE_OFFSET_W'h0};
end
`CREG_ADDR_CAUSE : begin // #5: Exception cause
creg_rd_data = {{`WORD_DATA_W-1-`ISA_EXP_W{1'b0}},
dly_flag, exp_code};
end
`CREG_ADDR_INT_MASK : begin // #6: Interrupt mask
creg_rd_data = {{`WORD_DATA_W-`CPU_IRQ_CH{1'b0}}, mask};
end
`CREG_ADDR_IRQ : begin // #6: Interrupt cause
creg_rd_data = {{`WORD_DATA_W-`CPU_IRQ_CH{1'b0}}, irq};
end
`CREG_ADDR_ROM_SIZE : begin // #7:ROM's size
creg_rd_data = $unsigned(`ROM_SIZE);
end
`CREG_ADDR_SPM_SIZE : begin // #8:SPM's size
creg_rd_data = $unsigned(`SPM_SIZE);
end
`CREG_ADDR_CPU_INFO : begin // #9:CPU information
creg_rd_data = {`RELEASE_YEAR, `RELEASE_MONTH,
`RELEASE_VERSION, `RELEASE_REVISION};
end
default : begin // Default value
creg_rd_data = `WORD_DATA_W'h0;
end
endcase
end
/********** CPU control **********/
always @(posedge clk or `RESET_EDGE reset) begin
if (reset == `RESET_ENABLE) begin
/* Asynchronous reset */
exe_mode <= #1 `CPU_KERNEL_MODE;
int_en <= #1 `DISABLE;
pre_exe_mode <= #1 `CPU_KERNEL_MODE;
pre_int_en <= #1 `DISABLE;
exp_code <= #1 `ISA_EXP_NO_EXP;
mask <= #1 {`CPU_IRQ_CH{`ENABLE}};
dly_flag <= #1 `DISABLE;
epc <= #1 `WORD_ADDR_W'h0;
exp_vector <= #1 `WORD_ADDR_W'h0;
pre_pc <= #1 `WORD_ADDR_W'h0;
br_flag <= #1 `DISABLE;
end else begin
/* Update CPU status */
if ((mem_en == `ENABLE) && (stall == `DISABLE)) begin
/* Save PC and brach flag */
//之前的PC保存MEM阶段的PC,分支标志位保存MEM阶段的分支标志位,
//这些信息在异常发生时使用
pre_pc <= #1 mem_pc;
br_flag <= #1 mem_br_flag;
/* CPU status control */
if (mem_exp_code != `ISA_EXP_NO_EXP) begin // Exception happened
exe_mode <= #1 `CPU_KERNEL_MODE;
int_en <= #1 `DISABLE;
pre_exe_mode <= #1 exe_mode;
pre_int_en <= #1 int_en;
exp_code <= #1 mem_exp_code;
dly_flag <= #1 br_flag;
epc <= #1 pre_pc;
end else if (mem_ctrl_op == `CTRL_OP_EXRT) begin // EXRT instruction
exe_mode <= #1 pre_exe_mode;
int_en <= #1 pre_int_en;
end else if (mem_ctrl_op == `CTRL_OP_WRCR) begin // WRCR instruction
/* Write control register */
case (mem_dst_addr)
`CREG_ADDR_STATUS : begin // Status
exe_mode <= #1 mem_out[`CregExeModeLoc];
int_en <= #1 mem_out[`CregIntEnableLoc];
end
`CREG_ADDR_PRE_STATUS : begin // Status before exception happened
pre_exe_mode <= #1 mem_out[`CregExeModeLoc];
pre_int_en <= #1 mem_out[`CregIntEnableLoc];
end
`CREG_ADDR_EPC : begin // Exception program
epc <= #1 mem_out[`WordAddrLoc];
end
`CREG_ADDR_EXP_VECTOR : begin // Exception vector
exp_vector <= #1 mem_out[`WordAddrLoc];
end
`CREG_ADDR_CAUSE : begin // Exception cause
dly_flag <= #1 mem_out[`CregDlyFlagLoc];
exp_code <= #1 mem_out[`CregExpCodeLoc];
end
`CREG_ADDR_INT_MASK : begin // Interrupt mask
mask <= #1 mem_out[`CPU_IRQ_CH-1:0];
end
endcase
end
end
end
end
endmodule
2.CPU总模块连接
将IF阶段、ID阶段、EX阶段、MEM阶段、cpu控制模块、SPM模块、GPR模块连接起来。
代码如下:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2022/02/04 19:55:47
// Design Name:
// Module Name: cpu
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
// CPU top module
// 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"
`include "bus.vh"
`include "spm.vh"
module cpu(
/********** Clock & Reset **********/
input wire clk, // Clock
input wire clk_, // Clock (180)
input wire reset, // Asynchronous reset
/********** Bus interface **********/
// IF Stage
input wire [`WordDataBus] if_bus_rd_data, // Read data
input wire if_bus_rdy_, // Ready
input wire if_bus_grnt_, // Bus grant
output wire if_bus_req_, // Bus request
output wire [`WordAddrBus] if_bus_addr, // Address
output wire if_bus_as_, // Address strobe
output wire if_bus_rw, // Read/Write
output wire [`WordDataBus] if_bus_wr_data, // Write data
// MEM Stage
input wire [`WordDataBus] mem_bus_rd_data, // Read data
input wire mem_bus_rdy_, // Ready
input wire mem_bus_grnt_, // Bus grant
output wire mem_bus_req_, // Bus reqeuest
output wire [`WordAddrBus] mem_bus_addr, // Address
output wire mem_bus_as_, // Address strobe
output wire mem_bus_rw, // Read/Write
output wire [`WordDataBus] mem_bus_wr_data, // Write data
/********** Interrupt **********/
input wire [`CPU_IRQ_CH-1:0] cpu_irq // Interrupt request
);
/********** Pipeline register **********/
// IF/ID
wire [`WordAddrBus] if_pc;
wire [`WordDataBus] if_insn;
wire if_en;
// ID/EX pipeline register
wire [`WordAddrBus] id_pc;
wire id_en;
wire [`AluOpBus] id_alu_op;
wire [`WordDataBus] id_alu_in_0;
wire [`WordDataBus] id_alu_in_1;
wire id_br_flag;
wire [`MemOpBus] id_mem_op;
wire [`WordDataBus] id_mem_wr_data;
wire [`CtrlOpBus] id_ctrl_op;
wire [`RegAddrBus] id_dst_addr;
wire id_gpr_we_;
wire [`IsaExpBus] id_exp_code;
// EX/MEM pipeline register
wire [`WordAddrBus] ex_pc;
wire ex_en;
wire ex_br_flag;
wire [`MemOpBus] ex_mem_op;
wire [`WordDataBus] ex_mem_wr_data;
wire [`CtrlOpBus] ex_ctrl_op;
wire [`RegAddrBus] ex_dst_addr;
wire ex_gpr_we_;
wire [`IsaExpBus] ex_exp_code;
wire [`WordDataBus] ex_out;
// MEM/WB pipeline register
wire [`WordAddrBus] mem_pc;
wire mem_en;
wire mem_br_flag;
wire [`CtrlOpBus] mem_ctrl_op;
wire [`RegAddrBus] mem_dst_addr;
wire mem_gpr_we_;
wire [`IsaExpBus] mem_exp_code;
wire [`WordDataBus] mem_out;
/********** Pipeline control signal **********/
// Stall signal
wire if_stall; // IF stage
wire id_stall; // ID stage
wire ex_stall; // EX stage
wire mem_stall; // MEM stage
// Flush signal
wire if_flush; // IF stage
wire id_flush; // ID stage
wire ex_flush; // EX stage
wire mem_flush; // MEM stage
// Busy signal
wire if_busy; // IF stage
wire mem_busy; // MEM stage
// Other control signal
wire [`WordAddrBus] new_pc; // New program counter
wire [`WordAddrBus] br_addr; // Branch address
wire br_taken; // Branch taken
wire ld_hazard; // Load hazard
/********** GPR signal **********/
wire [`WordDataBus] gpr_rd_data_0;
wire [`WordDataBus] gpr_rd_data_1;
wire [`RegAddrBus] gpr_rd_addr_0;
wire [`RegAddrBus] gpr_rd_addr_1;
/********** Control register signal **********/
wire [`CpuExeModeBus] exe_mode;
wire [`WordDataBus] creg_rd_data;
wire [`RegAddrBus] creg_rd_addr;
/********** Interrupt Request **********/
wire int_detect;
/********** Scratchpad memory signal **********/
// IF stage
wire [`WordDataBus] if_spm_rd_data;
wire [`WordAddrBus] if_spm_addr;
wire if_spm_as_;
wire if_spm_rw;
wire [`WordDataBus] if_spm_wr_data;
// MEM stage
wire [`WordDataBus] mem_spm_rd_data;
wire [`WordAddrBus] mem_spm_addr;
wire mem_spm_as_;
wire mem_spm_rw;
wire [`WordDataBus] mem_spm_wr_data;
/********** Forwarding signal **********/
wire [`WordDataBus] ex_fwd_data; // EX stage
wire [`WordDataBus] mem_fwd_data; // MEM stage
/********** IF stage **********/
if_stage if_stage (
/********** Clock & Reset **********/
.clk (clk),
.reset (reset),
/********** SPM interface **********/
.spm_rd_data (if_spm_rd_data),
.spm_addr (if_spm_addr),
.spm_as_ (if_spm_as_),
.spm_rw (if_spm_rw),
.spm_wr_data (if_spm_wr_data),
/********** Bus interface **********/
.bus_rd_data (if_bus_rd_data),
.bus_rdy_ (if_bus_rdy_),
.bus_grnt_ (if_bus_grnt_),
.bus_req_ (if_bus_req_),
.bus_addr (if_bus_addr),
.bus_as_ (if_bus_as_),
.bus_rw (if_bus_rw),
.bus_wr_data (if_bus_wr_data),
/********** Pipeline control signal **********/
.stall (if_stall),
.flush (if_flush),
.new_pc (new_pc),
.br_taken (br_taken),
.br_addr (br_addr),
.busy (if_busy),
/********** IF/ID pipeline register **********/
.if_pc (if_pc),
.if_insn (if_insn),
.if_en (if_en)
);
/********** ID stage **********/
id_stage id_stage (
/********** Clock & Reset **********/
.clk (clk),
.reset (reset),
/********** GPR interface **********/
.gpr_rd_data_0 (gpr_rd_data_0),
.gpr_rd_data_1 (gpr_rd_data_1),
.gpr_rd_addr_0 (gpr_rd_addr_0),
.gpr_rd_addr_1 (gpr_rd_addr_1),
/********** Forwarding **********/
// Forwarding from 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 from 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),
/********** Pipeline control signal **********/
.stall (id_stall),
.flush (id_flush),
.br_addr (br_addr),
.br_taken (br_taken),
.ld_hazard (ld_hazard),
/********** IF/ID pipeline register **********/
.if_pc (if_pc),
.if_insn (if_insn),
.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)
);
/********** EX stage **********/
ex_stage ex_stage (
/********** Clock & Reset **********/
.clk (clk),
.reset (reset),
/********** Pipeline control signal **********/
.stall (ex_stall),
.flush (ex_flush),
.int_detect (int_detect),
/********** Forwarding **********/
.fwd_data (ex_fwd_data),
/********** 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),
/********** EX/MEM pipeline register **********/
.ex_pc (ex_pc),
.ex_en (ex_en),
.ex_br_flag (ex_br_flag),
.ex_mem_op (ex_mem_op),
.ex_mem_wr_data (ex_mem_wr_data),
.ex_ctrl_op (ex_ctrl_op),
.ex_dst_addr (ex_dst_addr),
.ex_gpr_we_ (ex_gpr_we_),
.ex_exp_code (ex_exp_code),
.ex_out (ex_out)
);
/********** MEM Stage **********/
mem_stage mem_stage (
/********** Clock & Reset **********/
.clk (clk),
.reset (reset),
/********** Pipeline control signal **********/
.stall (mem_stall),
.flush (mem_flush),
.busy (mem_busy),
/********** Forwarding **********/
.fwd_data (mem_fwd_data),
/********** SPM interface **********/
.spm_rd_data (mem_spm_rd_data),
.spm_addr (mem_spm_addr),
.spm_as_ (mem_spm_as_),
.spm_rw (mem_spm_rw),
.spm_wr_data (mem_spm_wr_data),
/********** Bus interface **********/
.bus_rd_data (mem_bus_rd_data),
.bus_rdy_ (mem_bus_rdy_),
.bus_grnt_ (mem_bus_grnt_),
.bus_req_ (mem_bus_req_),
.bus_addr (mem_bus_addr),
.bus_as_ (mem_bus_as_),
.bus_rw (mem_bus_rw),
.bus_wr_data (mem_bus_wr_data),
/********** EX/MEM pipeline register **********/
.ex_pc (ex_pc),
.ex_en (ex_en),
.ex_br_flag (ex_br_flag),
.ex_mem_op (ex_mem_op),
.ex_mem_wr_data (ex_mem_wr_data),
.ex_ctrl_op (ex_ctrl_op),
.ex_dst_addr (ex_dst_addr),
.ex_gpr_we_ (ex_gpr_we_),
.ex_exp_code (ex_exp_code),
.ex_out (ex_out),
/********** MEM/WB pipeline register **********/
.mem_pc (mem_pc),
.mem_en (mem_en),
.mem_br_flag (mem_br_flag),
.mem_ctrl_op (mem_ctrl_op),
.mem_dst_addr (mem_dst_addr),
.mem_gpr_we_ (mem_gpr_we_),
.mem_exp_code (mem_exp_code),
.mem_out (mem_out)
);
/********** Control unit **********/
ctrl ctrl (
/********** Clock & Reset **********/
.clk (clk),
.reset (reset),
/********** Control register interface **********/
.creg_rd_addr (creg_rd_addr),
.creg_rd_data (creg_rd_data),
.exe_mode (exe_mode),
/********** Interrupt **********/
.irq (cpu_irq),
.int_detect (int_detect),
/********** ID/EX pipeline register **********/
.id_pc (id_pc),
/********** MEM/WB pipeline register **********/
.mem_pc (mem_pc),
.mem_en (mem_en),
.mem_br_flag (mem_br_flag),
.mem_ctrl_op (mem_ctrl_op),
.mem_dst_addr (mem_dst_addr),
.mem_exp_code (mem_exp_code),
.mem_out (mem_out),
/********** Pipeline control signal **********/
// Status of pipeline
.if_busy (if_busy),
.ld_hazard (ld_hazard),
.mem_busy (mem_busy),
// stall singal
.if_stall (if_stall),
.id_stall (id_stall),
.ex_stall (ex_stall),
.mem_stall (mem_stall),
// Flush signal
.if_flush (if_flush),
.id_flush (id_flush),
.ex_flush (ex_flush),
.mem_flush (mem_flush),
// New program counter
.new_pc (new_pc)
);
/********** GPR **********/
gpr gpr (
/********** Clock & Reset **********/
.clk (clk),
.reset (reset),
/********** Read port 0 **********/
.rd_addr_0 (gpr_rd_addr_0),
.rd_data_0 (gpr_rd_data_0),
/********** Read port 1 **********/
.rd_addr_1 (gpr_rd_addr_1),
.rd_data_1 (gpr_rd_data_1),
/********** Write port **********/
.we_ (mem_gpr_we_),
.wr_addr (mem_dst_addr),
.wr_data (mem_out)
);
/********** Scratchpad memory **********/
spm spm (
/********** Clock **********/
.clk (clk_),
/********** PortA : IF stage **********/
.if_spm_addr (if_spm_addr[`SpmAddrLoc]),
.if_spm_as_ (if_spm_as_),
.if_spm_rw (if_spm_rw),
.if_spm_wr_data (if_spm_wr_data),
.if_spm_rd_data (if_spm_rd_data),
/********** PortB : MEM stage **********/
.mem_spm_addr (mem_spm_addr[`SpmAddrLoc]),
.mem_spm_as_ (mem_spm_as_),
.mem_spm_rw (mem_spm_rw),
.mem_spm_wr_data (mem_spm_wr_data),
.mem_spm_rd_data (mem_spm_rd_data)
);
endmodule
3.仿真验证
这边对于cpu控制寄存器对应模块的相关内容还未掌握,暂时未涉及到中断等异常的判断处理。
验证思路:
由于top模块连接中if_bus_rd_data作为输入源,
在testbench中将if_bus_rd_data可设为reg类型
而if_pc在定义时是wire类型,不好进行对应赋值。
这边将指令传输给if_bus_rd_data,进行寄存器之间的加法运算。
先将需要进行计算的数据放入寄存器群中,这边将实现100+200=300的计算,并将计算结果写入gpr[3].
gpr[2]<=32'd100;
gpr[1]<=32'd200;
仿真代码如下:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2022/02/04 21:25:14
// Design Name:
// Module Name: cpu_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"
`include "bus.vh"
`include "spm.vh"
module cpu_test(
);
//端口定义
/********** Clock & Reset **********/
reg clk; // Clock
reg clk_; // Clock (180)
reg reset; // Asynchronous reset
/********** Bus interface **********/
// IF Stage
reg [`WordDataBus] if_bus_rd_data; // Read data
reg if_bus_rdy_; // Ready
reg if_bus_grnt_; // Bus grant
wire if_bus_req_; // Bus request
wire [`WordAddrBus] if_bus_addr; // Address
wire if_bus_as_; // Address strobe
wire if_bus_rw; // Read/Write
wire [`WordDataBus] if_bus_wr_data; // Write data
// MEM Stage
reg [`WordDataBus] mem_bus_rd_data; // Read data
reg mem_bus_rdy_; // Ready
reg mem_bus_grnt_; // Bus grant
wire mem_bus_req_; // Bus reqeuest
wire [`WordAddrBus] mem_bus_addr; // Address
wire mem_bus_as_; // Address strobe
wire mem_bus_rw; // Read/Write
wire [`WordDataBus] mem_bus_wr_data; // Write data
/********** Interrupt **********/
reg [`CPU_IRQ_CH-1:0] cpu_irq; // Interrupt request
/********** Pipeline register **********/
// IF/ID
wire [`WordAddrBus] if_pc;
wire [`WordDataBus] if_insn;
wire if_en;
// ID/EX pipeline register
wire [`WordAddrBus] id_pc;
wire id_en;
wire [`AluOpBus] id_alu_op;
wire [`WordDataBus] id_alu_in_0;
wire [`WordDataBus] id_alu_in_1;
wire id_br_flag;
wire [`MemOpBus] id_mem_op;
wire [`WordDataBus] id_mem_wr_data;
wire [`CtrlOpBus] id_ctrl_op;
wire [`RegAddrBus] id_dst_addr;
wire id_gpr_we_;
wire [`IsaExpBus] id_exp_code;
// EX/MEM pipeline register
wire [`WordAddrBus] ex_pc;
wire ex_en;
wire ex_br_flag;
wire [`MemOpBus] ex_mem_op;
wire [`WordDataBus] ex_mem_wr_data;
wire [`CtrlOpBus] ex_ctrl_op;
wire [`RegAddrBus] ex_dst_addr;
wire ex_gpr_we_;
wire [`IsaExpBus] ex_exp_code;
wire [`WordDataBus] ex_out;
// MEM/WB pipeline register
wire [`WordAddrBus] mem_pc;
wire mem_en;
wire mem_br_flag;
wire [`CtrlOpBus] mem_ctrl_op;
wire [`RegAddrBus] mem_dst_addr;
wire mem_gpr_we_;
wire [`IsaExpBus] mem_exp_code;
wire [`WordDataBus] mem_out;
/********** Pipeline control signal **********/
// Stall signal
wire if_stall; // IF stage
wire id_stall; // ID stage
wire ex_stall; // EX stage
wire mem_stall; // MEM stage
// Flush signal
wire if_flush; // IF stage
wire id_flush; // ID stage
wire ex_flush; // EX stage
wire mem_flush; // MEM stage
// Busy signal
wire if_busy; // IF stage
wire mem_busy; // MEM stage
// Other control signal
wire [`WordAddrBus] new_pc; // New program counter
wire [`WordAddrBus] br_addr; // Branch address
wire br_taken; // Branch taken
wire ld_hazard; // Load hazard
/********** GPR signal **********/
wire [`WordDataBus] gpr_rd_data_0;
wire [`WordDataBus] gpr_rd_data_1;
wire [`RegAddrBus] gpr_rd_addr_0;
wire [`RegAddrBus] gpr_rd_addr_1;
/********** Control register signal **********/
wire [`CpuExeModeBus] exe_mode;
wire [`WordDataBus] creg_rd_data;
wire [`RegAddrBus] creg_rd_addr;
/********** Interrupt Request **********/
wire int_detect;
/********** Scratchpad memory signal **********/
// IF stage
wire [`WordDataBus] if_spm_rd_data;
wire [`WordAddrBus] if_spm_addr;
wire if_spm_as_;
wire if_spm_rw;
wire [`WordDataBus] if_spm_wr_data;
// MEM stage
wire [`WordDataBus] mem_spm_rd_data;
wire [`WordAddrBus] mem_spm_addr;
wire mem_spm_as_;
wire mem_spm_rw;
wire [`WordDataBus] mem_spm_wr_data;
/********** Forwarding signal **********/
wire [`WordDataBus] ex_fwd_data; // EX stage
wire [`WordDataBus] mem_fwd_data; // MEM stage
//时钟激励:
integer i;
parameter STEP=100;
always#(STEP/2)begin
clk<=~clk;
clk_ <=~clk_;
end
//实例化
/********** IF stage **********/
if_stage if_stage (
/********** Clock & Reset **********/
.clk (clk),
.reset (reset),
/********** SPM interface **********/
.spm_rd_data (if_spm_rd_data),
.spm_addr (if_spm_addr),
.spm_as_ (if_spm_as_),
.spm_rw (if_spm_rw),
.spm_wr_data (if_spm_wr_data),
/********** Bus interface **********/
.bus_rd_data (if_bus_rd_data),
.bus_rdy_ (if_bus_rdy_),
.bus_grnt_ (if_bus_grnt_),
.bus_req_ (if_bus_req_),
.bus_addr (if_bus_addr),
.bus_as_ (if_bus_as_),
.bus_rw (if_bus_rw),
.bus_wr_data (if_bus_wr_data),
/********** Pipeline control signal **********/
.stall (if_stall),
.flush (if_flush),
.new_pc (new_pc),
.br_taken (br_taken),
.br_addr (br_addr),
.busy (if_busy),
/********** IF/ID pipeline register **********/
.if_pc (if_pc),
.if_insn (if_insn),
.if_en (if_en)
);
/********** ID stage **********/
id_stage id_stage (
/********** Clock & Reset **********/
.clk (clk),
.reset (reset),
/********** GPR interface **********/
.gpr_rd_data_0 (gpr_rd_data_0),
.gpr_rd_data_1 (gpr_rd_data_1),
.gpr_rd_addr_0 (gpr_rd_addr_0),
.gpr_rd_addr_1 (gpr_rd_addr_1),
/********** Forwarding **********/
// Forwarding from 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 from 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),
/********** Pipeline control signal **********/
.stall (id_stall),
.flush (id_flush),
.br_addr (br_addr),
.br_taken (br_taken),
.ld_hazard (ld_hazard),
/********** IF/ID pipeline register **********/
.if_pc (if_pc),
.if_insn (if_insn),
.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)
);
/********** EX stage **********/
ex_stage ex_stage (
/********** Clock & Reset **********/
.clk (clk),
.reset (reset),
/********** Pipeline control signal **********/
.stall (ex_stall),
.flush (ex_flush),
.int_detect (int_detect),
/********** Forwarding **********/
.fwd_data (ex_fwd_data),
/********** 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),
/********** EX/MEM pipeline register **********/
.ex_pc (ex_pc),
.ex_en (ex_en),
.ex_br_flag (ex_br_flag),
.ex_mem_op (ex_mem_op),
.ex_mem_wr_data (ex_mem_wr_data),
.ex_ctrl_op (ex_ctrl_op),
.ex_dst_addr (ex_dst_addr),
.ex_gpr_we_ (ex_gpr_we_),
.ex_exp_code (ex_exp_code),
.ex_out (ex_out)
);
/********** MEM Stage **********/
mem_stage mem_stage (
/********** Clock & Reset **********/
.clk (clk),
.reset (reset),
/********** Pipeline control signal **********/
.stall (mem_stall),
.flush (mem_flush),
.busy (mem_busy),
/********** Forwarding **********/
.fwd_data (mem_fwd_data),
/********** SPM interface **********/
.spm_rd_data (mem_spm_rd_data),
.spm_addr (mem_spm_addr),
.spm_as_ (mem_spm_as_),
.spm_rw (mem_spm_rw),
.spm_wr_data (mem_spm_wr_data),
/********** Bus interface **********/
.bus_rd_data (mem_bus_rd_data),
.bus_rdy_ (mem_bus_rdy_),
.bus_grnt_ (mem_bus_grnt_),
.bus_req_ (mem_bus_req_),
.bus_addr (mem_bus_addr),
.bus_as_ (mem_bus_as_),
.bus_rw (mem_bus_rw),
.bus_wr_data (mem_bus_wr_data),
/********** EX/MEM pipeline register **********/
.ex_pc (ex_pc),
.ex_en (ex_en),
.ex_br_flag (ex_br_flag),
.ex_mem_op (ex_mem_op),
.ex_mem_wr_data (ex_mem_wr_data),
.ex_ctrl_op (ex_ctrl_op),
.ex_dst_addr (ex_dst_addr),
.ex_gpr_we_ (ex_gpr_we_),
.ex_exp_code (ex_exp_code),
.ex_out (ex_out),
/********** MEM/WB pipeline register **********/
.mem_pc (mem_pc),
.mem_en (mem_en),
.mem_br_flag (mem_br_flag),
.mem_ctrl_op (mem_ctrl_op),
.mem_dst_addr (mem_dst_addr),
.mem_gpr_we_ (mem_gpr_we_),
.mem_exp_code (mem_exp_code),
.mem_out (mem_out)
);
/********** Control unit **********/
ctrl ctrl (
/********** Clock & Reset **********/
.clk (clk),
.reset (reset),
/********** Control register interface **********/
.creg_rd_addr (creg_rd_addr),
.creg_rd_data (creg_rd_data),
.exe_mode (exe_mode),
/********** Interrupt **********/
.irq (cpu_irq),
.int_detect (int_detect),
/********** ID/EX pipeline register **********/
.id_pc (id_pc),
/********** MEM/WB pipeline register **********/
.mem_pc (mem_pc),
.mem_en (mem_en),
.mem_br_flag (mem_br_flag),
.mem_ctrl_op (mem_ctrl_op),
.mem_dst_addr (mem_dst_addr),
.mem_exp_code (mem_exp_code),
.mem_out (mem_out),
/********** Pipeline control signal **********/
// Status of pipeline
.if_busy (if_busy),
.ld_hazard (ld_hazard),
.mem_busy (mem_busy),
// stall singal
.if_stall (if_stall),
.id_stall (id_stall),
.ex_stall (ex_stall),
.mem_stall (mem_stall),
// Flush signal
.if_flush (if_flush),
.id_flush (id_flush),
.ex_flush (ex_flush),
.mem_flush (mem_flush),
// New program counter
.new_pc (new_pc)
);
/********** GPR **********/
gpr gpr (
/********** Clock & Reset **********/
.clk (clk),
.reset (reset),
/********** Read port 0 **********/
.rd_addr_0 (gpr_rd_addr_0),
.rd_data_0 (gpr_rd_data_0),
/********** Read port 1 **********/
.rd_addr_1 (gpr_rd_addr_1),
.rd_data_1 (gpr_rd_data_1),
/********** Write port **********/
.we_ (mem_gpr_we_),
.wr_addr (mem_dst_addr),
.wr_data (mem_out)
);
/********** Scratchpad memory **********/
spm spm (
/********** Clock **********/
.clk (clk_),
/********** PortA : IF stage **********/
.if_spm_addr (if_spm_addr[`SpmAddrLoc]),
.if_spm_as_ (if_spm_as_),
.if_spm_rw (if_spm_rw),
.if_spm_wr_data (if_spm_wr_data),
.if_spm_rd_data (if_spm_rd_data),
/********** PortB : MEM stage **********/
.mem_spm_addr (mem_spm_addr[`SpmAddrLoc]),
.mem_spm_as_ (mem_spm_as_),
.mem_spm_rw (mem_spm_rw),
.mem_spm_wr_data (mem_spm_wr_data),
.mem_spm_rd_data (mem_spm_rd_data)
);
//测试模式:
initial
begin
clk<=1;
clk_<=0;
reset<=`RESET_ENABLE;
#(STEP*3/4)
#STEP begin
reset<=`RESET_DISABLE;
#STEP
if_bus_rd_data<= {{`ISA_OP_ADDSR},{5'b00001},{5'b00010},{5'b00011},{11{1'b0}}};
#STEP
if_bus_grnt_<=`ENABLE_;
#STEP
if_bus_rdy_ <=`ENABLE_;
end
end
endmodule
仿真结果:
1.IF模块取出代码,这边我们将指令赋值给if_bus_rd_data。
if寄存器将会存储下指令(insn)传递给ID模块。
2.在ID模块的解码中,将指令分解。得到对于操作和操作数地址
接着传给ID寄存器,ID寄存器传递指令给EX模块
下图显示操作数为gpr【1】和gpr【2】,数值分别为100和200
这边将需要的信号存入id寄存器中,op=4,alu0=100,alu1=200,计算返回寄存器为gpr[3].
3.EX阶段进行指令的执行,得到out=300的结果,保存到ex寄存器,并传递给mem模块。
alu结果:
ex寄存器:
4.MEM阶段,将ex结果写回寄存器群中,dst_addr=3,即写回gpr[3]。注意gpr_we写入标志位这时是有效的。仿真结束。