aboutsummaryrefslogtreecommitdiff
path: root/hdl/ex_stage.v
diff options
context:
space:
mode:
Diffstat (limited to 'hdl/ex_stage.v')
-rw-r--r--hdl/ex_stage.v120
1 files changed, 120 insertions, 0 deletions
diff --git a/hdl/ex_stage.v b/hdl/ex_stage.v
new file mode 100644
index 0000000..cca87e9
--- /dev/null
+++ b/hdl/ex_stage.v
@@ -0,0 +1,120 @@
+module ex_stage(
+ input clk,
+ input rst,
+
+ input wb_reg_write,
+ input wb_mem_to_reg,
+
+ input mem_read,
+ input mem_write,
+
+ input ex_imm_command,
+ input ex_alu_src_b,
+ input ex_dst_reg_sel,
+ input [1:0] ex_alu_op,
+
+ input [31:0] A,
+ input [31:0] B,
+ input [31:0] sign_extend_offset,
+ input [4:0] rt, // target register
+ input [4:0] rd, // destination register
+ input [5:0] opcode,
+ input [1:0] rs_fwd_sel, // forwarding muxes control
+ input [1:0] rt_fwd_sel, // forwarding muxes control
+ input [31:0] mem_fwd_val, // forwarding from EX_MEM
+ input [31:0] wb_fwd_val, // forwarding from WB
+
+ // outputs
+ output [4:0] ex_dst_reg,
+ output [5:0] ex_opcode,
+
+ output reg [31:0] EX_MEM_alu_result,
+ output reg [31:0] EX_MEM_B_value,
+ output reg [4:0] EX_MEM_dst_reg,
+ output reg [5:0] EX_MEM_opcode,
+ output reg EX_MEM_mem_read,
+ output reg EX_MEM_mem_write,
+ output reg EX_MEM_wb_reg_write,
+ output reg EX_MEM_wb_mem_to_reg
+);
+
+
+ wire [5:0] func_field; // func code field in instruction
+ wire [5:0] func_code; // func code for ALU control
+ wire [4:0] alu_ctl; // ALU control lines
+
+ reg [31:0] alu_a_in;
+ wire [31:0] alu_b_in;
+ reg[31:0] b_value;
+
+ wire [31:0] alu_result;
+ wire zero;
+
+
+ always @*
+ begin
+ case(rs_fwd_sel)
+ 0: alu_a_in = A;
+ 1: alu_a_in = mem_fwd_val;
+ 2: alu_a_in = wb_fwd_val;
+ endcase
+ end
+
+ always @*
+ begin
+ case(rt_fwd_sel)
+ 0: b_value = B;
+ 1: b_value = mem_fwd_val;
+ 2: b_value = wb_fwd_val;
+ endcase
+ end
+
+ assign alu_b_in = ex_alu_src_b ? sign_extend_offset : b_value;
+ assign func_field = sign_extend_offset [5:0]; // looks wierd, but func code is encoded there
+ assign func_code = ex_imm_command ? {{2'b10},{~opcode[2] & opcode[1] & ~opcode[0]},opcode[2:0]} : func_field;
+ assign ex_opcode = opcode;
+ assign ex_dst_reg = ex_dst_reg_sel ? rd : rt;
+
+
+
+ alu_ctrl aluctl_inst(
+ .alu_op (ex_alu_op),
+ .func_code (func_code),
+ .alu_ctl (alu_ctl)
+ );
+
+ alu alu_inst (
+ .alu_ctl (alu_ctl),
+ .a_in (alu_a_in),
+ .b_in (alu_b_in),
+ .result (alu_result),
+ .zero_flag (zero)
+ );
+
+ // EX/MEM Pipeline register
+ always @(posedge clk) begin
+ if (rst)
+ begin
+ EX_MEM_alu_result <= 0;
+ EX_MEM_B_value <= 0;
+ EX_MEM_dst_reg <= 0;
+ EX_MEM_mem_read <= 0;
+ EX_MEM_mem_write <= 0;
+ EX_MEM_wb_reg_write <= 0;
+ EX_MEM_wb_mem_to_reg <= 0;
+ end
+ else
+ begin
+ EX_MEM_alu_result <= alu_result;
+ EX_MEM_B_value <= b_value;
+ EX_MEM_dst_reg <= ex_dst_reg;
+ EX_MEM_opcode <= opcode;
+ EX_MEM_mem_read <= mem_read;
+ EX_MEM_mem_write <= mem_write;
+ EX_MEM_wb_reg_write <= wb_reg_write;
+ EX_MEM_wb_mem_to_reg <= wb_mem_to_reg;
+ end
+ end
+
+
+endmodule