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

Subversion Repositories System09

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /System09/trunk/rtl/VHDL
    from Rev 118 to Rev 122
    Reverse comparison

Rev 118 → Rev 122

/XuLA_clk.vhd
0,0 → 1,140
--=============================================================================--
-- --
-- System09 - Synthesizable System On a Chip - XuLA System Clock DCM --
-- --
--=============================================================================--
--
--
-- File name : XuLA_clk.vhd
--
-- Entity name : XuLA_clk
--
-- Purpose : Clock module to generate 48MHz SDRAM clock
-- and 24MHz CPU and VDU pixel clock
-- from the 12MHz PIC FPGA Clock
--
-- Dependencies : ieee.Std_Logic_1164
-- ieee.std_logic_unsigned
-- ieee.std_logic_arith
-- ieee.numeric_std
--
-- Uses :
--
-- Author : John E. Kent
-- dilbert57@opencores.org
--
-- Copyright (C) 2011 John Kent
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
--===========================================================================--
--
-- Revision History:
--
--===========================================================================--
--
-- Version 0.1 - 30 April 2011 - John Kent
-- Initial version
--
library ieee;
use ieee.std_logic_1164.all;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use ieee.numeric_std.all;
library unisim;
use unisim.vcomponents.all;
 
Entity XuLA_clk is
generic(
FPGA_CLK_FREQ : integer := 12000000; -- HZ
CPU_CLK_FREQ : integer := 24000000; -- Hz
VDU_CLK_FREQ : integer := 24000000; -- Hz
RAM_CLK_FREQ : integer := 48000000 -- Hz
);
port(
fpga_clk : in std_logic; -- 12MHz FPGA Clock
cpu_clk : out std_logic; -- 24MHz CPU clock
vdu_clk : out std_logic; -- 24MHz VDU clock
ram_clk : out std_logic -- 48MHz RAM clock
);
end XuLA_clk;
 
Architecture RTL of XuLA_clk is
 
signal clk12_dcm : std_logic;
signal clk24_dcm : std_logic;
signal clk48_dcm : std_logic;
 
component BUFG
port (
I : in std_logic;
O : out std_logic
);
end component;
 
begin
DCM_XuLA_inst : DCM
generic map (
DLL_FREQUENCY_MODE => "LOW", -- "LOW" or "HIGH"
CLKIN_PERIOD => 84.0, -- in nsec
CLKFX_DIVIDE => 1,
CLKFX_MULTIPLY => 4,
CLKDV_DIVIDE => 2.0,
CLKIN_DIVIDE_BY_2 => FALSE,
CLKOUT_PHASE_SHIFT => "NONE",
CLK_FEEDBACK => "1X",
DESKEW_ADJUST => "SYSTEM_SYNCHRONOUS",
DFS_FREQUENCY_MODE => "LOW",
DUTY_CYCLE_CORRECTION => TRUE,
FACTORY_JF => X"8080",
PHASE_SHIFT => 0,
STARTUP_WAIT => FALSE)
port map (
CLKIN => fpga_clk, -- input 12MHz
CLKFB => clk12_dcm, -- feedback input
CLK0 => clk12_dcm, -- Feedback output (phase, freq = input)
CLK90 => open, -- Feedback output + 90deg
CLK180 => open, -- Feedback output + 180deg
CLK270 => open, -- Feedback output + 270deg
CLK2X => clk24_dcm, -- 2 x input Freq Output
CLK2X180 => open, -- 2 x input Freq Output + 180 deg
CLKDV => open, -- Fclkdv = Fclkin/CLKDV_DIVIDE
CLKFX => clk48_dcm, -- Fclkfx = Fclkin*CLKFX_MULIPLY/CLKFX_DIVIDE
CLKFX180 => open, -- CLKFX180 = CLKFX + 180 degrees
LOCKED => open, -- DCM in lock
PSDONE => open,
STATUS => open,
PSCLK => open, -- Clock input to dynamic phase shifter
PSEN => open,
PSINCDEC => open,
RST => '0'
);
 
bufram : BUFG port map(
I => clk48_dcm,
O => ram_clk
);
 
bufcpu : BUFG port map (
I => clk24_dcm,
O => cpu_clk
);
 
bufvdu : BUFG port map (
I => clk24_dcm,
O => vdu_clk
);
 
end RTL;
/xula_ioport.vhd
0,0 → 1,237
--===========================================================================--
-- --
-- xula_ioport.vhd - Synthesizable Dual Bidirectionsal I/O Port --
-- --
--===========================================================================--
--
-- File name : xula_ioport.vhd
--
-- Purpose : Implements a dual 8 bit bidirectional I/O port
-- modified for the XuLA implementation of System09
-- Port A supports a full 8 bit bidirectional port
-- Port B supports a 5 bit bidirectional port with 3 inputs
--
-- Dependencies : ieee.std_logic_1164
-- ieee.std_logic_unsigned
-- unisim.vcomponents
--
-- Author : John E. Kent
--
-- Email : dilbert57@opencores.org
--
-- Web : http://opencores.org/project,system09
--
-- xula_ioport.vhd is a dual bi-directional 8 bit I/O port written in VHDL.
--
-- address function
-- ======= ========
-- base+0 port a data register
-- bits 0 - 7 = i/o
-- base+1 port b data register
-- bits 0 - 4 = i/o
-- bits 5 - 7 - inputs
-- base+2 port a direction register
-- 0 => port a bit = input
-- 1 => port a bit = output
-- base+3 port b direction
-- For bits 0 to 4:
-- 0 => port b bit = input
-- 1 => port b bit = output
-- For bits 5 to 7:
-- 0 => port b bit = interrupt disable
-- 1 => port b bit = interrupt enable
-- interrupt inputs on port b bits 5 to 7 are active high
--
-- Copyright (C) 2002 - 2011 John Kent
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
--===========================================================================--
-- --
-- Revision History --
-- --
--===========================================================================--
--
-- Version Author Date Description
-- 0.1 John E. Kent 11 October 2002 Used a loop counter for
-- data direction & read port signals
-- 0.2 John E. Kent 5 September 2003 Reduced to 2 x 8 bit ports
-- 1.0 John E. Kent 6 September 2003 Changed Clock Edge
-- 1.1 John E. Kent 25 Februrary 2007 Modified sensitivity lists
-- 1.2 John E. Kent 30 May 2010 Updated Header, added unisim library
-- 2.0 John E. Kent 30 April 2011 modified for XuLA System09 I/O
--===========================================================================
--
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
--library unisim;
-- use unisim.vcomponents.all;
 
entity xula_ioport is
port (
clk : in std_logic;
rst : in std_logic;
cs : in std_logic;
rw : in std_logic;
addr : in std_logic_vector(1 downto 0);
data_in : in std_logic_vector(7 downto 0);
data_out : out std_logic_vector(7 downto 0);
porta_io : inout std_logic_vector(7 downto 0);
portb_io : inout std_logic_vector(4 downto 0);
portc_in : in std_logic_vector(7 downto 5);
irq : out std_logic
);
end;
 
architecture rtl of xula_ioport is
 
signal porta_ddr : std_logic_vector(7 downto 0);
signal portb_ddr : std_logic_vector(7 downto 0);
signal porta_data : std_logic_vector(7 downto 0);
signal portb_data : std_logic_vector(7 downto 0);
 
begin
 
 
--------------------------------
--
-- read I/O port
--
--------------------------------
 
ioport_read : process( addr,
porta_ddr, portb_ddr,
porta_data, portb_data,
porta_io, portb_io )
variable count : integer;
begin
case addr is
when "00" =>
for count in 0 to 7 loop
if porta_ddr(count) = '1' then
data_out(count) <= porta_data(count);
else
data_out(count) <= porta_io(count);
end if;
end loop;
 
when "01" =>
for count in 0 to 7 loop
if portb_ddr(count) = '1' then
data_out(count) <= portb_data(count);
else
if count < 5 then
data_out(count) <= portb_io(count);
else
data_out(count) <= portc_in(count);
end if;
end if;
end loop;
 
when "10" =>
data_out <= porta_ddr;
when "11" =>
data_out <= portb_ddr;
when others =>
null;
end case;
 
end process;
 
---------------------------------
--
-- Write I/O ports
--
---------------------------------
 
ioport_write : process( clk, rst, addr, cs, rw, data_in,
porta_data, portb_data,
porta_ddr, portb_ddr )
begin
if clk'event and clk = '0' then
if rst = '1' then
porta_data <= (others=>'0');
portb_data <= (others=>'0');
porta_ddr <= (others=>'0');
portb_ddr <= (others=>'0');
else
if cs = '1' and rw = '0' then
case addr is
when "00" =>
porta_data <= data_in;
when "01" =>
portb_data <= data_in;
when "10" =>
porta_ddr <= data_in;
when "11" =>
portb_ddr <= data_in;
when others =>
null;
end case;
end if;
end if;
end if;
end process;
 
---------------------------------
--
-- direction control port a
--
---------------------------------
porta_direction : process ( porta_data, porta_ddr )
variable count : integer;
begin
for count in 0 to 7 loop
if porta_ddr(count) = '1' then
porta_io(count) <= porta_data(count);
else
porta_io(count) <= 'Z';
end if;
end loop;
end process;
---------------------------------
--
-- direction control port b
--
---------------------------------
portb_direction : process ( portb_data, portb_ddr, portb_io )
variable count : integer;
variable irq_temp : std_logic;
begin
--
-- For bit 0 to 4 DDR determines the direction of the port
--
for count in 0 to 4 loop
if portb_ddr(count) = '1' then
portb_io(count) <= portb_data(count);
else
portb_io(count) <= 'Z';
end if;
end loop;
 
--
-- For bit 5 to 7 DDR is an interrupt enable
--
irq_temp := '0';
for count in 5 to 7 loop
irq_temp := (portc_in(count) AND portb_ddr(count)) OR irq_temp;
end loop;
irq <= irq_temp;
end process;
---------------------------------
 
end rtl;
/datram.vhd
36,20 → 36,20
-- Reg Val Addr Addr
-- fff0 - 0f - page 0 - $0xxx = $00xxx (RAM)
-- fff1 - 0e - page 1 - $1xxx = $01xxx (RAM)
-- fff2 - 0d - page 0 - $2xxx = $02xxx (RAM)
-- fff3 - 0c - page 0 - $3xxx = $03xxx (RAM)
-- fff4 - 0b - page 0 - $4xxx = $04xxx (RAM)
-- fff5 - 0a - page 0 - $5xxx = $05xxx (RAM)
-- fff6 - 09 - page 0 - $6xxx = $06xxx (RAM)
-- fff7 - 08 - page 0 - $7xxx = $07xxx (RAM)
-- fff8 - 07 - page 0 - $8xxx = $08xxx (RAM)
-- fff9 - 06 - page 0 - $9xxx = $09xxx (RAM)
-- fffa - 05 - page 0 - $axxx = $0axxx (RAM)
-- fffb - 04 - page 0 - $bxxx = $0bxxx (RAM)
-- fffc - 03 - page 0 - $cxxx = $0cxxx (RAM)
-- fffd - 02 - page 0 - $dxxx = $0dxxx (RAM)
-- fffe - f1 - page 0 - $exxx = $fexxx (I/O)
-- ffff - f0 - page 0 - $fxxx = $ffxxx (ROM/DMFA2)
-- fff2 - 0d - page 2 - $2xxx = $02xxx (RAM)
-- fff3 - 0c - page 3 - $3xxx = $03xxx (RAM)
-- fff4 - 0b - page 4 - $4xxx = $04xxx (RAM)
-- fff5 - 0a - page 5 - $5xxx = $05xxx (RAM)
-- fff6 - 09 - page 6 - $6xxx = $06xxx (RAM)
-- fff7 - 08 - page 7 - $7xxx = $07xxx (RAM)
-- fff8 - 07 - page 8 - $8xxx = $08xxx (RAM)
-- fff9 - 06 - page 9 - $9xxx = $09xxx (RAM)
-- fffa - 05 - page A - $axxx = $0axxx (RAM)
-- fffb - 04 - page B - $bxxx = $0bxxx (RAM)
-- fffc - 03 - page C - $cxxx = $0cxxx (RAM)
-- fffd - 02 - page D - $dxxx = $0dxxx (RAM)
-- fffe - f1 - page E - $exxx = $fexxx (I/O)
-- ffff - f0 - page F - $fxxx = $ffxxx (ROM/DMFA2)
--
-- Copyright (C) 2003 - 2010 John Kent
--
82,7 → 82,9
-- 0.3 2007-02-25 John Kent Modify the sensitivity lists
--
-- 0.4 2010-06-17 John Kent Update header and added GPL
--
--
-- 0.5 2010-12-10 John Kent Correction of pages in header documentation
--
 
library ieee;
use ieee.std_logic_1164.all;
/xula_iobus.vhd
0,0 → 1,237
--===========================================================================--
-- --
-- xula_iobus.vhd - Synthesizable Dual Bidirectionsal I/O Port --
-- --
--===========================================================================--
--
-- File name : xula_ioport.vhd
--
-- Purpose : Implements a dual 8 bit bidirectional I/O port
-- modified for the XuLA implementation of System09
-- Port A supports a full 8 bit bidirectional port
-- Port B supports a 5 bit bidirectional port with 3 inputs
--
-- Dependencies : ieee.std_logic_1164
-- ieee.std_logic_unsigned
-- unisim.vcomponents
--
-- Author : John E. Kent
--
-- Email : dilbert57@opencores.org
--
-- Web : http://opencores.org/project,system09
--
-- xula_ioport.vhd is a dual bi-directional 8 bit I/O port written in VHDL.
--
-- address function
-- ======= ========
-- base+0 port a data register
-- bits 0 - 7 = i/o
-- base+1 port b data register
-- bits 0 - 4 = i/o
-- bits 5 - 7 - inputs
-- base+2 port a direction register
-- 0 => port a bit = input
-- 1 => port a bit = output
-- base+3 port b direction
-- For bits 0 to 4:
-- 0 => port b bit = input
-- 1 => port b bit = output
-- For bits 5 to 7:
-- 0 => port b bit = interrupt disable
-- 1 => port b bit = interrupt enable
-- interrupt inputs on port b bits 5 to 7 are active high
--
-- Copyright (C) 2002 - 2011 John Kent
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
--===========================================================================--
-- --
-- Revision History --
-- --
--===========================================================================--
--
-- Version Author Date Description
-- 0.1 John E. Kent 11 October 2002 Used a loop counter for
-- data direction & read port signals
-- 0.2 John E. Kent 5 September 2003 Reduced to 2 x 8 bit ports
-- 1.0 John E. Kent 6 September 2003 Changed Clock Edge
-- 1.1 John E. Kent 25 Februrary 2007 Modified sensitivity lists
-- 1.2 John E. Kent 30 May 2010 Updated Header, added unisim library
-- 2.0 John E. Kent 30 April 2011 modified for XuLA System09 I/O
--===========================================================================
--
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
--library unisim;
-- use unisim.vcomponents.all;
 
entity xula_ioport is
port (
clk : in std_logic;
rst : in std_logic;
cs : in std_logic;
rw : in std_logic;
addr : in std_logic_vector(1 downto 0);
data_in : in std_logic_vector(7 downto 0);
data_out : out std_logic_vector(7 downto 0);
porta_io : inout std_logic_vector(7 downto 0);
portb_io : inout std_logic_vector(4 downto 0);
portc_in : in std_logic_vector(7 downto 5);
irq : out std_logic
);
end;
 
architecture rtl of xula_ioport is
 
signal porta_ddr : std_logic_vector(7 downto 0);
signal portb_ddr : std_logic_vector(7 downto 0);
signal porta_data : std_logic_vector(7 downto 0);
signal portb_data : std_logic_vector(7 downto 0);
 
begin
 
 
--------------------------------
--
-- read I/O port
--
--------------------------------
 
ioport_read : process( addr,
porta_ddr, portb_ddr,
porta_data, portb_data,
porta_io, portb_io )
variable count : integer;
begin
case addr is
when "00" =>
for count in 0 to 7 loop
if porta_ddr(count) = '1' then
data_out(count) <= porta_data(count);
else
data_out(count) <= porta_io(count);
end if;
end loop;
 
when "01" =>
for count in 0 to 7 loop
if portb_ddr(count) = '1' then
data_out(count) <= portb_data(count);
else
if count < 5 then
data_out(count) <= portb_io(count);
else
data_out(count) <= portc_in(count);
end if;
end if;
end loop;
 
when "10" =>
data_out <= porta_ddr;
when "11" =>
data_out <= portb_ddr;
when others =>
null;
end case;
 
end process;
 
---------------------------------
--
-- Write I/O ports
--
---------------------------------
 
ioport_write : process( clk, rst, addr, cs, rw, data_in,
porta_data, portb_data,
porta_ddr, portb_ddr )
begin
if clk'event and clk = '0' then
if rst = '1' then
porta_data <= (others=>'0');
portb_data <= (others=>'0');
porta_ddr <= (others=>'0');
portb_ddr <= (others=>'0');
else
if cs = '1' and rw = '0' then
case addr is
when "00" =>
porta_data <= data_in;
when "01" =>
portb_data <= data_in;
when "10" =>
porta_ddr <= data_in;
when "11" =>
portb_ddr <= data_in;
when others =>
null;
end case;
end if;
end if;
end if;
end process;
 
---------------------------------
--
-- direction control port a
--
---------------------------------
porta_direction : process ( porta_data, porta_ddr )
variable count : integer;
begin
for count in 0 to 7 loop
if porta_ddr(count) = '1' then
porta_io(count) <= porta_data(count);
else
porta_io(count) <= 'Z';
end if;
end loop;
end process;
---------------------------------
--
-- direction control port b
--
---------------------------------
portb_direction : process ( portb_data, portb_ddr, portb_io )
variable count : integer;
variable irq_temp : std_logic;
begin
--
-- For bit 0 to 4 DDR determines the direction of the port
--
for count in 0 to 4 loop
if portb_ddr(count) = '1' then
portb_io(count) <= portb_data(count);
else
portb_io(count) <= 'Z';
end if;
end loop;
 
--
-- For bit 5 to 7 DDR is an interrupt enable
--
irq_temp := '0';
for count in 5 to 7 loop
irq_temp := (portc_in(count) AND portb_ddr(count)) OR irq_temp;
end loop;
irq <= irq_temp;
end process;
---------------------------------
 
end rtl;
/cpu09l.vhd
0,0 → 1,5744
--===========================================================================--
-- --
-- Synthesizable 6809 instruction compatible VHDL CPU core --
-- --
--===========================================================================--
--
-- File name : cpu09l.vhd
--
-- Entity name : cpu09
--
-- Purpose : 6809 instruction compatible CPU core written in VHDL
-- with Last Instruction Cycle, bus available, bus status,
-- and instruction fetch signals.
-- Not cycle compatible with the original 6809 CPU
--
-- Dependencies : ieee.std_logic_1164
-- ieee.std_logic_unsigned
--
-- Author : John E. Kent
--
-- Email : dilbert57@opencores.org
--
-- Web : http://opencores.org/project,system09
--
-- Description : VMA (valid memory address) is hight whenever a valid memory
-- access is made by an instruction fetch, interrupt vector fetch
-- or a data read or write otherwise it is low indicating an idle
-- bus cycle.
-- IFETCH (instruction fetch output) is high whenever an
-- instruction byte is read i.e. the program counter is applied
-- to the address bus.
-- LIC (last instruction cycle output) is normally low
-- but goes high on the last cycle of an instruction.
-- BA (bus available output) is normally low but goes high while
-- waiting in a Sync instruction state or the CPU is halted
-- i.e. a DMA grant.
-- BS (bus status output) is normally low but goes high during an
-- interrupt or reset vector fetch or the processor is halted
-- i.e. a DMA grant.
--
-- Copyright (C) 2003 - 2010 John Kent
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
--===========================================================================--
-- --
-- Revision History --
-- --
--===========================================================================--
--
-- Version 0.1 - 26 June 2003 - John Kent
-- Added extra level in state stack
-- fixed some calls to the extended addressing state
--
-- Version 0.2 - 5 Sept 2003 - John Kent
-- Fixed 16 bit indexed offset (was doing read rather than fetch)
-- Added/Fixed STY and STS instructions.
-- ORCC_STATE ANDed CC state rather than ORed it - Now fixed
-- CMPX Loaded ACCA and ACCB - Now fixed
--
-- Version 1.0 - 6 Sep 2003 - John Kent
-- Initial release to Open Cores
-- reversed clock edge
--
-- Version 1.1 - 29 November 2003 John kent
-- ACCA and ACCB indexed offsets are 2's complement.
-- ALU Right Mux now sign extends ACCA & ACCB offsets
-- Absolute Indirect addressing performed a read on the
-- second byte of the address rather than a fetch
-- so it formed an incorrect address. Now fixed.
--
-- Version 1.2 - 29 November 2003 John Kent
-- LEAX and LEAY affect the Z bit only
-- LEAS and LEAU do not affect any condition codes
-- added an extra ALU control for LEA.
--
-- Version 1.3 - 12 December 2003 John Kent
-- CWAI did not work, was missed a PUSH_ST on calling
-- the ANDCC_STATE. Thanks go to Ghassan Kraidy for
-- finding this fault.
--
-- Version 1.4 - 12 December 2003 John Kent
-- Missing cc_ctrl assignment in otherwise case of
-- lea_state resulted in cc_ctrl being latched in
-- that state.
-- The otherwise statement should never be reached,
-- and has been fixed simply to resolve synthesis warnings.
--
-- Version 1.5 - 17 january 2004 John kent
-- The clear instruction used "alu_ld8" to control the ALU
-- rather than "alu_clr". This mean the Carry was not being
-- cleared correctly.
--
-- Version 1.6 - 24 January 2004 John Kent
-- Fixed problems in PSHU instruction
--
-- Version 1.7 - 25 January 2004 John Kent
-- removed redundant "alu_inx" and "alu_dex'
-- Removed "test_alu" and "test_cc"
-- STD instruction did not set condition codes
-- JMP direct was not decoded properly
-- CLR direct performed an unwanted read cycle
-- Bogus "latch_md" in Page2 indexed addressing
--
-- Version 1.8 - 27 January 2004 John Kent
-- CWAI in decode1_state should increment the PC.
-- ABX is supposed to be an unsigned addition.
-- Added extra ALU function
-- ASR8 slightly changed in the ALU.
--
-- Version 1.9 - 20 August 2005
-- LSR8 is now handled in ASR8 and ROR8 case in the ALU,
-- rather than LSR16. There was a problem with single
-- operand instructions using the MD register which is
-- sign extended on the first 8 bit fetch.
--
-- Version 1.10 - 13 September 2005
-- TFR & EXG instructions did not work for the Condition Code Register
-- An extra case has been added to the ALU for the alu_tfr control
-- to assign the left ALU input (alu_left) to the condition code
-- outputs (cc_out).
--
-- Version 1.11 - 16 September 2005
-- JSR ,X should not predecrement S before calculating the jump address.
-- The reason is that JSR [0,S] needs S to point to the top of the stack
-- to fetch a valid vector address. The solution is to have the addressing
-- mode microcode called before decrementing S and then decrementing S in
-- JSR_STATE. JSR_STATE in turn calls PUSH_RETURN_LO_STATE rather than
-- PUSH_RETURN_HI_STATE so that both the High & Low halves of the PC are
-- pushed on the stack. This adds one extra bus cycle, but resolves the
-- addressing conflict. I've also removed the pre-decement S in
-- JSR EXTENDED as it also calls JSR_STATE.
--
-- Version 1.12 - 6th June 2006
-- 6809 Programming reference manual says V is not affected by ASR, LSR and ROR
-- This is different to the 6800. CLR should reset the V bit.
--
-- Version 1.13 - 7th July 2006
-- Disable NMI on reset until S Stack pointer has been loaded.
-- Added nmi_enable signal in sp_reg process and nmi_handler process.
--
-- Version 1.14 - 11th July 2006
-- 1. Added new state to RTI called rti_entire_state.
-- This state tests the CC register after it has been loaded
-- from the stack. Previously the current CC was tested which
-- was incorrect. The Entire Flag should be set before the
-- interrupt stacks the CC.
-- 2. On bogus Interrupts, int_cc_state went to rti_state,
-- which was an enumerated state, but not defined anywhere.
-- rti_state has been changed to rti_cc_state so that bogus interrupt
-- will perform an RTI after entering that state.
-- 3. Sync should generate an interrupt if the interrupt masks
-- are cleared. If the interrupt masks are set, then an interrupt
-- will cause the the PC to advance to the next instruction.
-- Note that I don't wait for an interrupt to be asserted for
-- three clock cycles.
-- 4. Added new ALU control state "alu_mul". "alu_mul" is used in
-- the Multiply instruction replacing "alu_add16". This is similar
-- to "alu_add16" except it sets the Carry bit to B7 of the result
-- in ACCB, sets the Zero bit if the 16 bit result is zero, but
-- does not affect The Half carry (H), Negative (N) or Overflow (V)
-- flags. The logic was re-arranged so that it adds md or zero so
-- that the Carry condition code is set on zero multiplicands.
-- 5. DAA (Decimal Adjust Accumulator) should set the Negative (N)
-- and Zero Flags. It will also affect the Overflow (V) flag although
-- the operation is undefined. It's anyones guess what DAA does to V.
--
-- Version 1.15 - 25th Feb 2007 - John Kent
-- line 9672 changed "if Halt <= '1' then" to "if Halt = '1' then"
-- Changed sensitivity lists.
--
-- Version 1.16 - 5th February 2008 - John Kent
-- FIRQ interrupts should take priority over IRQ Interrupts.
-- This presumably means they should be tested for before IRQ
-- when they happen concurrently.
--
-- Version 1.17 - 18th February 2008 - John Kent
-- NMI in CWAI should mask IRQ and FIRQ interrupts
--
-- Version 1.18 - 21st February 2008 - John Kent
-- Removed default register settings in each case statement
-- and placed them at the beginning of the state sequencer.
-- Modified the SYNC instruction so that the interrupt vector(iv)
-- is not set unless an unmasked FIRQ or IRQ is received.
--
-- Version 1.19 - 25th February 2008 - John Kent
-- Enumerated separate states for FIRQ/FAST and NMIIRQ/ENTIRE
-- Enumerated separate states for MASKI and MASKIF states
-- Removed code on BSR/JSR in fetch cycle
--
-- Version 1.10 - 8th October 2011 - John Kent
-- added fetch output which should go high during the fetch cycle
--
-- Version 1.11 - 8th October 2011 - John Kent
-- added Last Instruction Cycle signal
-- replaced fetch with ifetch (instruction fetch) signal
-- added ba & bs (bus available & bus status) signals
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
 
entity cpu09 is
port (
clk : in std_logic; -- E clock input (falling edge)
rst : in std_logic; -- reset input (active high)
vma : out std_logic; -- valid memory address (active high)
lic : out std_logic; -- last instruction cycle (active high)
ifetch : out std_logic; -- instruction fetch cycle (active high)
ba : out std_logic; -- bus available (high on sync wait or DMA grant)
bs : out std_logic; -- bus status (high on interrupt or reset vector fetch or DMA grant)
addr : out std_logic_vector(15 downto 0); -- address bus output
rw : out std_logic; -- read not write output
data_out : out std_logic_vector(7 downto 0); -- data bus output
data_in : in std_logic_vector(7 downto 0); -- data bus input
irq : in std_logic; -- interrupt request input (active high)
firq : in std_logic; -- fast interrupt request input (active high)
nmi : in std_logic; -- non maskable interrupt request input (active high)
halt : in std_logic; -- halt input (active high) grants DMA
hold : in std_logic -- hold input (active high) extend bus cycle
);
end cpu09;
 
architecture rtl of cpu09 is
 
constant EBIT : integer := 7;
constant FBIT : integer := 6;
constant HBIT : integer := 5;
constant IBIT : integer := 4;
constant NBIT : integer := 3;
constant ZBIT : integer := 2;
constant VBIT : integer := 1;
constant CBIT : integer := 0;
 
--
-- Interrupt vector modifiers
--
constant RST_VEC : std_logic_vector(2 downto 0) := "111";
constant NMI_VEC : std_logic_vector(2 downto 0) := "110";
constant SWI_VEC : std_logic_vector(2 downto 0) := "101";
constant IRQ_VEC : std_logic_vector(2 downto 0) := "100";
constant FIRQ_VEC : std_logic_vector(2 downto 0) := "011";
constant SWI2_VEC : std_logic_vector(2 downto 0) := "010";
constant SWI3_VEC : std_logic_vector(2 downto 0) := "001";
constant RESV_VEC : std_logic_vector(2 downto 0) := "000";
 
type state_type is (-- Start off in Reset
reset_state,
-- Fetch Interrupt Vectors (including reset)
vect_lo_state, vect_hi_state,
-- Fetch Instruction Cycle
fetch_state,
-- Decode Instruction Cycles
decode1_state, decode2_state, decode3_state,
-- Calculate Effective Address
imm16_state,
indexed_state, index8_state, index16_state, index16_2_state,
pcrel8_state, pcrel16_state, pcrel16_2_state,
indexaddr_state, indexaddr2_state,
postincr1_state, postincr2_state,
indirect_state, indirect2_state, indirect3_state,
extended_state,
-- single ops
single_op_read_state,
single_op_exec_state,
single_op_write_state,
-- Dual op states
dual_op_read8_state, dual_op_read16_state, dual_op_read16_2_state,
dual_op_write8_state, dual_op_write16_state,
--
sync_state, halt_state, error_state,
--
andcc_state, orcc_state,
tfr_state, exg_state, exg1_state,
lea_state,
-- Multiplication
mul_state, mulea_state, muld_state,
mul0_state, mul1_state, mul2_state, mul3_state,
mul4_state, mul5_state, mul6_state, mul7_state,
-- Branches
lbranch_state, sbranch_state,
-- Jumps, Subroutine Calls and Returns
jsr_state, jmp_state,
push_return_hi_state, push_return_lo_state,
pull_return_hi_state, pull_return_lo_state,
-- Interrupt cycles
int_nmiirq_state, int_firq_state,
int_entire_state, int_fast_state,
int_pcl_state, int_pch_state,
int_upl_state, int_uph_state,
int_iyl_state, int_iyh_state,
int_ixl_state, int_ixh_state,
int_dp_state,
int_accb_state, int_acca_state,
int_cc_state,
int_cwai_state,
int_maski_state, int_maskif_state,
-- Return From Interrupt
rti_cc_state, rti_entire_state,
rti_acca_state, rti_accb_state,
rti_dp_state,
rti_ixl_state, rti_ixh_state,
rti_iyl_state, rti_iyh_state,
rti_upl_state, rti_uph_state,
rti_pcl_state, rti_pch_state,
-- Push Registers using SP
pshs_state,
pshs_pcl_state, pshs_pch_state,
pshs_upl_state, pshs_uph_state,
pshs_iyl_state, pshs_iyh_state,
pshs_ixl_state, pshs_ixh_state,
pshs_dp_state,
pshs_acca_state, pshs_accb_state,
pshs_cc_state,
-- Pull Registers using SP
puls_state,
puls_cc_state,
puls_acca_state, puls_accb_state,
puls_dp_state,
puls_ixl_state, puls_ixh_state,
puls_iyl_state, puls_iyh_state,
puls_upl_state, puls_uph_state,
puls_pcl_state, puls_pch_state,
-- Push Registers using UP
pshu_state,
pshu_pcl_state, pshu_pch_state,
pshu_spl_state, pshu_sph_state,
pshu_iyl_state, pshu_iyh_state,
pshu_ixl_state, pshu_ixh_state,
pshu_dp_state,
pshu_acca_state, pshu_accb_state,
pshu_cc_state,
-- Pull Registers using UP
pulu_state,
pulu_cc_state,
pulu_acca_state, pulu_accb_state,
pulu_dp_state,
pulu_ixl_state, pulu_ixh_state,
pulu_iyl_state, pulu_iyh_state,
pulu_spl_state, pulu_sph_state,
pulu_pcl_state, pulu_pch_state );
 
type stack_type is array(2 downto 0) of state_type;
type st_type is (idle_st, push_st, pull_st );
type addr_type is (idle_ad, fetch_ad, read_ad, write_ad, pushu_ad, pullu_ad, pushs_ad, pulls_ad, int_hi_ad, int_lo_ad );
type dout_type is (cc_dout, acca_dout, accb_dout, dp_dout,
ix_lo_dout, ix_hi_dout, iy_lo_dout, iy_hi_dout,
up_lo_dout, up_hi_dout, sp_lo_dout, sp_hi_dout,
pc_lo_dout, pc_hi_dout, md_lo_dout, md_hi_dout );
type op_type is (reset_op, fetch_op, latch_op );
type pre_type is (reset_pre, fetch_pre, latch_pre );
type cc_type is (reset_cc, load_cc, pull_cc, latch_cc );
type acca_type is (reset_acca, load_acca, load_hi_acca, pull_acca, latch_acca );
type accb_type is (reset_accb, load_accb, pull_accb, latch_accb );
type dp_type is (reset_dp, load_dp, pull_dp, latch_dp );
type ix_type is (reset_ix, load_ix, pull_lo_ix, pull_hi_ix, latch_ix );
type iy_type is (reset_iy, load_iy, pull_lo_iy, pull_hi_iy, latch_iy );
type sp_type is (reset_sp, latch_sp, load_sp, pull_hi_sp, pull_lo_sp );
type up_type is (reset_up, latch_up, load_up, pull_hi_up, pull_lo_up );
type pc_type is (reset_pc, latch_pc, load_pc, pull_lo_pc, pull_hi_pc, incr_pc );
type md_type is (reset_md, latch_md, load_md, fetch_first_md, fetch_next_md, shiftl_md );
type ea_type is (reset_ea, latch_ea, load_ea, fetch_first_ea, fetch_next_ea );
type iv_type is (latch_iv, reset_iv, nmi_iv, irq_iv, firq_iv, swi_iv, swi2_iv, swi3_iv, resv_iv);
type nmi_type is (reset_nmi, set_nmi, latch_nmi );
type left_type is (cc_left, acca_left, accb_left, dp_left,
ix_left, iy_left, up_left, sp_left,
accd_left, md_left, pc_left, ea_left );
type right_type is (ea_right, zero_right, one_right, two_right,
acca_right, accb_right, accd_right,
md_right, md_sign5_right, md_sign8_right );
type alu_type is (alu_add8, alu_sub8, alu_add16, alu_sub16, alu_adc, alu_sbc,
alu_and, alu_ora, alu_eor,
alu_tst, alu_inc, alu_dec, alu_clr, alu_neg, alu_com,
alu_lsr16, alu_lsl16,
alu_ror8, alu_rol8, alu_mul,
alu_asr8, alu_asl8, alu_lsr8,
alu_andcc, alu_orcc, alu_sex, alu_tfr, alu_abx,
alu_seif, alu_sei, alu_see, alu_cle,
alu_ld8, alu_st8, alu_ld16, alu_st16, alu_lea, alu_nop, alu_daa );
 
signal op_code: std_logic_vector(7 downto 0);
signal pre_code: std_logic_vector(7 downto 0);
signal acca: std_logic_vector(7 downto 0);
signal accb: std_logic_vector(7 downto 0);
signal cc: std_logic_vector(7 downto 0);
signal cc_out: std_logic_vector(7 downto 0);
signal dp: std_logic_vector(7 downto 0);
signal xreg: std_logic_vector(15 downto 0);
signal yreg: std_logic_vector(15 downto 0);
signal sp: std_logic_vector(15 downto 0);
signal up: std_logic_vector(15 downto 0);
signal ea: std_logic_vector(15 downto 0);
signal pc: std_logic_vector(15 downto 0);
signal md: std_logic_vector(15 downto 0);
signal left: std_logic_vector(15 downto 0);
signal right: std_logic_vector(15 downto 0);
signal out_alu: std_logic_vector(15 downto 0);
signal iv: std_logic_vector(2 downto 0);
signal nmi_req: std_logic;
signal nmi_ack: std_logic;
signal nmi_enable: std_logic;
 
signal state: state_type;
signal next_state: state_type;
signal saved_state: state_type;
signal return_state: state_type;
signal state_stack: stack_type;
signal st_ctrl: st_type;
signal pc_ctrl: pc_type;
signal ea_ctrl: ea_type;
signal op_ctrl: op_type;
signal pre_ctrl: pre_type;
signal md_ctrl: md_type;
signal acca_ctrl: acca_type;
signal accb_ctrl: accb_type;
signal ix_ctrl: ix_type;
signal iy_ctrl: iy_type;
signal cc_ctrl: cc_type;
signal dp_ctrl: dp_type;
signal sp_ctrl: sp_type;
signal up_ctrl: up_type;
signal iv_ctrl: iv_type;
signal left_ctrl: left_type;
signal right_ctrl: right_type;
signal alu_ctrl: alu_type;
signal addr_ctrl: addr_type;
signal dout_ctrl: dout_type;
signal nmi_ctrl: nmi_type;
 
 
begin
 
----------------------------------
--
-- State machine stack
--
----------------------------------
--state_stack_proc: process( clk, hold, state_stack, st_ctrl,
-- return_state, fetch_state )
state_stack_proc: process( clk, state_stack )
begin
if clk'event and clk = '0' then
if hold= '1' then
state_stack(0) <= state_stack(0);
state_stack(1) <= state_stack(1);
state_stack(2) <= state_stack(2);
else
case st_ctrl is
when idle_st =>
state_stack(0) <= state_stack(0);
state_stack(1) <= state_stack(1);
state_stack(2) <= state_stack(2);
when push_st =>
state_stack(0) <= return_state;
state_stack(1) <= state_stack(0);
state_stack(2) <= state_stack(1);
when pull_st =>
state_stack(0) <= state_stack(1);
state_stack(1) <= state_stack(2);
state_stack(2) <= fetch_state;
when others =>
state_stack(0) <= state_stack(0);
state_stack(1) <= state_stack(1);
state_stack(2) <= state_stack(2);
end case;
end if;
end if;
saved_state <= state_stack(0);
end process;
 
----------------------------------
--
-- Program Counter Control
--
----------------------------------
 
--pc_reg: process( clk, pc_ctrl, hold, pc, out_alu, data_in )
pc_reg: process( clk )
begin
if clk'event and clk = '0' then
if hold= '1' then
pc <= pc;
else
case pc_ctrl is
when reset_pc =>
pc <= "0000000000000000";
when load_pc =>
pc <= out_alu(15 downto 0);
when pull_lo_pc =>
pc(7 downto 0) <= data_in;
when pull_hi_pc =>
pc(15 downto 8) <= data_in;
when incr_pc =>
pc <= pc + 1;
when others =>
-- when latch_pc =>
pc <= pc;
end case;
end if;
end if;
end process;
 
----------------------------------
--
-- Effective Address Control
--
----------------------------------
 
--ea_reg: process( clk, ea_ctrl, hold, ea, out_alu, data_in, dp )
ea_reg: process( clk )
begin
 
if clk'event and clk = '0' then
if hold= '1' then
ea <= ea;
else
case ea_ctrl is
when reset_ea =>
ea <= "0000000000000000";
when fetch_first_ea =>
ea(7 downto 0) <= data_in;
ea(15 downto 8) <= dp;
when fetch_next_ea =>
ea(15 downto 8) <= ea(7 downto 0);
ea(7 downto 0) <= data_in;
when load_ea =>
ea <= out_alu(15 downto 0);
when others =>
-- when latch_ea =>
ea <= ea;
end case;
end if;
end if;
end process;
 
--------------------------------
--
-- Accumulator A
--
--------------------------------
--acca_reg : process( clk, acca_ctrl, hold, out_alu, acca, data_in )
acca_reg : process( clk )
begin
if clk'event and clk = '0' then
if hold= '1' then
acca <= acca;
else
case acca_ctrl is
when reset_acca =>
acca <= "00000000";
when load_acca =>
acca <= out_alu(7 downto 0);
when load_hi_acca =>
acca <= out_alu(15 downto 8);
when pull_acca =>
acca <= data_in;
when others =>
-- when latch_acca =>
acca <= acca;
end case;
end if;
end if;
end process;
 
--------------------------------
--
-- Accumulator B
--
--------------------------------
--accb_reg : process( clk, accb_ctrl, hold, out_alu, accb, data_in )
accb_reg : process( clk )
begin
if clk'event and clk = '0' then
if hold= '1' then
accb <= accb;
else
case accb_ctrl is
when reset_accb =>
accb <= "00000000";
when load_accb =>
accb <= out_alu(7 downto 0);
when pull_accb =>
accb <= data_in;
when others =>
-- when latch_accb =>
accb <= accb;
end case;
end if;
end if;
end process;
 
--------------------------------
--
-- X Index register
--
--------------------------------
--ix_reg : process( clk, ix_ctrl, hold, out_alu, xreg, data_in )
ix_reg : process( clk )
begin
if clk'event and clk = '0' then
if hold= '1' then
xreg <= xreg;
else
case ix_ctrl is
when reset_ix =>
xreg <= "0000000000000000";
when load_ix =>
xreg <= out_alu(15 downto 0);
when pull_hi_ix =>
xreg(15 downto 8) <= data_in;
when pull_lo_ix =>
xreg(7 downto 0) <= data_in;
when others =>
-- when latch_ix =>
xreg <= xreg;
end case;
end if;
end if;
end process;
 
--------------------------------
--
-- Y Index register
--
--------------------------------
--iy_reg : process( clk, iy_ctrl, hold, out_alu, yreg, data_in )
iy_reg : process( clk )
begin
if clk'event and clk = '0' then
if hold= '1' then
yreg <= yreg;
else
case iy_ctrl is
when reset_iy =>
yreg <= "0000000000000000";
when load_iy =>
yreg <= out_alu(15 downto 0);
when pull_hi_iy =>
yreg(15 downto 8) <= data_in;
when pull_lo_iy =>
yreg(7 downto 0) <= data_in;
when others =>
-- when latch_iy =>
yreg <= yreg;
end case;
end if;
end if;
end process;
 
--------------------------------
--
-- S stack pointer
--
--------------------------------
--sp_reg : process( clk, sp_ctrl, hold, sp, out_alu, data_in, nmi_enable )
sp_reg : process( clk )
begin
if clk'event and clk = '0' then
if hold= '1' then
sp <= sp;
nmi_enable <= nmi_enable;
else
case sp_ctrl is
when reset_sp =>
sp <= "0000000000000000";
nmi_enable <= '0';
when load_sp =>
sp <= out_alu(15 downto 0);
nmi_enable <= '1';
when pull_hi_sp =>
sp(15 downto 8) <= data_in;
nmi_enable <= nmi_enable;
when pull_lo_sp =>
sp(7 downto 0) <= data_in;
nmi_enable <= '1';
when others =>
-- when latch_sp =>
sp <= sp;
nmi_enable <= nmi_enable;
end case;
end if;
end if;
end process;
 
--------------------------------
--
-- U stack pointer
--
--------------------------------
--up_reg : process( clk, up_ctrl, hold, up, out_alu, data_in )
up_reg : process( clk )
begin
if clk'event and clk = '0' then
if hold= '1' then
up <= up;
else
case up_ctrl is
when reset_up =>
up <= "0000000000000000";
when load_up =>
up <= out_alu(15 downto 0);
when pull_hi_up =>
up(15 downto 8) <= data_in;
when pull_lo_up =>
up(7 downto 0) <= data_in;
when others =>
-- when latch_up =>
up <= up;
end case;
end if;
end if;
end process;
 
--------------------------------
--
-- Memory Data
--
--------------------------------
--md_reg : process( clk, md_ctrl, hold, out_alu, data_in, md )
md_reg : process( clk )
begin
if clk'event and clk = '0' then
if hold= '1' then
md <= md;
else
case md_ctrl is
when reset_md =>
md <= "0000000000000000";
when load_md =>
md <= out_alu(15 downto 0);
when fetch_first_md => -- sign extend md for branches
md(15 downto 8) <= data_in(7) & data_in(7) & data_in(7) & data_in(7) &
data_in(7) & data_in(7) & data_in(7) & data_in(7) ;
md(7 downto 0) <= data_in;
when fetch_next_md =>
md(15 downto 8) <= md(7 downto 0);
md(7 downto 0) <= data_in;
when shiftl_md =>
md(15 downto 1) <= md(14 downto 0);
md(0) <= '0';
when others =>
-- when latch_md =>
md <= md;
end case;
end if;
end if;
end process;
 
 
----------------------------------
--
-- Condition Codes
--
----------------------------------
 
--cc_reg: process( clk, cc_ctrl, hold, cc_out, cc, data_in )
cc_reg: process( clk )
begin
if clk'event and clk = '0' then
if hold= '1' then
cc <= cc;
else
case cc_ctrl is
when reset_cc =>
cc <= "11010000"; -- set EBIT, FBIT & IBIT
when load_cc =>
cc <= cc_out;
when pull_cc =>
cc <= data_in;
when others =>
-- when latch_cc =>
cc <= cc;
end case;
end if;
end if;
end process;
 
----------------------------------
--
-- Direct Page register
--
----------------------------------
 
--dp_reg: process( clk, dp_ctrl, hold, out_alu, dp, data_in )
dp_reg: process( clk )
begin
if clk'event and clk = '0' then
if hold= '1' then
dp <= dp;
else
case dp_ctrl is
when reset_dp =>
dp <= "00000000";
when load_dp =>
dp <= out_alu(7 downto 0);
when pull_dp =>
dp <= data_in;
when others =>
-- when latch_dp =>
dp <= dp;
end case;
end if;
end if;
end process;
 
----------------------------------
--
-- interrupt vector
--
----------------------------------
 
--iv_mux: process( clk, iv_ctrl, hold, iv )
iv_mux: process( clk )
begin
if clk'event and clk = '0' then
if hold= '1' then
iv <= iv;
else
case iv_ctrl is
when reset_iv =>
iv <= RST_VEC;
when nmi_iv =>
iv <= NMI_VEC;
when swi_iv =>
iv <= SWI_VEC;
when irq_iv =>
iv <= IRQ_VEC;
when firq_iv =>
iv <= FIRQ_VEC;
when swi2_iv =>
iv <= SWI2_VEC;
when swi3_iv =>
iv <= SWI3_VEC;
when resv_iv =>
iv <= RESV_VEC;
when others =>
iv <= iv;
end case;
end if;
end if;
end process;
 
 
----------------------------------
--
-- op code register
--
----------------------------------
 
--op_reg: process( clk, op_ctrl, hold, op_code, data_in )
op_reg: process( clk )
begin
if clk'event and clk = '0' then
if hold= '1' then
op_code <= op_code;
else
case op_ctrl is
when reset_op =>
op_code <= "00010010";
when fetch_op =>
op_code <= data_in;
when others =>
-- when latch_op =>
op_code <= op_code;
end case;
end if;
end if;
end process;
 
 
----------------------------------
--
-- pre byte op code register
--
----------------------------------
 
--pre_reg: process( clk, pre_ctrl, hold, pre_code, data_in )
pre_reg: process( clk )
begin
if clk'event and clk = '0' then
if hold= '1' then
pre_code <= pre_code;
else
case pre_ctrl is
when reset_pre =>
pre_code <= "00000000";
when fetch_pre =>
pre_code <= data_in;
when others =>
-- when latch_pre =>
pre_code <= pre_code;
end case;
end if;
end if;
end process;
 
--------------------------------
--
-- state machine
--
--------------------------------
 
--change_state: process( clk, rst, state, hold, next_state )
change_state: process( clk )
begin
if clk'event and clk = '0' then
if rst = '1' then
state <= reset_state;
else
if hold = '1' then
state <= state;
else
state <= next_state;
end if;
end if;
end if;
end process;
-- output
------------------------------------
--
-- Nmi register
--
------------------------------------
 
--nmi_reg: process( clk, nmi_ctrl, hold, nmi_ack )
nmi_reg: process( clk )
begin
if clk'event and clk='0' then
if hold = '1' then
nmi_ack <= nmi_ack;
else
case nmi_ctrl is
when set_nmi =>
nmi_ack <= '1';
when reset_nmi =>
nmi_ack <= '0';
when others =>
-- when latch_nmi =>
nmi_ack <= nmi_ack;
end case;
end if;
end if;
end process;
 
------------------------------------
--
-- Detect Edge of NMI interrupt
--
------------------------------------
 
--nmi_handler : process( clk, rst, nmi, nmi_ack, nmi_req, nmi_enable )
nmi_handler : process( rst, clk )
begin
if rst='1' then
nmi_req <= '0';
elsif clk'event and clk='0' then
if (nmi='1') and (nmi_ack='0') and (nmi_enable='1') then
nmi_req <= '1';
else
if (nmi='0') and (nmi_ack='1') then
nmi_req <= '0';
end if;
end if;
end if;
end process;
 
 
----------------------------------
--
-- Address output multiplexer
--
----------------------------------
 
addr_mux: process( addr_ctrl, pc, ea, up, sp, iv )
begin
ifetch <= '0';
vma <= '1';
rw <= '1';
addr <= "1111111111111111";
case addr_ctrl is
when fetch_ad =>
addr <= pc;
ifetch <= '1';
when read_ad =>
addr <= ea;
when write_ad =>
addr <= ea;
rw <= '0';
when pushs_ad =>
addr <= sp;
rw <= '0';
when pulls_ad =>
addr <= sp;
when pushu_ad =>
addr <= up;
rw <= '0';
when pullu_ad =>
addr <= up;
when int_hi_ad =>
addr <= "111111111111" & iv & "0";
when int_lo_ad =>
addr <= "111111111111" & iv & "1";
when others =>
vma <= '0';
end case;
end process;
 
--------------------------------
--
-- Data Bus output
--
--------------------------------
dout_mux : process( dout_ctrl, md, acca, accb, dp, xreg, yreg, sp, up, pc, cc )
begin
case dout_ctrl is
when cc_dout => -- condition code register
data_out <= cc;
when acca_dout => -- accumulator a
data_out <= acca;
when accb_dout => -- accumulator b
data_out <= accb;
when dp_dout => -- direct page register
data_out <= dp;
when ix_lo_dout => -- X index reg
data_out <= xreg(7 downto 0);
when ix_hi_dout => -- X index reg
data_out <= xreg(15 downto 8);
when iy_lo_dout => -- Y index reg
data_out <= yreg(7 downto 0);
when iy_hi_dout => -- Y index reg
data_out <= yreg(15 downto 8);
when up_lo_dout => -- U stack pointer
data_out <= up(7 downto 0);
when up_hi_dout => -- U stack pointer
data_out <= up(15 downto 8);
when sp_lo_dout => -- S stack pointer
data_out <= sp(7 downto 0);
when sp_hi_dout => -- S stack pointer
data_out <= sp(15 downto 8);
when md_lo_dout => -- alu output
data_out <= md(7 downto 0);
when md_hi_dout => -- alu output
data_out <= md(15 downto 8);
when pc_lo_dout => -- low order pc
data_out <= pc(7 downto 0);
when pc_hi_dout => -- high order pc
data_out <= pc(15 downto 8);
when others =>
data_out <= "00000000";
end case;
end process;
 
----------------------------------
--
-- Left Mux
--
----------------------------------
 
left_mux: process( left_ctrl, acca, accb, cc, dp, xreg, yreg, up, sp, pc, ea, md )
begin
case left_ctrl is
when cc_left =>
left(15 downto 8) <= "00000000";
left(7 downto 0) <= cc;
when acca_left =>
left(15 downto 8) <= "00000000";
left(7 downto 0) <= acca;
when accb_left =>
left(15 downto 8) <= "00000000";
left(7 downto 0) <= accb;
when dp_left =>
left(15 downto 8) <= "00000000";
left(7 downto 0) <= dp;
when accd_left =>
left(15 downto 8) <= acca;
left(7 downto 0) <= accb;
when md_left =>
left <= md;
when ix_left =>
left <= xreg;
when iy_left =>
left <= yreg;
when sp_left =>
left <= sp;
when up_left =>
left <= up;
when pc_left =>
left <= pc;
when others =>
-- when ea_left =>
left <= ea;
end case;
end process;
 
----------------------------------
--
-- Right Mux
--
----------------------------------
 
right_mux: process( right_ctrl, md, acca, accb, ea )
begin
case right_ctrl is
when ea_right =>
right <= ea;
when zero_right =>
right <= "0000000000000000";
when one_right =>
right <= "0000000000000001";
when two_right =>
right <= "0000000000000010";
when acca_right =>
if acca(7) = '0' then
right <= "00000000" & acca(7 downto 0);
else
right <= "11111111" & acca(7 downto 0);
end if;
when accb_right =>
if accb(7) = '0' then
right <= "00000000" & accb(7 downto 0);
else
right <= "11111111" & accb(7 downto 0);
end if;
when accd_right =>
right <= acca & accb;
when md_sign5_right =>
if md(4) = '0' then
right <= "00000000000" & md(4 downto 0);
else
right <= "11111111111" & md(4 downto 0);
end if;
when md_sign8_right =>
if md(7) = '0' then
right <= "00000000" & md(7 downto 0);
else
right <= "11111111" & md(7 downto 0);
end if;
when others =>
-- when md_right =>
right <= md;
end case;
end process;
 
----------------------------------
--
-- Arithmetic Logic Unit
--
----------------------------------
 
alu: process( alu_ctrl, cc, left, right, out_alu, cc_out )
variable valid_lo, valid_hi : boolean;
variable carry_in : std_logic;
variable daa_reg : std_logic_vector(7 downto 0);
begin
 
case alu_ctrl is
when alu_adc | alu_sbc |
alu_rol8 | alu_ror8 =>
carry_in := cc(CBIT);
when alu_asr8 =>
carry_in := left(7);
when others =>
carry_in := '0';
end case;
 
valid_lo := left(3 downto 0) <= 9;
valid_hi := left(7 downto 4) <= 9;
 
if (cc(CBIT) = '0') then
if( cc(HBIT) = '1' ) then
if valid_hi then
daa_reg := "00000110";
else
daa_reg := "01100110";
end if;
else
if valid_lo then
if valid_hi then
daa_reg := "00000000";
else
daa_reg := "01100000";
end if;
else
if( left(7 downto 4) <= 8 ) then
daa_reg := "00000110";
else
daa_reg := "01100110";
end if;
end if;
end if;
else
if ( cc(HBIT) = '1' )then
daa_reg := "01100110";
else
if valid_lo then
daa_reg := "01100000";
else
daa_reg := "01100110";
end if;
end if;
end if;
 
case alu_ctrl is
when alu_add8 | alu_inc |
alu_add16 | alu_adc | alu_mul =>
out_alu <= left + right + ("000000000000000" & carry_in);
when alu_sub8 | alu_dec |
alu_sub16 | alu_sbc =>
out_alu <= left - right - ("000000000000000" & carry_in);
when alu_abx =>
out_alu <= left + ("00000000" & right(7 downto 0)) ;
when alu_and =>
out_alu <= left and right; -- and/bit
when alu_ora =>
out_alu <= left or right; -- or
when alu_eor =>
out_alu <= left xor right; -- eor/xor
when alu_lsl16 | alu_asl8 | alu_rol8 =>
out_alu <= left(14 downto 0) & carry_in; -- rol8/asl8/lsl16
when alu_lsr16 =>
out_alu <= carry_in & left(15 downto 1); -- lsr16
when alu_lsr8 | alu_asr8 | alu_ror8 =>
out_alu <= "00000000" & carry_in & left(7 downto 1); -- ror8/asr8/lsr8
when alu_neg =>
out_alu <= right - left; -- neg (right=0)
when alu_com =>
out_alu <= not left;
when alu_clr | alu_ld8 | alu_ld16 | alu_lea =>
out_alu <= right; -- clr, ld
when alu_st8 | alu_st16 | alu_andcc | alu_orcc | alu_tfr =>
out_alu <= left;
when alu_daa =>
out_alu <= left + ("00000000" & daa_reg);
when alu_sex =>
if left(7) = '0' then
out_alu <= "00000000" & left(7 downto 0);
else
out_alu <= "11111111" & left(7 downto 0);
end if;
when others =>
out_alu <= left; -- nop
end case;
 
--
-- carry bit
--
case alu_ctrl is
when alu_add8 | alu_adc =>
cc_out(CBIT) <= (left(7) and right(7)) or
(left(7) and not out_alu(7)) or
(right(7) and not out_alu(7));
when alu_sub8 | alu_sbc =>
cc_out(CBIT) <= ((not left(7)) and right(7)) or
((not left(7)) and out_alu(7)) or
(right(7) and out_alu(7));
when alu_add16 =>
cc_out(CBIT) <= (left(15) and right(15)) or
(left(15) and not out_alu(15)) or
(right(15) and not out_alu(15));
when alu_sub16 =>
cc_out(CBIT) <= ((not left(15)) and right(15)) or
((not left(15)) and out_alu(15)) or
(right(15) and out_alu(15));
when alu_ror8 | alu_lsr16 | alu_lsr8 | alu_asr8 =>
cc_out(CBIT) <= left(0);
when alu_rol8 | alu_asl8 =>
cc_out(CBIT) <= left(7);
when alu_lsl16 =>
cc_out(CBIT) <= left(15);
when alu_com =>
cc_out(CBIT) <= '1';
when alu_neg | alu_clr =>
cc_out(CBIT) <= out_alu(7) or out_alu(6) or out_alu(5) or out_alu(4) or
out_alu(3) or out_alu(2) or out_alu(1) or out_alu(0);
when alu_mul =>
cc_out(CBIT) <= out_alu(7);
when alu_daa =>
if ( daa_reg(7 downto 4) = "0110" ) then
cc_out(CBIT) <= '1';
else
cc_out(CBIT) <= '0';
end if;
when alu_andcc =>
cc_out(CBIT) <= left(CBIT) and cc(CBIT);
when alu_orcc =>
cc_out(CBIT) <= left(CBIT) or cc(CBIT);
when alu_tfr =>
cc_out(CBIT) <= left(CBIT);
when others =>
cc_out(CBIT) <= cc(CBIT);
end case;
--
-- Zero flag
--
case alu_ctrl is
when alu_add8 | alu_sub8 |
alu_adc | alu_sbc |
alu_and | alu_ora | alu_eor |
alu_inc | alu_dec |
alu_neg | alu_com | alu_clr |
alu_rol8 | alu_ror8 | alu_asr8 | alu_asl8 | alu_lsr8 |
alu_ld8 | alu_st8 | alu_sex | alu_daa =>
cc_out(ZBIT) <= not( out_alu(7) or out_alu(6) or out_alu(5) or out_alu(4) or
out_alu(3) or out_alu(2) or out_alu(1) or out_alu(0) );
when alu_add16 | alu_sub16 | alu_mul |
alu_lsl16 | alu_lsr16 |
alu_ld16 | alu_st16 | alu_lea =>
cc_out(ZBIT) <= not( out_alu(15) or out_alu(14) or out_alu(13) or out_alu(12) or
out_alu(11) or out_alu(10) or out_alu(9) or out_alu(8) or
out_alu(7) or out_alu(6) or out_alu(5) or out_alu(4) or
out_alu(3) or out_alu(2) or out_alu(1) or out_alu(0) );
when alu_andcc =>
cc_out(ZBIT) <= left(ZBIT) and cc(ZBIT);
when alu_orcc =>
cc_out(ZBIT) <= left(ZBIT) or cc(ZBIT);
when alu_tfr =>
cc_out(ZBIT) <= left(ZBIT);
when others =>
cc_out(ZBIT) <= cc(ZBIT);
end case;
 
--
-- negative flag
--
case alu_ctrl is
when alu_add8 | alu_sub8 |
alu_adc | alu_sbc |
alu_and | alu_ora | alu_eor |
alu_rol8 | alu_ror8 | alu_asr8 | alu_asl8 | alu_lsr8 |
alu_inc | alu_dec | alu_neg | alu_com | alu_clr |
alu_ld8 | alu_st8 | alu_sex | alu_daa =>
cc_out(NBIT) <= out_alu(7);
when alu_add16 | alu_sub16 |
alu_lsl16 | alu_lsr16 |
alu_ld16 | alu_st16 =>
cc_out(NBIT) <= out_alu(15);
when alu_andcc =>
cc_out(NBIT) <= left(NBIT) and cc(NBIT);
when alu_orcc =>
cc_out(NBIT) <= left(NBIT) or cc(NBIT);
when alu_tfr =>
cc_out(NBIT) <= left(NBIT);
when others =>
cc_out(NBIT) <= cc(NBIT);
end case;
 
--
-- Interrupt mask flag
--
case alu_ctrl is
when alu_andcc =>
cc_out(IBIT) <= left(IBIT) and cc(IBIT);
when alu_orcc =>
cc_out(IBIT) <= left(IBIT) or cc(IBIT);
when alu_tfr =>
cc_out(IBIT) <= left(IBIT);
when alu_seif | alu_sei =>
cc_out(IBIT) <= '1';
when others =>
cc_out(IBIT) <= cc(IBIT); -- interrupt mask
end case;
 
--
-- Half Carry flag
--
case alu_ctrl is
when alu_add8 | alu_adc =>
cc_out(HBIT) <= (left(3) and right(3)) or
(right(3) and not out_alu(3)) or
(left(3) and not out_alu(3));
when alu_andcc =>
cc_out(HBIT) <= left(HBIT) and cc(HBIT);
when alu_orcc =>
cc_out(HBIT) <= left(HBIT) or cc(HBIT);
when alu_tfr =>
cc_out(HBIT) <= left(HBIT);
when others =>
cc_out(HBIT) <= cc(HBIT);
end case;
 
--
-- Overflow flag
--
case alu_ctrl is
when alu_add8 | alu_adc =>
cc_out(VBIT) <= (left(7) and right(7) and (not out_alu(7))) or
((not left(7)) and (not right(7)) and out_alu(7));
when alu_sub8 | alu_sbc =>
cc_out(VBIT) <= (left(7) and (not right(7)) and (not out_alu(7))) or
((not left(7)) and right(7) and out_alu(7));
when alu_add16 =>
cc_out(VBIT) <= (left(15) and right(15) and (not out_alu(15))) or
((not left(15)) and (not right(15)) and out_alu(15));
when alu_sub16 =>
cc_out(VBIT) <= (left(15) and (not right(15)) and (not out_alu(15))) or
((not left(15)) and right(15) and out_alu(15));
when alu_inc =>
cc_out(VBIT) <= ((not left(7)) and left(6) and left(5) and left(4) and
left(3) and left(2) and left(1) and left(0));
when alu_dec | alu_neg =>
cc_out(VBIT) <= (left(7) and (not left(6)) and (not left(5)) and (not left(4)) and
(not left(3)) and (not left(2)) and (not left(1)) and (not left(0)));
-- 6809 Programming reference manual says
-- V not affected by ASR, LSR and ROR
-- This is different to the 6800
-- John Kent 6th June 2006
-- when alu_asr8 =>
-- cc_out(VBIT) <= left(0) xor left(7);
-- when alu_lsr8 | alu_lsr16 =>
-- cc_out(VBIT) <= left(0);
-- when alu_ror8 =>
-- cc_out(VBIT) <= left(0) xor cc(CBIT);
when alu_lsl16 =>
cc_out(VBIT) <= left(15) xor left(14);
when alu_rol8 | alu_asl8 =>
cc_out(VBIT) <= left(7) xor left(6);
--
-- 11th July 2006 - John Kent
-- What DAA does with V is anyones guess
-- It is undefined in the 6809 programming manual
--
when alu_daa =>
cc_out(VBIT) <= left(7) xor out_alu(7) xor cc(CBIT);
-- CLR resets V Bit
-- John Kent 6th June 2006
when alu_and | alu_ora | alu_eor | alu_com | alu_clr |
alu_st8 | alu_st16 | alu_ld8 | alu_ld16 | alu_sex =>
cc_out(VBIT) <= '0';
when alu_andcc =>
cc_out(VBIT) <= left(VBIT) and cc(VBIT);
when alu_orcc =>
cc_out(VBIT) <= left(VBIT) or cc(VBIT);
when alu_tfr =>
cc_out(VBIT) <= left(VBIT);
when others =>
cc_out(VBIT) <= cc(VBIT);
end case;
 
case alu_ctrl is
when alu_andcc =>
cc_out(FBIT) <= left(FBIT) and cc(FBIT);
when alu_orcc =>
cc_out(FBIT) <= left(FBIT) or cc(FBIT);
when alu_tfr =>
cc_out(FBIT) <= left(FBIT);
when alu_seif =>
cc_out(FBIT) <= '1';
when others =>
cc_out(FBIT) <= cc(FBIT);
end case;
 
case alu_ctrl is
when alu_andcc =>
cc_out(EBIT) <= left(EBIT) and cc(EBIT);
when alu_orcc =>
cc_out(EBIT) <= left(EBIT) or cc(EBIT);
when alu_tfr =>
cc_out(EBIT) <= left(EBIT);
when alu_see =>
cc_out(EBIT) <= '1';
when alu_cle =>
cc_out(EBIT) <= '0';
when others =>
cc_out(EBIT) <= cc(EBIT);
end case;
end process;
 
------------------------------------
--
-- state sequencer
--
------------------------------------
process( state, saved_state,
op_code, pre_code,
cc, ea, md, iv,
irq, firq, nmi_req, nmi_ack, halt )
variable cond_true : boolean; -- variable used to evaluate coditional branches
begin
ba <= '0';
bs <= '0';
lic <= '0';
-- Registers preserved
cc_ctrl <= latch_cc;
acca_ctrl <= latch_acca;
accb_ctrl <= latch_accb;
dp_ctrl <= latch_dp;
ix_ctrl <= latch_ix;
iy_ctrl <= latch_iy;
up_ctrl <= latch_up;
sp_ctrl <= latch_sp;
pc_ctrl <= latch_pc;
md_ctrl <= latch_md;
ea_ctrl <= latch_ea;
iv_ctrl <= latch_iv;
op_ctrl <= latch_op;
pre_ctrl <= latch_pre;
nmi_ctrl <= latch_nmi;
-- ALU Idle
left_ctrl <= pc_left;
right_ctrl <= zero_right;
alu_ctrl <= alu_nop;
-- Bus idle
addr_ctrl <= idle_ad;
dout_ctrl <= cc_dout;
-- Next State Fetch
st_ctrl <= idle_st;
return_state <= fetch_state;
next_state <= fetch_state;
 
case state is
when reset_state => -- released from reset
-- reset the registers
op_ctrl <= reset_op;
pre_ctrl <= reset_pre;
cc_ctrl <= reset_cc;
acca_ctrl <= reset_acca;
accb_ctrl <= reset_accb;
dp_ctrl <= reset_dp;
ix_ctrl <= reset_ix;
iy_ctrl <= reset_iy;
up_ctrl <= reset_up;
sp_ctrl <= reset_sp;
pc_ctrl <= reset_pc;
ea_ctrl <= reset_ea;
md_ctrl <= reset_md;
iv_ctrl <= reset_iv;
nmi_ctrl <= reset_nmi;
next_state <= vect_hi_state;
 
--
-- Jump via interrupt vector
-- iv holds interrupt type
-- fetch PC hi from vector location
--
when vect_hi_state =>
-- fetch pc low interrupt vector
pc_ctrl <= pull_hi_pc;
addr_ctrl <= int_hi_ad;
bs <= '1';
next_state <= vect_lo_state;
--
-- jump via interrupt vector
-- iv holds vector type
-- fetch PC lo from vector location
--
when vect_lo_state =>
-- fetch the vector low byte
pc_ctrl <= pull_lo_pc;
addr_ctrl <= int_lo_ad;
bs <= '1';
next_state <= fetch_state;
--
-- Here to fetch an instruction
-- PC points to opcode
-- Should service interrupt requests at this point
-- either from the timer
-- or from the external input.
--
when fetch_state =>
-- fetch the op code
op_ctrl <= fetch_op;
pre_ctrl <= fetch_pre;
ea_ctrl <= reset_ea;
-- Fetch op code
addr_ctrl <= fetch_ad;
--
case op_code(7 downto 6) is
when "10" => -- acca
case op_code(3 downto 0) is
when "0000" => -- suba
left_ctrl <= acca_left;
right_ctrl <= md_right;
alu_ctrl <= alu_sub8;
cc_ctrl <= load_cc;
acca_ctrl <= load_acca;
when "0001" => -- cmpa
left_ctrl <= acca_left;
right_ctrl <= md_right;
alu_ctrl <= alu_sub8;
cc_ctrl <= load_cc;
when "0010" => -- sbca
left_ctrl <= acca_left;
right_ctrl <= md_right;
alu_ctrl <= alu_sbc;
cc_ctrl <= load_cc;
acca_ctrl <= load_acca;
when "0011" =>
case pre_code is
when "00010000" => -- page 2 -- cmpd
left_ctrl <= accd_left;
right_ctrl <= md_right;
alu_ctrl <= alu_sub16;
cc_ctrl <= load_cc;
when "00010001" => -- page 3 -- cmpu
left_ctrl <= up_left;
right_ctrl <= md_right;
alu_ctrl <= alu_sub16;
cc_ctrl <= load_cc;
when others => -- page 1 -- subd
left_ctrl <= accd_left;
right_ctrl <= md_right;
alu_ctrl <= alu_sub16;
cc_ctrl <= load_cc;
acca_ctrl <= load_hi_acca;
accb_ctrl <= load_accb;
end case;
when "0100" => -- anda
left_ctrl <= acca_left;
right_ctrl <= md_right;
alu_ctrl <= alu_and;
cc_ctrl <= load_cc;
acca_ctrl <= load_acca;
when "0101" => -- bita
left_ctrl <= acca_left;
right_ctrl <= md_right;
alu_ctrl <= alu_and;
cc_ctrl <= load_cc;
when "0110" => -- ldaa
left_ctrl <= acca_left;
right_ctrl <= md_right;
alu_ctrl <= alu_ld8;
cc_ctrl <= load_cc;
acca_ctrl <= load_acca;
when "0111" => -- staa
left_ctrl <= acca_left;
right_ctrl <= md_right;
alu_ctrl <= alu_st8;
cc_ctrl <= load_cc;
when "1000" => -- eora
left_ctrl <= acca_left;
right_ctrl <= md_right;
alu_ctrl <= alu_eor;
cc_ctrl <= load_cc;
acca_ctrl <= load_acca;
when "1001" => -- adca
left_ctrl <= acca_left;
right_ctrl <= md_right;
alu_ctrl <= alu_adc;
cc_ctrl <= load_cc;
acca_ctrl <= load_acca;
when "1010" => -- oraa
left_ctrl <= acca_left;
right_ctrl <= md_right;
alu_ctrl <= alu_ora;
cc_ctrl <= load_cc;
acca_ctrl <= load_acca;
when "1011" => -- adda
left_ctrl <= acca_left;
right_ctrl <= md_right;
alu_ctrl <= alu_add8;
cc_ctrl <= load_cc;
acca_ctrl <= load_acca;
when "1100" =>
case pre_code is
when "00010000" => -- page 2 -- cmpy
left_ctrl <= iy_left;
right_ctrl <= md_right;
alu_ctrl <= alu_sub16;
cc_ctrl <= load_cc;
when "00010001" => -- page 3 -- cmps
left_ctrl <= sp_left;
right_ctrl <= md_right;
alu_ctrl <= alu_sub16;
cc_ctrl <= load_cc;
when others => -- page 1 -- cmpx
left_ctrl <= ix_left;
right_ctrl <= md_right;
alu_ctrl <= alu_sub16;
cc_ctrl <= load_cc;
end case;
when "1101" => -- bsr / jsr
null;
when "1110" => -- ldx
case pre_code is
when "00010000" => -- page 2 -- ldy
left_ctrl <= iy_left;
right_ctrl <= md_right;
alu_ctrl <= alu_ld16;
cc_ctrl <= load_cc;
iy_ctrl <= load_iy;
when others => -- page 1 -- ldx
left_ctrl <= ix_left;
right_ctrl <= md_right;
alu_ctrl <= alu_ld16;
cc_ctrl <= load_cc;
ix_ctrl <= load_ix;
end case;
when "1111" => -- stx
case pre_code is
when "00010000" => -- page 2 -- sty
left_ctrl <= iy_left;
right_ctrl <= md_right;
alu_ctrl <= alu_st16;
cc_ctrl <= load_cc;
when others => -- page 1 -- stx
left_ctrl <= ix_left;
right_ctrl <= md_right;
alu_ctrl <= alu_st16;
cc_ctrl <= load_cc;
end case;
when others =>
null;
end case;
when "11" => -- accb dual op
case op_code(3 downto 0) is
when "0000" => -- subb
left_ctrl <= accb_left;
right_ctrl <= md_right;
alu_ctrl <= alu_sub8;
cc_ctrl <= load_cc;
accb_ctrl <= load_accb;
when "0001" => -- cmpb
left_ctrl <= accb_left;
right_ctrl <= md_right;
alu_ctrl <= alu_sub8;
cc_ctrl <= load_cc;
when "0010" => -- sbcb
left_ctrl <= accb_left;
right_ctrl <= md_right;
alu_ctrl <= alu_sbc;
cc_ctrl <= load_cc;
accb_ctrl <= load_accb;
when "0011" => -- addd
left_ctrl <= accd_left;
right_ctrl <= md_right;
alu_ctrl <= alu_add16;
cc_ctrl <= load_cc;
acca_ctrl <= load_hi_acca;
accb_ctrl <= load_accb;
when "0100" => -- andb
left_ctrl <= accb_left;
right_ctrl <= md_right;
alu_ctrl <= alu_and;
cc_ctrl <= load_cc;
accb_ctrl <= load_accb;
when "0101" => -- bitb
left_ctrl <= accb_left;
right_ctrl <= md_right;
alu_ctrl <= alu_and;
cc_ctrl <= load_cc;
when "0110" => -- ldab
left_ctrl <= accb_left;
right_ctrl <= md_right;
alu_ctrl <= alu_ld8;
cc_ctrl <= load_cc;
accb_ctrl <= load_accb;
when "0111" => -- stab
left_ctrl <= accb_left;
right_ctrl <= md_right;
alu_ctrl <= alu_st8;
cc_ctrl <= load_cc;
when "1000" => -- eorb
left_ctrl <= accb_left;
right_ctrl <= md_right;
alu_ctrl <= alu_eor;
cc_ctrl <= load_cc;
accb_ctrl <= load_accb;
when "1001" => -- adcb
left_ctrl <= accb_left;
right_ctrl <= md_right;
alu_ctrl <= alu_adc;
cc_ctrl <= load_cc;
accb_ctrl <= load_accb;
when "1010" => -- orab
left_ctrl <= accb_left;
right_ctrl <= md_right;
alu_ctrl <= alu_ora;
cc_ctrl <= load_cc;
accb_ctrl <= load_accb;
when "1011" => -- addb
left_ctrl <= accb_left;
right_ctrl <= md_right;
alu_ctrl <= alu_add8;
cc_ctrl <= load_cc;
accb_ctrl <= load_accb;
when "1100" => -- ldd
left_ctrl <= accd_left;
right_ctrl <= md_right;
alu_ctrl <= alu_ld16;
cc_ctrl <= load_cc;
acca_ctrl <= load_hi_acca;
accb_ctrl <= load_accb;
when "1101" => -- std
left_ctrl <= accd_left;
right_ctrl <= md_right;
alu_ctrl <= alu_st16;
cc_ctrl <= load_cc;
when "1110" => -- ldu
case pre_code is
when "00010000" => -- page 2 -- lds
left_ctrl <= sp_left;
right_ctrl <= md_right;
alu_ctrl <= alu_ld16;
cc_ctrl <= load_cc;
sp_ctrl <= load_sp;
when others => -- page 1 -- ldu
left_ctrl <= up_left;
right_ctrl <= md_right;
alu_ctrl <= alu_ld16;
cc_ctrl <= load_cc;
up_ctrl <= load_up;
end case;
when "1111" =>
case pre_code is
when "00010000" => -- page 2 -- sts
left_ctrl <= sp_left;
right_ctrl <= md_right;
alu_ctrl <= alu_st16;
cc_ctrl <= load_cc;
when others => -- page 1 -- stu
left_ctrl <= up_left;
right_ctrl <= md_right;
alu_ctrl <= alu_st16;
cc_ctrl <= load_cc;
end case;
when others =>
null;
end case;
when others =>
null;
end case;
if halt = '1' then
iv_ctrl <= reset_iv;
next_state <= halt_state;
-- service non maskable interrupts
elsif (nmi_req = '1') and (nmi_ack = '0') then
iv_ctrl <= nmi_iv;
nmi_ctrl <= set_nmi;
next_state <= int_nmiirq_state;
-- service maskable interrupts
else
--
-- nmi request is not cleared until nmi input goes low
--
if(nmi_req = '0') and (nmi_ack='1') then
nmi_ctrl <= reset_nmi;
end if;
--
-- FIRQ & IRQ are level sensitive
--
if (firq = '1') and (cc(FBIT) = '0') then
iv_ctrl <= firq_iv;
next_state <= int_firq_state;
elsif (irq = '1') and (cc(IBIT) = '0') then
iv_ctrl <= irq_iv;
next_state <= int_nmiirq_state;
else
-- Advance the PC to fetch next instruction byte
iv_ctrl <= reset_iv; -- default to reset
pc_ctrl <= incr_pc;
next_state <= decode1_state;
end if;
end if;
--
-- Here to decode instruction
-- and fetch next byte of intruction
-- whether it be necessary or not
--
when decode1_state =>
-- fetch first byte of address or immediate data
ea_ctrl <= fetch_first_ea;
md_ctrl <= fetch_first_md;
addr_ctrl <= fetch_ad;
case op_code(7 downto 4) is
--
-- direct single op (2 bytes)
-- 6809 => 6 cycles
-- cpu09 => 5 cycles
-- 1 op=(pc) / pc=pc+1
-- 2 ea_hi=dp / ea_lo=(pc) / pc=pc+1
-- 3 md_lo=(ea) / pc=pc
-- 4 alu_left=md / md=alu_out / pc=pc
-- 5 (ea)=md_lo / pc=pc
--
-- Exception is JMP
-- 6809 => 3 cycles
-- cpu09 => 3 cycles
-- 1 op=(pc) / pc=pc+1
-- 2 ea_hi=dp / ea_lo=(pc) / pc=pc+1
-- 3 pc=ea
--
when "0000" =>
-- advance the PC
pc_ctrl <= incr_pc;
case op_code(3 downto 0) is
when "1110" => -- jmp
next_state <= jmp_state;
when "1111" => -- clr
next_state <= single_op_exec_state;
when others =>
next_state <= single_op_read_state;
end case;
 
-- acca / accb inherent instructions
when "0001" =>
case op_code(3 downto 0) is
--
-- Page2 pre byte
-- pre=(pc) / pc=pc+1
-- op=(pc) / pc=pc+1
--
when "0000" => -- page2
op_ctrl <= fetch_op;
-- advance pc
pc_ctrl <= incr_pc;
next_state <= decode2_state;
 
--
-- Page3 pre byte
-- pre=(pc) / pc=pc+1
-- op=(pc) / pc=pc+1
--
when "0001" => -- page3
op_ctrl <= fetch_op;
-- advance pc
pc_ctrl <= incr_pc;
next_state <= decode3_state;
 
--
-- nop - No operation ( 1 byte )
-- 6809 => 2 cycles
-- cpu09 => 2 cycles
-- 1 op=(pc) / pc=pc+1
-- 2 decode
--
when "0010" => -- nop
lic <= '1';
next_state <= fetch_state;
 
--
-- sync - halt execution until an interrupt is received
-- interrupt may be NMI, IRQ or FIRQ
-- program execution continues if the
-- interrupt is asserted for 3 clock cycles
-- note that registers are not pushed onto the stack
-- CPU09 => Interrupts need only be asserted for one clock cycle
--
when "0011" => -- sync
next_state <= sync_state;
 
--
-- lbra -- long branch (3 bytes)
-- 6809 => 5 cycles
-- cpu09 => 4 cycles
-- 1 op=(pc) / pc=pc+1
-- 2 md_hi=sign(pc) / md_lo=(pc) / pc=pc+1
-- 3 md_hi=md_lo / md_lo=(pc) / pc=pc+1
-- 4 pc=pc+md
--
when "0110" =>
-- increment the pc
pc_ctrl <= incr_pc;
next_state <= lbranch_state;
 
--
-- lbsr - long branch to subroutine (3 bytes)
-- 6809 => 9 cycles
-- cpu09 => 6 cycles
-- 1 op=(pc) /pc=pc+1
-- 2 md_hi=sign(pc) / md_lo=(pc) / pc=pc+1 / sp=sp-1
-- 3 md_hi=md_lo / md_lo=(pc) / pc=pc+1
-- 4 (sp)= pc_lo / sp=sp-1 / pc=pc
-- 5 (sp)=pc_hi / pc=pc
-- 6 pc=pc+md
--
when "0111" =>
-- pre decrement sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
sp_ctrl <= load_sp;
-- increment the pc
pc_ctrl <= incr_pc;
next_state <= lbranch_state;
 
when "1001" => -- daa
left_ctrl <= acca_left;
right_ctrl <= accb_right;
alu_ctrl <= alu_daa;
cc_ctrl <= load_cc;
acca_ctrl <= load_acca;
lic <= '1';
next_state <= fetch_state;
 
when "1010" => -- orcc
-- increment the pc
pc_ctrl <= incr_pc;
st_ctrl <= push_st;
return_state <= fetch_state;
next_state <= orcc_state;
 
when "1100" => -- andcc
-- increment the pc
pc_ctrl <= incr_pc;
st_ctrl <= push_st;
return_state <= fetch_state;
next_state <= andcc_state;
 
when "1101" => -- sex
-- have sex
left_ctrl <= accb_left;
right_ctrl <= zero_right;
alu_ctrl <= alu_sex;
cc_ctrl <= load_cc;
acca_ctrl <= load_hi_acca;
lic <= '1';
next_state <= fetch_state;
 
when "1110" => -- exg
-- increment the pc
pc_ctrl <= incr_pc;
next_state <= exg_state;
 
when "1111" => -- tfr
-- increment the pc
pc_ctrl <= incr_pc;
-- call transfer as a subroutine
st_ctrl <= push_st;
return_state <= fetch_state;
next_state <= tfr_state;
 
when others =>
-- increment the pc
pc_ctrl <= incr_pc;
lic <= '1';
next_state <= fetch_state;
end case;
--
-- Short branch conditional
-- 6809 => always 3 cycles
-- cpu09 => always = 3 cycles
-- 1 op=(pc) / pc=pc+1
-- 2 md_hi=sign(pc) / md_lo=(pc) / pc=pc+1 / test cc
-- 3 if cc tru pc=pc+md else pc=pc
--
when "0010" => -- branch conditional
-- increment the pc
pc_ctrl <= incr_pc;
next_state <= sbranch_state;
--
-- Single byte stack operators
-- Do not advance PC
--
when "0011" =>
--
-- lea - load effective address (2+ bytes)
-- 6809 => 4 cycles + addressing mode
-- cpu09 => 4 cycles + addressing mode
-- 1 op=(pc) / pc=pc+1
-- 2 md_lo=(pc) / pc=pc+1
-- 3 calculate ea
-- 4 ix/iy/sp/up = ea
--
case op_code(3 downto 0) is
when "0000" | -- leax
"0001" | -- leay
"0010" | -- leas
"0011" => -- leau
-- advance PC
pc_ctrl <= incr_pc;
st_ctrl <= push_st;
return_state <= lea_state;
next_state <= indexed_state;
 
--
-- pshs - push registers onto sp stack
-- 6809 => 5 cycles + registers
-- cpu09 => 3 cycles + registers
-- 1 op=(pc) / pc=pc+1
-- 2 ea_lo=(pc) / pc=pc+1
-- 3 if ea(7 downto 0) != "00000000" then sp=sp-1
-- 4 if ea(7) = 1 (sp)=pcl, sp=sp-1
-- 5 if ea(7) = 1 (sp)=pch
-- if ea(6 downto 0) != "0000000" then sp=sp-1
-- 6 if ea(6) = 1 (sp)=upl, sp=sp-1
-- 7 if ea(6) = 1 (sp)=uph
-- if ea(5 downto 0) != "000000" then sp=sp-1
-- 8 if ea(5) = 1 (sp)=iyl, sp=sp-1
-- 9 if ea(5) = 1 (sp)=iyh
-- if ea(4 downto 0) != "00000" then sp=sp-1
-- 10 if ea(4) = 1 (sp)=ixl, sp=sp-1
-- 11 if ea(4) = 1 (sp)=ixh
-- if ea(3 downto 0) != "0000" then sp=sp-1
-- 12 if ea(3) = 1 (sp)=dp
-- if ea(2 downto 0) != "000" then sp=sp-1
-- 13 if ea(2) = 1 (sp)=accb
-- if ea(1 downto 0) != "00" then sp=sp-1
-- 14 if ea(1) = 1 (sp)=acca
-- if ea(0 downto 0) != "0" then sp=sp-1
-- 15 if ea(0) = 1 (sp)=cc
--
when "0100" => -- pshs
-- advance PC
pc_ctrl <= incr_pc;
next_state <= pshs_state;
 
--
-- puls - pull registers of sp stack
-- 6809 => 5 cycles + registers
-- cpu09 => 3 cycles + registers
--
when "0101" => -- puls
-- advance PC
pc_ctrl <= incr_pc;
next_state <= puls_state;
 
--
-- pshu - push registers onto up stack
-- 6809 => 5 cycles + registers
-- cpu09 => 3 cycles + registers
--
when "0110" => -- pshu
-- advance PC
pc_ctrl <= incr_pc;
next_state <= pshu_state;
 
--
-- pulu - pull registers of up stack
-- 6809 => 5 cycles + registers
-- cpu09 => 3 cycles + registers
--
when "0111" => -- pulu
-- advance PC
pc_ctrl <= incr_pc;
next_state <= pulu_state;
 
--
-- rts - return from subroutine
-- 6809 => 5 cycles
-- cpu09 => 4 cycles
-- 1 op=(pc) / pc=pc+1
-- 2 decode op
-- 3 pc_hi = (sp) / sp=sp+1
-- 4 pc_lo = (sp) / sp=sp+1
--
when "1001" =>
st_ctrl <= push_st;
return_state <= fetch_state;
next_state <= pull_return_hi_state;
 
--
-- add accb to index register
-- *** Note: this is an unsigned addition.
-- does not affect any condition codes
-- 6809 => 3 cycles
-- cpu09 => 2 cycles
-- 1 op=(pc) / pc=pc+1
-- 2 alu_left=ix / alu_right=accb / ix=alu_out / pc=pc
--
when "1010" => -- abx
left_ctrl <= ix_left;
right_ctrl <= accb_right;
alu_ctrl <= alu_abx;
ix_ctrl <= load_ix;
lic <= '1';
next_state <= fetch_state;
 
when "1011" => -- rti
next_state <= rti_cc_state;
 
when "1100" => -- cwai #$<cc_mask>
-- pre decrement sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
sp_ctrl <= load_sp;
iv_ctrl <= reset_iv;
-- increment pc
pc_ctrl <= incr_pc;
st_ctrl <= push_st;
return_state <= int_entire_state; -- set entire flag
next_state <= andcc_state;
 
when "1101" => -- mul
next_state <= mul_state;
 
when "1111" => -- swi
-- predecrement SP
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
sp_ctrl <= load_sp;
iv_ctrl <= swi_iv;
next_state <= int_entire_state;
 
when others =>
lic <= '1';
next_state <= fetch_state;
 
end case;
--
-- Accumulator A Single operand
-- source = acca, dest = acca
-- Do not advance PC
-- Typically 2 cycles 1 bytes
-- 1 opcode fetch
-- 2 post byte fetch / instruction decode
-- Note that there is no post byte
-- so do not advance PC in decode cycle
-- Re-run opcode fetch cycle after decode
--
when "0100" => -- acca single op
left_ctrl <= acca_left;
case op_code(3 downto 0) is
when "0000" => -- neg
right_ctrl <= zero_right;
alu_ctrl <= alu_neg;
acca_ctrl <= load_acca;
cc_ctrl <= load_cc;
when "0011" => -- com
right_ctrl <= zero_right;
alu_ctrl <= alu_com;
acca_ctrl <= load_acca;
cc_ctrl <= load_cc;
when "0100" => -- lsr
right_ctrl <= zero_right;
alu_ctrl <= alu_lsr8;
acca_ctrl <= load_acca;
cc_ctrl <= load_cc;
when "0110" => -- ror
right_ctrl <= zero_right;
alu_ctrl <= alu_ror8;
acca_ctrl <= load_acca;
cc_ctrl <= load_cc;
when "0111" => -- asr
right_ctrl <= zero_right;
alu_ctrl <= alu_asr8;
acca_ctrl <= load_acca;
cc_ctrl <= load_cc;
when "1000" => -- asl
right_ctrl <= zero_right;
alu_ctrl <= alu_asl8;
acca_ctrl <= load_acca;
cc_ctrl <= load_cc;
when "1001" => -- rol
right_ctrl <= zero_right;
alu_ctrl <= alu_rol8;
acca_ctrl <= load_acca;
cc_ctrl <= load_cc;
when "1010" => -- dec
right_ctrl <= one_right;
alu_ctrl <= alu_dec;
acca_ctrl <= load_acca;
cc_ctrl <= load_cc;
when "1011" => -- undefined
right_ctrl <= zero_right;
alu_ctrl <= alu_nop;
acca_ctrl <= latch_acca;
cc_ctrl <= latch_cc;
when "1100" => -- inc
right_ctrl <= one_right;
alu_ctrl <= alu_inc;
acca_ctrl <= load_acca;
cc_ctrl <= load_cc;
when "1101" => -- tst
right_ctrl <= zero_right;
alu_ctrl <= alu_st8;
acca_ctrl <= latch_acca;
cc_ctrl <= load_cc;
when "1110" => -- jmp (not defined)
right_ctrl <= zero_right;
alu_ctrl <= alu_nop;
acca_ctrl <= latch_acca;
cc_ctrl <= latch_cc;
when "1111" => -- clr
right_ctrl <= zero_right;
alu_ctrl <= alu_clr;
acca_ctrl <= load_acca;
cc_ctrl <= load_cc;
when others =>
right_ctrl <= zero_right;
alu_ctrl <= alu_nop;
acca_ctrl <= latch_acca;
cc_ctrl <= latch_cc;
end case;
lic <= '1';
next_state <= fetch_state;
--
-- Single Operand accb
-- source = accb, dest = accb
-- Typically 2 cycles 1 bytes
-- 1 opcode fetch
-- 2 post byte fetch / instruction decode
-- Note that there is no post byte
-- so do not advance PC in decode cycle
-- Re-run opcode fetch cycle after decode
--
when "0101" =>
left_ctrl <= accb_left;
case op_code(3 downto 0) is
when "0000" => -- neg
right_ctrl <= zero_right;
alu_ctrl <= alu_neg;
accb_ctrl <= load_accb;
cc_ctrl <= load_cc;
when "0011" => -- com
right_ctrl <= zero_right;
alu_ctrl <= alu_com;
accb_ctrl <= load_accb;
cc_ctrl <= load_cc;
when "0100" => -- lsr
right_ctrl <= zero_right;
alu_ctrl <= alu_lsr8;
accb_ctrl <= load_accb;
cc_ctrl <= load_cc;
when "0110" => -- ror
right_ctrl <= zero_right;
alu_ctrl <= alu_ror8;
accb_ctrl <= load_accb;
cc_ctrl <= load_cc;
when "0111" => -- asr
right_ctrl <= zero_right;
alu_ctrl <= alu_asr8;
accb_ctrl <= load_accb;
cc_ctrl <= load_cc;
when "1000" => -- asl
right_ctrl <= zero_right;
alu_ctrl <= alu_asl8;
accb_ctrl <= load_accb;
cc_ctrl <= load_cc;
when "1001" => -- rol
right_ctrl <= zero_right;
alu_ctrl <= alu_rol8;
accb_ctrl <= load_accb;
cc_ctrl <= load_cc;
when "1010" => -- dec
right_ctrl <= one_right;
alu_ctrl <= alu_dec;
accb_ctrl <= load_accb;
cc_ctrl <= load_cc;
when "1011" => -- undefined
right_ctrl <= zero_right;
alu_ctrl <= alu_nop;
accb_ctrl <= latch_accb;
cc_ctrl <= latch_cc;
when "1100" => -- inc
right_ctrl <= one_right;
alu_ctrl <= alu_inc;
accb_ctrl <= load_accb;
cc_ctrl <= load_cc;
when "1101" => -- tst
right_ctrl <= zero_right;
alu_ctrl <= alu_st8;
accb_ctrl <= latch_accb;
cc_ctrl <= load_cc;
when "1110" => -- jmp (undefined)
right_ctrl <= zero_right;
alu_ctrl <= alu_nop;
accb_ctrl <= latch_accb;
cc_ctrl <= latch_cc;
when "1111" => -- clr
right_ctrl <= zero_right;
alu_ctrl <= alu_clr;
accb_ctrl <= load_accb;
cc_ctrl <= load_cc;
when others =>
right_ctrl <= zero_right;
alu_ctrl <= alu_nop;
accb_ctrl <= latch_accb;
cc_ctrl <= latch_cc;
end case;
lic <= '1';
next_state <= fetch_state;
--
-- Single operand indexed
-- Two byte instruction so advance PC
-- EA should hold index offset
--
when "0110" => -- indexed single op
-- increment the pc
pc_ctrl <= incr_pc;
st_ctrl <= push_st;
case op_code(3 downto 0) is
when "1110" => -- jmp
return_state <= jmp_state;
when "1111" => -- clr
return_state <= single_op_exec_state;
when others =>
return_state <= single_op_read_state;
end case;
next_state <= indexed_state;
--
-- Single operand extended addressing
-- three byte instruction so advance the PC
-- Low order EA holds high order address
--
when "0111" => -- extended single op
-- increment PC
pc_ctrl <= incr_pc;
st_ctrl <= push_st;
case op_code(3 downto 0) is
when "1110" => -- jmp
return_state <= jmp_state;
when "1111" => -- clr
return_state <= single_op_exec_state;
when others =>
return_state <= single_op_read_state;
end case;
next_state <= extended_state;
 
when "1000" => -- acca immediate
-- increment the pc
pc_ctrl <= incr_pc;
case op_code(3 downto 0) is
when "0011" | -- subd #
"1100" | -- cmpx #
"1110" => -- ldx #
st_ctrl <= push_st;
return_state <= fetch_state;
next_state <= imm16_state;
 
--
-- bsr offset - Branch to subroutine (2 bytes)
-- 6809 => 7 cycles
-- cpu09 => 5 cycles
-- 1 op=(pc) / pc=pc+1
-- 2 md_hi=sign(pc) / md_lo=(pc) / sp=sp-1 / pc=pc+1
-- 3 (sp)=pc_lo / sp=sp-1
-- 4 (sp)=pc_hi
-- 5 pc=pc+md
--
when "1101" => -- bsr
-- pre decrement SP
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
sp_ctrl <= load_sp;
--
st_ctrl <= push_st;
return_state <= sbranch_state;
next_state <= push_return_lo_state;
 
when others =>
lic <= '1';
next_state <= fetch_state;
end case;
 
when "1001" => -- acca direct
-- increment the pc
pc_ctrl <= incr_pc;
case op_code(3 downto 0) is
when "0011" | -- subd
"1100" | -- cmpx
"1110" => -- ldx
next_state <= dual_op_read16_state;
 
when "0111" => -- sta direct
next_state <= dual_op_write8_state;
 
when "1111" => -- stx direct
-- idle ALU
left_ctrl <= ix_left;
right_ctrl <= zero_right;
alu_ctrl <= alu_nop;
cc_ctrl <= latch_cc;
sp_ctrl <= latch_sp;
next_state <= dual_op_write16_state;
 
--
-- jsr direct - Jump to subroutine in direct page (2 bytes)
-- 6809 => 7 cycles
-- cpu09 => 5 cycles
-- 1 op=(pc) / pc=pc+1
-- 2 ea_hi=0 / ea_lo=(pc) / sp=sp-1 / pc=pc+1
-- 3 (sp)=pc_lo / sp=sp-1
-- 4 (sp)=pc_hi
-- 5 pc=ea
--
when "1101" => -- jsr direct
-- pre decrement sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
sp_ctrl <= load_sp;
--
st_ctrl <= push_st;
return_state <= jmp_state;
next_state <= push_return_lo_state;
 
when others =>
next_state <= dual_op_read8_state;
end case;
 
when "1010" => -- acca indexed
-- increment the pc
pc_ctrl <= incr_pc;
case op_code(3 downto 0) is
when "0011" | -- subd
"1100" | -- cmpx
"1110" => -- ldx
st_ctrl <= push_st;
return_state <= dual_op_read16_state;
next_state <= indexed_state;
 
when "0111" => -- staa ,x
st_ctrl <= push_st;
return_state <= dual_op_write8_state;
next_state <= indexed_state;
 
when "1111" => -- stx ,x
st_ctrl <= push_st;
return_state <= dual_op_write16_state;
next_state <= indexed_state;
 
when "1101" => -- jsr ,x
-- DO NOT pre decrement SP
st_ctrl <= push_st;
return_state <= jsr_state;
next_state <= indexed_state;
 
when others =>
st_ctrl <= push_st;
return_state <= dual_op_read8_state;
next_state <= indexed_state;
end case;
 
when "1011" => -- acca extended
-- increment the pc
pc_ctrl <= incr_pc;
case op_code(3 downto 0) is
when "0011" | -- subd
"1100" | -- cmpx
"1110" => -- ldx
st_ctrl <= push_st;
return_state <= dual_op_read16_state;
next_state <= extended_state;
 
when "0111" => -- staa >
st_ctrl <= push_st;
return_state <= dual_op_write8_state;
next_state <= extended_state;
 
when "1111" => -- stx >
st_ctrl <= push_st;
return_state <= dual_op_write16_state;
next_state <= extended_state;
 
when "1101" => -- jsr >extended
-- DO NOT pre decrement sp
st_ctrl <= push_st;
return_state <= jsr_state;
next_state <= extended_state;
 
when others =>
st_ctrl <= push_st;
return_state <= dual_op_read8_state;
next_state <= extended_state;
end case;
 
when "1100" => -- accb immediate
-- increment the pc
pc_ctrl <= incr_pc;
case op_code(3 downto 0) is
when "0011" | -- addd #
"1100" | -- ldd #
"1110" => -- ldu #
st_ctrl <= push_st;
return_state <= fetch_state;
next_state <= imm16_state;
 
when others =>
lic <= '1';
next_state <= fetch_state;
 
end case;
 
 
when "1101" => -- accb direct
-- increment the pc
pc_ctrl <= incr_pc;
case op_code(3 downto 0) is
when "0011" | -- addd
"1100" | -- ldd
"1110" => -- ldu
next_state <= dual_op_read16_state;
 
when "0111" => -- stab direct
next_state <= dual_op_write8_state;
 
when "1101" => -- std direct
next_state <= dual_op_write16_state;
 
when "1111" => -- stu direct
next_state <= dual_op_write16_state;
 
when others =>
next_state <= dual_op_read8_state;
end case;
 
when "1110" => -- accb indexed
-- increment the pc
pc_ctrl <= incr_pc;
case op_code(3 downto 0) is
when "0011" | -- addd
"1100" | -- ldd
"1110" => -- ldu
st_ctrl <= push_st;
return_state <= dual_op_read16_state;
next_state <= indexed_state;
 
when "0111" => -- stab indexed
st_ctrl <= push_st;
return_state <= dual_op_write8_state;
next_state <= indexed_state;
 
when "1101" => -- std indexed
st_ctrl <= push_st;
return_state <= dual_op_write16_state;
next_state <= indexed_state;
 
when "1111" => -- stu indexed
st_ctrl <= push_st;
return_state <= dual_op_write16_state;
next_state <= indexed_state;
 
when others =>
st_ctrl <= push_st;
return_state <= dual_op_read8_state;
next_state <= indexed_state;
end case;
 
when "1111" => -- accb extended
-- increment the pc
pc_ctrl <= incr_pc;
case op_code(3 downto 0) is
when "0011" | -- addd
"1100" | -- ldd
"1110" => -- ldu
st_ctrl <= push_st;
return_state <= dual_op_read16_state;
next_state <= extended_state;
 
when "0111" => -- stab extended
st_ctrl <= push_st;
return_state <= dual_op_write8_state;
next_state <= extended_state;
 
when "1101" => -- std extended
st_ctrl <= push_st;
return_state <= dual_op_write16_state;
next_state <= extended_state;
 
when "1111" => -- stu extended
st_ctrl <= push_st;
return_state <= dual_op_write16_state;
next_state <= extended_state;
 
when others =>
st_ctrl <= push_st;
return_state <= dual_op_read8_state;
next_state <= extended_state;
end case;
 
when others =>
null;
end case;
 
--
-- Here to decode prefix 2 instruction
-- and fetch next byte of intruction
-- whether it be necessary or not
--
when decode2_state =>
-- fetch first byte of address or immediate data
ea_ctrl <= fetch_first_ea;
md_ctrl <= fetch_first_md;
addr_ctrl <= fetch_ad;
case op_code(7 downto 4) is
--
-- lbcc -- long branch conditional
-- 6809 => branch 6 cycles, no branch 5 cycles
-- cpu09 => always 5 cycles
-- 1 pre=(pc) / pc=pc+1
-- 2 op=(pc) / pc=pc+1
-- 3 md_hi=sign(pc) / md_lo=(pc) / pc=pc+1
-- 4 md_hi=md_lo / md_lo=(pc) / pc=pc+1
-- 5 if cond pc=pc+md else pc=pc
--
when "0010" =>
-- increment the pc
pc_ctrl <= incr_pc;
next_state <= lbranch_state;
 
--
-- Single byte stack operators
-- Do not advance PC
--
when "0011" =>
case op_code(3 downto 0) is
when "1111" => -- swi 2
-- predecrement sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
sp_ctrl <= load_sp;
iv_ctrl <= swi2_iv;
next_state <= int_entire_state;
 
when others =>
lic <= '1';
next_state <= fetch_state;
end case;
 
when "1000" => -- acca immediate
-- increment the pc
pc_ctrl <= incr_pc;
case op_code(3 downto 0) is
when "0011" | -- cmpd #
"1100" | -- cmpy #
"1110" => -- ldy #
st_ctrl <= push_st;
return_state <= fetch_state;
next_state <= imm16_state;
 
when others =>
lic <= '1';
next_state <= fetch_state;
 
end case;
 
when "1001" => -- acca direct
-- increment the pc
pc_ctrl <= incr_pc;
case op_code(3 downto 0) is
when "0011" | -- cmpd <
"1100" | -- cmpy <
"1110" => -- ldy <
next_state <= dual_op_read16_state;
 
when "1111" => -- sty <
next_state <= dual_op_write16_state;
 
when others =>
lic <= '1';
next_state <= fetch_state;
 
end case;
 
when "1010" => -- acca indexed
-- increment the pc
pc_ctrl <= incr_pc;
case op_code(3 downto 0) is
when "0011" | -- cmpd ,ind
"1100" | -- cmpy ,ind
"1110" => -- ldy ,ind
st_ctrl <= push_st;
return_state <= dual_op_read16_state;
next_state <= indexed_state;
 
when "1111" => -- sty ,ind
st_ctrl <= push_st;
return_state <= dual_op_write16_state;
next_state <= indexed_state;
 
when others =>
lic <= '1';
next_state <= fetch_state;
end case;
 
when "1011" => -- acca extended
-- increment the pc
pc_ctrl <= incr_pc;
case op_code(3 downto 0) is
when "0011" | -- cmpd <
"1100" | -- cmpy <
"1110" => -- ldy <
st_ctrl <= push_st;
return_state <= dual_op_read16_state;
next_state <= extended_state;
 
when "1111" => -- sty >
st_ctrl <= push_st;
return_state <= dual_op_write16_state;
next_state <= extended_state;
 
when others =>
lic <= '1';
next_state <= fetch_state;
 
end case;
 
when "1100" => -- accb immediate
-- increment the pc
pc_ctrl <= incr_pc;
case op_code(3 downto 0) is
when "0011" | -- undef #
"1100" | -- undef #
"1110" => -- lds #
st_ctrl <= push_st;
return_state <= fetch_state;
next_state <= imm16_state;
 
when others =>
next_state <= fetch_state;
 
end case;
 
when "1101" => -- accb direct
-- increment the pc
pc_ctrl <= incr_pc;
case op_code(3 downto 0) is
when "0011" | -- undef <
"1100" | -- undef <
"1110" => -- lds <
next_state <= dual_op_read16_state;
 
when "1111" => -- sts <
next_state <= dual_op_write16_state;
 
when others =>
lic <= '1';
next_state <= fetch_state;
 
end case;
 
when "1110" => -- accb indexed
-- increment the pc
pc_ctrl <= incr_pc;
case op_code(3 downto 0) is
when "0011" | -- undef ,ind
"1100" | -- undef ,ind
"1110" => -- lds ,ind
st_ctrl <= push_st;
return_state <= dual_op_read16_state;
next_state <= indexed_state;
 
when "1111" => -- sts ,ind
st_ctrl <= push_st;
return_state <= dual_op_write16_state;
next_state <= indexed_state;
 
when others =>
lic <= '1';
next_state <= fetch_state;
 
end case;
 
when "1111" => -- accb extended
-- increment the pc
pc_ctrl <= incr_pc;
case op_code(3 downto 0) is
when "0011" | -- undef >
"1100" | -- undef >
"1110" => -- lds >
st_ctrl <= push_st;
return_state <= dual_op_read16_state;
next_state <= extended_state;
 
when "1111" => -- sts >
st_ctrl <= push_st;
return_state <= dual_op_write16_state;
next_state <= extended_state;
 
when others =>
lic <= '1';
next_state <= fetch_state;
end case;
 
when others =>
lic <= '1';
next_state <= fetch_state;
end case;
--
-- Here to decode instruction
-- and fetch next byte of intruction
-- whether it be necessary or not
--
when decode3_state =>
ea_ctrl <= fetch_first_ea;
md_ctrl <= fetch_first_md;
addr_ctrl <= fetch_ad;
dout_ctrl <= md_lo_dout;
case op_code(7 downto 4) is
--
-- Single byte stack operators
-- Do not advance PC
--
when "0011" =>
case op_code(3 downto 0) is
when "1111" => -- swi3
-- predecrement sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
sp_ctrl <= load_sp;
iv_ctrl <= swi3_iv;
next_state <= int_entire_state;
when others =>
lic <= '1';
next_state <= fetch_state;
end case;
 
when "1000" => -- acca immediate
-- increment the pc
pc_ctrl <= incr_pc;
case op_code(3 downto 0) is
when "0011" | -- cmpu #
"1100" | -- cmps #
"1110" => -- undef #
st_ctrl <= push_st;
return_state <= fetch_state;
next_state <= imm16_state;
when others =>
lic <= '1';
next_state <= fetch_state;
end case;
 
when "1001" => -- acca direct
-- increment the pc
pc_ctrl <= incr_pc;
case op_code(3 downto 0) is
when "0011" | -- cmpu <
"1100" | -- cmps <
"1110" => -- undef <
st_ctrl <= idle_st;
return_state <= fetch_state;
next_state <= dual_op_read16_state;
 
when others =>
lic <= '1';
next_state <= fetch_state;
 
end case;
 
when "1010" => -- acca indexed
-- increment the pc
pc_ctrl <= incr_pc;
case op_code(3 downto 0) is
when "0011" | -- cmpu ,X
"1100" | -- cmps ,X
"1110" => -- undef ,X
st_ctrl <= push_st;
return_state <= dual_op_read16_state;
next_state <= indexed_state;
 
when others =>
lic <= '1';
next_state <= fetch_state;
 
end case;
 
when "1011" => -- acca extended
-- increment the pc
pc_ctrl <= incr_pc;
case op_code(3 downto 0) is
when "0011" | -- cmpu >
"1100" | -- cmps >
"1110" => -- undef >
st_ctrl <= push_st;
return_state <= dual_op_read16_state;
next_state <= extended_state;
when others =>
lic <= '1';
next_state <= fetch_state;
end case;
 
when others =>
lic <= '1';
next_state <= fetch_state;
end case;
 
--
-- here if ea holds low byte
-- Direct
-- Extended
-- Indexed
-- read memory location
--
when single_op_read_state =>
-- read memory into md
md_ctrl <= fetch_first_md;
addr_ctrl <= read_ad;
dout_ctrl <= md_lo_dout;
next_state <= single_op_exec_state;
 
when single_op_exec_state =>
case op_code(3 downto 0) is
when "0000" => -- neg
left_ctrl <= md_left;
right_ctrl <= zero_right;
alu_ctrl <= alu_neg;
cc_ctrl <= load_cc;
md_ctrl <= load_md;
next_state <= single_op_write_state;
when "0011" => -- com
left_ctrl <= md_left;
right_ctrl <= zero_right;
alu_ctrl <= alu_com;
cc_ctrl <= load_cc;
md_ctrl <= load_md;
next_state <= single_op_write_state;
when "0100" => -- lsr
left_ctrl <= md_left;
right_ctrl <= zero_right;
alu_ctrl <= alu_lsr8;
cc_ctrl <= load_cc;
md_ctrl <= load_md;
next_state <= single_op_write_state;
when "0110" => -- ror
left_ctrl <= md_left;
right_ctrl <= zero_right;
alu_ctrl <= alu_ror8;
cc_ctrl <= load_cc;
md_ctrl <= load_md;
next_state <= single_op_write_state;
when "0111" => -- asr
left_ctrl <= md_left;
right_ctrl <= zero_right;
alu_ctrl <= alu_asr8;
cc_ctrl <= load_cc;
md_ctrl <= load_md;
next_state <= single_op_write_state;
when "1000" => -- asl
left_ctrl <= md_left;
right_ctrl <= zero_right;
alu_ctrl <= alu_asl8;
cc_ctrl <= load_cc;
md_ctrl <= load_md;
next_state <= single_op_write_state;
when "1001" => -- rol
left_ctrl <= md_left;
right_ctrl <= zero_right;
alu_ctrl <= alu_rol8;
cc_ctrl <= load_cc;
md_ctrl <= load_md;
next_state <= single_op_write_state;
when "1010" => -- dec
left_ctrl <= md_left;
right_ctrl <= one_right;
alu_ctrl <= alu_dec;
cc_ctrl <= load_cc;
md_ctrl <= load_md;
next_state <= single_op_write_state;
when "1011" => -- undefined
lic <= '1';
next_state <= fetch_state;
when "1100" => -- inc
left_ctrl <= md_left;
right_ctrl <= one_right;
alu_ctrl <= alu_inc;
cc_ctrl <= load_cc;
md_ctrl <= load_md;
next_state <= single_op_write_state;
when "1101" => -- tst
left_ctrl <= md_left;
right_ctrl <= zero_right;
alu_ctrl <= alu_st8;
cc_ctrl <= load_cc;
lic <= '1';
next_state <= fetch_state;
when "1110" => -- jmp
left_ctrl <= md_left;
right_ctrl <= zero_right;
alu_ctrl <= alu_ld16;
pc_ctrl <= load_pc;
lic <= '1';
next_state <= fetch_state;
when "1111" => -- clr
left_ctrl <= md_left;
right_ctrl <= zero_right;
alu_ctrl <= alu_clr;
cc_ctrl <= load_cc;
md_ctrl <= load_md;
next_state <= single_op_write_state;
when others =>
lic <= '1';
next_state <= fetch_state;
end case;
--
-- single operand 8 bit write
-- Write low 8 bits of ALU output
-- EA holds address
-- MD holds data
--
when single_op_write_state =>
-- write ALU low byte output
addr_ctrl <= write_ad;
dout_ctrl <= md_lo_dout;
lic <= '1';
next_state <= fetch_state;
 
--
-- here if ea holds address of low byte
-- read memory location
--
when dual_op_read8_state =>
-- read first data byte from ea
md_ctrl <= fetch_first_md;
addr_ctrl <= read_ad;
lic <= '1';
next_state <= fetch_state;
 
--
-- Here to read a 16 bit value into MD
-- pointed to by the EA register
-- The first byte is read
-- and the EA is incremented
--
when dual_op_read16_state =>
-- increment the effective address
left_ctrl <= ea_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
ea_ctrl <= load_ea;
-- read the high byte of the 16 bit data
md_ctrl <= fetch_first_md;
addr_ctrl <= read_ad;
next_state <= dual_op_read16_2_state;
 
--
-- here to read the second byte
-- pointed to by EA into MD
--
when dual_op_read16_2_state =>
-- read the low byte of the 16 bit data
md_ctrl <= fetch_next_md;
addr_ctrl <= read_ad;
lic <= '1';
next_state <= fetch_state;
 
--
-- 16 bit Write state
-- EA hold address of memory to write to
-- Advance the effective address in ALU
-- decode op_code to determine which
-- register to write
--
when dual_op_write16_state =>
-- increment the effective address
left_ctrl <= ea_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
ea_ctrl <= load_ea;
-- write the ALU hi byte at ea
addr_ctrl <= write_ad;
if op_code(6) = '0' then
case op_code(3 downto 0) is
when "1111" => -- stx / sty
case pre_code is
when "00010000" => -- page 2 -- sty
dout_ctrl <= iy_hi_dout;
when others => -- page 1 -- stx
dout_ctrl <= ix_hi_dout;
end case;
when others =>
dout_ctrl <= md_hi_dout;
end case;
else
case op_code(3 downto 0) is
when "1101" => -- std
dout_ctrl <= acca_dout; -- acca is high byte of ACCD
when "1111" => -- stu / sts
case pre_code is
when "00010000" => -- page 2 -- sts
dout_ctrl <= sp_hi_dout;
when others => -- page 1 -- stu
dout_ctrl <= up_hi_dout;
end case;
when others =>
dout_ctrl <= md_hi_dout;
end case;
end if;
next_state <= dual_op_write8_state;
 
--
-- Dual operand 8 bit write
-- Write 8 bit accumulator
-- or low byte of 16 bit register
-- EA holds address
-- decode opcode to determine
-- which register to apply to the bus
-- Also set the condition codes here
--
when dual_op_write8_state =>
if op_code(6) = '0' then
case op_code(3 downto 0) is
when "0111" => -- sta
dout_ctrl <= acca_dout;
when "1111" => -- stx / sty
case pre_code is
when "00010000" => -- page 2 -- sty
dout_ctrl <= iy_lo_dout;
when others => -- page 1 -- stx
dout_ctrl <= ix_lo_dout;
end case;
when others =>
dout_ctrl <= md_lo_dout;
end case;
else
case op_code(3 downto 0) is
when "0111" => -- stb
dout_ctrl <= accb_dout;
when "1101" => -- std
dout_ctrl <= accb_dout; -- accb is low byte of accd
when "1111" => -- stu / sts
case pre_code is
when "00010000" => -- page 2 -- sts
dout_ctrl <= sp_lo_dout;
when others => -- page 1 -- stu
dout_ctrl <= up_lo_dout;
end case;
when others =>
dout_ctrl <= md_lo_dout;
end case;
end if;
-- write ALU low byte output
addr_ctrl <= write_ad;
lic <= '1';
next_state <= fetch_state;
 
--
-- 16 bit immediate addressing mode
--
when imm16_state =>
-- increment pc
pc_ctrl <= incr_pc;
-- fetch next immediate byte
md_ctrl <= fetch_next_md;
addr_ctrl <= fetch_ad;
st_ctrl <= pull_st;
lic <= '1';
next_state <= saved_state;
 
--
-- md & ea holds 8 bit index offset
-- calculate the effective memory address
-- using the alu
--
when indexed_state =>
--
-- decode indexing mode
--
if md(7) = '0' then
case md(6 downto 5) is
when "00" =>
left_ctrl <= ix_left;
when "01" =>
left_ctrl <= iy_left;
when "10" =>
left_ctrl <= up_left;
when others =>
-- when "11" =>
left_ctrl <= sp_left;
end case;
right_ctrl <= md_sign5_right;
alu_ctrl <= alu_add16;
ea_ctrl <= load_ea;
st_ctrl <= pull_st;
next_state <= saved_state;
 
else
case md(3 downto 0) is
when "0000" => -- ,R+
case md(6 downto 5) is
when "00" =>
left_ctrl <= ix_left;
when "01" =>
left_ctrl <= iy_left;
when "10" =>
left_ctrl <= up_left;
when others =>
left_ctrl <= sp_left;
end case;
--
right_ctrl <= zero_right;
alu_ctrl <= alu_add16;
ea_ctrl <= load_ea;
next_state <= postincr1_state;
 
when "0001" => -- ,R++
case md(6 downto 5) is
when "00" =>
left_ctrl <= ix_left;
when "01" =>
left_ctrl <= iy_left;
when "10" =>
left_ctrl <= up_left;
when others =>
-- when "11" =>
left_ctrl <= sp_left;
end case;
right_ctrl <= zero_right;
alu_ctrl <= alu_add16;
ea_ctrl <= load_ea;
next_state <= postincr2_state;
 
when "0010" => -- ,-R
case md(6 downto 5) is
when "00" =>
left_ctrl <= ix_left;
ix_ctrl <= load_ix;
when "01" =>
left_ctrl <= iy_left;
iy_ctrl <= load_iy;
when "10" =>
left_ctrl <= up_left;
up_ctrl <= load_up;
when others =>
-- when "11" =>
left_ctrl <= sp_left;
sp_ctrl <= load_sp;
end case;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
ea_ctrl <= load_ea;
st_ctrl <= pull_st;
next_state <= saved_state;
 
when "0011" => -- ,--R
case md(6 downto 5) is
when "00" =>
left_ctrl <= ix_left;
ix_ctrl <= load_ix;
when "01" =>
left_ctrl <= iy_left;
iy_ctrl <= load_iy;
when "10" =>
left_ctrl <= up_left;
up_ctrl <= load_up;
when others =>
-- when "11" =>
left_ctrl <= sp_left;
sp_ctrl <= load_sp;
end case;
right_ctrl <= two_right;
alu_ctrl <= alu_sub16;
ea_ctrl <= load_ea;
if md(4) = '0' then
st_ctrl <= pull_st;
next_state <= saved_state;
else
next_state <= indirect_state;
end if;
 
when "0100" => -- ,R (zero offset)
case md(6 downto 5) is
when "00" =>
left_ctrl <= ix_left;
when "01" =>
left_ctrl <= iy_left;
when "10" =>
left_ctrl <= up_left;
when others =>
-- when "11" =>
left_ctrl <= sp_left;
end case;
right_ctrl <= zero_right;
alu_ctrl <= alu_add16;
ea_ctrl <= load_ea;
if md(4) = '0' then
st_ctrl <= pull_st;
next_state <= saved_state;
else
next_state <= indirect_state;
end if;
 
when "0101" => -- ACCB,R
case md(6 downto 5) is
when "00" =>
left_ctrl <= ix_left;
when "01" =>
left_ctrl <= iy_left;
when "10" =>
left_ctrl <= up_left;
when others =>
-- when "11" =>
left_ctrl <= sp_left;
end case;
right_ctrl <= accb_right;
alu_ctrl <= alu_add16;
ea_ctrl <= load_ea;
if md(4) = '0' then
st_ctrl <= pull_st;
next_state <= saved_state;
else
next_state <= indirect_state;
end if;
 
when "0110" => -- ACCA,R
case md(6 downto 5) is
when "00" =>
left_ctrl <= ix_left;
when "01" =>
left_ctrl <= iy_left;
when "10" =>
left_ctrl <= up_left;
when others =>
-- when "11" =>
left_ctrl <= sp_left;
end case;
right_ctrl <= acca_right;
alu_ctrl <= alu_add16;
ea_ctrl <= load_ea;
if md(4) = '0' then
st_ctrl <= pull_st;
next_state <= saved_state;
else
next_state <= indirect_state;
end if;
 
when "0111" => -- undefined
case md(6 downto 5) is
when "00" =>
left_ctrl <= ix_left;
when "01" =>
left_ctrl <= iy_left;
when "10" =>
left_ctrl <= up_left;
when others =>
-- when "11" =>
left_ctrl <= sp_left;
end case;
right_ctrl <= zero_right;
alu_ctrl <= alu_add16;
ea_ctrl <= load_ea;
if md(4) = '0' then
st_ctrl <= pull_st;
next_state <= saved_state;
else
next_state <= indirect_state;
end if;
 
when "1000" => -- offset8,R
md_ctrl <= fetch_first_md; -- pick up 8 bit offset
addr_ctrl <= fetch_ad;
pc_ctrl <= incr_pc;
next_state <= index8_state;
 
when "1001" => -- offset16,R
md_ctrl <= fetch_first_md; -- pick up first byte of 16 bit offset
addr_ctrl <= fetch_ad;
pc_ctrl <= incr_pc;
next_state <= index16_state;
 
when "1010" => -- undefined
case md(6 downto 5) is
when "00" =>
left_ctrl <= ix_left;
when "01" =>
left_ctrl <= iy_left;
when "10" =>
left_ctrl <= up_left;
when others =>
-- when "11" =>
left_ctrl <= sp_left;
end case;
right_ctrl <= zero_right;
alu_ctrl <= alu_add16;
ea_ctrl <= load_ea;
--
if md(4) = '0' then
st_ctrl <= pull_st;
next_state <= saved_state;
else
next_state <= indirect_state;
end if;
 
when "1011" => -- ACCD,R
case md(6 downto 5) is
when "00" =>
left_ctrl <= ix_left;
when "01" =>
left_ctrl <= iy_left;
when "10" =>
left_ctrl <= up_left;
when others =>
-- when "11" =>
left_ctrl <= sp_left;
end case;
right_ctrl <= accd_right;
alu_ctrl <= alu_add16;
ea_ctrl <= load_ea;
if md(4) = '0' then
st_ctrl <= pull_st;
next_state <= saved_state;
else
next_state <= indirect_state;
end if;
 
when "1100" => -- offset8,PC
-- fetch 8 bit offset
md_ctrl <= fetch_first_md;
addr_ctrl <= fetch_ad;
pc_ctrl <= incr_pc;
next_state <= pcrel8_state;
 
when "1101" => -- offset16,PC
-- fetch offset
md_ctrl <= fetch_first_md;
addr_ctrl <= fetch_ad;
pc_ctrl <= incr_pc;
next_state <= pcrel16_state;
 
when "1110" => -- undefined
case md(6 downto 5) is
when "00" =>
left_ctrl <= ix_left;
when "01" =>
left_ctrl <= iy_left;
when "10" =>
left_ctrl <= up_left;
when others =>
-- when "11" =>
left_ctrl <= sp_left;
end case;
right_ctrl <= zero_right;
alu_ctrl <= alu_add16;
ea_ctrl <= load_ea;
if md(4) = '0' then
st_ctrl <= pull_st;
next_state <= saved_state;
else
next_state <= indirect_state;
end if;
 
when others =>
-- when "1111" => -- [,address]
-- advance PC to pick up address
md_ctrl <= fetch_first_md;
addr_ctrl <= fetch_ad;
pc_ctrl <= incr_pc;
next_state <= indexaddr_state;
end case;
end if;
 
-- load index register with ea plus one
when postincr1_state =>
left_ctrl <= ea_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
case md(6 downto 5) is
when "00" =>
ix_ctrl <= load_ix;
when "01" =>
iy_ctrl <= load_iy;
when "10" =>
up_ctrl <= load_up;
when others =>
-- when "11" =>
sp_ctrl <= load_sp;
end case;
-- return to previous state
if md(4) = '0' then
st_ctrl <= pull_st;
next_state <= saved_state;
else
next_state <= indirect_state;
end if;
 
-- load index register with ea plus two
when postincr2_state =>
-- increment register by two (address)
left_ctrl <= ea_left;
right_ctrl <= two_right;
alu_ctrl <= alu_add16;
case md(6 downto 5) is
when "00" =>
ix_ctrl <= load_ix;
when "01" =>
iy_ctrl <= load_iy;
when "10" =>
up_ctrl <= load_up;
when others =>
-- when "11" =>
sp_ctrl <= load_sp;
end case;
-- return to previous state
if md(4) = '0' then
st_ctrl <= pull_st;
next_state <= saved_state;
else
next_state <= indirect_state;
end if;
--
-- ea = index register + md (8 bit signed offset)
-- ea holds post byte
--
when index8_state =>
case ea(6 downto 5) is
when "00" =>
left_ctrl <= ix_left;
when "01" =>
left_ctrl <= iy_left;
when "10" =>
left_ctrl <= up_left;
when others =>
-- when "11" =>
left_ctrl <= sp_left;
end case;
-- ea = index reg + md
right_ctrl <= md_sign8_right;
alu_ctrl <= alu_add16;
ea_ctrl <= load_ea;
-- return to previous state
if ea(4) = '0' then
st_ctrl <= pull_st;
next_state <= saved_state;
else
next_state <= indirect_state;
end if;
 
-- fetch low byte of 16 bit indexed offset
when index16_state =>
-- advance pc
pc_ctrl <= incr_pc;
-- fetch low byte
md_ctrl <= fetch_next_md;
addr_ctrl <= fetch_ad;
next_state <= index16_2_state;
 
-- ea = index register + md (16 bit offset)
-- ea holds post byte
when index16_2_state =>
case ea(6 downto 5) is
when "00" =>
left_ctrl <= ix_left;
when "01" =>
left_ctrl <= iy_left;
when "10" =>
left_ctrl <= up_left;
when others =>
-- when "11" =>
left_ctrl <= sp_left;
end case;
-- ea = index reg + md
right_ctrl <= md_right;
alu_ctrl <= alu_add16;
ea_ctrl <= load_ea;
-- return to previous state
if ea(4) = '0' then
st_ctrl <= pull_st;
next_state <= saved_state;
else
next_state <= indirect_state;
end if;
--
-- pc relative with 8 bit signed offest
-- md holds signed offset
--
when pcrel8_state =>
-- ea = pc + signed md
left_ctrl <= pc_left;
right_ctrl <= md_sign8_right;
alu_ctrl <= alu_add16;
ea_ctrl <= load_ea;
-- return to previous state
if ea(4) = '0' then
st_ctrl <= pull_st;
next_state <= saved_state;
else
next_state <= indirect_state;
end if;
 
-- pc relative addressing with 16 bit offset
-- pick up the low byte of the offset in md
-- advance the pc
when pcrel16_state =>
-- advance pc
pc_ctrl <= incr_pc;
-- fetch low byte
md_ctrl <= fetch_next_md;
addr_ctrl <= fetch_ad;
next_state <= pcrel16_2_state;
 
-- pc relative with16 bit signed offest
-- md holds signed offset
when pcrel16_2_state =>
-- ea = pc + md
left_ctrl <= pc_left;
right_ctrl <= md_right;
alu_ctrl <= alu_add16;
ea_ctrl <= load_ea;
-- return to previous state
if ea(4) = '0' then
st_ctrl <= pull_st;
next_state <= saved_state;
else
next_state <= indirect_state;
end if;
 
-- indexed to address
-- pick up the low byte of the address
-- advance the pc
when indexaddr_state =>
-- advance pc
pc_ctrl <= incr_pc;
-- fetch low byte
md_ctrl <= fetch_next_md;
addr_ctrl <= fetch_ad;
next_state <= indexaddr2_state;
 
-- indexed to absolute address
-- md holds address
-- ea hold indexing mode byte
when indexaddr2_state =>
-- ea = md
left_ctrl <= pc_left;
right_ctrl <= md_right;
alu_ctrl <= alu_ld16;
ea_ctrl <= load_ea;
-- return to previous state
if ea(4) = '0' then
st_ctrl <= pull_st;
next_state <= saved_state;
else
next_state <= indirect_state;
end if;
 
--
-- load md with high byte of indirect address
-- pointed to by ea
-- increment ea
--
when indirect_state =>
-- increment ea
left_ctrl <= ea_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
ea_ctrl <= load_ea;
-- fetch high byte
md_ctrl <= fetch_first_md;
addr_ctrl <= read_ad;
next_state <= indirect2_state;
--
-- load md with low byte of indirect address
-- pointed to by ea
-- ea has previously been incremented
--
when indirect2_state =>
-- fetch high byte
md_ctrl <= fetch_next_md;
addr_ctrl <= read_ad;
dout_ctrl <= md_lo_dout;
next_state <= indirect3_state;
--
-- complete idirect addressing
-- by loading ea with md
--
when indirect3_state =>
-- load ea with md
left_ctrl <= ea_left;
right_ctrl <= md_right;
alu_ctrl <= alu_ld16;
ea_ctrl <= load_ea;
-- return to previous state
st_ctrl <= pull_st;
next_state <= saved_state;
 
--
-- ea holds the low byte of the absolute address
-- Move ea low byte into ea high byte
-- load new ea low byte to for absolute 16 bit address
-- advance the program counter
--
when extended_state => -- fetch ea low byte
-- increment pc
pc_ctrl <= incr_pc;
-- fetch next effective address bytes
ea_ctrl <= fetch_next_ea;
addr_ctrl <= fetch_ad;
-- return to previous state
st_ctrl <= pull_st;
next_state <= saved_state;
 
when lea_state => -- here on load effective address
-- load index register with effective address
left_ctrl <= pc_left;
right_ctrl <= ea_right;
alu_ctrl <= alu_lea;
case op_code(3 downto 0) is
when "0000" => -- leax
cc_ctrl <= load_cc;
ix_ctrl <= load_ix;
when "0001" => -- leay
cc_ctrl <= load_cc;
iy_ctrl <= load_iy;
when "0010" => -- leas
sp_ctrl <= load_sp;
when "0011" => -- leau
up_ctrl <= load_up;
when others =>
null;
end case;
lic <= '1';
next_state <= fetch_state;
 
--
-- jump to subroutine
-- sp=sp-1
-- call push_return_lo_state to save pc
-- return to jmp_state
--
when jsr_state =>
-- decrement sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
sp_ctrl <= load_sp;
-- call push_return_state
st_ctrl <= push_st;
return_state <= jmp_state;
next_state <= push_return_lo_state;
 
--
-- Load pc with ea
-- (JMP)
--
when jmp_state =>
-- load PC with effective address
left_ctrl <= pc_left;
right_ctrl <= ea_right;
alu_ctrl <= alu_ld16;
pc_ctrl <= load_pc;
lic <= '1';
next_state <= fetch_state;
 
--
-- long branch or branch to subroutine
-- pick up next md byte
-- md_hi = md_lo
-- md_lo = (pc)
-- pc=pc+1
-- if a lbsr push return address
-- continue to sbranch_state
-- to evaluate conditional branches
--
when lbranch_state =>
pc_ctrl <= incr_pc;
-- fetch the next byte into md_lo
md_ctrl <= fetch_next_md;
addr_ctrl <= fetch_ad;
-- if lbsr - push return address
-- then continue on to short branch
if op_code = "00010111" then
st_ctrl <= push_st;
return_state <= sbranch_state;
next_state <= push_return_lo_state;
else
next_state <= sbranch_state;
end if;
 
--
-- here to execute conditional branch
-- short conditional branch md = signed 8 bit offset
-- long branch md = 16 bit offset
--
when sbranch_state =>
left_ctrl <= pc_left;
right_ctrl <= md_right;
alu_ctrl <= alu_add16;
-- Test condition for branch
if op_code(7 downto 4) = "0010" then -- conditional branch
case op_code(3 downto 0) is
when "0000" => -- bra
cond_true := (1 = 1);
when "0001" => -- brn
cond_true := (1 = 0);
when "0010" => -- bhi
cond_true := ((cc(CBIT) or cc(ZBIT)) = '0');
when "0011" => -- bls
cond_true := ((cc(CBIT) or cc(ZBIT)) = '1');
when "0100" => -- bcc/bhs
cond_true := (cc(CBIT) = '0');
when "0101" => -- bcs/blo
cond_true := (cc(CBIT) = '1');
when "0110" => -- bne
cond_true := (cc(ZBIT) = '0');
when "0111" => -- beq
cond_true := (cc(ZBIT) = '1');
when "1000" => -- bvc
cond_true := (cc(VBIT) = '0');
when "1001" => -- bvs
cond_true := (cc(VBIT) = '1');
when "1010" => -- bpl
cond_true := (cc(NBIT) = '0');
when "1011" => -- bmi
cond_true := (cc(NBIT) = '1');
when "1100" => -- bge
cond_true := ((cc(NBIT) xor cc(VBIT)) = '0');
when "1101" => -- blt
cond_true := ((cc(NBIT) xor cc(VBIT)) = '1');
when "1110" => -- bgt
cond_true := ((cc(ZBIT) or (cc(NBIT) xor cc(VBIT))) = '0');
when "1111" => -- ble
cond_true := ((cc(ZBIT) or (cc(NBIT) xor cc(VBIT))) = '1');
when others =>
null;
end case;
else
cond_true := (1 = 1); -- lbra, lbsr, bsr
end if;
if cond_true then
pc_ctrl <= load_pc;
end if;
lic <= '1';
next_state <= fetch_state;
 
--
-- push return address onto the S stack
--
-- (sp) = pc_lo
-- sp = sp - 1
--
when push_return_lo_state =>
-- decrement the sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
sp_ctrl <= load_sp;
-- write PC low
addr_ctrl <= pushs_ad;
dout_ctrl <= pc_lo_dout;
next_state <= push_return_hi_state;
 
--
-- push program counter hi byte onto the stack
-- (sp) = pc_hi
-- sp = sp
-- return to originating state
--
when push_return_hi_state =>
-- write pc hi bytes
addr_ctrl <= pushs_ad;
dout_ctrl <= pc_hi_dout;
st_ctrl <= pull_st;
next_state <= saved_state;
 
when pull_return_hi_state =>
-- increment the sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
sp_ctrl <= load_sp;
-- read pc hi
pc_ctrl <= pull_hi_pc;
addr_ctrl <= pulls_ad;
next_state <= pull_return_lo_state;
 
when pull_return_lo_state =>
-- increment the SP
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
sp_ctrl <= load_sp;
-- read pc low
pc_ctrl <= pull_lo_pc;
addr_ctrl <= pulls_ad;
dout_ctrl <= pc_lo_dout;
--
st_ctrl <= pull_st;
lic <= '1';
next_state <= saved_state;
 
when andcc_state =>
-- AND CC with md
left_ctrl <= md_left;
right_ctrl <= zero_right;
alu_ctrl <= alu_andcc;
cc_ctrl <= load_cc;
--
st_ctrl <= pull_st;
lic <= '1';
next_state <= saved_state;
 
when orcc_state =>
-- OR CC with md
left_ctrl <= md_left;
right_ctrl <= zero_right;
alu_ctrl <= alu_orcc;
cc_ctrl <= load_cc;
--
st_ctrl <= pull_st;
lic <= '1';
next_state <= saved_state;
 
when tfr_state =>
-- select source register
case md(7 downto 4) is
when "0000" =>
left_ctrl <= accd_left;
when "0001" =>
left_ctrl <= ix_left;
when "0010" =>
left_ctrl <= iy_left;
when "0011" =>
left_ctrl <= up_left;
when "0100" =>
left_ctrl <= sp_left;
when "0101" =>
left_ctrl <= pc_left;
when "1000" =>
left_ctrl <= acca_left;
when "1001" =>
left_ctrl <= accb_left;
when "1010" =>
left_ctrl <= cc_left;
when "1011" =>
left_ctrl <= dp_left;
when others =>
left_ctrl <= md_left;
end case;
right_ctrl <= zero_right;
alu_ctrl <= alu_tfr;
-- select destination register
case md(3 downto 0) is
when "0000" => -- accd
acca_ctrl <= load_hi_acca;
accb_ctrl <= load_accb;
when "0001" => -- ix
ix_ctrl <= load_ix;
when "0010" => -- iy
iy_ctrl <= load_iy;
when "0011" => -- up
up_ctrl <= load_up;
when "0100" => -- sp
sp_ctrl <= load_sp;
when "0101" => -- pc
pc_ctrl <= load_pc;
when "1000" => -- acca
acca_ctrl <= load_acca;
when "1001" => -- accb
accb_ctrl <= load_accb;
when "1010" => -- cc
cc_ctrl <= load_cc;
when "1011" => --dp
dp_ctrl <= load_dp;
when others =>
null;
end case;
--
st_ctrl <= pull_st;
lic <= '1';
next_state <= saved_state;
 
when exg_state =>
-- save destination register
case md(3 downto 0) is
when "0000" =>
left_ctrl <= accd_left;
when "0001" =>
left_ctrl <= ix_left;
when "0010" =>
left_ctrl <= iy_left;
when "0011" =>
left_ctrl <= up_left;
when "0100" =>
left_ctrl <= sp_left;
when "0101" =>
left_ctrl <= pc_left;
when "1000" =>
left_ctrl <= acca_left;
when "1001" =>
left_ctrl <= accb_left;
when "1010" =>
left_ctrl <= cc_left;
when "1011" =>
left_ctrl <= dp_left;
when others =>
left_ctrl <= md_left;
end case;
right_ctrl <= zero_right;
alu_ctrl <= alu_tfr;
ea_ctrl <= load_ea;
-- call tranfer microcode
st_ctrl <= push_st;
return_state <= exg1_state;
next_state <= tfr_state;
 
when exg1_state =>
-- restore destination
left_ctrl <= ea_left;
right_ctrl <= zero_right;
alu_ctrl <= alu_tfr;
-- save as source register
case md(7 downto 4) is
when "0000" => -- accd
acca_ctrl <= load_hi_acca;
accb_ctrl <= load_accb;
when "0001" => -- ix
ix_ctrl <= load_ix;
when "0010" => -- iy
iy_ctrl <= load_iy;
when "0011" => -- up
up_ctrl <= load_up;
when "0100" => -- sp
sp_ctrl <= load_sp;
when "0101" => -- pc
pc_ctrl <= load_pc;
when "1000" => -- acca
acca_ctrl <= load_acca;
when "1001" => -- accb
accb_ctrl <= load_accb;
when "1010" => -- cc
cc_ctrl <= load_cc;
when "1011" => --dp
dp_ctrl <= load_dp;
when others =>
null;
end case;
lic <= '1';
next_state <= fetch_state;
 
when mul_state =>
-- move acca to md
left_ctrl <= acca_left;
right_ctrl <= zero_right;
alu_ctrl <= alu_st16;
md_ctrl <= load_md;
next_state <= mulea_state;
 
when mulea_state =>
-- move accb to ea
left_ctrl <= accb_left;
right_ctrl <= zero_right;
alu_ctrl <= alu_st16;
ea_ctrl <= load_ea;
next_state <= muld_state;
 
when muld_state =>
-- clear accd
left_ctrl <= acca_left;
right_ctrl <= zero_right;
alu_ctrl <= alu_ld8;
acca_ctrl <= load_hi_acca;
accb_ctrl <= load_accb;
next_state <= mul0_state;
 
when mul0_state =>
-- if bit 0 of ea set, add accd to md
left_ctrl <= accd_left;
if ea(0) = '1' then
right_ctrl <= md_right;
else
right_ctrl <= zero_right;
end if;
alu_ctrl <= alu_mul;
cc_ctrl <= load_cc;
acca_ctrl <= load_hi_acca;
accb_ctrl <= load_accb;
md_ctrl <= shiftl_md;
next_state <= mul1_state;
 
when mul1_state =>
-- if bit 1 of ea set, add accd to md
left_ctrl <= accd_left;
if ea(1) = '1' then
right_ctrl <= md_right;
else
right_ctrl <= zero_right;
end if;
alu_ctrl <= alu_mul;
cc_ctrl <= load_cc;
acca_ctrl <= load_hi_acca;
accb_ctrl <= load_accb;
md_ctrl <= shiftl_md;
next_state <= mul2_state;
 
when mul2_state =>
-- if bit 2 of ea set, add accd to md
left_ctrl <= accd_left;
if ea(2) = '1' then
right_ctrl <= md_right;
else
right_ctrl <= zero_right;
end if;
alu_ctrl <= alu_mul;
cc_ctrl <= load_cc;
acca_ctrl <= load_hi_acca;
accb_ctrl <= load_accb;
md_ctrl <= shiftl_md;
next_state <= mul3_state;
 
when mul3_state =>
-- if bit 3 of ea set, add accd to md
left_ctrl <= accd_left;
if ea(3) = '1' then
right_ctrl <= md_right;
else
right_ctrl <= zero_right;
end if;
alu_ctrl <= alu_mul;
cc_ctrl <= load_cc;
acca_ctrl <= load_hi_acca;
accb_ctrl <= load_accb;
md_ctrl <= shiftl_md;
next_state <= mul4_state;
 
when mul4_state =>
-- if bit 4 of ea set, add accd to md
left_ctrl <= accd_left;
if ea(4) = '1' then
right_ctrl <= md_right;
else
right_ctrl <= zero_right;
end if;
alu_ctrl <= alu_mul;
cc_ctrl <= load_cc;
acca_ctrl <= load_hi_acca;
accb_ctrl <= load_accb;
md_ctrl <= shiftl_md;
next_state <= mul5_state;
 
when mul5_state =>
-- if bit 5 of ea set, add accd to md
left_ctrl <= accd_left;
if ea(5) = '1' then
right_ctrl <= md_right;
else
right_ctrl <= zero_right;
end if;
alu_ctrl <= alu_mul;
cc_ctrl <= load_cc;
acca_ctrl <= load_hi_acca;
accb_ctrl <= load_accb;
md_ctrl <= shiftl_md;
next_state <= mul6_state;
 
when mul6_state =>
-- if bit 6 of ea set, add accd to md
left_ctrl <= accd_left;
if ea(6) = '1' then
right_ctrl <= md_right;
else
right_ctrl <= zero_right;
end if;
alu_ctrl <= alu_mul;
cc_ctrl <= load_cc;
acca_ctrl <= load_hi_acca;
accb_ctrl <= load_accb;
md_ctrl <= shiftl_md;
next_state <= mul7_state;
 
when mul7_state =>
-- if bit 7 of ea set, add accd to md
left_ctrl <= accd_left;
if ea(7) = '1' then
right_ctrl <= md_right;
else
right_ctrl <= zero_right;
end if;
alu_ctrl <= alu_mul;
cc_ctrl <= load_cc;
acca_ctrl <= load_hi_acca;
accb_ctrl <= load_accb;
md_ctrl <= shiftl_md;
lic <= '1';
next_state <= fetch_state;
 
--
-- Enter here on pushs
-- ea holds post byte
--
when pshs_state =>
-- decrement sp if any registers to be pushed
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
-- idle address
addr_ctrl <= idle_ad;
dout_ctrl <= cc_dout;
if ea(7 downto 0) = "00000000" then
sp_ctrl <= latch_sp;
else
sp_ctrl <= load_sp;
end if;
if ea(7) = '1' then
next_state <= pshs_pcl_state;
elsif ea(6) = '1' then
next_state <= pshs_upl_state;
elsif ea(5) = '1' then
next_state <= pshs_iyl_state;
elsif ea(4) = '1' then
next_state <= pshs_ixl_state;
elsif ea(3) = '1' then
next_state <= pshs_dp_state;
elsif ea(2) = '1' then
next_state <= pshs_accb_state;
elsif ea(1) = '1' then
next_state <= pshs_acca_state;
elsif ea(0) = '1' then
next_state <= pshs_cc_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
 
when pshs_pcl_state =>
-- decrement sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
sp_ctrl <= load_sp;
-- write pc low
addr_ctrl <= pushs_ad;
dout_ctrl <= pc_lo_dout;
next_state <= pshs_pch_state;
 
when pshs_pch_state =>
-- decrement sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
if ea(6 downto 0) = "0000000" then
sp_ctrl <= latch_sp;
else
sp_ctrl <= load_sp;
end if;
-- write pc hi
addr_ctrl <= pushs_ad;
dout_ctrl <= pc_hi_dout;
if ea(6) = '1' then
next_state <= pshs_upl_state;
elsif ea(5) = '1' then
next_state <= pshs_iyl_state;
elsif ea(4) = '1' then
next_state <= pshs_ixl_state;
elsif ea(3) = '1' then
next_state <= pshs_dp_state;
elsif ea(2) = '1' then
next_state <= pshs_accb_state;
elsif ea(1) = '1' then
next_state <= pshs_acca_state;
elsif ea(0) = '1' then
next_state <= pshs_cc_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
 
 
when pshs_upl_state =>
-- decrement sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
sp_ctrl <= load_sp;
-- write pc low
addr_ctrl <= pushs_ad;
dout_ctrl <= up_lo_dout;
next_state <= pshs_uph_state;
 
when pshs_uph_state =>
-- decrement sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
if ea(5 downto 0) = "000000" then
sp_ctrl <= latch_sp;
else
sp_ctrl <= load_sp;
end if;
-- write pc hi
addr_ctrl <= pushs_ad;
dout_ctrl <= up_hi_dout;
if ea(5) = '1' then
next_state <= pshs_iyl_state;
elsif ea(4) = '1' then
next_state <= pshs_ixl_state;
elsif ea(3) = '1' then
next_state <= pshs_dp_state;
elsif ea(2) = '1' then
next_state <= pshs_accb_state;
elsif ea(1) = '1' then
next_state <= pshs_acca_state;
elsif ea(0) = '1' then
next_state <= pshs_cc_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
 
when pshs_iyl_state =>
-- decrement sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
sp_ctrl <= load_sp;
-- write iy low
addr_ctrl <= pushs_ad;
dout_ctrl <= iy_lo_dout;
next_state <= pshs_iyh_state;
 
when pshs_iyh_state =>
-- decrement sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
if ea(4 downto 0) = "00000" then
sp_ctrl <= latch_sp;
else
sp_ctrl <= load_sp;
end if;
-- write iy hi
addr_ctrl <= pushs_ad;
dout_ctrl <= iy_hi_dout;
if ea(4) = '1' then
next_state <= pshs_ixl_state;
elsif ea(3) = '1' then
next_state <= pshs_dp_state;
elsif ea(2) = '1' then
next_state <= pshs_accb_state;
elsif ea(1) = '1' then
next_state <= pshs_acca_state;
elsif ea(0) = '1' then
next_state <= pshs_cc_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
 
when pshs_ixl_state =>
-- decrement sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
sp_ctrl <= load_sp;
-- write ix low
addr_ctrl <= pushs_ad;
dout_ctrl <= ix_lo_dout;
next_state <= pshs_ixh_state;
 
when pshs_ixh_state =>
-- decrement sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
if ea(3 downto 0) = "0000" then
sp_ctrl <= latch_sp;
else
sp_ctrl <= load_sp;
end if;
-- write ix hi
addr_ctrl <= pushs_ad;
dout_ctrl <= ix_hi_dout;
if ea(3) = '1' then
next_state <= pshs_dp_state;
elsif ea(2) = '1' then
next_state <= pshs_accb_state;
elsif ea(1) = '1' then
next_state <= pshs_acca_state;
elsif ea(0) = '1' then
next_state <= pshs_cc_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
 
when pshs_dp_state =>
-- decrement sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
if ea(2 downto 0) = "000" then
sp_ctrl <= latch_sp;
else
sp_ctrl <= load_sp;
end if;
-- write dp
addr_ctrl <= pushs_ad;
dout_ctrl <= dp_dout;
if ea(2) = '1' then
next_state <= pshs_accb_state;
elsif ea(1) = '1' then
next_state <= pshs_acca_state;
elsif ea(0) = '1' then
next_state <= pshs_cc_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
 
when pshs_accb_state =>
-- decrement sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
if ea(1 downto 0) = "00" then
sp_ctrl <= latch_sp;
else
sp_ctrl <= load_sp;
end if;
-- write accb
addr_ctrl <= pushs_ad;
dout_ctrl <= accb_dout;
if ea(1) = '1' then
next_state <= pshs_acca_state;
elsif ea(0) = '1' then
next_state <= pshs_cc_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
 
when pshs_acca_state =>
-- decrement sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
if ea(0) = '1' then
sp_ctrl <= load_sp;
else
sp_ctrl <= latch_sp;
end if;
-- write acca
addr_ctrl <= pushs_ad;
dout_ctrl <= acca_dout;
if ea(0) = '1' then
next_state <= pshs_cc_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
 
when pshs_cc_state =>
-- idle sp
-- write cc
addr_ctrl <= pushs_ad;
dout_ctrl <= cc_dout;
lic <= '1';
next_state <= fetch_state;
 
--
-- enter here on PULS
-- ea hold register mask
--
when puls_state =>
if ea(0) = '1' then
next_state <= puls_cc_state;
elsif ea(1) = '1' then
next_state <= puls_acca_state;
elsif ea(2) = '1' then
next_state <= puls_accb_state;
elsif ea(3) = '1' then
next_state <= puls_dp_state;
elsif ea(4) = '1' then
next_state <= puls_ixh_state;
elsif ea(5) = '1' then
next_state <= puls_iyh_state;
elsif ea(6) = '1' then
next_state <= puls_uph_state;
elsif ea(7) = '1' then
next_state <= puls_pch_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
 
when puls_cc_state =>
-- increment sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
sp_ctrl <= load_sp;
-- read cc
cc_ctrl <= pull_cc;
addr_ctrl <= pulls_ad;
if ea(1) = '1' then
next_state <= puls_acca_state;
elsif ea(2) = '1' then
next_state <= puls_accb_state;
elsif ea(3) = '1' then
next_state <= puls_dp_state;
elsif ea(4) = '1' then
next_state <= puls_ixh_state;
elsif ea(5) = '1' then
next_state <= puls_iyh_state;
elsif ea(6) = '1' then
next_state <= puls_uph_state;
elsif ea(7) = '1' then
next_state <= puls_pch_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
 
when puls_acca_state =>
-- increment sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
sp_ctrl <= load_sp;
-- read acca
acca_ctrl <= pull_acca;
addr_ctrl <= pulls_ad;
if ea(2) = '1' then
next_state <= puls_accb_state;
elsif ea(3) = '1' then
next_state <= puls_dp_state;
elsif ea(4) = '1' then
next_state <= puls_ixh_state;
elsif ea(5) = '1' then
next_state <= puls_iyh_state;
elsif ea(6) = '1' then
next_state <= puls_uph_state;
elsif ea(7) = '1' then
next_state <= puls_pch_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
 
when puls_accb_state =>
-- increment sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
sp_ctrl <= load_sp;
-- read accb
accb_ctrl <= pull_accb;
addr_ctrl <= pulls_ad;
if ea(3) = '1' then
next_state <= puls_dp_state;
elsif ea(4) = '1' then
next_state <= puls_ixh_state;
elsif ea(5) = '1' then
next_state <= puls_iyh_state;
elsif ea(6) = '1' then
next_state <= puls_uph_state;
elsif ea(7) = '1' then
next_state <= puls_pch_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
 
when puls_dp_state =>
-- increment sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
sp_ctrl <= load_sp;
-- read dp
dp_ctrl <= pull_dp;
addr_ctrl <= pulls_ad;
if ea(4) = '1' then
next_state <= puls_ixh_state;
elsif ea(5) = '1' then
next_state <= puls_iyh_state;
elsif ea(6) = '1' then
next_state <= puls_uph_state;
elsif ea(7) = '1' then
next_state <= puls_pch_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
 
when puls_ixh_state =>
-- increment sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
sp_ctrl <= load_sp;
-- pull ix hi
ix_ctrl <= pull_hi_ix;
addr_ctrl <= pulls_ad;
next_state <= puls_ixl_state;
 
when puls_ixl_state =>
-- increment sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
sp_ctrl <= load_sp;
-- read ix low
ix_ctrl <= pull_lo_ix;
addr_ctrl <= pulls_ad;
if ea(5) = '1' then
next_state <= puls_iyh_state;
elsif ea(6) = '1' then
next_state <= puls_uph_state;
elsif ea(7) = '1' then
next_state <= puls_pch_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
 
when puls_iyh_state =>
-- increment sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
sp_ctrl <= load_sp;
-- pull iy hi
iy_ctrl <= pull_hi_iy;
addr_ctrl <= pulls_ad;
next_state <= puls_iyl_state;
 
when puls_iyl_state =>
-- increment sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
sp_ctrl <= load_sp;
-- read iy low
iy_ctrl <= pull_lo_iy;
addr_ctrl <= pulls_ad;
if ea(6) = '1' then
next_state <= puls_uph_state;
elsif ea(7) = '1' then
next_state <= puls_pch_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
 
when puls_uph_state =>
-- increment sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
sp_ctrl <= load_sp;
-- pull up hi
up_ctrl <= pull_hi_up;
addr_ctrl <= pulls_ad;
next_state <= puls_upl_state;
 
when puls_upl_state =>
-- increment sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
sp_ctrl <= load_sp;
-- read up low
up_ctrl <= pull_lo_up;
addr_ctrl <= pulls_ad;
if ea(7) = '1' then
next_state <= puls_pch_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
 
when puls_pch_state =>
-- increment sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
sp_ctrl <= load_sp;
-- pull pc hi
pc_ctrl <= pull_hi_pc;
addr_ctrl <= pulls_ad;
next_state <= puls_pcl_state;
 
when puls_pcl_state =>
-- increment sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
sp_ctrl <= load_sp;
-- read pc low
pc_ctrl <= pull_lo_pc;
addr_ctrl <= pulls_ad;
lic <= '1';
next_state <= fetch_state;
 
--
-- Enter here on pshu
-- ea holds post byte
--
when pshu_state =>
-- decrement up if any registers to be pushed
left_ctrl <= up_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
if ea(7 downto 0) = "00000000" then
up_ctrl <= latch_up;
else
up_ctrl <= load_up;
end if;
-- write idle bus
if ea(7) = '1' then
next_state <= pshu_pcl_state;
elsif ea(6) = '1' then
next_state <= pshu_spl_state;
elsif ea(5) = '1' then
next_state <= pshu_iyl_state;
elsif ea(4) = '1' then
next_state <= pshu_ixl_state;
elsif ea(3) = '1' then
next_state <= pshu_dp_state;
elsif ea(2) = '1' then
next_state <= pshu_accb_state;
elsif ea(1) = '1' then
next_state <= pshu_acca_state;
elsif ea(0) = '1' then
next_state <= pshu_cc_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
--
-- push PC onto U stack
--
when pshu_pcl_state =>
-- decrement up
left_ctrl <= up_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
up_ctrl <= load_up;
-- write pc low
addr_ctrl <= pushu_ad;
dout_ctrl <= pc_lo_dout;
next_state <= pshu_pch_state;
 
when pshu_pch_state =>
-- decrement up
left_ctrl <= up_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
if ea(6 downto 0) = "0000000" then
up_ctrl <= latch_up;
else
up_ctrl <= load_up;
end if;
-- write pc hi
addr_ctrl <= pushu_ad;
dout_ctrl <= pc_hi_dout;
if ea(6) = '1' then
next_state <= pshu_spl_state;
elsif ea(5) = '1' then
next_state <= pshu_iyl_state;
elsif ea(4) = '1' then
next_state <= pshu_ixl_state;
elsif ea(3) = '1' then
next_state <= pshu_dp_state;
elsif ea(2) = '1' then
next_state <= pshu_accb_state;
elsif ea(1) = '1' then
next_state <= pshu_acca_state;
elsif ea(0) = '1' then
next_state <= pshu_cc_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
 
when pshu_spl_state =>
-- decrement up
left_ctrl <= up_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
up_ctrl <= load_up;
-- write sp low
addr_ctrl <= pushu_ad;
dout_ctrl <= sp_lo_dout;
next_state <= pshu_sph_state;
 
when pshu_sph_state =>
-- decrement up
left_ctrl <= up_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
if ea(5 downto 0) = "000000" then
up_ctrl <= latch_up;
else
up_ctrl <= load_up;
end if;
-- write sp hi
addr_ctrl <= pushu_ad;
dout_ctrl <= sp_hi_dout;
if ea(5) = '1' then
next_state <= pshu_iyl_state;
elsif ea(4) = '1' then
next_state <= pshu_ixl_state;
elsif ea(3) = '1' then
next_state <= pshu_dp_state;
elsif ea(2) = '1' then
next_state <= pshu_accb_state;
elsif ea(1) = '1' then
next_state <= pshu_acca_state;
elsif ea(0) = '1' then
next_state <= pshu_cc_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
 
when pshu_iyl_state =>
-- decrement up
left_ctrl <= up_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
up_ctrl <= load_up;
-- write iy low
addr_ctrl <= pushu_ad;
dout_ctrl <= iy_lo_dout;
next_state <= pshu_iyh_state;
 
when pshu_iyh_state =>
-- decrement up
left_ctrl <= up_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
if ea(4 downto 0) = "00000" then
up_ctrl <= latch_up;
else
up_ctrl <= load_up;
end if;
-- write iy hi
addr_ctrl <= pushu_ad;
dout_ctrl <= iy_hi_dout;
if ea(4) = '1' then
next_state <= pshu_ixl_state;
elsif ea(3) = '1' then
next_state <= pshu_dp_state;
elsif ea(2) = '1' then
next_state <= pshu_accb_state;
elsif ea(1) = '1' then
next_state <= pshu_acca_state;
elsif ea(0) = '1' then
next_state <= pshu_cc_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
 
when pshu_ixl_state =>
-- decrement up
left_ctrl <= up_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
up_ctrl <= load_up;
-- write ix low
addr_ctrl <= pushu_ad;
dout_ctrl <= ix_lo_dout;
next_state <= pshu_ixh_state;
 
when pshu_ixh_state =>
-- decrement up
left_ctrl <= up_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
if ea(3 downto 0) = "0000" then
up_ctrl <= latch_up;
else
up_ctrl <= load_up;
end if;
-- write ix hi
addr_ctrl <= pushu_ad;
dout_ctrl <= ix_hi_dout;
if ea(3) = '1' then
next_state <= pshu_dp_state;
elsif ea(2) = '1' then
next_state <= pshu_accb_state;
elsif ea(1) = '1' then
next_state <= pshu_acca_state;
elsif ea(0) = '1' then
next_state <= pshu_cc_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
 
when pshu_dp_state =>
-- decrement up
left_ctrl <= up_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
if ea(2 downto 0) = "000" then
up_ctrl <= latch_up;
else
up_ctrl <= load_up;
end if;
-- write dp
addr_ctrl <= pushu_ad;
dout_ctrl <= dp_dout;
if ea(2) = '1' then
next_state <= pshu_accb_state;
elsif ea(1) = '1' then
next_state <= pshu_acca_state;
elsif ea(0) = '1' then
next_state <= pshu_cc_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
 
when pshu_accb_state =>
-- decrement up
left_ctrl <= up_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
if ea(1 downto 0) = "00" then
up_ctrl <= latch_up;
else
up_ctrl <= load_up;
end if;
-- write accb
addr_ctrl <= pushu_ad;
dout_ctrl <= accb_dout;
if ea(1) = '1' then
next_state <= pshu_acca_state;
elsif ea(0) = '1' then
next_state <= pshu_cc_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
 
when pshu_acca_state =>
-- decrement up
left_ctrl <= up_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
if ea(0) = '0' then
up_ctrl <= latch_up;
else
up_ctrl <= load_up;
end if;
-- write acca
addr_ctrl <= pushu_ad;
dout_ctrl <= acca_dout;
if ea(0) = '1' then
next_state <= pshu_cc_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
 
when pshu_cc_state =>
-- idle up
-- write cc
addr_ctrl <= pushu_ad;
dout_ctrl <= cc_dout;
lic <= '1';
next_state <= fetch_state;
 
--
-- enter here on PULU
-- ea hold register mask
--
when pulu_state =>
-- idle UP
-- idle bus
if ea(0) = '1' then
next_state <= pulu_cc_state;
elsif ea(1) = '1' then
next_state <= pulu_acca_state;
elsif ea(2) = '1' then
next_state <= pulu_accb_state;
elsif ea(3) = '1' then
next_state <= pulu_dp_state;
elsif ea(4) = '1' then
next_state <= pulu_ixh_state;
elsif ea(5) = '1' then
next_state <= pulu_iyh_state;
elsif ea(6) = '1' then
next_state <= pulu_sph_state;
elsif ea(7) = '1' then
next_state <= pulu_pch_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
 
when pulu_cc_state =>
-- increment up
left_ctrl <= up_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
up_ctrl <= load_up;
-- read cc
cc_ctrl <= pull_cc;
addr_ctrl <= pullu_ad;
if ea(1) = '1' then
next_state <= pulu_acca_state;
elsif ea(2) = '1' then
next_state <= pulu_accb_state;
elsif ea(3) = '1' then
next_state <= pulu_dp_state;
elsif ea(4) = '1' then
next_state <= pulu_ixh_state;
elsif ea(5) = '1' then
next_state <= pulu_iyh_state;
elsif ea(6) = '1' then
next_state <= pulu_sph_state;
elsif ea(7) = '1' then
next_state <= pulu_pch_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
 
when pulu_acca_state =>
-- increment up
left_ctrl <= up_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
up_ctrl <= load_up;
-- read acca
acca_ctrl <= pull_acca;
addr_ctrl <= pullu_ad;
if ea(2) = '1' then
next_state <= pulu_accb_state;
elsif ea(3) = '1' then
next_state <= pulu_dp_state;
elsif ea(4) = '1' then
next_state <= pulu_ixh_state;
elsif ea(5) = '1' then
next_state <= pulu_iyh_state;
elsif ea(6) = '1' then
next_state <= pulu_sph_state;
elsif ea(7) = '1' then
next_state <= pulu_pch_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
 
when pulu_accb_state =>
-- increment up
left_ctrl <= up_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
up_ctrl <= load_up;
-- read accb
accb_ctrl <= pull_accb;
addr_ctrl <= pullu_ad;
if ea(3) = '1' then
next_state <= pulu_dp_state;
elsif ea(4) = '1' then
next_state <= pulu_ixh_state;
elsif ea(5) = '1' then
next_state <= pulu_iyh_state;
elsif ea(6) = '1' then
next_state <= pulu_sph_state;
elsif ea(7) = '1' then
next_state <= pulu_pch_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
 
when pulu_dp_state =>
-- increment up
left_ctrl <= up_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
up_ctrl <= load_up;
-- read dp
dp_ctrl <= pull_dp;
addr_ctrl <= pullu_ad;
if ea(4) = '1' then
next_state <= pulu_ixh_state;
elsif ea(5) = '1' then
next_state <= pulu_iyh_state;
elsif ea(6) = '1' then
next_state <= pulu_sph_state;
elsif ea(7) = '1' then
next_state <= pulu_pch_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
 
when pulu_ixh_state =>
-- increment up
left_ctrl <= up_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
up_ctrl <= load_up;
-- read ix hi
ix_ctrl <= pull_hi_ix;
addr_ctrl <= pullu_ad;
next_state <= pulu_ixl_state;
 
when pulu_ixl_state =>
-- increment up
left_ctrl <= up_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
up_ctrl <= load_up;
-- read ix low
ix_ctrl <= pull_lo_ix;
addr_ctrl <= pullu_ad;
if ea(5) = '1' then
next_state <= pulu_iyh_state;
elsif ea(6) = '1' then
next_state <= pulu_sph_state;
elsif ea(7) = '1' then
next_state <= pulu_pch_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
 
when pulu_iyh_state =>
-- increment up
left_ctrl <= up_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
up_ctrl <= load_up;
-- read iy hi
iy_ctrl <= pull_hi_iy;
addr_ctrl <= pullu_ad;
next_state <= pulu_iyl_state;
 
when pulu_iyl_state =>
-- increment up
left_ctrl <= up_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
up_ctrl <= load_up;
-- read iy low
iy_ctrl <= pull_lo_iy;
addr_ctrl <= pullu_ad;
if ea(6) = '1' then
next_state <= pulu_sph_state;
elsif ea(7) = '1' then
next_state <= pulu_pch_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
 
when pulu_sph_state =>
-- increment up
left_ctrl <= up_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
up_ctrl <= load_up;
-- read sp hi
sp_ctrl <= pull_hi_sp;
addr_ctrl <= pullu_ad;
next_state <= pulu_spl_state;
 
when pulu_spl_state =>
-- increment up
left_ctrl <= up_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
up_ctrl <= load_up;
-- read sp low
sp_ctrl <= pull_lo_sp;
addr_ctrl <= pullu_ad;
if ea(7) = '1' then
next_state <= pulu_pch_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
 
when pulu_pch_state =>
-- increment up
left_ctrl <= up_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
up_ctrl <= load_up;
-- pull pc hi
pc_ctrl <= pull_hi_pc;
addr_ctrl <= pullu_ad;
next_state <= pulu_pcl_state;
 
when pulu_pcl_state =>
-- increment up
left_ctrl <= up_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
up_ctrl <= load_up;
-- read pc low
pc_ctrl <= pull_lo_pc;
addr_ctrl <= pullu_ad;
lic <= '1';
next_state <= fetch_state;
 
--
-- pop the Condition codes
--
when rti_cc_state =>
-- increment sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
sp_ctrl <= load_sp;
-- read cc
cc_ctrl <= pull_cc;
addr_ctrl <= pulls_ad;
next_state <= rti_entire_state;
 
--
-- Added RTI cycle 11th July 2006 John Kent.
-- test the "Entire" Flag
-- that has just been popped off the stack
--
when rti_entire_state =>
--
-- The Entire flag must be recovered from the stack
-- before testing.
--
if cc(EBIT) = '1' then
next_state <= rti_acca_state;
else
next_state <= rti_pch_state;
end if;
 
when rti_acca_state =>
-- increment sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
sp_ctrl <= load_sp;
-- read acca
acca_ctrl <= pull_acca;
addr_ctrl <= pulls_ad;
next_state <= rti_accb_state;
 
when rti_accb_state =>
-- increment sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
sp_ctrl <= load_sp;
-- read accb
accb_ctrl <= pull_accb;
addr_ctrl <= pulls_ad;
next_state <= rti_dp_state;
 
when rti_dp_state =>
-- increment sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
sp_ctrl <= load_sp;
-- read dp
dp_ctrl <= pull_dp;
addr_ctrl <= pulls_ad;
next_state <= rti_ixh_state;
 
when rti_ixh_state =>
-- increment sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
sp_ctrl <= load_sp;
-- read ix hi
ix_ctrl <= pull_hi_ix;
addr_ctrl <= pulls_ad;
next_state <= rti_ixl_state;
 
when rti_ixl_state =>
-- increment sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
sp_ctrl <= load_sp;
-- read ix low
ix_ctrl <= pull_lo_ix;
addr_ctrl <= pulls_ad;
next_state <= rti_iyh_state;
 
when rti_iyh_state =>
-- increment sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
sp_ctrl <= load_sp;
-- read iy hi
iy_ctrl <= pull_hi_iy;
addr_ctrl <= pulls_ad;
next_state <= rti_iyl_state;
 
when rti_iyl_state =>
-- increment sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
sp_ctrl <= load_sp;
-- read iy low
iy_ctrl <= pull_lo_iy;
addr_ctrl <= pulls_ad;
next_state <= rti_uph_state;
 
 
when rti_uph_state =>
-- increment sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
sp_ctrl <= load_sp;
-- read up hi
up_ctrl <= pull_hi_up;
addr_ctrl <= pulls_ad;
next_state <= rti_upl_state;
 
when rti_upl_state =>
-- increment sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
sp_ctrl <= load_sp;
-- read up low
up_ctrl <= pull_lo_up;
addr_ctrl <= pulls_ad;
next_state <= rti_pch_state;
 
when rti_pch_state =>
-- increment sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
sp_ctrl <= load_sp;
-- pull pc hi
pc_ctrl <= pull_hi_pc;
addr_ctrl <= pulls_ad;
next_state <= rti_pcl_state;
 
when rti_pcl_state =>
-- increment sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_add16;
sp_ctrl <= load_sp;
-- pull pc low
pc_ctrl <= pull_lo_pc;
addr_ctrl <= pulls_ad;
lic <= '1';
next_state <= fetch_state;
 
--
-- here on IRQ or NMI interrupt
-- pre decrement the sp
-- Idle bus cycle
--
when int_nmiirq_state =>
-- decrement sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
sp_ctrl <= load_sp;
next_state <= int_entire_state;
 
--
-- set Entire Flag on SWI, SWI2, SWI3 and CWAI, IRQ and NMI
-- clear Entire Flag on FIRQ
-- before stacking all registers
--
when int_entire_state =>
-- set entire flag
alu_ctrl <= alu_see;
cc_ctrl <= load_cc;
next_state <= int_pcl_state;
 
--
-- here on FIRQ interrupt
-- pre decrement the sp
-- Idle bus cycle
--
when int_firq_state =>
-- decrement sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
sp_ctrl <= load_sp;
next_state <= int_fast_state;
--
-- clear Entire Flag on FIRQ
-- before stacking all registers
--
when int_fast_state =>
-- clear entire flag
alu_ctrl <= alu_cle;
cc_ctrl <= load_cc;
next_state <= int_pcl_state;
 
when int_pcl_state =>
-- decrement sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
sp_ctrl <= load_sp;
-- write pc low
addr_ctrl <= pushs_ad;
dout_ctrl <= pc_lo_dout;
next_state <= int_pch_state;
 
when int_pch_state =>
-- decrement sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
sp_ctrl <= load_sp;
-- write pc hi
addr_ctrl <= pushs_ad;
dout_ctrl <= pc_hi_dout;
if cc(EBIT) = '1' then
next_state <= int_upl_state;
else
next_state <= int_cc_state;
end if;
 
when int_upl_state =>
-- decrement sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
sp_ctrl <= load_sp;
-- write up low
addr_ctrl <= pushs_ad;
dout_ctrl <= up_lo_dout;
next_state <= int_uph_state;
 
when int_uph_state =>
-- decrement sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
sp_ctrl <= load_sp;
-- write ix hi
addr_ctrl <= pushs_ad;
dout_ctrl <= up_hi_dout;
next_state <= int_iyl_state;
 
when int_iyl_state =>
-- decrement sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
sp_ctrl <= load_sp;
-- write ix low
addr_ctrl <= pushs_ad;
dout_ctrl <= iy_lo_dout;
next_state <= int_iyh_state;
 
when int_iyh_state =>
-- decrement sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
sp_ctrl <= load_sp;
-- write ix hi
addr_ctrl <= pushs_ad;
dout_ctrl <= iy_hi_dout;
next_state <= int_ixl_state;
 
when int_ixl_state =>
-- decrement sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
sp_ctrl <= load_sp;
-- write ix low
addr_ctrl <= pushs_ad;
dout_ctrl <= ix_lo_dout;
next_state <= int_ixh_state;
 
when int_ixh_state =>
-- decrement sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
sp_ctrl <= load_sp;
-- write ix hi
addr_ctrl <= pushs_ad;
dout_ctrl <= ix_hi_dout;
next_state <= int_dp_state;
 
when int_dp_state =>
-- decrement sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
sp_ctrl <= load_sp;
-- write accb
addr_ctrl <= pushs_ad;
dout_ctrl <= dp_dout;
next_state <= int_accb_state;
 
when int_accb_state =>
-- decrement sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
sp_ctrl <= load_sp;
-- write accb
addr_ctrl <= pushs_ad;
dout_ctrl <= accb_dout;
next_state <= int_acca_state;
 
when int_acca_state =>
-- decrement sp
left_ctrl <= sp_left;
right_ctrl <= one_right;
alu_ctrl <= alu_sub16;
sp_ctrl <= load_sp;
-- write acca
addr_ctrl <= pushs_ad;
dout_ctrl <= acca_dout;
next_state <= int_cc_state;
 
when int_cc_state =>
-- write cc
addr_ctrl <= pushs_ad;
dout_ctrl <= cc_dout;
case iv is
when NMI_VEC =>
next_state <= int_maskif_state;
when SWI_VEC =>
next_state <= int_maskif_state;
when FIRQ_VEC =>
next_state <= int_maskif_state;
when IRQ_VEC =>
next_state <= int_maski_state;
when SWI2_VEC =>
next_state <= vect_hi_state;
when SWI3_VEC =>
next_state <= vect_hi_state;
when others =>
if op_code = "00111100" then -- CWAI
next_state <= int_cwai_state;
else
next_state <= rti_cc_state; -- spurious interrupt, do a RTI
end if;
end case;
 
--
-- wait here for an inteerupt
--
when int_cwai_state =>
if (nmi_req = '1') and (nmi_ack='0') then
iv_ctrl <= nmi_iv;
nmi_ctrl <= set_nmi;
next_state <= int_maskif_state;
else
--
-- nmi request is not cleared until nmi input goes low
--
if (nmi_req = '0') and (nmi_ack='1') then
nmi_ctrl <= reset_nmi;
end if;
--
-- FIRQ is level sensitive
--
if (firq = '1') and (cc(FBIT) = '0') then
iv_ctrl <= firq_iv;
next_state <= int_maskif_state;
--
-- IRQ is level sensitive
--
elsif (irq = '1') and (cc(IBIT) = '0') then
iv_ctrl <= irq_iv;
next_state <= int_maski_state;
else
iv_ctrl <= reset_iv;
next_state <= int_cwai_state;
end if;
end if;
 
when int_maski_state =>
alu_ctrl <= alu_sei;
cc_ctrl <= load_cc;
next_state <= vect_hi_state;
 
when int_maskif_state =>
alu_ctrl <= alu_seif;
cc_ctrl <= load_cc;
next_state <= vect_hi_state;
 
--
-- According to the 6809 programming manual:
-- If an interrupt is received and is masked
-- or lasts for less than three cycles, the PC
-- will advance to the next instruction.
-- If an interrupt is unmasked and lasts
-- for more than three cycles, an interrupt
-- will be generated.
-- Note that I don't wait 3 clock cycles.
-- John Kent 11th July 2006
--
when sync_state =>
if (nmi_req = '1') and (nmi_ack='0') then
iv_ctrl <= nmi_iv;
nmi_ctrl <= set_nmi;
next_state <= int_nmiirq_state;
else
--
-- nmi request is not cleared until nmi input goes low
--
if (nmi_req = '0') and (nmi_ack='1') then
iv_ctrl <= reset_iv;
nmi_ctrl <= reset_nmi;
end if;
--
-- FIRQ is level sensitive
--
if (firq = '1') then
if (cc(FBIT) = '0') then
iv_ctrl <= firq_iv;
next_state <= int_firq_state;
else
iv_ctrl <= reset_iv;
lic <= '1';
next_state <= fetch_state;
end if;
--
-- IRQ is level sensitive
--
elsif (irq = '1') then
if (cc(IBIT) = '0') then
iv_ctrl <= irq_iv;
next_state <= int_nmiirq_state;
else
iv_ctrl <= reset_iv;
lic <= '1';
next_state <= fetch_state;
end if;
else
iv_ctrl <= reset_iv;
ba <= '1';
next_state <= sync_state;
end if;
end if;
 
 
when halt_state =>
if halt = '1' then
ba <= '1';
bs <= '1';
next_state <= halt_state;
else
lic <= '1';
next_state <= fetch_state;
end if;
 
when others => -- halt on undefine states
next_state <= error_state;
end case;
end process;
 
end rtl;

powered by: WebSVN 2.1.0

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