aboutsummaryrefslogtreecommitdiff
path: root/hdl/control.v
blob: 58f273ffffd8c505133e84320940e87fabc4ded9 (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
106
107
108
109
110
111
112
113
114
`timescale 1ns / 1ps

module control(
               input [5:0]      opcode,
               input            branch_eq, // result of comparison for conditional branch

               output reg [1:0] if_pc_source,
               output           id_rt_is_source,    // rt is source

               output           ex_imm_command,
               output reg       ex_alu_src_b,
               output reg       ex_dst_reg_sel,
               output reg [1:0] ex_alu_op,
               output reg       mem_read,
               output reg       mem_write,
               output reg       wb_mem_to_reg,
               output reg       wb_reg_write
               );


   localparam 
     LW = 6'b100011, 
     SW = 6'b101011, 
     BEQ=6'b000100, 
     RTYPE = 6'b0, 
     J=6'd2, 
     JAL=6'd3,			
     ADDI = 6'b001000, 
     ANDI = 6'b001100, 
     ORI = 6'b001101, 
     XORI = 6'b001110, 
     SLTI = 6'b001010;     // opcodes

   reg    memory_op;
   reg    r_type_op;
   reg    immediate_op;
   reg    branch_op;
   reg    jump_op;
   

   assign ex_imm_command = immediate_op;
   assign id_rt_is_source = (r_type_op | branch_op | opcode == SW);
   
                           
   always @*
     begin
        // default values
        if_pc_source   = 0;
        ex_alu_src_b   = 0;
        ex_dst_reg_sel = 0;
        ex_alu_op      = 0;
        mem_read       = 0;
        mem_write      = 0;
        wb_mem_to_reg  = 0;
        wb_reg_write   = 0;

        memory_op = ( (opcode == LW) | (opcode == SW) );
        r_type_op  = ( opcode == RTYPE );
        branch_op = ( opcode == BEQ );
        immediate_op = ( (opcode == ADDI) | (opcode == ANDI) | (opcode == ORI) | (opcode == XORI) | (opcode == SLTI) );
        jump_op = ( opcode == J);
        
        if (memory_op) begin
           ex_alu_src_b = 1'b1;   // select sign_extend_offset input
           ex_dst_reg_sel = 1'b0; // rt
           ex_alu_op = 2'b00;     // add op
           wb_mem_to_reg = 1'b1;  // select mem_out
           
           if ( opcode == LW ) begin
              mem_read = 1'b1;
              wb_reg_write = 1'b1;              
           end
           else 
             mem_write = 1'b1; // opcode == SW
           
        end
        
        else if (r_type_op) begin
           ex_alu_src_b = 1'b0;   // select B input
           ex_dst_reg_sel = 1'b1; // rd
           ex_alu_op = 2'b10;     // operaction defined by func code
           
           wb_mem_to_reg = 1'b0;  // alu_out
           wb_reg_write  = 1'b1;  // write result to regfile           
        end

        else if (immediate_op) begin
           ex_alu_src_b = 1'b1; // select sign_extend_offset input
           ex_dst_reg_sel = 1'b0; // rt
           ex_alu_op = 2'b10; // operation defined by function code

           wb_mem_to_reg = 1'b0; // alu_out
           wb_reg_write = 1'b01;           
        end
        
        else if (branch_op) begin
           if (branch_eq) if_pc_source = 2'b01; // PC <= branch_addr
           else if_pc_source = 2'b00;
           
        end

        else if (jump_op) begin
           if_pc_source = 2'b10;  // PC <= jump_addr
        end
 
        else begin
           // NOP
        end
          
        
     end
   
   
endmodule