OpenCores
URL https://opencores.org/ocsvn/t80/t80/trunk

Subversion Repositories t80

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /t80/trunk/rtl/vhdl
    from Rev 46 to Rev 47
    Reverse comparison

Rev 46 → Rev 47

/SSRAM2.vhd
0,0 → 1,92
--
-- Inferrable Synchronous SRAM for Leonardo synthesis, no write through!
--
-- Version : 0236
--
-- Copyright (c) 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/t51/
--
-- Limitations :
--
-- File history :
--
 
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
 
entity SSRAM is
generic(
AddrWidth : integer := 16;
DataWidth : integer := 8
);
port(
Clk : in std_logic;
CE_n : in std_logic;
WE_n : in std_logic;
A : in std_logic_vector(AddrWidth - 1 downto 0);
DIn : in std_logic_vector(DataWidth - 1 downto 0);
DOut : out std_logic_vector(DataWidth - 1 downto 0)
);
end SSRAM;
 
architecture behaviour of SSRAM is
 
type Memory_Image is array (natural range <>) of std_logic_vector(DataWidth - 1 downto 0);
signal RAM : Memory_Image(0 to 2 ** AddrWidth - 1);
-- signal A_r : std_logic_vector(AddrWidth - 1 downto 0);
 
begin
 
process (Clk)
begin
if Clk'event and Clk = '1' then
-- pragma translate_off
if not is_x(A) then
-- pragma translate_on
DOut <= RAM(to_integer(unsigned(A(AddrWidth - 1 downto 0))));
-- pragma translate_off
end if;
-- pragma translate_on
if CE_n = '0' and WE_n = '0' then
RAM(to_integer(unsigned(A))) <= DIn;
end if;
-- A_r <= A;
end if;
end process;
 
end;
/SSRAMX.vhd
0,0 → 1,132
--
-- Xilinx Block RAM, 8 bit wide and variable size (Min. 512 bytes)
--
-- Version : 0247
--
-- Copyright (c) 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/t51/
--
-- Limitations :
--
-- File history :
--
-- 0240 : Initial release
--
-- 0242 : Changed RAMB4_S8 to map by name
--
-- 0247 : Added RAMB4_S8 component declaration
--
 
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
 
entity SSRAM is
generic(
AddrWidth : integer := 11;
DataWidth : integer := 8
);
port(
Clk : in std_logic;
CE_n : in std_logic;
WE_n : in std_logic;
A : in std_logic_vector(AddrWidth - 1 downto 0);
DIn : in std_logic_vector(DataWidth - 1 downto 0);
DOut : out std_logic_vector(DataWidth - 1 downto 0)
);
end SSRAM;
 
architecture rtl of SSRAM is
 
component RAMB4_S8
port(
DO : out std_logic_vector(7 downto 0);
ADDR : in std_logic_vector(8 downto 0);
CLK : in std_ulogic;
DI : in std_logic_vector(7 downto 0);
EN : in std_ulogic;
RST : in std_ulogic;
WE : in std_ulogic);
end component;
 
constant RAMs : integer := (2 ** AddrWidth) / 512;
 
type bRAMOut_a is array(0 to RAMs - 1) of std_logic_vector(7 downto 0);
 
signal bRAMOut : bRAMOut_a;
signal biA_r : integer;
signal A_r : unsigned(A'left downto 0);
-- signal A_i : std_logic_vector(8 downto 0);
signal WEA : std_logic_vector(RAMs - 1 downto 0);
 
begin
 
process (Clk)
begin
if Clk'event and Clk = '1' then
A_r <= unsigned(A);
end if;
end process;
 
biA_r <= to_integer(A_r(A'left downto 9));
-- A_i <= std_logic_vector(A_r(8 downto 0)) when (CE_n nor WE_n) = '1' else A(8 downto 0);
 
bG1: for I in 0 to RAMs - 1 generate
begin
WEA(I) <= '1' when (CE_n nor WE_n) = '1' and biA_r = I else '0';
BSSRAM : RAMB4_S8
port map(
DI => DIn,
EN => '1',
WE => WEA(I),
RST => '0',
CLK => Clk,
ADDR => A,
DO => bRAMOut(I));
end generate;
 
process (biA_r, bRAMOut)
begin
DOut <= bRAMOut(0);
for I in 1 to RAMs - 1 loop
if biA_r = I then
DOut <= bRAMOut(I);
end if;
end loop;
end process;
 
end;
/SSRAM.vhd
0,0 → 1,92
--
-- Inferrable Synchronous SRAM for XST synthesis
--
-- Version : 0220
--
-- Copyright (c) 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/t51/
--
-- Limitations :
--
-- File history :
-- 0208 : Initial release
-- 0218 : Fixed data out at write
-- 0220 : Added support for XST
 
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
 
entity SSRAM is
generic(
AddrWidth : integer := 11;
DataWidth : integer := 8
);
port(
Clk : in std_logic;
CE_n : in std_logic;
WE_n : in std_logic;
A : in std_logic_vector(AddrWidth - 1 downto 0);
DIn : in std_logic_vector(DataWidth - 1 downto 0);
DOut : out std_logic_vector(DataWidth - 1 downto 0)
);
end SSRAM;
 
architecture behaviour of SSRAM is
 
type Memory_Image is array (natural range <>) of std_logic_vector(DataWidth - 1 downto 0);
signal RAM : Memory_Image(0 to 2 ** AddrWidth - 1);
signal A_r : std_logic_vector(AddrWidth - 1 downto 0);
 
begin
 
process (Clk)
begin
if Clk'event and Clk = '1' then
if (CE_n nor WE_n) = '1' then
RAM(to_integer(unsigned(A))) <= DIn;
end if;
A_r <= A;
end if;
end process;
 
DOut <= RAM(to_integer(unsigned(A_r)))
-- pragma translate_off
when not is_x(A_r) else (others => '-')
-- pragma translate_on
;
end;
/T16450.vhd
0,0 → 1,459
--
-- 16450 compatible UART with synchronous bus interface
-- RClk/BaudOut is XIn enable instead of actual clock
--
-- Version : 0249b
--
-- Copyright (c) 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 release
--
-- 0249 : Fixed interrupt and baud rate bugs found by Andy Dyer
-- Added modem status and break detection
-- Added support for 1.5 and 2 stop bits
--
-- 0249b : Fixed loopback break generation bugs found by Andy Dyer
--
 
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
 
entity T16450 is
port(
MR_n : in std_logic;
XIn : in std_logic;
RClk : in std_logic;
CS_n : in std_logic;
Rd_n : in std_logic;
Wr_n : in std_logic;
A : in std_logic_vector(2 downto 0);
D_In : in std_logic_vector(7 downto 0);
D_Out : out std_logic_vector(7 downto 0);
SIn : in std_logic;
CTS_n : in std_logic;
DSR_n : in std_logic;
RI_n : in std_logic;
DCD_n : in std_logic;
SOut : out std_logic;
RTS_n : out std_logic;
DTR_n : out std_logic;
OUT1_n : out std_logic;
OUT2_n : out std_logic;
BaudOut : out std_logic;
Intr : out std_logic
);
end T16450;
 
architecture rtl of T16450 is
 
signal RBR : std_logic_vector(7 downto 0); -- Reciever Buffer Register
signal THR : std_logic_vector(7 downto 0); -- Transmitter Holding Register
signal IER : std_logic_vector(7 downto 0); -- Interrupt Enable Register
signal IIR : std_logic_vector(7 downto 0); -- Interrupt Ident. Register
signal LCR : std_logic_vector(7 downto 0); -- Line Control Register
signal MCR : std_logic_vector(7 downto 0); -- MODEM Control Register
signal LSR : std_logic_vector(7 downto 0); -- Line Status Register
signal MSR : std_logic_vector(7 downto 0); -- MODEM Status Register
signal SCR : std_logic_vector(7 downto 0); -- Scratch Register
signal DLL : std_logic_vector(7 downto 0); -- Divisor Latch (LS)
signal DLM : std_logic_vector(7 downto 0); -- Divisor Latch (MS)
 
signal DM0 : std_logic_vector(7 downto 0);
signal DM1 : std_logic_vector(7 downto 0);
 
signal MSR_In : std_logic_vector(3 downto 0);
 
signal Bit_Phase : unsigned(3 downto 0);
signal Brk_Cnt : unsigned(3 downto 0);
signal RX_Filtered : std_logic;
signal RX_ShiftReg : std_logic_vector(7 downto 0);
signal RX_Bit_Cnt : integer range 0 to 11;
signal RX_Parity : std_logic;
signal RXD : std_logic;
 
signal TX_Tick : std_logic;
signal TX_ShiftReg : std_logic_vector(7 downto 0);
signal TX_Bit_Cnt : integer range 0 to 11;
signal TX_Parity : std_logic;
signal TX_Next_Is_Stop : std_logic;
signal TX_Stop_Bit : std_logic;
signal TXD : std_logic;
 
begin
 
DTR_n <= MCR(4) or not MCR(0);
RTS_n <= MCR(4) or not MCR(1);
OUT1_n <= MCR(4) or not MCR(2);
OUT2_n <= MCR(4) or not MCR(3);
SOut <= MCR(4) or (TXD and not LCR(6));
RXD <= SIn when MCR(4) = '0' else (TXD and not LCR(6));
 
Intr <= not IIR(0);
 
-- Registers
DM0 <= DLL when LCR(7) = '1' else RBR;
DM1 <= DLM when LCR(7) = '1' else IER;
with A select
D_Out <=
DM0 when "000",
DM1 when "001",
IIR when "010",
LCR when "011",
MCR when "100",
LSR when "101",
MSR when "110",
SCR when others;
process (MR_n, XIn)
begin
if MR_n = '0' then
THR <= "00000000";
IER <= "00000000";
LCR <= "00000000";
MCR <= "00000000";
MSR(3 downto 0) <= "0000";
SCR <= "00000000"; -- ??
DLL <= "00000000"; -- ??
DLM <= "00000000"; -- ??
elsif XIn'event and XIn = '1' then
if Wr_n = '0' and CS_n = '0' then
case A is
when "000" =>
if LCR(7) = '1' then
DLL <= D_In;
else
THR <= D_In;
end if;
when "001" =>
if LCR(7) = '1' then
DLM <= D_In;
else
IER(3 downto 0) <= D_In(3 downto 0);
end if;
when "011" =>
LCR <= D_In;
when "100" =>
MCR <= D_In;
when "111" =>
SCR <= D_In;
when others =>
end case;
end if;
if Rd_n = '0' and CS_n = '0' and A = "110" then
MSR(3 downto 0) <= "0000";
end if;
if MSR(4) /= MSR_In(0) then
MSR(0) <= '1';
end if;
if MSR(5) /= MSR_In(1) then
MSR(1) <= '1';
end if;
if MSR(6) = '0' and MSR_In(2) = '1' then
MSR(2) <= '1';
end if;
if MSR(7) /= MSR_In(3) then
MSR(3) <= '1';
end if;
end if;
end process;
process (XIn)
begin
if XIn'event and XIn = '1' then
if MCR(4) = '0' then
MSR(4) <= MSR_In(0);
MSR(5) <= MSR_In(1);
MSR(6) <= MSR_In(2);
MSR(7) <= MSR_In(3);
else
MSR(4) <= MCR(1);
MSR(5) <= MCR(0);
MSR(6) <= MCR(2);
MSR(7) <= MCR(3);
end if;
MSR_In(0) <= CTS_n;
MSR_In(1) <= DSR_n;
MSR_In(2) <= RI_n;
MSR_In(3) <= DCD_n;
end if;
end process;
 
IIR(7 downto 3) <= "00000";
IIR(2 downto 0) <=
"110" when IER(2) = '1' and LSR(4 downto 1) /= "0000" else
"100" when (IER(0) and LSR(0)) = '1' else
"010" when (IER(1) and LSR(5)) = '1' else
"000" when IER(3) = '1' and ((MCR(4) = '0' and MSR(3 downto 0) /= "0000") or
(MCR(4) = '1' and MCR(3 downto 0) /= "0000")) else
"001";
 
-- Baud x 16 clock generator
process (MR_n, XIn)
variable Baud_Cnt : unsigned(15 downto 0);
begin
if MR_n = '0' then
Baud_Cnt := "0000000000000000";
BaudOut <= '0';
elsif XIn'event and XIn = '1' then
if Baud_Cnt(15 downto 1) = "000000000000000" or (Wr_n = '0' and CS_n = '0' and A(2 downto 1) = "00" and LCR(7) = '1') then
Baud_Cnt(15 downto 8) := unsigned(DLM);
Baud_Cnt(7 downto 0) := unsigned(DLL);
BaudOut <= '1';
else
Baud_Cnt := Baud_Cnt - 1;
BaudOut <= '0';
end if;
end if;
end process;
 
-- Input filter
process (MR_n, XIn)
variable Samples : std_logic_vector(1 downto 0);
begin
if MR_n = '0' then
Samples := "11";
RX_Filtered <= '1';
elsif XIn'event and XIn = '1' then
if RClk = '1' then
Samples(1) := Samples(0);
Samples(0) := RXD;
end if;
if Samples = "00" then
RX_Filtered <= '0';
end if;
if Samples = "11" then
RX_Filtered <= '1';
end if;
end if;
end process;
 
-- Receive state machine
process (MR_n, XIn)
begin
if MR_n = '0' then
RBR <= "00000000";
LSR(4 downto 0) <= "00000";
Bit_Phase <= "0000";
Brk_Cnt <= "0000";
RX_ShiftReg(7 downto 0) <= "00000000";
RX_Bit_Cnt <= 0;
RX_Parity <= '0';
elsif XIn'event and XIn = '1' then
if A = "000" and LCR(7) = '0' and Rd_n = '0' and CS_n = '0' then
LSR(0) <= '0'; -- DR
end if;
if A = "101" and Rd_n = '0' and CS_n = '0' then
LSR(4) <= '0'; -- BI
LSR(3) <= '0'; -- FE
LSR(2) <= '0'; -- PE
LSR(1) <= '0'; -- OE
end if;
if RClk = '1' then
if RX_Bit_Cnt = 0 and (RX_Filtered = '1' or Bit_Phase = "0111") then
Bit_Phase <= "0000";
else
Bit_Phase <= Bit_Phase + 1;
end if;
if Bit_Phase = "1111" then
if RX_Filtered = '1' then
Brk_Cnt <= "0000";
else
Brk_Cnt <= Brk_Cnt + 1;
end if;
if Brk_Cnt = "1100" then
LSR(4) <= '1'; -- BI
end if;
end if;
if RX_Bit_Cnt = 0 then
if Bit_Phase = "0111" then
RX_Bit_Cnt <= RX_Bit_Cnt + 1;
RX_Parity <= not LCR(4); -- EPS
end if;
elsif Bit_Phase = "1111" then
RX_Bit_Cnt <= RX_Bit_Cnt + 1;
if RX_Bit_Cnt = 10 then -- Parity stop bit
RX_Bit_Cnt <= 0;
LSR(0) <= '1'; -- UART Receive complete
LSR(3) <= not RX_Filtered; -- Framing error
elsif (RX_Bit_Cnt = 9 and LCR(1 downto 0) = "11") or
(RX_Bit_Cnt = 8 and LCR(1 downto 0) = "10") or
(RX_Bit_Cnt = 7 and LCR(1 downto 0) = "01") or
(RX_Bit_Cnt = 6 and LCR(1 downto 0) = "00") then -- Stop bit/Parity
RX_Bit_Cnt <= 0;
if LCR(3) = '1' then -- PEN
RX_Bit_Cnt <= 10;
if LCR(5) = '1' then -- Stick parity
if RX_Filtered = LCR(4) then
LSR(2) <= '1';
end if;
else
if RX_Filtered /= RX_Parity then
LSR(2) <= '1';
end if;
end if;
else
LSR(0) <= '1'; -- UART Receive complete
LSR(3) <= not RX_Filtered; -- Framing error
end if;
RBR <= RX_ShiftReg(7 downto 0);
LSR(1) <= LSR(0);
if A = "101" and Rd_n = '0' and CS_n = '0' then
LSR(1) <= '0';
end if;
else
RX_ShiftReg(6 downto 0) <= RX_ShiftReg(7 downto 1);
RX_ShiftReg(7) <= RX_Filtered;
if LCR(1 downto 0) = "10" then
RX_ShiftReg(7) <= '0';
RX_ShiftReg(6) <= RX_Filtered;
end if;
if LCR(1 downto 0) = "01" then
RX_ShiftReg(7) <= '0';
RX_ShiftReg(6) <= '0';
RX_ShiftReg(5) <= RX_Filtered;
end if;
if LCR(1 downto 0) = "00" then
RX_ShiftReg(7) <= '0';
RX_ShiftReg(6) <= '0';
RX_ShiftReg(5) <= '0';
RX_ShiftReg(4) <= RX_Filtered;
end if;
RX_Parity <= RX_Filtered xor RX_Parity;
end if;
end if;
end if;
end if;
end process;
 
-- Transmit bit tick
process (MR_n, XIn)
variable TX_Cnt : unsigned(4 downto 0);
begin
if MR_n = '0' then
TX_Cnt := "00000";
TX_Tick <= '0';
elsif XIn'event and XIn = '1' then
TX_Tick <= '0';
if RClk = '1' then
TX_Cnt := TX_Cnt + 1;
if LCR(2) = '1' and TX_Stop_Bit = '1' then
if LCR(1 downto 0) = "00" then
if TX_Cnt = "10111" then
TX_Tick <= '1';
TX_Cnt(3 downto 0) := "0000";
end if;
else
if TX_Cnt = "11111" then
TX_Tick <= '1';
TX_Cnt(3 downto 0) := "0000";
end if;
end if;
else
TX_Cnt(4) := '1';
if TX_Cnt(3 downto 0) = "1111" then
TX_Tick <= '1';
end if;
end if;
end if;
end if;
end process;
 
-- Transmit state machine
process (MR_n, XIn)
begin
if MR_n = '0' then
LSR(7 downto 5) <= "011";
TX_Bit_Cnt <= 0;
TX_ShiftReg <= (others => '0');
TXD <= '1';
TX_Parity <= '0';
TX_Next_Is_Stop <= '0';
TX_Stop_Bit <= '0';
elsif XIn'event and XIn = '1' then
if TX_Tick = '1' then
TX_Next_Is_Stop <= '0';
TX_Stop_Bit <= TX_Next_Is_Stop;
case TX_Bit_Cnt is
when 0 =>
if LSR(5) <= '0' then -- THRE
TX_Bit_Cnt <= 1;
end if;
TXD <= '1';
when 1 => -- Start bit
TX_ShiftReg(7 downto 0) <= THR;
LSR(5) <= '1'; -- THRE
TXD <= '0';
TX_Parity <= not LCR(4); -- EPS
TX_Bit_Cnt <= TX_Bit_Cnt + 1;
when 10 => -- Parity bit
TXD <= TX_Parity;
if LCR(5) = '1' then -- Stick parity
TXD <= not LCR(4);
end if;
TX_Bit_Cnt <= 0;
TX_Next_Is_Stop <= '1';
when others =>
TX_Bit_Cnt <= TX_Bit_Cnt + 1;
if (TX_Bit_Cnt = 9 and LCR(1 downto 0) = "11") or
(TX_Bit_Cnt = 8 and LCR(1 downto 0) = "10") or
(TX_Bit_Cnt = 7 and LCR(1 downto 0) = "01") or
(TX_Bit_Cnt = 6 and LCR(1 downto 0) = "00") then
TX_Bit_Cnt <= 0;
if LCR(3) = '1' then -- PEN
TX_Bit_Cnt <= 10;
else
TX_Next_Is_Stop <= '1';
end if;
LSR(6) <= '1'; -- TEMT
end if;
TXD <= TX_ShiftReg(0);
TX_ShiftReg(6 downto 0) <= TX_ShiftReg(7 downto 1);
TX_Parity <= TX_ShiftReg(0) xor TX_Parity;
end case;
end if;
if Wr_n = '0' and CS_n = '0' and A = "000" and LCR(7) = '0' then
LSR(5) <= '0'; -- THRE
LSR(6) <= '0'; -- TEMT
end if;
end if;
end process;
 
end;
/T80.vhd
0,0 → 1,1073
--
-- 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;
 
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,
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);
 
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 and Auto_Wait_t1 = '0' 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' and Auto_Wait_t1 = '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;
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' and Auto_Wait_t1 = '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;
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
if T_Res = '1' then
Auto_Wait_t1 <= '0';
else
Auto_Wait_t1 <= Auto_Wait or IORQ_i;
end if;
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' and Auto_Wait_t2 = '0') nor
(IOWait = 1 and IORQ_i = '1' and Auto_Wait_t1 = '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;
/T80a.vhd
0,0 → 1,253
--
-- Z80 compatible microprocessor core, asynchronous top level
--
-- 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
--
-- 0211 : Fixed interrupt cycle
--
-- 0235 : Updated for T80 interface change
--
-- 0238 : Updated for T80 interface change
--
-- 0240 : Updated for T80 interface change
--
-- 0242 : Updated for T80 interface change
--
-- 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 T80a is
generic(
Mode : integer := 0 -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB
);
port(
RESET_n : in std_logic;
CLK_n : 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;
MREQ_n : out std_logic;
IORQ_n : out std_logic;
RD_n : out std_logic;
WR_n : 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);
D : inout std_logic_vector(7 downto 0)
);
end T80a;
 
architecture rtl of T80a is
 
signal CEN : std_logic;
signal Reset_s : std_logic;
signal IntCycle_n : std_logic;
signal IORQ : std_logic;
signal NoRead : std_logic;
signal Write : std_logic;
signal MREQ : std_logic;
signal MReq_Inhibit : std_logic;
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 RFSH_n_i : std_logic;
signal BUSAK_n_i : std_logic;
signal A_i : std_logic_vector(15 downto 0);
signal DO : std_logic_vector(7 downto 0);
signal DI_Reg : std_logic_vector (7 downto 0); -- Input synchroniser
signal Wait_s : std_logic;
signal MCycle : std_logic_vector(2 downto 0);
signal TState : std_logic_vector(2 downto 0);
 
begin
 
CEN <= '1';
 
BUSAK_n <= BUSAK_n_i;
MREQ_n_i <= not MREQ or (Req_Inhibit and MReq_Inhibit);
RD_n_i <= not RD or Req_Inhibit;
 
MREQ_n <= MREQ_n_i when BUSAK_n_i = '1' else 'Z';
IORQ_n <= IORQ_n_i when BUSAK_n_i = '1' else 'Z';
RD_n <= RD_n_i when BUSAK_n_i = '1' else 'Z';
WR_n <= WR_n_i when BUSAK_n_i = '1' else 'Z';
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');
 
process (RESET_n, CLK_n)
begin
if RESET_n = '0' then
Reset_s <= '0';
elsif CLK_n'event and CLK_n = '1' then
Reset_s <= '1';
end if;
end process;
 
u0 : T80
generic map(
Mode => Mode,
IOWait => 1)
port map(
CEN => CEN,
M1_n => M1_n,
IORQ => IORQ,
NoRead => NoRead,
Write => Write,
RFSH_n => RFSH_n_i,
HALT_n => HALT_n,
WAIT_n => Wait_s,
INT_n => INT_n,
NMI_n => NMI_n,
RESET_n => Reset_s,
BUSRQ_n => BUSRQ_n,
BUSAK_n => BUSAK_n_i,
CLK_n => CLK_n,
A => A_i,
DInst => D,
DI => DI_Reg,
DO => DO,
MC => MCycle,
TS => TState,
IntCycle_n => IntCycle_n);
 
process (CLK_n)
begin
if CLK_n'event and CLK_n = '0' then
Wait_s <= WAIT_n;
if TState = "011" and BUSAK_n_i = '1' then
DI_Reg <= to_x01(D);
end if;
end if;
end process;
 
process (Reset_s,CLK_n)
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;
end if;
end if;
end process;
 
process (Reset_s,CLK_n)
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
Req_Inhibit <= '1';
else
Req_Inhibit <= '0';
end if;
end if;
end process;
 
process (Reset_s,CLK_n)
begin
if Reset_s = '0' then
MReq_Inhibit <= '0';
elsif CLK_n'event and CLK_n = '0' then
if MCycle = "001" and TState = "010" then
MReq_Inhibit <= '1';
else
MReq_Inhibit <= '0';
end if;
end if;
end process;
 
process(Reset_s,CLK_n)
begin
if Reset_s = '0' then
RD <= '0';
IORQ_n_i <= '1';
MREQ <= '0';
elsif CLK_n'event and CLK_n = '0' then
 
if MCycle = "001" then
if TState = "001" then
RD <= IntCycle_n;
MREQ <= IntCycle_n;
IORQ_n_i <= IntCycle_n;
end if;
if TState = "011" then
RD <= '0';
IORQ_n_i <= '1';
MREQ <= '1';
end if;
if TState = "100" then
MREQ <= '0';
end if;
else
if TState = "001" and NoRead = '0' then
RD <= not Write;
IORQ_n_i <= not IORQ;
MREQ <= not IORQ;
end if;
if TState = "011" then
RD <= '0';
IORQ_n_i <= '1';
MREQ <= '0';
end if;
end if;
end if;
end process;
 
end;
/T80_ALU.vhd
0,0 → 1,351
--
-- 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 :
--
-- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test
--
-- 0238 : Fixed zero flag for 16 bit SBC and ADC
--
-- 0240 : Added GB operations
--
-- 0242 : Cleanup
--
-- 0247 : Cleanup
--
 
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
 
entity T80_ALU is
generic(
Mode : integer := 0;
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(
Arith16 : in std_logic;
Z16 : in std_logic;
ALU_Op : in std_logic_vector(3 downto 0);
IR : in std_logic_vector(5 downto 0);
ISet : in std_logic_vector(1 downto 0);
BusA : in std_logic_vector(7 downto 0);
BusB : in std_logic_vector(7 downto 0);
F_In : in std_logic_vector(7 downto 0);
Q : out std_logic_vector(7 downto 0);
F_Out : out std_logic_vector(7 downto 0)
);
end T80_ALU;
 
architecture rtl of T80_ALU is
 
procedure AddSub(A : std_logic_vector;
B : std_logic_vector;
Sub : std_logic;
Carry_In : std_logic;
signal Res : out std_logic_vector;
signal Carry : out std_logic) is
variable B_i : unsigned(A'length - 1 downto 0);
variable Res_i : unsigned(A'length + 1 downto 0);
begin
if Sub = '1' then
B_i := not unsigned(B);
else
B_i := unsigned(B);
end if;
Res_i := unsigned("0" & A & Carry_In) + unsigned("0" & B_i & "1");
Carry <= Res_i(A'length + 1);
Res <= std_logic_vector(Res_i(A'length downto 1));
end;
 
-- AddSub variables (temporary signals)
signal UseCarry : std_logic;
signal Carry7_v : std_logic;
signal Overflow_v : std_logic;
signal HalfCarry_v : std_logic;
signal Carry_v : std_logic;
signal Q_v : std_logic_vector(7 downto 0);
 
signal BitMask : std_logic_vector(7 downto 0);
 
begin
 
with IR(5 downto 3) select BitMask <= "00000001" when "000",
"00000010" when "001",
"00000100" when "010",
"00001000" when "011",
"00010000" when "100",
"00100000" when "101",
"01000000" when "110",
"10000000" when others;
 
UseCarry <= not ALU_Op(2) and ALU_Op(0);
AddSub(BusA(3 downto 0), BusB(3 downto 0), ALU_Op(1), ALU_Op(1) xor (UseCarry and F_In(Flag_C)), Q_v(3 downto 0), HalfCarry_v);
AddSub(BusA(6 downto 4), BusB(6 downto 4), ALU_Op(1), HalfCarry_v, Q_v(6 downto 4), Carry7_v);
AddSub(BusA(7 downto 7), BusB(7 downto 7), ALU_Op(1), Carry7_v, Q_v(7 downto 7), Carry_v);
OverFlow_v <= Carry_v xor Carry7_v;
 
process (Arith16, ALU_OP, F_In, BusA, BusB, IR, Q_v, Carry_v, HalfCarry_v, OverFlow_v, BitMask, ISet, Z16)
variable Q_t : std_logic_vector(7 downto 0);
variable DAA_Q : unsigned(8 downto 0);
begin
Q_t := "--------";
F_Out <= F_In;
DAA_Q := "---------";
case ALU_Op is
when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" | "0110" | "0111" =>
F_Out(Flag_N) <= '0';
F_Out(Flag_C) <= '0';
case ALU_OP(2 downto 0) is
when "000" | "001" => -- ADD, ADC
Q_t := Q_v;
F_Out(Flag_C) <= Carry_v;
F_Out(Flag_H) <= HalfCarry_v;
F_Out(Flag_P) <= OverFlow_v;
when "010" | "011" | "111" => -- SUB, SBC, CP
Q_t := Q_v;
F_Out(Flag_N) <= '1';
F_Out(Flag_C) <= not Carry_v;
F_Out(Flag_H) <= not HalfCarry_v;
F_Out(Flag_P) <= OverFlow_v;
when "100" => -- AND
Q_t(7 downto 0) := BusA and BusB;
F_Out(Flag_H) <= '1';
when "101" => -- XOR
Q_t(7 downto 0) := BusA xor BusB;
F_Out(Flag_H) <= '0';
when others => -- OR "110"
Q_t(7 downto 0) := BusA or BusB;
F_Out(Flag_H) <= '0';
end case;
if ALU_Op(2 downto 0) = "111" then -- CP
F_Out(Flag_X) <= BusB(3);
F_Out(Flag_Y) <= BusB(5);
else
F_Out(Flag_X) <= Q_t(3);
F_Out(Flag_Y) <= Q_t(5);
end if;
if Q_t(7 downto 0) = "00000000" then
F_Out(Flag_Z) <= '1';
if Z16 = '1' then
F_Out(Flag_Z) <= F_In(Flag_Z); -- 16 bit ADC,SBC
end if;
else
F_Out(Flag_Z) <= '0';
end if;
F_Out(Flag_S) <= Q_t(7);
case ALU_Op(2 downto 0) is
when "000" | "001" | "010" | "011" | "111" => -- ADD, ADC, SUB, SBC, CP
when others =>
F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor
Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7));
end case;
if Arith16 = '1' then
F_Out(Flag_S) <= F_In(Flag_S);
F_Out(Flag_Z) <= F_In(Flag_Z);
F_Out(Flag_P) <= F_In(Flag_P);
end if;
when "1100" =>
-- DAA
F_Out(Flag_H) <= F_In(Flag_H);
F_Out(Flag_C) <= F_In(Flag_C);
DAA_Q(7 downto 0) := unsigned(BusA);
DAA_Q(8) := '0';
if F_In(Flag_N) = '0' then
-- After addition
-- Alow > 9 or H = 1
if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then
if (DAA_Q(3 downto 0) > 9) then
F_Out(Flag_H) <= '1';
else
F_Out(Flag_H) <= '0';
end if;
DAA_Q := DAA_Q + 6;
end if;
-- new Ahigh > 9 or C = 1
if DAA_Q(8 downto 4) > 9 or F_In(Flag_C) = '1' then
DAA_Q := DAA_Q + 96; -- 0x60
end if;
else
-- After subtraction
if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then
if DAA_Q(3 downto 0) > 5 then
F_Out(Flag_H) <= '0';
end if;
DAA_Q(7 downto 0) := DAA_Q(7 downto 0) - 6;
end if;
if unsigned(BusA) > 153 or F_In(Flag_C) = '1' then
DAA_Q := DAA_Q - 352; -- 0x160
end if;
end if;
F_Out(Flag_X) <= DAA_Q(3);
F_Out(Flag_Y) <= DAA_Q(5);
F_Out(Flag_C) <= F_In(Flag_C) or DAA_Q(8);
Q_t := std_logic_vector(DAA_Q(7 downto 0));
if DAA_Q(7 downto 0) = "00000000" then
F_Out(Flag_Z) <= '1';
else
F_Out(Flag_Z) <= '0';
end if;
F_Out(Flag_S) <= DAA_Q(7);
F_Out(Flag_P) <= not (DAA_Q(0) xor DAA_Q(1) xor DAA_Q(2) xor DAA_Q(3) xor
DAA_Q(4) xor DAA_Q(5) xor DAA_Q(6) xor DAA_Q(7));
when "1101" | "1110" =>
-- RLD, RRD
Q_t(7 downto 4) := BusA(7 downto 4);
if ALU_Op(0) = '1' then
Q_t(3 downto 0) := BusB(7 downto 4);
else
Q_t(3 downto 0) := BusB(3 downto 0);
end if;
F_Out(Flag_H) <= '0';
F_Out(Flag_N) <= '0';
F_Out(Flag_X) <= Q_t(3);
F_Out(Flag_Y) <= Q_t(5);
if Q_t(7 downto 0) = "00000000" then
F_Out(Flag_Z) <= '1';
else
F_Out(Flag_Z) <= '0';
end if;
F_Out(Flag_S) <= Q_t(7);
F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor
Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7));
when "1001" =>
-- BIT
Q_t(7 downto 0) := BusB and BitMask;
F_Out(Flag_S) <= Q_t(7);
if Q_t(7 downto 0) = "00000000" then
F_Out(Flag_Z) <= '1';
F_Out(Flag_P) <= '1';
else
F_Out(Flag_Z) <= '0';
F_Out(Flag_P) <= '0';
end if;
F_Out(Flag_H) <= '1';
F_Out(Flag_N) <= '0';
F_Out(Flag_X) <= '0';
F_Out(Flag_Y) <= '0';
if IR(2 downto 0) /= "110" then
F_Out(Flag_X) <= BusB(3);
F_Out(Flag_Y) <= BusB(5);
end if;
when "1010" =>
-- SET
Q_t(7 downto 0) := BusB or BitMask;
when "1011" =>
-- RES
Q_t(7 downto 0) := BusB and not BitMask;
when "1000" =>
-- ROT
case IR(5 downto 3) is
when "000" => -- RLC
Q_t(7 downto 1) := BusA(6 downto 0);
Q_t(0) := BusA(7);
F_Out(Flag_C) <= BusA(7);
when "010" => -- RL
Q_t(7 downto 1) := BusA(6 downto 0);
Q_t(0) := F_In(Flag_C);
F_Out(Flag_C) <= BusA(7);
when "001" => -- RRC
Q_t(6 downto 0) := BusA(7 downto 1);
Q_t(7) := BusA(0);
F_Out(Flag_C) <= BusA(0);
when "011" => -- RR
Q_t(6 downto 0) := BusA(7 downto 1);
Q_t(7) := F_In(Flag_C);
F_Out(Flag_C) <= BusA(0);
when "100" => -- SLA
Q_t(7 downto 1) := BusA(6 downto 0);
Q_t(0) := '0';
F_Out(Flag_C) <= BusA(7);
when "110" => -- SLL (Undocumented) / SWAP
if Mode = 3 then
Q_t(7 downto 4) := BusA(3 downto 0);
Q_t(3 downto 0) := BusA(7 downto 4);
F_Out(Flag_C) <= '0';
else
Q_t(7 downto 1) := BusA(6 downto 0);
Q_t(0) := '1';
F_Out(Flag_C) <= BusA(7);
end if;
when "101" => -- SRA
Q_t(6 downto 0) := BusA(7 downto 1);
Q_t(7) := BusA(7);
F_Out(Flag_C) <= BusA(0);
when others => -- SRL
Q_t(6 downto 0) := BusA(7 downto 1);
Q_t(7) := '0';
F_Out(Flag_C) <= BusA(0);
end case;
F_Out(Flag_H) <= '0';
F_Out(Flag_N) <= '0';
F_Out(Flag_X) <= Q_t(3);
F_Out(Flag_Y) <= Q_t(5);
F_Out(Flag_S) <= Q_t(7);
if Q_t(7 downto 0) = "00000000" then
F_Out(Flag_Z) <= '1';
else
F_Out(Flag_Z) <= '0';
end if;
F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor
Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7));
if ISet = "00" then
F_Out(Flag_P) <= F_In(Flag_P);
F_Out(Flag_S) <= F_In(Flag_S);
F_Out(Flag_Z) <= F_In(Flag_Z);
end if;
when others =>
null;
end case;
Q <= Q_t;
end process;
 
end;
/T80_Reg.vhd
0,0 → 1,105
--
-- T80 Registers, technology independent
--
-- Version : 0244
--
-- Copyright (c) 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/t51/
--
-- Limitations :
--
-- File history :
--
-- 0242 : Initial release
--
-- 0244 : Changed to single register file
--
 
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
 
entity T80_Reg is
port(
Clk : in std_logic;
CEN : in std_logic;
WEH : in std_logic;
WEL : in std_logic;
AddrA : in std_logic_vector(2 downto 0);
AddrB : in std_logic_vector(2 downto 0);
AddrC : in std_logic_vector(2 downto 0);
DIH : in std_logic_vector(7 downto 0);
DIL : in std_logic_vector(7 downto 0);
DOAH : out std_logic_vector(7 downto 0);
DOAL : out std_logic_vector(7 downto 0);
DOBH : out std_logic_vector(7 downto 0);
DOBL : out std_logic_vector(7 downto 0);
DOCH : out std_logic_vector(7 downto 0);
DOCL : out std_logic_vector(7 downto 0)
);
end T80_Reg;
 
architecture rtl of T80_Reg is
 
type Register_Image is array (natural range <>) of std_logic_vector(7 downto 0);
signal RegsH : Register_Image(0 to 7);
signal RegsL : Register_Image(0 to 7);
 
begin
 
process (Clk)
begin
if Clk'event and Clk = '1' then
if CEN = '1' then
if WEH = '1' then
RegsH(to_integer(unsigned(AddrA))) <= DIH;
end if;
if WEL = '1' then
RegsL(to_integer(unsigned(AddrA))) <= DIL;
end if;
end if;
end if;
end process;
 
DOAH <= RegsH(to_integer(unsigned(AddrA)));
DOAL <= RegsL(to_integer(unsigned(AddrA)));
DOBH <= RegsH(to_integer(unsigned(AddrB)));
DOBL <= RegsL(to_integer(unsigned(AddrB)));
DOCH <= RegsH(to_integer(unsigned(AddrC)));
DOCL <= RegsL(to_integer(unsigned(AddrC)));
 
end;
/T80_RegX.vhd
0,0 → 1,167
--
-- T80 Registers for Xilinx Select RAM
--
-- Version : 0244
--
-- Copyright (c) 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/t51/
--
-- Limitations :
--
-- File history :
--
-- 0242 : Initial release
--
-- 0244 : Removed UNISIM library and added componet declaration
--
 
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
 
entity T80_Reg is
port(
Clk : in std_logic;
CEN : in std_logic;
WEH : in std_logic;
WEL : in std_logic;
AddrA : in std_logic_vector(2 downto 0);
AddrB : in std_logic_vector(2 downto 0);
AddrC : in std_logic_vector(2 downto 0);
DIH : in std_logic_vector(7 downto 0);
DIL : in std_logic_vector(7 downto 0);
DOAH : out std_logic_vector(7 downto 0);
DOAL : out std_logic_vector(7 downto 0);
DOBH : out std_logic_vector(7 downto 0);
DOBL : out std_logic_vector(7 downto 0);
DOCH : out std_logic_vector(7 downto 0);
DOCL : out std_logic_vector(7 downto 0)
);
end T80_Reg;
 
architecture rtl of T80_Reg is
 
component RAM16X1D
port(
DPO : out std_ulogic;
SPO : out std_ulogic;
A0 : in std_ulogic;
A1 : in std_ulogic;
A2 : in std_ulogic;
A3 : in std_ulogic;
D : in std_ulogic;
DPRA0 : in std_ulogic;
DPRA1 : in std_ulogic;
DPRA2 : in std_ulogic;
DPRA3 : in std_ulogic;
WCLK : in std_ulogic;
WE : in std_ulogic);
end component;
 
signal ENH : std_logic;
signal ENL : std_logic;
 
begin
 
ENH <= CEN and WEH;
ENL <= CEN and WEL;
 
bG1: for I in 0 to 7 generate
begin
Reg1H : RAM16X1D
port map(
DPO => DOBH(i),
SPO => DOAH(i),
A0 => AddrA(0),
A1 => AddrA(1),
A2 => AddrA(2),
A3 => '0',
D => DIH(i),
DPRA0 => AddrB(0),
DPRA1 => AddrB(1),
DPRA2 => AddrB(2),
DPRA3 => '0',
WCLK => Clk,
WE => ENH);
Reg1L : RAM16X1D
port map(
DPO => DOBL(i),
SPO => DOAL(i),
A0 => AddrA(0),
A1 => AddrA(1),
A2 => AddrA(2),
A3 => '0',
D => DIL(i),
DPRA0 => AddrB(0),
DPRA1 => AddrB(1),
DPRA2 => AddrB(2),
DPRA3 => '0',
WCLK => Clk,
WE => ENL);
Reg2H : RAM16X1D
port map(
DPO => DOCH(i),
SPO => open,
A0 => AddrA(0),
A1 => AddrA(1),
A2 => AddrA(2),
A3 => '0',
D => DIH(i),
DPRA0 => AddrC(0),
DPRA1 => AddrC(1),
DPRA2 => AddrC(2),
DPRA3 => '0',
WCLK => Clk,
WE => ENH);
Reg2L : RAM16X1D
port map(
DPO => DOCL(i),
SPO => open,
A0 => AddrA(0),
A1 => AddrA(1),
A2 => AddrA(2),
A3 => '0',
D => DIL(i),
DPRA0 => AddrC(0),
DPRA1 => AddrC(1),
DPRA2 => AddrC(2),
DPRA3 => '0',
WCLK => Clk,
WE => ENL);
end generate;
 
end;
/T80se.vhd
0,0 → 1,184
--
-- Z80 compatible microprocessor core, synchronous top level with clock enable
-- Different timing than the original z80
-- Inputs needs to be synchronous and outputs may glitch
--
-- Version : 0242
--
-- 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 :
--
-- 0235 : First release
--
-- 0236 : Added T2Write generic
--
-- 0237 : Fixed T2Write with wait state
--
-- 0238 : Updated for T80 interface change
--
-- 0240 : Updated for T80 interface change
--
-- 0242 : Updated for T80 interface change
--
 
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.T80_Pack.all;
 
entity T80se is
generic(
Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB
T2Write : integer := 0; -- 0 => WR_n active in T3, /=0 => WR_n active in T2
IOWait : integer := 1 -- 0 => Single cycle I/O, 1 => Std I/O cycle
);
port(
RESET_n : in std_logic;
CLK_n : in std_logic;
CLKEN : 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;
MREQ_n : out std_logic;
IORQ_n : out std_logic;
RD_n : out std_logic;
WR_n : 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);
DI : in std_logic_vector(7 downto 0);
DO : out std_logic_vector(7 downto 0)
);
end T80se;
 
architecture rtl of T80se is
 
signal IntCycle_n : std_logic;
signal NoRead : std_logic;
signal Write : std_logic;
signal IORQ : std_logic;
signal DI_Reg : std_logic_vector(7 downto 0);
signal MCycle : std_logic_vector(2 downto 0);
signal TState : std_logic_vector(2 downto 0);
 
begin
 
u0 : T80
generic map(
Mode => Mode,
IOWait => IOWait)
port map(
CEN => CLKEN,
M1_n => M1_n,
IORQ => IORQ,
NoRead => NoRead,
Write => Write,
RFSH_n => RFSH_n,
HALT_n => HALT_n,
WAIT_n => Wait_n,
INT_n => INT_n,
NMI_n => NMI_n,
RESET_n => RESET_n,
BUSRQ_n => BUSRQ_n,
BUSAK_n => BUSAK_n,
CLK_n => CLK_n,
A => A,
DInst => DI,
DI => DI_Reg,
DO => DO,
MC => MCycle,
TS => TState,
IntCycle_n => IntCycle_n);
 
process (RESET_n, CLK_n)
begin
if RESET_n = '0' then
RD_n <= '1';
WR_n <= '1';
IORQ_n <= '1';
MREQ_n <= '1';
DI_Reg <= "00000000";
elsif CLK_n'event and CLK_n = '1' then
if CLKEN = '1' then
RD_n <= '1';
WR_n <= '1';
IORQ_n <= '1';
MREQ_n <= '1';
if MCycle = "001" then
if TState = "001" or (TState = "010" and Wait_n = '0') then
RD_n <= not IntCycle_n;
MREQ_n <= not IntCycle_n;
IORQ_n <= IntCycle_n;
end if;
if TState = "011" then
MREQ_n <= '0';
end if;
else
if (TState = "001" or (TState = "010" and Wait_n = '0')) and NoRead = '0' and Write = '0' then
RD_n <= '0';
IORQ_n <= not IORQ;
MREQ_n <= IORQ;
end if;
if T2Write = 0 then
if TState = "010" and Write = '1' then
WR_n <= '0';
IORQ_n <= not IORQ;
MREQ_n <= IORQ;
end if;
else
if (TState = "001" or (TState = "010" and Wait_n = '0')) and Write = '1' then
WR_n <= '0';
IORQ_n <= not IORQ;
MREQ_n <= IORQ;
end if;
end if;
end if;
if TState = "010" and Wait_n = '1' then
DI_Reg <= DI;
end if;
end if;
end if;
end process;
 
end;
/DebugSystemXR.vhd
0,0 → 1,185
-- Z80, Monitor ROM, external SRAM interface and two 16450 UARTs
-- that can be synthesized and used with
-- the NoICE debugger that can be found at
-- http://www.noicedebugger.com/
 
library IEEE;
use IEEE.std_logic_1164.all;
 
entity DebugSystemXR is
port(
Reset_n : in std_logic;
Clk : in std_logic;
NMI_n : in std_logic;
OE_n : out std_logic;
WE_n : out std_logic;
RAMCS_n : out std_logic;
ROMCS_n : out std_logic;
PGM_n : out std_logic;
A : out std_logic_vector(16 downto 0);
D : inout std_logic_vector(7 downto 0);
RXD0 : in std_logic;
CTS0 : in std_logic;
DSR0 : in std_logic;
RI0 : in std_logic;
DCD0 : in std_logic;
RXD1 : in std_logic;
CTS1 : in std_logic;
DSR1 : in std_logic;
RI1 : in std_logic;
DCD1 : in std_logic;
TXD0 : out std_logic;
RTS0 : out std_logic;
DTR0 : out std_logic;
TXD1 : out std_logic;
RTS1 : out std_logic;
DTR1 : out std_logic
);
end entity DebugSystemXR;
 
architecture struct of DebugSystemXR is
 
signal M1_n : std_logic;
signal MREQ_n : std_logic;
signal IORQ_n : std_logic;
signal RD_n : std_logic;
signal WR_n : std_logic;
signal RFSH_n : std_logic;
signal HALT_n : std_logic;
signal WAIT_n : std_logic;
signal INT_n : std_logic;
signal RESET_s : std_logic;
signal BUSRQ_n : std_logic;
signal BUSAK_n : std_logic;
signal A_i : std_logic_vector(15 downto 0);
signal D_i : std_logic_vector(7 downto 0);
signal ROM_D : std_logic_vector(7 downto 0);
signal UART0_D : std_logic_vector(7 downto 0);
signal UART1_D : std_logic_vector(7 downto 0);
signal CPU_D : std_logic_vector(7 downto 0);
 
signal Mirror : std_logic;
 
signal IOWR_n : std_logic;
signal RAMCS_n_i : std_logic;
signal UART0CS_n : std_logic;
signal UART1CS_n : std_logic;
 
signal BaudOut0 : std_logic;
signal BaudOut1 : std_logic;
 
begin
 
Wait_n <= '1';
BusRq_n <= '1';
INT_n <= '1';
 
OE_n <= RD_n;
WE_n <= WR_n;
RAMCS_n <= RAMCS_n_i;
ROMCS_n <= '1';
PGM_n <= '1';
A(14 downto 0) <= A_i(14 downto 0);
A(16 downto 15) <= "00";
D <= D_i when WR_n = '0' else "ZZZZZZZZ";
 
process (Reset_n, Clk)
begin
if Reset_n = '0' then
Reset_s <= '0';
Mirror <= '0';
elsif Clk'event and Clk = '1' then
Reset_s <= '1';
if IORQ_n = '0' and A_i(7 downto 4) = "1111" then
Mirror <= D_i(0);
end if;
end if;
end process;
 
IOWR_n <= WR_n or IORQ_n;
RAMCS_n_i <= (not Mirror and not A_i(15)) or MREQ_n;
UART0CS_n <= '0' when IORQ_n = '0' and A_i(7 downto 3) = "00000" else '1';
UART1CS_n <= '0' when IORQ_n = '0' and A_i(7 downto 3) = "10000" else '1';
 
CPU_D <=
D when RAMCS_n_i = '0' else
UART0_D when UART0CS_n = '0' else
UART1_D when UART1CS_n = '0' else
ROM_D;
 
u0 : entity work.T80s
generic map(Mode => 1, T2Write => 1, IOWait => 0)
port map(
RESET_n => RESET_s,
CLK_n => Clk,
WAIT_n => WAIT_n,
INT_n => INT_n,
NMI_n => NMI_n,
BUSRQ_n => BUSRQ_n,
M1_n => M1_n,
MREQ_n => MREQ_n,
IORQ_n => IORQ_n,
RD_n => RD_n,
WR_n => WR_n,
RFSH_n => RFSH_n,
HALT_n => HALT_n,
BUSAK_n => BUSAK_n,
A => A_i,
DI => CPU_D,
DO => D_i);
 
u1 : entity work.MonZ80
port map(
Clk => Clk,
A => A_i(10 downto 0),
D => ROM_D);
 
u3 : entity work.T16450
port map(
MR_n => Reset_s,
XIn => Clk,
RClk => BaudOut0,
CS_n => UART0CS_n,
Rd_n => RD_n,
Wr_n => IOWR_n,
A => A_i(2 downto 0),
D_In => D_i,
D_Out => UART0_D,
SIn => RXD0,
CTS_n => CTS0,
DSR_n => DSR0,
RI_n => RI0,
DCD_n => DCD0,
SOut => TXD0,
RTS_n => RTS0,
DTR_n => DTR0,
OUT1_n => open,
OUT2_n => open,
BaudOut => BaudOut0,
Intr => open);
 
u4 : entity work.T16450
port map(
MR_n => Reset_s,
XIn => Clk,
RClk => BaudOut1,
CS_n => UART1CS_n,
Rd_n => RD_n,
Wr_n => IOWR_n,
A => A_i(2 downto 0),
D_In => D_i,
D_Out => UART1_D,
SIn => RXD1,
CTS_n => CTS1,
DSR_n => DSR1,
RI_n => RI1,
DCD_n => DCD1,
SOut => TXD1,
RTS_n => RTS1,
DTR_n => DTR1,
OUT1_n => open,
OUT2_n => open,
BaudOut => BaudOut1,
Intr => open);
 
end;
/T80_Pack.vhd
0,0 → 1,208
--
-- Z80 compatible microprocessor core
--
-- Version : 0242
--
-- 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 :
--
 
library IEEE;
use IEEE.std_logic_1164.all;
 
package T80_Pack is
 
component T80
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 component;
 
component T80_Reg
port(
Clk : in std_logic;
CEN : in std_logic;
WEH : in std_logic;
WEL : in std_logic;
AddrA : in std_logic_vector(2 downto 0);
AddrB : in std_logic_vector(2 downto 0);
AddrC : in std_logic_vector(2 downto 0);
DIH : in std_logic_vector(7 downto 0);
DIL : in std_logic_vector(7 downto 0);
DOAH : out std_logic_vector(7 downto 0);
DOAL : out std_logic_vector(7 downto 0);
DOBH : out std_logic_vector(7 downto 0);
DOBL : out std_logic_vector(7 downto 0);
DOCH : out std_logic_vector(7 downto 0);
DOCL : out std_logic_vector(7 downto 0)
);
end component;
 
component T80_MCode
generic(
Mode : integer := 0;
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(
IR : in std_logic_vector(7 downto 0);
ISet : in std_logic_vector(1 downto 0);
MCycle : in std_logic_vector(2 downto 0);
F : in std_logic_vector(7 downto 0);
NMICycle : in std_logic;
IntCycle : in std_logic;
MCycles : out std_logic_vector(2 downto 0);
TStates : out std_logic_vector(2 downto 0);
Prefix : out std_logic_vector(1 downto 0); -- None,BC,ED,DD/FD
Inc_PC : out std_logic;
Inc_WZ : out std_logic;
IncDec_16 : out std_logic_vector(3 downto 0); -- BC,DE,HL,SP 0 is inc
Read_To_Reg : out std_logic;
Read_To_Acc : out std_logic;
Set_BusA_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI/DB,A,SP(L),SP(M),0,F
Set_BusB_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI,A,SP(L),SP(M),1,F,PC(L),PC(M),0
ALU_Op : out std_logic_vector(3 downto 0);
-- ADD, ADC, SUB, SBC, AND, XOR, OR, CP, ROT, BIT, SET, RES, DAA, RLD, RRD, None
Save_ALU : out std_logic;
PreserveC : out std_logic;
Arith16 : out std_logic;
Set_Addr_To : out std_logic_vector(2 downto 0); -- aNone,aXY,aIOA,aSP,aBC,aDE,aZI
IORQ : out std_logic;
Jump : out std_logic;
JumpE : out std_logic;
JumpXY : out std_logic;
Call : out std_logic;
RstP : out std_logic;
LDZ : out std_logic;
LDW : out std_logic;
LDSPHL : out std_logic;
Special_LD : out std_logic_vector(2 downto 0); -- A,I;A,R;I,A;R,A;None
ExchangeDH : out std_logic;
ExchangeRp : out std_logic;
ExchangeAF : out std_logic;
ExchangeRS : out std_logic;
I_DJNZ : out std_logic;
I_CPL : out std_logic;
I_CCF : out std_logic;
I_SCF : out std_logic;
I_RETN : out std_logic;
I_BT : out std_logic;
I_BC : out std_logic;
I_BTR : out std_logic;
I_RLD : out std_logic;
I_RRD : out std_logic;
I_INRC : out std_logic;
SetDI : out std_logic;
SetEI : out std_logic;
IMode : out std_logic_vector(1 downto 0);
Halt : out std_logic;
NoRead : out std_logic;
Write : out std_logic
);
end component;
 
component T80_ALU
generic(
Mode : integer := 0;
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(
Arith16 : in std_logic;
Z16 : in std_logic;
ALU_Op : in std_logic_vector(3 downto 0);
IR : in std_logic_vector(5 downto 0);
ISet : in std_logic_vector(1 downto 0);
BusA : in std_logic_vector(7 downto 0);
BusB : in std_logic_vector(7 downto 0);
F_In : in std_logic_vector(7 downto 0);
Q : out std_logic_vector(7 downto 0);
F_Out : out std_logic_vector(7 downto 0)
);
end component;
 
end;
/T8080se.vhd
0,0 → 1,185
--
-- 8080 compatible microprocessor core, synchronous top level with clock enable
-- Different timing than the original 8080
-- Inputs needs to be synchronous and outputs may glitch
--
-- Version : 0242
--
-- Copyright (c) 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 :
-- STACK status output not supported
--
-- File history :
--
-- 0237 : First version
--
-- 0238 : Updated for T80 interface change
--
-- 0240 : Updated for T80 interface change
--
-- 0242 : Updated for T80 interface change
--
 
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.T80_Pack.all;
 
entity T8080se is
generic(
Mode : integer := 2; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB
T2Write : integer := 0 -- 0 => WR_n active in T3, /=0 => WR_n active in T2
);
port(
RESET_n : in std_logic;
CLK : in std_logic;
CLKEN : in std_logic;
READY : in std_logic;
HOLD : in std_logic;
INT : in std_logic;
INTE : out std_logic;
DBIN : out std_logic;
SYNC : out std_logic;
VAIT : out std_logic;
HLDA : out std_logic;
WR_n : out std_logic;
A : out std_logic_vector(15 downto 0);
DI : in std_logic_vector(7 downto 0);
DO : out std_logic_vector(7 downto 0)
);
end T8080se;
 
architecture rtl of T8080se is
 
signal IntCycle_n : std_logic;
signal NoRead : std_logic;
signal Write : std_logic;
signal IORQ : std_logic;
signal INT_n : std_logic;
signal HALT_n : std_logic;
signal BUSRQ_n : std_logic;
signal BUSAK_n : std_logic;
signal DO_i : std_logic_vector(7 downto 0);
signal DI_Reg : std_logic_vector(7 downto 0);
signal MCycle : std_logic_vector(2 downto 0);
signal TState : std_logic_vector(2 downto 0);
signal One : std_logic;
 
begin
 
INT_n <= not INT;
BUSRQ_n <= HOLD;
HLDA <= not BUSAK_n;
SYNC <= '1' when TState = "001" else '0';
VAIT <= '1' when TState = "010" else '0';
One <= '1';
 
DO(0) <= not IntCycle_n when TState = "001" else DO_i(0); -- INTA
DO(1) <= Write when TState = "001" else DO_i(1); -- WO_n
DO(2) <= DO_i(2); -- STACK not supported !!!!!!!!!!
DO(3) <= not HALT_n when TState = "001" else DO_i(3); -- HLTA
DO(4) <= IORQ and Write when TState = "001" else DO_i(4); -- OUT
DO(5) <= DO_i(5) when TState /= "001" else '1' when MCycle = "001" else '0'; -- M1
DO(6) <= IORQ and not Write when TState = "001" else DO_i(6); -- INP
DO(7) <= not IORQ and not Write and IntCycle_n when TState = "001" else DO_i(7); -- MEMR
 
u0 : T80
generic map(
Mode => Mode,
IOWait => 0)
port map(
CEN => CLKEN,
M1_n => open,
IORQ => IORQ,
NoRead => NoRead,
Write => Write,
RFSH_n => open,
HALT_n => HALT_n,
WAIT_n => READY,
INT_n => INT_n,
NMI_n => One,
RESET_n => RESET_n,
BUSRQ_n => One,
BUSAK_n => BUSAK_n,
CLK_n => CLK,
A => A,
DInst => DI,
DI => DI_Reg,
DO => DO_i,
MC => MCycle,
TS => TState,
IntCycle_n => IntCycle_n,
IntE => INTE);
 
process (RESET_n, CLK)
begin
if RESET_n = '0' then
DBIN <= '0';
WR_n <= '1';
DI_Reg <= "00000000";
elsif CLK'event and CLK = '1' then
if CLKEN = '1' then
DBIN <= '0';
WR_n <= '1';
if MCycle = "001" then
if TState = "001" or (TState = "010" and READY = '0') then
DBIN <= IntCycle_n;
end if;
else
if (TState = "001" or (TState = "010" and READY = '0')) and NoRead = '0' and Write = '0' then
DBIN <= '1';
end if;
if T2Write = 0 then
if TState = "010" and Write = '1' then
WR_n <= '0';
end if;
else
if (TState = "001" or (TState = "010" and READY = '0')) and Write = '1' then
WR_n <= '0';
end if;
end if;
end if;
if TState = "010" and READY = '1' then
DI_Reg <= DI;
end if;
end if;
end if;
end process;
 
end;
/T80_MCode.vhd
0,0 → 1,1934
--
-- Z80 compatible microprocessor core
--
-- Version : 0242
--
-- 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
--
-- 0211 : Fixed IM 1
--
-- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test
--
-- 0235 : Added IM 2 fix by Mike Johnson
--
-- 0238 : Added NoRead signal
--
-- 0238b: Fixed instruction timing for POP and DJNZ
--
-- 0240 : Added (IX/IY+d) states, removed op-codes from mode 2 and added all remaining mode 3 op-codes
--
-- 0242 : Fixed I/O instruction timing, cleanup
--
 
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
 
entity T80_MCode is
generic(
Mode : integer := 0;
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(
IR : in std_logic_vector(7 downto 0);
ISet : in std_logic_vector(1 downto 0);
MCycle : in std_logic_vector(2 downto 0);
F : in std_logic_vector(7 downto 0);
NMICycle : in std_logic;
IntCycle : in std_logic;
MCycles : out std_logic_vector(2 downto 0);
TStates : out std_logic_vector(2 downto 0);
Prefix : out std_logic_vector(1 downto 0); -- None,BC,ED,DD/FD
Inc_PC : out std_logic;
Inc_WZ : out std_logic;
IncDec_16 : out std_logic_vector(3 downto 0); -- BC,DE,HL,SP 0 is inc
Read_To_Reg : out std_logic;
Read_To_Acc : out std_logic;
Set_BusA_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI/DB,A,SP(L),SP(M),0,F
Set_BusB_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI,A,SP(L),SP(M),1,F,PC(L),PC(M),0
ALU_Op : out std_logic_vector(3 downto 0);
-- ADD, ADC, SUB, SBC, AND, XOR, OR, CP, ROT, BIT, SET, RES, DAA, RLD, RRD, None
Save_ALU : out std_logic;
PreserveC : out std_logic;
Arith16 : out std_logic;
Set_Addr_To : out std_logic_vector(2 downto 0); -- aNone,aXY,aIOA,aSP,aBC,aDE,aZI
IORQ : out std_logic;
Jump : out std_logic;
JumpE : out std_logic;
JumpXY : out std_logic;
Call : out std_logic;
RstP : out std_logic;
LDZ : out std_logic;
LDW : out std_logic;
LDSPHL : out std_logic;
Special_LD : out std_logic_vector(2 downto 0); -- A,I;A,R;I,A;R,A;None
ExchangeDH : out std_logic;
ExchangeRp : out std_logic;
ExchangeAF : out std_logic;
ExchangeRS : out std_logic;
I_DJNZ : out std_logic;
I_CPL : out std_logic;
I_CCF : out std_logic;
I_SCF : out std_logic;
I_RETN : out std_logic;
I_BT : out std_logic;
I_BC : out std_logic;
I_BTR : out std_logic;
I_RLD : out std_logic;
I_RRD : out std_logic;
I_INRC : out std_logic;
SetDI : out std_logic;
SetEI : out std_logic;
IMode : out std_logic_vector(1 downto 0);
Halt : out std_logic;
NoRead : out std_logic;
Write : out std_logic
);
end T80_MCode;
 
architecture rtl of T80_MCode 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";
-- constant aNone : std_logic_vector(2 downto 0) := "000";
-- constant aXY : std_logic_vector(2 downto 0) := "001";
-- constant aIOA : std_logic_vector(2 downto 0) := "010";
-- constant aSP : std_logic_vector(2 downto 0) := "011";
-- constant aBC : std_logic_vector(2 downto 0) := "100";
-- constant aDE : std_logic_vector(2 downto 0) := "101";
-- constant aZI : std_logic_vector(2 downto 0) := "110";
 
function is_cc_true(
F : std_logic_vector(7 downto 0);
cc : bit_vector(2 downto 0)
) return boolean is
begin
if Mode = 3 then
case cc is
when "000" => return F(7) = '0'; -- NZ
when "001" => return F(7) = '1'; -- Z
when "010" => return F(4) = '0'; -- NC
when "011" => return F(4) = '1'; -- C
when "100" => return false;
when "101" => return false;
when "110" => return false;
when "111" => return false;
end case;
else
case cc is
when "000" => return F(6) = '0'; -- NZ
when "001" => return F(6) = '1'; -- Z
when "010" => return F(0) = '0'; -- NC
when "011" => return F(0) = '1'; -- C
when "100" => return F(2) = '0'; -- PO
when "101" => return F(2) = '1'; -- PE
when "110" => return F(7) = '0'; -- P
when "111" => return F(7) = '1'; -- M
end case;
end if;
end;
 
begin
 
process (IR, ISet, MCycle, F, NMICycle, IntCycle)
variable DDD : std_logic_vector(2 downto 0);
variable SSS : std_logic_vector(2 downto 0);
variable DPair : std_logic_vector(1 downto 0);
variable IRB : bit_vector(7 downto 0);
begin
DDD := IR(5 downto 3);
SSS := IR(2 downto 0);
DPair := IR(5 downto 4);
IRB := to_bitvector(IR);
 
MCycles <= "001";
if MCycle = "001" then
TStates <= "100";
else
TStates <= "011";
end if;
Prefix <= "00";
Inc_PC <= '0';
Inc_WZ <= '0';
IncDec_16 <= "0000";
Read_To_Acc <= '0';
Read_To_Reg <= '0';
Set_BusB_To <= "0000";
Set_BusA_To <= "0000";
ALU_Op <= "0" & IR(5 downto 3);
Save_ALU <= '0';
PreserveC <= '0';
Arith16 <= '0';
IORQ <= '0';
Set_Addr_To <= aNone;
Jump <= '0';
JumpE <= '0';
JumpXY <= '0';
Call <= '0';
RstP <= '0';
LDZ <= '0';
LDW <= '0';
LDSPHL <= '0';
Special_LD <= "000";
ExchangeDH <= '0';
ExchangeRp <= '0';
ExchangeAF <= '0';
ExchangeRS <= '0';
I_DJNZ <= '0';
I_CPL <= '0';
I_CCF <= '0';
I_SCF <= '0';
I_RETN <= '0';
I_BT <= '0';
I_BC <= '0';
I_BTR <= '0';
I_RLD <= '0';
I_RRD <= '0';
I_INRC <= '0';
SetDI <= '0';
SetEI <= '0';
IMode <= "11";
Halt <= '0';
NoRead <= '0';
Write <= '0';
 
case ISet is
when "00" =>
 
------------------------------------------------------------------------------
--
-- Unprefixed instructions
--
------------------------------------------------------------------------------
 
case IRB is
-- 8 BIT LOAD GROUP
when "01000000"|"01000001"|"01000010"|"01000011"|"01000100"|"01000101"|"01000111"
|"01001000"|"01001001"|"01001010"|"01001011"|"01001100"|"01001101"|"01001111"
|"01010000"|"01010001"|"01010010"|"01010011"|"01010100"|"01010101"|"01010111"
|"01011000"|"01011001"|"01011010"|"01011011"|"01011100"|"01011101"|"01011111"
|"01100000"|"01100001"|"01100010"|"01100011"|"01100100"|"01100101"|"01100111"
|"01101000"|"01101001"|"01101010"|"01101011"|"01101100"|"01101101"|"01101111"
|"01111000"|"01111001"|"01111010"|"01111011"|"01111100"|"01111101"|"01111111" =>
-- LD r,r'
Set_BusB_To(2 downto 0) <= SSS;
ExchangeRp <= '1';
Set_BusA_To(2 downto 0) <= DDD;
Read_To_Reg <= '1';
when "00000110"|"00001110"|"00010110"|"00011110"|"00100110"|"00101110"|"00111110" =>
-- LD r,n
MCycles <= "010";
case to_integer(unsigned(MCycle)) is
when 2 =>
Inc_PC <= '1';
Set_BusA_To(2 downto 0) <= DDD;
Read_To_Reg <= '1';
when others => null;
end case;
when "01000110"|"01001110"|"01010110"|"01011110"|"01100110"|"01101110"|"01111110" =>
-- LD r,(HL)
MCycles <= "010";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aXY;
when 2 =>
Set_BusA_To(2 downto 0) <= DDD;
Read_To_Reg <= '1';
when others => null;
end case;
when "01110000"|"01110001"|"01110010"|"01110011"|"01110100"|"01110101"|"01110111" =>
-- LD (HL),r
MCycles <= "010";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aXY;
Set_BusB_To(2 downto 0) <= SSS;
Set_BusB_To(3) <= '0';
when 2 =>
Write <= '1';
when others => null;
end case;
when "00110110" =>
-- LD (HL),n
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 2 =>
Inc_PC <= '1';
Set_Addr_To <= aXY;
Set_BusB_To(2 downto 0) <= SSS;
Set_BusB_To(3) <= '0';
when 3 =>
Write <= '1';
when others => null;
end case;
when "00001010" =>
-- LD A,(BC)
MCycles <= "010";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aBC;
when 2 =>
Read_To_Acc <= '1';
when others => null;
end case;
when "00011010" =>
-- LD A,(DE)
MCycles <= "010";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aDE;
when 2 =>
Read_To_Acc <= '1';
when others => null;
end case;
when "00111010" =>
if Mode = 3 then
-- LDD A,(HL)
MCycles <= "010";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aXY;
when 2 =>
Read_To_Acc <= '1';
IncDec_16 <= "1110";
when others => null;
end case;
else
-- LD A,(nn)
MCycles <= "100";
case to_integer(unsigned(MCycle)) is
when 2 =>
Inc_PC <= '1';
LDZ <= '1';
when 3 =>
Set_Addr_To <= aZI;
Inc_PC <= '1';
when 4 =>
Read_To_Acc <= '1';
when others => null;
end case;
end if;
when "00000010" =>
-- LD (BC),A
MCycles <= "010";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aBC;
Set_BusB_To <= "0111";
when 2 =>
Write <= '1';
when others => null;
end case;
when "00010010" =>
-- LD (DE),A
MCycles <= "010";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aDE;
Set_BusB_To <= "0111";
when 2 =>
Write <= '1';
when others => null;
end case;
when "00110010" =>
if Mode = 3 then
-- LDD (HL),A
MCycles <= "010";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aXY;
Set_BusB_To <= "0111";
when 2 =>
Write <= '1';
IncDec_16 <= "1110";
when others => null;
end case;
else
-- LD (nn),A
MCycles <= "100";
case to_integer(unsigned(MCycle)) is
when 2 =>
Inc_PC <= '1';
LDZ <= '1';
when 3 =>
Set_Addr_To <= aZI;
Inc_PC <= '1';
Set_BusB_To <= "0111";
when 4 =>
Write <= '1';
when others => null;
end case;
end if;
 
-- 16 BIT LOAD GROUP
when "00000001"|"00010001"|"00100001"|"00110001" =>
-- LD dd,nn
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 2 =>
Inc_PC <= '1';
Read_To_Reg <= '1';
if DPAIR = "11" then
Set_BusA_To(3 downto 0) <= "1000";
else
Set_BusA_To(2 downto 1) <= DPAIR;
Set_BusA_To(0) <= '1';
end if;
when 3 =>
Inc_PC <= '1';
Read_To_Reg <= '1';
if DPAIR = "11" then
Set_BusA_To(3 downto 0) <= "1001";
else
Set_BusA_To(2 downto 1) <= DPAIR;
Set_BusA_To(0) <= '0';
end if;
when others => null;
end case;
when "00101010" =>
if Mode = 3 then
-- LDI A,(HL)
MCycles <= "010";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aXY;
when 2 =>
Read_To_Acc <= '1';
IncDec_16 <= "0110";
when others => null;
end case;
else
-- LD HL,(nn)
MCycles <= "101";
case to_integer(unsigned(MCycle)) is
when 2 =>
Inc_PC <= '1';
LDZ <= '1';
when 3 =>
Set_Addr_To <= aZI;
Inc_PC <= '1';
LDW <= '1';
when 4 =>
Set_BusA_To(2 downto 0) <= "101"; -- L
Read_To_Reg <= '1';
Inc_WZ <= '1';
Set_Addr_To <= aZI;
when 5 =>
Set_BusA_To(2 downto 0) <= "100"; -- H
Read_To_Reg <= '1';
when others => null;
end case;
end if;
when "00100010" =>
if Mode = 3 then
-- LDI (HL),A
MCycles <= "010";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aXY;
Set_BusB_To <= "0111";
when 2 =>
Write <= '1';
IncDec_16 <= "0110";
when others => null;
end case;
else
-- LD (nn),HL
MCycles <= "101";
case to_integer(unsigned(MCycle)) is
when 2 =>
Inc_PC <= '1';
LDZ <= '1';
when 3 =>
Set_Addr_To <= aZI;
Inc_PC <= '1';
LDW <= '1';
Set_BusB_To <= "0101"; -- L
when 4 =>
Inc_WZ <= '1';
Set_Addr_To <= aZI;
Write <= '1';
Set_BusB_To <= "0100"; -- H
when 5 =>
Write <= '1';
when others => null;
end case;
end if;
when "11111001" =>
-- LD SP,HL
TStates <= "110";
LDSPHL <= '1';
when "11000101"|"11010101"|"11100101"|"11110101" =>
-- PUSH qq
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 1 =>
TStates <= "101";
IncDec_16 <= "1111";
Set_Addr_TO <= aSP;
if DPAIR = "11" then
Set_BusB_To <= "0111";
else
Set_BusB_To(2 downto 1) <= DPAIR;
Set_BusB_To(0) <= '0';
Set_BusB_To(3) <= '0';
end if;
when 2 =>
IncDec_16 <= "1111";
Set_Addr_To <= aSP;
if DPAIR = "11" then
Set_BusB_To <= "1011";
else
Set_BusB_To(2 downto 1) <= DPAIR;
Set_BusB_To(0) <= '1';
Set_BusB_To(3) <= '0';
end if;
Write <= '1';
when 3 =>
Write <= '1';
when others => null;
end case;
when "11000001"|"11010001"|"11100001"|"11110001" =>
-- POP qq
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aSP;
when 2 =>
IncDec_16 <= "0111";
Set_Addr_To <= aSP;
Read_To_Reg <= '1';
if DPAIR = "11" then
Set_BusA_To(3 downto 0) <= "1011";
else
Set_BusA_To(2 downto 1) <= DPAIR;
Set_BusA_To(0) <= '1';
end if;
when 3 =>
IncDec_16 <= "0111";
Read_To_Reg <= '1';
if DPAIR = "11" then
Set_BusA_To(3 downto 0) <= "0111";
else
Set_BusA_To(2 downto 1) <= DPAIR;
Set_BusA_To(0) <= '0';
end if;
when others => null;
end case;
 
-- EXCHANGE, BLOCK TRANSFER AND SEARCH GROUP
when "11101011" =>
if Mode /= 3 then
-- EX DE,HL
ExchangeDH <= '1';
end if;
when "00001000" =>
if Mode = 3 then
-- LD (nn),SP
MCycles <= "101";
case to_integer(unsigned(MCycle)) is
when 2 =>
Inc_PC <= '1';
LDZ <= '1';
when 3 =>
Set_Addr_To <= aZI;
Inc_PC <= '1';
LDW <= '1';
Set_BusB_To <= "1000";
when 4 =>
Inc_WZ <= '1';
Set_Addr_To <= aZI;
Write <= '1';
Set_BusB_To <= "1001";
when 5 =>
Write <= '1';
when others => null;
end case;
elsif Mode < 2 then
-- EX AF,AF'
ExchangeAF <= '1';
end if;
when "11011001" =>
if Mode = 3 then
-- RETI
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_TO <= aSP;
when 2 =>
IncDec_16 <= "0111";
Set_Addr_To <= aSP;
LDZ <= '1';
when 3 =>
Jump <= '1';
IncDec_16 <= "0111";
I_RETN <= '1';
SetEI <= '1';
when others => null;
end case;
elsif Mode < 2 then
-- EXX
ExchangeRS <= '1';
end if;
when "11100011" =>
if Mode /= 3 then
-- EX (SP),HL
MCycles <= "101";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aSP;
when 2 =>
Read_To_Reg <= '1';
Set_BusA_To <= "0101";
Set_BusB_To <= "0101";
Set_Addr_To <= aSP;
when 3 =>
IncDec_16 <= "0111";
Set_Addr_To <= aSP;
TStates <= "100";
Write <= '1';
when 4 =>
Read_To_Reg <= '1';
Set_BusA_To <= "0100";
Set_BusB_To <= "0100";
Set_Addr_To <= aSP;
when 5 =>
IncDec_16 <= "1111";
TStates <= "101";
Write <= '1';
when others => null;
end case;
end if;
 
-- 8 BIT ARITHMETIC AND LOGICAL GROUP
when "10000000"|"10000001"|"10000010"|"10000011"|"10000100"|"10000101"|"10000111"
|"10001000"|"10001001"|"10001010"|"10001011"|"10001100"|"10001101"|"10001111"
|"10010000"|"10010001"|"10010010"|"10010011"|"10010100"|"10010101"|"10010111"
|"10011000"|"10011001"|"10011010"|"10011011"|"10011100"|"10011101"|"10011111"
|"10100000"|"10100001"|"10100010"|"10100011"|"10100100"|"10100101"|"10100111"
|"10101000"|"10101001"|"10101010"|"10101011"|"10101100"|"10101101"|"10101111"
|"10110000"|"10110001"|"10110010"|"10110011"|"10110100"|"10110101"|"10110111"
|"10111000"|"10111001"|"10111010"|"10111011"|"10111100"|"10111101"|"10111111" =>
-- ADD A,r
-- ADC A,r
-- SUB A,r
-- SBC A,r
-- AND A,r
-- OR A,r
-- XOR A,r
-- CP A,r
Set_BusB_To(2 downto 0) <= SSS;
Set_BusA_To(2 downto 0) <= "111";
Read_To_Reg <= '1';
Save_ALU <= '1';
when "10000110"|"10001110"|"10010110"|"10011110"|"10100110"|"10101110"|"10110110"|"10111110" =>
-- ADD A,(HL)
-- ADC A,(HL)
-- SUB A,(HL)
-- SBC A,(HL)
-- AND A,(HL)
-- OR A,(HL)
-- XOR A,(HL)
-- CP A,(HL)
MCycles <= "010";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aXY;
when 2 =>
Read_To_Reg <= '1';
Save_ALU <= '1';
Set_BusB_To(2 downto 0) <= SSS;
Set_BusA_To(2 downto 0) <= "111";
when others => null;
end case;
when "11000110"|"11001110"|"11010110"|"11011110"|"11100110"|"11101110"|"11110110"|"11111110" =>
-- ADD A,n
-- ADC A,n
-- SUB A,n
-- SBC A,n
-- AND A,n
-- OR A,n
-- XOR A,n
-- CP A,n
MCycles <= "010";
if MCycle = "010" then
Inc_PC <= '1';
Read_To_Reg <= '1';
Save_ALU <= '1';
Set_BusB_To(2 downto 0) <= SSS;
Set_BusA_To(2 downto 0) <= "111";
end if;
when "00000100"|"00001100"|"00010100"|"00011100"|"00100100"|"00101100"|"00111100" =>
-- INC r
Set_BusB_To <= "1010";
Set_BusA_To(2 downto 0) <= DDD;
Read_To_Reg <= '1';
Save_ALU <= '1';
PreserveC <= '1';
ALU_Op <= "0000";
when "00110100" =>
-- INC (HL)
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aXY;
when 2 =>
TStates <= "100";
Set_Addr_To <= aXY;
Read_To_Reg <= '1';
Save_ALU <= '1';
PreserveC <= '1';
ALU_Op <= "0000";
Set_BusB_To <= "1010";
Set_BusA_To(2 downto 0) <= DDD;
when 3 =>
Write <= '1';
when others => null;
end case;
when "00000101"|"00001101"|"00010101"|"00011101"|"00100101"|"00101101"|"00111101" =>
-- DEC r
Set_BusB_To <= "1010";
Set_BusA_To(2 downto 0) <= DDD;
Read_To_Reg <= '1';
Save_ALU <= '1';
PreserveC <= '1';
ALU_Op <= "0010";
when "00110101" =>
-- DEC (HL)
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aXY;
when 2 =>
TStates <= "100";
Set_Addr_To <= aXY;
ALU_Op <= "0010";
Read_To_Reg <= '1';
Save_ALU <= '1';
PreserveC <= '1';
Set_BusB_To <= "1010";
Set_BusA_To(2 downto 0) <= DDD;
when 3 =>
Write <= '1';
when others => null;
end case;
 
-- GENERAL PURPOSE ARITHMETIC AND CPU CONTROL GROUPS
when "00100111" =>
-- DAA
Set_BusA_To(2 downto 0) <= "111";
Read_To_Reg <= '1';
ALU_Op <= "1100";
Save_ALU <= '1';
when "00101111" =>
-- CPL
I_CPL <= '1';
when "00111111" =>
-- CCF
I_CCF <= '1';
when "00110111" =>
-- SCF
I_SCF <= '1';
when "00000000" =>
if NMICycle = '1' then
-- NMI
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 1 =>
TStates <= "101";
IncDec_16 <= "1111";
Set_Addr_To <= aSP;
Set_BusB_To <= "1101";
when 2 =>
TStates <= "100";
Write <= '1';
IncDec_16 <= "1111";
Set_Addr_To <= aSP;
Set_BusB_To <= "1100";
when 3 =>
TStates <= "100";
Write <= '1';
when others => null;
end case;
elsif IntCycle = '1' then
-- INT (IM 2)
MCycles <= "101";
case to_integer(unsigned(MCycle)) is
when 1 =>
LDZ <= '1';
TStates <= "101";
IncDec_16 <= "1111";
Set_Addr_To <= aSP;
Set_BusB_To <= "1101";
when 2 =>
TStates <= "100";
Write <= '1';
IncDec_16 <= "1111";
Set_Addr_To <= aSP;
Set_BusB_To <= "1100";
when 3 =>
TStates <= "100";
Write <= '1';
when 4 =>
Inc_PC <= '1';
LDZ <= '1';
when 5 =>
Jump <= '1';
when others => null;
end case;
else
-- NOP
end if;
when "01110110" =>
-- HALT
Halt <= '1';
when "11110011" =>
-- DI
SetDI <= '1';
when "11111011" =>
-- EI
SetEI <= '1';
 
-- 16 BIT ARITHMETIC GROUP
when "00001001"|"00011001"|"00101001"|"00111001" =>
-- ADD HL,ss
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 2 =>
NoRead <= '1';
ALU_Op <= "0000";
Read_To_Reg <= '1';
Save_ALU <= '1';
Set_BusA_To(2 downto 0) <= "101";
case to_integer(unsigned(IR(5 downto 4))) is
when 0|1|2 =>
Set_BusB_To(2 downto 1) <= IR(5 downto 4);
Set_BusB_To(0) <= '1';
when others =>
Set_BusB_To <= "1000";
end case;
TStates <= "100";
Arith16 <= '1';
when 3 =>
NoRead <= '1';
Read_To_Reg <= '1';
Save_ALU <= '1';
ALU_Op <= "0001";
Set_BusA_To(2 downto 0) <= "100";
case to_integer(unsigned(IR(5 downto 4))) is
when 0|1|2 =>
Set_BusB_To(2 downto 1) <= IR(5 downto 4);
when others =>
Set_BusB_To <= "1001";
end case;
Arith16 <= '1';
when others =>
end case;
when "00000011"|"00010011"|"00100011"|"00110011" =>
-- INC ss
TStates <= "110";
IncDec_16(3 downto 2) <= "01";
IncDec_16(1 downto 0) <= DPair;
when "00001011"|"00011011"|"00101011"|"00111011" =>
-- DEC ss
TStates <= "110";
IncDec_16(3 downto 2) <= "11";
IncDec_16(1 downto 0) <= DPair;
 
-- ROTATE AND SHIFT GROUP
when "00000111"
-- RLCA
|"00010111"
-- RLA
|"00001111"
-- RRCA
|"00011111" =>
-- RRA
Set_BusA_To(2 downto 0) <= "111";
ALU_Op <= "1000";
Read_To_Reg <= '1';
Save_ALU <= '1';
 
-- JUMP GROUP
when "11000011" =>
-- JP nn
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 2 =>
Inc_PC <= '1';
LDZ <= '1';
when 3 =>
Inc_PC <= '1';
Jump <= '1';
when others => null;
end case;
when "11000010"|"11001010"|"11010010"|"11011010"|"11100010"|"11101010"|"11110010"|"11111010" =>
if IR(5) = '1' and Mode = 3 then
case IRB(4 downto 3) is
when "00" =>
-- LD ($FF00+C),A
MCycles <= "010";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aBC;
Set_BusB_To <= "0111";
when 2 =>
Write <= '1';
IORQ <= '1';
when others =>
end case;
when "01" =>
-- LD (nn),A
MCycles <= "100";
case to_integer(unsigned(MCycle)) is
when 2 =>
Inc_PC <= '1';
LDZ <= '1';
when 3 =>
Set_Addr_To <= aZI;
Inc_PC <= '1';
Set_BusB_To <= "0111";
when 4 =>
Write <= '1';
when others => null;
end case;
when "10" =>
-- LD A,($FF00+C)
MCycles <= "010";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aBC;
when 2 =>
Read_To_Acc <= '1';
IORQ <= '1';
when others =>
end case;
when "11" =>
-- LD A,(nn)
MCycles <= "100";
case to_integer(unsigned(MCycle)) is
when 2 =>
Inc_PC <= '1';
LDZ <= '1';
when 3 =>
Set_Addr_To <= aZI;
Inc_PC <= '1';
when 4 =>
Read_To_Acc <= '1';
when others => null;
end case;
end case;
else
-- JP cc,nn
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 2 =>
Inc_PC <= '1';
LDZ <= '1';
when 3 =>
Inc_PC <= '1';
if is_cc_true(F, to_bitvector(IR(5 downto 3))) then
Jump <= '1';
end if;
when others => null;
end case;
end if;
when "00011000" =>
if Mode /= 2 then
-- JR e
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 2 =>
Inc_PC <= '1';
when 3 =>
NoRead <= '1';
JumpE <= '1';
TStates <= "101";
when others => null;
end case;
end if;
when "00111000" =>
if Mode /= 2 then
-- JR C,e
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 2 =>
Inc_PC <= '1';
if F(Flag_C) = '0' then
MCycles <= "010";
end if;
when 3 =>
NoRead <= '1';
JumpE <= '1';
TStates <= "101";
when others => null;
end case;
end if;
when "00110000" =>
if Mode /= 2 then
-- JR NC,e
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 2 =>
Inc_PC <= '1';
if F(Flag_C) = '1' then
MCycles <= "010";
end if;
when 3 =>
NoRead <= '1';
JumpE <= '1';
TStates <= "101";
when others => null;
end case;
end if;
when "00101000" =>
if Mode /= 2 then
-- JR Z,e
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 2 =>
Inc_PC <= '1';
if F(Flag_Z) = '0' then
MCycles <= "010";
end if;
when 3 =>
NoRead <= '1';
JumpE <= '1';
TStates <= "101";
when others => null;
end case;
end if;
when "00100000" =>
if Mode /= 2 then
-- JR NZ,e
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 2 =>
Inc_PC <= '1';
if F(Flag_Z) = '1' then
MCycles <= "010";
end if;
when 3 =>
NoRead <= '1';
JumpE <= '1';
TStates <= "101";
when others => null;
end case;
end if;
when "11101001" =>
-- JP (HL)
JumpXY <= '1';
when "00010000" =>
if Mode = 3 then
I_DJNZ <= '1';
elsif Mode < 2 then
-- DJNZ,e
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 1 =>
TStates <= "101";
I_DJNZ <= '1';
Set_BusB_To <= "1010";
Set_BusA_To(2 downto 0) <= "000";
Read_To_Reg <= '1';
Save_ALU <= '1';
ALU_Op <= "0010";
when 2 =>
I_DJNZ <= '1';
Inc_PC <= '1';
when 3 =>
NoRead <= '1';
JumpE <= '1';
TStates <= "101";
when others => null;
end case;
end if;
 
-- CALL AND RETURN GROUP
when "11001101" =>
-- CALL nn
MCycles <= "101";
case to_integer(unsigned(MCycle)) is
when 2 =>
Inc_PC <= '1';
LDZ <= '1';
when 3 =>
IncDec_16 <= "1111";
Inc_PC <= '1';
TStates <= "100";
Set_Addr_To <= aSP;
LDW <= '1';
Set_BusB_To <= "1101";
when 4 =>
Write <= '1';
IncDec_16 <= "1111";
Set_Addr_To <= aSP;
Set_BusB_To <= "1100";
when 5 =>
Write <= '1';
Call <= '1';
when others => null;
end case;
when "11000100"|"11001100"|"11010100"|"11011100"|"11100100"|"11101100"|"11110100"|"11111100" =>
if IR(5) = '0' or Mode /= 3 then
-- CALL cc,nn
MCycles <= "101";
case to_integer(unsigned(MCycle)) is
when 2 =>
Inc_PC <= '1';
LDZ <= '1';
when 3 =>
Inc_PC <= '1';
LDW <= '1';
if is_cc_true(F, to_bitvector(IR(5 downto 3))) then
IncDec_16 <= "1111";
Set_Addr_TO <= aSP;
TStates <= "100";
Set_BusB_To <= "1101";
else
MCycles <= "011";
end if;
when 4 =>
Write <= '1';
IncDec_16 <= "1111";
Set_Addr_To <= aSP;
Set_BusB_To <= "1100";
when 5 =>
Write <= '1';
Call <= '1';
when others => null;
end case;
end if;
when "11001001" =>
-- RET
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 1 =>
TStates <= "101";
Set_Addr_TO <= aSP;
when 2 =>
IncDec_16 <= "0111";
Set_Addr_To <= aSP;
LDZ <= '1';
when 3 =>
Jump <= '1';
IncDec_16 <= "0111";
when others => null;
end case;
when "11000000"|"11001000"|"11010000"|"11011000"|"11100000"|"11101000"|"11110000"|"11111000" =>
if IR(5) = '1' and Mode = 3 then
case IRB(4 downto 3) is
when "00" =>
-- LD ($FF00+nn),A
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 2 =>
Inc_PC <= '1';
Set_Addr_To <= aIOA;
Set_BusB_To <= "0111";
when 3 =>
Write <= '1';
when others => null;
end case;
when "01" =>
-- ADD SP,n
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 2 =>
ALU_Op <= "0000";
Inc_PC <= '1';
Read_To_Reg <= '1';
Save_ALU <= '1';
Set_BusA_To <= "1000";
Set_BusB_To <= "0110";
when 3 =>
NoRead <= '1';
Read_To_Reg <= '1';
Save_ALU <= '1';
ALU_Op <= "0001";
Set_BusA_To <= "1001";
Set_BusB_To <= "1110"; -- Incorrect unsigned !!!!!!!!!!!!!!!!!!!!!
when others =>
end case;
when "10" =>
-- LD A,($FF00+nn)
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 2 =>
Inc_PC <= '1';
Set_Addr_To <= aIOA;
when 3 =>
Read_To_Acc <= '1';
when others => null;
end case;
when "11" =>
-- LD HL,SP+n -- Not correct !!!!!!!!!!!!!!!!!!!
MCycles <= "101";
case to_integer(unsigned(MCycle)) is
when 2 =>
Inc_PC <= '1';
LDZ <= '1';
when 3 =>
Set_Addr_To <= aZI;
Inc_PC <= '1';
LDW <= '1';
when 4 =>
Set_BusA_To(2 downto 0) <= "101"; -- L
Read_To_Reg <= '1';
Inc_WZ <= '1';
Set_Addr_To <= aZI;
when 5 =>
Set_BusA_To(2 downto 0) <= "100"; -- H
Read_To_Reg <= '1';
when others => null;
end case;
end case;
else
-- RET cc
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 1 =>
if is_cc_true(F, to_bitvector(IR(5 downto 3))) then
Set_Addr_TO <= aSP;
else
MCycles <= "001";
end if;
TStates <= "101";
when 2 =>
IncDec_16 <= "0111";
Set_Addr_To <= aSP;
LDZ <= '1';
when 3 =>
Jump <= '1';
IncDec_16 <= "0111";
when others => null;
end case;
end if;
when "11000111"|"11001111"|"11010111"|"11011111"|"11100111"|"11101111"|"11110111"|"11111111" =>
-- RST p
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 1 =>
TStates <= "101";
IncDec_16 <= "1111";
Set_Addr_To <= aSP;
Set_BusB_To <= "1101";
when 2 =>
Write <= '1';
IncDec_16 <= "1111";
Set_Addr_To <= aSP;
Set_BusB_To <= "1100";
when 3 =>
Write <= '1';
RstP <= '1';
when others => null;
end case;
 
-- INPUT AND OUTPUT GROUP
when "11011011" =>
if Mode /= 3 then
-- IN A,(n)
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 2 =>
Inc_PC <= '1';
Set_Addr_To <= aIOA;
when 3 =>
Read_To_Acc <= '1';
IORQ <= '1';
when others => null;
end case;
end if;
when "11010011" =>
if Mode /= 3 then
-- OUT (n),A
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 2 =>
Inc_PC <= '1';
Set_Addr_To <= aIOA;
Set_BusB_To <= "0111";
when 3 =>
Write <= '1';
IORQ <= '1';
when others => null;
end case;
end if;
 
------------------------------------------------------------------------------
------------------------------------------------------------------------------
-- MULTIBYTE INSTRUCTIONS
------------------------------------------------------------------------------
------------------------------------------------------------------------------
 
when "11001011" =>
if Mode /= 2 then
Prefix <= "01";
end if;
 
when "11101101" =>
if Mode < 2 then
Prefix <= "10";
end if;
 
when "11011101"|"11111101" =>
if Mode < 2 then
Prefix <= "11";
end if;
 
end case;
 
when "01" =>
 
------------------------------------------------------------------------------
--
-- CB prefixed instructions
--
------------------------------------------------------------------------------
 
Set_BusA_To(2 downto 0) <= IR(2 downto 0);
Set_BusB_To(2 downto 0) <= IR(2 downto 0);
 
case IRB is
when "00000000"|"00000001"|"00000010"|"00000011"|"00000100"|"00000101"|"00000111"
|"00010000"|"00010001"|"00010010"|"00010011"|"00010100"|"00010101"|"00010111"
|"00001000"|"00001001"|"00001010"|"00001011"|"00001100"|"00001101"|"00001111"
|"00011000"|"00011001"|"00011010"|"00011011"|"00011100"|"00011101"|"00011111"
|"00100000"|"00100001"|"00100010"|"00100011"|"00100100"|"00100101"|"00100111"
|"00101000"|"00101001"|"00101010"|"00101011"|"00101100"|"00101101"|"00101111"
|"00110000"|"00110001"|"00110010"|"00110011"|"00110100"|"00110101"|"00110111"
|"00111000"|"00111001"|"00111010"|"00111011"|"00111100"|"00111101"|"00111111" =>
-- RLC r
-- RL r
-- RRC r
-- RR r
-- SLA r
-- SRA r
-- SRL r
-- SLL r (Undocumented) / SWAP r
if MCycle = "001" then
ALU_Op <= "1000";
Read_To_Reg <= '1';
Save_ALU <= '1';
end if;
when "00000110"|"00010110"|"00001110"|"00011110"|"00101110"|"00111110"|"00100110"|"00110110" =>
-- RLC (HL)
-- RL (HL)
-- RRC (HL)
-- RR (HL)
-- SRA (HL)
-- SRL (HL)
-- SLA (HL)
-- SLL (HL) (Undocumented) / SWAP (HL)
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 1 | 7 =>
Set_Addr_To <= aXY;
when 2 =>
ALU_Op <= "1000";
Read_To_Reg <= '1';
Save_ALU <= '1';
Set_Addr_To <= aXY;
TStates <= "100";
when 3 =>
Write <= '1';
when others =>
end case;
when "01000000"|"01000001"|"01000010"|"01000011"|"01000100"|"01000101"|"01000111"
|"01001000"|"01001001"|"01001010"|"01001011"|"01001100"|"01001101"|"01001111"
|"01010000"|"01010001"|"01010010"|"01010011"|"01010100"|"01010101"|"01010111"
|"01011000"|"01011001"|"01011010"|"01011011"|"01011100"|"01011101"|"01011111"
|"01100000"|"01100001"|"01100010"|"01100011"|"01100100"|"01100101"|"01100111"
|"01101000"|"01101001"|"01101010"|"01101011"|"01101100"|"01101101"|"01101111"
|"01110000"|"01110001"|"01110010"|"01110011"|"01110100"|"01110101"|"01110111"
|"01111000"|"01111001"|"01111010"|"01111011"|"01111100"|"01111101"|"01111111" =>
-- BIT b,r
if MCycle = "001" then
Set_BusB_To(2 downto 0) <= IR(2 downto 0);
ALU_Op <= "1001";
end if;
when "01000110"|"01001110"|"01010110"|"01011110"|"01100110"|"01101110"|"01110110"|"01111110" =>
-- BIT b,(HL)
MCycles <= "010";
case to_integer(unsigned(MCycle)) is
when 1 | 7 =>
Set_Addr_To <= aXY;
when 2 =>
ALU_Op <= "1001";
TStates <= "100";
when others =>
end case;
when "11000000"|"11000001"|"11000010"|"11000011"|"11000100"|"11000101"|"11000111"
|"11001000"|"11001001"|"11001010"|"11001011"|"11001100"|"11001101"|"11001111"
|"11010000"|"11010001"|"11010010"|"11010011"|"11010100"|"11010101"|"11010111"
|"11011000"|"11011001"|"11011010"|"11011011"|"11011100"|"11011101"|"11011111"
|"11100000"|"11100001"|"11100010"|"11100011"|"11100100"|"11100101"|"11100111"
|"11101000"|"11101001"|"11101010"|"11101011"|"11101100"|"11101101"|"11101111"
|"11110000"|"11110001"|"11110010"|"11110011"|"11110100"|"11110101"|"11110111"
|"11111000"|"11111001"|"11111010"|"11111011"|"11111100"|"11111101"|"11111111" =>
-- SET b,r
if MCycle = "001" then
ALU_Op <= "1010";
Read_To_Reg <= '1';
Save_ALU <= '1';
end if;
when "11000110"|"11001110"|"11010110"|"11011110"|"11100110"|"11101110"|"11110110"|"11111110" =>
-- SET b,(HL)
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 1 | 7 =>
Set_Addr_To <= aXY;
when 2 =>
ALU_Op <= "1010";
Read_To_Reg <= '1';
Save_ALU <= '1';
Set_Addr_To <= aXY;
TStates <= "100";
when 3 =>
Write <= '1';
when others =>
end case;
when "10000000"|"10000001"|"10000010"|"10000011"|"10000100"|"10000101"|"10000111"
|"10001000"|"10001001"|"10001010"|"10001011"|"10001100"|"10001101"|"10001111"
|"10010000"|"10010001"|"10010010"|"10010011"|"10010100"|"10010101"|"10010111"
|"10011000"|"10011001"|"10011010"|"10011011"|"10011100"|"10011101"|"10011111"
|"10100000"|"10100001"|"10100010"|"10100011"|"10100100"|"10100101"|"10100111"
|"10101000"|"10101001"|"10101010"|"10101011"|"10101100"|"10101101"|"10101111"
|"10110000"|"10110001"|"10110010"|"10110011"|"10110100"|"10110101"|"10110111"
|"10111000"|"10111001"|"10111010"|"10111011"|"10111100"|"10111101"|"10111111" =>
-- RES b,r
if MCycle = "001" then
ALU_Op <= "1011";
Read_To_Reg <= '1';
Save_ALU <= '1';
end if;
when "10000110"|"10001110"|"10010110"|"10011110"|"10100110"|"10101110"|"10110110"|"10111110" =>
-- RES b,(HL)
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 1 | 7 =>
Set_Addr_To <= aXY;
when 2 =>
ALU_Op <= "1011";
Read_To_Reg <= '1';
Save_ALU <= '1';
Set_Addr_To <= aXY;
TStates <= "100";
when 3 =>
Write <= '1';
when others =>
end case;
end case;
 
when others =>
 
------------------------------------------------------------------------------
--
-- ED prefixed instructions
--
------------------------------------------------------------------------------
 
case IRB is
when "00000000"|"00000001"|"00000010"|"00000011"|"00000100"|"00000101"|"00000110"|"00000111"
|"00001000"|"00001001"|"00001010"|"00001011"|"00001100"|"00001101"|"00001110"|"00001111"
|"00010000"|"00010001"|"00010010"|"00010011"|"00010100"|"00010101"|"00010110"|"00010111"
|"00011000"|"00011001"|"00011010"|"00011011"|"00011100"|"00011101"|"00011110"|"00011111"
|"00100000"|"00100001"|"00100010"|"00100011"|"00100100"|"00100101"|"00100110"|"00100111"
|"00101000"|"00101001"|"00101010"|"00101011"|"00101100"|"00101101"|"00101110"|"00101111"
|"00110000"|"00110001"|"00110010"|"00110011"|"00110100"|"00110101"|"00110110"|"00110111"
|"00111000"|"00111001"|"00111010"|"00111011"|"00111100"|"00111101"|"00111110"|"00111111"
 
 
|"10000000"|"10000001"|"10000010"|"10000011"|"10000100"|"10000101"|"10000110"|"10000111"
|"10001000"|"10001001"|"10001010"|"10001011"|"10001100"|"10001101"|"10001110"|"10001111"
|"10010000"|"10010001"|"10010010"|"10010011"|"10010100"|"10010101"|"10010110"|"10010111"
|"10011000"|"10011001"|"10011010"|"10011011"|"10011100"|"10011101"|"10011110"|"10011111"
| "10100100"|"10100101"|"10100110"|"10100111"
| "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"
|"11100000"|"11100001"|"11100010"|"11100011"|"11100100"|"11100101"|"11100110"|"11100111"
|"11101000"|"11101001"|"11101010"|"11101011"|"11101100"|"11101101"|"11101110"|"11101111"
|"11110000"|"11110001"|"11110010"|"11110011"|"11110100"|"11110101"|"11110110"|"11110111"
|"11111000"|"11111001"|"11111010"|"11111011"|"11111100"|"11111101"|"11111110"|"11111111" =>
null; -- NOP, undocumented
when "01111110"|"01111111" =>
-- NOP, undocumented
null;
-- 8 BIT LOAD GROUP
when "01010111" =>
-- LD A,I
Special_LD <= "100";
TStates <= "101";
when "01011111" =>
-- LD A,R
Special_LD <= "101";
TStates <= "101";
when "01000111" =>
-- LD I,A
Special_LD <= "110";
TStates <= "101";
when "01001111" =>
-- LD R,A
Special_LD <= "111";
TStates <= "101";
-- 16 BIT LOAD GROUP
when "01001011"|"01011011"|"01101011"|"01111011" =>
-- LD dd,(nn)
MCycles <= "101";
case to_integer(unsigned(MCycle)) is
when 2 =>
Inc_PC <= '1';
LDZ <= '1';
when 3 =>
Set_Addr_To <= aZI;
Inc_PC <= '1';
LDW <= '1';
when 4 =>
Read_To_Reg <= '1';
if IR(5 downto 4) = "11" then
Set_BusA_To <= "1000";
else
Set_BusA_To(2 downto 1) <= IR(5 downto 4);
Set_BusA_To(0) <= '1';
end if;
Inc_WZ <= '1';
Set_Addr_To <= aZI;
when 5 =>
Read_To_Reg <= '1';
if IR(5 downto 4) = "11" then
Set_BusA_To <= "1001";
else
Set_BusA_To(2 downto 1) <= IR(5 downto 4);
Set_BusA_To(0) <= '0';
end if;
when others => null;
end case;
when "01000011"|"01010011"|"01100011"|"01110011" =>
-- LD (nn),dd
MCycles <= "101";
case to_integer(unsigned(MCycle)) is
when 2 =>
Inc_PC <= '1';
LDZ <= '1';
when 3 =>
Set_Addr_To <= aZI;
Inc_PC <= '1';
LDW <= '1';
if IR(5 downto 4) = "11" then
Set_BusB_To <= "1000";
else
Set_BusB_To(2 downto 1) <= IR(5 downto 4);
Set_BusB_To(0) <= '1';
Set_BusB_To(3) <= '0';
end if;
when 4 =>
Inc_WZ <= '1';
Set_Addr_To <= aZI;
Write <= '1';
if IR(5 downto 4) = "11" then
Set_BusB_To <= "1001";
else
Set_BusB_To(2 downto 1) <= IR(5 downto 4);
Set_BusB_To(0) <= '0';
Set_BusB_To(3) <= '0';
end if;
when 5 =>
Write <= '1';
when others => null;
end case;
when "10100000" | "10101000" | "10110000" | "10111000" =>
-- LDI, LDD, LDIR, LDDR
MCycles <= "100";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aXY;
IncDec_16 <= "1100"; -- BC
when 2 =>
Set_BusB_To <= "0110";
Set_BusA_To(2 downto 0) <= "111";
ALU_Op <= "0000";
Set_Addr_To <= aDE;
if IR(3) = '0' then
IncDec_16 <= "0110"; -- IX
else
IncDec_16 <= "1110";
end if;
when 3 =>
I_BT <= '1';
TStates <= "101";
Write <= '1';
if IR(3) = '0' then
IncDec_16 <= "0101"; -- DE
else
IncDec_16 <= "1101";
end if;
when 4 =>
NoRead <= '1';
TStates <= "101";
when others => null;
end case;
when "10100001" | "10101001" | "10110001" | "10111001" =>
-- CPI, CPD, CPIR, CPDR
MCycles <= "100";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aXY;
IncDec_16 <= "1100"; -- BC
when 2 =>
Set_BusB_To <= "0110";
Set_BusA_To(2 downto 0) <= "111";
ALU_Op <= "0111";
Save_ALU <= '1';
PreserveC <= '1';
if IR(3) = '0' then
IncDec_16 <= "0110";
else
IncDec_16 <= "1110";
end if;
when 3 =>
NoRead <= '1';
I_BC <= '1';
TStates <= "101";
when 4 =>
NoRead <= '1';
TStates <= "101";
when others => null;
end case;
when "01000100"|"01001100"|"01010100"|"01011100"|"01100100"|"01101100"|"01110100"|"01111100" =>
-- NEG
Alu_OP <= "0010";
Set_BusB_To <= "0111";
Set_BusA_To <= "1010";
Read_To_Acc <= '1';
Save_ALU <= '1';
when "01000110"|"01001110"|"01100110"|"01101110" =>
-- IM 0
IMode <= "00";
when "01010110"|"01110110" =>
-- IM 1
IMode <= "01";
when "01011110"|"01110111" =>
-- IM 2
IMode <= "10";
-- 16 bit arithmetic
when "01001010"|"01011010"|"01101010"|"01111010" =>
-- ADC HL,ss
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 2 =>
NoRead <= '1';
ALU_Op <= "0001";
Read_To_Reg <= '1';
Save_ALU <= '1';
Set_BusA_To(2 downto 0) <= "101";
case to_integer(unsigned(IR(5 downto 4))) is
when 0|1|2 =>
Set_BusB_To(2 downto 1) <= IR(5 downto 4);
Set_BusB_To(0) <= '1';
when others =>
Set_BusB_To <= "1000";
end case;
TStates <= "100";
when 3 =>
NoRead <= '1';
Read_To_Reg <= '1';
Save_ALU <= '1';
ALU_Op <= "0001";
Set_BusA_To(2 downto 0) <= "100";
case to_integer(unsigned(IR(5 downto 4))) is
when 0|1|2 =>
Set_BusB_To(2 downto 1) <= IR(5 downto 4);
Set_BusB_To(0) <= '0';
when others =>
Set_BusB_To <= "1001";
end case;
when others =>
end case;
when "01000010"|"01010010"|"01100010"|"01110010" =>
-- SBC HL,ss
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 2 =>
NoRead <= '1';
ALU_Op <= "0011";
Read_To_Reg <= '1';
Save_ALU <= '1';
Set_BusA_To(2 downto 0) <= "101";
case to_integer(unsigned(IR(5 downto 4))) is
when 0|1|2 =>
Set_BusB_To(2 downto 1) <= IR(5 downto 4);
Set_BusB_To(0) <= '1';
when others =>
Set_BusB_To <= "1000";
end case;
TStates <= "100";
when 3 =>
NoRead <= '1';
ALU_Op <= "0011";
Read_To_Reg <= '1';
Save_ALU <= '1';
Set_BusA_To(2 downto 0) <= "100";
case to_integer(unsigned(IR(5 downto 4))) is
when 0|1|2 =>
Set_BusB_To(2 downto 1) <= IR(5 downto 4);
when others =>
Set_BusB_To <= "1001";
end case;
when others =>
end case;
when "01101111" =>
-- RLD
MCycles <= "100";
case to_integer(unsigned(MCycle)) is
when 2 =>
NoRead <= '1';
Set_Addr_To <= aXY;
when 3 =>
Read_To_Reg <= '1';
Set_BusB_To(2 downto 0) <= "110";
Set_BusA_To(2 downto 0) <= "111";
ALU_Op <= "1101";
TStates <= "100";
Set_Addr_To <= aXY;
Save_ALU <= '1';
when 4 =>
I_RLD <= '1';
Write <= '1';
when others =>
end case;
when "01100111" =>
-- RRD
MCycles <= "100";
case to_integer(unsigned(MCycle)) is
when 2 =>
Set_Addr_To <= aXY;
when 3 =>
Read_To_Reg <= '1';
Set_BusB_To(2 downto 0) <= "110";
Set_BusA_To(2 downto 0) <= "111";
ALU_Op <= "1110";
TStates <= "100";
Set_Addr_To <= aXY;
Save_ALU <= '1';
when 4 =>
I_RRD <= '1';
Write <= '1';
when others =>
end case;
when "01000101"|"01001101"|"01010101"|"01011101"|"01100101"|"01101101"|"01110101"|"01111101" =>
-- RETI, RETN
MCycles <= "011";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_TO <= aSP;
when 2 =>
IncDec_16 <= "0111";
Set_Addr_To <= aSP;
LDZ <= '1';
when 3 =>
Jump <= '1';
IncDec_16 <= "0111";
I_RETN <= '1';
when others => null;
end case;
when "01000000"|"01001000"|"01010000"|"01011000"|"01100000"|"01101000"|"01110000"|"01111000" =>
-- IN r,(C)
MCycles <= "010";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aBC;
when 2 =>
IORQ <= '1';
if IR(5 downto 3) /= "110" then
Read_To_Reg <= '1';
Set_BusA_To(2 downto 0) <= IR(5 downto 3);
end if;
I_INRC <= '1';
when others =>
end case;
when "01000001"|"01001001"|"01010001"|"01011001"|"01100001"|"01101001"|"01110001"|"01111001" =>
-- OUT (C),r
-- OUT (C),0
MCycles <= "010";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aBC;
Set_BusB_To(2 downto 0) <= IR(5 downto 3);
if IR(5 downto 3) = "110" then
Set_BusB_To(3) <= '1';
end if;
when 2 =>
Write <= '1';
IORQ <= '1';
when others =>
end case;
when "10100010" | "10101010" | "10110010" | "10111010" =>
-- INI, IND, INIR, INDR
MCycles <= "100";
case to_integer(unsigned(MCycle)) is
when 1 =>
Set_Addr_To <= aBC;
Set_BusB_To <= "1010";
Set_BusA_To <= "0000";
Read_To_Reg <= '1';
Save_ALU <= '1';
ALU_Op <= "0010";
when 2 =>
IORQ <= '1';
Set_BusB_To <= "0110";
Set_Addr_To <= aXY;
when 3 =>
if IR(3) = '0' then
IncDec_16 <= "0010";
else
IncDec_16 <= "1010";
end if;
TStates <= "100";
Write <= '1';
I_BTR <= '1';
when 4 =>
NoRead <= '1';
TStates <= "101";
when others => null;
end case;
when "10100011" | "10101011" | "10110011" | "10111011" =>
-- OUTI, OUTD, OTIR, OTDR
MCycles <= "100";
case to_integer(unsigned(MCycle)) is
when 1 =>
TStates <= "101";
Set_Addr_To <= aXY;
Set_BusB_To <= "1010";
Set_BusA_To <= "0000";
Read_To_Reg <= '1';
Save_ALU <= '1';
ALU_Op <= "0010";
when 2 =>
Set_BusB_To <= "0110";
Set_Addr_To <= aBC;
when 3 =>
if IR(3) = '0' then
IncDec_16 <= "0010";
else
IncDec_16 <= "1010";
end if;
IORQ <= '1';
Write <= '1';
I_BTR <= '1';
when 4 =>
NoRead <= '1';
TStates <= "101";
when others => null;
end case;
end case;
 
end case;
 
if Mode = 1 then
if MCycle = "001" then
-- TStates <= "100";
else
TStates <= "011";
end if;
end if;
 
if Mode = 3 then
if MCycle = "001" then
-- TStates <= "100";
else
TStates <= "100";
end if;
end if;
 
if Mode < 2 then
if MCycle = "110" then
Inc_PC <= '1';
if Mode = 1 then
Set_Addr_To <= aXY;
TStates <= "100";
Set_BusB_To(2 downto 0) <= SSS;
Set_BusB_To(3) <= '0';
end if;
if IRB = "00110110" or IRB = "11001011" then
Set_Addr_To <= aNone;
end if;
end if;
if MCycle = "111" then
if Mode = 0 then
TStates <= "101";
end if;
if ISet /= "01" then
Set_Addr_To <= aXY;
end if;
Set_BusB_To(2 downto 0) <= SSS;
Set_BusB_To(3) <= '0';
if IRB = "00110110" or ISet = "01" then
-- LD (HL),n
Inc_PC <= '1';
else
NoRead <= '1';
end if;
end if;
end if;
 
end process;
 
end;
/DebugSystem.vhd
0,0 → 1,181
-- Z80, Monitor ROM, 4k RAM and two 16450 UARTs
-- that can be synthesized and used with
-- the NoICE debugger that can be found at
-- http://www.noicedebugger.com/
 
library IEEE;
use IEEE.std_logic_1164.all;
 
entity DebugSystem is
port(
Reset_n : in std_logic;
Clk : in std_logic;
NMI_n : in std_logic;
RXD0 : in std_logic;
CTS0 : in std_logic;
DSR0 : in std_logic;
RI0 : in std_logic;
DCD0 : in std_logic;
RXD1 : in std_logic;
CTS1 : in std_logic;
DSR1 : in std_logic;
RI1 : in std_logic;
DCD1 : in std_logic;
TXD0 : out std_logic;
RTS0 : out std_logic;
DTR0 : out std_logic;
TXD1 : out std_logic;
RTS1 : out std_logic;
DTR1 : out std_logic
);
end DebugSystem;
 
architecture struct of DebugSystem is
 
signal M1_n : std_logic;
signal MREQ_n : std_logic;
signal IORQ_n : std_logic;
signal RD_n : std_logic;
signal WR_n : std_logic;
signal RFSH_n : std_logic;
signal HALT_n : std_logic;
signal WAIT_n : std_logic;
signal INT_n : std_logic;
signal RESET_s : std_logic;
signal BUSRQ_n : std_logic;
signal BUSAK_n : std_logic;
signal A : std_logic_vector(15 downto 0);
signal D : std_logic_vector(7 downto 0);
signal ROM_D : std_logic_vector(7 downto 0);
signal SRAM_D : std_logic_vector(7 downto 0);
signal UART0_D : std_logic_vector(7 downto 0);
signal UART1_D : std_logic_vector(7 downto 0);
signal CPU_D : std_logic_vector(7 downto 0);
 
signal Mirror : std_logic;
 
signal IOWR_n : std_logic;
signal RAMCS_n : std_logic;
signal UART0CS_n : std_logic;
signal UART1CS_n : std_logic;
 
signal BaudOut0 : std_logic;
signal BaudOut1 : std_logic;
 
begin
 
Wait_n <= '1';
BusRq_n <= '1';
INT_n <= '1';
 
process (Reset_n, Clk)
begin
if Reset_n = '0' then
Reset_s <= '0';
Mirror <= '0';
elsif Clk'event and Clk = '1' then
Reset_s <= '1';
if IORQ_n = '0' and A(7 downto 4) = "1111" then
Mirror <= D(0);
end if;
end if;
end process;
 
IOWR_n <= WR_n or IORQ_n;
RAMCS_n <= (not Mirror and not A(15)) or MREQ_n;
UART0CS_n <= '0' when IORQ_n = '0' and A(7 downto 3) = "00000" else '1';
UART1CS_n <= '0' when IORQ_n = '0' and A(7 downto 3) = "10000" else '1';
 
CPU_D <=
SRAM_D when RAMCS_n = '0' else
UART0_D when UART0CS_n = '0' else
UART1_D when UART1CS_n = '0' else
ROM_D;
 
u0 : entity work.T80s
generic map(Mode => 1, T2Write => 1, IOWait => 0)
port map(
RESET_n => RESET_s,
CLK_n => Clk,
WAIT_n => WAIT_n,
INT_n => INT_n,
NMI_n => NMI_n,
BUSRQ_n => BUSRQ_n,
M1_n => M1_n,
MREQ_n => MREQ_n,
IORQ_n => IORQ_n,
RD_n => RD_n,
WR_n => WR_n,
RFSH_n => RFSH_n,
HALT_n => HALT_n,
BUSAK_n => BUSAK_n,
A => A,
DI => CPU_D,
DO => D);
 
u1 : entity work.MonZ80
port map(
Clk => Clk,
A => A(10 downto 0),
D => ROM_D);
 
u2 : entity work.SSRAM
generic map(
AddrWidth => 12)
port map(
Clk => Clk,
CE_n => RAMCS_n,
WE_n => WR_n,
A => A(11 downto 0),
DIn => D,
DOut => SRAM_D);
 
u3 : entity work.T16450
port map(
MR_n => Reset_s,
XIn => Clk,
RClk => BaudOut0,
CS_n => UART0CS_n,
Rd_n => RD_n,
Wr_n => IOWR_n,
A => A(2 downto 0),
D_In => D,
D_Out => UART0_D,
SIn => RXD0,
CTS_n => CTS0,
DSR_n => DSR0,
RI_n => RI0,
DCD_n => DCD0,
SOut => TXD0,
RTS_n => RTS0,
DTR_n => DTR0,
OUT1_n => open,
OUT2_n => open,
BaudOut => BaudOut0,
Intr => open);
 
u4 : entity work.T16450
port map(
MR_n => Reset_s,
XIn => Clk,
RClk => BaudOut1,
CS_n => UART1CS_n,
Rd_n => RD_n,
Wr_n => IOWR_n,
A => A(2 downto 0),
D_In => D,
D_Out => UART1_D,
SIn => RXD1,
CTS_n => CTS1,
DSR_n => DSR1,
RI_n => RI1,
DCD_n => DCD1,
SOut => TXD1,
RTS_n => RTS1,
DTR_n => DTR1,
OUT1_n => open,
OUT2_n => open,
BaudOut => BaudOut1,
Intr => open);
 
end;
/T80s.vhd
0,0 → 1,190
--
-- Z80 compatible microprocessor core, synchronous top level
-- Different timing than the original z80
-- Inputs needs to be synchronous and outputs may glitch
--
-- Version : 0242
--
-- 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 read with wait
--
-- 0211 : Fixed interrupt cycle
--
-- 0235 : Updated for T80 interface change
--
-- 0236 : Added T2Write generic
--
-- 0237 : Fixed T2Write with wait state
--
-- 0238 : Updated for T80 interface change
--
-- 0240 : Updated for T80 interface change
--
-- 0242 : Updated for T80 interface change
--
 
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.T80_Pack.all;
 
entity T80s is
generic(
Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB
T2Write : integer := 0; -- 0 => WR_n active in T3, /=0 => WR_n active in T2
IOWait : integer := 1 -- 0 => Single cycle I/O, 1 => Std I/O cycle
);
port(
RESET_n : in std_logic;
CLK_n : 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;
MREQ_n : out std_logic;
IORQ_n : out std_logic;
RD_n : out std_logic;
WR_n : 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);
DI : in std_logic_vector(7 downto 0);
DO : out std_logic_vector(7 downto 0)
);
end T80s;
 
architecture rtl of T80s is
 
signal CEN : std_logic;
signal IntCycle_n : std_logic;
signal NoRead : std_logic;
signal Write : std_logic;
signal IORQ : std_logic;
signal DI_Reg : std_logic_vector(7 downto 0);
signal MCycle : std_logic_vector(2 downto 0);
signal TState : std_logic_vector(2 downto 0);
 
begin
 
CEN <= '1';
 
u0 : T80
generic map(
Mode => Mode,
IOWait => IOWait)
port map(
CEN => CEN,
M1_n => M1_n,
IORQ => IORQ,
NoRead => NoRead,
Write => Write,
RFSH_n => RFSH_n,
HALT_n => HALT_n,
WAIT_n => Wait_n,
INT_n => INT_n,
NMI_n => NMI_n,
RESET_n => RESET_n,
BUSRQ_n => BUSRQ_n,
BUSAK_n => BUSAK_n,
CLK_n => CLK_n,
A => A,
DInst => DI,
DI => DI_Reg,
DO => DO,
MC => MCycle,
TS => TState,
IntCycle_n => IntCycle_n);
 
process (RESET_n, CLK_n)
begin
if RESET_n = '0' then
RD_n <= '1';
WR_n <= '1';
IORQ_n <= '1';
MREQ_n <= '1';
DI_Reg <= "00000000";
elsif CLK_n'event and CLK_n = '1' then
RD_n <= '1';
WR_n <= '1';
IORQ_n <= '1';
MREQ_n <= '1';
if MCycle = "001" then
if TState = "001" or (TState = "010" and Wait_n = '0') then
RD_n <= not IntCycle_n;
MREQ_n <= not IntCycle_n;
IORQ_n <= IntCycle_n;
end if;
if TState = "011" then
MREQ_n <= '0';
end if;
else
if (TState = "001" or (TState = "010" and Wait_n = '0')) and NoRead = '0' and Write = '0' then
RD_n <= '0';
IORQ_n <= not IORQ;
MREQ_n <= IORQ;
end if;
if T2Write = 0 then
if TState = "010" and Write = '1' then
WR_n <= '0';
IORQ_n <= not IORQ;
MREQ_n <= IORQ;
end if;
else
if (TState = "001" or (TState = "010" and Wait_n = '0')) and Write = '1' then
WR_n <= '0';
IORQ_n <= not IORQ;
MREQ_n <= IORQ;
end if;
end if;
end if;
if TState = "010" and Wait_n = '1' then
DI_Reg <= DI;
end if;
end if;
end process;
 
end;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.