-
Notifications
You must be signed in to change notification settings - Fork 1
/
cpu.vhd
262 lines (233 loc) · 8.34 KB
/
cpu.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
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.P_ALU.all;
use work.P_REGS.all;
use work.P_CONTROL.all;
entity cpu is
port (
CLOCK : in STD_LOGIC;
CLOCK_MAIN : out STD_LOGIC;
RESET : in STD_LOGIC;
ADDRESS : out STD_LOGIC_VECTOR (14 downto 0);
UPPER_DATA : out STD_LOGIC;
LOWER_DATA : out STD_LOGIC;
DATA_IN : in STD_LOGIC_VECTOR (15 downto 0);
DATA_OUT : out STD_LOGIC_VECTOR (15 downto 0);
BUS_ERROR : out STD_LOGIC;
READ : out STD_LOGIC;
WRITE : out STD_LOGIC;
HALTED : out STD_LOGIC
);
end entity;
architecture behavioural of cpu is
-- Clocks
signal LOCAL_CLOCK_MAIN : STD_LOGIC := '0';
-- The mux selectors
signal ALU_LEFT_MUX_SEL : T_ALU_LEFT_MUX_SEL;
signal ALU_RIGHT_MUX_SEL : T_ALU_RIGHT_MUX_SEL;
signal ALU_OP_MUX_SEL : T_ALU_OP_MUX_SEL;
signal REGS_INPUT_MUX_SEL : T_REGS_INPUT_MUX_SEL;
signal TEMPORARY_INPUT_MUX_SEL : T_TEMPORARY_INPUT_MUX_SEL;
signal PC_INPUT_MUX_SEL : T_PC_INPUT_MUX_SEL;
signal ADDRESS_MUX_SEL : T_ADDRESS_MUX_SEL;
signal DATA_OUT_MUX_SEL : T_DATA_OUT_MUX_SEL;
-- Internal side of bus
signal CYCLETYPE : T_CYCLETYPE;
signal CPU_READ : STD_LOGIC := '0';
signal CPU_WRITE : STD_LOGIC := '0';
signal CPU_DATA_IN_EXTENDED : T_REG := (others => '0');
signal CPU_ADDRESS : STD_LOGIC_VECTOR (15 downto 0) := (others => '0');
signal CPU_BUS_ACTIVE : STD_LOGIC := '0';
signal CPU_DATA_IN : STD_LOGIC_VECTOR (15 downto 0) := (others => '0');
signal CPU_DATA_OUT : STD_LOGIC_VECTOR (15 downto 0) := (others => '0');
signal CPU_CYCLETYPE_BYTE : STD_LOGIC := '0';
-- Instruction
signal INSTRUCTION_WRITE : STD_LOGIC := '0';
signal INSTRUCTION_OPCODE : T_OPCODE := (others => '0');
signal INSTRUCTION_PARAMS : STD_LOGIC_VECTOR (9 downto 0) := (others => '0');
signal INSTRUCTION_ALU_OP : T_ALU_OP := (others => '0');
signal INSTRUCTION_FLOW_CARES : T_FLOWTYPE := (others => '0');
signal INSTRUCTION_FLOW_POLARITY : T_FLOWTYPE := (others => '0');
signal INSTRUCTION_CYCLETYPE : T_CYCLETYPE := (others => '0');
signal INSTRUCTION_LEFT_INDEX : T_REG_INDEX := (others => '0');
signal INSTRUCTION_RIGHT_INDEX : T_REG_INDEX := (others => '0');
-- ALU
signal ALU_OP : T_ALU_OP := (others => '0');
signal ALU_LEFT_IN : STD_LOGIC_VECTOR (15 downto 0) := (others => '0');
signal ALU_RIGHT_IN : STD_LOGIC_VECTOR (15 downto 0) := (others => '0');
signal ALU_CARRY_IN : STD_LOGIC := '0';
signal ALU_RESULT : STD_LOGIC_VECTOR (15 downto 0) := (others => '0'); -- outputs
signal ALU_CARRY_OUT : STD_LOGIC := '0';
signal ALU_ZERO_OUT : STD_LOGIC := '0';
signal ALU_NEG_OUT : STD_LOGIC := '0';
signal ALU_OVER_OUT : STD_LOGIC := '0';
-- Registers
signal REGS_CLEAR : STD_LOGIC := '0';
signal REGS_WRITE : STD_LOGIC := '0';
signal REGS_INC : STD_LOGIC := '0';
signal REGS_DEC : STD_LOGIC := '0';
signal REGS_WRITE_INDEX : T_REG_INDEX := (others => '0');
signal REGS_LEFT_OUTPUT : T_REG := (others => '0');
signal REGS_RIGHT_OUTPUT : T_REG := (others => '0');
signal REGS_INPUT : T_REG := (others => '0');
-- PC
signal PC_JUMP : STD_LOGIC := '0';
signal PC_BRANCH : STD_LOGIC := '0';
signal PC_INCREMENT : STD_LOGIC := '0';
signal PC_INPUT : T_REG := (others => '0');
signal PC_OUTPUT : T_REG := (others => '0');
-- Temporary
signal TEMPORARY_WRITE : STD_LOGIC := '0';
signal TEMPORARY_INPUT : T_REG := (others => '0');
signal TEMPORARY_OUTPUT : T_REG := (others => '0');
begin
clockdiv: entity work.clockdiv port map (
CLOCK => CLOCK,
CLOCK_MAIN => LOCAL_CLOCK_MAIN
);
control: entity work.control port map (
CLOCK => LOCAL_CLOCK_MAIN,
RESET => RESET,
DATA_IN => DATA_IN,
READ => CPU_READ,
WRITE => CPU_WRITE,
CYCLETYPE => CYCLETYPE,
HALTED => HALTED,
ALU_LEFT_MUX_SEL => ALU_LEFT_MUX_SEL,
ALU_RIGHT_MUX_SEL => ALU_RIGHT_MUX_SEL,
ALU_OP_MUX_SEL => ALU_OP_MUX_SEL,
REGS_INPUT_MUX_SEL => REGS_INPUT_MUX_SEL,
PC_INPUT_MUX_SEL => PC_INPUT_MUX_SEL,
TEMPORARY_INPUT_MUX_SEL => TEMPORARY_INPUT_MUX_SEL,
ADDRESS_MUX_SEL => ADDRESS_MUX_SEL,
DATA_OUT_MUX_SEL => DATA_OUT_MUX_SEL,
INSTRUCTION_WRITE => INSTRUCTION_WRITE,
INSTRUCTION_OPCODE => INSTRUCTION_OPCODE,
INSTRUCTION_PARAMS => INSTRUCTION_PARAMS,
INSTRUCTION_FLOW_CARES => INSTRUCTION_FLOW_CARES,
INSTRUCTION_FLOW_POLARITY => INSTRUCTION_FLOW_POLARITY,
INSTRUCTION_CYCLETYPE => INSTRUCTION_CYCLETYPE,
ALU_CARRY_IN => ALU_CARRY_IN,
ALU_CARRY_OUT => ALU_CARRY_OUT,
ALU_ZERO_OUT => ALU_ZERO_OUT,
ALU_NEG_OUT => ALU_NEG_OUT,
ALU_OVER_OUT => ALU_OVER_OUT,
REGS_CLEAR => REGS_CLEAR,
REGS_WRITE => REGS_WRITE,
REGS_INC => REGS_INC,
REGS_DEC => REGS_DEC,
PC_JUMP => PC_JUMP,
PC_INCREMENT => PC_INCREMENT,
TEMPORARY_WRITE => TEMPORARY_WRITE,
TEMPORARY_OUTPUT => TEMPORARY_OUTPUT
);
instruction: entity work.instruction port map (
CLOCK => LOCAL_CLOCK_MAIN,
RESET => RESET,
CYCLETYPE => INSTRUCTION_CYCLETYPE,
WRITE => INSTRUCTION_WRITE,
INPUT => DATA_IN,
OPCODE => INSTRUCTION_OPCODE,
PARAMS => INSTRUCTION_PARAMS,
ALU_OP => INSTRUCTION_ALU_OP,
LEFT_INDEX => INSTRUCTION_LEFT_INDEX,
RIGHT_INDEX => INSTRUCTION_RIGHT_INDEX,
FLOW_CARES => INSTRUCTION_FLOW_CARES,
FLOW_POLARITY => INSTRUCTION_FLOW_POLARITY
);
alu: entity work.alu port map (
OP => ALU_OP,
LEFT => ALU_LEFT_IN,
RIGHT => ALU_RIGHT_IN,
CARRY_IN => ALU_CARRY_IN,
RESULT => ALU_RESULT,
CARRY_OUT => ALU_CARRY_OUT,
ZERO_OUT => ALU_ZERO_OUT,
NEG_OUT => ALU_NEG_OUT,
OVER_OUT => ALU_OVER_OUT
);
registers: entity work.registers port map (
CLOCK => LOCAL_CLOCK_MAIN,
RESET => RESET,
CLEAR => REGS_CLEAR,
WRITE => REGS_WRITE,
INC => REGS_INC,
DEC => REGS_DEC,
READ_LEFT_INDEX => INSTRUCTION_LEFT_INDEX,
READ_RIGHT_INDEX => INSTRUCTION_RIGHT_INDEX,
WRITE_INDEX => INSTRUCTION_RIGHT_INDEX,
INCDEC_INDEX => INSTRUCTION_LEFT_INDEX,
LEFT_OUTPUT => REGS_LEFT_OUTPUT,
RIGHT_OUTPUT => REGS_RIGHT_OUTPUT,
INPUT => REGS_INPUT
);
programcounter: entity work.programcounter port map (
CLOCK => LOCAL_CLOCK_MAIN,
RESET => RESET,
JUMP => PC_JUMP,
INPUT => PC_INPUT,
INCREMENT => PC_INCREMENT,
OUTPUT => PC_OUTPUT
);
temporary: entity work.temporary port map (
CLOCK => LOCAL_CLOCK_MAIN,
RESET => RESET,
WRITE => TEMPORARY_WRITE,
INPUT => TEMPORARY_INPUT,
OUTPUT => TEMPORARY_OUTPUT
);
businterface: entity work.businterface port map (
CLOCK => CLOCK,
RESET => RESET,
CPU_ADDRESS => CPU_ADDRESS,
CPU_BUS_ACTIVE => CPU_BUS_ACTIVE,
CPU_CYCLETYPE_BYTE => CPU_CYCLETYPE_BYTE,
CPU_DATA_OUT => CPU_DATA_OUT,
CPU_DATA_IN => CPU_DATA_IN,
CPU_READ => CPU_READ,
CPU_WRITE => CPU_WRITE,
BUSINTERFACE_ADDRESS => ADDRESS,
BUSINTERFACE_DATA_IN => DATA_IN,
BUSINTERFACE_DATA_OUT => DATA_OUT,
BUSINTERFACE_UPPER_DATA => UPPER_DATA,
BUSINTERFACE_LOWER_DATA => LOWER_DATA,
BUSINTERFACE_ERROR => BUS_ERROR,
BUSINTERFACE_READ => READ,
BUSINTERFACE_WRITE => WRITE
);
-- Sign extend for data into a register, ie. LOADR, LOADRD
CPU_DATA_IN_EXTENDED <=
(8 to 15 => CPU_DATA_IN (7)) & CPU_DATA_IN (7 downto 0) when
(CYCLETYPE = CYCLETYPE_BYTE_SIGNED) else
(8 to 15 => '0') & CPU_DATA_IN (7 downto 0) when
(CYCLETYPE = CYCLETYPE_BYTE_UNSIGNED) else
CPU_DATA_IN;
ALU_LEFT_IN <= PC_OUTPUT when (ALU_LEFT_MUX_SEL = S_PC) else
REGS_LEFT_OUTPUT when (ALU_LEFT_MUX_SEL = S_INSTRUCTION_LEFT) else
CPU_DATA_IN;
ALU_RIGHT_IN <= REGS_RIGHT_OUTPUT when (ALU_RIGHT_MUX_SEL = S_INSTRUCTION_RIGHT) else
CPU_DATA_IN;
ALU_OP <= INSTRUCTION_ALU_OP when (ALU_OP_MUX_SEL = S_INSTRUCTION_ALU_OP) else
OP_ADD;
REGS_INPUT <= ALU_RESULT when (REGS_INPUT_MUX_SEL = S_ALU_RESULT) else
CPU_DATA_IN_EXTENDED;
TEMPORARY_INPUT <= CPU_DATA_IN when (TEMPORARY_INPUT_MUX_SEL = S_DATA_IN) else
ALU_RESULT;
PC_INPUT <= CPU_DATA_IN when (PC_INPUT_MUX_SEL = S_DATA_IN) else
TEMPORARY_OUTPUT when (PC_INPUT_MUX_SEL = S_TEMPORARY_OUTPUT) else
ALU_RESULT;
CPU_ADDRESS <= PC_OUTPUT when (ADDRESS_MUX_SEL = S_PC) else
REGS_LEFT_OUTPUT when (ADDRESS_MUX_SEL = S_INSTRUCTION_LEFT) else
ALU_RESULT when (ADDRESS_MUX_SEL = S_ALU_RESULT) else
TEMPORARY_OUTPUT;
CPU_DATA_OUT <= PC_OUTPUT when (DATA_OUT_MUX_SEL = S_PC) else
REGS_RIGHT_OUTPUT;
-- Set the byte cycle state, if we are doing one.
CPU_CYCLETYPE_BYTE <= '1' when (
(CYCLETYPE = CYCLETYPE_BYTE_SIGNED or CYCLETYPE = CYCLETYPE_BYTE_UNSIGNED)
) else '0';
CPU_BUS_ACTIVE <= '1' when (CPU_READ = '1' or CPU_WRITE = '1') else '0';
CLOCK_MAIN <= LOCAL_CLOCK_MAIN;
end architecture;