-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathControlUnit.v
More file actions
257 lines (182 loc) · 7.84 KB
/
Copy pathControlUnit.v
File metadata and controls
257 lines (182 loc) · 7.84 KB
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
`include "constants.v"
module controlUnit(
clock,
// Signals to be outputted by the CU
sigPCSrc,
sigDstReg,
sigRB,
sigENW,
sigALUSrc,
sigALUOp,
sigExt,
sigNewSP,
sigStackMem,
sigAddData,
sigMemR,
sigMemW,
sigWB,
sigWriteVal,
// Enable signals to be outputted by the CU
enIF, // enable instruction fetch
enID, // enable instruction decode
enE, // enable execute
enMem,// enable memory
enWRB,
// Inputs for CU, to manage branches, J-Type, and S-Type instructions
zeroFlag,
negativeFlag,
fullFlag,
emptyFlag,
// Opcode to determine signals
instructionCode
);
input wire clock;
input wire zeroFlag, negativeFlag, fullFlag, emptyFlag;
input wire [5:0] instructionCode;
output reg [2:0] sigPCSrc = pcDefault;
output reg [1:0] sigALUOp, sigNewSP;
output reg sigDstReg, sigRB, sigALUSrc, sigWB, sigExt, sigStackMem, sigAddData, sigWriteVal;
output reg sigENW = LOW,
sigMemW = LOW,
sigMemR = LOW;
output reg enE = LOW,
enIF = LOW,
enID = LOW,
enMem = LOW,
enWRB = LOW;
// Code to determine stages and manage stage paths
`define STG_FTCH 3'b000
`define STG_DCDE 3'b001
`define STG_EXEC 3'b010
`define STG_MEM 3'b011
`define STG_WRB 3'b100
`define STG_INIT 3'b101
reg [2:0] currentStage = `STG_INIT;
reg [2:0] nextStage = `STG_FTCH;
always@(posedge clock) begin
currentStage = nextStage;
end
always@(posedge clock) begin
case (currentStage)
`STG_INIT: begin
enIF = LOW;
nextStage <= `STG_FTCH;
end
`STG_FTCH: begin
// Disable all previous stages leading up to IF
enID = LOW;
enE = LOW;
enMem = LOW;
enWRB = LOW;
// Disable signals
sigENW = LOW;
sigMemW = LOW;
sigMemR = LOW;
sigNewSP = 2'd0;
// Enable IF
enIF = HIGH; // Fetch after finding PC src
// Determine next stage
nextStage <= `STG_DCDE;
// Determine next PC through testing of opcodes
if (instructionCode == BGT && negativeFlag || instructionCode == BLT && ~negativeFlag || instructionCode == BEQ && zeroFlag || instructionCode == BNE && ~zeroFlag) begin
sigPCSrc = pcSgnImm;
end else if (instructionCode == JMP || instructionCode == CALL) begin
sigPCSrc = pcImm;
end else if (instructionCode == RET) begin
sigPCSrc = pcStack;
end else begin
sigPCSrc = pcDefault;
end
end
`STG_DCDE: begin
// Disable all previous stages leading up to ID
enIF = LOW;
// Enable IF
enID = HIGH;
// Next stage is determined by opcode
if (instructionCode == CALL || instructionCode == RET) begin
nextStage <= `STG_MEM;
end
else if (instructionCode == JMP) begin
nextStage <= `STG_FTCH;
end
else begin
nextStage <= `STG_EXEC;
end
sigRB = (instructionCode == SW || instructionCode == BGT || instructionCode == BLT || instructionCode == BEQ || instructionCode == BNE || instructionCode == PUSH) ? HIGH : LOW;
sigDstReg = (instructionCode == LWPOI && enID) ? LOW : HIGH; // Destination Register is R1 for this stage
sigENW = (instructionCode == LWPOI || instructionCode == LW) ? HIGH : LOW;
sigExt = (instructionCode == ANDI) ? LOW : HIGH;
sigALUSrc = (instructionCode == ANDI || instructionCode == ADDI || instructionCode == LW || instructionCode == LWPOI || instructionCode == SW) ? LOW : HIGH;
sigWriteVal = (instructionCode == LWPOI && enID) ? LOW : HIGH;
end
`STG_EXEC: begin
// Disable all previous stages leading up to execute stage
enID = LOW;
// Enable execute stage
enE = HIGH;
// Next stage is determined by opcode
if (instructionCode == LW || instructionCode == LWPOI || instructionCode == SW || instructionCode == POP || instructionCode == PUSH) begin
nextStage <= `STG_MEM;
end else if (instructionCode == AND || instructionCode == ADD || instructionCode == SUB || instructionCode == ANDI || instructionCode == ADDI) begin
nextStage <= `STG_WRB;
end else begin
nextStage <= `STG_FTCH;
end
// Set ALUOp signal based on the opcodes
if (instructionCode == AND || instructionCode == ANDI) begin
sigALUOp = ALU_AND;
end else if (instructionCode == ADD || instructionCode == ADDI || instructionCode == LW || instructionCode == LWPOI || instructionCode == SW) begin
sigALUOp = ALU_ADD;
end else begin
sigALUOp = ALU_SUB;
end
sigENW = LOW;
end
`STG_MEM: begin
// Disable all previous stages leading up to memory stage
enE = LOW;
enID = LOW;
// Enable memory stage
enMem = HIGH;
// Next stage determined by opcodes
nextStage <= (instructionCode == LW || instructionCode == LWPOI || instructionCode == POP) ? `STG_WRB : `STG_FTCH;
// Memory write is determined by the SW instruction
sigMemW = (instructionCode == SW) ? HIGH : LOW;
// Memory Read is determined by Load instructions
sigMemR = (instructionCode == LW || instructionCode == LWPOI) ? HIGH : LOW;
// Signals determined by opcodes
sigStackMem = (instructionCode == CALL || instructionCode == RET || instructionCode == PUSH || instructionCode == POP) ? HIGH : LOW;
sigAddData = (instructionCode == CALL) ? HIGH : LOW;
// Stack pointer signal is determined by opcodes
if ((instructionCode == RET || instructionCode == POP) && ~emptyFlag) begin
sigNewSP = stackPointerPop;
end else if ((instructionCode == CALL || instructionCode == PUSH) && ~fullFlag) begin
sigNewSP = stackPointerPush;
end else begin
sigNewSP = stackPointerDef;
end
end
`STG_WRB: begin
// Disable all previous stages leading up to WRB
sigMemW = LOW;
sigMemR = LOW;
enE = LOW;
enMem = LOW;
sigNewSP = 2'b00;
// Enable WRB stage
enWRB = HIGH;
// Next stage following WRB is IF
nextStage <= `STG_FTCH;
// Enable writing to register filw
sigENW = HIGH;
sigENW = (instructionCode == SW || instructionCode == BGT || instructionCode == BLT || instructionCode == BEQ || instructionCode == BNE || instructionCode == JMP || instructionCode == CALL || instructionCode == PUSH) ? LOW : HIGH;
// Determine the register to write to
sigWB = (instructionCode == AND || instructionCode == ADD || instructionCode == SUB || instructionCode == ANDI || instructionCode == ADDI) ? LOW : HIGH;
// Set to 1 for all instructions
sigDstReg = HIGH;
sigWriteVal = HIGH;
end
endcase
end
endmodule