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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
|
module control_unit (
input clk, rst,
input [6:0] opcode,
input [2:0] funct3,
input [6:0] funct7,
input alu_zero,
input alu_equal,
output pc_we,
output reg mem_addr_src,
output reg mem_we,
output reg instr_we,
output reg [1:0] result_src,
output [3:0] alu_op,
output reg [1:0] alu_a_src,
output reg [1:0] alu_b_src,
output reg rf_we
);
parameter s00_fetch = 4'h0,
s01_decode = 4'h1,
s02_mem_addr = 4'h2,
s03_mem_read = 4'h3,
s04_mem_wb = 4'h4,
s05_mem_write = 4'h5,
s06_execute_r = 4'h6,
s07_alu_wb = 4'h7,
s08_execute_i = 4'h8,
s09_jal = 4'h9,
s10_beq = 4'ha;
reg [3:0] state, next_state;
always @ (posedge clk or posedge rst) begin
if (rst) state <= s00_fetch;
else state <= next_state;
end
always @ (*) begin
case(state)
s00_fetch: next_state <= s01_decode;
s01_decode: case(opcode)
7'b0000011: next_state <= s02_mem_addr;
7'b0100011: next_state <= s02_mem_addr;
7'b0110011: next_state <= s06_execute_r;
7'b0010011: next_state <= s08_execute_i;
7'b1101111: next_state <= s09_jal;
7'b1100011: next_state <= s10_beq;
endcase
s02_mem_addr: case(opcode)
7'b0000011: next_state <= s03_mem_read;
7'b0100011: next_state <= s05_mem_write;
endcase
s03_mem_read: next_state <= s04_mem_wb;
s04_mem_wb: next_state <= s00_fetch;
s05_mem_write: next_state <= s00_fetch;
s06_execute_r: next_state <= s07_alu_wb;
s07_alu_wb: next_state <= s00_fetch;
s08_execute_i: next_state <= s07_alu_wb;
s09_jal: next_state <= s07_alu_wb;
s10_beq: next_state <= s00_fetch;
endcase
end
reg branch;
reg pc_update;
reg [1:0] alu_ctrl;
assign pc_we = (alu_zero & branch) | pc_update;
always @ (*) begin
branch = 1'b0;
pc_update = 1'b0;
mem_we = 1'b0;
rf_we = 1'b0;
instr_we = 1'b0;
case(state)
s00_fetch: begin
mem_addr_src <= 1'b0;
instr_we = 1'b1;
alu_a_src <= 2'b00;
alu_b_src <= 2'b10;
alu_ctrl <= 2'b00;
result_src <= 2'b10;
pc_update = 1'b1;
end
s01_decode: begin
alu_a_src <= 2'b01;
alu_b_src <= 2'b01;
alu_ctrl <= 2'b00;
end
s02_mem_addr: begin
alu_a_src <= 2'b10;
alu_b_src <= 2'b01;
alu_ctrl <= 2'b00;
end
s03_mem_read: begin
result_src <= 2'b00;
mem_addr_src <= 1'b1;
end
s04_mem_wb: begin
result_src <= 2'b01;
rf_we = 1'b1;
end
s05_mem_write: begin
result_src <= 2'b00;
mem_addr_src <= 1'b1;
mem_we = 1'b1;
end
s06_execute_r: begin
alu_a_src <= 2'b10;
alu_b_src <= 2'b00;
alu_ctrl <= 2'b10;
end
s07_alu_wb: begin
result_src <= 2'b00;
rf_we = 1'b1;
end
s08_execute_i: begin
alu_a_src <= 2'b10;
alu_b_src <= 2'b01;
alu_ctrl <= 2'b10;
end
s09_jal: begin
alu_a_src <= 2'b01;
alu_b_src <= 2'b10;
alu_ctrl <= 2'b00;
result_src <= 2'b00;
pc_update = 1'b1;
end
s10_beq: begin
alu_a_src <= 2'b10;
alu_b_src <= 2'b00;
alu_ctrl <= 2'b01;
result_src <= 2'b00;
branch = 1'b1;
end
endcase
end
alu_op_decode aod (
.opcode(opcode),
.alu_ctrl(alu_ctrl),
.funct3(funct3),
.funct7(funct7),
.alu_op(alu_op)
);
endmodule
|