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; |