12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094 |
- -- ****
- -- T80(b) core. In an effort to merge and maintain bug fixes ....
- --
- --
- -- Ver 303 add undocumented DDCB and FDCB opcodes by TobiFlex 20.04.2010
- -- Ver 302 fixed IO cycle timing, tested thanks to Alessandro.
- -- Ver 301 parity flag is just parity for 8080, also overflow for Z80, by Sean Riddle
- -- Ver 300 started tidyup. Rmoved some auto_wait bits from 0247 which caused problems
- --
- -- MikeJ March 2005
- -- Latest version from www.fpgaarcade.com (original www.opencores.org)
- --
- -- ****
- --
- -- Z80 compatible microprocessor core
- --
- -- Version : 0247
- --
- -- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
- --
- -- All rights reserved
- --
- -- Redistribution and use in source and synthezised forms, with or without
- -- modification, are permitted provided that the following conditions are met:
- --
- -- Redistributions of source code must retain the above copyright notice,
- -- this list of conditions and the following disclaimer.
- --
- -- Redistributions in synthesized form must reproduce the above copyright
- -- notice, this list of conditions and the following disclaimer in the
- -- documentation and/or other materials provided with the distribution.
- --
- -- Neither the name of the author nor the names of other contributors may
- -- be used to endorse or promote products derived from this software without
- -- specific prior written permission.
- --
- -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- -- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- -- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- -- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
- -- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- -- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- -- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- -- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- -- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- -- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- -- POSSIBILITY OF SUCH DAMAGE.
- --
- -- Please report bugs to the author, but before you do so, please
- -- make sure that this is not a derivative work and that
- -- you have the latest version of this file.
- --
- -- The latest version of this file can be found at:
- -- http://www.opencores.org/cvsweb.shtml/t80/
- --
- -- Limitations :
- --
- -- File history :
- --
- -- 0208 : First complete release
- --
- -- 0210 : Fixed wait and halt
- --
- -- 0211 : Fixed Refresh addition and IM 1
- --
- -- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test
- --
- -- 0232 : Removed refresh address output for Mode > 1 and added DJNZ M1_n fix by Mike Johnson
- --
- -- 0235 : Added clock enable and IM 2 fix by Mike Johnson
- --
- -- 0237 : Changed 8080 I/O address output, added IntE output
- --
- -- 0238 : Fixed (IX/IY+d) timing and 16 bit ADC and SBC zero flag
- --
- -- 0240 : Added interrupt ack fix by Mike Johnson, changed (IX/IY+d) timing and changed flags in GB mode
- --
- -- 0242 : Added I/O wait, fixed refresh address, moved some registers to RAM
- --
- -- 0247 : Fixed bus req/ack cycle
- --
- library IEEE;
- use IEEE.std_logic_1164.all;
- use IEEE.numeric_std.all;
- use work.T80_Pack.all;
- entity T80 is
- generic(
- Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB
- IOWait : integer := 0; -- 1 => Single cycle I/O, 1 => Std I/O cycle
- Flag_C : integer := 0;
- Flag_N : integer := 1;
- Flag_P : integer := 2;
- Flag_X : integer := 3;
- Flag_H : integer := 4;
- Flag_Y : integer := 5;
- Flag_Z : integer := 6;
- Flag_S : integer := 7
- );
- port(
- RESET_n : in std_logic;
- CLK_n : in std_logic;
- CEN : in std_logic;
- WAIT_n : in std_logic;
- INT_n : in std_logic;
- NMI_n : in std_logic;
- BUSRQ_n : in std_logic;
- M1_n : out std_logic;
- IORQ : out std_logic;
- NoRead : out std_logic;
- Write : out std_logic;
- RFSH_n : out std_logic;
- HALT_n : out std_logic;
- BUSAK_n : out std_logic;
- A : out std_logic_vector(15 downto 0);
- DInst : in std_logic_vector(7 downto 0);
- DI : in std_logic_vector(7 downto 0);
- DO : out std_logic_vector(7 downto 0);
- MC : out std_logic_vector(2 downto 0);
- TS : out std_logic_vector(2 downto 0);
- IntCycle_n : out std_logic;
- IntE : out std_logic;
- Stop : out std_logic
- );
- end T80;
- architecture rtl of T80 is
- constant aNone : std_logic_vector(2 downto 0) := "111";
- constant aBC : std_logic_vector(2 downto 0) := "000";
- constant aDE : std_logic_vector(2 downto 0) := "001";
- constant aXY : std_logic_vector(2 downto 0) := "010";
- constant aIOA : std_logic_vector(2 downto 0) := "100";
- constant aSP : std_logic_vector(2 downto 0) := "101";
- constant aZI : std_logic_vector(2 downto 0) := "110";
- -- Registers
- signal ACC, F : std_logic_vector(7 downto 0);
- signal Ap, Fp : std_logic_vector(7 downto 0);
- signal I : std_logic_vector(7 downto 0);
- signal R : unsigned(7 downto 0);
- signal SP, PC : unsigned(15 downto 0);
- signal RegDIH : std_logic_vector(7 downto 0);
- signal RegDIL : std_logic_vector(7 downto 0);
- signal RegBusA : std_logic_vector(15 downto 0);
- signal RegBusB : std_logic_vector(15 downto 0);
- signal RegBusC : std_logic_vector(15 downto 0);
- signal RegAddrA_r : std_logic_vector(2 downto 0);
- signal RegAddrA : std_logic_vector(2 downto 0);
- signal RegAddrB_r : std_logic_vector(2 downto 0);
- signal RegAddrB : std_logic_vector(2 downto 0);
- signal RegAddrC : std_logic_vector(2 downto 0);
- signal RegWEH : std_logic;
- signal RegWEL : std_logic;
- signal Alternate : std_logic;
- -- Help Registers
- signal TmpAddr : std_logic_vector(15 downto 0); -- Temporary address register
- signal IR : std_logic_vector(7 downto 0); -- Instruction register
- signal ISet : std_logic_vector(1 downto 0); -- Instruction set selector
- signal RegBusA_r : std_logic_vector(15 downto 0);
- signal ID16 : signed(15 downto 0);
- signal Save_Mux : std_logic_vector(7 downto 0);
- signal TState : unsigned(2 downto 0);
- signal MCycle : std_logic_vector(2 downto 0);
- signal IntE_FF1 : std_logic;
- signal IntE_FF2 : std_logic;
- signal Halt_FF : std_logic;
- signal BusReq_s : std_logic;
- signal BusAck : std_logic;
- signal ClkEn : std_logic;
- signal NMI_s : std_logic;
- signal INT_s : std_logic;
- signal IStatus : std_logic_vector(1 downto 0);
- signal DI_Reg : std_logic_vector(7 downto 0);
- signal T_Res : std_logic;
- signal XY_State : std_logic_vector(1 downto 0);
- signal Pre_XY_F_M : std_logic_vector(2 downto 0);
- signal NextIs_XY_Fetch : std_logic;
- signal XY_Ind : std_logic;
- signal No_BTR : std_logic;
- signal BTR_r : std_logic;
- signal Auto_Wait : std_logic;
- signal Auto_Wait_t1 : std_logic;
- signal Auto_Wait_t2 : std_logic;
- signal IncDecZ : std_logic;
- -- ALU signals
- signal BusB : std_logic_vector(7 downto 0);
- signal BusA : std_logic_vector(7 downto 0);
- signal ALU_Q : std_logic_vector(7 downto 0);
- signal F_Out : std_logic_vector(7 downto 0);
- -- Registered micro code outputs
- signal Read_To_Reg_r : std_logic_vector(4 downto 0);
- signal Arith16_r : std_logic;
- signal Z16_r : std_logic;
- signal ALU_Op_r : std_logic_vector(3 downto 0);
- signal Save_ALU_r : std_logic;
- signal PreserveC_r : std_logic;
- signal MCycles : std_logic_vector(2 downto 0);
- -- Micro code outputs
- signal MCycles_d : std_logic_vector(2 downto 0);
- signal TStates : std_logic_vector(2 downto 0);
- signal IntCycle : std_logic;
- signal NMICycle : std_logic;
- signal Inc_PC : std_logic;
- signal Inc_WZ : std_logic;
- signal IncDec_16 : std_logic_vector(3 downto 0);
- signal Prefix : std_logic_vector(1 downto 0);
- signal Read_To_Acc : std_logic;
- signal Read_To_Reg : std_logic;
- signal Set_BusB_To : std_logic_vector(3 downto 0);
- signal Set_BusA_To : std_logic_vector(3 downto 0);
- signal ALU_Op : std_logic_vector(3 downto 0);
- signal Save_ALU : std_logic;
- signal PreserveC : std_logic;
- signal Arith16 : std_logic;
- signal Set_Addr_To : std_logic_vector(2 downto 0);
- signal Jump : std_logic;
- signal JumpE : std_logic;
- signal JumpXY : std_logic;
- signal Call : std_logic;
- signal RstP : std_logic;
- signal LDZ : std_logic;
- signal LDW : std_logic;
- signal LDSPHL : std_logic;
- signal IORQ_i : std_logic;
- signal Special_LD : std_logic_vector(2 downto 0);
- signal ExchangeDH : std_logic;
- signal ExchangeRp : std_logic;
- signal ExchangeAF : std_logic;
- signal ExchangeRS : std_logic;
- signal I_DJNZ : std_logic;
- signal I_CPL : std_logic;
- signal I_CCF : std_logic;
- signal I_SCF : std_logic;
- signal I_RETN : std_logic;
- signal I_BT : std_logic;
- signal I_BC : std_logic;
- signal I_BTR : std_logic;
- signal I_RLD : std_logic;
- signal I_RRD : std_logic;
- signal I_INRC : std_logic;
- signal SetDI : std_logic;
- signal SetEI : std_logic;
- signal IMode : std_logic_vector(1 downto 0);
- signal Halt : std_logic;
- signal XYbit_undoc : std_logic;
- begin
- mcode : T80_MCode
- generic map(
- Mode => Mode,
- Flag_C => Flag_C,
- Flag_N => Flag_N,
- Flag_P => Flag_P,
- Flag_X => Flag_X,
- Flag_H => Flag_H,
- Flag_Y => Flag_Y,
- Flag_Z => Flag_Z,
- Flag_S => Flag_S)
- port map(
- IR => IR,
- ISet => ISet,
- MCycle => MCycle,
- F => F,
- NMICycle => NMICycle,
- IntCycle => IntCycle,
- XY_State => XY_State,
- MCycles => MCycles_d,
- TStates => TStates,
- Prefix => Prefix,
- Inc_PC => Inc_PC,
- Inc_WZ => Inc_WZ,
- IncDec_16 => IncDec_16,
- Read_To_Acc => Read_To_Acc,
- Read_To_Reg => Read_To_Reg,
- Set_BusB_To => Set_BusB_To,
- Set_BusA_To => Set_BusA_To,
- ALU_Op => ALU_Op,
- Save_ALU => Save_ALU,
- PreserveC => PreserveC,
- Arith16 => Arith16,
- Set_Addr_To => Set_Addr_To,
- IORQ => IORQ_i,
- Jump => Jump,
- JumpE => JumpE,
- JumpXY => JumpXY,
- Call => Call,
- RstP => RstP,
- LDZ => LDZ,
- LDW => LDW,
- LDSPHL => LDSPHL,
- Special_LD => Special_LD,
- ExchangeDH => ExchangeDH,
- ExchangeRp => ExchangeRp,
- ExchangeAF => ExchangeAF,
- ExchangeRS => ExchangeRS,
- I_DJNZ => I_DJNZ,
- I_CPL => I_CPL,
- I_CCF => I_CCF,
- I_SCF => I_SCF,
- I_RETN => I_RETN,
- I_BT => I_BT,
- I_BC => I_BC,
- I_BTR => I_BTR,
- I_RLD => I_RLD,
- I_RRD => I_RRD,
- I_INRC => I_INRC,
- SetDI => SetDI,
- SetEI => SetEI,
- IMode => IMode,
- Halt => Halt,
- NoRead => NoRead,
- Write => Write,
- XYbit_undoc => XYbit_undoc);
- alu : T80_ALU
- generic map(
- Mode => Mode,
- Flag_C => Flag_C,
- Flag_N => Flag_N,
- Flag_P => Flag_P,
- Flag_X => Flag_X,
- Flag_H => Flag_H,
- Flag_Y => Flag_Y,
- Flag_Z => Flag_Z,
- Flag_S => Flag_S)
- port map(
- Arith16 => Arith16_r,
- Z16 => Z16_r,
- ALU_Op => ALU_Op_r,
- IR => IR(5 downto 0),
- ISet => ISet,
- BusA => BusA,
- BusB => BusB,
- F_In => F,
- Q => ALU_Q,
- F_Out => F_Out);
- ClkEn <= CEN and not BusAck;
- T_Res <= '1' when TState = unsigned(TStates) else '0';
- NextIs_XY_Fetch <= '1' when XY_State /= "00" and XY_Ind = '0' and
- ((Set_Addr_To = aXY) or
- (MCycle = "001" and IR = "11001011") or
- (MCycle = "001" and IR = "00110110")) else '0';
- Save_Mux <= BusB when ExchangeRp = '1' else
- DI_Reg when Save_ALU_r = '0' else
- ALU_Q;
- process (RESET_n, CLK_n)
- begin
- if RESET_n = '0' then
- PC <= (others => '0'); -- Program Counter
- A <= (others => '0');
- TmpAddr <= (others => '0');
- IR <= "00000000";
- ISet <= "00";
- XY_State <= "00";
- IStatus <= "00";
- MCycles <= "000";
- DO <= "00000000";
- ACC <= (others => '1');
- F <= (others => '1');
- Ap <= (others => '1');
- Fp <= (others => '1');
- I <= (others => '0');
- R <= (others => '0');
- SP <= (others => '1');
- Alternate <= '0';
- Read_To_Reg_r <= "00000";
- F <= (others => '1');
- Arith16_r <= '0';
- BTR_r <= '0';
- Z16_r <= '0';
- ALU_Op_r <= "0000";
- Save_ALU_r <= '0';
- PreserveC_r <= '0';
- XY_Ind <= '0';
- elsif CLK_n'event and CLK_n = '1' then
- if ClkEn = '1' then
- ALU_Op_r <= "0000";
- Save_ALU_r <= '0';
- Read_To_Reg_r <= "00000";
- MCycles <= MCycles_d;
- if IMode /= "11" then
- IStatus <= IMode;
- end if;
- Arith16_r <= Arith16;
- PreserveC_r <= PreserveC;
- if ISet = "10" and ALU_OP(2) = '0' and ALU_OP(0) = '1' and MCycle = "011" then
- Z16_r <= '1';
- else
- Z16_r <= '0';
- end if;
- if MCycle = "001" and TState(2) = '0' then
- -- MCycle = 1 and TState = 1, 2, or 3
- if TState = 2 and Wait_n = '1' then
- if Mode < 2 then
- A(7 downto 0) <= std_logic_vector(R);
- A(15 downto 8) <= I;
- R(6 downto 0) <= R(6 downto 0) + 1;
- end if;
- if Jump = '0' and Call = '0' and NMICycle = '0' and IntCycle = '0' and not (Halt_FF = '1' or Halt = '1') then
- PC <= PC + 1;
- end if;
- if IntCycle = '1' and IStatus = "01" then
- IR <= "11111111";
- elsif Halt_FF = '1' or (IntCycle = '1' and IStatus = "10") or NMICycle = '1' then
- IR <= "00000000";
- else
- IR <= DInst;
- end if;
- ISet <= "00";
- if Prefix /= "00" then
- if Prefix = "11" then
- if IR(5) = '1' then
- XY_State <= "10";
- else
- XY_State <= "01";
- end if;
- else
- if Prefix = "10" then
- XY_State <= "00";
- XY_Ind <= '0';
- end if;
- ISet <= Prefix;
- end if;
- else
- XY_State <= "00";
- XY_Ind <= '0';
- end if;
- end if;
- else
- -- either (MCycle > 1) OR (MCycle = 1 AND TState > 3)
- if MCycle = "110" then
- XY_Ind <= '1';
- if Prefix = "01" then
- ISet <= "01";
- end if;
- end if;
- if T_Res = '1' then
- BTR_r <= (I_BT or I_BC or I_BTR) and not No_BTR;
- if Jump = '1' then
- A(15 downto 8) <= DI_Reg;
- A(7 downto 0) <= TmpAddr(7 downto 0);
- PC(15 downto 8) <= unsigned(DI_Reg);
- PC(7 downto 0) <= unsigned(TmpAddr(7 downto 0));
- elsif JumpXY = '1' then
- A <= RegBusC;
- PC <= unsigned(RegBusC);
- elsif Call = '1' or RstP = '1' then
- A <= TmpAddr;
- PC <= unsigned(TmpAddr);
- elsif MCycle = MCycles and NMICycle = '1' then
- A <= "0000000001100110";
- PC <= "0000000001100110";
- elsif MCycle = "011" and IntCycle = '1' and IStatus = "10" then
- A(15 downto 8) <= I;
- A(7 downto 0) <= TmpAddr(7 downto 0);
- PC(15 downto 8) <= unsigned(I);
- PC(7 downto 0) <= unsigned(TmpAddr(7 downto 0));
- else
- case Set_Addr_To is
- when aXY =>
- if XY_State = "00" then
- A <= RegBusC;
- else
- if NextIs_XY_Fetch = '1' then
- A <= std_logic_vector(PC);
- else
- A <= TmpAddr;
- end if;
- end if;
- when aIOA =>
- if Mode = 3 then
- -- Memory map I/O on GBZ80
- A(15 downto 8) <= (others => '1');
- elsif Mode = 2 then
- -- Duplicate I/O address on 8080
- A(15 downto 8) <= DI_Reg;
- else
- A(15 downto 8) <= ACC;
- end if;
- A(7 downto 0) <= DI_Reg;
- when aSP =>
- A <= std_logic_vector(SP);
- when aBC =>
- if Mode = 3 and IORQ_i = '1' then
- -- Memory map I/O on GBZ80
- A(15 downto 8) <= (others => '1');
- A(7 downto 0) <= RegBusC(7 downto 0);
- else
- A <= RegBusC;
- end if;
- when aDE =>
- A <= RegBusC;
- when aZI =>
- if Inc_WZ = '1' then
- A <= std_logic_vector(unsigned(TmpAddr) + 1);
- else
- A(15 downto 8) <= DI_Reg;
- A(7 downto 0) <= TmpAddr(7 downto 0);
- end if;
- when others =>
- A <= std_logic_vector(PC);
- end case;
- end if;
- Save_ALU_r <= Save_ALU;
- ALU_Op_r <= ALU_Op;
- if I_CPL = '1' then
- -- CPL
- ACC <= not ACC;
- F(Flag_Y) <= not ACC(5);
- F(Flag_H) <= '1';
- F(Flag_X) <= not ACC(3);
- F(Flag_N) <= '1';
- end if;
- if I_CCF = '1' then
- -- CCF
- F(Flag_C) <= not F(Flag_C);
- F(Flag_Y) <= ACC(5);
- F(Flag_H) <= F(Flag_C);
- F(Flag_X) <= ACC(3);
- F(Flag_N) <= '0';
- end if;
- if I_SCF = '1' then
- -- SCF
- F(Flag_C) <= '1';
- F(Flag_Y) <= ACC(5);
- F(Flag_H) <= '0';
- F(Flag_X) <= ACC(3);
- F(Flag_N) <= '0';
- end if;
- end if;
- if TState = 2 and Wait_n = '1' then
- if ISet = "01" and MCycle = "111" then
- IR <= DInst;
- end if;
- if JumpE = '1' then
- PC <= unsigned(signed(PC) + signed(DI_Reg));
- elsif Inc_PC = '1' then
- PC <= PC + 1;
- end if;
- if BTR_r = '1' then
- PC <= PC - 2;
- end if;
- if RstP = '1' then
- TmpAddr <= (others =>'0');
- TmpAddr(5 downto 3) <= IR(5 downto 3);
- end if;
- end if;
- if TState = 3 and MCycle = "110" then
- TmpAddr <= std_logic_vector(signed(RegBusC) + signed(DI_Reg));
- end if;
- if (TState = 2 and Wait_n = '1') or (TState = 4 and MCycle = "001") then
- if IncDec_16(2 downto 0) = "111" then
- if IncDec_16(3) = '1' then
- SP <= SP - 1;
- else
- SP <= SP + 1;
- end if;
- end if;
- end if;
- if LDSPHL = '1' then
- SP <= unsigned(RegBusC);
- end if;
- if ExchangeAF = '1' then
- Ap <= ACC;
- ACC <= Ap;
- Fp <= F;
- F <= Fp;
- end if;
- if ExchangeRS = '1' then
- Alternate <= not Alternate;
- end if;
- end if;
- if TState = 3 then
- if LDZ = '1' then
- TmpAddr(7 downto 0) <= DI_Reg;
- end if;
- if LDW = '1' then
- TmpAddr(15 downto 8) <= DI_Reg;
- end if;
- if Special_LD(2) = '1' then
- case Special_LD(1 downto 0) is
- when "00" =>
- ACC <= I;
- F(Flag_P) <= IntE_FF2;
- when "01" =>
- ACC <= std_logic_vector(R);
- F(Flag_P) <= IntE_FF2;
- when "10" =>
- I <= ACC;
- when others =>
- R <= unsigned(ACC);
- end case;
- end if;
- end if;
- if (I_DJNZ = '0' and Save_ALU_r = '1') or ALU_Op_r = "1001" then
- if Mode = 3 then
- F(6) <= F_Out(6);
- F(5) <= F_Out(5);
- F(7) <= F_Out(7);
- if PreserveC_r = '0' then
- F(4) <= F_Out(4);
- end if;
- else
- F(7 downto 1) <= F_Out(7 downto 1);
- if PreserveC_r = '0' then
- F(Flag_C) <= F_Out(0);
- end if;
- end if;
- end if;
- if T_Res = '1' and I_INRC = '1' then
- F(Flag_H) <= '0';
- F(Flag_N) <= '0';
- if DI_Reg(7 downto 0) = "00000000" then
- F(Flag_Z) <= '1';
- else
- F(Flag_Z) <= '0';
- end if;
- F(Flag_S) <= DI_Reg(7);
- F(Flag_P) <= not (DI_Reg(0) xor DI_Reg(1) xor DI_Reg(2) xor DI_Reg(3) xor
- DI_Reg(4) xor DI_Reg(5) xor DI_Reg(6) xor DI_Reg(7));
- end if;
- if TState = 1 then
- DO <= BusB;
- if I_RLD = '1' then
- DO(3 downto 0) <= BusA(3 downto 0);
- DO(7 downto 4) <= BusB(3 downto 0);
- end if;
- if I_RRD = '1' then
- DO(3 downto 0) <= BusB(7 downto 4);
- DO(7 downto 4) <= BusA(3 downto 0);
- end if;
- end if;
- if T_Res = '1' then
- Read_To_Reg_r(3 downto 0) <= Set_BusA_To;
- Read_To_Reg_r(4) <= Read_To_Reg;
- if Read_To_Acc = '1' then
- Read_To_Reg_r(3 downto 0) <= "0111";
- Read_To_Reg_r(4) <= '1';
- end if;
- end if;
- if TState = 1 and I_BT = '1' then
- F(Flag_X) <= ALU_Q(3);
- F(Flag_Y) <= ALU_Q(1);
- F(Flag_H) <= '0';
- F(Flag_N) <= '0';
- end if;
- if I_BC = '1' or I_BT = '1' then
- F(Flag_P) <= IncDecZ;
- end if;
- if (TState = 1 and Save_ALU_r = '0') or
- (Save_ALU_r = '1' and ALU_OP_r /= "0111") then
- case Read_To_Reg_r is
- when "10111" =>
- ACC <= Save_Mux;
- when "10110" =>
- DO <= Save_Mux;
- when "11000" =>
- SP(7 downto 0) <= unsigned(Save_Mux);
- when "11001" =>
- SP(15 downto 8) <= unsigned(Save_Mux);
- when "11011" =>
- F <= Save_Mux;
- when others =>
- end case;
- if XYbit_undoc='1' then
- DO <= ALU_Q;
- end if;
- end if;
- end if;
- end if;
- end process;
- ---------------------------------------------------------------------------
- --
- -- BC('), DE('), HL('), IX and IY
- --
- ---------------------------------------------------------------------------
- process (CLK_n)
- begin
- if CLK_n'event and CLK_n = '1' then
- if ClkEn = '1' then
- -- Bus A / Write
- RegAddrA_r <= Alternate & Set_BusA_To(2 downto 1);
- if XY_Ind = '0' and XY_State /= "00" and Set_BusA_To(2 downto 1) = "10" then
- RegAddrA_r <= XY_State(1) & "11";
- end if;
- -- Bus B
- RegAddrB_r <= Alternate & Set_BusB_To(2 downto 1);
- if XY_Ind = '0' and XY_State /= "00" and Set_BusB_To(2 downto 1) = "10" then
- RegAddrB_r <= XY_State(1) & "11";
- end if;
- -- Address from register
- RegAddrC <= Alternate & Set_Addr_To(1 downto 0);
- -- Jump (HL), LD SP,HL
- if (JumpXY = '1' or LDSPHL = '1') then
- RegAddrC <= Alternate & "10";
- end if;
- if ((JumpXY = '1' or LDSPHL = '1') and XY_State /= "00") or (MCycle = "110") then
- RegAddrC <= XY_State(1) & "11";
- end if;
- if I_DJNZ = '1' and Save_ALU_r = '1' and Mode < 2 then
- IncDecZ <= F_Out(Flag_Z);
- end if;
- if (TState = 2 or (TState = 3 and MCycle = "001")) and IncDec_16(2 downto 0) = "100" then
- if ID16 = 0 then
- IncDecZ <= '0';
- else
- IncDecZ <= '1';
- end if;
- end if;
- RegBusA_r <= RegBusA;
- end if;
- end if;
- end process;
- RegAddrA <=
- -- 16 bit increment/decrement
- Alternate & IncDec_16(1 downto 0) when (TState = 2 or
- (TState = 3 and MCycle = "001" and IncDec_16(2) = '1')) and XY_State = "00" else
- XY_State(1) & "11" when (TState = 2 or
- (TState = 3 and MCycle = "001" and IncDec_16(2) = '1')) and IncDec_16(1 downto 0) = "10" else
- -- EX HL,DL
- Alternate & "10" when ExchangeDH = '1' and TState = 3 else
- Alternate & "01" when ExchangeDH = '1' and TState = 4 else
- -- Bus A / Write
- RegAddrA_r;
- RegAddrB <=
- -- EX HL,DL
- Alternate & "01" when ExchangeDH = '1' and TState = 3 else
- -- Bus B
- RegAddrB_r;
- ID16 <= signed(RegBusA) - 1 when IncDec_16(3) = '1' else
- signed(RegBusA) + 1;
- process (Save_ALU_r, Auto_Wait_t1, ALU_OP_r, Read_To_Reg_r,
- ExchangeDH, IncDec_16, MCycle, TState, Wait_n)
- begin
- RegWEH <= '0';
- RegWEL <= '0';
- if (TState = 1 and Save_ALU_r = '0') or
- (Save_ALU_r = '1' and ALU_OP_r /= "0111") then
- case Read_To_Reg_r is
- when "10000" | "10001" | "10010" | "10011" | "10100" | "10101" =>
- RegWEH <= not Read_To_Reg_r(0);
- RegWEL <= Read_To_Reg_r(0);
- when others =>
- end case;
- end if;
- if ExchangeDH = '1' and (TState = 3 or TState = 4) then
- RegWEH <= '1';
- RegWEL <= '1';
- end if;
- if IncDec_16(2) = '1' and ((TState = 2 and Wait_n = '1' and MCycle /= "001") or (TState = 3 and MCycle = "001")) then
- case IncDec_16(1 downto 0) is
- when "00" | "01" | "10" =>
- RegWEH <= '1';
- RegWEL <= '1';
- when others =>
- end case;
- end if;
- end process;
- process (Save_Mux, RegBusB, RegBusA_r, ID16,
- ExchangeDH, IncDec_16, MCycle, TState, Wait_n)
- begin
- RegDIH <= Save_Mux;
- RegDIL <= Save_Mux;
- if ExchangeDH = '1' and TState = 3 then
- RegDIH <= RegBusB(15 downto 8);
- RegDIL <= RegBusB(7 downto 0);
- end if;
- if ExchangeDH = '1' and TState = 4 then
- RegDIH <= RegBusA_r(15 downto 8);
- RegDIL <= RegBusA_r(7 downto 0);
- end if;
- if IncDec_16(2) = '1' and ((TState = 2 and MCycle /= "001") or (TState = 3 and MCycle = "001")) then
- RegDIH <= std_logic_vector(ID16(15 downto 8));
- RegDIL <= std_logic_vector(ID16(7 downto 0));
- end if;
- end process;
- Regs : T80_Reg
- port map(
- Clk => CLK_n,
- CEN => ClkEn,
- WEH => RegWEH,
- WEL => RegWEL,
- AddrA => RegAddrA,
- AddrB => RegAddrB,
- AddrC => RegAddrC,
- DIH => RegDIH,
- DIL => RegDIL,
- DOAH => RegBusA(15 downto 8),
- DOAL => RegBusA(7 downto 0),
- DOBH => RegBusB(15 downto 8),
- DOBL => RegBusB(7 downto 0),
- DOCH => RegBusC(15 downto 8),
- DOCL => RegBusC(7 downto 0));
- ---------------------------------------------------------------------------
- --
- -- Buses
- --
- ---------------------------------------------------------------------------
- process (CLK_n)
- begin
- if CLK_n'event and CLK_n = '1' then
- if ClkEn = '1' then
- case Set_BusB_To is
- when "0111" =>
- BusB <= ACC;
- when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" =>
- if Set_BusB_To(0) = '1' then
- BusB <= RegBusB(7 downto 0);
- else
- BusB <= RegBusB(15 downto 8);
- end if;
- when "0110" =>
- BusB <= DI_Reg;
- when "1000" =>
- BusB <= std_logic_vector(SP(7 downto 0));
- when "1001" =>
- BusB <= std_logic_vector(SP(15 downto 8));
- when "1010" =>
- BusB <= "00000001";
- when "1011" =>
- BusB <= F;
- when "1100" =>
- BusB <= std_logic_vector(PC(7 downto 0));
- when "1101" =>
- BusB <= std_logic_vector(PC(15 downto 8));
- when "1110" =>
- BusB <= "00000000";
- when others =>
- BusB <= "--------";
- end case;
- case Set_BusA_To is
- when "0111" =>
- BusA <= ACC;
- when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" =>
- if Set_BusA_To(0) = '1' then
- BusA <= RegBusA(7 downto 0);
- else
- BusA <= RegBusA(15 downto 8);
- end if;
- when "0110" =>
- BusA <= DI_Reg;
- when "1000" =>
- BusA <= std_logic_vector(SP(7 downto 0));
- when "1001" =>
- BusA <= std_logic_vector(SP(15 downto 8));
- when "1010" =>
- BusA <= "00000000";
- when others =>
- BusB <= "--------";
- end case;
- if XYbit_undoc='1' then
- BusA <= DI_Reg;
- BusB <= DI_Reg;
- end if;
- end if;
- end if;
- end process;
- ---------------------------------------------------------------------------
- --
- -- Generate external control signals
- --
- ---------------------------------------------------------------------------
- process (RESET_n,CLK_n)
- begin
- if RESET_n = '0' then
- RFSH_n <= '1';
- elsif CLK_n'event and CLK_n = '1' then
- if CEN = '1' then
- if MCycle = "001" and ((TState = 2 and Wait_n = '1') or TState = 3) then
- RFSH_n <= '0';
- else
- RFSH_n <= '1';
- end if;
- end if;
- end if;
- end process;
- MC <= std_logic_vector(MCycle);
- TS <= std_logic_vector(TState);
- DI_Reg <= DI;
- HALT_n <= not Halt_FF;
- BUSAK_n <= not BusAck;
- IntCycle_n <= not IntCycle;
- IntE <= IntE_FF1;
- IORQ <= IORQ_i;
- Stop <= I_DJNZ;
- -------------------------------------------------------------------------
- --
- -- Syncronise inputs
- --
- -------------------------------------------------------------------------
- process (RESET_n, CLK_n)
- variable OldNMI_n : std_logic;
- begin
- if RESET_n = '0' then
- BusReq_s <= '0';
- INT_s <= '0';
- NMI_s <= '0';
- OldNMI_n := '0';
- elsif CLK_n'event and CLK_n = '1' then
- if CEN = '1' then
- BusReq_s <= not BUSRQ_n;
- INT_s <= not INT_n;
- if NMICycle = '1' then
- NMI_s <= '0';
- elsif NMI_n = '0' and OldNMI_n = '1' then
- NMI_s <= '1';
- end if;
- OldNMI_n := NMI_n;
- end if;
- end if;
- end process;
- -------------------------------------------------------------------------
- --
- -- Main state machine
- --
- -------------------------------------------------------------------------
- process (RESET_n, CLK_n)
- begin
- if RESET_n = '0' then
- MCycle <= "001";
- TState <= "000";
- Pre_XY_F_M <= "000";
- Halt_FF <= '0';
- BusAck <= '0';
- NMICycle <= '0';
- IntCycle <= '0';
- IntE_FF1 <= '0';
- IntE_FF2 <= '0';
- No_BTR <= '0';
- Auto_Wait_t1 <= '0';
- Auto_Wait_t2 <= '0';
- M1_n <= '1';
- elsif CLK_n'event and CLK_n = '1' then
- if CEN = '1' then
- Auto_Wait_t1 <= Auto_Wait;
- Auto_Wait_t2 <= Auto_Wait_t1;
- No_BTR <= (I_BT and (not IR(4) or not F(Flag_P))) or
- (I_BC and (not IR(4) or F(Flag_Z) or not F(Flag_P))) or
- (I_BTR and (not IR(4) or F(Flag_Z)));
- if TState = 2 then
- if SetEI = '1' then
- IntE_FF1 <= '1';
- IntE_FF2 <= '1';
- end if;
- if I_RETN = '1' then
- IntE_FF1 <= IntE_FF2;
- end if;
- end if;
- if TState = 3 then
- if SetDI = '1' then
- IntE_FF1 <= '0';
- IntE_FF2 <= '0';
- end if;
- end if;
- if IntCycle = '1' or NMICycle = '1' then
- Halt_FF <= '0';
- end if;
- if MCycle = "001" and TState = 2 and Wait_n = '1' then
- M1_n <= '1';
- end if;
- if BusReq_s = '1' and BusAck = '1' then
- else
- BusAck <= '0';
- if TState = 2 and Wait_n = '0' then
- elsif T_Res = '1' then
- if Halt = '1' then
- Halt_FF <= '1';
- end if;
- if BusReq_s = '1' then
- BusAck <= '1';
- else
- TState <= "001";
- if NextIs_XY_Fetch = '1' then
- MCycle <= "110";
- Pre_XY_F_M <= MCycle;
- if IR = "00110110" and Mode = 0 then
- Pre_XY_F_M <= "010";
- end if;
- elsif (MCycle = "111") or
- (MCycle = "110" and Mode = 1 and ISet /= "01") then
- MCycle <= std_logic_vector(unsigned(Pre_XY_F_M) + 1);
- elsif (MCycle = MCycles) or
- No_BTR = '1' or
- (MCycle = "010" and I_DJNZ = '1' and IncDecZ = '1') then
- M1_n <= '0';
- MCycle <= "001";
- IntCycle <= '0';
- NMICycle <= '0';
- if NMI_s = '1' and Prefix = "00" then
- NMICycle <= '1';
- IntE_FF1 <= '0';
- elsif (IntE_FF1 = '1' and INT_s = '1') and Prefix = "00" and SetEI = '0' then
- IntCycle <= '1';
- IntE_FF1 <= '0';
- IntE_FF2 <= '0';
- end if;
- else
- MCycle <= std_logic_vector(unsigned(MCycle) + 1);
- end if;
- end if;
- else
- if Auto_Wait = '1' nand Auto_Wait_t2 = '0' then
- TState <= TState + 1;
- end if;
- end if;
- end if;
- if TState = 0 then
- M1_n <= '0';
- end if;
- end if;
- end if;
- end process;
- process (IntCycle, NMICycle, MCycle)
- begin
- Auto_Wait <= '0';
- if IntCycle = '1' or NMICycle = '1' then
- if MCycle = "001" then
- Auto_Wait <= '1';
- end if;
- end if;
- end process;
- end;
|