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
|