]>
Commit | Line | Data |
---|---|---|
1 | -- | |
2 | -- Z80 compatible microprocessor core | |
3 | -- | |
4 | -- Version : 0247 | |
5 | -- | |
6 | -- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) | |
7 | -- | |
8 | -- All rights reserved | |
9 | -- | |
10 | -- Redistribution and use in source and synthezised forms, with or without | |
11 | -- modification, are permitted provided that the following conditions are met: | |
12 | -- | |
13 | -- Redistributions of source code must retain the above copyright notice, | |
14 | -- this list of conditions and the following disclaimer. | |
15 | -- | |
16 | -- Redistributions in synthesized form must reproduce the above copyright | |
17 | -- notice, this list of conditions and the following disclaimer in the | |
18 | -- documentation and/or other materials provided with the distribution. | |
19 | -- | |
20 | -- Neither the name of the author nor the names of other contributors may | |
21 | -- be used to endorse or promote products derived from this software without | |
22 | -- specific prior written permission. | |
23 | -- | |
24 | -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
25 | -- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | |
26 | -- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
27 | -- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE | |
28 | -- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
29 | -- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
30 | -- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
31 | -- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
32 | -- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
33 | -- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
34 | -- POSSIBILITY OF SUCH DAMAGE. | |
35 | -- | |
36 | -- Please report bugs to the author, but before you do so, please | |
37 | -- make sure that this is not a derivative work and that | |
38 | -- you have the latest version of this file. | |
39 | -- | |
40 | -- The latest version of this file can be found at: | |
41 | -- http://www.opencores.org/cvsweb.shtml/t80/ | |
42 | -- | |
43 | -- Limitations : | |
44 | -- | |
45 | -- File history : | |
46 | -- | |
47 | -- 0208 : First complete release | |
48 | -- | |
49 | -- 0210 : Fixed wait and halt | |
50 | -- | |
51 | -- 0211 : Fixed Refresh addition and IM 1 | |
52 | -- | |
53 | -- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test | |
54 | -- | |
55 | -- 0232 : Removed refresh address output for Mode > 1 and added DJNZ M1_n fix by Mike Johnson | |
56 | -- | |
57 | -- 0235 : Added clock enable and IM 2 fix by Mike Johnson | |
58 | -- | |
59 | -- 0237 : Changed 8080 I/O address output, added IntE output | |
60 | -- | |
61 | -- 0238 : Fixed (IX/IY+d) timing and 16 bit ADC and SBC zero flag | |
62 | -- | |
63 | -- 0240 : Added interrupt ack fix by Mike Johnson, changed (IX/IY+d) timing and changed flags in GB mode | |
64 | -- | |
65 | -- 0242 : Added I/O wait, fixed refresh address, moved some registers to RAM | |
66 | -- | |
67 | -- 0247 : Fixed bus req/ack cycle | |
68 | -- | |
69 | ||
70 | library IEEE; | |
71 | use IEEE.std_logic_1164.all; | |
72 | use IEEE.numeric_std.all; | |
73 | use work.T80_Pack.all; | |
74 | ||
75 | entity T80 is | |
76 | generic( | |
77 | Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB | |
78 | IOWait : integer := 0; -- 1 => Single cycle I/O, 1 => Std I/O cycle | |
79 | Flag_C : integer := 0; | |
80 | Flag_N : integer := 1; | |
81 | Flag_P : integer := 2; | |
82 | Flag_X : integer := 3; | |
83 | Flag_H : integer := 4; | |
84 | Flag_Y : integer := 5; | |
85 | Flag_Z : integer := 6; | |
86 | Flag_S : integer := 7 | |
87 | ); | |
88 | port( | |
89 | RESET_n : in std_logic; | |
90 | CLK_n : in std_logic; | |
91 | CEN : in std_logic; | |
92 | WAIT_n : in std_logic; | |
93 | INT_n : in std_logic; | |
94 | NMI_n : in std_logic; | |
95 | BUSRQ_n : in std_logic; | |
96 | M1_n : out std_logic; | |
97 | IORQ : out std_logic; | |
98 | NoRead : out std_logic; | |
99 | Write : out std_logic; | |
100 | RFSH_n : out std_logic; | |
101 | HALT_n : out std_logic; | |
102 | BUSAK_n : out std_logic; | |
103 | A : out std_logic_vector(15 downto 0); | |
104 | DInst : in std_logic_vector(7 downto 0); | |
105 | DI : in std_logic_vector(7 downto 0); | |
106 | DO : out std_logic_vector(7 downto 0); | |
107 | MC : out std_logic_vector(2 downto 0); | |
108 | TS : out std_logic_vector(2 downto 0); | |
109 | IntCycle_n : out std_logic; | |
110 | IntE : out std_logic; | |
111 | Stop : out std_logic | |
112 | ); | |
113 | end T80; | |
114 | ||
115 | architecture rtl of T80 is | |
116 | ||
117 | constant aNone : std_logic_vector(2 downto 0) := "111"; | |
118 | constant aBC : std_logic_vector(2 downto 0) := "000"; | |
119 | constant aDE : std_logic_vector(2 downto 0) := "001"; | |
120 | constant aXY : std_logic_vector(2 downto 0) := "010"; | |
121 | constant aIOA : std_logic_vector(2 downto 0) := "100"; | |
122 | constant aSP : std_logic_vector(2 downto 0) := "101"; | |
123 | constant aZI : std_logic_vector(2 downto 0) := "110"; | |
124 | ||
125 | -- Registers | |
126 | signal ACC, F : std_logic_vector(7 downto 0); | |
127 | signal Ap, Fp : std_logic_vector(7 downto 0); | |
128 | signal I : std_logic_vector(7 downto 0); | |
129 | signal R : unsigned(7 downto 0); | |
130 | signal SP, PC : unsigned(15 downto 0); | |
131 | signal RegDIH : std_logic_vector(7 downto 0); | |
132 | signal RegDIL : std_logic_vector(7 downto 0); | |
133 | signal RegBusA : std_logic_vector(15 downto 0); | |
134 | signal RegBusB : std_logic_vector(15 downto 0); | |
135 | signal RegBusC : std_logic_vector(15 downto 0); | |
136 | signal RegAddrA_r : std_logic_vector(2 downto 0); | |
137 | signal RegAddrA : std_logic_vector(2 downto 0); | |
138 | signal RegAddrB_r : std_logic_vector(2 downto 0); | |
139 | signal RegAddrB : std_logic_vector(2 downto 0); | |
140 | signal RegAddrC : std_logic_vector(2 downto 0); | |
141 | signal RegWEH : std_logic; | |
142 | signal RegWEL : std_logic; | |
143 | signal Alternate : std_logic; | |
144 | ||
145 | -- Help Registers | |
146 | signal TmpAddr : std_logic_vector(15 downto 0); -- Temporary address register | |
147 | signal IR : std_logic_vector(7 downto 0); -- Instruction register | |
148 | signal ISet : std_logic_vector(1 downto 0); -- Instruction set selector | |
149 | signal RegBusA_r : std_logic_vector(15 downto 0); | |
150 | ||
151 | signal ID16 : signed(15 downto 0); | |
152 | signal Save_Mux : std_logic_vector(7 downto 0); | |
153 | ||
154 | signal TState : unsigned(2 downto 0); | |
155 | signal MCycle : std_logic_vector(2 downto 0); | |
156 | signal IntE_FF1 : std_logic; | |
157 | signal IntE_FF2 : std_logic; | |
158 | signal Halt_FF : std_logic; | |
159 | signal BusReq_s : std_logic; | |
160 | signal BusAck : std_logic; | |
161 | signal ClkEn : std_logic; | |
162 | signal NMI_s : std_logic; | |
163 | signal INT_s : std_logic; | |
164 | signal IStatus : std_logic_vector(1 downto 0); | |
165 | ||
166 | signal DI_Reg : std_logic_vector(7 downto 0); | |
167 | signal T_Res : std_logic; | |
168 | signal XY_State : std_logic_vector(1 downto 0); | |
169 | signal Pre_XY_F_M : std_logic_vector(2 downto 0); | |
170 | signal NextIs_XY_Fetch : std_logic; | |
171 | signal XY_Ind : std_logic; | |
172 | signal No_BTR : std_logic; | |
173 | signal BTR_r : std_logic; | |
174 | signal Auto_Wait : std_logic; | |
175 | signal Auto_Wait_t1 : std_logic; | |
176 | signal Auto_Wait_t2 : std_logic; | |
177 | signal IncDecZ : std_logic; | |
178 | ||
179 | -- ALU signals | |
180 | signal BusB : std_logic_vector(7 downto 0); | |
181 | signal BusA : std_logic_vector(7 downto 0); | |
182 | signal ALU_Q : std_logic_vector(7 downto 0); | |
183 | signal F_Out : std_logic_vector(7 downto 0); | |
184 | ||
185 | -- Registered micro code outputs | |
186 | signal Read_To_Reg_r : std_logic_vector(4 downto 0); | |
187 | signal Arith16_r : std_logic; | |
188 | signal Z16_r : std_logic; | |
189 | signal ALU_Op_r : std_logic_vector(3 downto 0); | |
190 | signal Save_ALU_r : std_logic; | |
191 | signal PreserveC_r : std_logic; | |
192 | signal MCycles : std_logic_vector(2 downto 0); | |
193 | ||
194 | -- Micro code outputs | |
195 | signal MCycles_d : std_logic_vector(2 downto 0); | |
196 | signal TStates : std_logic_vector(2 downto 0); | |
197 | signal IntCycle : std_logic; | |
198 | signal NMICycle : std_logic; | |
199 | signal Inc_PC : std_logic; | |
200 | signal Inc_WZ : std_logic; | |
201 | signal IncDec_16 : std_logic_vector(3 downto 0); | |
202 | signal Prefix : std_logic_vector(1 downto 0); | |
203 | signal Read_To_Acc : std_logic; | |
204 | signal Read_To_Reg : std_logic; | |
205 | signal Set_BusB_To : std_logic_vector(3 downto 0); | |
206 | signal Set_BusA_To : std_logic_vector(3 downto 0); | |
207 | signal ALU_Op : std_logic_vector(3 downto 0); | |
208 | signal Save_ALU : std_logic; | |
209 | signal PreserveC : std_logic; | |
210 | signal Arith16 : std_logic; | |
211 | signal Set_Addr_To : std_logic_vector(2 downto 0); | |
212 | signal Jump : std_logic; | |
213 | signal JumpE : std_logic; | |
214 | signal JumpXY : std_logic; | |
215 | signal Call : std_logic; | |
216 | signal RstP : std_logic; | |
217 | signal LDZ : std_logic; | |
218 | signal LDW : std_logic; | |
219 | signal LDSPHL : std_logic; | |
220 | signal IORQ_i : std_logic; | |
221 | signal Special_LD : std_logic_vector(2 downto 0); | |
222 | signal ExchangeDH : std_logic; | |
223 | signal ExchangeRp : std_logic; | |
224 | signal ExchangeAF : std_logic; | |
225 | signal ExchangeRS : std_logic; | |
226 | signal I_DJNZ : std_logic; | |
227 | signal I_CPL : std_logic; | |
228 | signal I_CCF : std_logic; | |
229 | signal I_SCF : std_logic; | |
230 | signal I_RETN : std_logic; | |
231 | signal I_BT : std_logic; | |
232 | signal I_BC : std_logic; | |
233 | signal I_BTR : std_logic; | |
234 | signal I_RLD : std_logic; | |
235 | signal I_RRD : std_logic; | |
236 | signal I_INRC : std_logic; | |
237 | signal SetDI : std_logic; | |
238 | signal SetEI : std_logic; | |
239 | signal IMode : std_logic_vector(1 downto 0); | |
240 | signal Halt : std_logic; | |
241 | ||
242 | begin | |
243 | ||
244 | mcode : T80_MCode | |
245 | generic map( | |
246 | Mode => Mode, | |
247 | Flag_C => Flag_C, | |
248 | Flag_N => Flag_N, | |
249 | Flag_P => Flag_P, | |
250 | Flag_X => Flag_X, | |
251 | Flag_H => Flag_H, | |
252 | Flag_Y => Flag_Y, | |
253 | Flag_Z => Flag_Z, | |
254 | Flag_S => Flag_S) | |
255 | port map( | |
256 | IR => IR, | |
257 | ISet => ISet, | |
258 | MCycle => MCycle, | |
259 | F => F, | |
260 | NMICycle => NMICycle, | |
261 | IntCycle => IntCycle, | |
262 | MCycles => MCycles_d, | |
263 | TStates => TStates, | |
264 | Prefix => Prefix, | |
265 | Inc_PC => Inc_PC, | |
266 | Inc_WZ => Inc_WZ, | |
267 | IncDec_16 => IncDec_16, | |
268 | Read_To_Acc => Read_To_Acc, | |
269 | Read_To_Reg => Read_To_Reg, | |
270 | Set_BusB_To => Set_BusB_To, | |
271 | Set_BusA_To => Set_BusA_To, | |
272 | ALU_Op => ALU_Op, | |
273 | Save_ALU => Save_ALU, | |
274 | PreserveC => PreserveC, | |
275 | Arith16 => Arith16, | |
276 | Set_Addr_To => Set_Addr_To, | |
277 | IORQ => IORQ_i, | |
278 | Jump => Jump, | |
279 | JumpE => JumpE, | |
280 | JumpXY => JumpXY, | |
281 | Call => Call, | |
282 | RstP => RstP, | |
283 | LDZ => LDZ, | |
284 | LDW => LDW, | |
285 | LDSPHL => LDSPHL, | |
286 | Special_LD => Special_LD, | |
287 | ExchangeDH => ExchangeDH, | |
288 | ExchangeRp => ExchangeRp, | |
289 | ExchangeAF => ExchangeAF, | |
290 | ExchangeRS => ExchangeRS, | |
291 | I_DJNZ => I_DJNZ, | |
292 | I_CPL => I_CPL, | |
293 | I_CCF => I_CCF, | |
294 | I_SCF => I_SCF, | |
295 | I_RETN => I_RETN, | |
296 | I_BT => I_BT, | |
297 | I_BC => I_BC, | |
298 | I_BTR => I_BTR, | |
299 | I_RLD => I_RLD, | |
300 | I_RRD => I_RRD, | |
301 | I_INRC => I_INRC, | |
302 | SetDI => SetDI, | |
303 | SetEI => SetEI, | |
304 | IMode => IMode, | |
305 | Halt => Halt, | |
306 | NoRead => NoRead, | |
307 | Write => Write); | |
308 | ||
309 | alu : T80_ALU | |
310 | generic map( | |
311 | Mode => Mode, | |
312 | Flag_C => Flag_C, | |
313 | Flag_N => Flag_N, | |
314 | Flag_P => Flag_P, | |
315 | Flag_X => Flag_X, | |
316 | Flag_H => Flag_H, | |
317 | Flag_Y => Flag_Y, | |
318 | Flag_Z => Flag_Z, | |
319 | Flag_S => Flag_S) | |
320 | port map( | |
321 | Arith16 => Arith16_r, | |
322 | Z16 => Z16_r, | |
323 | ALU_Op => ALU_Op_r, | |
324 | IR => IR(5 downto 0), | |
325 | ISet => ISet, | |
326 | BusA => BusA, | |
327 | BusB => BusB, | |
328 | F_In => F, | |
329 | Q => ALU_Q, | |
330 | F_Out => F_Out); | |
331 | ||
332 | ClkEn <= CEN and not BusAck; | |
333 | ||
334 | T_Res <= '1' when TState = unsigned(TStates) else '0'; | |
335 | ||
336 | NextIs_XY_Fetch <= '1' when XY_State /= "00" and XY_Ind = '0' and | |
337 | ((Set_Addr_To = aXY) or | |
338 | (MCycle = "001" and IR = "11001011") or | |
339 | (MCycle = "001" and IR = "00110110")) else '0'; | |
340 | ||
341 | Save_Mux <= BusB when ExchangeRp = '1' else | |
342 | DI_Reg when Save_ALU_r = '0' else | |
343 | ALU_Q; | |
344 | ||
345 | process (RESET_n, CLK_n) | |
346 | begin | |
347 | if RESET_n = '0' then | |
348 | PC <= (others => '0'); -- Program Counter | |
349 | A <= (others => '0'); | |
350 | TmpAddr <= (others => '0'); | |
351 | IR <= "00000000"; | |
352 | ISet <= "00"; | |
353 | XY_State <= "00"; | |
354 | IStatus <= "00"; | |
355 | MCycles <= "000"; | |
356 | DO <= "00000000"; | |
357 | ||
358 | ACC <= (others => '1'); | |
359 | F <= (others => '1'); | |
360 | Ap <= (others => '1'); | |
361 | Fp <= (others => '1'); | |
362 | I <= (others => '0'); | |
363 | R <= (others => '0'); | |
364 | SP <= (others => '1'); | |
365 | Alternate <= '0'; | |
366 | ||
367 | Read_To_Reg_r <= "00000"; | |
368 | F <= (others => '1'); | |
369 | Arith16_r <= '0'; | |
370 | BTR_r <= '0'; | |
371 | Z16_r <= '0'; | |
372 | ALU_Op_r <= "0000"; | |
373 | Save_ALU_r <= '0'; | |
374 | PreserveC_r <= '0'; | |
375 | XY_Ind <= '0'; | |
376 | ||
377 | elsif CLK_n'event and CLK_n = '1' then | |
378 | ||
379 | if ClkEn = '1' then | |
380 | ||
381 | ALU_Op_r <= "0000"; | |
382 | Save_ALU_r <= '0'; | |
383 | Read_To_Reg_r <= "00000"; | |
384 | ||
385 | MCycles <= MCycles_d; | |
386 | ||
387 | if IMode /= "11" then | |
388 | IStatus <= IMode; | |
389 | end if; | |
390 | ||
391 | Arith16_r <= Arith16; | |
392 | PreserveC_r <= PreserveC; | |
393 | if ISet = "10" and ALU_OP(2) = '0' and ALU_OP(0) = '1' and MCycle = "011" then | |
394 | Z16_r <= '1'; | |
395 | else | |
396 | Z16_r <= '0'; | |
397 | end if; | |
398 | ||
399 | if MCycle = "001" and TState(2) = '0' then | |
400 | -- MCycle = 1 and TState = 1, 2, or 3 | |
401 | ||
402 | if TState = 2 and Wait_n = '1' then | |
403 | if Mode < 2 then | |
404 | A(7 downto 0) <= std_logic_vector(R); | |
405 | A(15 downto 8) <= I; | |
406 | R(6 downto 0) <= R(6 downto 0) + 1; | |
407 | end if; | |
408 | ||
409 | if Jump = '0' and Call = '0' and NMICycle = '0' and IntCycle = '0' and not (Halt_FF = '1' or Halt = '1') then | |
410 | PC <= PC + 1; | |
411 | end if; | |
412 | ||
413 | if IntCycle = '1' and IStatus = "01" then | |
414 | IR <= "11111111"; | |
415 | elsif Halt_FF = '1' or (IntCycle = '1' and IStatus = "10") or NMICycle = '1' then | |
416 | IR <= "00000000"; | |
417 | else | |
418 | IR <= DInst; | |
419 | end if; | |
420 | ||
421 | ISet <= "00"; | |
422 | if Prefix /= "00" then | |
423 | if Prefix = "11" then | |
424 | if IR(5) = '1' then | |
425 | XY_State <= "10"; | |
426 | else | |
427 | XY_State <= "01"; | |
428 | end if; | |
429 | else | |
430 | if Prefix = "10" then | |
431 | XY_State <= "00"; | |
432 | XY_Ind <= '0'; | |
433 | end if; | |
434 | ISet <= Prefix; | |
435 | end if; | |
436 | else | |
437 | XY_State <= "00"; | |
438 | XY_Ind <= '0'; | |
439 | end if; | |
440 | end if; | |
441 | ||
442 | else | |
443 | -- either (MCycle > 1) OR (MCycle = 1 AND TState > 3) | |
444 | ||
445 | if MCycle = "110" then | |
446 | XY_Ind <= '1'; | |
447 | if Prefix = "01" then | |
448 | ISet <= "01"; | |
449 | end if; | |
450 | end if; | |
451 | ||
452 | if T_Res = '1' then | |
453 | BTR_r <= (I_BT or I_BC or I_BTR) and not No_BTR; | |
454 | if Jump = '1' then | |
455 | A(15 downto 8) <= DI_Reg; | |
456 | A(7 downto 0) <= TmpAddr(7 downto 0); | |
457 | PC(15 downto 8) <= unsigned(DI_Reg); | |
458 | PC(7 downto 0) <= unsigned(TmpAddr(7 downto 0)); | |
459 | elsif JumpXY = '1' then | |
460 | A <= RegBusC; | |
461 | PC <= unsigned(RegBusC); | |
462 | elsif Call = '1' or RstP = '1' then | |
463 | A <= TmpAddr; | |
464 | PC <= unsigned(TmpAddr); | |
465 | elsif MCycle = MCycles and NMICycle = '1' then | |
466 | A <= "0000000001100110"; | |
467 | PC <= "0000000001100110"; | |
468 | elsif MCycle = "011" and IntCycle = '1' and IStatus = "10" then | |
469 | A(15 downto 8) <= I; | |
470 | A(7 downto 0) <= TmpAddr(7 downto 0); | |
471 | PC(15 downto 8) <= unsigned(I); | |
472 | PC(7 downto 0) <= unsigned(TmpAddr(7 downto 0)); | |
473 | else | |
474 | case Set_Addr_To is | |
475 | when aXY => | |
476 | if XY_State = "00" then | |
477 | A <= RegBusC; | |
478 | else | |
479 | if NextIs_XY_Fetch = '1' then | |
480 | A <= std_logic_vector(PC); | |
481 | else | |
482 | A <= TmpAddr; | |
483 | end if; | |
484 | end if; | |
485 | when aIOA => | |
486 | if Mode = 3 then | |
487 | -- Memory map I/O on GBZ80 | |
488 | A(15 downto 8) <= (others => '1'); | |
489 | elsif Mode = 2 then | |
490 | -- Duplicate I/O address on 8080 | |
491 | A(15 downto 8) <= DI_Reg; | |
492 | else | |
493 | A(15 downto 8) <= ACC; | |
494 | end if; | |
495 | A(7 downto 0) <= DI_Reg; | |
496 | when aSP => | |
497 | A <= std_logic_vector(SP); | |
498 | when aBC => | |
499 | if Mode = 3 and IORQ_i = '1' then | |
500 | -- Memory map I/O on GBZ80 | |
501 | A(15 downto 8) <= (others => '1'); | |
502 | A(7 downto 0) <= RegBusC(7 downto 0); | |
503 | else | |
504 | A <= RegBusC; | |
505 | end if; | |
506 | when aDE => | |
507 | A <= RegBusC; | |
508 | when aZI => | |
509 | if Inc_WZ = '1' then | |
510 | A <= std_logic_vector(unsigned(TmpAddr) + 1); | |
511 | else | |
512 | A(15 downto 8) <= DI_Reg; | |
513 | A(7 downto 0) <= TmpAddr(7 downto 0); | |
514 | end if; | |
515 | when others => | |
516 | A <= std_logic_vector(PC); | |
517 | end case; | |
518 | end if; | |
519 | ||
520 | Save_ALU_r <= Save_ALU; | |
521 | ALU_Op_r <= ALU_Op; | |
522 | ||
523 | if I_CPL = '1' then | |
524 | -- CPL | |
525 | ACC <= not ACC; | |
526 | F(Flag_Y) <= not ACC(5); | |
527 | F(Flag_H) <= '1'; | |
528 | F(Flag_X) <= not ACC(3); | |
529 | F(Flag_N) <= '1'; | |
530 | end if; | |
531 | if I_CCF = '1' then | |
532 | -- CCF | |
533 | F(Flag_C) <= not F(Flag_C); | |
534 | F(Flag_Y) <= ACC(5); | |
535 | F(Flag_H) <= F(Flag_C); | |
536 | F(Flag_X) <= ACC(3); | |
537 | F(Flag_N) <= '0'; | |
538 | end if; | |
539 | if I_SCF = '1' then | |
540 | -- SCF | |
541 | F(Flag_C) <= '1'; | |
542 | F(Flag_Y) <= ACC(5); | |
543 | F(Flag_H) <= '0'; | |
544 | F(Flag_X) <= ACC(3); | |
545 | F(Flag_N) <= '0'; | |
546 | end if; | |
547 | end if; | |
548 | ||
549 | if TState = 2 and Wait_n = '1' then | |
550 | if ISet = "01" and MCycle = "111" then | |
551 | IR <= DInst; | |
552 | end if; | |
553 | if JumpE = '1' then | |
554 | PC <= unsigned(signed(PC) + signed(DI_Reg)); | |
555 | elsif Inc_PC = '1' then | |
556 | PC <= PC + 1; | |
557 | end if; | |
558 | if BTR_r = '1' then | |
559 | PC <= PC - 2; | |
560 | end if; | |
561 | if RstP = '1' then | |
562 | TmpAddr <= (others =>'0'); | |
563 | TmpAddr(5 downto 3) <= IR(5 downto 3); | |
564 | end if; | |
565 | end if; | |
566 | if TState = 3 and MCycle = "110" then | |
567 | TmpAddr <= std_logic_vector(signed(RegBusC) + signed(DI_Reg)); | |
568 | end if; | |
569 | ||
570 | if (TState = 2 and Wait_n = '1') or (TState = 4 and MCycle = "001") then | |
571 | if IncDec_16(2 downto 0) = "111" then | |
572 | if IncDec_16(3) = '1' then | |
573 | SP <= SP - 1; | |
574 | else | |
575 | SP <= SP + 1; | |
576 | end if; | |
577 | end if; | |
578 | end if; | |
579 | ||
580 | if LDSPHL = '1' then | |
581 | SP <= unsigned(RegBusC); | |
582 | end if; | |
583 | if ExchangeAF = '1' then | |
584 | Ap <= ACC; | |
585 | ACC <= Ap; | |
586 | Fp <= F; | |
587 | F <= Fp; | |
588 | end if; | |
589 | if ExchangeRS = '1' then | |
590 | Alternate <= not Alternate; | |
591 | end if; | |
592 | end if; | |
593 | ||
594 | if TState = 3 then | |
595 | if LDZ = '1' then | |
596 | TmpAddr(7 downto 0) <= DI_Reg; | |
597 | end if; | |
598 | if LDW = '1' then | |
599 | TmpAddr(15 downto 8) <= DI_Reg; | |
600 | end if; | |
601 | ||
602 | if Special_LD(2) = '1' then | |
603 | case Special_LD(1 downto 0) is | |
604 | when "00" => | |
605 | ACC <= I; | |
606 | F(Flag_P) <= IntE_FF2; | |
607 | when "01" => | |
608 | ACC <= std_logic_vector(R); | |
609 | F(Flag_P) <= IntE_FF2; | |
610 | when "10" => | |
611 | I <= ACC; | |
612 | when others => | |
613 | R <= unsigned(ACC); | |
614 | end case; | |
615 | end if; | |
616 | end if; | |
617 | ||
618 | if (I_DJNZ = '0' and Save_ALU_r = '1') or ALU_Op_r = "1001" then | |
619 | if Mode = 3 then | |
620 | F(6) <= F_Out(6); | |
621 | F(5) <= F_Out(5); | |
622 | F(7) <= F_Out(7); | |
623 | if PreserveC_r = '0' then | |
624 | F(4) <= F_Out(4); | |
625 | end if; | |
626 | else | |
627 | F(7 downto 1) <= F_Out(7 downto 1); | |
628 | if PreserveC_r = '0' then | |
629 | F(Flag_C) <= F_Out(0); | |
630 | end if; | |
631 | end if; | |
632 | end if; | |
633 | if T_Res = '1' and I_INRC = '1' then | |
634 | F(Flag_H) <= '0'; | |
635 | F(Flag_N) <= '0'; | |
636 | if DI_Reg(7 downto 0) = "00000000" then | |
637 | F(Flag_Z) <= '1'; | |
638 | else | |
639 | F(Flag_Z) <= '0'; | |
640 | end if; | |
641 | F(Flag_S) <= DI_Reg(7); | |
642 | F(Flag_P) <= not (DI_Reg(0) xor DI_Reg(1) xor DI_Reg(2) xor DI_Reg(3) xor | |
643 | DI_Reg(4) xor DI_Reg(5) xor DI_Reg(6) xor DI_Reg(7)); | |
644 | end if; | |
645 | ||
646 | if TState = 1 and Auto_Wait_t1 = '0' then | |
647 | DO <= BusB; | |
648 | if I_RLD = '1' then | |
649 | DO(3 downto 0) <= BusA(3 downto 0); | |
650 | DO(7 downto 4) <= BusB(3 downto 0); | |
651 | end if; | |
652 | if I_RRD = '1' then | |
653 | DO(3 downto 0) <= BusB(7 downto 4); | |
654 | DO(7 downto 4) <= BusA(3 downto 0); | |
655 | end if; | |
656 | end if; | |
657 | ||
658 | if T_Res = '1' then | |
659 | Read_To_Reg_r(3 downto 0) <= Set_BusA_To; | |
660 | Read_To_Reg_r(4) <= Read_To_Reg; | |
661 | if Read_To_Acc = '1' then | |
662 | Read_To_Reg_r(3 downto 0) <= "0111"; | |
663 | Read_To_Reg_r(4) <= '1'; | |
664 | end if; | |
665 | end if; | |
666 | ||
667 | if TState = 1 and I_BT = '1' then | |
668 | F(Flag_X) <= ALU_Q(3); | |
669 | F(Flag_Y) <= ALU_Q(1); | |
670 | F(Flag_H) <= '0'; | |
671 | F(Flag_N) <= '0'; | |
672 | end if; | |
673 | if I_BC = '1' or I_BT = '1' then | |
674 | F(Flag_P) <= IncDecZ; | |
675 | end if; | |
676 | ||
677 | if (TState = 1 and Save_ALU_r = '0' and Auto_Wait_t1 = '0') or | |
678 | (Save_ALU_r = '1' and ALU_OP_r /= "0111") then | |
679 | case Read_To_Reg_r is | |
680 | when "10111" => | |
681 | ACC <= Save_Mux; | |
682 | when "10110" => | |
683 | DO <= Save_Mux; | |
684 | when "11000" => | |
685 | SP(7 downto 0) <= unsigned(Save_Mux); | |
686 | when "11001" => | |
687 | SP(15 downto 8) <= unsigned(Save_Mux); | |
688 | when "11011" => | |
689 | F <= Save_Mux; | |
690 | when others => | |
691 | end case; | |
692 | end if; | |
693 | ||
694 | end if; | |
695 | ||
696 | end if; | |
697 | ||
698 | end process; | |
699 | ||
700 | --------------------------------------------------------------------------- | |
701 | -- | |
702 | -- BC('), DE('), HL('), IX and IY | |
703 | -- | |
704 | --------------------------------------------------------------------------- | |
705 | process (CLK_n) | |
706 | begin | |
707 | if CLK_n'event and CLK_n = '1' then | |
708 | if ClkEn = '1' then | |
709 | -- Bus A / Write | |
710 | RegAddrA_r <= Alternate & Set_BusA_To(2 downto 1); | |
711 | if XY_Ind = '0' and XY_State /= "00" and Set_BusA_To(2 downto 1) = "10" then | |
712 | RegAddrA_r <= XY_State(1) & "11"; | |
713 | end if; | |
714 | ||
715 | -- Bus B | |
716 | RegAddrB_r <= Alternate & Set_BusB_To(2 downto 1); | |
717 | if XY_Ind = '0' and XY_State /= "00" and Set_BusB_To(2 downto 1) = "10" then | |
718 | RegAddrB_r <= XY_State(1) & "11"; | |
719 | end if; | |
720 | ||
721 | -- Address from register | |
722 | RegAddrC <= Alternate & Set_Addr_To(1 downto 0); | |
723 | -- Jump (HL), LD SP,HL | |
724 | if (JumpXY = '1' or LDSPHL = '1') then | |
725 | RegAddrC <= Alternate & "10"; | |
726 | end if; | |
727 | if ((JumpXY = '1' or LDSPHL = '1') and XY_State /= "00") or (MCycle = "110") then | |
728 | RegAddrC <= XY_State(1) & "11"; | |
729 | end if; | |
730 | ||
731 | if I_DJNZ = '1' and Save_ALU_r = '1' and Mode < 2 then | |
732 | IncDecZ <= F_Out(Flag_Z); | |
733 | end if; | |
734 | if (TState = 2 or (TState = 3 and MCycle = "001")) and IncDec_16(2 downto 0) = "100" then | |
735 | if ID16 = 0 then | |
736 | IncDecZ <= '0'; | |
737 | else | |
738 | IncDecZ <= '1'; | |
739 | end if; | |
740 | end if; | |
741 | ||
742 | RegBusA_r <= RegBusA; | |
743 | end if; | |
744 | end if; | |
745 | end process; | |
746 | ||
747 | RegAddrA <= | |
748 | -- 16 bit increment/decrement | |
749 | Alternate & IncDec_16(1 downto 0) when (TState = 2 or | |
750 | (TState = 3 and MCycle = "001" and IncDec_16(2) = '1')) and XY_State = "00" else | |
751 | XY_State(1) & "11" when (TState = 2 or | |
752 | (TState = 3 and MCycle = "001" and IncDec_16(2) = '1')) and IncDec_16(1 downto 0) = "10" else | |
753 | -- EX HL,DL | |
754 | Alternate & "10" when ExchangeDH = '1' and TState = 3 else | |
755 | Alternate & "01" when ExchangeDH = '1' and TState = 4 else | |
756 | -- Bus A / Write | |
757 | RegAddrA_r; | |
758 | ||
759 | RegAddrB <= | |
760 | -- EX HL,DL | |
761 | Alternate & "01" when ExchangeDH = '1' and TState = 3 else | |
762 | -- Bus B | |
763 | RegAddrB_r; | |
764 | ||
765 | ID16 <= signed(RegBusA) - 1 when IncDec_16(3) = '1' else | |
766 | signed(RegBusA) + 1; | |
767 | ||
768 | process (Save_ALU_r, Auto_Wait_t1, ALU_OP_r, Read_To_Reg_r, | |
769 | ExchangeDH, IncDec_16, MCycle, TState, Wait_n) | |
770 | begin | |
771 | RegWEH <= '0'; | |
772 | RegWEL <= '0'; | |
773 | if (TState = 1 and Save_ALU_r = '0' and Auto_Wait_t1 = '0') or | |
774 | (Save_ALU_r = '1' and ALU_OP_r /= "0111") then | |
775 | case Read_To_Reg_r is | |
776 | when "10000" | "10001" | "10010" | "10011" | "10100" | "10101" => | |
777 | RegWEH <= not Read_To_Reg_r(0); | |
778 | RegWEL <= Read_To_Reg_r(0); | |
779 | when others => | |
780 | end case; | |
781 | end if; | |
782 | ||
783 | if ExchangeDH = '1' and (TState = 3 or TState = 4) then | |
784 | RegWEH <= '1'; | |
785 | RegWEL <= '1'; | |
786 | end if; | |
787 | ||
788 | if IncDec_16(2) = '1' and ((TState = 2 and Wait_n = '1' and MCycle /= "001") or (TState = 3 and MCycle = "001")) then | |
789 | case IncDec_16(1 downto 0) is | |
790 | when "00" | "01" | "10" => | |
791 | RegWEH <= '1'; | |
792 | RegWEL <= '1'; | |
793 | when others => | |
794 | end case; | |
795 | end if; | |
796 | end process; | |
797 | ||
798 | process (Save_Mux, RegBusB, RegBusA_r, ID16, | |
799 | ExchangeDH, IncDec_16, MCycle, TState, Wait_n) | |
800 | begin | |
801 | RegDIH <= Save_Mux; | |
802 | RegDIL <= Save_Mux; | |
803 | ||
804 | if ExchangeDH = '1' and TState = 3 then | |
805 | RegDIH <= RegBusB(15 downto 8); | |
806 | RegDIL <= RegBusB(7 downto 0); | |
807 | end if; | |
808 | if ExchangeDH = '1' and TState = 4 then | |
809 | RegDIH <= RegBusA_r(15 downto 8); | |
810 | RegDIL <= RegBusA_r(7 downto 0); | |
811 | end if; | |
812 | ||
813 | if IncDec_16(2) = '1' and ((TState = 2 and MCycle /= "001") or (TState = 3 and MCycle = "001")) then | |
814 | RegDIH <= std_logic_vector(ID16(15 downto 8)); | |
815 | RegDIL <= std_logic_vector(ID16(7 downto 0)); | |
816 | end if; | |
817 | end process; | |
818 | ||
819 | Regs : T80_Reg | |
820 | port map( | |
821 | Clk => CLK_n, | |
822 | CEN => ClkEn, | |
823 | WEH => RegWEH, | |
824 | WEL => RegWEL, | |
825 | AddrA => RegAddrA, | |
826 | AddrB => RegAddrB, | |
827 | AddrC => RegAddrC, | |
828 | DIH => RegDIH, | |
829 | DIL => RegDIL, | |
830 | DOAH => RegBusA(15 downto 8), | |
831 | DOAL => RegBusA(7 downto 0), | |
832 | DOBH => RegBusB(15 downto 8), | |
833 | DOBL => RegBusB(7 downto 0), | |
834 | DOCH => RegBusC(15 downto 8), | |
835 | DOCL => RegBusC(7 downto 0)); | |
836 | ||
837 | --------------------------------------------------------------------------- | |
838 | -- | |
839 | -- Buses | |
840 | -- | |
841 | --------------------------------------------------------------------------- | |
842 | process (CLK_n) | |
843 | begin | |
844 | if CLK_n'event and CLK_n = '1' then | |
845 | if ClkEn = '1' then | |
846 | case Set_BusB_To is | |
847 | when "0111" => | |
848 | BusB <= ACC; | |
849 | when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" => | |
850 | if Set_BusB_To(0) = '1' then | |
851 | BusB <= RegBusB(7 downto 0); | |
852 | else | |
853 | BusB <= RegBusB(15 downto 8); | |
854 | end if; | |
855 | when "0110" => | |
856 | BusB <= DI_Reg; | |
857 | when "1000" => | |
858 | BusB <= std_logic_vector(SP(7 downto 0)); | |
859 | when "1001" => | |
860 | BusB <= std_logic_vector(SP(15 downto 8)); | |
861 | when "1010" => | |
862 | BusB <= "00000001"; | |
863 | when "1011" => | |
864 | BusB <= F; | |
865 | when "1100" => | |
866 | BusB <= std_logic_vector(PC(7 downto 0)); | |
867 | when "1101" => | |
868 | BusB <= std_logic_vector(PC(15 downto 8)); | |
869 | when "1110" => | |
870 | BusB <= "00000000"; | |
871 | when others => | |
872 | BusB <= "--------"; | |
873 | end case; | |
874 | ||
875 | case Set_BusA_To is | |
876 | when "0111" => | |
877 | BusA <= ACC; | |
878 | when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" => | |
879 | if Set_BusA_To(0) = '1' then | |
880 | BusA <= RegBusA(7 downto 0); | |
881 | else | |
882 | BusA <= RegBusA(15 downto 8); | |
883 | end if; | |
884 | when "0110" => | |
885 | BusA <= DI_Reg; | |
886 | when "1000" => | |
887 | BusA <= std_logic_vector(SP(7 downto 0)); | |
888 | when "1001" => | |
889 | BusA <= std_logic_vector(SP(15 downto 8)); | |
890 | when "1010" => | |
891 | BusA <= "00000000"; | |
892 | when others => | |
893 | BusB <= "--------"; | |
894 | end case; | |
895 | end if; | |
896 | end if; | |
897 | end process; | |
898 | ||
899 | --------------------------------------------------------------------------- | |
900 | -- | |
901 | -- Generate external control signals | |
902 | -- | |
903 | --------------------------------------------------------------------------- | |
904 | process (RESET_n,CLK_n) | |
905 | begin | |
906 | if RESET_n = '0' then | |
907 | RFSH_n <= '1'; | |
908 | elsif CLK_n'event and CLK_n = '1' then | |
909 | if CEN = '1' then | |
910 | if MCycle = "001" and ((TState = 2 and Wait_n = '1') or TState = 3) then | |
911 | RFSH_n <= '0'; | |
912 | else | |
913 | RFSH_n <= '1'; | |
914 | end if; | |
915 | end if; | |
916 | end if; | |
917 | end process; | |
918 | ||
919 | MC <= std_logic_vector(MCycle); | |
920 | TS <= std_logic_vector(TState); | |
921 | DI_Reg <= DI; | |
922 | HALT_n <= not Halt_FF; | |
923 | BUSAK_n <= not BusAck; | |
924 | IntCycle_n <= not IntCycle; | |
925 | IntE <= IntE_FF1; | |
926 | IORQ <= IORQ_i; | |
927 | Stop <= I_DJNZ; | |
928 | ||
929 | ------------------------------------------------------------------------- | |
930 | -- | |
931 | -- Syncronise inputs | |
932 | -- | |
933 | ------------------------------------------------------------------------- | |
934 | process (RESET_n, CLK_n) | |
935 | variable OldNMI_n : std_logic; | |
936 | begin | |
937 | if RESET_n = '0' then | |
938 | BusReq_s <= '0'; | |
939 | INT_s <= '0'; | |
940 | NMI_s <= '0'; | |
941 | OldNMI_n := '0'; | |
942 | elsif CLK_n'event and CLK_n = '1' then | |
943 | if CEN = '1' then | |
944 | BusReq_s <= not BUSRQ_n; | |
945 | INT_s <= not INT_n; | |
946 | if NMICycle = '1' then | |
947 | NMI_s <= '0'; | |
948 | elsif NMI_n = '0' and OldNMI_n = '1' then | |
949 | NMI_s <= '1'; | |
950 | end if; | |
951 | OldNMI_n := NMI_n; | |
952 | end if; | |
953 | end if; | |
954 | end process; | |
955 | ||
956 | ------------------------------------------------------------------------- | |
957 | -- | |
958 | -- Main state machine | |
959 | -- | |
960 | ------------------------------------------------------------------------- | |
961 | process (RESET_n, CLK_n) | |
962 | begin | |
963 | if RESET_n = '0' then | |
964 | MCycle <= "001"; | |
965 | TState <= "000"; | |
966 | Pre_XY_F_M <= "000"; | |
967 | Halt_FF <= '0'; | |
968 | BusAck <= '0'; | |
969 | NMICycle <= '0'; | |
970 | IntCycle <= '0'; | |
971 | IntE_FF1 <= '0'; | |
972 | IntE_FF2 <= '0'; | |
973 | No_BTR <= '0'; | |
974 | Auto_Wait_t1 <= '0'; | |
975 | Auto_Wait_t2 <= '0'; | |
976 | M1_n <= '1'; | |
977 | elsif CLK_n'event and CLK_n = '1' then | |
978 | if CEN = '1' then | |
979 | if T_Res = '1' then | |
980 | Auto_Wait_t1 <= '0'; | |
981 | else | |
982 | Auto_Wait_t1 <= Auto_Wait or IORQ_i; | |
983 | end if; | |
984 | Auto_Wait_t2 <= Auto_Wait_t1; | |
985 | No_BTR <= (I_BT and (not IR(4) or not F(Flag_P))) or | |
986 | (I_BC and (not IR(4) or F(Flag_Z) or not F(Flag_P))) or | |
987 | (I_BTR and (not IR(4) or F(Flag_Z))); | |
988 | if TState = 2 then | |
989 | if SetEI = '1' then | |
990 | IntE_FF1 <= '1'; | |
991 | IntE_FF2 <= '1'; | |
992 | end if; | |
993 | if I_RETN = '1' then | |
994 | IntE_FF1 <= IntE_FF2; | |
995 | end if; | |
996 | end if; | |
997 | if TState = 3 then | |
998 | if SetDI = '1' then | |
999 | IntE_FF1 <= '0'; | |
1000 | IntE_FF2 <= '0'; | |
1001 | end if; | |
1002 | end if; | |
1003 | if IntCycle = '1' or NMICycle = '1' then | |
1004 | Halt_FF <= '0'; | |
1005 | end if; | |
1006 | if MCycle = "001" and TState = 2 and Wait_n = '1' then | |
1007 | M1_n <= '1'; | |
1008 | end if; | |
1009 | if BusReq_s = '1' and BusAck = '1' then | |
1010 | else | |
1011 | BusAck <= '0'; | |
1012 | if TState = 2 and Wait_n = '0' then | |
1013 | elsif T_Res = '1' then | |
1014 | if Halt = '1' then | |
1015 | Halt_FF <= '1'; | |
1016 | end if; | |
1017 | if BusReq_s = '1' then | |
1018 | BusAck <= '1'; | |
1019 | else | |
1020 | TState <= "001"; | |
1021 | if NextIs_XY_Fetch = '1' then | |
1022 | MCycle <= "110"; | |
1023 | Pre_XY_F_M <= MCycle; | |
1024 | if IR = "00110110" and Mode = 0 then | |
1025 | Pre_XY_F_M <= "010"; | |
1026 | end if; | |
1027 | elsif (MCycle = "111") or | |
1028 | (MCycle = "110" and Mode = 1 and ISet /= "01") then | |
1029 | MCycle <= std_logic_vector(unsigned(Pre_XY_F_M) + 1); | |
1030 | elsif (MCycle = MCycles) or | |
1031 | No_BTR = '1' or | |
1032 | (MCycle = "010" and I_DJNZ = '1' and IncDecZ = '1') then | |
1033 | M1_n <= '0'; | |
1034 | MCycle <= "001"; | |
1035 | IntCycle <= '0'; | |
1036 | NMICycle <= '0'; | |
1037 | if NMI_s = '1' and Prefix = "00" then | |
1038 | NMICycle <= '1'; | |
1039 | IntE_FF1 <= '0'; | |
1040 | elsif (IntE_FF1 = '1' and INT_s = '1') and Prefix = "00" and SetEI = '0' then | |
1041 | IntCycle <= '1'; | |
1042 | IntE_FF1 <= '0'; | |
1043 | IntE_FF2 <= '0'; | |
1044 | end if; | |
1045 | else | |
1046 | MCycle <= std_logic_vector(unsigned(MCycle) + 1); | |
1047 | end if; | |
1048 | end if; | |
1049 | else | |
1050 | if (Auto_Wait = '1' and Auto_Wait_t2 = '0') nor | |
1051 | (IOWait = 1 and IORQ_i = '1' and Auto_Wait_t1 = '0') then | |
1052 | TState <= TState + 1; | |
1053 | end if; | |
1054 | end if; | |
1055 | end if; | |
1056 | if TState = 0 then | |
1057 | M1_n <= '0'; | |
1058 | end if; | |
1059 | end if; | |
1060 | end if; | |
1061 | end process; | |
1062 | ||
1063 | process (IntCycle, NMICycle, MCycle) | |
1064 | begin | |
1065 | Auto_Wait <= '0'; | |
1066 | if IntCycle = '1' or NMICycle = '1' then | |
1067 | if MCycle = "001" then | |
1068 | Auto_Wait <= '1'; | |
1069 | end if; | |
1070 | end if; | |
1071 | end process; | |
1072 | ||
1073 | end; |