Execution(EX)阶段
EX阶段主要进行运算和中断检测操作。EX阶段由算术逻辑运算单元和流水线寄存器构成。
端口定义:
part6.EX阶段
EX阶段主要进行运算和中断检测操作。EX阶段由算术逻辑运算单元和流水线寄存器构成。
1.ALU
根据输入指定的操作对数据进行处理,并输出处理结果。
ALu的输入为一个操作码和俩个数据,输出为运算结果和溢出信号
alu:
input wire [`WordDataBus] in_0, // Input 0
input wire [`WordDataBus] in_1, // Input 1
input wire [`AluOpBus] op, // Operation
output reg [`WordDataBus] out, // Outpu
output reg of // Overflow
2.ex流水线寄存器
ex_reg:
/********** Clock & Reset **********/
input wire clk,
input wire reset,
/********** ALU's output **********/
input wire [`WordDataBus] alu_out, // Calculation result
input wire alu_of, // Overflow
/********** Pipeline control signal **********/
input wire stall, // Stall
input wire flush, // Flush
input wire int_detect, // Interrupt detection
/********** ID/EX pipeline register **********/
input wire [`WordAddrBus] id_pc, // Program counter
input wire id_en, // Enable pipeline data
input wire id_br_flag, // Branch flag
input wire [`MemOpBus] id_mem_op, // Memory operation
input wire [`WordDataBus] id_mem_wr_data, // Data to write to memory
input wire [`CtrlOpBus] id_ctrl_op, // Control operation
input wire [`RegAddrBus] id_dst_addr, // GPR write address
input wire id_gpr_we_, // GPR register write enable
input wire [`IsaExpBus] id_exp_code, // Exception code
/********** EX/MEM pipeline register **********/
output reg [`WordAddrBus] ex_pc, // Program counter
output reg ex_en, // Enable pipeline data
output reg ex_br_flag, // Branch flag
output reg [`MemOpBus] ex_mem_op, // Memory operation
output reg [`WordDataBus] ex_mem_wr_data, // Data to write to memory
output reg [`CtrlOpBus] ex_ctrl_op, // Control operation
output reg [`RegAddrBus] ex_dst_addr, // GPR write address
output reg ex_gpr_we_, // GPR register write enable
output reg [`IsaExpBus] ex_exp_code, // Exception code
output reg [`WordDataBus] ex_out // Processing result
3.top模块:
ex_stage:
/********** Clock & Reset **********/
input wire clk,
input wire reset,
/********** Pipeline control signal **********/
input wire stall, // Stal
input wire flush, // Flush
input wire int_detect, // Interrupt detection
/********** Forwarding **********/
output wire [`WordDataBus] fwd_data, // Forwarding
/********** ID/EX pipeline register **********/
input wire [`WordAddrBus] id_pc, // Program counter
input wire id_en, // Enable pipeline data
input wire [`AluOpBus] id_alu_op, // ALU operation
input wire [`WordDataBus] id_alu_in_0, // ALU input 0
input wire [`WordDataBus] id_alu_in_1, // ALU input 1
input wire id_br_flag, // Branch flag
input wire [`MemOpBus] id_mem_op, // Memory operation
input wire [`WordDataBus] id_mem_wr_data, // Memory write data
input wire [`CtrlOpBus] id_ctrl_op, // Control register operation
input wire [`RegAddrBus] id_dst_addr, // GPR write address
input wire id_gpr_we_, // GPR write enable
input wire [`IsaExpBus] id_exp_code, // Exception code
/********** EX/MEM pipeline register **********/
output wire [`WordAddrBus] ex_pc, // Program counter
output wire ex_en, // Enable pipeline data
output wire ex_br_flag, // Branch flag
output wire [`MemOpBus] ex_mem_op, // Memory operation
output wire [`WordDataBus] ex_mem_wr_data, // Memory write data
output wire [`CtrlOpBus] ex_ctrl_op, // Control register operation
output wire [`RegAddrBus] ex_dst_addr, // GPR write address
output wire ex_gpr_we_, // GPR write enable
output wire [`IsaExpBus] ex_exp_code, // Exception code
output wire [`WordDataBus] ex_out // Processing result
1.ALU模块
根据输入指定的操作对数据进行处理,并输出处理结果。
ALu的输入为一个操作码和两个数据,输出为运算结果和溢出信号
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2022/02/02 19:51:06
// Design Name:
// Module Name: alu
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
// Arithmetic logic unit
// Dependencies:
//
// 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 alu(
input wire [`WordDataBus] in_0, // Input 0
input wire [`WordDataBus] in_1, // Input 1
input wire [`AluOpBus] op, // Operation
output reg [`WordDataBus] out, // Outpu
output reg of // Overflow
);
/********** Signed I/O signal 有符号输入输出信号**********/
wire signed [`WordDataBus] s_in_0 = $signed(in_0); // Signed input 0
wire signed [`WordDataBus] s_in_1 = $signed(in_1); // Signed input 1
wire signed [`WordDataBus] s_out = $signed(out); // Signed output
/********** Arithmetic logic operation 算术逻辑运算**********/
always @(*) begin
case (op)
`ALU_OP_AND : begin //逻辑与 and
out = in_0 & in_1;
end
`ALU_OP_OR : begin //逻辑或 or
out = in_0 | in_1;
end
`ALU_OP_XOR : begin //逻辑异或 XOR
out = in_0 ^ in_1;
end
`ALU_OP_ADDS : begin //有符号加法
out = in_0 + in_1;
$display("in_0=%d,in_1=%d,out=%d",in_0,in_1,out);
end
`ALU_OP_ADDU : begin //无符号加法
out = in_0 + in_1;
end
`ALU_OP_SUBS : begin //有符号减法
out = in_0 - in_1;
end
`ALU_OP_SUBU : begin //无符号减法
out = in_0 - in_1;
end
`ALU_OP_SHRL : begin //逻辑右移 `define ShAmountLoc 4:0 // Shift amount location
out = in_0 >> in_1[`ShAmountLoc]; //32位的移位运算,最大位移量为32,所以5位可以表达的最大值为2^5=32
end
`ALU_OP_SHLL : begin //逻辑左移
out = in_0 << in_1[`ShAmountLoc];
end
default : begin // Default (No Operation)
out = in_0;
end
endcase
end
/********** Overflow check 溢出检测**********/
always @(*) begin
case (op)
`ALU_OP_ADDS : begin // ADD overflow check 加法溢出检测
if (((s_in_0 > 0) && (s_in_1 > 0) && (s_out < 0)) ||
((s_in_0 < 0) && (s_in_1 < 0) && (s_out > 0))) begin
of = `ENABLE;
end else begin
of = `DISABLE;
end
end
`ALU_OP_SUBS : begin // SUB overflow check 减法溢出检测
if (((s_in_0 < 0) && (s_in_1 > 0) && (s_out > 0)) ||
((s_in_0 > 0) && (s_in_1 < 0) && (s_out < 0))) begin
of = `ENABLE;
end else begin
of = `DISABLE;
end
end
default : begin // Default value 默认值
of = `DISABLE;
end
endcase
$display("of=%b",of);
end
endmodule
2.EX阶段流水线寄存器
实现将ex阶段寄存器赋值为i d阶段寄存器值,并且将alu计算出的数值输出。另外还有中断执行和溢出执行。
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2022/02/02 20:42:21
// Design Name:
// Module Name: ex_reg
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
// EX 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 ex_reg(
/********** Clock & Reset **********/
input wire clk,
input wire reset,
/********** ALU's output **********/
input wire [`WordDataBus] alu_out, // Calculation result
input wire alu_of, // Overflow
/********** Pipeline control signal **********/
input wire stall, // Stall
input wire flush, // Flush
input wire int_detect, // Interrupt detection
/********** ID/EX pipeline register **********/
input wire [`WordAddrBus] id_pc, // Program counter
input wire id_en, // Enable pipeline data
input wire id_br_flag, // Branch flag
input wire [`MemOpBus] id_mem_op, // Memory operation
input wire [`WordDataBus] id_mem_wr_data, // Data to write to memory
input wire [`CtrlOpBus] id_ctrl_op, // Control operation
input wire [`RegAddrBus] id_dst_addr, // GPR write address
input wire id_gpr_we_, // GPR register write enable
input wire [`IsaExpBus] id_exp_code, // Exception code
/********** EX/MEM pipeline register **********/
output reg [`WordAddrBus] ex_pc, // Program counter
output reg ex_en, // Enable pipeline data
output reg ex_br_flag, // Branch flag
output reg [`MemOpBus] ex_mem_op, // Memory operation
output reg [`WordDataBus] ex_mem_wr_data, // Data to write to memory
output reg [`CtrlOpBus] ex_ctrl_op, // Control operation
output reg [`RegAddrBus] ex_dst_addr, // GPR write address
output reg ex_gpr_we_, // GPR register write enable
output reg [`IsaExpBus] ex_exp_code, // Exception code
output reg [`WordDataBus] ex_out // Processing result
);
/********** Pipeline register **********/
always @(posedge clk or `RESET_EDGE reset) begin
/* Asynchronous Reset 异步复位 */
if (reset == `RESET_ENABLE) begin
ex_pc <= #1 `WORD_ADDR_W'h0;
ex_en <= #1 `DISABLE;
ex_br_flag <= #1 `DISABLE;
ex_mem_op <= #1 `MEM_OP_NOP;
ex_mem_wr_data <= #1 `WORD_DATA_W'h0;
ex_ctrl_op <= #1 `CTRL_OP_NOP;
ex_dst_addr <= #1 `REG_ADDR_W'd0;
ex_gpr_we_ <= #1 `DISABLE_;
ex_exp_code <= #1 `ISA_EXP_NO_EXP;
ex_out <= #1 `WORD_DATA_W'h0;
end else begin
/* Update pipeline register */
if (stall == `DISABLE) begin
if (flush == `ENABLE) begin // Flush
ex_pc <= #1 `WORD_ADDR_W'h0;
ex_en <= #1 `DISABLE;
ex_br_flag <= #1 `DISABLE;
ex_mem_op <= #1 `MEM_OP_NOP;
ex_mem_wr_data <= #1 `WORD_DATA_W'h0;
ex_ctrl_op <= #1 `CTRL_OP_NOP;
ex_dst_addr <= #1 `REG_ADDR_W'd0;
ex_gpr_we_ <= #1 `DISABLE_;
ex_exp_code <= #1 `ISA_EXP_NO_EXP;
ex_out <= #1 `WORD_DATA_W'h0;
end else if (int_detect == `ENABLE) begin // Interrupt detected
ex_pc <= #1 id_pc;
ex_en <= #1 id_en;
ex_br_flag <= #1 id_br_flag;
ex_mem_op <= #1 `MEM_OP_NOP;
ex_mem_wr_data <= #1 `WORD_DATA_W'h0;
ex_ctrl_op <= #1 `CTRL_OP_NOP;
ex_dst_addr <= #1 `REG_ADDR_W'd0;
ex_gpr_we_ <= #1 `DISABLE_;
ex_exp_code <= #1 `ISA_EXP_EXT_INT;
ex_out <= #1 `WORD_DATA_W'h0;
end else if (alu_of == `ENABLE) begin // Arithmetic overflow
ex_pc <= #1 id_pc;
ex_en <= #1 id_en;
ex_br_flag <= #1 id_br_flag;
ex_mem_op <= #1 `MEM_OP_NOP;
ex_mem_wr_data <= #1 `WORD_DATA_W'h0;
ex_ctrl_op <= #1 `CTRL_OP_NOP;
ex_dst_addr <= #1 `REG_ADDR_W'd0;
ex_gpr_we_ <= #1 `DISABLE_;
ex_exp_code <= #1 `ISA_EXP_OVERFLOW;
ex_out <= #1 `WORD_DATA_W'h0;
end else begin // Next data
ex_pc <= #1 id_pc;
ex_en <= #1 id_en;
ex_br_flag <= #1 id_br_flag;
ex_mem_op <= #1 id_mem_op;
ex_mem_wr_data <= #1 id_mem_wr_data;
ex_ctrl_op <= #1 id_ctrl_op;
ex_dst_addr <= #1 id_dst_addr;
ex_gpr_we_ <= #1 id_gpr_we_;
ex_exp_code <= #1 id_exp_code;
ex_out <= #1 alu_out;
$display("alu_of=%b,ex_out=%b,alu_out=%b",alu_of,ex_out,alu_out);
end
end
end
end
endmodule
3.top顶层模块,进行各个模块连接
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2022/02/02 21:25:50
// Design Name:
// Module Name: ex_stage
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
// EX stage的top模块
// 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 ex_stage(
/********** Clock & Reset **********/
input wire clk,
input wire reset,
/********** Pipeline control signal **********/
input wire stall, // Stal
input wire flush, // Flush
input wire int_detect, // Interrupt detection
/********** Forwarding **********/
output wire [`WordDataBus] fwd_data, // Forwarding
/********** ID/EX pipeline register **********/
input wire [`WordAddrBus] id_pc, // Program counter
input wire id_en, // Enable pipeline data
input wire [`AluOpBus] id_alu_op, // ALU operation
input wire [`WordDataBus] id_alu_in_0, // ALU input 0
input wire [`WordDataBus] id_alu_in_1, // ALU input 1
input wire id_br_flag, // Branch flag
input wire [`MemOpBus] id_mem_op, // Memory operation
input wire [`WordDataBus] id_mem_wr_data, // Memory write data
input wire [`CtrlOpBus] id_ctrl_op, // Control register operation
input wire [`RegAddrBus] id_dst_addr, // GPR write address
input wire id_gpr_we_, // GPR write enable
input wire [`IsaExpBus] id_exp_code, // Exception code
/********** EX/MEM pipeline register **********/
output wire [`WordAddrBus] ex_pc, // Program counter
output wire ex_en, // Enable pipeline data
output wire ex_br_flag, // Branch flag
output wire [`MemOpBus] ex_mem_op, // Memory operation
output wire [`WordDataBus] ex_mem_wr_data, // Memory write data
output wire [`CtrlOpBus] ex_ctrl_op, // Control register operation
output wire [`RegAddrBus] ex_dst_addr, // GPR write address
output wire ex_gpr_we_, // GPR write enable
output wire [`IsaExpBus] ex_exp_code, // Exception code
output wire [`WordDataBus] ex_out // Processing result
);
/********** ALU's output **********/
wire [`WordDataBus] alu_out; // Result
wire alu_of; // Overflow
/********** Forwarding result **********/
assign fwd_data = alu_out;
/********** ALU **********/
alu alu (
.in_0 (id_alu_in_0), // Input 0
.in_1 (id_alu_in_1), // Input 1
.op (id_alu_op), // Operation
.out (alu_out), // Output
.of (alu_of) // Overflow
);
/********** Pipeline register **********/
ex_reg ex_reg (
/********** Clock & Reset **********/
.clk (clk),
.reset (reset),
/********** ALU's output **********/
.alu_out (alu_out),
.alu_of (alu_of),
/********** Pipeline control signal **********/
.stall (stall),
.flush (flush),
.int_detect (int_detect),
/********** ID/EX pipeline register **********/
.id_pc (id_pc),
.id_en (id_en),
.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)
);
endmodule
4.仿真测试
仿真思路:
继续上次id实验的仿真,执行的指令为寄存器间有符号加法
将id寄存器的信号(如下图所示)作为输入信号:
将id_alu_in_0<=32’d10;
id_alu_in_1<=32’d20;
id_alu_op<=4’b0100;
进行加法运算可以得到最后结果30
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2022/02/10 11:27:44
// Design Name:
// Module Name: ex_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 ex_test(
);
/********** Clock & Reset **********/
reg clk;
reg reset;
/********** Pipeline control signal **********/
reg stall; // Stal
reg flush; // Flush
reg int_detect; // Interrupt detection
/********** Forwarding **********/
wire [`WordDataBus] fwd_data; // Forwarding
/********** ID/EX pipeline register **********/
reg [`WordAddrBus] id_pc; // Program counter
reg id_en; // Enable pipeline data
reg [`AluOpBus] id_alu_op; // ALU operation
reg [`WordDataBus] id_alu_in_0; // ALU reg 0
reg [`WordDataBus] id_alu_in_1; // ALU reg 1
reg id_br_flag; // Branch flag
reg [`MemOpBus] id_mem_op; // Memory operation
reg [`WordDataBus] id_mem_wr_data; // Memory write data
reg [`CtrlOpBus] id_ctrl_op; // Control register operation
reg [`RegAddrBus] id_dst_addr; // GPR write address
reg id_gpr_we_; // GPR write enable
reg [`IsaExpBus] id_exp_code; // Exception code
/********** EX/MEM pipeline register **********/
wire [`WordAddrBus] ex_pc; // Program counter
wire ex_en; // Enable pipeline data
wire ex_br_flag; // Branch flag
wire [`MemOpBus] ex_mem_op; // Memory operation
wire [`WordDataBus] ex_mem_wr_data; // Memory write data
wire [`CtrlOpBus] ex_ctrl_op; // Control register operation
wire [`RegAddrBus] ex_dst_addr; // GPR write address
wire ex_gpr_we_; // GPR write enable
wire [`IsaExpBus] ex_exp_code; // Exception code
wire [`WordDataBus] ex_out ; // Processing result
/********** ALU's wire **********/
wire[`WordDataBus] alu_out; // Result
wire alu_of; // Overflow
/********** Forwarding result **********/
assign fwd_data = alu_out;
integer i;
parameter STEP=100;
always#(STEP/2)begin
clk<=~clk;
end
//实例化
/********** ALU **********/
alu alu (
.in_0 (id_alu_in_0), // Input 0
.in_1 (id_alu_in_1), // Input 1
.op (id_alu_op), // Operation
.out (alu_out), // Output
.of (alu_of) // Overflow
);
/********** Pipeline register **********/
ex_reg ex_reg (
/********** Clock & Reset **********/
.clk (clk),
.reset (reset),
/********** ALU's output **********/
.alu_out (alu_out),
.alu_of (alu_of),
/********** Pipeline control signal **********/
.stall (stall),
.flush (flush),
.int_detect (int_detect),
/********** ID/EX pipeline register **********/
.id_pc (id_pc),
.id_en (id_en),
.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)
);
//测试
initial begin
#10 begin
clk<=1;
reset<=`RESET_ENABLE;
end
#(STEP*3/4)
#STEP begin
reset<=`RESET_DISABLE;
#STEP
id_alu_in_0<=32'd10;
id_alu_in_1<=32'd20;
id_alu_op<=4'b0100;
#STEP
stall <= `ENABLE;
#STEP
stall <= `DISABLE;
#STEP
id_en<=1'b1;
id_br_flag<=1'b0;
id_gpr_we_ <=1'b0;
id_exp_code<=3'b0;
end
#STEP
$finish;
end
endmodule
测试结果:
输入执行的指令和数据后,alu模块进行计算得到output30,溢出无效。
将得到的结果传入ex寄存器,最后输出,仿真结束。