aboutsummaryrefslogtreecommitdiff
path: root/hdl/ex_stage.v
blob: 082113e00187b7c5d2cd62877e8ac5f55bf10ce9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
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
                
                 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;
               default: alu_a_in = 0;   // 
          endcase
     end

     always @* begin
          case(rt_fwd_sel)
               0: b_value = B;
               1: b_value = mem_fwd_val;
               2: b_value = wb_fwd_val;
               default: b_value = 0;    //
          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