aboutsummaryrefslogtreecommitdiff
path: root/hdl/control.v
blob: 53a6d04182da642b2453b4b9c08c4e87516ae12a (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
`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 );

     //opcodes
     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;  
     //--------------------------------
   
     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'b1;           
          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)
               if_pc_source = 2'b10;  // PC <= jump_addr
          else begin
               //NOP
          end
     end
   
endmodule