-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathControlUnit.vhd
326 lines (282 loc) · 8.17 KB
/
ControlUnit.vhd
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
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
-- Control Unit Code
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
entity ControlUnit is
port (
--Op code used for instructions (NOT the ALU Op)
OpCode: in std_logic_vector(2 downto 0);
--Clock Signal
clk: in std_logic;
--Load bits to basically turn components on and off at a given state
ToALoad: out std_logic;
ToMarLoad: out std_logic;
ToIrLoad: out std_logic;
ToMdriLoad: out std_logic;
ToMdroLoad: out std_logic;
ToPcIncrement: out std_logic := '0';
ToMarMux: out std_logic;
ToRamWriteEnable: out std_logic;
--This is the ALU op code, look inside the ALU code to set this
ToAluOp: out std_logic_vector(2 downto 0)
);
end ControlUnit;
architecture behavior of ControlUnit is
--Custom Data Type to Define Each State
type cu_state_type is (load_mar, read_mem, load_mdri, load_ir, decode,
ldaa_load_mar, ldaa_read_mem, ldaa_load_mdri, ldaa_load_a,
adaa_load_mar, adaa_read_mem, adaa_load_mdri, adaa_store_load_a,
staa_load_mdro, staa_load_mar, staa_write_mem, increment_pc
);
--Signal to hold current state
signal current_state : cu_state_type;
begin
--Defines the transitions in our state machine
process(clk)
begin
if (clk'event and clk = '1') then
case current_state is
--Increment the pc and fetch the instruction, then load the IR with the fetched instruction
--Decode the instruction, use the diagram in the handout to determine the next states
when increment_pc =>
current_state <= load_mar;
when load_mar =>
current_state <= read_mem;
when read_mem =>
current_state <= load_mdri;
when load_mdri =>
current_state <= load_ir;
when load_ir =>
current_state <= decode;
--Decode Opcode to determine Instruction
--Assign current state based on the opCode
when decode =>
if OpCode = "000" then
current_state <= ldaa_load_mar;
elsif OpCode = "001" then
current_state <= adaa_load_mar;
elsif OpCode = "010" then
current_state <= staa_load_mdro;
else
current_state <= increment_pc;
end if;
--Instructions, need to determine the next state to implement each instruction
--Follow the path to perform each instruction as described in the handout, and determine
--Where the state machine needs to go to implement the instruction
---Load instruction
when ldaa_load_mar =>
current_state <= ldaa_read_mem;
when ldaa_read_mem =>
current_state <= ldaa_load_mdri;
when ldaa_load_mdri =>
current_state <= ldaa_load_a;
when ldaa_load_a =>
current_state <= increment_pc;
--Add Instruction
when adaa_load_mar =>
current_state <= adaa_read_mem;
when adaa_read_mem =>
current_state <= adaa_load_mdri;
when adaa_load_mdri =>
current_state <= adaa_store_load_a;
when adaa_store_load_a =>
current_state <= increment_pc;
--Store Instruction
when staa_load_mdro =>
current_state <= staa_load_mar;
when staa_load_mar =>
current_state <= staa_write_mem;
when staa_write_mem =>
current_state <= increment_pc;
end case;
end if;
end process;
-- Defines what happens at each state, set to '1' if we want that component to be on
-- Set Op Code accordingly based on ALU, different from the instruction op code, look at the actual ALU code
-- Keep in mind when ToMarMux = 0 , MAR is loaded from PC address, when ToMarMux = 1, MAR is loaded with IR address
process(current_state)
begin
ToALoad <= '0';
ToMdroLoad <= '0';
ToAluOp <= "000";
case current_state is
--Turns on the increment pc bit
when increment_pc =>
ToALoad <= '0';
ToPcIncrement <= '1';
ToMarMux <= '0';
ToMarLoad <= '0';
ToRamWriteEnable <= '0';
ToMdriLoad <= '0';
ToIrLoad <= '0';
ToMdroLoad <= '0';
ToAluOp <= "000";
-- FETCH INSTRUCTION
--Loads MAR with address from program counter
when load_mar =>
ToALoad <= '0';
ToPcIncrement <= '0';
ToMarMux <= '0';
ToMarLoad <= '1';
ToRamWriteEnable <= '0';
ToMdriLoad <= '0';
ToIrLoad <= '0';
ToMdroLoad <= '0';
--Reads Address located in MAR
when read_mem =>
ToALoad <= '0';
ToPcIncrement <= '0';
ToMarMux <= '0';
ToMarLoad <= '0';
ToRamWriteEnable <= '0';
ToMdriLoad <= '0';
ToIrLoad <= '0';
ToMdroLoad <= '0';
--Load Memory Data Register Input
when load_mdri =>
ToALoad <= '0';
ToPcIncrement <= '0';
ToMarMux <= '0';
ToMarLoad <= '0';
ToRamWriteEnable <= '0';
ToMdriLoad <= '1';
ToIrLoad <= '0';
ToMdroLoad <= '0';
--Loads the Instruction Register with instruction fetched from Memory
when load_ir =>
ToALoad <= '0';
ToPcIncrement <= '0';
ToMarMux <= '0';
ToMarLoad <= '0';
ToRamWriteEnable <= '0';
ToMdriLoad <= '0';
ToIrLoad <= '1';
ToMdroLoad <= '0';
-- DECODE
--Decodes The current instruction (everything should be off for this)
when decode =>
ToALoad <= '0';
ToPcIncrement <= '0';
ToMarMux <= '0';
ToMarLoad <= '0';
ToRamWriteEnable <= '0';
ToMdriLoad <= '0';
ToIrLoad <= '0';
ToMdroLoad <= '0';
-- LOAD INSTRUCTION
--Loads the MAR with address stored in IR
when ldaa_load_mar =>
ToALoad <= '0';
ToPcIncrement <= '0';
ToMarMux <= '1';
ToMarLoad <= '1';
ToRamWriteEnable <= '0';
ToMdriLoad <= '0';
ToIrLoad <= '0';
ToMdroLoad <= '0';
ToAluOp <= "101";
--Reads Data in memory retrieved from Address in MAR
when ldaa_read_mem =>
ToALoad <= '0';
ToPcIncrement <= '0';
ToMarMux <= '0';
ToMarLoad <= '1';
ToRamWriteEnable <= '0';
ToMdriLoad <= '0';
ToIrLoad <= '0';
ToMdroLoad <= '0';
ToAluOp <= "101";
--Loads the Memory data Register Input with data read from memory
when ldaa_load_mdri =>
ToALoad <= '0';
ToPcIncrement <= '0';
ToMarMux <= '0';
ToMarLoad <= '0';
ToRamWriteEnable <= '0';
ToMdriLoad <= '1';
ToIrLoad <= '0';
ToMdroLoad <= '0';
ToAluOp <= "101";
--Loads the accumulator with data held in MDRI
when ldaa_load_a =>
ToALoad <= '1';
ToPcIncrement <= '0';
ToMarMux <= '0';
ToMarLoad <= '0';
ToRamWriteEnable <= '0';
ToMdriLoad <= '0';
ToIrLoad <= '0';
ToMdroLoad <= '0';
ToAluOp <= "101";
-- ADDA INSTRUCTION
--Loads the MAR with address held in IR
when adaa_load_mar =>
ToALoad <= '0';
ToPcIncrement <= '0';
ToMarMux <= '1';
ToMarLoad <= '1';
ToRamWriteEnable <= '0';
ToMdriLoad <= '0';
ToIrLoad <= '0';
ToMdroLoad <= '0';
ToAluOp <= "000";
--Reads Memory based on address in MAR
when adaa_read_mem =>
ToALoad <= '0';
ToPcIncrement <= '0';
ToMarMux <= '0';
ToMarLoad <= '0';
ToRamWriteEnable <= '0';
ToMdriLoad <= '0';
ToIrLoad <= '0';
ToMdroLoad <= '0';
ToAluOp <= "000";
--Loads MDRI with data just read from memory
when adaa_load_mdri =>
ToALoad <= '0';
ToPcIncrement <= '0';
ToMarMux <= '0';
ToMarLoad <= '0';
ToRamWriteEnable <= '0';
ToMdriLoad <= '1';
ToIrLoad <= '0';
ToMdroLoad <= '0';
ToAluOp <= "000";
--Loads accumulator with data in MDRI
when adaa_store_load_a =>
ToALoad <= '1';
ToPcIncrement <= '0';
ToMarMux <= '0';
ToMarLoad <= '0';
ToRamWriteEnable <= '0';
ToMdriLoad <= '0';
ToIrLoad <= '0';
ToMdroLoad <= '0';
ToAluOp <= "000";
-- STOREA INSTRUCTION
--Loads MDRO with data to be written to memory (this data comes from the accumulator)
when staa_load_mdro =>
ToALoad <= '0';
ToPcIncrement <= '0';
ToMarMux <= '0';
ToMarLoad <= '0';
ToRamWriteEnable <= '0';
ToMdriLoad <= '0';
ToIrLoad <= '0';
ToMdroLoad <= '1';
ToAluOp <= "000";
--Writes to memory the data stored in MDRO
when staa_write_mem =>
ToALoad <= '0';
ToPcIncrement <= '0';
ToMarMux <= '0';
ToMarLoad <= '0';
ToRamWriteEnable <= '1';
ToMdriLoad <= '0';
ToIrLoad <= '0';
ToMdroLoad <= '0';
ToAluOp <= "000";
end case;
end process;
end behavior;