-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcontrol_unit.vhd
220 lines (173 loc) · 9.95 KB
/
control_unit.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
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity control_unit is
port(
clock : in std_logic;
reset : in std_logic;
-- ROM Data
rom_data : in unsigned(15 downto 0); -- Instruction
-- RAM Data
ram_data_in : out unsigned(15 downto 0);
ram_address : out unsigned(6 downto 0);
ram_write_en : out std_logic;
selec_regFile_input : out std_logic;
regA_out : in unsigned(15 downto 0);
regB_out : in unsigned(15 downto 0);
-- ULA Data
ULA_out : in unsigned(15 downto 0); -- Result of past ULA operation
ULA_inputB : out std_logic; -- Either a constant or register B
ULA_selec_op : out unsigned(1 downto 0); -- Code for ULA operation selection
PC_data_out : in unsigned(6 downto 0); -- Output data from PC
PC_data_in : out unsigned(6 downto 0); -- Current PC data
-- Flags for Jump Conditions
flag_zero : in std_logic;
flag_not_zero : in std_logic;
flag_less : in std_logic;
-- Conditions for setting flags
is_zero : out std_logic;
is_not_zero : out std_logic;
is_less : out std_logic;
-- Register Selection
-- registers A & B to get data, and a register to be written
selec_regA : out unsigned(2 downto 0);
selec_regB : out unsigned(2 downto 0);
selec_regWrite : out unsigned(2 downto 0);
not_jump_intruction : out std_logic; -- Flag used to indicate if current instruction is not a jump instruction,
-- if it's not then jump condition flags need to be updated
-- it is used as a write enable for the jump condition flip flops
carry_subt : in std_logic;
const : out unsigned(15 downto 0);
write_en : out std_logic;
PC_write_en : out std_logic
);
end entity;
architecture a_control_unit of control_unit is
component state_mach is
port(
clock : in std_logic;
reset : in std_logic;
state : out unsigned(1 downto 0)
);
end component;
signal opcode : unsigned(3 downto 0);
signal state_sig : unsigned(1 downto 0);
signal jump_address : unsigned(6 downto 0);
signal jump_en : std_logic;
-- Receives the part of the instruction that indicates the condition for a conditional jump instruction
signal jump_condition : unsigned(1 downto 0);
-- Constants for State Codes
constant fetch_state : unsigned(1 downto 0) := "00";
constant decode_state : unsigned(1 downto 0) := "01";
constant execution_state : unsigned(1 downto 0) := "10";
-- Constants for opcodes
constant nop_opcode : unsigned(3 downto 0) := "0000"; -- NOP
constant load_opcode : unsigned(3 downto 0) := "0001"; -- MOV <reg>, <value>
constant copy_opcode : unsigned(3 downto 0) := "0010"; -- MOV <reg>, <reg>
constant add_opcode : unsigned(3 downto 0) := "0011"; -- ADD <reg>, <reg>
constant subt_opcode : unsigned(3 downto 0) := "0100"; -- SUB <reg>, <reg>
constant cmp_opcode : unsigned(3 downto 0) := "0101"; -- CMP <reg>, <reg>
constant loadRAM_opcode : unsigned(3 downto 0) := "0111"; -- MOV <address>, <reg>
constant readRAM_opcode : unsigned(3 downto 0) := "1000"; -- MOV <reg>, <reg>
constant jmpa_opcode : unsigned(3 downto 0) := "1101"; -- JMPA <condition code>, <address>
constant jmpr_opcode : unsigned(3 downto 0) := "1110"; -- JMPR <condition code>, <value>
constant jmps_opcode : unsigned(3 downto 0) := "1111"; -- JMPS <address>
-- Constants for ULA operations
constant sum_operation : unsigned(1 downto 0) := "00";
constant subt_operation : unsigned(1 downto 0) := "01";
constant less_operation : unsigned(1 downto 0) := "10";
constant dif_operation : unsigned(1 downto 0) := "11";
-- Constants for Jump Conditions
constant equal_zero : unsigned(1 downto 0) := "01";
constant not_zero : unsigned(1 downto 0) := "10";
constant less : unsigned(1 downto 0) := "11";
-- Constants for ULA InputB Mux Selection
constant selec_const : std_logic := '0';
constant selec_mux_regB : std_logic := '1';
begin
state_mach_pm: state_mach port map(
clock => clock,
reset => reset,
state => state_sig
);
----------------------------- INSTRUCTION FETCH -----------------------------
-- reads ROM when 0, increments PC when 1
PC_write_en <= '1' when state_sig = fetch_state else
'0';
----------------------------- INSTRUCTION DECODE -----------------------------
opcode <= rom_data(15 downto 12);
ram_address <= rom_data(9 downto 3) when (opcode = loadRAM_opcode and rom_data(11 downto 10) = "00") else
regA_out(6 downto 0) when (opcode = loadRAM_opcode and rom_data(11 downto 10) = "01") else
regB_out(6 downto 0) when (opcode = readRAM_opcode) else
"0000000";
ram_data_in <= regB_out when (opcode = loadRAM_opcode) else
"0000000000000000";
-- Set condition for jump
jump_condition <= rom_data(11 downto 10) when (opcode = jmpa_opcode or opcode = jmpr_opcode) else
"00";
-- Set address for jump
-- > absolute and unconditional when JMPS
-- > absolute and conditional when JMPA
-- > relative and conditional when JMPR
jump_address <= rom_data(6 downto 0) when (opcode = jmps_opcode or opcode = jmpa_opcode) else
(rom_data(6 downto 0) + PC_data_out) when (opcode = jmpr_opcode) else
"0000000";
-- Jump Enable will be '1' when there is an unconditional jump opcode or
-- when there is a conditional jump opcode and the proper condition is selected and checked
jump_en <= '1' when (opcode = jmps_opcode or ((opcode = jmpa_opcode or opcode = jmpr_opcode) and
((flag_zero = '1' and jump_condition = equal_zero) or
(flag_not_zero = '1' and jump_condition = not_zero) or
(flag_less = '1' and jump_condition = less)))) else
'0';
ULA_selec_op <= sum_operation when opcode = load_opcode else
sum_operation when opcode = add_opcode else
subt_operation when opcode = subt_opcode else
less_operation when opcode = cmp_opcode else
"00";
----------------------------- INSTRUCTION EXECUTION -----------------------------
selec_regA <= "000" when (opcode = load_opcode or opcode = copy_opcode) else
rom_data(5 downto 3) when (opcode = loadRAM_opcode and rom_data(11 downto 10) = "01") else
rom_data(11 downto 9) when (opcode = add_opcode or opcode = subt_opcode or opcode = cmp_opcode) else
"000";
selec_regB <= rom_data(8 downto 6) when (opcode = copy_opcode) or
(opcode = add_opcode) or
(opcode = subt_opcode) or
(opcode = cmp_opcode) or
(opcode = readRAM_opcode) else
rom_data(2 downto 0) when (opcode = loadRAM_opcode) else
"000";
-- Concatenate constant to form 16 bit word for ULA
const <= "0000000" & rom_data(8 downto 0) when rom_data(8) = '0' else
"1111111" & rom_data(8 downto 0);
selec_regWrite <= rom_data(11 downto 9);
PC_data_in <= PC_data_out + "0000001" when jump_en = '0' else
jump_address when jump_en = '1';
-- Select if ULA data input will be register B output (0) or constant (1)
ULA_inputB <= selec_const when opcode = load_opcode else
selec_mux_regB;
write_en <= '1' when (state_sig = execution_state and ((opcode = load_opcode) or
(opcode = copy_opcode) or
(opcode = add_opcode) or
(opcode = subt_opcode) or
(opcode = readRAM_opcode))) else
'0';
ram_write_en <= '1' when (state_sig = execution_state and (opcode = loadRAM_opcode)) else
'0';
-- Select if Register File data input will be ULA output (0) or RAM output (1)
selec_regFile_input <= '1' when (opcode = readRAM_opcode) else
'0';
----- Setting signals used for setting jump condition flags -----
is_zero <= '1' when (((opcode = add_opcode) or
(opcode = subt_opcode)) and ULA_out = "0000000000000000") else
'0';
is_not_zero <= '0' when (((opcode = add_opcode) or
(opcode = subt_opcode)) and ULA_out = "0000000000000000") else
'1';
is_less <= '1' when ((opcode = cmp_opcode) and carry_subt = '1') else
'0';
-----------------------------------------------------------------
not_jump_intruction <= '1' when (state_sig = execution_state and ((opcode = add_opcode) or
(opcode = subt_opcode) or
(opcode = cmp_opcode))) else
'0';
end architecture;