diff --git a/README b/README index ab0bf22..2fce770 100644 --- a/README +++ b/README @@ -26,7 +26,7 @@ -- **** -- Z80 compatible microprocessor core -- --- Version : 0247 +-- Version : 0250 -- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) -- All rights reserved -- diff --git a/T80.vhd b/T80.vhd index a466db6..86a8619 100644 --- a/T80.vhd +++ b/T80.vhd @@ -21,7 +21,7 @@ -- **** -- Z80 compatible microprocessor core -- --- Version : 0247 +-- Version : 0250 -- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) -- All rights reserved -- @@ -73,6 +73,7 @@ -- 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 +-- 0250 : Added R800 Multiplier by TobiFlex 2017.10.15 -- library IEEE; @@ -118,6 +119,7 @@ entity T80 is IntCycle_n : out std_logic; IntE : out std_logic; Stop : out std_logic; + R800_mode : in std_logic := '0'; out0 : in std_logic := '0'; -- 0 => OUT(C),0, 1 => OUT(C),255 REG : out std_logic_vector(211 downto 0); -- IFF2, IFF1, IM, IY, HL', DE', BC', IX, HL, DE, BC, PC, SP, R, I, F', A', F, A @@ -155,6 +157,9 @@ architecture rtl of T80 is 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 MULU_Prod32 : std_logic_vector(31 downto 0); + signal MULU_tmp : std_logic_vector(31 downto 0); + signal MULU_Fakt1 : std_logic_vector(15 downto 0); signal ID16 : signed(15 downto 0); signal Save_Mux : std_logic_vector(7 downto 0); @@ -245,6 +250,8 @@ architecture rtl of T80 is signal I_RRD : std_logic; signal I_RXDD : std_logic; signal I_INRC : std_logic; + signal I_MULUB : std_logic; + signal I_MULU : std_logic; signal SetWZ : std_logic_vector(1 downto 0); signal SetDI : std_logic; signal SetEI : std_logic; @@ -326,6 +333,8 @@ begin I_RLD => I_RLD, I_RRD => I_RRD, I_INRC => I_INRC, + I_MULUB => I_MULUB, + I_MULU => I_MULU, SetWZ => SetWZ, SetDI => SetDI, SetEI => SetEI, @@ -333,7 +342,8 @@ begin Halt => Halt, NoRead => NoRead_int, Write => Write_int, - XYbit_undoc => XYbit_undoc); + XYbit_undoc => XYbit_undoc, + R800_mode => R800_mode); alu : T80_ALU generic map( @@ -874,6 +884,42 @@ begin end if; end process; +--------------------------------------------------------------------------- +-- +-- Multiply +-- +--------------------------------------------------------------------------- + process (CLK_n, ACC, RegBusB, MULU_tmp, MULU_Fakt1, MULU_Prod32) + begin + + MULU_tmp(31 downto 12) <= std_logic_vector((unsigned(MULU_Fakt1)*unsigned(MULU_Prod32(3 downto 0)))+unsigned("0000"&MULU_Prod32(31 downto 16))); + MULU_tmp(11 downto 0) <= MULU_Prod32(15 downto 4); + + if rising_edge(CLK_n) then + if ClkEn = '1' then + if T_Res='1' then + if I_MULUB='1' then + MULU_Prod32(7 downto 0) <= ACC; + MULU_Prod32(15 downto 8) <= "--------"; + MULU_Prod32(31 downto 16) <= X"0000"; + MULU_Fakt1(7 downto 0) <= "00000000"; + if Set_BusB_To(0) = '1' then + MULU_Fakt1(15 downto 8) <= RegBusB(7 downto 0); + else + MULU_Fakt1(15 downto 8) <= RegBusB(15 downto 8); + end if; + else + MULU_Prod32(15 downto 0) <= RegBusA; + MULU_Prod32(31 downto 16) <= X"0000"; + MULU_Fakt1 <= RegBusB; + end if; + else + MULU_Prod32 <= MULU_tmp; + end if; + end if; + end if; + end process; + --------------------------------------------------------------------------- -- -- BC('), DE('), HL('), IX and IY @@ -929,7 +975,7 @@ begin (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 + Alternate & "01" when (ExchangeDH = '1' or I_MULU = '1') and TState = 4 else -- LDHLSP "010" when LDHLSP = '1' and TState = 4 else -- Bus A / Write @@ -944,7 +990,7 @@ begin 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, + process (Save_ALU_r, Auto_Wait_t1, ALU_OP_r, Read_To_Reg_r, I_MULU, T_Res, ExchangeDH, IncDec_16, MCycle, TState, Wait_n, LDHLSP) begin RegWEH <= '0'; @@ -959,6 +1005,11 @@ begin end case; end if; + if I_MULU = '1' and (T_Res = '1' or TState = 4) then -- TState = 4 DE write + RegWEH <= '1'; + RegWEL <= '1'; + end if; + if ExchangeDH = '1' and (TState = 3 or TState = 4) then RegWEH <= '1'; RegWEL <= '1'; @@ -981,12 +1032,22 @@ begin TmpAddr2 <= std_logic_vector(unsigned(signed(SP) + signed(Save_Mux))); - process (Save_Mux, RegBusB, RegBusA_r, ID16, + process (Save_Mux, RegBusB, RegBusA_r, ID16, I_MULU, MULU_Prod32, MULU_tmp, T_Res, ExchangeDH, IncDec_16, MCycle, TState, Wait_n, LDHLSP, TmpAddr2) begin RegDIH <= Save_Mux; RegDIL <= Save_Mux; + if I_MULU = '1' then + if T_Res = '1' then + RegDIH <= MULU_Prod32(31 downto 24); + RegDIL <= MULU_Prod32(23 downto 16); + else + RegDIH <= MULU_tmp(15 downto 8); -- TState = 4 DE write + RegDIL <= MULU_tmp(7 downto 0); + end if; + end if; + if LDHLSP = '1' and MCycle = "010" and TState = 4 then RegDIH <= TmpAddr2(15 downto 8); RegDIL <= TmpAddr2(7 downto 0); diff --git a/T80_MCode.vhd b/T80_MCode.vhd index 7346548..bdd9b0e 100644 --- a/T80_MCode.vhd +++ b/T80_MCode.vhd @@ -19,7 +19,7 @@ -- **** -- Z80 compatible microprocessor core -- --- Version : 0242 +-- Version : 0250 -- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) -- All rights reserved -- @@ -69,6 +69,7 @@ -- 0240 : Added (IX/IY+d) states, removed op-codes from mode 2 and added all remaining mode 3 op-codes -- 0240mj1 fix for HL inc/dec for INI, IND, INIR, INDR, OUTI, OUTD, OTIR, OTDR -- 0242 : Fixed I/O instruction timing, cleanup +-- 0250 : Added R800 Multiplier by TobiFlex 2017.10.15 -- library IEEE; @@ -140,6 +141,8 @@ entity T80_MCode is I_RLD : out std_logic; I_RRD : out std_logic; I_INRC : out std_logic; + I_MULUB : out std_logic; + I_MULU : out std_logic; SetWZ : out std_logic_vector(1 downto 0); SetDI : out std_logic; SetEI : out std_logic; @@ -147,7 +150,8 @@ entity T80_MCode is Halt : out std_logic; NoRead : out std_logic; Write : out std_logic; - XYbit_undoc : out std_logic + XYbit_undoc : out std_logic; + R800_mode : in std_logic ); end T80_MCode; @@ -185,7 +189,7 @@ architecture rtl of T80_MCode is begin - process (IR, ISet, MCycle, F, NMICycle, IntCycle, XY_State) + process (IR, ISet, MCycle, F, NMICycle, IntCycle, XY_State, R800_mode) variable DDD : std_logic_vector(2 downto 0); variable SSS : std_logic_vector(2 downto 0); variable DPair : std_logic_vector(1 downto 0); @@ -243,6 +247,8 @@ begin I_RLD <= '0'; I_RRD <= '0'; I_INRC <= '0'; + I_MULUB <= '0'; + I_MULU <= '0'; SetDI <= '0'; SetEI <= '0'; IMode <= "11"; @@ -1769,13 +1775,13 @@ begin | "10101100"|"10101101"|"10101110"|"10101111" | "10110100"|"10110101"|"10110110"|"10110111" | "10111100"|"10111101"|"10111110"|"10111111" - |"11000000"|"11000001"|"11000010"|"11000011"|"11000100"|"11000101"|"11000110"|"11000111" - |"11001000"|"11001001"|"11001010"|"11001011"|"11001100"|"11001101"|"11001110"|"11001111" - |"11010000"|"11010001"|"11010010"|"11010011"|"11010100"|"11010101"|"11010110"|"11010111" - |"11011000"|"11011001"|"11011010"|"11011011"|"11011100"|"11011101"|"11011110"|"11011111" + |"11000000"| "11000010" |"11000100"|"11000101"|"11000110"|"11000111" + |"11001000"| "11001010"|"11001011"|"11001100"|"11001101"|"11001110"|"11001111" + |"11010000"| "11010010"|"11010011"|"11010100"|"11010101"|"11010110"|"11010111" + |"11011000"| "11011010"|"11011011"|"11011100"|"11011101"|"11011110"|"11011111" |"11100000"|"11100001"|"11100010"|"11100011"|"11100100"|"11100101"|"11100110"|"11100111" |"11101000"|"11101001"|"11101010"|"11101011"|"11101100"|"11101101"|"11101110"|"11101111" - |"11110000"|"11110001"|"11110010"|"11110011"|"11110100"|"11110101"|"11110110"|"11110111" + |"11110000"|"11110001"|"11110010" |"11110100"|"11110101"|"11110110"|"11110111" |"11111000"|"11111001"|"11111010"|"11111011"|"11111100"|"11111101"|"11111110"|"11111111" => null; -- NOP, undocumented when "01110111"|"01111111" => @@ -2159,6 +2165,46 @@ begin TStates <= "101"; when others => null; end case; + when "11000001"|"11001001"|"11010001"|"11011001" => + --R800 MULUB + if R800_mode = '1' then + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + NoRead <= '1'; + I_MULUB <= '1'; + Set_BusB_To(2 downto 0) <= IR(5 downto 3); + Set_BusB_To(3) <= '0'; + when 2 => + NoRead <= '1'; + I_MULU <= '1'; + Set_BusA_To(2 downto 0) <= "100"; + when others => null; + end case; + end if; + when "11000011"|"11110011" => + --R800 MULUW + if R800_mode = '1' then + MCycles <= "010"; + case to_integer(unsigned(MCycle)) is + when 1 => + NoRead <= '1'; + if DPAIR = "11" then + Set_BusB_To(3 downto 0) <= "1000"; + else + Set_BusB_To(2 downto 1) <= DPAIR; + Set_BusB_To(0) <= '0'; + Set_BusB_To(3) <= '0'; + end if; + Set_BusA_To(2 downto 0) <= "100"; + when 2 => + TStates <= "101"; + NoRead <= '1'; + I_MULU <= '1'; + Set_BusA_To(2 downto 0) <= "100"; + when others => null; + end case; + end if; end case; end case; diff --git a/T80_Pack.vhd b/T80_Pack.vhd index d674f44..fd9eebb 100644 --- a/T80_Pack.vhd +++ b/T80_Pack.vhd @@ -11,7 +11,7 @@ -- -- Z80 compatible microprocessor core -- --- Version : 0242 +-- Version : 0250 -- -- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) -- @@ -105,6 +105,7 @@ package T80_Pack is IntCycle_n : out std_logic; IntE : out std_logic; Stop : out std_logic; + R800_mode : in std_logic := '0'; out0 : in std_logic := '0'; -- 0 => OUT(C),0, 1 => OUT(C),255 REG : out std_logic_vector(211 downto 0); -- IFF2, IFF1, IM, IY, HL', DE', BC', IX, HL, DE, BC, PC, SP, R, I, F', A', F, A DIRSet : in std_logic := '0'; @@ -199,6 +200,8 @@ package T80_Pack is I_RLD : out std_logic; I_RRD : out std_logic; I_INRC : out std_logic; + I_MULUB : out std_logic; + I_MULU : out std_logic; SetWZ : out std_logic_vector(1 downto 0); SetDI : out std_logic; SetEI : out std_logic; @@ -206,7 +209,8 @@ package T80_Pack is Halt : out std_logic; NoRead : out std_logic; Write : out std_logic; - XYbit_undoc : out std_logic + XYbit_undoc : out std_logic; + R800_mode : in std_logic ); end component; diff --git a/T80a.vhd b/T80a.vhd index 75636aa..2103a5c 100644 --- a/T80a.vhd +++ b/T80a.vhd @@ -10,7 +10,7 @@ -- -- Z80 compatible microprocessor core, asynchronous top level -- --- Version : 0247 +-- Version : 0250 -- -- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org) -- @@ -67,6 +67,11 @@ -- -- 0247 : Fixed bus req/ack cycle -- +-- 0247a: 7th of September, 2003 by Kazuhiro Tsujikawa (tujikawa@hat.hi-ho.ne.jp) +-- Fixed IORQ_n, RD_n, WR_n bus timing +-- +-- 0250 : Added R800 Multiplier by TobiFlex 2017.10.15 +-- library IEEE; use IEEE.std_logic_1164.all; @@ -75,10 +80,12 @@ use work.T80_Pack.all; entity T80a is generic( - Mode : integer := 0 -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB + Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB + IOWait : integer := 1 -- 0 => Single I/O cycle, 1 => Std I/O cycle ); port( RESET_n : in std_logic; + R800_mode : in std_logic; CLK_n : in std_logic; WAIT_n : in std_logic; INT_n : in std_logic; @@ -92,8 +99,8 @@ entity T80a is RFSH_n : out std_logic; HALT_n : out std_logic; BUSAK_n : out std_logic; - A : out std_logic_vector(15 downto 0); - D : inout std_logic_vector(7 downto 0) + A : out std_logic_vector(15 downto 0); + D : inout std_logic_vector(7 downto 0) ); end T80a; @@ -107,12 +114,14 @@ architecture rtl of T80a is signal Write : std_logic; signal MREQ : std_logic; signal MReq_Inhibit : std_logic; + signal IReq_Inhibit : std_logic; -- 0247a signal Req_Inhibit : std_logic; signal RD : std_logic; signal MREQ_n_i : std_logic; signal IORQ_n_i : std_logic; signal RD_n_i : std_logic; signal WR_n_i : std_logic; + signal WR_n_j : std_logic; -- 0247a signal RFSH_n_i : std_logic; signal BUSAK_n_i : std_logic; signal A_i : std_logic_vector(15 downto 0); @@ -129,11 +138,12 @@ begin BUSAK_n <= BUSAK_n_i; MREQ_n_i <= not MREQ or (Req_Inhibit and MReq_Inhibit); RD_n_i <= not RD or Req_Inhibit; + WR_n_j <= WR_n_i; -- 0247a MREQ_n <= MREQ_n_i when BUSAK_n_i = '1' else 'Z'; - IORQ_n <= IORQ_n_i when BUSAK_n_i = '1' else 'Z'; + IORQ_n <= IORQ_n_i or IReq_Inhibit when BUSAK_n_i = '1' else 'Z'; -- 0247a RD_n <= RD_n_i when BUSAK_n_i = '1' else 'Z'; - WR_n <= WR_n_i when BUSAK_n_i = '1' else 'Z'; + WR_n <= WR_n_j when BUSAK_n_i = '1' else 'Z'; -- 0247a RFSH_n <= RFSH_n_i when BUSAK_n_i = '1' else 'Z'; A <= A_i when BUSAK_n_i = '1' else (others => 'Z'); D <= DO when Write = '1' and BUSAK_n_i = '1' else (others => 'Z'); @@ -150,8 +160,9 @@ begin u0 : T80 generic map( Mode => Mode, - IOWait => 1) + IOWait => IOWait) port map( + R800_mode => R800_mode, CEN => CEN, M1_n => M1_n, IORQ => IORQ, @@ -184,24 +195,40 @@ begin end if; end process; - process (Reset_s,CLK_n) + process (CLK_n) -- 0247a + begin + if CLK_n'event and CLK_n = '1' then + IReq_Inhibit <= not IORQ; + end if; + end process; + + process (Reset_s,CLK_n) -- 0247a begin if Reset_s = '0' then WR_n_i <= '1'; - elsif CLK_n'event and CLK_n = '1' then - WR_n_i <= '1'; - if TState = "001" then -- To short for IO writes !!!!!!!!!!!!!!!!!!! - WR_n_i <= not Write; + elsif CLK_n'event and CLK_n = '0' then + if (IORQ = '0') then + if TState = "010" then + WR_n_i <= not Write; + elsif Tstate = "011" then + WR_n_i <= '1'; + end if; + else + if TState = "001" and IORQ_n_i = '0' then + WR_n_i <= not Write; + elsif Tstate = "011" then + WR_n_i <= '1'; + end if; end if; end if; end process; - process (Reset_s,CLK_n) + process (Reset_s,CLK_n) -- 0247a begin if Reset_s = '0' then Req_Inhibit <= '0'; elsif CLK_n'event and CLK_n = '1' then - if MCycle = "001" and TState = "010" then + if MCycle = "001" and TState = "010" and wait_s = '1' then Req_Inhibit <= '1'; else Req_Inhibit <= '0'; @@ -246,9 +273,13 @@ begin end if; else if TState = "001" and NoRead = '0' then - RD <= not Write; IORQ_n_i <= not IORQ; MREQ <= not IORQ; + if IORQ = '0' then + RD <= not Write; + elsif IORQ_n_i = '0' then + RD <= not Write; + end if; end if; if TState = "011" then RD <= '0'; diff --git a/T80pa.vhd b/T80pa.vhd index cd971eb..2ac4e89 100644 --- a/T80pa.vhd +++ b/T80pa.vhd @@ -83,6 +83,7 @@ entity T80pa is A : out std_logic_vector(15 downto 0); DI : in std_logic_vector(7 downto 0); DO : out std_logic_vector(7 downto 0); + R800_mode : in std_logic := '0'; REG : out std_logic_vector(211 downto 0); -- IFF2, IFF1, IM, IY, HL', DE', BC', IX, HL, DE, BC, PC, SP, R, I, F', A', F, A DIRSet : in std_logic := '0'; DIR : in std_logic_vector(211 downto 0) := (others => '0') -- IFF2, IFF1, IM, IY, HL', DE', BC', IX, HL, DE, BC, PC, SP, R, I, F', A', F, A @@ -135,6 +136,7 @@ begin MC => MCycle, TS => TState, OUT0 => OUT0, + R800_mode => R800_mode, IntCycle_n => IntCycle_n, DIRSet => DIRSet, DIR => DIR