diff --git a/Computer_MiST/Acorn - Archimedes_MiST/README.txt b/Computer_MiST/Acorn - Archimedes_MiST/README.txt
deleted file mode 100644
index 8a3110fe..00000000
--- a/Computer_MiST/Acorn - Archimedes_MiST/README.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Acorn - Archimedes in FPGA
-
-FPGA Board: Mist FPGA
-
-Changed Clocks Source Code is the same like MiST Github Repo
diff --git a/Computer_MiST/Acorn - Archimedes_MiST/Release/archimedes.rbf b/Computer_MiST/Acorn - Archimedes_MiST/Release/archimedes.rbf
deleted file mode 100644
index 6c6627e7..00000000
Binary files a/Computer_MiST/Acorn - Archimedes_MiST/Release/archimedes.rbf and /dev/null differ
diff --git a/Computer_MiST/Galaksija_MiST/rtl/ay8912.vhd b/Computer_MiST/Galaksija_MiST/rtl/ay8912.vhd
new file mode 100644
index 00000000..9cd0a82e
--- /dev/null
+++ b/Computer_MiST/Galaksija_MiST/rtl/ay8912.vhd
@@ -0,0 +1,380 @@
+------------------------------------------------------------------------------
+------------------------------------------------------------------------------
+-- --
+-- Copyright (c) 2005-2009 Tobias Gubener --
+-- Subdesign CPC T-REX by TobiFlex --
+-- --
+-- This source file 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 source file 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 . --
+-- --
+------------------------------------------------------------------------------
+------------------------------------------------------------------------------
+
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+
+entity ay8912 is
+ port (
+ cpuclk : in STD_LOGIC; --48MHz
+ reset : in STD_LOGIC;
+ cs : in STD_LOGIC; --H-aktiv
+ bc0 : in STD_LOGIC; --
+ bdir : in STD_LOGIC;
+ Data_in : in STD_LOGIC_VECTOR (7 downto 0);
+ Data_out : out STD_LOGIC_VECTOR (7 downto 0);
+ IO_A : in STD_LOGIC_VECTOR (7 downto 0);
+ chanA : buffer STD_LOGIC_VECTOR (10 downto 0);
+ chanB : buffer STD_LOGIC_VECTOR (10 downto 0);
+ chanC : buffer STD_LOGIC_VECTOR (10 downto 0);
+ Arechts : out STD_LOGIC_VECTOR (15 downto 0);
+ Alinks : out STD_LOGIC_VECTOR (15 downto 0);
+ Amono : out STD_LOGIC_VECTOR (15 downto 0)
+ );
+end ay8912;
+
+architecture logic of ay8912 is
+signal t_Data : STD_LOGIC_VECTOR (7 downto 0);
+signal PSGReg : STD_LOGIC_VECTOR (3 downto 0);
+signal APeriode : STD_LOGIC_VECTOR (11 downto 0); --Reg 0,1
+signal BPeriode : STD_LOGIC_VECTOR (11 downto 0); --Reg 2,3
+signal CPeriode : STD_LOGIC_VECTOR (11 downto 0); --Reg 4,5
+signal Noise : STD_LOGIC_VECTOR (4 downto 0); --Reg 6
+signal enable : STD_LOGIC_VECTOR (7 downto 0); --Reg 7
+signal AVol : STD_LOGIC_VECTOR (4 downto 0); --Reg 8
+signal BVol : STD_LOGIC_VECTOR (4 downto 0); --Reg 9
+signal CVol : STD_LOGIC_VECTOR (4 downto 0); --Reg 10
+signal HPeriode : STD_LOGIC_VECTOR (15 downto 0); --Reg 11,12
+signal HKurve : STD_LOGIC_VECTOR (3 downto 0); --Reg 13
+signal PortA : STD_LOGIC_VECTOR (7 downto 0); --Reg 14
+signal PortB : STD_LOGIC_VECTOR (7 downto 0); --Reg 15
+signal AVollog : STD_LOGIC_VECTOR (9 downto 0); --Reg 8log
+signal BVollog : STD_LOGIC_VECTOR (9 downto 0); --Reg 9log
+signal CVollog : STD_LOGIC_VECTOR (9 downto 0); --Reg 10log
+signal Alog : STD_LOGIC_VECTOR (9 downto 0);
+signal Blog : STD_LOGIC_VECTOR (9 downto 0);
+signal Clog : STD_LOGIC_VECTOR (9 downto 0);
+signal HVollog : STD_LOGIC_VECTOR (11 downto 0);
+signal ACount : STD_LOGIC_VECTOR (11 downto 0);
+signal BCount : STD_LOGIC_VECTOR (11 downto 0);
+signal CCount : STD_LOGIC_VECTOR (11 downto 0);
+signal NCount : STD_LOGIC_VECTOR (4 downto 0);
+signal HCount : STD_LOGIC_VECTOR (15 downto 0);
+signal HVol : STD_LOGIC_VECTOR (4 downto 0);
+signal nHVol : STD_LOGIC_VECTOR (3 downto 0);
+signal HStart : STD_LOGIC;
+signal Noisebit : STD_LOGIC;
+signal RNG : STD_LOGIC_VECTOR (16 downto 0);
+signal Anot, Bnot, Cnot : STD_LOGIC;
+signal n_setreg : STD_LOGIC;
+signal n_Pegel : STD_LOGIC_VECTOR (11 downto 0);
+
+signal clockgen : STD_LOGIC_VECTOR (9 downto 0);
+signal S_Tick : STD_LOGIC;
+signal H_Tick : STD_LOGIC;
+
+
+
+begin
+
+-------------------------------------------------------------------------
+--Clock gen
+-------------------------------------------------------------------------
+process (cpuclk, clockgen)
+begin
+ S_Tick <= '0'; --sound
+ H_Tick <= '0'; --Hüllkurve
+ IF clockgen(9 downto 1)=0 THEN
+ S_Tick <= '1';
+ IF clockgen(0)='0' THEN
+ H_Tick <= '1';
+ END IF;
+ END IF;
+ IF rising_edge(cpuclk) THEN
+ Arechts <= (chanA&"00000")+('0'&chanB&"0000");
+ Alinks <= (chanC&"00000")+('0'&chanB&"0000");
+ Amono <= (chanC&"00000")+('0'&chanB&"0000")+(chanA&"00000");
+ IF H_Tick='1' THEN
+-- clockgen <= ((48*16)-1); --48MHz
+ clockgen <= "1011111111"; --48MHz
+ ELSE
+ clockgen <= clockgen-1;
+ END IF;
+ END IF;
+END process;
+-------------------------------------------------------------------------
+--IO Regs
+-------------------------------------------------------------------------
+process (cpuclk, reset, IO_A, PortA, PortB, Aperiode, Bperiode, Cperiode, Hperiode, AVol, BVol, CVol, Noise, HKurve, enable, Data_in, t_Data, PSGReg, bdir, bc0)
+begin
+ IF reset='0' THEN
+ enable <= (others => '0');
+ PortA <= "11111111";
+ PortB <= "11111111";
+ ELSIF rising_edge(cpuclk) THEN
+ HStart <= '0';
+ IF bdir='1' AND bc0='1' THEN
+ IF Data_in(7 downto 4)="0000" THEN
+ PSGReg <= Data_in(3 downto 0);
+ END IF;
+ ELSE
+ IF bdir='1' AND bc0='0' THEN
+ CASE PSGReg IS
+ WHEN "0000" =>
+ APeriode(7 downto 0) <= Data_in;
+ WHEN "0001" =>
+ APeriode(11 downto 8) <= Data_in(3 downto 0);
+ WHEN "0010" =>
+ BPeriode(7 downto 0) <= Data_in;
+ WHEN "0011" =>
+ BPeriode(11 downto 8) <= Data_in(3 downto 0);
+ WHEN "0100" =>
+ CPeriode(7 downto 0) <= Data_in;
+ WHEN "0101" =>
+ CPeriode(11 downto 8) <= Data_in(3 downto 0);
+ WHEN "0110" =>
+ Noise(4 downto 0) <= Data_in(4 downto 0);
+ WHEN "0111" =>
+ enable <= Data_in XOR B"00111111";
+ WHEN "1000" =>
+ AVollog <= n_Pegel(9 downto 0);
+ AVol(4 downto 0) <= Data_in(4 downto 0);
+ WHEN "1001" =>
+ BVollog <= n_Pegel(9 downto 0);
+ BVol(4 downto 0) <= Data_in(4 downto 0);
+ WHEN "1010" =>
+ CVollog <= n_Pegel(9 downto 0);
+ CVol(4 downto 0) <= Data_in(4 downto 0);
+ WHEN "1011" =>
+ HPeriode(7 downto 0) <= Data_in;
+ WHEN "1100" =>
+ HPeriode(15 downto 8) <= Data_in;
+ WHEN "1101" =>
+ HStart <= '1';
+ HKurve(3 downto 0) <= Data_in(3 downto 0);
+ WHEN "1110" =>
+ PortA <= Data_in;
+ WHEN "1111" =>
+ PortB <= Data_in;
+ WHEN OTHERS => null;
+ END CASE;
+ END IF;
+ END IF;
+ END IF;
+ CASE Data_in(3 downto 0) IS
+ WHEN "1111" => n_Pegel <= X"2AA"; -- Umsetzung in logarithmische Werte in ca. 3dB Schritten
+ WHEN "1110" => n_Pegel <= X"1E2"; -- für Kanäle
+ WHEN "1101" => n_Pegel <= X"155";
+ WHEN "1100" => n_Pegel <= X"0F1";
+ WHEN "1011" => n_Pegel <= X"0AA";
+ WHEN "1010" => n_Pegel <= X"078";
+ WHEN "1001" => n_Pegel <= X"055";
+ WHEN "1000" => n_Pegel <= X"03C";
+ WHEN "0111" => n_Pegel <= X"02A";
+ WHEN "0110" => n_Pegel <= X"01E";
+ WHEN "0101" => n_Pegel <= X"015";
+ WHEN "0100" => n_Pegel <= X"00F";
+ WHEN "0011" => n_Pegel <= X"00A";
+ WHEN "0010" => n_Pegel <= X"007";
+ WHEN "0001" => n_Pegel <= X"005";
+ WHEN "0000" => n_Pegel <= X"000";
+ WHEN OTHERS => null;
+ END CASE;
+-- read reg
+
+ IF bc0='1' AND bdir='0' THEN
+ Data_out <= t_Data;
+ ELSE
+ Data_out <= "11111111";
+ END IF;
+
+ t_Data <= "00000000";
+ CASE PSGReg IS
+ WHEN "0000" =>
+ t_Data <= Aperiode(7 downto 0);
+ WHEN "0001" =>
+ t_Data(3 downto 0) <= Aperiode(11 downto 8);
+ WHEN "0010" =>
+ t_Data <= Bperiode(7 downto 0);
+ WHEN "0011" =>
+ t_Data(3 downto 0) <= Bperiode(11 downto 8);
+ WHEN "0100" =>
+ t_Data <= Cperiode(7 downto 0);
+ WHEN "0101" =>
+ t_Data(3 downto 0) <= Cperiode(11 downto 8);
+ WHEN "0110" =>
+ t_Data(4 downto 0) <= Noise;
+ WHEN "0111" =>
+ t_Data <= enable XOR "00111111";
+ WHEN "1000" =>
+ t_Data(4 downto 0) <= AVol;
+ WHEN "1001" =>
+ t_Data(4 downto 0) <= BVol;
+ WHEN "1010" =>
+ t_Data(4 downto 0) <= CVol;
+ WHEN "1011" =>
+ t_Data <= Hperiode(7 downto 0);
+ WHEN "1100" =>
+ t_Data <= Hperiode(15 downto 8);
+ WHEN "1101" =>
+ t_Data(3 downto 0) <= HKurve;
+ WHEN "1110" =>
+ IF enable(6)='0' THEN
+ t_Data <= PortA AND IO_A;
+ ELSE
+ t_Data <= PortA;
+ END IF;
+ WHEN "1111" =>
+ t_Data <= PortB;
+ END CASE;
+END process;
+-------------------------------------------------------------------------
+--Soundgen
+-------------------------------------------------------------------------
+process (cpuclk, reset, AVol, BVol, CVol, HVol, nHVol, AVollog, BVollog, CVollog, HVollog, HKurve)
+begin
+-- channel A
+ IF AVol(4)='1' THEN
+ Alog <= HVollog(9 downto 0);
+ ELSE
+ Alog <= AVollog;
+ END IF;
+ IF rising_edge(cpuclk) THEN
+ IF ((enable(3) AND Noisebit) XOR Anot)='1' THEN
+ chanA <= ('0'&Alog);
+ ELSE
+ chanA <= (others => '0');
+ END IF;
+ IF enable(0)='0' OR APeriode="000000000000" THEN
+ Anot <= '1';
+ ACount <= "000000000000";
+ ELSIF S_Tick='1' THEN
+ IF ACount(11 downto 0)>=APeriode THEN
+ ACount <= "000000000001";
+ Anot <= NOT Anot;
+ ELSE
+ ACount <= ACount+1;
+ END IF;
+ END IF;
+ END IF;
+
+-- channel B
+ IF BVol(4)='1' THEN
+ Blog <= HVollog(9 downto 0);
+ ELSE
+ Blog <= BVollog;
+ END IF;
+ IF rising_edge(cpuclk) THEN
+ IF ((enable(4) AND Noisebit) XOR Bnot)='1' THEN
+ chanB <= ('0'&Blog);
+ ELSE
+ chanB <= (others => '0');
+ END IF;
+ IF enable(1)='0' OR BPeriode="000000000000" THEN
+ Bnot <= '1';
+ BCount <= "000000000000";
+ ELSIF S_Tick='1' THEN
+ IF BCount(11 downto 0)>=BPeriode THEN
+ BCount <= "000000000001";
+ Bnot <= NOT Bnot;
+ ELSE
+ BCount <= BCount+1;
+ END IF;
+ END IF;
+ END IF;
+
+-- channel C
+ IF CVol(4)='1' THEN
+ Clog <= HVollog(9 downto 0);
+ ELSE
+ Clog <= CVollog;
+ END IF;
+ IF rising_edge(cpuclk) THEN
+ IF ((enable(5) AND Noisebit) XOR Cnot)='1' THEN
+ chanC <= ('0'&Clog);
+ ELSE
+ chanC <= (others => '0');
+ END IF;
+ IF enable(2)='0' OR CPeriode="000000000000" THEN
+ Cnot <= '1';
+ CCount <= "000000000000";
+ ELSIF S_Tick='1' THEN
+ IF CCount(11 downto 0)>=CPeriode THEN
+ CCount <= "000000000001";
+ Cnot <= NOT Cnot;
+ ELSE
+ CCount <= CCount+1;
+ END IF;
+ END IF;
+ END IF;
+
+--noise
+--Noise="00000" and Noise="00001" is the same
+ IF rising_edge(cpuclk) THEN
+ IF S_Tick='1' THEN
+ IF NCount(4 downto 1)="0000" THEN
+ NCount <= Noise ;
+ RNG <= (NOT (RNG(0) XOR RNG(2))& RNG(16 downto 1));
+ Noisebit <= RNG(0);
+ ELSE
+ NCount <= NCount-1;
+ END IF;
+ END IF;
+ END IF;
+
+-- Huellkurve
+ nHVol <= HVol(3 downto 0);
+ IF ((HKurve(3) OR NOT HVol(4)) AND ( NOT HKurve(2) XOR ((HKurve(1) XOR HKurve(0)) AND HVol(4))))='1' THEN
+ nHVol <= HVol(3 downto 0) XOR "1111";
+ END IF;
+
+ IF rising_edge(cpuclk) THEN
+ IF HStart='1' THEN
+ HCount <= "0000000000000001";
+ HVol <= "00000";
+ ELSIF H_Tick='1' THEN
+ IF HCount>=HPeriode THEN
+ HCount <= "0000000000000001";
+ IF (NOT HVol(4) OR (NOT HKurve(0) AND HKurve(3)))='1' AND (HPeriode /= 0) THEN --HOLD
+-- IF (NOT HVol(4) OR (NOT HKurve(0) AND HKurve(3)))='1' THEN --HOLD
+ HVol <= HVol+1;
+ END IF;
+ ELSE
+ HCount <= HCount+1;
+ END IF;
+ END IF;
+ END IF;
+
+ CASE nHVol(3 downto 0) IS
+ WHEN "1111" => HVollog <= X"2AA"; -- Umsetzung in logarithmische Werte in ca. 3dB Schritten
+ WHEN "1110" => HVollog <= X"1E2"; -- für Hüllkurve
+ WHEN "1101" => HVollog <= X"155";
+ WHEN "1100" => HVollog <= X"0F1";
+ WHEN "1011" => HVollog <= X"0AA";
+ WHEN "1010" => HVollog <= X"078";
+ WHEN "1001" => HVollog <= X"055";
+ WHEN "1000" => HVollog <= X"03C";
+ WHEN "0111" => HVollog <= X"02A";
+ WHEN "0110" => HVollog <= X"01E";
+ WHEN "0101" => HVollog <= X"015";
+ WHEN "0100" => HVollog <= X"00F";
+ WHEN "0011" => HVollog <= X"00A";
+ WHEN "0010" => HVollog <= X"007";
+ WHEN "0001" => HVollog <= X"005";
+ WHEN "0000" => HVollog <= X"000";
+ WHEN OTHERS => null;
+ END CASE;
+END process;
+
+end logic;
diff --git a/common/CPU/6502_6510/aholme_6502.v b/common/CPU/6502_6510/aholme_6502.v
new file mode 100644
index 00000000..35083894
--- /dev/null
+++ b/common/CPU/6502_6510/aholme_6502.v
@@ -0,0 +1,32 @@
+module aholme_6502(
+ input clk,
+ input enable,
+ input reset,
+ output [15:0] ab,
+ input [7:0] dbi,
+ output [7:0] dbo,
+ output we,
+ input irq,
+ input nmi,
+ input ready
+);
+
+ wire we_c;
+
+ chip_6502 aholme_cpu (
+ .clk(clk),
+ .phi(clk & enable),
+ .res(~reset),
+ .so(1'b0),
+ .rdy(ready),
+ .nmi(nmi_n),
+ .irq(irq_n),
+ .rw(we_c),
+ .dbi(dbi),
+ .dbo(dbo),
+ .ab(ab)
+ );
+
+ assign we = ~we_c;
+
+endmodule
diff --git a/common/CPU/6502_6510/arlet_6502.v b/common/CPU/6502_6510/arlet_6502.v
new file mode 100644
index 00000000..7ea97d5a
--- /dev/null
+++ b/common/CPU/6502_6510/arlet_6502.v
@@ -0,0 +1,72 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+// Description: A wrapper for Arlet Ottens 6502 CPU core
+//
+// Author.....: Alan Garfield
+// Niels A. Moseley
+// Date.......: 26-1-2018
+//
+
+module arlet_6502(
+ input clk, // clock signal
+ input enable, // clock enable strobe
+ input rst, // active high reset signal
+ output reg [15:0] ab, // address bus
+ input [7:0] dbi, // 8-bit data bus (input)
+ output reg [7:0] dbo, // 8-bit data bus (output)
+ output reg we, // active high write enable strobe
+ input irq_n, // active low interrupt request
+ input nmi_n, // active low non-maskable interrupt
+ input ready, // CPU updates when ready = 1
+ output [15:0] pc_monitor // program counter monitor signal for debugging
+);
+
+ wire [7:0] dbo_c;
+ wire [15:0] ab_c;
+ wire we_c;
+
+ cpu arlet_cpu(
+ .clk(clk),
+ .reset(rst),
+ .AB(ab_c),
+ .DI(dbi),
+ .DO(dbo_c),
+ .WE(we_c),
+ .IRQ(~irq_n),
+ .NMI(~nmi_n),
+ .RDY(ready),
+ .PC_MONITOR(pc_monitor)
+ );
+
+ always @(posedge clk or posedge rst)
+ begin
+ if (rst)
+ begin
+ ab <= 16'd0;
+ dbo <= 8'd0;
+ we <= 1'b0;
+ end
+ else
+ if (enable)
+ begin
+ ab <= ab_c;
+ dbo <= dbo_c;
+ we <= we_c;
+ end
+ end
+endmodule
diff --git a/common/CPU/6502_6510/chip_6502.v b/common/CPU/6502_6510/chip_6502.v
new file mode 100644
index 00000000..49de2be9
--- /dev/null
+++ b/common/CPU/6502_6510/chip_6502.v
@@ -0,0 +1,66 @@
+`include "../rtl/cpu/aholme/chip_6502_nodes.inc"
+
+module LOGIC (
+ input [`NUM_NODES-1:0] i,
+ output [`NUM_NODES-1:0] o);
+
+ `include "chip_6502_logic.inc"
+endmodule
+
+
+module chip_6502 (
+ input clk, // FPGA clock
+ input phi, // 6502 clock
+ input res,
+ input so,
+ input rdy,
+ input nmi,
+ input irq,
+ input [7:0] dbi,
+ output [7:0] dbo,
+ output rw,
+ output sync,
+ output [15:0] ab);
+
+ // Node states
+ wire [`NUM_NODES-1:0] no;
+ reg [`NUM_NODES-1:0] ni;
+ reg [`NUM_NODES-1:0] q = 0;
+
+ LOGIC logic_00 (.i(ni), .o(no));
+
+ always @ (posedge clk)
+ q <= no;
+
+ always @* begin
+ ni = q;
+
+ ni[`NODE_vcc ] = 1'b1;
+ ni[`NODE_vss ] = 1'b0;
+ ni[`NODE_res ] = res;
+ ni[`NODE_clk0] = phi;
+ ni[`NODE_so ] = so;
+ ni[`NODE_rdy ] = rdy;
+ ni[`NODE_nmi ] = nmi;
+ ni[`NODE_irq ] = irq;
+
+ {ni[`NODE_db7],ni[`NODE_db6],ni[`NODE_db5],ni[`NODE_db4],
+ ni[`NODE_db3],ni[`NODE_db2],ni[`NODE_db1],ni[`NODE_db0]} = dbi[7:0];
+ end
+
+ assign dbo[7:0] = {
+ no[`NODE_db7],no[`NODE_db6],no[`NODE_db5],no[`NODE_db4],
+ no[`NODE_db3],no[`NODE_db2],no[`NODE_db1],no[`NODE_db0]
+ };
+
+ assign ab[15:0] = {
+ no[`NODE_ab15], no[`NODE_ab14], no[`NODE_ab13], no[`NODE_ab12],
+ no[`NODE_ab11], no[`NODE_ab10], no[`NODE_ab9], no[`NODE_ab8],
+ no[`NODE_ab7], no[`NODE_ab6], no[`NODE_ab5], no[`NODE_ab4],
+ no[`NODE_ab3], no[`NODE_ab2], no[`NODE_ab1], no[`NODE_ab0]
+ };
+
+ assign rw = no[`NODE_rw];
+ assign sync = no[`NODE_sync];
+
+endmodule
diff --git a/common/CPU/6502_6510/chip_6502_mux.v b/common/CPU/6502_6510/chip_6502_mux.v
new file mode 100644
index 00000000..a2b87e17
--- /dev/null
+++ b/common/CPU/6502_6510/chip_6502_mux.v
@@ -0,0 +1,10 @@
+module MUX #(
+ parameter N=1
+) (
+ output wire o,
+ input wire i,
+ input wire [N-1:0] s,
+ input wire [N-1:0] d);
+
+ assign o = (|s) ? &(d|(~s)) : i;
+endmodule
diff --git a/common/CPU/6502_6510/cpu6502.vhd b/common/CPU/6502_6510/cpu6502.vhd
new file mode 100644
index 00000000..1c521ffb
--- /dev/null
+++ b/common/CPU/6502_6510/cpu6502.vhd
@@ -0,0 +1,1598 @@
+-- -----------------------------------------------------------------------
+--
+-- FPGA 64
+--
+-- A fully functional commodore 64 implementation in a single FPGA
+--
+-- -----------------------------------------------------------------------
+--
+-- Table driven, cycle exact 6502/6510 core
+--
+-- -----------------------------------------------------------------------
+--
+-- cpu65xx_fast.vhdl, part of FPGA-64, is made available strictly for personal
+-- educational purposes. Distributed with apple2fgpa with permission.
+--
+-- Copyright 2005-2008 by Peter Wendrich (pwsoft@syntiac.com).
+-- All rights reserved.
+-- http://www.syntiac.com/fpga64.html
+--
+-- -----------------------------------------------------------------------
+
+library IEEE;
+use ieee.std_logic_1164.ALL;
+use ieee.numeric_std.ALL;
+
+entity cpu65xx is
+ generic (
+ pipelineOpcode : boolean;
+ pipelineAluMux : boolean;
+ pipelineAluOut : boolean
+ );
+ port (
+ clk : in std_logic;
+ enable : in std_logic;
+ reset : in std_logic;
+ nmi_n : in std_logic;
+ irq_n : in std_logic;
+ so_n : in std_logic := '1';
+
+ di : in unsigned(7 downto 0);
+ do : out unsigned(7 downto 0);
+ addr : out unsigned(15 downto 0);
+ we : out std_logic;
+
+ debugOpcode : out unsigned(7 downto 0);
+ debugPc : out unsigned(15 downto 0);
+ debugA : out unsigned(7 downto 0);
+ debugX : out unsigned(7 downto 0);
+ debugY : out unsigned(7 downto 0);
+ debugS : out unsigned(7 downto 0)
+ );
+end cpu65xx;
+
+-- -----------------------------------------------------------------------
+
+-- Store Zp (3) => fetch, cycle2, cycleEnd
+-- Store Zp,x (4) => fetch, cycle2, preWrite, cycleEnd
+-- Read Zp,x (4) => fetch, cycle2, cycleRead, cycleRead2
+-- Rmw Zp,x (6) => fetch, cycle2, cycleRead, cycleRead2, cycleRmw, cycleEnd
+-- Store Abs (4) => fetch, cycle2, cycle3, cycleEnd
+-- Store Abs,x (5) => fetch, cycle2, cycle3, preWrite, cycleEnd
+-- Rts (6) => fetch, cycle2, cycle3, cycleRead, cycleJump, cycleIncrEnd
+-- Rti (6) => fetch, cycle2, stack1, stack2, stack3, cycleJump
+-- Jsr (6) => fetch, cycle2, .. cycle5, cycle6, cycleJump
+-- Jmp abs (-) => fetch, cycle2, .., cycleJump
+-- Jmp (ind) (-) => fetch, cycle2, .., cycleJump
+-- Brk / irq (6) => fetch, cycle2, stack2, stack3, stack4
+-- -----------------------------------------------------------------------
+
+architecture fast of cpu65xx is
+-- Statemachine
+ type cpuCycles is (
+ opcodeFetch, -- New opcode is read and registers updated
+ cycle2,
+ cycle3,
+ cyclePreIndirect,
+ cycleIndirect,
+ cycleBranchTaken,
+ cycleBranchPage,
+ cyclePreRead, -- Cycle before read while doing zeropage indexed addressing.
+ cycleRead, -- Read cycle
+ cycleRead2, -- Second read cycle after page-boundary crossing.
+ cycleRmw, -- Calculate ALU output for read-modify-write instr.
+ cyclePreWrite, -- Cycle before write when doing indexed addressing.
+ cycleWrite, -- Write cycle for zeropage or absolute addressing.
+ cycleStack1,
+ cycleStack2,
+ cycleStack3,
+ cycleStack4,
+ cycleJump, -- Last cycle of Jsr, Jmp. Next fetch address is target addr.
+ cycleEnd
+ );
+ signal theCpuCycle : cpuCycles;
+ signal nextCpuCycle : cpuCycles;
+ signal updateRegisters : boolean;
+ signal processIrq : std_logic;
+ signal nmiReg: std_logic;
+ signal nmiEdge: std_logic;
+ signal irqReg : std_logic; -- Delay IRQ input with one clock cycle.
+ signal soReg : std_logic; -- SO pin edge detection
+
+-- Opcode decoding
+ constant opcUpdateA : integer := 0;
+ constant opcUpdateX : integer := 1;
+ constant opcUpdateY : integer := 2;
+ constant opcUpdateS : integer := 3;
+ constant opcUpdateN : integer := 4;
+ constant opcUpdateV : integer := 5;
+ constant opcUpdateD : integer := 6;
+ constant opcUpdateI : integer := 7;
+ constant opcUpdateZ : integer := 8;
+ constant opcUpdateC : integer := 9;
+
+ constant opcSecondByte : integer := 10;
+ constant opcAbsolute : integer := 11;
+ constant opcZeroPage : integer := 12;
+ constant opcIndirect : integer := 13;
+ constant opcStackAddr : integer := 14; -- Push/Pop address
+ constant opcStackData : integer := 15; -- Push/Pop status/data
+ constant opcJump : integer := 16;
+ constant opcBranch : integer := 17;
+ constant indexX : integer := 18;
+ constant indexY : integer := 19;
+ constant opcStackUp : integer := 20;
+ constant opcWrite : integer := 21;
+ constant opcRmw : integer := 22;
+ constant opcIncrAfter : integer := 23; -- Insert extra cycle to increment PC (RTS)
+ constant opcRti : integer := 24;
+ constant opcIRQ : integer := 25;
+
+ constant opcInA : integer := 26;
+ constant opcInE : integer := 27;
+ constant opcInX : integer := 28;
+ constant opcInY : integer := 29;
+ constant opcInS : integer := 30;
+ constant opcInT : integer := 31;
+ constant opcInH : integer := 32;
+ constant opcInClear : integer := 33;
+ constant aluMode1From : integer := 34;
+ --
+ constant aluMode1To : integer := 37;
+ constant aluMode2From : integer := 38;
+ --
+ constant aluMode2To : integer := 40;
+ --
+ constant opcInCmp : integer := 41;
+ constant opcInCpx : integer := 42;
+ constant opcInCpy : integer := 43;
+
+
+ subtype addrDef is unsigned(0 to 15);
+ --
+ -- is Interrupt -----------------+
+ -- instruction is RTI ----------------+|
+ -- PC++ on last cycle (RTS) ---------------+||
+ -- RMW --------------+|||
+ -- Write -------------+||||
+ -- Pop/Stack up -------------+|||||
+ -- Branch ---------+ ||||||
+ -- Jump ----------+| ||||||
+ -- Push or Pop data -------+|| ||||||
+ -- Push or Pop addr ------+||| ||||||
+ -- Indirect -----+|||| ||||||
+ -- ZeroPage ----+||||| ||||||
+ -- Absolute ---+|||||| ||||||
+ -- PC++ on cycle2 --+||||||| ||||||
+ -- |AZI||JBXY|WM|||
+ constant immediate : addrDef := "1000000000000000";
+ constant implied : addrDef := "0000000000000000";
+ -- Zero page
+ constant readZp : addrDef := "1010000000000000";
+ constant writeZp : addrDef := "1010000000010000";
+ constant rmwZp : addrDef := "1010000000001000";
+ -- Zero page indexed
+ constant readZpX : addrDef := "1010000010000000";
+ constant writeZpX : addrDef := "1010000010010000";
+ constant rmwZpX : addrDef := "1010000010001000";
+ constant readZpY : addrDef := "1010000001000000";
+ constant writeZpY : addrDef := "1010000001010000";
+ constant rmwZpY : addrDef := "1010000001001000";
+ -- Zero page indirect
+ constant readIndX : addrDef := "1001000010000000";
+ constant writeIndX : addrDef := "1001000010010000";
+ constant rmwIndX : addrDef := "1001000010001000";
+ constant readIndY : addrDef := "1001000001000000";
+ constant writeIndY : addrDef := "1001000001010000";
+ constant rmwIndY : addrDef := "1001000001001000";
+ -- |AZI||JBXY|WM||
+ -- Absolute
+ constant readAbs : addrDef := "1100000000000000";
+ constant writeAbs : addrDef := "1100000000010000";
+ constant rmwAbs : addrDef := "1100000000001000";
+ constant readAbsX : addrDef := "1100000010000000";
+ constant writeAbsX : addrDef := "1100000010010000";
+ constant rmwAbsX : addrDef := "1100000010001000";
+ constant readAbsY : addrDef := "1100000001000000";
+ constant writeAbsY : addrDef := "1100000001010000";
+ constant rmwAbsY : addrDef := "1100000001001000";
+ -- PHA PHP
+ constant push : addrDef := "0000010000000000";
+ -- PLA PLP
+ constant pop : addrDef := "0000010000100000";
+ -- Jumps
+ constant jsr : addrDef := "1000101000000000";
+ constant jumpAbs : addrDef := "1000001000000000";
+ constant jumpInd : addrDef := "1100001000000000";
+ constant relative : addrDef := "1000000100000000";
+ -- Specials
+ constant rts : addrDef := "0000101000100100";
+ constant rti : addrDef := "0000111000100010";
+ constant brk : addrDef := "1000111000000001";
+-- constant : unsigned(0 to 0) := "0";
+ constant xxxxxxxx : addrDef := "----------0---00";
+
+ -- A = accu
+ -- E = Accu | 0xEE (for ANE, LXA)
+ -- X = index X
+ -- Y = index Y
+ -- S = Stack pointer
+ -- H = indexH
+ --
+ -- AEXYSTHc
+ constant aluInA : unsigned(0 to 7) := "10000000";
+ constant aluInE : unsigned(0 to 7) := "01000000";
+ constant aluInEXT : unsigned(0 to 7) := "01100100";
+ constant aluInET : unsigned(0 to 7) := "01000100";
+ constant aluInX : unsigned(0 to 7) := "00100000";
+ constant aluInXH : unsigned(0 to 7) := "00100010";
+ constant aluInY : unsigned(0 to 7) := "00010000";
+ constant aluInYH : unsigned(0 to 7) := "00010010";
+ constant aluInS : unsigned(0 to 7) := "00001000";
+ constant aluInT : unsigned(0 to 7) := "00000100";
+ constant aluInAX : unsigned(0 to 7) := "10100000";
+ constant aluInAXH : unsigned(0 to 7) := "10100010";
+ constant aluInAT : unsigned(0 to 7) := "10000100";
+ constant aluInXT : unsigned(0 to 7) := "00100100";
+ constant aluInST : unsigned(0 to 7) := "00001100";
+ constant aluInSet : unsigned(0 to 7) := "00000000";
+ constant aluInClr : unsigned(0 to 7) := "00000001";
+ constant aluInXXX : unsigned(0 to 7) := "--------";
+
+ -- Most of the aluModes are just like the opcodes.
+ -- aluModeInp -> input is output. calculate N and Z
+ -- aluModeCmp -> Compare for CMP, CPX, CPY
+ -- aluModeFlg -> input to flags needed for PLP, RTI and CLC, SEC, CLV
+ -- aluModeInc -> for INC but also INX, INY
+ -- aluModeDec -> for DEC but also DEX, DEY
+
+ subtype aluMode1 is unsigned(0 to 3);
+ subtype aluMode2 is unsigned(0 to 2);
+ subtype aluMode is unsigned(0 to 9);
+
+ -- Logic/Shift ALU
+ constant aluModeInp : aluMode1 := "0000";
+ constant aluModeP : aluMode1 := "0001";
+ constant aluModeInc : aluMode1 := "0010";
+ constant aluModeDec : aluMode1 := "0011";
+ constant aluModeFlg : aluMode1 := "0100";
+ constant aluModeBit : aluMode1 := "0101";
+ -- 0110
+ -- 0111
+ constant aluModeLsr : aluMode1 := "1000";
+ constant aluModeRor : aluMode1 := "1001";
+ constant aluModeAsl : aluMode1 := "1010";
+ constant aluModeRol : aluMode1 := "1011";
+ -- 1100
+ -- 1101
+ -- 1110
+ constant aluModeAnc : aluMode1 := "1111";
+
+ -- Arithmetic ALU
+ constant aluModePss : aluMode2 := "000";
+ constant aluModeCmp : aluMode2 := "001";
+ constant aluModeAdc : aluMode2 := "010";
+ constant aluModeSbc : aluMode2 := "011";
+ constant aluModeAnd : aluMode2 := "100";
+ constant aluModeOra : aluMode2 := "101";
+ constant aluModeEor : aluMode2 := "110";
+ constant aluModeArr : aluMode2 := "111";
+
+
+ constant aluInp : aluMode := aluModeInp & aluModePss & "---";
+ constant aluP : aluMode := aluModeP & aluModePss & "---";
+ constant aluInc : aluMode := aluModeInc & aluModePss & "---";
+ constant aluDec : aluMode := aluModeDec & aluModePss & "---";
+ constant aluFlg : aluMode := aluModeFlg & aluModePss & "---";
+ constant aluBit : aluMode := aluModeBit & aluModeAnd & "---";
+ constant aluRor : aluMode := aluModeRor & aluModePss & "---";
+ constant aluLsr : aluMode := aluModeLsr & aluModePss & "---";
+ constant aluRol : aluMode := aluModeRol & aluModePss & "---";
+ constant aluAsl : aluMode := aluModeAsl & aluModePss & "---";
+
+ constant aluCmp : aluMode := aluModeInp & aluModeCmp & "100";
+ constant aluCpx : aluMode := aluModeInp & aluModeCmp & "010";
+ constant aluCpy : aluMode := aluModeInp & aluModeCmp & "001";
+ constant aluAdc : aluMode := aluModeInp & aluModeAdc & "---";
+ constant aluSbc : aluMode := aluModeInp & aluModeSbc & "---";
+ constant aluAnd : aluMode := aluModeInp & aluModeAnd & "---";
+ constant aluOra : aluMode := aluModeInp & aluModeOra & "---";
+ constant aluEor : aluMode := aluModeInp & aluModeEor & "---";
+
+ constant aluSlo : aluMode := aluModeAsl & aluModeOra & "---";
+ constant aluSre : aluMode := aluModeLsr & aluModeEor & "---";
+ constant aluRra : aluMode := aluModeRor & aluModeAdc & "---";
+ constant aluRla : aluMode := aluModeRol & aluModeAnd & "---";
+ constant aluDcp : aluMode := aluModeDec & aluModeCmp & "100";
+ constant aluIsc : aluMode := aluModeInc & aluModeSbc & "---";
+ constant aluAnc : aluMode := aluModeAnc & aluModeAnd & "---";
+ constant aluArr : aluMode := aluModeRor & aluModeArr & "---";
+ constant aluSbx : aluMode := aluModeInp & aluModeCmp & "110";
+
+ constant aluXXX : aluMode := (others => '-');
+
+
+ -- Stack operations. Push/Pop/None
+ constant stackInc : unsigned(0 to 0) := "0";
+ constant stackDec : unsigned(0 to 0) := "1";
+ constant stackXXX : unsigned(0 to 0) := "-";
+
+ subtype decodedBitsDef is unsigned(0 to 43);
+ type opcodeInfoTableDef is array(0 to 255) of decodedBitsDef;
+ constant opcodeInfoTable : opcodeInfoTableDef := (
+ -- +------- Update register A
+ -- |+------ Update register X
+ -- ||+----- Update register Y
+ -- |||+---- Update register S
+ -- |||| +-- Update Flags
+ -- |||| |
+ -- |||| _|__
+ -- |||| / \
+ -- AXYS NVDIZC addressing aluInput aluMode
+ "0000" & "000100" & brk & aluInXXX & aluP, -- 00 BRK
+ "1000" & "100010" & readIndX & aluInT & aluOra, -- 01 ORA (zp,x)
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 02 *** JAM ***
+ "1000" & "100011" & rmwIndX & aluInT & aluSlo, -- 03 iSLO (zp,x)
+ "0000" & "000000" & readZp & aluInXXX & aluXXX, -- 04 iNOP zp
+ "1000" & "100010" & readZp & aluInT & aluOra, -- 05 ORA zp
+ "0000" & "100011" & rmwZp & aluInT & aluAsl, -- 06 ASL zp
+ "1000" & "100011" & rmwZp & aluInT & aluSlo, -- 07 iSLO zp
+ "0000" & "000000" & push & aluInXXX & aluP, -- 08 PHP
+ "1000" & "100010" & immediate & aluInT & aluOra, -- 09 ORA imm
+ "1000" & "100011" & implied & aluInA & aluAsl, -- 0A ASL accu
+ "1000" & "100011" & immediate & aluInT & aluAnc, -- 0B iANC imm
+ "0000" & "000000" & readAbs & aluInXXX & aluXXX, -- 0C iNOP abs
+ "1000" & "100010" & readAbs & aluInT & aluOra, -- 0D ORA abs
+ "0000" & "100011" & rmwAbs & aluInT & aluAsl, -- 0E ASL abs
+ "1000" & "100011" & rmwAbs & aluInT & aluSlo, -- 0F iSLO abs
+ "0000" & "000000" & relative & aluInXXX & aluXXX, -- 10 BPL
+ "1000" & "100010" & readIndY & aluInT & aluOra, -- 11 ORA (zp),y
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 12 *** JAM ***
+ "1000" & "100011" & rmwIndY & aluInT & aluSlo, -- 13 iSLO (zp),y
+ "0000" & "000000" & readZpX & aluInXXX & aluXXX, -- 14 iNOP zp,x
+ "1000" & "100010" & readZpX & aluInT & aluOra, -- 15 ORA zp,x
+ "0000" & "100011" & rmwZpX & aluInT & aluAsl, -- 16 ASL zp,x
+ "1000" & "100011" & rmwZpX & aluInT & aluSlo, -- 17 iSLO zp,x
+ "0000" & "000001" & implied & aluInClr & aluFlg, -- 18 CLC
+ "1000" & "100010" & readAbsY & aluInT & aluOra, -- 19 ORA abs,y
+ "0000" & "000000" & implied & aluInXXX & aluXXX, -- 1A iNOP implied
+ "1000" & "100011" & rmwAbsY & aluInT & aluSlo, -- 1B iSLO abs,y
+ "0000" & "000000" & readAbsX & aluInXXX & aluXXX, -- 1C iNOP abs,x
+ "1000" & "100010" & readAbsX & aluInT & aluOra, -- 1D ORA abs,x
+ "0000" & "100011" & rmwAbsX & aluInT & aluAsl, -- 1E ASL abs,x
+ "1000" & "100011" & rmwAbsX & aluInT & aluSlo, -- 1F iSLO abs,x
+ -- AXYS NVDIZC addressing aluInput aluMode
+ "0000" & "000000" & jsr & aluInXXX & aluXXX, -- 20 JSR
+ "1000" & "100010" & readIndX & aluInT & aluAnd, -- 21 AND (zp,x)
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 22 *** JAM ***
+ "1000" & "100011" & rmwIndX & aluInT & aluRla, -- 23 iRLA (zp,x)
+ "0000" & "110010" & readZp & aluInT & aluBit, -- 24 BIT zp
+ "1000" & "100010" & readZp & aluInT & aluAnd, -- 25 AND zp
+ "0000" & "100011" & rmwZp & aluInT & aluRol, -- 26 ROL zp
+ "1000" & "100011" & rmwZp & aluInT & aluRla, -- 27 iRLA zp
+ "0000" & "111111" & pop & aluInT & aluFlg, -- 28 PLP
+ "1000" & "100010" & immediate & aluInT & aluAnd, -- 29 AND imm
+ "1000" & "100011" & implied & aluInA & aluRol, -- 2A ROL accu
+ "1000" & "100011" & immediate & aluInT & aluAnc, -- 2B iANC imm
+ "0000" & "110010" & readAbs & aluInT & aluBit, -- 2C BIT abs
+ "1000" & "100010" & readAbs & aluInT & aluAnd, -- 2D AND abs
+ "0000" & "100011" & rmwAbs & aluInT & aluRol, -- 2E ROL abs
+ "1000" & "100011" & rmwAbs & aluInT & aluRla, -- 2F iRLA abs
+ "0000" & "000000" & relative & aluInXXX & aluXXX, -- 30 BMI
+ "1000" & "100010" & readIndY & aluInT & aluAnd, -- 31 AND (zp),y
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 32 *** JAM ***
+ "1000" & "100011" & rmwIndY & aluInT & aluRla, -- 33 iRLA (zp),y
+ "0000" & "000000" & readZpX & aluInXXX & aluXXX, -- 34 iNOP zp,x
+ "1000" & "100010" & readZpX & aluInT & aluAnd, -- 35 AND zp,x
+ "0000" & "100011" & rmwZpX & aluInT & aluRol, -- 36 ROL zp,x
+ "1000" & "100011" & rmwZpX & aluInT & aluRla, -- 37 iRLA zp,x
+ "0000" & "000001" & implied & aluInSet & aluFlg, -- 38 SEC
+ "1000" & "100010" & readAbsY & aluInT & aluAnd, -- 39 AND abs,y
+ "0000" & "000000" & implied & aluInXXX & aluXXX, -- 3A iNOP implied
+ "1000" & "100011" & rmwAbsY & aluInT & aluRla, -- 3B iRLA abs,y
+ "0000" & "000000" & readAbsX & aluInXXX & aluXXX, -- 3C iNOP abs,x
+ "1000" & "100010" & readAbsX & aluInT & aluAnd, -- 3D AND abs,x
+ "0000" & "100011" & rmwAbsX & aluInT & aluRol, -- 3E ROL abs,x
+ "1000" & "100011" & rmwAbsX & aluInT & aluRla, -- 3F iRLA abs,x
+ -- AXYS NVDIZC addressing aluInput aluMode
+ "0000" & "111111" & rti & aluInT & aluFlg, -- 40 RTI
+ "1000" & "100010" & readIndX & aluInT & aluEor, -- 41 EOR (zp,x)
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 42 *** JAM ***
+ "1000" & "100011" & rmwIndX & aluInT & aluSre, -- 43 iSRE (zp,x)
+ "0000" & "000000" & readZp & aluInXXX & aluXXX, -- 44 iNOP zp
+ "1000" & "100010" & readZp & aluInT & aluEor, -- 45 EOR zp
+ "0000" & "100011" & rmwZp & aluInT & aluLsr, -- 46 LSR zp
+ "1000" & "100011" & rmwZp & aluInT & aluSre, -- 47 iSRE zp
+ "0000" & "000000" & push & aluInA & aluInp, -- 48 PHA
+ "1000" & "100010" & immediate & aluInT & aluEor, -- 49 EOR imm
+ "1000" & "100011" & implied & aluInA & aluLsr, -- 4A LSR accu
+ "1000" & "100011" & immediate & aluInAT & aluLsr, -- 4B iALR imm
+ "0000" & "000000" & jumpAbs & aluInXXX & aluXXX, -- 4C JMP abs
+ "1000" & "100010" & readAbs & aluInT & aluEor, -- 4D EOR abs
+ "0000" & "100011" & rmwAbs & aluInT & aluLsr, -- 4E LSR abs
+ "1000" & "100011" & rmwAbs & aluInT & aluSre, -- 4F iSRE abs
+ "0000" & "000000" & relative & aluInXXX & aluXXX, -- 50 BVC
+ "1000" & "100010" & readIndY & aluInT & aluEor, -- 51 EOR (zp),y
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 52 *** JAM ***
+ "1000" & "100011" & rmwIndY & aluInT & aluSre, -- 53 iSRE (zp),y
+ "0000" & "000000" & readZpX & aluInXXX & aluXXX, -- 54 iNOP zp,x
+ "1000" & "100010" & readZpX & aluInT & aluEor, -- 55 EOR zp,x
+ "0000" & "100011" & rmwZpX & aluInT & aluLsr, -- 56 LSR zp,x
+ "1000" & "100011" & rmwZpX & aluInT & aluSre, -- 57 SRE zp,x
+ "0000" & "000100" & implied & aluInClr & aluXXX, -- 58 CLI
+ "1000" & "100010" & readAbsY & aluInT & aluEor, -- 59 EOR abs,y
+ "0000" & "000000" & implied & aluInXXX & aluXXX, -- 5A iNOP implied
+ "1000" & "100011" & rmwAbsY & aluInT & aluSre, -- 5B iSRE abs,y
+ "0000" & "000000" & readAbsX & aluInXXX & aluXXX, -- 5C iNOP abs,x
+ "1000" & "100010" & readAbsX & aluInT & aluEor, -- 5D EOR abs,x
+ "0000" & "100011" & rmwAbsX & aluInT & aluLsr, -- 5E LSR abs,x
+ "1000" & "100011" & rmwAbsX & aluInT & aluSre, -- 5F SRE abs,x
+ -- AXYS NVDIZC addressing aluInput aluMode
+ "0000" & "000000" & rts & aluInXXX & aluXXX, -- 60 RTS
+ "1000" & "110011" & readIndX & aluInT & aluAdc, -- 61 ADC (zp,x)
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 62 *** JAM ***
+ "1000" & "110011" & rmwIndX & aluInT & aluRra, -- 63 iRRA (zp,x)
+ "0000" & "000000" & readZp & aluInXXX & aluXXX, -- 64 iNOP zp
+ "1000" & "110011" & readZp & aluInT & aluAdc, -- 65 ADC zp
+ "0000" & "100011" & rmwZp & aluInT & aluRor, -- 66 ROR zp
+ "1000" & "110011" & rmwZp & aluInT & aluRra, -- 67 iRRA zp
+ "1000" & "100010" & pop & aluInT & aluInp, -- 68 PLA
+ "1000" & "110011" & immediate & aluInT & aluAdc, -- 69 ADC imm
+ "1000" & "100011" & implied & aluInA & aluRor, -- 6A ROR accu
+ "1000" & "110011" & immediate & aluInAT & aluArr, -- 6B iARR imm
+ "0000" & "000000" & jumpInd & aluInXXX & aluXXX, -- 6C JMP indirect
+ "1000" & "110011" & readAbs & aluInT & aluAdc, -- 6D ADC abs
+ "0000" & "100011" & rmwAbs & aluInT & aluRor, -- 6E ROR abs
+ "1000" & "110011" & rmwAbs & aluInT & aluRra, -- 6F iRRA abs
+ "0000" & "000000" & relative & aluInXXX & aluXXX, -- 70 BVS
+ "1000" & "110011" & readIndY & aluInT & aluAdc, -- 71 ADC (zp),y
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 72 *** JAM ***
+ "1000" & "110011" & rmwIndY & aluInT & aluRra, -- 73 iRRA (zp),y
+ "0000" & "000000" & readZpX & aluInXXX & aluXXX, -- 74 iNOP zp,x
+ "1000" & "110011" & readZpX & aluInT & aluAdc, -- 75 ADC zp,x
+ "0000" & "100011" & rmwZpX & aluInT & aluRor, -- 76 ROR zp,x
+ "1000" & "110011" & rmwZpX & aluInT & aluRra, -- 77 iRRA zp,x
+ "0000" & "000100" & implied & aluInSet & aluXXX, -- 78 SEI
+ "1000" & "110011" & readAbsY & aluInT & aluAdc, -- 79 ADC abs,y
+ "0000" & "000000" & implied & aluInXXX & aluXXX, -- 7A iNOP implied
+ "1000" & "110011" & rmwAbsY & aluInT & aluRra, -- 7B iRRA abs,y
+ "0000" & "000000" & readAbsX & aluInXXX & aluXXX, -- 7C iNOP abs,x
+ "1000" & "110011" & readAbsX & aluInT & aluAdc, -- 7D ADC abs,x
+ "0000" & "100011" & rmwAbsX & aluInT & aluRor, -- 7E ROR abs,x
+ "1000" & "110011" & rmwAbsX & aluInT & aluRra, -- 7F iRRA abs,x
+ -- AXYS NVDIZC addressing aluInput aluMode
+ "0000" & "000000" & immediate & aluInXXX & aluXXX, -- 80 iNOP imm
+ "0000" & "000000" & writeIndX & aluInA & aluInp, -- 81 STA (zp,x)
+ "0000" & "000000" & immediate & aluInXXX & aluXXX, -- 82 iNOP imm
+ "0000" & "000000" & writeIndX & aluInAX & aluInp, -- 83 iSAX (zp,x)
+ "0000" & "000000" & writeZp & aluInY & aluInp, -- 84 STY zp
+ "0000" & "000000" & writeZp & aluInA & aluInp, -- 85 STA zp
+ "0000" & "000000" & writeZp & aluInX & aluInp, -- 86 STX zp
+ "0000" & "000000" & writeZp & aluInAX & aluInp, -- 87 iSAX zp
+ "0010" & "100010" & implied & aluInY & aluDec, -- 88 DEY
+ "0000" & "000000" & immediate & aluInXXX & aluXXX, -- 84 iNOP imm
+ "1000" & "100010" & implied & aluInX & aluInp, -- 8A TXA
+ "1000" & "100010" & immediate & aluInEXT & aluInp, -- 8B iANE imm
+ "0000" & "000000" & writeAbs & aluInY & aluInp, -- 8C STY abs
+ "0000" & "000000" & writeAbs & aluInA & aluInp, -- 8D STA abs
+ "0000" & "000000" & writeAbs & aluInX & aluInp, -- 8E STX abs
+ "0000" & "000000" & writeAbs & aluInAX & aluInp, -- 8F iSAX abs
+ "0000" & "000000" & relative & aluInXXX & aluXXX, -- 90 BCC
+ "0000" & "000000" & writeIndY & aluInA & aluInp, -- 91 STA (zp),y
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 92 *** JAM ***
+ "0000" & "000000" & writeIndY & aluInAXH & aluInp, -- 93 iAHX (zp),y
+ "0000" & "000000" & writeZpX & aluInY & aluInp, -- 94 STY zp,x
+ "0000" & "000000" & writeZpX & aluInA & aluInp, -- 95 STA zp,x
+ "0000" & "000000" & writeZpY & aluInX & aluInp, -- 96 STX zp,y
+ "0000" & "000000" & writeZpY & aluInAX & aluInp, -- 97 iSAX zp,y
+ "1000" & "100010" & implied & aluInY & aluInp, -- 98 TYA
+ "0000" & "000000" & writeAbsY & aluInA & aluInp, -- 99 STA abs,y
+ "0001" & "000000" & implied & aluInX & aluInp, -- 9A TXS
+ "0001" & "000000" & writeAbsY & aluInAXH & aluInp, -- 9B iSHS abs,y
+ "0000" & "000000" & writeAbsX & aluInYH & aluInp, -- 9C iSHY abs,x
+ "0000" & "000000" & writeAbsX & aluInA & aluInp, -- 9D STA abs,x
+ "0000" & "000000" & writeAbsY & aluInXH & aluInp, -- 9E iSHX abs,y
+ "0000" & "000000" & writeAbsY & aluInAXH & aluInp, -- 9F iAHX abs,y
+ -- AXYS NVDIZC addressing aluInput aluMode
+ "0010" & "100010" & immediate & aluInT & aluInp, -- A0 LDY imm
+ "1000" & "100010" & readIndX & aluInT & aluInp, -- A1 LDA (zp,x)
+ "0100" & "100010" & immediate & aluInT & aluInp, -- A2 LDX imm
+ "1100" & "100010" & readIndX & aluInT & aluInp, -- A3 LAX (zp,x)
+ "0010" & "100010" & readZp & aluInT & aluInp, -- A4 LDY zp
+ "1000" & "100010" & readZp & aluInT & aluInp, -- A5 LDA zp
+ "0100" & "100010" & readZp & aluInT & aluInp, -- A6 LDX zp
+ "1100" & "100010" & readZp & aluInT & aluInp, -- A7 iLAX zp
+ "0010" & "100010" & implied & aluInA & aluInp, -- A8 TAY
+ "1000" & "100010" & immediate & aluInT & aluInp, -- A9 LDA imm
+ "0100" & "100010" & implied & aluInA & aluInp, -- AA TAX
+ "1100" & "100010" & immediate & aluInET & aluInp, -- AB iLXA imm
+ "0010" & "100010" & readAbs & aluInT & aluInp, -- AC LDY abs
+ "1000" & "100010" & readAbs & aluInT & aluInp, -- AD LDA abs
+ "0100" & "100010" & readAbs & aluInT & aluInp, -- AE LDX abs
+ "1100" & "100010" & readAbs & aluInT & aluInp, -- AF iLAX abs
+ "0000" & "000000" & relative & aluInXXX & aluXXX, -- B0 BCS
+ "1000" & "100010" & readIndY & aluInT & aluInp, -- B1 LDA (zp),y
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- B2 *** JAM ***
+ "1100" & "100010" & readIndY & aluInT & aluInp, -- B3 iLAX (zp),y
+ "0010" & "100010" & readZpX & aluInT & aluInp, -- B4 LDY zp,x
+ "1000" & "100010" & readZpX & aluInT & aluInp, -- B5 LDA zp,x
+ "0100" & "100010" & readZpY & aluInT & aluInp, -- B6 LDX zp,y
+ "1100" & "100010" & readZpY & aluInT & aluInp, -- B7 iLAX zp,y
+ "0000" & "010000" & implied & aluInClr & aluFlg, -- B8 CLV
+ "1000" & "100010" & readAbsY & aluInT & aluInp, -- B9 LDA abs,y
+ "0100" & "100010" & implied & aluInS & aluInp, -- BA TSX
+ "1101" & "100010" & readAbsY & aluInST & aluInp, -- BB iLAS abs,y
+ "0010" & "100010" & readAbsX & aluInT & aluInp, -- BC LDY abs,x
+ "1000" & "100010" & readAbsX & aluInT & aluInp, -- BD LDA abs,x
+ "0100" & "100010" & readAbsY & aluInT & aluInp, -- BE LDX abs,y
+ "1100" & "100010" & readAbsY & aluInT & aluInp, -- BF iLAX abs,y
+ -- AXYS NVDIZC addressing aluInput aluMode
+ "0000" & "100011" & immediate & aluInT & aluCpy, -- C0 CPY imm
+ "0000" & "100011" & readIndX & aluInT & aluCmp, -- C1 CMP (zp,x)
+ "0000" & "000000" & immediate & aluInXXX & aluXXX, -- C2 iNOP imm
+ "0000" & "100011" & rmwIndX & aluInT & aluDcp, -- C3 iDCP (zp,x)
+ "0000" & "100011" & readZp & aluInT & aluCpy, -- C4 CPY zp
+ "0000" & "100011" & readZp & aluInT & aluCmp, -- C5 CMP zp
+ "0000" & "100010" & rmwZp & aluInT & aluDec, -- C6 DEC zp
+ "0000" & "100011" & rmwZp & aluInT & aluDcp, -- C7 iDCP zp
+ "0010" & "100010" & implied & aluInY & aluInc, -- C8 INY
+ "0000" & "100011" & immediate & aluInT & aluCmp, -- C9 CMP imm
+ "0100" & "100010" & implied & aluInX & aluDec, -- CA DEX
+ "0100" & "100011" & immediate & aluInT & aluSbx, -- CB SBX imm
+ "0000" & "100011" & readAbs & aluInT & aluCpy, -- CC CPY abs
+ "0000" & "100011" & readAbs & aluInT & aluCmp, -- CD CMP abs
+ "0000" & "100010" & rmwAbs & aluInT & aluDec, -- CE DEC abs
+ "0000" & "100011" & rmwAbs & aluInT & aluDcp, -- CF iDCP abs
+ "0000" & "000000" & relative & aluInXXX & aluXXX, -- D0 BNE
+ "0000" & "100011" & readIndY & aluInT & aluCmp, -- D1 CMP (zp),y
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- D2 *** JAM ***
+ "0000" & "100011" & rmwIndY & aluInT & aluDcp, -- D3 iDCP (zp),y
+ "0000" & "000000" & readZpX & aluInXXX & aluXXX, -- D4 iNOP zp,x
+ "0000" & "100011" & readZpX & aluInT & aluCmp, -- D5 CMP zp,x
+ "0000" & "100010" & rmwZpX & aluInT & aluDec, -- D6 DEC zp,x
+ "0000" & "100011" & rmwZpX & aluInT & aluDcp, -- D7 iDCP zp,x
+ "0000" & "001000" & implied & aluInClr & aluXXX, -- D8 CLD
+ "0000" & "100011" & readAbsY & aluInT & aluCmp, -- D9 CMP abs,y
+ "0000" & "000000" & implied & aluInXXX & aluXXX, -- DA iNOP implied
+ "0000" & "100011" & rmwAbsY & aluInT & aluDcp, -- DB iDCP abs,y
+ "0000" & "000000" & readAbsX & aluInXXX & aluXXX, -- DC iNOP abs,x
+ "0000" & "100011" & readAbsX & aluInT & aluCmp, -- DD CMP abs,x
+ "0000" & "100010" & rmwAbsX & aluInT & aluDec, -- DE DEC abs,x
+ "0000" & "100011" & rmwAbsX & aluInT & aluDcp, -- DF iDCP abs,x
+ -- AXYS NVDIZC addressing aluInput aluMode
+ "0000" & "100011" & immediate & aluInT & aluCpx, -- E0 CPX imm
+ "1000" & "110011" & readIndX & aluInT & aluSbc, -- E1 SBC (zp,x)
+ "0000" & "000000" & immediate & aluInXXX & aluXXX, -- E2 iNOP imm
+ "1000" & "110011" & rmwIndX & aluInT & aluIsc, -- E3 iISC (zp,x)
+ "0000" & "100011" & readZp & aluInT & aluCpx, -- E4 CPX zp
+ "1000" & "110011" & readZp & aluInT & aluSbc, -- E5 SBC zp
+ "0000" & "100010" & rmwZp & aluInT & aluInc, -- E6 INC zp
+ "1000" & "110011" & rmwZp & aluInT & aluIsc, -- E7 iISC zp
+ "0100" & "100010" & implied & aluInX & aluInc, -- E8 INX
+ "1000" & "110011" & immediate & aluInT & aluSbc, -- E9 SBC imm
+ "0000" & "000000" & implied & aluInXXX & aluXXX, -- EA NOP
+ "1000" & "110011" & immediate & aluInT & aluSbc, -- EB SBC imm (illegal opc)
+ "0000" & "100011" & readAbs & aluInT & aluCpx, -- EC CPX abs
+ "1000" & "110011" & readAbs & aluInT & aluSbc, -- ED SBC abs
+ "0000" & "100010" & rmwAbs & aluInT & aluInc, -- EE INC abs
+ "1000" & "110011" & rmwAbs & aluInT & aluIsc, -- EF iISC abs
+ "0000" & "000000" & relative & aluInXXX & aluXXX, -- F0 BEQ
+ "1000" & "110011" & readIndY & aluInT & aluSbc, -- F1 SBC (zp),y
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- F2 *** JAM ***
+ "1000" & "110011" & rmwIndY & aluInT & aluIsc, -- F3 iISC (zp),y
+ "0000" & "000000" & readZpX & aluInXXX & aluXXX, -- F4 iNOP zp,x
+ "1000" & "110011" & readZpX & aluInT & aluSbc, -- F5 SBC zp,x
+ "0000" & "100010" & rmwZpX & aluInT & aluInc, -- F6 INC zp,x
+ "1000" & "110011" & rmwZpX & aluInT & aluIsc, -- F7 iISC zp,x
+ "0000" & "001000" & implied & aluInSet & aluXXX, -- F8 SED
+ "1000" & "110011" & readAbsY & aluInT & aluSbc, -- F9 SBC abs,y
+ "0000" & "000000" & implied & aluInXXX & aluXXX, -- FA iNOP implied
+ "1000" & "110011" & rmwAbsY & aluInT & aluIsc, -- FB iISC abs,y
+ "0000" & "000000" & readAbsX & aluInXXX & aluXXX, -- FC iNOP abs,x
+ "1000" & "110011" & readAbsX & aluInT & aluSbc, -- FD SBC abs,x
+ "0000" & "100010" & rmwAbsX & aluInT & aluInc, -- FE INC abs,x
+ "1000" & "110011" & rmwAbsX & aluInT & aluIsc -- FF iISC abs,x
+ );
+ signal opcInfo : decodedBitsDef;
+ signal nextOpcInfo : decodedBitsDef; -- Next opcode (decoded)
+ signal nextOpcInfoReg : decodedBitsDef; -- Next opcode (decoded) pipelined
+ signal theOpcode : unsigned(7 downto 0);
+ signal nextOpcode : unsigned(7 downto 0);
+
+-- Program counter
+ signal PC : unsigned(15 downto 0); -- Program counter
+
+-- Address generation
+ type nextAddrDef is (
+ nextAddrHold,
+ nextAddrIncr,
+ nextAddrIncrL, -- Increment low bits only (zeropage accesses)
+ nextAddrIncrH, -- Increment high bits only (page-boundary)
+ nextAddrDecrH, -- Decrement high bits (branch backwards)
+ nextAddrPc,
+ nextAddrIrq,
+ nextAddrReset,
+ nextAddrAbs,
+ nextAddrAbsIndexed,
+ nextAddrZeroPage,
+ nextAddrZPIndexed,
+ nextAddrStack,
+ nextAddrRelative
+ );
+ signal nextAddr : nextAddrDef;
+ signal myAddr : unsigned(15 downto 0);
+ signal myAddrIncr : unsigned(15 downto 0);
+ signal myAddrIncrH : unsigned(7 downto 0);
+ signal myAddrDecrH : unsigned(7 downto 0);
+ signal theWe : std_logic;
+
+ signal irqActive : std_logic;
+
+-- Output register
+ signal doReg : unsigned(7 downto 0);
+
+-- Buffer register
+ signal T : unsigned(7 downto 0);
+
+-- General registers
+ signal A: unsigned(7 downto 0); -- Accumulator
+ signal X: unsigned(7 downto 0); -- Index X
+ signal Y: unsigned(7 downto 0); -- Index Y
+ signal S: unsigned(7 downto 0); -- stack pointer
+
+-- Status register
+ signal C: std_logic; -- Carry
+ signal Z: std_logic; -- Zero flag
+ signal I: std_logic; -- Interrupt flag
+ signal D: std_logic; -- Decimal mode
+ signal V: std_logic; -- Overflow
+ signal N: std_logic; -- Negative
+
+-- ALU
+ -- ALU input
+ signal aluInput : unsigned(7 downto 0);
+ signal aluCmpInput : unsigned(7 downto 0);
+ -- ALU output
+ signal aluRegisterOut : unsigned(7 downto 0);
+ signal aluRmwOut : unsigned(7 downto 0);
+ signal aluC : std_logic;
+ signal aluZ : std_logic;
+ signal aluV : std_logic;
+ signal aluN : std_logic;
+ -- Pipeline registers
+ signal aluInputReg : unsigned(7 downto 0);
+ signal aluCmpInputReg : unsigned(7 downto 0);
+ signal aluRmwReg : unsigned(7 downto 0);
+ signal aluNineReg : unsigned(7 downto 0);
+ signal aluCReg : std_logic;
+ signal aluZReg : std_logic;
+ signal aluVReg : std_logic;
+ signal aluNReg : std_logic;
+
+-- Indexing
+ signal indexOut : unsigned(8 downto 0);
+
+begin
+processAluInput: process(clk, opcInfo, A, X, Y, T, S)
+ variable temp : unsigned(7 downto 0);
+ begin
+ temp := (others => '1');
+ if opcInfo(opcInA) = '1' then
+ temp := temp and A;
+ end if;
+ if opcInfo(opcInE) = '1' then
+ temp := temp and (A or X"EE");
+ end if;
+ if opcInfo(opcInX) = '1' then
+ temp := temp and X;
+ end if;
+ if opcInfo(opcInY) = '1' then
+ temp := temp and Y;
+ end if;
+ if opcInfo(opcInS) = '1' then
+ temp := temp and S;
+ end if;
+ if opcInfo(opcInT) = '1' then
+ temp := temp and T;
+ end if;
+ if opcInfo(opcInClear) = '1' then
+ temp := (others => '0');
+ end if;
+ if rising_edge(clk) then
+ aluInputReg <= temp;
+ end if;
+
+ aluInput <= temp;
+ if pipelineAluMux then
+ aluInput <= aluInputReg;
+ end if;
+ end process;
+
+processCmpInput: process(clk, opcInfo, A, X, Y)
+ variable temp : unsigned(7 downto 0);
+ begin
+ temp := (others => '1');
+ if opcInfo(opcInCmp) = '1' then
+ temp := temp and A;
+ end if;
+ if opcInfo(opcInCpx) = '1' then
+ temp := temp and X;
+ end if;
+ if opcInfo(opcInCpy) = '1' then
+ temp := temp and Y;
+ end if;
+ if rising_edge(clk) then
+ aluCmpInputReg <= temp;
+ end if;
+
+ aluCmpInput <= temp;
+ if pipelineAluMux then
+ aluCmpInput <= aluCmpInputReg;
+ end if;
+ end process;
+
+ -- ALU consists of two parts
+ -- Read-Modify-Write or index instructions: INC/DEC/ASL/LSR/ROR/ROL
+ -- Accumulator instructions: ADC, SBC, EOR, AND, EOR, ORA
+ -- Some instructions are both RMW and accumulator so for most
+ -- instructions the rmw results are routed through accu alu too.
+processAlu: process(clk, opcInfo, aluInput, aluCmpInput, A, T, irqActive, N, V, D, I, Z, C)
+ variable lowBits: unsigned(5 downto 0);
+ variable nineBits: unsigned(8 downto 0);
+ variable rmwBits: unsigned(8 downto 0);
+
+ variable varC : std_logic;
+ variable varZ : std_logic;
+ variable varV : std_logic;
+ variable varN : std_logic;
+ begin
+ lowBits := (others => '-');
+ nineBits := (others => '-');
+ rmwBits := (others => '-');
+ varV := aluInput(6); -- Default for BIT / PLP / RTI
+
+ -- Shift unit
+ case opcInfo(aluMode1From to aluMode1To) is
+ when aluModeInp =>
+ rmwBits := C & aluInput;
+ when aluModeP =>
+ rmwBits := C & N & V & '1' & (not irqActive) & D & I & Z & C;
+ when aluModeInc =>
+ rmwBits := C & (aluInput + 1);
+ when aluModeDec =>
+ rmwBits := C & (aluInput - 1);
+ when aluModeAsl =>
+ rmwBits := aluInput & "0";
+ when aluModeFlg =>
+ rmwBits := aluInput(0) & aluInput;
+ when aluModeLsr =>
+ rmwBits := aluInput(0) & "0" & aluInput(7 downto 1);
+ when aluModeRol =>
+ rmwBits := aluInput & C;
+ when aluModeRoR =>
+ rmwBits := aluInput(0) & C & aluInput(7 downto 1);
+ when aluModeAnc =>
+ rmwBits := (aluInput(7) and A(7)) & aluInput;
+ when others =>
+ rmwBits := C & aluInput;
+ end case;
+
+ -- ALU
+ case opcInfo(aluMode2From to aluMode2To) is
+ when aluModeAdc =>
+ lowBits := ("0" & A(3 downto 0) & rmwBits(8)) + ("0" & rmwBits(3 downto 0) & "1");
+ ninebits := ("0" & A) + ("0" & rmwBits(7 downto 0)) + (B"00000000" & rmwBits(8));
+ when aluModeSbc =>
+ lowBits := ("0" & A(3 downto 0) & rmwBits(8)) + ("0" & (not rmwBits(3 downto 0)) & "1");
+ ninebits := ("0" & A) + ("0" & (not rmwBits(7 downto 0))) + (B"00000000" & rmwBits(8));
+ when aluModeCmp =>
+ ninebits := ("0" & aluCmpInput) + ("0" & (not rmwBits(7 downto 0))) + "000000001";
+ when aluModeAnd =>
+ ninebits := rmwBits(8) & (A and rmwBits(7 downto 0));
+ when aluModeEor =>
+ ninebits := rmwBits(8) & (A xor rmwBits(7 downto 0));
+ when aluModeOra =>
+ ninebits := rmwBits(8) & (A or rmwBits(7 downto 0));
+ when others =>
+ ninebits := rmwBits;
+ end case;
+
+ if (opcInfo(aluMode1From to aluMode1To) = aluModeFlg) then
+ varZ := rmwBits(1);
+ elsif ninebits(7 downto 0) = X"00" then
+ varZ := '1';
+ else
+ varZ := '0';
+ end if;
+
+ case opcInfo(aluMode2From to aluMode2To) is
+ when aluModeAdc =>
+ -- decimal mode low bits correction, is done after setting Z flag.
+ if D = '1' then
+ if lowBits(5 downto 1) > 9 then
+ ninebits(3 downto 0) := ninebits(3 downto 0) + 6;
+ if lowBits(5) = '0' then
+ ninebits(8 downto 4) := ninebits(8 downto 4) + 1;
+ end if;
+ end if;
+ end if;
+ when others =>
+ null;
+ end case;
+
+ if (opcInfo(aluMode1From to aluMode1To) = aluModeBit)
+ or (opcInfo(aluMode1From to aluMode1To) = aluModeFlg) then
+ varN := rmwBits(7);
+ else
+ varN := nineBits(7);
+ end if;
+ varC := ninebits(8);
+ if opcInfo(aluMode2From to aluMode2To) = aluModeArr then
+ varC := aluInput(7);
+ varV := aluInput(7) xor aluInput(6);
+ end if;
+
+ case opcInfo(aluMode2From to aluMode2To) is
+ when aluModeAdc =>
+ -- decimal mode high bits correction, is done after setting Z and N flags
+ varV := (A(7) xor ninebits(7)) and (rmwBits(7) xor ninebits(7));
+ if D = '1' then
+ if ninebits(8 downto 4) > 9 then
+ ninebits(8 downto 4) := ninebits(8 downto 4) + 6;
+ varC := '1';
+ end if;
+ end if;
+ when aluModeSbc =>
+ varV := (A(7) xor ninebits(7)) and ((not rmwBits(7)) xor ninebits(7));
+ if D = '1' then
+ -- Check for borrow (lower 4 bits)
+ if lowBits(5) = '0' then
+ ninebits(3 downto 0) := ninebits(3 downto 0) - 6;
+ end if;
+ -- Check for borrow (upper 4 bits)
+ if ninebits(8) = '0' then
+ ninebits(8 downto 4) := ninebits(8 downto 4) - 6;
+ end if;
+ end if;
+ when aluModeArr =>
+ if D = '1' then
+ if (("0" & aluInput(3 downto 0)) + ("0000" & aluInput(0))) > 5 then
+ ninebits(3 downto 0) := ninebits(3 downto 0) + 6;
+ end if;
+ if (("0" & aluInput(7 downto 4)) + ("0000" & aluInput(4))) > 5 then
+ ninebits(8 downto 4) := ninebits(8 downto 4) + 6;
+ varC := '1';
+ else
+ varC := '0';
+ end if;
+ end if;
+ when others =>
+ null;
+ end case;
+
+ if rising_edge(clk) then
+ aluRmwReg <= rmwBits(7 downto 0);
+ aluNineReg <= ninebits(7 downto 0);
+ aluCReg <= varC;
+ aluZReg <= varZ;
+ aluVReg <= varV;
+ aluNReg <= varN;
+ end if;
+
+ aluRmwOut <= rmwBits(7 downto 0);
+ aluRegisterOut <= ninebits(7 downto 0);
+ aluC <= varC;
+ aluZ <= varZ;
+ aluV <= varV;
+ aluN <= varN;
+ if pipelineAluOut then
+ aluRmwOut <= aluRmwReg;
+ aluRegisterOut <= aluNineReg;
+ aluC <= aluCReg;
+ aluZ <= aluZReg;
+ aluV <= aluVReg;
+ aluN <= aluNReg;
+ end if;
+ end process;
+
+calcInterrupt: process(clk)
+ begin
+ if rising_edge(clk) then
+ if enable = '1' then
+ if theCpuCycle = cycleStack4
+ or reset = '1' then
+ nmiReg <= '1';
+ end if;
+
+ if nextCpuCycle /= cycleBranchTaken
+ and nextCpuCycle /= opcodeFetch then
+ irqReg <= irq_n;
+ nmiEdge <= nmi_n;
+ if (nmiEdge = '1') and (nmi_n = '0') then
+ nmiReg <= '0';
+ end if;
+ end if;
+ -- The 'or opcInfo(opcSetI)' prevents NMI immediately after BRK or IRQ.
+ -- Presumably this is done in the real 6502/6510 to prevent a double IRQ.
+ processIrq <= not ((nmiReg and (irqReg or I)) or opcInfo(opcIRQ));
+ end if;
+ end if;
+ end process;
+
+calcNextOpcode: process(clk, di, reset, processIrq)
+ variable myNextOpcode : unsigned(7 downto 0);
+ begin
+ -- Next opcode is read from input unless a reset or IRQ is pending.
+ myNextOpcode := di;
+ if reset = '1' then
+ myNextOpcode := X"4C";
+ elsif processIrq = '1' then
+ myNextOpcode := X"00";
+ end if;
+
+ nextOpcode <= myNextOpcode;
+ end process;
+
+ nextOpcInfo <= opcodeInfoTable(to_integer(nextOpcode));
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ nextOpcInfoReg <= nextOpcInfo;
+ end if;
+ end process;
+
+ -- Read bits and flags from opcodeInfoTable and store in opcInfo.
+ -- This info is used to control the execution of the opcode.
+calcOpcInfo: process(clk)
+ begin
+ if rising_edge(clk) then
+ if enable = '1' then
+ if (reset = '1') or (theCpuCycle = opcodeFetch) then
+ opcInfo <= nextOpcInfo;
+ if pipelineOpcode then
+ opcInfo <= nextOpcInfoReg;
+ end if;
+ end if;
+ end if;
+ end if;
+ end process;
+
+calcTheOpcode: process(clk)
+ begin
+ if rising_edge(clk) then
+ if enable = '1' then
+ if theCpuCycle = opcodeFetch then
+ irqActive <= '0';
+ if processIrq = '1' then
+ irqActive <= '1';
+ end if;
+ -- Fetch opcode
+ theOpcode <= nextOpcode;
+ end if;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- State machine
+-- -----------------------------------------------------------------------
+ process(enable, theCpuCycle, opcInfo)
+ begin
+ updateRegisters <= false;
+ if enable = '1' then
+ if opcInfo(opcRti) = '1' then
+ if theCpuCycle = cycleRead then
+ updateRegisters <= true;
+ end if;
+ elsif theCpuCycle = opcodeFetch then
+ updateRegisters <= true;
+ end if;
+ end if;
+ end process;
+
+ debugOpcode <= theOpcode;
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if enable = '1' then
+ theCpuCycle <= nextCpuCycle;
+ end if;
+ if reset = '1' then
+ theCpuCycle <= cycle2;
+ end if;
+ end if;
+ end process;
+
+ -- Determine the next cpu cycle. After the last cycle we always
+ -- go to opcodeFetch to get the next opcode.
+calcNextCpuCycle: process(theCpuCycle, opcInfo, theOpcode, indexOut, T, N, V, C, Z)
+ begin
+ nextCpuCycle <= opcodeFetch;
+
+ case theCpuCycle is
+ when opcodeFetch =>
+ nextCpuCycle <= cycle2;
+ when cycle2 =>
+ if opcInfo(opcBranch) = '1' then
+ if (N = theOpcode(5) and theOpcode(7 downto 6) = "00")
+ or (V = theOpcode(5) and theOpcode(7 downto 6) = "01")
+ or (C = theOpcode(5) and theOpcode(7 downto 6) = "10")
+ or (Z = theOpcode(5) and theOpcode(7 downto 6) = "11") then
+ -- Branch condition is true
+ nextCpuCycle <= cycleBranchTaken;
+ end if;
+ elsif (opcInfo(opcStackUp) = '1') then
+ nextCpuCycle <= cycleStack1;
+ elsif opcInfo(opcStackAddr) = '1'
+ and opcInfo(opcStackData) = '1' then
+ nextCpuCycle <= cycleStack2;
+ elsif opcInfo(opcStackAddr) = '1' then
+ nextCpuCycle <= cycleStack1;
+ elsif opcInfo(opcStackData) = '1' then
+ nextCpuCycle <= cycleWrite;
+ elsif opcInfo(opcAbsolute) = '1' then
+ nextCpuCycle <= cycle3;
+ elsif opcInfo(opcIndirect) = '1' then
+ if opcInfo(indexX) = '1' then
+ nextCpuCycle <= cyclePreIndirect;
+ else
+ nextCpuCycle <= cycleIndirect;
+ end if;
+ elsif opcInfo(opcZeroPage) = '1' then
+ if opcInfo(opcWrite) = '1' then
+ if (opcInfo(indexX) = '1')
+ or (opcInfo(indexY) = '1') then
+ nextCpuCycle <= cyclePreWrite;
+ else
+ nextCpuCycle <= cycleWrite;
+ end if;
+ else
+ if (opcInfo(indexX) = '1')
+ or (opcInfo(indexY) = '1') then
+ nextCpuCycle <= cyclePreRead;
+ else
+ nextCpuCycle <= cycleRead2;
+ end if;
+ end if;
+ elsif opcInfo(opcJump) = '1' then
+ nextCpuCycle <= cycleJump;
+ end if;
+ when cycle3 =>
+ nextCpuCycle <= cycleRead;
+ if opcInfo(opcWrite) = '1' then
+ if (opcInfo(indexX) = '1')
+ or (opcInfo(indexY) = '1') then
+ nextCpuCycle <= cyclePreWrite;
+ else
+ nextCpuCycle <= cycleWrite;
+ end if;
+ end if;
+ if (opcInfo(opcIndirect) = '1')
+ and (opcInfo(indexX) = '1') then
+ if opcInfo(opcWrite) = '1' then
+ nextCpuCycle <= cycleWrite;
+ else
+ nextCpuCycle <= cycleRead2;
+ end if;
+ end if;
+ when cyclePreIndirect =>
+ nextCpuCycle <= cycleIndirect;
+ when cycleIndirect =>
+ nextCpuCycle <= cycle3;
+ when cycleBranchTaken =>
+ if indexOut(8) /= T(7) then
+ -- Page boundary crossing during branch.
+ nextCpuCycle <= cycleBranchPage;
+ end if;
+ when cyclePreRead =>
+ if opcInfo(opcZeroPage) = '1' then
+ nextCpuCycle <= cycleRead2;
+ end if;
+ when cycleRead =>
+ if opcInfo(opcJump) = '1' then
+ nextCpuCycle <= cycleJump;
+ elsif indexOut(8) = '1' then
+ -- Page boundary crossing while indexed addressing.
+ nextCpuCycle <= cycleRead2;
+ elsif opcInfo(opcRmw) = '1' then
+ nextCpuCycle <= cycleRmw;
+ if opcInfo(indexX) = '1'
+ or opcInfo(indexY) = '1' then
+ -- 6510 needs extra cycle for indexed addressing
+ -- combined with RMW indexing
+ nextCpuCycle <= cycleRead2;
+ end if;
+ end if;
+ when cycleRead2 =>
+ if opcInfo(opcRmw) = '1' then
+ nextCpuCycle <= cycleRmw;
+ end if;
+ when cycleRmw =>
+ nextCpuCycle <= cycleWrite;
+ when cyclePreWrite =>
+ nextCpuCycle <= cycleWrite;
+ when cycleStack1 =>
+ nextCpuCycle <= cycleRead;
+ if opcInfo(opcStackAddr) = '1' then
+ nextCpuCycle <= cycleStack2;
+ end if;
+ when cycleStack2 =>
+ nextCpuCycle <= cycleStack3;
+ if opcInfo(opcRti) = '1' then
+ nextCpuCycle <= cycleRead;
+ end if;
+ if opcInfo(opcStackData) = '0'
+ and opcInfo(opcStackUp) = '1' then
+ nextCpuCycle <= cycleJump;
+ end if;
+ when cycleStack3 =>
+ nextCpuCycle <= cycleRead;
+ if opcInfo(opcStackData) = '0'
+ or opcInfo(opcStackUp) = '1' then
+ nextCpuCycle <= cycleJump;
+ elsif opcInfo(opcStackAddr) = '1' then
+ nextCpuCycle <= cycleStack4;
+ end if;
+ when cycleStack4 =>
+ nextCpuCycle <= cycleRead;
+ when cycleJump =>
+ if opcInfo(opcIncrAfter) = '1' then
+ -- Insert extra cycle
+ nextCpuCycle <= cycleEnd;
+ end if;
+ when others =>
+ null;
+ end case;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- T register
+-- -----------------------------------------------------------------------
+calcT: process(clk)
+ begin
+ if rising_edge(clk) then
+ if enable = '1' then
+ case theCpuCycle is
+ when cycle2 =>
+ T <= di;
+ when cycleStack1 | cycleStack2 =>
+ if opcInfo(opcStackUp) = '1' then
+ -- Read from stack
+ T <= di;
+ end if;
+ when cycleIndirect | cycleRead | cycleRead2 =>
+ T <= di;
+ when others =>
+ null;
+ end case;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- A register
+-- -----------------------------------------------------------------------
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if updateRegisters then
+ if opcInfo(opcUpdateA) = '1' then
+ A <= aluRegisterOut;
+ end if;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- X register
+-- -----------------------------------------------------------------------
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if updateRegisters then
+ if opcInfo(opcUpdateX) = '1' then
+ X <= aluRegisterOut;
+ end if;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- Y register
+-- -----------------------------------------------------------------------
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if updateRegisters then
+ if opcInfo(opcUpdateY) = '1' then
+ Y <= aluRegisterOut;
+ end if;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- C flag
+-- -----------------------------------------------------------------------
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if updateRegisters then
+ if opcInfo(opcUpdateC) = '1' then
+ C <= aluC;
+ end if;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- Z flag
+-- -----------------------------------------------------------------------
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if updateRegisters then
+ if opcInfo(opcUpdateZ) = '1' then
+ Z <= aluZ;
+ end if;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- I flag
+-- -----------------------------------------------------------------------
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if updateRegisters then
+ if opcInfo(opcUpdateI) = '1' then
+ I <= aluInput(2);
+ end if;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- D flag
+-- -----------------------------------------------------------------------
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if updateRegisters then
+ if opcInfo(opcUpdateD) = '1' then
+ D <= aluInput(3);
+ end if;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- V flag
+-- -----------------------------------------------------------------------
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if updateRegisters then
+ if opcInfo(opcUpdateV) = '1' then
+ V <= aluV;
+ end if;
+ end if;
+ if enable = '1' then
+ if soReg = '1' and so_n = '0' then
+ V <= '1';
+ end if;
+ soReg <= so_n;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- N flag
+-- -----------------------------------------------------------------------
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if updateRegisters then
+ if opcInfo(opcUpdateN) = '1' then
+ N <= aluN;
+ end if;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- Stack pointer
+-- -----------------------------------------------------------------------
+ process(clk)
+ variable sIncDec : unsigned(7 downto 0);
+ variable updateFlag : boolean;
+ begin
+ if rising_edge(clk) then
+
+ if opcInfo(opcStackUp) = '1' then
+ sIncDec := S + 1;
+ else
+ sIncDec := S - 1;
+ end if;
+
+ if enable = '1' then
+ updateFlag := false;
+ case nextCpuCycle is
+ when cycleStack1 =>
+ if (opcInfo(opcStackUp) = '1')
+ or (opcInfo(opcStackData) = '1') then
+ updateFlag := true;
+ end if;
+ when cycleStack2 =>
+ updateFlag := true;
+ when cycleStack3 =>
+ updateFlag := true;
+ when cycleStack4 =>
+ updateFlag := true;
+ when cycleRead =>
+ if opcInfo(opcRti) = '1' then
+ updateFlag := true;
+ end if;
+ when cycleWrite =>
+ if opcInfo(opcStackData) = '1' then
+ updateFlag := true;
+ end if;
+ when others =>
+ null;
+ end case;
+ if updateFlag then
+ S <= sIncDec;
+ end if;
+ end if;
+ if updateRegisters then
+ if opcInfo(opcUpdateS) = '1' then
+ S <= aluRegisterOut;
+ end if;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- Data out
+-- -----------------------------------------------------------------------
+--calcDo: process(cpuNo, theCpuCycle, aluOut, PC, T)
+calcDo: process(clk)
+ begin
+ if rising_edge(clk) then
+ if enable = '1' then
+ doReg <= aluRmwOut;
+ if opcInfo(opcInH) = '1' then
+ -- For illegal opcodes SHA, SHX, SHY, SHS
+ doReg <= aluRmwOut and myAddrIncrH;
+ end if;
+
+ case nextCpuCycle is
+ when cycleStack2 =>
+ if opcInfo(opcIRQ) = '1'
+ and irqActive = '0' then
+ doReg <= myAddrIncr(15 downto 8);
+ else
+ doReg <= PC(15 downto 8);
+ end if;
+ when cycleStack3 =>
+ doReg <= PC(7 downto 0);
+ when cycleRmw =>
+-- do <= T; -- Read-modify-write write old value first.
+ doReg <= di; -- Read-modify-write write old value first.
+ when others => null;
+ end case;
+ end if;
+ end if;
+ end process;
+ do <= doReg;
+
+
+
+-- -----------------------------------------------------------------------
+-- Write enable
+-- -----------------------------------------------------------------------
+calcWe: process(clk)
+ begin
+ if rising_edge(clk) then
+ if enable = '1' then
+ theWe <= '0';
+ case nextCpuCycle is
+ when cycleStack1 =>
+ if opcInfo(opcStackUp) = '0'
+ and ((opcInfo(opcStackAddr) = '0')
+ or (opcInfo(opcStackData) = '1')) then
+ theWe <= '1';
+ end if;
+ when cycleStack2 | cycleStack3 | cycleStack4 =>
+ if opcInfo(opcStackUp) = '0' then
+ theWe <= '1';
+ end if;
+ when cycleRmw =>
+ theWe <= '1';
+ when cycleWrite =>
+ theWe <= '1';
+ when others =>
+ null;
+ end case;
+ end if;
+ end if;
+ end process;
+ we <= theWe;
+
+-- -----------------------------------------------------------------------
+-- Program counter
+-- -----------------------------------------------------------------------
+calcPC: process(clk)
+ begin
+ if rising_edge(clk) then
+ if enable = '1' then
+ case theCpuCycle is
+ when opcodeFetch =>
+ PC <= myAddr;
+ when cycle2 =>
+ if irqActive = '0' then
+ if opcInfo(opcSecondByte) = '1' then
+ PC <= myAddrIncr;
+ else
+ PC <= myAddr;
+ end if;
+ end if;
+ when cycle3 =>
+ if opcInfo(opcAbsolute) = '1' then
+ PC <= myAddrIncr;
+ end if;
+ when others =>
+ null;
+ end case;
+ end if;
+ end if;
+ end process;
+ debugPc <= PC;
+
+-- -----------------------------------------------------------------------
+-- Address generation
+-- -----------------------------------------------------------------------
+calcNextAddr: process(theCpuCycle, opcInfo, indexOut, T, reset)
+ begin
+ nextAddr <= nextAddrIncr;
+ case theCpuCycle is
+ when cycle2 =>
+ if opcInfo(opcStackAddr) = '1'
+ or opcInfo(opcStackData) = '1' then
+ nextAddr <= nextAddrStack;
+ elsif opcInfo(opcAbsolute) = '1' then
+ nextAddr <= nextAddrIncr;
+ elsif opcInfo(opcZeroPage) = '1' then
+ nextAddr <= nextAddrZeroPage;
+ elsif opcInfo(opcIndirect) = '1' then
+ nextAddr <= nextAddrZeroPage;
+ elsif opcInfo(opcSecondByte) = '1' then
+ nextAddr <= nextAddrIncr;
+ else
+ nextAddr <= nextAddrHold;
+ end if;
+ when cycle3 =>
+ if (opcInfo(opcIndirect) = '1')
+ and (opcInfo(indexX) = '1') then
+ nextAddr <= nextAddrAbs;
+ else
+ nextAddr <= nextAddrAbsIndexed;
+ end if;
+ when cyclePreIndirect =>
+ nextAddr <= nextAddrZPIndexed;
+ when cycleIndirect =>
+ nextAddr <= nextAddrIncrL;
+ when cycleBranchTaken =>
+ nextAddr <= nextAddrRelative;
+ when cycleBranchPage =>
+ if T(7) = '0' then
+ nextAddr <= nextAddrIncrH;
+ else
+ nextAddr <= nextAddrDecrH;
+ end if;
+ when cyclePreRead =>
+ nextAddr <= nextAddrZPIndexed;
+ when cycleRead =>
+ nextAddr <= nextAddrPc;
+ if opcInfo(opcJump) = '1' then
+ -- Emulate 6510 bug, jmp(xxFF) fetches from same page.
+ -- Replace with nextAddrIncr if emulating 65C02 or later cpu.
+ nextAddr <= nextAddrIncrL;
+ elsif indexOut(8) = '1' then
+ nextAddr <= nextAddrIncrH;
+ elsif opcInfo(opcRmw) = '1' then
+ nextAddr <= nextAddrHold;
+ end if;
+ when cycleRead2 =>
+ nextAddr <= nextAddrPc;
+ if opcInfo(opcRmw) = '1' then
+ nextAddr <= nextAddrHold;
+ end if;
+ when cycleRmw =>
+ nextAddr <= nextAddrHold;
+ when cyclePreWrite =>
+ nextAddr <= nextAddrHold;
+ if opcInfo(opcZeroPage) = '1' then
+ nextAddr <= nextAddrZPIndexed;
+ elsif indexOut(8) = '1' then
+ nextAddr <= nextAddrIncrH;
+ end if;
+ when cycleWrite =>
+ nextAddr <= nextAddrPc;
+ when cycleStack1 =>
+ nextAddr <= nextAddrStack;
+ when cycleStack2 =>
+ nextAddr <= nextAddrStack;
+ when cycleStack3 =>
+ nextAddr <= nextAddrStack;
+ if opcInfo(opcStackData) = '0' then
+ nextAddr <= nextAddrPc;
+ end if;
+ when cycleStack4 =>
+ nextAddr <= nextAddrIrq;
+ when cycleJump =>
+ nextAddr <= nextAddrAbs;
+ when others =>
+ null;
+ end case;
+ if reset = '1' then
+ nextAddr <= nextAddrReset;
+ end if;
+ end process;
+
+indexAlu: process(opcInfo, myAddr, T, X, Y)
+ begin
+ if opcInfo(indexX) = '1' then
+ indexOut <= (B"0" & T) + (B"0" & X);
+ elsif opcInfo(indexY) = '1' then
+ indexOut <= (B"0" & T) + (B"0" & Y);
+ elsif opcInfo(opcBranch) = '1' then
+ indexOut <= (B"0" & T) + (B"0" & myAddr(7 downto 0));
+ else
+ indexOut <= B"0" & T;
+ end if;
+ end process;
+
+calcAddr: process(clk)
+ begin
+ if rising_edge(clk) then
+ if enable = '1' then
+ case nextAddr is
+ when nextAddrIncr => myAddr <= myAddrIncr;
+ when nextAddrIncrL => myAddr(7 downto 0) <= myAddrIncr(7 downto 0);
+ when nextAddrIncrH => myAddr(15 downto 8) <= myAddrIncrH;
+ when nextAddrDecrH => myAddr(15 downto 8) <= myAddrDecrH;
+ when nextAddrPc => myAddr <= PC;
+ when nextAddrIrq =>
+ myAddr <= X"FFFE";
+ if nmiReg = '0' then
+ myAddr <= X"FFFA";
+ end if;
+ when nextAddrReset => myAddr <= X"FFFC";
+ when nextAddrAbs => myAddr <= di & T;
+ when nextAddrAbsIndexed => myAddr <= di & indexOut(7 downto 0);
+ when nextAddrZeroPage => myAddr <= "00000000" & di;
+ when nextAddrZPIndexed => myAddr <= "00000000" & indexOut(7 downto 0);
+ when nextAddrStack => myAddr <= "00000001" & S;
+ when nextAddrRelative => myAddr(7 downto 0) <= indexOut(7 downto 0);
+ when others => null;
+ end case;
+ end if;
+ end if;
+ end process;
+
+ myAddrIncr <= myAddr + 1;
+ myAddrIncrH <= myAddr(15 downto 8) + 1;
+ myAddrDecrH <= myAddr(15 downto 8) - 1;
+
+ addr <= myAddr;
+
+ debugA <= A;
+ debugX <= X;
+ debugY <= Y;
+ debugS <= S;
+
+end architecture;
+
+
diff --git a/common/CPU/6502_6510/cpu65xx_e.vhd b/common/CPU/6502_6510/cpu65xx_e.vhd
new file mode 100644
index 00000000..72e4b6cd
--- /dev/null
+++ b/common/CPU/6502_6510/cpu65xx_e.vhd
@@ -0,0 +1,87 @@
+-- -----------------------------------------------------------------------
+--
+-- FPGA 64
+--
+-- A fully functional commodore 64 implementation in a single FPGA
+--
+-- -----------------------------------------------------------------------
+-- Copyright 2005-2008 by Peter Wendrich (pwsoft@syntiac.com)
+-- http://www.syntiac.com/fpga64.html
+-- -----------------------------------------------------------------------
+--
+-- Interface to 6502/6510 core
+--
+-- -----------------------------------------------------------------------
+
+library IEEE;
+use ieee.std_logic_1164.ALL;
+use ieee.numeric_std.ALL;
+
+-- -----------------------------------------------------------------------
+
+entity cpu65xx is
+ generic (
+ pipelineOpcode : boolean;
+ pipelineAluMux : boolean;
+ pipelineAluOut : boolean
+ );
+ port (
+ clk : in std_logic;
+ enable : in std_logic;
+ reset : in std_logic;
+ nmi_n : in std_logic;
+ irq_n : in std_logic;
+ so_n : in std_logic := '1';
+
+ di : in unsigned(7 downto 0);
+ do : out unsigned(7 downto 0);
+ addr : out unsigned(15 downto 0);
+ we : out std_logic;
+
+ debugOpcode : out unsigned(7 downto 0);
+ debugPc : out unsigned(15 downto 0);
+ debugA : out unsigned(7 downto 0);
+ debugX : out unsigned(7 downto 0);
+ debugY : out unsigned(7 downto 0);
+ debugS : out unsigned(7 downto 0)
+ );
+end cpu65xx;
+
+library IEEE;
+use ieee.std_logic_1164.ALL;
+use ieee.numeric_std.ALL;
+
+entity cpu6502 is
+ port(
+ clk : in std_logic;
+ ce : in std_logic;
+ reset : in std_logic;
+ nmi : in std_logic;
+ irq : in std_logic;
+ din : in unsigned(7 downto 0);
+ dout : out unsigned(7 downto 0);
+ addr : out unsigned(15 downto 0);
+ we : out std_logic
+ );
+end cpu6502;
+
+architecture cpu6502 of cpu6502 is
+begin
+ cpuInstance: entity work.cpu65xx(fast)
+ generic map (
+ pipelineOpcode => false,
+ pipelineAluMux => false,
+ pipelineAluOut => false
+ )
+ port map (
+ clk => clk,
+ enable=> ce,
+ reset => reset,
+ nmi_n => not nmi,
+ irq_n => not irq,
+ di => din,
+ do => dout,
+ addr => addr,
+ we => we
+ );
+end architecture;
diff --git a/common/CPU/6502_6510/cpu65xx_fast.vhd b/common/CPU/6502_6510/cpu65xx_fast.vhd
new file mode 100644
index 00000000..a387b37d
--- /dev/null
+++ b/common/CPU/6502_6510/cpu65xx_fast.vhd
@@ -0,0 +1,1565 @@
+-- -----------------------------------------------------------------------
+--
+-- FPGA 64
+--
+-- A fully functional commodore 64 implementation in a single FPGA
+--
+-- -----------------------------------------------------------------------
+-- Copyright 2005-2008 by Peter Wendrich (pwsoft@syntiac.com)
+-- http://www.syntiac.com/fpga64.html
+-- -----------------------------------------------------------------------
+--
+-- Table driven, cycle exact 6502/6510 core
+--
+-- -----------------------------------------------------------------------
+
+library IEEE;
+use ieee.std_logic_1164.ALL;
+use ieee.std_logic_unsigned.ALL;
+use ieee.numeric_std.ALL;
+
+-- -----------------------------------------------------------------------
+
+-- Store Zp (3) => fetch, cycle2, cycleEnd
+-- Store Zp,x (4) => fetch, cycle2, preWrite, cycleEnd
+-- Read Zp,x (4) => fetch, cycle2, cycleRead, cycleRead2
+-- Rmw Zp,x (6) => fetch, cycle2, cycleRead, cycleRead2, cycleRmw, cycleEnd
+-- Store Abs (4) => fetch, cycle2, cycle3, cycleEnd
+-- Store Abs,x (5) => fetch, cycle2, cycle3, preWrite, cycleEnd
+-- Rts (6) => fetch, cycle2, cycle3, cycleRead, cycleJump, cycleIncrEnd
+-- Rti (6) => fetch, cycle2, stack1, stack2, stack3, cycleJump
+-- Jsr (6) => fetch, cycle2, .. cycle5, cycle6, cycleJump
+-- Jmp abs (-) => fetch, cycle2, .., cycleJump
+-- Jmp (ind) (-) => fetch, cycle2, .., cycleJump
+-- Brk / irq (6) => fetch, cycle2, stack2, stack3, stack4
+-- -----------------------------------------------------------------------
+
+architecture fast of cpu65xx is
+-- Statemachine
+ type cpuCycles is (
+ opcodeFetch, -- New opcode is read and registers updated
+ cycle2,
+ cycle3,
+ cyclePreIndirect,
+ cycleIndirect,
+ cycleBranchTaken,
+ cycleBranchPage,
+ cyclePreRead, -- Cycle before read while doing zeropage indexed addressing.
+ cycleRead, -- Read cycle
+ cycleRead2, -- Second read cycle after page-boundary crossing.
+ cycleRmw, -- Calculate ALU output for read-modify-write instr.
+ cyclePreWrite, -- Cycle before write when doing indexed addressing.
+ cycleWrite, -- Write cycle for zeropage or absolute addressing.
+ cycleStack1,
+ cycleStack2,
+ cycleStack3,
+ cycleStack4,
+ cycleJump, -- Last cycle of Jsr, Jmp. Next fetch address is target addr.
+ cycleEnd
+ );
+ signal theCpuCycle : cpuCycles;
+ signal nextCpuCycle : cpuCycles;
+ signal updateRegisters : boolean;
+ signal processIrq : std_logic;
+ signal nmiReg: std_logic;
+ signal nmiEdge: std_logic;
+ signal irqReg : std_logic; -- Delay IRQ input with one clock cycle.
+ signal soReg : std_logic; -- SO pin edge detection
+
+-- Opcode decoding
+ constant opcUpdateA : integer := 0;
+ constant opcUpdateX : integer := 1;
+ constant opcUpdateY : integer := 2;
+ constant opcUpdateS : integer := 3;
+ constant opcUpdateN : integer := 4;
+ constant opcUpdateV : integer := 5;
+ constant opcUpdateD : integer := 6;
+ constant opcUpdateI : integer := 7;
+ constant opcUpdateZ : integer := 8;
+ constant opcUpdateC : integer := 9;
+
+ constant opcSecondByte : integer := 10;
+ constant opcAbsolute : integer := 11;
+ constant opcZeroPage : integer := 12;
+ constant opcIndirect : integer := 13;
+ constant opcStackAddr : integer := 14; -- Push/Pop address
+ constant opcStackData : integer := 15; -- Push/Pop status/data
+ constant opcJump : integer := 16;
+ constant opcBranch : integer := 17;
+ constant indexX : integer := 18;
+ constant indexY : integer := 19;
+ constant opcStackUp : integer := 20;
+ constant opcWrite : integer := 21;
+ constant opcRmw : integer := 22;
+ constant opcIncrAfter : integer := 23; -- Insert extra cycle to increment PC (RTS)
+ constant opcRti : integer := 24;
+ constant opcIRQ : integer := 25;
+
+ constant opcInA : integer := 26;
+ constant opcInE : integer := 27;
+ constant opcInX : integer := 28;
+ constant opcInY : integer := 29;
+ constant opcInS : integer := 30;
+ constant opcInT : integer := 31;
+ constant opcInH : integer := 32;
+ constant opcInClear : integer := 33;
+ constant aluMode1From : integer := 34;
+ --
+ constant aluMode1To : integer := 37;
+ constant aluMode2From : integer := 38;
+ --
+ constant aluMode2To : integer := 40;
+ --
+ constant opcInCmp : integer := 41;
+ constant opcInCpx : integer := 42;
+ constant opcInCpy : integer := 43;
+
+
+ subtype addrDef is unsigned(0 to 15);
+ --
+ -- is Interrupt -----------------+
+ -- instruction is RTI ----------------+|
+ -- PC++ on last cycle (RTS) ---------------+||
+ -- RMW --------------+|||
+ -- Write -------------+||||
+ -- Pop/Stack up -------------+|||||
+ -- Branch ---------+ ||||||
+ -- Jump ----------+| ||||||
+ -- Push or Pop data -------+|| ||||||
+ -- Push or Pop addr ------+||| ||||||
+ -- Indirect -----+|||| ||||||
+ -- ZeroPage ----+||||| ||||||
+ -- Absolute ---+|||||| ||||||
+ -- PC++ on cycle2 --+||||||| ||||||
+ -- |AZI||JBXY|WM|||
+ constant immediate : addrDef := "1000000000000000";
+ constant implied : addrDef := "0000000000000000";
+ -- Zero page
+ constant readZp : addrDef := "1010000000000000";
+ constant writeZp : addrDef := "1010000000010000";
+ constant rmwZp : addrDef := "1010000000001000";
+ -- Zero page indexed
+ constant readZpX : addrDef := "1010000010000000";
+ constant writeZpX : addrDef := "1010000010010000";
+ constant rmwZpX : addrDef := "1010000010001000";
+ constant readZpY : addrDef := "1010000001000000";
+ constant writeZpY : addrDef := "1010000001010000";
+ constant rmwZpY : addrDef := "1010000001001000";
+ -- Zero page indirect
+ constant readIndX : addrDef := "1001000010000000";
+ constant writeIndX : addrDef := "1001000010010000";
+ constant rmwIndX : addrDef := "1001000010001000";
+ constant readIndY : addrDef := "1001000001000000";
+ constant writeIndY : addrDef := "1001000001010000";
+ constant rmwIndY : addrDef := "1001000001001000";
+ -- |AZI||JBXY|WM||
+ -- Absolute
+ constant readAbs : addrDef := "1100000000000000";
+ constant writeAbs : addrDef := "1100000000010000";
+ constant rmwAbs : addrDef := "1100000000001000";
+ constant readAbsX : addrDef := "1100000010000000";
+ constant writeAbsX : addrDef := "1100000010010000";
+ constant rmwAbsX : addrDef := "1100000010001000";
+ constant readAbsY : addrDef := "1100000001000000";
+ constant writeAbsY : addrDef := "1100000001010000";
+ constant rmwAbsY : addrDef := "1100000001001000";
+ -- PHA PHP
+ constant push : addrDef := "0000010000000000";
+ -- PLA PLP
+ constant pop : addrDef := "0000010000100000";
+ -- Jumps
+ constant jsr : addrDef := "1000101000000000";
+ constant jumpAbs : addrDef := "1000001000000000";
+ constant jumpInd : addrDef := "1100001000000000";
+ constant relative : addrDef := "1000000100000000";
+ -- Specials
+ constant rts : addrDef := "0000101000100100";
+ constant rti : addrDef := "0000111000100010";
+ constant brk : addrDef := "1000111000000001";
+-- constant : unsigned(0 to 0) := "0";
+ constant xxxxxxxx : addrDef := "----------0---00";
+
+ -- A = accu
+ -- E = Accu | 0xEE (for ANE, LXA)
+ -- X = index X
+ -- Y = index Y
+ -- S = Stack pointer
+ -- H = indexH
+ --
+ -- AEXYSTHc
+ constant aluInA : unsigned(0 to 7) := "10000000";
+ constant aluInE : unsigned(0 to 7) := "01000000";
+ constant aluInEXT : unsigned(0 to 7) := "01100100";
+ constant aluInET : unsigned(0 to 7) := "01000100";
+ constant aluInX : unsigned(0 to 7) := "00100000";
+ constant aluInXH : unsigned(0 to 7) := "00100010";
+ constant aluInY : unsigned(0 to 7) := "00010000";
+ constant aluInYH : unsigned(0 to 7) := "00010010";
+ constant aluInS : unsigned(0 to 7) := "00001000";
+ constant aluInT : unsigned(0 to 7) := "00000100";
+ constant aluInAX : unsigned(0 to 7) := "10100000";
+ constant aluInAXH : unsigned(0 to 7) := "10100010";
+ constant aluInAT : unsigned(0 to 7) := "10000100";
+ constant aluInXT : unsigned(0 to 7) := "00100100";
+ constant aluInST : unsigned(0 to 7) := "00001100";
+ constant aluInSet : unsigned(0 to 7) := "00000000";
+ constant aluInClr : unsigned(0 to 7) := "00000001";
+ constant aluInXXX : unsigned(0 to 7) := "--------";
+
+ -- Most of the aluModes are just like the opcodes.
+ -- aluModeInp -> input is output. calculate N and Z
+ -- aluModeCmp -> Compare for CMP, CPX, CPY
+ -- aluModeFlg -> input to flags needed for PLP, RTI and CLC, SEC, CLV
+ -- aluModeInc -> for INC but also INX, INY
+ -- aluModeDec -> for DEC but also DEX, DEY
+
+ subtype aluMode1 is unsigned(0 to 3);
+ subtype aluMode2 is unsigned(0 to 2);
+ subtype aluMode is unsigned(0 to 9);
+
+ -- Logic/Shift ALU
+ constant aluModeInp : aluMode1 := "0000";
+ constant aluModeP : aluMode1 := "0001";
+ constant aluModeInc : aluMode1 := "0010";
+ constant aluModeDec : aluMode1 := "0011";
+ constant aluModeFlg : aluMode1 := "0100";
+ constant aluModeBit : aluMode1 := "0101";
+ -- 0110
+ -- 0111
+ constant aluModeLsr : aluMode1 := "1000";
+ constant aluModeRor : aluMode1 := "1001";
+ constant aluModeAsl : aluMode1 := "1010";
+ constant aluModeRol : aluMode1 := "1011";
+ -- 1100
+ -- 1101
+ -- 1110
+ constant aluModeAnc : aluMode1 := "1111";
+
+ -- Arithmetic ALU
+ constant aluModePss : aluMode2 := "000";
+ constant aluModeCmp : aluMode2 := "001";
+ constant aluModeAdc : aluMode2 := "010";
+ constant aluModeSbc : aluMode2 := "011";
+ constant aluModeAnd : aluMode2 := "100";
+ constant aluModeOra : aluMode2 := "101";
+ constant aluModeEor : aluMode2 := "110";
+ constant aluModeArr : aluMode2 := "111";
+
+
+ constant aluInp : aluMode := aluModeInp & aluModePss & "---";
+ constant aluP : aluMode := aluModeP & aluModePss & "---";
+ constant aluInc : aluMode := aluModeInc & aluModePss & "---";
+ constant aluDec : aluMode := aluModeDec & aluModePss & "---";
+ constant aluFlg : aluMode := aluModeFlg & aluModePss & "---";
+ constant aluBit : aluMode := aluModeBit & aluModeAnd & "---";
+ constant aluRor : aluMode := aluModeRor & aluModePss & "---";
+ constant aluLsr : aluMode := aluModeLsr & aluModePss & "---";
+ constant aluRol : aluMode := aluModeRol & aluModePss & "---";
+ constant aluAsl : aluMode := aluModeAsl & aluModePss & "---";
+
+ constant aluCmp : aluMode := aluModeInp & aluModeCmp & "100";
+ constant aluCpx : aluMode := aluModeInp & aluModeCmp & "010";
+ constant aluCpy : aluMode := aluModeInp & aluModeCmp & "001";
+ constant aluAdc : aluMode := aluModeInp & aluModeAdc & "---";
+ constant aluSbc : aluMode := aluModeInp & aluModeSbc & "---";
+ constant aluAnd : aluMode := aluModeInp & aluModeAnd & "---";
+ constant aluOra : aluMode := aluModeInp & aluModeOra & "---";
+ constant aluEor : aluMode := aluModeInp & aluModeEor & "---";
+
+ constant aluSlo : aluMode := aluModeAsl & aluModeOra & "---";
+ constant aluSre : aluMode := aluModeLsr & aluModeEor & "---";
+ constant aluRra : aluMode := aluModeRor & aluModeAdc & "---";
+ constant aluRla : aluMode := aluModeRol & aluModeAnd & "---";
+ constant aluDcp : aluMode := aluModeDec & aluModeCmp & "100";
+ constant aluIsc : aluMode := aluModeInc & aluModeSbc & "---";
+ constant aluAnc : aluMode := aluModeAnc & aluModeAnd & "---";
+ constant aluArr : aluMode := aluModeRor & aluModeArr & "---";
+ constant aluSbx : aluMode := aluModeInp & aluModeCmp & "110";
+
+ constant aluXXX : aluMode := (others => '-');
+
+
+ -- Stack operations. Push/Pop/None
+ constant stackInc : unsigned(0 to 0) := "0";
+ constant stackDec : unsigned(0 to 0) := "1";
+ constant stackXXX : unsigned(0 to 0) := "-";
+
+ subtype decodedBitsDef is unsigned(0 to 43);
+ type opcodeInfoTableDef is array(0 to 255) of decodedBitsDef;
+ constant opcodeInfoTable : opcodeInfoTableDef := (
+ -- +------- Update register A
+ -- |+------ Update register X
+ -- ||+----- Update register Y
+ -- |||+---- Update register S
+ -- |||| +-- Update Flags
+ -- |||| |
+ -- |||| _|__
+ -- |||| / \
+ -- AXYS NVDIZC addressing aluInput aluMode
+ "0000" & "000100" & brk & aluInXXX & aluP, -- 00 BRK
+ "1000" & "100010" & readIndX & aluInT & aluOra, -- 01 ORA (zp,x)
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 02 *** JAM ***
+ "1000" & "100011" & rmwIndX & aluInT & aluSlo, -- 03 iSLO (zp,x)
+ "0000" & "000000" & readZp & aluInXXX & aluXXX, -- 04 iNOP zp
+ "1000" & "100010" & readZp & aluInT & aluOra, -- 05 ORA zp
+ "0000" & "100011" & rmwZp & aluInT & aluAsl, -- 06 ASL zp
+ "1000" & "100011" & rmwZp & aluInT & aluSlo, -- 07 iSLO zp
+ "0000" & "000000" & push & aluInXXX & aluP, -- 08 PHP
+ "1000" & "100010" & immediate & aluInT & aluOra, -- 09 ORA imm
+ "1000" & "100011" & implied & aluInA & aluAsl, -- 0A ASL accu
+ "1000" & "100011" & immediate & aluInT & aluAnc, -- 0B iANC imm
+ "0000" & "000000" & readAbs & aluInXXX & aluXXX, -- 0C iNOP abs
+ "1000" & "100010" & readAbs & aluInT & aluOra, -- 0D ORA abs
+ "0000" & "100011" & rmwAbs & aluInT & aluAsl, -- 0E ASL abs
+ "1000" & "100011" & rmwAbs & aluInT & aluSlo, -- 0F iSLO abs
+ "0000" & "000000" & relative & aluInXXX & aluXXX, -- 10 BPL
+ "1000" & "100010" & readIndY & aluInT & aluOra, -- 11 ORA (zp),y
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 12 *** JAM ***
+ "1000" & "100011" & rmwIndY & aluInT & aluSlo, -- 13 iSLO (zp),y
+ "0000" & "000000" & readZpX & aluInXXX & aluXXX, -- 14 iNOP zp,x
+ "1000" & "100010" & readZpX & aluInT & aluOra, -- 15 ORA zp,x
+ "0000" & "100011" & rmwZpX & aluInT & aluAsl, -- 16 ASL zp,x
+ "1000" & "100011" & rmwZpX & aluInT & aluSlo, -- 17 iSLO zp,x
+ "0000" & "000001" & implied & aluInClr & aluFlg, -- 18 CLC
+ "1000" & "100010" & readAbsY & aluInT & aluOra, -- 19 ORA abs,y
+ "0000" & "000000" & implied & aluInXXX & aluXXX, -- 1A iNOP implied
+ "1000" & "100011" & rmwAbsY & aluInT & aluSlo, -- 1B iSLO abs,y
+ "0000" & "000000" & readAbsX & aluInXXX & aluXXX, -- 1C iNOP abs,x
+ "1000" & "100010" & readAbsX & aluInT & aluOra, -- 1D ORA abs,x
+ "0000" & "100011" & rmwAbsX & aluInT & aluAsl, -- 1E ASL abs,x
+ "1000" & "100011" & rmwAbsX & aluInT & aluSlo, -- 1F iSLO abs,x
+ -- AXYS NVDIZC addressing aluInput aluMode
+ "0000" & "000000" & jsr & aluInXXX & aluXXX, -- 20 JSR
+ "1000" & "100010" & readIndX & aluInT & aluAnd, -- 21 AND (zp,x)
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 22 *** JAM ***
+ "1000" & "100011" & rmwIndX & aluInT & aluRla, -- 23 iRLA (zp,x)
+ "0000" & "110010" & readZp & aluInT & aluBit, -- 24 BIT zp
+ "1000" & "100010" & readZp & aluInT & aluAnd, -- 25 AND zp
+ "0000" & "100011" & rmwZp & aluInT & aluRol, -- 26 ROL zp
+ "1000" & "100011" & rmwZp & aluInT & aluRla, -- 27 iRLA zp
+ "0000" & "111111" & pop & aluInT & aluFlg, -- 28 PLP
+ "1000" & "100010" & immediate & aluInT & aluAnd, -- 29 AND imm
+ "1000" & "100011" & implied & aluInA & aluRol, -- 2A ROL accu
+ "1000" & "100011" & immediate & aluInT & aluAnc, -- 2B iANC imm
+ "0000" & "110010" & readAbs & aluInT & aluBit, -- 2C BIT abs
+ "1000" & "100010" & readAbs & aluInT & aluAnd, -- 2D AND abs
+ "0000" & "100011" & rmwAbs & aluInT & aluRol, -- 2E ROL abs
+ "1000" & "100011" & rmwAbs & aluInT & aluRla, -- 2F iRLA abs
+ "0000" & "000000" & relative & aluInXXX & aluXXX, -- 30 BMI
+ "1000" & "100010" & readIndY & aluInT & aluAnd, -- 31 AND (zp),y
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 32 *** JAM ***
+ "1000" & "100011" & rmwIndY & aluInT & aluRla, -- 33 iRLA (zp),y
+ "0000" & "000000" & readZpX & aluInXXX & aluXXX, -- 34 iNOP zp,x
+ "1000" & "100010" & readZpX & aluInT & aluAnd, -- 35 AND zp,x
+ "0000" & "100011" & rmwZpX & aluInT & aluRol, -- 36 ROL zp,x
+ "1000" & "100011" & rmwZpX & aluInT & aluRla, -- 37 iRLA zp,x
+ "0000" & "000001" & implied & aluInSet & aluFlg, -- 38 SEC
+ "1000" & "100010" & readAbsY & aluInT & aluAnd, -- 39 AND abs,y
+ "0000" & "000000" & implied & aluInXXX & aluXXX, -- 3A iNOP implied
+ "1000" & "100011" & rmwAbsY & aluInT & aluRla, -- 3B iRLA abs,y
+ "0000" & "000000" & readAbsX & aluInXXX & aluXXX, -- 3C iNOP abs,x
+ "1000" & "100010" & readAbsX & aluInT & aluAnd, -- 3D AND abs,x
+ "0000" & "100011" & rmwAbsX & aluInT & aluRol, -- 3E ROL abs,x
+ "1000" & "100011" & rmwAbsX & aluInT & aluRla, -- 3F iRLA abs,x
+ -- AXYS NVDIZC addressing aluInput aluMode
+ "0000" & "111111" & rti & aluInT & aluFlg, -- 40 RTI
+ "1000" & "100010" & readIndX & aluInT & aluEor, -- 41 EOR (zp,x)
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 42 *** JAM ***
+ "1000" & "100011" & rmwIndX & aluInT & aluSre, -- 43 iSRE (zp,x)
+ "0000" & "000000" & readZp & aluInXXX & aluXXX, -- 44 iNOP zp
+ "1000" & "100010" & readZp & aluInT & aluEor, -- 45 EOR zp
+ "0000" & "100011" & rmwZp & aluInT & aluLsr, -- 46 LSR zp
+ "1000" & "100011" & rmwZp & aluInT & aluSre, -- 47 iSRE zp
+ "0000" & "000000" & push & aluInA & aluInp, -- 48 PHA
+ "1000" & "100010" & immediate & aluInT & aluEor, -- 49 EOR imm
+ "1000" & "100011" & implied & aluInA & aluLsr, -- 4A LSR accu
+ "1000" & "100011" & immediate & aluInAT & aluLsr, -- 4B iALR imm
+ "0000" & "000000" & jumpAbs & aluInXXX & aluXXX, -- 4C JMP abs
+ "1000" & "100010" & readAbs & aluInT & aluEor, -- 4D EOR abs
+ "0000" & "100011" & rmwAbs & aluInT & aluLsr, -- 4E LSR abs
+ "1000" & "100011" & rmwAbs & aluInT & aluSre, -- 4F iSRE abs
+ "0000" & "000000" & relative & aluInXXX & aluXXX, -- 50 BVC
+ "1000" & "100010" & readIndY & aluInT & aluEor, -- 51 EOR (zp),y
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 52 *** JAM ***
+ "1000" & "100011" & rmwIndY & aluInT & aluSre, -- 53 iSRE (zp),y
+ "0000" & "000000" & readZpX & aluInXXX & aluXXX, -- 54 iNOP zp,x
+ "1000" & "100010" & readZpX & aluInT & aluEor, -- 55 EOR zp,x
+ "0000" & "100011" & rmwZpX & aluInT & aluLsr, -- 56 LSR zp,x
+ "1000" & "100011" & rmwZpX & aluInT & aluSre, -- 57 SRE zp,x
+ "0000" & "000100" & implied & aluInClr & aluXXX, -- 58 CLI
+ "1000" & "100010" & readAbsY & aluInT & aluEor, -- 59 EOR abs,y
+ "0000" & "000000" & implied & aluInXXX & aluXXX, -- 5A iNOP implied
+ "1000" & "100011" & rmwAbsY & aluInT & aluSre, -- 5B iSRE abs,y
+ "0000" & "000000" & readAbsX & aluInXXX & aluXXX, -- 5C iNOP abs,x
+ "1000" & "100010" & readAbsX & aluInT & aluEor, -- 5D EOR abs,x
+ "0000" & "100011" & rmwAbsX & aluInT & aluLsr, -- 5E LSR abs,x
+ "1000" & "100011" & rmwAbsX & aluInT & aluSre, -- 5F SRE abs,x
+ -- AXYS NVDIZC addressing aluInput aluMode
+ "0000" & "000000" & rts & aluInXXX & aluXXX, -- 60 RTS
+ "1000" & "110011" & readIndX & aluInT & aluAdc, -- 61 ADC (zp,x)
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 62 *** JAM ***
+ "1000" & "110011" & rmwIndX & aluInT & aluRra, -- 63 iRRA (zp,x)
+ "0000" & "000000" & readZp & aluInXXX & aluXXX, -- 64 iNOP zp
+ "1000" & "110011" & readZp & aluInT & aluAdc, -- 65 ADC zp
+ "0000" & "100011" & rmwZp & aluInT & aluRor, -- 66 ROR zp
+ "1000" & "110011" & rmwZp & aluInT & aluRra, -- 67 iRRA zp
+ "1000" & "100010" & pop & aluInT & aluInp, -- 68 PLA
+ "1000" & "110011" & immediate & aluInT & aluAdc, -- 69 ADC imm
+ "1000" & "100011" & implied & aluInA & aluRor, -- 6A ROR accu
+ "1000" & "110011" & immediate & aluInAT & aluArr, -- 6B iARR imm
+ "0000" & "000000" & jumpInd & aluInXXX & aluXXX, -- 6C JMP indirect
+ "1000" & "110011" & readAbs & aluInT & aluAdc, -- 6D ADC abs
+ "0000" & "100011" & rmwAbs & aluInT & aluRor, -- 6E ROR abs
+ "1000" & "110011" & rmwAbs & aluInT & aluRra, -- 6F iRRA abs
+ "0000" & "000000" & relative & aluInXXX & aluXXX, -- 70 BVS
+ "1000" & "110011" & readIndY & aluInT & aluAdc, -- 71 ADC (zp),y
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 72 *** JAM ***
+ "1000" & "110011" & rmwIndY & aluInT & aluRra, -- 73 iRRA (zp),y
+ "0000" & "000000" & readZpX & aluInXXX & aluXXX, -- 74 iNOP zp,x
+ "1000" & "110011" & readZpX & aluInT & aluAdc, -- 75 ADC zp,x
+ "0000" & "100011" & rmwZpX & aluInT & aluRor, -- 76 ROR zp,x
+ "1000" & "110011" & rmwZpX & aluInT & aluRra, -- 77 iRRA zp,x
+ "0000" & "000100" & implied & aluInSet & aluXXX, -- 78 SEI
+ "1000" & "110011" & readAbsY & aluInT & aluAdc, -- 79 ADC abs,y
+ "0000" & "000000" & implied & aluInXXX & aluXXX, -- 7A iNOP implied
+ "1000" & "110011" & rmwAbsY & aluInT & aluRra, -- 7B iRRA abs,y
+ "0000" & "000000" & readAbsX & aluInXXX & aluXXX, -- 7C iNOP abs,x
+ "1000" & "110011" & readAbsX & aluInT & aluAdc, -- 7D ADC abs,x
+ "0000" & "100011" & rmwAbsX & aluInT & aluRor, -- 7E ROR abs,x
+ "1000" & "110011" & rmwAbsX & aluInT & aluRra, -- 7F iRRA abs,x
+ -- AXYS NVDIZC addressing aluInput aluMode
+ "0000" & "000000" & immediate & aluInXXX & aluXXX, -- 80 iNOP imm
+ "0000" & "000000" & writeIndX & aluInA & aluInp, -- 81 STA (zp,x)
+ "0000" & "000000" & immediate & aluInXXX & aluXXX, -- 82 iNOP imm
+ "0000" & "000000" & writeIndX & aluInAX & aluInp, -- 83 iSAX (zp,x)
+ "0000" & "000000" & writeZp & aluInY & aluInp, -- 84 STY zp
+ "0000" & "000000" & writeZp & aluInA & aluInp, -- 85 STA zp
+ "0000" & "000000" & writeZp & aluInX & aluInp, -- 86 STX zp
+ "0000" & "000000" & writeZp & aluInAX & aluInp, -- 87 iSAX zp
+ "0010" & "100010" & implied & aluInY & aluDec, -- 88 DEY
+ "0000" & "000000" & immediate & aluInXXX & aluXXX, -- 84 iNOP imm
+ "1000" & "100010" & implied & aluInX & aluInp, -- 8A TXA
+ "1000" & "100010" & immediate & aluInEXT & aluInp, -- 8B iANE imm
+ "0000" & "000000" & writeAbs & aluInY & aluInp, -- 8C STY abs
+ "0000" & "000000" & writeAbs & aluInA & aluInp, -- 8D STA abs
+ "0000" & "000000" & writeAbs & aluInX & aluInp, -- 8E STX abs
+ "0000" & "000000" & writeAbs & aluInAX & aluInp, -- 8F iSAX abs
+ "0000" & "000000" & relative & aluInXXX & aluXXX, -- 90 BCC
+ "0000" & "000000" & writeIndY & aluInA & aluInp, -- 91 STA (zp),y
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 92 *** JAM ***
+ "0000" & "000000" & writeIndY & aluInAXH & aluInp, -- 93 iAHX (zp),y
+ "0000" & "000000" & writeZpX & aluInY & aluInp, -- 94 STY zp,x
+ "0000" & "000000" & writeZpX & aluInA & aluInp, -- 95 STA zp,x
+ "0000" & "000000" & writeZpY & aluInX & aluInp, -- 96 STX zp,y
+ "0000" & "000000" & writeZpY & aluInAX & aluInp, -- 97 iSAX zp,y
+ "1000" & "100010" & implied & aluInY & aluInp, -- 98 TYA
+ "0000" & "000000" & writeAbsY & aluInA & aluInp, -- 99 STA abs,y
+ "0001" & "000000" & implied & aluInX & aluInp, -- 9A TXS
+ "0001" & "000000" & writeAbsY & aluInAXH & aluInp, -- 9B iSHS abs,y
+ "0000" & "000000" & writeAbsX & aluInYH & aluInp, -- 9C iSHY abs,x
+ "0000" & "000000" & writeAbsX & aluInA & aluInp, -- 9D STA abs,x
+ "0000" & "000000" & writeAbsY & aluInXH & aluInp, -- 9E iSHX abs,y
+ "0000" & "000000" & writeAbsY & aluInAXH & aluInp, -- 9F iAHX abs,y
+ -- AXYS NVDIZC addressing aluInput aluMode
+ "0010" & "100010" & immediate & aluInT & aluInp, -- A0 LDY imm
+ "1000" & "100010" & readIndX & aluInT & aluInp, -- A1 LDA (zp,x)
+ "0100" & "100010" & immediate & aluInT & aluInp, -- A2 LDX imm
+ "1100" & "100010" & readIndX & aluInT & aluInp, -- A3 LAX (zp,x)
+ "0010" & "100010" & readZp & aluInT & aluInp, -- A4 LDY zp
+ "1000" & "100010" & readZp & aluInT & aluInp, -- A5 LDA zp
+ "0100" & "100010" & readZp & aluInT & aluInp, -- A6 LDX zp
+ "1100" & "100010" & readZp & aluInT & aluInp, -- A7 iLAX zp
+ "0010" & "100010" & implied & aluInA & aluInp, -- A8 TAY
+ "1000" & "100010" & immediate & aluInT & aluInp, -- A9 LDA imm
+ "0100" & "100010" & implied & aluInA & aluInp, -- AA TAX
+ "1100" & "100010" & immediate & aluInET & aluInp, -- AB iLXA imm
+ "0010" & "100010" & readAbs & aluInT & aluInp, -- AC LDY abs
+ "1000" & "100010" & readAbs & aluInT & aluInp, -- AD LDA abs
+ "0100" & "100010" & readAbs & aluInT & aluInp, -- AE LDX abs
+ "1100" & "100010" & readAbs & aluInT & aluInp, -- AF iLAX abs
+ "0000" & "000000" & relative & aluInXXX & aluXXX, -- B0 BCS
+ "1000" & "100010" & readIndY & aluInT & aluInp, -- B1 LDA (zp),y
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- B2 *** JAM ***
+ "1100" & "100010" & readIndY & aluInT & aluInp, -- B3 iLAX (zp),y
+ "0010" & "100010" & readZpX & aluInT & aluInp, -- B4 LDY zp,x
+ "1000" & "100010" & readZpX & aluInT & aluInp, -- B5 LDA zp,x
+ "0100" & "100010" & readZpY & aluInT & aluInp, -- B6 LDX zp,y
+ "1100" & "100010" & readZpY & aluInT & aluInp, -- B7 iLAX zp,y
+ "0000" & "010000" & implied & aluInClr & aluFlg, -- B8 CLV
+ "1000" & "100010" & readAbsY & aluInT & aluInp, -- B9 LDA abs,y
+ "0100" & "100010" & implied & aluInS & aluInp, -- BA TSX
+ "1101" & "100010" & readAbsY & aluInST & aluInp, -- BB iLAS abs,y
+ "0010" & "100010" & readAbsX & aluInT & aluInp, -- BC LDY abs,x
+ "1000" & "100010" & readAbsX & aluInT & aluInp, -- BD LDA abs,x
+ "0100" & "100010" & readAbsY & aluInT & aluInp, -- BE LDX abs,y
+ "1100" & "100010" & readAbsY & aluInT & aluInp, -- BF iLAX abs,y
+ -- AXYS NVDIZC addressing aluInput aluMode
+ "0000" & "100011" & immediate & aluInT & aluCpy, -- C0 CPY imm
+ "0000" & "100011" & readIndX & aluInT & aluCmp, -- C1 CMP (zp,x)
+ "0000" & "000000" & immediate & aluInXXX & aluXXX, -- C2 iNOP imm
+ "0000" & "100011" & rmwIndX & aluInT & aluDcp, -- C3 iDCP (zp,x)
+ "0000" & "100011" & readZp & aluInT & aluCpy, -- C4 CPY zp
+ "0000" & "100011" & readZp & aluInT & aluCmp, -- C5 CMP zp
+ "0000" & "100010" & rmwZp & aluInT & aluDec, -- C6 DEC zp
+ "0000" & "100011" & rmwZp & aluInT & aluDcp, -- C7 iDCP zp
+ "0010" & "100010" & implied & aluInY & aluInc, -- C8 INY
+ "0000" & "100011" & immediate & aluInT & aluCmp, -- C9 CMP imm
+ "0100" & "100010" & implied & aluInX & aluDec, -- CA DEX
+ "0100" & "100011" & immediate & aluInT & aluSbx, -- CB SBX imm
+ "0000" & "100011" & readAbs & aluInT & aluCpy, -- CC CPY abs
+ "0000" & "100011" & readAbs & aluInT & aluCmp, -- CD CMP abs
+ "0000" & "100010" & rmwAbs & aluInT & aluDec, -- CE DEC abs
+ "0000" & "100011" & rmwAbs & aluInT & aluDcp, -- CF iDCP abs
+ "0000" & "000000" & relative & aluInXXX & aluXXX, -- D0 BNE
+ "0000" & "100011" & readIndY & aluInT & aluCmp, -- D1 CMP (zp),y
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- D2 *** JAM ***
+ "0000" & "100011" & rmwIndY & aluInT & aluDcp, -- D3 iDCP (zp),y
+ "0000" & "000000" & readZpX & aluInXXX & aluXXX, -- D4 iNOP zp,x
+ "0000" & "100011" & readZpX & aluInT & aluCmp, -- D5 CMP zp,x
+ "0000" & "100010" & rmwZpX & aluInT & aluDec, -- D6 DEC zp,x
+ "0000" & "100011" & rmwZpX & aluInT & aluDcp, -- D7 iDCP zp,x
+ "0000" & "001000" & implied & aluInClr & aluXXX, -- D8 CLD
+ "0000" & "100011" & readAbsY & aluInT & aluCmp, -- D9 CMP abs,y
+ "0000" & "000000" & implied & aluInXXX & aluXXX, -- DA iNOP implied
+ "0000" & "100011" & rmwAbsY & aluInT & aluDcp, -- DB iDCP abs,y
+ "0000" & "000000" & readAbsX & aluInXXX & aluXXX, -- DC iNOP abs,x
+ "0000" & "100011" & readAbsX & aluInT & aluCmp, -- DD CMP abs,x
+ "0000" & "100010" & rmwAbsX & aluInT & aluDec, -- DE DEC abs,x
+ "0000" & "100011" & rmwAbsX & aluInT & aluDcp, -- DF iDCP abs,x
+ -- AXYS NVDIZC addressing aluInput aluMode
+ "0000" & "100011" & immediate & aluInT & aluCpx, -- E0 CPX imm
+ "1000" & "110011" & readIndX & aluInT & aluSbc, -- E1 SBC (zp,x)
+ "0000" & "000000" & immediate & aluInXXX & aluXXX, -- E2 iNOP imm
+ "1000" & "110011" & rmwIndX & aluInT & aluIsc, -- E3 iISC (zp,x)
+ "0000" & "100011" & readZp & aluInT & aluCpx, -- E4 CPX zp
+ "1000" & "110011" & readZp & aluInT & aluSbc, -- E5 SBC zp
+ "0000" & "100010" & rmwZp & aluInT & aluInc, -- E6 INC zp
+ "1000" & "110011" & rmwZp & aluInT & aluIsc, -- E7 iISC zp
+ "0100" & "100010" & implied & aluInX & aluInc, -- E8 INX
+ "1000" & "110011" & immediate & aluInT & aluSbc, -- E9 SBC imm
+ "0000" & "000000" & implied & aluInXXX & aluXXX, -- EA NOP
+ "1000" & "110011" & immediate & aluInT & aluSbc, -- EB SBC imm (illegal opc)
+ "0000" & "100011" & readAbs & aluInT & aluCpx, -- EC CPX abs
+ "1000" & "110011" & readAbs & aluInT & aluSbc, -- ED SBC abs
+ "0000" & "100010" & rmwAbs & aluInT & aluInc, -- EE INC abs
+ "1000" & "110011" & rmwAbs & aluInT & aluIsc, -- EF iISC abs
+ "0000" & "000000" & relative & aluInXXX & aluXXX, -- F0 BEQ
+ "1000" & "110011" & readIndY & aluInT & aluSbc, -- F1 SBC (zp),y
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- F2 *** JAM ***
+ "1000" & "110011" & rmwIndY & aluInT & aluIsc, -- F3 iISC (zp),y
+ "0000" & "000000" & readZpX & aluInXXX & aluXXX, -- F4 iNOP zp,x
+ "1000" & "110011" & readZpX & aluInT & aluSbc, -- F5 SBC zp,x
+ "0000" & "100010" & rmwZpX & aluInT & aluInc, -- F6 INC zp,x
+ "1000" & "110011" & rmwZpX & aluInT & aluIsc, -- F7 iISC zp,x
+ "0000" & "001000" & implied & aluInSet & aluXXX, -- F8 SED
+ "1000" & "110011" & readAbsY & aluInT & aluSbc, -- F9 SBC abs,y
+ "0000" & "000000" & implied & aluInXXX & aluXXX, -- FA iNOP implied
+ "1000" & "110011" & rmwAbsY & aluInT & aluIsc, -- FB iISC abs,y
+ "0000" & "000000" & readAbsX & aluInXXX & aluXXX, -- FC iNOP abs,x
+ "1000" & "110011" & readAbsX & aluInT & aluSbc, -- FD SBC abs,x
+ "0000" & "100010" & rmwAbsX & aluInT & aluInc, -- FE INC abs,x
+ "1000" & "110011" & rmwAbsX & aluInT & aluIsc -- FF iISC abs,x
+ );
+ signal opcInfo : decodedBitsDef;
+ signal nextOpcInfo : decodedBitsDef; -- Next opcode (decoded)
+ signal nextOpcInfoReg : decodedBitsDef; -- Next opcode (decoded) pipelined
+ signal theOpcode : unsigned(7 downto 0);
+ signal nextOpcode : unsigned(7 downto 0);
+
+-- Program counter
+ signal PC : unsigned(15 downto 0); -- Program counter
+
+-- Address generation
+ type nextAddrDef is (
+ nextAddrHold,
+ nextAddrIncr,
+ nextAddrIncrL, -- Increment low bits only (zeropage accesses)
+ nextAddrIncrH, -- Increment high bits only (page-boundary)
+ nextAddrDecrH, -- Decrement high bits (branch backwards)
+ nextAddrPc,
+ nextAddrIrq,
+ nextAddrReset,
+ nextAddrAbs,
+ nextAddrAbsIndexed,
+ nextAddrZeroPage,
+ nextAddrZPIndexed,
+ nextAddrStack,
+ nextAddrRelative
+ );
+ signal nextAddr : nextAddrDef;
+ signal myAddr : unsigned(15 downto 0);
+ signal myAddrIncr : unsigned(15 downto 0);
+ signal myAddrIncrH : unsigned(7 downto 0);
+ signal myAddrDecrH : unsigned(7 downto 0);
+ signal theWe : std_logic;
+
+ signal irqActive : std_logic;
+
+-- Output register
+ signal doReg : unsigned(7 downto 0);
+
+-- Buffer register
+ signal T : unsigned(7 downto 0);
+
+-- General registers
+ signal A: unsigned(7 downto 0); -- Accumulator
+ signal X: unsigned(7 downto 0); -- Index X
+ signal Y: unsigned(7 downto 0); -- Index Y
+ signal S: unsigned(7 downto 0); -- stack pointer
+
+-- Status register
+ signal C: std_logic; -- Carry
+ signal Z: std_logic; -- Zero flag
+ signal I: std_logic; -- Interrupt flag
+ signal D: std_logic; -- Decimal mode
+ signal V: std_logic; -- Overflow
+ signal N: std_logic; -- Negative
+
+-- ALU
+ -- ALU input
+ signal aluInput : unsigned(7 downto 0);
+ signal aluCmpInput : unsigned(7 downto 0);
+ -- ALU output
+ signal aluRegisterOut : unsigned(7 downto 0);
+ signal aluRmwOut : unsigned(7 downto 0);
+ signal aluC : std_logic;
+ signal aluZ : std_logic;
+ signal aluV : std_logic;
+ signal aluN : std_logic;
+ -- Pipeline registers
+ signal aluInputReg : unsigned(7 downto 0);
+ signal aluCmpInputReg : unsigned(7 downto 0);
+ signal aluRmwReg : unsigned(7 downto 0);
+ signal aluNineReg : unsigned(7 downto 0);
+ signal aluCReg : std_logic;
+ signal aluZReg : std_logic;
+ signal aluVReg : std_logic;
+ signal aluNReg : std_logic;
+
+-- Indexing
+ signal indexOut : unsigned(8 downto 0);
+
+begin
+processAluInput: process(clk, opcInfo, A, X, Y, T, S)
+ variable temp : unsigned(7 downto 0);
+ begin
+ temp := (others => '1');
+ if opcInfo(opcInA) = '1' then
+ temp := temp and A;
+ end if;
+ if opcInfo(opcInE) = '1' then
+ temp := temp and (A or X"EE");
+ end if;
+ if opcInfo(opcInX) = '1' then
+ temp := temp and X;
+ end if;
+ if opcInfo(opcInY) = '1' then
+ temp := temp and Y;
+ end if;
+ if opcInfo(opcInS) = '1' then
+ temp := temp and S;
+ end if;
+ if opcInfo(opcInT) = '1' then
+ temp := temp and T;
+ end if;
+ if opcInfo(opcInClear) = '1' then
+ temp := (others => '0');
+ end if;
+ if rising_edge(clk) then
+ aluInputReg <= temp;
+ end if;
+
+ aluInput <= temp;
+ if pipelineAluMux then
+ aluInput <= aluInputReg;
+ end if;
+ end process;
+
+processCmpInput: process(clk, opcInfo, A, X, Y)
+ variable temp : unsigned(7 downto 0);
+ begin
+ temp := (others => '1');
+ if opcInfo(opcInCmp) = '1' then
+ temp := temp and A;
+ end if;
+ if opcInfo(opcInCpx) = '1' then
+ temp := temp and X;
+ end if;
+ if opcInfo(opcInCpy) = '1' then
+ temp := temp and Y;
+ end if;
+ if rising_edge(clk) then
+ aluCmpInputReg <= temp;
+ end if;
+
+ aluCmpInput <= temp;
+ if pipelineAluMux then
+ aluCmpInput <= aluCmpInputReg;
+ end if;
+ end process;
+
+ -- ALU consists of two parts
+ -- Read-Modify-Write or index instructions: INC/DEC/ASL/LSR/ROR/ROL
+ -- Accumulator instructions: ADC, SBC, EOR, AND, EOR, ORA
+ -- Some instructions are both RMW and accumulator so for most
+ -- instructions the rmw results are routed through accu alu too.
+processAlu: process(clk, opcInfo, aluInput, aluCmpInput, A, T, irqActive, N, V, D, I, Z, C)
+ variable lowBits: unsigned(5 downto 0);
+ variable nineBits: unsigned(8 downto 0);
+ variable rmwBits: unsigned(8 downto 0);
+
+ variable varC : std_logic;
+ variable varZ : std_logic;
+ variable varV : std_logic;
+ variable varN : std_logic;
+ begin
+ lowBits := (others => '-');
+ nineBits := (others => '-');
+ rmwBits := (others => '-');
+ varV := aluInput(6); -- Default for BIT / PLP / RTI
+
+ -- Shift unit
+ case opcInfo(aluMode1From to aluMode1To) is
+ when aluModeInp =>
+ rmwBits := C & aluInput;
+ when aluModeP =>
+ rmwBits := C & N & V & '1' & (not irqActive) & D & I & Z & C;
+ when aluModeInc =>
+ rmwBits := C & (aluInput + 1);
+ when aluModeDec =>
+ rmwBits := C & (aluInput - 1);
+ when aluModeAsl =>
+ rmwBits := aluInput & "0";
+ when aluModeFlg =>
+ rmwBits := aluInput(0) & aluInput;
+ when aluModeLsr =>
+ rmwBits := aluInput(0) & "0" & aluInput(7 downto 1);
+ when aluModeRol =>
+ rmwBits := aluInput & C;
+ when aluModeRoR =>
+ rmwBits := aluInput(0) & C & aluInput(7 downto 1);
+ when aluModeAnc =>
+ rmwBits := (aluInput(7) and A(7)) & aluInput;
+ when others =>
+ rmwBits := C & aluInput;
+ end case;
+
+ -- ALU
+ case opcInfo(aluMode2From to aluMode2To) is
+ when aluModeAdc =>
+ lowBits := ("0" & A(3 downto 0) & rmwBits(8)) + ("0" & rmwBits(3 downto 0) & "1");
+ ninebits := ("0" & A) + ("0" & rmwBits(7 downto 0)) + (B"00000000" & rmwBits(8));
+ when aluModeSbc =>
+ lowBits := ("0" & A(3 downto 0) & rmwBits(8)) + ("0" & (not rmwBits(3 downto 0)) & "1");
+ ninebits := ("0" & A) + ("0" & (not rmwBits(7 downto 0))) + (B"00000000" & rmwBits(8));
+ when aluModeCmp =>
+ ninebits := ("0" & aluCmpInput) + ("0" & (not rmwBits(7 downto 0))) + "000000001";
+ when aluModeAnd =>
+ ninebits := rmwBits(8) & (A and rmwBits(7 downto 0));
+ when aluModeEor =>
+ ninebits := rmwBits(8) & (A xor rmwBits(7 downto 0));
+ when aluModeOra =>
+ ninebits := rmwBits(8) & (A or rmwBits(7 downto 0));
+ when others =>
+ ninebits := rmwBits;
+ end case;
+
+ if (opcInfo(aluMode1From to aluMode1To) = aluModeFlg) then
+ varZ := rmwBits(1);
+ elsif ninebits(7 downto 0) = X"00" then
+ varZ := '1';
+ else
+ varZ := '0';
+ end if;
+
+ case opcInfo(aluMode2From to aluMode2To) is
+ when aluModeAdc =>
+ -- decimal mode low bits correction, is done after setting Z flag.
+ if D = '1' then
+ if lowBits(5 downto 1) > 9 then
+ ninebits(3 downto 0) := ninebits(3 downto 0) + 6;
+ if lowBits(5) = '0' then
+ ninebits(8 downto 4) := ninebits(8 downto 4) + 1;
+ end if;
+ end if;
+ end if;
+ when others =>
+ null;
+ end case;
+
+ if (opcInfo(aluMode1From to aluMode1To) = aluModeBit)
+ or (opcInfo(aluMode1From to aluMode1To) = aluModeFlg) then
+ varN := rmwBits(7);
+ else
+ varN := nineBits(7);
+ end if;
+ varC := ninebits(8);
+ if opcInfo(aluMode2From to aluMode2To) = aluModeArr then
+ varC := aluInput(7);
+ varV := aluInput(7) xor aluInput(6);
+ end if;
+
+ case opcInfo(aluMode2From to aluMode2To) is
+ when aluModeAdc =>
+ -- decimal mode high bits correction, is done after setting Z and N flags
+ varV := (A(7) xor ninebits(7)) and (rmwBits(7) xor ninebits(7));
+ if D = '1' then
+ if ninebits(8 downto 4) > 9 then
+ ninebits(8 downto 4) := ninebits(8 downto 4) + 6;
+ varC := '1';
+ end if;
+ end if;
+ when aluModeSbc =>
+ varV := (A(7) xor ninebits(7)) and ((not rmwBits(7)) xor ninebits(7));
+ if D = '1' then
+ -- Check for borrow (lower 4 bits)
+ if lowBits(5) = '0' then
+ ninebits(3 downto 0) := ninebits(3 downto 0) - 6;
+ end if;
+ -- Check for borrow (upper 4 bits)
+ if ninebits(8) = '0' then
+ ninebits(8 downto 4) := ninebits(8 downto 4) - 6;
+ end if;
+ end if;
+ when aluModeArr =>
+ if D = '1' then
+ if (("0" & aluInput(3 downto 0)) + ("0000" & aluInput(0))) > 5 then
+ ninebits(3 downto 0) := ninebits(3 downto 0) + 6;
+ end if;
+ if (("0" & aluInput(7 downto 4)) + ("0000" & aluInput(4))) > 5 then
+ ninebits(8 downto 4) := ninebits(8 downto 4) + 6;
+ varC := '1';
+ else
+ varC := '0';
+ end if;
+ end if;
+ when others =>
+ null;
+ end case;
+
+ if rising_edge(clk) then
+ aluRmwReg <= rmwBits(7 downto 0);
+ aluNineReg <= ninebits(7 downto 0);
+ aluCReg <= varC;
+ aluZReg <= varZ;
+ aluVReg <= varV;
+ aluNReg <= varN;
+ end if;
+
+ aluRmwOut <= rmwBits(7 downto 0);
+ aluRegisterOut <= ninebits(7 downto 0);
+ aluC <= varC;
+ aluZ <= varZ;
+ aluV <= varV;
+ aluN <= varN;
+ if pipelineAluOut then
+ aluRmwOut <= aluRmwReg;
+ aluRegisterOut <= aluNineReg;
+ aluC <= aluCReg;
+ aluZ <= aluZReg;
+ aluV <= aluVReg;
+ aluN <= aluNReg;
+ end if;
+ end process;
+
+calcInterrupt: process(clk)
+ begin
+ if rising_edge(clk) then
+ if enable = '1' then
+ if theCpuCycle = cycleStack4
+ or reset = '1' then
+ nmiReg <= '1';
+ end if;
+
+ if nextCpuCycle /= cycleBranchTaken
+ and nextCpuCycle /= opcodeFetch then
+ irqReg <= irq_n;
+ nmiEdge <= nmi_n;
+ if (nmiEdge = '1') and (nmi_n = '0') then
+ nmiReg <= '0';
+ end if;
+ end if;
+ -- The 'or opcInfo(opcSetI)' prevents NMI immediately after BRK or IRQ.
+ -- Presumably this is done in the real 6502/6510 to prevent a double IRQ.
+ processIrq <= not ((nmiReg and (irqReg or I)) or opcInfo(opcIRQ));
+ end if;
+ end if;
+ end process;
+
+calcNextOpcode: process(clk, di, reset, processIrq)
+ variable myNextOpcode : unsigned(7 downto 0);
+ begin
+ -- Next opcode is read from input unless a reset or IRQ is pending.
+ myNextOpcode := di;
+ if reset = '1' then
+ myNextOpcode := X"4C";
+ elsif processIrq = '1' then
+ myNextOpcode := X"00";
+ end if;
+
+ nextOpcode <= myNextOpcode;
+ end process;
+
+ nextOpcInfo <= opcodeInfoTable(to_integer(nextOpcode));
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ nextOpcInfoReg <= nextOpcInfo;
+ end if;
+ end process;
+
+ -- Read bits and flags from opcodeInfoTable and store in opcInfo.
+ -- This info is used to control the execution of the opcode.
+calcOpcInfo: process(clk)
+ begin
+ if rising_edge(clk) then
+ if enable = '1' then
+ if (reset = '1') or (theCpuCycle = opcodeFetch) then
+ opcInfo <= nextOpcInfo;
+ if pipelineOpcode then
+ opcInfo <= nextOpcInfoReg;
+ end if;
+ end if;
+ end if;
+ end if;
+ end process;
+
+calcTheOpcode: process(clk)
+ begin
+ if rising_edge(clk) then
+ if enable = '1' then
+ if theCpuCycle = opcodeFetch then
+ irqActive <= '0';
+ if processIrq = '1' then
+ irqActive <= '1';
+ end if;
+ -- Fetch opcode
+ theOpcode <= nextOpcode;
+ end if;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- State machine
+-- -----------------------------------------------------------------------
+ process(enable, theCpuCycle, opcInfo)
+ begin
+ updateRegisters <= false;
+ if enable = '1' then
+ if opcInfo(opcRti) = '1' then
+ if theCpuCycle = cycleRead then
+ updateRegisters <= true;
+ end if;
+ elsif theCpuCycle = opcodeFetch then
+ updateRegisters <= true;
+ end if;
+ end if;
+ end process;
+
+ debugOpcode <= theOpcode;
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if enable = '1' then
+ theCpuCycle <= nextCpuCycle;
+ end if;
+ if reset = '1' then
+ theCpuCycle <= cycle2;
+ end if;
+ end if;
+ end process;
+
+ -- Determine the next cpu cycle. After the last cycle we always
+ -- go to opcodeFetch to get the next opcode.
+calcNextCpuCycle: process(theCpuCycle, opcInfo, theOpcode, indexOut, T, N, V, C, Z)
+ begin
+ nextCpuCycle <= opcodeFetch;
+
+ case theCpuCycle is
+ when opcodeFetch =>
+ nextCpuCycle <= cycle2;
+ when cycle2 =>
+ if opcInfo(opcBranch) = '1' then
+ if (N = theOpcode(5) and theOpcode(7 downto 6) = "00")
+ or (V = theOpcode(5) and theOpcode(7 downto 6) = "01")
+ or (C = theOpcode(5) and theOpcode(7 downto 6) = "10")
+ or (Z = theOpcode(5) and theOpcode(7 downto 6) = "11") then
+ -- Branch condition is true
+ nextCpuCycle <= cycleBranchTaken;
+ end if;
+ elsif (opcInfo(opcStackUp) = '1') then
+ nextCpuCycle <= cycleStack1;
+ elsif opcInfo(opcStackAddr) = '1'
+ and opcInfo(opcStackData) = '1' then
+ nextCpuCycle <= cycleStack2;
+ elsif opcInfo(opcStackAddr) = '1' then
+ nextCpuCycle <= cycleStack1;
+ elsif opcInfo(opcStackData) = '1' then
+ nextCpuCycle <= cycleWrite;
+ elsif opcInfo(opcAbsolute) = '1' then
+ nextCpuCycle <= cycle3;
+ elsif opcInfo(opcIndirect) = '1' then
+ if opcInfo(indexX) = '1' then
+ nextCpuCycle <= cyclePreIndirect;
+ else
+ nextCpuCycle <= cycleIndirect;
+ end if;
+ elsif opcInfo(opcZeroPage) = '1' then
+ if opcInfo(opcWrite) = '1' then
+ if (opcInfo(indexX) = '1')
+ or (opcInfo(indexY) = '1') then
+ nextCpuCycle <= cyclePreWrite;
+ else
+ nextCpuCycle <= cycleWrite;
+ end if;
+ else
+ if (opcInfo(indexX) = '1')
+ or (opcInfo(indexY) = '1') then
+ nextCpuCycle <= cyclePreRead;
+ else
+ nextCpuCycle <= cycleRead2;
+ end if;
+ end if;
+ elsif opcInfo(opcJump) = '1' then
+ nextCpuCycle <= cycleJump;
+ end if;
+ when cycle3 =>
+ nextCpuCycle <= cycleRead;
+ if opcInfo(opcWrite) = '1' then
+ if (opcInfo(indexX) = '1')
+ or (opcInfo(indexY) = '1') then
+ nextCpuCycle <= cyclePreWrite;
+ else
+ nextCpuCycle <= cycleWrite;
+ end if;
+ end if;
+ if (opcInfo(opcIndirect) = '1')
+ and (opcInfo(indexX) = '1') then
+ if opcInfo(opcWrite) = '1' then
+ nextCpuCycle <= cycleWrite;
+ else
+ nextCpuCycle <= cycleRead2;
+ end if;
+ end if;
+ when cyclePreIndirect =>
+ nextCpuCycle <= cycleIndirect;
+ when cycleIndirect =>
+ nextCpuCycle <= cycle3;
+ when cycleBranchTaken =>
+ if indexOut(8) /= T(7) then
+ -- Page boundary crossing during branch.
+ nextCpuCycle <= cycleBranchPage;
+ end if;
+ when cyclePreRead =>
+ if opcInfo(opcZeroPage) = '1' then
+ nextCpuCycle <= cycleRead2;
+ end if;
+ when cycleRead =>
+ if opcInfo(opcJump) = '1' then
+ nextCpuCycle <= cycleJump;
+ elsif indexOut(8) = '1' then
+ -- Page boundary crossing while indexed addressing.
+ nextCpuCycle <= cycleRead2;
+ elsif opcInfo(opcRmw) = '1' then
+ nextCpuCycle <= cycleRmw;
+ if opcInfo(indexX) = '1'
+ or opcInfo(indexY) = '1' then
+ -- 6510 needs extra cycle for indexed addressing
+ -- combined with RMW indexing
+ nextCpuCycle <= cycleRead2;
+ end if;
+ end if;
+ when cycleRead2 =>
+ if opcInfo(opcRmw) = '1' then
+ nextCpuCycle <= cycleRmw;
+ end if;
+ when cycleRmw =>
+ nextCpuCycle <= cycleWrite;
+ when cyclePreWrite =>
+ nextCpuCycle <= cycleWrite;
+ when cycleStack1 =>
+ nextCpuCycle <= cycleRead;
+ if opcInfo(opcStackAddr) = '1' then
+ nextCpuCycle <= cycleStack2;
+ end if;
+ when cycleStack2 =>
+ nextCpuCycle <= cycleStack3;
+ if opcInfo(opcRti) = '1' then
+ nextCpuCycle <= cycleRead;
+ end if;
+ if opcInfo(opcStackData) = '0'
+ and opcInfo(opcStackUp) = '1' then
+ nextCpuCycle <= cycleJump;
+ end if;
+ when cycleStack3 =>
+ nextCpuCycle <= cycleRead;
+ if opcInfo(opcStackData) = '0'
+ or opcInfo(opcStackUp) = '1' then
+ nextCpuCycle <= cycleJump;
+ elsif opcInfo(opcStackAddr) = '1' then
+ nextCpuCycle <= cycleStack4;
+ end if;
+ when cycleStack4 =>
+ nextCpuCycle <= cycleRead;
+ when cycleJump =>
+ if opcInfo(opcIncrAfter) = '1' then
+ -- Insert extra cycle
+ nextCpuCycle <= cycleEnd;
+ end if;
+ when others =>
+ null;
+ end case;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- T register
+-- -----------------------------------------------------------------------
+calcT: process(clk)
+ begin
+ if rising_edge(clk) then
+ if enable = '1' then
+ case theCpuCycle is
+ when cycle2 =>
+ T <= di;
+ when cycleStack1 | cycleStack2 =>
+ if opcInfo(opcStackUp) = '1' then
+ -- Read from stack
+ T <= di;
+ end if;
+ when cycleIndirect | cycleRead | cycleRead2 =>
+ T <= di;
+ when others =>
+ null;
+ end case;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- A register
+-- -----------------------------------------------------------------------
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if updateRegisters then
+ if opcInfo(opcUpdateA) = '1' then
+ A <= aluRegisterOut;
+ end if;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- X register
+-- -----------------------------------------------------------------------
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if updateRegisters then
+ if opcInfo(opcUpdateX) = '1' then
+ X <= aluRegisterOut;
+ end if;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- Y register
+-- -----------------------------------------------------------------------
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if updateRegisters then
+ if opcInfo(opcUpdateY) = '1' then
+ Y <= aluRegisterOut;
+ end if;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- C flag
+-- -----------------------------------------------------------------------
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if updateRegisters then
+ if opcInfo(opcUpdateC) = '1' then
+ C <= aluC;
+ end if;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- Z flag
+-- -----------------------------------------------------------------------
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if updateRegisters then
+ if opcInfo(opcUpdateZ) = '1' then
+ Z <= aluZ;
+ end if;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- I flag
+-- -----------------------------------------------------------------------
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if updateRegisters then
+ if opcInfo(opcUpdateI) = '1' then
+ I <= aluInput(2);
+ end if;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- D flag
+-- -----------------------------------------------------------------------
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if updateRegisters then
+ if opcInfo(opcUpdateD) = '1' then
+ D <= aluInput(3);
+ end if;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- V flag
+-- -----------------------------------------------------------------------
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if updateRegisters then
+ if opcInfo(opcUpdateV) = '1' then
+ V <= aluV;
+ end if;
+ end if;
+ if enable = '1' then
+ if soReg = '1' and so_n = '0' then
+ V <= '1';
+ end if;
+ soReg <= so_n;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- N flag
+-- -----------------------------------------------------------------------
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if updateRegisters then
+ if opcInfo(opcUpdateN) = '1' then
+ N <= aluN;
+ end if;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- Stack pointer
+-- -----------------------------------------------------------------------
+ process(clk)
+ variable sIncDec : unsigned(7 downto 0);
+ variable updateFlag : boolean;
+ begin
+ if rising_edge(clk) then
+
+ if opcInfo(opcStackUp) = '1' then
+ sIncDec := S + 1;
+ else
+ sIncDec := S - 1;
+ end if;
+
+ if enable = '1' then
+ updateFlag := false;
+ case nextCpuCycle is
+ when cycleStack1 =>
+ if (opcInfo(opcStackUp) = '1')
+ or (opcInfo(opcStackData) = '1') then
+ updateFlag := true;
+ end if;
+ when cycleStack2 =>
+ updateFlag := true;
+ when cycleStack3 =>
+ updateFlag := true;
+ when cycleStack4 =>
+ updateFlag := true;
+ when cycleRead =>
+ if opcInfo(opcRti) = '1' then
+ updateFlag := true;
+ end if;
+ when cycleWrite =>
+ if opcInfo(opcStackData) = '1' then
+ updateFlag := true;
+ end if;
+ when others =>
+ null;
+ end case;
+ if updateFlag then
+ S <= sIncDec;
+ end if;
+ end if;
+ if updateRegisters then
+ if opcInfo(opcUpdateS) = '1' then
+ S <= aluRegisterOut;
+ end if;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- Data out
+-- -----------------------------------------------------------------------
+--calcDo: process(cpuNo, theCpuCycle, aluOut, PC, T)
+calcDo: process(clk)
+ begin
+ if rising_edge(clk) then
+ if enable = '1' then
+ doReg <= aluRmwOut;
+ if opcInfo(opcInH) = '1' then
+ -- For illegal opcodes SHA, SHX, SHY, SHS
+ doReg <= aluRmwOut and myAddrIncrH;
+ end if;
+
+ case nextCpuCycle is
+ when cycleStack2 =>
+ if opcInfo(opcIRQ) = '1'
+ and irqActive = '0' then
+ doReg <= myAddrIncr(15 downto 8);
+ else
+ doReg <= PC(15 downto 8);
+ end if;
+ when cycleStack3 =>
+ doReg <= PC(7 downto 0);
+ when cycleRmw =>
+-- do <= T; -- Read-modify-write write old value first.
+ doReg <= di; -- Read-modify-write write old value first.
+ when others => null;
+ end case;
+ end if;
+ end if;
+ end process;
+ do <= doReg;
+
+
+
+-- -----------------------------------------------------------------------
+-- Write enable
+-- -----------------------------------------------------------------------
+calcWe: process(clk)
+ begin
+ if rising_edge(clk) then
+ if enable = '1' then
+ theWe <= '0';
+ case nextCpuCycle is
+ when cycleStack1 =>
+ if opcInfo(opcStackUp) = '0'
+ and ((opcInfo(opcStackAddr) = '0')
+ or (opcInfo(opcStackData) = '1')) then
+ theWe <= '1';
+ end if;
+ when cycleStack2 | cycleStack3 | cycleStack4 =>
+ if opcInfo(opcStackUp) = '0' then
+ theWe <= '1';
+ end if;
+ when cycleRmw =>
+ theWe <= '1';
+ when cycleWrite =>
+ theWe <= '1';
+ when others =>
+ null;
+ end case;
+ end if;
+ end if;
+ end process;
+ we <= theWe;
+
+-- -----------------------------------------------------------------------
+-- Program counter
+-- -----------------------------------------------------------------------
+calcPC: process(clk)
+ begin
+ if rising_edge(clk) then
+ if enable = '1' then
+ case theCpuCycle is
+ when opcodeFetch =>
+ PC <= myAddr;
+ when cycle2 =>
+ if irqActive = '0' then
+ if opcInfo(opcSecondByte) = '1' then
+ PC <= myAddrIncr;
+ else
+ PC <= myAddr;
+ end if;
+ end if;
+ when cycle3 =>
+ if opcInfo(opcAbsolute) = '1' then
+ PC <= myAddrIncr;
+ end if;
+ when others =>
+ null;
+ end case;
+ end if;
+ end if;
+ end process;
+ debugPc <= PC;
+
+-- -----------------------------------------------------------------------
+-- Address generation
+-- -----------------------------------------------------------------------
+calcNextAddr: process(theCpuCycle, opcInfo, indexOut, T, reset)
+ begin
+ nextAddr <= nextAddrIncr;
+ case theCpuCycle is
+ when cycle2 =>
+ if opcInfo(opcStackAddr) = '1'
+ or opcInfo(opcStackData) = '1' then
+ nextAddr <= nextAddrStack;
+ elsif opcInfo(opcAbsolute) = '1' then
+ nextAddr <= nextAddrIncr;
+ elsif opcInfo(opcZeroPage) = '1' then
+ nextAddr <= nextAddrZeroPage;
+ elsif opcInfo(opcIndirect) = '1' then
+ nextAddr <= nextAddrZeroPage;
+ elsif opcInfo(opcSecondByte) = '1' then
+ nextAddr <= nextAddrIncr;
+ else
+ nextAddr <= nextAddrHold;
+ end if;
+ when cycle3 =>
+ if (opcInfo(opcIndirect) = '1')
+ and (opcInfo(indexX) = '1') then
+ nextAddr <= nextAddrAbs;
+ else
+ nextAddr <= nextAddrAbsIndexed;
+ end if;
+ when cyclePreIndirect =>
+ nextAddr <= nextAddrZPIndexed;
+ when cycleIndirect =>
+ nextAddr <= nextAddrIncrL;
+ when cycleBranchTaken =>
+ nextAddr <= nextAddrRelative;
+ when cycleBranchPage =>
+ if T(7) = '0' then
+ nextAddr <= nextAddrIncrH;
+ else
+ nextAddr <= nextAddrDecrH;
+ end if;
+ when cyclePreRead =>
+ nextAddr <= nextAddrZPIndexed;
+ when cycleRead =>
+ nextAddr <= nextAddrPc;
+ if opcInfo(opcJump) = '1' then
+ -- Emulate 6510 bug, jmp(xxFF) fetches from same page.
+ -- Replace with nextAddrIncr if emulating 65C02 or later cpu.
+ nextAddr <= nextAddrIncrL;
+ elsif indexOut(8) = '1' then
+ nextAddr <= nextAddrIncrH;
+ elsif opcInfo(opcRmw) = '1' then
+ nextAddr <= nextAddrHold;
+ end if;
+ when cycleRead2 =>
+ nextAddr <= nextAddrPc;
+ if opcInfo(opcRmw) = '1' then
+ nextAddr <= nextAddrHold;
+ end if;
+ when cycleRmw =>
+ nextAddr <= nextAddrHold;
+ when cyclePreWrite =>
+ nextAddr <= nextAddrHold;
+ if opcInfo(opcZeroPage) = '1' then
+ nextAddr <= nextAddrZPIndexed;
+ elsif indexOut(8) = '1' then
+ nextAddr <= nextAddrIncrH;
+ end if;
+ when cycleWrite =>
+ nextAddr <= nextAddrPc;
+ when cycleStack1 =>
+ nextAddr <= nextAddrStack;
+ when cycleStack2 =>
+ nextAddr <= nextAddrStack;
+ when cycleStack3 =>
+ nextAddr <= nextAddrStack;
+ if opcInfo(opcStackData) = '0' then
+ nextAddr <= nextAddrPc;
+ end if;
+ when cycleStack4 =>
+ nextAddr <= nextAddrIrq;
+ when cycleJump =>
+ nextAddr <= nextAddrAbs;
+ when others =>
+ null;
+ end case;
+ if reset = '1' then
+ nextAddr <= nextAddrReset;
+ end if;
+ end process;
+
+indexAlu: process(opcInfo, myAddr, T, X, Y)
+ begin
+ if opcInfo(indexX) = '1' then
+ indexOut <= (B"0" & T) + (B"0" & X);
+ elsif opcInfo(indexY) = '1' then
+ indexOut <= (B"0" & T) + (B"0" & Y);
+ elsif opcInfo(opcBranch) = '1' then
+ indexOut <= (B"0" & T) + (B"0" & myAddr(7 downto 0));
+ else
+ indexOut <= B"0" & T;
+ end if;
+ end process;
+
+calcAddr: process(clk)
+ begin
+ if rising_edge(clk) then
+ if enable = '1' then
+ case nextAddr is
+ when nextAddrIncr => myAddr <= myAddrIncr;
+ when nextAddrIncrL => myAddr(7 downto 0) <= myAddrIncr(7 downto 0);
+ when nextAddrIncrH => myAddr(15 downto 8) <= myAddrIncrH;
+ when nextAddrDecrH => myAddr(15 downto 8) <= myAddrDecrH;
+ when nextAddrPc => myAddr <= PC;
+ when nextAddrIrq =>
+ myAddr <= X"FFFE";
+ if nmiReg = '0' then
+ myAddr <= X"FFFA";
+ end if;
+ when nextAddrReset => myAddr <= X"FFFC";
+ when nextAddrAbs => myAddr <= di & T;
+ when nextAddrAbsIndexed => myAddr <= di & indexOut(7 downto 0);
+ when nextAddrZeroPage => myAddr <= "00000000" & di;
+ when nextAddrZPIndexed => myAddr <= "00000000" & indexOut(7 downto 0);
+ when nextAddrStack => myAddr <= "00000001" & S;
+ when nextAddrRelative => myAddr(7 downto 0) <= indexOut(7 downto 0);
+ when others => null;
+ end case;
+ end if;
+ end if;
+ end process;
+
+ myAddrIncr <= myAddr + 1;
+ myAddrIncrH <= myAddr(15 downto 8) + 1;
+ myAddrDecrH <= myAddr(15 downto 8) - 1;
+
+ addr <= myAddr;
+
+ debugA <= A;
+ debugX <= X;
+ debugY <= Y;
+ debugS <= S;
+
+end architecture;
+
+
diff --git a/common/CPU/6800/cpu68.vhd b/common/CPU/6800/cpu68.vhd
new file mode 100644
index 00000000..03bdfc63
--- /dev/null
+++ b/common/CPU/6800/cpu68.vhd
@@ -0,0 +1,3962 @@
+--===========================================================================--
+--
+-- S Y N T H E Z I A B L E CPU68 C O R E
+--
+-- www.OpenCores.Org - December 2002
+-- This core adheres to the GNU public license
+--
+-- File name : cpu68.vhd
+--
+-- Purpose : Implements a 6800 compatible CPU core with some
+-- additional instructions found in the 6801
+--
+-- Dependencies : ieee.Std_Logic_1164
+-- ieee.std_logic_unsigned
+--
+-- Author : John E. Kent
+--
+--===========================================================================----
+--
+-- Revision History:
+--
+-- Date: Revision Author
+-- 22 Sep 2002 0.1 John Kent
+--
+-- 30 Oct 2002 0.2 John Kent
+-- made NMI edge triggered
+--
+-- 30 Oct 2002 0.3 John Kent
+-- more corrections to NMI
+-- added wai_wait_state to prevent stack overflow on wai.
+--
+-- 1 Nov 2002 0.4 John Kent
+-- removed WAI states and integrated WAI with the interrupt service routine
+-- replace Data out (do) and Data in (di) register with a single Memory Data (md) reg.
+-- Added Multiply instruction states.
+-- run ALU and CC out of CPU module for timing measurements.
+--
+-- 3 Nov 2002 0.5 John Kent
+-- Memory Data Register was not loaded on Store instructions
+-- SEV and CLV were not defined in the ALU
+-- Overflow Flag on NEG was incorrect
+--
+-- 16th Feb 2003 0.6 John Kent
+-- Rearranged the execution cycle for dual operand instructions
+-- so that occurs during the following fetch cycle.
+-- This allows the reduction of one clock cycle from dual operand
+-- instruction. Note that this also necessitated re-arranging the
+-- program counter so that it is no longer incremented in the ALU.
+-- The effective address has also been re-arranged to include a
+-- separate added. The STD (store accd) now sets the condition codes.
+--
+-- 28th Jun 2003 0.7 John Kent
+-- Added Hold and Halt signals. Hold is used to steal cycles from the
+-- CPU or add wait states. Halt puts the CPU in the inactive state
+-- and is only honoured in the fetch cycle. Both signals are active high.
+--
+-- 9th Jan 2004 0.8 John Kent
+-- Clear instruction did an alu_ld8 rather than an alu_clr, so
+-- the carry bit was not cleared correctly.
+-- This error was picked up by Michael Hassenfratz.
+--
+
+library ieee;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.STD_LOGIC_ARITH.ALL;
+use IEEE.STD_LOGIC_UNSIGNED.ALL;
+
+entity cpu68 is
+ port (
+ clk: in std_logic;
+ rst: in std_logic;
+ rw: out std_logic;
+ vma: out std_logic;
+ address: out std_logic_vector(15 downto 0);
+ data_in: in std_logic_vector(7 downto 0);
+ data_out: out std_logic_vector(7 downto 0);
+ hold: in std_logic;
+ halt: in std_logic;
+ irq: in std_logic;
+ nmi: in std_logic;
+ test_alu: out std_logic_vector(15 downto 0);
+ test_cc: out std_logic_vector(7 downto 0)
+ );
+end;
+
+architecture CPU_ARCH of cpu68 is
+
+ constant SBIT : integer := 7;
+ constant XBIT : 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;
+
+ type state_type is (reset_state, fetch_state, decode_state,
+ extended_state, indexed_state, read8_state, read16_state, immediate16_state,
+ write8_state, write16_state,
+ execute_state, halt_state, error_state,
+ mul_state, mulea_state, muld_state,
+ mul0_state, mul1_state, mul2_state, mul3_state,
+ mul4_state, mul5_state, mul6_state, mul7_state,
+ jmp_state, jsr_state, jsr1_state,
+ branch_state, bsr_state, bsr1_state,
+ rts_hi_state, rts_lo_state,
+ int_pcl_state, int_pch_state,
+ int_ixl_state, int_ixh_state,
+ int_cc_state, int_acca_state, int_accb_state,
+ int_wai_state, int_mask_state,
+ rti_state, rti_cc_state, rti_acca_state, rti_accb_state,
+ rti_ixl_state, rti_ixh_state,
+ rti_pcl_state, rti_pch_state,
+ pula_state, psha_state, pulb_state, pshb_state,
+ pulx_lo_state, pulx_hi_state, pshx_lo_state, pshx_hi_state,
+ vect_lo_state, vect_hi_state );
+ type addr_type is (idle_ad, fetch_ad, read_ad, write_ad, push_ad, pull_ad, int_hi_ad, int_lo_ad );
+ type dout_type is (md_lo_dout, md_hi_dout, acca_dout, accb_dout, ix_lo_dout, ix_hi_dout, cc_dout, pc_lo_dout, pc_hi_dout );
+ type op_type is (reset_op, fetch_op, latch_op );
+ 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 cc_type is (reset_cc, load_cc, pull_cc, latch_cc );
+ type ix_type is (reset_ix, load_ix, pull_lo_ix, pull_hi_ix, latch_ix );
+ type sp_type is (reset_sp, latch_sp, load_sp );
+ type pc_type is (reset_pc, latch_pc, load_ea_pc, add_ea_pc, pull_lo_pc, pull_hi_pc, inc_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, add_ix_ea, load_accb_ea, inc_ea, fetch_first_ea, fetch_next_ea );
+ type iv_type is (reset_iv, latch_iv, swi_iv, nmi_iv, irq_iv );
+ type nmi_type is (reset_nmi, set_nmi, latch_nmi );
+ type left_type is (acca_left, accb_left, accd_left, md_left, ix_left, sp_left );
+ type right_type is (md_right, zero_right, plus_one_right, accb_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_inx, alu_dex, alu_cpx,
+ alu_lsr16, alu_lsl16,
+ alu_ror8, alu_rol8,
+ alu_asr8, alu_asl8, alu_lsr8,
+ alu_sei, alu_cli, alu_sec, alu_clc, alu_sev, alu_clv, alu_tpa, alu_tap,
+ alu_ld8, alu_st8, alu_ld16, alu_st16, alu_nop, alu_daa );
+
+ signal op_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 xreg: std_logic_vector(15 downto 0);
+ signal sp: 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(1 downto 0);
+ signal nmi_req: std_logic;
+ signal nmi_ack: std_logic;
+
+ signal state: state_type;
+ signal next_state: state_type;
+ signal pc_ctrl: pc_type;
+ signal ea_ctrl: ea_type;
+ signal op_ctrl: op_type;
+ signal md_ctrl: md_type;
+ signal acca_ctrl: acca_type;
+ signal accb_ctrl: accb_type;
+ signal ix_ctrl: ix_type;
+ signal cc_ctrl: cc_type;
+ signal sp_ctrl: sp_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
+
+----------------------------------
+--
+-- Address bus multiplexer
+--
+----------------------------------
+
+addr_mux: process( clk, addr_ctrl, pc, ea, sp, iv )
+begin
+ case addr_ctrl is
+ when idle_ad =>
+ address <= "1111111111111111";
+ vma <= '0';
+ rw <= '1';
+ when fetch_ad =>
+ address <= pc;
+ vma <= '1';
+ rw <= '1';
+ when read_ad =>
+ address <= ea;
+ vma <= '1';
+ rw <= '1';
+ when write_ad =>
+ address <= ea;
+ vma <= '1';
+ rw <= '0';
+ when push_ad =>
+ address <= sp;
+ vma <= '1';
+ rw <= '0';
+ when pull_ad =>
+ address <= sp;
+ vma <= '1';
+ rw <= '1';
+ when int_hi_ad =>
+ address <= "1111111111111" & iv & "0";
+ vma <= '1';
+ rw <= '1';
+ when int_lo_ad =>
+ address <= "1111111111111" & iv & "1";
+ vma <= '1';
+ rw <= '1';
+ when others =>
+ address <= "1111111111111111";
+ vma <= '0';
+ rw <= '1';
+ end case;
+end process;
+
+--------------------------------
+--
+-- Data Bus output
+--
+--------------------------------
+dout_mux : process( clk, dout_ctrl, md, acca, accb, xreg, pc, cc )
+begin
+ case dout_ctrl is
+ when md_hi_dout => -- alu output
+ data_out <= md(15 downto 8);
+ when md_lo_dout =>
+ data_out <= md(7 downto 0);
+ when acca_dout => -- accumulator a
+ data_out <= acca;
+ when accb_dout => -- accumulator b
+ data_out <= accb;
+ when ix_lo_dout => -- index reg
+ data_out <= xreg(7 downto 0);
+ when ix_hi_dout => -- index reg
+ data_out <= xreg(15 downto 8);
+ when cc_dout => -- condition codes
+ data_out <= cc;
+ 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;
+
+
+----------------------------------
+--
+-- Program Counter Control
+--
+----------------------------------
+
+pc_mux: process( clk, pc_ctrl, pc, out_alu, data_in, ea, hold )
+variable tempof : std_logic_vector(15 downto 0);
+variable temppc : std_logic_vector(15 downto 0);
+begin
+ case pc_ctrl is
+ when add_ea_pc =>
+ if ea(7) = '0' then
+ tempof := "00000000" & ea(7 downto 0);
+ else
+ tempof := "11111111" & ea(7 downto 0);
+ end if;
+ when inc_pc =>
+ tempof := "0000000000000001";
+ when others =>
+ tempof := "0000000000000000";
+ end case;
+
+ case pc_ctrl is
+ when reset_pc =>
+ temppc := "1111111111111110";
+ when load_ea_pc =>
+ temppc := ea;
+ when pull_lo_pc =>
+ temppc(7 downto 0) := data_in;
+ temppc(15 downto 8) := pc(15 downto 8);
+ when pull_hi_pc =>
+ temppc(7 downto 0) := pc(7 downto 0);
+ temppc(15 downto 8) := data_in;
+ when others =>
+ temppc := pc;
+ end case;
+
+ if clk'event and clk = '0' then
+ if hold = '1' then
+ pc <= pc;
+ else
+ pc <= temppc + tempof;
+ end if;
+ end if;
+end process;
+
+----------------------------------
+--
+-- Effective Address Control
+--
+----------------------------------
+
+ea_mux: process( clk, ea_ctrl, ea, out_alu, data_in, accb, xreg, hold )
+variable tempind : std_logic_vector(15 downto 0);
+variable tempea : std_logic_vector(15 downto 0);
+begin
+ case ea_ctrl is
+ when add_ix_ea =>
+ tempind := "00000000" & ea(7 downto 0);
+ when inc_ea =>
+ tempind := "0000000000000001";
+ when others =>
+ tempind := "0000000000000000";
+ end case;
+
+ case ea_ctrl is
+ when reset_ea =>
+ tempea := "0000000000000000";
+ when load_accb_ea =>
+ tempea := "00000000" & accb(7 downto 0);
+ when add_ix_ea =>
+ tempea := xreg;
+ when fetch_first_ea =>
+ tempea(7 downto 0) := data_in;
+ tempea(15 downto 8) := "00000000";
+ when fetch_next_ea =>
+ tempea(7 downto 0) := data_in;
+ tempea(15 downto 8) := ea(7 downto 0);
+ when others =>
+ tempea := ea;
+ end case;
+
+ if clk'event and clk = '0' then
+ if hold = '1' then
+ ea <= ea;
+ else
+ ea <= tempea + tempind;
+ end if;
+ end if;
+end process;
+
+--------------------------------
+--
+-- Accumulator A
+--
+--------------------------------
+acca_mux : process( clk, acca_ctrl, out_alu, acca, data_in, hold )
+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_mux : process( clk, accb_ctrl, out_alu, accb, data_in, hold )
+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_mux : process( clk, ix_ctrl, out_alu, xreg, data_in, hold )
+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;
+
+--------------------------------
+--
+-- stack pointer
+--
+--------------------------------
+sp_mux : process( clk, sp_ctrl, out_alu, hold )
+begin
+ if clk'event and clk = '0' then
+ if hold = '1' then
+ sp <= sp;
+ else
+ case sp_ctrl is
+ when reset_sp =>
+ sp <= "0000000000000000";
+ when load_sp =>
+ sp <= out_alu(15 downto 0);
+ when others =>
+-- when latch_sp =>
+ sp <= sp;
+ end case;
+ end if;
+ end if;
+end process;
+
+--------------------------------
+--
+-- Memory Data
+--
+--------------------------------
+md_mux : process( clk, md_ctrl, out_alu, data_in, md, hold )
+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 =>
+ md(15 downto 8) <= "00000000";
+ 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_mux: process( clk, cc_ctrl, cc_out, cc, data_in, hold )
+begin
+ if clk'event and clk = '0' then
+ if hold = '1' then
+ cc <= cc;
+ else
+ case cc_ctrl is
+ when reset_cc =>
+ cc <= "11000000";
+ 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;
+
+----------------------------------
+--
+-- interrupt vector
+--
+----------------------------------
+
+iv_mux: process( clk, iv_ctrl, hold )
+begin
+ if clk'event and clk = '0' then
+ if hold = '1' then
+ iv <= iv;
+ else
+ case iv_ctrl is
+ when reset_iv =>
+ iv <= "11";
+ when nmi_iv =>
+ iv <= "10";
+ when swi_iv =>
+ iv <= "01";
+ when irq_iv =>
+ iv <= "00";
+ when others =>
+ iv <= iv;
+ end case;
+ end if;
+ end if;
+end process;
+
+----------------------------------
+--
+-- op code fetch
+--
+----------------------------------
+
+op_fetch: process( clk, data_in, op_ctrl, op_code, hold )
+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 <= "00000001"; -- nop
+ when fetch_op =>
+ op_code <= data_in;
+ when others =>
+-- when latch_op =>
+ op_code <= op_code;
+ end case;
+ end if;
+ end if;
+end process;
+
+----------------------------------
+--
+-- Left Mux
+--
+----------------------------------
+
+left_mux: process( left_ctrl, acca, accb, xreg, sp, pc, ea, md )
+begin
+ case left_ctrl is
+ 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 accd_left =>
+ left(15 downto 8) <= acca;
+ left(7 downto 0) <= accb;
+ when ix_left =>
+ left <= xreg;
+ when sp_left =>
+ left <= sp;
+ when others =>
+-- when md_left =>
+ left <= md;
+ end case;
+end process;
+----------------------------------
+--
+-- Right Mux
+--
+----------------------------------
+
+right_mux: process( right_ctrl, data_in, md, accb, ea )
+begin
+ case right_ctrl is
+ when zero_right =>
+ right <= "0000000000000000";
+ when plus_one_right =>
+ right <= "0000000000000001";
+ when accb_right =>
+ right <= "00000000" & accb;
+ when others =>
+-- when md_right =>
+ right <= md;
+ end case;
+end process;
+
+----------------------------------
+--
+-- Arithmetic Logic Unit
+--
+----------------------------------
+
+mux_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 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_inx |
+ alu_adc =>
+ out_alu <= left + right + ("000000000000000" & carry_in);
+ when alu_sub8 | alu_dec |
+ alu_sub16 | alu_dex |
+ alu_sbc | alu_cpx =>
+ out_alu <= left - right - ("000000000000000" & carry_in);
+ 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 | alu_lsr8 =>
+ out_alu <= carry_in & left(15 downto 1); -- lsr
+ when alu_ror8 =>
+ out_alu <= "00000000" & carry_in & left(7 downto 1); -- ror
+ when alu_asr8 =>
+ out_alu <= "00000000" & left(7) & left(7 downto 1); -- asr
+ when alu_neg =>
+ out_alu <= right - left; -- neg (right=0)
+ when alu_com =>
+ out_alu <= not left;
+ when alu_clr | alu_ld8 | alu_ld16 =>
+ out_alu <= right; -- clr, ld
+ when alu_st8 | alu_st16 =>
+ out_alu <= left;
+ when alu_daa =>
+ out_alu <= left + ("00000000" & daa_reg);
+ when alu_tpa =>
+ out_alu <= "00000000" & cc;
+ 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_daa =>
+ if ( daa_reg(7 downto 4) = "0110" ) then
+ cc_out(CBIT) <= '1';
+ else
+ cc_out(CBIT) <= '0';
+ end if;
+ when alu_sec =>
+ cc_out(CBIT) <= '1';
+ when alu_clc =>
+ cc_out(CBIT) <= '0';
+ when alu_tap =>
+ cc_out(CBIT) <= left(CBIT);
+ when others => -- carry is not affected by cpx
+ 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 =>
+ 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_lsl16 | alu_lsr16 |
+ alu_inx | alu_dex |
+ alu_ld16 | alu_st16 | alu_cpx =>
+ 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_tap =>
+ 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 =>
+ cc_out(NBIT) <= out_alu(7);
+ when alu_add16 | alu_sub16 |
+ alu_lsl16 | alu_lsr16 |
+ alu_ld16 | alu_st16 | alu_cpx =>
+ cc_out(NBIT) <= out_alu(15);
+ when alu_tap =>
+ cc_out(NBIT) <= left(NBIT);
+ when others =>
+ cc_out(NBIT) <= cc(NBIT);
+ end case;
+
+ --
+ -- Interrupt mask flag
+ --
+ case alu_ctrl is
+ when alu_sei =>
+ cc_out(IBIT) <= '1'; -- set interrupt mask
+ when alu_cli =>
+ cc_out(IBIT) <= '0'; -- clear interrupt mask
+ when alu_tap =>
+ cc_out(IBIT) <= left(IBIT);
+ 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_tap =>
+ 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 | alu_cpx =>
+ 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)));
+ 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);
+ when alu_tap =>
+ cc_out(VBIT) <= left(VBIT);
+ when alu_and | alu_ora | alu_eor | alu_com |
+ alu_st8 | alu_st16 | alu_ld8 | alu_ld16 |
+ alu_clv =>
+ cc_out(VBIT) <= '0';
+ when alu_sev =>
+ cc_out(VBIT) <= '1';
+ when others =>
+ cc_out(VBIT) <= cc(VBIT);
+ end case;
+
+ case alu_ctrl is
+ when alu_tap =>
+ cc_out(XBIT) <= cc(XBIT) and left(XBIT);
+ cc_out(SBIT) <= left(SBIT);
+ when others =>
+ cc_out(XBIT) <= cc(XBIT) and left(XBIT);
+ cc_out(SBIT) <= cc(SBIT);
+ end case;
+
+ test_alu <= out_alu;
+ test_cc <= cc_out;
+end process;
+
+------------------------------------
+--
+-- Detect Edge of NMI interrupt
+--
+------------------------------------
+
+nmi_handler : process( clk, rst, nmi, nmi_ack )
+begin
+ if clk'event and clk='0' then
+ if hold = '1' then
+ nmi_req <= nmi_req;
+ else
+ if rst='1' then
+ nmi_req <= '0';
+ else
+ if (nmi='1') and (nmi_ack='0') then
+ nmi_req <= '1';
+ else
+ if (nmi='0') and (nmi_ack='1') then
+ nmi_req <= '0';
+ else
+ nmi_req <= nmi_req;
+ end if;
+ end if;
+ end if;
+ end if;
+ end if;
+end process;
+
+------------------------------------
+--
+-- Nmi mux
+--
+------------------------------------
+
+nmi_mux: process( clk, nmi_ctrl, nmi_ack, hold )
+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;
+
+------------------------------------
+--
+-- state sequencer
+--
+------------------------------------
+process( state, op_code, cc, ea, irq, nmi_req, nmi_ack, hold, halt )
+ begin
+ case state is
+ when reset_state => -- released from reset
+ -- reset the registers
+ op_ctrl <= reset_op;
+ acca_ctrl <= reset_acca;
+ accb_ctrl <= reset_accb;
+ ix_ctrl <= reset_ix;
+ sp_ctrl <= reset_sp;
+ pc_ctrl <= reset_pc;
+ ea_ctrl <= reset_ea;
+ md_ctrl <= reset_md;
+ iv_ctrl <= reset_iv;
+ nmi_ctrl <= reset_nmi;
+ -- idle the ALU
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= reset_cc;
+ -- idle the bus
+ dout_ctrl <= md_lo_dout;
+ addr_ctrl <= idle_ad;
+ next_state <= vect_hi_state;
+
+ --
+ -- Jump via interrupt vector
+ -- iv holds interrupt type
+ -- fetch PC hi from vector location
+ --
+ when vect_hi_state =>
+ -- default the registers
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ md_ctrl <= latch_md;
+ ea_ctrl <= latch_ea;
+ iv_ctrl <= latch_iv;
+ -- idle the ALU
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ -- fetch pc low interrupt vector
+ pc_ctrl <= pull_hi_pc;
+ addr_ctrl <= int_hi_ad;
+ dout_ctrl <= pc_hi_dout;
+ next_state <= vect_lo_state;
+ --
+ -- jump via interrupt vector
+ -- iv holds vector type
+ -- fetch PC lo from vector location
+ --
+ when vect_lo_state =>
+ -- default the registers
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ md_ctrl <= latch_md;
+ ea_ctrl <= latch_ea;
+ iv_ctrl <= latch_iv;
+ -- idle the ALU
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ -- fetch the vector low byte
+ pc_ctrl <= pull_lo_pc;
+ addr_ctrl <= int_lo_ad;
+ dout_ctrl <= pc_lo_dout;
+ 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 =>
+ case op_code(7 downto 4) is
+ when "0000" |
+ "0001" |
+ "0010" | -- branch conditional
+ "0011" |
+ "0100" | -- acca single op
+ "0101" | -- accb single op
+ "0110" | -- indexed single op
+ "0111" => -- extended single op
+ -- idle ALU
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+
+ when "1000" | -- acca immediate
+ "1001" | -- acca direct
+ "1010" | -- acca indexed
+ "1011" => -- acca extended
+ 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;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ when "0001" => -- cmpa
+ left_ctrl <= acca_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_sub8;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ when "0010" => -- sbca
+ left_ctrl <= acca_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_sbc;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= load_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ when "0011" => -- 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;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ when "0100" => -- anda
+ left_ctrl <= acca_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_and;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= load_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ when "0101" => -- bita
+ left_ctrl <= acca_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_and;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ when "0110" => -- ldaa
+ left_ctrl <= acca_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_ld8;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= load_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ when "0111" => -- staa
+ left_ctrl <= acca_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_st8;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ when "1000" => -- eora
+ left_ctrl <= acca_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_eor;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= load_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ when "1001" => -- adca
+ left_ctrl <= acca_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_adc;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= load_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ when "1010" => -- oraa
+ left_ctrl <= acca_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_ora;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= load_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ when "1011" => -- adda
+ left_ctrl <= acca_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_add8;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= load_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ when "1100" => -- cpx
+ left_ctrl <= ix_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_cpx;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ when "1101" => -- bsr / jsr
+ left_ctrl <= acca_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ when "1110" => -- lds
+ left_ctrl <= sp_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_ld16;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= load_sp;
+ when "1111" => -- sts
+ left_ctrl <= sp_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_st16;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ when others =>
+ left_ctrl <= acca_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ end case;
+ when "1100" | -- accb immediate
+ "1101" | -- accb direct
+ "1110" | -- accb indexed
+ "1111" => -- accb extended
+ 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;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= load_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ when "0001" => -- cmpb
+ left_ctrl <= accb_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_sub8;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ when "0010" => -- sbcb
+ left_ctrl <= accb_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_sbc;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= load_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ 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;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ when "0100" => -- andb
+ left_ctrl <= accb_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_and;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= load_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ when "0101" => -- bitb
+ left_ctrl <= accb_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_and;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ when "0110" => -- ldab
+ left_ctrl <= accb_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_ld8;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= load_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ when "0111" => -- stab
+ left_ctrl <= accb_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_st8;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ when "1000" => -- eorb
+ left_ctrl <= accb_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_eor;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= load_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ when "1001" => -- adcb
+ left_ctrl <= accb_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_adc;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= load_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ when "1010" => -- orab
+ left_ctrl <= accb_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_ora;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= load_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ when "1011" => -- addb
+ left_ctrl <= accb_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_add8;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= load_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ 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;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ when "1101" => -- std
+ left_ctrl <= accd_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_st16;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ when "1110" => -- ldx
+ left_ctrl <= ix_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_ld16;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= load_ix;
+ sp_ctrl <= latch_sp;
+ when "1111" => -- stx
+ left_ctrl <= ix_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_st16;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ when others =>
+ left_ctrl <= accb_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ end case;
+ when others =>
+ left_ctrl <= accd_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ end case;
+ md_ctrl <= latch_md;
+ -- fetch the op code
+ op_ctrl <= fetch_op;
+ ea_ctrl <= reset_ea;
+ addr_ctrl <= fetch_ad;
+ dout_ctrl <= md_lo_dout;
+ iv_ctrl <= latch_iv;
+ if halt = '1' then
+ pc_ctrl <= latch_pc;
+ nmi_ctrl <= latch_nmi;
+ next_state <= halt_state;
+ -- service non maskable interrupts
+ elsif (nmi_req = '1') and (nmi_ack = '0') then
+ pc_ctrl <= latch_pc;
+ nmi_ctrl <= set_nmi;
+ next_state <= int_pcl_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;
+ else
+ nmi_ctrl <= latch_nmi;
+ end if;
+ --
+ -- IRQ is level sensitive
+ --
+ if (irq = '1') and (cc(IBIT) = '0') then
+ pc_ctrl <= latch_pc;
+ next_state <= int_pcl_state;
+ else
+ -- Advance the PC to fetch next instruction byte
+ pc_ctrl <= inc_pc;
+ next_state <= decode_state;
+ end if;
+ end if;
+ --
+ -- Here to decode instruction
+ -- and fetch next byte of intruction
+ -- whether it be necessary or not
+ --
+ when decode_state =>
+ -- fetch first byte of address or immediate data
+ ea_ctrl <= fetch_first_ea;
+ addr_ctrl <= fetch_ad;
+ dout_ctrl <= md_lo_dout;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ iv_ctrl <= latch_iv;
+ case op_code(7 downto 4) is
+ when "0000" =>
+ md_ctrl <= fetch_first_md;
+ sp_ctrl <= latch_sp;
+ pc_ctrl <= latch_pc;
+ case op_code(3 downto 0) is
+ when "0001" => -- nop
+ left_ctrl <= accd_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ when "0100" => -- lsrd
+ left_ctrl <= accd_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_lsr16;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= load_hi_acca;
+ accb_ctrl <= load_accb;
+ ix_ctrl <= latch_ix;
+ when "0101" => -- lsld
+ left_ctrl <= accd_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_lsl16;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= load_hi_acca;
+ accb_ctrl <= load_accb;
+ ix_ctrl <= latch_ix;
+ when "0110" => -- tap
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_tap;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ when "0111" => -- tpa
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_tpa;
+ cc_ctrl <= latch_cc;
+ acca_ctrl <= load_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ when "1000" => -- inx
+ left_ctrl <= ix_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_inx;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= load_ix;
+ when "1001" => -- dex
+ left_ctrl <= ix_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_dex;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= load_ix;
+ when "1010" => -- clv
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_clv;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ when "1011" => -- sev
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_sev;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ when "1100" => -- clc
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_clc;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ when "1101" => -- sec
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_sec;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ when "1110" => -- cli
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_cli;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ when "1111" => -- sei
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_sei;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ when others =>
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ end case;
+ next_state <= fetch_state;
+ -- acca / accb inherent instructions
+ when "0001" =>
+ md_ctrl <= fetch_first_md;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ pc_ctrl <= latch_pc;
+ left_ctrl <= acca_left;
+ right_ctrl <= accb_right;
+ case op_code(3 downto 0) is
+ when "0000" => -- sba
+ alu_ctrl <= alu_sub8;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= load_acca;
+ accb_ctrl <= latch_accb;
+ when "0001" => -- cba
+ alu_ctrl <= alu_sub8;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ when "0110" => -- tab
+ alu_ctrl <= alu_st8;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= load_accb;
+ when "0111" => -- tba
+ alu_ctrl <= alu_ld8;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= load_acca;
+ accb_ctrl <= latch_accb;
+ when "1001" => -- daa
+ alu_ctrl <= alu_daa;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= load_acca;
+ accb_ctrl <= latch_accb;
+ when "1011" => -- aba
+ alu_ctrl <= alu_add8;
+ cc_ctrl <= load_cc;
+ acca_ctrl <= load_acca;
+ accb_ctrl <= latch_accb;
+ when others =>
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ end case;
+ next_state <= fetch_state;
+ when "0010" => -- branch conditional
+ md_ctrl <= fetch_first_md;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ -- increment the pc
+ pc_ctrl <= inc_pc;
+ case op_code(3 downto 0) is
+ when "0000" => -- bra
+ next_state <= branch_state;
+ when "0001" => -- brn
+ next_state <= fetch_state;
+ when "0010" => -- bhi
+ if (cc(CBIT) or cc(ZBIT)) = '0' then
+ next_state <= branch_state;
+ else
+ next_state <= fetch_state;
+ end if;
+ when "0011" => -- bls
+ if (cc(CBIT) or cc(ZBIT)) = '1' then
+ next_state <= branch_state;
+ else
+ next_state <= fetch_state;
+ end if;
+ when "0100" => -- bcc/bhs
+ if cc(CBIT) = '0' then
+ next_state <= branch_state;
+ else
+ next_state <= fetch_state;
+ end if;
+ when "0101" => -- bcs/blo
+ if cc(CBIT) = '1' then
+ next_state <= branch_state;
+ else
+ next_state <= fetch_state;
+ end if;
+ when "0110" => -- bne
+ if cc(ZBIT) = '0' then
+ next_state <= branch_state;
+ else
+ next_state <= fetch_state;
+ end if;
+ when "0111" => -- beq
+ if cc(ZBIT) = '1' then
+ next_state <= branch_state;
+ else
+ next_state <= fetch_state;
+ end if;
+ when "1000" => -- bvc
+ if cc(VBIT) = '0' then
+ next_state <= branch_state;
+ else
+ next_state <= fetch_state;
+ end if;
+ when "1001" => -- bvs
+ if cc(VBIT) = '1' then
+ next_state <= branch_state;
+ else
+ next_state <= fetch_state;
+ end if;
+ when "1010" => -- bpl
+ if cc(NBIT) = '0' then
+ next_state <= branch_state;
+ else
+ next_state <= fetch_state;
+ end if;
+ when "1011" => -- bmi
+ if cc(NBIT) = '1' then
+ next_state <= branch_state;
+ else
+ next_state <= fetch_state;
+ end if;
+ when "1100" => -- bge
+ if (cc(NBIT) xor cc(VBIT)) = '0' then
+ next_state <= branch_state;
+ else
+ next_state <= fetch_state;
+ end if;
+ when "1101" => -- blt
+ if (cc(NBIT) xor cc(VBIT)) = '1' then
+ next_state <= branch_state;
+ else
+ next_state <= fetch_state;
+ end if;
+ when "1110" => -- bgt
+ if (cc(ZBIT) or (cc(NBIT) xor cc(VBIT))) = '0' then
+ next_state <= branch_state;
+ else
+ next_state <= fetch_state;
+ end if;
+ when "1111" => -- ble
+ if (cc(ZBIT) or (cc(NBIT) xor cc(VBIT))) = '1' then
+ next_state <= branch_state;
+ else
+ next_state <= fetch_state;
+ end if;
+ when others =>
+ next_state <= fetch_state;
+ end case;
+ --
+ -- Single byte stack operators
+ -- Do not advance PC
+ --
+ when "0011" =>
+ md_ctrl <= fetch_first_md;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ pc_ctrl <= latch_pc;
+ case op_code(3 downto 0) is
+ when "0000" => -- tsx
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_add16;
+ cc_ctrl <= latch_cc;
+ ix_ctrl <= load_ix;
+ sp_ctrl <= latch_sp;
+ next_state <= fetch_state;
+ when "0001" => -- ins
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_add16;
+ cc_ctrl <= latch_cc;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= load_sp;
+ next_state <= fetch_state;
+ when "0010" => -- pula
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_add16;
+ cc_ctrl <= latch_cc;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= load_sp;
+ next_state <= pula_state;
+ when "0011" => -- pulb
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_add16;
+ cc_ctrl <= latch_cc;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= load_sp;
+ next_state <= pulb_state;
+ when "0100" => -- des
+ -- decrement sp
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_sub16;
+ cc_ctrl <= latch_cc;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= load_sp;
+ next_state <= fetch_state;
+ when "0101" => -- txs
+ left_ctrl <= ix_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_sub16;
+ cc_ctrl <= latch_cc;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= load_sp;
+ next_state <= fetch_state;
+ when "0110" => -- psha
+ left_ctrl <= sp_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ next_state <= psha_state;
+ when "0111" => -- pshb
+ left_ctrl <= sp_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ next_state <= pshb_state;
+ when "1000" => -- pulx
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_add16;
+ cc_ctrl <= latch_cc;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= load_sp;
+ next_state <= pulx_hi_state;
+ when "1001" => -- rts
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_add16;
+ cc_ctrl <= latch_cc;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= load_sp;
+ next_state <= rts_hi_state;
+ when "1010" => -- abx
+ left_ctrl <= ix_left;
+ right_ctrl <= accb_right;
+ alu_ctrl <= alu_add16;
+ cc_ctrl <= latch_cc;
+ ix_ctrl <= load_ix;
+ sp_ctrl <= latch_sp;
+ next_state <= fetch_state;
+ when "1011" => -- rti
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_add16;
+ cc_ctrl <= latch_cc;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= load_sp;
+ next_state <= rti_cc_state;
+ when "1100" => -- pshx
+ left_ctrl <= sp_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ next_state <= pshx_lo_state;
+ when "1101" => -- mul
+ left_ctrl <= acca_left;
+ right_ctrl <= accb_right;
+ alu_ctrl <= alu_add16;
+ cc_ctrl <= latch_cc;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ next_state <= mul_state;
+ when "1110" => -- wai
+ left_ctrl <= sp_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ next_state <= int_pcl_state;
+ when "1111" => -- swi
+ left_ctrl <= sp_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ next_state <= int_pcl_state;
+ when others =>
+ left_ctrl <= sp_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ next_state <= fetch_state;
+ end case;
+ --
+ -- Accumulator A Single operand
+ -- source = Acc A dest = Acc A
+ -- Do not advance PC
+ --
+ when "0100" => -- acca single op
+ md_ctrl <= fetch_first_md;
+ accb_ctrl <= latch_accb;
+ pc_ctrl <= latch_pc;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ 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 <= plus_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 <= plus_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
+ 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;
+ next_state <= fetch_state;
+ --
+ -- single operand acc b
+ -- Do not advance PC
+ --
+ when "0101" =>
+ md_ctrl <= fetch_first_md;
+ acca_ctrl <= latch_acca;
+ pc_ctrl <= latch_pc;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ 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 <= plus_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 <= plus_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
+ 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;
+ next_state <= fetch_state;
+ --
+ -- Single operand indexed
+ -- Two byte instruction so advance PC
+ -- EA should hold index offset
+ --
+ when "0110" => -- indexed single op
+ md_ctrl <= fetch_first_md;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ -- increment the pc
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ pc_ctrl <= inc_pc;
+ 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
+ md_ctrl <= fetch_first_md;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ -- increment the pc
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ pc_ctrl <= inc_pc;
+ next_state <= extended_state;
+
+ when "1000" => -- acca immediate
+ md_ctrl <= fetch_first_md;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ -- increment the pc
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ pc_ctrl <= inc_pc;
+ case op_code(3 downto 0) is
+ when "0011" | -- subdd #
+ "1100" | -- cpx #
+ "1110" => -- lds #
+ next_state <= immediate16_state;
+ when "1101" => -- bsr
+ next_state <= bsr_state;
+ when others =>
+ next_state <= fetch_state;
+ end case;
+
+ when "1001" => -- acca direct
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ -- increment the pc
+ pc_ctrl <= inc_pc;
+ case op_code(3 downto 0) is
+ when "0111" => -- staa direct
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_st8;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= load_md;
+ next_state <= write8_state;
+ when "1111" => -- sts direct
+ left_ctrl <= sp_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_st16;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= load_md;
+ next_state <= write16_state;
+ when "1101" => -- jsr direct
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= fetch_first_md;
+ next_state <= jsr_state;
+ when others =>
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= fetch_first_md;
+ next_state <= read8_state;
+ end case;
+
+ when "1010" => -- acca indexed
+ md_ctrl <= fetch_first_md;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ -- increment the pc
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ pc_ctrl <= inc_pc;
+ next_state <= indexed_state;
+
+ when "1011" => -- acca extended
+ md_ctrl <= fetch_first_md;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ -- increment the pc
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ pc_ctrl <= inc_pc;
+ next_state <= extended_state;
+
+ when "1100" => -- accb immediate
+ md_ctrl <= fetch_first_md;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ -- increment the pc
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ pc_ctrl <= inc_pc;
+ case op_code(3 downto 0) is
+ when "0011" | -- addd #
+ "1100" | -- ldd #
+ "1110" => -- ldx #
+ next_state <= immediate16_state;
+ when others =>
+ next_state <= fetch_state;
+ end case;
+
+ when "1101" => -- accb direct
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ -- increment the pc
+ pc_ctrl <= inc_pc;
+ case op_code(3 downto 0) is
+ when "0111" => -- stab direct
+ left_ctrl <= accb_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_st8;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= load_md;
+ next_state <= write8_state;
+ when "1101" => -- std direct
+ left_ctrl <= accd_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_st16;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= load_md;
+ next_state <= write16_state;
+ when "1111" => -- stx direct
+ left_ctrl <= ix_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_st16;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= load_md;
+ next_state <= write16_state;
+ when others =>
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= fetch_first_md;
+ next_state <= read8_state;
+ end case;
+
+ when "1110" => -- accb indexed
+ md_ctrl <= fetch_first_md;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ -- increment the pc
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ pc_ctrl <= inc_pc;
+ next_state <= indexed_state;
+
+ when "1111" => -- accb extended
+ md_ctrl <= fetch_first_md;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ -- increment the pc
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ pc_ctrl <= inc_pc;
+ next_state <= extended_state;
+
+ when others =>
+ md_ctrl <= fetch_first_md;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ -- idle the pc
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ pc_ctrl <= latch_pc;
+ next_state <= fetch_state;
+ end case;
+
+ when immediate16_state =>
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ op_ctrl <= latch_op;
+ iv_ctrl <= latch_iv;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- increment pc
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ pc_ctrl <= inc_pc;
+ -- fetch next immediate byte
+ md_ctrl <= fetch_next_md;
+ addr_ctrl <= fetch_ad;
+ dout_ctrl <= md_lo_dout;
+ next_state <= fetch_state;
+ --
+ -- ea holds 8 bit index offet
+ -- calculate the effective memory address
+ -- using the alu
+ --
+ when indexed_state =>
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ pc_ctrl <= latch_pc;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ -- calculate effective address from index reg
+ -- index offest is not sign extended
+ ea_ctrl <= add_ix_ea;
+ -- idle the bus
+ addr_ctrl <= idle_ad;
+ dout_ctrl <= md_lo_dout;
+ -- work out next state
+ case op_code(7 downto 4) is
+ when "0110" => -- single op indexed
+ md_ctrl <= latch_md;
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ case op_code(3 downto 0) is
+ when "1011" => -- undefined
+ next_state <= fetch_state;
+ when "1110" => -- jmp
+ next_state <= jmp_state;
+ when others =>
+ next_state <= read8_state;
+ end case;
+ when "1010" => -- acca indexed
+ case op_code(3 downto 0) is
+ when "0111" => -- staa
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_st8;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= load_md;
+ next_state <= write8_state;
+ when "1101" => -- jsr
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= latch_md;
+ next_state <= jsr_state;
+ when "1111" => -- sts
+ left_ctrl <= sp_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_st16;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= load_md;
+ next_state <= write16_state;
+ when others =>
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= latch_md;
+ next_state <= read8_state;
+ end case;
+ when "1110" => -- accb indexed
+ case op_code(3 downto 0) is
+ when "0111" => -- stab direct
+ left_ctrl <= accb_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_st8;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= load_md;
+ next_state <= write8_state;
+ when "1101" => -- std direct
+ left_ctrl <= accd_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_st16;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= load_md;
+ next_state <= write16_state;
+ when "1111" => -- stx direct
+ left_ctrl <= ix_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_st16;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= load_md;
+ next_state <= write16_state;
+ when others =>
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= latch_md;
+ next_state <= read8_state;
+ end case;
+ when others =>
+ md_ctrl <= latch_md;
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ next_state <= fetch_state;
+ end case;
+ --
+ -- 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
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ -- increment pc
+ pc_ctrl <= inc_pc;
+ -- fetch next effective address bytes
+ ea_ctrl <= fetch_next_ea;
+ addr_ctrl <= fetch_ad;
+ dout_ctrl <= md_lo_dout;
+ -- work out the next state
+ case op_code(7 downto 4) is
+ when "0111" => -- single op extended
+ md_ctrl <= latch_md;
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ case op_code(3 downto 0) is
+ when "1011" => -- undefined
+ next_state <= fetch_state;
+ when "1110" => -- jmp
+ next_state <= jmp_state;
+ when others =>
+ next_state <= read8_state;
+ end case;
+ when "1011" => -- acca extended
+ case op_code(3 downto 0) is
+ when "0111" => -- staa
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_st8;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= load_md;
+ next_state <= write8_state;
+ when "1101" => -- jsr
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= latch_md;
+ next_state <= jsr_state;
+ when "1111" => -- sts
+ left_ctrl <= sp_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_st16;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= load_md;
+ next_state <= write16_state;
+ when others =>
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= latch_md;
+ next_state <= read8_state;
+ end case;
+ when "1111" => -- accb extended
+ case op_code(3 downto 0) is
+ when "0111" => -- stab
+ left_ctrl <= accb_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_st8;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= load_md;
+ next_state <= write8_state;
+ when "1101" => -- std
+ left_ctrl <= accd_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_st16;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= load_md;
+ next_state <= write16_state;
+ when "1111" => -- stx
+ left_ctrl <= ix_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_st16;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= load_md;
+ next_state <= write16_state;
+ when others =>
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= latch_md;
+ next_state <= read8_state;
+ end case;
+ when others =>
+ md_ctrl <= latch_md;
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ next_state <= fetch_state;
+ end case;
+ --
+ -- here if ea holds low byte (direct page)
+ -- can enter here from extended addressing
+ -- read memory location
+ -- note that reads may be 8 or 16 bits
+ --
+ when read8_state => -- read data
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ pc_ctrl <= latch_pc;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ --
+ addr_ctrl <= read_ad;
+ dout_ctrl <= md_lo_dout;
+ case op_code(7 downto 4) is
+ when "0110" | "0111" => -- single operand
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= fetch_first_md;
+ ea_ctrl <= latch_ea;
+ next_state <= execute_state;
+
+ when "1001" | "1010" | "1011" => -- acca
+ case op_code(3 downto 0) is
+ when "0011" | -- subd
+ "1110" | -- lds
+ "1100" => -- cpx
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= fetch_first_md;
+ -- increment the effective address in case of 16 bit load
+ ea_ctrl <= inc_ea;
+ next_state <= read16_state;
+-- when "0111" => -- staa
+-- left_ctrl <= acca_left;
+-- right_ctrl <= zero_right;
+-- alu_ctrl <= alu_st8;
+-- cc_ctrl <= latch_cc;
+-- md_ctrl <= load_md;
+-- ea_ctrl <= latch_ea;
+-- next_state <= write8_state;
+-- when "1101" => -- jsr
+-- left_ctrl <= acca_left;
+-- right_ctrl <= zero_right;
+-- alu_ctrl <= alu_nop;
+-- cc_ctrl <= latch_cc;
+-- md_ctrl <= latch_md;
+-- ea_ctrl <= latch_ea;
+-- next_state <= jsr_state;
+-- when "1111" => -- sts
+-- left_ctrl <= sp_left;
+-- right_ctrl <= zero_right;
+-- alu_ctrl <= alu_st16;
+-- cc_ctrl <= latch_cc;
+-- md_ctrl <= load_md;
+-- ea_ctrl <= latch_ea;
+-- next_state <= write16_state;
+ when others =>
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= fetch_first_md;
+ ea_ctrl <= latch_ea;
+ next_state <= fetch_state;
+ end case;
+
+ when "1101" | "1110" | "1111" => -- accb
+ case op_code(3 downto 0) is
+ when "0011" | -- addd
+ "1100" | -- ldd
+ "1110" => -- ldx
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= fetch_first_md;
+ -- increment the effective address in case of 16 bit load
+ ea_ctrl <= inc_ea;
+ next_state <= read16_state;
+-- when "0111" => -- stab
+-- left_ctrl <= accb_left;
+-- right_ctrl <= zero_right;
+-- alu_ctrl <= alu_st8;
+-- cc_ctrl <= latch_cc;
+-- md_ctrl <= load_md;
+-- ea_ctrl <= latch_ea;
+-- next_state <= write8_state;
+-- when "1101" => -- std
+-- left_ctrl <= accd_left;
+-- right_ctrl <= zero_right;
+-- alu_ctrl <= alu_st16;
+-- cc_ctrl <= latch_cc;
+-- md_ctrl <= load_md;
+-- ea_ctrl <= latch_ea;
+-- next_state <= write16_state;
+-- when "1111" => -- stx
+-- left_ctrl <= ix_left;
+-- right_ctrl <= zero_right;
+-- alu_ctrl <= alu_st16;
+-- cc_ctrl <= latch_cc;
+-- md_ctrl <= load_md;
+-- ea_ctrl <= latch_ea;
+-- next_state <= write16_state;
+ when others =>
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= fetch_first_md;
+ ea_ctrl <= latch_ea;
+ next_state <= execute_state;
+ end case;
+ when others =>
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= fetch_first_md;
+ ea_ctrl <= latch_ea;
+ next_state <= fetch_state;
+ end case;
+
+ when read16_state => -- read second data byte from ea
+ -- default
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ pc_ctrl <= latch_pc;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ -- idle the effective address
+ ea_ctrl <= latch_ea;
+ -- read the low byte of the 16 bit data
+ md_ctrl <= fetch_next_md;
+ addr_ctrl <= read_ad;
+ dout_ctrl <= md_lo_dout;
+ next_state <= fetch_state;
+ --
+ -- 16 bit Write state
+ -- write high byte of ALU output.
+ -- EA hold address of memory to write to
+ -- Advance the effective address in ALU
+ --
+ when write16_state =>
+ -- default
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ -- increment the effective address
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ ea_ctrl <= inc_ea;
+ -- write the ALU hi byte to ea
+ addr_ctrl <= write_ad;
+ dout_ctrl <= md_hi_dout;
+ next_state <= write8_state;
+ --
+ -- 8 bit write
+ -- Write low 8 bits of ALU output
+ --
+ when write8_state =>
+ -- default registers
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- idle the ALU
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ -- write ALU low byte output
+ addr_ctrl <= write_ad;
+ dout_ctrl <= md_lo_dout;
+ next_state <= fetch_state;
+
+ when jmp_state =>
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- load PC with effective address
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ pc_ctrl <= load_ea_pc;
+ -- idle the bus
+ addr_ctrl <= idle_ad;
+ dout_ctrl <= md_lo_dout;
+ next_state <= fetch_state;
+
+ when jsr_state => -- JSR
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- decrement sp
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_sub16;
+ cc_ctrl <= latch_cc;
+ sp_ctrl <= load_sp;
+ -- write pc low
+ addr_ctrl <= push_ad;
+ dout_ctrl <= pc_lo_dout;
+ next_state <= jsr1_state;
+
+ when jsr1_state => -- JSR
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- decrement sp
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_sub16;
+ cc_ctrl <= latch_cc;
+ sp_ctrl <= load_sp;
+ -- write pc hi
+ addr_ctrl <= push_ad;
+ dout_ctrl <= pc_hi_dout;
+ next_state <= jmp_state;
+
+ when branch_state => -- Bcc
+ -- default registers
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- calculate signed branch
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ pc_ctrl <= add_ea_pc;
+ -- idle the bus
+ addr_ctrl <= idle_ad;
+ dout_ctrl <= md_lo_dout;
+ next_state <= fetch_state;
+
+ when bsr_state => -- BSR
+ -- default
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- decrement sp
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_sub16;
+ cc_ctrl <= latch_cc;
+ sp_ctrl <= load_sp;
+ -- write pc low
+ addr_ctrl <= push_ad;
+ dout_ctrl <= pc_lo_dout;
+ next_state <= bsr1_state;
+
+ when bsr1_state => -- BSR
+ -- default registers
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- decrement sp
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_sub16;
+ cc_ctrl <= latch_cc;
+ sp_ctrl <= load_sp;
+ -- write pc hi
+ addr_ctrl <= push_ad;
+ dout_ctrl <= pc_hi_dout;
+ next_state <= branch_state;
+
+ when rts_hi_state => -- RTS
+ -- default
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- increment the sp
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_add16;
+ cc_ctrl <= latch_cc;
+ sp_ctrl <= load_sp;
+ -- read pc hi
+ pc_ctrl <= pull_hi_pc;
+ addr_ctrl <= pull_ad;
+ dout_ctrl <= pc_hi_dout;
+ next_state <= rts_lo_state;
+
+ when rts_lo_state => -- RTS1
+ -- default
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- idle the ALU
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ -- read pc low
+ pc_ctrl <= pull_lo_pc;
+ addr_ctrl <= pull_ad;
+ dout_ctrl <= pc_lo_dout;
+ next_state <= fetch_state;
+
+ when mul_state =>
+ -- default
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ pc_ctrl <= latch_pc;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- move acca to md
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_st16;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= load_md;
+ -- idle bus
+ addr_ctrl <= idle_ad;
+ dout_ctrl <= md_lo_dout;
+ next_state <= mulea_state;
+
+ when mulea_state =>
+ -- default
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ pc_ctrl <= latch_pc;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ md_ctrl <= latch_md;
+ -- idle ALU
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ -- move accb to ea
+ ea_ctrl <= load_accb_ea;
+ -- idle bus
+ addr_ctrl <= idle_ad;
+ dout_ctrl <= md_lo_dout;
+ next_state <= muld_state;
+
+ when muld_state =>
+ -- default
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ pc_ctrl <= latch_pc;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ md_ctrl <= latch_md;
+ -- clear accd
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_ld8;
+ cc_ctrl <= latch_cc;
+ acca_ctrl <= load_hi_acca;
+ accb_ctrl <= load_accb;
+ -- idle bus
+ addr_ctrl <= idle_ad;
+ dout_ctrl <= md_lo_dout;
+ next_state <= mul0_state;
+
+ when mul0_state =>
+ -- default
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ pc_ctrl <= latch_pc;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- if bit 0 of ea set, add accd to md
+ left_ctrl <= accd_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_add16;
+ if ea(0) = '1' then
+ cc_ctrl <= load_cc;
+ acca_ctrl <= load_hi_acca;
+ accb_ctrl <= load_accb;
+ else
+ cc_ctrl <= latch_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ end if;
+ md_ctrl <= shiftl_md;
+ -- idle bus
+ addr_ctrl <= idle_ad;
+ dout_ctrl <= md_lo_dout;
+ next_state <= mul1_state;
+
+ when mul1_state =>
+ -- default
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ pc_ctrl <= latch_pc;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- if bit 1 of ea set, add accd to md
+ left_ctrl <= accd_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_add16;
+ if ea(1) = '1' then
+ cc_ctrl <= load_cc;
+ acca_ctrl <= load_hi_acca;
+ accb_ctrl <= load_accb;
+ else
+ cc_ctrl <= latch_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ end if;
+ md_ctrl <= shiftl_md;
+ -- idle bus
+ addr_ctrl <= idle_ad;
+ dout_ctrl <= md_lo_dout;
+ next_state <= mul2_state;
+
+ when mul2_state =>
+ -- default
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ pc_ctrl <= latch_pc;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- if bit 2 of ea set, add accd to md
+ left_ctrl <= accd_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_add16;
+ if ea(2) = '1' then
+ cc_ctrl <= load_cc;
+ acca_ctrl <= load_hi_acca;
+ accb_ctrl <= load_accb;
+ else
+ cc_ctrl <= latch_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ end if;
+ md_ctrl <= shiftl_md;
+ -- idle bus
+ addr_ctrl <= idle_ad;
+ dout_ctrl <= md_lo_dout;
+ next_state <= mul3_state;
+
+ when mul3_state =>
+ -- default
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ pc_ctrl <= latch_pc;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- if bit 3 of ea set, add accd to md
+ left_ctrl <= accd_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_add16;
+ if ea(3) = '1' then
+ cc_ctrl <= load_cc;
+ acca_ctrl <= load_hi_acca;
+ accb_ctrl <= load_accb;
+ else
+ cc_ctrl <= latch_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ end if;
+ md_ctrl <= shiftl_md;
+ -- idle bus
+ addr_ctrl <= idle_ad;
+ dout_ctrl <= md_lo_dout;
+ next_state <= mul4_state;
+
+ when mul4_state =>
+ -- default
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ pc_ctrl <= latch_pc;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- if bit 4 of ea set, add accd to md
+ left_ctrl <= accd_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_add16;
+ if ea(4) = '1' then
+ cc_ctrl <= load_cc;
+ acca_ctrl <= load_hi_acca;
+ accb_ctrl <= load_accb;
+ else
+ cc_ctrl <= latch_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ end if;
+ md_ctrl <= shiftl_md;
+ -- idle bus
+ addr_ctrl <= idle_ad;
+ dout_ctrl <= md_lo_dout;
+ next_state <= mul5_state;
+
+ when mul5_state =>
+ -- default
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ pc_ctrl <= latch_pc;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- if bit 5 of ea set, add accd to md
+ left_ctrl <= accd_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_add16;
+ if ea(5) = '1' then
+ cc_ctrl <= load_cc;
+ acca_ctrl <= load_hi_acca;
+ accb_ctrl <= load_accb;
+ else
+ cc_ctrl <= latch_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ end if;
+ md_ctrl <= shiftl_md;
+ -- idle bus
+ addr_ctrl <= idle_ad;
+ dout_ctrl <= md_lo_dout;
+ next_state <= mul6_state;
+
+ when mul6_state =>
+ -- default
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ pc_ctrl <= latch_pc;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- if bit 6 of ea set, add accd to md
+ left_ctrl <= accd_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_add16;
+ if ea(6) = '1' then
+ cc_ctrl <= load_cc;
+ acca_ctrl <= load_hi_acca;
+ accb_ctrl <= load_accb;
+ else
+ cc_ctrl <= latch_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ end if;
+ md_ctrl <= shiftl_md;
+ -- idle bus
+ addr_ctrl <= idle_ad;
+ dout_ctrl <= md_lo_dout;
+ next_state <= mul7_state;
+
+ when mul7_state =>
+ -- default
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ pc_ctrl <= latch_pc;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- if bit 7 of ea set, add accd to md
+ left_ctrl <= accd_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_add16;
+ if ea(7) = '1' then
+ cc_ctrl <= load_cc;
+ acca_ctrl <= load_hi_acca;
+ accb_ctrl <= load_accb;
+ else
+ cc_ctrl <= latch_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ end if;
+ md_ctrl <= shiftl_md;
+ -- idle bus
+ addr_ctrl <= idle_ad;
+ dout_ctrl <= md_lo_dout;
+ next_state <= fetch_state;
+
+ when execute_state => -- execute single operand instruction
+ -- default
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ case op_code(7 downto 4) is
+ when "0110" | -- indexed single op
+ "0111" => -- extended single op
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ pc_ctrl <= latch_pc;
+ iv_ctrl <= latch_iv;
+ ea_ctrl <= latch_ea;
+ -- idle the bus
+ addr_ctrl <= idle_ad;
+ dout_ctrl <= md_lo_dout;
+ left_ctrl <= md_left;
+ case op_code(3 downto 0) is
+ when "0000" => -- neg
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_neg;
+ cc_ctrl <= load_cc;
+ md_ctrl <= load_md;
+ next_state <= write8_state;
+ when "0011" => -- com
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_com;
+ cc_ctrl <= load_cc;
+ md_ctrl <= load_md;
+ next_state <= write8_state;
+ when "0100" => -- lsr
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_lsr8;
+ cc_ctrl <= load_cc;
+ md_ctrl <= load_md;
+ next_state <= write8_state;
+ when "0110" => -- ror
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_ror8;
+ cc_ctrl <= load_cc;
+ md_ctrl <= load_md;
+ next_state <= write8_state;
+ when "0111" => -- asr
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_asr8;
+ cc_ctrl <= load_cc;
+ md_ctrl <= load_md;
+ next_state <= write8_state;
+ when "1000" => -- asl
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_asl8;
+ cc_ctrl <= load_cc;
+ md_ctrl <= load_md;
+ next_state <= write8_state;
+ when "1001" => -- rol
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_rol8;
+ cc_ctrl <= load_cc;
+ md_ctrl <= load_md;
+ next_state <= write8_state;
+ when "1010" => -- dec
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_dec;
+ cc_ctrl <= load_cc;
+ md_ctrl <= load_md;
+ next_state <= write8_state;
+ when "1011" => -- undefined
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= latch_md;
+ next_state <= fetch_state;
+ when "1100" => -- inc
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_inc;
+ cc_ctrl <= load_cc;
+ md_ctrl <= load_md;
+ next_state <= write8_state;
+ when "1101" => -- tst
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_st8;
+ cc_ctrl <= load_cc;
+ md_ctrl <= latch_md;
+ next_state <= fetch_state;
+ when "1110" => -- jmp
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= latch_md;
+ next_state <= fetch_state;
+ when "1111" => -- clr
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_clr;
+ cc_ctrl <= load_cc;
+ md_ctrl <= load_md;
+ next_state <= write8_state;
+ when others =>
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ md_ctrl <= latch_md;
+ next_state <= fetch_state;
+ end case;
+
+ when others =>
+ left_ctrl <= accd_left;
+ right_ctrl <= md_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ ea_ctrl <= latch_ea;
+ -- idle the bus
+ addr_ctrl <= idle_ad;
+ dout_ctrl <= md_lo_dout;
+ next_state <= fetch_state;
+ end case;
+
+ when psha_state =>
+ -- default registers
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- decrement sp
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_sub16;
+ cc_ctrl <= latch_cc;
+ sp_ctrl <= load_sp;
+ -- write acca
+ addr_ctrl <= push_ad;
+ dout_ctrl <= acca_dout;
+ next_state <= fetch_state;
+
+ when pula_state =>
+ -- default registers
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- idle sp
+ left_ctrl <= sp_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ sp_ctrl <= latch_sp;
+ -- read acca
+ acca_ctrl <= pull_acca;
+ addr_ctrl <= pull_ad;
+ dout_ctrl <= acca_dout;
+ next_state <= fetch_state;
+
+ when pshb_state =>
+ -- default registers
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- decrement sp
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_sub16;
+ cc_ctrl <= latch_cc;
+ sp_ctrl <= load_sp;
+ -- write accb
+ addr_ctrl <= push_ad;
+ dout_ctrl <= accb_dout;
+ next_state <= fetch_state;
+
+ when pulb_state =>
+ -- default
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- idle sp
+ left_ctrl <= sp_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ sp_ctrl <= latch_sp;
+ -- read accb
+ accb_ctrl <= pull_accb;
+ addr_ctrl <= pull_ad;
+ dout_ctrl <= accb_dout;
+ next_state <= fetch_state;
+
+ when pshx_lo_state =>
+ -- default
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- decrement sp
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_sub16;
+ cc_ctrl <= latch_cc;
+ sp_ctrl <= load_sp;
+ -- write ix low
+ addr_ctrl <= push_ad;
+ dout_ctrl <= ix_lo_dout;
+ next_state <= pshx_hi_state;
+
+ when pshx_hi_state =>
+ -- default registers
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- decrement sp
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_sub16;
+ cc_ctrl <= latch_cc;
+ sp_ctrl <= load_sp;
+ -- write ix hi
+ addr_ctrl <= push_ad;
+ dout_ctrl <= ix_hi_dout;
+ next_state <= fetch_state;
+
+ when pulx_hi_state =>
+ -- default
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- increment sp
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_add16;
+ cc_ctrl <= latch_cc;
+ sp_ctrl <= load_sp;
+ -- pull ix hi
+ ix_ctrl <= pull_hi_ix;
+ addr_ctrl <= pull_ad;
+ dout_ctrl <= ix_hi_dout;
+ next_state <= pulx_lo_state;
+
+ when pulx_lo_state =>
+ -- default
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- idle sp
+ left_ctrl <= sp_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ sp_ctrl <= latch_sp;
+ -- read ix low
+ ix_ctrl <= pull_lo_ix;
+ addr_ctrl <= pull_ad;
+ dout_ctrl <= ix_lo_dout;
+ next_state <= fetch_state;
+
+ --
+ -- return from interrupt
+ -- enter here from bogus interrupts
+ --
+ when rti_state =>
+ -- default registers
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- increment sp
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_add16;
+ sp_ctrl <= load_sp;
+ -- idle address bus
+ cc_ctrl <= latch_cc;
+ addr_ctrl <= idle_ad;
+ dout_ctrl <= cc_dout;
+ next_state <= rti_cc_state;
+
+ when rti_cc_state =>
+ -- default registers
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- increment sp
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_add16;
+ sp_ctrl <= load_sp;
+ -- read cc
+ cc_ctrl <= pull_cc;
+ addr_ctrl <= pull_ad;
+ dout_ctrl <= cc_dout;
+ next_state <= rti_accb_state;
+
+ when rti_accb_state =>
+ -- default registers
+ acca_ctrl <= latch_acca;
+ ix_ctrl <= latch_ix;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- increment sp
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_add16;
+ cc_ctrl <= latch_cc;
+ sp_ctrl <= load_sp;
+ -- read accb
+ accb_ctrl <= pull_accb;
+ addr_ctrl <= pull_ad;
+ dout_ctrl <= accb_dout;
+ next_state <= rti_acca_state;
+
+ when rti_acca_state =>
+ -- default registers
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- increment sp
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_add16;
+ cc_ctrl <= latch_cc;
+ sp_ctrl <= load_sp;
+ -- read acca
+ acca_ctrl <= pull_acca;
+ addr_ctrl <= pull_ad;
+ dout_ctrl <= acca_dout;
+ next_state <= rti_ixh_state;
+
+ when rti_ixh_state =>
+ -- default
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- increment sp
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_add16;
+ cc_ctrl <= latch_cc;
+ sp_ctrl <= load_sp;
+ -- read ix hi
+ ix_ctrl <= pull_hi_ix;
+ addr_ctrl <= pull_ad;
+ dout_ctrl <= ix_hi_dout;
+ next_state <= rti_ixl_state;
+
+ when rti_ixl_state =>
+ -- default
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- increment sp
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_add16;
+ cc_ctrl <= latch_cc;
+ sp_ctrl <= load_sp;
+ -- read ix low
+ ix_ctrl <= pull_lo_ix;
+ addr_ctrl <= pull_ad;
+ dout_ctrl <= ix_lo_dout;
+ next_state <= rti_pch_state;
+
+ when rti_pch_state =>
+ -- default
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- increment sp
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_add16;
+ cc_ctrl <= latch_cc;
+ sp_ctrl <= load_sp;
+ -- pull pc hi
+ pc_ctrl <= pull_hi_pc;
+ addr_ctrl <= pull_ad;
+ dout_ctrl <= pc_hi_dout;
+ next_state <= rti_pcl_state;
+
+ when rti_pcl_state =>
+ -- default
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- idle sp
+ left_ctrl <= sp_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ sp_ctrl <= latch_sp;
+ -- pull pc low
+ pc_ctrl <= pull_lo_pc;
+ addr_ctrl <= pull_ad;
+ dout_ctrl <= pc_lo_dout;
+ next_state <= fetch_state;
+
+ --
+ -- here on interrupt
+ -- iv register hold interrupt type
+ --
+ when int_pcl_state =>
+ -- default
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- decrement sp
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_sub16;
+ cc_ctrl <= latch_cc;
+ sp_ctrl <= load_sp;
+ -- write pc low
+ addr_ctrl <= push_ad;
+ dout_ctrl <= pc_lo_dout;
+ next_state <= int_pch_state;
+
+ when int_pch_state =>
+ -- default
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- decrement sp
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_sub16;
+ cc_ctrl <= latch_cc;
+ sp_ctrl <= load_sp;
+ -- write pc hi
+ addr_ctrl <= push_ad;
+ dout_ctrl <= pc_hi_dout;
+ next_state <= int_ixl_state;
+
+ when int_ixl_state =>
+ -- default
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- decrement sp
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_sub16;
+ cc_ctrl <= latch_cc;
+ sp_ctrl <= load_sp;
+ -- write ix low
+ addr_ctrl <= push_ad;
+ dout_ctrl <= ix_lo_dout;
+ next_state <= int_ixh_state;
+
+ when int_ixh_state =>
+ -- default
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- decrement sp
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_sub16;
+ cc_ctrl <= latch_cc;
+ sp_ctrl <= load_sp;
+ -- write ix hi
+ addr_ctrl <= push_ad;
+ dout_ctrl <= ix_hi_dout;
+ next_state <= int_acca_state;
+
+ when int_acca_state =>
+ -- default
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- decrement sp
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_sub16;
+ cc_ctrl <= latch_cc;
+ sp_ctrl <= load_sp;
+ -- write acca
+ addr_ctrl <= push_ad;
+ dout_ctrl <= acca_dout;
+ next_state <= int_accb_state;
+
+
+ when int_accb_state =>
+ -- default
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- decrement sp
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_sub16;
+ cc_ctrl <= latch_cc;
+ sp_ctrl <= load_sp;
+ -- write accb
+ addr_ctrl <= push_ad;
+ dout_ctrl <= accb_dout;
+ next_state <= int_cc_state;
+
+ when int_cc_state =>
+ -- default
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- decrement sp
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_sub16;
+ cc_ctrl <= latch_cc;
+ sp_ctrl <= load_sp;
+ -- write cc
+ addr_ctrl <= push_ad;
+ dout_ctrl <= cc_dout;
+ nmi_ctrl <= latch_nmi;
+ --
+ -- nmi is edge triggered
+ -- nmi_req is cleared when nmi goes low.
+ --
+ if nmi_req = '1' then
+ iv_ctrl <= nmi_iv;
+ next_state <= vect_hi_state;
+ else
+ --
+ -- IRQ is level sensitive
+ --
+ if (irq = '1') and (cc(IBIT) = '0') then
+ iv_ctrl <= irq_iv;
+ next_state <= int_mask_state;
+ else
+ case op_code is
+ when "00111110" => -- WAI (wait for interrupt)
+ iv_ctrl <= latch_iv;
+ next_state <= int_wai_state;
+ when "00111111" => -- SWI (Software interrupt)
+ iv_ctrl <= swi_iv;
+ next_state <= vect_hi_state;
+ when others => -- bogus interrupt (return)
+ iv_ctrl <= latch_iv;
+ next_state <= rti_state;
+ end case;
+ end if;
+ end if;
+
+ when int_wai_state =>
+ -- default
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ op_ctrl <= latch_op;
+ ea_ctrl <= latch_ea;
+ -- enable interrupts
+ left_ctrl <= sp_left;
+ right_ctrl <= plus_one_right;
+ alu_ctrl <= alu_cli;
+ cc_ctrl <= load_cc;
+ sp_ctrl <= latch_sp;
+ -- idle bus
+ addr_ctrl <= idle_ad;
+ dout_ctrl <= cc_dout;
+ if (nmi_req = '1') and (nmi_ack='0') then
+ iv_ctrl <= nmi_iv;
+ nmi_ctrl <= set_nmi;
+ next_state <= vect_hi_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;
+ else
+ nmi_ctrl <= latch_nmi;
+ end if;
+ --
+ -- IRQ is level sensitive
+ --
+ if (irq = '1') and (cc(IBIT) = '0') then
+ iv_ctrl <= irq_iv;
+ next_state <= int_mask_state;
+ else
+ iv_ctrl <= latch_iv;
+ next_state <= int_wai_state;
+ end if;
+ end if;
+
+ when int_mask_state =>
+ -- default
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- Mask IRQ
+ left_ctrl <= sp_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_sei;
+ cc_ctrl <= load_cc;
+ sp_ctrl <= latch_sp;
+ -- idle bus cycle
+ addr_ctrl <= idle_ad;
+ dout_ctrl <= md_lo_dout;
+ next_state <= vect_hi_state;
+
+ when halt_state => -- halt CPU.
+ -- default
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- do nothing in ALU
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ -- idle bus cycle
+ addr_ctrl <= idle_ad;
+ dout_ctrl <= md_lo_dout;
+ if halt = '1' then
+ next_state <= halt_state;
+ else
+ next_state <= fetch_state;
+ end if;
+
+ when others => -- error state halt on undefine states
+ -- default
+ acca_ctrl <= latch_acca;
+ accb_ctrl <= latch_accb;
+ ix_ctrl <= latch_ix;
+ sp_ctrl <= latch_sp;
+ pc_ctrl <= latch_pc;
+ md_ctrl <= latch_md;
+ iv_ctrl <= latch_iv;
+ op_ctrl <= latch_op;
+ nmi_ctrl <= latch_nmi;
+ ea_ctrl <= latch_ea;
+ -- do nothing in ALU
+ left_ctrl <= acca_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_nop;
+ cc_ctrl <= latch_cc;
+ -- idle bus cycle
+ addr_ctrl <= idle_ad;
+ dout_ctrl <= md_lo_dout;
+ next_state <= error_state;
+ end case;
+end process;
+
+--------------------------------
+--
+-- state machine
+--
+--------------------------------
+
+change_state: process( clk, rst, state, hold )
+begin
+ if clk'event and clk = '0' then
+ if rst = '1' then
+ state <= reset_state;
+ elsif hold = '1' then
+ state <= state;
+ else
+ state <= next_state;
+ end if;
+ end if;
+end process;
+ -- output
+
+end CPU_ARCH;
diff --git a/common/CPU/68000/FX68k/Rom.sv b/common/CPU/68000/FX68k/Rom.sv
new file mode 100644
index 00000000..1b35c374
--- /dev/null
+++ b/common/CPU/68000/FX68k/Rom.sv
@@ -0,0 +1,28 @@
+//
+// microrom and nanorom instantiation
+//
+// There is bit of wasting of resources here. An extra registering pipeline happens that is not needed.
+// This is just for the purpose of helping inferring block RAM using pure generic code. Inferring RAM is important for performance.
+// Might be more efficient to use vendor specific features such as clock enable.
+//
+
+module uRom( input clk, input [UADDR_WIDTH-1:0] microAddr, output logic [UROM_WIDTH-1:0] microOutput);
+ reg [UROM_WIDTH-1:0] uRam[ UROM_DEPTH];
+ initial begin
+ $readmemb("microrom.mem", uRam);
+ end
+
+ always_ff @( posedge clk)
+ microOutput <= uRam[ microAddr];
+endmodule
+
+
+module nanoRom( input clk, input [NADDR_WIDTH-1:0] nanoAddr, output logic [NANO_WIDTH-1:0] nanoOutput);
+ reg [NANO_WIDTH-1:0] nRam[ NANO_DEPTH];
+ initial begin
+ $readmemb("nanorom.mem", nRam);
+ end
+
+ always_ff @( posedge clk)
+ nanoOutput <= nRam[ nanoAddr];
+endmodule
\ No newline at end of file
diff --git a/common/CPU/68000/FX68k/aluCorf.sv b/common/CPU/68000/FX68k/aluCorf.sv
new file mode 100644
index 00000000..d73bd08e
--- /dev/null
+++ b/common/CPU/68000/FX68k/aluCorf.sv
@@ -0,0 +1,35 @@
+// add bcd correction factor
+// It would be more efficient to merge add/sub with main ALU !!!
+module aluCorf( input [7:0] binResult, input bAdd, input cin, input hCarry,
+ output [7:0] bcdResult, output dC, output logic ov);
+
+ reg [8:0] htemp;
+ reg [4:0] hNib;
+
+ wire lowC = hCarry | (bAdd ? gt9( binResult[ 3:0]) : 1'b0);
+ wire highC = cin | (bAdd ? (gt9( htemp[7:4]) | htemp[8]) : 1'b0);
+
+ always_comb begin
+ if( bAdd) begin
+ htemp = { 1'b0, binResult} + (lowC ? 4'h6 : 4'h0);
+ hNib = htemp[8:4] + (highC ? 4'h6 : 4'h0);
+ ov = hNib[3] & ~binResult[7];
+ end
+ else begin
+ htemp = { 1'b0, binResult} - (lowC ? 4'h6 : 4'h0);
+ hNib = htemp[8:4] - (highC ? 4'h6 : 4'h0);
+ ov = ~hNib[3] & binResult[7];
+ end
+ end
+
+ assign bcdResult = { hNib[ 3:0], htemp[3:0]};
+ assign dC = hNib[4] | cin;
+
+ // Nibble > 9
+ function gt9 (input [3:0] nib);
+ begin
+ gt9 = nib[3] & (nib[2] | nib[1]);
+ end
+ endfunction
+
+endmodule
\ No newline at end of file
diff --git a/common/CPU/68000/FX68k/aluGetOp.sv b/common/CPU/68000/FX68k/aluGetOp.sv
new file mode 100644
index 00000000..8c779973
--- /dev/null
+++ b/common/CPU/68000/FX68k/aluGetOp.sv
@@ -0,0 +1,90 @@
+// Get current OP from row & col
+module aluGetOp( input [15:0] row, input [2:0] col, input isCorf,
+ output logic [4:0] aluOp);
+
+ always_comb begin
+ aluOp = 'X;
+ unique case( col)
+ 1: aluOp = OP_AND;
+ 5: aluOp = OP_EXT;
+
+ default:
+ unique case( 1'b1)
+ row[1]:
+ unique case( col)
+ 2: aluOp = OP_SUB;
+ 3: aluOp = OP_SUBC;
+ 4,6: aluOp = OP_SLAA;
+ endcase
+
+ row[2]:
+ unique case( col)
+ 2: aluOp = OP_ADD;
+ 3: aluOp = OP_ADDC;
+ 4: aluOp = OP_ASR;
+ endcase
+
+ row[3]:
+ unique case( col)
+ 2: aluOp = OP_ADDX;
+ 3: aluOp = isCorf ? OP_ABCD : OP_ADD;
+ 4: aluOp = OP_ASL;
+ endcase
+
+ row[4]:
+ aluOp = ( col == 4) ? OP_LSL : OP_AND;
+
+ row[5],
+ row[6]:
+ unique case( col)
+ 2: aluOp = OP_SUB;
+ 3: aluOp = OP_SUBC;
+ 4: aluOp = OP_LSR;
+ endcase
+
+ row[7]: // MUL
+ unique case( col)
+ 2: aluOp = OP_SUB;
+ 3: aluOp = OP_ADD;
+ 4: aluOp = OP_ROXR;
+ endcase
+
+ row[8]:
+ // OP_AND For EXT.L
+ // But would be more efficient to change ucode and use column 1 instead of col3 at ublock extr1!
+ unique case( col)
+ 2: aluOp = OP_EXT;
+ 3: aluOp = OP_AND;
+ 4: aluOp = OP_ROXR;
+ endcase
+
+ row[9]:
+ unique case( col)
+ 2: aluOp = OP_SUBX;
+ 3: aluOp = OP_SBCD;
+ 4: aluOp = OP_ROL;
+ endcase
+
+ row[10]:
+ unique case( col)
+ 2: aluOp = OP_SUBX;
+ 3: aluOp = OP_SUBC;
+ 4: aluOp = OP_ROR;
+ endcase
+
+ row[11]:
+ unique case( col)
+ 2: aluOp = OP_SUB0;
+ 3: aluOp = OP_SUB0;
+ 4: aluOp = OP_ROXL;
+ endcase
+
+ row[12]: aluOp = OP_ADDX;
+ row[13]: aluOp = OP_EOR;
+ row[14]: aluOp = (col == 4) ? OP_EOR : OP_OR;
+ row[15]: aluOp = (col == 3) ? OP_ADD : OP_OR; // OP_ADD used by DBcc
+
+ endcase
+ endcase
+ end
+endmodule
\ No newline at end of file
diff --git a/common/CPU/68000/FX68k/aluShifter.sv b/common/CPU/68000/FX68k/aluShifter.sv
new file mode 100644
index 00000000..c36d26eb
--- /dev/null
+++ b/common/CPU/68000/FX68k/aluShifter.sv
@@ -0,0 +1,32 @@
+module aluShifter( input [31:0] data,
+ input isByte, input isLong, swapWords,
+ input dir, input cin,
+ output logic [31:0] result);
+ // output reg cout
+
+ logic [31:0] tdata;
+
+ // size mux, put cin in position if dir == right
+ always_comb begin
+ tdata = data;
+ if( isByte & dir)
+ tdata[8] = cin;
+ else if( !isLong & dir)
+ tdata[16] = cin;
+ end
+
+ always_comb begin
+ // Reverse alu/alue position for MUL & DIV
+ // Result reversed again
+ if( swapWords & dir)
+ result = { tdata[0], tdata[31:17], cin, tdata[15:1]};
+ else if( swapWords)
+ result = { tdata[30:16], cin, tdata[14:0], tdata[31]};
+
+ else if( dir)
+ result = { cin, tdata[31:1]};
+ else
+ result = { tdata[30:0], cin};
+ end
+
+endmodule
\ No newline at end of file
diff --git a/common/CPU/68000/FX68k/busArbiter.sv b/common/CPU/68000/FX68k/busArbiter.sv
new file mode 100644
index 00000000..89bd2fb3
--- /dev/null
+++ b/common/CPU/68000/FX68k/busArbiter.sv
@@ -0,0 +1,87 @@
+//
+// DMA/BUS Arbitration
+//
+
+module busArbiter( input s_clks Clks,
+ input BRi, BgackI, Halti, bgBlock,
+ output busAvail,
+ output logic BGn);
+
+ enum int unsigned { DRESET = 0, DIDLE, D1, D_BR, D_BA, D_BRA, D3, D2} dmaPhase, next;
+
+ always_comb begin
+ case(dmaPhase)
+ DRESET: next = DIDLE;
+ DIDLE: begin
+ if( bgBlock)
+ next = DIDLE;
+ else if( ~BgackI)
+ next = D_BA;
+ else if( ~BRi)
+ next = D1;
+ else
+ next = DIDLE;
+ end
+
+ D_BA: begin // Loop while only BGACK asserted, BG negated here
+ if( ~BRi & !bgBlock)
+ next = D3;
+ else if( ~BgackI & !bgBlock)
+ next = D_BA;
+ else
+ next = DIDLE;
+ end
+
+ D1: next = D_BR; // Loop while only BR asserted
+ D_BR: next = ~BRi & BgackI ? D_BR : D_BA; // No direct path to IDLE !
+
+ D3: next = D_BRA;
+ D_BRA: begin // Loop while both BR and BGACK asserted
+ case( {BgackI, BRi} )
+ 2'b11: next = DIDLE; // Both deasserted
+ 2'b10: next = D_BR; // BR asserted only
+ 2'b01: next = D2; // BGACK asserted only
+ 2'b00: next = D_BRA; // Stay here while both asserted
+ endcase
+ end
+
+ // Might loop here if both deasserted, should normally don't arrive here anyway?
+ // D2: next = (BgackI & BRi) | bgBlock ? D2: D_BA;
+
+ D2: next = D_BA;
+
+ default: next = DIDLE; // Should not reach here normally
+ endcase
+ end
+
+ logic granting;
+ always_comb begin
+ unique case( next)
+ D1, D3, D_BR, D_BRA: granting = 1'b1;
+ default: granting = 1'b0;
+ endcase
+ end
+
+ reg rGranted;
+ assign busAvail = Halti & BRi & BgackI & ~rGranted;
+
+ always_ff @( posedge Clks.clk) begin
+ if( Clks.extReset) begin
+ dmaPhase <= DRESET;
+ rGranted <= 1'b0;
+ end
+ else if( Clks.enPhi2) begin
+ dmaPhase <= next;
+ // Internal signal changed on PHI2
+ rGranted <= granting;
+ end
+
+ // External Output changed on PHI1
+ if( Clks.extReset)
+ BGn <= 1'b1;
+ else if( Clks.enPhi1)
+ BGn <= ~rGranted;
+
+ end
+
+endmodule
\ No newline at end of file
diff --git a/common/CPU/68000/FX68k/busControl.sv b/common/CPU/68000/FX68k/busControl.sv
new file mode 100644
index 00000000..8236fbd7
--- /dev/null
+++ b/common/CPU/68000/FX68k/busControl.sv
@@ -0,0 +1,197 @@
+module busControl( input s_clks Clks, input enT1, input enT4,
+ input permStart, permStop, iStop,
+ input aob0,
+ input isWrite, isByte, isRmc,
+ input busAvail,
+ output bgBlock,
+ output busAddrErr,
+ output waitBusCycle,
+ output busStarting, // Asserted during S0
+ output logic addrOe, // Asserted from S1 to the end, whole bus cycle except S0
+ output bciWrite, // Used for SSW on bus/addr error
+
+ input rDtack, BeDebounced, Vpai,
+ output ASn, output LDSn, output UDSn, eRWn);
+
+ reg rAS, rLDS, rUDS, rRWn;
+ assign ASn = rAS;
+ assign LDSn = rLDS;
+ assign UDSn = rUDS;
+ assign eRWn = rRWn;
+
+ reg dataOe;
+
+ reg bcPend;
+ reg isWriteReg, bciByte, isRmcReg, wendReg;
+ assign bciWrite = isWriteReg;
+ reg addrOeDelay;
+ reg isByteT4;
+
+ wire canStart, busEnd;
+ wire bcComplete, bcReset;
+
+ wire isRcmReset = bcComplete & bcReset & isRmcReg;
+
+ assign busAddrErr = aob0 & ~bciByte;
+
+ // Bus retry not really supported.
+ // It's BERR and HALT and not address error, and not read-modify cycle.
+ wire busRetry = ~busAddrErr & 1'b0;
+
+ enum int unsigned { SRESET = 0, SIDLE, S0, S2, S4, S6, SRMC_RES} busPhase, next;
+
+ always_ff @( posedge Clks.clk) begin
+ if( Clks.extReset)
+ busPhase <= SRESET;
+ else if( Clks.enPhi1)
+ busPhase <= next;
+ end
+
+ always_comb begin
+ case( busPhase)
+ SRESET: next = SIDLE;
+ SRMC_RES: next = SIDLE; // Single cycle special state when read phase of RMC reset
+ S0: next = S2;
+ S2: next = S4;
+ S4: next = busEnd ? S6 : S4;
+ S6: next = isRcmReset ? SRMC_RES : (canStart ? S0 : SIDLE);
+ SIDLE: next = canStart ? S0 : SIDLE;
+ default: next = SIDLE;
+ endcase
+ end
+
+ // Idle phase of RMC bus cycle. Might be better to just add a new state
+ wire rmcIdle = (busPhase == SIDLE) & ~ASn & isRmcReg;
+
+ assign canStart = (busAvail | rmcIdle) & (bcPend | permStart) & !busRetry & !bcReset;
+
+ wire busEnding = (next == SIDLE) | (next == S0);
+
+ assign busStarting = (busPhase == S0);
+
+ // term signal (DTACK, BERR, VPA, adress error)
+ assign busEnd = ~rDtack | iStop;
+
+ // bcComplete asserted on raising edge of S6 (together with SNC).
+ assign bcComplete = (busPhase == S6);
+
+ // Clear bus info latch on completion (regular or aborted) and no bus retry (and not PHI1).
+ // bciClear asserted half clock later on PHI2, and bci latches cleared async concurrently
+ wire bciClear = bcComplete & ~busRetry;
+
+ // Reset on reset or (berr & berrDelay & (not halt or rmc) & not 6800 & in bus cycle) (and not PHI1)
+ assign bcReset = Clks.extReset | (addrOeDelay & BeDebounced & Vpai);
+
+ // Enable uclock only on S6 (S8 on Bus Error) or not bciPermStop
+ assign waitBusCycle = wendReg & !bcComplete;
+
+ // Block Bus Grant when starting new bus cycle. But No need if AS already asserted (read phase of RMC)
+ // Except that when that RMC phase aborted on bus error, it's asserted one cycle later!
+ assign bgBlock = ((busPhase == S0) & ASn) | (busPhase == SRMC_RES);
+
+ always_ff @( posedge Clks.clk) begin
+ if( Clks.extReset) begin
+ addrOe <= 1'b0;
+ end
+ else if( Clks.enPhi2 & ( busPhase == S0)) // From S1, whole bus cycle except S0
+ addrOe <= 1'b1;
+ else if( Clks.enPhi1 & (busPhase == SRMC_RES))
+ addrOe <= 1'b0;
+ else if( Clks.enPhi1 & ~isRmcReg & busEnding)
+ addrOe <= 1'b0;
+
+ if( Clks.enPhi1)
+ addrOeDelay <= addrOe;
+
+ if( Clks.extReset) begin
+ rAS <= 1'b1;
+ rUDS <= 1'b1;
+ rLDS <= 1'b1;
+ rRWn <= 1'b1;
+ dataOe <= '0;
+ end
+ else begin
+
+ if( Clks.enPhi2 & isWriteReg & (busPhase == S2))
+ dataOe <= 1'b1;
+ else if( Clks.enPhi1 & (busEnding | (busPhase == SIDLE)) )
+ dataOe <= 1'b0;
+
+ if( Clks.enPhi1 & busEnding)
+ rRWn <= 1'b1;
+ else if( Clks.enPhi1 & isWriteReg) begin
+ // Unlike LDS/UDS Asserted even in address error
+ if( (busPhase == S0) & isWriteReg)
+ rRWn <= 1'b0;
+ end
+
+ // AS. Actually follows addrOe half cycle later!
+ if( Clks.enPhi1 & (busPhase == S0))
+ rAS <= 1'b0;
+ else if( Clks.enPhi2 & (busPhase == SRMC_RES)) // Bus error on read phase of RMC. Deasserted one cycle later
+ rAS <= 1'b1;
+ else if( Clks.enPhi2 & bcComplete & ~SRMC_RES)
+ if( ~isRmcReg) // Keep AS asserted on the IDLE phase of RMC
+ rAS <= 1'b1;
+
+ if( Clks.enPhi1 & (busPhase == S0)) begin
+ if( ~isWriteReg & !busAddrErr) begin
+ rUDS <= ~(~bciByte | ~aob0);
+ rLDS <= ~(~bciByte | aob0);
+ end
+ end
+ else if( Clks.enPhi1 & isWriteReg & (busPhase == S2) & !busAddrErr) begin
+ rUDS <= ~(~bciByte | ~aob0);
+ rLDS <= ~(~bciByte | aob0);
+ end
+ else if( Clks.enPhi2 & bcComplete) begin
+ rUDS <= 1'b1;
+ rLDS <= 1'b1;
+ end
+
+ end
+
+ end
+
+ // Bus cycle info latch. Needed because uinstr might change if the bus is busy and we must wait.
+ // Note that urom advances even on wait states. It waits *after* updating urom and nanorom latches.
+ // Even without wait states, ublocks of type ir (init reading) will not wait for bus completion.
+ // Originally latched on (permStart AND T1).
+
+ // Bus cycle info latch: isRead, isByte, read-modify-cycle, and permStart (bus cycle pending). Some previously latched on T4?
+ // permStop also latched, but unconditionally on T1
+
+ // Might make more sense to register this outside this module
+ always_ff @( posedge Clks.clk) begin
+ if( enT4) begin
+ isByteT4 <= isByte;
+ end
+ end
+
+ // Bus Cycle Info Latch
+ always_ff @( posedge Clks.clk) begin
+ if( Clks.pwrUp) begin
+ bcPend <= 1'b0;
+ wendReg <= 1'b0;
+ isWriteReg <= 1'b0;
+ bciByte <= 1'b0;
+ isRmcReg <= 1'b0;
+ end
+
+ else if( Clks.enPhi2 & (bciClear | bcReset)) begin
+ bcPend <= 1'b0;
+ wendReg <= 1'b0;
+ end
+ else begin
+ if( enT1 & permStart) begin
+ isWriteReg <= isWrite;
+ bciByte <= isByteT4;
+ isRmcReg <= isRmc & ~isWrite; // We need special case the end of the read phase only.
+ bcPend <= 1'b1;
+ end
+ if( enT1)
+ wendReg <= permStop;
+ end
+ end
+
+endmodule
\ No newline at end of file
diff --git a/common/CPU/68000/FX68k/ccrTable.sv b/common/CPU/68000/FX68k/ccrTable.sv
new file mode 100644
index 00000000..b50f822f
--- /dev/null
+++ b/common/CPU/68000/FX68k/ccrTable.sv
@@ -0,0 +1,76 @@
+// Row/col CCR update table
+module ccrTable(
+ input [2:0] col, input [15:0] row, input finish,
+ output logic [MASK_NBITS-1:0] ccrMask);
+
+ localparam
+ KNZ00 = 5'b01111, // ok coz operators clear them
+ KKZKK = 5'b00100,
+ KNZKK = 5'b01100,
+ KNZ10 = 5'b01111, // Used by OP_EXT on divison overflow
+ KNZ0C = 5'b01111, // Used by DIV. V should be 0, but it is ok:
+ // DIVU: ends with quotient - 0, so V & C always clear.
+ // DIVS: ends with 1i (AND), again, V & C always clear.
+
+ KNZVC = 5'b01111,
+ CUPDALL = 5'b11111,
+ CUNUSED = 5'bxxxxx;
+
+
+ logic [MASK_NBITS-1:0] ccrMask1;
+
+ always_comb begin
+ unique case( col)
+ 1: ccrMask = ccrMask1;
+
+ 2,3:
+ unique case( 1'b1)
+ row[1]: ccrMask = KNZ0C; // DIV, used as 3n in col3
+ row[2],
+ row[3], // ABCD
+ row[5],
+ row[9], // SBCD/NBCD
+ row[10], // SUBX/NEGX
+ row[12]: ccrMask = CUPDALL; // ADDX
+ row[6], // CMP
+ row[7], // MUL
+ row[11]: ccrMask = KNZVC; // NOT
+ row[4],
+ row[8], // Not used in col 3
+ row[13],
+ row[14]: ccrMask = KNZ00;
+ row[15]: ccrMask = 5'b0; // TAS/Scc, not used in col 3
+ // default: ccrMask = CUNUSED;
+ endcase
+
+ 4:
+ unique case( row)
+ // 1: DIV, only n (4n & 6n)
+ // 14: BCLR 4n
+ // 6,12,13,15 // not used
+ `ALU_ROW_02,
+ `ALU_ROW_03, // ASL (originally ANZVA)
+ `ALU_ROW_04,
+ `ALU_ROW_05: ccrMask = CUPDALL; // Shifts (originally ANZ0A)
+
+ `ALU_ROW_07: ccrMask = KNZ00; // MUL (originally KNZ0A)
+ `ALU_ROW_09,
+ `ALU_ROW_10: ccrMask = KNZ00; // RO[lr] (originally KNZ0A)
+ `ALU_ROW_11: ccrMask = CUPDALL; // ROXL (originally ANZ0A)
+ default: ccrMask = CUNUSED;
+ endcase
+
+ 5: ccrMask = row[1] ? KNZ10 : 5'b0;
+ default: ccrMask = CUNUSED;
+ endcase
+ end
+
+ // Column 1 (AND)
+ always_comb begin
+ if( finish)
+ ccrMask1 = row[7] ? KNZ00 : KNZKK;
+ else
+ ccrMask1 = row[13] | row[14] ? KKZKK : KNZ00;
+ end
+
+endmodule
\ No newline at end of file
diff --git a/common/CPU/68000/FX68k/dataIo.sv b/common/CPU/68000/FX68k/dataIo.sv
new file mode 100644
index 00000000..c20f36d3
--- /dev/null
+++ b/common/CPU/68000/FX68k/dataIo.sv
@@ -0,0 +1,97 @@
+//
+// Data bus I/O
+// At a separate module because it is a bit complicated and the timing is special.
+// Here we do the low/high byte mux and the special case of MOVEP.
+//
+// Original implementation is rather complex because both the internal and external buses are bidirectional.
+// Input is latched async at the EDB register.
+// We capture directly from the external data bus to the internal registers (IRC & DBIN) on PHI2, starting the external S7 phase, at a T4 internal period.
+
+module dataIo( input s_clks Clks,
+ input enT1, enT2, enT3, enT4,
+ input s_nanod Nanod, input s_irdecod Irdecod,
+ input [15:0] iEdb,
+ input aob0,
+
+ input dobIdle,
+ input [15:0] dobInput,
+
+ output logic [15:0] Irc,
+ output logic [15:0] dbin,
+ output logic [15:0] oEdb
+ );
+
+ reg [15:0] dob;
+
+ // DBIN/IRC
+
+ // Timing is different than any other register. We can latch only on the next T4 (bus phase S7).
+ // We need to register all control signals correctly because the next ublock will already be started.
+ // Can't latch control on T4 because if there are wait states there might be multiple T4 before we latch.
+
+ reg xToDbin, xToIrc;
+ reg dbinNoLow, dbinNoHigh;
+ reg byteMux, isByte_T4;
+
+ always_ff @( posedge Clks.clk) begin
+
+ // Byte mux control. Can't latch at T1. AOB might be not ready yet.
+ // Must latch IRD decode at T1 (or T4). Then combine and latch only at T3.
+
+ // Can't latch at T3, a new IRD might be loaded already at T1.
+ // Ok to latch at T4 if combination latched then at T3
+ if( enT4)
+ isByte_T4 <= Irdecod.isByte; // Includes MOVEP from mem, we could OR it here
+
+ if( enT3) begin
+ dbinNoHigh <= Nanod.noHighByte;
+ dbinNoLow <= Nanod.noLowByte;
+ byteMux <= Nanod.busByte & isByte_T4 & ~aob0;
+ end
+
+ if( enT1) begin
+ // If on wait states, we continue latching until next T1
+ xToDbin <= 1'b0;
+ xToIrc <= 1'b0;
+ end
+ else if( enT3) begin
+ xToDbin <= Nanod.todbin;
+ xToIrc <= Nanod.toIrc;
+ end
+
+ // Capture on T4 of the next ucycle
+ // If there are wait states, we keep capturing every PHI2 until the next T1
+
+ if( xToIrc & Clks.enPhi2)
+ Irc <= iEdb;
+ if( xToDbin & Clks.enPhi2) begin
+ // Original connects both halves of EDB.
+ if( ~dbinNoLow)
+ dbin[ 7:0] <= byteMux ? iEdb[ 15:8] : iEdb[7:0];
+ if( ~dbinNoHigh)
+ dbin[ 15:8] <= ~byteMux & dbinNoLow ? iEdb[ 7:0] : iEdb[ 15:8];
+ end
+ end
+
+ // DOB
+ logic byteCycle;
+
+ always_ff @( posedge Clks.clk) begin
+ // Originaly on T1. Transfer to internal EDB also on T1 (stays enabled upto the next T1). But only on T4 (S3) output enables.
+ // It is safe to do on T3, then, but control signals if derived from IRD must be registered.
+ // Originally control signals are not registered.
+
+ // Wait states don't affect DOB operation that is done at the start of the bus cycle.
+
+ if( enT4)
+ byteCycle <= Nanod.busByte & Irdecod.isByte; // busIsByte but not MOVEP
+
+ // Originally byte low/high interconnect is done at EDB, not at DOB.
+ if( enT3 & ~dobIdle) begin
+ dob[7:0] <= Nanod.noLowByte ? dobInput[15:8] : dobInput[ 7:0];
+ dob[15:8] <= (byteCycle | Nanod.noHighByte) ? dobInput[ 7:0] : dobInput[15:8];
+ end
+ end
+ assign oEdb = dob;
+
+endmodule
\ No newline at end of file
diff --git a/common/CPU/68000/FX68k/excUnit.sv b/common/CPU/68000/FX68k/excUnit.sv
new file mode 100644
index 00000000..b42b4616
--- /dev/null
+++ b/common/CPU/68000/FX68k/excUnit.sv
@@ -0,0 +1,553 @@
+/*
+ Execution unit
+
+ Executes register transfers set by the microcode. Originally through a set of bidirectional buses.
+ Most sources are available at T3, but DBIN only at T4! CCR also might be updated at T4, but it is not connected to these buses.
+ We mux at T1 and T2, then transfer to the destination at T3. The exception is AOB that need to be updated earlier.
+
+*/
+
+module excUnit( input s_clks Clks,
+ input enT1, enT2, enT3, enT4,
+ input s_nanod Nanod, input s_irdecod Irdecod,
+ input [15:0] Ird, // ALU row (and others) decoder needs it
+ input pswS,
+ input [15:0] ftu,
+ input [15:0] iEdb,
+
+ output logic [7:0] ccr,
+ output [15:0] alue,
+
+ output prenEmpty, au05z,
+ output logic dcr4, ze,
+ output logic aob0,
+ output [15:0] AblOut,
+ output logic [15:0] Irc,
+ output logic [15:0] oEdb,
+ output logic [23:1] eab);
+
+localparam REG_USP = 15;
+localparam REG_SSP = 16;
+localparam REG_DT = 17;
+
+ // Register file
+ reg [15:0] regs68L[ 18];
+ reg [15:0] regs68H[ 18];
+
+// synthesis translate off
+ /*
+ It is bad practice to initialize simulation registers that the hardware doesn't.
+ There is risk that simulation would be different than the real hardware. But in this case is the other way around.
+ Some ROM uses something like sub.l An,An at powerup which clears the register
+ Simulator power ups the registers with 'X, as they are really undetermined at the real hardware.
+ But the simulator doesn't realize (it can't) that the same value is substracting from itself,
+ and that the result should be zero even when it's 'X - 'X.
+ */
+
+ initial begin
+ for( int i = 0; i < 18; i++) begin
+ regs68L[i] <= '0;
+ regs68H[i] <= '0;
+ end
+ end
+
+ // For simulation display only
+ wire [31:0] SSP = { regs68H[REG_SSP], regs68L[REG_SSP]};
+
+// synthesis translate on
+
+
+ wire [15:0] aluOut;
+ wire [15:0] dbin;
+ logic [15:0] dcrOutput;
+
+ reg [15:0] PcL, PcH;
+
+ reg [31:0] auReg, aob;
+
+ reg [15:0] Ath, Atl;
+
+ // Bus execution
+ reg [15:0] Dbl, Dbh;
+ reg [15:0] Abh, Abl;
+ reg [15:0] Abd, Dbd;
+
+ assign AblOut = Abl;
+ assign au05z = (~| auReg[5:0]);
+
+ logic [15:0] dblMux, dbhMux;
+ logic [15:0] abhMux, ablMux;
+ logic [15:0] abdMux, dbdMux;
+
+ logic abdIsByte;
+
+ logic Pcl2Dbl, Pch2Dbh;
+ logic Pcl2Abl, Pch2Abh;
+
+
+ // RX RY muxes
+ // RX and RY actual registers
+ logic [4:0] actualRx, actualRy;
+ logic [3:0] movemRx;
+ logic byteNotSpAlign; // Byte instruction and no sp word align
+
+ // IRD decoded signals must be latched. See comments on decoder
+ // But nanostore decoding can't be latched before T4.
+ //
+ // If we need this earlier we can register IRD decode on T3 and use nano async
+
+ logic [4:0] rxMux, ryMux;
+ logic [3:0] rxReg, ryReg;
+ logic rxIsSp, ryIsSp;
+ logic rxIsAreg, ryIsAreg;
+
+ always_comb begin
+
+ // Unique IF !!
+ if( Nanod.ssp) begin
+ rxMux = REG_SSP;
+ rxIsSp = 1'b1;
+ rxReg = 1'bX;
+ end
+ else if( Irdecod.rxIsUsp) begin
+ rxMux = REG_USP;
+ rxIsSp = 1'b1;
+ rxReg = 1'bX;
+ end
+ else if( Irdecod.rxIsDt & !Irdecod.implicitSp) begin
+ rxMux = REG_DT;
+ rxIsSp = 1'b0;
+ rxReg = 1'bX;
+ end
+ else begin
+ if( Irdecod.implicitSp)
+ rxReg = 15;
+ else if( Irdecod.rxIsMovem)
+ rxReg = movemRx;
+ else
+ rxReg = { Irdecod.rxIsAreg, Irdecod.rx};
+
+ if( (& rxReg)) begin
+ rxMux = pswS ? REG_SSP : 15;
+ rxIsSp = 1'b1;
+ end
+ else begin
+ rxMux = { 1'b0, rxReg};
+ rxIsSp = 1'b0;
+ end
+ end
+
+ // RZ has higher priority!
+ if( Irdecod.ryIsDt & !Nanod.rz) begin
+ ryMux = REG_DT;
+ ryIsSp = 1'b0;
+ ryReg = 'X;
+ end
+ else begin
+ ryReg = Nanod.rz ? Irc[15:12] : {Irdecod.ryIsAreg, Irdecod.ry};
+ ryIsSp = (& ryReg);
+ if( ryIsSp & pswS) // No implicit SP on RY
+ ryMux = REG_SSP;
+ else
+ ryMux = { 1'b0, ryReg};
+ end
+
+ end
+
+ always_ff @( posedge Clks.clk) begin
+ if( enT4) begin
+ byteNotSpAlign <= Irdecod.isByte & ~(Nanod.rxlDbl ? rxIsSp : ryIsSp);
+
+ actualRx <= rxMux;
+ actualRy <= ryMux;
+
+ rxIsAreg <= rxIsSp | rxMux[3];
+ ryIsAreg <= ryIsSp | ryMux[3];
+ end
+
+ if( enT4)
+ abdIsByte <= Nanod.abdIsByte & Irdecod.isByte;
+ end
+
+ // Set RX/RY low word to which bus segment is connected.
+
+ wire ryl2Abl = Nanod.ryl2ab & (ryIsAreg | Nanod.ablAbd);
+ wire ryl2Abd = Nanod.ryl2ab & (~ryIsAreg | Nanod.ablAbd);
+ wire ryl2Dbl = Nanod.ryl2db & (ryIsAreg | Nanod.dblDbd);
+ wire ryl2Dbd = Nanod.ryl2db & (~ryIsAreg | Nanod.dblDbd);
+
+ wire rxl2Abl = Nanod.rxl2ab & (rxIsAreg | Nanod.ablAbd);
+ wire rxl2Abd = Nanod.rxl2ab & (~rxIsAreg | Nanod.ablAbd);
+ wire rxl2Dbl = Nanod.rxl2db & (rxIsAreg | Nanod.dblDbd);
+ wire rxl2Dbd = Nanod.rxl2db & (~rxIsAreg | Nanod.dblDbd);
+
+ // Buses. Main mux
+
+ logic abhIdle, ablIdle, abdIdle;
+ logic dbhIdle, dblIdle, dbdIdle;
+
+ always_comb begin
+ {abhIdle, ablIdle, abdIdle} = '0;
+ {dbhIdle, dblIdle, dbdIdle} = '0;
+
+ unique case( 1'b1)
+ ryl2Dbd: dbdMux = regs68L[ actualRy];
+ rxl2Dbd: dbdMux = regs68L[ actualRx];
+ Nanod.alue2Dbd: dbdMux = alue;
+ Nanod.dbin2Dbd: dbdMux = dbin;
+ Nanod.alu2Dbd: dbdMux = aluOut;
+ Nanod.dcr2Dbd: dbdMux = dcrOutput;
+ default: begin dbdMux = 'X; dbdIdle = 1'b1; end
+ endcase
+
+ unique case( 1'b1)
+ rxl2Dbl: dblMux = regs68L[ actualRx];
+ ryl2Dbl: dblMux = regs68L[ actualRy];
+ Nanod.ftu2Dbl: dblMux = ftu;
+ Nanod.au2Db: dblMux = auReg[15:0];
+ Nanod.atl2Dbl: dblMux = Atl;
+ Pcl2Dbl: dblMux = PcL;
+ default: begin dblMux = 'X; dblIdle = 1'b1; end
+ endcase
+
+ unique case( 1'b1)
+ Nanod.rxh2dbh: dbhMux = regs68H[ actualRx];
+ Nanod.ryh2dbh: dbhMux = regs68H[ actualRy];
+ Nanod.au2Db: dbhMux = auReg[31:16];
+ Nanod.ath2Dbh: dbhMux = Ath;
+ Pch2Dbh: dbhMux = PcH;
+ default: begin dbhMux = 'X; dbhIdle = 1'b1; end
+ endcase
+
+ unique case( 1'b1)
+ ryl2Abd: abdMux = regs68L[ actualRy];
+ rxl2Abd: abdMux = regs68L[ actualRx];
+ Nanod.dbin2Abd: abdMux = dbin;
+ Nanod.alu2Abd: abdMux = aluOut;
+ default: begin abdMux = 'X; abdIdle = 1'b1; end
+ endcase
+
+ unique case( 1'b1)
+ Pcl2Abl: ablMux = PcL;
+ rxl2Abl: ablMux = regs68L[ actualRx];
+ ryl2Abl: ablMux = regs68L[ actualRy];
+ Nanod.ftu2Abl: ablMux = ftu;
+ Nanod.au2Ab: ablMux = auReg[15:0];
+ Nanod.aob2Ab: ablMux = aob[15:0];
+ Nanod.atl2Abl: ablMux = Atl;
+ default: begin ablMux = 'X; ablIdle = 1'b1; end
+ endcase
+
+ unique case( 1'b1)
+ Pch2Abh: abhMux = PcH;
+ Nanod.rxh2abh: abhMux = regs68H[ actualRx];
+ Nanod.ryh2abh: abhMux = regs68H[ actualRy];
+ Nanod.au2Ab: abhMux = auReg[31:16];
+ Nanod.aob2Ab: abhMux = aob[31:16];
+ Nanod.ath2Abh: abhMux = Ath;
+ default: begin abhMux = 'X; abhIdle = 1'b1; end
+ endcase
+
+ end
+
+ // Source starts driving the bus on T1. Bus holds data until end of T3. Destination latches at T3.
+
+ // These registers store the first level mux, without bus interconnections.
+ // Even when this uses almost to 100 registers, it saves a lot of comb muxing and it is much faster.
+ reg [15:0] preAbh, preAbl, preAbd;
+ reg [15:0] preDbh, preDbl, preDbd;
+
+ always_ff @( posedge Clks.clk) begin
+
+ // Register first level mux at T1
+ if( enT1) begin
+ {preAbh, preAbl, preAbd} <= { abhMux, ablMux, abdMux};
+ {preDbh, preDbl, preDbd} <= { dbhMux, dblMux, dbdMux};
+ end
+
+ // Process bus interconnection at T2. Many combinations only used on DIV
+ // We use a simple method. If a specific bus segment is not driven we know that it should get data from a neighbour segment.
+ // In some cases this is not true and the segment is really idle without any destination. But then it doesn't matter.
+
+ if( enT2) begin
+ if( Nanod.extAbh)
+ Abh <= { 16{ ablIdle ? preAbd[ 15] : preAbl[ 15] }};
+ else if( abhIdle)
+ Abh <= ablIdle ? preAbd : preAbl;
+ else
+ Abh <= preAbh;
+
+ if( ~ablIdle)
+ Abl <= preAbl;
+ else
+ Abl <= Nanod.ablAbh ? preAbh : preAbd;
+
+ Abd <= ~abdIdle ? preAbd : ablIdle ? preAbh : preAbl;
+
+ if( Nanod.extDbh)
+ Dbh <= { 16{ dblIdle ? preDbd[ 15] : preDbl[ 15] }};
+ else if( dbhIdle)
+ Dbh <= dblIdle ? preDbd : preDbl;
+ else
+ Dbh <= preDbh;
+
+ if( ~dblIdle)
+ Dbl <= preDbl;
+ else
+ Dbl <= Nanod.dblDbh ? preDbh : preDbd;
+
+ Dbd <= ~dbdIdle ? preDbd: dblIdle ? preDbh : preDbl;
+
+ /*
+ Dbl <= dblMux; Dbh <= dbhMux;
+ Abd <= abdMux; Dbd <= dbdMux;
+ Abh <= abhMux; Abl <= ablMux; */
+ end
+ end
+
+ // AOB
+ //
+ // Originally change on T1. We do on T2, only then the output is enabled anyway.
+ //
+ // AOB[0] is used for address error. But even when raises on T1, seems not actually used until T2 or possibly T3.
+ // It is used on T1 when deasserted at the BSER exception ucode. Probably deassertion timing is not critical.
+ // But in that case (at BSER), AOB is loaded from AU, so we can safely transfer on T1.
+
+ // We need to take directly from first level muxes that are updated and T1
+
+ wire au2Aob = Nanod.au2Aob | (Nanod.au2Db & Nanod.db2Aob);
+
+ always_ff @( posedge Clks.clk) begin
+ // UNIQUE IF !
+
+ if( enT1 & au2Aob) // From AU we do can on T1
+ aob <= auReg;
+ else if( enT2) begin
+ if( Nanod.db2Aob)
+ aob <= { preDbh, ~dblIdle ? preDbl : preDbd};
+ else if( Nanod.ab2Aob)
+ aob <= { preAbh, ~ablIdle ? preAbl : preAbd};
+ end
+ end
+
+ assign eab = aob[23:1];
+ assign aob0 = aob[0];
+
+ // AU
+ logic [31:0] auInpMux;
+
+ // `ifdef ALW_COMB_BUG
+ // Old Modelsim bug. Doesn't update ouput always. Need excplicit sensitivity list !?
+ // always @( Nanod.auCntrl) begin
+
+ always_comb begin
+ unique case( Nanod.auCntrl)
+ 3'b000: auInpMux = 0;
+ 3'b001: auInpMux = byteNotSpAlign | Nanod.noSpAlign ? 1 : 2; // +1/+2
+ 3'b010: auInpMux = -4;
+ 3'b011: auInpMux = { Abh, Abl};
+ 3'b100: auInpMux = 2;
+ 3'b101: auInpMux = 4;
+ 3'b110: auInpMux = -2;
+ 3'b111: auInpMux = byteNotSpAlign | Nanod.noSpAlign ? -1 : -2; // -1/-2
+ default: auInpMux = 'X;
+ endcase
+ end
+
+ // Simulation problem
+ // Sometimes (like in MULM1) DBH is not set. AU is used in these cases just as a 6 bits counter testing if bits 5-0 are zero.
+ // But when adding something like 32'hXXXX0000, the simulator (incorrectly) will set *all the 32 bits* of the result as X.
+
+// synthesis translate_off
+ `define SIMULBUGX32 1
+ wire [16:0] aulow = Dbl + auInpMux[15:0];
+ wire [31:0] auResult = {Dbh + auInpMux[31:16] + aulow[16], aulow[15:0]};
+// synthesis translate_on
+
+ always_ff @( posedge Clks.clk) begin
+ if( Clks.pwrUp)
+ auReg <= '0;
+ else if( enT3 & Nanod.auClkEn)
+ `ifdef SIMULBUGX32
+ auReg <= auResult;
+ `else
+ auReg <= { Dbh, Dbl } + auInpMux;
+ `endif
+ end
+
+
+ // Main A/D registers
+
+ always_ff @( posedge Clks.clk) begin
+ if( enT3) begin
+ if( Nanod.dbl2rxl | Nanod.abl2rxl) begin
+ if( ~rxIsAreg) begin
+ if( Nanod.dbl2rxl) regs68L[ actualRx] <= Dbd;
+ else if( abdIsByte) regs68L[ actualRx][7:0] <= Abd[7:0];
+ else regs68L[ actualRx] <= Abd;
+ end
+ else
+ regs68L[ actualRx] <= Nanod.dbl2rxl ? Dbl : Abl;
+ end
+
+ if( Nanod.dbl2ryl | Nanod.abl2ryl) begin
+ if( ~ryIsAreg) begin
+ if( Nanod.dbl2ryl) regs68L[ actualRy] <= Dbd;
+ else if( abdIsByte) regs68L[ actualRy][7:0] <= Abd[7:0];
+ else regs68L[ actualRy] <= Abd;
+ end
+ else
+ regs68L[ actualRy] <= Nanod.dbl2ryl ? Dbl : Abl;
+ end
+
+ // High registers are easier. Both A & D on the same buses, and not byte ops.
+ if( Nanod.dbh2rxh | Nanod.abh2rxh)
+ regs68H[ actualRx] <= Nanod.dbh2rxh ? Dbh : Abh;
+ if( Nanod.dbh2ryh | Nanod.abh2ryh)
+ regs68H[ actualRy] <= Nanod.dbh2ryh ? Dbh : Abh;
+
+ end
+ end
+
+ // PC & AT
+ reg dbl2Pcl, dbh2Pch, abh2Pch, abl2Pcl;
+
+ always_ff @( posedge Clks.clk) begin
+ if( Clks.extReset) begin
+ { dbl2Pcl, dbh2Pch, abh2Pch, abl2Pcl } <= '0;
+
+ Pcl2Dbl <= 1'b0;
+ Pch2Dbh <= 1'b0;
+ Pcl2Abl <= 1'b0;
+ Pch2Abh <= 1'b0;
+ end
+ else if( enT4) begin // Must latch on T4 !
+ dbl2Pcl <= Nanod.dbl2reg & Nanod.pcldbl;
+ dbh2Pch <= Nanod.dbh2reg & Nanod.pchdbh;
+ abh2Pch <= Nanod.abh2reg & Nanod.pchabh;
+ abl2Pcl <= Nanod.abl2reg & Nanod.pclabl;
+
+ Pcl2Dbl <= Nanod.reg2dbl & Nanod.pcldbl;
+ Pch2Dbh <= Nanod.reg2dbh & Nanod.pchdbh;
+ Pcl2Abl <= Nanod.reg2abl & Nanod.pclabl;
+ Pch2Abh <= Nanod.reg2abh & Nanod.pchabh;
+ end
+
+ // Unique IF !!!
+ if( enT1 & Nanod.au2Pc)
+ PcL <= auReg[15:0];
+ else if( enT3) begin
+ if( dbl2Pcl)
+ PcL <= Dbl;
+ else if( abl2Pcl)
+ PcL <= Abl;
+ end
+
+ // Unique IF !!!
+ if( enT1 & Nanod.au2Pc)
+ PcH <= auReg[31:16];
+ else if( enT3) begin
+ if( dbh2Pch)
+ PcH <= Dbh;
+ else if( abh2Pch)
+ PcH <= Abh;
+ end
+
+ // Unique IF !!!
+ if( enT3) begin
+ if( Nanod.dbl2Atl)
+ Atl <= Dbl;
+ else if( Nanod.abl2Atl)
+ Atl <= Abl;
+ end
+
+ // Unique IF !!!
+ if( enT3) begin
+ if( Nanod.abh2Ath)
+ Ath <= Abh;
+ else if( Nanod.dbh2Ath)
+ Ath <= Dbh;
+ end
+
+ end
+
+ // Movem reg mask priority encoder
+
+ wire rmIdle;
+ logic [3:0] prHbit;
+ logic [15:0] prenLatch;
+
+ // Invert reg order for predecrement mode
+ assign prenEmpty = (~| prenLatch);
+ pren rmPren( .mask( prenLatch), .hbit (prHbit));
+
+ always_ff @( posedge Clks.clk) begin
+ // Cheating: PREN always loaded from DBIN
+ // Must be on T1 to branch earlier if reg mask is empty!
+ if( enT1 & Nanod.abl2Pren)
+ prenLatch <= dbin;
+ else if( enT3 & Nanod.updPren) begin
+ prenLatch [prHbit] <= 1'b0;
+ movemRx <= Irdecod.movemPreDecr ? ~prHbit : prHbit;
+ end
+ end
+
+ // DCR
+ wire [15:0] dcrCode;
+
+ wire [3:0] dcrInput = abdIsByte ? { 1'b0, Abd[ 2:0]} : Abd[ 3:0];
+ onehotEncoder4 dcrDecoder( .bin( dcrInput), .bitMap( dcrCode));
+
+ always_ff @( posedge Clks.clk) begin
+ if( Clks.pwrUp)
+ dcr4 <= '0;
+ else if( enT3 & Nanod.abd2Dcr) begin
+ dcrOutput <= dcrCode;
+ dcr4 <= Abd[4];
+ end
+ end
+
+ // ALUB
+ reg [15:0] alub;
+
+ always_ff @( posedge Clks.clk) begin
+ if( enT3) begin
+ // UNIQUE IF !!
+ if( Nanod.dbd2Alub)
+ alub <= Dbd;
+ else if( Nanod.abd2Alub)
+ alub <= Abd; // abdIsByte affects this !!??
+ end
+ end
+
+ wire alueClkEn = enT3 & Nanod.dbd2Alue;
+
+ // DOB/DBIN/IRC
+
+ logic [15:0] dobInput;
+ wire dobIdle = (~| Nanod.dobCtrl);
+
+ always_comb begin
+ unique case (Nanod.dobCtrl)
+ NANO_DOB_ADB: dobInput = Abd;
+ NANO_DOB_DBD: dobInput = Dbd;
+ NANO_DOB_ALU: dobInput = aluOut;
+ default: dobInput = 'X;
+ endcase
+ end
+
+ dataIo dataIo( .Clks, .enT1, .enT2, .enT3, .enT4, .Nanod, .Irdecod,
+ .iEdb, .dobIdle, .dobInput, .aob0,
+ .Irc, .dbin, .oEdb);
+
+ fx68kAlu alu(
+ .clk( Clks.clk), .pwrUp( Clks.pwrUp), .enT1, .enT3, .enT4,
+ .ird( Ird),
+ .aluColumn( Nanod.aluColumn), .aluAddrCtrl( Nanod.aluActrl),
+ .init( Nanod.aluInit), .finish( Nanod.aluFinish), .aluIsByte( Irdecod.isByte),
+ .ftu2Ccr( Nanod.ftu2Ccr),
+ .alub, .ftu, .alueClkEn, .alue,
+ .aluDataCtrl( Nanod.aluDctrl), .iDataBus( Dbd), .iAddrBus(Abd),
+ .ze, .aluOut, .ccr);
+
+endmodule
diff --git a/common/CPU/68000/FX68k/fx68k.sv b/common/CPU/68000/FX68k/fx68k.sv
new file mode 100644
index 00000000..996d9ac3
--- /dev/null
+++ b/common/CPU/68000/FX68k/fx68k.sv
@@ -0,0 +1,642 @@
+//
+// FX68K
+//
+// M68000 cycle accurate, fully synchronous
+// Copyright (c) 2018 by Jorge Cwik
+//
+// TODO:
+// - Everything except bus retry already implemented.
+
+`timescale 1 ns / 1 ns
+
+// Define this to run a self contained compilation test build
+// `define FX68K_TEST
+
+localparam CF = 0, VF = 1, ZF = 2, NF = 3, XF = 4, SF = 13;
+
+localparam UADDR_WIDTH = 10;
+localparam UROM_WIDTH = 17;
+localparam UROM_DEPTH = 1024;
+
+localparam NADDR_WIDTH = 9;
+localparam NANO_WIDTH = 68;
+localparam NANO_DEPTH = 336;
+
+localparam BSER1_NMA = 'h003;
+localparam RSTP0_NMA = 'h002;
+localparam HALT1_NMA = 'h001;
+localparam TRAC1_NMA = 'h1C0;
+localparam ITLX1_NMA = 'h1C4;
+
+localparam TVN_SPURIOUS = 12;
+localparam TVN_AUTOVEC = 13;
+localparam TVN_INTERRUPT = 15;
+
+localparam NANO_DOB_DBD = 2'b01;
+localparam NANO_DOB_ADB = 2'b10;
+localparam NANO_DOB_ALU = 2'b11;
+
+
+// Clocks, phases and resets
+typedef struct {
+ logic clk;
+ logic extReset; // External sync reset on emulated system
+ logic pwrUp; // Asserted together with reset on emulated system coldstart
+ logic enPhi1, enPhi2; // Clock enables. Next cycle is PHI1 or PHI2
+} s_clks;
+
+// IRD decoded signals
+typedef struct {
+ logic isPcRel;
+ logic isTas;
+ logic implicitSp;
+ logic toCcr;
+ logic rxIsDt, ryIsDt;
+ logic rxIsUsp, rxIsMovem, movemPreDecr;
+ logic isByte;
+ logic isMovep;
+ logic [2:0] rx, ry;
+ logic rxIsAreg, ryIsAreg;
+ logic [15:0] ftuConst;
+ logic [5:0] macroTvn;
+ logic inhibitCcr;
+} s_irdecod;
+
+// Nano code decoded signals
+typedef struct {
+ logic permStart;
+ logic waitBusFinish;
+ logic isWrite;
+ logic busByte;
+ logic isRmc;
+ logic noLowByte, noHighByte;
+
+ logic updTpend, clrTpend;
+ logic tvn2Ftu, const2Ftu;
+ logic ftu2Dbl, ftu2Abl;
+ logic abl2Pren, updPren;
+ logic inl2psw, ftu2Sr, sr2Ftu, ftu2Ccr, pswIToFtu;
+ logic ird2Ftu, ssw2Ftu;
+ logic initST;
+ logic Ir2Ird;
+
+ logic auClkEn, noSpAlign;
+ logic [2:0] auCntrl;
+ logic todbin, toIrc;
+ logic dbl2Atl, abl2Atl, atl2Abl, atl2Dbl;
+ logic abh2Ath, dbh2Ath;
+ logic ath2Dbh, ath2Abh;
+
+ logic db2Aob, ab2Aob, au2Aob;
+ logic aob2Ab, updSsw;
+ // logic adb2Dob, dbd2Dob, alu2Dob;
+ logic [1:0] dobCtrl;
+
+ logic abh2reg, abl2reg;
+ logic reg2abl, reg2abh;
+ logic dbh2reg, dbl2reg;
+ logic reg2dbl, reg2dbh;
+ logic ssp, pchdbh, pcldbl, pclabl, pchabh;
+
+ logic rxh2dbh, rxh2abh;
+ logic dbl2rxl, dbh2rxh;
+ logic rxl2db, rxl2ab;
+ logic abl2rxl, abh2rxh;
+ logic dbh2ryh, abh2ryh;
+ logic ryl2db, ryl2ab;
+ logic ryh2dbh, ryh2abh;
+ logic dbl2ryl, abl2ryl;
+ logic rz;
+ logic rxlDbl;
+
+ logic [2:0] aluColumn;
+ logic [1:0] aluDctrl;
+ logic aluActrl;
+ logic aluInit, aluFinish;
+ logic abd2Dcr, dcr2Dbd;
+ logic dbd2Alue, alue2Dbd;
+ logic dbd2Alub, abd2Alub;
+
+ logic alu2Dbd, alu2Abd;
+ logic au2Db, au2Ab, au2Pc;
+ logic dbin2Abd, dbin2Dbd;
+ logic extDbh, extAbh;
+ logic ablAbd, ablAbh;
+ logic dblDbd, dblDbh;
+ logic abdIsByte;
+} s_nanod;
+
+module fx68k(
+ input clk,
+
+ // These two signals don't need to be registered. They are not async reset.
+ input extReset, // External sync reset on emulated system
+ input pwrUp, // Asserted together with reset on emulated system coldstart
+ input enPhi1, enPhi2, // Clock enables. Next cycle is PHI1 or PHI2
+
+ output eRWn, output ASn, output LDSn, output UDSn,
+ output logic E, output VMAn,
+ output FC0, output FC1, output FC2,
+ output BGn,
+ output oRESETn, output oHALTEDn,
+ input DTACKn, input VPAn,
+ input BERRn,
+ input BRn, BGACKn,
+ input IPL0n, input IPL1n, input IPL2n,
+ input [15:0] iEdb, output [15:0] oEdb,
+ output [23:1] eab
+ );
+
+ // wire clock = Clks.clk;
+ s_clks Clks;
+
+ assign Clks.clk = clk;
+ assign Clks.extReset = extReset;
+ assign Clks.pwrUp = pwrUp;
+ assign Clks.enPhi1 = enPhi1;
+ assign Clks.enPhi2 = enPhi2;
+
+ wire wClk;
+
+ // Internal sub clocks T1-T4
+ enum int unsigned { T0 = 0, T1, T2, T3, T4} tState;
+ wire enT1 = Clks.enPhi1 & (tState == T4) & ~wClk;
+ wire enT2 = Clks.enPhi2 & (tState == T1);
+ wire enT3 = Clks.enPhi1 & (tState == T2);
+ wire enT4 = Clks.enPhi2 & ((tState == T0) | (tState == T3));
+
+ // T4 continues ticking during reset and group0 exception.
+ // We also need it to erase ucode output latched on T4.
+ always_ff @( posedge Clks.clk) begin
+ if( Clks.pwrUp)
+ tState <= T0;
+ else begin
+ case( tState)
+ T0: if( Clks.enPhi2) tState <= T4;
+ T1: if( Clks.enPhi2) tState <= T2;
+ T2: if( Clks.enPhi1) tState <= T3;
+ T3: if( Clks.enPhi2) tState <= T4;
+ T4: if( Clks.enPhi1) tState <= wClk ? T0 : T1;
+ endcase
+ end
+ end
+
+ // The following signals are synchronized with 3 couplers, phi1-phi2-phi1.
+ // Will be valid internally one cycle later if changed at the rasing edge of the clock.
+ //
+ // DTACK, BERR
+
+ // DTACK valid at S6 if changed at the rasing edge of S4 to avoid wait states.
+ // SNC (sncClkEn) is deasserted together (unless DTACK asserted too early).
+ //
+ // We synchronize some signals half clock earlier. We compensate later
+ reg rDtack, rBerr;
+ reg [2:0] rIpl, iIpl;
+ reg Vpai, BeI, BRi, BgackI, BeiDelay;
+ // reg rBR;
+ wire BeDebounced = ~( BeI | BeiDelay);
+
+ always_ff @( posedge Clks.clk) begin
+ if( Clks.pwrUp) begin
+ rBerr <= 1'b0;
+ BeI <= 1'b0;
+ end
+ else if( Clks.enPhi2) begin
+ rDtack <= DTACKn;
+ rBerr <= BERRn;
+ rIpl <= ~{ IPL2n, IPL1n, IPL0n};
+ iIpl <= rIpl;
+
+ // rBR <= BRn; // Needed for cycle accuracy but only if BR is changed on the wrong edge of the clock
+ end
+ else if( Clks.enPhi1) begin
+ Vpai <= VPAn;
+ BeI <= rBerr;
+ BeiDelay <= BeI;
+
+ BRi <= BRn;
+ BgackI <= BGACKn;
+ // BRi <= rBR;
+ end
+ end
+
+ // Instantiate micro and nano rom
+ logic [NANO_WIDTH-1:0] nanoLatch;
+ logic [NANO_WIDTH-1:0] nanoOutput;
+ logic [UROM_WIDTH-1:0] microLatch;
+ logic [UROM_WIDTH-1:0] microOutput;
+
+ logic [UADDR_WIDTH-1:0] microAddr, nma;
+ logic [NADDR_WIDTH-1:0] nanoAddr, orgAddr;
+ wire rstUrom;
+
+ // For the time being, address translation is done for nanorom only.
+ microToNanoAddr microToNanoAddr(
+ .uAddr ( nma),
+ .orgAddr ( orgAddr)
+ );
+
+ // Output of these modules will be updated at T2 at the latest (depending on clock division)
+
+ nanoRom nanoRom(
+ .clk ( Clks.clk),
+ .nanoAddr (nanoAddr),
+ .nanoOutput (nanoOutput)
+ );
+
+ uRom uRom(
+ .clk ( Clks.clk),
+ .microAddr ( microAddr),
+ .microOutput( microOutput));
+
+ always_ff @( posedge Clks.clk) begin
+ // uaddr originally latched on T1, except bits 6 & 7, the conditional bits, on T2
+ // Seems we can latch whole address at either T1 or T2
+
+ // Originally it's invalid on hardware reset, and forced later when coming out of reset
+ if( Clks.pwrUp) begin
+ microAddr <= RSTP0_NMA;
+ nanoAddr <= RSTP0_NMA;
+ end
+ else if( enT1) begin
+ microAddr <= nma;
+ nanoAddr <= orgAddr; // Register translated uaddr to naddr
+ end
+
+ if( Clks.extReset) begin
+ microLatch <= '0;
+ nanoLatch <= '0;
+ end
+ else if( rstUrom) begin
+ // Originally reset these bits only. Not strictly needed like this.
+ // Can reset the whole register if it is important.
+ { microLatch[16], microLatch[15], microLatch[0]} <= '0;
+ nanoLatch <= '0;
+ end
+ else if( enT3) begin
+ microLatch <= microOutput;
+ nanoLatch <= nanoOutput;
+ end
+
+ end
+
+
+ // Decoded nanocode signals
+ s_nanod Nanod;
+ // IRD decoded control signals
+ s_irdecod Irdecod;
+
+ //
+ reg Tpend;
+ reg intPend; // Interrupt pending
+ reg pswT, pswS;
+ reg [ 2:0] pswI;
+ wire [7:0] ccr;
+
+ wire [15:0] psw = { pswT, 1'b0, pswS, 2'b00, pswI, ccr};
+
+ reg [15:0] ftu;
+ reg [15:0] Irc, Ir, Ird;
+
+ wire [15:0] alue;
+ wire [15:0] Abl;
+ wire prenEmpty, au05z, dcr4, ze;
+
+ wire [UADDR_WIDTH-1:0] a1, a2, a3;
+ wire isPriv, isIllegal, isLineA, isLineF;
+
+
+ // IR & IRD forwarding
+ always_ff @( posedge Clks.clk) begin
+ if( enT1) begin
+ if( Nanod.Ir2Ird)
+ Ird <= Ir;
+ else if(microLatch[0]) // prevented by IR => IRD !
+ Ir <= Irc;
+ end
+ end
+
+ wire [3:0] tvn;
+ wire waitBusCycle, busStarting;
+ wire BusRetry = 1'b0;
+ wire busAddrErr;
+ wire bciWrite; // Last bus cycle was write
+ wire bgBlock, busAvail;
+ wire addrOe;
+
+ wire busIsByte = Nanod.busByte & (Irdecod.isByte | Irdecod.isMovep);
+ wire aob0;
+
+ reg iStop; // Internal signal for ending bus cycle
+ reg A0Err; // Force bus/address error ucode
+ reg excRst; // Signal reset exception to sequencer
+ reg BerrA;
+ reg Spuria, Avia;
+ wire Iac;
+
+ reg rAddrErr, iBusErr, Err6591;
+ wire iAddrErr = rAddrErr & addrOe; // To simulate async reset
+ wire enErrClk;
+
+ // Reset micro/nano latch after T4 of the current ublock.
+ assign rstUrom = Clks.enPhi1 & enErrClk;
+
+ uaddrDecode uaddrDecode( .opcode( Ir), .a1, .a2, .a3, .isPriv, .isIllegal, .isLineA, .isLineF, .lineBmap());
+
+ sequencer sequencer( .Clks, .enT3, .microLatch, .Ird,
+ .A0Err, .excRst, .BerrA, .busAddrErr, .Spuria, .Avia,
+ .Tpend, .intPend, .isIllegal, .isPriv, .isLineA, .isLineF,
+ .nma, .a1, .a2, .a3, .tvn,
+ .psw, .prenEmpty, .au05z, .dcr4, .ze, .alue01( alue[1:0]), .i11( Irc[ 11]) );
+
+ excUnit excUnit( .Clks, .Nanod, .Irdecod, .enT1, .enT2, .enT3, .enT4,
+ .Ird, .ftu, .iEdb, .pswS,
+ .prenEmpty, .au05z, .dcr4, .ze, .AblOut( Abl), .eab, .aob0, .Irc, .oEdb,
+ .alue, .ccr);
+
+ nDecoder3 nDecoder( .Clks, .Nanod, .Irdecod, .enT2, .enT4, .microLatch, .nanoLatch);
+
+ irdDecode irdDecode( .ird( Ird), .Irdecod);
+
+ busControl busControl( .Clks, .enT1, .enT4, .permStart( Nanod.permStart), .permStop( Nanod.waitBusFinish), .iStop,
+ .aob0, .isWrite( Nanod.isWrite), .isRmc( Nanod.isRmc), .isByte( busIsByte), .busAvail,
+ .bciWrite, .addrOe, .bgBlock, .waitBusCycle, .busStarting, .busAddrErr,
+ .rDtack, .BeDebounced, .Vpai,
+ .ASn, .LDSn, .UDSn, .eRWn);
+
+ busArbiter busArbiter( .Clks, .BRi, .BgackI, .Halti( 1'b1), .bgBlock, .busAvail, .BGn);
+
+
+ // Output reset & halt control
+ wire [1:0] uFc = microLatch[ 16:15];
+ logic oReset, oHalted;
+ assign oRESETn = !oReset;
+ assign oHALTEDn = !oHalted;
+
+ // FC without permStart is special, either reset or halt
+ always_ff @( posedge Clks.clk) begin
+ if( Clks.pwrUp) begin
+ oReset <= 1'b0;
+ oHalted <= 1'b0;
+ end
+ else if( enT1) begin
+ oReset <= (uFc == 2'b01) & !Nanod.permStart;
+ oHalted <= (uFc == 2'b10) & !Nanod.permStart;
+ end
+ end
+
+ logic [2:0] rFC;
+ assign { FC2, FC1, FC0} = rFC; // ~rFC;
+ assign Iac = {rFC == 3'b111}; // & Control output enable !!
+
+ always_ff @( posedge Clks.clk) begin
+ if( Clks.extReset)
+ rFC <= '0;
+ else if( enT1 & Nanod.permStart) begin // S0 phase of bus cycle
+ rFC[2] <= pswS;
+ // PC relativ access is marked as FC type 'n' (0) at ucode.
+ // We don't care about RZ in this case. Those uinstructions with RZ don't start a bus cycle.
+ rFC[1] <= microLatch[ 16] | ( ~microLatch[ 15] & ~Irdecod.isPcRel);
+ rFC[0] <= microLatch[ 15] | ( ~microLatch[ 16] & Irdecod.isPcRel);
+ end
+ end
+
+
+ // IPL interface
+ reg [2:0] inl; // Int level latch
+ reg updIll;
+ reg prevNmi;
+
+ wire nmi = (iIpl == 3'b111);
+ wire iplStable = (iIpl == rIpl);
+ wire iplComp = iIpl > pswI;
+
+ always_ff @( posedge Clks.clk) begin
+ if( Clks.extReset) begin
+ intPend <= 1'b0;
+ prevNmi <= 1'b0;
+ end
+ else begin
+ if( Clks.enPhi2)
+ prevNmi <= nmi;
+
+ // Originally async RS-Latch on PHI2, followed by a transparent latch on T2
+ // Tricky because they might change simultaneously
+ // Syncronous on PHI2 is equivalent as long as the output is read on T3!
+
+ // Set on stable & NMI edge or compare
+ // Clear on: NMI Iack or (stable & !NMI & !Compare)
+
+ if( Clks.enPhi2) begin
+ if( iplStable & ((nmi & ~prevNmi) | iplComp) )
+ intPend <= 1'b1;
+ else if( ((inl == 3'b111) & Iac) | (iplStable & !nmi & !iplComp) )
+ intPend <= 1'b0;
+ end
+ end
+
+ if( Clks.extReset) begin
+ inl <= '1;
+ updIll <= 1'b0;
+ end
+ else if( enT4)
+ updIll <= microLatch[0]; // Update on any IRC->IR
+ else if( enT1 & updIll)
+ inl <= iIpl; // Timing is correct.
+
+ // Spurious interrupt, BERR on Interrupt Ack.
+ // Autovector interrupt. VPA on IACK.
+ // Timing is tight. Spuria is deasserted just after exception exception is recorded.
+ if( enT4) begin
+ Spuria <= ~BeiDelay & Iac;
+ Avia <= ~Vpai & Iac;
+ end
+
+ end
+
+ assign enErrClk = iAddrErr | iBusErr;
+ assign wClk = waitBusCycle | ~BeI | iAddrErr | Err6591;
+
+ // E clock and counter, VMA
+ reg [3:0] eCntr;
+ reg rVma;
+
+ assign VMAn = rVma;
+
+ // Internal stop just one cycle before E falling edge
+ wire xVma = ~rVma & (eCntr == 8);
+
+ always_ff @( posedge Clks.clk) begin
+ if( Clks.pwrUp) begin
+ E <= 1'b0;
+ eCntr <='0;
+ rVma <= 1'b1;
+ end
+ if( Clks.enPhi2) begin
+ if( eCntr == 9)
+ E <= 1'b0;
+ else if( eCntr == 5)
+ E <= 1'b1;
+
+ if( eCntr == 9)
+ eCntr <= '0;
+ else
+ eCntr <= eCntr + 1'b1;
+ end
+
+ if( Clks.enPhi2 & addrOe & ~Vpai & (eCntr == 3))
+ rVma <= 1'b0;
+ else if( Clks.enPhi1 & eCntr == '0)
+ rVma <= 1'b1;
+ end
+
+ always_ff @( posedge Clks.clk) begin
+
+ // This timing is critical to stop the clock phases at the exact point on bus/addr error.
+ // Timing should be such that current ublock completes (up to T3 or T4).
+ // But T1 for the next ublock shouldn't happen. Next T1 only after resetting ucode and ncode latches.
+
+ if( Clks.extReset)
+ rAddrErr <= 1'b0;
+ else if( Clks.enPhi1) begin
+ if( busAddrErr & addrOe) // Not on T1 ?!
+ rAddrErr <= 1'b1;
+ else if( ~addrOe) // Actually async reset!
+ rAddrErr <= 1'b0;
+ end
+
+ if( Clks.extReset)
+ iBusErr <= 1'b0;
+ else if( Clks.enPhi1) begin
+ iBusErr <= ( BerrA & ~BeI & ~Iac & !BusRetry);
+ end
+
+ if( Clks.extReset)
+ BerrA <= 1'b0;
+ else if( Clks.enPhi2) begin
+ if( ~BeI & ~Iac & addrOe)
+ BerrA <= 1'b1;
+ // else if( BeI & addrOe) // Bad, async reset since addrOe raising edge
+ else if( BeI & busStarting) // So replaced with this that raises one cycle earlier
+ BerrA <= 1'b0;
+ end
+
+ // Signal reset exception to sequencer.
+ // Originally cleared on 1st T2 after permstart. Must keep it until TVN latched.
+ if( Clks.extReset)
+ excRst <= 1'b1;
+ else if( enT2 & Nanod.permStart)
+ excRst <= 1'b0;
+
+ if( Clks.extReset)
+ A0Err <= 1'b1; // A0 Reset
+ else if( enT3) // Keep set until new urom words are being latched
+ A0Err <= 1'b0;
+ else if( Clks.enPhi1 & enErrClk & (busAddrErr | BerrA)) // Check bus error timing
+ A0Err <= 1'b1;
+
+ if( Clks.extReset) begin
+ iStop <= 1'b0;
+ Err6591 <= 1'b0;
+ end
+ else if( Clks.enPhi1)
+ Err6591 <= enErrClk;
+ else if( Clks.enPhi2)
+ iStop <= xVma | (Vpai & (iAddrErr | ~rBerr));
+ end
+
+ // PSW
+ logic irdToCcr_t4;
+ always_ff @( posedge Clks.clk) begin
+ if( Clks.pwrUp) begin
+ Tpend <= 1'b0;
+ {pswT, pswS, pswI } <= '0;
+ irdToCcr_t4 <= '0;
+ end
+
+ else if( enT4) begin
+ irdToCcr_t4 <= Irdecod.toCcr;
+ end
+
+ else if( enT3) begin
+
+ // UNIQUE IF !!
+ if( Nanod.updTpend)
+ Tpend <= pswT;
+ else if( Nanod.clrTpend)
+ Tpend <= 1'b0;
+
+ // UNIQUE IF !!
+ if( Nanod.ftu2Sr & !irdToCcr_t4)
+ {pswT, pswS, pswI } <= { ftu[ 15], ftu[13], ftu[10:8]};
+ else begin
+ if( Nanod.initST) begin
+ pswS <= 1'b1;
+ pswT <= 1'b0;
+ end
+ if( Nanod.inl2psw)
+ pswI <= inl;
+ end
+
+ end
+ end
+
+ // FTU
+ reg [4:0] ssw;
+ reg [3:0] tvnLatch;
+ logic [15:0] tvnMux;
+ reg inExcept01;
+
+ // Seems CPU has a buglet here.
+ // Flagging group 0 exceptions from TVN might not work because some bus cycles happen before TVN is updated.
+ // But doesn't matter because a group 0 exception inside another one will halt the CPU anyway and won't save the SSW.
+
+ always_ff @( posedge Clks.clk) begin
+
+ // Updated at the start of the exception ucode
+ if( Nanod.updSsw & enT3) begin
+ ssw <= { ~bciWrite, inExcept01, rFC};
+ end
+
+ // Update TVN on T1 & IR=>IRD
+ if( enT1 & Nanod.Ir2Ird) begin
+ tvnLatch <= tvn;
+ inExcept01 <= (tvn != 1);
+ end
+
+ if( Clks.pwrUp)
+ ftu <= '0;
+ else if( enT3) begin
+ unique case( 1'b1)
+ Nanod.tvn2Ftu: ftu <= tvnMux;
+
+ // 0 on unused bits seem to come from ftuConst PLA previously clearing FBUS
+ Nanod.sr2Ftu: ftu <= {pswT, 1'b0, pswS, 2'b00, pswI, 3'b000, ccr[4:0] };
+
+ Nanod.ird2Ftu: ftu <= Ird;
+ Nanod.ssw2Ftu: ftu[4:0] <= ssw; // Undoc. Other bits must be preserved from IRD saved above!
+ Nanod.pswIToFtu: ftu <= { 12'hFFF, pswI, 1'b0}; // Interrupt level shifted
+ Nanod.const2Ftu: ftu <= Irdecod.ftuConst;
+ Nanod.abl2Pren: ftu <= Abl; // From ALU or datareg. Used for SR modify
+ default: ftu <= ftu;
+ endcase
+ end
+ end
+
+ always_comb begin
+ if( inExcept01) begin
+ // Unique IF !!!
+ if( tvnLatch == TVN_SPURIOUS)
+ tvnMux = {9'b0, 5'd24, 2'b00};
+ else if( tvnLatch == TVN_AUTOVEC)
+ tvnMux = {9'b0, 2'b11, pswI, 2'b00}; // Set TVN PLA decoder
+ else if( tvnLatch == TVN_INTERRUPT)
+ tvnMux = {6'b0, Ird[7:0], 2'b00}; // Interrupt vector was read and transferred to IRD
+ else
+ tvnMux = {10'b0, tvnLatch, 2'b00};
+ end
+ else
+ tvnMux = { 8'h0, Irdecod.macroTvn, 2'b00};
+ end
+
+endmodule
\ No newline at end of file
diff --git a/common/CPU/68000/FX68k/fx68k.txt b/common/CPU/68000/FX68k/fx68k.txt
new file mode 100644
index 00000000..7ad0b47f
--- /dev/null
+++ b/common/CPU/68000/FX68k/fx68k.txt
@@ -0,0 +1,74 @@
+FX68K
+
+68000 cycle accurate core
+Copyright (c) 2018 by Jorge Cwik
+fx68k@fxatari.com
+
+
+FX68K is a 68K cycle exact compatible core. In theory at least, it should be impossible to distinguish functionally from a real 68K processor.
+
+On Cyclone families it uses just over 5,100 LEs and about 5KB internal ram, reaching a max clock frequency close to 40MHz. Some optimizations are still possible to implement and increase the performance.
+
+The core is fully synchronous. Considerable effort was done to avoid any asynchronous logic.
+
+Written in SystemVerilog.
+
+The timing of the external bus signals is exactly as the original processor. The only feature that is not implemented yet is bus retry using the external HALT input signal.
+
+It was designed to replace an actual chip on a real board. This wasn't yet tested however and not all necessary output enable control signals are fully implemented.
+
+
+Copyright
+
+//
+// This source file 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 source file 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 .
+//
+
+
+Developer Notes
+
+
+The core receives a clock that must be at least twice the frequency of the desired nominal speed. The core also receives two signals for masking both phases of the clock (PHI1 and PHI2). These signals are implemented as simple clock enable for all the flip flops used by the core. This way, the original clock frequency can be any multiple and it doesn't even need to be regular or constant.
+
+These two signals are enPhi1 and enPhi2. They must be a single cycle pulse, and they don't need to be registered. Because they are actually used as clock enable, the output signals change one cycle later.
+
+enPhi1 should be asserted one cycle before the high phase of the nominal clock, and enPhi2 one cycle before the low phase.
+
+E.g., during a bus cycle, AS is asserted one cycle after enPhi1 is asserted, and AS is deasserted one cycle after enPhi2 is asserted. This follows the original bus timing that specify AS being asserted on the raising edge of the clock, and deasserted on the falling edge one.
+
+All signals follow the original polarity and then most are low active.
+
+extReset is external reset and is synchronous and high active. Hence is doesn't have to be registered.
+
+pwrUp qualifies external reset as being a cold power up reset. If it is asserted, then extReset must be asserted as well. Most system don't need to distinguish between a cold and a warm reset at the CPU level. Then both signals can be always asserted together. The core does expect pwrUp to be asserted initially because there is no true asynchronous reset. The signal is high active.
+
+
+Timing analysis
+
+Microcode access is one of the slowest paths on the core. But the microcode output is not needed immediately. Use the following constraints to get a more accurate timing analysis. Note that the full path might need to be modified:
+
+# Altera/Intel
+
+set_multicycle_path -start -setup -from [get_keepers fx68k:fx68k|Ir[*]] -to [get_keepers fx68k:fx68k|microAddr[*]] 2
+set_multicycle_path -start -hold -from [get_keepers fx68k:fx68k|Ir[*]] -to [get_keepers fx68k:fx68k|microAddr[*]] 1
+set_multicycle_path -start -setup -from [get_keepers fx68k:fx68k|Ir[*]] -to [get_keepers fx68k:fx68k|nanoAddr[*]] 2
+set_multicycle_path -start -hold -from [get_keepers fx68k:fx68k|Ir[*]] -to [get_keepers fx68k:fx68k|nanoAddr[*]] 1
+
+# For Xilinx Vivado
+
+set_multicycle_path -setup -from [get_pins fx68k/Ir*/C] -to [get_pins fx68k/nanoAddr_reg*/D] 2
+set_multicycle_path -setup -from [get_pins fx68k/Ir*/C] -to [get_pins fx68k/microAddr_reg*/D] 2
+set_multicycle_path -hold -from [get_pins fx68k/Ir*/C] -to [get_pins fx68k/nanoAddr_reg*/D] 1
+set_multicycle_path -hold -from [get_pins fx68k/Ir*/C] -to [get_pins fx68k/microAddr_reg*/D] 1
+
diff --git a/common/CPU/68000/FX68k/fx68kAlu.sv b/common/CPU/68000/FX68k/fx68kAlu.sv
new file mode 100644
index 00000000..347b033d
--- /dev/null
+++ b/common/CPU/68000/FX68k/fx68kAlu.sv
@@ -0,0 +1,479 @@
+//
+// FX 68K
+//
+// M68K cycle accurate, fully synchronous
+// Copyright (c) 2018 by Jorge Cwik
+//
+// ALU
+//
+
+`timescale 1 ns / 1 ns
+
+localparam MASK_NBITS = 5;
+
+localparam
+ OP_AND = 1,
+ OP_SUB = 2, OP_SUBX = 3, OP_ADD = 4,
+ OP_EXT = 5, OP_SBCD = 6, OP_SUB0 = 7,
+ OP_OR = 8, OP_EOR = 9,
+ OP_SUBC = 10, OP_ADDC = 11, OP_ADDX = 12,
+ OP_ASL = 13,
+ OP_ASR = 14,
+ OP_LSL = 15,
+ OP_LSR = 16,
+ OP_ROL = 17,
+ OP_ROR = 18,
+ OP_ROXL = 19,
+ OP_ROXR = 20,
+ OP_SLAA = 21,
+ OP_ABCD = 22;
+
+module fx68kAlu ( input clk, pwrUp, enT1, enT3, enT4,
+ input [15:0] ird,
+ input [2:0] aluColumn,
+ input [1:0] aluDataCtrl,
+ input aluAddrCtrl, alueClkEn, ftu2Ccr, init, finish, aluIsByte,
+ input [15:0] ftu,
+ input [15:0] alub,
+ input [15:0] iDataBus, input [15:0] iAddrBus,
+ output ze,
+ output reg [15:0] alue,
+ output reg [7:0] ccr,
+ output [15:0] aluOut);
+
+
+`define ALU_ROW_01 16'h0002
+`define ALU_ROW_02 16'h0004
+`define ALU_ROW_03 16'h0008
+`define ALU_ROW_04 16'h0010
+`define ALU_ROW_05 16'h0020
+`define ALU_ROW_06 16'h0040
+`define ALU_ROW_07 16'h0080
+`define ALU_ROW_08 16'h0100
+`define ALU_ROW_09 16'h0200
+`define ALU_ROW_10 16'h0400
+`define ALU_ROW_11 16'h0800
+`define ALU_ROW_12 16'h1000
+`define ALU_ROW_13 16'h2000
+`define ALU_ROW_14 16'h4000
+`define ALU_ROW_15 16'h8000
+
+
+ // Bit positions for flags in CCR
+ localparam CF = 0, VF = 1, ZF = 2, NF = 3, XF = 4;
+
+ reg [15:0] aluLatch;
+ reg [4:0] pswCcr;
+ reg [4:0] ccrCore;
+
+ logic [15:0] result;
+ logic [4:0] ccrTemp;
+ reg coreH; // half carry latch
+
+ logic [15:0] subResult;
+ logic subHcarry;
+ logic subCout, subOv;
+
+ assign aluOut = aluLatch;
+ assign ze = ~ccrCore[ ZF]; // Check polarity !!!
+
+ //
+ // Control
+ // Signals derived from IRD *must* be registered on either T3 or T4
+ // Signals derived from nano rom can be registered on T4.
+
+ reg [15:0] row;
+ reg isArX; // Don't set Z
+ reg noCcrEn;
+ reg isByte;
+
+ reg [4:0] ccrMask;
+ reg [4:0] oper;
+
+ logic [15:0] aOperand, dOperand;
+ wire isCorf = ( aluDataCtrl == 2'b10);
+
+ wire [15:0] cRow;
+ wire cIsArX;
+ wire cNoCcrEn;
+ rowDecoder rowDecoder(
+ .ird ( ird),
+ .row ( cRow),
+ .noCcrEn ( cNoCcrEn),
+ .isArX ( cIsArX)
+ );
+
+ // Get Operation & CCR Mask from row/col
+ // Registering them on T4 increase performance. But slowest part seems to be corf !
+ wire [4:0] cMask;
+ wire [4:0] aluOp;
+
+ aluGetOp aluGetOp(
+ .row ( row),
+ .col ( aluColumn),
+ .isCorf ( isCorf),
+ .aluOp ( aluOp)
+ );
+
+ ccrTable ccrTable(
+ .col ( aluColumn),
+ .row ( row),
+ .finish ( finish),
+ .ccrMask ( cMask)
+ );
+
+ // Inefficient, uCode could help !
+ wire shftIsMul = row[7];
+ wire shftIsDiv = row[1];
+
+ wire [31:0] shftResult;
+ reg [7:0] bcdLatch;
+ reg bcdCarry, bcdOverf;
+
+ reg isLong;
+ reg rIrd8;
+ logic isShift;
+ logic shftCin, shftRight, addCin;
+
+ // Register some decoded signals
+ always_ff @( posedge clk) begin
+ if( enT3) begin
+ row <= cRow;
+ isArX <= cIsArX;
+ noCcrEn <= cNoCcrEn;
+ rIrd8 <= ird[8];
+ isByte <= aluIsByte;
+ end
+
+ if( enT4) begin
+ // Decode if long shift
+ // MUL and DIV are long (but special !)
+ isLong <= (ird[7] & ~ird[6]) | shftIsMul | shftIsDiv;
+
+ ccrMask <= cMask;
+ oper <= aluOp;
+ end
+ end
+
+
+ always_comb begin
+ // Dest (addr) operand source
+ // If aluCsr (depends on column/row) addrbus is shifted !!
+ aOperand = (aluAddrCtrl ? alub : iAddrBus);
+
+ // Second (data,source) operand mux
+ case( aluDataCtrl)
+ 2'b00: dOperand = iDataBus;
+ 2'b01: dOperand = 'h0000;
+ 2'b11: dOperand = 'hffff;
+ // 2'b10: dOperand = bcdResult;
+ 2'b10: dOperand = 'X;
+ endcase
+ end
+
+ // Execution
+
+ // shift operand MSB. Input in ASR/ROL. Carry in right.
+ // Can't be registered because uses bus operands that aren't available early !
+ wire shftMsb = isLong ? alue[15] : (isByte ? aOperand[7] : aOperand[15]);
+
+ aluShifter shifter(
+ .data ( { alue, aOperand}),
+ .swapWords ( shftIsMul | shftIsDiv),
+ .cin ( shftCin),
+ .dir ( shftRight),
+ .isByte ( isByte),
+ .isLong ( isLong),
+ .result ( shftResult)
+ );
+
+ wire [7:0] bcdResult;
+ wire bcdC, bcdV;
+ aluCorf aluCorf(
+ .binResult ( aluLatch[7:0]),
+ .hCarry ( coreH),
+ .bAdd ( (oper != OP_SBCD) ),
+ .cin ( pswCcr[ XF]),
+ .bcdResult ( bcdResult),
+ .dC ( bcdC),
+ .ov ( bcdV));
+
+ // BCD adjust is among the slowest processing on ALU !
+ // Precompute and register BCD result on T1
+ // We don't need to wait for execution buses because corf is always added to ALU previous result
+ always_ff @( posedge clk)
+ if( enT1) begin
+ bcdLatch <= bcdResult;
+ bcdCarry <= bcdC;
+ bcdOverf <= bcdV;
+ end
+
+ // Adder carry in selector
+ always_comb
+ begin
+ case( oper)
+ OP_ADD, OP_SUB: addCin = 1'b0;
+ OP_SUB0: addCin = 1'b1; // NOT = 0 - op - 1
+ OP_ADDC,OP_SUBC: addCin = ccrCore[ CF];
+ OP_ADDX,OP_SUBX: addCin = pswCcr[ XF];
+ default: addCin = 1'bX;
+ endcase
+ end
+
+ // Shifter carry in and direction selector
+ always_comb begin
+ case( oper)
+ OP_LSL, OP_ASL, OP_ROL, OP_ROXL, OP_SLAA: shftRight = 1'b0;
+ OP_LSR, OP_ASR, OP_ROR, OP_ROXR: shftRight = 1'b1;
+ default: shftRight = 1'bX;
+ endcase
+
+ case( oper)
+ OP_LSR,
+ OP_ASL,
+ OP_LSL: shftCin = 1'b0;
+ OP_ROL,
+ OP_ASR: shftCin = shftMsb;
+ OP_ROR: shftCin = aOperand[0];
+ OP_ROXL,
+ OP_ROXR:
+ if( shftIsMul)
+ shftCin = rIrd8 ? pswCcr[NF] ^ pswCcr[VF] : pswCcr[ CF];
+ else
+ shftCin = pswCcr[ XF];
+
+ OP_SLAA: shftCin = aluColumn[1]; // col4 -> 0, col 6-> 1
+ default: shftCin = 'X;
+ endcase
+ end
+
+ // ALU operation selector
+ always_comb begin
+
+ // sub is DATA - ADDR
+ mySubber( aOperand, dOperand, addCin,
+ (oper == OP_ADD) | (oper == OP_ADDC) | (oper == OP_ADDX),
+ isByte, subResult, subCout, subOv);
+
+ isShift = 1'b0;
+ case( oper)
+ OP_AND: result = aOperand & dOperand;
+ OP_OR: result = aOperand | dOperand;
+ OP_EOR: result = aOperand ^ dOperand;
+
+ OP_EXT: result = { {8{aOperand[7]}}, aOperand[7:0]};
+
+ OP_SLAA,
+ OP_ASL, OP_ASR,
+ OP_LSL, OP_LSR,
+ OP_ROL, OP_ROR,
+ OP_ROXL, OP_ROXR:
+ begin
+ result = shftResult[15:0];
+ isShift = 1'b1;
+ end
+
+ OP_ADD,
+ OP_ADDC,
+ OP_ADDX,
+ OP_SUB,
+ OP_SUBC,
+ OP_SUB0,
+ OP_SUBX: result = subResult;
+
+ OP_ABCD,
+ OP_SBCD: result = { 8'hXX, bcdLatch};
+
+ default: result = 'X;
+ endcase
+ end
+
+ task mySubber;
+ input [15:0] inpa, inpb;
+ input cin, bAdd, isByte;
+ output reg [15:0] result;
+ output cout, ov;
+
+ // Not very efficient!
+ logic [16:0] rtemp;
+ logic rm,sm,dm,tsm;
+
+ begin
+ if( isByte)
+ begin
+ rtemp = bAdd ? { 1'b0, inpb[7:0]} + { 1'b0, inpa[7:0]} + cin:
+ { 1'b0, inpb[7:0] } - { 1'b0, inpa[7:0]} - cin;
+ result = { {8{ rtemp[7]}}, rtemp[7:0]};
+ cout = rtemp[8];
+ end
+ else begin
+ rtemp = bAdd ? { 1'b0, inpb } + { 1'b0, inpa} + cin:
+ { 1'b0, inpb } - { 1'b0, inpa} - cin;
+ result = rtemp[ 15:0];
+ cout = rtemp[16];
+ end
+
+ rm = isByte ? rtemp[7] : rtemp[15];
+ dm = isByte ? inpb[ 7] : inpb[ 15];
+ tsm = isByte ? inpa[ 7] : inpa[ 15];
+ sm = bAdd ? tsm : ~tsm;
+
+ ov = (sm & dm & ~rm) | (~sm & ~dm & rm);
+
+ // Store half carry for bcd correction
+ subHcarry = inpa[4] ^ inpb[4] ^ rtemp[4];
+
+ end
+ endtask
+
+
+ // CCR flags process
+ always_comb begin
+
+ ccrTemp[XF] = pswCcr[XF]; ccrTemp[CF] = 0; ccrTemp[VF] = 0;
+
+ // Not on all operators !!!
+ ccrTemp[ ZF] = isByte ? ~(| result[7:0]) : ~(| result);
+ ccrTemp[ NF] = isByte ? result[7] : result[15];
+
+ unique case( oper)
+
+ OP_EXT:
+ // Division overflow.
+ if( aluColumn == 5) begin
+ ccrTemp[VF] = 1'b1; ccrTemp[NF] = 1'b1;
+ end
+
+ OP_SUB0, // used by NOT
+ OP_OR,
+ OP_EOR:
+ begin
+ ccrTemp[CF] = 0; ccrTemp[VF] = 0;
+ end
+
+ OP_AND:
+ begin
+ // ROXL/ROXR indeed copy X to C in column 1 (OP_AND), executed before entering the loop.
+ // Needed when rotate count is zero, the ucode with the ROX operator never reached.
+ // C must be set to the value of X, X remains unaffected.
+ if( (aluColumn == 1) & (row[11] | row[8]))
+ ccrTemp[CF] = pswCcr[XF];
+ else
+ ccrTemp[CF] = 0;
+ ccrTemp[VF] = 0;
+ end
+
+ // Assumes col 3 of DIV use C and not X !
+ // V will be set in other cols (2/3) of DIV
+ OP_SLAA: ccrTemp[ CF] = aOperand[15];
+
+ OP_LSL,OP_ROXL:
+ begin
+ ccrTemp[ CF] = shftMsb;
+ ccrTemp[ XF] = shftMsb;
+ ccrTemp[ VF] = 1'b0;
+ end
+
+ OP_LSR,OP_ROXR:
+ begin
+ // 0 Needed for mul, or carry gets in high word
+ ccrTemp[ CF] = shftIsMul ? 1'b0 : aOperand[0];
+ ccrTemp[ XF] = aOperand[0];
+ // Not relevant for MUL, we clear it at mulm6 (1f) anyway.
+ // Not that MUL can never overlow!
+ ccrTemp[ VF] = 0;
+ // Z is checking here ALU (low result is actually in ALUE).
+ // But it is correct, see comment above.
+ end
+
+ OP_ASL:
+ begin
+ ccrTemp[ XF] = shftMsb; ccrTemp[ CF] = shftMsb;
+ // V set if msb changed on any shift.
+ // Otherwise clear previously on OP_AND (col 1i).
+ ccrTemp[ VF] = pswCcr[VF] | (shftMsb ^
+ (isLong ? alue[15-1] : (isByte ? aOperand[7-1] : aOperand[15-1])) );
+ end
+ OP_ASR:
+ begin
+ ccrTemp[ XF] = aOperand[0]; ccrTemp[ CF] = aOperand[0];
+ ccrTemp[ VF] = 0;
+ end
+
+ // X not changed on ROL/ROR !
+ OP_ROL: ccrTemp[ CF] = shftMsb;
+ OP_ROR: ccrTemp[ CF] = aOperand[0];
+
+ OP_ADD,
+ OP_ADDC,
+ OP_ADDX,
+ OP_SUB,
+ OP_SUBC,
+ OP_SUBX:
+ begin
+ ccrTemp[ CF] = subCout;
+ ccrTemp[ XF] = subCout;
+ ccrTemp[ VF] = subOv;
+ end
+
+ OP_ABCD,
+ OP_SBCD:
+ begin
+ ccrTemp[ XF] = bcdCarry;
+ ccrTemp[ CF] = bcdCarry;
+ ccrTemp[ VF] = bcdOverf;
+ end
+
+ endcase
+
+ end
+
+ // Core and psw latched at the same cycle
+
+ // CCR filter
+ // CCR out mux for Z & C flags
+ // Z flag for 32-bit result
+ // Not described, but should be used also for instructions
+ // that clear but not set Z (ADDX/SUBX/ABCD, etc)!
+ logic [4:0] ccrMasked;
+ always_comb begin
+ ccrMasked = (ccrTemp & ccrMask) | (pswCcr & ~ccrMask);
+ if( finish | isCorf | isArX)
+ ccrMasked[ ZF] = ccrTemp[ ZF] & pswCcr[ ZF];
+ end
+
+ always_ff @( posedge clk) begin
+ if( enT3) begin
+ // Update latches from ALU operators
+ if( (| aluColumn)) begin
+ aluLatch <= result;
+
+ coreH <= subHcarry;
+
+ // Update CCR core
+ if( (| aluColumn))
+ ccrCore <= ccrTemp; // Most bits not really used
+ end
+
+ if( alueClkEn)
+ alue <= iDataBus;
+ else if( isShift & (| aluColumn))
+ alue <= shftResult[31:16];
+ end
+
+ // CCR
+ // Originally on T3-T4 edge pulse !!
+ // Might be possible to update on T4 (but not after T0) from partial result registered on T3, it will increase performance!
+ if( pwrUp)
+ pswCcr <= '0;
+ else if( enT3 & ftu2Ccr)
+ pswCcr <= ftu[4:0];
+ else if( enT3 & ~noCcrEn & (finish | init))
+ pswCcr <= ccrMasked;
+ end
+ assign ccr = { 3'b0, pswCcr};
+
+
+endmodule
+
+
diff --git a/common/CPU/68000/FX68k/fx68k_tb.sv b/common/CPU/68000/FX68k/fx68k_tb.sv
new file mode 100644
index 00000000..de558a77
--- /dev/null
+++ b/common/CPU/68000/FX68k/fx68k_tb.sv
@@ -0,0 +1,57 @@
+
+//
+// For compilation test only
+//
+
+module fx68k_tb( input clk32,
+ input extReset,
+ // input pwrUp,
+
+ input DTACKn, input VPAn,
+ input BERRn,
+ input BRn, BGACKn,
+ input IPL0n, input IPL1n, input IPL2n,
+ input [15:0] iEdb,
+
+ output [15:0] oEdb,
+ output eRWn, output ASn, output LDSn, output UDSn,
+ output logic E, output VMAn,
+ output FC0, output FC1, output FC2,
+ output BGn,
+ output oRESETn, output oHALTEDn,
+ output [23:1] eab
+ );
+
+ // Clock must be at least twice the desired frequency. A 32 MHz clock means a maximum 16 MHz effective frequency.
+ // In this example we divide the clock by 4. Resulting on an effective processor running at 8 MHz.
+
+ reg [1:0] clkDivisor = '0;
+ always @( posedge clk32) begin
+ clkDivisor <= clkDivisor + 1'b1;
+ end
+
+ /*
+ These two signals must be a single cycle pulse. They don't need to be registered.
+ Same signal can't be asserted twice in a row. Other than that there are no restrictions.
+ There can be any number of cycles, or none, even variable non constant cycles, between each pulse.
+ */
+
+ wire enPhi1 = (clkDivisor == 2'b11);
+ wire enPhi2 = (clkDivisor == 2'b01);
+
+
+ fx68k fx68k( .clk( clk32),
+ .extReset, .pwrUp( extReset), .enPhi1, .enPhi2,
+
+ .DTACKn, .VPAn, .BERRn, .BRn, .BGACKn,
+ .IPL0n, .IPL1n, .IPL2n,
+ .iEdb,
+
+ .oEdb,
+ .eRWn, .ASn, .LDSn, .UDSn,
+ .E, .VMAn,
+ .FC0, .FC1, .FC2,
+ .BGn,
+ .oRESETn, .oHALTEDn, .eab);
+
+endmodule
\ No newline at end of file
diff --git a/common/CPU/68000/FX68k/irdDecode.sv b/common/CPU/68000/FX68k/irdDecode.sv
new file mode 100644
index 00000000..0a3d193a
--- /dev/null
+++ b/common/CPU/68000/FX68k/irdDecode.sv
@@ -0,0 +1,208 @@
+//
+// IRD execution decoder. Complements nano code decoder
+//
+// IRD updated on T1, while ncode still executing. To avoid using the next IRD,
+// decoded signals must be registered on T3, or T4 before using them.
+//
+module irdDecode( input [15:0] ird,
+ output s_irdecod Irdecod);
+
+ wire [3:0] line = ird[15:12];
+ logic [15:0] lineOnehot;
+
+ // This can be registered and pipelined from the IR decoder !
+ onehotEncoder4 irdLines( line, lineOnehot);
+
+ wire isRegShift = (lineOnehot['he]) & (ird[7:6] != 2'b11);
+ wire isDynShift = isRegShift & ird[5];
+
+ assign Irdecod.isPcRel = (& ird[ 5:3]) & ~isDynShift & !ird[2] & ird[1];
+ assign Irdecod.isTas = lineOnehot[4] & (ird[11:6] == 6'b101011);
+
+ assign Irdecod.rx = ird[11:9];
+ assign Irdecod.ry = ird[ 2:0];
+
+ wire isPreDecr = (ird[ 5:3] == 3'b100);
+ wire eaAreg = (ird[5:3] == 3'b001);
+
+ // rx is A or D
+ // movem
+ always_comb begin
+ unique case( 1'b1)
+ lineOnehot[1],
+ lineOnehot[2],
+ lineOnehot[3]:
+ // MOVE: RX always Areg except if dest mode is Dn 000
+ Irdecod.rxIsAreg = (| ird[8:6]);
+
+ lineOnehot[4]: Irdecod.rxIsAreg = (& ird[8:6]); // not CHK (LEA)
+
+ lineOnehot['h8]: Irdecod.rxIsAreg = eaAreg & ird[8] & ~ird[7]; // SBCD
+ lineOnehot['hc]: Irdecod.rxIsAreg = eaAreg & ird[8] & ~ird[7]; // ABCD/EXG An,An
+
+ lineOnehot['h9],
+ lineOnehot['hb],
+ lineOnehot['hd]: Irdecod.rxIsAreg =
+ (ird[7] & ird[6]) | // SUBA/CMPA/ADDA
+ (eaAreg & ird[8] & (ird[7:6] != 2'b11)); // SUBX/CMPM/ADDX
+ default:
+ Irdecod.rxIsAreg = Irdecod.implicitSp;
+ endcase
+ end
+
+ // RX is movem
+ always_comb begin
+ Irdecod.rxIsMovem = lineOnehot[4] & ~ird[8] & ~Irdecod.implicitSp;
+ end
+ assign Irdecod.movemPreDecr = Irdecod.rxIsMovem & isPreDecr;
+
+ // RX is DT.
+ // but SSP explicit or pc explicit has higher priority!
+ // addq/subq (scc & dbcc also, but don't use rx)
+ // Immediate including static bit
+ assign Irdecod.rxIsDt = lineOnehot[5] | (lineOnehot[0] & ~ird[8]);
+
+ // RX is USP
+ assign Irdecod.rxIsUsp = lineOnehot[4] & (ird[ 11:4] == 8'he6);
+
+ // RY is DT
+ // rz or PC explicit has higher priority
+
+ wire eaImmOrAbs = (ird[5:3] == 3'b111) & ~ird[1];
+ assign Irdecod.ryIsDt = eaImmOrAbs & ~isRegShift;
+
+ // RY is Address register
+ always_comb begin
+ logic eaIsAreg;
+
+ // On most cases RY is Areg expect if mode is 000 (DATA REG) or 111 (IMM, ABS,PC REL)
+ eaIsAreg = (ird[5:3] != 3'b000) & (ird[5:3] != 3'b111);
+
+ unique case( 1'b1)
+ // MOVE: RY always Areg expect if mode is 000 (DATA REG) or 111 (IMM, ABS,PC REL)
+ // Most lines, including misc line 4, also.
+ default: Irdecod.ryIsAreg = eaIsAreg;
+
+ lineOnehot[5]: // DBcc is an exception
+ Irdecod.ryIsAreg = eaIsAreg & (ird[7:3] != 5'b11001);
+
+ lineOnehot[6],
+ lineOnehot[7]: Irdecod.ryIsAreg = 1'b0;
+
+ lineOnehot['he]:
+ Irdecod.ryIsAreg = ~isRegShift;
+ endcase
+ end
+
+ // Byte sized instruction
+
+ // Original implementation sets this for some instructions that aren't really byte size
+ // but doesn't matter because they don't have a byte transfer enabled at nanocode, such as MOVEQ
+
+ wire xIsScc = (ird[7:6] == 2'b11) & (ird[5:3] != 3'b001);
+ wire xStaticMem = (ird[11:8] == 4'b1000) & (ird[5:4] == 2'b00); // Static bit to mem
+ always_comb begin
+ unique case( 1'b1)
+ lineOnehot[0]:
+ Irdecod.isByte =
+ ( ird[8] & (ird[5:4] != 2'b00) ) | // Dynamic bit to mem
+ ( (ird[11:8] == 4'b1000) & (ird[5:4] != 2'b00) ) | // Static bit to mem
+ ( (ird[8:7] == 2'b10) & (ird[5:3] == 3'b001) ) | // Movep from mem only! For byte mux
+ ( (ird[8:6] == 3'b000) & !xStaticMem ); // Immediate byte
+
+ lineOnehot[1]: Irdecod.isByte = 1'b1; // MOVE.B
+
+
+ lineOnehot[4]: Irdecod.isByte = (ird[7:6] == 2'b00) | Irdecod.isTas;
+ lineOnehot[5]: Irdecod.isByte = (ird[7:6] == 2'b00) | xIsScc;
+
+ lineOnehot[8],
+ lineOnehot[9],
+ lineOnehot['hb],
+ lineOnehot['hc],
+ lineOnehot['hd],
+ lineOnehot['he]: Irdecod.isByte = (ird[7:6] == 2'b00);
+
+ default: Irdecod.isByte = 1'b0;
+ endcase
+ end
+
+ // Need it for special byte size. Bus is byte, but whole register word is modified.
+ assign Irdecod.isMovep = lineOnehot[0] & ird[8] & eaAreg;
+
+
+ // rxIsSP implicit use of RX for actual SP transfer
+ //
+ // This logic is simple and will include some instructions that don't actually reference SP.
+ // But doesn't matter as long as they don't perform any RX transfer.
+
+ always_comb begin
+ unique case( 1'b1)
+ lineOnehot[6]: Irdecod.implicitSp = (ird[11:8] == 4'b0001); // BSR
+ lineOnehot[4]:
+ // Misc like RTS, JSR, etc
+ Irdecod.implicitSp = (ird[11:8] == 4'b1110) | (ird[11:6] == 6'b1000_01);
+ default: Irdecod.implicitSp = 1'b0;
+ endcase
+ end
+
+ // Modify CCR (and not SR)
+ // Probably overkill !! Only needs to distinguish SR vs CCR
+ // RTR, MOVE to CCR, xxxI to CCR
+ assign Irdecod.toCcr = ( lineOnehot[4] & ((ird[11:0] == 12'he77) | (ird[11:6] == 6'b010011)) ) |
+ ( lineOnehot[0] & (ird[8:6] == 3'b000));
+
+ // FTU constants
+ // This should not be latched on T3/T4. Latch on T2 or not at all. FTU needs it on next T3.
+ // Note: Reset instruction gets constant from ALU not from FTU!
+ logic [15:0] ftuConst;
+ wire [3:0] zero28 = (ird[11:9] == 0) ? 4'h8 : { 1'b0, ird[11:9]}; // xltate 0,1-7 into 8,1-7
+
+ always_comb begin
+ unique case( 1'b1)
+ lineOnehot[6], // Bcc short
+ lineOnehot[7]: ftuConst = { { 8{ ird[ 7]}}, ird[ 7:0] }; // MOVEQ
+
+ lineOnehot['h5], // addq/subq/static shift double check this
+ lineOnehot['he]: ftuConst = { 12'b0, zero28};
+
+ // MULU/MULS DIVU/DIVS
+ lineOnehot['h8],
+ lineOnehot['hc]: ftuConst = 16'h0f;
+
+ lineOnehot[4]: ftuConst = 16'h80; // TAS
+
+ default: ftuConst = '0;
+ endcase
+ end
+ assign Irdecod.ftuConst = ftuConst;
+
+ //
+ // TRAP Vector # for group 2 exceptions
+ //
+
+ always_comb begin
+ if( lineOnehot[4]) begin
+ case ( ird[6:5])
+ 2'b00,2'b01: Irdecod.macroTvn = 6; // CHK
+ 2'b11: Irdecod.macroTvn = 7; // TRAPV
+ 2'b10: Irdecod.macroTvn = {2'b10, ird[3:0]}; // TRAP
+ endcase
+ end
+ else
+ Irdecod.macroTvn = 5; // Division by zero
+ end
+
+
+ wire eaAdir = (ird[ 5:3] == 3'b001);
+ wire size11 = ird[7] & ird[6];
+
+ // Opcodes variants that don't affect flags
+ // ADDA/SUBA ADDQ/SUBQ MOVEA
+
+ assign Irdecod.inhibitCcr =
+ ( (lineOnehot[9] | lineOnehot['hd]) & size11) | // ADDA/SUBA
+ ( lineOnehot[5] & eaAdir) | // ADDQ/SUBQ to An (originally checks for line[4] as well !?)
+ ( (lineOnehot[2] | lineOnehot[3]) & ird[8:6] == 3'b001); // MOVEA
+
+endmodule
\ No newline at end of file
diff --git a/common/CPU/68000/FX68k/microToNanoAddr.sv b/common/CPU/68000/FX68k/microToNanoAddr.sv
new file mode 100644
index 00000000..0113eb96
--- /dev/null
+++ b/common/CPU/68000/FX68k/microToNanoAddr.sv
@@ -0,0 +1,157 @@
+// Translate uaddr to nanoaddr
+module microToNanoAddr(
+ input [UADDR_WIDTH-1:0] uAddr,
+ output [NADDR_WIDTH-1:0] orgAddr);
+
+ wire [UADDR_WIDTH-1:2] baseAddr = uAddr[UADDR_WIDTH-1:2];
+ logic [NADDR_WIDTH-1:2] orgBase;
+ assign orgAddr = { orgBase, uAddr[1:0]};
+
+ always @( baseAddr)
+ begin
+ // nano ROM (136 addresses)
+ case( baseAddr)
+
+'h00: orgBase = 7'h0 ;
+'h01: orgBase = 7'h1 ;
+'h02: orgBase = 7'h2 ;
+'h03: orgBase = 7'h2 ;
+'h08: orgBase = 7'h3 ;
+'h09: orgBase = 7'h4 ;
+'h0A: orgBase = 7'h5 ;
+'h0B: orgBase = 7'h5 ;
+'h10: orgBase = 7'h6 ;
+'h11: orgBase = 7'h7 ;
+'h12: orgBase = 7'h8 ;
+'h13: orgBase = 7'h8 ;
+'h18: orgBase = 7'h9 ;
+'h19: orgBase = 7'hA ;
+'h1A: orgBase = 7'hB ;
+'h1B: orgBase = 7'hB ;
+'h20: orgBase = 7'hC ;
+'h21: orgBase = 7'hD ;
+'h22: orgBase = 7'hE ;
+'h23: orgBase = 7'hD ;
+'h28: orgBase = 7'hF ;
+'h29: orgBase = 7'h10 ;
+'h2A: orgBase = 7'h11 ;
+'h2B: orgBase = 7'h10 ;
+'h30: orgBase = 7'h12 ;
+'h31: orgBase = 7'h13 ;
+'h32: orgBase = 7'h14 ;
+'h33: orgBase = 7'h14 ;
+'h38: orgBase = 7'h15 ;
+'h39: orgBase = 7'h16 ;
+'h3A: orgBase = 7'h17 ;
+'h3B: orgBase = 7'h17 ;
+'h40: orgBase = 7'h18 ;
+'h41: orgBase = 7'h18 ;
+'h42: orgBase = 7'h18 ;
+'h43: orgBase = 7'h18 ;
+'h44: orgBase = 7'h19 ;
+'h45: orgBase = 7'h19 ;
+'h46: orgBase = 7'h19 ;
+'h47: orgBase = 7'h19 ;
+'h48: orgBase = 7'h1A ;
+'h49: orgBase = 7'h1A ;
+'h4A: orgBase = 7'h1A ;
+'h4B: orgBase = 7'h1A ;
+'h4C: orgBase = 7'h1B ;
+'h4D: orgBase = 7'h1B ;
+'h4E: orgBase = 7'h1B ;
+'h4F: orgBase = 7'h1B ;
+'h54: orgBase = 7'h1C ;
+'h55: orgBase = 7'h1D ;
+'h56: orgBase = 7'h1E ;
+'h57: orgBase = 7'h1F ;
+'h5C: orgBase = 7'h20 ;
+'h5D: orgBase = 7'h21 ;
+'h5E: orgBase = 7'h22 ;
+'h5F: orgBase = 7'h23 ;
+'h70: orgBase = 7'h24 ;
+'h71: orgBase = 7'h24 ;
+'h72: orgBase = 7'h24 ;
+'h73: orgBase = 7'h24 ;
+'h74: orgBase = 7'h24 ;
+'h75: orgBase = 7'h24 ;
+'h76: orgBase = 7'h24 ;
+'h77: orgBase = 7'h24 ;
+'h78: orgBase = 7'h25 ;
+'h79: orgBase = 7'h25 ;
+'h7A: orgBase = 7'h25 ;
+'h7B: orgBase = 7'h25 ;
+'h7C: orgBase = 7'h25 ;
+'h7D: orgBase = 7'h25 ;
+'h7E: orgBase = 7'h25 ;
+'h7F: orgBase = 7'h25 ;
+'h84: orgBase = 7'h26 ;
+'h85: orgBase = 7'h27 ;
+'h86: orgBase = 7'h28 ;
+'h87: orgBase = 7'h29 ;
+'h8C: orgBase = 7'h2A ;
+'h8D: orgBase = 7'h2B ;
+'h8E: orgBase = 7'h2C ;
+'h8F: orgBase = 7'h2D ;
+'h94: orgBase = 7'h2E ;
+'h95: orgBase = 7'h2F ;
+'h96: orgBase = 7'h30 ;
+'h97: orgBase = 7'h31 ;
+'h9C: orgBase = 7'h32 ;
+'h9D: orgBase = 7'h33 ;
+'h9E: orgBase = 7'h34 ;
+'h9F: orgBase = 7'h35 ;
+'hA4: orgBase = 7'h36 ;
+'hA5: orgBase = 7'h36 ;
+'hA6: orgBase = 7'h37 ;
+'hA7: orgBase = 7'h37 ;
+'hAC: orgBase = 7'h38 ;
+'hAD: orgBase = 7'h38 ;
+'hAE: orgBase = 7'h39 ;
+'hAF: orgBase = 7'h39 ;
+'hB4: orgBase = 7'h3A ;
+'hB5: orgBase = 7'h3A ;
+'hB6: orgBase = 7'h3B ;
+'hB7: orgBase = 7'h3B ;
+'hBC: orgBase = 7'h3C ;
+'hBD: orgBase = 7'h3C ;
+'hBE: orgBase = 7'h3D ;
+'hBF: orgBase = 7'h3D ;
+'hC0: orgBase = 7'h3E ;
+'hC1: orgBase = 7'h3F ;
+'hC2: orgBase = 7'h40 ;
+'hC3: orgBase = 7'h41 ;
+'hC8: orgBase = 7'h42 ;
+'hC9: orgBase = 7'h43 ;
+'hCA: orgBase = 7'h44 ;
+'hCB: orgBase = 7'h45 ;
+'hD0: orgBase = 7'h46 ;
+'hD1: orgBase = 7'h47 ;
+'hD2: orgBase = 7'h48 ;
+'hD3: orgBase = 7'h49 ;
+'hD8: orgBase = 7'h4A ;
+'hD9: orgBase = 7'h4B ;
+'hDA: orgBase = 7'h4C ;
+'hDB: orgBase = 7'h4D ;
+'hE0: orgBase = 7'h4E ;
+'hE1: orgBase = 7'h4E ;
+'hE2: orgBase = 7'h4F ;
+'hE3: orgBase = 7'h4F ;
+'hE8: orgBase = 7'h50 ;
+'hE9: orgBase = 7'h50 ;
+'hEA: orgBase = 7'h51 ;
+'hEB: orgBase = 7'h51 ;
+'hF0: orgBase = 7'h52 ;
+'hF1: orgBase = 7'h52 ;
+'hF2: orgBase = 7'h52 ;
+'hF3: orgBase = 7'h52 ;
+'hF8: orgBase = 7'h53 ;
+'hF9: orgBase = 7'h53 ;
+'hFA: orgBase = 7'h53 ;
+'hFB: orgBase = 7'h53 ;
+
+ default:
+ orgBase = 'X;
+ endcase
+ end
+
+endmodule
\ No newline at end of file
diff --git a/common/CPU/68000/FX68k/microrom.mem b/common/CPU/68000/FX68k/microrom.mem
new file mode 100644
index 00000000..9fc7cb1e
--- /dev/null
+++ b/common/CPU/68000/FX68k/microrom.mem
@@ -0,0 +1,1024 @@
+10010000101100000
+10000100000000000
+00101001011010000
+00111110011000000
+01000000000001100
+01000000000001100
+01000010010000000
+10001100011100000
+01000100010000000
+10000000010000000
+10000000010000000
+01000100010000000
+00001010010000000
+10000000100000000
+10000000100000000
+01101001100000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000100
+00001010110000000
+00111000001100000
+00100101001001010
+00000000000001100
+10110000110100001
+00000000000001100
+00001110100000000
+00110100101000000
+00100011010100000
+00000010010000000
+10000110000000010
+00111110110000000
+00000100011100000
+00101111010100000
+10010011100000010
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+10011101000000000
+00000100110010110
+00101001010000000
+10110000110100001
+00000000000000100
+00111110000100000
+10010111010100000
+01000110000100000
+01010111100000000
+10001010010011010
+01000110010100001
+00000110010111010
+01001100010100000
+10001010010010111
+01000000000100001
+00110100111000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000010001100000
+01001010000100001
+10110100111000000
+00011011010100000
+10000000000000100
+10110100111000000
+00000000000000100
+00001000001000000
+00000100011100110
+10001110010100001
+00000000011110010
+01001000011000000
+00001000010100110
+10001010000110111
+00000000111110010
+01001000111000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+10101001000000001
+10001000001000001
+01000000000000100
+01001100001111010
+00000110001000000
+00010110001100000
+00011010000000000
+10110000110100001
+01111000001100000
+00011000000000000
+00000100100100001
+00000000000000100
+00000000101100000
+00000000000000100
+00010001010100000
+10010111000100001
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000010001100000
+00000000000000100
+01111000011100000
+00011011010100000
+00101101000000000
+01000110010111010
+00101101000000000
+10001010101100000
+01010110001100000
+00011000110000000
+01010110001100000
+10001110011100001
+00000100101100000
+01000110010111010
+00000100101100000
+10001010111100000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+10101001000000001
+00001000101010110
+00011111010100000
+01101101110000000
+00000000000000100
+10111110000100000
+00000100011100000
+10001100101000001
+00000110001000000
+00001110000010010
+00100101000010110
+00101101000100000
+00000000011100000
+00001000111100000
+00100101000011010
+00110100111000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000010000100010
+00001010110000000
+00000000000000100
+00101101010000000
+01010001010000000
+01000110111000000
+00000000000000100
+00000000010110010
+00110100101000000
+00100011010100000
+10000000000001000
+01101011010000000
+00111110110000000
+00000100011100000
+10010101000000000
+01111110010100000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+10001100101000001
+10000010100000010
+01000010101000000
+00011111100100000
+10100111100000001
+10010010110000010
+01110100111000000
+00010111010000000
+10101011100000001
+10010010100000010
+01110000100100000
+00000000100100000
+10100101100100001
+10000010110000010
+01001010101000000
+00010111000000000
+00010001000010110
+01110010100111010
+10110100010000000
+00110100111000000
+01000010010000110
+01110010110111011
+01111100000000000
+00101101000100000
+00101001001010001
+01011011111100000
+01101111011000000
+00100011100000000
+00111110000110000
+00000000000000000
+10101111011000000
+00000000000000000
+00001010100000000
+10101011100100001
+01010011000100001
+10010101010000000
+00000000110000000
+10111010000100001
+01011001010000000
+10010101000000000
+00101101101100000
+10100011100100001
+01011110100000000
+01110100011100000
+00101011111000000
+10110000110100001
+01010101010100001
+00000000000000000
+00111000100000000
+01011011000000000
+00001000100100000
+10001100101000001
+00100001100000000
+01011011010000000
+00001000110100000
+10011001110100001
+00000110010111010
+01011011100000000
+00000000110100000
+10011101010000001
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+10110000110100001
+00011101000100000
+00011101000100000
+00010001000101110
+01011010110000000
+01011001010100000
+10011101010100000
+00000000000000100
+10110000110100001
+00110110000000000
+10110000011100001
+10110000011100001
+10011101000000001
+01110100111000000
+00101101100100000
+10011000100000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+10000000000000100
+00000000000000100
+00000100111000000
+00000100111000000
+00000100111000000
+00001100010101010
+00001000000010110
+00101001010000000
+10011000100000000
+00011011100100000
+01000100010000000
+01000000000001100
+10011000010000001
+10011011110100000
+10011111110100001
+00011000010000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00111110001000000
+10101011100100001
+10001010100000000
+10101011100100001
+00100011010000000
+10110000001100001
+10000000110000000
+10110000101100001
+00000000000000000
+10110000101100001
+10110110110100000
+10100001110100001
+00111100010000000
+10011101100000001
+10111110100100000
+10010011010100001
+00111100010100000
+10101011100000001
+10101001101000000
+10101011100000001
+00000000000000000
+10011111000100001
+10101001111000000
+10011011000100001
+00000000000000000
+10010011010100001
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00001010100000000
+10111110000100000
+10000100100000000
+00111010001100000
+00000000110000000
+10011001000000000
+10000100110000000
+00111010011100000
+00101101101100000
+10001110111000000
+10101111101000000
+00010100100000000
+00101011111000000
+10110100001100000
+10101111111000000
+00010100010000000
+00111000100000000
+10110100101100000
+10101001010100000
+00101011001000000
+00100001100000000
+10001110010000000
+10101111001000000
+00101011011000000
+00000110010111010
+10111000110000000
+10011101110100000
+00111010101100000
+00000000000000000
+10101011011100000
+01100011110100001
+00111010111100000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00100101000000000
+00000100000010110
+00000000000000100
+00001110000001110
+00100001000000000
+10110000110100001
+00100101011001010
+00111000001100000
+00100101100000001
+10011000010000000
+01101101100000000
+00000000000001100
+01100101110000000
+00000000000001100
+00001100001111010
+01001100001111010
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+10101111000000001
+00000100111000000
+10101111000000001
+00000000000000100
+00100111010000000
+00001110101100000
+11010001100000000
+00110010100111010
+00000000000000100
+00000100111000000
+00000000000000100
+10110000110100001
+01100111110000001
+10000000000000100
+01111100100100000
+01100001100100001
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000001100000
+10001010010100001
+00110110100000110
+00000000000000100
+00100001000000000
+10111110000100000
+10100111000100000
+00111000010000000
+10000000000000100
+00101001100100000
+00101101100100000
+00000000000000100
+00100101110100000
+00000000000000100
+00100101110100000
+00100101110100000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+10100111000100000
+01101011000100000
+01111110000100001
+10100111000100000
+10100111001000000
+10111110000100000
+00101111010000000
+00110010100111010
+00000000000000100
+10100011100100001
+00000000000000100
+00000010011100001
+10100111110100000
+00000000000000100
+00101111110100000
+00101111101100000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00100101001000000
+00101001000010110
+00110010000100000
+00100011000100000
+00100101011000000
+00101001011100000
+00101011110110000
+00101111001000000
+00010100000000000
+10110100111000001
+01110010100100000
+10110000110100001
+00010100110000000
+10110100110100001
+01111000110100000
+10111110110100001
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00100011010100000
+00100111000100000
+00000110100000010
+10111110000100000
+00000100011100000
+00110000110000000
+00000110110000010
+10010001110000000
+10110100111000001
+10000000000001000
+01110000100100000
+10110100101000000
+10010101110100001
+10111110000100000
+01101101111100000
+10101011101000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00101001000010110
+10001010011100001
+00100001000000110
+00101101000000110
+00101001011100000
+10001010011100001
+00110110111000110
+00101101010000110
+10001100101000001
+10110100101000000
+10101101101100000
+01111110000100001
+10100101100100001
+10101011101000000
+10101011111000000
+01100001100100001
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00110010100111010
+10001010010100001
+10110100100000000
+10110100111000001
+01110010110111010
+10001010010100001
+10101011010100000
+10110100110100001
+10111100100100001
+01101111110000000
+01000110010000001
+10101111111100000
+10101011110000001
+01100011110000000
+01110100100100001
+10110000000000000
+10011001110000000
+00110110000000000
+00101111001000000
+10111110000100000
+00110100111000000
+10001100100100000
+00000000000000100
+00110010000000000
+00000100010100110
+00111110000100000
+00111110000100000
+10100111011000000
+01110100110000001
+01110100100100000
+10010101000000000
+10110110100000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00110110000000000
+00010110001100000
+00000110010111010
+00000110010111010
+00110100111000000
+10111010010000000
+00001110110000000
+00000000000000100
+10110000110100001
+01111010100000000
+01010110001100001
+10111010110000000
+10110000110100000
+00100001010001010
+01010110001100001
+01110000100100000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000100111000000
+10111000000100001
+00000000000000100
+00110000010100000
+01111110000100000
+10111000010100001
+00000000000000100
+00111000001100000
+01111110000100000
+10000000000000100
+01111100100100000
+01000000000000100
+00000000000000100
+01110100111000000
+01111100110100000
+01110010100100000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+01001110111100000
+00000000000000100
+00000000000000100
+10110000110100001
+00000000000000000
+00000000000000000
+00000000000000000
+01011001100000000
+01111010100100001
+00000000001001010
+10000000000000100
+01110010110100000
+01110110110100000
+01111010110100001
+01111110000100000
+00000000000000100
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+10001100110100111
+10111100001000001
+10111100001000001
+00101101000000110
+10001100101100111
+10111100011000001
+10111100011000001
+00101101010000110
+10110100101000000
+01111110000100000
+10110100101000000
+10111100100100001
+10111110110000000
+01000000000000100
+10111110110000000
+10111000100100001
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+10111110000000000
+10110010010000001
+00111110010000001
+00111000001100000
+10101001110000000
+10110000000100001
+00101111100100000
+00111000101110000
+00110010100111010
+01111010101000000
+01000110010000001
+01000110010000000
+01110010110111010
+01111010111000000
+01110100100100001
+01110100100100001
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00101001110100000
+10001100100100000
+01110010000100000
+10110000110100001
+00000010000011110
+01111000000000000
+01000000101000000
+10110000010000001
+00101101110100000
+10111010000000000
+01001010001000000
+10110110000100001
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+10100111101000000
+00000000000000000
+10010010000000010
+10100111000000001
+10100111111000000
+00000000000000000
+10010010010000010
+10001110011100001
+00100011001100000
+00100001001001010
+10010011000000010
+10001010110100001
+01100011011100000
+00100001011001010
+10010011010000010
+10001010100100001
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
+00000000000000000
diff --git a/common/CPU/68000/FX68k/nDecoder3.sv b/common/CPU/68000/FX68k/nDecoder3.sv
new file mode 100644
index 00000000..8b6f9759
--- /dev/null
+++ b/common/CPU/68000/FX68k/nDecoder3.sv
@@ -0,0 +1,274 @@
+// Nanorom (plus) decoder for die nanocode
+module nDecoder3( input s_clks Clks, input s_irdecod Irdecod, output s_nanod Nanod,
+ input enT2, enT4,
+ input [UROM_WIDTH-1:0] microLatch,
+ input [NANO_WIDTH-1:0] nanoLatch);
+
+localparam NANO_IR2IRD = 67;
+localparam NANO_TOIRC = 66;
+localparam NANO_ALU_COL = 63; // ALU operator column order is 63-64-65 !
+localparam NANO_ALU_FI = 61; // ALU finish-init 62-61
+localparam NANO_TODBIN = 60;
+localparam NANO_ALUE = 57; // 57-59 shared with DCR control
+localparam NANO_DCR = 57; // 57-59 shared with ALUE control
+localparam NANO_DOBCTRL_1 = 56; // Input to control and permwrite
+localparam NANO_LOWBYTE = 55; // Used by MOVEP
+localparam NANO_HIGHBYTE = 54;
+localparam NANO_DOBCTRL_0 = 53; // Input to control and permwrite
+localparam NANO_ALU_DCTRL = 51; // 52-51 databus input mux control
+localparam NANO_ALU_ACTRL = 50; // addrbus input mux control
+localparam NANO_DBD2ALUB = 49;
+localparam NANO_ABD2ALUB = 48;
+localparam NANO_DBIN2DBD = 47;
+localparam NANO_DBIN2ABD = 46;
+localparam NANO_ALU2ABD = 45;
+localparam NANO_ALU2DBD = 44;
+localparam NANO_RZ = 43;
+localparam NANO_BUSBYTE = 42; // If *both* this set and instruction is byte sized, then bus cycle is byte sized.
+localparam NANO_PCLABL = 41;
+localparam NANO_RXL_DBL = 40; // Switches RXL/RYL on DBL/ABL buses
+localparam NANO_PCLDBL = 39;
+localparam NANO_ABDHRECHARGE = 38;
+localparam NANO_REG2ABL = 37; // register to ABL
+localparam NANO_ABL2REG = 36; // ABL to register
+localparam NANO_ABLABD = 35;
+localparam NANO_DBLDBD = 34;
+localparam NANO_DBL2REG = 33; // DBL to register
+localparam NANO_REG2DBL = 32; // register to DBL
+localparam NANO_ATLCTRL = 29; // 31-29
+localparam NANO_FTUCONTROL = 25;
+localparam NANO_SSP = 24;
+localparam NANO_RXH_DBH = 22; // Switches RXH/RYH on DBH/ABH buses
+localparam NANO_AUOUT = 20; // 21-20
+localparam NANO_AUCLKEN = 19;
+localparam NANO_AUCTRL = 16; // 18-16
+localparam NANO_DBLDBH = 15;
+localparam NANO_ABLABH = 14;
+localparam NANO_EXT_ABH = 13;
+localparam NANO_EXT_DBH = 12;
+localparam NANO_ATHCTRL = 9; // 11-9
+localparam NANO_REG2ABH = 8; // register to ABH
+localparam NANO_ABH2REG = 7; // ABH to register
+localparam NANO_REG2DBH = 6; // register to DBH
+localparam NANO_DBH2REG = 5; // DBH to register
+localparam NANO_AOBCTRL = 3; // 4-3
+localparam NANO_PCH = 0; // 1-0 PchDbh PchAbh
+localparam NANO_NO_SP_ALGN = 0; // Same bits as above when both set
+
+localparam NANO_FTU_UPDTPEND = 1; // Also loads FTU constant according to IRD !
+localparam NANO_FTU_INIT_ST = 15; // Set S, clear T (but not TPEND)
+localparam NANO_FTU_CLRTPEND = 14;
+localparam NANO_FTU_TVN = 13;
+localparam NANO_FTU_ABL2PREN = 12; // ABL => FTU & ABL => PREN. Both transfers enabled, but only one will be used depending on uroutine.
+localparam NANO_FTU_SSW = 11;
+localparam NANO_FTU_RSTPREN = 10;
+localparam NANO_FTU_IRD = 9;
+localparam NANO_FTU_2ABL = 8;
+localparam NANO_FTU_RDSR = 7;
+localparam NANO_FTU_INL = 6;
+localparam NANO_FTU_PSWI = 5; // Read Int Mask into FTU
+localparam NANO_FTU_DBL = 4;
+localparam NANO_FTU_2SR = 2;
+localparam NANO_FTU_CONST = 1;
+
+ reg [3:0] ftuCtrl;
+
+ logic [2:0] athCtrl, atlCtrl;
+ assign athCtrl = nanoLatch[ NANO_ATHCTRL+2: NANO_ATHCTRL];
+ assign atlCtrl = nanoLatch[ NANO_ATLCTRL+2: NANO_ATLCTRL];
+ wire [1:0] aobCtrl = nanoLatch[ NANO_AOBCTRL+1:NANO_AOBCTRL];
+ wire [1:0] dobCtrl = {nanoLatch[ NANO_DOBCTRL_1], nanoLatch[NANO_DOBCTRL_0]};
+
+ always_ff @( posedge Clks.clk) begin
+ if( enT4) begin
+ // Reverse order!
+ ftuCtrl <= { nanoLatch[ NANO_FTUCONTROL+0], nanoLatch[ NANO_FTUCONTROL+1], nanoLatch[ NANO_FTUCONTROL+2], nanoLatch[ NANO_FTUCONTROL+3]} ;
+
+ Nanod.auClkEn <= !nanoLatch[ NANO_AUCLKEN];
+ Nanod.auCntrl <= nanoLatch[ NANO_AUCTRL+2 : NANO_AUCTRL+0];
+ Nanod.noSpAlign <= (nanoLatch[ NANO_NO_SP_ALGN + 1:NANO_NO_SP_ALGN] == 2'b11);
+ Nanod.extDbh <= nanoLatch[ NANO_EXT_DBH];
+ Nanod.extAbh <= nanoLatch[ NANO_EXT_ABH];
+ Nanod.todbin <= nanoLatch[ NANO_TODBIN];
+ Nanod.toIrc <= nanoLatch[ NANO_TOIRC];
+
+ // ablAbd is disabled on byte transfers (adbhCharge plus irdIsByte). Not sure the combination makes much sense.
+ // It happens in a few cases but I don't see anything enabled on abL (or abH) section anyway.
+
+ Nanod.ablAbd <= nanoLatch[ NANO_ABLABD];
+ Nanod.ablAbh <= nanoLatch[ NANO_ABLABH];
+ Nanod.dblDbd <= nanoLatch[ NANO_DBLDBD];
+ Nanod.dblDbh <= nanoLatch[ NANO_DBLDBH];
+
+ Nanod.dbl2Atl <= (atlCtrl == 3'b010);
+ Nanod.atl2Dbl <= (atlCtrl == 3'b011);
+ Nanod.abl2Atl <= (atlCtrl == 3'b100);
+ Nanod.atl2Abl <= (atlCtrl == 3'b101);
+
+ Nanod.aob2Ab <= (athCtrl == 3'b101); // Used on BSER1 only
+
+ Nanod.abh2Ath <= (athCtrl == 3'b001) | (athCtrl == 3'b101);
+ Nanod.dbh2Ath <= (athCtrl == 3'b100);
+ Nanod.ath2Dbh <= (athCtrl == 3'b110);
+ Nanod.ath2Abh <= (athCtrl == 3'b011);
+
+ Nanod.alu2Dbd <= nanoLatch[ NANO_ALU2DBD];
+ Nanod.alu2Abd <= nanoLatch[ NANO_ALU2ABD];
+
+ Nanod.abd2Dcr <= (nanoLatch[ NANO_DCR+1:NANO_DCR] == 2'b11);
+ Nanod.dcr2Dbd <= (nanoLatch[ NANO_DCR+2:NANO_DCR+1] == 2'b11);
+ Nanod.dbd2Alue <= (nanoLatch[ NANO_ALUE+2:NANO_ALUE+1] == 2'b10);
+ Nanod.alue2Dbd <= (nanoLatch[ NANO_ALUE+1:NANO_ALUE] == 2'b01);
+
+ Nanod.dbd2Alub <= nanoLatch[ NANO_DBD2ALUB];
+ Nanod.abd2Alub <= nanoLatch[ NANO_ABD2ALUB];
+
+ // Originally not latched. We better should because we transfer one cycle later, T3 instead of T1.
+ Nanod.dobCtrl <= dobCtrl;
+ // Nanod.adb2Dob <= (dobCtrl == 2'b10); Nanod.dbd2Dob <= (dobCtrl == 2'b01); Nanod.alu2Dob <= (dobCtrl == 2'b11);
+
+ end
+ end
+
+ // Update SSW at the start of Bus/Addr error ucode
+ assign Nanod.updSsw = Nanod.aob2Ab;
+
+ assign Nanod.updTpend = (ftuCtrl == NANO_FTU_UPDTPEND);
+ assign Nanod.clrTpend = (ftuCtrl == NANO_FTU_CLRTPEND);
+ assign Nanod.tvn2Ftu = (ftuCtrl == NANO_FTU_TVN);
+ assign Nanod.const2Ftu = (ftuCtrl == NANO_FTU_CONST);
+ assign Nanod.ftu2Dbl = (ftuCtrl == NANO_FTU_DBL) | ( ftuCtrl == NANO_FTU_INL);
+ assign Nanod.ftu2Abl = (ftuCtrl == NANO_FTU_2ABL);
+ assign Nanod.inl2psw = (ftuCtrl == NANO_FTU_INL);
+ assign Nanod.pswIToFtu = (ftuCtrl == NANO_FTU_PSWI);
+ assign Nanod.ftu2Sr = (ftuCtrl == NANO_FTU_2SR);
+ assign Nanod.sr2Ftu = (ftuCtrl == NANO_FTU_RDSR);
+ assign Nanod.ird2Ftu = (ftuCtrl == NANO_FTU_IRD); // Used on bus/addr error
+ assign Nanod.ssw2Ftu = (ftuCtrl == NANO_FTU_SSW);
+ assign Nanod.initST = (ftuCtrl == NANO_FTU_INL) | (ftuCtrl == NANO_FTU_CLRTPEND) | (ftuCtrl == NANO_FTU_INIT_ST);
+ assign Nanod.abl2Pren = (ftuCtrl == NANO_FTU_ABL2PREN);
+ assign Nanod.updPren = (ftuCtrl == NANO_FTU_RSTPREN);
+
+ assign Nanod.Ir2Ird = nanoLatch[ NANO_IR2IRD];
+
+ // ALU control better latched later after combining with IRD decoding
+
+ assign Nanod.aluDctrl = nanoLatch[ NANO_ALU_DCTRL+1 : NANO_ALU_DCTRL];
+ assign Nanod.aluActrl = nanoLatch[ NANO_ALU_ACTRL];
+ assign Nanod.aluColumn = { nanoLatch[ NANO_ALU_COL], nanoLatch[ NANO_ALU_COL+1], nanoLatch[ NANO_ALU_COL+2]};
+ wire [1:0] aluFinInit = nanoLatch[ NANO_ALU_FI+1:NANO_ALU_FI];
+ assign Nanod.aluFinish = (aluFinInit == 2'b10);
+ assign Nanod.aluInit = (aluFinInit == 2'b01);
+
+ // FTU 2 CCR encoded as both ALU Init and ALU Finish set.
+ // In theory this encoding allows writes to CCR without writing to SR
+ // But FTU 2 CCR and to SR are both set together at nanorom.
+ assign Nanod.ftu2Ccr = ( aluFinInit == 2'b11);
+
+ assign Nanod.abdIsByte = nanoLatch[ NANO_ABDHRECHARGE];
+
+ // Not being latched on T4 creates non unique case warning!
+ assign Nanod.au2Db = (nanoLatch[ NANO_AUOUT + 1: NANO_AUOUT] == 2'b01);
+ assign Nanod.au2Ab = (nanoLatch[ NANO_AUOUT + 1: NANO_AUOUT] == 2'b10);
+ assign Nanod.au2Pc = (nanoLatch[ NANO_AUOUT + 1: NANO_AUOUT] == 2'b11);
+
+ assign Nanod.db2Aob = (aobCtrl == 2'b10);
+ assign Nanod.ab2Aob = (aobCtrl == 2'b01);
+ assign Nanod.au2Aob = (aobCtrl == 2'b11);
+
+ assign Nanod.dbin2Abd = nanoLatch[ NANO_DBIN2ABD];
+ assign Nanod.dbin2Dbd = nanoLatch[ NANO_DBIN2DBD];
+
+ assign Nanod.permStart = (| aobCtrl);
+ assign Nanod.isWrite = ( | dobCtrl);
+ assign Nanod.waitBusFinish = nanoLatch[ NANO_TOIRC] | nanoLatch[ NANO_TODBIN] | Nanod.isWrite;
+ assign Nanod.busByte = nanoLatch[ NANO_BUSBYTE];
+
+ assign Nanod.noLowByte = nanoLatch[ NANO_LOWBYTE];
+ assign Nanod.noHighByte = nanoLatch[ NANO_HIGHBYTE];
+
+ // Not registered. Register at T4 after combining
+ // Might be better to remove all those and combine here instead of at execution unit !!
+ assign Nanod.abl2reg = nanoLatch[ NANO_ABL2REG];
+ assign Nanod.abh2reg = nanoLatch[ NANO_ABH2REG];
+ assign Nanod.dbl2reg = nanoLatch[ NANO_DBL2REG];
+ assign Nanod.dbh2reg = nanoLatch[ NANO_DBH2REG];
+ assign Nanod.reg2dbl = nanoLatch[ NANO_REG2DBL];
+ assign Nanod.reg2dbh = nanoLatch[ NANO_REG2DBH];
+ assign Nanod.reg2abl = nanoLatch[ NANO_REG2ABL];
+ assign Nanod.reg2abh = nanoLatch[ NANO_REG2ABH];
+
+ assign Nanod.ssp = nanoLatch[ NANO_SSP];
+
+ assign Nanod.rz = nanoLatch[ NANO_RZ];
+
+ // Actually DTL can't happen on PC relative mode. See IR decoder.
+
+ wire dtldbd = 1'b0;
+ wire dthdbh = 1'b0;
+ wire dtlabd = 1'b0;
+ wire dthabh = 1'b0;
+
+ wire dblSpecial = Nanod.pcldbl | dtldbd;
+ wire dbhSpecial = Nanod.pchdbh | dthdbh;
+ wire ablSpecial = Nanod.pclabl | dtlabd;
+ wire abhSpecial = Nanod.pchabh | dthabh;
+
+ //
+ // Combine with IRD decoding
+ // Careful that IRD is updated only on T1! All output depending on IRD must be latched on T4!
+ //
+
+ // PC used instead of RY on PC relative instuctions
+
+ assign Nanod.rxlDbl = nanoLatch[ NANO_RXL_DBL];
+ wire isPcRel = Irdecod.isPcRel & !Nanod.rz;
+ wire pcRelDbl = isPcRel & !nanoLatch[ NANO_RXL_DBL];
+ wire pcRelDbh = isPcRel & !nanoLatch[ NANO_RXH_DBH];
+ wire pcRelAbl = isPcRel & nanoLatch[ NANO_RXL_DBL];
+ wire pcRelAbh = isPcRel & nanoLatch[ NANO_RXH_DBH];
+
+ assign Nanod.pcldbl = nanoLatch[ NANO_PCLDBL] | pcRelDbl;
+ assign Nanod.pchdbh = (nanoLatch[ NANO_PCH+1:NANO_PCH] == 2'b01) | pcRelDbh;
+
+ assign Nanod.pclabl = nanoLatch[ NANO_PCLABL] | pcRelAbl;
+ assign Nanod.pchabh = (nanoLatch[ NANO_PCH+1:NANO_PCH] == 2'b10) | pcRelAbh;
+
+ // Might be better not to register these signals to allow latching RX/RY mux earlier!
+ // But then must latch Irdecod.isPcRel on T3!
+
+ always_ff @( posedge Clks.clk) begin
+ if( enT4) begin
+ Nanod.rxl2db <= Nanod.reg2dbl & !dblSpecial & nanoLatch[ NANO_RXL_DBL];
+ Nanod.rxl2ab <= Nanod.reg2abl & !ablSpecial & !nanoLatch[ NANO_RXL_DBL];
+
+ Nanod.dbl2rxl <= Nanod.dbl2reg & !dblSpecial & nanoLatch[ NANO_RXL_DBL];
+ Nanod.abl2rxl <= Nanod.abl2reg & !ablSpecial & !nanoLatch[ NANO_RXL_DBL];
+
+ Nanod.rxh2dbh <= Nanod.reg2dbh & !dbhSpecial & nanoLatch[ NANO_RXH_DBH];
+ Nanod.rxh2abh <= Nanod.reg2abh & !abhSpecial & !nanoLatch[ NANO_RXH_DBH];
+
+ Nanod.dbh2rxh <= Nanod.dbh2reg & !dbhSpecial & nanoLatch[ NANO_RXH_DBH];
+ Nanod.abh2rxh <= Nanod.abh2reg & !abhSpecial & !nanoLatch[ NANO_RXH_DBH];
+
+ Nanod.dbh2ryh <= Nanod.dbh2reg & !dbhSpecial & !nanoLatch[ NANO_RXH_DBH];
+ Nanod.abh2ryh <= Nanod.abh2reg & !abhSpecial & nanoLatch[ NANO_RXH_DBH];
+
+ Nanod.dbl2ryl <= Nanod.dbl2reg & !dblSpecial & !nanoLatch[ NANO_RXL_DBL];
+ Nanod.abl2ryl <= Nanod.abl2reg & !ablSpecial & nanoLatch[ NANO_RXL_DBL];
+
+ Nanod.ryl2db <= Nanod.reg2dbl & !dblSpecial & !nanoLatch[ NANO_RXL_DBL];
+ Nanod.ryl2ab <= Nanod.reg2abl & !ablSpecial & nanoLatch[ NANO_RXL_DBL];
+
+ Nanod.ryh2dbh <= Nanod.reg2dbh & !dbhSpecial & !nanoLatch[ NANO_RXH_DBH];
+ Nanod.ryh2abh <= Nanod.reg2abh & !abhSpecial & nanoLatch[ NANO_RXH_DBH];
+ end
+
+ // Originally isTas only delayed on T2 (and seems only a late mask rev fix)
+ // Better latch the combination on T4
+ if( enT4)
+ Nanod.isRmc <= Irdecod.isTas & nanoLatch[ NANO_BUSBYTE];
+ end
+
+
+endmodule
\ No newline at end of file
diff --git a/common/CPU/68000/FX68k/nanorom.mem b/common/CPU/68000/FX68k/nanorom.mem
new file mode 100644
index 00000000..be868964
--- /dev/null
+++ b/common/CPU/68000/FX68k/nanorom.mem
@@ -0,0 +1,336 @@
+00000000000000000000000000000000000000000000000010000000000000000000
+00000000000000000000000000000000000000000000000010000000000000000000
+00000000000000000000000000000000000000000000000010000000000000000000
+00000000000000000000000000001000000110011100000000000000101001000001
+00100001000000011000010001001000000110100000000001000000011001001001
+00000001100000000010100000001000000110000000001001000000001001001001
+00100000000000011000010001000000000101000000000010000000100001010000
+11000001000000000000000000001000000100010000000001000000000001010001
+00100001000000011000010000000000000000000000000101000000000000010000
+01000001011000000000100000000110010001000000001100000000110100011000
+01000001011000000000100000000110010001000000001100000001100100011000
+00100001000000011000010000000000000100000000000001000000000001010000
+10100100001000011000001000010000101001110000000001000100110010100001
+01000000000000000000000010000000010100000000001000110001000000000000
+00100001000000011000000000110010100100011111010001100000000001000000
+00100010000000011000000000000000100010000100000000010100000100000011
+00000001011000000000000001000110000000000000000010000000000100000000
+00000000000000000000000000001000000100000000000001000000000001010001
+00000001100000000010100000001000000110000000001001010000001001001001
+00101000000000001000010000000000000000000000000010000000000000000000
+01100010000000011000010010000000010100000000001000110001000000000000
+00000000000000000000000010010010100000000000000100110010000000000000
+00100000000000011000010001001000000110000000001001010000001001001001
+00000000000000000000001000000000100100000000000000110010000001011000
+00010010000000000100100000001000000100000000000010000000000001010001
+00100010000000011100000000000000000001100000000010001000100000000000
+00010010000000000100000000000000010001100000000010000000000000000000
+00000000000000000000000000011001100110100000010001000000011011010001
+10100010110000000000000000000000100000010000010010000100000100000000
+10000000000000000000000000001000000100010000000001000000000001000001
+00100000000000011001000000011010000110000000001001000000001001001001
+00010011000000000000101000010000001001000000010101000000100000110000
+00000001000000000001010000000000000000000000000101100000000000010000
+00100010000000011000001000001000100110000000000001000000000001010001
+00000001000000000010100001010000001001000000010110000000100000110000
+01000001000000000000000000000000000001101010001100000000110000000000
+00110100000000000100000100000000000000000000000010000000000000000000
+00000000000100100000100000000000010000000000000000000001000000011000
+01110101000000000100100000100010000001100000000000000000110100001010
+00100010000000011010000100000000100010000100000000010100000100000011
+11000001000000000000000000001000000100010000000001000000000001010001
+01010011000000000100100000100010000001100000000000000000110100001010
+11000001000000000000000000001001100110110000000001000000011011000001
+01001001110000000000001000001000001000000000000101000000000000100001
+00000000000000000000100000100010010000000000000000110001000100000010
+00010000110000000001010000000000000000011100000010000000000000011000
+01010001110000000001000000011010100100000000000001000000000001000001
+00000000000000000000000001000000000100000000001100010000000001010000
+00001000000000011001001000001000000110100000000001000100000011010001
+01010001110000000001010000001000001000000000000101000000000000110001
+10100010110100100100000001000000000001110000000010000000110000010000
+00000000000100000000000000000010100001001010000101100000100000010000
+00010000110000000001000000000000100000000000010010000100000100000000
+10000000000000000000000000001000000100010000000001000000000001000001
+00000001000000000000000001000000001001000000000101000000100000100000
+00010010000000000000100000001010101000000000000101000000000000110001
+10100000000100111000000000100001100010111010000101100000011010010010
+00100000000000011000000000110010100110000000010000100000001101000010
+00010010000000001100000000000000000000000000000010000000000000000000
+11000001000000000000001000011101100100010000000001000000000001000001
+00010100000000000100000100000000000000000000000010000000000000000000
+10100010110000000100001000000000100000010000010010000100000010000000
+00100000000100111000000000000000100000010010000101000100000100010010
+00100010000000011000000000000000100010000100000000010100000100000011
+00100010100000011001010000010000100100000000001110000100001000000000
+00000000000100000000000000000010100000001010000101000000000000010000
+00100010100000011001000000010010100100000000001110000100001000000000
+00000001000000000000010000000000100000000000010101000100000010010000
+00000000000100100000000000100010000000000100000000110001000100011010
+00100000000000011000000000010000100110000000011000100000001001000000
+00000000000100100000100000100010010000000000000000110001000100011010
+00000000011000000000000000000110000000000000001110000000110100111000
+00011000000000011001001000001000000100000000000001000000000001010001
+00100010000000011100000000000000000001100000000010001000100000000000
+00110000100000001000000100000000100000000000000010000100000100000000
+00000000000100000000000000000010100001000000000101100000100000010000
+10100010110000000100001000010001100000010000000010000000000000000000
+01000001000000000000000000000000000000000000000101000000000000010000
+10000000000000000000000000001000000100010000000001000000000001000001
+00000000000000000000000000001000001000000000000101000000000000110001
+00001000110000000000001000000000000000000000000010000000000000000000
+00010010000000001100000000000000000000000000000010000000000000000000
+00010000000000001010000100000000110001000000000010000100011000000000
+01010001000000011000001000000000000001100000000000000000110000000000
+00001100000000011000001000100001000010100000000101110000000000000011
+01000000000000000000000010000000010100000000001000110000000001000000
+11000001000000000000000000001000001000010000000101000000000000100001
+00000000000000000000000000001000000100011100000001100000000001000001
+00000000000000000000000000000000000000000000000101100000000000000000
+00000000000100000000000000000000100000000000000101000100000100010000
+11101011000000000000000000000000000000010000000010000000000000000000
+01100001000000011001000000011010100100000000000001000000000001000001
+01100010000000011000010010000000010100000000001000110000000001000000
+00000000000000000000000010010010100000000000010100110000000100000000
+01000001000000000000010000011001101000000000000101000100001000110001
+00100000000100111100000000000000000010000010000100100010001000010000
+00010010000000000000000000000010110100000000001110000000000000011000
+00000000000000000000001000010000100100000000011100110010000001011000
+00000000000100000000000000010000111000000000010101000100011000110000
+00000000011000000010100000000110000100000000001101110000000101000000
+00000000000000000000000000000000000000000000000010000000000000000000
+00000001000000000000000000000000010101001010001101000000100001010000
+00000001000000000000010000000000100000000000000101000100001000010000
+01110101000000010000001000000000000001100000000000000000110000000000
+01000001000000000000000010000000010100001010001000110001000000000000
+00100010000000011000000000011010101010000000010101000000001100110001
+00100001000000011000010001010000000100000000010000010000000001010000
+01000001000000000000010000000000100000000110000101000000000000010000
+01000001000000000000000010000000010100001010001000110001000000000000
+00100000000000011000010001010001000000000000011010000000000010001000
+00000001000000000000000001010000000100000000010001110000000001000000
+00010010000000001000000000011010101000000000000101000000000000110001
+00000000000000000000000000001000001000000000000101000000000000110001
+00010010000000000001100000000010000000000000000101100000000000000000
+00010010000000000001000000000010000100000000000101100000000000000000
+00100010000000011100000000001000001000000000000101000000000000100001
+00000001000000000001010000000000001010100000000110000000011000101000
+00000001100000000000100000000000000000000000000101000000000000010000
+00010010000000000000101000001001000100000000001001000000000011010001
+11110101001000000100000000000000000000010000000010000000000000000000
+00000000000000000000010000001001101000000000000101000010000010110001
+00000000000000000000010000000000100000000110000101100000000000000000
+00100010100000001001100000000010000010000100001000000000001000001000
+00100010100000001001000000000010000110000100001000000000001000001000
+00010010000000001000010000000000000000000000001110000000000000011000
+00110100000100101100000000000000000001100000000001100000110000010000
+01110101000000001000000100000000111000000000010010000100000100000000
+01000000000000000000010000010000100110000000011100100000000001011000
+11010011000000000000101000001001000100010000001001000000000011010001
+11110101001000000000000000000000100000010000000010000100000100000000
+01110101000000000100000000000000010000000000010010001000000001000000
+01110101000000000000000000000000110000000000010010001100000101000000
+01110101000000000000000000000000110000000000010010001100011001000000
+01110000000000011100000000000000000001100000001101000000110000000000
+00010000000000001000000000000010100000000000000010000000000000000000
+00010010000000000100000100000000010001000000000010000000000000000000
+01000000000000000000010000010000100110000000011100100010001001011000
+00100000000000011000010000000000000100000000000000100000000001000000
+00000001000000000000000000000000001000000000000101000000000000110000
+00100001000000011100000001011001000110000000011000000000001011001001
+01100001000000011000000000010010100110000000011100100000001101011000
+01100001000000011000010000010010000010000000010101000000001100010000
+00000000000000000000000100000000010010100000001100110001011000011000
+01100001000000011000000000010000100110000000011000100000001001000000
+00000000000000000000000000001000000100011100000001100000000001000001
+00010010000000000000000000010010110110000000001110000010001000011000
+01000001000000000000100000010010010000000000010000110001000100011000
+00010010000000000000010000010000110110000000001110000010001000011000
+01000001000000000000000010000000010100001010001000110000000001000000
+01000001000000000000010000001000101000000110000101000000000000110001
+00000001000000000000010000000000100000000000000101000100001000010000
+00101000000000001000010000000000000000000000000010000000000000000000
+00100010000000011000000000000000100000000000000010000100011000000000
+00100010001000011010000000000000100000000000000010000100000100000000
+11010011001000000100000000010000011000010000000010000000000000000000
+00010010000000000100000000000000010000000000010010001000000001000000
+00001000000000011000001000000000000000000000000101110000000000000011
+00100010110000000000010000001000001000000000000101000000000000110001
+00100010000000011000000000000000100010100000000010000000000000000000
+00100000000000011000000000110001100100011111011001100000000011000010
+00100000000000011000000000001000100110000000001001010000001001000001
+01000001000000000000000000010000000100000000011100100000000001011000
+00000000100000000010100000000000000001000000000101000000100000010000
+00000001000000000000000000011001000100000000011001000000000011000001
+00000000011000000010100001000110000101000000000000010000100101010000
+00100001000000011100000001011001000100000000011001000000000011000001
+01000000000000000000000000000000000101001010001101100000100001000000
+00000000000100000000000000000000100001001010000101100100100100010000
+00000000011000000000000000000010110110000000001100000000001101011000
+01000001000000000000000000000001111001100000001010000000110010100000
+00110010000000011000000000010010100010000000001110000010001000011000
+11000001000000000000000000011001100110110000010001000000011011000001
+00100000000000011010000000100001110000001100001010000000000010000010
+00000000000000000000000000010000000100010101010001100000000001000000
+01000000000000000000000000000000000010100000000010000000011000001000
+00000001000000000000000000000000000001101010001101000000110000010000
+10000000000000000000001000001101100100010000000001000000000001000001
+01110101000000000000000000000000110000000000000010001100000101000000
+11000001000000000000000000001000000100010000000001000000000001000001
+00100010000000011000000000001001101000000010000101000010000010110001
+00100010000100011000000000010010100000000000000101000000000000010000
+11100101000000011100000000001001000100010000001001000000000011010001
+00100100000100111000000000000000100000000000010101100100000100010000
+00100010000100011000000000011010100100000000000000000000000001011001
+00100000000000001000001000000000100000000000000010000100000010000000
+00100010000000011100001000001000100100000000000001000100001001010001
+00010010000000000100000100000000010001000000000010000000000000000000
+10000000000000000000001000011101000100010000000001000000000001000001
+00011000000000011000001000000000100010000000000010000000000000000000
+01000000000000000000000000000000000100000000000001000000000001010000
+01000000000000000000010000010000100110000000011100100000011001001000
+00000000001000000010001000010001010000000000000010001000000000100000
+11100101000000011100000000001000001000010000000101000000000000110001
+01000001000000000000001000010001100000000000000010000000000000000000
+00110100000000000000000000000000110000000000000010001100000101000000
+10000000000000000000001000001000100100010000010001000100000011000001
+01110101000000000100001000000001110000000000010010001000000001000000
+10000000000000000000001000001000100100010000000001000100000011000001
+00110100000000000000000000000000110000000000010010001100000101000000
+00110100000000000000000000000000110000000000010010001100011001000000
+01000000000000000000000000010000000110100000011100100000011001001000
+00000000000100000000000000010000111000000000010101000100000100110010
+00000000000100000000000000100010100001100000000001000000110000011000
+01000000000000000000000000010010000110000000010000100000001101001000
+00000000000000000000000000001000000110000000001001000000001001001001
+01000000000000000000010000000001100000000000000101000010000010010000
+01000000000000000000000000001000000110000000001001010000001001000001
+00000001000000000000000000000000000001101010001101000000110000000000
+11100101000000011000000000010000111001110000010010000100110100100000
+00000000000000000000000000011010101010000000000101000010001000110001
+11000001000000000000001000001101100100010000000001000000000001000001
+00000000000000000000000100000000010000000000000001100001000000000000
+00000000000000000000000000001001100100000000001001000000000011010001
+11000001000000000000010000010001100000010000010010000000011010000000
+00000000000000000000000000000000000000010110000010000000000000000000
+00000000000000000000000000000000000000001100000000000001000000000000
+00100010000000011000000000000000100010100000000010000000000000000000
+00001000000000011000001000000000000000000000000101110000000000000011
+10000000000000000000000000000000000000010000000010000000000000000000
+00000000000000000000010000000000100010000000000010000010001000000000
+00101000000000001000001000000000000000000000000010000000000000000000
+01010011000000000000100000000010100001100000001100000000110000011000
+00000001000010000000000001000000000000000000000101000000000000010000
+00100010000000011000010000001101101000000000000101000000000000110001
+00000000000000000000100000010010010000000000010000110001000100000000
+01000000000000000000000000010000000100000000011100100000000001000000
+00000000000000000000000100010010010000000000010000110001000100000000
+01000000000000000000100000000000010000000000000001000000110000010000
+01010011000000001000010000000000000001100000001100000000110000011000
+01000001000000000000010000001001101000000000000101000000000000110001
+00100100000100011001000000000000100000000000010101000100000100010000
+01100010000000011000100000010010110010000000001100000000110000011000
+00011000000000011000001000000000000000000000000101110000000000000011
+00000000000000000000000000001000000100000000000001000000000001010001
+00010010000000000100000100000000010001000000000010000000000000000000
+00001010000000011000001000000000000000000000000101110000000000000011
+00010010000000000000000000000001110100000010001110000010000010011000
+01100010000000011000100000010010110010000000001100000001000000011000
+01000000000000000000100000000010010000000000001100110001000100011000
+00100010000100011000000001011010100100000000000001000000000001011001
+00000001000000000000010000000001100001001010000101000000100000010000
+00000000000000000000010000000000100101000110001110000000100001011000
+00000000000000000000100000010010010000000000010000110001000100011000
+01010011000000000000100000000001100001100010001100000010110010011000
+01100011000000011000000000010010100100000000011101110000000001011000
+00000000000100000001000000010000100100000000011101000100000101010000
+00100010000100011000000001010010100100000000011100010000000001010000
+00000001000000000000010000000000100000000001000101000100000010010000
+00000001000000000000010000000001100000001111000101000000000000010000
+00000000000000000000000000010010100000000110010101100000000100000000
+00000111000000000000010000010000111000001000010110000100001000100000
+01000000000000000000100000000001110000000000001001000000110010010000
+01001011000000011000001000000000000001100000000000000000110000000000
+00000000000000000000010000000000100010000000000101000000000000010000
+10100100000000011100000000001000000100010000000001000000000001000001
+00010000000000000000000000010000100100000010000010000000000000000000
+00000000000000000000000000001000000100000010000000110010000001000001
+01000000000000000000000000001001100100000000001001010000000011000001
+00000000000000000000000000001001100100000000001001010000000011000001
+00100000000000011000000000010010100010000000010101000000001100010000
+00000000000100000000000000000000101000000000000101000100011000110000
+00000000000100100000100000010010010000000000010000110001000100011000
+01000000000000000000010000010001100000000000010101000010000010010000
+00100001000000011100010100000000110010000000001110001000100000011000
+00000000000000000000001000000000100000000110000101000000000000000000
+00000110000000000000000000000000000000001000000010000000000000000000
+01000000000000000000010000000000100100001010001100110010000001000000
+01000000000000000000000000000000000100001010001100000000000001000000
+01100001000000011000000000000000100001100010000000000000110000000000
+01000001000000000000010000000000100000000110000101010000000000010000
+00101000000000001000010000001000101010000000000101100000000000100001
+10000110000000000000000000001000001000001000000101100000000000100001
+00000000000000000000000000001000000100000000000001000000000001010001
+00100010000100111000100000000000110010100000000001000000110000010000
+00100100000100111100000000001000000100000000000001000000000001011001
+00100011000000011000010100000000010000000000001110001000100000011000
+00000000000000000000000000011001100110100000010001000000011011010001
+00000000000000000000000000000000000000000000000010000000000000000000
+00000000000100100000010001001000100100000000000001000000011001001001
+00100100001000111100001000000000100010000000000101000000000000010000
+01000001000000000000000000010001100000000010000010000000000000000000
+00100010000000011010000000000000110100000000011110001100100100011000
+11100101000000011100000100000000001000010000010101000000011010000000
+00010000000000000000100000000000100001100010001100000000110000000000
+00100010000100111000010001001000000100000000000000000000000001011001
+00010000000000000010000000000000100100000010001110000000000000011000
+11100011000000011100001000010101100000010000000101000000000000000000
+00100000000000011000000000110010100100011111010001100000000001000000
+10000000000100000000000000001000100110110000000001000000000001011001
+11000001000000000000000000001001000100010000001001000000000011010001
+00100100000100111100000000000000000000000000000101100000000000010000
+10000000000100100000000001001001000100010000001001000000000011001001
+11000001000000000000000000000000000000010000000010000000000000000000
+00110100001100100000000000000000100000000000000101100100000100010000
+00000001000001000000000001000000000000000000000101000000000000010000
+00000001000010000000010001000000100000000000000101000100000010010000
+00100000000100111000000000010000101000010111010101000100000100110010
+11100101000000011100000000000000000000010000000010000000000000000000
+11100101000000011000000000000000100000010000010010000100000100000000
+00000000000000000000000000001000001000000000000101000000000000110001
+00000000000000000000000000000000000000000000000010000000000000000000
+00000000000000000000000000000000000000000000000010000000000000000000
+00000000000000000000000000000000000000000000000010000000000000000000
+00000001000000000000000000001000001001100000000001000000110000110001
+00000001000001000000000001001000000100000000000001010000000001011001
+00100000000000001000001000000000100000000000000010000100000010000000
+11000001000000000000010000001001001000010000000101000000000000110001
+00000000000110000000000001000000100000000000000101000100000100010000
+00000000000101000000000001000000100000000000000101000100000100010000
+00000000000010100000000001010000000100000000000101000000000000010000
+00000000000101000000000001001010000100000000000001010000000001011001
+11100101001000011100000000000000010000010000010010001000000000100000
+00100000000000001000000000001000001000000000000110000000000000110001
+00100000000000011000000000000000100000000100011100000101000100011000
+00100000000000011000000000010000110100000000011100000101000100011000
+01100011100000011000000100010010000000000000000101110000000000000011
+01100010000000011000010100000000010000000000001100000001000000011000
+10000000000100100000000001001000000100010000000001000000000001011001
+01100010000000011000010100000010010000000000001100110001000100011000
+01100011000000011000010000010000000100000000011101110000000001011000
+00000000000000000000010000000000100000000110000101000000000000010000
+00000000000000000000000000000000000000011100001110000000000000011000
+10100000000000001000010000001000101000000110000101000000000000100001
+00100000000000011000000000110001100100001111011001100000000011000010
+00000001000000000000010000000001100001001010000101000010100010010000
+00100010001000111000010000010000000100000000011101000000000001010000
+00100100000100111100000000000000000000000000000101000000000000010000
+00100010000100011000010001010000000100000000011100010000000001010000
+01000001000000000000000100010000011000000000000010000000000000000000
+00000000000000000000010000000000100010000000000101000010001000010000
+00100000000100111000000000000000100000000010000100100000000000010000
+00100010000000011000010000001000001000000000000101000000000000110001
+00000001000000000000010000000000100000000000000101000100000010010000
+00000000000000000000000000000000000000000000000010000000000000000000
+00000000000000000000001000000000100100000000000000110010000001011000
+00000000011000000000000000000010110110000000001100000000001101011000
diff --git a/common/CPU/68000/FX68k/onehotEncoder4.sv b/common/CPU/68000/FX68k/onehotEncoder4.sv
new file mode 100644
index 00000000..c7771b41
--- /dev/null
+++ b/common/CPU/68000/FX68k/onehotEncoder4.sv
@@ -0,0 +1,23 @@
+// bin to one-hot, 4 bits to 16-bit bitmap
+module onehotEncoder4( input [3:0] bin, output reg [15:0] bitMap);
+ always_comb begin
+ case( bin)
+ 'b0000: bitMap = 16'h0001;
+ 'b0001: bitMap = 16'h0002;
+ 'b0010: bitMap = 16'h0004;
+ 'b0011: bitMap = 16'h0008;
+ 'b0100: bitMap = 16'h0010;
+ 'b0101: bitMap = 16'h0020;
+ 'b0110: bitMap = 16'h0040;
+ 'b0111: bitMap = 16'h0080;
+ 'b1000: bitMap = 16'h0100;
+ 'b1001: bitMap = 16'h0200;
+ 'b1010: bitMap = 16'h0400;
+ 'b1011: bitMap = 16'h0800;
+ 'b1100: bitMap = 16'h1000;
+ 'b1101: bitMap = 16'h2000;
+ 'b1110: bitMap = 16'h4000;
+ 'b1111: bitMap = 16'h8000;
+ endcase
+ end
+endmodule
\ No newline at end of file
diff --git a/common/CPU/68000/FX68k/pren.sv b/common/CPU/68000/FX68k/pren.sv
new file mode 100644
index 00000000..ff46c068
--- /dev/null
+++ b/common/CPU/68000/FX68k/pren.sv
@@ -0,0 +1,25 @@
+// priority encoder
+// used by MOVEM regmask
+// this might benefit from device specific features
+// MOVEM doesn't need speed, will read the result 2 CPU cycles after each update.
+module pren( mask, hbit);
+ parameter size = 16;
+ parameter outbits = 4;
+
+ input [size-1:0] mask;
+ output reg [outbits-1:0] hbit;
+ // output reg idle;
+
+ always @( mask) begin
+ integer i;
+ hbit = 0;
+ // idle = 1;
+ for( i = size-1; i >= 0; i = i - 1) begin
+ if( mask[ i]) begin
+ hbit = i;
+ // idle = 0;
+ end
+ end
+ end
+
+endmodule
\ No newline at end of file
diff --git a/common/CPU/68000/FX68k/rowDecoder.sv b/common/CPU/68000/FX68k/rowDecoder.sv
new file mode 100644
index 00000000..8fa9c038
--- /dev/null
+++ b/common/CPU/68000/FX68k/rowDecoder.sv
@@ -0,0 +1,139 @@
+// Decodes IRD into ALU row (1-15)
+// Slow, but no need to optimize for speed since IRD is latched at least two CPU cycles before it is used
+// We also register the result after combining with column from nanocode
+//
+// Many opcodes are not decoded because they either don't do any ALU op,
+// or use only columns 1 and 5 that are the same for all rows.
+
+module rowDecoder( input [15:0] ird,
+ output logic [15:0] row, output noCcrEn, output logic isArX);
+
+
+ // Addr or data register direct
+ wire eaRdir = (ird[ 5:4] == 2'b00);
+ // Addr register direct
+ wire eaAdir = (ird[ 5:3] == 3'b001);
+ wire size11 = ird[7] & ird[6];
+
+ always_comb begin
+ case( ird[15:12])
+ 'h4,
+ 'h9,
+ 'hd:
+ isArX = row[10] | row[12];
+ default:
+ isArX = 1'b0;
+ endcase
+ end
+
+ always_comb begin
+ unique case( ird[15:12])
+
+ 'h4: begin
+ if( ird[8])
+ row = `ALU_ROW_06; // chk (or lea)
+ else case( ird[11:9])
+ 'b000: row = `ALU_ROW_10; // negx
+ 'b001: row = `ALU_ROW_04; // clr
+ 'b010: row = `ALU_ROW_05; // neg
+ 'b011: row = `ALU_ROW_11; // not
+ 'b100: row = (ird[7]) ? `ALU_ROW_08 : `ALU_ROW_09; // nbcd/swap/ext(or pea)
+ 'b101: row = `ALU_ROW_15; // tst & tas
+ default: row = 0;
+ endcase
+ end
+
+ 'h0: begin
+ if( ird[8]) // dynamic bit
+ row = ird[7] ? `ALU_ROW_14 : `ALU_ROW_13;
+ else case( ird[ 11:9])
+ 'b000: row = `ALU_ROW_14; // ori
+ 'b001: row = `ALU_ROW_04; // andi
+ 'b010: row = `ALU_ROW_05; // subi
+ 'b011: row = `ALU_ROW_02; // addi
+ 'b100: row = ird[7] ? `ALU_ROW_14 : `ALU_ROW_13; // static bit
+ 'b101: row = `ALU_ROW_13; // eori
+ 'b110: row = `ALU_ROW_06; // cmpi
+ default: row = 0;
+ endcase
+ end
+
+ // MOVE
+ // move.b originally also rows 5 & 15. Only because IRD bit 14 is not decoded.
+ // It's the same for move the operations performed by MOVE.B
+
+ 'h1,'h2,'h3: row = `ALU_ROW_02;
+
+ 'h5:
+ if( size11)
+ row = `ALU_ROW_15; // As originally and easier to decode
+ else
+ row = ird[8] ? `ALU_ROW_05 : `ALU_ROW_02; // addq/subq
+ 'h6: row = 0; //bcc/bra/bsr
+ 'h7: row = `ALU_ROW_02; // moveq
+ 'h8:
+ if( size11) // div
+ row = `ALU_ROW_01;
+ else if( ird[8] & eaRdir) // sbcd
+ row = `ALU_ROW_09;
+ else
+ row = `ALU_ROW_14; // or
+ 'h9:
+ if( ird[8] & ~size11 & eaRdir)
+ row = `ALU_ROW_10; // subx
+ else
+ row = `ALU_ROW_05; // sub/suba
+ 'hb:
+ if( ird[8] & ~size11 & ~eaAdir)
+ row = `ALU_ROW_13; // eor
+ else
+ row = `ALU_ROW_06; // cmp/cmpa/cmpm
+ 'hc:
+ if( size11)
+ row = `ALU_ROW_07; // mul
+ else if( ird[8] & eaRdir) // abcd
+ row = `ALU_ROW_03;
+ else
+ row = `ALU_ROW_04; // and
+ 'hd:
+ if( ird[8] & ~size11 & eaRdir)
+ row = `ALU_ROW_12; // addx
+ else
+ row = `ALU_ROW_02; // add/adda
+ 'he:
+ begin
+ reg [1:0] stype;
+
+ if( size11) // memory shift/rotate
+ stype = ird[ 10:9];
+ else // register shift/rotate
+ stype = ird[ 4:3];
+
+ case( {stype, ird[8]})
+ 0: row = `ALU_ROW_02; // ASR
+ 1: row = `ALU_ROW_03; // ASL
+ 2: row = `ALU_ROW_05; // LSR
+ 3: row = `ALU_ROW_04; // LSL
+ 4: row = `ALU_ROW_08; // ROXR
+ 5: row = `ALU_ROW_11; // ROXL
+ 6: row = `ALU_ROW_10; // ROR
+ 7: row = `ALU_ROW_09; // ROL
+ endcase
+ end
+
+ default: row = 0;
+ endcase
+ end
+
+ // Decode opcodes that don't affect flags
+ // ADDA/SUBA ADDQ/SUBQ MOVEA
+
+ assign noCcrEn =
+ // ADDA/SUBA
+ ( ird[15] & ~ird[13] & ird[12] & size11) |
+ // ADDQ/SUBQ to An
+ ( (ird[15:12] == 4'h5) & eaAdir) |
+ // MOVEA
+ ( (~ird[15] & ~ird[14] & ird[13]) & ird[8:6] == 3'b001);
+
+endmodule
\ No newline at end of file
diff --git a/common/CPU/68000/FX68k/sequencer.sv b/common/CPU/68000/FX68k/sequencer.sv
new file mode 100644
index 00000000..dade6edc
--- /dev/null
+++ b/common/CPU/68000/FX68k/sequencer.sv
@@ -0,0 +1,237 @@
+// Microcode sequencer
+
+module sequencer( input s_clks Clks, input enT3,
+ input [UROM_WIDTH-1:0] microLatch,
+ input A0Err, BerrA, busAddrErr, Spuria, Avia,
+ input Tpend, intPend, isIllegal, isPriv, excRst, isLineA, isLineF,
+ input [15:0] psw,
+ input prenEmpty, au05z, dcr4, ze, i11,
+ input [1:0] alue01,
+ input [15:0] Ird,
+ input [UADDR_WIDTH-1:0] a1, a2, a3,
+ output logic [3:0] tvn,
+ output logic [UADDR_WIDTH-1:0] nma);
+
+ logic [UADDR_WIDTH-1:0] uNma;
+ logic [UADDR_WIDTH-1:0] grp1Nma;
+ logic [1:0] c0c1;
+ reg a0Rst;
+ wire A0Sel;
+ wire inGrp0Exc;
+
+ // assign nma = Clks.extReset ? RSTP0_NMA : (A0Err ? BSER1_NMA : uNma);
+ // assign nma = A0Err ? (a0Rst ? RSTP0_NMA : BSER1_NMA) : uNma;
+
+ // word type I: 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
+ // NMA : .. .. 09 08 01 00 05 04 03 02 07 06 .. .. .. .. ..
+
+ wire [UADDR_WIDTH-1:0] dbNma = { microLatch[ 14:13], microLatch[ 6:5], microLatch[ 10:7], microLatch[ 12:11]};
+
+ // Group 0 exception.
+ // Separated block from regular NMA. Otherwise simulation might depend on order of assigments.
+ always_comb begin
+ if( A0Err) begin
+ if( a0Rst) // Reset
+ nma = RSTP0_NMA;
+ else if( inGrp0Exc) // Double fault
+ nma = HALT1_NMA;
+ else // Bus or address error
+ nma = BSER1_NMA;
+ end
+ else
+ nma = uNma;
+ end
+
+ always_comb begin
+ // Format II (conditional) or I (direct branch)
+ if( microLatch[1])
+ uNma = { microLatch[ 14:13], c0c1, microLatch[ 10:7], microLatch[ 12:11]};
+ else
+ case( microLatch[ 3:2])
+ 0: uNma = dbNma; // DB
+ 1: uNma = A0Sel ? grp1Nma : a1;
+ 2: uNma = a2;
+ 3: uNma = a3;
+ endcase
+ end
+
+ // Format II, conditional, NMA decoding
+ wire [1:0] enl = { Ird[6], prenEmpty}; // Updated on T3
+
+ wire [1:0] ms0 = { Ird[8], alue01[0]};
+ wire [3:0] m01 = { au05z, Ird[8], alue01};
+ wire [1:0] nz1 = { psw[ NF], psw[ ZF]};
+ wire [1:0] nv = { psw[ NF], psw[ VF]};
+
+ logic ccTest;
+ wire [4:0] cbc = microLatch[ 6:2]; // CBC bits
+
+ always_comb begin
+ unique case( cbc)
+ 'h0: c0c1 = {i11, i11}; // W/L offset EA, from IRC
+
+ 'h1: c0c1 = (au05z) ? 2'b01 : 2'b11; // Updated on T3
+ 'h11: c0c1 = (au05z) ? 2'b00 : 2'b11;
+
+ 'h02: c0c1 = { 1'b0, ~psw[ CF]}; // C used in DIV
+ 'h12: c0c1 = { 1'b1, ~psw[ CF]};
+
+ 'h03: c0c1 = {psw[ ZF], psw[ ZF]}; // Z used in DIVU
+
+ 'h04: // nz1, used in DIVS
+ case( nz1)
+ 'b00: c0c1 = 2'b10;
+ 'b10: c0c1 = 2'b01;
+ 'b01,'b11: c0c1 = 2'b11;
+ endcase
+
+ 'h05: c0c1 = {psw[ NF], 1'b1}; // N used in CHK and DIV
+ 'h15: c0c1 = {1'b1, psw[ NF]};
+
+ // nz2, used in DIVS (same combination as nz1)
+ 'h06: c0c1 = { ~nz1[1] & ~nz1[0], 1'b1};
+
+ 'h07: // ms0 used in MUL
+ case( ms0)
+ 'b10, 'b00: c0c1 = 2'b11;
+ 'b01: c0c1 = 2'b01;
+ 'b11: c0c1 = 2'b10;
+ endcase
+
+ 'h08: // m01 used in MUL
+ case( m01)
+ 'b0000,'b0001,'b0100,'b0111: c0c1 = 2'b11;
+ 'b0010,'b0011,'b0101: c0c1 = 2'b01;
+ 'b0110: c0c1 = 2'b10;
+ default: c0c1 = 2'b00;
+ endcase
+
+ // Conditional
+ 'h09: c0c1 = (ccTest) ? 2'b11 : 2'b01;
+ 'h19: c0c1 = (ccTest) ? 2'b11 : 2'b10;
+
+ // DCR bit 4 (high or low word)
+ 'h0c: c0c1 = dcr4 ? 2'b01: 2'b11;
+ 'h1c: c0c1 = dcr4 ? 2'b10: 2'b11;
+
+ // DBcc done
+ 'h0a: c0c1 = ze ? 2'b11 : 2'b00;
+
+ // nv, used in CHK
+ 'h0b: c0c1 = (nv == 2'b00) ? 2'b00 : 2'b11;
+
+ // V, used in trapv
+ 'h0d: c0c1 = { ~psw[ VF], ~psw[VF]};
+
+ // enl, combination of pren idle and word/long on IRD
+ 'h0e,'h1e:
+ case( enl)
+ 2'b00: c0c1 = 'b10;
+ 2'b10: c0c1 = 'b11;
+ // 'hx1 result 00/01 depending on condition 0e/1e
+ 2'b01,2'b11:
+ c0c1 = { 1'b0, microLatch[ 6]};
+ endcase
+
+ default: c0c1 = 'X;
+ endcase
+ end
+
+ // CCR conditional
+ always_comb begin
+ unique case( Ird[ 11:8])
+ 'h0: ccTest = 1'b1; // T
+ 'h1: ccTest = 1'b0; // F
+ 'h2: ccTest = ~psw[ CF] & ~psw[ ZF]; // HI
+ 'h3: ccTest = psw[ CF] | psw[ZF]; // LS
+ 'h4: ccTest = ~psw[ CF]; // CC (HS)
+ 'h5: ccTest = psw[ CF]; // CS (LO)
+ 'h6: ccTest = ~psw[ ZF]; // NE
+ 'h7: ccTest = psw[ ZF]; // EQ
+ 'h8: ccTest = ~psw[ VF]; // VC
+ 'h9: ccTest = psw[ VF]; // VS
+ 'ha: ccTest = ~psw[ NF]; // PL
+ 'hb: ccTest = psw[ NF]; // MI
+ 'hc: ccTest = (psw[ NF] & psw[ VF]) | (~psw[ NF] & ~psw[ VF]); // GE
+ 'hd: ccTest = (psw[ NF] & ~psw[ VF]) | (~psw[ NF] & psw[ VF]); // LT
+ 'he: ccTest = (psw[ NF] & psw[ VF] & ~psw[ ZF]) |
+ (~psw[ NF] & ~psw[ VF] & ~psw[ ZF]); // GT
+ 'hf: ccTest = psw[ ZF] | (psw[ NF] & ~psw[VF]) | (~psw[ NF] & psw[VF]); // LE
+ endcase
+ end
+
+ // Exception logic
+ logic rTrace, rInterrupt;
+ logic rIllegal, rPriv, rLineA, rLineF;
+ logic rExcRst, rExcAdrErr, rExcBusErr;
+ logic rSpurious, rAutovec;
+ wire grp1LatchEn, grp0LatchEn;
+
+ // Originally control signals latched on T4. Then exception latches updated on T3
+ assign grp1LatchEn = microLatch[0] & (microLatch[1] | !microLatch[4]);
+ assign grp0LatchEn = microLatch[4] & !microLatch[1];
+
+ assign inGrp0Exc = rExcRst | rExcBusErr | rExcAdrErr;
+
+ always_ff @( posedge Clks.clk) begin
+ if( grp0LatchEn & enT3) begin
+ rExcRst <= excRst;
+ rExcBusErr <= BerrA;
+ rExcAdrErr <= busAddrErr;
+ rSpurious <= Spuria;
+ rAutovec <= Avia;
+ end
+
+ // Update group 1 exception latches
+ // Inputs from IR decoder updated on T1 as soon as IR loaded
+ // Trace pending updated on T3 at the start of the instruction
+ // Interrupt pending on T2
+ if( grp1LatchEn & enT3) begin
+ rTrace <= Tpend;
+ rInterrupt <= intPend;
+ rIllegal <= isIllegal & ~isLineA & ~isLineF;
+ rLineA <= isLineA;
+ rLineF <= isLineF;
+ rPriv <= isPriv & !psw[ SF];
+ end
+ end
+
+ // exception priority
+ always_comb begin
+ grp1Nma = TRAC1_NMA;
+ if( rExcRst)
+ tvn = '0; // Might need to change that to signal in exception
+ else if( rExcBusErr | rExcAdrErr)
+ tvn = { 1'b1, rExcAdrErr};
+
+ // Seudo group 0 exceptions. Just for updating TVN
+ else if( rSpurious | rAutovec)
+ tvn = rSpurious ? TVN_SPURIOUS : TVN_AUTOVEC;
+
+ else if( rTrace)
+ tvn = 9;
+ else if( rInterrupt) begin
+ tvn = TVN_INTERRUPT;
+ grp1Nma = ITLX1_NMA;
+ end
+ else begin
+ unique case( 1'b1) // Can't happen more than one of these
+ rIllegal: tvn = 4;
+ rPriv: tvn = 8;
+ rLineA: tvn = 10;
+ rLineF: tvn = 11;
+ default: tvn = 1; // Signal no group 0/1 exception
+ endcase
+ end
+ end
+
+ assign A0Sel = rIllegal | rLineF | rLineA | rPriv | rTrace | rInterrupt;
+
+ always_ff @( posedge Clks.clk) begin
+ if( Clks.extReset)
+ a0Rst <= 1'b1;
+ else if( enT3)
+ a0Rst <= 1'b0;
+ end
+
+endmodule
\ No newline at end of file
diff --git a/common/CPU/68000/FX68k/uaddrDecode.sv b/common/CPU/68000/FX68k/uaddrDecode.sv
new file mode 100644
index 00000000..3efdc011
--- /dev/null
+++ b/common/CPU/68000/FX68k/uaddrDecode.sv
@@ -0,0 +1,91 @@
+// Provides ucode routine entries (A1/A3) for each opcode
+// Also checks for illegal opcode and priv violation
+
+// This is one of the slowest part of the processor.
+// But no need to optimize or pipeline because the result is not needed until at least 4 cycles.
+// IR updated at the least one microinstruction earlier.
+// Just need to configure the timing analizer correctly.
+
+module uaddrDecode(
+ input [15:0] opcode,
+ output [UADDR_WIDTH-1:0] a1, a2, a3,
+ output logic isPriv, isIllegal, isLineA, isLineF,
+ output [15:0] lineBmap);
+
+ wire [3:0] line = opcode[15:12];
+ logic [3:0] eaCol, movEa;
+
+ onehotEncoder4 irLineDecod( line, lineBmap);
+
+ assign isLineA = lineBmap[ 'hA];
+ assign isLineF = lineBmap[ 'hF];
+
+ pla_lined pla_lined( .movEa( movEa), .col( eaCol),
+ .opcode( opcode), .lineBmap( lineBmap),
+ .palIll( isIllegal), .plaA1( a1), .plaA2( a2), .plaA3( a3) );
+
+ // ea decoding
+ assign eaCol = eaDecode( opcode[ 5:0]);
+ assign movEa = eaDecode( {opcode[ 8:6], opcode[ 11:9]} );
+
+ // EA decode
+ function [3:0] eaDecode;
+ input [5:0] eaBits;
+ begin
+ unique case( eaBits[ 5:3])
+ 3'b111:
+ case( eaBits[ 2:0])
+ 3'b000: eaDecode = 7; // Absolute short
+ 3'b001: eaDecode = 8; // Absolute long
+ 3'b010: eaDecode = 9; // PC displacement
+ 3'b011: eaDecode = 10; // PC offset
+ 3'b100: eaDecode = 11; // Immediate
+ default: eaDecode = 12; // Invalid
+ endcase
+
+ default: eaDecode = eaBits[5:3]; // Register based EAs
+ endcase
+ end
+ endfunction
+
+
+ /*
+ Privileged instructions:
+
+ ANDI/EORI/ORI SR
+ MOVE to SR
+ MOVE to/from USP
+ RESET
+ RTE
+ STOP
+ */
+
+ always_comb begin
+ unique case( lineBmap)
+
+ // ori/andi/eori SR
+ 'h01: isPriv = ((opcode & 16'hf5ff) == 16'h007c);
+
+ 'h10:
+ begin
+ // No priority !!!
+ if( (opcode & 16'hffc0) == 16'h46c0) // move to sr
+ isPriv = 1'b1;
+
+ else if( (opcode & 16'hfff0) == 16'h4e60) // move usp
+ isPriv = 1'b1;
+
+ else if( opcode == 16'h4e70 || // reset
+ opcode == 16'h4e73 || // rte
+ opcode == 16'h4e72) // stop
+ isPriv = 1'b1;
+ else
+ isPriv = 1'b0;
+ end
+
+ default: isPriv = 1'b0;
+ endcase
+ end
+
+
+endmodule
\ No newline at end of file
diff --git a/common/CPU/68000/FX68k/uaddrPla.sv b/common/CPU/68000/FX68k/uaddrPla.sv
new file mode 100644
index 00000000..40544c6f
--- /dev/null
+++ b/common/CPU/68000/FX68k/uaddrPla.sv
@@ -0,0 +1,2192 @@
+//
+// FX68K
+//
+// Opcode to uaddr entry routines (A2-A2-A3) PLA
+//
+
+`timescale 1 ns / 1 ns
+
+`define NMA_BITS 10
+
+`define SFTM1 'h3C7
+`define SRRW1 'h382
+`define SRIW1 'h381
+`define SRRL1 'h386
+`define SRIL1 'h385
+`define BSRI1 'h089
+`define BSRW1 'h0A9
+`define BBCI1 'h308
+`define BBCW1 'h068
+`define RLQL1 'h23B
+`define ADRW1 'h006
+`define PINW1 'h21C
+`define PDCW1 'h103
+`define ADSW1 'h1C2
+`define AIXW0 'h1E3
+`define ABWW1 'h00A
+`define ABLW1 'h1E2
+`define TRAP1 'h1D0
+`define LINK1 'h30B
+`define UNLK1 'h119
+`define LUSP1 'h2F5
+`define SUSP1 'h230
+`define TRPV1 'h06D
+`define RSET1 'h3A6
+`define B 'h363
+`define STOP1 'h3A2
+`define RTR1 'h12A
+`define RTS1 'h126
+
+
+module pla_lined(
+ input [3:0] movEa,
+ input [3:0] col,
+
+ input [15:0] opcode,
+ input [15:0] lineBmap,
+
+ output palIll,
+ output logic [`NMA_BITS-1:0] plaA1,
+ output logic [`NMA_BITS-1:0] plaA2,
+ output logic [`NMA_BITS-1:0] plaA3
+ );
+
+ wire [3:0] line = opcode[ 15:12];
+ wire [2:0] row86 = opcode[8:6];
+
+ logic [15:0] arIll;
+ logic [`NMA_BITS-1:0] arA1[ 15:0];
+ logic [`NMA_BITS-1:0] arA23[ 15:0];
+ logic [`NMA_BITS-1:0] scA3;
+
+ logic illMisc;
+ logic [`NMA_BITS-1:0] a1Misc;
+
+ /*
+ reg [`NMA_BITS-1:0] lineMask[ 15:0];
+ always_comb begin
+ integer i;
+ for( i = 0; i < 16; i = i + 1)
+ lineMask[i] = { 16{lineBmap[ i]}};
+ end
+ */
+
+ assign palIll = (| (arIll & lineBmap));
+
+ // Only line 0 has 3 subs
+ assign plaA1 = arA1[ line];
+ assign plaA2 = arA23[ line];
+ assign plaA3 = lineBmap[0] ? scA3 : arA23[ line];
+
+
+ // Simple lines
+ always_comb begin
+ // Line 6: Branch
+ arIll[ 'h6] = 1'b0;
+ arA23[ 'h6] = 'X;
+ if( opcode[ 11:8] == 4'h1)
+ arA1[ 'h6] = (| opcode[7:0]) ? `BSRI1 : `BSRW1;
+ else
+ arA1[ 'h6] = (| opcode[7:0]) ? `BBCI1 : `BBCW1;
+
+ // Line 7: moveq
+ arIll[ 'h7] = opcode[ 8];
+ arA23[ 'h7] = 'X;
+ arA1[ 'h7] = `RLQL1;
+
+ // Line A & F
+ arIll[ 'ha] = 1'b1; arIll[ 'hf] = 1'b1;
+ arA1[ 'ha] = 'X; arA1[ 'hf] = 'X;
+ arA23[ 'ha] = 'X; arA23[ 'hf] = 'X;
+
+ end
+
+ // Special lines
+
+ // Line e: shifts
+ always_comb begin
+ if( ~opcode[11] & opcode[7] & opcode[6])
+ begin
+ arA23[ 'he] = `SFTM1;
+ unique case( col)
+ 2: begin arIll[ 'he] = 1'b0; arA1[ 'he] = `ADRW1; end
+ 3: begin arIll[ 'he] = 1'b0; arA1[ 'he] = `PINW1; end
+ 4: begin arIll[ 'he] = 1'b0; arA1[ 'he] = `PDCW1; end
+ 5: begin arIll[ 'he] = 1'b0; arA1[ 'he] = `ADSW1; end
+ 6: begin arIll[ 'he] = 1'b0; arA1[ 'he] = `AIXW0; end
+ 7: begin arIll[ 'he] = 1'b0; arA1[ 'he] = `ABWW1; end
+ 8: begin arIll[ 'he] = 1'b0; arA1[ 'he] = `ABLW1; end
+ default: begin arIll[ 'he] = 1'b1; arA1[ 'he] = 'X; end
+ endcase
+ end
+ else
+ begin
+ arA23[ 'he] = 'X;
+ unique case( opcode[ 7:6])
+ 2'b00,
+ 2'b01: begin
+ arIll[ 'he] = 1'b0;
+ arA1[ 'he] = opcode[ 5] ? `SRRW1 : `SRIW1;
+ end
+ 2'b10: begin
+ arIll[ 'he] = 1'b0;
+ arA1[ 'he] = opcode[ 5] ? `SRRL1 : `SRIL1;
+ end
+ 2'b11: begin arIll[ 'he] = 1'b1; arA1[ 'he] = 'X; end
+ endcase
+ end
+ end
+
+ // Misc. line 4 row
+ always_comb begin
+ illMisc = 1'b0;
+ case( opcode[ 5:3])
+ 3'b000,
+ 3'b001: a1Misc = `TRAP1;
+ 3'b010: a1Misc = `LINK1;
+ 3'b011: a1Misc = `UNLK1;
+ 3'b100: a1Misc = `LUSP1;
+ 3'b101: a1Misc = `SUSP1;
+
+ 3'b110:
+ case( opcode[ 2:0])
+ 3'b110: a1Misc = `TRPV1;
+ 3'b000: a1Misc = `RSET1;
+ 3'b001: a1Misc = `B;
+ 3'b010: a1Misc = `STOP1;
+ 3'b011: a1Misc = `RTR1;
+ 3'b111: a1Misc = `RTR1;
+ 3'b101: a1Misc = `RTS1;
+ default: begin illMisc = 1'b1; a1Misc = 'X; end
+ endcase
+
+ default: begin illMisc = 1'b1; a1Misc = 'X; end
+ endcase
+ end
+
+//
+// Past here
+//
+
+
+//
+// Line: 0
+//
+always_comb begin
+
+if( (opcode[11:6] & 'h1F) == 'h8) begin
+ unique case ( col)
+ 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h100; scA3 = 'X; end
+ 1: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h006; scA3 = 'h299; end
+ 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h21C; scA3 = 'h299; end
+ 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h103; scA3 = 'h299; end
+ 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1C2; scA3 = 'h299; end
+ 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E3; scA3 = 'h299; end
+ 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h00A; scA3 = 'h299; end
+ 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E2; scA3 = 'h299; end
+ 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 11: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1CC; scA3 = 'X; end
+ default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ endcase
+end
+
+else if( (opcode[11:6] & 'h37) == 'h0) begin
+ unique case ( col)
+ 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h100; scA3 = 'X; end
+ 1: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h006; scA3 = 'h299; end
+ 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h21C; scA3 = 'h299; end
+ 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h103; scA3 = 'h299; end
+ 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1C2; scA3 = 'h299; end
+ 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E3; scA3 = 'h299; end
+ 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h00A; scA3 = 'h299; end
+ 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E2; scA3 = 'h299; end
+ 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 11: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1CC; scA3 = 'X; end
+ default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ endcase
+end
+
+else if( (opcode[11:6] & 'h1F) == 'h9) begin
+ unique case ( col)
+ 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h100; scA3 = 'X; end
+ 1: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h006; scA3 = 'h299; end
+ 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h21C; scA3 = 'h299; end
+ 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h103; scA3 = 'h299; end
+ 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1C2; scA3 = 'h299; end
+ 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E3; scA3 = 'h299; end
+ 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h00A; scA3 = 'h299; end
+ 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E2; scA3 = 'h299; end
+ 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 11: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1CC; scA3 = 'X; end
+ default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ endcase
+end
+
+else if( (opcode[11:6] & 'h37) == 'h1) begin
+ unique case ( col)
+ 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h100; scA3 = 'X; end
+ 1: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h006; scA3 = 'h299; end
+ 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h21C; scA3 = 'h299; end
+ 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h103; scA3 = 'h299; end
+ 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1C2; scA3 = 'h299; end
+ 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E3; scA3 = 'h299; end
+ 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h00A; scA3 = 'h299; end
+ 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E2; scA3 = 'h299; end
+ 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 11: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1CC; scA3 = 'X; end
+ default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ endcase
+end
+
+else if( (opcode[11:6] & 'h1F) == 'hA) begin
+ unique case ( col)
+ 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h10C; scA3 = 'X; end
+ 1: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h00B; scA3 = 'h29D; end
+ 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h00F; scA3 = 'h29D; end
+ 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h179; scA3 = 'h29D; end
+ 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h1C6; scA3 = 'h29D; end
+ 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h1E7; scA3 = 'h29D; end
+ 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h00E; scA3 = 'h29D; end
+ 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h1E6; scA3 = 'h29D; end
+ 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 11: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ endcase
+end
+
+else if( (opcode[11:6] & 'h37) == 'h2) begin
+ unique case ( col)
+ 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h10C; scA3 = 'X; end
+ 1: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h00B; scA3 = 'h29D; end
+ 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h00F; scA3 = 'h29D; end
+ 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h179; scA3 = 'h29D; end
+ 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h1C6; scA3 = 'h29D; end
+ 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h1E7; scA3 = 'h29D; end
+ 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h00E; scA3 = 'h29D; end
+ 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h1E6; scA3 = 'h29D; end
+ 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 11: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ endcase
+end
+
+else if( (opcode[11:6] & 'h37) == 'h10) begin
+ unique case ( col)
+ 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h100; scA3 = 'X; end
+ 1: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h006; scA3 = 'h299; end
+ 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h21C; scA3 = 'h299; end
+ 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h103; scA3 = 'h299; end
+ 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1C2; scA3 = 'h299; end
+ 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E3; scA3 = 'h299; end
+ 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h00A; scA3 = 'h299; end
+ 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E2; scA3 = 'h299; end
+ 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 11: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ endcase
+end
+
+else if( (opcode[11:6] & 'h37) == 'h11) begin
+ unique case ( col)
+ 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h100; scA3 = 'X; end
+ 1: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h006; scA3 = 'h299; end
+ 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h21C; scA3 = 'h299; end
+ 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h103; scA3 = 'h299; end
+ 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1C2; scA3 = 'h299; end
+ 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E3; scA3 = 'h299; end
+ 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h00A; scA3 = 'h299; end
+ 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E2; scA3 = 'h299; end
+ 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 11: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ endcase
+end
+
+else if( (opcode[11:6] & 'h37) == 'h12) begin
+ unique case ( col)
+ 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h10C; scA3 = 'X; end
+ 1: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h00B; scA3 = 'h29D; end
+ 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h00F; scA3 = 'h29D; end
+ 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h179; scA3 = 'h29D; end
+ 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h1C6; scA3 = 'h29D; end
+ 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h1E7; scA3 = 'h29D; end
+ 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h00E; scA3 = 'h29D; end
+ 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h1E6; scA3 = 'h29D; end
+ 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 11: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ endcase
+end
+
+else if( (opcode[11:6] & 'h7) == 'h4) begin
+ unique case ( col)
+ 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E7; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 1: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1D2; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h006; arA23[ 'h0] = 'X; scA3 = 'h215; end
+ 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h21C; arA23[ 'h0] = 'X; scA3 = 'h215; end
+ 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h103; arA23[ 'h0] = 'X; scA3 = 'h215; end
+ 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1C2; arA23[ 'h0] = 'X; scA3 = 'h215; end
+ 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1E3; arA23[ 'h0] = 'X; scA3 = 'h215; end
+ 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h00A; arA23[ 'h0] = 'X; scA3 = 'h215; end
+ 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1E2; arA23[ 'h0] = 'X; scA3 = 'h215; end
+ 9: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1C2; arA23[ 'h0] = 'X; scA3 = 'h215; end
+ 10: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1E3; arA23[ 'h0] = 'X; scA3 = 'h215; end
+ 11: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h0EA; arA23[ 'h0] = 'h0AB; scA3 = 'X; end
+ default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ endcase
+end
+
+else if( (opcode[11:6] & 'h7) == 'h5) begin
+ unique case ( col)
+ 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3EF; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 1: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1D6; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h006; arA23[ 'h0] = 'X; scA3 = 'h081; end
+ 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h21C; arA23[ 'h0] = 'X; scA3 = 'h081; end
+ 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h103; arA23[ 'h0] = 'X; scA3 = 'h081; end
+ 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1C2; arA23[ 'h0] = 'X; scA3 = 'h081; end
+ 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1E3; arA23[ 'h0] = 'X; scA3 = 'h081; end
+ 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h00A; arA23[ 'h0] = 'X; scA3 = 'h081; end
+ 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1E2; arA23[ 'h0] = 'X; scA3 = 'h081; end
+ 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 11: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ endcase
+end
+
+else if( (opcode[11:6] & 'h7) == 'h7) begin
+ unique case ( col)
+ 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3EF; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 1: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1CE; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h006; arA23[ 'h0] = 'X; scA3 = 'h081; end
+ 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h21C; arA23[ 'h0] = 'X; scA3 = 'h081; end
+ 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h103; arA23[ 'h0] = 'X; scA3 = 'h081; end
+ 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1C2; arA23[ 'h0] = 'X; scA3 = 'h081; end
+ 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1E3; arA23[ 'h0] = 'X; scA3 = 'h081; end
+ 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h00A; arA23[ 'h0] = 'X; scA3 = 'h081; end
+ 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1E2; arA23[ 'h0] = 'X; scA3 = 'h081; end
+ 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 11: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ endcase
+end
+
+else if( (opcode[11:6] & 'h7) == 'h6) begin
+ unique case ( col)
+ 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3EB; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 1: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1CA; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h006; arA23[ 'h0] = 'X; scA3 = 'h069; end
+ 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h21C; arA23[ 'h0] = 'X; scA3 = 'h069; end
+ 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h103; arA23[ 'h0] = 'X; scA3 = 'h069; end
+ 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1C2; arA23[ 'h0] = 'X; scA3 = 'h069; end
+ 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1E3; arA23[ 'h0] = 'X; scA3 = 'h069; end
+ 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h00A; arA23[ 'h0] = 'X; scA3 = 'h069; end
+ 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h1E2; arA23[ 'h0] = 'X; scA3 = 'h069; end
+ 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 11: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ endcase
+end
+
+else if( opcode[11:6] == 'h20) begin
+ unique case ( col)
+ 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h3E7; scA3 = 'X; end
+ 1: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h006; scA3 = 'h215; end
+ 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h21C; scA3 = 'h215; end
+ 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h103; scA3 = 'h215; end
+ 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1C2; scA3 = 'h215; end
+ 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E3; scA3 = 'h215; end
+ 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h00A; scA3 = 'h215; end
+ 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E2; scA3 = 'h215; end
+ 9: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1C2; scA3 = 'h215; end
+ 10: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E3; scA3 = 'h215; end
+ 11: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ endcase
+end
+
+else if( opcode[11:6] == 'h21) begin
+ unique case ( col)
+ 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h3EF; scA3 = 'X; end
+ 1: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h006; scA3 = 'h081; end
+ 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h21C; scA3 = 'h081; end
+ 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h103; scA3 = 'h081; end
+ 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1C2; scA3 = 'h081; end
+ 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E3; scA3 = 'h081; end
+ 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h00A; scA3 = 'h081; end
+ 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E2; scA3 = 'h081; end
+ 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 11: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ endcase
+end
+
+else if( opcode[11:6] == 'h23) begin
+ unique case ( col)
+ 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h3EF; scA3 = 'X; end
+ 1: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h006; scA3 = 'h081; end
+ 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h21C; scA3 = 'h081; end
+ 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h103; scA3 = 'h081; end
+ 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1C2; scA3 = 'h081; end
+ 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E3; scA3 = 'h081; end
+ 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h00A; scA3 = 'h081; end
+ 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E2; scA3 = 'h081; end
+ 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 11: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ endcase
+end
+
+else if( opcode[11:6] == 'h22) begin
+ unique case ( col)
+ 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h3EB; scA3 = 'X; end
+ 1: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h006; scA3 = 'h069; end
+ 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h21C; scA3 = 'h069; end
+ 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h103; scA3 = 'h069; end
+ 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1C2; scA3 = 'h069; end
+ 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E3; scA3 = 'h069; end
+ 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h00A; scA3 = 'h069; end
+ 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E2; scA3 = 'h069; end
+ 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 11: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ endcase
+end
+
+else if( opcode[11:6] == 'h30) begin
+ unique case ( col)
+ 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h108; scA3 = 'X; end
+ 1: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h006; scA3 = 'h087; end
+ 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h21C; scA3 = 'h087; end
+ 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h103; scA3 = 'h087; end
+ 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1C2; scA3 = 'h087; end
+ 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E3; scA3 = 'h087; end
+ 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h00A; scA3 = 'h087; end
+ 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E2; scA3 = 'h087; end
+ 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 11: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ endcase
+end
+
+else if( opcode[11:6] == 'h31) begin
+ unique case ( col)
+ 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h108; scA3 = 'X; end
+ 1: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h006; scA3 = 'h087; end
+ 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h21C; scA3 = 'h087; end
+ 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h103; scA3 = 'h087; end
+ 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1C2; scA3 = 'h087; end
+ 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E3; scA3 = 'h087; end
+ 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h00A; scA3 = 'h087; end
+ 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h2B9; arA23[ 'h0] = 'h1E2; scA3 = 'h087; end
+ 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 11: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ endcase
+end
+
+else if( opcode[11:6] == 'h32) begin
+ unique case ( col)
+ 0: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h104; scA3 = 'X; end
+ 1: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 2: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h00B; scA3 = 'h08F; end
+ 3: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h00F; scA3 = 'h08F; end
+ 4: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h179; scA3 = 'h08F; end
+ 5: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h1C6; scA3 = 'h08F; end
+ 6: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h1E7; scA3 = 'h08F; end
+ 7: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h00E; scA3 = 'h08F; end
+ 8: begin arIll[ 'h0] = 1'b0; arA1[ 'h0] = 'h3E0; arA23[ 'h0] = 'h1E6; scA3 = 'h08F; end
+ 9: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 10: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ 11: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ default: begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+ endcase
+end
+
+else begin arIll[ 'h0] = 1'b1; arA1[ 'h0] = 'X ; arA23[ 'h0] = 'X; scA3 = 'X; end
+
+end
+
+
+//
+// Line: 4
+//
+always_comb begin
+
+if( (opcode[11:6] & 'h27) == 'h0) begin
+ unique case ( col)
+ 0: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h133; arA23[ 'h4] = 'X; end
+ 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h006; arA23[ 'h4] = 'h2B8; end
+ 3: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h21C; arA23[ 'h4] = 'h2B8; end
+ 4: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h103; arA23[ 'h4] = 'h2B8; end
+ 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1C2; arA23[ 'h4] = 'h2B8; end
+ 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E3; arA23[ 'h4] = 'h2B8; end
+ 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h00A; arA23[ 'h4] = 'h2B8; end
+ 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E2; arA23[ 'h4] = 'h2B8; end
+ 9: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 10: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 11: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ endcase
+end
+
+else if( (opcode[11:6] & 'h27) == 'h1) begin
+ unique case ( col)
+ 0: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h133; arA23[ 'h4] = 'X; end
+ 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h006; arA23[ 'h4] = 'h2B8; end
+ 3: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h21C; arA23[ 'h4] = 'h2B8; end
+ 4: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h103; arA23[ 'h4] = 'h2B8; end
+ 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1C2; arA23[ 'h4] = 'h2B8; end
+ 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E3; arA23[ 'h4] = 'h2B8; end
+ 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h00A; arA23[ 'h4] = 'h2B8; end
+ 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E2; arA23[ 'h4] = 'h2B8; end
+ 9: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 10: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 11: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ endcase
+end
+
+else if( (opcode[11:6] & 'h27) == 'h2) begin
+ unique case ( col)
+ 0: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h137; arA23[ 'h4] = 'X; end
+ 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h00B; arA23[ 'h4] = 'h2BC; end
+ 3: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h00F; arA23[ 'h4] = 'h2BC; end
+ 4: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h179; arA23[ 'h4] = 'h2BC; end
+ 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1C6; arA23[ 'h4] = 'h2BC; end
+ 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E7; arA23[ 'h4] = 'h2BC; end
+ 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h00E; arA23[ 'h4] = 'h2BC; end
+ 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E6; arA23[ 'h4] = 'h2BC; end
+ 9: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 10: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 11: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ endcase
+end
+
+else if( opcode[11:6] == 'h3) begin
+ unique case ( col)
+ 0: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h3A5; arA23[ 'h4] = 'X; end
+ 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h006; arA23[ 'h4] = 'h3A1; end
+ 3: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h21C; arA23[ 'h4] = 'h3A1; end
+ 4: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h103; arA23[ 'h4] = 'h3A1; end
+ 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1C2; arA23[ 'h4] = 'h3A1; end
+ 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E3; arA23[ 'h4] = 'h3A1; end
+ 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h00A; arA23[ 'h4] = 'h3A1; end
+ 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E2; arA23[ 'h4] = 'h3A1; end
+ 9: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 10: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 11: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ endcase
+end
+
+else if( opcode[11:6] == 'h13) begin
+ unique case ( col)
+ 0: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h301; arA23[ 'h4] = 'X; end
+ 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h006; arA23[ 'h4] = 'h159; end
+ 3: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h21C; arA23[ 'h4] = 'h159; end
+ 4: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h103; arA23[ 'h4] = 'h159; end
+ 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1C2; arA23[ 'h4] = 'h159; end
+ 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E3; arA23[ 'h4] = 'h159; end
+ 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h00A; arA23[ 'h4] = 'h159; end
+ 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E2; arA23[ 'h4] = 'h159; end
+ 9: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1C2; arA23[ 'h4] = 'h159; end
+ 10: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E3; arA23[ 'h4] = 'h159; end
+ 11: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h0EA; arA23[ 'h4] = 'h301; end
+ default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ endcase
+end
+
+else if( opcode[11:6] == 'h1B) begin
+ unique case ( col)
+ 0: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h301; arA23[ 'h4] = 'X; end
+ 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h006; arA23[ 'h4] = 'h159; end
+ 3: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h21C; arA23[ 'h4] = 'h159; end
+ 4: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h103; arA23[ 'h4] = 'h159; end
+ 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1C2; arA23[ 'h4] = 'h159; end
+ 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E3; arA23[ 'h4] = 'h159; end
+ 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h00A; arA23[ 'h4] = 'h159; end
+ 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E2; arA23[ 'h4] = 'h159; end
+ 9: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1C2; arA23[ 'h4] = 'h159; end
+ 10: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E3; arA23[ 'h4] = 'h159; end
+ 11: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h0EA; arA23[ 'h4] = 'h301; end
+ default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ endcase
+end
+
+else if( opcode[11:6] == 'h20) begin
+ unique case ( col)
+ 0: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h13B; arA23[ 'h4] = 'X; end
+ 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h006; arA23[ 'h4] = 'h15C; end
+ 3: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h21C; arA23[ 'h4] = 'h15C; end
+ 4: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h103; arA23[ 'h4] = 'h15C; end
+ 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1C2; arA23[ 'h4] = 'h15C; end
+ 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E3; arA23[ 'h4] = 'h15C; end
+ 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h00A; arA23[ 'h4] = 'h15C; end
+ 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E2; arA23[ 'h4] = 'h15C; end
+ 9: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 10: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 11: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ endcase
+end
+
+else if( opcode[11:6] == 'h21) begin
+ unique case ( col)
+ 0: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h341; arA23[ 'h4] = 'X; end
+ 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h17C; arA23[ 'h4] = 'X; end
+ 3: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 4: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h17D; arA23[ 'h4] = 'X; end
+ 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1FF; arA23[ 'h4] = 'X; end
+ 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h178; arA23[ 'h4] = 'X; end
+ 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1FA; arA23[ 'h4] = 'X; end
+ 9: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h17D; arA23[ 'h4] = 'X; end
+ 10: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1FF; arA23[ 'h4] = 'X; end
+ 11: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ endcase
+end
+
+else if( opcode[11:6] == 'h22) begin
+ unique case ( col)
+ 0: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h133; arA23[ 'h4] = 'X; end
+ 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h3A0; arA23[ 'h4] = 'X; end
+ 3: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 4: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h3A4; arA23[ 'h4] = 'X; end
+ 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1F1; arA23[ 'h4] = 'X; end
+ 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h325; arA23[ 'h4] = 'X; end
+ 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1ED; arA23[ 'h4] = 'X; end
+ 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E5; arA23[ 'h4] = 'X; end
+ 9: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 10: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 11: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ endcase
+end
+
+else if( opcode[11:6] == 'h23) begin
+ unique case ( col)
+ 0: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h232; arA23[ 'h4] = 'X; end
+ 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h3A0; arA23[ 'h4] = 'X; end
+ 3: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 4: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h3A4; arA23[ 'h4] = 'X; end
+ 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1F1; arA23[ 'h4] = 'X; end
+ 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h325; arA23[ 'h4] = 'X; end
+ 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1ED; arA23[ 'h4] = 'X; end
+ 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E5; arA23[ 'h4] = 'X; end
+ 9: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 10: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 11: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ endcase
+end
+
+else if( opcode[11:6] == 'h28) begin
+ unique case ( col)
+ 0: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h12D; arA23[ 'h4] = 'X; end
+ 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h006; arA23[ 'h4] = 'h3C3; end
+ 3: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h21C; arA23[ 'h4] = 'h3C3; end
+ 4: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h103; arA23[ 'h4] = 'h3C3; end
+ 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1C2; arA23[ 'h4] = 'h3C3; end
+ 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E3; arA23[ 'h4] = 'h3C3; end
+ 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h00A; arA23[ 'h4] = 'h3C3; end
+ 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E2; arA23[ 'h4] = 'h3C3; end
+ 9: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 10: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 11: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ endcase
+end
+
+else if( opcode[11:6] == 'h29) begin
+ unique case ( col)
+ 0: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h12D; arA23[ 'h4] = 'X; end
+ 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h006; arA23[ 'h4] = 'h3C3; end
+ 3: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h21C; arA23[ 'h4] = 'h3C3; end
+ 4: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h103; arA23[ 'h4] = 'h3C3; end
+ 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1C2; arA23[ 'h4] = 'h3C3; end
+ 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E3; arA23[ 'h4] = 'h3C3; end
+ 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h00A; arA23[ 'h4] = 'h3C3; end
+ 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E2; arA23[ 'h4] = 'h3C3; end
+ 9: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 10: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 11: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ endcase
+end
+
+else if( opcode[11:6] == 'h2A) begin
+ unique case ( col)
+ 0: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h125; arA23[ 'h4] = 'X; end
+ 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h00B; arA23[ 'h4] = 'h3CB; end
+ 3: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h00F; arA23[ 'h4] = 'h3CB; end
+ 4: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h179; arA23[ 'h4] = 'h3CB; end
+ 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1C6; arA23[ 'h4] = 'h3CB; end
+ 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E7; arA23[ 'h4] = 'h3CB; end
+ 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h00E; arA23[ 'h4] = 'h3CB; end
+ 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E6; arA23[ 'h4] = 'h3CB; end
+ 9: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 10: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 11: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ endcase
+end
+
+else if( opcode[11:6] == 'h2B) begin
+ unique case ( col)
+ 0: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h345; arA23[ 'h4] = 'X; end
+ 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h006; arA23[ 'h4] = 'h343; end
+ 3: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h21C; arA23[ 'h4] = 'h343; end
+ 4: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h103; arA23[ 'h4] = 'h343; end
+ 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1C2; arA23[ 'h4] = 'h343; end
+ 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E3; arA23[ 'h4] = 'h343; end
+ 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h00A; arA23[ 'h4] = 'h343; end
+ 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E2; arA23[ 'h4] = 'h343; end
+ 9: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 10: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 11: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ endcase
+end
+
+else if( (opcode[11:6] & 'h3E) == 'h32) begin
+ unique case ( col)
+ 0: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h127; arA23[ 'h4] = 'X; end
+ 3: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h123; arA23[ 'h4] = 'X; end
+ 4: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1FD; arA23[ 'h4] = 'X; end
+ 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1F5; arA23[ 'h4] = 'X; end
+ 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1F9; arA23[ 'h4] = 'X; end
+ 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E9; arA23[ 'h4] = 'X; end
+ 9: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1FD; arA23[ 'h4] = 'X; end
+ 10: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1F5; arA23[ 'h4] = 'X; end
+ 11: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ endcase
+end
+
+else if( (opcode[11:6] & 'h7) == 'h6) begin
+ unique case ( col)
+ 0: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h152; arA23[ 'h4] = 'X; end
+ 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h006; arA23[ 'h4] = 'h151; end
+ 3: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h21C; arA23[ 'h4] = 'h151; end
+ 4: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h103; arA23[ 'h4] = 'h151; end
+ 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1C2; arA23[ 'h4] = 'h151; end
+ 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E3; arA23[ 'h4] = 'h151; end
+ 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h00A; arA23[ 'h4] = 'h151; end
+ 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E2; arA23[ 'h4] = 'h151; end
+ 9: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1C2; arA23[ 'h4] = 'h151; end
+ 10: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1E3; arA23[ 'h4] = 'h151; end
+ 11: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h0EA; arA23[ 'h4] = 'h152; end
+ default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ endcase
+end
+
+else if( (opcode[11:6] & 'h7) == 'h7) begin
+ unique case ( col)
+ 0: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h2F1; arA23[ 'h4] = 'X; end
+ 3: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 4: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h2F2; arA23[ 'h4] = 'X; end
+ 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1FB; arA23[ 'h4] = 'X; end
+ 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h275; arA23[ 'h4] = 'X; end
+ 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h3E4; arA23[ 'h4] = 'X; end
+ 9: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h2F2; arA23[ 'h4] = 'X; end
+ 10: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1FB; arA23[ 'h4] = 'X; end
+ 11: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ endcase
+end
+
+else if( opcode[11:6] == 'h3A) begin
+ unique case ( col)
+ 0: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h273; arA23[ 'h4] = 'X; end
+ 3: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 4: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h2B0; arA23[ 'h4] = 'X; end
+ 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1F3; arA23[ 'h4] = 'X; end
+ 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h293; arA23[ 'h4] = 'X; end
+ 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1F2; arA23[ 'h4] = 'X; end
+ 9: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h2B0; arA23[ 'h4] = 'X; end
+ 10: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1F3; arA23[ 'h4] = 'X; end
+ 11: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ endcase
+end
+
+else if( opcode[11:6] == 'h3B) begin
+ unique case ( col)
+ 0: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 1: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 2: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h255; arA23[ 'h4] = 'X; end
+ 3: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 4: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ 5: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h2B4; arA23[ 'h4] = 'X; end
+ 6: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1F7; arA23[ 'h4] = 'X; end
+ 7: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h297; arA23[ 'h4] = 'X; end
+ 8: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1F6; arA23[ 'h4] = 'X; end
+ 9: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h2B4; arA23[ 'h4] = 'X; end
+ 10: begin arIll[ 'h4] = 1'b0; arA1[ 'h4] = 'h1F7; arA23[ 'h4] = 'X; end
+ 11: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ default: begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+ endcase
+end
+
+else if( opcode[11:6] == 'h39) begin
+ arIll[ 'h4] = illMisc; arA1[ 'h4] = a1Misc ; arA23[ 'h4] = 'X;
+end
+
+else begin arIll[ 'h4] = 1'b1; arA1[ 'h4] = 'X ; arA23[ 'h4] = 'X; end
+
+end
+
+always_comb begin
+
+//
+// Line: 1
+//
+unique case( movEa)
+
+0: // Row: 0
+ unique case ( col)
+ 0: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h121; arA23[ 'h1] = 'X; end
+ 1: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end
+ 2: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h006; arA23[ 'h1] = 'h29B; end
+ 3: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h21C; arA23[ 'h1] = 'h29B; end
+ 4: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h103; arA23[ 'h1] = 'h29B; end
+ 5: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1C2; arA23[ 'h1] = 'h29B; end
+ 6: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E3; arA23[ 'h1] = 'h29B; end
+ 7: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h00A; arA23[ 'h1] = 'h29B; end
+ 8: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E2; arA23[ 'h1] = 'h29B; end
+ 9: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1C2; arA23[ 'h1] = 'h29B; end
+ 10: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E3; arA23[ 'h1] = 'h29B; end
+ 11: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h0EA; arA23[ 'h1] = 'h121; end
+ default: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end
+ endcase
+
+2: // Row: 2
+ unique case ( col)
+ 0: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h2FA; arA23[ 'h1] = 'X; end
+ 1: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end
+ 2: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h006; arA23[ 'h1] = 'h3AB; end
+ 3: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h21C; arA23[ 'h1] = 'h3AB; end
+ 4: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h103; arA23[ 'h1] = 'h3AB; end
+ 5: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1C2; arA23[ 'h1] = 'h3AB; end
+ 6: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E3; arA23[ 'h1] = 'h3AB; end
+ 7: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h00A; arA23[ 'h1] = 'h3AB; end
+ 8: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E2; arA23[ 'h1] = 'h3AB; end
+ 9: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1C2; arA23[ 'h1] = 'h3AB; end
+ 10: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E3; arA23[ 'h1] = 'h3AB; end
+ 11: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h0EA; arA23[ 'h1] = 'h2FA; end
+ default: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end
+ endcase
+
+3: // Row: 3
+ unique case ( col)
+ 0: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h2FE; arA23[ 'h1] = 'X; end
+ 1: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end
+ 2: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h006; arA23[ 'h1] = 'h3AF; end
+ 3: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h21C; arA23[ 'h1] = 'h3AF; end
+ 4: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h103; arA23[ 'h1] = 'h3AF; end
+ 5: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1C2; arA23[ 'h1] = 'h3AF; end
+ 6: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E3; arA23[ 'h1] = 'h3AF; end
+ 7: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h00A; arA23[ 'h1] = 'h3AF; end
+ 8: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E2; arA23[ 'h1] = 'h3AF; end
+ 9: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1C2; arA23[ 'h1] = 'h3AF; end
+ 10: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E3; arA23[ 'h1] = 'h3AF; end
+ 11: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h0EA; arA23[ 'h1] = 'h2FE; end
+ default: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end
+ endcase
+
+4: // Row: 4
+ unique case ( col)
+ 0: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h2F8; arA23[ 'h1] = 'X; end
+ 1: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end
+ 2: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h006; arA23[ 'h1] = 'h38B; end
+ 3: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h21C; arA23[ 'h1] = 'h38B; end
+ 4: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h103; arA23[ 'h1] = 'h38B; end
+ 5: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1C2; arA23[ 'h1] = 'h38B; end
+ 6: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E3; arA23[ 'h1] = 'h38B; end
+ 7: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h00A; arA23[ 'h1] = 'h38B; end
+ 8: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E2; arA23[ 'h1] = 'h38B; end
+ 9: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1C2; arA23[ 'h1] = 'h38B; end
+ 10: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E3; arA23[ 'h1] = 'h38B; end
+ 11: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h0EA; arA23[ 'h1] = 'h2F8; end
+ default: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end
+ endcase
+
+5: // Row: 5
+ unique case ( col)
+ 0: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h2DA; arA23[ 'h1] = 'X; end
+ 1: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end
+ 2: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h006; arA23[ 'h1] = 'h38A; end
+ 3: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h21C; arA23[ 'h1] = 'h38A; end
+ 4: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h103; arA23[ 'h1] = 'h38A; end
+ 5: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1C2; arA23[ 'h1] = 'h38A; end
+ 6: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E3; arA23[ 'h1] = 'h38A; end
+ 7: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h00A; arA23[ 'h1] = 'h38A; end
+ 8: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E2; arA23[ 'h1] = 'h38A; end
+ 9: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1C2; arA23[ 'h1] = 'h38A; end
+ 10: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E3; arA23[ 'h1] = 'h38A; end
+ 11: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h0EA; arA23[ 'h1] = 'h2DA; end
+ default: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end
+ endcase
+
+6: // Row: 6
+ unique case ( col)
+ 0: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1EB; arA23[ 'h1] = 'X; end
+ 1: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end
+ 2: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h006; arA23[ 'h1] = 'h298; end
+ 3: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h21C; arA23[ 'h1] = 'h298; end
+ 4: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h103; arA23[ 'h1] = 'h298; end
+ 5: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1C2; arA23[ 'h1] = 'h298; end
+ 6: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E3; arA23[ 'h1] = 'h298; end
+ 7: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h00A; arA23[ 'h1] = 'h298; end
+ 8: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E2; arA23[ 'h1] = 'h298; end
+ 9: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1C2; arA23[ 'h1] = 'h298; end
+ 10: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E3; arA23[ 'h1] = 'h298; end
+ 11: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h0EA; arA23[ 'h1] = 'h1EB; end
+ default: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end
+ endcase
+
+7: // Row: 7
+ unique case ( col)
+ 0: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h2D9; arA23[ 'h1] = 'X; end
+ 1: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end
+ 2: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h006; arA23[ 'h1] = 'h388; end
+ 3: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h21C; arA23[ 'h1] = 'h388; end
+ 4: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h103; arA23[ 'h1] = 'h388; end
+ 5: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1C2; arA23[ 'h1] = 'h388; end
+ 6: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E3; arA23[ 'h1] = 'h388; end
+ 7: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h00A; arA23[ 'h1] = 'h388; end
+ 8: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E2; arA23[ 'h1] = 'h388; end
+ 9: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1C2; arA23[ 'h1] = 'h388; end
+ 10: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E3; arA23[ 'h1] = 'h388; end
+ 11: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h0EA; arA23[ 'h1] = 'h2D9; end
+ default: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end
+ endcase
+
+8: // Row: 8
+ unique case ( col)
+ 0: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1EA; arA23[ 'h1] = 'X; end
+ 1: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end
+ 2: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h006; arA23[ 'h1] = 'h32B; end
+ 3: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h21C; arA23[ 'h1] = 'h32B; end
+ 4: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h103; arA23[ 'h1] = 'h32B; end
+ 5: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1C2; arA23[ 'h1] = 'h32B; end
+ 6: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E3; arA23[ 'h1] = 'h32B; end
+ 7: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h00A; arA23[ 'h1] = 'h32B; end
+ 8: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E2; arA23[ 'h1] = 'h32B; end
+ 9: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1C2; arA23[ 'h1] = 'h32B; end
+ 10: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h1E3; arA23[ 'h1] = 'h32B; end
+ 11: begin arIll[ 'h1] = 1'b0; arA1[ 'h1] = 'h0EA; arA23[ 'h1] = 'h1EA; end
+ default: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end
+ endcase
+default: begin arIll[ 'h1] = 1'b1; arA1[ 'h1] = 'X ; arA23[ 'h1] = 'X; end
+endcase
+
+//
+// Line: 2
+//
+unique case( movEa)
+
+0: // Row: 0
+ unique case ( col)
+ 0: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h129; arA23[ 'h2] = 'X; end
+ 1: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h129; arA23[ 'h2] = 'X; end
+ 2: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00B; arA23[ 'h2] = 'h29F; end
+ 3: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00F; arA23[ 'h2] = 'h29F; end
+ 4: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h179; arA23[ 'h2] = 'h29F; end
+ 5: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h29F; end
+ 6: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h29F; end
+ 7: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00E; arA23[ 'h2] = 'h29F; end
+ 8: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E6; arA23[ 'h2] = 'h29F; end
+ 9: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h29F; end
+ 10: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h29F; end
+ 11: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h0A7; arA23[ 'h2] = 'h129; end
+ default: begin arIll[ 'h2] = 1'b1; arA1[ 'h2] = 'X ; arA23[ 'h2] = 'X; end
+ endcase
+
+1: // Row: 1
+ unique case ( col)
+ 0: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h129; arA23[ 'h2] = 'X; end
+ 1: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h129; arA23[ 'h2] = 'X; end
+ 2: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00B; arA23[ 'h2] = 'h29F; end
+ 3: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00F; arA23[ 'h2] = 'h29F; end
+ 4: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h179; arA23[ 'h2] = 'h29F; end
+ 5: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h29F; end
+ 6: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h29F; end
+ 7: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00E; arA23[ 'h2] = 'h29F; end
+ 8: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E6; arA23[ 'h2] = 'h29F; end
+ 9: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h29F; end
+ 10: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h29F; end
+ 11: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h0A7; arA23[ 'h2] = 'h129; end
+ default: begin arIll[ 'h2] = 1'b1; arA1[ 'h2] = 'X ; arA23[ 'h2] = 'X; end
+ endcase
+
+2: // Row: 2
+ unique case ( col)
+ 0: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h2F9; arA23[ 'h2] = 'X; end
+ 1: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h2F9; arA23[ 'h2] = 'X; end
+ 2: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00B; arA23[ 'h2] = 'h3A9; end
+ 3: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00F; arA23[ 'h2] = 'h3A9; end
+ 4: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h179; arA23[ 'h2] = 'h3A9; end
+ 5: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h3A9; end
+ 6: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h3A9; end
+ 7: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00E; arA23[ 'h2] = 'h3A9; end
+ 8: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E6; arA23[ 'h2] = 'h3A9; end
+ 9: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h3A9; end
+ 10: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h3A9; end
+ 11: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h0A7; arA23[ 'h2] = 'h2F9; end
+ default: begin arIll[ 'h2] = 1'b1; arA1[ 'h2] = 'X ; arA23[ 'h2] = 'X; end
+ endcase
+
+3: // Row: 3
+ unique case ( col)
+ 0: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h2FD; arA23[ 'h2] = 'X; end
+ 1: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h2FD; arA23[ 'h2] = 'X; end
+ 2: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00B; arA23[ 'h2] = 'h3AD; end
+ 3: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00F; arA23[ 'h2] = 'h3AD; end
+ 4: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h179; arA23[ 'h2] = 'h3AD; end
+ 5: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h3AD; end
+ 6: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h3AD; end
+ 7: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00E; arA23[ 'h2] = 'h3AD; end
+ 8: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E6; arA23[ 'h2] = 'h3AD; end
+ 9: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h3AD; end
+ 10: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h3AD; end
+ 11: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h0A7; arA23[ 'h2] = 'h2FD; end
+ default: begin arIll[ 'h2] = 1'b1; arA1[ 'h2] = 'X ; arA23[ 'h2] = 'X; end
+ endcase
+
+4: // Row: 4
+ unique case ( col)
+ 0: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h2FC; arA23[ 'h2] = 'X; end
+ 1: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h2FC; arA23[ 'h2] = 'X; end
+ 2: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00B; arA23[ 'h2] = 'h38F; end
+ 3: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00F; arA23[ 'h2] = 'h38F; end
+ 4: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h179; arA23[ 'h2] = 'h38F; end
+ 5: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h38F; end
+ 6: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h38F; end
+ 7: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00E; arA23[ 'h2] = 'h38F; end
+ 8: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E6; arA23[ 'h2] = 'h38F; end
+ 9: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h38F; end
+ 10: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h38F; end
+ 11: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h0A7; arA23[ 'h2] = 'h2FC; end
+ default: begin arIll[ 'h2] = 1'b1; arA1[ 'h2] = 'X ; arA23[ 'h2] = 'X; end
+ endcase
+
+5: // Row: 5
+ unique case ( col)
+ 0: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h2DE; arA23[ 'h2] = 'X; end
+ 1: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h2DE; arA23[ 'h2] = 'X; end
+ 2: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00B; arA23[ 'h2] = 'h38E; end
+ 3: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00F; arA23[ 'h2] = 'h38E; end
+ 4: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h179; arA23[ 'h2] = 'h38E; end
+ 5: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h38E; end
+ 6: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h38E; end
+ 7: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00E; arA23[ 'h2] = 'h38E; end
+ 8: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E6; arA23[ 'h2] = 'h38E; end
+ 9: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h38E; end
+ 10: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h38E; end
+ 11: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h0A7; arA23[ 'h2] = 'h2DE; end
+ default: begin arIll[ 'h2] = 1'b1; arA1[ 'h2] = 'X ; arA23[ 'h2] = 'X; end
+ endcase
+
+6: // Row: 6
+ unique case ( col)
+ 0: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1EF; arA23[ 'h2] = 'X; end
+ 1: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1EF; arA23[ 'h2] = 'X; end
+ 2: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00B; arA23[ 'h2] = 'h29C; end
+ 3: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00F; arA23[ 'h2] = 'h29C; end
+ 4: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h179; arA23[ 'h2] = 'h29C; end
+ 5: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h29C; end
+ 6: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h29C; end
+ 7: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00E; arA23[ 'h2] = 'h29C; end
+ 8: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E6; arA23[ 'h2] = 'h29C; end
+ 9: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h29C; end
+ 10: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h29C; end
+ 11: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h0A7; arA23[ 'h2] = 'h1EF; end
+ default: begin arIll[ 'h2] = 1'b1; arA1[ 'h2] = 'X ; arA23[ 'h2] = 'X; end
+ endcase
+
+7: // Row: 7
+ unique case ( col)
+ 0: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h2DD; arA23[ 'h2] = 'X; end
+ 1: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h2DD; arA23[ 'h2] = 'X; end
+ 2: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00B; arA23[ 'h2] = 'h38C; end
+ 3: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00F; arA23[ 'h2] = 'h38C; end
+ 4: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h179; arA23[ 'h2] = 'h38C; end
+ 5: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h38C; end
+ 6: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h38C; end
+ 7: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00E; arA23[ 'h2] = 'h38C; end
+ 8: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E6; arA23[ 'h2] = 'h38C; end
+ 9: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h38C; end
+ 10: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h38C; end
+ 11: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h0A7; arA23[ 'h2] = 'h2DD; end
+ default: begin arIll[ 'h2] = 1'b1; arA1[ 'h2] = 'X ; arA23[ 'h2] = 'X; end
+ endcase
+
+8: // Row: 8
+ unique case ( col)
+ 0: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1EE; arA23[ 'h2] = 'X; end
+ 1: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1EE; arA23[ 'h2] = 'X; end
+ 2: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00B; arA23[ 'h2] = 'h30F; end
+ 3: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00F; arA23[ 'h2] = 'h30F; end
+ 4: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h179; arA23[ 'h2] = 'h30F; end
+ 5: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h30F; end
+ 6: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h30F; end
+ 7: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h00E; arA23[ 'h2] = 'h30F; end
+ 8: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E6; arA23[ 'h2] = 'h30F; end
+ 9: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1C6; arA23[ 'h2] = 'h30F; end
+ 10: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h1E7; arA23[ 'h2] = 'h30F; end
+ 11: begin arIll[ 'h2] = 1'b0; arA1[ 'h2] = 'h0A7; arA23[ 'h2] = 'h1EE; end
+ default: begin arIll[ 'h2] = 1'b1; arA1[ 'h2] = 'X ; arA23[ 'h2] = 'X; end
+ endcase
+default: begin arIll[ 'h2] = 1'b1; arA1[ 'h2] = 'X ; arA23[ 'h2] = 'X; end
+endcase
+
+//
+// Line: 3
+//
+unique case( movEa)
+
+0: // Row: 0
+ unique case ( col)
+ 0: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h121; arA23[ 'h3] = 'X; end
+ 1: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h121; arA23[ 'h3] = 'X; end
+ 2: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h006; arA23[ 'h3] = 'h29B; end
+ 3: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h21C; arA23[ 'h3] = 'h29B; end
+ 4: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h103; arA23[ 'h3] = 'h29B; end
+ 5: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h29B; end
+ 6: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h29B; end
+ 7: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h00A; arA23[ 'h3] = 'h29B; end
+ 8: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E2; arA23[ 'h3] = 'h29B; end
+ 9: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h29B; end
+ 10: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h29B; end
+ 11: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h0EA; arA23[ 'h3] = 'h121; end
+ default: begin arIll[ 'h3] = 1'b1; arA1[ 'h3] = 'X ; arA23[ 'h3] = 'X; end
+ endcase
+
+1: // Row: 1
+ unique case ( col)
+ 0: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h279; arA23[ 'h3] = 'X; end
+ 1: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h279; arA23[ 'h3] = 'X; end
+ 2: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h006; arA23[ 'h3] = 'h158; end
+ 3: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h21C; arA23[ 'h3] = 'h158; end
+ 4: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h103; arA23[ 'h3] = 'h158; end
+ 5: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h158; end
+ 6: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h158; end
+ 7: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h00A; arA23[ 'h3] = 'h158; end
+ 8: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E2; arA23[ 'h3] = 'h158; end
+ 9: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h158; end
+ 10: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h158; end
+ 11: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h0EA; arA23[ 'h3] = 'h279; end
+ default: begin arIll[ 'h3] = 1'b1; arA1[ 'h3] = 'X ; arA23[ 'h3] = 'X; end
+ endcase
+
+2: // Row: 2
+ unique case ( col)
+ 0: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h2FA; arA23[ 'h3] = 'X; end
+ 1: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h2FA; arA23[ 'h3] = 'X; end
+ 2: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h006; arA23[ 'h3] = 'h3AB; end
+ 3: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h21C; arA23[ 'h3] = 'h3AB; end
+ 4: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h103; arA23[ 'h3] = 'h3AB; end
+ 5: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h3AB; end
+ 6: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h3AB; end
+ 7: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h00A; arA23[ 'h3] = 'h3AB; end
+ 8: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E2; arA23[ 'h3] = 'h3AB; end
+ 9: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h3AB; end
+ 10: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h3AB; end
+ 11: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h0EA; arA23[ 'h3] = 'h2FA; end
+ default: begin arIll[ 'h3] = 1'b1; arA1[ 'h3] = 'X ; arA23[ 'h3] = 'X; end
+ endcase
+
+3: // Row: 3
+ unique case ( col)
+ 0: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h2FE; arA23[ 'h3] = 'X; end
+ 1: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h2FE; arA23[ 'h3] = 'X; end
+ 2: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h006; arA23[ 'h3] = 'h3AF; end
+ 3: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h21C; arA23[ 'h3] = 'h3AF; end
+ 4: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h103; arA23[ 'h3] = 'h3AF; end
+ 5: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h3AF; end
+ 6: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h3AF; end
+ 7: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h00A; arA23[ 'h3] = 'h3AF; end
+ 8: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E2; arA23[ 'h3] = 'h3AF; end
+ 9: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h3AF; end
+ 10: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h3AF; end
+ 11: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h0EA; arA23[ 'h3] = 'h2FE; end
+ default: begin arIll[ 'h3] = 1'b1; arA1[ 'h3] = 'X ; arA23[ 'h3] = 'X; end
+ endcase
+
+4: // Row: 4
+ unique case ( col)
+ 0: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h2F8; arA23[ 'h3] = 'X; end
+ 1: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h2F8; arA23[ 'h3] = 'X; end
+ 2: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h006; arA23[ 'h3] = 'h38B; end
+ 3: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h21C; arA23[ 'h3] = 'h38B; end
+ 4: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h103; arA23[ 'h3] = 'h38B; end
+ 5: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h38B; end
+ 6: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h38B; end
+ 7: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h00A; arA23[ 'h3] = 'h38B; end
+ 8: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E2; arA23[ 'h3] = 'h38B; end
+ 9: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h38B; end
+ 10: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h38B; end
+ 11: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h0EA; arA23[ 'h3] = 'h2F8; end
+ default: begin arIll[ 'h3] = 1'b1; arA1[ 'h3] = 'X ; arA23[ 'h3] = 'X; end
+ endcase
+
+5: // Row: 5
+ unique case ( col)
+ 0: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h2DA; arA23[ 'h3] = 'X; end
+ 1: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h2DA; arA23[ 'h3] = 'X; end
+ 2: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h006; arA23[ 'h3] = 'h38A; end
+ 3: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h21C; arA23[ 'h3] = 'h38A; end
+ 4: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h103; arA23[ 'h3] = 'h38A; end
+ 5: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h38A; end
+ 6: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h38A; end
+ 7: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h00A; arA23[ 'h3] = 'h38A; end
+ 8: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E2; arA23[ 'h3] = 'h38A; end
+ 9: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h38A; end
+ 10: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h38A; end
+ 11: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h0EA; arA23[ 'h3] = 'h2DA; end
+ default: begin arIll[ 'h3] = 1'b1; arA1[ 'h3] = 'X ; arA23[ 'h3] = 'X; end
+ endcase
+
+6: // Row: 6
+ unique case ( col)
+ 0: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1EB; arA23[ 'h3] = 'X; end
+ 1: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1EB; arA23[ 'h3] = 'X; end
+ 2: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h006; arA23[ 'h3] = 'h298; end
+ 3: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h21C; arA23[ 'h3] = 'h298; end
+ 4: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h103; arA23[ 'h3] = 'h298; end
+ 5: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h298; end
+ 6: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h298; end
+ 7: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h00A; arA23[ 'h3] = 'h298; end
+ 8: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E2; arA23[ 'h3] = 'h298; end
+ 9: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h298; end
+ 10: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h298; end
+ 11: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h0EA; arA23[ 'h3] = 'h1EB; end
+ default: begin arIll[ 'h3] = 1'b1; arA1[ 'h3] = 'X ; arA23[ 'h3] = 'X; end
+ endcase
+
+7: // Row: 7
+ unique case ( col)
+ 0: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h2D9; arA23[ 'h3] = 'X; end
+ 1: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h2D9; arA23[ 'h3] = 'X; end
+ 2: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h006; arA23[ 'h3] = 'h388; end
+ 3: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h21C; arA23[ 'h3] = 'h388; end
+ 4: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h103; arA23[ 'h3] = 'h388; end
+ 5: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h388; end
+ 6: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h388; end
+ 7: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h00A; arA23[ 'h3] = 'h388; end
+ 8: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E2; arA23[ 'h3] = 'h388; end
+ 9: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h388; end
+ 10: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h388; end
+ 11: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h0EA; arA23[ 'h3] = 'h2D9; end
+ default: begin arIll[ 'h3] = 1'b1; arA1[ 'h3] = 'X ; arA23[ 'h3] = 'X; end
+ endcase
+
+8: // Row: 8
+ unique case ( col)
+ 0: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1EA; arA23[ 'h3] = 'X; end
+ 1: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1EA; arA23[ 'h3] = 'X; end
+ 2: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h006; arA23[ 'h3] = 'h32B; end
+ 3: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h21C; arA23[ 'h3] = 'h32B; end
+ 4: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h103; arA23[ 'h3] = 'h32B; end
+ 5: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h32B; end
+ 6: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h32B; end
+ 7: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h00A; arA23[ 'h3] = 'h32B; end
+ 8: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E2; arA23[ 'h3] = 'h32B; end
+ 9: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1C2; arA23[ 'h3] = 'h32B; end
+ 10: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h1E3; arA23[ 'h3] = 'h32B; end
+ 11: begin arIll[ 'h3] = 1'b0; arA1[ 'h3] = 'h0EA; arA23[ 'h3] = 'h1EA; end
+ default: begin arIll[ 'h3] = 1'b1; arA1[ 'h3] = 'X ; arA23[ 'h3] = 'X; end
+ endcase
+default: begin arIll[ 'h3] = 1'b1; arA1[ 'h3] = 'X ; arA23[ 'h3] = 'X; end
+endcase
+
+//
+// Line: 5
+//
+unique case( row86)
+
+3'b000: // Row: 0
+ unique case ( col)
+ 0: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h2D8; arA23[ 'h5] = 'X; end
+ 1: begin arIll[ 'h5] = 1'b1; arA1[ 'h5] = 'X ; arA23[ 'h5] = 'X; end
+ 2: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h006; arA23[ 'h5] = 'h2F3; end
+ 3: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h21C; arA23[ 'h5] = 'h2F3; end
+ 4: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h103; arA23[ 'h5] = 'h2F3; end
+ 5: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1C2; arA23[ 'h5] = 'h2F3; end
+ 6: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1E3; arA23[ 'h5] = 'h2F3; end
+ 7: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h00A; arA23[ 'h5] = 'h2F3; end
+ 8: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1E2; arA23[ 'h5] = 'h2F3; end
+ default: begin arIll[ 'h5] = 1'b1; arA1[ 'h5] = 'X ; arA23[ 'h5] = 'X; end
+ endcase
+
+3'b001: // Row: 1
+ unique case ( col)
+ 0: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h2D8; arA23[ 'h5] = 'X; end
+ 1: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h2DC; arA23[ 'h5] = 'X; end
+ 2: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h006; arA23[ 'h5] = 'h2F3; end
+ 3: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h21C; arA23[ 'h5] = 'h2F3; end
+ 4: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h103; arA23[ 'h5] = 'h2F3; end
+ 5: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1C2; arA23[ 'h5] = 'h2F3; end
+ 6: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1E3; arA23[ 'h5] = 'h2F3; end
+ 7: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h00A; arA23[ 'h5] = 'h2F3; end
+ 8: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1E2; arA23[ 'h5] = 'h2F3; end
+ default: begin arIll[ 'h5] = 1'b1; arA1[ 'h5] = 'X ; arA23[ 'h5] = 'X; end
+ endcase
+
+3'b010: // Row: 2
+ unique case ( col)
+ 0: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h2DC; arA23[ 'h5] = 'X; end
+ 1: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h2DC; arA23[ 'h5] = 'X; end
+ 2: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h00B; arA23[ 'h5] = 'h2F7; end
+ 3: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h00F; arA23[ 'h5] = 'h2F7; end
+ 4: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h179; arA23[ 'h5] = 'h2F7; end
+ 5: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1C6; arA23[ 'h5] = 'h2F7; end
+ 6: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1E7; arA23[ 'h5] = 'h2F7; end
+ 7: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h00E; arA23[ 'h5] = 'h2F7; end
+ 8: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1E6; arA23[ 'h5] = 'h2F7; end
+ default: begin arIll[ 'h5] = 1'b1; arA1[ 'h5] = 'X ; arA23[ 'h5] = 'X; end
+ endcase
+
+3'b011: // Row: 3
+ unique case ( col)
+ 0: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h384; arA23[ 'h5] = 'X; end
+ 1: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h06C; arA23[ 'h5] = 'X; end
+ 2: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h006; arA23[ 'h5] = 'h380; end
+ 3: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h21C; arA23[ 'h5] = 'h380; end
+ 4: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h103; arA23[ 'h5] = 'h380; end
+ 5: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1C2; arA23[ 'h5] = 'h380; end
+ 6: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1E3; arA23[ 'h5] = 'h380; end
+ 7: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h00A; arA23[ 'h5] = 'h380; end
+ 8: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1E2; arA23[ 'h5] = 'h380; end
+ default: begin arIll[ 'h5] = 1'b1; arA1[ 'h5] = 'X ; arA23[ 'h5] = 'X; end
+ endcase
+
+3'b100: // Row: 4
+ unique case ( col)
+ 0: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h2D8; arA23[ 'h5] = 'X; end
+ 1: begin arIll[ 'h5] = 1'b1; arA1[ 'h5] = 'X ; arA23[ 'h5] = 'X; end
+ 2: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h006; arA23[ 'h5] = 'h2F3; end
+ 3: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h21C; arA23[ 'h5] = 'h2F3; end
+ 4: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h103; arA23[ 'h5] = 'h2F3; end
+ 5: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1C2; arA23[ 'h5] = 'h2F3; end
+ 6: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1E3; arA23[ 'h5] = 'h2F3; end
+ 7: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h00A; arA23[ 'h5] = 'h2F3; end
+ 8: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1E2; arA23[ 'h5] = 'h2F3; end
+ default: begin arIll[ 'h5] = 1'b1; arA1[ 'h5] = 'X ; arA23[ 'h5] = 'X; end
+ endcase
+
+3'b101: // Row: 5
+ unique case ( col)
+ 0: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h2D8; arA23[ 'h5] = 'X; end
+ 1: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h2DC; arA23[ 'h5] = 'X; end
+ 2: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h006; arA23[ 'h5] = 'h2F3; end
+ 3: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h21C; arA23[ 'h5] = 'h2F3; end
+ 4: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h103; arA23[ 'h5] = 'h2F3; end
+ 5: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1C2; arA23[ 'h5] = 'h2F3; end
+ 6: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1E3; arA23[ 'h5] = 'h2F3; end
+ 7: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h00A; arA23[ 'h5] = 'h2F3; end
+ 8: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1E2; arA23[ 'h5] = 'h2F3; end
+ default: begin arIll[ 'h5] = 1'b1; arA1[ 'h5] = 'X ; arA23[ 'h5] = 'X; end
+ endcase
+
+3'b110: // Row: 6
+ unique case ( col)
+ 0: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h2DC; arA23[ 'h5] = 'X; end
+ 1: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h2DC; arA23[ 'h5] = 'X; end
+ 2: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h00B; arA23[ 'h5] = 'h2F7; end
+ 3: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h00F; arA23[ 'h5] = 'h2F7; end
+ 4: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h179; arA23[ 'h5] = 'h2F7; end
+ 5: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1C6; arA23[ 'h5] = 'h2F7; end
+ 6: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1E7; arA23[ 'h5] = 'h2F7; end
+ 7: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h00E; arA23[ 'h5] = 'h2F7; end
+ 8: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1E6; arA23[ 'h5] = 'h2F7; end
+ default: begin arIll[ 'h5] = 1'b1; arA1[ 'h5] = 'X ; arA23[ 'h5] = 'X; end
+ endcase
+
+3'b111: // Row: 7
+ unique case ( col)
+ 0: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h384; arA23[ 'h5] = 'X; end
+ 1: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h06C; arA23[ 'h5] = 'X; end
+ 2: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h006; arA23[ 'h5] = 'h380; end
+ 3: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h21C; arA23[ 'h5] = 'h380; end
+ 4: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h103; arA23[ 'h5] = 'h380; end
+ 5: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1C2; arA23[ 'h5] = 'h380; end
+ 6: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1E3; arA23[ 'h5] = 'h380; end
+ 7: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h00A; arA23[ 'h5] = 'h380; end
+ 8: begin arIll[ 'h5] = 1'b0; arA1[ 'h5] = 'h1E2; arA23[ 'h5] = 'h380; end
+ default: begin arIll[ 'h5] = 1'b1; arA1[ 'h5] = 'X ; arA23[ 'h5] = 'X; end
+ endcase
+endcase
+
+//
+// Line: 8
+//
+unique case( row86)
+
+3'b000: // Row: 0
+ unique case ( col)
+ 0: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1C1; arA23[ 'h8] = 'X; end
+ 1: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end
+ 2: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h006; arA23[ 'h8] = 'h1C3; end
+ 3: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h21C; arA23[ 'h8] = 'h1C3; end
+ 4: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h103; arA23[ 'h8] = 'h1C3; end
+ 5: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1C2; arA23[ 'h8] = 'h1C3; end
+ 6: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E3; arA23[ 'h8] = 'h1C3; end
+ 7: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h00A; arA23[ 'h8] = 'h1C3; end
+ 8: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E2; arA23[ 'h8] = 'h1C3; end
+ 9: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1C2; arA23[ 'h8] = 'h1C3; end
+ 10: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E3; arA23[ 'h8] = 'h1C3; end
+ 11: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h0EA; arA23[ 'h8] = 'h1C1; end
+ default: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end
+ endcase
+
+3'b001: // Row: 1
+ unique case ( col)
+ 0: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1C1; arA23[ 'h8] = 'X; end
+ 1: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end
+ 2: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h006; arA23[ 'h8] = 'h1C3; end
+ 3: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h21C; arA23[ 'h8] = 'h1C3; end
+ 4: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h103; arA23[ 'h8] = 'h1C3; end
+ 5: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1C2; arA23[ 'h8] = 'h1C3; end
+ 6: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E3; arA23[ 'h8] = 'h1C3; end
+ 7: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h00A; arA23[ 'h8] = 'h1C3; end
+ 8: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E2; arA23[ 'h8] = 'h1C3; end
+ 9: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1C2; arA23[ 'h8] = 'h1C3; end
+ 10: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E3; arA23[ 'h8] = 'h1C3; end
+ 11: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h0EA; arA23[ 'h8] = 'h1C1; end
+ default: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end
+ endcase
+
+3'b010: // Row: 2
+ unique case ( col)
+ 0: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1C5; arA23[ 'h8] = 'X; end
+ 1: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end
+ 2: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h00B; arA23[ 'h8] = 'h1CB; end
+ 3: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h00F; arA23[ 'h8] = 'h1CB; end
+ 4: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h179; arA23[ 'h8] = 'h1CB; end
+ 5: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1C6; arA23[ 'h8] = 'h1CB; end
+ 6: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E7; arA23[ 'h8] = 'h1CB; end
+ 7: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h00E; arA23[ 'h8] = 'h1CB; end
+ 8: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E6; arA23[ 'h8] = 'h1CB; end
+ 9: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1C6; arA23[ 'h8] = 'h1CB; end
+ 10: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E7; arA23[ 'h8] = 'h1CB; end
+ 11: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h0A7; arA23[ 'h8] = 'h1C5; end
+ default: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end
+ endcase
+
+3'b011: // Row: 3
+ unique case ( col)
+ 0: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h0A6; arA23[ 'h8] = 'X; end
+ 1: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end
+ 2: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h006; arA23[ 'h8] = 'h0A4; end
+ 3: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h21C; arA23[ 'h8] = 'h0A4; end
+ 4: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h103; arA23[ 'h8] = 'h0A4; end
+ 5: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1C2; arA23[ 'h8] = 'h0A4; end
+ 6: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E3; arA23[ 'h8] = 'h0A4; end
+ 7: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h00A; arA23[ 'h8] = 'h0A4; end
+ 8: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E2; arA23[ 'h8] = 'h0A4; end
+ 9: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1C2; arA23[ 'h8] = 'h0A4; end
+ 10: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E3; arA23[ 'h8] = 'h0A4; end
+ 11: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h0EA; arA23[ 'h8] = 'h0A6; end
+ default: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end
+ endcase
+
+3'b100: // Row: 4
+ unique case ( col)
+ 0: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1CD; arA23[ 'h8] = 'X; end
+ 1: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h107; arA23[ 'h8] = 'X; end
+ 2: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h006; arA23[ 'h8] = 'h299; end
+ 3: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h21C; arA23[ 'h8] = 'h299; end
+ 4: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h103; arA23[ 'h8] = 'h299; end
+ 5: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1C2; arA23[ 'h8] = 'h299; end
+ 6: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E3; arA23[ 'h8] = 'h299; end
+ 7: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h00A; arA23[ 'h8] = 'h299; end
+ 8: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E2; arA23[ 'h8] = 'h299; end
+ 9: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end
+ 10: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end
+ 11: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end
+ default: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end
+ endcase
+
+3'b101: // Row: 5
+ unique case ( col)
+ 0: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end
+ 1: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end
+ 2: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h006; arA23[ 'h8] = 'h299; end
+ 3: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h21C; arA23[ 'h8] = 'h299; end
+ 4: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h103; arA23[ 'h8] = 'h299; end
+ 5: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1C2; arA23[ 'h8] = 'h299; end
+ 6: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E3; arA23[ 'h8] = 'h299; end
+ 7: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h00A; arA23[ 'h8] = 'h299; end
+ 8: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E2; arA23[ 'h8] = 'h299; end
+ 9: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end
+ 10: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end
+ 11: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end
+ default: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end
+ endcase
+
+3'b110: // Row: 6
+ unique case ( col)
+ 0: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end
+ 1: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end
+ 2: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h00B; arA23[ 'h8] = 'h29D; end
+ 3: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h00F; arA23[ 'h8] = 'h29D; end
+ 4: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h179; arA23[ 'h8] = 'h29D; end
+ 5: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1C6; arA23[ 'h8] = 'h29D; end
+ 6: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E7; arA23[ 'h8] = 'h29D; end
+ 7: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h00E; arA23[ 'h8] = 'h29D; end
+ 8: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E6; arA23[ 'h8] = 'h29D; end
+ 9: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end
+ 10: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end
+ 11: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end
+ default: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end
+ endcase
+
+3'b111: // Row: 7
+ unique case ( col)
+ 0: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h0AE; arA23[ 'h8] = 'X; end
+ 1: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end
+ 2: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h006; arA23[ 'h8] = 'h0AC; end
+ 3: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h21C; arA23[ 'h8] = 'h0AC; end
+ 4: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h103; arA23[ 'h8] = 'h0AC; end
+ 5: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1C2; arA23[ 'h8] = 'h0AC; end
+ 6: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E3; arA23[ 'h8] = 'h0AC; end
+ 7: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h00A; arA23[ 'h8] = 'h0AC; end
+ 8: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E2; arA23[ 'h8] = 'h0AC; end
+ 9: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1C2; arA23[ 'h8] = 'h0AC; end
+ 10: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h1E3; arA23[ 'h8] = 'h0AC; end
+ 11: begin arIll[ 'h8] = 1'b0; arA1[ 'h8] = 'h0EA; arA23[ 'h8] = 'h0AE; end
+ default: begin arIll[ 'h8] = 1'b1; arA1[ 'h8] = 'X ; arA23[ 'h8] = 'X; end
+ endcase
+endcase
+
+//
+// Line: 9
+//
+unique case( row86)
+
+3'b000: // Row: 0
+ unique case ( col)
+ 0: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C1; arA23[ 'h9] = 'X; end
+ 1: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end
+ 2: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h006; arA23[ 'h9] = 'h1C3; end
+ 3: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h21C; arA23[ 'h9] = 'h1C3; end
+ 4: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h103; arA23[ 'h9] = 'h1C3; end
+ 5: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C2; arA23[ 'h9] = 'h1C3; end
+ 6: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E3; arA23[ 'h9] = 'h1C3; end
+ 7: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h00A; arA23[ 'h9] = 'h1C3; end
+ 8: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E2; arA23[ 'h9] = 'h1C3; end
+ 9: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C2; arA23[ 'h9] = 'h1C3; end
+ 10: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E3; arA23[ 'h9] = 'h1C3; end
+ 11: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h0EA; arA23[ 'h9] = 'h1C1; end
+ default: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end
+ endcase
+
+3'b001: // Row: 1
+ unique case ( col)
+ 0: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C1; arA23[ 'h9] = 'X; end
+ 1: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C1; arA23[ 'h9] = 'X; end
+ 2: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h006; arA23[ 'h9] = 'h1C3; end
+ 3: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h21C; arA23[ 'h9] = 'h1C3; end
+ 4: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h103; arA23[ 'h9] = 'h1C3; end
+ 5: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C2; arA23[ 'h9] = 'h1C3; end
+ 6: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E3; arA23[ 'h9] = 'h1C3; end
+ 7: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h00A; arA23[ 'h9] = 'h1C3; end
+ 8: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E2; arA23[ 'h9] = 'h1C3; end
+ 9: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C2; arA23[ 'h9] = 'h1C3; end
+ 10: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E3; arA23[ 'h9] = 'h1C3; end
+ 11: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h0EA; arA23[ 'h9] = 'h1C1; end
+ default: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end
+ endcase
+
+3'b010: // Row: 2
+ unique case ( col)
+ 0: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C5; arA23[ 'h9] = 'X; end
+ 1: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C5; arA23[ 'h9] = 'X; end
+ 2: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h00B; arA23[ 'h9] = 'h1CB; end
+ 3: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h00F; arA23[ 'h9] = 'h1CB; end
+ 4: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h179; arA23[ 'h9] = 'h1CB; end
+ 5: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C6; arA23[ 'h9] = 'h1CB; end
+ 6: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E7; arA23[ 'h9] = 'h1CB; end
+ 7: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h00E; arA23[ 'h9] = 'h1CB; end
+ 8: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E6; arA23[ 'h9] = 'h1CB; end
+ 9: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C6; arA23[ 'h9] = 'h1CB; end
+ 10: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E7; arA23[ 'h9] = 'h1CB; end
+ 11: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h0A7; arA23[ 'h9] = 'h1C5; end
+ default: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end
+ endcase
+
+3'b011: // Row: 3
+ unique case ( col)
+ 0: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C9; arA23[ 'h9] = 'X; end
+ 1: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C9; arA23[ 'h9] = 'X; end
+ 2: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h006; arA23[ 'h9] = 'h1C7; end
+ 3: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h21C; arA23[ 'h9] = 'h1C7; end
+ 4: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h103; arA23[ 'h9] = 'h1C7; end
+ 5: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C2; arA23[ 'h9] = 'h1C7; end
+ 6: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E3; arA23[ 'h9] = 'h1C7; end
+ 7: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h00A; arA23[ 'h9] = 'h1C7; end
+ 8: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E2; arA23[ 'h9] = 'h1C7; end
+ 9: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C2; arA23[ 'h9] = 'h1C7; end
+ 10: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E3; arA23[ 'h9] = 'h1C7; end
+ 11: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h0EA; arA23[ 'h9] = 'h1C9; end
+ default: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end
+ endcase
+
+3'b100: // Row: 4
+ unique case ( col)
+ 0: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C1; arA23[ 'h9] = 'X; end
+ 1: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h10F; arA23[ 'h9] = 'X; end
+ 2: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h006; arA23[ 'h9] = 'h299; end
+ 3: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h21C; arA23[ 'h9] = 'h299; end
+ 4: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h103; arA23[ 'h9] = 'h299; end
+ 5: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C2; arA23[ 'h9] = 'h299; end
+ 6: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E3; arA23[ 'h9] = 'h299; end
+ 7: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h00A; arA23[ 'h9] = 'h299; end
+ 8: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E2; arA23[ 'h9] = 'h299; end
+ 9: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end
+ 10: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end
+ 11: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end
+ default: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end
+ endcase
+
+3'b101: // Row: 5
+ unique case ( col)
+ 0: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C1; arA23[ 'h9] = 'X; end
+ 1: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h10F; arA23[ 'h9] = 'X; end
+ 2: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h006; arA23[ 'h9] = 'h299; end
+ 3: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h21C; arA23[ 'h9] = 'h299; end
+ 4: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h103; arA23[ 'h9] = 'h299; end
+ 5: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C2; arA23[ 'h9] = 'h299; end
+ 6: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E3; arA23[ 'h9] = 'h299; end
+ 7: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h00A; arA23[ 'h9] = 'h299; end
+ 8: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E2; arA23[ 'h9] = 'h299; end
+ 9: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end
+ 10: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end
+ 11: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end
+ default: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end
+ endcase
+
+3'b110: // Row: 6
+ unique case ( col)
+ 0: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C5; arA23[ 'h9] = 'X; end
+ 1: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h10B; arA23[ 'h9] = 'X; end
+ 2: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h00B; arA23[ 'h9] = 'h29D; end
+ 3: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h00F; arA23[ 'h9] = 'h29D; end
+ 4: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h179; arA23[ 'h9] = 'h29D; end
+ 5: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C6; arA23[ 'h9] = 'h29D; end
+ 6: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E7; arA23[ 'h9] = 'h29D; end
+ 7: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h00E; arA23[ 'h9] = 'h29D; end
+ 8: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E6; arA23[ 'h9] = 'h29D; end
+ 9: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end
+ 10: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end
+ 11: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end
+ default: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end
+ endcase
+
+3'b111: // Row: 7
+ unique case ( col)
+ 0: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C5; arA23[ 'h9] = 'X; end
+ 1: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C5; arA23[ 'h9] = 'X; end
+ 2: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h00B; arA23[ 'h9] = 'h1CB; end
+ 3: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h00F; arA23[ 'h9] = 'h1CB; end
+ 4: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h179; arA23[ 'h9] = 'h1CB; end
+ 5: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C6; arA23[ 'h9] = 'h1CB; end
+ 6: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E7; arA23[ 'h9] = 'h1CB; end
+ 7: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h00E; arA23[ 'h9] = 'h1CB; end
+ 8: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E6; arA23[ 'h9] = 'h1CB; end
+ 9: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1C6; arA23[ 'h9] = 'h1CB; end
+ 10: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h1E7; arA23[ 'h9] = 'h1CB; end
+ 11: begin arIll[ 'h9] = 1'b0; arA1[ 'h9] = 'h0A7; arA23[ 'h9] = 'h1C5; end
+ default: begin arIll[ 'h9] = 1'b1; arA1[ 'h9] = 'X ; arA23[ 'h9] = 'X; end
+ endcase
+endcase
+
+//
+// Line: B
+//
+unique case( row86)
+
+3'b000: // Row: 0
+ unique case ( col)
+ 0: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1D1; arA23[ 'hb] = 'X; end
+ 1: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end
+ 2: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h006; arA23[ 'hb] = 'h1D3; end
+ 3: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h21C; arA23[ 'hb] = 'h1D3; end
+ 4: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h103; arA23[ 'hb] = 'h1D3; end
+ 5: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1C2; arA23[ 'hb] = 'h1D3; end
+ 6: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E3; arA23[ 'hb] = 'h1D3; end
+ 7: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h00A; arA23[ 'hb] = 'h1D3; end
+ 8: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E2; arA23[ 'hb] = 'h1D3; end
+ 9: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1C2; arA23[ 'hb] = 'h1D3; end
+ 10: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E3; arA23[ 'hb] = 'h1D3; end
+ 11: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h0EA; arA23[ 'hb] = 'h1D1; end
+ default: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end
+ endcase
+
+3'b001: // Row: 1
+ unique case ( col)
+ 0: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1D1; arA23[ 'hb] = 'X; end
+ 1: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1D1; arA23[ 'hb] = 'X; end
+ 2: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h006; arA23[ 'hb] = 'h1D3; end
+ 3: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h21C; arA23[ 'hb] = 'h1D3; end
+ 4: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h103; arA23[ 'hb] = 'h1D3; end
+ 5: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1C2; arA23[ 'hb] = 'h1D3; end
+ 6: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E3; arA23[ 'hb] = 'h1D3; end
+ 7: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h00A; arA23[ 'hb] = 'h1D3; end
+ 8: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E2; arA23[ 'hb] = 'h1D3; end
+ 9: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1C2; arA23[ 'hb] = 'h1D3; end
+ 10: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E3; arA23[ 'hb] = 'h1D3; end
+ 11: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h0EA; arA23[ 'hb] = 'h1D1; end
+ default: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end
+ endcase
+
+3'b010: // Row: 2
+ unique case ( col)
+ 0: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1D5; arA23[ 'hb] = 'X; end
+ 1: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1D5; arA23[ 'hb] = 'X; end
+ 2: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h00B; arA23[ 'hb] = 'h1D7; end
+ 3: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h00F; arA23[ 'hb] = 'h1D7; end
+ 4: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h179; arA23[ 'hb] = 'h1D7; end
+ 5: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1C6; arA23[ 'hb] = 'h1D7; end
+ 6: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E7; arA23[ 'hb] = 'h1D7; end
+ 7: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h00E; arA23[ 'hb] = 'h1D7; end
+ 8: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E6; arA23[ 'hb] = 'h1D7; end
+ 9: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1C6; arA23[ 'hb] = 'h1D7; end
+ 10: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E7; arA23[ 'hb] = 'h1D7; end
+ 11: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h0A7; arA23[ 'hb] = 'h1D5; end
+ default: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end
+ endcase
+
+3'b011: // Row: 3
+ unique case ( col)
+ 0: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1D9; arA23[ 'hb] = 'X; end
+ 1: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1D9; arA23[ 'hb] = 'X; end
+ 2: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h006; arA23[ 'hb] = 'h1CF; end
+ 3: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h21C; arA23[ 'hb] = 'h1CF; end
+ 4: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h103; arA23[ 'hb] = 'h1CF; end
+ 5: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1C2; arA23[ 'hb] = 'h1CF; end
+ 6: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E3; arA23[ 'hb] = 'h1CF; end
+ 7: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h00A; arA23[ 'hb] = 'h1CF; end
+ 8: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E2; arA23[ 'hb] = 'h1CF; end
+ 9: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1C2; arA23[ 'hb] = 'h1CF; end
+ 10: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E3; arA23[ 'hb] = 'h1CF; end
+ 11: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h0EA; arA23[ 'hb] = 'h1D9; end
+ default: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end
+ endcase
+
+3'b100: // Row: 4
+ unique case ( col)
+ 0: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h100; arA23[ 'hb] = 'X; end
+ 1: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h06B; arA23[ 'hb] = 'X; end
+ 2: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h006; arA23[ 'hb] = 'h299; end
+ 3: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h21C; arA23[ 'hb] = 'h299; end
+ 4: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h103; arA23[ 'hb] = 'h299; end
+ 5: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1C2; arA23[ 'hb] = 'h299; end
+ 6: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E3; arA23[ 'hb] = 'h299; end
+ 7: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h00A; arA23[ 'hb] = 'h299; end
+ 8: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E2; arA23[ 'hb] = 'h299; end
+ 9: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end
+ 10: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end
+ 11: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end
+ default: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end
+ endcase
+
+3'b101: // Row: 5
+ unique case ( col)
+ 0: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h100; arA23[ 'hb] = 'X; end
+ 1: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h06B; arA23[ 'hb] = 'X; end
+ 2: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h006; arA23[ 'hb] = 'h299; end
+ 3: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h21C; arA23[ 'hb] = 'h299; end
+ 4: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h103; arA23[ 'hb] = 'h299; end
+ 5: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1C2; arA23[ 'hb] = 'h299; end
+ 6: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E3; arA23[ 'hb] = 'h299; end
+ 7: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h00A; arA23[ 'hb] = 'h299; end
+ 8: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E2; arA23[ 'hb] = 'h299; end
+ 9: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end
+ 10: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end
+ 11: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end
+ default: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end
+ endcase
+
+3'b110: // Row: 6
+ unique case ( col)
+ 0: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h10C; arA23[ 'hb] = 'X; end
+ 1: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h06F; arA23[ 'hb] = 'X; end
+ 2: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h00B; arA23[ 'hb] = 'h29D; end
+ 3: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h00F; arA23[ 'hb] = 'h29D; end
+ 4: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h179; arA23[ 'hb] = 'h29D; end
+ 5: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1C6; arA23[ 'hb] = 'h29D; end
+ 6: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E7; arA23[ 'hb] = 'h29D; end
+ 7: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h00E; arA23[ 'hb] = 'h29D; end
+ 8: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E6; arA23[ 'hb] = 'h29D; end
+ 9: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end
+ 10: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end
+ 11: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end
+ default: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end
+ endcase
+
+3'b111: // Row: 7
+ unique case ( col)
+ 0: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1D5; arA23[ 'hb] = 'X; end
+ 1: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1D5; arA23[ 'hb] = 'X; end
+ 2: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h00B; arA23[ 'hb] = 'h1D7; end
+ 3: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h00F; arA23[ 'hb] = 'h1D7; end
+ 4: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h179; arA23[ 'hb] = 'h1D7; end
+ 5: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1C6; arA23[ 'hb] = 'h1D7; end
+ 6: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E7; arA23[ 'hb] = 'h1D7; end
+ 7: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h00E; arA23[ 'hb] = 'h1D7; end
+ 8: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E6; arA23[ 'hb] = 'h1D7; end
+ 9: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1C6; arA23[ 'hb] = 'h1D7; end
+ 10: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h1E7; arA23[ 'hb] = 'h1D7; end
+ 11: begin arIll[ 'hb] = 1'b0; arA1[ 'hb] = 'h0A7; arA23[ 'hb] = 'h1D5; end
+ default: begin arIll[ 'hb] = 1'b1; arA1[ 'hb] = 'X ; arA23[ 'hb] = 'X; end
+ endcase
+endcase
+
+//
+// Line: C
+//
+unique case( row86)
+
+3'b000: // Row: 0
+ unique case ( col)
+ 0: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1C1; arA23[ 'hc] = 'X; end
+ 1: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end
+ 2: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h006; arA23[ 'hc] = 'h1C3; end
+ 3: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h21C; arA23[ 'hc] = 'h1C3; end
+ 4: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h103; arA23[ 'hc] = 'h1C3; end
+ 5: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1C2; arA23[ 'hc] = 'h1C3; end
+ 6: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E3; arA23[ 'hc] = 'h1C3; end
+ 7: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h00A; arA23[ 'hc] = 'h1C3; end
+ 8: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E2; arA23[ 'hc] = 'h1C3; end
+ 9: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1C2; arA23[ 'hc] = 'h1C3; end
+ 10: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E3; arA23[ 'hc] = 'h1C3; end
+ 11: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h0EA; arA23[ 'hc] = 'h1C1; end
+ default: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end
+ endcase
+
+3'b001: // Row: 1
+ unique case ( col)
+ 0: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1C1; arA23[ 'hc] = 'X; end
+ 1: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end
+ 2: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h006; arA23[ 'hc] = 'h1C3; end
+ 3: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h21C; arA23[ 'hc] = 'h1C3; end
+ 4: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h103; arA23[ 'hc] = 'h1C3; end
+ 5: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1C2; arA23[ 'hc] = 'h1C3; end
+ 6: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E3; arA23[ 'hc] = 'h1C3; end
+ 7: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h00A; arA23[ 'hc] = 'h1C3; end
+ 8: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E2; arA23[ 'hc] = 'h1C3; end
+ 9: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1C2; arA23[ 'hc] = 'h1C3; end
+ 10: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E3; arA23[ 'hc] = 'h1C3; end
+ 11: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h0EA; arA23[ 'hc] = 'h1C1; end
+ default: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end
+ endcase
+
+3'b010: // Row: 2
+ unique case ( col)
+ 0: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1C5; arA23[ 'hc] = 'X; end
+ 1: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end
+ 2: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h00B; arA23[ 'hc] = 'h1CB; end
+ 3: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h00F; arA23[ 'hc] = 'h1CB; end
+ 4: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h179; arA23[ 'hc] = 'h1CB; end
+ 5: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1C6; arA23[ 'hc] = 'h1CB; end
+ 6: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E7; arA23[ 'hc] = 'h1CB; end
+ 7: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h00E; arA23[ 'hc] = 'h1CB; end
+ 8: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E6; arA23[ 'hc] = 'h1CB; end
+ 9: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1C6; arA23[ 'hc] = 'h1CB; end
+ 10: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E7; arA23[ 'hc] = 'h1CB; end
+ 11: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h0A7; arA23[ 'hc] = 'h1C5; end
+ default: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end
+ endcase
+
+3'b011: // Row: 3
+ unique case ( col)
+ 0: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h15B; arA23[ 'hc] = 'X; end
+ 1: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end
+ 2: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h006; arA23[ 'hc] = 'h15A; end
+ 3: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h21C; arA23[ 'hc] = 'h15A; end
+ 4: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h103; arA23[ 'hc] = 'h15A; end
+ 5: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1C2; arA23[ 'hc] = 'h15A; end
+ 6: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E3; arA23[ 'hc] = 'h15A; end
+ 7: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h00A; arA23[ 'hc] = 'h15A; end
+ 8: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E2; arA23[ 'hc] = 'h15A; end
+ 9: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1C2; arA23[ 'hc] = 'h15A; end
+ 10: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E3; arA23[ 'hc] = 'h15A; end
+ 11: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h0EA; arA23[ 'hc] = 'h15B; end
+ default: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end
+ endcase
+
+3'b100: // Row: 4
+ unique case ( col)
+ 0: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1CD; arA23[ 'hc] = 'X; end
+ 1: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h107; arA23[ 'hc] = 'X; end
+ 2: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h006; arA23[ 'hc] = 'h299; end
+ 3: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h21C; arA23[ 'hc] = 'h299; end
+ 4: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h103; arA23[ 'hc] = 'h299; end
+ 5: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1C2; arA23[ 'hc] = 'h299; end
+ 6: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E3; arA23[ 'hc] = 'h299; end
+ 7: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h00A; arA23[ 'hc] = 'h299; end
+ 8: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E2; arA23[ 'hc] = 'h299; end
+ 9: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end
+ 10: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end
+ 11: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end
+ default: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end
+ endcase
+
+3'b101: // Row: 5
+ unique case ( col)
+ 0: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h3E3; arA23[ 'hc] = 'X; end
+ 1: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h3E3; arA23[ 'hc] = 'X; end
+ 2: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h006; arA23[ 'hc] = 'h299; end
+ 3: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h21C; arA23[ 'hc] = 'h299; end
+ 4: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h103; arA23[ 'hc] = 'h299; end
+ 5: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1C2; arA23[ 'hc] = 'h299; end
+ 6: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E3; arA23[ 'hc] = 'h299; end
+ 7: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h00A; arA23[ 'hc] = 'h299; end
+ 8: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E2; arA23[ 'hc] = 'h299; end
+ 9: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end
+ 10: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end
+ 11: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end
+ default: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end
+ endcase
+
+3'b110: // Row: 6
+ unique case ( col)
+ 0: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end
+ 1: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h3E3; arA23[ 'hc] = 'X; end
+ 2: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h00B; arA23[ 'hc] = 'h29D; end
+ 3: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h00F; arA23[ 'hc] = 'h29D; end
+ 4: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h179; arA23[ 'hc] = 'h29D; end
+ 5: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1C6; arA23[ 'hc] = 'h29D; end
+ 6: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E7; arA23[ 'hc] = 'h29D; end
+ 7: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h00E; arA23[ 'hc] = 'h29D; end
+ 8: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E6; arA23[ 'hc] = 'h29D; end
+ 9: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end
+ 10: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end
+ 11: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end
+ default: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end
+ endcase
+
+3'b111: // Row: 7
+ unique case ( col)
+ 0: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h15B; arA23[ 'hc] = 'X; end
+ 1: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end
+ 2: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h006; arA23[ 'hc] = 'h15A; end
+ 3: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h21C; arA23[ 'hc] = 'h15A; end
+ 4: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h103; arA23[ 'hc] = 'h15A; end
+ 5: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1C2; arA23[ 'hc] = 'h15A; end
+ 6: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E3; arA23[ 'hc] = 'h15A; end
+ 7: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h00A; arA23[ 'hc] = 'h15A; end
+ 8: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E2; arA23[ 'hc] = 'h15A; end
+ 9: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1C2; arA23[ 'hc] = 'h15A; end
+ 10: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h1E3; arA23[ 'hc] = 'h15A; end
+ 11: begin arIll[ 'hc] = 1'b0; arA1[ 'hc] = 'h0EA; arA23[ 'hc] = 'h15B; end
+ default: begin arIll[ 'hc] = 1'b1; arA1[ 'hc] = 'X ; arA23[ 'hc] = 'X; end
+ endcase
+endcase
+
+//
+// Line: D
+//
+unique case( row86)
+
+3'b000: // Row: 0
+ unique case ( col)
+ 0: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C1; arA23[ 'hd] = 'X; end
+ 1: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end
+ 2: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h006; arA23[ 'hd] = 'h1C3; end
+ 3: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h21C; arA23[ 'hd] = 'h1C3; end
+ 4: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h103; arA23[ 'hd] = 'h1C3; end
+ 5: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C2; arA23[ 'hd] = 'h1C3; end
+ 6: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E3; arA23[ 'hd] = 'h1C3; end
+ 7: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h00A; arA23[ 'hd] = 'h1C3; end
+ 8: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E2; arA23[ 'hd] = 'h1C3; end
+ 9: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C2; arA23[ 'hd] = 'h1C3; end
+ 10: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E3; arA23[ 'hd] = 'h1C3; end
+ 11: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h0EA; arA23[ 'hd] = 'h1C1; end
+ default: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end
+ endcase
+
+3'b001: // Row: 1
+ unique case ( col)
+ 0: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C1; arA23[ 'hd] = 'X; end
+ 1: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C1; arA23[ 'hd] = 'X; end
+ 2: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h006; arA23[ 'hd] = 'h1C3; end
+ 3: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h21C; arA23[ 'hd] = 'h1C3; end
+ 4: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h103; arA23[ 'hd] = 'h1C3; end
+ 5: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C2; arA23[ 'hd] = 'h1C3; end
+ 6: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E3; arA23[ 'hd] = 'h1C3; end
+ 7: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h00A; arA23[ 'hd] = 'h1C3; end
+ 8: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E2; arA23[ 'hd] = 'h1C3; end
+ 9: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C2; arA23[ 'hd] = 'h1C3; end
+ 10: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E3; arA23[ 'hd] = 'h1C3; end
+ 11: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h0EA; arA23[ 'hd] = 'h1C1; end
+ default: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end
+ endcase
+
+3'b010: // Row: 2
+ unique case ( col)
+ 0: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C5; arA23[ 'hd] = 'X; end
+ 1: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C5; arA23[ 'hd] = 'X; end
+ 2: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h00B; arA23[ 'hd] = 'h1CB; end
+ 3: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h00F; arA23[ 'hd] = 'h1CB; end
+ 4: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h179; arA23[ 'hd] = 'h1CB; end
+ 5: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C6; arA23[ 'hd] = 'h1CB; end
+ 6: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E7; arA23[ 'hd] = 'h1CB; end
+ 7: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h00E; arA23[ 'hd] = 'h1CB; end
+ 8: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E6; arA23[ 'hd] = 'h1CB; end
+ 9: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C6; arA23[ 'hd] = 'h1CB; end
+ 10: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E7; arA23[ 'hd] = 'h1CB; end
+ 11: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h0A7; arA23[ 'hd] = 'h1C5; end
+ default: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end
+ endcase
+
+3'b011: // Row: 3
+ unique case ( col)
+ 0: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C9; arA23[ 'hd] = 'X; end
+ 1: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C9; arA23[ 'hd] = 'X; end
+ 2: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h006; arA23[ 'hd] = 'h1C7; end
+ 3: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h21C; arA23[ 'hd] = 'h1C7; end
+ 4: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h103; arA23[ 'hd] = 'h1C7; end
+ 5: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C2; arA23[ 'hd] = 'h1C7; end
+ 6: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E3; arA23[ 'hd] = 'h1C7; end
+ 7: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h00A; arA23[ 'hd] = 'h1C7; end
+ 8: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E2; arA23[ 'hd] = 'h1C7; end
+ 9: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C2; arA23[ 'hd] = 'h1C7; end
+ 10: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E3; arA23[ 'hd] = 'h1C7; end
+ 11: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h0EA; arA23[ 'hd] = 'h1C9; end
+ default: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end
+ endcase
+
+3'b100: // Row: 4
+ unique case ( col)
+ 0: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C1; arA23[ 'hd] = 'X; end
+ 1: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h10F; arA23[ 'hd] = 'X; end
+ 2: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h006; arA23[ 'hd] = 'h299; end
+ 3: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h21C; arA23[ 'hd] = 'h299; end
+ 4: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h103; arA23[ 'hd] = 'h299; end
+ 5: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C2; arA23[ 'hd] = 'h299; end
+ 6: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E3; arA23[ 'hd] = 'h299; end
+ 7: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h00A; arA23[ 'hd] = 'h299; end
+ 8: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E2; arA23[ 'hd] = 'h299; end
+ 9: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end
+ 10: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end
+ 11: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end
+ default: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end
+ endcase
+
+3'b101: // Row: 5
+ unique case ( col)
+ 0: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C1; arA23[ 'hd] = 'X; end
+ 1: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h10F; arA23[ 'hd] = 'X; end
+ 2: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h006; arA23[ 'hd] = 'h299; end
+ 3: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h21C; arA23[ 'hd] = 'h299; end
+ 4: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h103; arA23[ 'hd] = 'h299; end
+ 5: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C2; arA23[ 'hd] = 'h299; end
+ 6: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E3; arA23[ 'hd] = 'h299; end
+ 7: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h00A; arA23[ 'hd] = 'h299; end
+ 8: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E2; arA23[ 'hd] = 'h299; end
+ 9: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end
+ 10: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end
+ 11: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end
+ default: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end
+ endcase
+
+3'b110: // Row: 6
+ unique case ( col)
+ 0: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C5; arA23[ 'hd] = 'X; end
+ 1: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h10B; arA23[ 'hd] = 'X; end
+ 2: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h00B; arA23[ 'hd] = 'h29D; end
+ 3: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h00F; arA23[ 'hd] = 'h29D; end
+ 4: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h179; arA23[ 'hd] = 'h29D; end
+ 5: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C6; arA23[ 'hd] = 'h29D; end
+ 6: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E7; arA23[ 'hd] = 'h29D; end
+ 7: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h00E; arA23[ 'hd] = 'h29D; end
+ 8: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E6; arA23[ 'hd] = 'h29D; end
+ 9: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end
+ 10: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end
+ 11: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end
+ default: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end
+ endcase
+
+3'b111: // Row: 7
+ unique case ( col)
+ 0: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C5; arA23[ 'hd] = 'X; end
+ 1: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C5; arA23[ 'hd] = 'X; end
+ 2: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h00B; arA23[ 'hd] = 'h1CB; end
+ 3: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h00F; arA23[ 'hd] = 'h1CB; end
+ 4: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h179; arA23[ 'hd] = 'h1CB; end
+ 5: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C6; arA23[ 'hd] = 'h1CB; end
+ 6: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E7; arA23[ 'hd] = 'h1CB; end
+ 7: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h00E; arA23[ 'hd] = 'h1CB; end
+ 8: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E6; arA23[ 'hd] = 'h1CB; end
+ 9: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1C6; arA23[ 'hd] = 'h1CB; end
+ 10: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h1E7; arA23[ 'hd] = 'h1CB; end
+ 11: begin arIll[ 'hd] = 1'b0; arA1[ 'hd] = 'h0A7; arA23[ 'hd] = 'h1C5; end
+ default: begin arIll[ 'hd] = 1'b1; arA1[ 'hd] = 'X ; arA23[ 'hd] = 'X; end
+ endcase
+endcase
+end
+
+
+endmodule
diff --git a/common/CPU/68000/tg68/TG68.vhd b/common/CPU/68000/tg68/TG68.vhd
new file mode 100644
index 00000000..d7a0919e
--- /dev/null
+++ b/common/CPU/68000/tg68/TG68.vhd
@@ -0,0 +1,224 @@
+------------------------------------------------------------------------------
+------------------------------------------------------------------------------
+-- --
+-- This is the TOP-Level for TG68_fast to generate 68K Bus signals --
+-- --
+-- Copyright (c) 2007-2008 Tobias Gubener --
+-- --
+-- This source file is free software: you can redistribute it and/or modify --
+-- it under the terms of the GNU Lesser General Public License as published --
+-- by the Free Software Foundation, either version 3 of the License, or --
+-- (at your option) any later version. --
+-- --
+-- This source file 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 . --
+-- --
+------------------------------------------------------------------------------
+------------------------------------------------------------------------------
+--
+-- Revision 1.02 2008/01/23
+-- bugfix Timing
+--
+-- Revision 1.01 2007/11/28
+-- add MOVEP
+-- Bugfix Interrupt in MOVEQ
+--
+-- Revision 1.0 2007/11/05
+-- Clean up code and first release
+--
+-- known bugs/todo:
+-- Add CHK INSTRUCTION
+-- full decode ILLEGAL INSTRUCTIONS
+-- Add FDC Output
+-- add odd Address test
+-- add TRACE
+-- Movem with regmask==x0000
+
+
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+
+entity TG68 is
+ port(
+ clk : in std_logic;
+ reset : in std_logic;
+ clkena_in : in std_logic:='1';
+ data_in : in std_logic_vector(15 downto 0);
+ IPL : in std_logic_vector(2 downto 0):="111";
+ dtack : in std_logic;
+ addr : out std_logic_vector(31 downto 0);
+ data_out : out std_logic_vector(15 downto 0);
+ as : out std_logic;
+ uds : out std_logic;
+ lds : out std_logic;
+ rw : out std_logic;
+ drive_data : out std_logic --enable for data_out driver
+ );
+end TG68;
+
+ARCHITECTURE logic OF TG68 IS
+
+ COMPONENT TG68_fast
+ PORT (
+ clk : in std_logic;
+ reset : in std_logic;
+ clkena_in : in std_logic;
+ data_in : in std_logic_vector(15 downto 0);
+ IPL : in std_logic_vector(2 downto 0);
+ test_IPL : in std_logic;
+ address : out std_logic_vector(31 downto 0);
+ data_write : out std_logic_vector(15 downto 0);
+ state_out : out std_logic_vector(1 downto 0);
+ decodeOPC : buffer std_logic;
+ wr : out std_logic;
+ UDS, LDS : out std_logic
+ );
+ END COMPONENT;
+
+
+ SIGNAL as_s : std_logic;
+ SIGNAL as_e : std_logic;
+ SIGNAL uds_s : std_logic;
+ SIGNAL uds_e : std_logic;
+ SIGNAL lds_s : std_logic;
+ SIGNAL lds_e : std_logic;
+ SIGNAL rw_s : std_logic;
+ SIGNAL rw_e : std_logic;
+ SIGNAL waitm : std_logic;
+ SIGNAL clkena_e : std_logic;
+ SIGNAL S_state : std_logic_vector(1 downto 0);
+ SIGNAL decode : std_logic;
+ SIGNAL wr : std_logic;
+ SIGNAL uds_in : std_logic;
+ SIGNAL lds_in : std_logic;
+ SIGNAL state : std_logic_vector(1 downto 0);
+ SIGNAL clkena : std_logic;
+ SIGNAL n_clk : std_logic;
+ SIGNAL cpuIPL : std_logic_vector(2 downto 0);
+
+
+BEGIN
+
+ n_clk <= NOT clk;
+
+TG68_fast_inst: TG68_fast
+ PORT MAP (
+ clk => n_clk, -- : in std_logic;
+ reset => reset, -- : in std_logic;
+ clkena_in => clkena, -- : in std_logic;
+ data_in => data_in, -- : in std_logic_vector(15 downto 0);
+ IPL => cpuIPL, -- : in std_logic_vector(2 downto 0);
+ test_IPL => '0', -- : in std_logic;
+ address => addr, -- : out std_logic_vector(31 downto 0);
+ data_write => data_out, -- : out std_logic_vector(15 downto 0);
+ state_out => state, -- : out std_logic_vector(1 downto 0);
+ decodeOPC => decode, -- : buffer std_logic;
+ wr => wr, -- : out std_logic;
+ UDS => uds_in, -- : out std_logic;
+ LDS => lds_in -- : out std_logic;
+ );
+
+ PROCESS (clk)
+ BEGIN
+ IF clkena_in='1' AND (clkena_e='1' OR state="01") THEN
+ clkena <= '1';
+ ELSE
+ clkena <= '0';
+ END IF;
+ END PROCESS;
+
+PROCESS (clk, reset, state, as_s, as_e, rw_s, rw_e, uds_s, uds_e, lds_s, lds_e)
+ BEGIN
+ IF state="01" THEN
+ as <= '1';
+ rw <= '1';
+ uds <= '1';
+ lds <= '1';
+ ELSE
+ as <= as_s AND as_e;
+ rw <= rw_s AND rw_e;
+ uds <= uds_s AND uds_e;
+ lds <= lds_s AND lds_e;
+ END IF;
+ IF reset='0' THEN
+ S_state <= "11";
+ as_s <= '1';
+ rw_s <= '1';
+ uds_s <= '1';
+ lds_s <= '1';
+ ELSIF rising_edge(clk) THEN
+ IF clkena_in='1' THEN
+ as_s <= '1';
+ rw_s <= '1';
+ uds_s <= '1';
+ lds_s <= '1';
+ IF state/="01" OR decode='1' THEN
+ CASE S_state IS
+ WHEN "00" => as_s <= '0';
+ rw_s <= wr;
+ IF wr='1' THEN
+ uds_s <= uds_in;
+ lds_s <= lds_in;
+ END IF;
+ S_state <= "01";
+ WHEN "01" => as_s <= '0';
+ rw_s <= wr;
+ uds_s <= uds_in;
+ lds_s <= lds_in;
+ S_state <= "10";
+ WHEN "10" =>
+ rw_s <= wr;
+ IF waitm='0' THEN
+ S_state <= "11";
+ END IF;
+ WHEN "11" =>
+ S_state <= "00";
+ WHEN OTHERS => null;
+ END CASE;
+ END IF;
+ END IF;
+ END IF;
+ IF reset='0' THEN
+ as_e <= '1';
+ rw_e <= '1';
+ uds_e <= '1';
+ lds_e <= '1';
+ clkena_e <= '0';
+ cpuIPL <= "111";
+ drive_data <= '0';
+ ELSIF falling_edge(clk) THEN
+ IF clkena_in='1' THEN
+ as_e <= '1';
+ rw_e <= '1';
+ uds_e <= '1';
+ lds_e <= '1';
+ clkena_e <= '0';
+ drive_data <= '0';
+ CASE S_state IS
+ WHEN "00" => null;
+ WHEN "01" => drive_data <= NOT wr;
+ WHEN "10" => as_e <= '0';
+ uds_e <= uds_in;
+ lds_e <= lds_in;
+ cpuIPL <= IPL;
+ drive_data <= NOT wr;
+ IF state="01" THEN
+ clkena_e <= '1';
+ waitm <= '0';
+ ELSE
+ clkena_e <= NOT dtack;
+ waitm <= dtack;
+ END IF;
+ WHEN OTHERS => null;
+ END CASE;
+ END IF;
+ END IF;
+ END PROCESS;
+END;
\ No newline at end of file
diff --git a/common/CPU/68000/tg68/TG68_fast.vhd b/common/CPU/68000/tg68/TG68_fast.vhd
new file mode 100644
index 00000000..2f9ff3cb
--- /dev/null
+++ b/common/CPU/68000/tg68/TG68_fast.vhd
@@ -0,0 +1,3256 @@
+------------------------------------------------------------------------------
+------------------------------------------------------------------------------
+-- --
+-- This is the 68000 software compatible Kernal of TG68 --
+-- --
+-- Copyright (c) 2007-2010 Tobias Gubener --
+-- --
+-- This source file is free software: you can redistribute it and/or modify --
+-- it under the terms of the GNU Lesser General Public License as published --
+-- by the Free Software Foundation, either version 3 of the License, or --
+-- (at your option) any later version. --
+-- --
+-- This source file 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 . --
+-- --
+------------------------------------------------------------------------------
+------------------------------------------------------------------------------
+--
+-- Revision 1.08 2010/06/14
+-- Bugfix Movem with regmask==xFFFF
+-- Add missing Illegal $4AFC
+--
+-- Revision 1.07 2009/10/02
+-- Bugfix Movem with regmask==x0000
+--
+-- Revision 1.06 2009/02/10
+-- Bugfix shift and rotations opcodes when the bitcount and the data are in the same register:
+-- Example lsr.l D2,D2
+-- Thanks to Peter Graf for report
+--
+-- Revision 1.05 2009/01/26
+-- Implement missing RTR
+-- Thanks to Peter Graf for report
+--
+-- Revision 1.04 2007/12/29
+-- size improvement
+-- change signal "microaddr" to one hot state machine
+--
+-- Revision 1.03 2007/12/21
+-- Thanks to Andreas Ehliar
+-- Split regfile to use blockram for registers
+-- insert "WHEN OTHERS => null;" on END CASE;
+--
+-- Revision 1.02 2007/12/17
+-- Bugfix jsr nn.w
+--
+-- Revision 1.01 2007/11/28
+-- add MOVEP
+-- Bugfix Interrupt in MOVEQ
+--
+-- Revision 1.0 2007/11/05
+-- Clean up code and first release
+--
+-- known bugs/todo:
+-- Add CHK INSTRUCTION
+-- full decode ILLEGAL INSTRUCTIONS
+-- Add FC Output
+-- add odd Address test
+-- add TRACE
+
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+
+entity TG68_fast is
+ port(clk : in std_logic;
+ reset : in std_logic; --low active
+ clkena_in : in std_logic:='1';
+ data_in : in std_logic_vector(15 downto 0);
+ IPL : in std_logic_vector(2 downto 0):="111";
+ test_IPL : in std_logic:='0'; --only for debugging
+ address : out std_logic_vector(31 downto 0);
+ data_write : out std_logic_vector(15 downto 0);
+ state_out : out std_logic_vector(1 downto 0);
+ LDS, UDS : out std_logic;
+ decodeOPC : buffer std_logic;
+ wr : out std_logic
+ );
+end TG68_fast;
+
+architecture logic of TG68_fast is
+
+ signal state : std_logic_vector(1 downto 0);
+ signal clkena : std_logic;
+ signal TG68_PC : std_logic_vector(31 downto 0);
+ signal TG68_PC_add : std_logic_vector(31 downto 0);
+ signal memaddr : std_logic_vector(31 downto 0);
+ signal memaddr_in : std_logic_vector(31 downto 0);
+ signal ea_data : std_logic_vector(31 downto 0);
+ signal ea_data_OP1 : std_logic;
+ signal setaddrlong : std_logic;
+ signal OP1out, OP2out : std_logic_vector(31 downto 0);
+ signal OP1outbrief : std_logic_vector(15 downto 0);
+ signal OP1in : std_logic_vector(31 downto 0);
+ signal data_write_tmp : std_logic_vector(31 downto 0);
+ signal Xtmp : std_logic_vector(31 downto 0);
+ signal PC_dataa, PC_datab, PC_result : std_logic_vector(31 downto 0);
+ signal setregstore : std_logic;
+ signal datatype : std_logic_vector(1 downto 0);
+ signal longread : std_logic;
+ signal longreaddirect : std_logic;
+ signal long_done : std_logic;
+ signal nextpass : std_logic;
+ signal setnextpass : std_logic;
+ signal setdispbyte : std_logic;
+ signal setdisp : std_logic;
+ signal setdispbrief : std_logic;
+ signal regdirectsource : std_logic;
+ signal endOPC : std_logic;
+ signal postadd : std_logic;
+ signal presub : std_logic;
+ signal addsub_a : std_logic_vector(31 downto 0);
+ signal addsub_b : std_logic_vector(31 downto 0);
+ signal addsub_q : std_logic_vector(31 downto 0);
+ signal briefext : std_logic_vector(31 downto 0);
+ signal setbriefext : std_logic;
+ signal addsub : std_logic;
+ signal c_in : std_logic_vector(3 downto 0);
+ signal c_out : std_logic_vector(2 downto 0);
+ signal add_result : std_logic_vector(33 downto 0);
+ signal addsub_ofl : std_logic_vector(2 downto 0);
+ signal flag_z : std_logic_vector(2 downto 0);
+
+ signal last_data_read : std_logic_vector(15 downto 0);
+ signal data_read : std_logic_vector(31 downto 0);
+
+ signal registerin : std_logic_vector(31 downto 0);
+ signal reg_QA : std_logic_vector(31 downto 0);
+ signal reg_QB : std_logic_vector(31 downto 0);
+ signal Hwrena,Lwrena : std_logic;
+ signal Regwrena : std_logic;
+ signal rf_dest_addr : std_logic_vector(6 downto 0);
+ signal rf_source_addr : std_logic_vector(6 downto 0);
+ signal rf_dest_addr_tmp : std_logic_vector(6 downto 0);
+ signal rf_source_addr_tmp : std_logic_vector(6 downto 0);
+ signal opcode : std_logic_vector(15 downto 0);
+ signal laststate : std_logic_vector(1 downto 0);
+ signal setstate : std_logic_vector(1 downto 0);
+
+ signal mem_address : std_logic_vector(31 downto 0);
+ signal memaddr_a : std_logic_vector(31 downto 0);
+ signal mem_data_read : std_logic_vector(31 downto 0);
+ signal mem_data_write : std_logic_vector(31 downto 0);
+ signal set_mem_rega : std_logic;
+ signal data_read_ram : std_logic_vector(31 downto 0);
+ signal data_read_uart : std_logic_vector(7 downto 0);
+
+ signal counter_reg : std_logic_vector(31 downto 0);
+
+ signal TG68_PC_br8 : std_logic;
+ signal TG68_PC_brw : std_logic;
+ signal TG68_PC_nop : std_logic;
+ signal setgetbrief : std_logic;
+ signal getbrief : std_logic;
+ signal brief : std_logic_vector(15 downto 0);
+ signal dest_areg : std_logic;
+ signal source_areg : std_logic;
+ signal data_is_source : std_logic;
+ signal set_store_in_tmp : std_logic;
+ signal store_in_tmp : std_logic;
+ signal write_back : std_logic;
+ signal setaddsub : std_logic;
+ signal setstackaddr : std_logic;
+ signal writePC : std_logic;
+ signal writePC_add : std_logic;
+ signal set_TG68_PC_dec: std_logic;
+ signal TG68_PC_dec : std_logic_vector(1 downto 0);
+ signal directPC : std_logic;
+ signal set_directPC : std_logic;
+ signal execOPC : std_logic;
+ signal fetchOPC : std_logic;
+ signal Flags : std_logic_vector(15 downto 0); --T.S..III ...XNZVC
+ signal set_Flags : std_logic_vector(3 downto 0); --NZVC
+ signal exec_ADD : std_logic;
+ signal exec_OR : std_logic;
+ signal exec_AND : std_logic;
+ signal exec_EOR : std_logic;
+ signal exec_MOVE : std_logic;
+ signal exec_MOVEQ : std_logic;
+ signal exec_MOVESR : std_logic;
+ signal exec_DIRECT : std_logic;
+ signal exec_ADDQ : std_logic;
+ signal exec_CMP : std_logic;
+ signal exec_ROT : std_logic;
+ signal exec_exg : std_logic;
+ signal exec_swap : std_logic;
+ signal exec_write_back: std_logic;
+ signal exec_tas : std_logic;
+ signal exec_EXT : std_logic;
+ signal exec_ABCD : std_logic;
+ signal exec_SBCD : std_logic;
+ signal exec_MULU : std_logic;
+ signal exec_DIVU : std_logic;
+ signal exec_Scc : std_logic;
+ signal exec_CPMAW : std_logic;
+ signal set_exec_ADD : std_logic;
+ signal set_exec_OR : std_logic;
+ signal set_exec_AND : std_logic;
+ signal set_exec_EOR : std_logic;
+ signal set_exec_MOVE : std_logic;
+ signal set_exec_MOVEQ : std_logic;
+ signal set_exec_MOVESR: std_logic;
+ signal set_exec_ADDQ : std_logic;
+ signal set_exec_CMP : std_logic;
+ signal set_exec_ROT : std_logic;
+ signal set_exec_tas : std_logic;
+ signal set_exec_EXT : std_logic;
+ signal set_exec_ABCD : std_logic;
+ signal set_exec_SBCD : std_logic;
+ signal set_exec_MULU : std_logic;
+ signal set_exec_DIVU : std_logic;
+ signal set_exec_Scc : std_logic;
+ signal set_exec_CPMAW : std_logic;
+
+ signal condition : std_logic;
+ signal OP2out_one : std_logic;
+ signal OP1out_zero : std_logic;
+ signal ea_to_pc : std_logic;
+ signal ea_build : std_logic;
+ signal ea_only : std_logic;
+ signal get_ea_now : std_logic;
+ signal source_lowbits : std_logic;
+ signal dest_hbits : std_logic;
+ signal rot_rot : std_logic;
+ signal rot_lsb : std_logic;
+ signal rot_msb : std_logic;
+ signal rot_XC : std_logic;
+ signal set_rot_nop : std_logic;
+ signal rot_nop : std_logic;
+ signal rot_out : std_logic_vector(31 downto 0);
+ signal rot_bits : std_logic_vector(1 downto 0);
+ signal rot_cnt : std_logic_vector(5 downto 0);
+ signal set_rot_cnt : std_logic_vector(5 downto 0);
+ signal movem_busy : std_logic;
+ signal set_movem_busy : std_logic;
+ signal movem_addr : std_logic;
+ signal movem_regaddr : std_logic_vector(3 downto 0);
+ signal movem_mask : std_logic_vector(15 downto 0);
+ signal set_get_movem_mask : std_logic;
+ signal get_movem_mask : std_logic;
+ signal maskzero : std_logic;
+ signal test_maskzero : std_logic;
+ signal movem_muxa : std_logic_vector(7 downto 0);
+ signal movem_muxb : std_logic_vector(3 downto 0);
+ signal movem_muxc : std_logic_vector(1 downto 0);
+ signal movem_presub : std_logic;
+ signal save_memaddr : std_logic;
+ signal movem_bits : std_logic_vector(4 downto 0);
+ signal ea_calc_b : std_logic_vector(31 downto 0);
+ signal set_mem_addsub : std_logic;
+ signal bit_bits : std_logic_vector(1 downto 0);
+ signal bit_number_reg : std_logic_vector(4 downto 0);
+ signal bit_number : std_logic_vector(4 downto 0);
+ signal exec_Bits : std_logic;
+ signal bits_out : std_logic_vector(31 downto 0);
+ signal one_bit_in : std_logic;
+ signal one_bit_out : std_logic;
+ signal set_get_bitnumber : std_logic;
+ signal get_bitnumber : std_logic;
+ signal mem_byte : std_logic;
+ signal wait_mem_byte : std_logic;
+ signal movepl : std_logic;
+ signal movepw : std_logic;
+ signal set_movepl : std_logic;
+ signal set_movepw : std_logic;
+ signal set_direct_data: std_logic;
+ signal use_direct_data: std_logic;
+ signal direct_data : std_logic;
+ signal set_get_extendedOPC : std_logic;
+ signal get_extendedOPC: std_logic;
+ signal setstate_delay : std_logic_vector(1 downto 0);
+ signal setstate_mux : std_logic_vector(1 downto 0);
+ signal use_XZFlag : std_logic;
+ signal use_XFlag : std_logic;
+
+ signal dummy_a : std_logic_vector(8 downto 0);
+ signal niba_l : std_logic_vector(5 downto 0);
+ signal niba_h : std_logic_vector(5 downto 0);
+ signal niba_lc : std_logic;
+ signal niba_hc : std_logic;
+ signal bcda_lc : std_logic;
+ signal bcda_hc : std_logic;
+ signal dummy_s : std_logic_vector(8 downto 0);
+ signal nibs_l : std_logic_vector(5 downto 0);
+ signal nibs_h : std_logic_vector(5 downto 0);
+ signal nibs_lc : std_logic;
+ signal nibs_hc : std_logic;
+ signal dummy_mulu : std_logic_vector(31 downto 0);
+ signal dummy_div : std_logic_vector(31 downto 0);
+ signal dummy_div_sub : std_logic_vector(16 downto 0);
+ signal dummy_div_over : std_logic_vector(16 downto 0);
+ signal set_V_Flag : std_logic;
+ signal OP1sign : std_logic;
+ signal set_sign : std_logic;
+ signal sign : std_logic;
+ signal sign2 : std_logic;
+ signal muls_msb : std_logic;
+ signal mulu_reg : std_logic_vector(31 downto 0);
+ signal div_reg : std_logic_vector(31 downto 0);
+ signal div_sign : std_logic;
+ signal div_quot : std_logic_vector(31 downto 0);
+ signal div_ovl : std_logic;
+ signal pre_V_Flag : std_logic;
+ signal set_vectoraddr : std_logic;
+ signal writeSR : std_logic;
+ signal trap_illegal : std_logic;
+ signal trap_priv : std_logic;
+ signal trap_1010 : std_logic;
+ signal trap_1111 : std_logic;
+ signal trap_trap : std_logic;
+ signal trap_trapv : std_logic;
+ signal trap_interrupt : std_logic;
+ signal trapmake : std_logic;
+ signal trapd : std_logic;
+-- signal trap_PC : std_logic_vector(31 downto 0);
+ signal trap_SR : std_logic_vector(15 downto 0);
+
+ signal set_directSR : std_logic;
+ signal directSR : std_logic;
+ signal set_directCCR : std_logic;
+ signal directCCR : std_logic;
+ signal set_stop : std_logic;
+ signal stop : std_logic;
+ signal trap_vector : std_logic_vector(31 downto 0);
+ signal to_USP : std_logic;
+ signal from_USP : std_logic;
+ signal to_SR : std_logic;
+ signal from_SR : std_logic;
+ signal illegal_write_mode : std_logic;
+ signal illegal_read_mode : std_logic;
+ signal illegal_byteaddr : std_logic;
+ signal use_SP : std_logic;
+
+ signal no_Flags : std_logic;
+ signal IPL_nr : std_logic_vector(2 downto 0);
+ signal rIPL_nr : std_logic_vector(2 downto 0);
+ signal interrupt : std_logic;
+ signal SVmode : std_logic;
+ signal trap_chk : std_logic;
+ signal test_delay : std_logic_vector(2 downto 0);
+ signal set_PCmarker : std_logic;
+ signal PCmarker : std_logic;
+ signal set_Z_error : std_logic;
+ signal Z_error : std_logic;
+
+ type micro_states is (idle, nop, ld_nn, st_nn, ld_dAn1, ld_dAn2, ld_AnXn1, ld_AnXn2, ld_AnXn3, st_dAn1, st_dAn2,
+ st_AnXn1, st_AnXn2, st_AnXn3, bra1, bra2, bsr1, bsr2, dbcc1, dbcc2,
+ movem, andi, op_AxAy, cmpm, link, int1, int2, int3, int4, rte, trap1, trap2, trap3,
+ movep1, movep2, movep3, movep4, movep5, init1, init2,
+ mul1, mul2, mul3, mul4, mul5, mul6, mul7, mul8, mul9, mul10, mul11, mul12, mul13, mul14, mul15,
+ div1, div2, div3, div4, div5, div6, div7, div8, div9, div10, div11, div12, div13, div14, div15 );
+ signal micro_state : micro_states;
+ signal next_micro_state : micro_states;
+
+ type regfile_t is array(0 to 16) of std_logic_vector(15 downto 0);
+ signal regfile_low : regfile_t;
+ signal regfile_high : regfile_t;
+ signal RWindex_A : integer range 0 to 16;
+ signal RWindex_B : integer range 0 to 16;
+
+
+BEGIN
+
+-----------------------------------------------------------------------------
+-- Registerfile
+-----------------------------------------------------------------------------
+
+ RWindex_A <= conv_integer(rf_dest_addr(4)&(rf_dest_addr(3 downto 0) XOR "1111"));
+ RWindex_B <= conv_integer(rf_source_addr(4)&(rf_source_addr(3 downto 0) XOR "1111"));
+
+ PROCESS (clk)
+ BEGIN
+ IF falling_edge(clk) THEN
+ IF clkena='1' THEN
+ reg_QA <= regfile_high(RWindex_A) & regfile_low(RWindex_A);
+ reg_QB <= regfile_high(RWindex_B) & regfile_low(RWindex_B);
+ END IF;
+ END IF;
+ IF rising_edge(clk) THEN
+ IF clkena='1' THEN
+ IF Lwrena='1' THEN
+ regfile_low(RWindex_A) <= registerin(15 downto 0);
+ END IF;
+ IF Hwrena='1' THEN
+ regfile_high(RWindex_A) <= registerin(31 downto 16);
+ END IF;
+ END IF;
+ END IF;
+ END PROCESS;
+
+
+
+ address <= TG68_PC when state="00" else X"ffffffff" when state="01" else memaddr;
+ LDS <= '0' WHEN (datatype/="00" OR state="00" OR memaddr(0)='1') AND state/="01" ELSE '1';
+ UDS <= '0' WHEN (datatype/="00" OR state="00" OR memaddr(0)='0') AND state/="01" ELSE '1';
+ state_out <= state;
+ wr <= '0' WHEN state="11" ELSE '1';
+ IPL_nr <= NOT IPL;
+
+
+-----------------------------------------------------------------------------
+-- "ALU"
+-----------------------------------------------------------------------------
+PROCESS (addsub_a, addsub_b, addsub, add_result, c_in)
+ BEGIN
+ IF addsub='1' THEN --ADD
+ add_result <= (('0'&addsub_a&c_in(0))+('0'&addsub_b&c_in(0)));
+ ELSE --SUB
+ add_result <= (('0'&addsub_a&'0')-('0'&addsub_b&c_in(0)));
+ END IF;
+ addsub_q <= add_result(32 downto 1);
+ c_in(1) <= add_result(9) XOR addsub_a(8) XOR addsub_b(8);
+ c_in(2) <= add_result(17) XOR addsub_a(16) XOR addsub_b(16);
+ c_in(3) <= add_result(33);
+ addsub_ofl(0) <= (c_in(1) XOR add_result(8) XOR addsub_a(7) XOR addsub_b(7)); --V Byte
+ addsub_ofl(1) <= (c_in(2) XOR add_result(16) XOR addsub_a(15) XOR addsub_b(15)); --V Word
+ addsub_ofl(2) <= (c_in(3) XOR add_result(32) XOR addsub_a(31) XOR addsub_b(31)); --V Long
+ c_out <= c_in(3 downto 1);
+END PROCESS;
+
+-----------------------------------------------------------------------------
+-- MEM_IO
+-----------------------------------------------------------------------------
+PROCESS (clk, reset, clkena_in, opcode, rIPL_nr, longread, get_extendedOPC, memaddr, memaddr_a, set_mem_addsub, movem_presub,
+ movem_busy, state, PCmarker, execOPC, datatype, setdisp, setdispbrief, briefext, setdispbyte, brief,
+ set_mem_rega, reg_QA, setaddrlong, data_read, decodeOPC, TG68_PC, data_in, long_done, last_data_read, mem_byte,
+ data_write_tmp, addsub_q, set_vectoraddr, trap_vector, interrupt)
+ BEGIN
+ clkena <= clkena_in AND NOT longread AND NOT get_extendedOPC;
+
+ IF rising_edge(clk) THEN
+ IF clkena='1' THEN
+ trap_vector(31 downto 8) <= (others => '0');
+ -- IF trap_addr_fault='1' THEN
+ -- trap_vector(7 downto 0) <= X"08";
+ -- END IF;
+ -- IF trap_addr_error='1' THEN
+ -- trap_vector(7 downto 0) <= X"0C";
+ -- END IF;
+ IF trap_illegal='1' THEN
+ trap_vector(7 downto 0) <= X"10";
+ END IF;
+ IF z_error='1' THEN
+ trap_vector(7 downto 0) <= X"14";
+ END IF;
+-- IF trap_chk='1' THEN
+-- trap_vector(7 downto 0) <= X"18";
+-- END IF;
+ IF trap_trapv='1' THEN
+ trap_vector(7 downto 0) <= X"1C";
+ END IF;
+ IF trap_priv='1' THEN
+ trap_vector(7 downto 0) <= X"20";
+ END IF;
+ -- IF trap_trace='1' THEN
+ -- trap_vector(7 downto 0) <= X"24";
+ -- END IF;
+ IF trap_1010='1' THEN
+ trap_vector(7 downto 0) <= X"28";
+ END IF;
+ IF trap_1111='1' THEN
+ trap_vector(7 downto 0) <= X"2C";
+ END IF;
+ IF trap_trap='1' THEN
+ trap_vector(7 downto 2) <= "10"&opcode(3 downto 0);
+ END IF;
+ IF interrupt='1' THEN
+ trap_vector(7 downto 2) <= "011"&rIPL_nr;
+ END IF;
+ END IF;
+ END IF;
+
+ memaddr_a(3 downto 0) <= "0000";
+ memaddr_a(7 downto 4) <= (OTHERS=>memaddr_a(3));
+ memaddr_a(15 downto 8) <= (OTHERS=>memaddr_a(7));
+ memaddr_a(31 downto 16) <= (OTHERS=>memaddr_a(15));
+ IF movem_presub='1' THEN
+ IF movem_busy='1' OR longread='1' THEN
+ memaddr_a(3 downto 0) <= "1110";
+ END IF;
+ ELSIF state(1)='1' OR (get_extendedOPC='1' AND PCmarker='1') THEN
+ memaddr_a(1) <= '1';
+ ELSIF execOPC='1' THEN
+ IF datatype="10" THEN
+ memaddr_a(3 downto 0) <= "1100";
+ ELSE
+ memaddr_a(3 downto 0) <= "1110";
+ END IF;
+ ELSIF setdisp='1' THEN
+ IF setdispbrief='1' THEN
+ memaddr_a <= briefext;
+ ELSIF setdispbyte='1' THEN
+ memaddr_a(7 downto 0) <= brief(7 downto 0);
+ ELSE
+ memaddr_a(15 downto 0) <= brief;
+ END IF;
+ END IF;
+
+ memaddr_in <= memaddr+memaddr_a;
+ IF longread='0' THEN
+ IF set_mem_addsub='1' THEN
+ memaddr_in <= addsub_q;
+ ELSIF set_vectoraddr='1' THEN
+ memaddr_in <= trap_vector;
+ ELSIF interrupt='1' THEN
+ memaddr_in <= "1111111111111111111111111111"&rIPL_nr&'0';
+ ELSIF set_mem_rega='1' THEN
+ memaddr_in <= reg_QA;
+ ELSIF setaddrlong='1' AND longread='0' THEN
+ memaddr_in <= data_read;
+ ELSIF decodeOPC='1' THEN
+ memaddr_in <= TG68_PC;
+ END IF;
+ END IF;
+
+ data_read(15 downto 0) <= data_in;
+ data_read(31 downto 16) <= (OTHERS=>data_in(15));
+ IF long_done='1' THEN
+ data_read(31 downto 16) <= last_data_read;
+ END IF;
+ IF mem_byte='1' AND memaddr(0)='0' THEN
+ data_read(7 downto 0) <= data_in(15 downto 8);
+ END IF;
+
+ IF longread='1' THEN
+ data_write <= data_write_tmp(31 downto 16);
+ ELSE
+ data_write(7 downto 0) <= data_write_tmp(7 downto 0);
+ IF mem_byte='1' THEN
+ data_write(15 downto 8) <= data_write_tmp(7 downto 0);
+ ELSE
+ data_write(15 downto 8) <= data_write_tmp(15 downto 8);
+ IF datatype="00" THEN
+ data_write(7 downto 0) <= data_write_tmp(15 downto 8);
+ END IF;
+ END IF;
+ END IF;
+
+ IF reset='0' THEN
+ longread <= '0';
+ long_done <= '0';
+ ELSIF rising_edge(clk) THEN
+ IF clkena_in='1' THEN
+ last_data_read <= data_in;
+ long_done <= longread;
+ IF get_extendedOPC='0' OR (get_extendedOPC='1' AND PCmarker='1') THEN
+ memaddr <= memaddr_in;
+ END IF;
+ IF get_extendedOPC='0' THEN
+
+ IF ((setstate_mux(1)='1' AND datatype="10") OR longreaddirect='1') AND longread='0' AND interrupt='0' THEN
+ longread <= '1';
+ ELSE
+ longread <= '0';
+ END IF;
+ END IF;
+
+ END IF;
+ END IF;
+ END PROCESS;
+-----------------------------------------------------------------------------
+-- brief
+-----------------------------------------------------------------------------
+process (clk, brief, OP1out)
+ begin
+ IF brief(11)='1' THEN
+ OP1outbrief <= OP1out(31 downto 16);
+ ELSE
+ OP1outbrief <= (OTHERS=>OP1out(15));
+ END IF;
+ IF rising_edge(clk) THEN
+ IF clkena='1' THEN
+ briefext <= OP1outbrief&OP1out(15 downto 0);
+-- CASE brief(10 downto 9) IS
+-- WHEN "00" => briefext <= OP1outbrief&OP1out(15 downto 0);
+-- WHEN "01" => briefext <= OP1outbrief(14 downto 0)&OP1out(15 downto 0)&'0';
+-- WHEN "10" => briefext <= OP1outbrief(13 downto 0)&OP1out(15 downto 0)&"00";
+-- WHEN "11" => briefext <= OP1outbrief(12 downto 0)&OP1out(15 downto 0)&"000";
+-- END CASE;
+ end if;
+ end if;
+ end process;
+
+-----------------------------------------------------------------------------
+-- PC Calc + fetch opcode
+-----------------------------------------------------------------------------
+process (clk, reset, opcode, TG68_PC, TG68_PC_dec, TG68_PC_br8, TG68_PC_brw, PC_dataa, PC_datab, execOPC, last_data_read, get_extendedOPC,
+ setstate_delay, setstate)
+ begin
+ PC_dataa <= TG68_PC;
+ PC_datab(2 downto 0) <= "010";
+ PC_datab(7 downto 3) <= (others => PC_datab(2));
+ PC_datab(15 downto 8) <= (others => PC_datab(7));
+ PC_datab(31 downto 16) <= (others => PC_datab(15));
+ IF execOPC='0' THEN
+ IF TG68_PC_br8='1' THEN
+ PC_datab(7 downto 0) <= opcode(7 downto 0);
+ END IF;
+ IF TG68_PC_dec(1)='1' THEN
+ PC_datab(2) <= '1';
+ END IF;
+ IF TG68_PC_brw = '1' THEN
+ PC_datab(15 downto 0) <= last_data_read(15 downto 0);
+ END IF;
+ END IF;
+ TG68_PC_add <= PC_dataa+PC_datab;
+
+ IF get_extendedOPC='1' THEN
+ setstate_mux <= setstate_delay;
+ ELSE
+ setstate_mux <= setstate;
+ END IF;
+
+
+ IF reset = '0' THEN
+ opcode(15 downto 12) <= X"7"; --moveq
+ opcode(8 downto 6) <= "010"; --long
+ TG68_PC <= (others =>'0');
+ state <= "01";
+ decodeOPC <= '0';
+ fetchOPC <= '0';
+ endOPC <= '0';
+ interrupt <= '0';
+ trap_interrupt <= '1';
+ execOPC <= '0';
+ getbrief <= '0';
+ TG68_PC_dec <= "00";
+ directPC <= '0';
+ directSR <= '0';
+ directCCR <= '0';
+ stop <= '0';
+ exec_ADD <= '0';
+ exec_OR <= '0';
+ exec_AND <= '0';
+ exec_EOR <= '0';
+ exec_MOVE <= '0';
+ exec_MOVEQ <= '0';
+ exec_MOVESR <= '0';
+ exec_ADDQ <= '0';
+ exec_CMP <= '0';
+ exec_ROT <= '0';
+ exec_EXT <= '0';
+ exec_ABCD <= '0';
+ exec_SBCD <= '0';
+ exec_MULU <= '0';
+ exec_DIVU <= '0';
+ exec_Scc <= '0';
+ exec_CPMAW <= '0';
+ mem_byte <= '0';
+ rot_cnt <="000001";
+ rot_nop <= '0';
+ get_extendedOPC <= '0';
+ get_bitnumber <= '0';
+ get_movem_mask <= '0';
+ test_maskzero <= '0';
+ movepl <= '0';
+ movepw <= '0';
+ test_delay <= "000";
+ PCmarker <= '0';
+ ELSIF rising_edge(clk) THEN
+ IF clkena_in='1' THEN
+ get_extendedOPC <= set_get_extendedOPC;
+ get_bitnumber <= set_get_bitnumber;
+ get_movem_mask <= set_get_movem_mask;
+ test_maskzero <= get_movem_mask;
+ setstate_delay <= setstate;
+
+ TG68_PC_dec <= TG68_PC_dec(0)&set_TG68_PC_dec;
+ IF directPC='1' AND clkena='1' THEN
+ TG68_PC <= data_read;
+ ELSIF ea_to_pc='1' AND longread='0' THEN
+ TG68_PC <= memaddr_in;
+ ELSIF (state ="00" AND TG68_PC_nop='0') OR TG68_PC_br8='1' OR TG68_PC_brw='1' OR TG68_PC_dec(1)='1' THEN
+ TG68_PC <= TG68_PC_add;
+ END IF;
+
+ IF get_bitnumber='1' THEN
+ bit_number_reg <= data_read(4 downto 0);
+ END IF;
+
+ IF clkena='1' OR get_extendedOPC='1' THEN
+ IF set_get_extendedOPC='1' THEN
+ state <= "00";
+ ELSIF get_extendedOPC='1' THEN
+ state <= setstate_mux;
+ ELSIF fetchOPC='1' OR (state="10" AND write_back='1' AND setstate/="10") OR set_rot_cnt/="000001" OR stop='1' THEN
+ state <= "01"; --decode cycle, execute cycle
+ ELSE
+ state <= setstate_mux;
+ END IF;
+ IF setstate_mux(1)='1' AND datatype="00" AND set_get_extendedOPC='0' AND wait_mem_byte='0' THEN
+ mem_byte <= '1';
+ ELSE
+ mem_byte <= '0';
+ END IF;
+
+ END IF;
+ END IF;
+
+ IF clkena='1' THEN
+ exec_ADD <= '0';
+ exec_OR <= '0';
+ exec_AND <= '0';
+ exec_EOR <= '0';
+ exec_MOVE <= '0';
+ exec_MOVEQ <= '0';
+ exec_MOVESR <= '0';
+ exec_ADDQ <= '0';
+ exec_CMP <= '0';
+ exec_ROT <= '0';
+ exec_ABCD <= '0';
+ exec_SBCD <= '0';
+ fetchOPC <= '0';
+ exec_CPMAW <= '0';
+ endOPC <= '0';
+ interrupt <= '0';
+ execOPC <= '0';
+ exec_EXT <= '0';
+ exec_Scc <= '0';
+ rot_nop <= '0';
+ decodeOPC <= fetchOPC;
+ directPC <= set_directPC;
+ directSR <= set_directSR;
+ directCCR <= set_directCCR;
+ exec_MULU <= set_exec_MULU;
+ exec_DIVU <= set_exec_DIVU;
+ movepl <= '0';
+ movepw <= '0';
+
+ stop <= set_stop OR (stop AND NOT interrupt);
+ IF set_PCmarker='1' THEN
+ PCmarker <= '1';
+ ELSIF (state="10" AND longread='0') OR (ea_only='1' AND get_ea_now='1') THEN
+ PCmarker <= '0';
+ END IF;
+ IF (decodeOPC OR execOPC)='1' THEN
+ rot_cnt <= set_rot_cnt;
+ END IF;
+ IF next_micro_state=idle AND setstate_mux="00" AND (setnextpass='0' OR ea_only='1') AND endOPC='0' AND movem_busy='0' AND set_movem_busy='0' AND set_get_bitnumber='0' THEN
+ nextpass <= '0';
+ IF (exec_write_back='0' OR state="11") AND set_rot_cnt="000001" THEN
+ endOPC <= '1';
+ IF Flags(10 downto 8) '0');
+ ELSIF from_SR='1' THEN
+ OP1out(15 downto 0) <= Flags;
+ ELSIF ea_data_OP1='1' AND set_store_in_tmp='1' THEN
+ OP1out <= ea_data;
+ END IF;
+ END PROCESS;
+
+-----------------------------------------------------------------------------
+-- set source regaddr
+-----------------------------------------------------------------------------
+PROCESS (opcode, Flags, movem_addr, movem_presub, movem_regaddr, source_lowbits, source_areg, from_USP, rf_source_addr_tmp)
+ BEGIN
+ rf_source_addr <= rf_source_addr_tmp;
+ IF rf_source_addr_tmp(3 downto 0)="1111" AND from_USP='0' THEN
+ rf_source_addr(4) <= Flags(13);
+ END IF;
+ IF movem_addr='1' THEN
+ IF movem_presub='1' THEN
+ rf_source_addr_tmp <= "000"&(movem_regaddr XOR "1111");
+ ELSE
+ rf_source_addr_tmp <= "000"&movem_regaddr;
+ END IF;
+ ELSIF from_USP='1' THEN
+ rf_source_addr_tmp <= "0001111";
+ ELSIF source_lowbits='1' THEN
+ rf_source_addr_tmp <= "000"&source_areg&opcode(2 downto 0);
+ ELSE
+ rf_source_addr_tmp <= "000"&source_areg&opcode(11 downto 9);
+ END IF;
+ END PROCESS;
+
+-----------------------------------------------------------------------------
+-- set OP2
+-----------------------------------------------------------------------------
+PROCESS (OP2out, reg_QB, opcode, datatype, OP2out_one, exec_EXT, exec_MOVEQ, EXEC_ADDQ, use_direct_data, data_write_tmp,
+ ea_data_OP1, set_store_in_tmp, ea_data, movepl)
+ BEGIN
+ OP2out(15 downto 0) <= reg_QB(15 downto 0);
+ OP2out(31 downto 16) <= (OTHERS => OP2out(15));
+ IF OP2out_one='1' THEN
+ OP2out(15 downto 0) <= "1111111111111111";
+ ELSIF exec_EXT='1' THEN
+ IF opcode(6)='0' THEN --ext.w
+ OP2out(15 downto 8) <= (OTHERS => OP2out(7));
+ END IF;
+ ELSIF use_direct_data='1' THEN
+ OP2out <= data_write_tmp;
+ ELSIF ea_data_OP1='0' AND set_store_in_tmp='1' THEN
+ OP2out <= ea_data;
+ ELSIF exec_MOVEQ='1' THEN
+ OP2out(7 downto 0) <= opcode(7 downto 0);
+ OP2out(15 downto 8) <= (OTHERS => opcode(7));
+ ELSIF exec_ADDQ='1' THEN
+ OP2out(2 downto 0) <= opcode(11 downto 9);
+ IF opcode(11 downto 9)="000" THEN
+ OP2out(3) <='1';
+ ELSE
+ OP2out(3) <='0';
+ END IF;
+ OP2out(15 downto 4) <= (OTHERS => '0');
+ ELSIF datatype="10" OR movepl='1' THEN
+ OP2out(31 downto 16) <= reg_QB(31 downto 16);
+ END IF;
+ END PROCESS;
+
+-----------------------------------------------------------------------------
+-- addsub
+-----------------------------------------------------------------------------
+PROCESS (OP1out, OP2out, presub, postadd, execOPC, OP2out_one, datatype, use_SP, use_XZFlag, use_XFlag, Flags, setaddsub)
+ BEGIN
+ addsub_a <= OP1out;
+ addsub_b <= OP2out;
+ addsub <= NOT presub;
+ c_in(0) <='0';
+ IF execOPC='0' AND OP2out_one='0' THEN
+ IF datatype="00" AND use_SP='0' THEN
+ addsub_b <= "00000000000000000000000000000001";
+ ELSIF datatype="10" AND (presub OR postadd)='1' THEN
+ addsub_b <= "00000000000000000000000000000100";
+ ELSE
+ addsub_b <= "00000000000000000000000000000010";
+ END IF;
+ ELSE
+ IF (use_XZFlag='1' OR use_XFlag='1') AND Flags(4)='1' THEN
+ c_in(0) <= '1';
+ END IF;
+ addsub <= setaddsub;
+ END IF;
+ END PROCESS;
+
+-----------------------------------------------------------------------------
+-- Write Reg
+-----------------------------------------------------------------------------
+PROCESS (clkena, OP1in, datatype, presub, postadd, endOPC, regwrena, state, execOPC, last_data_read, movem_addr, rf_dest_addr, reg_QA, maskzero)
+ BEGIN
+ Lwrena <= '0';
+ Hwrena <= '0';
+ registerin <= OP1in;
+
+ IF (presub='1' OR postadd='1') AND endOPC='0' THEN -- -(An)+
+ Hwrena <= '1';
+ Lwrena <= '1';
+ ELSIF Regwrena='1' AND maskzero='0' THEN --read (mem)
+ Lwrena <= '1';
+ CASE datatype IS
+ WHEN "00" => --BYTE
+ registerin(15 downto 8) <= reg_QA(15 downto 8);
+ WHEN "01" => --WORD
+ IF rf_dest_addr(3)='1' OR movem_addr='1' THEN
+ Hwrena <='1';
+ END IF;
+ WHEN OTHERS => --LONG
+ Hwrena <= '1';
+ END CASE;
+ END IF;
+ END PROCESS;
+
+------------------------------------------------------------------------------
+--ALU
+------------------------------------------------------------------------------
+PROCESS (opcode, OP1in, OP1out, OP2out, datatype, c_out, exec_ABCD, exec_SBCD, exec_CPMAW, exec_MOVESR, bits_out, Flags, flag_z, use_XZFlag, addsub_ofl,
+ dummy_s, dummy_a, niba_hc, niba_h, niba_l, niba_lc, nibs_hc, nibs_h, nibs_l, nibs_lc, addsub_q, movem_addr, data_read, exec_MULU, exec_DIVU, exec_OR,
+ exec_AND, exec_Scc, exec_EOR, exec_MOVE, exec_exg, exec_ROT, execOPC, exec_swap, exec_Bits, rot_out, dummy_mulu, dummy_div, save_memaddr, memaddr,
+ memaddr_in, ea_only, get_ea_now)
+ BEGIN
+
+--BCD_ARITH-------------------------------------------------------------------
+ --ADC
+ dummy_a <= niba_hc&(niba_h(4 downto 1)+('0',niba_hc,niba_hc,'0'))&(niba_l(4 downto 1)+('0',niba_lc,niba_lc,'0'));
+ niba_l <= ('0'&OP1out(3 downto 0)&'1') + ('0'&OP2out(3 downto 0)&Flags(4));
+ niba_lc <= niba_l(5) OR (niba_l(4) AND niba_l(3)) OR (niba_l(4) AND niba_l(2));
+
+ niba_h <= ('0'&OP1out(7 downto 4)&'1') + ('0'&OP2out(7 downto 4)&niba_lc);
+ niba_hc <= niba_h(5) OR (niba_h(4) AND niba_h(3)) OR (niba_h(4) AND niba_h(2));
+ --SBC
+ dummy_s <= nibs_hc&(nibs_h(4 downto 1)-('0',nibs_hc,nibs_hc,'0'))&(nibs_l(4 downto 1)-('0',nibs_lc,nibs_lc,'0'));
+ nibs_l <= ('0'&OP1out(3 downto 0)&'0') - ('0'&OP2out(3 downto 0)&Flags(4));
+ nibs_lc <= nibs_l(5);
+
+ nibs_h <= ('0'&OP1out(7 downto 4)&'0') - ('0'&OP2out(7 downto 4)&nibs_lc);
+ nibs_hc <= nibs_h(5);
+------------------------------------------------------------------------------
+
+ flag_z <= "000";
+
+ OP1in <= addsub_q;
+ IF movem_addr='1' THEN
+ OP1in <= data_read;
+ ELSIF exec_ABCD='1' THEN
+ OP1in(7 downto 0) <= dummy_a(7 downto 0);
+ ELSIF exec_SBCD='1' THEN
+ OP1in(7 downto 0) <= dummy_s(7 downto 0);
+ ELSIF exec_MULU='1' THEN
+ OP1in <= dummy_mulu;
+ ELSIF exec_DIVU='1' AND execOPC='1' THEN
+ OP1in <= dummy_div;
+ ELSIF exec_OR='1' THEN
+ OP1in <= OP2out OR OP1out;
+ ELSIF exec_AND='1' OR exec_Scc='1' THEN
+ OP1in <= OP2out AND OP1out;
+ ELSIF exec_EOR='1' THEN
+ OP1in <= OP2out XOR OP1out;
+ ELSIF exec_MOVE='1' OR exec_exg='1' THEN
+ OP1in <= OP2out;
+ ELSIF exec_ROT='1' THEN
+ OP1in <= rot_out;
+ ELSIF save_memaddr='1' THEN
+ OP1in <= memaddr;
+ ELSIF get_ea_now='1' AND ea_only='1' THEN
+ OP1in <= memaddr_in;
+ ELSIF exec_swap='1' THEN
+ OP1in <= OP1out(15 downto 0)& OP1out(31 downto 16);
+ ELSIF exec_bits='1' THEN
+ OP1in <= bits_out;
+ ELSIF exec_MOVESR='1' THEN
+ OP1in(15 downto 0) <= Flags;
+ END IF;
+
+ IF use_XZFlag='1' AND flags(2)='0' THEN
+ flag_z <= "000";
+ ELSIF OP1in(7 downto 0)="00000000" THEN
+ flag_z(0) <= '1';
+ IF OP1in(15 downto 8)="00000000" THEN
+ flag_z(1) <= '1';
+ IF OP1in(31 downto 16)="0000000000000000" THEN
+ flag_z(2) <= '1';
+ END IF;
+ END IF;
+ END IF;
+
+-- --Flags NZVC
+ IF datatype="00" THEN --Byte
+ set_flags <= OP1IN(7)&flag_z(0)&addsub_ofl(0)&c_out(0);
+ IF exec_ABCD='1' THEN
+ set_flags(0) <= dummy_a(8);
+ ELSIF exec_SBCD='1' THEN
+ set_flags(0) <= dummy_s(8);
+ END IF;
+ ELSIF datatype="10" OR exec_CPMAW='1' THEN --Long
+ set_flags <= OP1IN(31)&flag_z(2)&addsub_ofl(2)&c_out(2);
+ ELSE --Word
+ set_flags <= OP1IN(15)&flag_z(1)&addsub_ofl(1)&c_out(1);
+ END IF;
+ END PROCESS;
+
+------------------------------------------------------------------------------
+--Flags
+------------------------------------------------------------------------------
+PROCESS (clk, reset, opcode)
+ BEGIN
+ IF reset='0' THEN
+ Flags(13) <= '1';
+ SVmode <= '1';
+ Flags(10 downto 8) <= "111";
+ ELSIF rising_edge(clk) THEN
+
+ IF clkena = '1' THEN
+ IF directSR='1' THEN
+ Flags <= data_read(15 downto 0);
+ END IF;
+ IF directCCR='1' THEN
+ Flags(7 downto 0) <= data_read(7 downto 0);
+ END IF;
+ IF interrupt='1' THEN
+ Flags(10 downto 8) <=rIPL_nr;
+ SVmode <= '1';
+ END IF;
+ IF writeSR='1' OR interrupt='1' THEN
+ Flags(13) <='1';
+ END IF;
+ IF endOPC='1' AND to_SR='0' THEN
+ SVmode <= Flags(13);
+ END IF;
+ IF execOPC='1' AND to_SR='1' THEN
+ Flags(7 downto 0) <= OP1in(7 downto 0); --CCR
+ IF datatype="01" AND (opcode(14)='0' OR opcode(9)='1') THEN --move to CCR wird als word gespeichert
+ Flags(15 downto 8) <= OP1in(15 downto 8); --SR
+ SVmode <= OP1in(13);
+ END IF;
+ ELSIF Z_error='1' THEN
+ IF opcode(8)='0' THEN
+ Flags(3 downto 0) <= "1000";
+ ELSE
+ Flags(3 downto 0) <= "0100";
+ END IF;
+ ELSIF no_Flags='0' AND trapmake='0' THEN
+ IF exec_ADD='1' THEN
+ Flags(4) <= set_flags(0);
+ ELSIF exec_ROT='1' AND rot_bits/="11" AND rot_nop='0' THEN
+ Flags(4) <= rot_XC;
+ END IF;
+
+ IF (exec_ADD OR exec_CMP)='1' THEN
+ Flags(3 downto 0) <= set_flags;
+ ELSIF decodeOPC='1' and set_exec_ROT='1' THEN
+ Flags(1) <= '0';
+ ELSIF exec_DIVU='1' THEN
+ IF set_V_Flag='1' THEN
+ Flags(3 downto 0) <= "1010";
+ ELSE
+ Flags(3 downto 0) <= OP1IN(15)&flag_z(1)&"00";
+ END IF;
+ ELSIF exec_OR='1' OR exec_AND='1' OR exec_EOR='1' OR exec_MOVE='1' OR exec_swap='1' OR exec_MULU='1' THEN
+ Flags(3 downto 0) <= set_flags(3 downto 2)&"00";
+ ELSIF exec_ROT='1' THEN
+ Flags(3 downto 2) <= set_flags(3 downto 2);
+ Flags(0) <= rot_XC;
+ IF rot_bits="00" THEN --ASL/ASR
+ Flags(1) <= ((set_flags(3) XOR rot_rot) OR Flags(1));
+ END IF;
+ ELSIF exec_bits='1' THEN
+ Flags(2) <= NOT one_bit_in;
+ END IF;
+ END IF;
+ END IF;
+ END IF;
+ END PROCESS;
+
+-----------------------------------------------------------------------------
+-- execute opcode
+-----------------------------------------------------------------------------
+PROCESS (clk, reset, OP2out, opcode, fetchOPC, decodeOPC, execOPC, endOPC, nextpass, condition, set_V_flag, trapmake, trapd, interrupt, trap_interrupt, rot_nop,
+ Z_error, c_in, rot_cnt, one_bit_in, bit_number_reg, bit_number, ea_only, get_ea_now, ea_build, datatype, exec_write_back, get_extendedOPC,
+ Flags, SVmode, movem_addr, movem_busy, getbrief, set_exec_AND, set_exec_OR, set_exec_EOR, TG68_PC_dec, c_out, OP1out, micro_state)
+ BEGIN
+ TG68_PC_br8 <= '0';
+ TG68_PC_brw <= '0';
+ TG68_PC_nop <= '0';
+ setstate <= "00";
+ Regwrena <= '0';
+ postadd <= '0';
+ presub <= '0';
+ movem_presub <= '0';
+ setaddsub <= '1';
+ setaddrlong <= '0';
+ setnextpass <= '0';
+ regdirectsource <= '0';
+ setdisp <= '0';
+ setdispbyte <= '0';
+ setdispbrief <= '0';
+ setbriefext <= '0';
+ setgetbrief <= '0';
+ longreaddirect <= '0';
+ dest_areg <= '0';
+ source_areg <= '0';
+ data_is_source <= '0';
+ write_back <= '0';
+ setstackaddr <= '0';
+ writePC <= '0';
+ writePC_add <= '0';
+ set_TG68_PC_dec <= '0';
+ set_directPC <= '0';
+ set_exec_ADD <= '0';
+ set_exec_OR <= '0';
+ set_exec_AND <= '0';
+ set_exec_EOR <= '0';
+ set_exec_MOVE <= '0';
+ set_exec_MOVEQ <= '0';
+ set_exec_MOVESR <= '0';
+ set_exec_ADDQ <= '0';
+ set_exec_CMP <= '0';
+ set_exec_ROT <= '0';
+ set_exec_EXT <= '0';
+ set_exec_CPMAW <= '0';
+ OP2out_one <= '0';
+ ea_to_pc <= '0';
+ ea_build <= '0';
+ get_ea_now <= '0';
+ rot_bits <= "XX";
+ set_rot_nop <= '0';
+ set_rot_cnt <= "000001";
+ set_movem_busy <= '0';
+ set_get_movem_mask <= '0';
+ save_memaddr <= '0';
+ set_mem_addsub <= '0';
+ exec_exg <= '0';
+ exec_swap <= '0';
+ exec_Bits <= '0';
+ set_get_bitnumber <= '0';
+ dest_hbits <= '0';
+ source_lowbits <= '0';
+ set_mem_rega <= '0';
+ ea_data_OP1 <= '0';
+ ea_only <= '0';
+ set_direct_data <= '0';
+ set_get_extendedOPC <= '0';
+ set_exec_tas <= '0';
+ OP1out_zero <= '0';
+ use_XZFlag <= '0';
+ use_XFlag <= '0';
+ set_exec_ABCD <= '0';
+ set_exec_SBCD <= '0';
+ set_exec_MULU <= '0';
+ set_exec_DIVU <= '0';
+ set_exec_Scc <= '0';
+ trap_illegal <='0';
+ trap_priv <='0';
+ trap_1010 <='0';
+ trap_1111 <='0';
+ trap_trap <='0';
+ trap_trapv <= '0';
+ trapmake <='0';
+ set_vectoraddr <='0';
+ writeSR <= '0';
+ set_directSR <= '0';
+ set_directCCR <= '0';
+ set_stop <= '0';
+ from_SR <= '0';
+ to_SR <= '0';
+ from_USP <= '0';
+ to_USP <= '0';
+ illegal_write_mode <= '0';
+ illegal_read_mode <= '0';
+ illegal_byteaddr <= '0';
+ no_Flags <= '0';
+ set_PCmarker <= '0';
+ use_SP <= '0';
+ set_Z_error <= '0';
+ wait_mem_byte <= '0';
+ set_movepl <= '0';
+ set_movepw <= '0';
+
+ trap_chk <= '0';
+ next_micro_state <= idle;
+
+------------------------------------------------------------------------------
+--Sourcepass
+------------------------------------------------------------------------------
+ IF ea_only='0' AND get_ea_now='1' THEN
+ setstate <= "10";
+ END IF;
+
+ IF ea_build='1' THEN
+ CASE opcode(5 downto 3) IS --source
+ WHEN "010"|"011"|"100" => -- -(An)+
+ get_ea_now <='1';
+ setnextpass <= '1';
+ IF opcode(4)='1' THEN
+ set_mem_rega <= '1';
+ ELSE
+ set_mem_addsub <= '1';
+ END IF;
+ IF opcode(3)='1' THEN --(An)+
+ postadd <= '1';
+ IF opcode(2 downto 0)="111" THEN
+ use_SP <= '1';
+ END IF;
+ END IF;
+ IF opcode(5)='1' THEN -- -(An)
+ presub <= '1';
+ IF opcode(2 downto 0)="111" THEN
+ use_SP <= '1';
+ END IF;
+ END IF;
+ IF opcode(4 downto 3)/="10" THEN
+ regwrena <= '1';
+ END IF;
+ WHEN "101" => --(d16,An)
+ next_micro_state <= ld_dAn1;
+ setgetbrief <='1';
+ set_mem_regA <= '1';
+ WHEN "110" => --(d8,An,Xn)
+ next_micro_state <= ld_AnXn1;
+ setgetbrief <='1';
+ set_mem_regA <= '1';
+ WHEN "111" =>
+ CASE opcode(2 downto 0) IS
+ WHEN "000" => --(xxxx).w
+ next_micro_state <= ld_nn;
+ WHEN "001" => --(xxxx).l
+ longreaddirect <= '1';
+ next_micro_state <= ld_nn;
+ WHEN "010" => --(d16,PC)
+ next_micro_state <= ld_dAn1;
+ setgetbrief <= '1';
+ set_PCmarker <= '1';
+ WHEN "011" => --(d8,PC,Xn)
+ next_micro_state <= ld_AnXn1;
+ setgetbrief <= '1';
+ set_PCmarker <= '1';
+ WHEN "100" => --#data
+ setnextpass <= '1';
+ set_direct_data <= '1';
+ IF datatype="10" THEN
+ longreaddirect <= '1';
+ END IF;
+ WHEN OTHERS =>
+ END CASE;
+ WHEN OTHERS =>
+ END CASE;
+ END IF;
+------------------------------------------------------------------------------
+--prepere opcode
+------------------------------------------------------------------------------
+ CASE opcode(7 downto 6) IS
+ WHEN "00" => datatype <= "00"; --Byte
+ WHEN "01" => datatype <= "01"; --Word
+ WHEN OTHERS => datatype <= "10"; --Long
+ END CASE;
+
+ IF execOPC='1' AND endOPC='0' AND exec_write_back='1' THEN
+ setstate <="11";
+ END IF;
+
+------------------------------------------------------------------------------
+--test illegal mode
+------------------------------------------------------------------------------
+ IF (opcode(5 downto 3)="111" AND opcode(2 downto 1)/="00") OR (opcode(5 downto 3)="001" AND datatype="00") THEN
+ illegal_write_mode <= '1';
+ END IF;
+ IF (opcode(5 downto 2)="1111" AND opcode(1 downto 0)/="00") OR (opcode(5 downto 3)="001" AND datatype="00") THEN
+ illegal_read_mode <= '1';
+ END IF;
+ IF opcode(5 downto 3)="001" AND datatype="00" THEN
+ illegal_byteaddr <= '1';
+ END IF;
+
+
+ CASE opcode(15 downto 12) IS
+-- 0000 ----------------------------------------------------------------------------
+ WHEN "0000" =>
+ IF opcode(8)='1' AND opcode(5 downto 3)="001" THEN --movep
+ datatype <= "00"; --Byte
+ use_SP <= '1';
+ no_Flags <='1';
+ IF opcode(7)='0' THEN
+ set_exec_move <= '1';
+ set_movepl <= '1';
+ END IF;
+ IF decodeOPC='1' THEN
+ IF opcode(7)='0' THEN
+ set_direct_data <= '1';
+ END IF;
+ next_micro_state <= movep1;
+ setgetbrief <='1';
+ set_mem_regA <= '1';
+ END IF;
+ IF opcode(7)='0' AND endOPC='1' THEN
+ IF opcode(6)='1' THEN
+ datatype <= "10"; --Long
+ ELSE
+ datatype <= "01"; --Word
+ END IF;
+ dest_hbits <='1';
+ regwrena <= '1';
+ END IF;
+ ELSE
+ IF opcode(8)='1' OR opcode(11 downto 8)="1000" THEN --Bits
+ IF execOPC='1' AND get_extendedOPC='0' THEN
+ IF opcode(7 downto 6)/="00" AND endOPC='1' THEN
+ regwrena <= '1';
+ END IF;
+ exec_Bits <= '1';
+ ea_data_OP1 <= '1';
+ END IF;
+-- IF get_extendedOPC='1' THEN
+-- datatype <= "01"; --Word
+-- ELS
+ IF opcode(5 downto 4)="00" THEN
+ datatype <= "10"; --Long
+ ELSE
+ datatype <= "00"; --Byte
+ IF opcode(7 downto 6)/="00" THEN
+ write_back <= '1';
+ END IF;
+ END IF;
+ IF decodeOPC='1' THEN
+ ea_build <= '1';
+ IF opcode(8)='0' THEN
+ IF opcode(5 downto 4)/="00" THEN --Dn, An
+ set_get_extendedOPC <= '1';
+ END IF;
+ set_get_bitnumber <= '1';
+ END IF;
+ END IF;
+ ELSE --andi, ...xxxi
+ IF opcode(11 downto 8)="0000" THEN --ORI
+ set_exec_OR <= '1';
+ END IF;
+ IF opcode(11 downto 8)="0010" THEN --ANDI
+ set_exec_AND <= '1';
+ END IF;
+ IF opcode(11 downto 8)="0100" OR opcode(11 downto 8)="0110" THEN --SUBI, ADDI
+ set_exec_ADD <= '1';
+ END IF;
+ IF opcode(11 downto 8)="1010" THEN --EORI
+ set_exec_EOR <= '1';
+ END IF;
+ IF opcode(11 downto 8)="1100" THEN --CMPI
+ set_exec_CMP <= '1';
+ ELSIF trapmake='0' THEN
+ write_back <= '1';
+ END IF;
+ IF opcode(7)='0' AND opcode(5 downto 0)="111100" AND (set_exec_AND OR set_exec_OR OR set_exec_EOR)='1' THEN --SR
+-- IF opcode(7)='0' AND opcode(5 downto 0)="111100" AND (opcode(11 downto 8)="0010" OR opcode(11 downto 8)="0000" OR opcode(11 downto 8)="1010") THEN --SR
+ IF SVmode='0' AND opcode(6)='1' THEN --SR
+ trap_priv <= '1';
+ trapmake <= '1';
+ ELSE
+ from_SR <= '1';
+ to_SR <= '1';
+ IF decodeOPC='1' THEN
+ setnextpass <= '1';
+ set_direct_data <= '1';
+ END IF;
+ END IF;
+ ELSE
+ IF decodeOPC='1' THEN
+ IF opcode(11 downto 8)="0010" OR opcode(11 downto 8)="0000" OR opcode(11 downto 8)="0100" --ANDI, ORI, SUBI
+ OR opcode(11 downto 8)="0110" OR opcode(11 downto 8)="1010" OR opcode(11 downto 8)="1100" THEN --ADDI, EORI, CMPI
+ -- IF (set_exec_AND OR set_exec_OR OR set_exec_ADD --ANDI, ORI, SUBI
+ -- OR set_exec_EOR OR set_exec_CMP)='1' THEN --ADDI, EORI, CMPI
+
+ next_micro_state <= andi;
+ set_direct_data <= '1';
+ IF datatype="10" THEN
+ longreaddirect <= '1';
+ END IF;
+ END IF;
+ END IF;
+
+ IF execOPC='1' THEN
+ ea_data_OP1 <= '1';
+ IF opcode(11 downto 8)/="1100" THEN --CMPI
+ IF endOPC='1' THEN
+ Regwrena <= '1';
+ END IF;
+ END IF;
+ IF opcode(11 downto 8)="1100" OR opcode(11 downto 8)="0100" THEN --CMPI, SUBI
+ setaddsub <= '0';
+ END IF;
+ END IF;
+ END IF;
+ END IF;
+ END IF;
+
+-- 0001, 0010, 0011 -----------------------------------------------------------------
+ WHEN "0001"|"0010"|"0011" => --move.b, move.l, move.w
+ set_exec_MOVE <= '1';
+ IF opcode(8 downto 6)="001" THEN
+ no_Flags <= '1';
+ END IF;
+ IF opcode(5 downto 4)="00" THEN --Dn, An
+ regdirectsource <= '1';
+ END IF;
+ CASE opcode(13 downto 12) IS
+ WHEN "01" => datatype <= "00"; --Byte
+ WHEN "10" => datatype <= "10"; --Long
+ WHEN OTHERS => datatype <= "01"; --Word
+ END CASE;
+ source_lowbits <= '1'; -- Dn=> An=>
+ IF opcode(3)='1' THEN
+ source_areg <= '1';
+ END IF;
+ IF getbrief='1' AND nextpass='1' THEN -- =>(d16,An) =>(d8,An,Xn)
+ set_mem_rega <= '1';
+ END IF;
+
+ IF execOPC='1' AND opcode(8 downto 7)="00" THEN
+ Regwrena <= '1';
+ END IF;
+
+ IF nextpass='1' OR execOPC='1' OR opcode(5 downto 4)="00" THEN
+ dest_hbits <= '1';
+ IF opcode(8 downto 6)/="000" THEN
+ dest_areg <= '1';
+ END IF;
+ END IF;
+
+ IF decodeOPC='1' THEN
+ ea_build <= '1';
+ END IF;
+
+ IF micro_state=idle AND (nextpass='1' OR (opcode(5 downto 4)="00" AND decodeOPC='1')) THEN
+ CASE opcode(8 downto 6) IS --destination
+-- WHEN "000" => --Dn
+-- WHEN "001" => --An
+ WHEN "010"|"011"|"100" => --destination -(an)+
+ IF opcode(7)='1' THEN
+ set_mem_rega <= '1';
+ ELSE
+ set_mem_addsub <= '1';
+ END IF;
+ IF opcode(6)='1' THEN --(An)+
+ postadd <= '1';
+ IF opcode(11 downto 9)="111" THEN
+ use_SP <= '1';
+ END IF;
+ END IF;
+ IF opcode(8)='1' THEN -- -(An)
+ presub <= '1';
+ IF opcode(11 downto 9)="111" THEN
+ use_SP <= '1';
+ END IF;
+ END IF;
+ IF opcode(7 downto 6)/="10" THEN
+ regwrena <= '1';
+ END IF;
+ setstate <= "11";
+ next_micro_state <= nop;
+ WHEN "101" => --(d16,An)
+ next_micro_state <= st_dAn1;
+ set_mem_regA <= '1';
+ setgetbrief <= '1';
+ WHEN "110" => --(d8,An,Xn)
+ next_micro_state <= st_AnXn1;
+ set_mem_regA <= '1';
+ setgetbrief <= '1';
+ WHEN "111" =>
+ CASE opcode(11 downto 9) IS
+ WHEN "000" => --(xxxx).w
+ next_micro_state <= st_nn;
+ WHEN "001" => --(xxxx).l
+ longreaddirect <= '1';
+ next_micro_state <= st_nn;
+ WHEN OTHERS =>
+ END CASE;
+ WHEN OTHERS =>
+ END CASE;
+ END IF;
+-- 0100 ----------------------------------------------------------------------------
+ WHEN "0100" => --rts_group
+ IF opcode(8)='1' THEN --lea
+ IF opcode(6)='1' THEN --lea
+ IF opcode(7)='1' THEN
+ ea_only <= '1';
+ IF opcode(5 downto 3)="010" THEN --lea (Am),An
+ set_exec_move <='1';
+ no_Flags <='1';
+ dest_areg <= '1';
+ dest_hbits <= '1';
+ source_lowbits <= '1';
+ source_areg <= '1';
+ IF execOPC='1' THEN
+ Regwrena <= '1';
+ END IF;
+ ELSE
+ IF decodeOPC='1' THEN
+ ea_build <= '1';
+ END IF;
+ END IF;
+ IF get_ea_now='1' THEN
+ dest_areg <= '1';
+ dest_hbits <= '1';
+ regwrena <= '1';
+ END IF;
+ ELSE
+ trap_illegal <= '1';
+ trapmake <= '1';
+ END IF;
+ ELSE --chk
+ IF opcode(7)='1' THEN
+ set_exec_ADD <= '1';
+ IF decodeOPC='1' THEN
+ ea_build <= '1';
+ END IF;
+ datatype <= "01"; --Word
+ IF execOPC='1' THEN
+ setaddsub <= '0';
+--first alternative
+ ea_data_OP1 <= '1';
+ IF c_out(1)='1' OR OP1out(15)='1' OR OP2out(15)='1' THEN
+ -- trap_chk <= '1'; --first I must change the Trap System
+ -- trapmake <= '1';
+ END IF;
+--second alternative
+-- IF (c_out(1)='0' AND flag_z(1)='0') OR OP1out(15)='1' OR OP2out(15)='1' THEN
+-- -- trap_chk <= '1'; --first I must change the Trap System
+-- -- trapmake <= '1';
+-- END IF;
+-- dest_hbits <= '1';
+-- source_lowbits <='1';
+ END IF;
+ ELSE
+ trap_illegal <= '1'; -- chk long for 68020
+ trapmake <= '1';
+ END IF;
+ END IF;
+ ELSE
+ CASE opcode(11 downto 9) IS
+ WHEN "000"=>
+ IF decodeOPC='1' THEN
+ ea_build <= '1';
+ END IF;
+ IF opcode(7 downto 6)="11" THEN --move from SR
+ set_exec_MOVESR <= '1';
+ datatype <= "01";
+ write_back <='1'; -- im 68000 wird auch erst gelesen
+ IF execOPC='1' THEN
+ IF endOPC='1' THEN
+ Regwrena <= '1';
+ END IF;
+ END IF;
+ ELSE --negx
+ use_XFlag <= '1';
+ write_back <='1';
+ set_exec_ADD <= '1';
+ setaddsub <='0';
+ IF execOPC='1' THEN
+ source_lowbits <= '1';
+ OP1out_zero <= '1';
+ IF endOPC='1' THEN
+ Regwrena <= '1';
+ END IF;
+ END IF;
+ END IF;
+ WHEN "001"=>
+ IF opcode(7 downto 6)="11" THEN --move from CCR 68010
+ trap_illegal <= '1';
+ trapmake <= '1';
+ ELSE --clr
+ IF decodeOPC='1' THEN
+ ea_build <= '1';
+ END IF;
+ write_back <='1';
+ set_exec_AND <= '1';
+ IF execOPC='1' THEN
+ OP1out_zero <= '1';
+ IF endOPC='1' THEN
+ Regwrena <= '1';
+ END IF;
+ END IF;
+ END IF;
+ WHEN "010"=>
+ IF decodeOPC='1' THEN
+ ea_build <= '1';
+ END IF;
+ IF opcode(7 downto 6)="11" THEN --move to CCR
+ set_exec_MOVE <= '1';
+ datatype <= "01";
+ IF execOPC='1' THEN
+ source_lowbits <= '1';
+ to_SR <= '1';
+ END IF;
+ ELSE --neg
+ write_back <='1';
+ set_exec_ADD <= '1';
+ setaddsub <='0';
+ IF execOPC='1' THEN
+ source_lowbits <= '1';
+ OP1out_zero <= '1';
+ IF endOPC='1' THEN
+ Regwrena <= '1';
+ END IF;
+ END IF;
+ END IF;
+ WHEN "011"=> --not, move toSR
+ IF opcode(7 downto 6)="11" THEN --move to SR
+ IF SVmode='1' THEN
+ IF decodeOPC='1' THEN
+ ea_build <= '1';
+ END IF;
+ set_exec_MOVE <= '1';
+ datatype <= "01";
+ IF execOPC='1' THEN
+ source_lowbits <= '1';
+ to_SR <= '1';
+ END IF;
+ ELSE
+ trap_priv <= '1';
+ trapmake <= '1';
+ END IF;
+ ELSE --not
+ IF decodeOPC='1' THEN
+ ea_build <= '1';
+ END IF;
+ write_back <='1';
+ set_exec_EOR <= '1';
+ IF execOPC='1' THEN
+ OP2out_one <= '1';
+ ea_data_OP1 <= '1';
+ IF endOPC='1' THEN
+ Regwrena <= '1';
+ END IF;
+ END IF;
+ END IF;
+ WHEN "100"|"110"=>
+ IF opcode(7)='1' THEN --movem, ext
+ IF opcode(5 downto 3)="000" AND opcode(10)='0' THEN --ext
+ source_lowbits <= '1';
+ IF decodeOPC='1' THEN
+ set_exec_EXT <= '1';
+ set_exec_move <= '1';
+ END IF;
+ IF opcode(6)='0' THEN
+ datatype <= "01"; --WORD
+ END IF;
+ IF execOPC='1' THEN
+ regwrena <= '1';
+ END IF;
+ ELSE --movem
+-- IF opcode(11 downto 7)="10001" OR opcode(11 downto 7)="11001" THEN --MOVEM
+ ea_only <= '1';
+ IF decodeOPC='1' THEN
+ datatype <= "01"; --Word
+ set_get_movem_mask <='1';
+ set_get_extendedOPC <='1';
+
+ IF opcode(5 downto 3)="010" OR opcode(5 downto 3)="011" OR opcode(5 downto 3)="100" THEN
+ set_mem_rega <= '1';
+ setstate <= "01";
+ IF opcode(10)='0' THEN
+ set_movem_busy <='1';
+ ELSE
+ next_micro_state <= movem;
+ END IF;
+ ELSE
+ ea_build <= '1';
+ END IF;
+
+ ELSE
+ IF opcode(6)='0' THEN
+ datatype <= "01"; --Word
+ END IF;
+ END IF;
+ IF execOPC='1' THEN
+ IF opcode(5 downto 3)="100" OR opcode(5 downto 3)="011" THEN
+ regwrena <= '1';
+ save_memaddr <= '1';
+ END IF;
+ END IF;
+ IF get_ea_now='1' THEN
+ set_movem_busy <= '1';
+ IF opcode(10)='0' THEN
+ setstate <="01";
+ ELSE
+ setstate <="10";
+ END IF;
+ END IF;
+ IF opcode(5 downto 3)="100" THEN
+ movem_presub <= '1';
+ END IF;
+ IF movem_addr='1' THEN
+ IF opcode(10)='1' THEN
+ regwrena <= '1';
+ END IF;
+ END IF;
+ IF movem_busy='1' THEN
+ IF opcode(10)='0' THEN
+ setstate <="11";
+ ELSE
+ setstate <="10";
+ END IF;
+ END IF;
+ END IF;
+ ELSE
+ IF opcode(10)='1' THEN --MUL, DIV 68020
+ trap_illegal <= '1';
+ trapmake <= '1';
+ ELSE --pea, swap
+ IF opcode(6)='1' THEN
+ datatype <= "10";
+ IF opcode(5 downto 3)="000" THEN --swap
+ IF execOPC='1' THEN
+ exec_swap <= '1';
+ regwrena <= '1';
+ END IF;
+ ELSIF opcode(5 downto 3)="001" THEN --bkpt
+
+ ELSE --pea
+ ea_only <= '1';
+ IF decodeOPC='1' THEN
+ ea_build <= '1';
+ END IF;
+ IF nextpass='1' AND micro_state=idle THEN
+ presub <= '1';
+ setstackaddr <='1';
+ set_mem_addsub <= '1';
+ setstate <="11";
+ next_micro_state <= nop;
+ END IF;
+ IF get_ea_now='1' THEN
+ setstate <="01";
+ END IF;
+ END IF;
+ ELSE --nbcd
+ IF decodeOPC='1' THEN --nbcd
+ ea_build <= '1';
+ END IF;
+ use_XFlag <= '1';
+ write_back <='1';
+ set_exec_ADD <= '1';
+ set_exec_SBCD <= '1';
+ IF execOPC='1' THEN
+ source_lowbits <= '1';
+ OP1out_zero <= '1';
+ IF endOPC='1' THEN
+ Regwrena <= '1';
+ END IF;
+ END IF;
+ END IF;
+ END IF;
+ END IF;
+
+ WHEN "101"=> --tst, tas
+ IF opcode(7 downto 2)="111111" THEN --4AFC illegal
+ trap_illegal <= '1';
+ trapmake <= '1';
+ ELSE
+ IF decodeOPC='1' THEN
+ ea_build <= '1';
+ END IF;
+ IF execOPC='1' THEN
+ dest_hbits <= '1'; --for Flags
+ source_lowbits <= '1';
+ -- IF opcode(3)='1' THEN --MC68020...
+ -- source_areg <= '1';
+ -- END IF;
+ END IF;
+ set_exec_MOVE <= '1';
+ IF opcode(7 downto 6)="11" THEN --tas
+ set_exec_tas <= '1';
+ write_back <= '1';
+ datatype <= "00"; --Byte
+ IF execOPC='1' AND endOPC='1' THEN
+ regwrena <= '1';
+ END IF;
+ END IF;
+ END IF;
+-- WHEN "110"=>
+ WHEN "111"=> --4EXX
+ IF opcode(7)='1' THEN --jsr, jmp
+ datatype <= "10";
+ ea_only <= '1';
+ IF nextpass='1' AND micro_state=idle THEN
+ presub <= '1';
+ setstackaddr <='1';
+ set_mem_addsub <= '1';
+ setstate <="11";
+ next_micro_state <= nop;
+ END IF;
+ IF decodeOPC='1' THEN
+ ea_build <= '1';
+ END IF;
+ IF get_ea_now='1' THEN --jsr
+ IF opcode(6)='0' THEN
+ setstate <="01";
+ END IF;
+ ea_to_pc <= '1';
+ IF opcode(5 downto 1)="11100" THEN
+ writePC_add <= '1';
+ ELSE
+ writePC <= '1';
+ END IF;
+ END IF;
+ ELSE --
+ CASE opcode(6 downto 0) IS
+ WHEN "1000000"|"1000001"|"1000010"|"1000011"|"1000100"|"1000101"|"1000110"|"1000111"| --trap
+ "1001000"|"1001001"|"1001010"|"1001011"|"1001100"|"1001101"|"1001110"|"1001111" => --trap
+ trap_trap <='1';
+ trapmake <= '1';
+ WHEN "1010000"|"1010001"|"1010010"|"1010011"|"1010100"|"1010101"|"1010110"|"1010111" => --link
+ datatype <= "10";
+ IF decodeOPC='1' THEN
+ next_micro_state <= link;
+ set_exec_MOVE <= '1'; --fr displacement
+ presub <= '1';
+ setstackaddr <='1';
+ set_mem_addsub <= '1';
+ source_lowbits <= '1';
+ source_areg <= '1';
+ END IF;
+ IF execOPC='1' THEN
+ setstackaddr <='1';
+ regwrena <= '1';
+ END IF;
+
+ WHEN "1011000"|"1011001"|"1011010"|"1011011"|"1011100"|"1011101"|"1011110"|"1011111" => --unlink
+ datatype <= "10";
+ IF decodeOPC='1' THEN
+ setstate <= "10";
+ set_mem_rega <= '1';
+ ELSIF execOPC='1' THEN
+ regwrena <= '1';
+ exec_exg <= '1';
+ ELSE
+ setstackaddr <='1';
+ regwrena <= '1';
+ get_ea_now <= '1';
+ ea_only <= '1';
+ END IF;
+
+ WHEN "1100000"|"1100001"|"1100010"|"1100011"|"1100100"|"1100101"|"1100110"|"1100111" => --move An,USP
+ IF SVmode='1' THEN
+ no_Flags <= '1';
+ to_USP <= '1';
+ setstackaddr <= '1';
+ source_lowbits <= '1';
+ source_areg <= '1';
+ set_exec_MOVE <= '1';
+ datatype <= "10";
+ IF execOPC='1' THEN
+ regwrena <= '1';
+ END IF;
+ ELSE
+ trap_priv <= '1';
+ trapmake <= '1';
+ END IF;
+ WHEN "1101000"|"1101001"|"1101010"|"1101011"|"1101100"|"1101101"|"1101110"|"1101111" => --move USP,An
+ IF SVmode='1' THEN
+ no_Flags <= '1';
+ from_USP <= '1';
+ set_exec_MOVE <= '1';
+ datatype <= "10";
+ IF execOPC='1' THEN
+ regwrena <= '1';
+ END IF;
+ ELSE
+ trap_priv <= '1';
+ trapmake <= '1';
+ END IF;
+
+ WHEN "1110000" => --reset
+ IF SVmode='0' THEN
+ trap_priv <= '1';
+ trapmake <= '1';
+ END IF;
+
+ WHEN "1110001" => --nop
+
+ WHEN "1110010" => --stop
+ IF SVmode='0' THEN
+ trap_priv <= '1';
+ trapmake <= '1';
+ ELSE
+ IF decodeOPC='1' THEN
+ setnextpass <= '1';
+ set_directSR <= '1';
+ set_stop <= '1';
+ END IF;
+ END IF;
+
+ WHEN "1110011" => --rte
+ IF SVmode='1' THEN
+ IF decodeOPC='1' THEN
+ datatype <= "01";
+ setstate <= "10";
+ postadd <= '1';
+ setstackaddr <= '1';
+ set_mem_rega <= '1';
+ set_directSR <= '1';
+ next_micro_state <= rte;
+ END IF;
+ ELSE
+ trap_priv <= '1';
+ trapmake <= '1';
+ END IF;
+
+ WHEN "1110101" => --rts
+ IF decodeOPC='1' THEN
+ datatype <= "10";
+ setstate <= "10";
+ postadd <= '1';
+ setstackaddr <= '1';
+ set_mem_rega <= '1';
+ set_directPC <= '1';
+ next_micro_state <= nop;
+ END IF;
+
+ WHEN "1110110" => --trapv
+ IF Flags(1)='1' THEN
+ trap_trapv <= '1';
+ trapmake <= '1';
+ END IF;
+
+ WHEN "1110111" => --rtr
+ IF decodeOPC='1' THEN
+ datatype <= "01";
+ setstate <= "10";
+ postadd <= '1';
+ setstackaddr <= '1';
+ set_mem_rega <= '1';
+ set_directCCR <= '1';
+ next_micro_state <= rte;
+ END IF;
+
+
+ WHEN OTHERS =>
+ trap_illegal <= '1';
+ trapmake <= '1';
+ END CASE;
+ END IF;
+ WHEN OTHERS => null;
+ END CASE;
+ END IF;
+
+-- 0101 ----------------------------------------------------------------------------
+ WHEN "0101" => --subq, addq
+
+ IF opcode(7 downto 6)="11" THEN --dbcc
+ IF opcode(5 downto 3)="001" THEN --dbcc
+ datatype <= "01"; --Word
+ IF decodeOPC='1' THEN
+ next_micro_state <= nop;
+ OP2out_one <= '1';
+ IF condition='0' THEN
+ Regwrena <= '1';
+ IF c_in(2)='1' THEN
+ next_micro_state <= dbcc1;
+ END IF;
+ END IF;
+ data_is_source <= '1';
+ END IF;
+ ELSE --Scc
+ datatype <= "00"; --Byte
+ write_back <= '1';
+ IF decodeOPC='1' THEN
+ ea_build <= '1';
+ END IF;
+ IF condition='0' THEN
+ set_exec_Scc <= '1';
+ END IF;
+ IF execOPC='1' THEN
+ IF condition='1' THEN
+ OP2out_one <= '1';
+ exec_EXG <= '1';
+ ELSE
+ OP1out_zero <= '1';
+ END IF;
+ IF endOPC='1' THEN
+ Regwrena <= '1';
+ END IF;
+ END IF;
+ END IF;
+ ELSE --addq, subq
+ IF decodeOPC='1' THEN
+ ea_build <= '1';
+ END IF;
+ IF opcode(5 downto 3)="001" THEN
+ no_Flags <= '1';
+ END IF;
+ write_back <= '1';
+ set_exec_ADDQ <= '1';
+ set_exec_ADD <= '1';
+ IF execOPC='1' THEN
+ ea_data_OP1 <= '1';
+ IF endOPC='1' THEN
+ Regwrena <= '1';
+ END IF;
+ IF opcode(8)='1' THEN
+ setaddsub <= '0';
+ END IF;
+ END IF;
+ END IF;
+
+-- 0110 ----------------------------------------------------------------------------
+ WHEN "0110" => --bra,bsr,bcc
+ datatype <= "10";
+
+ IF micro_state=idle THEN
+ IF opcode(11 downto 8)="0001" THEN --bsr
+ IF opcode(7 downto 0)="00000000" THEN
+ next_micro_state <= bsr1;
+ ELSE
+ next_micro_state <= bsr2;
+ setstate <= "01";
+ END IF;
+ presub <= '1';
+ setstackaddr <='1';
+ set_mem_addsub <= '1';
+ ELSE --bra
+ IF opcode(7 downto 0)="00000000" THEN
+ next_micro_state <= bra1;
+ END IF;
+ IF condition='1' THEN
+ TG68_PC_br8 <= '1';
+ END IF;
+ END IF;
+ END IF;
+
+-- 0111 ----------------------------------------------------------------------------
+ WHEN "0111" => --moveq
+ IF opcode(8)='0' THEN
+ IF trap_interrupt='0' THEN
+ datatype <= "10"; --Long
+ Regwrena <= '1';
+ set_exec_MOVEQ <= '1';
+ set_exec_MOVE <= '1';
+ dest_hbits <= '1';
+ END IF;
+ ELSE
+ trap_illegal <= '1';
+ trapmake <= '1';
+ END IF;
+
+-- 1000 ----------------------------------------------------------------------------
+ WHEN "1000" => --or
+ IF opcode(7 downto 6)="11" THEN --divu, divs
+ IF opcode(5 downto 4)="00" THEN --Dn, An
+ regdirectsource <= '1';
+ END IF;
+ IF (micro_state=idle AND nextpass='1') OR (opcode(5 downto 4)="00" AND decodeOPC='1') THEN
+ set_exec_DIVU <= '1';
+ setstate <="01";
+ next_micro_state <= div1;
+ END IF;
+ IF decodeOPC='1' THEN
+ ea_build <= '1';
+ END IF;
+ IF execOPC='1' AND z_error='0' AND set_V_Flag='0' THEN
+ regwrena <= '1';
+ END IF;
+ IF (micro_state/=idle AND nextpass='1') OR execOPC='1' THEN
+ dest_hbits <= '1';
+ source_lowbits <='1';
+ ELSE
+ datatype <= "01";
+ END IF;
+
+
+ ELSIF opcode(8)='1' AND opcode(5 downto 4)="00" THEN --sbcd, pack , unpack
+ IF opcode(7 downto 6)="00" THEN --sbcd
+ use_XZFlag <= '1';
+ set_exec_ADD <= '1';
+ set_exec_SBCD <= '1';
+ IF opcode(3)='1' THEN
+ write_back <= '1';
+ IF decodeOPC='1' THEN
+ set_direct_data <= '1';
+ setstate <= "10";
+ set_mem_addsub <= '1';
+ presub <= '1';
+ next_micro_state <= op_AxAy;
+ END IF;
+ END IF;
+ IF execOPC='1' THEN
+ ea_data_OP1 <= '1';
+ dest_hbits <= '1';
+ source_lowbits <='1';
+ IF endOPC='1' THEN
+ Regwrena <= '1';
+ END IF;
+ END IF;
+ ELSE --pack, unpack
+ trap_illegal <= '1';
+ trapmake <= '1';
+ END IF;
+ ELSE --or
+ set_exec_OR <= '1';
+ IF opcode(8)='1' THEN
+ write_back <= '1';
+ END IF;
+ IF decodeOPC='1' THEN
+ ea_build <= '1';
+ END IF;
+ IF execOPC='1' THEN
+ IF endOPC='1' THEN
+ Regwrena <= '1';
+ END IF;
+ IF opcode(8)='1' THEN
+ ea_data_OP1 <= '1';
+ ELSE
+ dest_hbits <= '1';
+ source_lowbits <='1';
+ IF opcode(3)='1' THEN
+ source_areg <= '1';
+ END IF;
+ END IF;
+ END IF;
+ END IF;
+
+-- 1001, 1101 -----------------------------------------------------------------------
+ WHEN "1001"|"1101" => --sub, add
+ set_exec_ADD <= '1';
+ IF decodeOPC='1' THEN
+ ea_build <= '1';
+ END IF;
+ IF opcode(8 downto 6)="011" THEN --adda.w, suba.w
+ datatype <= "01"; --Word
+ END IF;
+ IF execOPC='1' THEN
+ IF endOPC='1' THEN
+ Regwrena <= '1';
+ END IF;
+ IF opcode(14)='0' THEN
+ setaddsub <= '0';
+ END IF;
+ END IF;
+ IF opcode(8)='1' AND opcode(5 downto 4)="00" AND opcode(7 downto 6)/="11" THEN --addx, subx
+ use_XZFlag <= '1';
+ IF opcode(3)='1' THEN
+ write_back <= '1';
+ IF decodeOPC='1' THEN
+ set_direct_data <= '1';
+ setstate <= "10";
+ set_mem_addsub <= '1';
+ presub <= '1';
+ next_micro_state <= op_AxAy;
+ END IF;
+ END IF;
+ IF execOPC='1' THEN
+ ea_data_OP1 <= '1';
+ dest_hbits <= '1';
+ source_lowbits <='1';
+ END IF;
+ ELSE --sub, add
+ IF opcode(8)='1' AND opcode(7 downto 6)/="11" THEN
+ write_back <= '1';
+ END IF;
+ IF execOPC='1' THEN
+ IF opcode(7 downto 6)="11" THEN --adda, suba
+ no_Flags <= '1';
+ dest_areg <='1';
+ dest_hbits <= '1';
+ source_lowbits <='1';
+ IF opcode(3)='1' THEN
+ source_areg <= '1';
+ END IF;
+ ELSE
+ IF opcode(8)='1' THEN
+ ea_data_OP1 <= '1';
+ ELSE
+ dest_hbits <= '1';
+ source_lowbits <='1';
+ IF opcode(3)='1' THEN
+ source_areg <= '1';
+ END IF;
+ END IF;
+ END IF;
+ END IF;
+ END IF;
+
+-- 1010 ----------------------------------------------------------------------------
+ WHEN "1010" => --Trap 1010
+ trap_1010 <= '1';
+ trapmake <= '1';
+-- 1011 ----------------------------------------------------------------------------
+ WHEN "1011" => --eor, cmp
+ IF decodeOPC='1' THEN
+ ea_build <= '1';
+ END IF;
+ IF opcode(8 downto 6)="011" THEN --cmpa.w
+ datatype <= "01"; --Word
+ set_exec_CPMAW <= '1';
+ END IF;
+ IF opcode(8)='1' AND opcode(5 downto 3)="001" AND opcode(7 downto 6)/="11" THEN --cmpm
+ set_exec_CMP <= '1';
+ IF decodeOPC='1' THEN
+ set_direct_data <= '1';
+ setstate <= "10";
+ set_mem_rega <= '1';
+ postadd <= '1';
+ next_micro_state <= cmpm;
+ END IF;
+ IF execOPC='1' THEN
+ ea_data_OP1 <= '1';
+ setaddsub <= '0';
+ END IF;
+ ELSE --sub, add
+ IF opcode(8)='1' AND opcode(7 downto 6)/="11" THEN --eor
+ set_exec_EOR <= '1';
+ write_back <= '1';
+ ELSE --cmp
+ set_exec_CMP <= '1';
+ END IF;
+
+ IF execOPC='1' THEN
+ IF opcode(8)='1' AND opcode(7 downto 6)/="11" THEN --eor
+ ea_data_OP1 <= '1';
+ IF endOPC='1' THEN
+ Regwrena <= '1';
+ END IF;
+ ELSE --cmp
+ source_lowbits <='1';
+ IF opcode(3)='1' THEN
+ source_areg <= '1';
+ END IF;
+ IF opcode(7 downto 6)="11" THEN --cmpa
+ dest_areg <='1';
+ END IF;
+ dest_hbits <= '1';
+ setaddsub <= '0';
+ END IF;
+ END IF;
+ END IF;
+
+-- 1100 ----------------------------------------------------------------------------
+ WHEN "1100" => --and, exg
+ IF opcode(7 downto 6)="11" THEN --mulu, muls
+ IF opcode(5 downto 4)="00" THEN --Dn, An
+ regdirectsource <= '1';
+ END IF;
+ IF (micro_state=idle AND nextpass='1') OR (opcode(5 downto 4)="00" AND decodeOPC='1') THEN
+ set_exec_MULU <= '1';
+ setstate <="01";
+ next_micro_state <= mul1;
+ END IF;
+ IF decodeOPC='1' THEN
+ ea_build <= '1';
+ END IF;
+ IF execOPC='1' THEN
+ regwrena <= '1';
+ END IF;
+ IF (micro_state/=idle AND nextpass='1') OR execOPC='1' THEN
+ dest_hbits <= '1';
+ source_lowbits <='1';
+ ELSE
+ datatype <= "01";
+ END IF;
+
+ ELSIF opcode(8)='1' AND opcode(5 downto 4)="00" THEN --exg, abcd
+ IF opcode(7 downto 6)="00" THEN --abcd
+ use_XZFlag <= '1';
+-- datatype <= "00"; --ist schon default
+ set_exec_ADD <= '1';
+ set_exec_ABCD <= '1';
+ IF opcode(3)='1' THEN
+ write_back <= '1';
+ IF decodeOPC='1' THEN
+ set_direct_data <= '1';
+ setstate <= "10";
+ set_mem_addsub <= '1';
+ presub <= '1';
+ next_micro_state <= op_AxAy;
+ END IF;
+ END IF;
+ IF execOPC='1' THEN
+ ea_data_OP1 <= '1';
+ dest_hbits <= '1';
+ source_lowbits <='1';
+ IF endOPC='1' THEN
+ Regwrena <= '1';
+ END IF;
+ END IF;
+ ELSE --exg
+ datatype <= "10";
+ regwrena <= '1';
+ IF opcode(6)='1' AND opcode(3)='1' THEN
+ dest_areg <= '1';
+ source_areg <= '1';
+ END IF;
+ IF decodeOPC='1' THEN
+ set_mem_rega <= '1';
+ exec_exg <= '1';
+ ELSE
+ save_memaddr <= '1';
+ dest_hbits <= '1';
+ END IF;
+ END IF;
+ ELSE --and
+ set_exec_AND <= '1';
+ IF opcode(8)='1' THEN
+ write_back <= '1';
+ END IF;
+ IF decodeOPC='1' THEN
+ ea_build <= '1';
+ END IF;
+
+ IF execOPC='1' THEN
+ IF endOPC='1' THEN
+ Regwrena <= '1';
+ END IF;
+ IF opcode(8)='1' THEN
+ ea_data_OP1 <= '1';
+ ELSE
+ dest_hbits <= '1';
+ source_lowbits <='1';
+ IF opcode(3)='1' THEN
+ source_areg <= '1';
+ END IF;
+ END IF;
+ END IF;
+ END IF;
+
+-- 1110 ----------------------------------------------------------------------------
+ WHEN "1110" => --rotation
+ set_exec_ROT <= '1';
+ IF opcode(7 downto 6)="11" THEN
+ datatype <= "01";
+ rot_bits <= opcode(10 downto 9);
+ ea_data_OP1 <= '1';
+ write_back <= '1';
+ ELSE
+ rot_bits <= opcode(4 downto 3);
+ data_is_source <= '1';
+ END IF;
+
+ IF decodeOPC='1' THEN
+ IF opcode(7 downto 6)="11" THEN
+ ea_build <= '1';
+ ELSE
+ IF opcode(5)='1' THEN
+ IF OP2out(5 downto 0)/="000000" THEN
+ set_rot_cnt <= OP2out(5 downto 0);
+ ELSE
+ set_rot_nop <= '1';
+ END IF;
+ ELSE
+ set_rot_cnt(2 downto 0) <= opcode(11 downto 9);
+ IF opcode(11 downto 9)="000" THEN
+ set_rot_cnt(3) <='1';
+ ELSE
+ set_rot_cnt(3) <='0';
+ END IF;
+ END IF;
+ END IF;
+ END IF;
+ IF opcode(7 downto 6)/="11" THEN
+ IF execOPC='1' AND rot_nop='0' THEN
+ Regwrena <= '1';
+ set_rot_cnt <= rot_cnt-1;
+ END IF;
+ END IF;
+
+-- ----------------------------------------------------------------------------
+ WHEN OTHERS =>
+ trap_1111 <= '1';
+ trapmake <= '1';
+
+ END CASE;
+
+-- END PROCESS;
+
+-----------------------------------------------------------------------------
+-- execute microcode
+-----------------------------------------------------------------------------
+--PROCESS (micro_state)
+-- BEGIN
+ IF Z_error='1' THEN -- divu by zero
+ trapmake <= '1'; --wichtig fr USP
+ IF trapd='0' THEN
+ writePC <= '1';
+ END IF;
+ END IF;
+
+ IF trapmake='1' AND trapd='0' THEN
+ next_micro_state <= trap1;
+ presub <= '1';
+ setstackaddr <='1';
+ set_mem_addsub <= '1';
+ setstate <= "11";
+ datatype <= "10";
+ END IF;
+
+ IF interrupt='1' THEN
+ next_micro_state <= int1;
+ setstate <= "10";
+-- datatype <= "01"; --wirkt sich auf Flags aus
+ END IF;
+
+ IF reset='0' THEN
+ micro_state <= init1;
+ ELSIF rising_edge(clk) THEN
+ IF clkena='1' THEN
+ trapd <= trapmake;
+ IF fetchOPC='1' THEN
+ micro_state <= idle;
+ ELSE
+ micro_state <= next_micro_state;
+ END IF;
+ END IF;
+ END IF;
+ CASE micro_state IS
+ WHEN ld_nn => -- (nnnn).w/l=>
+ get_ea_now <='1';
+ setnextpass <= '1';
+ setaddrlong <= '1';
+
+ WHEN st_nn => -- =>(nnnn).w/l
+ setstate <= "11";
+ setaddrlong <= '1';
+ next_micro_state <= nop;
+
+ WHEN ld_dAn1 => -- d(An)=>, --d(PC)=>
+ setstate <= "01";
+ next_micro_state <= ld_dAn2;
+ WHEN ld_dAn2 => -- d(An)=>, --d(PC)=>
+ get_ea_now <='1';
+ setdisp <= '1'; --word
+ setnextpass <= '1';
+
+ WHEN ld_AnXn1 => -- d(An,Xn)=>, --d(PC,Xn)=>
+ setstate <= "01";
+ next_micro_state <= ld_AnXn2;
+ WHEN ld_AnXn2 => -- d(An,Xn)=>, --d(PC,Xn)=>
+ setdisp <= '1'; --byte
+ setdispbyte <= '1';
+ setstate <= "01";
+ setbriefext <= '1';
+ next_micro_state <= ld_AnXn3;
+ WHEN ld_AnXn3 =>
+ get_ea_now <='1';
+ setdisp <= '1'; --brief
+ setdispbrief <= '1';
+ setnextpass <= '1';
+
+ WHEN st_dAn1 => -- =>d(An)
+ setstate <= "01";
+ next_micro_state <= st_dAn2;
+ WHEN st_dAn2 => -- =>d(An)
+ setstate <= "11";
+ setdisp <= '1'; --word
+ next_micro_state <= nop;
+
+ WHEN st_AnXn1 => -- =>d(An,Xn)
+ setstate <= "01";
+ next_micro_state <= st_AnXn2;
+ WHEN st_AnXn2 => -- =>d(An,Xn)
+ setdisp <= '1'; --byte
+ setdispbyte <= '1';
+ setstate <= "01";
+ setbriefext <= '1';
+ next_micro_state <= st_AnXn3;
+ WHEN st_AnXn3 =>
+ setstate <= "11";
+ setdisp <= '1'; --brief
+ setdispbrief <= '1';
+ next_micro_state <= nop;
+
+ WHEN bra1 => --bra
+ IF condition='1' THEN
+ TG68_PC_br8 <= '1'; --pc+0000
+ setstate <= "01";
+ next_micro_state <= bra2;
+ END IF;
+ WHEN bra2 => --bra
+ TG68_PC_brw <= '1';
+
+ WHEN bsr1 => --bsr
+ set_TG68_PC_dec <= '1'; --in 2 Takten -2
+ setstate <= "01";
+ next_micro_state <= bsr2;
+ WHEN bsr2 => --bsr
+ IF TG68_PC_dec(0)='1' THEN
+ TG68_PC_brw <= '1';
+ ELSE
+ TG68_PC_br8 <= '1';
+ END IF;
+ writePC <= '1';
+ setstate <= "11";
+ next_micro_state <= nop;
+
+ WHEN dbcc1 => --dbcc
+ TG68_PC_nop <= '1';
+ setstate <= "01";
+ next_micro_state <= dbcc2;
+ WHEN dbcc2 => --dbcc
+ TG68_PC_brw <= '1';
+
+ WHEN movem => --movem
+ set_movem_busy <='1';
+ setstate <= "10";
+
+ WHEN andi => --andi
+ IF opcode(5 downto 4)/="00" THEN
+ ea_build <= '1';
+ setnextpass <= '1';
+ END IF;
+
+ WHEN op_AxAy => -- op -(Ax),-(Ay)
+ presub <= '1';
+ dest_hbits <= '1';
+ dest_areg <= '1';
+ set_mem_addsub <= '1';
+ setstate <= "10";
+
+ WHEN cmpm => -- cmpm (Ay)+,(Ax)+
+ postadd <= '1';
+ dest_hbits <= '1';
+ dest_areg <= '1';
+ set_mem_rega <= '1';
+ setstate <= "10";
+
+ WHEN link => -- link
+ setstate <="11";
+ save_memaddr <= '1';
+ regwrena <= '1';
+
+ WHEN int1 => -- interrupt
+ presub <= '1';
+ setstackaddr <='1';
+ set_mem_addsub <= '1';
+ setstate <= "11";
+ datatype <= "10";
+ next_micro_state <= int2;
+ WHEN int2 => -- interrupt
+ presub <= '1';
+ setstackaddr <='1';
+ set_mem_addsub <= '1';
+ setstate <= "11";
+ datatype <= "01";
+ writeSR <= '1';
+ next_micro_state <= int3;
+ WHEN int3 => -- interrupt
+ set_vectoraddr <= '1';
+ datatype <= "10";
+ set_directPC <= '1';
+ setstate <= "10";
+ next_micro_state <= int4;
+ WHEN int4 => -- interrupt
+ datatype <= "10";
+
+ WHEN rte => -- RTE
+ datatype <= "10";
+ setstate <= "10";
+ postadd <= '1';
+ setstackaddr <= '1';
+ set_mem_rega <= '1';
+ set_directPC <= '1';
+ next_micro_state <= nop;
+
+ WHEN trap1 => -- TRAP
+ presub <= '1';
+ setstackaddr <='1';
+ set_mem_addsub <= '1';
+ setstate <= "11";
+ datatype <= "01";
+ writeSR <= '1';
+ next_micro_state <= trap2;
+ WHEN trap2 => -- TRAP
+ set_vectoraddr <= '1';
+ datatype <= "10";
+ set_directPC <= '1';
+-- longreaddirect <= '1';
+ setstate <= "10";
+ next_micro_state <= trap3;
+ WHEN trap3 => -- TRAP
+ datatype <= "10";
+
+ WHEN movep1 => -- MOVEP d(An)
+ setstate <= "01";
+ IF opcode(6)='1' THEN
+ set_movepl <= '1';
+ END IF;
+ next_micro_state <= movep2;
+ WHEN movep2 =>
+ setdisp <= '1';
+ IF opcode(7)='0' THEN
+ setstate <= "10";
+ ELSE
+ setstate <= "11";
+ wait_mem_byte <= '1';
+ END IF;
+ next_micro_state <= movep3;
+ WHEN movep3 =>
+ IF opcode(6)='1' THEN
+ set_movepw <= '1';
+ next_micro_state <= movep4;
+ END IF;
+ IF opcode(7)='0' THEN
+ setstate <= "10";
+ ELSE
+ setstate <= "11";
+ END IF;
+ WHEN movep4 =>
+ IF opcode(7)='0' THEN
+ setstate <= "10";
+ ELSE
+ wait_mem_byte <= '1';
+ setstate <= "11";
+ END IF;
+ next_micro_state <= movep5;
+ WHEN movep5 =>
+ IF opcode(7)='0' THEN
+ setstate <= "10";
+ ELSE
+ setstate <= "11";
+ END IF;
+
+ WHEN init1 => -- init SP
+ longreaddirect <= '1';
+ next_micro_state <= init2;
+ WHEN init2 => -- init PC
+ get_ea_now <='1'; --\
+ ea_only <= '1'; --- OP1in <= memaddr_in
+ setaddrlong <= '1'; -- memaddr_in <= data_read
+ regwrena <= '1';
+ setstackaddr <='1'; -- dest_addr <= SP
+ set_directPC <= '1';
+ longreaddirect <= '1';
+ next_micro_state <= nop;
+
+ WHEN mul1 => -- mulu
+ set_exec_MULU <= '1';
+ setstate <="01";
+ next_micro_state <= mul2;
+ WHEN mul2 => -- mulu
+ set_exec_MULU <= '1';
+ setstate <="01";
+ next_micro_state <= mul3;
+ WHEN mul3 => -- mulu
+ set_exec_MULU <= '1';
+ setstate <="01";
+ next_micro_state <= mul4;
+ WHEN mul4 => -- mulu
+ set_exec_MULU <= '1';
+ setstate <="01";
+ next_micro_state <= mul5;
+ WHEN mul5 => -- mulu
+ set_exec_MULU <= '1';
+ setstate <="01";
+ next_micro_state <= mul6;
+ WHEN mul6 => -- mulu
+ set_exec_MULU <= '1';
+ setstate <="01";
+ next_micro_state <= mul7;
+ WHEN mul7 => -- mulu
+ set_exec_MULU <= '1';
+ setstate <="01";
+ next_micro_state <= mul8;
+ WHEN mul8 => -- mulu
+ set_exec_MULU <= '1';
+ setstate <="01";
+ next_micro_state <= mul9;
+ WHEN mul9 => -- mulu
+ set_exec_MULU <= '1';
+ setstate <="01";
+ next_micro_state <= mul10;
+ WHEN mul10 => -- mulu
+ set_exec_MULU <= '1';
+ setstate <="01";
+ next_micro_state <= mul11;
+ WHEN mul11 => -- mulu
+ set_exec_MULU <= '1';
+ setstate <="01";
+ next_micro_state <= mul12;
+ WHEN mul12 => -- mulu
+ set_exec_MULU <= '1';
+ setstate <="01";
+ next_micro_state <= mul13;
+ WHEN mul13 => -- mulu
+ set_exec_MULU <= '1';
+ setstate <="01";
+ next_micro_state <= mul14;
+ WHEN mul14 => -- mulu
+ set_exec_MULU <= '1';
+ setstate <="01";
+ next_micro_state <= mul15;
+ WHEN mul15 => -- mulu
+ set_exec_MULU <= '1';
+
+ WHEN div1 => -- divu
+ IF OP2out(15 downto 0)=x"0000" THEN --div zero
+ set_Z_error <= '1';
+ ELSE
+ set_exec_DIVU <= '1';
+ next_micro_state <= div2;
+ END IF;
+ setstate <="01";
+ WHEN div2 => -- divu
+ set_exec_DIVU <= '1';
+ setstate <="01";
+ next_micro_state <= div3;
+ WHEN div3 => -- divu
+ set_exec_DIVU <= '1';
+ setstate <="01";
+ next_micro_state <= div4;
+ WHEN div4 => -- divu
+ set_exec_DIVU <= '1';
+ setstate <="01";
+ next_micro_state <= div5;
+ WHEN div5 => -- divu
+ set_exec_DIVU <= '1';
+ setstate <="01";
+ next_micro_state <= div6;
+ WHEN div6 => -- divu
+ set_exec_DIVU <= '1';
+ setstate <="01";
+ next_micro_state <= div7;
+ WHEN div7 => -- divu
+ set_exec_DIVU <= '1';
+ setstate <="01";
+ next_micro_state <= div8;
+ WHEN div8 => -- divu
+ set_exec_DIVU <= '1';
+ setstate <="01";
+ next_micro_state <= div9;
+ WHEN div9 => -- divu
+ set_exec_DIVU <= '1';
+ setstate <="01";
+ next_micro_state <= div10;
+ WHEN div10 => -- divu
+ set_exec_DIVU <= '1';
+ setstate <="01";
+ next_micro_state <= div11;
+ WHEN div11 => -- divu
+ set_exec_DIVU <= '1';
+ setstate <="01";
+ next_micro_state <= div12;
+ WHEN div12 => -- divu
+ set_exec_DIVU <= '1';
+ setstate <="01";
+ next_micro_state <= div13;
+ WHEN div13 => -- divu
+ set_exec_DIVU <= '1';
+ setstate <="01";
+ next_micro_state <= div14;
+ WHEN div14 => -- divu
+ set_exec_DIVU <= '1';
+ setstate <="01";
+ next_micro_state <= div15;
+ WHEN div15 => -- divu
+ set_exec_DIVU <= '1';
+
+ WHEN OTHERS => null;
+ END CASE;
+ END PROCESS;
+
+-----------------------------------------------------------------------------
+-- Conditions
+-----------------------------------------------------------------------------
+PROCESS (opcode, Flags)
+ BEGIN
+ CASE opcode(11 downto 8) IS
+ WHEN X"0" => condition <= '1';
+ WHEN X"1" => condition <= '0';
+ WHEN X"2" => condition <= NOT Flags(0) AND NOT Flags(2);
+ WHEN X"3" => condition <= Flags(0) OR Flags(2);
+ WHEN X"4" => condition <= NOT Flags(0);
+ WHEN X"5" => condition <= Flags(0);
+ WHEN X"6" => condition <= NOT Flags(2);
+ WHEN X"7" => condition <= Flags(2);
+ WHEN X"8" => condition <= NOT Flags(1);
+ WHEN X"9" => condition <= Flags(1);
+ WHEN X"a" => condition <= NOT Flags(3);
+ WHEN X"b" => condition <= Flags(3);
+ WHEN X"c" => condition <= (Flags(3) AND Flags(1)) OR (NOT Flags(3) AND NOT Flags(1));
+ WHEN X"d" => condition <= (Flags(3) AND NOT Flags(1)) OR (NOT Flags(3) AND Flags(1));
+ WHEN X"e" => condition <= (Flags(3) AND Flags(1) AND NOT Flags(2)) OR (NOT Flags(3) AND NOT Flags(1) AND NOT Flags(2));
+ WHEN X"f" => condition <= (Flags(3) AND NOT Flags(1)) OR (NOT Flags(3) AND Flags(1)) OR Flags(2);
+ WHEN OTHERS => null;
+ END CASE;
+ END PROCESS;
+
+-----------------------------------------------------------------------------
+-- Bits
+-----------------------------------------------------------------------------
+PROCESS (opcode, OP1out, OP2out, one_bit_in, one_bit_out, bit_Number, bit_number_reg)
+ BEGIN
+ CASE opcode(7 downto 6) IS
+ WHEN "00" => --btst
+ one_bit_out <= one_bit_in;
+ WHEN "01" => --bchg
+ one_bit_out <= NOT one_bit_in;
+ WHEN "10" => --bclr
+ one_bit_out <= '0';
+ WHEN "11" => --bset
+ one_bit_out <= '1';
+ WHEN OTHERS => null;
+ END CASE;
+
+ IF opcode(8)='0' THEN
+ IF opcode(5 downto 4)="00" THEN
+ bit_number <= bit_number_reg(4 downto 0);
+ ELSE
+ bit_number <= "00"&bit_number_reg(2 downto 0);
+ END IF;
+ ELSE
+ IF opcode(5 downto 4)="00" THEN
+ bit_number <= OP2out(4 downto 0);
+ ELSE
+ bit_number <= "00"&OP2out(2 downto 0);
+ END IF;
+ END IF;
+
+ bits_out <= OP1out;
+ CASE bit_Number IS
+ WHEN "00000" => one_bit_in <= OP1out(0);
+ bits_out(0) <= one_bit_out;
+ WHEN "00001" => one_bit_in <= OP1out(1);
+ bits_out(1) <= one_bit_out;
+ WHEN "00010" => one_bit_in <= OP1out(2);
+ bits_out(2) <= one_bit_out;
+ WHEN "00011" => one_bit_in <= OP1out(3);
+ bits_out(3) <= one_bit_out;
+ WHEN "00100" => one_bit_in <= OP1out(4);
+ bits_out(4) <= one_bit_out;
+ WHEN "00101" => one_bit_in <= OP1out(5);
+ bits_out(5) <= one_bit_out;
+ WHEN "00110" => one_bit_in <= OP1out(6);
+ bits_out(6) <= one_bit_out;
+ WHEN "00111" => one_bit_in <= OP1out(7);
+ bits_out(7) <= one_bit_out;
+ WHEN "01000" => one_bit_in <= OP1out(8);
+ bits_out(8) <= one_bit_out;
+ WHEN "01001" => one_bit_in <= OP1out(9);
+ bits_out(9) <= one_bit_out;
+ WHEN "01010" => one_bit_in <= OP1out(10);
+ bits_out(10) <= one_bit_out;
+ WHEN "01011" => one_bit_in <= OP1out(11);
+ bits_out(11) <= one_bit_out;
+ WHEN "01100" => one_bit_in <= OP1out(12);
+ bits_out(12) <= one_bit_out;
+ WHEN "01101" => one_bit_in <= OP1out(13);
+ bits_out(13) <= one_bit_out;
+ WHEN "01110" => one_bit_in <= OP1out(14);
+ bits_out(14) <= one_bit_out;
+ WHEN "01111" => one_bit_in <= OP1out(15);
+ bits_out(15) <= one_bit_out;
+ WHEN "10000" => one_bit_in <= OP1out(16);
+ bits_out(16) <= one_bit_out;
+ WHEN "10001" => one_bit_in <= OP1out(17);
+ bits_out(17) <= one_bit_out;
+ WHEN "10010" => one_bit_in <= OP1out(18);
+ bits_out(18) <= one_bit_out;
+ WHEN "10011" => one_bit_in <= OP1out(19);
+ bits_out(19) <= one_bit_out;
+ WHEN "10100" => one_bit_in <= OP1out(20);
+ bits_out(20) <= one_bit_out;
+ WHEN "10101" => one_bit_in <= OP1out(21);
+ bits_out(21) <= one_bit_out;
+ WHEN "10110" => one_bit_in <= OP1out(22);
+ bits_out(22) <= one_bit_out;
+ WHEN "10111" => one_bit_in <= OP1out(23);
+ bits_out(23) <= one_bit_out;
+ WHEN "11000" => one_bit_in <= OP1out(24);
+ bits_out(24) <= one_bit_out;
+ WHEN "11001" => one_bit_in <= OP1out(25);
+ bits_out(25) <= one_bit_out;
+ WHEN "11010" => one_bit_in <= OP1out(26);
+ bits_out(26) <= one_bit_out;
+ WHEN "11011" => one_bit_in <= OP1out(27);
+ bits_out(27) <= one_bit_out;
+ WHEN "11100" => one_bit_in <= OP1out(28);
+ bits_out(28) <= one_bit_out;
+ WHEN "11101" => one_bit_in <= OP1out(29);
+ bits_out(29) <= one_bit_out;
+ WHEN "11110" => one_bit_in <= OP1out(30);
+ bits_out(30) <= one_bit_out;
+ WHEN "11111" => one_bit_in <= OP1out(31);
+ bits_out(31) <= one_bit_out;
+ WHEN OTHERS => null;
+ END CASE;
+ END PROCESS;
+
+-----------------------------------------------------------------------------
+-- Rotation
+-----------------------------------------------------------------------------
+PROCESS (opcode, OP1out, Flags, rot_bits, rot_msb, rot_lsb, rot_rot, rot_nop)
+ BEGIN
+ CASE opcode(7 downto 6) IS
+ WHEN "00" => --Byte
+ rot_rot <= OP1out(7);
+ WHEN "01"|"11" => --Word
+ rot_rot <= OP1out(15);
+ WHEN "10" => --Long
+ rot_rot <= OP1out(31);
+ WHEN OTHERS => null;
+ END CASE;
+
+ CASE rot_bits IS
+ WHEN "00" => --ASL, ASR
+ rot_lsb <= '0';
+ rot_msb <= rot_rot;
+ WHEN "01" => --LSL, LSR
+ rot_lsb <= '0';
+ rot_msb <= '0';
+ WHEN "10" => --ROXL, ROXR
+ rot_lsb <= Flags(4);
+ rot_msb <= Flags(4);
+ WHEN "11" => --ROL, ROR
+ rot_lsb <= rot_rot;
+ rot_msb <= OP1out(0);
+ WHEN OTHERS => null;
+ END CASE;
+
+ IF rot_nop='1' THEN
+ rot_out <= OP1out;
+ rot_XC <= Flags(0);
+ ELSE
+ IF opcode(8)='1' THEN --left
+ rot_out <= OP1out(30 downto 0)&rot_lsb;
+ rot_XC <= rot_rot;
+ ELSE --right
+ rot_XC <= OP1out(0);
+ rot_out <= rot_msb&OP1out(31 downto 1);
+ CASE opcode(7 downto 6) IS
+ WHEN "00" => --Byte
+ rot_out(7) <= rot_msb;
+ WHEN "01"|"11" => --Word
+ rot_out(15) <= rot_msb;
+ WHEN OTHERS =>
+ END CASE;
+ END IF;
+ END IF;
+ END PROCESS;
+
+-----------------------------------------------------------------------------
+-- MULU/MULS
+-----------------------------------------------------------------------------
+PROCESS (clk, opcode, OP2out, muls_msb, mulu_reg, OP1sign, sign2)
+ BEGIN
+ IF rising_edge(clk) THEN
+ IF clkena='1' THEN
+ IF decodeOPC='1' THEN
+ IF opcode(8)='1' AND reg_QB(15)='1' THEN --MULS Neg faktor
+ OP1sign <= '1';
+ mulu_reg <= "0000000000000000"&(0-reg_QB(15 downto 0));
+ ELSE
+ OP1sign <= '0';
+ mulu_reg <= "0000000000000000"®_QB(15 downto 0);
+ END IF;
+ ELSIF exec_MULU='1' THEN
+ mulu_reg <= dummy_mulu;
+ END IF;
+ END IF;
+ END IF;
+
+ IF (opcode(8)='1' AND OP2out(15)='1') OR OP1sign='1' THEN
+ muls_msb <= mulu_reg(31);
+ ELSE
+ muls_msb <= '0';
+ END IF;
+
+ IF opcode(8)='1' AND OP2out(15)='1' THEN
+ sign2 <= '1';
+ ELSE
+ sign2 <= '0';
+ END IF;
+
+ IF mulu_reg(0)='1' THEN
+ IF OP1sign='1' THEN
+ dummy_mulu <= (muls_msb&mulu_reg(31 downto 16))-(sign2&OP2out(15 downto 0))& mulu_reg(15 downto 1);
+ ELSE
+ dummy_mulu <= (muls_msb&mulu_reg(31 downto 16))+(sign2&OP2out(15 downto 0))& mulu_reg(15 downto 1);
+ END IF;
+ ELSE
+ dummy_mulu <= muls_msb&mulu_reg(31 downto 1);
+ END IF;
+ END PROCESS;
+
+-----------------------------------------------------------------------------
+-- DIVU
+-----------------------------------------------------------------------------
+PROCESS (clk, execOPC, opcode, OP1out, OP2out, div_reg, dummy_div_sub, div_quot, div_sign, dummy_div_over, dummy_div)
+ BEGIN
+ set_V_Flag <= '0';
+
+ IF rising_edge(clk) THEN
+ IF clkena='1' THEN
+ IF decodeOPC='1' THEN
+ IF opcode(8)='1' AND reg_QB(31)='1' THEN -- Neg divisor
+ div_sign <= '1';
+ div_reg <= 0-reg_QB;
+ ELSE
+ div_sign <= '0';
+ div_reg <= reg_QB;
+ END IF;
+ ELSIF exec_DIVU='1' THEN
+ div_reg <= div_quot;
+ END IF;
+ END IF;
+ END IF;
+
+ dummy_div_over <= ('0'&OP1out(31 downto 16))-('0'&OP2out(15 downto 0));
+
+ IF opcode(8)='1' AND OP2out(15) ='1' THEN
+ dummy_div_sub <= (div_reg(31 downto 15))+('1'&OP2out(15 downto 0));
+ ELSE
+ dummy_div_sub <= (div_reg(31 downto 15))-('0'&OP2out(15 downto 0));
+ END IF;
+
+ IF (dummy_div_sub(16))='1' THEN
+ div_quot(31 downto 16) <= div_reg(30 downto 15);
+ ELSE
+ div_quot(31 downto 16) <= dummy_div_sub(15 downto 0);
+ END IF;
+
+ div_quot(15 downto 0) <= div_reg(14 downto 0)&NOT dummy_div_sub(16);
+
+ IF execOPC='1' AND opcode(8)='1' AND (OP2out(15) XOR div_sign)='1' THEN
+ dummy_div(15 downto 0) <= 0-div_quot(15 downto 0);
+ ELSE
+ dummy_div(15 downto 0) <= div_quot(15 downto 0);
+ END IF;
+
+ IF div_sign='1' THEN
+ dummy_div(31 downto 16) <= 0-div_quot(31 downto 16);
+ ELSE
+ dummy_div(31 downto 16) <= div_quot(31 downto 16);
+ END IF;
+
+ IF (opcode(8)='1' AND (OP2out(15) XOR div_sign XOR dummy_div(15))='1' AND dummy_div(15 downto 0)/=X"0000") --Overflow DIVS
+ OR (opcode(8)='0' AND dummy_div_over(16)='0') THEN --Overflow DIVU
+ set_V_Flag <= '1';
+ END IF;
+ END PROCESS;
+
+-----------------------------------------------------------------------------
+-- Movem
+-----------------------------------------------------------------------------
+PROCESS (reset, clk, movem_mask, movem_muxa ,movem_muxb, movem_muxc)
+ BEGIN
+ IF movem_mask(7 downto 0)="00000000" THEN
+ movem_muxa <= movem_mask(15 downto 8);
+ movem_regaddr(3) <= '1';
+ ELSE
+ movem_muxa <= movem_mask(7 downto 0);
+ movem_regaddr(3) <= '0';
+ END IF;
+ IF movem_muxa(3 downto 0)="0000" THEN
+ movem_muxb <= movem_muxa(7 downto 4);
+ movem_regaddr(2) <= '1';
+ ELSE
+ movem_muxb <= movem_muxa(3 downto 0);
+ movem_regaddr(2) <= '0';
+ END IF;
+ IF movem_muxb(1 downto 0)="00" THEN
+ movem_muxc <= movem_muxb(3 downto 2);
+ movem_regaddr(1) <= '1';
+ ELSE
+ movem_muxc <= movem_muxb(1 downto 0);
+ movem_regaddr(1) <= '0';
+ END IF;
+ IF movem_muxc(0)='0' THEN
+ movem_regaddr(0) <= '1';
+ ELSE
+ movem_regaddr(0) <= '0';
+ END IF;
+
+ movem_bits <= ("0000"&movem_mask(0))+("0000"&movem_mask(1))+("0000"&movem_mask(2))+("0000"&movem_mask(3))+
+ ("0000"&movem_mask(4))+("0000"&movem_mask(5))+("0000"&movem_mask(6))+("0000"&movem_mask(7))+
+ ("0000"&movem_mask(8))+("0000"&movem_mask(9))+("0000"&movem_mask(10))+("0000"&movem_mask(11))+
+ ("0000"&movem_mask(12))+("0000"&movem_mask(13))+("0000"&movem_mask(14))+("0000"&movem_mask(15));
+
+ IF reset = '0' THEN
+ movem_busy <= '0';
+ movem_addr <= '0';
+ maskzero <= '0';
+ ELSIF rising_edge(clk) THEN
+ IF clkena_in='1' AND get_movem_mask='1' THEN
+ movem_mask <= data_read(15 downto 0);
+ END IF;
+ IF clkena_in='1' AND test_maskzero='1' THEN
+ IF movem_mask=X"0000" THEN
+ maskzero <= '1';
+ END IF;
+ END IF;
+ IF clkena_in='1' AND endOPC='1' THEN
+ maskzero <= '0';
+ END IF;
+ IF clkena='1' THEN
+ IF set_movem_busy='1' THEN
+ IF movem_bits(4 downto 1) /= "0000" OR opcode(10)='0' THEN
+ movem_busy <= '1';
+ END IF;
+ movem_addr <= '1';
+ END IF;
+ IF movem_addr='1' THEN
+ CASE movem_regaddr IS
+ WHEN "0000" => movem_mask(0) <= '0';
+ WHEN "0001" => movem_mask(1) <= '0';
+ WHEN "0010" => movem_mask(2) <= '0';
+ WHEN "0011" => movem_mask(3) <= '0';
+ WHEN "0100" => movem_mask(4) <= '0';
+ WHEN "0101" => movem_mask(5) <= '0';
+ WHEN "0110" => movem_mask(6) <= '0';
+ WHEN "0111" => movem_mask(7) <= '0';
+ WHEN "1000" => movem_mask(8) <= '0';
+ WHEN "1001" => movem_mask(9) <= '0';
+ WHEN "1010" => movem_mask(10) <= '0';
+ WHEN "1011" => movem_mask(11) <= '0';
+ WHEN "1100" => movem_mask(12) <= '0';
+ WHEN "1101" => movem_mask(13) <= '0';
+ WHEN "1110" => movem_mask(14) <= '0';
+ WHEN "1111" => movem_mask(15) <= '0';
+ WHEN OTHERS => null;
+ END CASE;
+ IF opcode(10)='1' THEN
+ IF movem_bits="00010" OR movem_bits="00001" OR movem_bits="00000" THEN
+ movem_busy <= '0';
+ END IF;
+ END IF;
+ IF movem_bits="00001" OR movem_bits="00000" THEN
+ movem_busy <= '0';
+ movem_addr <= '0';
+ END IF;
+ END IF;
+ END IF;
+ END IF;
+ END PROCESS;
+END;
diff --git a/common/CPU/68000/tg68/gpl.txt b/common/CPU/68000/tg68/gpl.txt
new file mode 100644
index 00000000..94a9ed02
--- /dev/null
+++ b/common/CPU/68000/tg68/gpl.txt
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ 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 .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/common/CPU/68000/tg68/lgpl.txt b/common/CPU/68000/tg68/lgpl.txt
new file mode 100644
index 00000000..fc8a5de7
--- /dev/null
+++ b/common/CPU/68000/tg68/lgpl.txt
@@ -0,0 +1,165 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/common/CPU/68000/tg68k/TG68K.vhd b/common/CPU/68000/tg68k/TG68K.vhd
new file mode 100644
index 00000000..98968f25
--- /dev/null
+++ b/common/CPU/68000/tg68k/TG68K.vhd
@@ -0,0 +1,417 @@
+------------------------------------------------------------------------------
+------------------------------------------------------------------------------
+-- --
+-- Copyright (c) 2009-2011 Tobias Gubener --
+-- Subdesign fAMpIGA by TobiFlex --
+-- --
+-- This is the TOP-Level for TG68KdotC_Kernel to generate 68K Bus signals --
+-- --
+-- This source file 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 source file 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 . --
+-- --
+------------------------------------------------------------------------------
+------------------------------------------------------------------------------
+
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+
+entity TG68K is
+ port(
+ clk : in std_logic;
+ reset : in std_logic;
+ clkena_in : in std_logic:='1';
+ IPL : in std_logic_vector(2 downto 0):="111";
+ dtack : in std_logic;
+ vpa : in std_logic:='1';
+ ein : in std_logic:='1';
+ addr : buffer std_logic_vector(31 downto 0);
+ data_read : in std_logic_vector(15 downto 0);
+ data_write : out std_logic_vector(15 downto 0);
+ as : out std_logic;
+ uds : out std_logic;
+ lds : out std_logic;
+ rw : out std_logic;
+ e : out std_logic;
+ vma : buffer std_logic:='1';
+ wrd : out std_logic;
+ ena7RDreg : in std_logic:='1';
+ ena7WRreg : in std_logic:='1';
+ enaWRreg : in std_logic:='1';
+
+ fromram : in std_logic_vector(15 downto 0);
+ ramready : in std_logic:='0';
+ cpu : in std_logic_vector(1 downto 0);
+ memcfg : in std_logic_vector(5 downto 0);
+ ramaddr : out std_logic_vector(31 downto 0);
+ cpustate : out std_logic_vector(5 downto 0);
+ nResetOut : out std_logic;
+ skipFetch : buffer std_logic;
+ cpuDMA : buffer std_logic;
+ ramlds : out std_logic;
+ ramuds : out std_logic
+ );
+end TG68K;
+
+ARCHITECTURE logic OF TG68K IS
+
+
+COMPONENT TG68KdotC_Kernel
+ generic(
+ SR_Read : integer:= 2; --0=>user, 1=>privileged, 2=>switchable with CPU(0)
+ VBR_Stackframe : integer:= 2; --0=>no, 1=>yes/extended, 2=>switchable with CPU(0)
+ extAddr_Mode : integer:= 2; --0=>no, 1=>yes, 2=>switchable with CPU(1)
+ MUL_Mode : integer := 2; --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no MUL,
+ DIV_Mode : integer := 2; --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no DIV,
+ BitField : integer := 2 --0=>no, 1=>yes, 2=>switchable with CPU(1)
+ );
+ port(clk : in std_logic;
+ nReset : in std_logic; --low active
+ clkena_in : in std_logic:='1';
+ data_in : in std_logic_vector(15 downto 0);
+ IPL : in std_logic_vector(2 downto 0):="111";
+ IPL_autovector : in std_logic:='0';
+ CPU : in std_logic_vector(1 downto 0):="00"; -- 00->68000 01->68010 11->68020(only same parts - yet)
+ addr : buffer std_logic_vector(31 downto 0);
+ data_write : out std_logic_vector(15 downto 0);
+ nWr : out std_logic;
+ nUDS, nLDS : out std_logic;
+ nResetOut : out std_logic;
+ FC : out std_logic_vector(2 downto 0);
+-- for debug
+ busstate : out std_logic_vector(1 downto 0); -- 00-> fetch code 10->read data 11->write data 01->no memaccess
+ skipFetch : out std_logic;
+ regin : buffer std_logic_vector(31 downto 0)
+ );
+ END COMPONENT;
+
+
+ SIGNAL cpuaddr : std_logic_vector(31 downto 0);
+ SIGNAL t_addr : std_logic_vector(31 downto 0);
+-- SIGNAL data_write : std_logic_vector(15 downto 0);
+-- SIGNAL t_data : std_logic_vector(15 downto 0);
+ SIGNAL r_data : std_logic_vector(15 downto 0);
+ SIGNAL cpuIPL : std_logic_vector(2 downto 0);
+ SIGNAL addr_akt_s : std_logic;
+ SIGNAL addr_akt_e : std_logic;
+ SIGNAL data_akt_s : std_logic;
+ SIGNAL data_akt_e : std_logic;
+ SIGNAL as_s : std_logic;
+ SIGNAL as_e : std_logic;
+ SIGNAL uds_s : std_logic;
+ SIGNAL uds_e : std_logic;
+ SIGNAL lds_s : std_logic;
+ SIGNAL lds_e : std_logic;
+ SIGNAL rw_s : std_logic;
+ SIGNAL rw_e : std_logic;
+ SIGNAL vpad : std_logic;
+ SIGNAL waitm : std_logic;
+ SIGNAL clkena_e : std_logic;
+ SIGNAL S_state : std_logic_vector(1 downto 0);
+ SIGNAL S_stated : std_logic_vector(1 downto 0);
+ SIGNAL decode : std_logic;
+ SIGNAL wr : std_logic;
+ SIGNAL uds_in : std_logic;
+ SIGNAL lds_in : std_logic;
+ SIGNAL state : std_logic_vector(1 downto 0);
+ SIGNAL clkena : std_logic;
+-- SIGNAL n_clk : std_logic;
+ SIGNAL vmaena : std_logic;
+ SIGNAL vmaenad : std_logic;
+ SIGNAL state_ena : std_logic;
+ SIGNAL sync_state3 : std_logic;
+ SIGNAL eind : std_logic;
+ SIGNAL eindd : std_logic;
+ SIGNAL sel_autoconfig: std_logic;
+ SIGNAL autoconfig_out: std_logic;
+ SIGNAL autoconfig_data: std_logic_vector(3 downto 0);
+ SIGNAL sel_fast: std_logic;
+ SIGNAL slower : std_logic_vector(3 downto 0);
+
+
+ type sync_states is (sync0, sync1, sync2, sync3, sync4, sync5, sync6, sync7, sync8, sync9);
+ signal sync_state : sync_states;
+
+ SIGNAL datatg68 : std_logic_vector(15 downto 0);
+ SIGNAL ramcs : std_logic;
+
+BEGIN
+-- n_clk <= NOT clk;
+-- wrd <= data_akt_e OR data_akt_s;
+ wrd <= wr;
+ addr <= cpuaddr;-- WHEN addr_akt_e='1' ELSE t_addr WHEN addr_akt_s='1' ELSE "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
+-- data <= data_write WHEN data_akt_e='1' ELSE t_data WHEN data_akt_s='1' ELSE "ZZZZZZZZZZZZZZZZ";
+-- datatg68 <= fromram WHEN sel_fast='1' ELSE r_data;
+ datatg68 <= fromram WHEN sel_fast='1' ELSE r_data WHEN sel_autoconfig='0' ELSE autoconfig_data&r_data(11 downto 0);
+-- toram <= data_write;
+
+ sel_autoconfig <= '1' when cpuaddr(23 downto 19)="11101" AND autoconfig_out='1' ELSE '0'; --$E80000 - $EFFFFF
+ sel_fast <= '1' when state/="01" AND (cpuaddr(23 downto 21)="001" OR cpuaddr(23 downto 21)="010" OR cpuaddr(23 downto 21)="011" OR cpuaddr(23 downto 21)="100") ELSE '0'; --$200000 - $9FFFFF
+-- sel_fast <= '1' when cpuaddr(23 downto 21)="001" OR cpuaddr(23 downto 21)="010" ELSE '0'; --$200000 - $5FFFFF
+-- sel_fast <= '1' when cpuaddr(23 downto 19)="11111" ELSE '0'; --$F800000;
+-- sel_fast <= '0'; --$200000 - $9FFFFF
+-- sel_fast <= '1' when cpuaddr(24)='1' AND state/="01" ELSE '0'; --$1000000 - $1FFFFFF
+ ramcs <= NOT sel_fast;-- OR (state(0) AND NOT state(1));
+-- cpuDMA <= NOT ramcs;
+ cpuDMA <= sel_fast;
+ cpustate <= clkena&slower(1 downto 0)&ramcs&state;
+ ramlds <= lds_in;
+ ramuds <= uds_in;
+ ramaddr(23 downto 0) <= cpuaddr(23 downto 0);
+ ramaddr(24) <= sel_fast;
+ ramaddr(31 downto 25) <= cpuaddr(31 downto 25);
+
+
+pf68K_Kernel_inst: TG68KdotC_Kernel
+ generic map(
+ SR_Read => 2, --0=>user, 1=>privileged, 2=>switchable with CPU(0)
+ VBR_Stackframe => 2, --0=>no, 1=>yes/extended, 2=>switchable with CPU(0)
+ extAddr_Mode => 2, --0=>no, 1=>yes, 2=>switchable with CPU(1)
+ MUL_Mode => 2, --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no MUL,
+ DIV_Mode => 2 --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no DIV,
+ )
+ PORT MAP(
+ clk => clk, -- : in std_logic;
+ nReset => reset, -- : in std_logic:='1'; --low active
+ clkena_in => clkena, -- : in std_logic:='1';
+-- data_in => r_data, -- : in std_logic_vector(15 downto 0);
+-- data_in => data_read, -- : in std_logic_vector(15 downto 0);
+ data_in => datatg68, -- : in std_logic_vector(15 downto 0);
+ IPL => cpuIPL, -- : in std_logic_vector(2 downto 0):="111";
+ IPL_autovector => '1', -- : in std_logic:='0';
+ addr => cpuaddr, -- : buffer std_logic_vector(31 downto 0);
+ data_write => data_write, -- : out std_logic_vector(15 downto 0);
+ busstate => state, -- : buffer std_logic_vector(1 downto 0);
+ regin => open, -- : out std_logic_vector(31 downto 0);
+ nWr => wr, -- : out std_logic;
+ nUDS => uds_in,
+ nLDS => lds_in, -- : out std_logic;
+ nResetOut => nResetOut,
+ CPU => cpu,
+ skipFetch => skipFetch -- : out std_logic
+ );
+
+ PROCESS (clk)
+ BEGIN
+ autoconfig_data <= "1111";
+ IF memcfg(5 downto 4)/="00" THEN
+ CASE cpuaddr(6 downto 1) IS
+ WHEN "000000" => autoconfig_data <= "1110"; --normal card, add mem, no ROM
+ WHEN "000001" =>
+ CASE memcfg(5 downto 4) IS
+ WHEN "01" => autoconfig_data <= "0110"; --2MB
+ WHEN "10" => autoconfig_data <= "0111"; --4MB
+ WHEN OTHERS => autoconfig_data <= "0000"; --8MB
+ END CASE;
+ WHEN "001000" => autoconfig_data <= "1110"; --4626=icomp
+ WHEN "001001" => autoconfig_data <= "1101";
+ WHEN "001010" => autoconfig_data <= "1110";
+ WHEN "001011" => autoconfig_data <= "1101";
+ WHEN "010011" => autoconfig_data <= "1110"; --serial=1
+ WHEN OTHERS => null;
+ END CASE;
+ END IF;
+ IF rising_edge(clk) THEN
+ IF reset='0' THEN
+ autoconfig_out <= '1'; --autoconfig on
+ ELSIF enaWRreg='1' THEN
+ IF sel_autoconfig='1' AND state="11"AND uds_in='0' AND cpuaddr(6 downto 1)="100100" THEN
+ autoconfig_out <= '0'; --autoconfig off
+ END IF;
+ END IF;
+ END IF;
+ END PROCESS;
+
+ PROCESS (clk)
+ BEGIN
+ IF rising_edge(clk) THEN
+ IF reset='0' THEN
+ vmaena <= '0';
+ vmaenad <= '0';
+ sync_state3 <= '0';
+ ELSIF ena7RDreg='1' THEN
+ vmaena <= '0';
+ sync_state3 <= '0';
+ IF state/="01" OR state_ena='1' THEN
+ vmaenad <= vmaena;
+ END IF;
+ IF sync_state=sync5 THEN
+ e <= '1';
+ END IF;
+ IF sync_state=sync3 THEN
+ sync_state3 <= '1';
+ END IF;
+ IF sync_state=sync9 THEN
+ e <= '0';
+ vmaena <= NOT vma;
+ END IF;
+ END IF;
+ END IF;
+ IF rising_edge(clk) THEN
+ S_stated <= S_state;
+ IF ena7WRreg='1' THEN
+ eind <= ein;
+ eindd <= eind;
+ CASE sync_state IS
+ WHEN sync0 => sync_state <= sync1;
+ WHEN sync1 => sync_state <= sync2;
+ WHEN sync2 => sync_state <= sync3;
+ WHEN sync3 => sync_state <= sync4;
+ vma <= vpa;
+ WHEN sync4 => sync_state <= sync5;
+ WHEN sync5 => sync_state <= sync6;
+ WHEN sync6 => sync_state <= sync7;
+ WHEN sync7 => sync_state <= sync8;
+ WHEN sync8 => sync_state <= sync9;
+ WHEN OTHERS => sync_state <= sync0;
+ vma <= '1';
+ END CASE;
+ IF eind='1' AND eindd='0' THEN
+ sync_state <= sync7;
+ END IF;
+ END IF;
+ END IF;
+ END PROCESS;
+
+
+ PROCESS (clk)
+ BEGIN
+ state_ena <= '0';
+ IF clkena_in='1' AND enaWRreg='1' AND (state="01" OR (ena7RDreg='1' AND clkena_e='1') OR ramready='1') THEN
+ clkena <= '1';
+ ELSE
+ clkena <= '0';
+ END IF;
+ IF state="01" THEN
+ state_ena <= '1';
+ END IF;
+ IF rising_edge(clk) THEN
+ IF clkena='1' THEN
+ slower <= "1000";
+ ELSE
+ slower(3 downto 0) <= enaWRreg&slower(3 downto 1);
+-- slower(0) <= NOT slower(3) AND NOT slower(2);
+ END IF;
+ END IF;
+ END PROCESS;
+
+PROCESS (clk, reset, state, as_s, as_e, rw_s, rw_e, uds_s, uds_e, lds_s, lds_e)
+ BEGIN
+ IF state="01" THEN
+ as <= '1';
+ rw <= '1';
+ uds <= '1';
+ lds <= '1';
+ ELSE
+ as <= (as_s AND as_e) OR sel_fast;
+ rw <= rw_s AND rw_e;
+ uds <= uds_s AND uds_e;
+ lds <= lds_s AND lds_e;
+ END IF;
+ IF reset='0' THEN
+ S_state <= "00";
+ as_s <= '1';
+ rw_s <= '1';
+ uds_s <= '1';
+ lds_s <= '1';
+ addr_akt_s <= '0';
+ data_akt_s <= '0';
+ ELSIF rising_edge(clk) THEN
+ IF ena7WRreg='1' THEN
+ as_s <= '1';
+ rw_s <= '1';
+ uds_s <= '1';
+ lds_s <= '1';
+ addr_akt_s <= '0';
+ data_akt_s <= '0';
+ CASE S_state IS
+ WHEN "00" => IF state/="01" AND sel_fast='0' THEN
+ uds_s <= uds_in;
+ lds_s <= lds_in;
+ S_state <= "01";
+ END IF;
+ WHEN "01" => as_s <= '0';
+ rw_s <= wr;
+ uds_s <= uds_in;
+ lds_s <= lds_in;
+ S_state <= "10";
+ t_addr <= cpuaddr;
+-- t_data <= data_write;
+ WHEN "10" =>
+ addr_akt_s <= '1';
+ data_akt_s <= NOT wr;
+ r_data <= data_read;
+ IF waitm='0' OR (vma='0' AND sync_state=sync9) THEN
+ S_state <= "11";
+ ELSE
+ as_s <= '0';
+ rw_s <= wr;
+ uds_s <= uds_in;
+ lds_s <= lds_in;
+ END IF;
+ WHEN "11" =>
+ S_state <= "00";
+ WHEN OTHERS => null;
+ END CASE;
+ END IF;
+ END IF;
+ IF reset='0' THEN
+ as_e <= '1';
+ rw_e <= '1';
+ uds_e <= '1';
+ lds_e <= '1';
+ clkena_e <= '0';
+ addr_akt_e <= '0';
+ data_akt_e <= '0';
+ ELSIF rising_edge(clk) THEN
+ IF ena7RDreg='1' THEN
+ as_e <= '1';
+ rw_e <= '1';
+ uds_e <= '1';
+ lds_e <= '1';
+ clkena_e <= '0';
+ addr_akt_e <= '0';
+ data_akt_e <= '0';
+ CASE S_state IS
+ WHEN "00" => addr_akt_e <= '1';
+ cpuIPL <= IPL;
+ IF sel_fast='0' THEN
+ IF state/="01" THEN
+ as_e <= '0';
+ END IF;
+ rw_e <= wr;
+ data_akt_e <= NOT wr;
+ IF wr='1' THEN
+ uds_e <= uds_in;
+ lds_e <= lds_in;
+ END IF;
+ END IF;
+ WHEN "01" => addr_akt_e <= '1';
+ data_akt_e <= NOT wr;
+ as_e <= '0';
+ rw_e <= wr;
+ uds_e <= uds_in;
+ lds_e <= lds_in;
+ WHEN "10" => rw_e <= wr;
+ addr_akt_e <= '1';
+ data_akt_e <= NOT wr;
+ cpuIPL <= IPL;
+ waitm <= dtack;
+ WHEN OTHERS => --null;
+ clkena_e <= '1';
+ END CASE;
+ END IF;
+ END IF;
+ END PROCESS;
+END;
\ No newline at end of file
diff --git a/common/CPU/68000/tg68k/TG68K_ALU.vhd b/common/CPU/68000/tg68k/TG68K_ALU.vhd
new file mode 100644
index 00000000..f34c3f1c
--- /dev/null
+++ b/common/CPU/68000/tg68k/TG68K_ALU.vhd
@@ -0,0 +1,918 @@
+------------------------------------------------------------------------------
+------------------------------------------------------------------------------
+-- --
+-- Copyright (c) 2009-2011 Tobias Gubener --
+-- Subdesign fAMpIGA by TobiFlex --
+-- --
+-- This source file 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 source file 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 . --
+-- --
+------------------------------------------------------------------------------
+------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use IEEE.numeric_std.all;
+use work.TG68K_Pack.all;
+
+entity TG68K_ALU is
+generic(
+ MUL_Mode : integer := 0; --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no MUL,
+ DIV_Mode : integer := 0 --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no DIV,
+ );
+ port(clk : in std_logic;
+ Reset : in std_logic;
+ clkena_lw : in std_logic:='1';
+ execOPC : in std_logic;
+ exe_condition : in std_logic;
+ exec_tas : in std_logic;
+ long_start : in std_logic;
+ movem_presub : in bit;
+ set_stop : in bit;
+ Z_error : in bit;
+ rot_bits : in std_logic_vector(1 downto 0);
+ exec : in bit_vector(lastOpcBit downto 0);
+ OP1out : in std_logic_vector(31 downto 0);
+ OP2out : in std_logic_vector(31 downto 0);
+ reg_QA : in std_logic_vector(31 downto 0);
+ reg_QB : in std_logic_vector(31 downto 0);
+ opcode : in std_logic_vector(15 downto 0);
+ datatype : in std_logic_vector(1 downto 0);
+ exe_opcode : in std_logic_vector(15 downto 0);
+ exe_datatype : in std_logic_vector(1 downto 0);
+ sndOPC : in std_logic_vector(15 downto 0);
+ last_data_read : in std_logic_vector(15 downto 0);
+ data_read : in std_logic_vector(15 downto 0);
+ FlagsSR : in std_logic_vector(7 downto 0);
+ micro_state : in micro_states;
+ bf_ext_in : in std_logic_vector(7 downto 0);
+ bf_ext_out : out std_logic_vector(7 downto 0);
+ bf_shift : in std_logic_vector(5 downto 0);
+ bf_width : in std_logic_vector(5 downto 0);
+ bf_loffset : in std_logic_vector(4 downto 0);
+
+ set_V_Flag : buffer bit;
+ Flags : buffer std_logic_vector(7 downto 0);
+ c_out : buffer std_logic_vector(2 downto 0);
+ addsub_q : buffer std_logic_vector(31 downto 0);
+ ALUout : out std_logic_vector(31 downto 0)
+ );
+end TG68K_ALU;
+
+architecture logic of TG68K_ALU is
+-----------------------------------------------------------------------------
+-----------------------------------------------------------------------------
+-- ALU and more
+-----------------------------------------------------------------------------
+-----------------------------------------------------------------------------
+ signal OP1in : std_logic_vector(31 downto 0);
+ signal addsub_a : std_logic_vector(31 downto 0);
+ signal addsub_b : std_logic_vector(31 downto 0);
+ signal notaddsub_b : std_logic_vector(33 downto 0);
+ signal add_result : std_logic_vector(33 downto 0);
+ signal addsub_ofl : std_logic_vector(2 downto 0);
+ signal opaddsub : bit;
+ signal c_in : std_logic_vector(3 downto 0);
+ signal flag_z : std_logic_vector(2 downto 0);
+ signal set_Flags : std_logic_vector(3 downto 0); --NZVC
+ signal CCRin : std_logic_vector(7 downto 0);
+
+ signal niba_l : std_logic_vector(5 downto 0);
+ signal niba_h : std_logic_vector(5 downto 0);
+ signal niba_lc : std_logic;
+ signal niba_hc : std_logic;
+ signal bcda_lc : std_logic;
+ signal bcda_hc : std_logic;
+ signal nibs_l : std_logic_vector(5 downto 0);
+ signal nibs_h : std_logic_vector(5 downto 0);
+ signal nibs_lc : std_logic;
+ signal nibs_hc : std_logic;
+
+ signal bcd_a : std_logic_vector(8 downto 0);
+ signal bcd_s : std_logic_vector(8 downto 0);
+ signal result_mulu : std_logic_vector(63 downto 0);
+ signal result_div : std_logic_vector(63 downto 0);
+ signal set_mV_Flag : std_logic;
+ signal V_Flag : bit;
+
+ signal rot_rot : std_logic;
+ signal rot_lsb : std_logic;
+ signal rot_msb : std_logic;
+ signal rot_X : std_logic;
+ signal rot_C : std_logic;
+ signal rot_out : std_logic_vector(31 downto 0);
+ signal asl_VFlag : std_logic;
+ signal bit_bits : std_logic_vector(1 downto 0);
+ signal bit_number : std_logic_vector(4 downto 0);
+ signal bits_out : std_logic_vector(31 downto 0);
+ signal one_bit_in : std_logic;
+ signal bchg : std_logic;
+ signal bset : std_logic;
+
+ signal mulu_sign : std_logic;
+ signal mulu_signext : std_logic_vector(16 downto 0);
+ signal muls_msb : std_logic;
+ signal mulu_reg : std_logic_vector(63 downto 0);
+ signal FAsign : std_logic;
+ signal faktorA : std_logic_vector(31 downto 0);
+ signal faktorB : std_logic_vector(31 downto 0);
+
+ signal div_reg : std_logic_vector(63 downto 0);
+ signal div_quot : std_logic_vector(63 downto 0);
+ signal div_ovl : std_logic;
+ signal div_neg : std_logic;
+ signal div_bit : std_logic;
+ signal div_sub : std_logic_vector(32 downto 0);
+ signal div_over : std_logic_vector(32 downto 0);
+ signal nozero : std_logic;
+ signal div_qsign : std_logic;
+ signal divisor : std_logic_vector(63 downto 0);
+ signal divs : std_logic;
+ signal signedOP : std_logic;
+ signal OP1_sign : std_logic;
+ signal OP2_sign : std_logic;
+ signal OP2outext : std_logic_vector(15 downto 0);
+
+ signal in_offset : std_logic_vector(5 downto 0);
+-- signal in_width : std_logic_vector(5 downto 0);
+ signal datareg : std_logic_vector(31 downto 0);
+ signal insert : std_logic_vector(31 downto 0);
+-- signal bf_result : std_logic_vector(31 downto 0);
+-- signal bf_offset : std_logic_vector(5 downto 0);
+-- signal bf_width : std_logic_vector(5 downto 0);
+-- signal bf_firstbit : std_logic_vector(5 downto 0);
+ signal bf_datareg : std_logic_vector(31 downto 0);
+-- signal bf_out : std_logic_vector(31 downto 0);
+ signal result : std_logic_vector(39 downto 0);
+ signal result_tmp : std_logic_vector(39 downto 0);
+ signal sign : std_logic_vector(31 downto 0);
+ signal bf_set1 : std_logic_vector(39 downto 0);
+ signal inmux0 : std_logic_vector(39 downto 0);
+ signal inmux1 : std_logic_vector(39 downto 0);
+ signal inmux2 : std_logic_vector(39 downto 0);
+ signal inmux3 : std_logic_vector(31 downto 0);
+ signal copymux0 : std_logic_vector(39 downto 0);
+ signal copymux1 : std_logic_vector(39 downto 0);
+ signal copymux2 : std_logic_vector(39 downto 0);
+ signal copymux3 : std_logic_vector(31 downto 0);
+ signal bf_set2 : std_logic_vector(31 downto 0);
+-- signal bf_set3 : std_logic_vector(31 downto 0);
+ signal shift : std_logic_vector(39 downto 0);
+ signal copy : std_logic_vector(39 downto 0);
+-- signal offset : std_logic_vector(5 downto 0);
+-- signal width : std_logic_vector(5 downto 0);
+ signal bf_firstbit : std_logic_vector(5 downto 0);
+ signal mux : std_logic_vector(3 downto 0);
+ signal bitnr : std_logic_vector(4 downto 0);
+ signal mask : std_logic_vector(31 downto 0);
+ signal bf_bset : std_logic;
+ signal bf_NFlag : std_logic;
+ signal bf_bchg : std_logic;
+ signal bf_ins : std_logic;
+ signal bf_exts : std_logic;
+ signal bf_fffo : std_logic;
+ signal bf_d32 : std_logic;
+ signal bf_s32 : std_logic;
+ signal index : std_logic_vector(4 downto 0);
+-- signal i : integer range 0 to 31;
+-- signal i : integer range 0 to 31;
+-- signal i : std_logic_vector(5 downto 0);
+BEGIN
+-----------------------------------------------------------------------------
+-- set OP1in
+-----------------------------------------------------------------------------
+PROCESS (OP2out, reg_QB, opcode, OP1out, OP1in, exe_datatype, addsub_q, execOPC, exec,
+ bcd_a, bcd_s, result_mulu, result_div, exe_condition, bf_shift,
+ Flags, FlagsSR, bits_out, exec_tas, rot_out, exe_opcode, result, bf_fffo, bf_firstbit, bf_datareg)
+ BEGIN
+ ALUout <= OP1in;
+ ALUout(7) <= OP1in(7) OR exec_tas;
+ IF exec(opcBFwb)='1' THEN
+ ALUout <= result(31 downto 0);
+ IF bf_fffo='1' THEN
+ ALUout <= (OTHERS =>'0');
+ ALUout(5 downto 0) <= bf_firstbit + bf_shift;
+ END IF;
+ END IF;
+
+ OP1in <= addsub_q;
+ IF exec(opcABCD)='1' THEN
+ OP1in(7 downto 0) <= bcd_a(7 downto 0);
+ ELSIF exec(opcSBCD)='1' THEN
+ OP1in(7 downto 0) <= bcd_s(7 downto 0);
+ ELSIF exec(opcMULU)='1' AND MUL_Mode/=3 THEN
+ IF exec(write_lowlong)='1' AND (MUL_Mode=1 OR MUL_Mode=2) THEN
+ OP1in <= result_mulu(31 downto 0);
+ ELSE
+ OP1in <= result_mulu(63 downto 32);
+ END IF;
+ ELSIF exec(opcDIVU)='1' AND DIV_Mode/=3 THEN
+ IF exe_opcode(15)='1' OR DIV_Mode=0 THEN
+-- IF exe_opcode(15)='1' THEN
+ OP1in <= result_div(47 downto 32)&result_div(15 downto 0);
+ ELSE --64bit
+ IF exec(write_reminder)='1' THEN
+ OP1in <= result_div(63 downto 32);
+ ELSE
+ OP1in <= result_div(31 downto 0);
+ END IF;
+ END IF;
+ ELSIF exec(opcOR)='1' THEN
+ OP1in <= OP2out OR OP1out;
+ ELSIF exec(opcAND)='1' THEN
+ OP1in <= OP2out AND OP1out;
+ ELSIF exec(opcScc)='1' THEN
+ OP1in(7 downto 0) <= (others=>exe_condition);
+ ELSIF exec(opcEOR)='1' THEN
+ OP1in <= OP2out XOR OP1out;
+ ELSIF exec(opcMOVE)='1' OR exec(exg)='1' THEN
+-- OP1in <= OP2out(31 downto 8)&(OP2out(7)OR exec_tas)&OP2out(6 downto 0);
+ OP1in <= OP2out;
+ ELSIF exec(opcROT)='1' THEN
+ OP1in <= rot_out;
+ ELSIF exec(opcSWAP)='1' THEN
+ OP1in <= OP1out(15 downto 0)& OP1out(31 downto 16);
+ ELSIF exec(opcBITS)='1' THEN
+ OP1in <= bits_out;
+ ELSIF exec(opcBF)='1' THEN
+ OP1in <= bf_datareg;
+ ELSIF exec(opcMOVESR)='1' THEN
+ OP1in(7 downto 0) <= Flags;
+ IF exe_datatype="00" THEN
+ OP1in(15 downto 8) <= "00000000";
+ ELSE
+ OP1in(15 downto 8) <= FlagsSR;
+ END IF;
+ END IF;
+ END PROCESS;
+
+-----------------------------------------------------------------------------
+-- addsub
+-----------------------------------------------------------------------------
+PROCESS (OP1out, OP2out, execOPC, datatype, Flags, long_start, movem_presub, exe_datatype, exec, addsub_a, addsub_b, opaddsub,
+ notaddsub_b, add_result, c_in, sndOPC)
+ BEGIN
+ addsub_a <= OP1out;
+ IF exec(get_bfoffset)='1' THEN
+ IF sndOPC(11)='1' THEN
+ addsub_a <= OP1out(31)&OP1out(31)&OP1out(31)&OP1out(31 downto 3);
+ ELSE
+ addsub_a <= "000000000000000000000000000000"&sndOPC(10 downto 9);
+ END IF;
+ END IF;
+
+ IF exec(subidx)='1' THEN
+ opaddsub <= '1';
+ ELSE
+ opaddsub <= '0';
+ END IF;
+
+ c_in(0) <='0';
+ addsub_b <= OP2out;
+ IF execOPC='0' AND exec(OP2out_one)='0' AND exec(get_bfoffset)='0'THEN
+ IF long_start='0' AND datatype="00" AND exec(use_SP)='0' THEN
+ addsub_b <= "00000000000000000000000000000001";
+ ELSIF long_start='0' AND exe_datatype="10" AND (exec(presub) OR exec(postadd) OR movem_presub)='1' THEN
+ IF exec(movem_action)='1' THEN
+ addsub_b <= "00000000000000000000000000000110";
+ ELSE
+ addsub_b <= "00000000000000000000000000000100";
+ END IF;
+ ELSE
+ addsub_b <= "00000000000000000000000000000010";
+ END IF;
+ ELSE
+ IF (exec(use_XZFlag)='1' AND Flags(4)='1') OR exec(opcCHK)='1' THEN
+ c_in(0) <= '1';
+ END IF;
+ opaddsub <= exec(addsub);
+ END IF;
+
+ IF opaddsub='0' OR long_start='1' THEN --ADD
+ notaddsub_b <= '0'&addsub_b&c_in(0);
+ ELSE --SUB
+ notaddsub_b <= NOT ('0'&addsub_b&c_in(0));
+ END IF;
+ add_result <= (('0'&addsub_a¬addsub_b(0))+notaddsub_b);
+ c_in(1) <= add_result(9) XOR addsub_a(8) XOR addsub_b(8);
+ c_in(2) <= add_result(17) XOR addsub_a(16) XOR addsub_b(16);
+ c_in(3) <= add_result(33);
+ addsub_q <= add_result(32 downto 1);
+ addsub_ofl(0) <= (c_in(1) XOR add_result(8) XOR addsub_a(7) XOR addsub_b(7)); --V Byte
+ addsub_ofl(1) <= (c_in(2) XOR add_result(16) XOR addsub_a(15) XOR addsub_b(15)); --V Word
+ addsub_ofl(2) <= (c_in(3) XOR add_result(32) XOR addsub_a(31) XOR addsub_b(31)); --V Long
+ c_out <= c_in(3 downto 1);
+ END PROCESS;
+
+------------------------------------------------------------------------------
+--ALU
+------------------------------------------------------------------------------
+PROCESS (OP1out, OP2out, niba_hc, niba_h, niba_l, niba_lc, nibs_hc, nibs_h, nibs_l, nibs_lc, Flags)
+ BEGIN
+--BCD_ARITH-------------------------------------------------------------------
+ --ADC
+ bcd_a <= niba_hc&(niba_h(4 downto 1)+('0',niba_hc,niba_hc,'0'))&(niba_l(4 downto 1)+('0',niba_lc,niba_lc,'0'));
+ niba_l <= ('0'&OP1out(3 downto 0)&'1') + ('0'&OP2out(3 downto 0)&Flags(4));
+ niba_lc <= niba_l(5) OR (niba_l(4) AND niba_l(3)) OR (niba_l(4) AND niba_l(2));
+
+ niba_h <= ('0'&OP1out(7 downto 4)&'1') + ('0'&OP2out(7 downto 4)&niba_lc);
+ niba_hc <= niba_h(5) OR (niba_h(4) AND niba_h(3)) OR (niba_h(4) AND niba_h(2));
+ --SBC
+ bcd_s <= nibs_hc&(nibs_h(4 downto 1)-('0',nibs_hc,nibs_hc,'0'))&(nibs_l(4 downto 1)-('0',nibs_lc,nibs_lc,'0'));
+ nibs_l <= ('0'&OP1out(3 downto 0)&'0') - ('0'&OP2out(3 downto 0)&Flags(4));
+ nibs_lc <= nibs_l(5);
+
+ nibs_h <= ('0'&OP1out(7 downto 4)&'0') - ('0'&OP2out(7 downto 4)&nibs_lc);
+ nibs_hc <= nibs_h(5);
+ END PROCESS;
+
+-----------------------------------------------------------------------------
+-- Bits
+-----------------------------------------------------------------------------
+PROCESS (clk, exe_opcode, OP1out, OP2out, one_bit_in, bchg, bset, bit_Number, sndOPC)
+ BEGIN
+ IF rising_edge(clk) THEN
+ IF clkena_lw = '1' THEN
+ bchg <= '0';
+ bset <= '0';
+ CASE opcode(7 downto 6) IS
+ WHEN "01" => --bchg
+ bchg <= '1';
+ WHEN "11" => --bset
+ bset <= '1';
+ WHEN OTHERS => NULL;
+ END CASE;
+ END IF;
+ END IF;
+
+ IF exe_opcode(8)='0' THEN
+ IF exe_opcode(5 downto 4)="00" THEN
+ bit_number <= sndOPC(4 downto 0);
+ ELSE
+ bit_number <= "00"&sndOPC(2 downto 0);
+ END IF;
+ ELSE
+ IF exe_opcode(5 downto 4)="00" THEN
+ bit_number <= OP2out(4 downto 0);
+ ELSE
+ bit_number <= "00"&OP2out(2 downto 0);
+ END IF;
+ END IF;
+
+ one_bit_in <= OP1out(to_integer(unsigned(bit_Number)));
+ bits_out <= OP1out;
+ bits_out(to_integer(unsigned(bit_Number))) <= (bchg AND NOT one_bit_in) OR bset ;
+ END PROCESS;
+
+-----------------------------------------------------------------------------
+-- Bit Field
+-----------------------------------------------------------------------------
+PROCESS (clk, mux, mask, bitnr, bf_ins, bf_bchg, bf_bset, bf_exts, bf_shift, inmux0, inmux1, inmux2, inmux3, bf_set2, OP1out, OP2out, result_tmp, bf_ext_in,
+ shift, datareg, bf_NFlag, result, reg_QB, sign, bf_d32, bf_s32, copy, bf_loffset, copymux0, copymux1, copymux2, copymux3, bf_width)
+ BEGIN
+ IF rising_edge(clk) THEN
+ IF clkena_lw = '1' THEN
+ bf_bset <= '0';
+ bf_bchg <= '0';
+ bf_ins <= '0';
+ bf_exts <= '0';
+ bf_fffo <= '0';
+ bf_d32 <= '0';
+ bf_s32 <= '0';
+ CASE opcode(10 downto 8) IS
+ WHEN "010" => bf_bchg <= '1'; --BFCHG
+ WHEN "011" => bf_exts <= '1'; --BFEXTS
+-- WHEN "100" => insert <= (OTHERS =>'0'); --BFCLR
+ WHEN "101" => bf_fffo <= '1'; --BFFFO
+ WHEN "110" => bf_bset <= '1'; --BFSET
+ WHEN "111" => bf_ins <= '1'; --BFINS
+ bf_s32 <= '1';
+ WHEN OTHERS => NULL;
+ END CASE;
+ IF opcode(4 downto 3)="00" THEN
+ bf_d32 <= '1';
+ END IF;
+ bf_ext_out <= result(39 downto 32);
+ END IF;
+ END IF;
+ shift <= bf_ext_in&OP2out;
+ IF bf_s32='1' THEN
+ shift(39 downto 32) <= OP2out(7 downto 0);
+ END IF;
+
+ IF bf_shift(0)='1' THEN
+ inmux0 <= shift(0)&shift(39 downto 1);
+ ELSE
+ inmux0 <= shift;
+ END IF;
+ IF bf_shift(1)='1' THEN
+ inmux1 <= inmux0(1 downto 0)&inmux0(39 downto 2);
+ ELSE
+ inmux1 <= inmux0;
+ END IF;
+ IF bf_shift(2)='1' THEN
+ inmux2 <= inmux1(3 downto 0)&inmux1(39 downto 4);
+ ELSE
+ inmux2 <= inmux1;
+ END IF;
+ IF bf_shift(3)='1' THEN
+ inmux3 <= inmux2(7 downto 0)&inmux2(31 downto 8);
+ ELSE
+ inmux3 <= inmux2(31 downto 0);
+ END IF;
+ IF bf_shift(4)='1' THEN
+ bf_set2(31 downto 0) <= inmux3(15 downto 0)&inmux3(31 downto 16);
+ ELSE
+ bf_set2(31 downto 0) <= inmux3;
+ END IF;
+
+ IF bf_loffset(4)='1' THEN
+ copymux3 <= sign(15 downto 0)&sign(31 downto 16);
+ ELSE
+ copymux3 <= sign;
+ END IF;
+ IF bf_loffset(3)='1' THEN
+ copymux2(31 downto 0) <= copymux3(23 downto 0)©mux3(31 downto 24);
+ ELSE
+ copymux2(31 downto 0) <= copymux3;
+ END IF;
+ IF bf_d32='1' THEN
+ copymux2(39 downto 32) <= copymux3(7 downto 0);
+ ELSE
+ copymux2(39 downto 32) <= "11111111";
+ END IF;
+ IF bf_loffset(2)='1' THEN
+ copymux1 <= copymux2(35 downto 0)©mux2(39 downto 36);
+ ELSE
+ copymux1 <= copymux2;
+ END IF;
+ IF bf_loffset(1)='1' THEN
+ copymux0 <= copymux1(37 downto 0)©mux1(39 downto 38);
+ ELSE
+ copymux0 <= copymux1;
+ END IF;
+ IF bf_loffset(0)='1' THEN
+ copy <= copymux0(38 downto 0)©mux0(39);
+ ELSE
+ copy <= copymux0;
+ END IF;
+
+ result_tmp <= bf_ext_in&OP1out;
+ IF bf_ins='1' THEN
+ datareg <= reg_QB;
+ ELSE
+ datareg <= bf_set2;
+ END IF;
+ IF bf_ins='1' THEN
+ result(31 downto 0) <= bf_set2;
+ result(39 downto 32) <= bf_set2(7 downto 0);
+ ELSIF bf_bchg='1' THEN
+ result(31 downto 0) <= NOT OP1out;
+ result(39 downto 32) <= NOT bf_ext_in;
+ ELSE
+ result <= (OTHERS => '0');
+ END IF;
+ IF bf_bset='1' THEN
+ result <= (OTHERS => '1');
+ END IF;
+
+ sign <= (OTHERS => '0');
+ bf_NFlag <= datareg(to_integer(unsigned(bf_width)));
+ FOR i in 0 to 31 LOOP
+ IF i>bf_width(4 downto 0) THEN
+ datareg(i) <= '0';
+ sign(i) <= '1';
+ END IF;
+ END LOOP;
+
+ FOR i in 0 to 39 LOOP
+ IF copy(i)='1' THEN
+ result(i) <= result_tmp(i);
+ END IF;
+ END LOOP;
+
+ IF bf_exts='1' AND bf_NFlag='1' THEN
+ bf_datareg <= datareg OR sign;
+ ELSE
+ bf_datareg <= datareg;
+ END IF;
+-- bf_datareg <= copy(31 downto 0);
+-- result(31 downto 0)<=datareg;
+--BFFFO
+ mask <= datareg;
+ bf_firstbit <= '0'&bitnr;
+ bitnr <= "11111";
+ IF mask(31 downto 28)="0000" THEN
+ IF mask(27 downto 24)="0000" THEN
+ IF mask(23 downto 20)="0000" THEN
+ IF mask(19 downto 16)="0000" THEN
+ bitnr(4) <= '0';
+ IF mask(15 downto 12)="0000" THEN
+ IF mask(11 downto 8)="0000" THEN
+ bitnr(3) <= '0';
+ IF mask(7 downto 4)="0000" THEN
+ bitnr(2) <= '0';
+ mux <= mask(3 downto 0);
+ ELSE
+ mux <= mask(7 downto 4);
+ END IF;
+ ELSE
+ mux <= mask(11 downto 8);
+ bitnr(2) <= '0';
+ END IF;
+ ELSE
+ mux <= mask(15 downto 12);
+ END IF;
+ ELSE
+ mux <= mask(19 downto 16);
+ bitnr(3) <= '0';
+ bitnr(2) <= '0';
+ END IF;
+ ELSE
+ mux <= mask(23 downto 20);
+ bitnr(3) <= '0';
+ END IF;
+ ELSE
+ mux <= mask(27 downto 24);
+ bitnr(2) <= '0';
+ END IF;
+ ELSE
+ mux <= mask(31 downto 28);
+ END IF;
+
+ IF mux(3 downto 2)="00" THEN
+ bitnr(1) <= '0';
+ IF mux(1)='0' THEN
+ bitnr(0) <= '0';
+ END IF;
+ ELSE
+ IF mux(3)='0' THEN
+ bitnr(0) <= '0';
+ END IF;
+ END IF;
+ END PROCESS;
+
+-----------------------------------------------------------------------------
+-- Rotation
+-----------------------------------------------------------------------------
+PROCESS (exe_opcode, OP1out, Flags, rot_bits, rot_msb, rot_lsb, rot_rot, exec)
+ BEGIN
+ CASE exe_opcode(7 downto 6) IS
+ WHEN "00" => --Byte
+ rot_rot <= OP1out(7);
+ WHEN "01"|"11" => --Word
+ rot_rot <= OP1out(15);
+ WHEN "10" => --Long
+ rot_rot <= OP1out(31);
+ WHEN OTHERS => NULL;
+ END CASE;
+
+ CASE rot_bits IS
+ WHEN "00" => --ASL, ASR
+ rot_lsb <= '0';
+ rot_msb <= rot_rot;
+ WHEN "01" => --LSL, LSR
+ rot_lsb <= '0';
+ rot_msb <= '0';
+ WHEN "10" => --ROXL, ROXR
+ rot_lsb <= Flags(4);
+ rot_msb <= Flags(4);
+ WHEN "11" => --ROL, ROR
+ rot_lsb <= rot_rot;
+ rot_msb <= OP1out(0);
+ WHEN OTHERS => NULL;
+ END CASE;
+
+ IF exec(rot_nop)='1' THEN
+ rot_out <= OP1out;
+ rot_X <= Flags(4);
+ IF rot_bits="10" THEN --ROXL, ROXR
+ rot_C <= Flags(4);
+ ELSE
+ rot_C <= '0';
+ END IF;
+ ELSE
+ IF exe_opcode(8)='1' THEN --left
+ rot_out <= OP1out(30 downto 0)&rot_lsb;
+ rot_X <= rot_rot;
+ rot_C <= rot_rot;
+ ELSE --right
+ rot_X <= OP1out(0);
+ rot_C <= OP1out(0);
+ rot_out <= rot_msb&OP1out(31 downto 1);
+ CASE exe_opcode(7 downto 6) IS
+ WHEN "00" => --Byte
+ rot_out(7) <= rot_msb;
+ WHEN "01"|"11" => --Word
+ rot_out(15) <= rot_msb;
+ WHEN OTHERS => NULL;
+ END CASE;
+ END IF;
+ END IF;
+ END PROCESS;
+
+------------------------------------------------------------------------------
+--CCR op
+------------------------------------------------------------------------------
+PROCESS (clk, Reset, exe_opcode, exe_datatype, Flags, last_data_read, OP2out, flag_z, OP1IN, c_out, addsub_ofl,
+ bcd_s, bcd_a, exec)
+ BEGIN
+ IF exec(andiSR)='1' THEN
+ CCRin <= Flags AND last_data_read(7 downto 0);
+ ELSIF exec(eoriSR)='1' THEN
+ CCRin <= Flags XOR last_data_read(7 downto 0);
+ ELSIF exec(oriSR)='1' THEN
+ CCRin <= Flags OR last_data_read(7 downto 0);
+ ELSE
+ CCRin <= OP2out(7 downto 0);
+ END IF;
+
+------------------------------------------------------------------------------
+--Flags
+------------------------------------------------------------------------------
+ flag_z <= "000";
+ IF exec(use_XZFlag)='1' AND flags(2)='0' THEN
+ flag_z <= "000";
+ ELSIF OP1in(7 downto 0)="00000000" THEN
+ flag_z(0) <= '1';
+ IF OP1in(15 downto 8)="00000000" THEN
+ flag_z(1) <= '1';
+ IF OP1in(31 downto 16)="0000000000000000" THEN
+ flag_z(2) <= '1';
+ END IF;
+ END IF;
+ END IF;
+
+-- --Flags NZVC
+ IF exe_datatype="00" THEN --Byte
+ set_flags <= OP1IN(7)&flag_z(0)&addsub_ofl(0)&c_out(0);
+ IF exec(opcABCD)='1' THEN
+ set_flags(0) <= bcd_a(8);
+ ELSIF exec(opcSBCD)='1' THEN
+ set_flags(0) <= bcd_s(8);
+ END IF;
+ ELSIF exe_datatype="10" OR exec(opcCPMAW)='1' THEN --Long
+ set_flags <= OP1IN(31)&flag_z(2)&addsub_ofl(2)&c_out(2);
+ ELSE --Word
+ set_flags <= OP1IN(15)&flag_z(1)&addsub_ofl(1)&c_out(1);
+ END IF;
+
+ IF rising_edge(clk) THEN
+ IF clkena_lw = '1' THEN
+ IF exec(directSR)='1' OR set_stop='1' THEN
+ Flags(7 downto 0) <= data_read(7 downto 0);
+ END IF;
+ IF exec(directCCR)='1' THEN
+ Flags(7 downto 0) <= data_read(7 downto 0);
+ END IF;
+
+ IF exec(opcROT)='1' THEN
+ asl_VFlag <= ((set_flags(3) XOR rot_rot) OR asl_VFlag);
+ ELSE
+ asl_VFlag <= '0';
+ END IF;
+ IF exec(to_CCR)='1' THEN
+ Flags(7 downto 0) <= CCRin(7 downto 0); --CCR
+ ELSIF Z_error='1' THEN
+ IF exe_opcode(8)='0' THEN
+ Flags(3 downto 0) <= reg_QA(31)&"000";
+ ELSE
+ Flags(3 downto 0) <= "0100";
+ END IF;
+ ELSIF exec(no_Flags)='0' THEN
+ IF exec(opcADD)='1' THEN
+ Flags(4) <= set_flags(0);
+ ELSIF exec(opcROT)='1' AND rot_bits/="11" AND exec(rot_nop)='0' THEN
+ Flags(4) <= rot_X;
+ END IF;
+
+ IF (exec(opcADD) OR exec(opcCMP))='1' THEN
+ Flags(3 downto 0) <= set_flags;
+ ELSIF exec(opcDIVU)='1' AND DIV_Mode/=3 THEN
+ IF V_Flag='1' THEN
+ Flags(3 downto 0) <= "1010";
+ ELSE
+ Flags(3 downto 0) <= OP1IN(15)&flag_z(1)&"00";
+ END IF;
+ ELSIF exec(write_reminder)='1' AND MUL_Mode/=3 THEN -- z-flag MULU.l
+ Flags(3) <= set_flags(3);
+ Flags(2) <= set_flags(2) AND Flags(2);
+ Flags(1) <= '0';
+ Flags(0) <= '0';
+ ELSIF exec(write_lowlong)='1' AND (MUL_Mode=1 OR MUL_Mode=2) THEN -- flag MULU.l
+ Flags(3) <= set_flags(3);
+ Flags(2) <= set_flags(2);
+ Flags(1) <= set_mV_Flag; --V
+ Flags(0) <= '0';
+ ELSIF exec(opcOR)='1' OR exec(opcAND)='1' OR exec(opcEOR)='1' OR exec(opcMOVE)='1' OR exec(opcMOVEQ)='1' OR exec(opcSWAP)='1' OR exec(opcBF)='1' OR (exec(opcMULU)='1' AND MUL_Mode/=3) THEN
+ Flags(1 downto 0) <= "00";
+ Flags(3 downto 2) <= set_flags(3 downto 2);
+ IF exec(opcBF)='1' THEN
+ Flags(3) <= bf_NFlag;
+ END IF;
+ ELSIF exec(opcROT)='1' THEN
+ Flags(3 downto 2) <= set_flags(3 downto 2);
+ Flags(0) <= rot_C;
+ IF rot_bits="00" AND ((set_flags(3) XOR rot_rot) OR asl_VFlag)='1' THEN --ASL/ASR
+ Flags(1) <= '1';
+ ELSE
+ Flags(1) <= '0';
+ END IF;
+ ELSIF exec(opcBITS)='1' THEN
+ Flags(2) <= NOT one_bit_in;
+ ELSIF exec(opcCHK)='1' THEN
+ IF exe_datatype="01" THEN --Word
+ Flags(3) <= OP1out(15);
+ ELSE
+ Flags(3) <= OP1out(31);
+ END IF;
+ IF OP1out(15 downto 0)=X"0000" AND (exe_datatype="01" OR OP1out(31 downto 16)=X"0000") THEN
+ Flags(2) <='1';
+ ELSE
+ Flags(2) <='0';
+ END IF;
+ Flags(1 downto 0) <= "00";
+ END IF;
+ END IF;
+ END IF;
+ Flags(7 downto 5) <= "000";
+ END IF;
+ END PROCESS;
+
+-------------------------------------------------------------------------------
+---- MULU/MULS
+-------------------------------------------------------------------------------
+PROCESS (exe_opcode, OP2out, muls_msb, mulu_reg, FAsign, mulu_sign, reg_QA, faktorB, result_mulu, signedOP)
+ BEGIN
+ IF (signedOP='1' AND faktorB(31)='1') OR FAsign='1' THEN
+ muls_msb <= mulu_reg(63);
+ ELSE
+ muls_msb <= '0';
+ END IF;
+
+ IF signedOP='1' AND faktorB(31)='1' THEN
+ mulu_sign <= '1';
+ ELSE
+ mulu_sign <= '0';
+ END IF;
+
+ IF MUL_Mode=0 THEN -- 16 Bit
+ result_mulu(63 downto 32) <= muls_msb&mulu_reg(63 downto 33);
+ result_mulu(15 downto 0) <= 'X'&mulu_reg(15 downto 1);
+ IF mulu_reg(0)='1' THEN
+ IF FAsign='1' THEN
+ result_mulu(63 downto 47) <= (muls_msb&mulu_reg(63 downto 48)-(mulu_sign&faktorB(31 downto 16)));
+ ELSE
+ result_mulu(63 downto 47) <= (muls_msb&mulu_reg(63 downto 48)+(mulu_sign&faktorB(31 downto 16)));
+ END IF;
+ END IF;
+ ELSE -- 32 Bit
+ result_mulu <= muls_msb&mulu_reg(63 downto 1);
+ IF mulu_reg(0)='1' THEN
+ IF FAsign='1' THEN
+ result_mulu(63 downto 31) <= (muls_msb&mulu_reg(63 downto 32)-(mulu_sign&faktorB));
+ ELSE
+ result_mulu(63 downto 31) <= (muls_msb&mulu_reg(63 downto 32)+(mulu_sign&faktorB));
+ END IF;
+ END IF;
+ END IF;
+ IF exe_opcode(15)='1' OR MUL_Mode=0 THEN
+ faktorB(31 downto 16) <= OP2out(15 downto 0);
+ faktorB(15 downto 0) <= (OTHERS=>'0');
+ ELSE
+ faktorB <= OP2out;
+ END IF;
+ IF (result_mulu(63 downto 32)=X"00000000" AND (signedOP='0' OR result_mulu(31)='0')) OR
+ (result_mulu(63 downto 32)=X"FFFFFFFF" AND signedOP='1' AND result_mulu(31)='1') THEN
+ set_mV_Flag <= '0';
+ ELSE
+ set_mV_Flag <= '1';
+ END IF;
+ END PROCESS;
+
+PROCESS (clk)
+ BEGIN
+ IF rising_edge(clk) THEN
+ IF clkena_lw='1' THEN
+ IF micro_state=mul1 THEN
+ mulu_reg(63 downto 32) <= (OTHERS=>'0');
+ IF divs='1' AND ((exe_opcode(15)='1' AND reg_QA(15)='1') OR (exe_opcode(15)='0' AND reg_QA(31)='1')) THEN --MULS Neg faktor
+ FAsign <= '1';
+ mulu_reg(31 downto 0) <= 0-reg_QA;
+ ELSE
+ FAsign <= '0';
+ mulu_reg(31 downto 0) <= reg_QA;
+ END IF;
+ ELSIF exec(opcMULU)='0' THEN
+ mulu_reg <= result_mulu;
+ END IF;
+ END IF;
+ END IF;
+ END PROCESS;
+
+-------------------------------------------------------------------------------
+---- DIVU/DIVS
+-------------------------------------------------------------------------------
+
+PROCESS (execOPC, OP1out, OP2out, div_reg, div_neg, div_bit, div_sub, div_quot, OP1_sign, div_over, result_div, reg_QA, opcode, sndOPC, divs, exe_opcode, reg_QB,
+ signedOP, nozero, div_qsign, OP2outext)
+ BEGIN
+ divs <= (opcode(15) AND opcode(8)) OR (NOT opcode(15) AND sndOPC(11));
+ divisor(15 downto 0) <= (OTHERS=> '0');
+ divisor(63 downto 32) <= (OTHERS=> divs AND reg_QA(31));
+ IF exe_opcode(15)='1' OR DIV_Mode=0 THEN
+ divisor(47 downto 16) <= reg_QA;
+ ELSE
+ divisor(31 downto 0) <= reg_QA;
+ IF exe_opcode(14)='1' AND sndOPC(10)='1' THEN
+ divisor(63 downto 32) <= reg_QB;
+ END IF;
+ END IF;
+ IF signedOP='1' OR opcode(15)='0' THEN
+ OP2outext <= OP2out(31 downto 16);
+ ELSE
+ OP2outext <= (OTHERS=> '0');
+ END IF;
+ IF signedOP='1' AND OP2out(31) ='1' THEN
+ div_sub <= (div_reg(63 downto 31))+('1'&OP2out(31 downto 0));
+ ELSE
+ div_sub <= (div_reg(63 downto 31))-('0'&OP2outext(15 downto 0)&OP2out(15 downto 0));
+ END IF;
+ IF DIV_Mode=0 THEN
+ div_bit <= div_sub(16);
+ ELSE
+ div_bit <= div_sub(32);
+ END IF;
+ IF div_bit='1' THEN
+ div_quot(63 downto 32) <= div_reg(62 downto 31);
+ ELSE
+ div_quot(63 downto 32) <= div_sub(31 downto 0);
+ END IF;
+ div_quot(31 downto 0) <= div_reg(30 downto 0)&NOT div_bit;
+
+
+ IF ((nozero='1' AND signedOP='1' AND (OP2out(31) XOR OP1_sign XOR div_neg XOR div_qsign)='1' ) --Overflow DIVS
+ OR (signedOP='0' AND div_over(32)='0')) AND DIV_Mode/=3 THEN --Overflow DIVU
+ set_V_Flag <= '1';
+ ELSE
+ set_V_Flag <= '0';
+ END IF;
+ END PROCESS;
+
+PROCESS (clk)
+ BEGIN
+ IF rising_edge(clk) THEN
+ IF clkena_lw='1' THEN
+ V_Flag <= set_V_Flag;
+ signedOP <= divs;
+ IF micro_state=div1 THEN
+ nozero <= '0';
+ IF divs='1' AND divisor(63)='1' THEN -- Neg divisor
+ OP1_sign <= '1';
+ div_reg <= 0-divisor;
+ ELSE
+ OP1_sign <= '0';
+ div_reg <= divisor;
+ END IF;
+ ELSE
+ div_reg <= div_quot;
+ nozero <= NOT div_bit OR nozero;
+ END IF;
+ IF micro_state=div2 THEN
+ div_qsign <= NOT div_bit;
+ div_neg <= signedOP AND (OP2out(31) XOR OP1_sign);
+ IF DIV_Mode=0 THEN
+ div_over(32 downto 16) <= ('0'&div_reg(47 downto 32))-('0'&OP2out(15 downto 0));
+ ELSE
+ div_over <= ('0'&div_reg(63 downto 32))-('0'&OP2out);
+ END IF;
+ END IF;
+ IF exec(write_reminder)='0' THEN
+-- IF exec_DIVU='0' THEN
+ IF div_neg='1' THEN
+ result_div(31 downto 0) <= 0-div_quot(31 downto 0);
+ ELSE
+ result_div(31 downto 0) <= div_quot(31 downto 0);
+ END IF;
+
+ IF OP1_sign='1' THEN
+ result_div(63 downto 32) <= 0-div_quot(63 downto 32);
+ ELSE
+ result_div(63 downto 32) <= div_quot(63 downto 32);
+ END IF;
+ END IF;
+ END IF;
+ END IF;
+ END PROCESS;
+END;
\ No newline at end of file
diff --git a/common/CPU/68000/tg68k/TG68K_Pack.vhd b/common/CPU/68000/tg68k/TG68K_Pack.vhd
new file mode 100644
index 00000000..0d6cee30
--- /dev/null
+++ b/common/CPU/68000/tg68k/TG68K_Pack.vhd
@@ -0,0 +1,165 @@
+------------------------------------------------------------------------------
+------------------------------------------------------------------------------
+-- --
+-- Copyright (c) 2009-2011 Tobias Gubener --
+-- Subdesign fAMpIGA by TobiFlex --
+-- --
+-- This source file 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 source file 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 . --
+-- --
+------------------------------------------------------------------------------
+------------------------------------------------------------------------------
+library IEEE;
+use IEEE.std_logic_1164.all;
+
+package TG68K_Pack is
+
+ type micro_states is (idle, nop, ld_nn, st_nn, ld_dAn1, ld_AnXn1, ld_AnXn2, st_dAn1, ld_AnXnbd1, ld_AnXnbd2, ld_AnXnbd3,
+ ld_229_1, ld_229_2, ld_229_3, ld_229_4, st_229_1, st_229_2, st_229_3, st_229_4,
+ st_AnXn1, st_AnXn2, bra1, bsr1, bsr2, nopnop, dbcc1, movem1, movem2, movem3,
+ andi, op_AxAy, cmpm, link1, link2, unlink1, unlink2, int1, int2, int3, int4, rte1, rte2, rte3, trap0, trap1, trap2, trap3,
+ movec1, movep1, movep2, movep3, movep4, movep5, movep6, rota1, bf1,
+ mul1, mul2, mul_end1, mul_end2, div1, div2, div3, div4, div_end1, div_end2);
+
+ constant opcMOVE : integer := 0; --
+ constant opcMOVEQ : integer := 1; --
+ constant opcMOVESR : integer := 2; --
+ constant opcADD : integer := 3; --
+ constant opcADDQ : integer := 4; --
+ constant opcOR : integer := 5; --
+ constant opcAND : integer := 6; --
+ constant opcEOR : integer := 7; --
+ constant opcCMP : integer := 8; --
+ constant opcROT : integer := 9; --
+ constant opcCPMAW : integer := 10;
+ constant opcEXT : integer := 11; --
+ constant opcABCD : integer := 12; --
+ constant opcSBCD : integer := 13; --
+ constant opcBITS : integer := 14; --
+ constant opcSWAP : integer := 15; --
+ constant opcScc : integer := 16; --
+ constant andiSR : integer := 17; --
+ constant eoriSR : integer := 18; --
+ constant oriSR : integer := 19; --
+ constant opcMULU : integer := 20; --
+ constant opcDIVU : integer := 21; --
+ constant dispouter : integer := 22; --
+ constant rot_nop : integer := 23; --
+ constant ld_rot_cnt : integer := 24; --
+ constant writePC_add : integer := 25; --
+ constant ea_data_OP1 : integer := 26; --
+ constant ea_data_OP2 : integer := 27; --
+ constant use_XZFlag : integer := 28; --
+ constant get_bfoffset : integer := 29; --
+ constant save_memaddr : integer := 30; --
+ constant opcCHK : integer := 31; --
+ constant movec_rd : integer := 32; --
+ constant movec_wr : integer := 33; --
+ constant Regwrena : integer := 34; --
+ constant update_FC : integer := 35; --
+ constant linksp : integer := 36; --
+ constant movepl : integer := 37; --
+ constant update_ld : integer := 38; --
+ constant OP1addr : integer := 39; --
+ constant write_reg : integer := 40; --
+ constant changeMode : integer := 41; --
+ constant ea_build : integer := 42; --
+ constant trap_chk : integer := 43; --
+ constant store_ea_data : integer := 44; --
+ constant addrlong : integer := 45; --
+ constant postadd : integer := 46; --
+ constant presub : integer := 47; --
+ constant subidx : integer := 48; --
+ constant no_Flags : integer := 49; --
+ constant use_SP : integer := 50; --
+ constant to_CCR : integer := 51; --
+ constant to_SR : integer := 52; --
+ constant OP2out_one : integer := 53; --
+ constant OP1out_zero : integer := 54; --
+ constant mem_addsub : integer := 55; --
+ constant addsub : integer := 56; --
+ constant directPC : integer := 57; --
+ constant direct_delta : integer := 58; --
+ constant directSR : integer := 59; --
+ constant directCCR : integer := 60; --
+ constant exg : integer := 61; --
+ constant get_ea_now : integer := 62; --
+ constant ea_to_pc : integer := 63; --
+ constant hold_dwr : integer := 64; --
+ constant to_USP : integer := 65; --
+ constant from_USP : integer := 66; --
+ constant write_lowlong : integer := 67; --
+ constant write_reminder : integer := 68; --
+ constant movem_action : integer := 69; --
+ constant briefext : integer := 70; --
+ constant get_2ndOPC : integer := 71; --
+ constant mem_byte : integer := 72; --
+ constant longaktion : integer := 73; --
+ constant opcRESET : integer := 74; --
+ constant opcBF : integer := 75; --
+ constant opcBFwb : integer := 76; --
+ constant s2nd_hbits : integer := 77; --
+-- constant : integer := 75; --
+-- constant : integer := 76; --
+-- constant : integer := 7; --
+-- constant : integer := 7; --
+-- constant : integer := 7; --
+
+ constant lastOpcBit : integer := 77;
+
+ component TG68K_ALU
+ generic(
+ MUL_Mode : integer := 0; --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no MUL,
+ DIV_Mode : integer := 0 --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no DIV,
+ );
+ port(
+ clk : in std_logic;
+ Reset : in std_logic;
+ clkena_lw : in std_logic:='1';
+ execOPC : in bit;
+ exe_condition : in std_logic;
+ exec_tas : in std_logic;
+ long_start : in bit;
+ movem_presub : in bit;
+ set_stop : in bit;
+ Z_error : in bit;
+ rot_bits : in std_logic_vector(1 downto 0);
+ exec : in bit_vector(lastOpcBit downto 0);
+ OP1out : in std_logic_vector(31 downto 0);
+ OP2out : in std_logic_vector(31 downto 0);
+ reg_QA : in std_logic_vector(31 downto 0);
+ reg_QB : in std_logic_vector(31 downto 0);
+ opcode : in std_logic_vector(15 downto 0);
+ datatype : in std_logic_vector(1 downto 0);
+ exe_opcode : in std_logic_vector(15 downto 0);
+ exe_datatype : in std_logic_vector(1 downto 0);
+ sndOPC : in std_logic_vector(15 downto 0);
+ last_data_read : in std_logic_vector(15 downto 0);
+ data_read : in std_logic_vector(15 downto 0);
+ FlagsSR : in std_logic_vector(7 downto 0);
+ micro_state : in micro_states;
+ bf_ext_in : in std_logic_vector(7 downto 0);
+ bf_ext_out : out std_logic_vector(7 downto 0);
+ bf_shift : in std_logic_vector(5 downto 0);
+ bf_width : in std_logic_vector(5 downto 0);
+ bf_loffset : in std_logic_vector(4 downto 0);
+
+ set_V_Flag : buffer bit;
+ Flags : buffer std_logic_vector(7 downto 0);
+ c_out : buffer std_logic_vector(2 downto 0);
+ addsub_q : buffer std_logic_vector(31 downto 0);
+ ALUout : out std_logic_vector(31 downto 0)
+ );
+ end component;
+
+end;
\ No newline at end of file
diff --git a/common/CPU/68000/tg68k/TG68KdotC_Kernel.vhd b/common/CPU/68000/tg68k/TG68KdotC_Kernel.vhd
new file mode 100644
index 00000000..fa1b80a7
--- /dev/null
+++ b/common/CPU/68000/tg68k/TG68KdotC_Kernel.vhd
@@ -0,0 +1,3200 @@
+------------------------------------------------------------------------------
+------------------------------------------------------------------------------
+-- --
+-- Copyright (c) 2009-2012 Tobias Gubener --
+-- Subdesign fAMpIGA by TobiFlex --
+-- --
+-- This source file 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 source file 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 . --
+-- --
+------------------------------------------------------------------------------
+------------------------------------------------------------------------------
+-- to do 68010:
+-- (MOVEC)
+-- BKPT
+-- RTD
+-- MOVES
+--
+-- to do 68020:
+-- (CALLM)
+-- (RETM)
+
+-- CAS, CAS2
+-- CHK2
+-- CMP2
+-- cpXXX Coprozessor stuff
+-- PACK
+-- TRAPcc
+-- UNPK
+
+-- done 020:
+-- Bitfields
+-- address modes
+-- long bra
+-- DIVS.L, DIVU.L
+-- LINK long
+-- MULS.L, MULU.L
+-- extb.l
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use work.TG68K_Pack.all;
+
+entity TG68KdotC_Kernel is
+ generic(
+ SR_Read : integer:= 0; --0=>user, 1=>privileged, 2=>switchable with CPU(0)
+ VBR_Stackframe : integer:= 0; --0=>no, 1=>yes/extended, 2=>switchable with CPU(0)
+ extAddr_Mode : integer:= 0; --0=>no, 1=>yes, 2=>switchable with CPU(1)
+ MUL_Mode : integer := 0; --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no MUL,
+ DIV_Mode : integer := 0; --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no DIV,
+ BitField : integer := 0 --0=>no, 1=>yes, 2=>switchable with CPU(1)
+ );
+ port(clk : in std_logic;
+ nReset : in std_logic; --low active
+ clkena_in : in std_logic:='1';
+ data_in : in std_logic_vector(15 downto 0);
+ IPL : in std_logic_vector(2 downto 0):="111";
+ IPL_autovector : in std_logic:='0';
+ CPU : in std_logic_vector(1 downto 0):="00"; -- 00->68000 01->68010 11->68020(only some parts - yet)
+ addr : buffer std_logic_vector(31 downto 0);
+ data_write : out std_logic_vector(15 downto 0);
+ nWr : out std_logic;
+ nUDS, nLDS : out std_logic;
+ busstate : out std_logic_vector(1 downto 0); -- 00-> fetch code 10->read data 11->write data 01->no memaccess
+ nResetOut : out std_logic;
+ FC : out std_logic_vector(2 downto 0);
+-- for debug
+ skipFetch : out std_logic;
+ regin : buffer std_logic_vector(31 downto 0)
+ );
+end TG68KdotC_Kernel;
+
+architecture logic of TG68KdotC_Kernel is
+
+
+ signal syncReset : std_logic_vector(3 downto 0);
+ signal Reset : std_logic;
+ signal clkena_lw : std_logic;
+ signal TG68_PC : std_logic_vector(31 downto 0);
+ signal tmp_TG68_PC : std_logic_vector(31 downto 0);
+ signal TG68_PC_add : std_logic_vector(31 downto 0);
+ signal PC_dataa : std_logic_vector(31 downto 0);
+ signal PC_datab : std_logic_vector(31 downto 0);
+ signal memaddr : std_logic_vector(31 downto 0);
+ signal state : std_logic_vector(1 downto 0);
+ signal datatype : std_logic_vector(1 downto 0);
+ signal set_datatype : std_logic_vector(1 downto 0);
+ signal exe_datatype : std_logic_vector(1 downto 0);
+ signal setstate : std_logic_vector(1 downto 0);
+
+ signal opcode : std_logic_vector(15 downto 0);
+ signal exe_opcode : std_logic_vector(15 downto 0);
+ signal sndOPC : std_logic_vector(15 downto 0);
+
+ signal last_opc_read : std_logic_vector(15 downto 0);
+ signal registerin : std_logic_vector(31 downto 0);
+ signal reg_QA : std_logic_vector(31 downto 0);
+ signal reg_QB : std_logic_vector(31 downto 0);
+ signal Wwrena,Lwrena : bit;
+ signal Bwrena : bit;
+ signal Regwrena_now : bit;
+ signal rf_dest_addr : std_logic_vector(3 downto 0);
+ signal rf_source_addr : std_logic_vector(3 downto 0);
+ signal rf_source_addrd : std_logic_vector(3 downto 0);
+
+ type regfile_t is array(0 to 15) of std_logic_vector(15 downto 0);
+ signal regfile_low : regfile_t;
+ signal regfile_high : regfile_t;
+ signal RDindex_A : integer range 0 to 15;
+ signal RDindex_B : integer range 0 to 15;
+ signal WR_AReg : std_logic;
+
+
+ signal memaddr_reg : std_logic_vector(31 downto 0);
+ signal memaddr_delta : std_logic_vector(31 downto 0);
+ signal use_base : bit;
+
+ signal ea_data : std_logic_vector(31 downto 0);
+ signal OP1out, OP2out : std_logic_vector(31 downto 0);
+ signal OP1outbrief : std_logic_vector(15 downto 0);
+ signal OP1in : std_logic_vector(31 downto 0);
+ signal ALUout : std_logic_vector(31 downto 0);
+ signal data_write_tmp : std_logic_vector(31 downto 0);
+ signal data_write_muxin : std_logic_vector(31 downto 0);
+ signal data_write_mux : std_logic_vector(47 downto 0);
+ signal nextpass : bit;
+ signal setnextpass : bit;
+ signal setdispbyte : bit;
+ signal setdisp : bit;
+ signal regdirectsource :bit; -- checken !!!
+ signal addsub_q : std_logic_vector(31 downto 0);
+ signal briefdata : std_logic_vector(31 downto 0);
+-- signal c_in : std_logic_vector(3 downto 0);
+ signal c_out : std_logic_vector(2 downto 0);
+
+ signal mem_address : std_logic_vector(31 downto 0);
+ signal memaddr_a : std_logic_vector(31 downto 0);
+
+ signal TG68_PC_brw : bit;
+ signal TG68_PC_word : bit;
+ signal getbrief : bit;
+ signal brief : std_logic_vector(15 downto 0);
+ signal dest_areg : std_logic;
+ signal source_areg : std_logic;
+ signal data_is_source : bit;
+ signal store_in_tmp : bit;
+ signal write_back : bit;
+ signal exec_write_back: bit;
+ signal setstackaddr : bit;
+ signal writePC : bit;
+ signal writePCbig : bit;
+ signal set_writePCbig : bit;
+ signal setopcode : bit;
+ signal decodeOPC : bit;
+ signal execOPC : bit;
+ signal setexecOPC : bit;
+ signal endOPC : bit;
+ signal setendOPC : bit;
+ signal Flags : std_logic_vector(7 downto 0); -- ...XNZVC
+ signal FlagsSR : std_logic_vector(7 downto 0); -- T.S..III
+ signal SRin : std_logic_vector(7 downto 0);
+ signal exec_DIRECT : bit;
+ signal exec_tas : std_logic;
+ signal set_exec_tas : std_logic;
+
+ signal exe_condition : std_logic;
+ signal ea_only : bit;
+ signal source_lowbits : bit;
+ signal source_2ndHbits : bit;
+ signal source_2ndLbits : bit;
+ signal dest_2ndHbits : bit;
+ signal dest_hbits : bit;
+ signal rot_bits : std_logic_vector(1 downto 0);
+ signal set_rot_bits : std_logic_vector(1 downto 0);
+ signal rot_cnt : std_logic_vector(5 downto 0);
+ signal set_rot_cnt : std_logic_vector(5 downto 0);
+ signal movem_actiond : bit;
+ signal movem_regaddr : std_logic_vector(3 downto 0);
+ signal movem_mux : std_logic_vector(3 downto 0);
+ signal movem_presub : bit;
+ signal movem_run : bit;
+ signal ea_calc_b : std_logic_vector(31 downto 0);
+ signal set_direct_data: bit;
+ signal use_direct_data: bit;
+ signal direct_data : bit;
+
+ signal set_V_Flag : bit;
+ signal set_vectoraddr : bit;
+ signal writeSR : bit;
+ signal trap_illegal : bit;
+ signal trap_addr_error : bit;
+ signal trap_priv : bit;
+ signal trap_trace : bit;
+ signal trap_1010 : bit;
+ signal trap_1111 : bit;
+ signal trap_trap : bit;
+ signal trap_trapv : bit;
+ signal trap_interrupt : bit;
+ signal trapmake : bit;
+ signal trapd : bit;
+ signal trap_SR : std_logic_vector(7 downto 0);
+ signal make_trace : std_logic;
+
+ signal set_stop : bit;
+ signal stop : bit;
+ signal trap_vector : std_logic_vector(31 downto 0);
+ signal trap_vector_vbr : std_logic_vector(31 downto 0);
+ signal USP : std_logic_vector(31 downto 0);
+ signal illegal_write_mode : bit;
+ signal illegal_read_mode : bit;
+ signal illegal_byteaddr : bit;
+
+ signal IPL_nr : std_logic_vector(2 downto 0);
+ signal rIPL_nr : std_logic_vector(2 downto 0);
+ signal interrupt : bit;
+ signal setinterrupt : bit;
+ signal SVmode : std_logic;
+ signal preSVmode : std_logic;
+ signal Suppress_Base : bit;
+ signal set_Suppress_Base : bit;
+ signal set_Z_error : bit;
+ signal Z_error : bit;
+ signal ea_build_now : bit;
+ signal build_logical : bit;
+ signal build_bcd : bit;
+
+ signal data_read : std_logic_vector(31 downto 0);
+ signal bf_ext_in : std_logic_vector(7 downto 0);
+ signal bf_ext_out : std_logic_vector(7 downto 0);
+ signal byte : bit;
+ signal long_start : bit;
+ signal long_start_alu : bit;
+ signal long_done : bit;
+-- signal long_odd_start : bit;
+-- signal odd_aktion : bit;
+-- signal odd_start : bit;
+-- signal odd_done : bit;
+ signal memmask : std_logic_vector(5 downto 0);
+ signal set_memmask : std_logic_vector(5 downto 0);
+ signal memread : std_logic_vector(3 downto 0);
+ signal wbmemmask : std_logic_vector(5 downto 0);
+ signal memmaskmux : std_logic_vector(5 downto 0);
+ signal oddout : std_logic;
+ signal set_oddout : std_logic;
+ signal PCbase : std_logic;
+ signal set_PCbase : std_logic;
+
+ signal last_data_read : std_logic_vector(31 downto 0);
+ signal last_data_in : std_logic_vector(31 downto 0);
+-- signal recall_last : std_logic;
+-- signal set_recall_last : std_logic;
+
+ signal bf_offset : std_logic_vector(5 downto 0);
+ signal bf_width : std_logic_vector(5 downto 0);
+ signal bf_bhits : std_logic_vector(5 downto 0);
+ signal bf_shift : std_logic_vector(5 downto 0);
+ signal alu_width : std_logic_vector(5 downto 0);
+ signal alu_bf_shift : std_logic_vector(5 downto 0);
+ signal bf_loffset : std_logic_vector(5 downto 0);
+ signal alu_bf_loffset : std_logic_vector(5 downto 0);
+
+ signal movec_data : std_logic_vector(31 downto 0);
+ signal VBR : std_logic_vector(31 downto 0);
+ signal CACR : std_logic_vector(3 downto 0);
+ signal DFC : std_logic_vector(2 downto 0);
+ signal SFC : std_logic_vector(2 downto 0);
+
+
+ signal set : bit_vector(lastOpcBit downto 0);
+ signal set_exec : bit_vector(lastOpcBit downto 0);
+ signal exec : bit_vector(lastOpcBit downto 0);
+
+ signal micro_state : micro_states;
+ signal next_micro_state : micro_states;
+
+
+
+BEGIN
+
+ALU: TG68K_ALU
+ generic map(
+ MUL_Mode => MUL_Mode, --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no MUL,
+ DIV_Mode => DIV_Mode --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no DIV,
+ )
+ port map(
+ clk => clk, --: in std_logic;
+ Reset => Reset, --: in std_logic;
+ clkena_lw => clkena_lw, --: in std_logic:='1';
+ execOPC => execOPC, --: in bit;
+ exe_condition => exe_condition, --: in std_logic;
+ exec_tas => exec_tas, --: in std_logic;
+ long_start => long_start_alu, --: in bit;
+ movem_presub => movem_presub, --: in bit;
+ set_stop => set_stop, --: in bit;
+ Z_error => Z_error, --: in bit;
+
+ rot_bits => rot_bits, --: in std_logic_vector(1 downto 0);
+ exec => exec, --: in bit_vector(lastOpcBit downto 0);
+ OP1out => OP1out, --: in std_logic_vector(31 downto 0);
+ OP2out => OP2out, --: in std_logic_vector(31 downto 0);
+ reg_QA => reg_QA, --: in std_logic_vector(31 downto 0);
+ reg_QB => reg_QB, --: in std_logic_vector(31 downto 0);
+ opcode => opcode, --: in std_logic_vector(15 downto 0);
+ datatype => datatype, --: in std_logic_vector(1 downto 0);
+ exe_opcode => exe_opcode, --: in std_logic_vector(15 downto 0);
+ exe_datatype => exe_datatype, --: in std_logic_vector(1 downto 0);
+ sndOPC => sndOPC, --: in std_logic_vector(15 downto 0);
+ last_data_read => last_data_read(15 downto 0), --: in std_logic_vector(31 downto 0);
+ data_read => data_read(15 downto 0), --: in std_logic_vector(31 downto 0);
+ FlagsSR => FlagsSR, --: in std_logic_vector(7 downto 0);
+ micro_state => micro_state, --: in micro_states;
+ bf_ext_in => bf_ext_in,
+ bf_ext_out => bf_ext_out,
+ bf_shift => alu_bf_shift,
+ bf_width => alu_width,
+ bf_loffset => alu_bf_loffset(4 downto 0),
+
+ set_V_Flag => set_V_Flag, --: buffer bit;
+ Flags => Flags, --: buffer std_logic_vector(8 downto 0);
+ c_out => c_out, --: buffer std_logic_vector(2 downto 0);
+ addsub_q => addsub_q, --: buffer std_logic_vector(31 downto 0);
+ ALUout => ALUout --: buffer std_logic_vector(31 downto 0)
+ );
+
+ long_start_alu <= to_bit(NOT memmaskmux(3));
+-----------------------------------------------------------------------------
+-- Bus control
+-----------------------------------------------------------------------------
+ nWr <= '0' WHEN state="11" ELSE '1';
+ busstate <= state;
+ nResetOut <= '0' WHEN exec(opcRESET)='1' ELSE '1';
+ memmaskmux <= memmask WHEN addr(0)='1' ELSE memmask(4 downto 0)&'1';
+ nUDS <= memmaskmux(5);
+ nLDS <= memmaskmux(4);
+ clkena_lw <= '1' WHEN clkena_in='1' AND memmaskmux(3)='1' ELSE '0';
+
+ PROCESS (clk, nReset)
+ BEGIN
+ IF nReset='0' THEN
+ syncReset <= "0000";
+ Reset <= '1';
+ ELSIF rising_edge(clk) THEN
+ IF clkena_in='1' THEN
+ syncReset <= syncReset(2 downto 0)&'1';
+ Reset <= NOT syncReset(3);
+ END IF;
+ END IF;
+ END PROCESS;
+
+PROCESS (clk, long_done, last_data_in, data_in, byte, addr, long_start, memmaskmux, memread, memmask, data_read)
+ BEGIN
+ IF memmaskmux(4)='0' THEN
+ data_read <= last_data_in(15 downto 0)&data_in;
+ ELSE
+ data_read <= last_data_in(23 downto 0)&data_in(15 downto 8);
+ END IF;
+ IF memread(0)='1' OR (memread(1 downto 0)="10" AND memmaskmux(4)='1')THEN
+ data_read(31 downto 16) <= (OTHERS=>data_read(15));
+ END IF;
+
+ IF rising_edge(clk) THEN
+ IF clkena_lw='1' AND state="10" THEN
+ IF memmaskmux(4)='0' THEN
+ bf_ext_in <= last_data_in(23 downto 16);
+ ELSE
+ bf_ext_in <= last_data_in(31 downto 24);
+ END IF;
+ END IF;
+ IF Reset='1' THEN
+-- long_start <= '0';
+-- long_odd_start <= '0';
+ last_data_read <= (OTHERS => '0');
+ ELSIF clkena_in='1' THEN
+ IF state="00" OR exec(update_ld)='1' THEN
+ last_data_read <= data_read;
+-- IF state(1)='0' AND long_start='1' THEN
+ IF state(1)='0' AND memmask(1)='0' THEN
+ last_data_read(31 downto 16) <= last_opc_read;
+-- ELSIF state(1)='0' OR long_done='0' THEN
+ ELSIF state(1)='0' OR memread(1)='1' THEN
+ last_data_read(31 downto 16) <= (OTHERS=>data_in(15));
+ END IF;
+ END IF;
+ last_data_in <= last_data_in(15 downto 0)&data_in(15 downto 0);
+
+---- long_start <= set(longaktion) AND NOT long_odd_start;
+---- long_odd_start <= (set(longaktion) AND NOT long_odd_start) OR (long_start AND odd_start);
+---- long_done <= long_odd_start AND NOT odd_start;
+---- odd_done <= NOT long_start AND (odd_start OR long_odd_start);
+---- odd_aktion <= odd_start OR (NOT long_start AND long_odd_start);
+-- long_start <= set(longaktion) AND NOT long_start;
+-- long_done <= long_start;
+ END IF;
+ END IF;
+ long_start <= to_bit(NOT memmask(1));
+ long_done <= to_bit(NOT memread(1));
+ END PROCESS;
+
+PROCESS (byte, long_start, reg_QB, data_write_tmp, exec, data_read, data_write_mux, memmaskmux, bf_ext_out,
+ data_write_muxin, memmask, oddout, addr)
+ BEGIN
+ IF exec(write_reg)='1' THEN
+ data_write_muxin <= reg_QB;
+ ELSE
+ data_write_muxin <= data_write_tmp;
+ END IF;
+-- IF memmaskmux(4)='0' THEN
+ IF oddout=addr(0) THEN
+ data_write_mux <= "XXXXXXXX"&bf_ext_out&data_write_muxin;
+ ELSE
+ data_write_mux <= bf_ext_out&data_write_muxin&"XXXXXXXX";
+ END IF;
+
+ IF memmaskmux(1)='0' THEN
+ data_write <= data_write_mux(47 downto 32);
+ ELSIF memmaskmux(3)='0' THEN
+ data_write <= data_write_mux(31 downto 16);
+ ELSE
+ data_write <= data_write_mux(15 downto 0);
+ END IF;
+-- IF exec(mem_byte)='1' OR odd_start='1' THEN --movep
+ IF exec(mem_byte)='1' THEN --movep
+ data_write(7 downto 0) <= data_write_tmp(15 downto 8);
+ END IF;
+-- IF long_start='1' THEN
+-- data_write <= data_write_mux(31 downto 16);
+-- IF odd_start='1' THEN
+-- data_write(7 downto 0) <= data_write_mux(31 downto 24);
+-- END IF;
+-- ELSE
+-- data_write <= data_write_mux(15 downto 0);
+-- IF long_odd_start='1' THEN
+-- data_write <= data_write_mux(23 downto 8);
+-- END IF;
+-- IF exec(mem_byte)='1' OR odd_start='1' THEN --movep
+-- data_write(7 downto 0) <= data_write_tmp(15 downto 8);
+-- ELSIF byte='1' OR odd_done='1' THEN
+-- data_write(15 downto 8) <= data_write_mux(7 downto 0);
+-- END IF;
+-- END IF;
+ END PROCESS;
+
+-----------------------------------------------------------------------------
+-- Registerfile
+-----------------------------------------------------------------------------
+
+
+PROCESS (clk, regfile_high, regfile_low, RDindex_A, RDindex_B, ALUout, exec, memaddr, memaddr_a, ea_only, USP, movec_data)
+ BEGIN
+ OP1in <= ALUout;
+ IF exec(save_memaddr)='1' THEN
+ OP1in <= memaddr;
+ ELSIF exec(get_ea_now)='1' AND ea_only='1' THEN
+ OP1in <= memaddr_a;
+ ELSIF exec(from_USP)='1' THEN
+ OP1in <= USP;
+ ELSIF exec(movec_rd)='1' THEN
+ OP1in <= movec_data;
+ END IF;
+
+ reg_QA <= regfile_high(RDindex_A) & regfile_low(RDindex_A);
+ reg_QB <= regfile_high(RDindex_B) & regfile_low(RDindex_B);
+ IF rising_edge(clk) THEN
+ IF clkena_lw='1' THEN
+ rf_source_addrd <= rf_source_addr;
+ WR_AReg <= rf_dest_addr(3);
+ RDindex_A <= conv_integer(rf_dest_addr(3 downto 0));
+ RDindex_B <= conv_integer(rf_source_addr(3 downto 0));
+ IF Bwrena='1' THEN
+ regfile_low(RDindex_A)(7 downto 0) <= OP1in(7 downto 0);
+ END IF;
+ IF Wwrena='1' THEN
+-- regfile_low(RDindex_A)(15 downto 8) <= OP1in(15 downto 8);
+ regfile_low(RDindex_A) <= regin(15 downto 0);
+ END IF;
+ IF Lwrena='1' THEN
+ regfile_high(RDindex_A) <= OP1in(31 downto 16);
+ END IF;
+
+ IF exec(to_USP)='1' THEN
+ USP <= reg_QA;
+ END IF;
+ END IF;
+ END IF;
+ END PROCESS;
+
+-----------------------------------------------------------------------------
+-- Write Reg
+-----------------------------------------------------------------------------
+PROCESS (OP1in, reg_QA, Regwrena_now, exe_datatype, WR_AReg, movem_actiond, exec)
+ BEGIN
+ Bwrena <= '0';
+ Wwrena <= '0';
+ Lwrena <= '0';
+ regin <= OP1in;
+ IF exec(presub)='1' OR exec(postadd)='1' OR exec(changeMode)='1' THEN -- -(An)+
+ Bwrena <= '1';
+ Wwrena <= '1';
+ Lwrena <= '1';
+ ELSIF Regwrena_now='1' THEN
+ Bwrena <= '1';
+ Wwrena <= '1';
+ ELSIF exec(Regwrena)='1' THEN --read (mem)
+ CASE exe_datatype IS
+ WHEN "00" => --BYTE
+ Bwrena <= '1';
+ regin(15 downto 8) <= reg_QA(15 downto 8);
+ WHEN "01" => --WORD
+ Bwrena <= '1';
+ Wwrena <= '1';
+ IF WR_AReg='1' OR movem_actiond='1' THEN
+ Lwrena <='1';
+ END IF;
+ WHEN OTHERS => --LONG
+ Bwrena <= '1';
+ Wwrena <= '1';
+ Lwrena <= '1';
+ END CASE;
+ END IF;
+ END PROCESS;
+
+-----------------------------------------------------------------------------
+-- set dest regaddr
+-----------------------------------------------------------------------------
+PROCESS (opcode, rf_source_addrd, brief, setstackaddr, dest_hbits, dest_areg, data_is_source, sndOPC, exec, set, dest_2ndHbits)
+ BEGIN
+ IF exec(movem_action) ='1' THEN
+ rf_dest_addr <= rf_source_addrd;
+ ELSIF set(briefext)='1' THEN
+ rf_dest_addr <= brief(15 downto 12);
+ ELSIF set(get_bfoffset)='1' THEN
+ rf_dest_addr <= sndOPC(9 downto 6);
+ ELSIF dest_2ndHbits='1' THEN
+ rf_dest_addr <= sndOPC(15 downto 12);
+ ELSIF set(write_reminder)='1' THEN
+ rf_dest_addr <= sndOPC(3 downto 0);
+ ELSIF setstackaddr='1' THEN
+ rf_dest_addr <= "1111";
+ ELSIF dest_hbits='1' THEN
+ rf_dest_addr <= dest_areg&opcode(11 downto 9);
+ ELSE
+ IF opcode(5 downto 3)="000" OR data_is_source='1' THEN
+ rf_dest_addr <= dest_areg&opcode(2 downto 0);
+ ELSE
+ rf_dest_addr <= '1'&opcode(2 downto 0);
+ END IF;
+ END IF;
+ END PROCESS;
+
+-----------------------------------------------------------------------------
+-- set source regaddr
+-----------------------------------------------------------------------------
+PROCESS (opcode, movem_presub, movem_regaddr, source_lowbits, source_areg, sndOPC, exec, set, source_2ndLbits, source_2ndHbits)
+ BEGIN
+ IF exec(movem_action)='1' OR set(movem_action) ='1' THEN
+ IF movem_presub='1' THEN
+ rf_source_addr <= movem_regaddr XOR "1111";
+ ELSE
+ rf_source_addr <= movem_regaddr;
+ END IF;
+ ELSIF source_2ndLbits='1' THEN
+ rf_source_addr <= sndOPC(3 downto 0);
+ ELSIF source_2ndHbits='1' THEN
+ rf_source_addr <= sndOPC(15 downto 12);
+ ELSIF source_lowbits='1' THEN
+ rf_source_addr <= source_areg&opcode(2 downto 0);
+ ELSIF exec(linksp)='1' THEN
+ rf_source_addr <= "1111";
+ ELSE
+ rf_source_addr <= source_areg&opcode(11 downto 9);
+ END IF;
+ END PROCESS;
+
+-----------------------------------------------------------------------------
+-- set OP1out
+-----------------------------------------------------------------------------
+PROCESS (reg_QA, store_in_tmp, ea_data, long_start, addr, exec, memmaskmux)
+ BEGIN
+ OP1out <= reg_QA;
+ IF exec(OP1out_zero)='1' THEN
+ OP1out <= (OTHERS => '0');
+ ELSIF exec(ea_data_OP1)='1' AND store_in_tmp='1' THEN
+ OP1out <= ea_data;
+-- ELSIF exec(movem_action)='1' OR long_odd_start='1' OR odd_start='1' OR exec(OP1addr)='1' THEN
+ ELSIF exec(movem_action)='1' OR memmaskmux(3)='0' OR exec(OP1addr)='1' THEN
+ OP1out <= addr;
+ END IF;
+ END PROCESS;
+
+-----------------------------------------------------------------------------
+-- set OP2out
+-----------------------------------------------------------------------------
+PROCESS (OP2out, reg_QB, exe_opcode, exe_datatype, execOPC, exec, use_direct_data,
+ store_in_tmp, data_write_tmp, ea_data)
+ BEGIN
+ OP2out(15 downto 0) <= reg_QB(15 downto 0);
+ OP2out(31 downto 16) <= (OTHERS => OP2out(15));
+ IF exec(OP2out_one)='1' THEN
+ OP2out(15 downto 0) <= "1111111111111111";
+ ELSIF exec(opcEXT)='1' THEN
+ IF exe_opcode(6)='0' OR exe_opcode(8)='1' THEN --ext.w
+ OP2out(15 downto 8) <= (OTHERS => OP2out(7));
+ END IF;
+ ELSIF use_direct_data='1' OR (exec(exg)='1' AND execOPC='1') OR exec(get_bfoffset)='1' THEN
+ OP2out <= data_write_tmp;
+ ELSIF (exec(ea_data_OP1)='0' AND store_in_tmp='1') OR exec(ea_data_OP2)='1' THEN
+ OP2out <= ea_data;
+ ELSIF exec(opcMOVEQ)='1' THEN
+ OP2out(7 downto 0) <= exe_opcode(7 downto 0);
+ OP2out(15 downto 8) <= (OTHERS => exe_opcode(7));
+ ELSIF exec(opcADDQ)='1' THEN
+ OP2out(2 downto 0) <= exe_opcode(11 downto 9);
+ IF exe_opcode(11 downto 9)="000" THEN
+ OP2out(3) <='1';
+ ELSE
+ OP2out(3) <='0';
+ END IF;
+ OP2out(15 downto 4) <= (OTHERS => '0');
+ ELSIF exe_datatype="10" THEN
+ OP2out(31 downto 16) <= reg_QB(31 downto 16);
+ END IF;
+ END PROCESS;
+
+
+-----------------------------------------------------------------------------
+-- handle EA_data, data_write
+-----------------------------------------------------------------------------
+PROCESS (clk)
+ BEGIN
+ IF rising_edge(clk) THEN
+ IF Reset = '1' THEN
+ store_in_tmp <='0';
+ exec_write_back <= '0';
+ direct_data <= '0';
+ use_direct_data <= '0';
+ Z_error <= '0';
+ ELSIF clkena_lw='1' THEN
+ direct_data <= '0';
+ IF state="11" THEN
+ exec_write_back <= '0';
+ ELSIF setstate="10" AND write_back='1' THEN
+ exec_write_back <= '1';
+ END IF;
+
+
+ IF set_direct_data='1' THEN
+ direct_data <= '1';
+ use_direct_data <= '1';
+ ELSIF endOPC='1' THEN
+ use_direct_data <= '0';
+ END IF;
+ exec_DIRECT <= set_exec(opcMOVE);
+
+ IF endOPC='1' THEN
+ store_in_tmp <='0';
+ Z_error <= '0';
+ ELSE
+ IF set_Z_error='1' THEN
+ Z_error <= '1';
+ END IF;
+ IF set_exec(opcMOVE)='1' AND state="11" THEN
+ use_direct_data <= '1';
+ END IF;
+
+ IF state="10" THEN
+ store_in_tmp <= '1';
+ END IF;
+ IF direct_data='1' AND state="00" THEN
+ store_in_tmp <= '1';
+ END IF;
+ END IF;
+ IF state="10" THEN
+ ea_data <= data_read;
+ ELSIF exec(get_2ndOPC)='1' THEN
+ ea_data <= addr;
+ ELSIF exec(store_ea_data)='1' OR (direct_data='1' AND state="00") THEN
+ ea_data <= last_data_read;
+ END IF;
+
+ IF writePC='1' THEN
+ data_write_tmp <= TG68_PC;
+ ELSIF exec(writePC_add)='1' THEN
+ data_write_tmp <= TG68_PC_add;
+ ELSIF micro_state=trap0 THEN
+ data_write_tmp(15 downto 0) <= trap_vector(15 downto 0);
+ ELSIF exec(hold_dwr)='1' THEN
+ data_write_tmp <= data_write_tmp;
+ ELSIF exec(exg)='1' THEN
+ data_write_tmp <= OP1out;
+ ELSIF exec(get_ea_now)='1' AND ea_only='1' THEN -- ist fr pea
+ data_write_tmp <= addr;
+ ELSIF execOPC='1' THEN
+ data_write_tmp <= ALUout;
+ ELSIF (exec_DIRECT='1' AND state="10") THEN
+ data_write_tmp <= data_read;
+ IF exec(movepl)='1' THEN
+ data_write_tmp(31 downto 8) <= data_write_tmp(23 downto 0);
+ END IF;
+ ELSIF exec(movepl)='1' THEN
+ data_write_tmp(15 downto 0) <= reg_QB(31 downto 16);
+ ELSIF direct_data='1' THEN
+ data_write_tmp <= last_data_read;
+ ELSIF writeSR='1'THEN
+ data_write_tmp(15 downto 0) <= trap_SR(7 downto 0)& Flags(7 downto 0);
+ ELSE
+ data_write_tmp <= OP2out;
+ END IF;
+ END IF;
+ END IF;
+ END PROCESS;
+
+-----------------------------------------------------------------------------
+-- brief
+-----------------------------------------------------------------------------
+PROCESS (brief, OP1out, OP1outbrief, cpu)
+ BEGIN
+ IF brief(11)='1' THEN
+ OP1outbrief <= OP1out(31 downto 16);
+ ELSE
+ OP1outbrief <= (OTHERS=>OP1out(15));
+ END IF;
+ briefdata <= OP1outbrief&OP1out(15 downto 0);
+ IF extAddr_Mode=1 OR (cpu(1)='1' AND extAddr_Mode=2) THEN
+ CASE brief(10 downto 9) IS
+ WHEN "00" => briefdata <= OP1outbrief&OP1out(15 downto 0);
+ WHEN "01" => briefdata <= OP1outbrief(14 downto 0)&OP1out(15 downto 0)&'0';
+ WHEN "10" => briefdata <= OP1outbrief(13 downto 0)&OP1out(15 downto 0)&"00";
+ WHEN "11" => briefdata <= OP1outbrief(12 downto 0)&OP1out(15 downto 0)&"000";
+ WHEN OTHERS => NULL;
+ END CASE;
+ END IF;
+ END PROCESS;
+
+-----------------------------------------------------------------------------
+-- MEM_IO
+-----------------------------------------------------------------------------
+PROCESS (clk, setdisp, memaddr_a, briefdata, memaddr_delta, setdispbyte, datatype, interrupt, rIPL_nr,
+ memaddr_reg, reg_QA, use_base, VBR, last_data_read, trap_vector, exec, set, cpu)
+ BEGIN
+
+ IF rising_edge(clk) THEN
+ IF clkena_lw='1' THEN
+ trap_vector(31 downto 8) <= (others => '0');
+ -- IF trap_addr_fault='1' THEN
+ -- trap_vector(7 downto 0) <= X"08";
+ -- END IF;
+ IF trap_addr_error='1' THEN
+ trap_vector(7 downto 0) <= X"0C";
+ END IF;
+ IF trap_illegal='1' THEN
+ trap_vector(7 downto 0) <= X"10";
+ END IF;
+ IF z_error='1' THEN
+ trap_vector(7 downto 0) <= X"14";
+ END IF;
+ IF exec(trap_chk)='1' THEN
+ trap_vector(7 downto 0) <= X"18";
+ END IF;
+ IF trap_trapv='1' THEN
+ trap_vector(7 downto 0) <= X"1C";
+ END IF;
+ IF trap_priv='1' THEN
+ trap_vector(7 downto 0) <= X"20";
+ END IF;
+ IF trap_trace='1' THEN
+ trap_vector(7 downto 0) <= X"24";
+ END IF;
+ IF trap_1010='1' THEN
+ trap_vector(7 downto 0) <= X"28";
+ END IF;
+ IF trap_1111='1' THEN
+ trap_vector(7 downto 0) <= X"2C";
+ END IF;
+ IF trap_trap='1' THEN
+ trap_vector(7 downto 2) <= "10"&opcode(3 downto 0);
+ END IF;
+ IF trap_interrupt='1' THEN
+ trap_vector(7 downto 2) <= "011"&rIPL_nr;
+ END IF;
+ END IF;
+ END IF;
+ IF VBR_Stackframe=0 OR (cpu(0)='0' AND VBR_Stackframe=2) THEN
+ trap_vector_vbr <= trap_vector;
+ ELSE
+ trap_vector_vbr <= trap_vector+VBR;
+ END IF;
+
+ memaddr_a(4 downto 0) <= "00000";
+ memaddr_a(7 downto 5) <= (OTHERS=>memaddr_a(4));
+ memaddr_a(15 downto 8) <= (OTHERS=>memaddr_a(7));
+ memaddr_a(31 downto 16) <= (OTHERS=>memaddr_a(15));
+ IF setdisp='1' THEN
+ IF exec(briefext)='1' THEN
+ memaddr_a <= briefdata+memaddr_delta;
+ ELSIF setdispbyte='1' THEN
+ memaddr_a(7 downto 0) <= last_data_read(7 downto 0);
+ ELSE
+ memaddr_a <= last_data_read;
+ END IF;
+ ELSIF set(presub)='1' THEN
+ IF set(longaktion)='1' THEN
+ memaddr_a(4 downto 0) <= "11100";
+ ELSIF datatype="00" AND set(use_SP)='0' THEN
+ memaddr_a(4 downto 0) <= "11111";
+ ELSE
+ memaddr_a(4 downto 0) <= "11110";
+ END IF;
+ ELSIF interrupt='1' THEN
+ memaddr_a(4 downto 0) <= '1'&rIPL_nr&'0';
+ END IF;
+
+ IF rising_edge(clk) THEN
+ IF clkena_in='1' THEN
+-- IF exec(get_2ndOPC)='1' OR (state="10" AND long_start='1') OR (state="10" AND long_start='0' AND datatype/="10") THEN
+-- IF exec(get_2ndOPC)='1' OR (state="10" AND long_start='1') OR (state="10" AND long_start='0' AND datatype/="10" AND odd_done='0') THEN
+ IF exec(get_2ndOPC)='1' OR (state="10" AND memread(0)='1') THEN
+ tmp_TG68_PC <= addr;
+ END IF;
+ use_base <= '0';
+-- IF long_odd_start='1' OR exec(mem_addsub)='1' OR odd_start='1' THEN
+ IF memmaskmux(3)='0' OR exec(mem_addsub)='1' THEN
+ memaddr_delta <= addsub_q;
+ ELSIF state="01" AND exec_write_back='1' THEN
+ memaddr_delta <= tmp_TG68_PC;
+ ELSIF exec(direct_delta)='1' THEN
+ memaddr_delta <= data_read;
+ ELSIF exec(ea_to_pc)='1' AND setstate="00" THEN
+ memaddr_delta <= addr;
+ ELSIF set(addrlong)='1' THEN
+ memaddr_delta <= last_data_read;
+ ELSIF setstate="00" THEN
+ memaddr_delta <= TG68_PC_add;
+ ELSIF exec(dispouter)='1' THEN
+ memaddr_delta <= ea_data+memaddr_a;
+ ELSIF set_vectoraddr='1' THEN
+ memaddr_delta <= trap_vector_vbr;
+ ELSE
+ memaddr_delta <= memaddr_a;
+ IF interrupt='0' AND Suppress_Base='0' THEN
+-- IF interrupt='0' AND Suppress_Base='0' AND setstate(1)='1' THEN
+ use_base <= '1';
+ END IF;
+ END IF;
+
+-- IF clkena_in THEN
+ IF (long_done='0' AND state(1)='1') OR movem_presub='0' THEN
+ memaddr <= addr;
+ END IF;
+-- END IF;
+ END IF;
+ END IF;
+
+ addr <= memaddr_reg+memaddr_delta;
+ IF use_base='0' THEN
+ memaddr_reg <= (others=>'0');
+ ELSE
+ memaddr_reg <= reg_QA;
+ END IF;
+ END PROCESS;
+
+-----------------------------------------------------------------------------
+-- PC Calc + fetch opcode
+-----------------------------------------------------------------------------
+PROCESS (clk, IPL, setstate, state, exec_write_back, set_direct_data, next_micro_state, stop, make_trace, IPL_nr, FlagsSR, set_rot_cnt, opcode, writePCbig, set_exec, exec,
+ PC_dataa, PC_datab, setnextpass, last_data_read, TG68_PC_brw, TG68_PC_word, Z_error, trap_trap, trap_trapv, interrupt, tmp_TG68_PC, TG68_PC)
+ BEGIN
+
+ PC_dataa <= TG68_PC;
+ IF TG68_PC_brw = '1' THEN
+ PC_dataa <= tmp_TG68_PC;
+ END IF;
+
+ PC_datab(2 downto 0) <= (others => '0');
+ PC_datab(3) <= PC_datab(2);
+ PC_datab(7 downto 4) <= (others => PC_datab(3));
+ PC_datab(15 downto 8) <= (others => PC_datab(7));
+ PC_datab(31 downto 16) <= (others => PC_datab(15));
+ IF interrupt='1' THEN
+ PC_datab(2 downto 1) <= "11";
+ END IF;
+ IF exec(writePC_add) ='1' THEN
+ IF writePCbig='1' THEN
+ PC_datab(3) <= '1';
+ PC_datab(1) <= '1';
+ ELSE
+ PC_datab(2) <= '1';
+ END IF;
+ IF trap_trap='1' OR trap_trapv='1' OR exec(trap_chk)='1' OR Z_error='1' THEN
+ PC_datab(1) <= '1';
+ END IF;
+ ELSIF state="00" THEN
+ PC_datab(1) <= '1';
+ END IF;
+ IF TG68_PC_brw = '1' THEN
+ IF TG68_PC_word='1' THEN
+ PC_datab <= last_data_read;
+ ELSE
+ PC_datab(7 downto 0) <= opcode(7 downto 0);
+ END IF;
+ END IF;
+
+ TG68_PC_add <= PC_dataa+PC_datab;
+
+ setopcode <= '0';
+ setendOPC <= '0';
+ setinterrupt <= '0';
+ IF setstate="00" AND next_micro_state=idle AND setnextpass='0' AND (exec_write_back='0' OR state="11") AND set_rot_cnt="000001" AND set_exec(opcCHK)='0'THEN
+ setendOPC <= '1';
+ IF FlagsSR(2 downto 0)
+ set_memmask <= "101111";
+ WHEN "001" =>
+ set_memmask <= "100111";
+ WHEN "010" =>
+ set_memmask <= "100011";
+ WHEN "011" =>
+ set_memmask <= "100001";
+ WHEN OTHERS =>
+ set_memmask <= "100000";
+ END CASE;
+ IF setstate="00" THEN
+ set_memmask <= "100111";
+ END IF;
+ END PROCESS;
+
+------------------------------------------------------------------------------
+--SR op
+------------------------------------------------------------------------------
+PROCESS (clk, Reset, FlagsSR, last_data_read, OP2out, exec)
+ BEGIN
+ IF exec(andiSR)='1' THEN
+ SRin <= FlagsSR AND last_data_read(15 downto 8);
+ ELSIF exec(eoriSR)='1' THEN
+ SRin <= FlagsSR XOR last_data_read(15 downto 8);
+ ELSIF exec(oriSR)='1' THEN
+ SRin <= FlagsSR OR last_data_read(15 downto 8);
+ ELSE
+ SRin <= OP2out(15 downto 8);
+ END IF;
+
+ IF rising_edge(clk) THEN
+ IF Reset='1' THEN
+ FlagsSR(5) <= '1';
+ FC(2) <= '1';
+ SVmode <= '1';
+ preSVmode <= '1';
+ FlagsSR(2 downto 0) <= "111";
+ make_trace <= '0';
+ ELSIF clkena_lw = '1' THEN
+ IF setopcode='1' THEN
+ make_trace <= FlagsSR(7);
+ IF set(changeMode)='1' THEN
+ SVmode <= NOT SVmode;
+ ELSE
+ SVmode <= preSVmode;
+ END IF;
+ END IF;
+ IF set(changeMode)='1' THEN
+ preSVmode <= NOT preSVmode;
+ FlagsSR(5) <= NOT preSVmode;
+ FC(2) <= NOT preSVmode;
+ END IF;
+ IF micro_state=trap3 THEN
+ FlagsSR(7) <= '0';
+ END IF;
+ IF trap_trace='1' AND state="10" THEN
+ make_trace <= '0';
+ END IF;
+ IF exec(directSR)='1' OR set_stop='1' THEN
+ FlagsSR <= data_read(15 downto 8);
+ END IF;
+ IF interrupt='1' AND trap_interrupt='1' THEN
+ FlagsSR(2 downto 0) <=rIPL_nr;
+ END IF;
+-- IF exec(to_CCR)='1' AND exec(to_SR)='1' THEN
+ IF exec(to_SR)='1' THEN
+ FlagsSR(7 downto 0) <= SRin; --SR
+ FC(2) <= SRin(5);
+-- END IF;
+ ELSIF exec(update_FC)='1' THEN
+ FC(2) <= FlagsSR(5);
+ END IF;
+ IF interrupt='1' THEN
+ FC(2) <= '1';
+ END IF;
+ END IF;
+ END IF;
+ END PROCESS;
+
+-----------------------------------------------------------------------------
+-- decode opcode
+-----------------------------------------------------------------------------
+PROCESS (clk, cpu, OP1out, OP2out, opcode, exe_condition, nextpass, micro_state, decodeOPC, state, setexecOPC, Flags, FlagsSR, direct_data, build_logical,
+ build_bcd, set_Z_error, trapd, movem_run, last_data_read, set, set_V_Flag, z_error, trap_trace, trap_interrupt,
+ SVmode, preSVmode, stop, long_done, ea_only, setstate, execOPC, exec_write_back, exe_datatype,
+ datatype, interrupt, c_out, trapmake, rot_cnt, brief, addr,
+ long_start, set_datatype, sndOPC, set_exec, exec, ea_build_now, reg_QA, reg_QB)
+ BEGIN
+ TG68_PC_brw <= '0';
+ setstate <= "00";
+ Regwrena_now <= '0';
+ movem_presub <= '0';
+ setnextpass <= '0';
+ regdirectsource <= '0';
+ setdisp <= '0';
+ setdispbyte <= '0';
+ getbrief <= '0';
+ dest_areg <= '0';
+ source_areg <= '0';
+ data_is_source <= '0';
+ write_back <= '0';
+ setstackaddr <= '0';
+ writePC <= '0';
+ ea_build_now <= '0';
+ set_rot_bits <= "XX";
+ set_rot_cnt <= "000001";
+ dest_hbits <= '0';
+ source_lowbits <= '0';
+ source_2ndHbits <= '0';
+ source_2ndLbits <= '0';
+ dest_2ndHbits <= '0';
+ ea_only <= '0';
+ set_direct_data <= '0';
+ set_exec_tas <= '0';
+ trap_illegal <='0';
+ trap_addr_error <= '0';
+ trap_priv <='0';
+ trap_1010 <='0';
+ trap_1111 <='0';
+ trap_trap <='0';
+ trap_trapv <= '0';
+ trapmake <='0';
+ set_vectoraddr <='0';
+ writeSR <= '0';
+ set_stop <= '0';
+ illegal_write_mode <= '0';
+ illegal_read_mode <= '0';
+ illegal_byteaddr <= '0';
+ set_Z_error <= '0';
+
+ next_micro_state <= idle;
+ build_logical <= '0';
+ build_bcd <= '0';
+ skipFetch <= '0';
+ set_writePCbig <= '0';
+-- set_recall_last <= '0';
+ set_Suppress_Base <= '0';
+ set_PCbase <= '0';
+
+ IF rot_cnt/="000001" THEN
+ set_rot_cnt <= rot_cnt-1;
+ END IF;
+ set_datatype <= datatype;
+
+ set <= (OTHERS=>'0');
+ set_exec <= (OTHERS=>'0');
+ set(update_ld) <= '0';
+-- odd_start <= '0';
+------------------------------------------------------------------------------
+--Sourcepass
+------------------------------------------------------------------------------
+ CASE opcode(7 downto 6) IS
+ WHEN "00" => datatype <= "00"; --Byte
+ WHEN "01" => datatype <= "01"; --Word
+ WHEN OTHERS => datatype <= "10"; --Long
+ END CASE;
+
+ IF trapmake='1' AND trapd='0' THEN
+ next_micro_state <= trap0;
+ IF VBR_Stackframe=0 OR (cpu(0)='0' AND VBR_Stackframe=2) THEN
+ set(writePC_add) <= '1';
+-- set_datatype <= "10";
+ END IF;
+ IF preSVmode='0' THEN
+ set(changeMode) <= '1';
+ END IF;
+ setstate <= "01";
+ END IF;
+ IF micro_state=int1 OR (interrupt='1' AND trap_trace='1') THEN
+ next_micro_state <= trap0;
+-- IF cpu(0)='0' THEN
+-- set_datatype <= "10";
+-- END IF;
+ IF preSVmode='0' THEN
+ set(changeMode) <= '1';
+ END IF;
+ setstate <= "01";
+ END IF;
+
+ IF setexecOPC='1' AND FlagsSR(5)/=preSVmode THEN
+ set(changeMode) <= '1';
+-- setstate <= "01";
+-- next_micro_state <= nop;
+ END IF;
+
+ IF interrupt='1' AND trap_interrupt='1'THEN
+-- skipFetch <= '1';
+ next_micro_state <= int1;
+ set(update_ld) <= '1';
+ setstate <= "10";
+ END IF;
+
+ IF set(changeMode)='1' THEN
+ set(to_USP) <= '1';
+ set(from_USP) <= '1';
+ setstackaddr <='1';
+ END IF;
+
+ IF ea_only='0' AND set(get_ea_now)='1' THEN
+ setstate <= "10";
+-- set_recall_last <= '1';
+-- set(update_ld) <= '0';
+ END IF;
+
+ IF setstate(1)='1' AND set_datatype(1)='1' THEN
+ set(longaktion) <= '1';
+ END IF;
+
+ IF (ea_build_now='1' AND decodeOPC='1') OR exec(ea_build)='1' THEN
+ CASE opcode(5 downto 3) IS --source
+ WHEN "010"|"011"|"100" => -- -(An)+
+ set(get_ea_now) <='1';
+ setnextpass <= '1';
+ IF opcode(3)='1' THEN --(An)+
+ set(postadd) <= '1';
+ IF opcode(2 downto 0)="111" THEN
+ set(use_SP) <= '1';
+ END IF;
+ END IF;
+ IF opcode(5)='1' THEN -- -(An)
+ set(presub) <= '1';
+ IF opcode(2 downto 0)="111" THEN
+ set(use_SP) <= '1';
+ END IF;
+ END IF;
+ WHEN "101" => --(d16,An)
+ next_micro_state <= ld_dAn1;
+ WHEN "110" => --(d8,An,Xn)
+ next_micro_state <= ld_AnXn1;
+ getbrief <='1';
+ WHEN "111" =>
+ CASE opcode(2 downto 0) IS
+ WHEN "000" => --(xxxx).w
+ next_micro_state <= ld_nn;
+ WHEN "001" => --(xxxx).l
+ set(longaktion) <= '1';
+ next_micro_state <= ld_nn;
+ WHEN "010" => --(d16,PC)
+ next_micro_state <= ld_dAn1;
+ set(dispouter) <= '1';
+ set_Suppress_Base <= '1';
+ set_PCbase <= '1';
+ WHEN "011" => --(d8,PC,Xn)
+ next_micro_state <= ld_AnXn1;
+ getbrief <= '1';
+ set(dispouter) <= '1';
+ set_Suppress_Base <= '1';
+ set_PCbase <= '1';
+ WHEN "100" => --#data
+ setnextpass <= '1';
+ set_direct_data <= '1';
+ IF datatype="10" THEN
+ set(longaktion) <= '1';
+ END IF;
+ WHEN OTHERS => NULL;
+ END CASE;
+ WHEN OTHERS => NULL;
+ END CASE;
+ END IF;
+------------------------------------------------------------------------------
+--prepere opcode
+------------------------------------------------------------------------------
+ CASE opcode(15 downto 12) IS
+-- 0000 ----------------------------------------------------------------------------
+ WHEN "0000" =>
+ IF opcode(8)='1' AND opcode(5 downto 3)="001" THEN --movep
+ datatype <= "00"; --Byte
+ set(use_SP) <= '1'; --addr+2
+ set(no_Flags) <='1';
+ IF opcode(7)='0' THEN --to register
+ set_exec(Regwrena) <= '1';
+ set_exec(opcMOVE) <= '1';
+ set(movepl) <= '1';
+ END IF;
+ IF decodeOPC='1' THEN
+ IF opcode(7)='0' THEN
+ set_direct_data <= '1'; -- to register
+ END IF;
+ next_micro_state <= movep1;
+ getbrief <='1';
+ END IF;
+ IF setexecOPC='1' THEN
+ dest_hbits <='1';
+ END IF;
+ ELSE
+ IF opcode(8)='1' OR opcode(11 downto 9)="100" THEN --Bits
+ set_exec(opcBITS) <= '1';
+ set_exec(ea_data_OP1) <= '1';
+ IF opcode(7 downto 6)/="00" THEN
+ IF opcode(5 downto 4)="00" THEN
+ set_exec(Regwrena) <= '1';
+ END IF;
+ write_back <= '1';
+ END IF;
+ IF opcode(5 downto 4)="00" THEN
+ datatype <= "10"; --Long
+ ELSE
+ datatype <= "00"; --Byte
+ END IF;
+ IF opcode(8)='0' THEN
+ IF decodeOPC='1' THEN
+ next_micro_state <= nop;
+ set(get_2ndOPC) <= '1';
+ set(ea_build) <= '1';
+ END IF;
+ ELSE
+ ea_build_now <= '1';
+ END IF;
+ ELSIF opcode(11 downto 9)="111" THEN --MOVES not in 68000
+ trap_illegal <= '1';
+-- trap_addr_error <= '1';
+ trapmake <= '1';
+ ELSE --andi, ...xxxi
+ IF opcode(11 downto 9)="000" THEN --ORI
+ set_exec(opcOR) <= '1';
+ END IF;
+ IF opcode(11 downto 9)="001" THEN --ANDI
+ set_exec(opcAND) <= '1';
+ END IF;
+ IF opcode(11 downto 9)="010" OR opcode(11 downto 9)="011" THEN --SUBI, ADDI
+ set_exec(opcADD) <= '1';
+ END IF;
+ IF opcode(11 downto 9)="101" THEN --EORI
+ set_exec(opcEOR) <= '1';
+ END IF;
+ IF opcode(11 downto 9)="110" THEN --CMPI
+ set_exec(opcCMP) <= '1';
+ END IF;
+ IF opcode(7)='0' AND opcode(5 downto 0)="111100" AND (set_exec(opcAND) OR set_exec(opcOR) OR set_exec(opcEOR))='1' THEN --SR
+ IF decodeOPC='1' AND SVmode='0' AND opcode(6)='1' THEN --SR
+ trap_priv <= '1';
+ trapmake <= '1';
+ ELSE
+ set(no_Flags) <= '1';
+ IF decodeOPC='1' THEN
+ IF opcode(6)='1' THEN
+ set(to_SR) <= '1';
+ END IF;
+ set(to_CCR) <= '1';
+ set(andiSR) <= set_exec(opcAND);
+ set(eoriSR) <= set_exec(opcEOR);
+ set(oriSR) <= set_exec(opcOR);
+ setstate <= "01";
+ next_micro_state <= nopnop;
+ END IF;
+ END IF;
+ ELSE
+ IF decodeOPC='1' THEN
+ next_micro_state <= andi;
+ set(ea_build) <= '1';
+ set_direct_data <= '1';
+ IF datatype="10" THEN
+ set(longaktion) <= '1';
+ END IF;
+ END IF;
+ IF opcode(5 downto 4)/="00" THEN
+ set_exec(ea_data_OP1) <= '1';
+ END IF;
+ IF opcode(11 downto 9)/="110" THEN --CMPI
+ IF opcode(5 downto 4)="00" THEN
+ set_exec(Regwrena) <= '1';
+ END IF;
+ write_back <= '1';
+ END IF;
+ IF opcode(10 downto 9)="10" THEN --CMPI, SUBI
+ set(addsub) <= '1';
+ END IF;
+ END IF;
+ END IF;
+ END IF;
+
+-- 0001, 0010, 0011 -----------------------------------------------------------------
+ WHEN "0001"|"0010"|"0011" => --move.b, move.l, move.w
+ set_exec(opcMOVE) <= '1';
+ ea_build_now <= '1';
+ IF opcode(8 downto 6)="001" THEN
+ set(no_Flags) <= '1';
+ END IF;
+ IF opcode(5 downto 4)="00" THEN --Dn, An
+ IF opcode(8 downto 7)="00" THEN
+ set_exec(Regwrena) <= '1';
+ END IF;
+ END IF;
+ CASE opcode(13 downto 12) IS
+ WHEN "01" => datatype <= "00"; --Byte
+ WHEN "10" => datatype <= "10"; --Long
+ WHEN OTHERS => datatype <= "01"; --Word
+ END CASE;
+ source_lowbits <= '1'; -- Dn=> An=>
+ IF opcode(3)='1' THEN
+ source_areg <= '1';
+ END IF;
+
+ IF nextpass='1' OR opcode(5 downto 4)="00" THEN
+ dest_hbits <= '1';
+ IF opcode(8 downto 6)/="000" THEN
+ dest_areg <= '1';
+ END IF;
+ END IF;
+-- IF setstate="10" THEN
+-- set(update_ld) <= '0';
+-- END IF;
+--
+ IF micro_state=idle AND (nextpass='1' OR (opcode(5 downto 4)="00" AND decodeOPC='1')) THEN
+ CASE opcode(8 downto 6) IS --destination
+ WHEN "000"|"001" => --Dn,An
+ set_exec(Regwrena) <= '1';
+ WHEN "010"|"011"|"100" => --destination -(an)+
+ IF opcode(6)='1' THEN --(An)+
+ set(postadd) <= '1';
+ IF opcode(11 downto 9)="111" THEN
+ set(use_SP) <= '1';
+ END IF;
+ END IF;
+ IF opcode(8)='1' THEN -- -(An)
+ set(presub) <= '1';
+ IF opcode(11 downto 9)="111" THEN
+ set(use_SP) <= '1';
+ END IF;
+ END IF;
+ setstate <= "11";
+ next_micro_state <= nop;
+ IF nextpass='0' THEN
+ set(write_reg) <= '1';
+ END IF;
+ WHEN "101" => --(d16,An)
+ next_micro_state <= st_dAn1;
+-- getbrief <= '1';
+ WHEN "110" => --(d8,An,Xn)
+ next_micro_state <= st_AnXn1;
+ getbrief <= '1';
+ WHEN "111" =>
+ CASE opcode(11 downto 9) IS
+ WHEN "000" => --(xxxx).w
+ next_micro_state <= st_nn;
+ WHEN "001" => --(xxxx).l
+ set(longaktion) <= '1';
+ next_micro_state <= st_nn;
+ WHEN OTHERS => NULL;
+ END CASE;
+ WHEN OTHERS => NULL;
+ END CASE;
+ END IF;
+---- 0100 ----------------------------------------------------------------------------
+ WHEN "0100" => --rts_group
+ IF opcode(8)='1' THEN --lea
+ IF opcode(6)='1' THEN --lea
+ IF opcode(7)='1' THEN
+ source_lowbits <= '1';
+-- IF opcode(5 downto 3)="000" AND opcode(10)='0' THEN --ext
+ IF opcode(5 downto 4)="00" THEN --extb.l
+ set_exec(opcEXT) <= '1';
+ set_exec(opcMOVE) <= '1';
+ set_exec(Regwrena) <= '1';
+-- IF opcode(6)='0' THEN
+-- datatype <= "01"; --WORD
+-- END IF;
+ ELSE
+ source_areg <= '1';
+ ea_only <= '1';
+ set_exec(Regwrena) <= '1';
+ set_exec(opcMOVE) <='1';
+ set(no_Flags) <='1';
+ IF opcode(5 downto 3)="010" THEN --lea (Am),An
+ dest_areg <= '1';
+ dest_hbits <= '1';
+ ELSE
+ ea_build_now <= '1';
+ END IF;
+ IF set(get_ea_now)='1' THEN
+ setstate <= "01";
+ set_direct_data <= '1';
+ END IF;
+ IF setexecOPC='1' THEN
+ dest_areg <= '1';
+ dest_hbits <= '1';
+ END IF;
+ END IF;
+ ELSE
+ trap_illegal <= '1';
+ trapmake <= '1';
+ END IF;
+ ELSE --chk
+ IF opcode(7)='1' THEN
+ datatype <= "01"; --Word
+ set(trap_chk) <= '1';
+ IF (c_out(1)='0' OR OP1out(15)='1' OR OP2out(15)='1') AND exec(opcCHK)='1' THEN
+ trapmake <= '1';
+ END IF;
+ ELSIF cpu(1)='1' THEN --chk long for 68020
+ datatype <= "10"; --Long
+ set(trap_chk) <= '1';
+ IF (c_out(2)='1' OR OP1out(31)='1' OR OP2out(31)='1') AND exec(opcCHK)='1' THEN
+ trapmake <= '1';
+ END IF;
+ ELSE
+ trap_illegal <= '1'; -- chk long for 68020
+ trapmake <= '1';
+ END IF;
+ IF opcode(7)='1' OR cpu(1)='1' THEN
+ IF (nextpass='1' OR opcode(5 downto 4)="00") AND exec(opcCHK)='0' AND micro_state=idle THEN
+ set_exec(opcCHK) <= '1';
+ END IF;
+ ea_build_now <= '1';
+ set(addsub) <= '1';
+ IF setexecOPC='1' THEN
+ dest_hbits <= '1';
+ source_lowbits <='1';
+ END IF;
+ END IF;
+ END IF;
+ ELSE
+ CASE opcode(11 downto 9) IS
+ WHEN "000"=>
+ IF opcode(7 downto 6)="11" THEN --move from SR
+ IF SR_Read=0 OR (cpu(0)='0' AND SR_Read=2) OR SVmode='1' THEN
+-- IF SVmode='1' THEN
+ ea_build_now <= '1';
+ set_exec(opcMOVESR) <= '1';
+ datatype <= "01";
+ write_back <='1'; -- im 68000 wird auch erst gelesen
+ IF cpu(0)='1' AND state="10" THEN
+ skipFetch <= '1';
+ END IF;
+ IF opcode(5 downto 4)="00" THEN
+ set_exec(Regwrena) <= '1';
+ END IF;
+ ELSE
+ trap_priv <= '1';
+ trapmake <= '1';
+ END IF;
+ ELSE --negx
+ ea_build_now <= '1';
+ set_exec(use_XZFlag) <= '1';
+ write_back <='1';
+ set_exec(opcADD) <= '1';
+ set(addsub) <= '1';
+ source_lowbits <= '1';
+ IF opcode(5 downto 4)="00" THEN
+ set_exec(Regwrena) <= '1';
+ END IF;
+ IF setexecOPC='1' THEN
+ set(OP1out_zero) <= '1';
+ END IF;
+ END IF;
+ WHEN "001"=>
+ IF opcode(7 downto 6)="11" THEN --move from CCR 68010
+ IF SR_Read=1 OR (cpu(0)='1' AND SR_Read=2) THEN
+ ea_build_now <= '1';
+ set_exec(opcMOVESR) <= '1';
+ datatype <= "00";
+ write_back <='1'; -- im 68000 wird auch erst gelesen
+ IF opcode(5 downto 4)="00" THEN
+ set_exec(Regwrena) <= '1';
+ END IF;
+ ELSE
+ trap_illegal <= '1';
+ trapmake <= '1';
+ END IF;
+ ELSE --clr
+ ea_build_now <= '1';
+ write_back <='1';
+ set_exec(opcAND) <= '1';
+ IF cpu(0)='1' AND state="10" THEN
+ skipFetch <= '1';
+ END IF;
+ IF setexecOPC='1' THEN
+ set(OP1out_zero) <= '1';
+ END IF;
+ IF opcode(5 downto 4)="00" THEN
+ set_exec(Regwrena) <= '1';
+ END IF;
+ END IF;
+ WHEN "010"=>
+ ea_build_now <= '1';
+ IF opcode(7 downto 6)="11" THEN --move to CCR
+ datatype <= "01";
+ source_lowbits <= '1';
+ IF (decodeOPC='1' AND opcode(5 downto 4)="00") OR state="10" OR direct_data='1' THEN
+ set(to_CCR) <= '1';
+ END IF;
+ ELSE --neg
+ write_back <='1';
+ set_exec(opcADD) <= '1';
+ set(addsub) <= '1';
+ source_lowbits <= '1';
+ IF opcode(5 downto 4)="00" THEN
+ set_exec(Regwrena) <= '1';
+ END IF;
+ IF setexecOPC='1' THEN
+ set(OP1out_zero) <= '1';
+ END IF;
+ END IF;
+ WHEN "011"=> --not, move toSR
+ IF opcode(7 downto 6)="11" THEN --move to SR
+ IF SVmode='1' THEN
+ ea_build_now <= '1';
+ datatype <= "01";
+ source_lowbits <= '1';
+ IF (decodeOPC='1' AND opcode(5 downto 4)="00") OR state="10" OR direct_data='1' THEN
+ set(to_SR) <= '1';
+ set(to_CCR) <= '1';
+ END IF;
+ IF exec(to_SR)='1' OR (decodeOPC='1' AND opcode(5 downto 4)="00") OR state="10" OR direct_data='1' THEN
+ setstate <="01";
+ END IF;
+ ELSE
+ trap_priv <= '1';
+ trapmake <= '1';
+ END IF;
+ ELSE --not
+ ea_build_now <= '1';
+ write_back <='1';
+ set_exec(opcEOR) <= '1';
+ set_exec(ea_data_OP1) <= '1';
+ IF opcode(5 downto 3)="000" THEN
+ set_exec(Regwrena) <= '1';
+ END IF;
+ IF setexecOPC='1' THEN
+ set(OP2out_one) <= '1';
+ END IF;
+ END IF;
+ WHEN "100"|"110"=>
+ IF opcode(7)='1' THEN --movem, ext
+ IF opcode(5 downto 3)="000" AND opcode(10)='0' THEN --ext
+ source_lowbits <= '1';
+ set_exec(opcEXT) <= '1';
+ set_exec(opcMOVE) <= '1';
+ set_exec(Regwrena) <= '1';
+ IF opcode(6)='0' THEN
+ datatype <= "01"; --WORD
+ END IF;
+ ELSE --movem
+-- IF opcode(11 downto 7)="10001" OR opcode(11 downto 7)="11001" THEN --MOVEM
+ ea_only <= '1';
+ set(no_Flags) <= '1';
+ IF opcode(6)='0' THEN
+ datatype <= "01"; --Word transfer
+ END IF;
+ IF opcode(5 downto 3)="100" OR opcode(5 downto 3)="011" THEN -- -(An), (An)+
+ set_exec(save_memaddr) <= '1';
+ set_exec(Regwrena) <= '1';
+ END IF;
+ IF opcode(5 downto 3)="100" THEN -- -(An)
+ movem_presub <= '1';
+ set(subidx) <= '1';
+ END IF;
+ IF state="10" THEN
+ set(Regwrena) <= '1';
+ set(opcMOVE) <= '1';
+ END IF;
+ IF decodeOPC='1' THEN
+ set(get_2ndOPC) <='1';
+ IF opcode(5 downto 3)="010" OR opcode(5 downto 3)="011" OR opcode(5 downto 3)="100" THEN
+ next_micro_state <= movem1;
+ ELSE
+ next_micro_state <= nop;
+ set(ea_build) <= '1';
+ END IF;
+ END IF;
+ IF set(get_ea_now)='1' THEN
+ IF movem_run='1' THEN
+ set(movem_action) <= '1';
+ IF opcode(10)='0' THEN
+ setstate <="11";
+ set(write_reg) <= '1';
+ ELSE
+ setstate <="10";
+ END IF;
+ next_micro_state <= movem2;
+ set(mem_addsub) <= '1';
+ ELSE
+ setstate <="01";
+ END IF;
+ END IF;
+ END IF;
+ ELSE
+ IF opcode(10)='1' THEN --MUL.L, DIV.L 68020
+-- IF cpu(1)='1' THEN
+ IF (opcode(6)='1' AND (DIV_Mode=1 OR (cpu(1)='1' AND DIV_Mode=2))) OR
+ (opcode(6)='0' AND (MUL_Mode=1 OR (cpu(1)='1' AND MUL_Mode=2))) THEN
+ IF decodeOPC='1' THEN
+ next_micro_state <= nop;
+ set(get_2ndOPC) <= '1';
+ set(ea_build) <= '1';
+ END IF;
+ IF (micro_state=idle AND nextpass='1') OR (opcode(5 downto 4)="00" AND exec(ea_build)='1')THEN
+ setstate <="01";
+ dest_2ndHbits <= '1';
+ source_2ndLbits <= '1';
+ IF opcode(6)='1' THEN
+ next_micro_state <= div1;
+ ELSE
+ next_micro_state <= mul1;
+ set(ld_rot_cnt) <= '1';
+ END IF;
+ END IF;
+ IF z_error='0' AND set_V_Flag='0' AND set(opcDIVU)='1' THEN
+ set(Regwrena) <= '1';
+ END IF;
+ source_lowbits <='1';
+ IF nextpass='1' OR (opcode(5 downto 4)="00" AND decodeOPC='1') THEN
+ dest_hbits <= '1';
+ END IF;
+ datatype <= "10";
+ ELSE
+ trap_illegal <= '1';
+ trapmake <= '1';
+ END IF;
+
+ ELSE --pea, swap
+ IF opcode(6)='1' THEN
+ datatype <= "10";
+ IF opcode(5 downto 3)="000" THEN --swap
+ set_exec(opcSWAP) <= '1';
+ set_exec(Regwrena) <= '1';
+ ELSIF opcode(5 downto 3)="001" THEN --bkpt
+
+ ELSE --pea
+ ea_only <= '1';
+ ea_build_now <= '1';
+ IF nextpass='1' AND micro_state=idle THEN
+ set(presub) <= '1';
+ setstackaddr <='1';
+ setstate <="11";
+ next_micro_state <= nop;
+ END IF;
+ IF set(get_ea_now)='1' THEN
+ setstate <="01";
+ END IF;
+ END IF;
+ ELSE
+ IF opcode(5 downto 3)="001" THEN --link.l
+ datatype <= "10";
+ set_exec(opcADD) <= '1'; --fr displacement
+ set_exec(Regwrena) <= '1';
+ set(no_Flags) <= '1';
+ IF decodeOPC='1' THEN
+ set(linksp) <= '1';
+ set(longaktion) <= '1';
+ next_micro_state <= link1;
+ set(presub) <= '1';
+ setstackaddr <='1';
+ set(mem_addsub) <= '1';
+ source_lowbits <= '1';
+ source_areg <= '1';
+ set(store_ea_data) <= '1';
+ END IF;
+ ELSE --nbcd
+ ea_build_now <= '1';
+ set_exec(use_XZFlag) <= '1';
+ write_back <='1';
+ set_exec(opcADD) <= '1';
+ set_exec(opcSBCD) <= '1';
+ source_lowbits <= '1';
+ IF opcode(5 downto 4)="00" THEN
+ set_exec(Regwrena) <= '1';
+ END IF;
+ IF setexecOPC='1' THEN
+ set(OP1out_zero) <= '1';
+ END IF;
+ END IF;
+ END IF;
+ END IF;
+ END IF;
+--
+ WHEN "101"=> --tst, tas 4aFC - illegal
+ IF opcode(7 downto 2)="111111" THEN --illegal
+ trap_illegal <= '1';
+ trapmake <= '1';
+ ELSE
+ ea_build_now <= '1';
+ IF setexecOPC='1' THEN
+ source_lowbits <= '1';
+ IF opcode(3)='1' THEN --MC68020...
+ source_areg <= '1';
+ END IF;
+ END IF;
+ set_exec(opcMOVE) <= '1';
+ IF opcode(7 downto 6)="11" THEN --tas
+ set_exec_tas <= '1';
+ write_back <= '1';
+ datatype <= "00"; --Byte
+ IF opcode(5 downto 4)="00" THEN
+ set_exec(Regwrena) <= '1';
+ END IF;
+ END IF;
+ END IF;
+---- WHEN "110"=>
+ WHEN "111"=> --4EXX
+--
+-- ea_only <= '1';
+-- ea_build_now <= '1';
+-- IF nextpass='1' AND micro_state=idle THEN
+-- set(presub) <= '1';
+-- setstackaddr <='1';
+-- set(mem_addsub) <= '1';
+-- setstate <="11";
+-- next_micro_state <= nop;
+-- END IF;
+-- IF set(get_ea_now)='1' THEN
+-- setstate <="01";
+-- END IF;
+--
+
+
+
+ IF opcode(7)='1' THEN --jsr, jmp
+ datatype <= "10";
+ ea_only <= '1';
+ ea_build_now <= '1';
+ IF exec(ea_to_pc)='1' THEN
+ next_micro_state <= nop;
+ END IF;
+ IF nextpass='1' AND micro_state=idle AND opcode(6)='0' THEN
+ set(presub) <= '1';
+ setstackaddr <='1';
+ setstate <="11";
+ next_micro_state <= nopnop;
+ END IF;
+-- achtung buggefahr
+ IF micro_state=ld_AnXn1 AND brief(8)='0'THEN --JMP/JSR n(Ax,Dn)
+ skipFetch <= '1';
+ END IF;
+ IF state="00" THEN
+ writePC <= '1';
+ END IF;
+ set(hold_dwr) <= '1';
+ IF set(get_ea_now)='1' THEN --jsr
+ IF exec(longaktion)='0' OR long_done='1' THEN
+ skipFetch <= '1';
+ END IF;
+ setstate <="01";
+ set(ea_to_pc) <= '1';
+ END IF;
+ ELSE --
+ CASE opcode(6 downto 0) IS
+ WHEN "1000000"|"1000001"|"1000010"|"1000011"|"1000100"|"1000101"|"1000110"|"1000111"| --trap
+ "1001000"|"1001001"|"1001010"|"1001011"|"1001100"|"1001101"|"1001110"|"1001111" => --trap
+ trap_trap <='1';
+ trapmake <= '1';
+ WHEN "1010000"|"1010001"|"1010010"|"1010011"|"1010100"|"1010101"|"1010110"|"1010111"=> --link
+ datatype <= "10";
+ set_exec(opcADD) <= '1'; --fr displacement
+ set_exec(Regwrena) <= '1';
+ set(no_Flags) <= '1';
+ IF decodeOPC='1' THEN
+ next_micro_state <= link1;
+ set(presub) <= '1';
+ setstackaddr <='1';
+ set(mem_addsub) <= '1';
+ source_lowbits <= '1';
+ source_areg <= '1';
+ set(store_ea_data) <= '1';
+ END IF;
+
+ WHEN "1011000"|"1011001"|"1011010"|"1011011"|"1011100"|"1011101"|"1011110"|"1011111" => --unlink
+ datatype <= "10";
+ set_exec(Regwrena) <= '1';
+ set_exec(opcMOVE) <= '1';
+ set(no_Flags) <= '1';
+ IF decodeOPC='1' THEN
+ setstate <= "01";
+ next_micro_state <= unlink1;
+ set(opcMOVE) <= '1';
+ set(Regwrena) <= '1';
+ setstackaddr <='1';
+ source_lowbits <= '1';
+ source_areg <= '1';
+ END IF;
+
+ WHEN "1100000"|"1100001"|"1100010"|"1100011"|"1100100"|"1100101"|"1100110"|"1100111" => --move An,USP
+ IF SVmode='1' THEN
+-- set(no_Flags) <= '1';
+ set(to_USP) <= '1';
+ source_lowbits <= '1';
+ source_areg <= '1';
+ datatype <= "10";
+ ELSE
+ trap_priv <= '1';
+ trapmake <= '1';
+ END IF;
+ WHEN "1101000"|"1101001"|"1101010"|"1101011"|"1101100"|"1101101"|"1101110"|"1101111" => --move USP,An
+ IF SVmode='1' THEN
+-- set(no_Flags) <= '1';
+ set(from_USP) <= '1';
+ datatype <= "10";
+ set_exec(Regwrena) <= '1';
+ ELSE
+ trap_priv <= '1';
+ trapmake <= '1';
+ END IF;
+
+ WHEN "1110000" => --reset
+ IF SVmode='0' THEN
+ trap_priv <= '1';
+ trapmake <= '1';
+ ELSE
+ set(opcRESET) <= '1';
+ IF decodeOPC='1' THEN
+ set(ld_rot_cnt) <= '1';
+ set_rot_cnt <= "000000";
+ END IF;
+ END IF;
+
+ WHEN "1110001" => --nop
+
+ WHEN "1110010" => --stop
+ IF SVmode='0' THEN
+ trap_priv <= '1';
+ trapmake <= '1';
+ ELSE
+ IF decodeOPC='1' THEN
+ setnextpass <= '1';
+ set_stop <= '1';
+ END IF;
+ IF stop='1' THEN
+ skipFetch <= '1';
+ END IF;
+
+ END IF;
+
+ WHEN "1110011"|"1110111" => --rte/rtr
+ IF SVmode='1' OR opcode(2)='1' THEN
+ IF decodeOPC='1' THEN
+ setstate <= "10";
+ set(postadd) <= '1';
+ setstackaddr <= '1';
+ IF opcode(2)='1' THEN
+ set(directCCR) <= '1';
+ ELSE
+ set(directSR) <= '1';
+ END IF;
+ next_micro_state <= rte1;
+ END IF;
+ ELSE
+ trap_priv <= '1';
+ trapmake <= '1';
+ END IF;
+
+ WHEN "1110101" => --rts
+ datatype <= "10";
+ IF decodeOPC='1' THEN
+ setstate <= "10";
+ set(postadd) <= '1';
+ setstackaddr <= '1';
+ set(direct_delta) <= '1';
+ set(directPC) <= '1';
+ next_micro_state <= nopnop;
+ END IF;
+
+ WHEN "1110110" => --trapv
+ IF decodeOPC='1' THEN
+ setstate <= "01";
+ END IF;
+ IF Flags(1)='1' AND state="01" THEN
+ trap_trapv <= '1';
+ trapmake <= '1';
+ END IF;
+
+ WHEN "1111010"|"1111011" => --movec
+ IF VBR_Stackframe=0 OR (cpu(0)='0' AND VBR_Stackframe=2) THEN
+ trap_illegal <= '1';
+ trapmake <= '1';
+ ELSIF SVmode='0' THEN
+ trap_priv <= '1';
+ trapmake <= '1';
+ ELSE
+ datatype <= "10"; --Long
+ IF last_data_read(11 downto 0)=X"800" THEN
+ set(from_USP) <= '1';
+ IF opcode(0)='1' THEN
+ set(to_USP) <= '1';
+ END IF;
+ END IF;
+ IF opcode(0)='0' THEN
+ set_exec(movec_rd) <= '1';
+ ELSE
+ set_exec(movec_wr) <= '1';
+ END IF;
+ IF decodeOPC='1' THEN
+ next_micro_state <= movec1;
+ getbrief <='1';
+ END IF;
+ END IF;
+
+ WHEN OTHERS =>
+ trap_illegal <= '1';
+ trapmake <= '1';
+ END CASE;
+ END IF;
+ WHEN OTHERS => NULL;
+ END CASE;
+ END IF;
+--
+---- 0101 ----------------------------------------------------------------------------
+ WHEN "0101" => --subq, addq
+
+ IF opcode(7 downto 6)="11" THEN --dbcc
+ IF opcode(5 downto 3)="001" THEN --dbcc
+ IF decodeOPC='1' THEN
+ next_micro_state <= dbcc1;
+ set(OP2out_one) <= '1';
+ data_is_source <= '1';
+ END IF;
+ ELSE --Scc
+ datatype <= "00"; --Byte
+ ea_build_now <= '1';
+ write_back <= '1';
+ set_exec(opcScc) <= '1';
+ IF cpu(0)='1' AND state="10" THEN
+ skipFetch <= '1';
+ END IF;
+ IF opcode(5 downto 4)="00" THEN
+ set_exec(Regwrena) <= '1';
+ END IF;
+ END IF;
+ ELSE --addq, subq
+ ea_build_now <= '1';
+ IF opcode(5 downto 3)="001" THEN
+ set(no_Flags) <= '1';
+ END IF;
+ IF opcode(8)='1' THEN
+ set(addsub) <= '1';
+ END IF;
+ write_back <= '1';
+ set_exec(opcADDQ) <= '1';
+ set_exec(opcADD) <= '1';
+ set_exec(ea_data_OP1) <= '1';
+ IF opcode(5 downto 4)="00" THEN
+ set_exec(Regwrena) <= '1';
+ END IF;
+ END IF;
+--
+---- 0110 ----------------------------------------------------------------------------
+ WHEN "0110" => --bra,bsr,bcc
+ datatype <= "10";
+
+ IF micro_state=idle THEN
+ IF opcode(11 downto 8)="0001" THEN --bsr
+ set(presub) <= '1';
+ setstackaddr <='1';
+ IF opcode(7 downto 0)="11111111" THEN
+ next_micro_state <= bsr2;
+ set(longaktion) <= '1';
+ ELSIF opcode(7 downto 0)="00000000" THEN
+ next_micro_state <= bsr2;
+ ELSE
+ next_micro_state <= bsr1;
+ setstate <= "11";
+ writePC <= '1';
+ END IF;
+ ELSE --bra
+ IF opcode(7 downto 0)="11111111" THEN
+ next_micro_state <= bra1;
+ set(longaktion) <= '1';
+ ELSIF opcode(7 downto 0)="00000000" THEN
+ next_micro_state <= bra1;
+ ELSE
+ setstate <= "01";
+ next_micro_state <= bra1;
+ END IF;
+ END IF;
+ END IF;
+
+-- 0111 ----------------------------------------------------------------------------
+ WHEN "0111" => --moveq
+ IF opcode(8)='0' THEN
+ IF trap_interrupt='0' AND trap_trace='0' THEN
+ datatype <= "10"; --Long
+ set_exec(Regwrena) <= '1';
+ set_exec(opcMOVEQ) <= '1';
+ set_exec(opcMOVE) <= '1';
+ dest_hbits <= '1';
+ END IF;
+ ELSE
+ trap_illegal <= '1';
+ trapmake <= '1';
+ END IF;
+
+---- 1000 ----------------------------------------------------------------------------
+ WHEN "1000" => --or
+ IF opcode(7 downto 6)="11" THEN --divu, divs
+ IF DIV_Mode/=3 THEN
+ IF opcode(5 downto 4)="00" THEN --Dn, An
+ regdirectsource <= '1';
+ END IF;
+ IF (micro_state=idle AND nextpass='1') OR (opcode(5 downto 4)="00" AND decodeOPC='1') THEN
+ setstate <="01";
+ next_micro_state <= div1;
+ END IF;
+ ea_build_now <= '1';
+ IF z_error='0' AND set_V_Flag='0' THEN
+ set_exec(Regwrena) <= '1';
+ END IF;
+ source_lowbits <='1';
+ IF nextpass='1' OR (opcode(5 downto 4)="00" AND decodeOPC='1') THEN
+ dest_hbits <= '1';
+ END IF;
+ datatype <= "01";
+ ELSE
+ trap_illegal <= '1';
+ trapmake <= '1';
+ END IF;
+
+ ELSIF opcode(8)='1' AND opcode(5 downto 4)="00" THEN --sbcd, pack , unpack
+ IF opcode(7 downto 6)="00" THEN --sbcd
+ build_bcd <= '1';
+ set_exec(opcADD) <= '1';
+ set_exec(opcSBCD) <= '1';
+ ELSE --pack, unpack
+ trap_illegal <= '1';
+ trapmake <= '1';
+ END IF;
+ ELSE --or
+ set_exec(opcOR) <= '1';
+ build_logical <= '1';
+ END IF;
+
+---- 1001, 1101 -----------------------------------------------------------------------
+ WHEN "1001"|"1101" => --sub, add
+ set_exec(opcADD) <= '1';
+ ea_build_now <= '1';
+ IF opcode(14)='0' THEN
+ set(addsub) <= '1';
+ END IF;
+ IF opcode(7 downto 6)="11" THEN -- --adda, suba
+ IF opcode(8)='0' THEN --adda.w, suba.w
+ datatype <= "01"; --Word
+ END IF;
+ set_exec(Regwrena) <= '1';
+ source_lowbits <='1';
+ IF opcode(3)='1' THEN
+ source_areg <= '1';
+ END IF;
+ set(no_Flags) <= '1';
+ IF setexecOPC='1' THEN
+ dest_areg <='1';
+ dest_hbits <= '1';
+ END IF;
+ ELSE
+ IF opcode(8)='1' AND opcode(5 downto 4)="00" THEN --addx, subx
+ build_bcd <= '1';
+ ELSE --sub, add
+ build_logical <= '1';
+ END IF;
+ END IF;
+
+--
+---- 1010 ----------------------------------------------------------------------------
+ WHEN "1010" => --Trap 1010
+ trap_1010 <= '1';
+ trapmake <= '1';
+---- 1011 ----------------------------------------------------------------------------
+ WHEN "1011" => --eor, cmp
+ ea_build_now <= '1';
+ IF opcode(7 downto 6)="11" THEN --CMPA
+ IF opcode(8)='0' THEN --cmpa.w
+ datatype <= "01"; --Word
+ set_exec(opcCPMAW) <= '1';
+ END IF;
+ set_exec(opcCMP) <= '1';
+ IF setexecOPC='1' THEN
+ source_lowbits <='1';
+ IF opcode(3)='1' THEN
+ source_areg <= '1';
+ END IF;
+ dest_areg <='1';
+ dest_hbits <= '1';
+ END IF;
+ set(addsub) <= '1';
+ ELSE
+ IF opcode(8)='1' THEN
+ IF opcode(5 downto 3)="001" THEN --cmpm
+ set_exec(opcCMP) <= '1';
+ IF decodeOPC='1' THEN
+ setstate <= "10";
+ set(update_ld) <= '1';
+ set(postadd) <= '1';
+ next_micro_state <= cmpm;
+ END IF;
+ set_exec(ea_data_OP1) <= '1';
+ set(addsub) <= '1';
+ ELSE --EOR
+ build_logical <= '1';
+ set_exec(opcEOR) <= '1';
+ END IF;
+ ELSE --CMP
+ build_logical <= '1';
+ set_exec(opcCMP) <= '1';
+ set(addsub) <= '1';
+ END IF;
+ END IF;
+--
+---- 1100 ----------------------------------------------------------------------------
+ WHEN "1100" => --and, exg
+ IF opcode(7 downto 6)="11" THEN --mulu, muls
+ IF MUL_Mode/=3 THEN
+ IF opcode(5 downto 4)="00" THEN --Dn, An
+ regdirectsource <= '1';
+ END IF;
+ IF (micro_state=idle AND nextpass='1') OR (opcode(5 downto 4)="00" AND decodeOPC='1') THEN
+ setstate <="01";
+ set(ld_rot_cnt) <= '1';
+ next_micro_state <= mul1;
+ END IF;
+ ea_build_now <= '1';
+ set_exec(Regwrena) <= '1';
+ source_lowbits <='1';
+ IF (nextpass='1') OR (opcode(5 downto 4)="00" AND decodeOPC='1') THEN
+ dest_hbits <= '1';
+ END IF;
+ datatype <= "01";
+ ELSE
+ trap_illegal <= '1';
+ trapmake <= '1';
+ END IF;
+
+ ELSIF opcode(8)='1' AND opcode(5 downto 4)="00" THEN --exg, abcd
+ IF opcode(7 downto 6)="00" THEN --abcd
+ build_bcd <= '1';
+ set_exec(opcADD) <= '1';
+ set_exec(opcABCD) <= '1';
+ ELSE --exg
+ datatype <= "10";
+ set(Regwrena) <= '1';
+ set(exg) <= '1';
+ IF opcode(6)='1' AND opcode(3)='1' THEN
+ dest_areg <= '1';
+ source_areg <= '1';
+ END IF;
+ IF decodeOPC='1' THEN
+ setstate <= "01";
+ ELSE
+ dest_hbits <= '1';
+ END IF;
+ END IF;
+ ELSE --and
+ set_exec(opcAND) <= '1';
+ build_logical <= '1';
+ END IF;
+--
+---- 1110 ----------------------------------------------------------------------------
+ WHEN "1110" => --rotation / bitfield
+ IF opcode(7 downto 6)="11" THEN
+ IF opcode(11)='0' THEN
+ set_exec(opcROT) <= '1';
+ ea_build_now <= '1';
+ datatype <= "01";
+ set_rot_bits <= opcode(10 downto 9);
+ set_exec(ea_data_OP1) <= '1';
+ write_back <= '1';
+ ELSE --bitfield
+ IF BitField=0 OR (cpu(1)='0' AND BitField=2) THEN
+ trap_illegal <= '1';
+ trapmake <= '1';
+ ELSE
+ IF decodeOPC='1' THEN
+ next_micro_state <= nop;
+ set(get_2ndOPC) <= '1';
+ set(ea_build) <= '1';
+ END IF;
+ set_exec(opcBF) <= '1';
+ IF opcode(10)='1' OR opcode(8)='0' THEN
+ set_exec(opcBFwb) <= '1';
+-- END IF;
+-- IF opcode(10 downto 8)="111" THEN
+ set_exec(ea_data_OP1) <= '1';
+ END IF;
+ IF opcode(10 downto 8)="010" OR opcode(10 downto 8)="100" OR opcode(10 downto 8)="110" OR opcode(10 downto 8)="111" THEN
+ write_back <= '1';
+ END IF;
+ ea_only <= '1';
+ IF opcode(10 downto 8)="001" OR opcode(10 downto 8)="011" OR opcode(10 downto 8)="101" THEN
+ set_exec(Regwrena) <= '1';
+ END IF;
+ IF opcode(4 downto 3)="00" THEN
+ set_exec(Regwrena) <= '1';
+ IF exec(ea_build)='1' THEN
+ dest_2ndHbits <= '1';
+ source_2ndLbits <= '1';
+ set(get_bfoffset) <='1';
+ setstate <= "01";
+ END IF;
+ END IF;
+ IF set(get_ea_now)='1' THEN
+ setstate <= "01";
+ END IF;
+ IF exec(get_ea_now)='1' THEN
+ dest_2ndHbits <= '1';
+ source_2ndLbits <= '1';
+ set(get_bfoffset) <='1';
+ setstate <= "01";
+ set(mem_addsub) <='1';
+ next_micro_state <= bf1;
+ END IF;
+
+-- BFINS D1,D0 s2ndHbits < D0
+-- BFEXT D0,D1 sLbits >>D0 -> D1 d2ndHbits
+-- BFINS D1,(A0) s2ndHbits < (A0)
+-- BFEXT (A0),D1 >>(A0) -> D1 d2ndHbits
+ IF setexecOPC='1' THEN
+ IF opcode(10 downto 8)="111" THEN --BFINS
+ source_2ndHbits <= '1';
+ ELSE
+ source_lowbits <= '1';
+ dest_2ndHbits <= '1';
+ END IF;
+ END IF;
+ END IF;
+ END IF;
+ ELSE
+ set_exec(opcROT) <= '1';
+ set_rot_bits <= opcode(4 downto 3);
+ data_is_source <= '1';
+ set_exec(Regwrena) <= '1';
+ IF decodeOPC='1' THEN
+ IF opcode(5)='1' THEN
+ next_micro_state <= rota1;
+ set(ld_rot_cnt) <= '1';
+ setstate <= "01";
+ ELSE
+ set_rot_cnt(2 downto 0) <= opcode(11 downto 9);
+ IF opcode(11 downto 9)="000" THEN
+ set_rot_cnt(3) <='1';
+ ELSE
+ set_rot_cnt(3) <='0';
+ END IF;
+ END IF;
+ END IF;
+ END IF;
+--
+---- ----------------------------------------------------------------------------
+ WHEN OTHERS =>
+ trap_1111 <= '1';
+ trapmake <= '1';
+
+ END CASE;
+
+-- use for AND, OR, EOR, CMP
+ IF build_logical='1' THEN
+ ea_build_now <= '1';
+ IF set_exec(opcCMP)='0' AND (opcode(8)='0' OR opcode(5 downto 4)="00" ) THEN
+ set_exec(Regwrena) <= '1';
+ END IF;
+ IF opcode(8)='1' THEN
+ write_back <= '1';
+ set_exec(ea_data_OP1) <= '1';
+ ELSE
+ source_lowbits <='1';
+ IF opcode(3)='1' THEN --use for cmp
+ source_areg <= '1';
+ END IF;
+ IF setexecOPC='1' THEN
+ dest_hbits <= '1';
+ END IF;
+ END IF;
+ END IF;
+
+-- use for ABCD, SBCD
+ IF build_bcd='1' THEN
+ set_exec(use_XZFlag) <= '1';
+ set_exec(ea_data_OP1) <= '1';
+ write_back <= '1';
+ source_lowbits <='1';
+ IF opcode(3)='1' THEN
+ IF decodeOPC='1' THEN
+ setstate <= "10";
+ set(update_ld) <= '1';
+ set(presub) <= '1';
+ next_micro_state <= op_AxAy;
+ dest_areg <= '1'; --???
+ END IF;
+ ELSE
+ dest_hbits <= '1';
+ set_exec(Regwrena) <= '1';
+ END IF;
+ END IF;
+
+
+------------------------------------------------------------------------------
+------------------------------------------------------------------------------
+ IF set_Z_error='1' THEN -- divu by zero
+ trapmake <= '1'; --wichtig fr USP
+ IF trapd='0' THEN
+ writePC <= '1';
+ END IF;
+ END IF;
+
+-----------------------------------------------------------------------------
+-- execute microcode
+-----------------------------------------------------------------------------
+ IF rising_edge(clk) THEN
+ IF Reset='1' THEN
+ micro_state <= ld_nn;
+ ELSIF clkena_lw='1' THEN
+ trapd <= trapmake;
+ micro_state <= next_micro_state;
+ END IF;
+ END IF;
+
+ CASE micro_state IS
+ WHEN ld_nn => -- (nnnn).w/l=>
+ set(get_ea_now) <='1';
+ setnextpass <= '1';
+ set(addrlong) <= '1';
+
+ WHEN st_nn => -- =>(nnnn).w/l
+ setstate <= "11";
+ set(addrlong) <= '1';
+ next_micro_state <= nop;
+
+ WHEN ld_dAn1 => -- d(An)=>, --d(PC)=>
+ set(get_ea_now) <='1';
+ setdisp <= '1'; --word
+ setnextpass <= '1';
+
+ WHEN ld_AnXn1 => -- d(An,Xn)=>, --d(PC,Xn)=>
+ IF brief(8)='0' OR extAddr_Mode=0 OR (cpu(1)='0' AND extAddr_Mode=2) THEN
+ setdisp <= '1'; --byte
+ setdispbyte <= '1';
+ setstate <= "01";
+ set(briefext) <= '1';
+ next_micro_state <= ld_AnXn2;
+ ELSE
+ IF brief(7)='1'THEN --suppress Base
+ set_suppress_base <= '1';
+ ELSIF exec(dispouter)='1' THEN
+ set(dispouter) <= '1';
+ END IF;
+ IF brief(5)='0' THEN --NULL Base Displacement
+ setstate <= "01";
+ ELSE --WORD Base Displacement
+ IF brief(4)='1' THEN
+ set(longaktion) <= '1'; --LONG Base Displacement
+ END IF;
+ END IF;
+ next_micro_state <= ld_229_1;
+ END IF;
+
+ WHEN ld_AnXn2 =>
+ set(get_ea_now) <='1';
+ setdisp <= '1'; --brief
+ setnextpass <= '1';
+
+-------------------------------------------------------------------------------------
+
+ WHEN ld_229_1 => -- (bd,An,Xn)=>, --(bd,PC,Xn)=>
+ IF brief(5)='1' THEN --Base Displacement
+ setdisp <= '1'; --add last_data_read
+ END IF;
+ IF brief(6)='0' AND brief(2)='0' THEN --Preindex or Index
+ set(briefext) <= '1';
+ setstate <= "01";
+ IF brief(1 downto 0)="00" THEN
+ next_micro_state <= ld_AnXn2;
+ ELSE
+ next_micro_state <= ld_229_2;
+ END IF;
+ ELSE
+ IF brief(1 downto 0)="00" THEN
+ set(get_ea_now) <='1';
+ setnextpass <= '1';
+ ELSE
+ setstate <= "10";
+ set(longaktion) <= '1';
+ next_micro_state <= ld_229_3;
+ END IF;
+ END IF;
+
+ WHEN ld_229_2 => -- (bd,An,Xn)=>, --(bd,PC,Xn)=>
+ setdisp <= '1'; -- add Index
+ setstate <= "10";
+ set(longaktion) <= '1';
+ next_micro_state <= ld_229_3;
+
+ WHEN ld_229_3 => -- (bd,An,Xn)=>, --(bd,PC,Xn)=>
+ set_suppress_base <= '1';
+ set(dispouter) <= '1';
+ IF brief(1)='0' THEN --NULL Outer Displacement
+ setstate <= "01";
+ ELSE --WORD Outer Displacement
+ IF brief(0)='1' THEN
+ set(longaktion) <= '1'; --LONG Outer Displacement
+ END IF;
+ END IF;
+ next_micro_state <= ld_229_4;
+
+ WHEN ld_229_4 => -- (bd,An,Xn)=>, --(bd,PC,Xn)=>
+ IF brief(1)='1' THEN -- Outer Displacement
+ setdisp <= '1'; --add last_data_read
+ END IF;
+ IF brief(6)='0' AND brief(2)='1' THEN --Postindex
+ set(briefext) <= '1';
+ setstate <= "01";
+ next_micro_state <= ld_AnXn2;
+ ELSE
+ set(get_ea_now) <='1';
+ setnextpass <= '1';
+ END IF;
+
+----------------------------------------------------------------------------------------
+ WHEN st_dAn1 => -- =>d(An)
+ setstate <= "11";
+ setdisp <= '1'; --word
+ next_micro_state <= nop;
+
+ WHEN st_AnXn1 => -- =>d(An,Xn)
+ IF brief(8)='0' OR extAddr_Mode=0 OR (cpu(1)='0' AND extAddr_Mode=2) THEN
+ setdisp <= '1'; --byte
+ setdispbyte <= '1';
+ setstate <= "01";
+ set(briefext) <= '1';
+ next_micro_state <= st_AnXn2;
+ ELSE
+ IF brief(7)='1'THEN --suppress Base
+ set_suppress_base <= '1';
+-- ELSIF exec(dispouter)='1' THEN
+-- set(dispouter) <= '1';
+ END IF;
+ IF brief(5)='0' THEN --NULL Base Displacement
+ setstate <= "01";
+ ELSE --WORD Base Displacement
+ IF brief(4)='1' THEN
+ set(longaktion) <= '1'; --LONG Base Displacement
+ END IF;
+ END IF;
+ next_micro_state <= st_229_1;
+ END IF;
+
+ WHEN st_AnXn2 =>
+ setstate <= "11";
+ setdisp <= '1'; --brief
+ next_micro_state <= nop;
+
+-------------------------------------------------------------------------------------
+
+ WHEN st_229_1 => -- (bd,An,Xn)=>, --(bd,PC,Xn)=>
+ IF brief(5)='1' THEN --Base Displacement
+ setdisp <= '1'; --add last_data_read
+ END IF;
+ IF brief(6)='0' AND brief(2)='0' THEN --Preindex or Index
+ set(briefext) <= '1';
+ setstate <= "01";
+ IF brief(1 downto 0)="00" THEN
+ next_micro_state <= st_AnXn2;
+ ELSE
+ next_micro_state <= st_229_2;
+ END IF;
+ ELSE
+ IF brief(1 downto 0)="00" THEN
+ setstate <= "11";
+ next_micro_state <= nop;
+ ELSE
+ set(hold_dwr) <= '1';
+ setstate <= "10";
+ set(longaktion) <= '1';
+ next_micro_state <= st_229_3;
+ END IF;
+ END IF;
+
+ WHEN st_229_2 => -- (bd,An,Xn)=>, --(bd,PC,Xn)=>
+ setdisp <= '1'; -- add Index
+ set(hold_dwr) <= '1';
+ setstate <= "10";
+ set(longaktion) <= '1';
+ next_micro_state <= st_229_3;
+
+ WHEN st_229_3 => -- (bd,An,Xn)=>, --(bd,PC,Xn)=>
+ set(hold_dwr) <= '1';
+ set_suppress_base <= '1';
+ set(dispouter) <= '1';
+ IF brief(1)='0' THEN --NULL Outer Displacement
+ setstate <= "01";
+ ELSE --WORD Outer Displacement
+ IF brief(0)='1' THEN
+ set(longaktion) <= '1'; --LONG Outer Displacement
+ END IF;
+ END IF;
+ next_micro_state <= st_229_4;
+
+ WHEN st_229_4 => -- (bd,An,Xn)=>, --(bd,PC,Xn)=>
+ set(hold_dwr) <= '1';
+ IF brief(1)='1' THEN -- Outer Displacement
+ setdisp <= '1'; --add last_data_read
+ END IF;
+ IF brief(6)='0' AND brief(2)='1' THEN --Postindex
+ set(briefext) <= '1';
+ setstate <= "01";
+ next_micro_state <= st_AnXn2;
+ ELSE
+ setstate <= "11";
+ next_micro_state <= nop;
+ END IF;
+
+----------------------------------------------------------------------------------------
+ WHEN bra1 => --bra
+ IF exe_condition='1' THEN
+ TG68_PC_brw <= '1'; --pc+0000
+ next_micro_state <= nop;
+ skipFetch <= '1';
+ END IF;
+
+ WHEN bsr1 => --bsr short
+ TG68_PC_brw <= '1';
+ next_micro_state <= nop;
+
+ WHEN bsr2 => --bsr
+ IF long_start='0' THEN
+ TG68_PC_brw <= '1';
+ END IF;
+ skipFetch <= '1';
+ set(longaktion) <= '1';
+ writePC <= '1';
+ setstate <= "11";
+ next_micro_state <= nopnop;
+ setstackaddr <='1';
+ WHEN nopnop => --bsr
+ next_micro_state <= nop;
+
+ WHEN dbcc1 => --dbcc
+ IF exe_condition='0' THEN
+ Regwrena_now <= '1';
+ IF c_out(1)='1' THEN
+ skipFetch <= '1';
+ next_micro_state <= nop;
+ TG68_PC_brw <= '1';
+ END IF;
+ END IF;
+
+ WHEN movem1 => --movem
+ IF last_data_read(15 downto 0)/=X"0000" THEN
+ setstate <="01";
+ IF opcode(5 downto 3)="100" THEN
+ set(mem_addsub) <= '1';
+ END IF;
+ next_micro_state <= movem2;
+ END IF;
+ WHEN movem2 => --movem
+ IF movem_run='0' THEN
+ setstate <="01";
+ ELSE
+ set(movem_action) <= '1';
+ set(mem_addsub) <= '1';
+ next_micro_state <= movem2;
+ IF opcode(10)='0' THEN
+ setstate <="11";
+ set(write_reg) <= '1';
+ ELSE
+ setstate <="10";
+ END IF;
+ END IF;
+
+ WHEN andi => --andi
+ IF opcode(5 downto 4)/="00" THEN
+ setnextpass <= '1';
+ END IF;
+
+ WHEN op_AxAy => -- op -(Ax),-(Ay)
+ set_direct_data <= '1';
+ set(presub) <= '1';
+ dest_hbits <= '1';
+ dest_areg <= '1';
+ setstate <= "10";
+
+ WHEN cmpm => -- cmpm (Ay)+,(Ax)+
+ set_direct_data <= '1';
+ set(postadd) <= '1';
+ dest_hbits <= '1';
+ dest_areg <= '1';
+ setstate <= "10";
+
+ WHEN link1 => -- link
+ setstate <="11";
+ source_areg <= '1';
+ set(opcMOVE) <= '1';
+ set(Regwrena) <= '1';
+ next_micro_state <= link2;
+ WHEN link2 => -- link
+ setstackaddr <='1';
+ set(ea_data_OP2) <= '1';
+
+ WHEN unlink1 => -- unlink
+ setstate <="10";
+ setstackaddr <='1';
+ set(postadd) <= '1';
+ next_micro_state <= unlink2;
+ WHEN unlink2 => -- unlink
+ set(ea_data_OP2) <= '1';
+
+ WHEN trap0 => -- TRAP
+ set(presub) <= '1';
+ setstackaddr <='1';
+ setstate <= "11";
+ IF VBR_Stackframe=1 OR (cpu(0)='1' AND VBR_Stackframe=2) THEN --68010
+ set(writePC_add) <= '1';
+ datatype <= "01";
+-- set_datatype <= "10";
+ next_micro_state <= trap1;
+ ELSE
+ IF trap_interrupt='1' OR trap_trace='1' THEN
+ writePC <= '1';
+ END IF;
+ datatype <= "10";
+ next_micro_state <= trap2;
+ END IF;
+ WHEN trap1 => -- TRAP
+ IF trap_interrupt='1' OR trap_trace='1' THEN
+ writePC <= '1';
+ END IF;
+ set(presub) <= '1';
+ setstackaddr <='1';
+ setstate <= "11";
+ datatype <= "10";
+ next_micro_state <= trap2;
+ WHEN trap2 => -- TRAP
+ set(presub) <= '1';
+ setstackaddr <='1';
+ setstate <= "11";
+ datatype <= "01";
+ writeSR <= '1';
+ next_micro_state <= trap3;
+ WHEN trap3 => -- TRAP
+ set_vectoraddr <= '1';
+ datatype <= "10";
+ set(direct_delta) <= '1';
+ set(directPC) <= '1';
+ setstate <= "10";
+ next_micro_state <= nopnop;
+
+ WHEN rte1 => -- RTE
+ datatype <= "10";
+ setstate <= "10";
+ set(postadd) <= '1';
+ setstackaddr <= '1';
+ IF VBR_Stackframe=0 OR (cpu(0)='0' AND VBR_Stackframe=2) THEN
+ set(direct_delta) <= '1';
+ END IF;
+ set(directPC) <= '1';
+ next_micro_state <= rte2;
+ WHEN rte2 => -- RTE
+ datatype <= "01";
+ set(update_FC) <= '1';
+ IF VBR_Stackframe=1 OR (cpu(0)='1' AND VBR_Stackframe=2) THEN
+ setstate <= "10";
+ set(postadd) <= '1';
+ setstackaddr <= '1';
+ next_micro_state <= rte3;
+ ELSE
+ next_micro_state <= nop;
+ END IF;
+ WHEN rte3 => -- RTE
+ next_micro_state <= nop;
+-- set(update_FC) <= '1';
+
+ WHEN movec1 => -- MOVEC
+ set(briefext) <= '1';
+ set_writePCbig <='1';
+ IF (brief(11 downto 0)=X"000" OR brief(11 downto 0)=X"001" OR brief(11 downto 0)=X"800" OR brief(11 downto 0)=X"801") OR
+ (cpu(1)='1' AND (brief(11 downto 0)=X"002" OR brief(11 downto 0)=X"802" OR brief(11 downto 0)=X"803" OR brief(11 downto 0)=X"804")) THEN
+ IF opcode(0)='0' THEN
+ set(Regwrena) <= '1';
+ END IF;
+-- ELSIF brief(11 downto 0)=X"800"OR brief(11 downto 0)=X"001" OR brief(11 downto 0)=X"000" THEN
+-- trap_addr_error <= '1';
+-- trapmake <= '1';
+ ELSE
+ trap_illegal <= '1';
+ trapmake <= '1';
+ END IF;
+
+ WHEN movep1 => -- MOVEP d(An)
+ setstate <= "01";
+ IF opcode(6)='1' THEN
+ set(movepl) <= '1';
+ END IF;
+ next_micro_state <= movep2;
+ WHEN movep2 =>
+ setdisp <= '1';
+ set(mem_addsub) <= '1';
+ set(mem_byte) <= '1';
+ set(OP1addr) <= '1';
+ IF opcode(6)='1' THEN
+ set(movepl) <= '1';
+ END IF;
+ IF opcode(7)='0' THEN
+ setstate <= "10";
+ ELSE
+ setstate <= "11";
+ END IF;
+ next_micro_state <= movep3;
+ WHEN movep3 =>
+ IF opcode(6)='1' THEN
+ set(mem_addsub) <= '1';
+ set(OP1addr) <= '1';
+ END IF;
+ IF opcode(7)='0' THEN
+ setstate <= "10";
+ ELSE
+ setstate <= "11";
+ END IF;
+ next_micro_state <= movep4;
+ WHEN movep4 =>
+ IF opcode(6)='1' THEN
+ set(mem_addsub) <= '1';
+ set(OP1addr) <= '1';
+ set(mem_byte) <= '1';
+ IF opcode(7)='0' THEN
+ setstate <= "10";
+ ELSE
+ setstate <= "11";
+ END IF;
+ next_micro_state <= movep5;
+ ELSE
+ datatype <= "01"; --Word
+ END IF;
+ WHEN movep5 =>
+ IF opcode(7)='0' THEN
+ setstate <= "10";
+ ELSE
+ setstate <= "11";
+ END IF;
+ next_micro_state <= movep6;
+ WHEN movep6 =>
+ datatype <= "10"; --Long
+
+ WHEN mul1 => -- mulu
+ IF opcode(15)='1' OR MUL_Mode=0 THEN
+ set_rot_cnt <= "001110";
+ ELSE
+ set_rot_cnt <= "011110";
+ END IF;
+ setstate <="01";
+ next_micro_state <= mul2;
+ WHEN mul2 => -- mulu
+ setstate <="01";
+ IF rot_cnt="00001" THEN
+ next_micro_state <= mul_end1;
+ ELSE
+ next_micro_state <= mul2;
+ END IF;
+ WHEN mul_end1 => -- mulu
+ datatype <= "10";
+ set(opcMULU) <= '1';
+ IF opcode(15)='0' AND (MUL_Mode=1 OR MUL_Mode=2) THEN
+ dest_2ndHbits <= '1';
+ source_2ndLbits <= '1';--???
+ set(write_lowlong) <= '1';
+ IF sndOPC(10)='1' THEN
+ setstate <="01";
+ next_micro_state <= mul_end2;
+ END IF;
+ set(Regwrena) <= '1';
+ END IF;
+ datatype <= "10";
+ WHEN mul_end2 => -- divu
+ set(write_reminder) <= '1';
+ set(Regwrena) <= '1';
+ set(opcMULU) <= '1';
+
+ WHEN div1 => -- divu
+ setstate <="01";
+ next_micro_state <= div2;
+ WHEN div2 => -- divu
+ IF (OP2out(31 downto 16)=x"0000" OR opcode(15)='1' OR DIV_Mode=0) AND OP2out(15 downto 0)=x"0000" THEN --div zero
+ set_Z_error <= '1';
+ ELSE
+ next_micro_state <= div3;
+ END IF;
+ set(ld_rot_cnt) <= '1';
+ setstate <="01";
+ WHEN div3 => -- divu
+ IF opcode(15)='1' OR DIV_Mode=0 THEN
+ set_rot_cnt <= "001101";
+ ELSE
+ set_rot_cnt <= "011101";
+ END IF;
+ setstate <="01";
+ next_micro_state <= div4;
+ WHEN div4 => -- divu
+ setstate <="01";
+ IF rot_cnt="00001" THEN
+ next_micro_state <= div_end1;
+ ELSE
+ next_micro_state <= div4;
+ END IF;
+ WHEN div_end1 => -- divu
+ IF opcode(15)='0' AND (DIV_Mode=1 OR DIV_Mode=2) THEN
+ set(write_reminder) <= '1';
+ next_micro_state <= div_end2;
+ setstate <="01";
+ END IF;
+ set(opcDIVU) <= '1';
+ datatype <= "10";
+ WHEN div_end2 => -- divu
+ dest_2ndHbits <= '1';
+ source_2ndLbits <= '1';--???
+ set(opcDIVU) <= '1';
+
+ WHEN rota1 =>
+ IF OP2out(5 downto 0)/="000000" THEN
+ set_rot_cnt <= OP2out(5 downto 0);
+ ELSE
+ set_exec(rot_nop) <= '1';
+ END IF;
+
+ WHEN bf1 =>
+ setstate <="10";
+
+ WHEN OTHERS => NULL;
+ END CASE;
+ END PROCESS;
+
+-----------------------------------------------------------------------------
+-- MOVEC
+-----------------------------------------------------------------------------
+PROCESS (clk, VBR, CACR, brief)
+ BEGIN
+ IF rising_edge(clk) THEN
+ IF Reset = '1' THEN
+ VBR <= (OTHERS => '0');
+ CACR <= (OTHERS => '0');
+ ELSIF clkena_lw='1' AND exec(movec_wr)='1' THEN
+ CASE brief(11 downto 0) IS
+ WHEN X"002" => CACR <= reg_QA(3 downto 0);
+ WHEN X"801" => VBR <= reg_QA;
+ WHEN OTHERS => NULL;
+ END CASE;
+ END IF;
+ END IF;
+ movec_data <= (OTHERS=>'0');
+ CASE brief(11 downto 0) IS
+ WHEN X"002" => movec_data(3 downto 0) <= CACR;
+ WHEN X"801" => --IF VBR_Stackframe=1 OR (cpu(0)='1' AND VBR_Stackframe=2) THEN
+ movec_data <= VBR;
+ --END IF;
+ WHEN OTHERS => NULL;
+ END CASE;
+ END PROCESS;
+
+-----------------------------------------------------------------------------
+-- Conditions
+-----------------------------------------------------------------------------
+PROCESS (exe_opcode, Flags)
+ BEGIN
+ CASE exe_opcode(11 downto 8) IS
+ WHEN X"0" => exe_condition <= '1';
+ WHEN X"1" => exe_condition <= '0';
+ WHEN X"2" => exe_condition <= NOT Flags(0) AND NOT Flags(2);
+ WHEN X"3" => exe_condition <= Flags(0) OR Flags(2);
+ WHEN X"4" => exe_condition <= NOT Flags(0);
+ WHEN X"5" => exe_condition <= Flags(0);
+ WHEN X"6" => exe_condition <= NOT Flags(2);
+ WHEN X"7" => exe_condition <= Flags(2);
+ WHEN X"8" => exe_condition <= NOT Flags(1);
+ WHEN X"9" => exe_condition <= Flags(1);
+ WHEN X"a" => exe_condition <= NOT Flags(3);
+ WHEN X"b" => exe_condition <= Flags(3);
+ WHEN X"c" => exe_condition <= (Flags(3) AND Flags(1)) OR (NOT Flags(3) AND NOT Flags(1));
+ WHEN X"d" => exe_condition <= (Flags(3) AND NOT Flags(1)) OR (NOT Flags(3) AND Flags(1));
+ WHEN X"e" => exe_condition <= (Flags(3) AND Flags(1) AND NOT Flags(2)) OR (NOT Flags(3) AND NOT Flags(1) AND NOT Flags(2));
+ WHEN X"f" => exe_condition <= (Flags(3) AND NOT Flags(1)) OR (NOT Flags(3) AND Flags(1)) OR Flags(2);
+ WHEN OTHERS => NULL;
+ END CASE;
+ END PROCESS;
+
+-----------------------------------------------------------------------------
+-- Movem
+-----------------------------------------------------------------------------
+PROCESS (clk)
+ BEGIN
+ IF rising_edge(clk) THEN
+ IF clkena_lw='1' THEN
+ movem_actiond <= exec(movem_action);
+ IF decodeOPC='1' THEN
+ sndOPC <= data_read(15 downto 0);
+ ELSIF exec(movem_action)='1' OR set(movem_action) ='1' THEN
+ CASE movem_regaddr IS
+ WHEN "0000" => sndOPC(0) <= '0';
+ WHEN "0001" => sndOPC(1) <= '0';
+ WHEN "0010" => sndOPC(2) <= '0';
+ WHEN "0011" => sndOPC(3) <= '0';
+ WHEN "0100" => sndOPC(4) <= '0';
+ WHEN "0101" => sndOPC(5) <= '0';
+ WHEN "0110" => sndOPC(6) <= '0';
+ WHEN "0111" => sndOPC(7) <= '0';
+ WHEN "1000" => sndOPC(8) <= '0';
+ WHEN "1001" => sndOPC(9) <= '0';
+ WHEN "1010" => sndOPC(10) <= '0';
+ WHEN "1011" => sndOPC(11) <= '0';
+ WHEN "1100" => sndOPC(12) <= '0';
+ WHEN "1101" => sndOPC(13) <= '0';
+ WHEN "1110" => sndOPC(14) <= '0';
+ WHEN "1111" => sndOPC(15) <= '0';
+ WHEN OTHERS => NULL;
+ END CASE;
+ END IF;
+ END IF;
+ END IF;
+ END PROCESS;
+
+PROCESS (sndOPC, movem_mux)
+ BEGIN
+ movem_regaddr <="0000";
+ movem_run <= '1';
+ IF sndOPC(3 downto 0)="0000" THEN
+ IF sndOPC(7 downto 4)="0000" THEN
+ movem_regaddr(3) <= '1';
+ IF sndOPC(11 downto 8)="0000" THEN
+ IF sndOPC(15 downto 12)="0000" THEN
+ movem_run <= '0';
+ END IF;
+ movem_regaddr(2) <= '1';
+ movem_mux <= sndOPC(15 downto 12);
+ ELSE
+ movem_mux <= sndOPC(11 downto 8);
+ END IF;
+ ELSE
+ movem_mux <= sndOPC(7 downto 4);
+ movem_regaddr(2) <= '1';
+ END IF;
+ ELSE
+ movem_mux <= sndOPC(3 downto 0);
+ END IF;
+ IF movem_mux(1 downto 0)="00" THEN
+ movem_regaddr(1) <= '1';
+ IF movem_mux(2)='0' THEN
+ movem_regaddr(0) <= '1';
+ END IF;
+ ELSE
+ IF movem_mux(0)='0' THEN
+ movem_regaddr(0) <= '1';
+ END IF;
+ END IF;
+ END PROCESS;
+END;
\ No newline at end of file
diff --git a/common/CPU/68000/wf_68k00_ip/68K00_quirks-and-squirrels.txt b/common/CPU/68000/wf_68k00_ip/68K00_quirks-and-squirrels.txt
new file mode 100644
index 00000000..c62e9e55
--- /dev/null
+++ b/common/CPU/68000/wf_68k00_ip/68K00_quirks-and-squirrels.txt
@@ -0,0 +1,18 @@
+CPU core original CPU unclear items:
+
+- CMPM, MOVE, ADDX, SUBX, ABCD, SBCD: generally spoken all operations where a source and a destination location are given. The predecrement and the postincrement addressing modes are affected. Which result is calculated by addressing modes (ax)+,(ay)+ and -(ax),-(ay). The result depends on the time when the address registers are incremented or decremented and the order, the operands are loaded. I assume, that the addresws registers are incremented twice during these instructions and that the address registers are incremented during the operation in a way, that the second operand is already taken from the postincremented or the predecremented address.
+
+MOVEM:
+- If the addressing register is included in the register list, the initial value of the register should be written to the memory. For the 68K20+ the decremented value is written. Which value is the correct one? Decremented by the actual amount of already transfered registers or the decremented value for the total amount of decremented registers?
+- If the register list mask is empty, the MOVEM does nothing and behaves like a NOP.
+
+ROL, ROR, ROXL, ROXR, ROTL, ROTR:
+- The operation (example) ROL d0,d0 takes the number of required rotations out of do, rotates d0 and copies afterwards the result to d0.
+- If the immediate rotation register is zero, no shift operation results, the status flags are updated.
+
+ILLEGAL: The address written on the stack is the address of the ILLEGAL statement. In the simulator, the address written is the address of the ILLEGAL statement plus two.
+
+Other things to do:
+Further reduction of the core size.
+
+WF 20071224
diff --git a/common/CPU/68000/wf_68k00_ip/68k00-release-notes.txt b/common/CPU/68000/wf_68k00_ip/68k00-release-notes.txt
new file mode 100644
index 00000000..28ec40a6
--- /dev/null
+++ b/common/CPU/68000/wf_68k00_ip/68k00-release-notes.txt
@@ -0,0 +1,19 @@
+The CPU IP core has been improved during the last release. There are still open topics. For more information see the 68K00 quirks-and-squirrels.txt in this directory.
+
+Main changes since the last release:
+1. The CPU does now work with the SUSKA IP core to run the emutos operating system.
+2. Reduced the size from 10200 LEs (Altera Cyclone II) to about 9400 LEs.
+3. Simplified the data register section.
+4. Some bug fixes in several modules.
+
+Please send me an email to wf@inventronik.de if bugs are encountered or also for tips and
+suggestions.
+
+Known issues:
+The function code outputs (FC) are coded in a way, that the patterns during the bus transfers meet the patterns of the original 68000 CPUs. If there is no bus transfer and the processor is the bus master, there results a funcion code of "000". If the processor has no control over the bus, the function code outputs are high impedant.
+
+The deasserted bus control signals UDSn or LDSn produce during byte wide bus access and in the predecrement addressing mode short spikes. This behaviour does not affect the correct bus transfer.
+
+The EXT operation in the operation type OP_68K00 is named EXTW due to compiler constraints with the Xilinx ISE.
+
+WF - 20080418.
\ No newline at end of file
diff --git a/common/CPU/68000/wf_68k00_ip/pace_wf68k00ip_top_soc.vhd b/common/CPU/68000/wf_68k00_ip/pace_wf68k00ip_top_soc.vhd
new file mode 100644
index 00000000..ebee9019
--- /dev/null
+++ b/common/CPU/68000/wf_68k00_ip/pace_wf68k00ip_top_soc.vhd
@@ -0,0 +1,196 @@
+library IEEE;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+
+entity PACE_WF68K00IP_TOP_SOC is
+ port
+ (
+ CLK : in std_logic;
+ RESET_COREn : in std_logic; -- Core reset.
+
+ -- Address and data:
+ ADR_OUT : out std_logic_vector(23 downto 1);
+ ADR_EN : out std_logic;
+ DATA_IN : in std_logic_vector(15 downto 0);
+ DATA_OUT : out std_logic_vector(15 downto 0);
+ DATA_EN : out std_logic;
+
+ -- System control:
+ BERRn : in std_logic;
+ RESET_INn : in std_logic;
+ RESET_OUT_EN : out std_logic; -- Open drain.
+ HALT_INn : in std_logic;
+ HALT_OUT_EN : out std_logic; -- Open drain.
+
+ -- Processor status:
+ FC_OUT : out std_logic_vector(2 downto 0);
+ FC_OUT_EN : out std_logic;
+
+ -- Interrupt control:
+ AVECn : in std_logic; -- Originally 68Ks use VPAn.
+ IPLn : in std_logic_vector(2 downto 0);
+
+ -- Aynchronous bus control:
+ DTACKn : in std_logic;
+ AS_OUTn : out std_logic;
+ AS_OUT_EN : out std_logic;
+ RWn_OUT : out std_logic;
+ RW_OUT_EN : out std_logic;
+ UDS_OUTn : out std_logic;
+ UDS_OUT_EN : out std_logic;
+ LDS_OUTn : out std_logic;
+ LDS_OUT_EN : out std_logic;
+
+ -- Synchronous peripheral control:
+ E : out std_logic;
+ VMA_OUTn : out std_logic;
+ VMA_OUT_EN : out std_logic;
+ VPAn : in std_logic;
+
+ -- Bus arbitration control:
+ BRn : in std_logic;
+ BGn : out std_logic;
+ BGACKn : in std_logic
+ );
+end entity PACE_WF68K00IP_TOP_SOC;
+
+architecture SYN of PACE_WF68K00IP_TOP_SOC is
+
+ signal CLK_s : bit;
+ signal RESET_COREn_s : bit;
+
+ -- Address and data:
+ signal ADR_EN_s : bit;
+ signal DATA_EN_s : bit;
+
+ -- System control:
+ signal BERRn_s : bit;
+ signal RESET_INn_s : bit;
+ signal RESET_OUT_EN_s : bit; -- Open drain.
+ signal HALT_OUT_EN_s : bit; -- Open drain.
+
+ -- Processor status:
+ signal FC_OUT_EN_s : bit;
+
+ -- Interrupt control:
+ signal AVECn_s : bit; -- Originally 68Ks use VPAn.
+ signal IPLn_s : std_logic_vector(2 downto 0);
+
+ -- Aynchronous bus control:
+ signal DTACKn_s : bit;
+ signal AS_OUTn_s : bit;
+ signal AS_OUT_EN_s : bit;
+ signal RWn_OUT_s : bit;
+ signal RW_OUT_EN_s : bit;
+ signal UDS_OUTn_s : bit;
+ signal UDS_OUT_EN_s : bit;
+ signal LDS_OUTn_s : bit;
+ signal LDS_OUT_EN_s : bit;
+
+ -- Synchronous peripheral control:
+ signal E_s : bit;
+ signal VMA_OUTn_s : bit;
+ signal VMA_OUT_EN_s : bit;
+ signal VPAn_s : bit;
+
+ -- Bus arbitration control:
+ signal BRn_s : bit;
+ signal BGn_s : bit;
+ signal BGACKn_s : bit;
+
+begin
+
+ CLK_s <= TO_BIT(CLK);
+ RESET_COREn_s <= TO_BIT(RESET_COREn);
+
+ -- Address and data:
+ ADR_EN <= TO_X01(ADR_EN_s);
+ DATA_EN <= TO_X01(DATA_EN_s);
+
+ -- System control:
+ BERRn_s <= TO_BIT(BERRn);
+ RESET_INn_s <= TO_BIT(RESET_INn);
+ RESET_OUT_EN <= TO_X01(RESET_OUT_EN_s);
+ HALT_OUT_EN <= TO_X01(HALT_OUT_EN_s);
+
+ -- Processor status:
+ FC_OUT_EN <= TO_X01(FC_OUT_EN_s);
+
+ -- Interrupt control:
+ AVECn_s <= TO_BIT(AVECn);
+ IPLn_s <= IPLn;
+
+ -- Aynchronous bus control:
+ DTACKn_s <= TO_BIT(DTACKn);
+ AS_OUTn <= TO_X01(AS_OUTn_s);
+ AS_OUT_EN <= TO_X01(AS_OUT_EN_s);
+ RWn_OUT <= TO_X01(RWn_OUT_s);
+ RW_OUT_EN <= TO_X01(RW_OUT_EN_s);
+ UDS_OUTn <= TO_X01(UDS_OUTn_s);
+ UDS_OUT_EN <= TO_X01(UDS_OUT_EN_s);
+ LDS_OUTn <= TO_X01(LDS_OUTn_s);
+ LDS_OUT_EN <= TO_X01(LDS_OUT_EN_s);
+
+ -- Synchronous peripheral control:
+ E <= TO_X01(E_s);
+ VMA_OUTn <= TO_X01(VMA_OUTn_s);
+ VMA_OUT_EN <= TO_X01(VMA_OUT_EN_s);
+ VPAn_s <= TO_BIT(VPAn);
+
+ -- Bus arbitration control:
+ BRn_s <= TO_BIT(BRn);
+ BGn <= TO_X01(BGn_s);
+ BGACKn_s <= TO_BIT(BGACKn);
+
+ WF68K00IP_TOP_SOC_inst : entity work.WF68K00IP_TOP_SOC
+ port map
+ (
+ CLK => CLK_s,
+ RESET_COREn => RESET_COREn_s,
+
+ -- Address and data:
+ ADR_OUT => ADR_OUT,
+ ADR_EN => ADR_EN_s,
+ DATA_IN => DATA_IN,
+ DATA_OUT => DATA_OUT,
+ DATA_EN => DATA_EN_s,
+
+ -- System control:
+ BERRn => BERRn_s,
+ RESET_INn => RESET_INn_s,
+ RESET_OUT_EN => RESET_OUT_EN_s,
+ HALT_INn => HALT_INn,
+ HALT_OUT_EN => HALT_OUT_EN_s,
+
+ -- Processor status:
+ FC_OUT => FC_OUT,
+ FC_OUT_EN => FC_OUT_EN_s,
+
+ -- Interrupt control:
+ AVECn => AVECn_s,
+ IPLn => IPLn_s,
+
+ -- Aynchronous bus control:
+ DTACKn => DTACKn_s,
+ AS_OUTn => AS_OUTn_s,
+ AS_OUT_EN => AS_OUT_EN_s,
+ RWn_OUT => RWn_OUT_s,
+ RW_OUT_EN => RW_OUT_EN_s,
+ UDS_OUTn => UDS_OUTn_s,
+ UDS_OUT_EN => UDS_OUT_EN_s,
+ LDS_OUTn => LDS_OUTn_s,
+ LDS_OUT_EN => LDS_OUT_EN_s,
+
+ -- Synchronous peripheral control:
+ E => E_s,
+ VMA_OUTn => VMA_OUTn_s,
+ VMA_OUT_EN => VMA_OUT_EN_s,
+ VPAn => VPAn_s,
+
+ -- Bus arbitration control:
+ BRn => BRn_s,
+ BGn => BGn_s,
+ BGACKn => BGACKn_s
+ );
+
+end SYN;
diff --git a/common/CPU/68000/wf_68k00_ip/wf68k00ip_address_registers.vhd b/common/CPU/68000/wf_68k00_ip/wf68k00ip_address_registers.vhd
new file mode 100644
index 00000000..fe3a5d16
--- /dev/null
+++ b/common/CPU/68000/wf_68k00_ip/wf68k00ip_address_registers.vhd
@@ -0,0 +1,544 @@
+----------------------------------------------------------------------
+---- ----
+---- MC68000 compatible IP Core ----
+---- ----
+---- This file is part of the SUSKA ATARI clone project. ----
+---- http://www.experiment-s.de ----
+---- ----
+---- Description: ----
+---- This model provides an opcode and bus timing compatible ip ----
+---- core compared to Motorola's MC68000 microprocessor. ----
+---- ----
+---- This file contains the 68Ks address registers. ----
+---- ----
+---- ----
+---- Description: ----
+---- This file contains the 68K series data and address ----
+---- registers, the user stack pointer (USP), the supervisor ----
+---- stack pointer (SSP) and the 32-bit program counter (PC). ----
+---- The required sign extensions for the INDEX and the DISPLACE- ----
+---- ment are provided by this model. ----
+---- ----
+---- ----
+---- Author(s): ----
+---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
+---- ----
+----------------------------------------------------------------------
+---- ----
+---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
+---- ----
+---- This source file 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 2 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, write to the Free ----
+---- Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ----
+---- Boston, MA 02110-1301, USA. ----
+---- ----
+----------------------------------------------------------------------
+--
+-- Revision History
+--
+-- Revision 2K6B 2006/12/24 WF
+-- Initial Release.
+-- Revision 2K7A 2007/05/31 WF
+-- Updated all modules.
+-- Revision 2K7B 2007/12/24 WF
+-- See the 68K00 top level file.
+-- Revision 2K8A 2008/07/14 WF
+-- See the 68K00 top level file.
+--
+
+use work.wf68k00ip_pkg.all;
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+
+entity WF68K00IP_ADDRESS_REGISTERS is
+ port (
+ CLK : in bit;
+ RESETn : in bit;
+
+ -- Address and data:
+ DATA_IN : in std_logic_vector(15 downto 0); -- Extension word input.
+ ADATA_IN : in std_logic_vector(31 downto 0); -- Address register and USP, SSP and PC input.
+ REGSEL_B : in std_logic_vector(2 downto 0); -- Register number.
+ REGSEL_A : in std_logic_vector(2 downto 0); -- Register number.
+ ADR_REG_QB : out std_logic_vector(31 downto 0); -- Register selected by REGSEL_B.
+ ADR_REG_QA : out std_logic_vector(31 downto 0); -- Register selected by REGSEL_A.
+ USP_OUT : out std_logic_vector(31 downto 0); -- User stack pointer.
+ SSP_OUT : out std_logic_vector(31 downto 0); -- Supervisor stack pointer.
+ PC_OUT : out std_logic_vector(31 downto 0); -- Program counter.
+
+ -- Extension words:
+ EXWORD : in EXWORDTYPE;
+ DEST_EXWORD : in EXWORDTYPE;
+
+ -- Registers controls:
+ DR : in bit; -- Direction control.
+ USP_CPY : in bit; -- Copy among address registers.
+ AR_EXG : in bit; -- Exchange address register contents.
+ AR_WR : in bit; -- Address register write.
+ USP_INC : in bit; -- User stack pointer increment by 2.
+ USP_DEC : in bit; -- User stack pointer decrement by 2.
+ ADR_TMP_CLR : in bit; -- Temporary address offset clear.
+ ADR_TMP_INC : in bit; -- Address register increment temporarily.
+ AR_INC : in bit; -- Address register increment.
+ AR_DEC : in bit; -- Address register decrement.
+ SSP_INC : in bit; -- Supervisor stack pointer increment by 2.
+ SSP_DEC : in bit; -- Supervisor stack pointer decrement by 2.
+ SSP_INIT : in bit; -- Initialize SSP.
+ SP_ADD_DISPL : in bit; -- Forces the adding of the sign extended displacement to the SP.
+ USE_SP_ADR : in bit; -- Indicates the use of the stack (suer or supervisor).
+ USE_SSP_ADR : in bit; -- Indicates the use of the supervisor stack.
+ PC_WR : in bit; -- Program counter write.
+ PC_INC : in bit; -- Program counter increment.
+ PC_TMP_CLR : in bit; -- Clear temporary PC.
+ PC_TMP_INC : in bit; -- Increment temporary PC.
+ PC_INIT : in bit; -- Initialize the program counter.
+ PC_ADD_DISPL : in bit; -- Forces the adding of the sign extended displacement to the SP.
+
+ -- Misc controls:
+ SRC_DESTn : in bit; -- '1' for read operand from source, '0' store result to destination (MOVE).
+ SBIT : in bit; -- Superuser flag.
+ OP : in OP_68K00; -- the operations.
+ OP_SIZE : in OP_SIZETYPE; -- BYTE, WORD or LONG.
+ OP_MODE : in std_logic_vector(4 downto 0);
+ OP_START : in bit; -- Used for the MOVEM.
+ ADR_MODE : in std_logic_vector(2 downto 0); -- Address mode indicator.
+ MOVE_D_AM : in std_logic_vector(2 downto 0); -- Destination address mode for MOVE.
+ FORCE_BIW2 : in bit;
+ FORCE_BIW3 : in bit;
+
+ -- Displacement stuff:
+ EXT_DSIZE : in D_SIZETYPE;
+ SEL_DISPLACE_BIW : in bit;
+ DISPLACE_BIW : in std_logic_vector(31 downto 0); -- Displacement (8 or 16 bit).
+
+ -- Index and data register stuff:
+ REGSEL_INDEX : in std_logic_vector(2 downto 0); -- Index register address select.
+ INDEX_D_IN : in std_logic_vector(31 downto 0); -- Index from a data register.
+
+ -- Traps:
+ CHK_PC : in bit; -- Check program counter for TRAP_AERR.
+ CHK_ADR : in bit; -- Check effective address for TRAP_AERR.
+ TRAP_AERR : out bit; -- Address error indication.
+
+ -- Effective address (result of the address logic):
+ ADR_EFF : out std_logic_vector(31 downto 0) -- This is the effective address.
+ );
+end entity WF68K00IP_ADDRESS_REGISTERS;
+
+architecture BEHAVIOR of WF68K00IP_ADDRESS_REGISTERS is
+type AR_TYPE is array(0 to 6) of std_logic_vector(31 downto 0);
+signal AR : AR_TYPE; -- Address registers A0 to A6.
+signal DATA_SIGNED : std_logic_vector(31 downto 0); -- Sign extended data.
+signal USP : std_logic_vector(31 downto 0); -- User stack pointer (refers to A7 in the user mode.).
+signal SSP : std_logic_vector(31 downto 0); -- Supervisor stack pointer (refers to A7' in the supervisor mode).
+signal PC : std_logic_vector(31 downto 0); -- Program counter.
+signal AREG_TMP : std_logic_vector(31 downto 0); -- Temporary address holding register.
+signal ADR_MODE_I : std_logic_vector(2 downto 0);
+signal DISPLACE : std_logic_vector(31 downto 0);
+signal DISPL_EXT : std_logic_vector(31 downto 0);
+signal I_D_A : bit;
+signal I_W_L : bit;
+signal I_SCALE : bit_vector(1 downto 0); -- Scale information for the index.
+signal INDEX_SIGN : bit; -- Sign of the index.
+signal INDEX_SCALED : std_logic_vector(31 downto 0);
+signal ABS_ADDRESS : std_logic_vector(31 downto 0);
+signal AR_NR_A : integer range 0 to 7;
+signal AR_NR_B : integer range 0 to 7;
+signal AR_NR_I : integer range 0 to 7;
+signal ADR_EFF_I : std_logic_vector(31 downto 0);
+signal ADR_TMP : std_logic_vector(5 downto 0);
+signal PC_TMP : std_logic_vector(4 downto 0);
+signal PC_OFFSET : std_logic_vector(3 downto 0); -- Used for PC relative addressing modes.
+signal AR_STEP : std_logic_vector(2 downto 0);
+begin
+ -- Address mode selector switch:
+ -- The default assignment is valid for source and destination access
+ -- regardless of the value of SRC_DESTn (e.g. ADD, ADDX).
+ ADR_MODE_I <= MOVE_D_AM when SRC_DESTn = '0' and OP = MOVE else ADR_MODE;
+
+ -- Address pointers:
+ AR_NR_A <= conv_integer(REGSEL_A);
+ AR_NR_B <= conv_integer(REGSEL_B);
+ AR_NR_I <= conv_integer(REGSEL_INDEX);
+
+ -- TRAP_AERR:
+ -- 1. If an operation is read from an odd adress.
+ -- 2. If the respective stack pointers in use are at an odd address.
+ -- 2. If there is a WORD oder LONG bus access at an odd address.
+ -- Note: Do not change the priority of these conditions!
+ TRAP_AERR <= '1' when CHK_PC = '1' and PC(0) = '1' else -- OP-Code at an odd address.
+ '1' when CHK_ADR = '1' and USE_SSP_ADR = '1' and SSP(0) = '1' else
+ '1' when CHK_ADR = '1' and USE_SP_ADR = '1' and SBIT = '1' and SSP(0) = '1' else
+ '1' when CHK_ADR = '1' and USE_SP_ADR = '1' and USP(0) = '1' else
+ '0' when CHK_ADR = '1' and (USE_SSP_ADR = '1' or USE_SP_ADR = '1') else -- Stack is correct.
+ -- MOVEP size is long or word but the acces is at byte boarders:
+ '1' when CHK_ADR = '1' and OP /= MOVEP and OP_SIZE = LONG and ADR_EFF_I(0) = '1' else -- LONG at an odd address.
+ '1' when CHK_ADR = '1' and OP /= MOVEP and OP_SIZE = WORD and ADR_EFF_I(0) = '1' else '0'; -- WORD at an odd address.
+
+ -- The address register increment and decrement values:
+ AR_STEP <= "100" when OP_SIZE = LONG else
+ "010" when OP_SIZE = WORD else
+ "010" when OP_SIZE = BYTE and AR_NR_B = 7 else "001";
+
+ -- Data outputs:
+ USP_OUT <= USP;
+ SSP_OUT <= SSP;
+ PC_OUT <= PC + PC_TMP; -- Plus offset.
+
+ ADR_REG_QA <= AREG_TMP when OP = MOVEM and ADR_MODE_I = "100" and REGSEL_A = REGSEL_B else -- See P_AREG_TMP, case A.
+ SSP when AR_NR_A = 7 and SBIT= '1' else -- Supervisor stack pointer.
+ USP when AR_NR_A = 7 and SBIT= '0' else -- User stack pointer.
+ AR(AR_NR_A);
+
+ ADR_REG_QB <= SSP when AR_NR_B = 7 and SBIT= '1' else -- Supervisor stack pointer.
+ USP when AR_NR_B = 7 and SBIT= '0' else -- User stack pointer.
+ AR(AR_NR_B);
+
+ P_AREG_TMP: process(RESETn, CLK)
+ -- This register holds a temporary copy of the desired address register
+ -- for the MOVEM operation. There are two special cases:
+ -- Case A: if the addressing register in the predecrement mode is
+ -- written to memory, the initial value (not decremented) is written out.
+ -- Case B: If the addressing register in the non postincrement
+ -- addressing mode is loaded from memory, the AREG_TMP holds the
+ -- old addressing register value until the end of the MOVEM.
+ begin
+ if RESETn = '0' then
+ AREG_TMP <= x"00000000";
+ elsif CLK = '1' and CLK' event then
+ if OP = MOVEM and OP_START = '1' then
+ case AR_NR_B is
+ when 7 =>
+ if SBIT= '1' then
+ AREG_TMP <= SSP;
+ else
+ AREG_TMP <= USP;
+ end if;
+ when others => AREG_TMP <= AR(AR_NR_B);
+ end case;
+ end if;
+ end if;
+ end process P_AREG_TMP;
+
+ SRC_SIGNEXT: process(OP, OP_SIZE, ADATA_IN, ADR_EFF_I)
+ -- The MOVEA and MOVEM require a sign extended source data
+ -- which is provided by this logic. The BYTE size is not
+ -- allowed for these operations and not taken into account.
+ begin
+ if (OP = MOVEA or OP = MOVEM) and OP_SIZE = WORD then
+ for i in 31 downto 16 loop
+ DATA_SIGNED(i) <= ADATA_IN(15);
+ end loop;
+ DATA_SIGNED(15 downto 0) <= ADATA_IN(15 downto 0);
+ elsif OP = JMP or OP = JSR or OP = LEA then
+ DATA_SIGNED <= ADR_EFF_I;
+ else
+ DATA_SIGNED <= ADATA_IN;
+ end if;
+ end process SRC_SIGNEXT;
+
+ I_D_A <= '1' when EXWORD(0)(15) = '1' and SRC_DESTn = '1' else
+ '1' when DEST_EXWORD(0)(15) = '1' and SRC_DESTn = '0' else '0';
+ I_W_L <= '1' when EXWORD(0)(11) = '1' and SRC_DESTn = '1' else
+ '1' when DEST_EXWORD(0)(11) = '1' and SRC_DESTn = '0' else '0';
+
+ -- The SCALE is not implemented in the original 68000. Nevertheless, the SCALE
+ -- is foreseen in this core because the OPCODE compatibility is given.
+ I_SCALE <= To_BitVector(EXWORD(0)(10 downto 9)) when SRC_DESTn = '1' else
+ To_BitVector(DEST_EXWORD(0)(10 downto 9));
+
+ -- The absolute address is valid for the absolute address modes 'WORD' and 'LONG'.
+ -- The sign extension is provided in the address mode process.
+ ABS_ADDRESS <= x"0000" & EXWORD(0) when ADR_MODE_I = "111" and REGSEL_B = "000" and SRC_DESTn = '1' else
+ x"0000" & DEST_EXWORD(0) when ADR_MODE_I = "111" and REGSEL_B = "000" and SRC_DESTn = '0' else
+ EXWORD(0) & EXWORD(1) when SRC_DESTn = '1' else DEST_EXWORD(0) & DEST_EXWORD(1);
+
+ EXTEND_INDEX: process(AR_NR_I, I_D_A, I_W_L, AR, INDEX_D_IN, I_SCALE)
+ -- This process selects the INDEX from one of the data
+ -- registers or from one of the address registers. Further-
+ -- more the index needs to be sign extended from 8 bit to 32
+ -- bit or from 16 bit to 32 bit dependent on the address mode.
+ -- In case of a long word operation, no extension is required.
+ -- The index is multiplied by 1, 2, 4 or 8. The ADR_EFF is the
+ -- scaled index for the address calculation.
+ variable INDEX : std_logic_vector(31 downto 0);
+ variable INDEX_EXT : std_logic_vector(31 downto 0);
+ begin
+ if I_D_A = '1' then
+ INDEX := AR(AR_NR_I);
+ else
+ INDEX := INDEX_D_IN;
+ end if;
+
+ case I_W_L is
+ when '0' => -- Sign extended word.
+ for i in 31 downto 16 loop
+ INDEX_EXT(i) := INDEX(15);
+ end loop;
+ INDEX_EXT(15 downto 0) := INDEX(15 downto 0);
+ when '1' => -- Long word.
+ INDEX_EXT := INDEX;
+ end case;
+
+ case I_SCALE is
+ when "00" => INDEX_SCALED <= INDEX_EXT; -- Multiple by 1.
+ when "01" => INDEX_SCALED <= INDEX_EXT(31 downto 1) & '0'; -- Multiple by 2.
+ when "10" => INDEX_SCALED <= INDEX_EXT(31 downto 2) & "00"; -- Multiple by 4.
+ when "11" => INDEX_SCALED <= INDEX_EXT(31 downto 3) & "000"; -- Multiple by 8.
+ end case;
+ end process EXTEND_INDEX;
+
+ -- Displacement multiplexer:
+ DISPLACE <= DISPLACE_BIW when SEL_DISPLACE_BIW = '1' else
+ x"0000" & EXWORD(0) when EXT_DSIZE = WORD and SRC_DESTn = '1' else
+ x"000000" & EXWORD(0)(7 downto 0) when EXT_DSIZE = BYTE and SRC_DESTn = '1' else
+ x"0000" & DEST_EXWORD(0) when EXT_DSIZE = WORD else
+ x"000000" & DEST_EXWORD(0)(7 downto 0);
+
+ EXTEND_DISPLACEMENT: process(DISPLACE, EXT_DSIZE)
+ -- The displacement needs to be sign extended from 8 bit to 32, from 16 bit to 32 bit or
+ -- not extended dependent on the address mode.
+ begin
+ case EXT_DSIZE is
+ when BYTE => -- 8 bit wide displacement.
+ for i in 31 downto 8 loop
+ DISPL_EXT(i) <= DISPLACE(7);
+ end loop;
+ DISPL_EXT(7 downto 0) <= DISPLACE(7 downto 0);
+ when WORD => -- 16 bit wide displacement.
+ for i in 31 downto 16 loop
+ DISPL_EXT(i) <= DISPLACE(15);
+ end loop;
+ DISPL_EXT(15 downto 0) <= DISPLACE(15 downto 0);
+ when LONG =>
+ DISPL_EXT <= DISPLACE;
+ end case;
+ end process EXTEND_DISPLACEMENT;
+
+ P_ADR_TMP: process(RESETn, CLK)
+ -- This process provides a temporary address offset during
+ -- bus access over several bytes. The 6 bits are used for
+ -- the MOVEM command in the non postincrement /predecrement mode.
+ -- Other commands requires a maximum of
+ -- 3 bits.
+ begin
+ if RESETn = '0' then
+ ADR_TMP <= "000000";
+ elsif CLK = '1' and CLK' event then
+ if ADR_TMP_CLR = '1' then
+ ADR_TMP <= "000000";
+ elsif ADR_TMP_INC = '1' and OP_SIZE = BYTE then
+ ADR_TMP <= ADR_TMP + "01";
+ elsif ADR_TMP_INC = '1' then
+ ADR_TMP <= ADR_TMP + "10";
+ end if;
+ end if;
+ end process P_ADR_TMP;
+
+ P_PC_TMP: process(RESETn, CLK)
+ -- This process provides a temporary program counter offset
+ -- during the 'fetch phase'.
+ variable PC_TMPVAR : std_logic_vector(3 downto 0);
+ begin
+ if RESETn = '0' then
+ PC_TMPVAR := x"0";
+ elsif CLK = '1' and CLK' event then
+ if PC_INC = '1' or PC_TMP_CLR = '1' then
+ PC_TMPVAR := x"0";
+ elsif PC_TMP_INC = '1' then
+ PC_TMPVAR := PC_TMPVAR + '1';
+ end if;
+ end if;
+ PC_TMP <= PC_TMPVAR & "0"; -- Increment always by two.
+ end process P_PC_TMP;
+
+ PC_OFFSET <= x"6" when FORCE_BIW3 = '1' and FORCE_BIW2 = '1' else
+ x"4" when FORCE_BIW2 = '1' else x"2";
+
+ ADDRESS_MODES: process(ADR_MODE_I, REGSEL_B, AR, AR_NR_B, SBIT, USP, SSP, DISPL_EXT, AREG_TMP,
+ ADR_TMP, OP, INDEX_SCALED, ABS_ADDRESS, PC, PC_OFFSET, ADR_EFF_I, DR)
+ -- The effective address calculation takes place in this process depending on the
+ -- chosen addressing mode.
+ variable ADR_EFF_TMP : std_logic_vector(31 downto 0);
+ variable AREG : std_logic_vector(31 downto 0);
+ begin
+ if OP = MOVEM and (ADR_MODE_I = "010" or ADR_MODE_I = "101" or ADR_MODE_I = "110") and DR = '1' then
+ AREG := AREG_TMP; -- See P_AREG_TMP, case B.
+ else
+ case AR_NR_B is
+ when 7 =>
+ if SBIT= '1' then
+ AREG := SSP;
+ else
+ AREG := USP;
+ end if;
+ when others => AREG := AR(AR_NR_B);
+ end case;
+ end if;
+ --
+ case ADR_MODE_I is
+ -- when "000" | "001" => Direct address modes: no effective address required.
+ when "010" | "011" | "100" =>
+ -- x"2": Address register indirect mode. Assembler syntax: (An).
+ -- x"3": Address register indirect with postincrement mode. Assembler syntax: (An)+.
+ -- x"4": Address register indirect with predecrement mode. Assembler syntax: -(An).
+ -- x"2": The ADR_EFF is the pointer to the operand.
+ -- x"3": The ADR_EFF is the pointer to the operand.
+ -- x"4": The ADR_EFF is the pointer to the operand.
+ ADR_EFF_TMP := AREG;
+ when "101" => -- Address register indirect with offset. Assembler syntax: (d16,An).
+ ADR_EFF_TMP := AREG + DISPL_EXT;
+ when "110" =>
+ -- The ADR_EFF is the pointer to the operand.
+ -- Assembler syntax: (d8,An,Xn.SIZE*SCALE).
+ ADR_EFF_TMP := AREG + DISPL_EXT + INDEX_SCALED;
+ when "111" =>
+ case REGSEL_B is
+ when "000" => -- Absolute short addressing mode.
+ -- Assembler syntax: (xxx).W
+ -- The ADR_EFF is the pointer to the operand.
+ for i in 31 downto 16 loop
+ ADR_EFF_TMP(i) := ABS_ADDRESS(15); -- Sign extension.
+ end loop;
+ ADR_EFF_TMP(15 downto 0) := ABS_ADDRESS(15 downto 0);
+ when "001" => -- Absolute long addressing mode.
+ -- Assembler syntax: (xxx).L
+ -- The ADR_EFF is the pointer to the operand.
+ ADR_EFF_TMP := ABS_ADDRESS;
+ when "010" => -- Program counter relative with offset.
+ -- Assembler syntax: (d16,PC).
+ -- The effective address during PC relative addressing
+ -- contains the PC offset plus two.
+ ADR_EFF_TMP := PC + PC_OFFSET + DISPL_EXT;
+ when "011" => -- Program counter relative with index and offset.
+ -- Assembler syntax: (d8,PC,Xn.SIZE*SCALE).
+ -- The effective address during PC relative addressing
+ -- contains the PC offset plus two.
+ ADR_EFF_TMP := PC + PC_OFFSET + DISPL_EXT + INDEX_SCALED;
+ when others =>
+ ADR_EFF_TMP := (others => '-'); -- Don't care, not used dummy.
+ end case;
+ when others =>
+ ADR_EFF_TMP := (others => '-'); -- Result not required.
+ end case;
+ ADR_EFF_I <= ADR_EFF_TMP;
+ -- Copy of the effective address plus offsets:
+ ADR_EFF <= ADR_EFF_I + ADR_TMP;
+ end process ADDRESS_MODES;
+
+ REG_WR_MODIFY: process(RESETn, CLK, OP, AR_NR_A, AR_NR_B)
+ -- This process provides data transfer to the respective registers (write).
+ -- Affected are the address registers (AR), the supervisor stack pointer (SSP),
+ -- the user stack pointer (USP) and the program counter (PC).
+ begin
+ --
+ if RESETn = '0' then
+ for i in 0 to 6 loop
+ AR(i) <= (others => '0');
+ end loop;
+ USP <= (others => '0');
+ SSP <= (others => '0');
+ PC <= (others => '0');
+ elsif CLK = '1' and CLK' event then
+ -- Write operations are always long:
+ if AR_WR = '1' then
+ if AR_NR_A < 7 then
+ AR(AR_NR_A) <= DATA_SIGNED; -- Load AREG.
+ elsif SBIT = '1' then
+ SSP <= DATA_SIGNED; -- Load SSP.
+ else
+ USP <= DATA_SIGNED; -- Load USP.
+ end if;
+ end if;
+
+ -- Predecrement and postincrement:
+ if AR_INC = '1' and AR_NR_B < 7 then
+ AR(AR_NR_B) <= AR(AR_NR_B) + AR_STEP;
+ elsif AR_INC = '1' and SBIT= '1' then
+ SSP <= SSP + AR_STEP;
+ elsif AR_INC = '1' then
+ USP <= USP + AR_STEP;
+ elsif AR_DEC = '1' and AR_NR_B < 7 then
+ AR(AR_NR_B) <= AR(AR_NR_B) - AR_STEP;
+ elsif AR_DEC = '1' and SBIT= '1' then
+ SSP <= SSP - AR_STEP;
+ elsif AR_DEC = '1' then
+ USP <= USP - AR_STEP;
+ end if;
+
+ -- Increment / decrement the stack:
+ if USP_INC = '1' then
+ USP <= USP + "10"; -- Increment 2 bytes.
+ elsif USP_DEC = '1' then
+ USP <= USP - "10"; -- Decrement 2 bytes.
+ elsif SSP_INIT = '1' then
+ SSP <= ADATA_IN;
+ elsif SSP_INC = '1' then
+ SSP <= SSP + "10"; -- Increment 2 bytes.
+ elsif SSP_DEC = '1' then
+ SSP <= SSP - "10"; -- Decrement 2 bytes.
+ end if;
+
+ -- Displacement operations (concurrent to AR_WR..., see LINK).
+ if SP_ADD_DISPL = '1' and SBIT = '1' then
+ SSP <= SSP + DISPL_EXT; -- Used for LINK.
+ elsif SP_ADD_DISPL = '1' then
+ USP <= USP + DISPL_EXT; -- Used for LINK.
+ end if;
+
+ -- Exchange the content of address registers:
+ if AR_EXG = '1' and OP_MODE = "01001" then -- Exchange two address registers.
+ AR(AR_NR_B) <= AR(AR_NR_A); -- Internal wired because there is no second data input.
+ AR(AR_NR_A) <= ADATA_IN;
+ elsif AR_EXG = '1' and OP_MODE = "10001" then -- Exchange a data and an address register.
+ AR(AR_NR_B) <= ADATA_IN;
+ end if;
+
+ -- Address Register copies:
+ if USP_CPY = '1' and DR = '0' then -- Copy the address register to user stack pointer.
+ if AR_NR_B < 7 then
+ USP <= AR(AR_NR_B);
+ elsif SBIT = '1' then
+ USP <= SSP;
+ end if;
+ elsif USP_CPY = '1' then -- Copy the user stack pointer to the address register.
+ if AR_NR_B < 7 then
+ AR(AR_NR_B) <= USP;
+ elsif SBIT = '1' then
+ SSP <= USP;
+ end if;
+ end if;
+
+ -- Program counter arithmetics:
+ if PC_WR = '1' then -- JMP, JSR.
+ PC <= DATA_SIGNED;
+ elsif PC_INIT = '1' then
+ PC <= ADATA_IN;
+ -- The PC_ADD_DISPL and the PC_INC are asserted simultaneously when the
+ -- operation is used for Bcc and BRA. Therefore the prioritization of
+ -- PC_ADD_DISPL over PC_INC is important.
+ -- When PC_INC is active, the program counter is increased by the
+ -- value of PC_TMP plus two when the following execution state after
+ -- a fetch phase is FETCH_BIW_1.
+ elsif PC_ADD_DISPL = '1' then -- Used for Bcc, BRA, BSR, DBcc.
+ PC <= PC + DISPL_EXT + "10";
+ elsif PC_INC = '1' then
+ PC <= PC + PC_TMP + "10";
+ end if;
+ end if;
+ end process REG_WR_MODIFY;
+end BEHAVIOR;
diff --git a/common/CPU/68000/wf_68k00_ip/wf68k00ip_alu.vhd b/common/CPU/68000/wf_68k00_ip/wf68k00ip_alu.vhd
new file mode 100644
index 00000000..526be07e
--- /dev/null
+++ b/common/CPU/68000/wf_68k00_ip/wf68k00ip_alu.vhd
@@ -0,0 +1,850 @@
+----------------------------------------------------------------------
+---- ----
+---- MC68000 compatible IP Core ----
+---- ----
+---- This file is part of the SUSKA ATARI clone project. ----
+---- http://www.experiment-s.de ----
+---- ----
+---- Description: ----
+---- This model provides an opcode and bus timing compatible ip ----
+---- core compared to Motorola's MC68000 microprocessor. ----
+---- ----
+---- This file contains the arithmetic logic unit (ALU). ----
+---- ----
+---- ----
+---- Description: ----
+---- Arithmetic Logic Unit performs the arithmetic and logic ----
+---- operations during execution of an instruction. It contains ----
+---- the accumulator and related logic such as arithmetic unit, ----
+---- logic unit, multiplier and divider. BCD operation are exe- ----
+---- cuted in this unit and condition code flags (N-negative, ----
+---- Z-zero, C-carry V-overflow) for most instructions. ----
+---- For a proper operation, the ALU requires sign extended ----
+---- operands OP_IN_S, OP_IN_D_LO and OP_IN_D_HI. In case of the ----
+---- OP_IN_D_HI a sign extension is required for the long ----
+---- (DIVL) only. ----
+---- ----
+---- Author(s): ----
+---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
+---- ----
+----------------------------------------------------------------------
+---- ----
+---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
+---- ----
+---- This source file 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 2 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, write to the Free ----
+---- Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ----
+---- Boston, MA 02110-1301, USA. ----
+---- ----
+----------------------------------------------------------------------
+--
+-- Revision History
+--
+-- Revision 2K6B 2006/12/24 WF
+-- Initial Release.
+-- Revision 2K7A 2007/05/31 WF
+-- Updated all modules.
+-- Revision 2K7B 2007/12/24 WF
+-- See the 68K00 top level file.
+-- Revision 2K8A 2008/07/14 WF
+-- See the 68K00 top level file.
+--
+
+use work.WF68K00IP_PKG.all;
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+
+entity WF68K00IP_ALU is
+ port (
+ RESETn : in bit;
+ CLK : in bit;
+ ADR_MODE : in std_logic_vector(2 downto 0);
+ OP_SIZE : in OP_SIZETYPE;
+ OP : in OP_68K00;
+ -- The Flags:
+ XNZVC_IN : in std_logic_vector(4 downto 0);
+ XNZVC_OUT : out std_logic_vector(4 downto 0);
+
+ -- Operands and result:
+ OP_IN_S : in std_logic_vector(31 downto 0);
+ OP_IN_D_HI : in std_logic_vector(31 downto 0);
+ OP_IN_D_LO : in std_logic_vector(31 downto 0);
+ RESULT_HI : out std_logic_vector(31 downto 0);
+ RESULT_LO : out std_logic_vector(31 downto 0);
+
+ -- Status and Control:
+ OP_START : in bit; -- 1 CLK cycle.
+ TRAP_CHK_EN : in bit; -- 1 CLK cycle.
+ DIV_MUL_32n64 : in bit; -- 1 for 64 bit long MUL or DIV, 0 for 32 bit long MUL or DIV.
+ OP_BUSY : out bit;
+ TRAP_CHK : out bit; -- Trap due to the CHK instruction.
+ TRAP_DIVZERO : out bit -- Trap due to divide by zero.
+ );
+end entity WF68K00IP_ALU;
+
+architecture BEHAVIOR of WF68K00IP_ALU is
+type MUL_STATES is (MUL_IDLE, MUL_ADD, MUL_VERIFY_SHIFT);
+type DIV_STATES is (DIV_IDLE, DIV_VERIFY, DIV_ADDSUB, DIV_SIGN);
+signal MUL_STATE : MUL_STATES;
+signal NEXT_MUL_STATE : MUL_STATES;
+signal DIV_STATE : DIV_STATES;
+signal NEXT_DIV_STATE : DIV_STATES;
+signal OP_IN_S_SIGN : std_logic_vector(31 downto 0);
+signal OP_IN_D_SIGN_LO : std_logic_vector(31 downto 0);
+signal RESULT_LOGOP : std_logic_vector(31 downto 0);
+signal RESULT_BCD : std_logic_vector(7 downto 0);
+signal RESULT_INTOP : std_logic_vector(31 downto 0);
+signal RESULT_SPECIAL : std_logic_vector(31 downto 0);
+signal RESULT_I_DIV : std_logic_vector(31 downto 0);
+signal RESULT_I : std_logic_vector(31 downto 0);
+signal RESULT_II : std_logic_vector(32 downto 0);
+signal DIVISOR : std_logic_vector(63 downto 0);
+signal DIVIDEND : std_logic_vector(63 downto 0);
+signal CB_BCD : std_logic;
+signal OV_DIV : std_logic;
+signal MUL_CYC_CNT : unsigned(5 downto 0);
+signal OP_MUL : bit;
+signal OP_DIV : bit;
+signal MUL_DIV_OP_S : std_logic_vector(31 downto 0);
+signal MUL_OP_D : std_logic_vector(31 downto 0);
+signal DIV_VAR : std_logic_vector(31 downto 0);
+signal DIV_OLD_MSB : std_logic;
+signal DIV_SHIFT_EN : bit;
+begin
+ OP_BUSY <= OP_MUL or OP_DIV;
+
+ -- Result multiplexers:
+ with OP select
+ RESULT_HI <= RESULT_II(31 downto 0) when DIVS | DIVU | MULS | MULU, x"00000000" when others;
+ with OP select
+ RESULT_LO <= RESULT_LOGOP when AND_B | ANDI | ANDI_TO_CCR | ANDI_TO_SR | EOR | EORI | EORI_TO_CCR,
+ RESULT_LOGOP when EORI_TO_SR | NOT_B | OR_B | ORI | ORI_TO_CCR | ORI_TO_SR,
+ RESULT_INTOP when ADD | ADDA | ADDI | ADDQ | ADDX | CLR | CMP | CMPA | CMPI | CMPM,
+ RESULT_INTOP when NEG | NEGX | SUB | SUBA | SUBI | SUBQ | SUBX,
+ RESULT_SPECIAL when EXTW | SWAP | TAS,
+ x"000000" & RESULT_BCD when ABCD | NBCD | SBCD, -- Byte only.
+ RESULT_I_DIV when DIVS | DIVU,
+ RESULT_I when MULS | MULU,
+ OP_IN_S when others; -- Default for CHK, MOVE, MOVEQ.
+
+ -- Use low bytes of RESULT_II and RESULT_I for word wide DIVS, DIVU:
+ RESULT_I_DIV <= RESULT_II(15 downto 0) & RESULT_I(15 downto 0) when OP_SIZE = WORD else RESULT_I;
+
+ SIGNEXT: process(OP, OP_IN_S, OP_IN_D_LO, OP_SIZE)
+ -- This module provides the required sign extensions.
+ begin
+ case OP_SIZE is
+ when LONG =>
+ OP_IN_S_SIGN <= OP_IN_S;
+ OP_IN_D_SIGN_LO <= OP_IN_D_LO;
+ when WORD =>
+ for i in 31 downto 16 loop
+ OP_IN_S_SIGN(i) <= OP_IN_S(15);
+ OP_IN_D_SIGN_LO(i) <= OP_IN_D_LO(15);
+ end loop;
+ OP_IN_S_SIGN(15 downto 0) <= OP_IN_S(15 downto 0);
+ OP_IN_D_SIGN_LO(15 downto 0) <= OP_IN_D_LO(15 downto 0);
+ when BYTE =>
+ for i in 31 downto 8 loop
+ OP_IN_S_SIGN(i) <= OP_IN_S(7);
+ OP_IN_D_SIGN_LO(i) <= OP_IN_D_LO(7);
+ end loop;
+ OP_IN_S_SIGN(7 downto 0) <= OP_IN_S(7 downto 0);
+ OP_IN_D_SIGN_LO(7 downto 0) <= OP_IN_D_LO(7 downto 0);
+ end case;
+ end process SIGNEXT;
+
+ TRAP_CHK <= '1' when TRAP_CHK_EN = '1' and OP_IN_D_SIGN_LO(31) = '1' else -- Negative destination.
+ '1' when TRAP_CHK_EN = '1' and RESULT_INTOP(31) = '0' else '0'; -- Destination > Source.
+
+ TRAP_DIVZERO <= '1' when OP = DIVU and DIV_STATE = DIV_IDLE and OP_START = '1' and OP_IN_S = x"00000000" else
+ '1' when OP = DIVS and DIV_STATE = DIV_IDLE and OP_START = '1' and OP_IN_S = x"00000000" else '0';
+
+ P_LOGOP: process(OP, OP_IN_S, OP_IN_D_LO)
+ -- This process provides the logic operations:
+ -- AND, OR, XOR and NOT.
+ -- The logic operations require no signed / unsigned
+ -- modelling.
+ begin
+ case OP is
+ when AND_B | ANDI | ANDI_TO_CCR | ANDI_TO_SR =>
+ RESULT_LOGOP <= OP_IN_S and OP_IN_D_LO;
+ when OR_B | ORI | ORI_TO_CCR | ORI_TO_SR =>
+ RESULT_LOGOP <= OP_IN_S or OP_IN_D_LO;
+ when EOR | EORI | EORI_TO_CCR | EORI_TO_SR =>
+ RESULT_LOGOP <= OP_IN_S xor OP_IN_D_LO;
+ when NOT_B =>
+ RESULT_LOGOP <= not OP_IN_D_LO;
+ when MOVE =>
+ RESULT_LOGOP <= OP_IN_S; -- Used for MOVE.
+ when others =>
+ RESULT_LOGOP <= OP_IN_D_LO; -- Used for TST.
+ end case;
+ end process P_LOGOP;
+
+ P_INTOP: process(OP, OP_IN_S, OP_IN_S_SIGN, OP_IN_D_LO, OP_IN_D_SIGN_LO, ADR_MODE, XNZVC_IN, OP_SIZE, RESULT_INTOP)
+ -- The integer arithmetics ADD, SUB, NEG and CMP in their different variations are modelled here.
+ variable X_IN_I : Std_Logic_Vector(0 downto 0);
+ variable RESULT : unsigned(31 downto 0);
+ begin
+ X_IN_I(0) := XNZVC_IN(4); -- Extended Flag.
+ case OP is
+ when ADDA =>
+ RESULT := unsigned(OP_IN_D_LO) + unsigned(OP_IN_S_SIGN); -- No sign extension for the destination.
+ when ADDQ =>
+ case ADR_MODE is
+ when "001" => RESULT := unsigned(OP_IN_D_LO) + unsigned(OP_IN_S_SIGN); -- No sign extension for address destination.
+ when others => RESULT := unsigned(OP_IN_D_SIGN_LO) + unsigned(OP_IN_S_SIGN);
+ end case;
+ when ADD | ADDI =>
+ RESULT := unsigned(OP_IN_D_SIGN_LO) + unsigned(OP_IN_S_SIGN);
+ when ADDX =>
+ RESULT := unsigned(OP_IN_D_SIGN_LO) + unsigned(OP_IN_S_SIGN) + unsigned(X_IN_I);
+ when CMPA | SUBA =>
+ RESULT := unsigned(OP_IN_D_LO) - unsigned(OP_IN_S_SIGN); -- No sign extension for the destination.
+ when SUBQ =>
+ case ADR_MODE is
+ when "001" => RESULT := unsigned(OP_IN_D_LO) - unsigned(OP_IN_S_SIGN); -- No sign extension for address destination.
+ when others => RESULT := unsigned(OP_IN_D_SIGN_LO) - unsigned(OP_IN_S_SIGN);
+ end case;
+ when CHK | CMP | CMPI | CMPM | SUB | SUBI =>
+ RESULT := unsigned(OP_IN_D_SIGN_LO) - unsigned(OP_IN_S_SIGN);
+ when SUBX =>
+ RESULT := unsigned(OP_IN_D_SIGN_LO) - unsigned(OP_IN_S_SIGN) - unsigned(X_IN_I);
+ when NEG =>
+ RESULT := unsigned(OP_IN_S_SIGN) - unsigned(OP_IN_D_SIGN_LO);
+ when NEGX =>
+ RESULT := unsigned(OP_IN_S_SIGN) - unsigned(OP_IN_D_SIGN_LO) - unsigned(X_IN_I);
+ when CLR =>
+ RESULT := (others => '0');
+ when others =>
+ RESULT := (others => '0'); -- Don't care.
+ end case;
+ RESULT_INTOP <= std_logic_vector(RESULT);
+ end process P_INTOP;
+
+ P_SPECIAL: process(OP, OP_IN_S, OP_IN_D_LO, OP_SIZE, RESULT_INTOP)
+ -- This process provides the calculation for special operations.
+ variable RESULT : unsigned(31 downto 0);
+ begin
+ case OP is
+ when EXTW =>
+ case OP_SIZE is
+ when LONG =>
+ for i in 31 downto 16 loop
+ RESULT(i) := OP_IN_S(15);
+ end loop;
+ RESULT(15 downto 0) := unsigned(OP_IN_S(15 downto 0));
+ when others => -- Word.
+ for i in 15 downto 8 loop
+ RESULT(i) := OP_IN_S(7);
+ end loop;
+ RESULT(31 downto 16) := unsigned(OP_IN_S(31 downto 16));
+ RESULT(7 downto 0) := unsigned(OP_IN_S(7 downto 0));
+ end case;
+ when SWAP =>
+ RESULT := unsigned(OP_IN_S(15 downto 0)) & unsigned(OP_IN_S(31 downto 16));
+ when TAS =>
+ RESULT := x"000000" & '1' & unsigned(OP_IN_D_LO(6 downto 0)); -- Set the MSB.
+ when others =>
+ RESULT := (others => '0'); -- Don't care.
+ end case;
+ RESULT_SPECIAL <= std_logic_vector(RESULT);
+ end process P_SPECIAL;
+
+ P_BCDOP: process(OP, XNZVC_IN, OP_IN_S, OP_IN_D_LO)
+ -- The BCD operations are all byte wide and unsigned.
+ variable X_IN_I : unsigned(0 downto 0);
+ variable TEMP0 : unsigned(4 downto 0);
+ variable TEMP1 : unsigned(4 downto 0);
+ variable Z_0 : unsigned(3 downto 0);
+ variable C_0 : unsigned(0 downto 0);
+ variable Z_1 : unsigned(3 downto 0);
+ variable C_1 : std_logic;
+ variable S_0 : unsigned(3 downto 0);
+ variable S_1 : unsigned(3 downto 0);
+ begin
+ X_IN_I(0) := XNZVC_IN(4); -- Inverted extended Flag.
+ case OP is
+ when ABCD =>
+ TEMP0 := unsigned('0' & OP_IN_D_LO(3 downto 0)) + unsigned('0' & OP_IN_S(3 downto 0)) + ("0000" & X_IN_I);
+ TEMP1 := unsigned('0' & OP_IN_D_LO(7 downto 4)) + unsigned('0' & OP_IN_S(7 downto 4)) + ("0000" & C_0);
+ when NBCD =>
+ TEMP0 := "00000" - unsigned('0' & OP_IN_D_LO(3 downto 0)) - ("0000" & X_IN_I);
+ TEMP1 := "00000" - unsigned('0' & OP_IN_D_LO(7 downto 4)) - ("0000" & C_0);
+ when others => -- Valid for SBCD.
+ TEMP0 := unsigned('0' & OP_IN_D_LO(3 downto 0)) - unsigned('0' & OP_IN_S(3 downto 0)) - ("0000" & X_IN_I);
+ TEMP1 := unsigned('0' & OP_IN_D_LO(7 downto 4)) - unsigned('0' & OP_IN_S(7 downto 4)) - ("0000" & C_0);
+ end case;
+ if std_logic_vector(TEMP0) > "01001" then
+ Z_0 := "0110";
+ C_0 := "1";
+ else
+ Z_0 := "0000";
+ C_0 := "0";
+ end if;
+ if std_logic_vector(TEMP1) > "01001" then
+ Z_1 := "0110";
+ C_1 := '1';
+ else
+ Z_1 := "0000";
+ C_1 := '0';
+ end if;
+ case OP is
+ when ABCD =>
+ S_1 := TEMP1(3 downto 0) + Z_1;
+ S_0 := TEMP0(3 downto 0) + Z_0;
+ when others => -- Valid for SBCD, NBCD.
+ S_1 := TEMP1(3 downto 0) - Z_1;
+ S_0 := TEMP0(3 downto 0) - Z_0;
+ end case;
+ --
+ CB_BCD <= C_1;
+ RESULT_BCD(7 downto 4) <= std_logic_vector(S_1);
+ RESULT_BCD(3 downto 0) <= std_logic_vector(S_0);
+ end process P_BCDOP;
+
+ COND_CODES: process(OP, RESULT_BCD, CB_BCD, RESULT_LOGOP, RESULT_INTOP, OP_SIZE, XNZVC_IN, RESULT_SPECIAL,
+ OP_IN_D_SIGN_LO, OP_IN_S_SIGN, RESULT_I, RESULT_II, MUL_STATE, DIV_MUL_32n64, OV_DIV)
+ -- In this process all the condition codes X (eXtended), N (Negative)
+ -- Z (Zero), V (oVerflow) and C (Carry / borrow) are calculated for
+ -- all integer operations. Except for the MULS, MULU, DIVS, DIVU the
+ -- new conditions are valid one clock cycle after the operation starts.
+ -- For the multiplication and the division, the codes are valid after
+ -- BUSY is released.
+ -- Although MOVE, MOVEQ and CHK does not require any data processing by the ALU,
+ -- the condition codes are computated here.
+ variable Z, RM, SM, DM : std_logic;
+ begin
+ -- Concerning Z,V,C Flags:
+ case OP is
+ when ADD | ADDI | ADDQ | ADDX | CMP | CMPA | CMPI | CMPM | NEG | NEGX | SUB | SUBI | SUBQ | SUBX =>
+ RM := RESULT_INTOP(31);
+ SM := OP_IN_S_SIGN(31);
+ DM := OP_IN_D_SIGN_LO(31);
+ when others =>
+ RM := '-'; SM := '-'; DM := '-';
+ end case;
+ -- Concerning Z Flag:
+ case OP is
+ when ADD | ADDI | ADDQ | ADDX | CMP | CMPA | CMPI | CMPM | NEG | NEGX | SUB | SUBI | SUBQ | SUBX =>
+ if RESULT_INTOP = x"00000000" then
+ Z := '1';
+ else
+ Z := '0';
+ end if;
+ when others =>
+ Z := '0';
+ end case;
+ --
+ case OP is
+ when ABCD | NBCD | SBCD =>
+ if RESULT_BCD = x"00" then -- N and V are undefined, don't care.
+ XNZVC_OUT <= CB_BCD & '-' & XNZVC_IN(2) & '-' & CB_BCD;
+ else
+ XNZVC_OUT <= CB_BCD & '-' & '0' & '-' & CB_BCD;
+ end if;
+ when ADD | ADDI | ADDQ | ADDX =>
+ if Z = '1' then
+ if OP = ADDX then
+ XNZVC_OUT(3 downto 2) <= '0' & XNZVC_IN(2);
+ else
+ XNZVC_OUT(3 downto 2) <= "01";
+ end if;
+ else
+ XNZVC_OUT(3 downto 2) <= RM & '0';
+ end if;
+ --
+ case To_Bit(RM) & To_Bit(SM) & To_Bit(DM) is
+ when "011" => XNZVC_OUT(1) <= '1';
+ when "100" => XNZVC_OUT(1) <= '1';
+ when others => XNZVC_OUT(1) <= '0';
+ end case;
+ if (SM = '1' and DM = '1') or (RM = '0' and SM = '1') or (RM = '0' and DM = '1') then
+ XNZVC_OUT(4) <= '1'; XNZVC_OUT(0) <= '1';
+ else
+ XNZVC_OUT(4) <= '0'; XNZVC_OUT(0) <= '0';
+ end if;
+ when CLR =>
+ XNZVC_OUT <= XNZVC_IN(4) & "0100";
+ when SUB | SUBI | SUBQ | SUBX =>
+ if Z = '1' then
+ if OP = SUBX then
+ XNZVC_OUT(3 downto 2) <= '0' & XNZVC_IN(2);
+ else
+ XNZVC_OUT(3 downto 2) <= "01";
+ end if;
+ else
+ XNZVC_OUT(3 downto 2) <= RM & '0';
+ end if;
+ --
+ case To_Bit(RM) & To_Bit(SM) & To_Bit(DM) is
+ when "001" => XNZVC_OUT(1) <= '1';
+ when "110" => XNZVC_OUT(1) <= '1';
+ when others => XNZVC_OUT(1) <= '0';
+ end case;
+ if (SM = '1' and DM = '0') or (RM = '1' and SM = '1') or (RM = '1' and DM = '0') then
+ XNZVC_OUT(4) <= '1'; XNZVC_OUT(0) <= '1';
+ else
+ XNZVC_OUT(4) <= '0'; XNZVC_OUT(0) <= '0';
+ end if;
+ when CMP | CMPA | CMPI | CMPM =>
+ XNZVC_OUT(4) <= XNZVC_IN(4);
+ if Z = '1' then
+ XNZVC_OUT(3 downto 2) <= "01";
+ else
+ XNZVC_OUT(3 downto 2) <= RM & '0';
+ end if;
+ --
+ case To_Bit(RM) & To_Bit(SM) & To_Bit(DM) is
+ when "001" => XNZVC_OUT(1) <= '1';
+ when "110" => XNZVC_OUT(1) <= '1';
+ when others => XNZVC_OUT(1) <= '0';
+ end case;
+ if (SM = '1' and DM = '0') or (RM = '1' and SM = '1') or (RM = '1' and DM = '0') then
+ XNZVC_OUT(0) <= '1';
+ else
+ XNZVC_OUT(0) <= '0';
+ end if;
+ when NEG | NEGX =>
+ if Z = '1' then
+ if OP = NEGX then
+ XNZVC_OUT(3 downto 2) <= '0' & XNZVC_IN(2);
+ else
+ XNZVC_OUT(3 downto 2) <= "01";
+ end if;
+ else
+ XNZVC_OUT(3 downto 2) <= RM & '0';
+ end if;
+ XNZVC_OUT(4) <= DM or RM;
+ XNZVC_OUT(1) <= DM and RM;
+ XNZVC_OUT(0) <= DM or RM;
+ when AND_B | ANDI | EOR | EORI | OR_B | ORI | MOVE | NOT_B | TST =>
+ case OP_SIZE is
+ when LONG =>
+ if RESULT_LOGOP = x"00000000" then
+ XNZVC_OUT <= XNZVC_IN(4) & "0100";
+ else
+ XNZVC_OUT <= XNZVC_IN(4) & RESULT_LOGOP(31) &"000";
+ end if;
+ when WORD =>
+ if RESULT_LOGOP(15 downto 0) = x"0000" then
+ XNZVC_OUT <= XNZVC_IN(4) & "0100";
+ else
+ XNZVC_OUT <= XNZVC_IN(4) & RESULT_LOGOP(15) &"000";
+ end if;
+ when others => -- Byte.
+ if RESULT_LOGOP(7 downto 0) = x"00" then
+ XNZVC_OUT <= XNZVC_IN(4) & "0100";
+ else
+ XNZVC_OUT <= XNZVC_IN(4) & RESULT_LOGOP(7) &"000";
+ end if;
+ end case;
+ -- The ANDI_TO_CCR, ANDI_TO_SR, EORI_TO_CCR, EORI_TO_SR, ORI_TO_CCR, ORI_TO_SR
+ -- are determined in the LOGOP process.
+ when CHK =>
+ if OP_IN_D_SIGN_LO(31) = '1' then
+ XNZVC_OUT <= XNZVC_IN(4) & '1' & "---";
+ elsif RESULT_INTOP(31) = '0' then
+ XNZVC_OUT <= XNZVC_IN(4) & '0' & "---";
+ else
+ XNZVC_OUT <= XNZVC_IN(4 downto 3) & "---";
+ end if;
+ when DIVS | DIVU =>
+ if OP_SIZE = WORD and RESULT_I(15) = '1' then
+ XNZVC_OUT <= XNZVC_IN(4) & '1' & '0' & OV_DIV & '0'; -- Negative number.
+ elsif RESULT_I(31) = '1' then
+ XNZVC_OUT <= XNZVC_IN(4) & '1' & '0' & OV_DIV & '0'; -- Negative number.
+ elsif RESULT_I = x"00000000" then
+ XNZVC_OUT <= XNZVC_IN(4) & '0' & '1' & OV_DIV & '0'; -- Zero.
+ else
+ XNZVC_OUT <= XNZVC_IN(4) & '0' & '0' & OV_DIV & '0';
+ end if;
+ when EXTW =>
+ case OP_SIZE is
+ when LONG =>
+ if RESULT_SPECIAL = x"00000000" then
+ XNZVC_OUT <= XNZVC_IN(4) & "0100";
+ else
+ XNZVC_OUT <= XNZVC_IN(4) & RESULT_SPECIAL(31) & "000";
+ end if;
+ when others => -- Word.
+ if RESULT_SPECIAL(15 downto 0) = x"0000" then
+ XNZVC_OUT <= XNZVC_IN(4) & "0100";
+ else
+ XNZVC_OUT <= XNZVC_IN(4) & RESULT_SPECIAL(15) & "000";
+ end if;
+ end case;
+ when MOVEQ =>
+ if OP_IN_S_SIGN(7 downto 0) = x"00" then
+ XNZVC_OUT <= XNZVC_IN(4) & "0100";
+ else
+ XNZVC_OUT <= XNZVC_IN(4) & OP_IN_S_SIGN(7) & "000";
+ end if;
+ when MULS | MULU =>
+ -- X is unaffected, C is always zero.
+ -- The sign flag is stored in the end of the operation. The Z and V flags
+ -- are valid after the operation, when the MULU or the MULS is not BUSY.
+ --
+ XNZVC_OUT <= XNZVC_IN(4) & '0' & '0' & '0' & '0'; -- Default...
+ --
+ if RESULT_I = x"00000000" and RESULT_II(31 downto 0) = x"00000000" then
+ XNZVC_OUT <= XNZVC_IN(4) & '0' & '1' & '0' & '0'; -- Result is zero.
+ elsif OP_SIZE = WORD and RESULT_I(31) = '1' then
+ XNZVC_OUT <= XNZVC_IN(4) & '1' & '0' & '0' & '0'; -- Negative result.
+ elsif OP_SIZE = LONG and DIV_MUL_32n64 = '0' then
+ if RESULT_I(31) = '1' and RESULT_II(31 downto 0) /= x"00000000" then -- Negative and overflow.
+ XNZVC_OUT <= XNZVC_IN(4) & '1' & '0' & '1' & '0';
+ elsif RESULT_I(31) = '1' then -- Negative.
+ XNZVC_OUT <= XNZVC_IN(4) & '1' & '0' & '0' & '0';
+ elsif RESULT_II(31 downto 0) /= x"00000000" then -- Overflow.
+ XNZVC_OUT <= XNZVC_IN(4) & '0' & '0' & '1' & '0';
+ end if;
+ elsif OP_SIZE = LONG and RESULT_II(31) = '1' then -- Long64 form: negative result, no overflow.
+ XNZVC_OUT <= XNZVC_IN(4) & '1' & '0' & '0' & '0';
+ end if;
+ when SWAP =>
+ -- The FLAGS are calculated 'look ahead' for the register and the
+ -- condition code register is written simultaneously.
+ -- The OP_IN(15) is the swapped bit 31.
+ if RESULT_SPECIAL = x"00000000" then
+ XNZVC_OUT <= XNZVC_IN(4) & "0100";
+ else
+ XNZVC_OUT <= XNZVC_IN(4) & RESULT_SPECIAL(31) & "000";
+ end if;
+ when TAS => -- TAS is Byte only.
+ if OP_IN_D_SIGN_LO(7 downto 0) = x"00" then
+ XNZVC_OUT <= XNZVC_IN(4) & "0100";
+ else
+ XNZVC_OUT <= XNZVC_IN(4) & OP_IN_D_SIGN_LO(7) &"000";
+ end if;
+ when others => XNZVC_OUT <= "-----";
+ end case;
+ end process COND_CODES;
+
+ -- For the source and destination operands it is necessary to distinguish between WORD and LONG format and between
+ -- signed and unsigned operations:
+ MUL_DIV_OP_S <= x"FFFF" & OP_IN_S(15 downto 0) when OP_SIZE = WORD and OP_IN_S(15) = '1' and (OP = MULS or OP = DIVS) else
+ x"0000" & OP_IN_S(15 downto 0) when OP_SIZE = WORD else OP_IN_S;
+
+ MUL_OP_D <= x"FFFF" & OP_IN_D_LO(15 downto 0) when OP_SIZE = WORD and OP_IN_D_LO(15) = '1' and OP = MULS else
+ x"0000" & OP_IN_D_LO(15 downto 0) when OP_SIZE = WORD else OP_IN_D_LO;
+
+ MUL_DIV_BUFFER: process(RESETn, CLK)
+ -- The Result is stored in two 32 bit wide registers. If a register is not used in an
+ -- operation, it remains unchanged. If parts of a register are not used, the respective
+ -- bits also remain unchanged.
+ begin
+ if RESETn = '0' then
+ RESULT_I <= (others => '0');
+ RESULT_II <= (others => '0');
+ elsif CLK = '1' and CLK' event then
+ -- The MULS, MULU, DIVS, DIVU require a definite start condition in form
+ -- of a start strobe.
+ if OP_START = '1' then
+ case OP is
+ when MULS | MULU => -- Load operands.
+ RESULT_II <= (others => '0');
+ if OP_IN_D_LO = x"00000000" or OP_IN_S = x"00000000" then
+ -- The result is zero if any of the operands is zero.
+ RESULT_I <= x"00000000";
+ else
+ RESULT_I <= MUL_OP_D;
+ end if;
+ when DIVU =>
+ -- Register function: see DIV_STATE_DEC process.
+ if OP_SIZE = LONG and DIV_MUL_32n64 = '1' then
+ DIVIDEND <= OP_IN_D_HI & OP_IN_D_LO;
+ else
+ DIVIDEND <= x"00000000" & OP_IN_D_LO;
+ end if;
+ DIVISOR <= x"00000000" & MUL_DIV_OP_S;
+ RESULT_I <= (others => '0'); -- Initialize.
+ RESULT_II <= (others => '0'); -- Initialize.
+ DIV_VAR <= x"00000001"; -- Shift variable.
+ when DIVS =>
+ -- Register function: see DIV_STATE_DEC process.
+ if OP_SIZE = LONG and DIV_MUL_32n64 = '1' and OP_IN_D_HI(31) = '0' then
+ DIVIDEND <= OP_IN_D_HI & OP_IN_D_LO; -- Positive.
+ elsif OP_SIZE = LONG and DIV_MUL_32n64 = '1' then
+ DIVIDEND <= unsigned(not(OP_IN_D_HI & OP_IN_D_LO)) + '1';
+ elsif OP_IN_D_LO(31) = '0' then
+ DIVIDEND <= x"00000000" & OP_IN_D_LO; -- Positive.
+ else
+ DIVIDEND <= x"00000000" & unsigned(not(OP_IN_D_LO)) + '1'; -- Negative, load twos complement.
+ end if;
+ --
+ if MUL_DIV_OP_S(31) = '1' then
+ DIVISOR <= x"00000000" & unsigned(not(MUL_DIV_OP_S)) + '1'; -- Negative, load twos complement.
+ else
+ DIVISOR <= x"00000000" & MUL_DIV_OP_S;
+ end if;
+ RESULT_I <= (others => '0'); -- Initialize.
+ RESULT_II <= (others => '0'); -- Initialize.
+ DIV_VAR <= x"00000001"; -- Shift variable.
+ when others =>
+ null;
+ end case;
+ elsif MUL_STATE = MUL_ADD then
+ -- Use sign extended value of source operand for MULS.
+ -- The RESULT_II(32) is the carry bit of the adder.
+ RESULT_II <= unsigned(RESULT_II) + unsigned(MUL_DIV_OP_S);
+ elsif MUL_STATE = MUL_VERIFY_SHIFT then -- Right shift.
+ -- Special case:
+ -- The MULS algorithm works fine, if we sign extend the operands and shift over a bit width of the result width.
+ -- This is done for the WORD format. In case of the LONG format, we shift 32 times (time efficient multiplication).
+ -- The algorithm delivers a wrong result in case of the signed multiplikation, when one or both operand are
+ -- negative. This error does not take any effect in the first LONG form, where the wrong high register result is
+ -- discarded. In case of the second long form, the high register result must be corrected by the addition of the
+ -- twos complements of the respective operands. The correction takes place during the last shift step.
+ case MUL_CYC_CNT is
+ when "000000" =>
+ if OP = MULS and OP_SIZE = LONG and MUL_DIV_OP_S(31) = '1' and OP_IN_D_LO(31) = '1' then
+ RESULT_II <= unsigned('0' & RESULT_II(32 downto 1)) + unsigned(not(OP_IN_D_LO)) + '1'
+ + unsigned(not(MUL_DIV_OP_S)) + '1';
+ elsif OP = MULS and OP_SIZE = LONG and MUL_DIV_OP_S(31) = '1' then
+ RESULT_II <= unsigned('0' & RESULT_II(32 downto 1)) + unsigned(not(OP_IN_D_LO)) + '1';
+ elsif OP = MULS and OP_SIZE = LONG and OP_IN_D_LO(31) = '1' then
+ RESULT_II <= unsigned('0' & RESULT_II(32 downto 1)) + unsigned(not(MUL_DIV_OP_S)) + '1';
+ else
+ RESULT_II <= '0' & RESULT_II(32 downto 1); -- Carry Bit at MSB.
+ end if;
+ when others => RESULT_II <= '0' & RESULT_II(32 downto 1);
+ end case;
+ RESULT_I <= RESULT_II(0) & RESULT_I(31 downto 1);
+ elsif DIV_SHIFT_EN = '1' then -- Shift the DIVIDEND left.
+ -- Shift the DIVIDEND and the shift variable:
+ DIVISOR <= DIVISOR(62 downto 0) & '0';
+ DIV_VAR <= DIV_VAR(30 downto 0) & '0';
+ elsif DIV_STATE = DIV_ADDSUB then
+ -- The subtraction is unsigned for DIVS and DIVU.
+ DIVIDEND <= unsigned(DIVIDEND) - unsigned(DIVISOR); -- Remainder's register.
+ RESULT_I <= unsigned(RESULT_I) + unsigned(DIV_VAR); -- Quotient's register.
+ -- Reset the shift variable and reload the DIVISOR:
+ DIV_VAR <= x"00000001";
+ if OP = DIVS and MUL_DIV_OP_S(31) = '1' then
+ DIVISOR <= x"00000000" & unsigned(not(MUL_DIV_OP_S)) + '1'; -- Negative, load twos complement.
+ else
+ DIVISOR <= x"00000000" & MUL_DIV_OP_S;
+ end if;
+ elsif DIV_STATE = DIV_SIGN then
+ case OP_SIZE is
+ when LONG =>
+ if DIV_MUL_32n64 = '1' and OP = DIVS and ((OP_IN_D_HI(31) xor OP_IN_S(31)) = '1') then -- 64 bit dividend.
+ RESULT_I <= unsigned(not(RESULT_I)) + '1'; -- Negative, change sign.
+ elsif OP = DIVS and ((OP_IN_D_LO(31) xor OP_IN_S(31)) = '1') then -- 32 bit dividend.
+ RESULT_I <= unsigned(not(RESULT_I)) + '1'; -- Negative, change sign.
+ end if;
+ when others => -- WORD.
+ if OP = DIVS and ((OP_IN_D_LO(31) xor OP_IN_S(15)) = '1') then
+ RESULT_I <= unsigned(not(RESULT_I)) + '1'; -- Negative, change sign.
+ end if;
+ end case;
+ --
+ -- Remainder's sign = DIVISOR's sign:
+ if OP = DIVS and OP_SIZE = LONG and DIV_MUL_32n64 = '1' and OP_IN_D_HI(31) = '1' then
+ RESULT_II(31 downto 0) <= unsigned(not(DIVIDEND(31 downto 0))) + '1';
+ elsif OP = DIVS and DIV_MUL_32n64 = '0' and OP_IN_D_LO(31) = '1' then
+ RESULT_II(31 downto 0) <= unsigned(not(DIVIDEND(31 downto 0))) + '1';
+ else
+ RESULT_II(31 downto 0) <= DIVIDEND(31 downto 0);
+ end if;
+ end if;
+ end if;
+ end process MUL_DIV_BUFFER;
+
+ MUL_REGs: process(RESETn, CLK, MUL_CYC_CNT, MUL_STATE)
+ -- This unit provides on the one hand the state register for the
+ -- multiplier state machine and on the other hand the progress
+ -- control in form of the cycle counter MUL_CYC_CNT.
+ begin
+ if RESETn = '0' then
+ MUL_CYC_CNT <= "000000";
+ MUL_STATE <= MUL_IDLE;
+ elsif CLK = '1' and CLK' event then
+ --
+ MUL_STATE <= NEXT_MUL_STATE;
+ --
+ -- Cycle counter arithmetic:
+ if (OP = MULS or OP = MULU) and OP_START = '1' then
+ MUL_CYC_CNT <= "100000";
+ elsif MUL_STATE = MUL_VERIFY_SHIFT and (OP_IN_D_LO = x"00000000" or OP_IN_S = x"00000000") then
+ MUL_CYC_CNT <= "000000";
+ elsif MUL_STATE = MUL_VERIFY_SHIFT then
+ case MUL_CYC_CNT is
+ when "000000" => null;
+ when others => MUL_CYC_CNT <= MUL_CYC_CNT - '1';
+ end case;
+ end if;
+ end if;
+ --
+ case MUL_CYC_CNT is
+ when "000000" =>
+ if MUL_STATE = MUL_IDLE then
+ OP_MUL <= '0';
+ else
+ OP_MUL <= '1';
+ end if;
+ when others => OP_MUL <= '1';
+ end case;
+ end process MUL_REGs;
+
+ MUL_DEC: process(MUL_STATE, OP_START, OP, RESULT_I, MUL_CYC_CNT, OP_IN_D_LO, OP_IN_S)
+ --This is the process for the MULU and MULS operation.
+ -- This multiplier provides the WORD format as also the LONG formats of the 68K20+.
+ -- The algorithm for this multiplication is partly taken from:
+ -- http://mandalex.manderby.com/i/integerarithmetik.php?id=94, dated September, 2006.
+ -- The site is in German language.
+ begin
+ case MUL_STATE is
+ when MUL_IDLE =>
+ if (OP = MULS or OP = MULU) and OP_START = '1' then
+ NEXT_MUL_STATE <= MUL_VERIFY_SHIFT;
+ else
+ NEXT_MUL_STATE <= MUL_IDLE;
+ end if;
+ when MUL_VERIFY_SHIFT =>
+ if OP_IN_D_LO = x"00000000" or OP_IN_S = x"00000000" then
+ NEXT_MUL_STATE <= MUL_IDLE; -- Product is zero.
+ elsif RESULT_I(0) = '1' then
+ NEXT_MUL_STATE <= MUL_ADD;
+ else
+ case MUL_CYC_CNT is
+ when "000000" =>
+ NEXT_MUL_STATE <= MUL_IDLE; -- Finished.
+ when others =>
+ NEXT_MUL_STATE <= MUL_VERIFY_SHIFT; -- Go on.
+ end case;
+ end if;
+ when MUL_ADD =>
+ NEXT_MUL_STATE <= MUL_VERIFY_SHIFT;
+ end case;
+ end process MUL_DEC;
+
+ DIV_REGs: process(RESETn, CLK)
+ -- This unit provides the state register for the divider
+ -- state machine.
+ begin
+ if RESETn = '0' then
+ DIV_STATE <= DIV_IDLE;
+ elsif CLK = '1' and CLK' event then
+ DIV_STATE <= NEXT_DIV_STATE;
+ -- MSB for overflow check:
+ -- During adding a value to the RESULT_I, one operand is ADR_VAR and the other
+ -- one is RESULT_I itself. For overflow checking, it is therefore required to store
+ -- the old RESULT_I operand's MSB.
+ if OP_START = '1' then
+ DIV_OLD_MSB <= '0';
+ elsif DIV_STATE = DIV_ADDSUB and OP = DIVS then
+ case OP_SIZE is
+ when LONG =>
+ DIV_OLD_MSB <= RESULT_I(30);
+ when others => -- Word.
+ DIV_OLD_MSB <= RESULT_I(14);
+ end case;
+ elsif DIV_STATE = DIV_ADDSUB then
+ case OP_SIZE is
+ when LONG =>
+ DIV_OLD_MSB <= RESULT_I(31);
+ when others => -- Word.
+ DIV_OLD_MSB <= RESULT_I(15);
+ end case;
+ end if;
+ end if;
+ end process DIV_REGs;
+
+ DIV_DEC: process(DIV_STATE, OP_START, OP, OP_IN_S, DIVIDEND, DIVISOR, RESULT_I, OP_SIZE, DIV_VAR, DIV_OLD_MSB)
+ -- This is the process for the DIVU and DIVS operation. The division is always done
+ -- with the positive operands by loading the positive value or the 2s complement of the
+ -- negative value. After the last computation step, the sign is taken into account to get
+ -- the correct result.
+ -- This divider provides the WORD format as also the LONG formats of the 68K20+.
+ --
+ -- The Registers are used as follows:
+ -- Word:
+ -- The DIVIDEND is located in the DIVIDEND register.
+ -- The DIVISOR is located in lowest word of the DIVISOR register.
+ -- The quotient is located in RESULT_I(15 downto 0).
+ -- The remainder is located in RESULT_II(15 downto 0).
+ -- The shift variable is located in DIV_VAR.
+ -- LONG:
+ -- The DIVIDEND is located in the DIVIDEND register (lower Word for 32 bit DIVIDEND).
+ -- The DIVISOR is located in the lower half of the DIVISOR register.
+ -- The quotient is located in RESULT_I
+ -- The remainder is located in RESULT_II
+ -- The shift variable is located in DIV_VAR.
+ begin
+ -- Default assignments:
+ DIV_SHIFT_EN <= '0';
+ OP_DIV <= '1';
+
+ case DIV_STATE is
+ when DIV_IDLE =>
+ if (OP = DIVS or OP = DIVU) and OP_START = '1' and OP_IN_S = x"00000000" then
+ NEXT_DIV_STATE <= DIV_IDLE; -- Divide by zero -> Trap.
+ elsif (OP = DIVS or OP = DIVU) and OP_START = '1' then
+ NEXT_DIV_STATE <= DIV_VERIFY;
+ else
+ NEXT_DIV_STATE <= DIV_IDLE;
+ end if;
+ OP_DIV <= '0';
+ when DIV_VERIFY =>
+ -- Check overflow:
+ -- The variable ADR_VAR carries only one bit with a value of '1' at the same time.
+ -- Therefore the overflow can be detected by looking at the old MSB and the new one.
+ if OP_SIZE = LONG and OP = DIVS and DIV_OLD_MSB = '1' and RESULT_I(30) = '0' then
+ NEXT_DIV_STATE <= DIV_IDLE; -- Break due to overflow.
+ elsif OP_SIZE = WORD and OP = DIVS and DIV_OLD_MSB = '1' and RESULT_I(14) = '0' then
+ NEXT_DIV_STATE <= DIV_IDLE; -- Break due to overflow.
+ elsif OP_SIZE = LONG and OP = DIVU and DIV_OLD_MSB = '1' and RESULT_I(31) = '0' then
+ NEXT_DIV_STATE <= DIV_IDLE; -- Break due to overflow.
+ elsif OP_SIZE = WORD and OP = DIVU and DIV_OLD_MSB = '1' and RESULT_I(15) = '0' then
+ NEXT_DIV_STATE <= DIV_IDLE; -- Break due to overflow.
+ elsif DIVIDEND < DIVISOR then
+ NEXT_DIV_STATE <= DIV_SIGN;
+ --
+ -- A ADDSUB operation takes place, when the shifted result
+ -- would be greater than the current remainder. Otherwise, there
+ -- takes place a shift operation.
+ elsif DIVISOR(63 downto 0) & '0' > '0' & DIVIDEND then
+ NEXT_DIV_STATE <= DIV_ADDSUB;
+ else -- Shift condition:
+ if OP_SIZE = LONG and DIV_VAR(31) = '1' then
+ NEXT_DIV_STATE <= DIV_IDLE; -- Break due to DIV_VAR overflow.
+ elsif OP_SIZE = WORD and DIV_VAR(15) = '1' then
+ NEXT_DIV_STATE <= DIV_IDLE; -- Break due to DIV_VAR overflow.
+ else
+ NEXT_DIV_STATE <= DIV_VERIFY;
+ DIV_SHIFT_EN <= '1'; -- Shift operation enabled.
+ end if;
+ end if;
+ when DIV_ADDSUB =>
+ NEXT_DIV_STATE <= DIV_VERIFY;
+ when DIV_SIGN =>
+ -- Set the sign and computate the 2s complement of the quotient and the
+ -- remainder, when necessary. See result buffer.
+ NEXT_DIV_STATE <= DIV_IDLE;
+ end case;
+ end process DIV_DEC;
+
+ OV_DIV <= '1' when OP_SIZE = LONG and DIV_VAR(31) = '1' else
+ '1' when OP_SIZE = WORD and DIV_VAR(15) = '1' else
+ '1' when OP_SIZE = LONG and OP = DIVS and DIV_OLD_MSB = '1' and RESULT_I(30) = '0' else
+ '1' when OP_SIZE = WORD and OP = DIVS and DIV_OLD_MSB = '1' and RESULT_I(14) = '0' else
+ '1' when OP_SIZE = LONG and OP = DIVU and DIV_OLD_MSB = '1' and RESULT_I(31) = '0' else
+ '1' when OP_SIZE = WORD and OP = DIVU and DIV_OLD_MSB = '1' and RESULT_I(15) = '0' else '0';
+end BEHAVIOR;
diff --git a/common/CPU/68000/wf_68k00_ip/wf68k00ip_bus_interface.vhd b/common/CPU/68000/wf_68k00_ip/wf68k00ip_bus_interface.vhd
new file mode 100644
index 00000000..aff75729
--- /dev/null
+++ b/common/CPU/68000/wf_68k00_ip/wf68k00ip_bus_interface.vhd
@@ -0,0 +1,709 @@
+----------------------------------------------------------------------
+---- ----
+---- MC68000 compatible IP Core ----
+---- ----
+---- This file is part of the SUSKA ATARI clone project. ----
+---- http://www.experiment-s.de ----
+---- ----
+---- Description: ----
+---- This model provides an opcode and bus timing compatible ip ----
+---- core compared to Motorola's MC68000 microprocessor. ----
+---- ----
+---- This file contains the 68Ks bus interface unit. ----
+---- ----
+---- Description: ----
+---- This module provides bus control during read cycles, write ----
+---- cycles and read modify write cycles. It also provides 2 and ----
+---- 3 wire bus arbitration control, halt and rerun operation, ----
+---- bus and address error generation, wait state insertion and ----
+---- synchronous bus operation (68000). ----
+---- In the following there are some remarks on the working ----
+---- principle of this core. ----
+---- ----
+---- Bus cycle operation: ----
+---- A bus cycle is released by either asserting RD_BUS for ----
+---- entering a read cycle, WR_BUS for entering a write cycle or ----
+---- RDWR_BUS for entering the read modify write cycle. There ----
+---- must not be asserted two or three of these signals at the ----
+---- same time. Once the bus cycle is started, the RD_BUS, WR_BUS ----
+---- or RDWR_BUS must be asserted until the cycle finishes. This ----
+---- is indicated by the signal BUS_CYC_RDY, which is valid ----
+---- for one clock cycle after the bus operation finished. ----
+---- ----
+---- Synchronous timing topics: ----
+---- During the synchronous timing, the DTACKn must not be ----
+---- asserted and due to asynchronous timing, the VPAn must not ----
+---- be asserted, otherwise unpredictable behavior will result. ----
+---- ----
+---- Bus arbitration topics: ----
+---- No bus arbitration during read modify write cycle. ----
+---- In the case of a 2 wire bus arbitration, no re-entry for ----
+---- another device is possible. ----
+---- ----
+---- Bus error topics: ----
+---- During a bus error, the bus cycle finishes also asserting ----
+---- the BUS_CYC_RDY signal during S9 for read, write and the ----
+---- read portion of the read modify write cycle and during S19 ----
+---- for the write portion of a read modify write cycle. ----
+---- ----
+---- Bus re-run topics: ----
+---- During a re-run condition, the bus cycle finishes also ----
+---- asserting the BUS_CYC_RDY signal during S7 for read and ----
+---- write cycle and during S19 for the read modify write cycle. ----
+---- ----
+---- RESET topics: ----
+---- When a reset is released by the CPU due to the RESET_EN ----
+---- control, the RESET_RDY indicates the finishing of the reset ----
+---- cycle 124 clock cycles later. The RESET_EN may be asserted ----
+---- until RESET_RDY indicates 'ready'. The RESET_RDY is a strobe ----
+---- and therefore valid for one clock cycle. ----
+---- ----
+---- Author(s): ----
+---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
+---- ----
+----------------------------------------------------------------------
+---- ----
+---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
+---- ----
+---- This source file 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 2 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, write to the Free ----
+---- Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ----
+---- Boston, MA 02110-1301, USA. ----
+---- ----
+----------------------------------------------------------------------
+--
+-- Revision History
+--
+-- Revision 2K6B 2006/12/24 WF
+-- Initial Release.
+-- Revision 2K7A 2007/05/31 WF
+-- Updated all modules.
+-- Revision 2K7B 2007/12/24 WF
+-- See the 68K00 top level file.
+-- Revision 2K8A 2008/07/14 WF
+-- See the 68K00 top level file.
+--
+
+library work;
+use work.wf68k00ip_pkg.all;
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+
+entity WF68K00IP_BUS_INTERFACE is
+ port (
+ -- System control:
+ CLK : in bit; -- System clock.
+ RESETn : in bit; -- Core reset.
+ RESET_INn : in bit; -- System's reset input.
+ RESET_OUT_EN : out bit; -- System's reset output open drain enable.
+ RESET_CPUn : out bit; -- Internal reset used for CPU initialization.
+ RESET_EN : in bit; -- Force reset control.
+ RESET_RDY : out bit; -- Indicates the end of a forced reset cycle (strobe).
+
+ -- Data lines:
+ DATA_IN : in std_logic_vector(15 downto 0); -- Data bus input lines.
+
+ -- Receive buffers:
+ SEL_A_HI : in bit; -- Select data A buffer high byte.
+ SEL_A_MIDHI : in bit; -- Select data A buffer midhigh byte.
+ SEL_A_MIDLO : in bit; -- Select data A buffer midlow byte.
+ SEL_A_LO : in bit; -- Select data A buffer low byte.
+ SEL_BUFF_A_LO : in bit; -- Select data A buffer low word.
+ SEL_BUFF_A_HI : in bit; -- Select data A buffer high word.
+ SEL_BUFF_B_LO : in bit; -- Select data B buffer low word.
+ SEL_BUFF_B_HI : in bit; -- Select data B buffer high word.
+ SYS_INIT : in bit; -- Indicates the system initialisation (PC, SSP).
+ OP_SIZE : in OP_SIZETYPE; -- Used for the input multiplexer (buffers).
+ BUFFER_A : out std_logic_vector(31 downto 0); -- Receive buffer A.
+ BUFFER_B : out std_logic_vector(31 downto 0); -- Receive buffer B.
+ DATA_CORE_OUT : out std_logic_vector(15 downto 0); -- Data buffer.
+
+ -- Control signals:
+ RD_BUS : in bit; -- Read bus request.
+ WR_BUS : in bit; -- Wriyte request.
+ RDWR_BUS : in bit; -- Read modify write request.
+ A0 : in std_logic; -- Least significant bit of the address counter.
+ BYTEn_WORD : in bit; -- Byte or Word format for read or write bus cycles.
+ EXEC_ABORT : in bit; -- Skip the current bus cycle, if '1'.
+ BUS_CYC_RDY : out bit; -- Indicates 'Ready' (strobe).
+ DATA_VALID : out bit;
+
+ -- Bus control signals:
+ DTACKn : in bit;
+ BERRn : in bit;
+ AVECn : in bit;
+ HALTn : in std_logic;
+
+ ADR_EN : out bit;
+ WR_HI : in bit;
+ HI_WORD_EN : out bit;
+ HI_BYTE_EN : out bit;
+ LO_BYTE_EN : out bit;
+ FC_EN : out bit;
+ ASn : out bit;
+ AS_EN : out bit;
+ UDSn : out bit;
+ UDS_EN : out bit;
+ LDSn : out bit;
+ LDS_EN : out bit;
+ RWn : out bit;
+ RW_EN : out bit;
+
+ -- Synchronous Bus controls:
+ VPAn : in bit;
+ VMAn : out bit;
+ VMA_EN : out bit;
+ E : out bit;
+
+ -- Bus arbitration:
+ BRn : in bit;
+ BGACKn : in bit;
+ BGn : out bit
+ );
+end entity WF68K00IP_BUS_INTERFACE;
+
+architecture BEHAVIOR of WF68K00IP_BUS_INTERFACE is
+type ARB_STATES is(IDLE, GRANT, WAIT_RELEASE_3WIRE, WAIT_RELEASE_2WIRE);
+type TIME_SLICES is (S0, S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, S12, S13, S14, S15, S16, S17, S18, S19, S20);
+signal RESET_OUT_EN_I : bit;
+signal RESET_CPU_In : bit;
+signal ARB_STATE : ARB_STATES;
+signal NEXT_ARB_STATE : ARB_STATES;
+signal T_SLICE : TIME_SLICES;
+signal SLICE_CNT : std_logic_vector(3 downto 0);
+signal BERR : bit;
+signal FC_ENAB : bit;
+signal VMA_In : bit;
+signal UDS_RD_EN_N : bit;
+signal UDS_RD_EN_P : bit;
+signal UDS_RD_EN : bit;
+signal LDS_RD_EN_N : bit;
+signal LDS_RD_EN_P : bit;
+signal LDS_RD_EN : bit;
+signal UDS_WR_EN_N : bit;
+signal UDS_WR_EN_P : bit;
+signal UDS_WR_EN : bit;
+signal LDS_WR_EN_N : bit;
+signal LDS_WR_EN_P : bit;
+signal LDS_WR_EN : bit;
+signal UDS_RDWR_EN_N : bit; -- For read modify write;
+signal UDS_RDWR_EN_P : bit; -- For read modify write;
+signal UDS_RDWR_EN : bit; -- For read modify write;
+signal LDS_RDWR_EN_N : bit; -- For read modify write;
+signal LDS_RDWR_EN_P : bit; -- For read modify write;
+signal LDS_RDWR_EN : bit; -- For read modify write;
+signal AS_ENAB_N : bit;
+signal AS_ENAB_P : bit;
+signal AS_ENAB : bit;
+signal AS_RDWR_INH : bit; -- For read modify write;
+signal DATA_EN_N : bit;
+signal DATA_EN_P : bit;
+signal DATA_EN : bit;
+signal DATA_RDWR_EN_N : bit; -- For read modify write;
+signal DATA_RDWR_EN_P : bit; -- For read modify write;
+signal DATA_RDWR_EN : bit; -- For read modify write;
+signal WR_ENAB_P : bit;
+signal WR_ENAB : bit;
+signal WR_EN_RDWR_P : bit; -- For read modify write;
+signal WR_RDWR_EN : bit; -- For read modify write;
+signal ADR_INH : bit;
+signal ADR_RDWR_INH : bit; -- For read modify write;
+signal WAITSTATES : bit;
+signal HALTED : bit;
+signal SYNCn : bit;
+begin
+ -- Three state controls:
+ UDS_EN <= '1' when BGACKn = '1' else '0'; -- Hi-Z during arbitration.
+ LDS_EN <= '1' when BGACKn = '1' else '0'; -- Hi-Z during arbitration.
+ AS_EN <= '1' when BGACKn = '1' else '0'; -- Hi-Z during arbitration.
+ RW_EN <= '1' when BGACKn = '1' else '0'; -- Hi-Z during arbitration.
+
+ DATA_VALID <= '1' when T_SLICE = S6 else '0'; -- Sample the data during S6.
+
+ BUS_BUFFER: process(RESETn, CLK)
+ -- This process samples the data from the data bus during the bus phase S6.
+ -- During S6 the received data from the bus is valid depending on the selection
+ -- of UDSn and LDSn. This means that the respective byte (high or low) is valid,
+ -- if wether UDSn or LDSn is asserted. If both are asserted, both bytes are valid.
+ -- For S6 is followed by a falling clock edge, the process reacts on it.
+ begin
+ if RESETn = '0' then
+ BUFFER_A <= (others => '0');
+ BUFFER_B <= (others => '0');
+ elsif CLK = '0' and CLK' event then
+ if T_SLICE = S6 and SEL_A_HI = '1' and A0 = '0' and RD_BUS = '1' then -- Read Byte from even address.
+ BUFFER_A(31 downto 24) <= DATA_IN(15 downto 8);
+ elsif T_SLICE = S6 and SEL_A_HI = '1' and RD_BUS = '1' then -- Read Byte from odd address.
+ BUFFER_A(31 downto 24) <= DATA_IN(7 downto 0);
+ elsif T_SLICE = S6 and SEL_A_MIDHI = '1' and A0 = '0' and RD_BUS = '1' then
+ BUFFER_A(23 downto 16) <= DATA_IN(15 downto 8);
+ elsif T_SLICE = S6 and SEL_A_MIDHI = '1' and RD_BUS = '1' then
+ BUFFER_A(23 downto 16) <= DATA_IN(7 downto 0);
+ elsif T_SLICE = S6 and SEL_A_MIDLO = '1' and A0 = '0' and RD_BUS = '1' then
+ BUFFER_A(15 downto 8) <= DATA_IN(15 downto 8);
+ elsif T_SLICE = S6 and SEL_A_MIDLO = '1' and RD_BUS = '1' then
+ BUFFER_A(15 downto 8) <= DATA_IN(7 downto 0);
+ elsif T_SLICE = S6 and SEL_A_LO = '1' and A0 = '0' and RD_BUS = '1' then
+ BUFFER_A(7 downto 0) <= DATA_IN(15 downto 8);
+ elsif T_SLICE = S6 and SEL_A_LO = '1' and RD_BUS = '1' then
+ BUFFER_A(7 downto 0) <= DATA_IN(7 downto 0);
+ --
+ elsif T_SLICE = S6 and SYS_INIT = '1' and SEL_BUFF_A_HI = '1' then -- During system startup.
+ BUFFER_A(31 downto 16) <= DATA_IN;
+ elsif T_SLICE = S6 and SYS_INIT = '1' and SEL_BUFF_A_LO = '1' then -- During system startup.
+ BUFFER_A(15 downto 0) <= DATA_IN;
+ elsif T_SLICE = S6 and SEL_BUFF_A_LO = '1' and OP_SIZE = BYTE and A0 = '0' then -- Byte from an even address.
+ BUFFER_A <= x"000000" & DATA_IN(15 downto 8);
+ elsif T_SLICE = S6 and SEL_BUFF_A_LO = '1' and OP_SIZE = BYTE then -- Byte from an odd address.
+ BUFFER_A <= x"000000" & DATA_IN(7 downto 0);
+ elsif T_SLICE = S6 and SEL_BUFF_A_LO = '1' then -- Word or long access.
+ BUFFER_A(15 downto 0) <= DATA_IN;
+ elsif T_SLICE = S6 and SEL_BUFF_A_HI = '1' then -- Long access.
+ BUFFER_A(31 downto 16) <= DATA_IN;
+ --
+ elsif T_SLICE = S6 and SEL_BUFF_B_LO = '1' and OP_SIZE = BYTE and A0 = '0' then -- Byte from an even address.
+ BUFFER_B <= x"000000" & DATA_IN(15 downto 8);
+ elsif T_SLICE = S6 and SEL_BUFF_B_LO = '1' and OP_SIZE = BYTE then -- Byte from an odd address.
+ BUFFER_B <= x"000000" & DATA_IN(7 downto 0);
+ elsif T_SLICE = S6 and SEL_BUFF_B_LO = '1' then -- Word or long access.
+ BUFFER_B(15 downto 0) <= DATA_IN;
+ elsif T_SLICE = S6 and SEL_BUFF_B_HI = '1' then -- Long access.
+ BUFFER_B(31 downto 16) <= DATA_IN;
+ end if;
+ if T_SLICE = S6 then
+ DATA_CORE_OUT <= DATA_IN; -- Transparent buffer.
+ end if;
+ end if;
+ end process BUS_BUFFER;
+
+ -- For the condition of the bus error see the 68K family user manual.
+ -- Bus errors during S0, S1 and S2 cannot occur.
+ -- There are no retry cycles in the read modify write mode.
+ BERR <= '1' when BERRn = '0' and HALTn = '1' and DTACKn = '1' and T_SLICE /= S0 and T_SLICE /= S1 and T_SLICE /= S2 else
+ '1' when BERRn = '0' and HALTn = '0' and RDWR_BUS = '1' and T_SLICE /= S0 and T_SLICE /= S1 and T_SLICE /= S2 else '0';
+
+ BUS_CYC_RDY <= '0' when BERRn = '0' and HALTn = '0' else -- Force a retry cycle.
+ '1' when HALTED = '1' and HALTn = '1' else -- Release immediately after the halt.
+ '1' when (RD_BUS = '1' or WR_BUS = '1') and T_SLICE = S7 else
+ '1' when RDWR_BUS = '1' and T_SLICE = S19 else '0';
+
+ FC_EN <= '1' when FC_ENAB = '1' else '0';
+
+ ADR_EN <= '1' when (RD_BUS = '1' or WR_BUS = '1') and ADR_INH = '0' else
+ '1' when RDWR_BUS = '1' and ADR_RDWR_INH = '0' else '0';
+
+ ASn <= '0' when (RD_BUS = '1' or WR_BUS = '1') and AS_ENAB = '1' else
+ '0' when RDWR_BUS = '1' and AS_RDWR_INH = '0' else '1';
+
+ UDSn <= '0' when RD_BUS = '1' and UDS_RD_EN = '1' and A0 = '0' and BYTEn_WORD = '0' else
+ '0' when WR_BUS = '1' and UDS_WR_EN = '1' and A0 = '0' and BYTEn_WORD = '0' else
+ '0' when RD_BUS = '1' and UDS_RD_EN = '1' and BYTEn_WORD = '1' else
+ '0' when WR_BUS = '1' and UDS_WR_EN = '1' and BYTEn_WORD = '1' else
+ -- Read modify write is always byte wide:
+ '0' when RDWR_BUS = '1' and UDS_RDWR_EN = '1' and A0 = '0' else '1';
+
+ LDSn <= '0' when RD_BUS = '1' and LDS_RD_EN = '1' and A0 = '1' and BYTEn_WORD = '0' else
+ '0' when WR_BUS = '1' and LDS_WR_EN = '1' and A0 = '1' and BYTEn_WORD = '0' else
+ '0' when RD_BUS = '1' and LDS_RD_EN = '1' and BYTEn_WORD = '1' else
+ '0' when WR_BUS = '1' and LDS_WR_EN = '1' and BYTEn_WORD = '1' else
+ -- Read modify write is always byte wide:
+ '0' when RDWR_BUS = '1' and LDS_RDWR_EN = '1' and A0 = '1' else '1';
+
+ RWn <= '0' when WR_BUS = '1' and WR_ENAB = '1' else
+ '0' when RDWR_BUS = '1' and WR_RDWR_EN = '1' else '1';
+
+ -- To meet the behavior of the bus during bus error, the HI_WORD_EN must have higher priority than
+ -- HI_BYTE_EN or LOW_BYTE_EN (using these signals for the bus drivers).
+ -- Nevertheless during bus error, there will be written invalid data via the HI_WORD_EN signal to the bus.
+ -- Read modify write is always byte wide due to used exclusively by the TAS operation.
+ HI_WORD_EN <= '1' when WR_BUS = '1' and DATA_EN = '1' and WR_HI = '1' else '0';
+ HI_BYTE_EN <= '1' when WR_BUS = '1' and DATA_EN = '1' and A0 = '0' and BYTEn_WORD = '0' else
+ '1' when WR_BUS = '1' and DATA_EN = '1' and BYTEn_WORD = '1' else
+ '1' when RDWR_BUS = '1' and DATA_RDWR_EN = '1' and A0 = '0' else '0';
+ LO_BYTE_EN <= '1' when WR_BUS = '1' and DATA_EN = '1' and A0 = '1' and BYTEn_WORD = '0' else
+ '1' when WR_BUS = '1' and DATA_EN = '1' and BYTEn_WORD = '1' else
+ '1' when RDWR_BUS = '1' and DATA_RDWR_EN = '1' and A0 = '1' else '0';
+
+ P_WAITSTATES: process
+ -- During read, write or read modify write processes, the read access is delayed by wait
+ -- states (slow read, slow write) if there is no DTACKn asserted until the end of S4 and
+ -- until the end of S16 (during read modify write). This is done by stopping the slice
+ -- counter. After the halt, in principle a S5, S17 bwould be possible. This is not correct
+ -- for not asserted DTACKn. This process provides a locking of this forbidden case and the
+ -- stop control for the slice counter. For more information see the 68000 processor data
+ -- sheet (bus cycles).
+ -- In case of a buss error, the bus cycle is finished by realeasing the WAITSTATES via BERR.
+ -- The SYNCn controls the synchronous bus timing. This is not valid for read modify write
+ -- cycles.
+ -- The AVECn ends the bus cycle in case of an autovector interrupt acknowledge cycle.
+ begin
+ wait until CLK = '0' and CLK' event;
+ if T_SLICE = S4 then
+ WAITSTATES <= DTACKn and SYNCn and AVECn and not BERR;
+ elsif T_SLICE = S16 then
+ WAITSTATES <= DTACKn and not BERR; -- For read modify write.
+ else
+ WAITSTATES <= '0';
+ end if;
+ end process P_WAITSTATES;
+
+ HALTSTATE: process
+ -- This is a flag to control the halted state of a bus cycle
+ -- and to release the BUS_CYC_RDY in the halted state.
+ begin
+ wait until CLK = '1' and CLK' event;
+ if HALTn = '0' and BERRn = '1' then
+ HALTED <= '1';
+ elsif SLICE_CNT = "0000" and HALTn = '1' then
+ HALTED <= '0';
+ end if;
+ end process HALTSTATE;
+
+ SLICES: process(RESETn, CLK)
+ -- This process provides the central timing for the read, write and read modify write cycle
+ -- as also for the bus arbitration procedure.
+ begin
+ if RESETn = '0' then
+ SLICE_CNT <= "1111";
+ elsif CLK = '1' and CLK' event then
+ -- Cycle reset:
+ if RESET_CPU_In = '0' then
+ SLICE_CNT <= "0000"; -- Abort current bus cycle.
+ elsif ARB_STATE /= IDLE and SLICE_CNT = "0000" then -- Do not start a bus sequence when the bus is granted.
+ SLICE_CNT <= "1111";
+ elsif ARB_STATE /= IDLE and SLICE_CNT = "1111" then -- Stay until the bus is released.
+ SLICE_CNT <= "1111";
+ -- Initialization:
+ elsif RD_BUS = '0' and WR_BUS = '0' and RDWR_BUS = '0' then
+ SLICE_CNT <= "0000"; -- Init.
+ elsif SLICE_CNT = "0000" and HALTn = '0' then
+ SLICE_CNT <= "0000"; -- Wait in retry or halt operation until HALTn is released.
+ -- Counting:
+ elsif (RD_BUS = '1' or WR_BUS = '1') and SLICE_CNT = "0011" then
+ SLICE_CNT <= "0000"; -- Finish the read or write cycle.
+ elsif RDWR_BUS = '1' and SLICE_CNT = "1001" then
+ SLICE_CNT <= "0000"; -- Finish the read modify write cycle.
+ elsif (RD_BUS = '1' or WR_BUS = '1' or RDWR_BUS = '1') and WAITSTATES = '0' and HALTED = '0' then
+ SLICE_CNT <= SLICE_CNT + '1'; -- Cycle active.
+ end if;
+ end if;
+ end process SLICES;
+
+ T_SLICE <= S0 when RD_BUS = '0' and WR_BUS = '0' and RDWR_BUS = '0' else -- IDLE Mode.
+ S0 when SLICE_CNT = "0000" and CLK = '1' else
+ S0 when SLICE_CNT = "0000" and CLK = '0' and HALTn = '0' else -- Stay in IDLE during retry with HALTn asserted.
+ S1 when SLICE_CNT = "0000" and CLK = '0' else
+ S2 when SLICE_CNT = "0001" and CLK = '1' else
+ S3 when SLICE_CNT = "0001" and CLK = '0' else
+ S4 when SLICE_CNT = "0010" and CLK = '1' else
+ S4 when WAITSTATES = '1' and SLICE_CNT = "0010" and CLK = '0' else
+ S5 when WAITSTATES = '0' and SLICE_CNT = "0010" and CLK = '0' else
+ S6 when SLICE_CNT = "0011" and CLK = '1' else
+ S7 when SLICE_CNT = "0011" and CLK = '0' else
+ S8 when SLICE_CNT = "0100" and CLK = '1' else
+ S9 when SLICE_CNT = "0100" and CLK = '0' else
+ S10 when SLICE_CNT = "0101" and CLK = '1' else
+ S11 when SLICE_CNT = "0101" and CLK = '0' else
+ S12 when SLICE_CNT = "0110" and CLK = '1' else
+ S13 when SLICE_CNT = "0110" and CLK = '0' else
+ S14 when SLICE_CNT = "0111" and CLK = '1' else
+ S15 when SLICE_CNT = "0111" and CLK = '0' else
+ S16 when SLICE_CNT = "1000" and CLK = '1' else
+ S16 when WAITSTATES = '1' and SLICE_CNT = "1000" and CLK = '0' else
+ S17 when WAITSTATES = '0' and SLICE_CNT = "1000" and CLK = '0' else
+ S18 when SLICE_CNT = "1001" and CLK = '1' else
+ S19 when SLICE_CNT = "1001" and CLK = '0' else S20; -- S20 is the Bus arbitration state.
+
+ -- The modelling with the two processes working on the positive and negative clock edge
+ -- is a bit complicated. But it results in rather 'clean' (glitch free) bus control
+ -- signals. Every signal is modelled with it's own timing to give the core a high degree
+ -- of freedom.
+ N: process
+ begin
+ wait until CLK = '0' and CLK' event;
+ case T_SLICE is
+ when S4 => UDS_WR_EN_N <= '1';
+ when others => UDS_WR_EN_N <= '0';
+ end case;
+ case T_SLICE is
+ when S4 => LDS_WR_EN_N <= '1';
+ when others => LDS_WR_EN_N <= '0';
+ end case;
+ case T_SLICE is
+ when S2 | S4 => UDS_RD_EN_N <= '1';
+ when others => UDS_RD_EN_N <= '0';
+ end case;
+ case T_SLICE is
+ when S2 | S4 => LDS_RD_EN_N <= '1';
+ when others => LDS_RD_EN_N <= '0';
+ end case;
+
+ case T_SLICE is
+ when S2 | S4 => AS_ENAB_N <= '1';
+ when others => AS_ENAB_N <= '0';
+ end case;
+ case T_SLICE is
+ when S2 | S4 | S16 => UDS_RDWR_EN_N <= '1';
+ when others => UDS_RDWR_EN_N <= '0';
+ end case;
+ case T_SLICE is
+ when S2 | S4 | S16 => LDS_RDWR_EN_N <= '1';
+ when others => LDS_RDWR_EN_N <= '0';
+ end case;
+ case T_SLICE is
+ when S2 => DATA_EN_N <= '1';
+ when others => DATA_EN_N <= '0';
+ end case;
+ case T_SLICE is
+ when S14 => DATA_RDWR_EN_N <= '1';
+ when others => DATA_RDWR_EN_N <= '0';
+ end case;
+ end process N;
+
+ P: process
+ begin
+ wait until CLK = '1' and CLK' event;
+ case T_SLICE is
+ when S1 | S3 => AS_ENAB_P <= '1';
+ when others => AS_ENAB_P <= '0';
+ end case;
+ case T_SLICE is
+ when S3 => UDS_WR_EN_P <= '1';
+ when others => UDS_WR_EN_P <= '0';
+ end case;
+ case T_SLICE is
+ when S1 | S3 | S15 => UDS_RDWR_EN_P <= '1';
+ when others => UDS_RDWR_EN_P <= '0';
+ end case;
+ case T_SLICE is
+ when S1 | S3 | S15 => LDS_RDWR_EN_P <= '1';
+ when others => LDS_RDWR_EN_P <= '0';
+ end case;
+ case T_SLICE is
+ when S3 => LDS_WR_EN_P <= '1';
+ when others => LDS_WR_EN_P <= '0';
+ end case;
+ case T_SLICE is
+ when S1 | S3 => UDS_RD_EN_P <= '1';
+ when others => UDS_RD_EN_P <= '0';
+ end case;
+ case T_SLICE is
+ when S1 | S3 => LDS_RD_EN_P <= '1';
+ when others => LDS_RD_EN_P <= '0';
+ end case;
+ case T_SLICE is
+ when S1 | S3 | S4 | S5 => WR_ENAB_P <= '1'; -- S4 due to wait states.
+ when others => WR_ENAB_P <= '0';
+ end case;
+ case T_SLICE is
+ when S13 | S15 | S16 | S17 => WR_EN_RDWR_P <= '1'; -- S16 due to wait states.
+ when others => WR_EN_RDWR_P <= '0';
+ end case;
+ case T_SLICE is
+ when S3 | S4 | S5 => DATA_EN_P <= '1'; -- S4 due to wait states.
+ when others => DATA_EN_P <= '0';
+ end case;
+ case T_SLICE is
+ when S15 | S16 | S17 => DATA_RDWR_EN_P <= '1'; -- S16 due to wait states.
+ when others => DATA_RDWR_EN_P <= '0';
+ end case;
+ end process P;
+
+ -- Read and write timing:
+ UDS_WR_EN <= UDS_WR_EN_N or UDS_WR_EN_P; -- '1' when S4 | S5 | S6.
+ LDS_WR_EN <= LDS_WR_EN_N or LDS_WR_EN_P; -- '1' when S4 | S5 | S6.
+ UDS_RD_EN <= UDS_RD_EN_N or UDS_RD_EN_P; -- '1' when S2 | S3 | S4 | S5 | S6.
+ LDS_RD_EN <= LDS_RD_EN_N or LDS_RD_EN_P; -- '1' when S2 | S3 | S4 | S5 | S6.
+ AS_ENAB <= AS_ENAB_N or AS_ENAB_P; -- '1' when S2 | S3 | S4 | S5 | S6.
+ WR_ENAB <= WR_ENAB_P; -- '1' when S2 | S3 | S4 | S5 | S6 | S7.
+ DATA_EN <= DATA_EN_N or DATA_EN_P; -- '1' when S3 | S4 | S5 | S6 | S7.
+ ADR_INH <= '1' when T_SLICE = S0 else '0';
+ -- Read modify write timing:
+ UDS_RDWR_EN <= UDS_RDWR_EN_N or UDS_RDWR_EN_P; -- '1' when S2 | S3 | S4 | S5 | S6 | S16 | S17 | S18.
+ LDS_RDWR_EN <= LDS_RDWR_EN_N or LDS_RDWR_EN_P; -- '1' when S2 | S3 | S4 | S5 | S6 | S16 | S17 | S18.
+ AS_RDWR_INH <= '1' when T_SLICE = S0 else '0';
+ WR_RDWR_EN <= WR_EN_RDWR_P; -- '1' when S14 | S15 | S16 | S17 | S18 | S19.
+ DATA_RDWR_EN <= DATA_RDWR_EN_N or DATA_RDWR_EN_P; -- '1' when S3 | S4 | S5 | S6 | S7 | S15 | S16 | S17 | S18 | S19.
+ ADR_RDWR_INH <= '1' when T_SLICE = S0 else '0';
+
+ -- Timing valid for all modes:
+ FC_ENAB <= '0' when T_SLICE = S0 and HALTn = '0' else -- During halt.
+ '0' when RD_BUS = '0' and WR_BUS = '0' and RDWR_BUS = '0' and T_SLICE = S0 else -- Normal operation.
+ '0' when BGACKn = '0' else '1'; -- During arbitration.
+
+ -- Synchronous bus timing:
+ E_TIMER: process(RESETn, CLK)
+ -- The E clock is a free running clock with a period of 10 times
+ -- the CLK period. The pulse ratio is 4 CLK high and 6 CLK low.
+ variable TMP : std_logic_vector(3 downto 0);
+ begin
+ if RESETn = '0' then
+ TMP := x"0";
+ VMA_In <= '1';
+ SYNCn <= '1';
+ E <= '1';
+ elsif CLK = '1' and CLK' event then
+ if TMP < x"9" then
+ TMP := TMP + '1';
+ else
+ TMP := x"0";
+ end if;
+
+ -- E logic:
+ if TMP = x"0" then
+ E <= '1';
+ elsif TMP = x"4" then
+ E <= '0';
+ end if;
+
+ -- VMA logic:
+ if VPAn = '0' and TMP >= x"4" then -- Switch, when E is low.
+ VMA_In <= '0';
+ elsif T_SLICE = S7 then
+ VMA_In <= '1';
+ end if;
+
+ -- SYNCn logic (wait states controlling):
+ if VPAn = '0' and VMA_In = '0' and TMP = x"0" then -- Switch, when E is just high.
+ SYNCn <= '0';
+ elsif VPAn = '1' or VMA_In = '1' then
+ SYNCn <= '1';
+ end if;
+ end if;
+ end process E_TIMER;
+ VMA_EN <= '0' when BGACKn = '0' else '1';
+ VMAn <= VMA_In;
+
+ -- Bus arbitration:
+ ARB_REG: process(RESETn, CLK)
+ begin
+ if RESETn = '0' then
+ ARB_STATE <= IDLE;
+ elsif CLK = '1' and CLK' event then
+ ARB_STATE <= NEXT_ARB_STATE;
+ end if;
+ end process ARB_REG;
+
+ ARB_DEC: process(ARB_STATE, RDWR_BUS, BRn, RD_BUS, WR_BUS, T_SLICE, BGACKn)
+ -- The state machine for the bus grant works on the positive clock edge. Therefore it is
+ -- sufficient to control on the odd time slices (S1, S3, S5, S7). In the case, that the
+ -- bus request is asserted early, the bus grant is asserted during S4 otherwise one clock
+ -- later (S6 or IDLE).
+ begin
+ case ARB_STATE is
+ when IDLE =>
+ if RDWR_BUS = '1' then
+ NEXT_ARB_STATE <= IDLE; -- No bus arbitration during read modify write cycle.
+ elsif BRn = '0' and T_SLICE /= S1 then
+ NEXT_ARB_STATE <= GRANT; -- Bus grant delayed in case of S1, otherwise immediately.
+ else
+ NEXT_ARB_STATE <= IDLE;
+ end if;
+ when GRANT =>
+ if BGACKn = '0' then
+ NEXT_ARB_STATE <= WAIT_RELEASE_2WIRE;
+ elsif BRn = '1' then
+ NEXT_ARB_STATE <= IDLE; -- Re-initialize.
+ else
+ NEXT_ARB_STATE <= GRANT;
+ end if;
+ when WAIT_RELEASE_2WIRE =>
+ -- In the case of a 2 wire bus arbitration, no re-entry for another
+ -- device is possible.
+ if BGACKn = '1' and BRn = '1' then
+ NEXT_ARB_STATE <= IDLE;
+ elsif BGACKn = '0' then
+ NEXT_ARB_STATE <= WAIT_RELEASE_3WIRE; -- BGACKn = '0' indicates 3 wire arbitration.
+ else
+ NEXT_ARB_STATE <= WAIT_RELEASE_2WIRE;
+ end if;
+ when WAIT_RELEASE_3WIRE =>
+ if BGACKn = '1' and BRn = '0' then
+ NEXT_ARB_STATE <= GRANT; -- Re-enter new arbitration.
+ elsif BGACKn = '1' then
+ NEXT_ARB_STATE <= IDLE;
+ else
+ NEXT_ARB_STATE <= WAIT_RELEASE_3WIRE;
+ end if;
+ end case;
+ end process ARB_DEC;
+
+ BGn <= '0' when ARB_STATE = GRANT else -- 3 wire and 2 wire arbitration.
+ '0' when ARB_STATE = WAIT_RELEASE_2WIRE else '1'; -- 2 wire arbitration.
+
+ -- RESET logic:
+ RESET_FILTER: process(RESETn, CLK)
+ -- This process filters the incoming reset pin.
+ -- If RESET_INn and HALTn are asserted together for longer
+ -- than 10 clock cycles over the execution of a CPU reset
+ -- command, the CPU reset is released.
+ variable TMP : std_logic_vector(3 downto 0);
+ begin
+ if RESETn = '0' then
+ TMP := x"F"; -- For correct startup.
+ RESET_CPU_In <= '0';
+ elsif CLK = '1' and CLK' event then
+ if RESET_INn = '0' and HALTn = '0' and RESET_OUT_EN_I = '0' and TMP < x"F" then
+ TMP := TMP + '1';
+ elsif RESET_INn = '1' or HALTn = '1' or RESET_OUT_EN_I = '1' then
+ TMP := x"0";
+ end if;
+ if TMP > x"A" then
+ RESET_CPU_In <= '0'; -- Release internal reset.
+ else
+ RESET_CPU_In <= '1';
+ end if;
+ end if;
+ end process RESET_FILTER;
+
+ RESET_TIMER: process(RESETn, CLK)
+ -- This logic is responsible for the assertion of the
+ -- reset output for 124 clock cycles, during the reset
+ -- command. The LOCK variable avoids re-initialisation
+ -- of the counter in the case that the RESET_EN is no
+ -- strobe.
+ variable TMP : std_logic_vector(6 downto 0);
+ variable LOCK : boolean;
+ begin
+ if RESETn = '0' then
+ TMP := (others => '0');
+ LOCK := false;
+ elsif CLK = '1' and CLK' event then
+ if RESET_EN = '1' and LOCK = false then
+ TMP := "1111100"; -- 124 initial value.
+ LOCK := true; -- Lock the counter initialisation.
+ elsif TMP > "0000000" then
+ TMP := TMP - '1';
+ elsif RESET_EN = '0' then
+ LOCK := false; -- Unlock the counter initialisation.
+ end if;
+ if TMP = "0000001" then
+ RESET_OUT_EN_I <= '0';
+ RESET_RDY <= '1';
+ elsif TMP <= "0000011" then
+ RESET_OUT_EN_I <= '0';
+ RESET_RDY <= '0';
+ else
+ RESET_OUT_EN_I <= '1';
+ RESET_RDY <= '0';
+ end if;
+ end if;
+ end process RESET_TIMER;
+
+ RESET_OUT_EN <= RESET_OUT_EN_I;
+ RESET_CPUn <= RESET_CPU_In;
+end BEHAVIOR;
diff --git a/common/CPU/68000/wf_68k00_ip/wf68k00ip_control.vhd b/common/CPU/68000/wf_68k00_ip/wf68k00ip_control.vhd
new file mode 100644
index 00000000..dfb91b3b
--- /dev/null
+++ b/common/CPU/68000/wf_68k00_ip/wf68k00ip_control.vhd
@@ -0,0 +1,1483 @@
+----------------------------------------------------------------------
+---- ----
+---- MC68000 compatible IP Core ----
+---- ----
+---- This file is part of the SUSKA ATARI clone project. ----
+---- http://www.experiment-s.de ----
+---- ----
+---- Description: ----
+---- This model provides an opcode and bus timing compatible ip ----
+---- core compared to Motorola's MC68000 microprocessor. ----
+---- ----
+---- This file contains the system control unit. ----
+---- ----
+---- ----
+---- Description: ----
+---- Performs the core synchronization and data flow control. ----
+---- This module manages execution of all instructions. It con- ----
+---- tains the status register which consists of two portions ----
+---- supervisor byte and user byte and its related logic. ----
+---- ----
+---- ----
+---- Author(s): ----
+---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
+---- ----
+----------------------------------------------------------------------
+---- ----
+---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
+---- ----
+---- This source file 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 2 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, write to the Free ----
+---- Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ----
+---- Boston, MA 02110-1301, USA. ----
+---- ----
+----------------------------------------------------------------------
+--
+-- Revision History
+--
+-- Revision 2K6B 2006/12/24 WF
+-- Initial Release.
+-- Revision 2K7A 2007/05/31 WF
+-- Updated all modules.
+-- Revision 2K7B 2007/12/24 WF
+-- See the 68K00 top level file.
+-- Revision 2K8A 2008/07/14 WF
+-- See the 68K00 top level file.
+--
+
+use work.wf68k00ip_pkg.all;
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+
+entity WF68K00IP_CONTROL is
+ port (
+ CLK : in bit; -- System clock.
+ RESETn : in bit; -- Core reset.
+
+ -- Several data:
+ C_CODE : in bit_vector(3 downto 0); -- Conditional code.
+ REGLISTMASK : in std_logic_vector(15 downto 0); -- Used in MOVEM.
+
+ -- Main control machine signals:
+ CTRL_EN : in bit; -- Enable main controller.
+ EXEC_ABORT : in bit; -- Abort the current execution.
+ DATA_VALID : in bit; -- Indicates sample time for the bus data.
+ BUS_CYC_RDY : in bit; -- Indicates that the bus access has finished.
+ CTRL_RDY : out bit; -- Main controller finished an execution.
+
+ -- Status register and controls:
+ INIT_STATUS : in bit;
+ PRESET_IRQ_MASK : in bit;
+ SR_CCR_IN : in std_logic_vector(15 downto 0); -- Status and condition code register input.
+ IRQ : in std_logic_vector(2 downto 0);
+ IRQ_SAVE : in bit;
+ XNZVC_IN : in std_logic_vector(4 downto 0); -- Conditional flags.
+ STATUS_REG_OUT : out std_logic_vector(15 downto 0);
+
+ -- Load controls (besides the first instruction word):
+ FORCE_BIW2 : in bit;
+ FORCE_BIW3 : in bit;
+ EXT_CNT : in integer range 0 to 2;
+ DEST_EXT_CNT : in integer range 0 to 2;
+ REGSEL_20 : in std_logic_vector(2 downto 0);
+
+ -- Instruction word controls:
+ IW_ADR : out integer range 0 to 2; -- Instruction word address.
+ IW_WR : out bit; -- Instruction word write control.
+
+ -- Extension word controls:
+ SRC_DESTn : out bit; -- '1' for read operand from source, '0' store result to destination (MOVE).
+ EW_WR : out bit; -- Write control.
+ EW_ADR : out integer range 0 to 1; -- Source extension word address.
+
+ -- Bus controls:
+ RD_BUS : out bit; -- Read bus request.
+ WR_BUS : out bit; -- Wriyte request.
+ RDWR_BUS : out bit; -- Read modify write request.
+ WR_HI : out bit; -- Write the high word to the external bus.
+ SEL_A_HI : out bit; -- Select data A buffer high byte.
+ SEL_A_MIDHI : out bit; -- Select data A buffer midhigh byte.
+ SEL_A_MIDLO : out bit; -- Select data A buffer midlow byte.
+ SEL_A_LO : out bit; -- Select data A buffer low byte.
+ SEL_BUFF_A_LO : out bit; -- Select data A buffer low word.
+ SEL_BUFF_A_HI : out bit; -- Select data A buffer high word.
+ SEL_BUFF_B_LO : out bit; -- Select data B buffer low word.
+ SEL_BUFF_B_HI : out bit; -- Select data B buffer high word.
+ FC_OUT : out std_logic_vector(2 downto 0);
+ FC_EN : out bit;
+
+ -- Program counter controls:
+ PC_INIT : out bit; -- Write the hi PC portion.
+ PC_WR : out bit; -- Write program counter (PC).
+ PC_INC : out bit; -- Increment PC.
+ PC_TMP_CLR : out bit; -- Clear temporary PC.
+ PC_TMP_INC : out bit; -- Increment temporary PC.
+ PC_ADD_DISPL : out bit; -- Forces the adding of the sign extended displacement to the PC.
+
+ -- Stack pointer controls:
+ USP_INC : out bit; -- User stack pointer increment by 2.
+ SSP_INC : out bit; -- Supervisor stack pointer increment by 2.
+ USP_DEC : out bit; -- User stack pointer decrement by 2.
+ SSP_DEC : out bit; -- Supervisor stack pointer decrement by 2.
+ USP_CPY : out bit; -- Copy user stack to or from address registers.
+ SP_ADD_DISPL : out bit; -- Forces the adding of the sign extended displacement to the SP.
+
+ -- Address register controls:
+ ADR_TMP_CLR : out bit; -- Temporary address offset clear.
+ ADR_TMP_INC : out bit; -- Address register increment temporarily.
+ AR_INC : out bit; -- Address register increment.
+ AR_DEC : out bit; -- Address register decrement.
+ AR_WR : out bit; -- Address register write.
+ AR_DR_EXG : out bit; -- Exchange data or address registers.
+
+ -- Data register controls:
+ DR_WR : out bit; -- Write the data register.
+ DR_DEC : out bit; -- Decrement data register by 1.
+
+ -- Traps:
+ SCAN_TRAPS : out bit; -- Scan the traps in the end of FETCH_BIW_1.
+ TRAP_PRIV : in bit; -- Trap by violation of the priviledge.
+ TRAP_TRACE : out bit; -- Trap due to the trace mode.
+
+ -- Miscellaneous flags:
+ OP : in OP_68K00; -- Type of operation.
+ OP_MODE : in std_logic_vector(2 downto 0); -- Operation mode.
+ OP_SIZE : in OP_SIZETYPE; -- Operation size.
+ ADR_MODE : in std_logic_vector(2 downto 0); -- Address mode indicator.
+ MOVE_D_AM : in std_logic_vector(2 downto 0); -- Move statement destination address mode.
+ RESET_RDY : in bit; -- Progress control for the RESET operation.
+ OP_BUSY : in bit; -- Progress control for MUL and DIV.
+ MEM_SHFT : in bit; -- Shift operations in registers ('0') or in memory ('1').
+ SHFT_BUSY : in bit; -- Progress control for the shift operations.
+ DR : in bit; -- Direction control.
+ RM : in bit; -- Register or memory control.
+ DIV_MUL_32n64 : in bit; -- Format of the DIV and MUL.
+ EXEC_RESUME : in bit; -- Resume after STOP.
+ DBcc_COND : in boolean; -- DBcc control, see data registers.
+
+ -- Miscellaneous controls:
+ USE_SP_ADR : out bit;
+ OP_START : out bit; -- 1 CLK cycle, start condition for DIV and MUL.
+ TRAP_CHK_EN : out bit; -- Enabes the CHK command result.
+ MOVEM_REGSEL : out std_logic_vector(2 downto 0); -- Register number selection.
+ MOVEM_ADn : out bit; -- Address or data register select ('1' = address).
+ Scc_COND : out boolean; -- For the Scc command.
+ SHIFTER_LOAD : out bit; -- Strobe of 1 clock pulse, start condition for the shifter.
+ CHK_PC : out bit; -- Check program counter for TRAP_AERR.
+ CHK_ADR : out bit; -- Check effective address for TRAP_AERR.
+ SBIT : out bit; -- Superuser flag.
+ UNLK_SP_An : out bit; -- Multiplexer switch for the UNLK.
+ RESET_EN : out bit -- Control for the reset logic in the bus interface.
+ );
+end entity WF68K00IP_CONTROL;
+
+architecture BEHAVIOR of WF68K00IP_CONTROL is
+type EXEC_STATES is (IDLE, FETCH_BIW_1, FETCH_BIW_2, FETCH_BIW_3, FETCH_EXT, FETCH_DEST_EXT,
+ RD_SRC_1, RD_SRC_1_LO, RD_SRC_1_HI, RD_SRC_2, RD_SRC_2_LO, RD_SRC_2_HI, WR_DEST_1,
+ WR_DEST_1_LO, WR_DEST_1_HI, WR_DEST_2_LO, WR_DEST_2_HI, RD_SP_HI, RD_SP, RD_SP_LO,
+ WR_SP_HI, WR_SP_LO, WAIT_OPERATION, MOVEM_TST);
+signal EXEC_STATE : EXEC_STATES;
+signal NEXT_EXEC_STATE : EXEC_STATES;
+signal STATUS_REG : std_logic_vector(15 downto 0);
+signal SR_WR : bit;
+signal CCR_WR : bit;
+signal CC_UPDT : bit;
+signal GOT_EXT : boolean;
+signal GOT_DEST_EXT : boolean;
+signal MOVEM_EN : bit;
+signal MOVEM_CPY : std_logic;
+signal MOVEM_ADn_I : bit;
+signal MOVEM_PI_CORR : bit;
+signal COND : boolean; -- Used for conditional tests.
+signal OP_END_I : bit;
+signal RD_BUS_I : bit;
+signal WR_BUS_I : bit;
+signal RDWR_BUS_I : bit;
+signal AR_INC_I : bit;
+signal AR_DEC_I : bit;
+signal UPDT_CC : bit;
+signal SBIT_I : bit;
+signal TRAPLOCK : boolean;
+begin
+ -- OP_START indicates the start condition of the MULS, MULU, DIVS or DIVU computation.
+ OP_START <= '1' when OP = MOVEM and EXEC_STATE = FETCH_BIW_1 and BUS_CYC_RDY = '1' else
+ '1' when OP /= STOP and EXEC_STATE /= WAIT_OPERATION and NEXT_EXEC_STATE = WAIT_OPERATION else '0';
+
+ -- The end of an operation is indicated by the NEXT_EXEC_STATE for one clock cycle.
+ OP_END_I <= '1' when EXEC_STATE /= IDLE and EXEC_STATE /= FETCH_BIW_1 and NEXT_EXEC_STATE = FETCH_BIW_1 else
+ '1' when EXEC_STATE = FETCH_BIW_1 and NEXT_EXEC_STATE = FETCH_BIW_1 and BUS_CYC_RDY = '1' else '0';
+
+ CTRL_RDY <= '1' when EXEC_STATE = IDLE else '0';
+
+ -- Signal to switch the stack pointer addresses to the address bus.
+ USE_SP_ADR <= '1' when EXEC_STATE = RD_SP else
+ '1' when EXEC_STATE = RD_SP_HI else
+ '1' when EXEC_STATE = RD_SP_LO else
+ '1' when EXEC_STATE = WR_SP_HI else
+ '1' when EXEC_STATE = WR_SP_LO else '0';
+
+ SHIFTER_LOAD <= '1' when (OP = ASL or OP = ASR) and EXEC_STATE /= WAIT_OPERATION and NEXT_EXEC_STATE = WAIT_OPERATION else
+ '1' when (OP = LSL or OP = LSR) and EXEC_STATE /= WAIT_OPERATION and NEXT_EXEC_STATE = WAIT_OPERATION else
+ '1' when (OP = ROTL or OP = ROTR) and EXEC_STATE /= WAIT_OPERATION and NEXT_EXEC_STATE = WAIT_OPERATION else
+ '1' when (OP = ROXL or OP = ROXR) and EXEC_STATE /= WAIT_OPERATION and NEXT_EXEC_STATE = WAIT_OPERATION else '0';
+
+ TRAP_TRACE <= '1' when OP_END_I = '1' and STATUS_REG(15) = '1' else '0';
+
+ CHK_ADR_STRB: process(RESETn, CLK)
+ -- This process provides strobe controls for checking the adress error in the address register
+ -- section of this core. The strobes occurs every time a bus cycle starts (read, write or read
+ -- modify write). If the bus cycle is finished, the strobe locking is released. If there is an
+ -- address error during a bus cycle, the unlocking is done during the IDLE state.
+ variable LOCK : boolean;
+ begin
+ if RESETn = '0' then
+ CHK_PC <= '0';
+ CHK_ADR <= '0';
+ LOCK := false;
+ elsif CLK = '1' and CLK' event then
+ CHK_PC <= '0';
+ CHK_ADR <= '0';
+ if CTRL_EN = '0' then
+ null; -- Do nothing during exception handling.
+ elsif (EXEC_STATE = FETCH_BIW_1 or EXEC_STATE = FETCH_BIW_2 or EXEC_STATE = FETCH_BIW_3) and LOCK = false then
+ LOCK := true;
+ CHK_PC <= '1';
+ elsif (EXEC_STATE = FETCH_EXT or EXEC_STATE = FETCH_DEST_EXT) and LOCK = false then
+ LOCK := true;
+ CHK_PC <= '1';
+ elsif (RD_BUS_I = '1' or WR_BUS_I = '1') and LOCK = false then -- No RDWR_BUS due to TAS is byte wide.
+ LOCK := true;
+ CHK_ADR <= '1';
+ elsif BUS_CYC_RDY = '1' or EXEC_STATE = IDLE then
+ LOCK := false;
+ CHK_ADR <= '0';
+ CHK_PC <= '0';
+ end if;
+ end if;
+ end process CHK_ADR_STRB;
+
+ -- These signals controls the high word and low word bus access to the 32 bit wide registers.
+ SEL_A_HI <= '1' when OP = MOVEP and EXEC_STATE = RD_SRC_1_HI else -- LONG.
+ '1' when OP = MOVEP and EXEC_STATE = WR_DEST_1_HI else '0'; -- LONG.
+ SEL_A_MIDHI <= '1' when OP = MOVEP and EXEC_STATE = RD_SRC_1_LO else -- LONG.
+ '1' when OP = MOVEP and EXEC_STATE = WR_DEST_1_LO else '0'; -- LONG.
+ SEL_A_MIDLO <= '1' when OP = MOVEP and EXEC_STATE = RD_SRC_2_HI else -- LONG or WORD.
+ '1' when OP = MOVEP and EXEC_STATE = WR_DEST_2_HI else '0'; -- LONG or WORD.
+ SEL_A_LO <= '1' when OP = MOVEP and EXEC_STATE = RD_SRC_2_LO else -- LONG or WORD.
+ '1' when OP = MOVEP and EXEC_STATE = WR_DEST_2_LO else '0'; -- LONG or WORD.
+ SEL_BUFF_A_LO <= '1' when EXEC_STATE = RD_SRC_1 else
+ '1' when EXEC_STATE = RD_SRC_1_LO else
+ '1' when EXEC_STATE = RD_SP_LO else '0';
+ SEL_BUFF_A_HI <= '1' when EXEC_STATE = RD_SRC_1_HI else
+ '1' when EXEC_STATE = RD_SP_HI else '0';
+ SEL_BUFF_B_LO <= '1' when EXEC_STATE = RD_SRC_2 else
+ '1' when EXEC_STATE = RD_SRC_2_LO else '0';
+ SEL_BUFF_B_HI <= '1' when EXEC_STATE = RD_SRC_2_HI else '0';
+
+ SCAN_TRAPS <= '1' when EXEC_STATE = FETCH_BIW_1 and BUS_CYC_RDY = '1' else '0';
+
+ SBIT <= SBIT_I;
+ SBIT_I <= '1' when STATUS_REG(13) = '1' else '0';
+
+ -- The function codes are as follows:
+ -- 001: User data, 010: User program, 101: Supervisor data, 110: Supervisor program.
+ -- The default "000" is for example valid during the RESET operation or the busy ALU.
+ -- This implementation does not affect any drawback because the bus is not driven during
+ -- these states.
+ FC_EN <= '1' when (RD_BUS_I = '1' or WR_BUS_I = '1' or RDWR_BUS_I = '1') else '0';
+ FC_OUT <= "010" when SBIT_I = '0' and (EXEC_STATE = FETCH_BIW_1 or EXEC_STATE = FETCH_BIW_2 or
+ EXEC_STATE = FETCH_BIW_3 or EXEC_STATE = FETCH_EXT or EXEC_STATE = FETCH_DEST_EXT) else
+ "110" when SBIT_I = '1' and (EXEC_STATE = FETCH_BIW_1 or EXEC_STATE = FETCH_BIW_2 or
+ EXEC_STATE = FETCH_BIW_3 or EXEC_STATE = FETCH_EXT or EXEC_STATE = FETCH_DEST_EXT) else
+ "001" when (RD_BUS_I = '1' or WR_BUS_I = '1' or RDWR_BUS_I = '1') and SBIT_I = '0' else
+ "101" when (RD_BUS_I = '1' or WR_BUS_I = '1' or RDWR_BUS_I = '1') and SBIT_I = '1' else "000";
+
+ -- Status register conditions: (STATUS_REG(4) = X, STATUS_REG(3) = N, STATUS_REG(2) = Z,
+ -- STATUS_REG(1) = V, STATUS_REG(0) = C.)
+ COND <= true when C_CODE = x"0" else -- True.
+ true when C_CODE = x"2" and (STATUS_REG(2) nor STATUS_REG(0)) = '1' else -- High.
+ true when C_CODE = x"3" and (STATUS_REG(2) or STATUS_REG(0)) = '1' else -- Low or same.
+ true when C_CODE = x"4" and STATUS_REG(0) = '0' else -- Carry clear.
+ true when C_CODE = x"5" and STATUS_REG(0) = '1' else -- Carry set.
+ true when C_CODE = x"6" and STATUS_REG(2) = '0' else -- Not Equal.
+ true when C_CODE = x"7" and STATUS_REG(2) = '1' else -- Equal.
+ true when C_CODE = x"8" and STATUS_REG(1) = '0' else -- Overflow clear.
+ true when C_CODE = x"9" and STATUS_REG(1) = '1' else -- Overflow set.
+ true when C_CODE = x"A" and STATUS_REG(3) = '0' else -- Plus.
+ true when C_CODE = x"B" and STATUS_REG(3) = '1' else -- Minus.
+ true when C_CODE = x"C" and (STATUS_REG(3) xnor STATUS_REG(1)) = '1' else -- Greater or Equal.
+ true when C_CODE = x"D" and (STATUS_REG(3) xor STATUS_REG(1)) = '1' else -- Less than.
+ true when C_CODE = x"E" and STATUS_REG(3 downto 1) = "101" else -- Greater than.
+ true when C_CODE = x"E" and STATUS_REG(3 downto 1) = "000" else -- Greater than.
+ true when C_CODE = x"F" and STATUS_REG(2) = '1' else -- Less or equal.
+ true when C_CODE = x"F" and (STATUS_REG(3) xor STATUS_REG(1)) = '1' else false; -- Less or equal.
+
+ Scc_COND <= COND; -- Copy the conditional test result to the output.
+
+ EW_WR <= '1' when EXEC_STATE = FETCH_EXT and DATA_VALID = '1' else
+ '1' when EXEC_STATE = FETCH_DEST_EXT and DATA_VALID = '1' else '0';
+
+ IW_ADR <= 2 when EXEC_STATE = FETCH_BIW_3 else
+ 1 when EXEC_STATE = FETCH_BIW_2 else 0; -- Default during FETCH_BIW_1.
+
+ IW_WR <= '1' when EXEC_STATE = FETCH_BIW_1 and DATA_VALID = '1' else
+ '1' when EXEC_STATE = FETCH_BIW_2 and DATA_VALID = '1' else
+ '1' when EXEC_STATE = FETCH_BIW_3 and DATA_VALID = '1' else '0';
+
+ -- Select stack pointer or address data:
+ -- '1' means: write address register to stack pointer.
+ UNLK_SP_An <= '1' when OP = UNLK and EXEC_STATE = FETCH_BIW_1 else '0';
+
+ -- Source or destination control for the ABCD, ADDX, CMPM, MOVE, SBCD and SUBX operations:
+ SRC_DESTn <= '0' when OP = MOVE and EXEC_STATE = FETCH_DEST_EXT else
+ '0' when (OP = ABCD or OP = ADDX or OP = CMPM or OP = SBCD or OP = SUBX) and EXEC_STATE = RD_SRC_2 else
+ '0' when (OP = ADDX or OP = CMPM or OP = SUBX) and EXEC_STATE = RD_SRC_2_HI else
+ '0' when (OP = ADDX or OP = CMPM or OP = SUBX) and EXEC_STATE = RD_SRC_2_LO else
+ '0' when (OP = ADDX or OP = SUBX or OP = MOVE) and EXEC_STATE = WR_DEST_1_HI else
+ '0' when (OP = ADDX or OP = SUBX or OP = MOVE) and EXEC_STATE = WR_DEST_1_LO else
+ '0' when (OP = ABCD or OP = ADDX or OP = MOVE or OP = SBCD or OP = SUBX) and EXEC_STATE = WR_DEST_1 else '1';
+
+ AR_DR_EXG <= '1' when OP = EXG and OP_END_I = '1' else '0';
+
+ DR_DEC <= '1' when OP = DBcc and NEXT_EXEC_STATE = WAIT_OPERATION else '0';
+
+ DR_WR <= '1' when (OP = ABCD or OP = SBCD) and RM = '0' and OP_END_I = '1' else
+ '1' when (OP = ADD or OP = SUB or OP = AND_B or OP = OR_B) and OP_MODE = "000" and OP_END_I = '1' else
+ '1' when (OP = ADD or OP = SUB or OP = AND_B or OP = OR_B) and OP_MODE = "001" and OP_END_I = '1' else
+ '1' when (OP = ADD or OP = SUB or OP = AND_B or OP = OR_B) and OP_MODE = "010" and OP_END_I = '1' else
+ '1' when (OP = ADDI or OP = ADDQ) and ADR_MODE = "000" and OP_END_I = '1' else
+ '1' when (OP = ANDI or OP = ORI) and ADR_MODE = "000" and OP_END_I = '1' else
+ '1' when (OP = ADDX or OP = SUBX) and RM = '0' and OP_END_I = '1' else
+ '1' when (OP = EXTW or OP = SWAP) and OP_END_I = '1' else
+ '1' when (OP = EOR or OP = EORI) and ADR_MODE = "000" and OP_END_I = '1' else
+ '1' when (OP = SUBI or OP = SUBQ) and ADR_MODE = "000" and OP_END_I = '1' else
+ '1' when (OP = NEG or OP = NEGX) and ADR_MODE = "000" and OP_END_I = '1' else
+ '1' when (OP = NBCD or OP = NOT_B) and ADR_MODE = "000" and OP_END_I = '1' else
+ '1' when (OP = ASL or OP = ASR) and MEM_SHFT = '0' and OP_END_I = '1' else
+ '1' when (OP = LSL or OP = LSR) and MEM_SHFT = '0' and OP_END_I = '1' else
+ '1' when (OP = ROTL or OP = ROTR) and MEM_SHFT = '0' and OP_END_I = '1' else
+ '1' when (OP = ROXL or OP = ROXR) and MEM_SHFT = '0' and OP_END_I = '1' else
+ '1' when (OP = BCHG or OP = BCLR or OP = BSET or OP = CLR) and ADR_MODE = "000" and OP_END_I = '1' else
+ '1' when (OP = DIVS or OP = DIVU) and EXEC_STATE = WAIT_OPERATION and OP_BUSY = '0' else
+ '1' when OP = MOVE and MOVE_D_AM = "000" and OP_END_I = '1' else
+ '1' when (OP = MOVE_FROM_CCR or OP = MOVE_FROM_SR) and ADR_MODE = "000" and OP_END_I = '1' else
+ '1' when OP = MOVEQ and OP_END_I = '1' else
+ '1' when OP = MOVEP and (OP_MODE = "101" or OP_MODE = "100") and OP_END_I = '1' else
+ '1' when OP = MOVEM and NEXT_EXEC_STATE = MOVEM_TST and MOVEM_CPY = '1' and DR = '1' and MOVEM_ADn_I = '0' else
+ '1' when (OP = MULS or OP = MULU) and EXEC_STATE = WAIT_OPERATION and OP_BUSY = '0' else
+ '1' when OP = Scc and ADR_MODE = "000" and OP_END_I = '1' else
+ '1' when OP = TAS and ADR_MODE = "000" and OP_END_I = '1' else '0';
+
+ AR_WR <= '1' when (OP = ADDA or OP = SUBA or OP = LEA) and OP_END_I = '1' else
+ '1' when OP = MOVEA and OP_END_I = '1' else
+ '1' when (OP = ADDQ or OP = SUBQ) and ADR_MODE = "001" and OP_END_I = '1' else
+ '1' when OP = LINK and OP_END_I = '1' else
+ '1' when OP = UNLK and EXEC_STATE = FETCH_BIW_1 and BUS_CYC_RDY = '1' else
+ '1' when OP = UNLK and OP_END_I = '1' else
+ '1' when OP = MOVEM and NEXT_EXEC_STATE = MOVEM_TST and MOVEM_CPY = '1' and DR = '1' and MOVEM_ADn_I = '1' else '0';
+
+ -- Postincrement mode:
+ -- The immediate operations and the read modify write operations require only one increment
+ -- per read write pair in the end of the operation.
+ AR_INC <= AR_INC_I;
+ AR_INC_I <= '1' when (OP = ADD or OP = ADDA or OP = ADDI or OP = ADDQ) and ADR_MODE = "011" and OP_END_I = '1' else
+ '1' when (OP = AND_B or OP = ANDI) and ADR_MODE = "011" and OP_END_I = '1' else
+ '1' when (OP = ASL or OP = ASR) and MEM_SHFT = '1' and ADR_MODE = "011" and OP_END_I = '1' else
+ '1' when (OP = BCHG or OP = BCLR or OP = BSET or OP = BTST) and ADR_MODE = "011" and OP_END_I = '1' else
+ '1' when (OP = CHK or OP = CLR ) and ADR_MODE = "011" and OP_END_I = '1' else
+ '1' when (OP = CMP or OP = CMPA or OP = CMPI) and ADR_MODE = "011" and OP_END_I = '1' else
+ '1' when OP = CMPM and EXEC_STATE = RD_SRC_1 and BUS_CYC_RDY = '1' else -- Byte.
+ '1' when OP = CMPM and EXEC_STATE = RD_SRC_1_LO and BUS_CYC_RDY = '1' else -- Word and long.
+ '1' when OP = CMPM and OP_END_I = '1' else -- Increment the destination address register.
+ '1' when (OP = DIVS or OP = DIVU) and ADR_MODE = "011" and OP_END_I = '1' else
+ '1' when (OP = EOR or OP = EORI) and ADR_MODE = "011" and OP_END_I = '1' else
+ '1' when (OP = LSL or OP = LSR) and MEM_SHFT = '1' and ADR_MODE = "011" and OP_END_I = '1' else
+ '1' when OP = MOVE and EXEC_STATE = RD_SRC_1 and ADR_MODE = "011" and BUS_CYC_RDY = '1' else
+ '1' when OP = MOVE and EXEC_STATE = RD_SRC_1_LO and ADR_MODE = "011" and BUS_CYC_RDY = '1' else
+ '1' when OP = MOVE and EXEC_STATE = WR_DEST_1 and MOVE_D_AM = "011" and BUS_CYC_RDY = '1' else
+ '1' when OP = MOVE and EXEC_STATE = WR_DEST_1_LO and MOVE_D_AM = "011" and BUS_CYC_RDY = '1' else
+ '1' when (OP = MOVEA or OP = MOVE_FROM_CCR or OP = MOVE_FROM_SR) and ADR_MODE = "011" and OP_END_I = '1' else
+ '1' when (OP = MOVE_TO_CCR or OP = MOVE_TO_SR) and ADR_MODE = "011" and OP_END_I = '1' else
+ '1' when OP = MOVEM and ADR_MODE = "011" and EXEC_STATE = RD_SRC_1 and BUS_CYC_RDY = '1' else
+ '1' when OP = MOVEM and ADR_MODE = "011" and EXEC_STATE = RD_SRC_1_LO and BUS_CYC_RDY = '1' else
+ '1' when OP = MOVEM and MOVEM_PI_CORR = '1' else -- MOVEM postincrement correction
+ '1' when (OP = MULS or OP = MULU) and ADR_MODE = "011" and OP_END_I = '1' else
+ '1' when (OP = NBCD or OP = NEG or OP = NEGX) and ADR_MODE = "011" and OP_END_I = '1' else
+ '1' when (OP = NOT_B or OP = OR_B or OP = ORI) and ADR_MODE = "011" and OP_END_I = '1' else
+ '1' when (OP = ROTL or OP = ROTR) and MEM_SHFT = '1' and ADR_MODE = "011" and OP_END_I = '1' else
+ '1' when (OP = ROXL or OP = ROXR) and MEM_SHFT = '1' and ADR_MODE = "011" and OP_END_I = '1' else
+ '1' when (OP = SUB or OP = SUBA or OP = SUBI or OP = SUBQ) and ADR_MODE = "011" and OP_END_I = '1' else
+ '1' when (OP = Scc or OP = TAS or OP = TST) and ADR_MODE = "011" and OP_END_I = '1' else '0';
+
+ PREDEC_CTRL: process(RESETn, CLK, AR_DEC_I)
+ -- Predecrement mode: the address register is decremented right in the beginning of
+ -- the respective execution states. The AR_DEC control is modelled by an edge detector.
+ -- This is necessary because predecrementing before entering the states is not possible
+ -- due to the multiplexing of the destination data set by SRC_DESTn which occurs exactly
+ -- during these execution states.
+ -- Note: the immediate operations and the read modify write operations require only one
+ -- increment per read write arrangement at the beginning of the operation.
+ -- Note: This process uses a complex interaction between the modelling with the variable
+ -- LOCK and the prioritization of the 'if - elsif - end if' construction. Provide changes
+ -- with care!
+ variable LOCK: boolean;
+ begin
+ if RESETn = '0' then
+ LOCK := false;
+ AR_DEC_I <= '0';
+ elsif CLK = '1' and CLK' event then
+ AR_DEC_I <= '0'; -- Default.
+ --
+ if (OP = ABCD or OP = SBCD) and (EXEC_STATE = RD_SRC_1 or EXEC_STATE = RD_SRC_1_HI) and BUS_CYC_RDY = '1' then
+ LOCK := false;
+ elsif (OP = ADDX or OP = SUBX) and (EXEC_STATE = RD_SRC_1 or EXEC_STATE = RD_SRC_1_HI) and BUS_CYC_RDY = '1' then
+ LOCK := false;
+ elsif (OP = MOVE or OP = MOVEM) and BUS_CYC_RDY = '1' then
+ LOCK := false;
+ elsif OP_END_I = '1' then
+ LOCK := false;
+ --
+ -- All predecrement except the MOVE:
+ elsif (EXEC_STATE = RD_SRC_1 or EXEC_STATE = RD_SRC_1_HI or
+ EXEC_STATE = WR_DEST_1 or EXEC_STATE = WR_DEST_1_HI) and LOCK = false then
+ case OP is
+ -- Read modify write operations (in some configurations):
+ when ADD | ADDI | ADDQ | AND_B | ANDI | ASL | ASR | BCHG | BCLR | BSET | BTST | EOR | EORI | LSL | LSR |
+ NEG | NEGX | NOT_B | NBCD | OR_B | ORI | ROTL | ROTR | ROXL | ROXR | SUB | SUBI | SUBQ | TAS =>
+ if ADR_MODE = "100" then
+ AR_DEC_I <= '1';
+ LOCK := true;
+ end if;
+ -- Write only operations:
+ when CLR | MOVE_FROM_CCR | MOVE_FROM_SR | Scc =>
+ if ADR_MODE = "100" then
+ AR_DEC_I <= '1';
+ LOCK := true;
+ end if;
+ -- Read only operations:
+ when ADDA | CHK | CMP | CMPA | CMPI | DIVS | DIVU | MOVE_TO_CCR | MOVE_TO_SR | MOVEA | MOVEM | MULS |
+ MULU | SUBA | TST =>
+ if ADR_MODE = "100" then
+ AR_DEC_I <= '1';
+ LOCK := true;
+ end if;
+ -- Special operations:
+ when ABCD | ADDX | SBCD | SUBX =>
+ if ADR_MODE = "100" then
+ AR_DEC_I <= '1';
+ LOCK := true;
+ end if;
+ -- MOVE operation:
+ when MOVE =>
+ if (EXEC_STATE = RD_SRC_1 or EXEC_STATE = RD_SRC_1_HI) and ADR_MODE = "100" then -- Read from source.
+ AR_DEC_I <= '1';
+ LOCK := true;
+ elsif (EXEC_STATE = WR_DEST_1 or EXEC_STATE = WR_DEST_1_HI) and MOVE_D_AM = "100" then -- Write to destination.
+ AR_DEC_I <= '1';
+ LOCK := true;
+ end if;
+ when others => null;
+ end case;
+ elsif (EXEC_STATE = RD_SRC_2 or EXEC_STATE = RD_SRC_2_HI) and LOCK = false then
+ case OP is
+ when ABCD | ADDX | SBCD | SUBX =>
+ AR_DEC_I <= '1';
+ LOCK := true;
+ when others => null;
+ end case;
+ end if;
+ end if;
+ --
+ AR_DEC <= AR_DEC_I;
+ end process PREDEC_CTRL;
+
+ -- The conditions for clearing the temporary address offset are as follows:
+ -- Opereation ends (after a write process).
+ -- Post increment or pre decrement addressing mode (during increments / decrements).
+ -- After the end of the respective read periods (take care of the MOVEM).
+ -- The OP /= MOVEM ... is important for the MOVEM in the non predecrement / postincrement
+ -- address modes see also ADR_TMP_INC.
+ ADR_TMP_CLR <= '1' when OP_END_I = '1' or AR_INC_I = '1' or AR_DEC_I = '1' else
+ '1' when OP /= MOVEM and EXEC_STATE = RD_SRC_1 and BUS_CYC_RDY = '1' else
+ '1' when EXEC_STATE = RD_SRC_2 and BUS_CYC_RDY = '1' else -- For ABCD, ADDX, SBCD, SUBX.
+ '1' when OP /= MOVEM and EXEC_STATE = RD_SRC_1_LO and BUS_CYC_RDY = '1' else
+ '1' when EXEC_STATE = RD_SRC_2_LO and BUS_CYC_RDY = '1' else '0'; -- ADDX, SUBX.
+
+ ADR_TMP_INC <= '1' when OP = MOVEM and EXEC_STATE = RD_SRC_1 and BUS_CYC_RDY = '1' else
+ '1' when EXEC_STATE = RD_SRC_1_HI and BUS_CYC_RDY = '1' else
+ '1' when EXEC_STATE = RD_SRC_1_LO and BUS_CYC_RDY = '1' else
+ '1' when EXEC_STATE = RD_SRC_2_HI and BUS_CYC_RDY = '1' else
+ '1' when OP = MOVEM and EXEC_STATE = WR_DEST_1 and BUS_CYC_RDY = '1' else
+ '1' when EXEC_STATE = WR_DEST_1_HI and BUS_CYC_RDY = '1' else
+ '1' when EXEC_STATE = WR_DEST_1_LO and BUS_CYC_RDY = '1' else
+ '1' when EXEC_STATE = WR_DEST_2_HI and BUS_CYC_RDY = '1' else '0';
+
+ USP_CPY <= '1' when OP = MOVE_USP and OP_END_I = '1' else '0';
+
+ SP_ADD_DISPL <= '1' when OP = LINK and OP_END_I = '1' else '0';
+
+ USP_INC <= '1' when EXEC_STATE = RD_SP and BUS_CYC_RDY = '1' and SBIT_I = '0' else
+ '1' when EXEC_STATE = RD_SP_HI and BUS_CYC_RDY = '1' and SBIT_I = '0' else
+ '1' when EXEC_STATE = RD_SP_LO and BUS_CYC_RDY = '1' and SBIT_I = '0' else '0';
+
+ -- Decrement before use:
+ USP_DEC <= '1' when EXEC_STATE /= WR_SP_HI and NEXT_EXEC_STATE = WR_SP_HI and SBIT_I = '0' else
+ '1' when EXEC_STATE /= WR_SP_LO and NEXT_EXEC_STATE = WR_SP_LO and SBIT_I = '0' else '0';
+
+ SSP_INC <= '1' when EXEC_STATE = RD_SP and BUS_CYC_RDY = '1' and SBIT_I = '1' else
+ '1' when EXEC_STATE = RD_SP_HI and BUS_CYC_RDY = '1' and SBIT_I = '1' else
+ '1' when EXEC_STATE = RD_SP_LO and BUS_CYC_RDY = '1' and SBIT_I = '1' else '0';
+
+ -- Decrement before use:
+ SSP_DEC <= '1' when EXEC_STATE /= WR_SP_HI and NEXT_EXEC_STATE = WR_SP_HI and SBIT_I = '1' else
+ '1' when EXEC_STATE /= WR_SP_LO and NEXT_EXEC_STATE = WR_SP_LO and SBIT_I = '1' else '0';
+
+ PC_ADD_DISPL <= '1' when (OP = BRA or OP = BSR) and OP_END_I = '1' else
+ '1' when OP = Bcc and COND = true and OP_END_I = '1' else
+ '1' when OP = DBcc and OP_END_I = '1' and COND = false and DBcc_COND = false else '0';
+
+ -- The PC_INC takes place in the end of an operation. In case of the ILLEGAL, STOP, TRAP and TRAPV the
+ -- inrement is produced 'artificially' by generating the OP_END signal although the state machine register
+ -- changes to IDLE. See the respective state machine decoding for more details. For the UNIMPLEMENTED,
+ -- the priviledge trap and the reserved patterns, the PC may not be incremented.
+ PC_INC <= '1' when OP_END_I = '1' else '0';
+
+ PC_TMP_CLR <= '1' when EXEC_STATE = IDLE else '0'; -- Clear the temporary PC during exceptions.
+
+ -- The PC_TMP may increment during the fetch phase but must not increment in the last step of the fetch phase.
+ PC_TMP_INC <= '1' when EXEC_STATE = FETCH_BIW_1 and BUS_CYC_RDY = '1' and NEXT_EXEC_STATE = FETCH_BIW_2 else
+ '1' when EXEC_STATE = FETCH_BIW_1 and BUS_CYC_RDY = '1' and NEXT_EXEC_STATE = FETCH_EXT else
+ '1' when EXEC_STATE = FETCH_BIW_1 and BUS_CYC_RDY = '1' and NEXT_EXEC_STATE = FETCH_DEST_EXT else
+ '1' when EXEC_STATE = FETCH_BIW_2 and BUS_CYC_RDY = '1' and NEXT_EXEC_STATE = FETCH_BIW_3 else
+ '1' when EXEC_STATE = FETCH_BIW_2 and BUS_CYC_RDY = '1' and NEXT_EXEC_STATE = FETCH_EXT else
+ '1' when EXEC_STATE = FETCH_BIW_3 and BUS_CYC_RDY = '1' and NEXT_EXEC_STATE = FETCH_EXT else
+ '1' when EXEC_STATE = FETCH_EXT and BUS_CYC_RDY = '1' and NEXT_EXEC_STATE = FETCH_EXT else
+ '1' when EXEC_STATE = FETCH_EXT and BUS_CYC_RDY = '1' and NEXT_EXEC_STATE = FETCH_DEST_EXT else
+ '1' when EXEC_STATE = FETCH_DEST_EXT and BUS_CYC_RDY = '1' and NEXT_EXEC_STATE = FETCH_DEST_EXT else '0';
+
+ PC_INIT <= '1' when OP = RTE and EXEC_STATE = RD_SP_LO and BUS_CYC_RDY = '1' else
+ '1' when OP = RTR and EXEC_STATE = RD_SP_LO and BUS_CYC_RDY = '1' else
+ '1' when OP = RTS and EXEC_STATE = RD_SP_LO and BUS_CYC_RDY = '1' else '0';
+
+ PC_WR <= '1' when (OP = JMP or OP = JSR) and OP_END_I = '1' else '0';
+
+ SR_WR <= '1' when (OP = ANDI_TO_SR or OP = EORI_TO_SR or OP = ORI_TO_SR) and OP_END_I = '1' else
+ '1' when (OP = MOVE_TO_SR or OP = RTE) and OP_END_I = '1' else
+ '1' when OP = STOP and EXEC_STATE = FETCH_BIW_2 and BUS_CYC_RDY = '1' else '0';
+
+ CCR_WR <= '1' when (OP = ANDI_TO_CCR or OP = EORI_TO_CCR or OP = ORI_TO_CCR) and OP_END_I = '1' else
+ '1' when OP = MOVE_TO_CCR and OP_END_I = '1' else
+ '1' when OP = RTR and EXEC_STATE = RD_SP and BUS_CYC_RDY = '1' else '0';
+
+ -- Test at the end of the CHK operation:
+ TRAP_CHK_EN <= OP_END_I when OP = CHK else '0';
+
+ -- Enables the reset counter in the bus interface.
+ RESET_EN <= '1' when OP = RESET and EXEC_STATE = WAIT_OPERATION else '0';
+
+ UPDT_CC <= OP_END_I when ADR_MODE /= "001" else '0'; -- Valid for ADDQ and SUBQ.
+
+ with OP select
+ CC_UPDT <= UPDT_CC when ADDQ | SUBQ, -- Do not update when destination is an address register.
+ OP_END_I when ABCD | ADD | ADDI | ADDX | AND_B | ANDI | ASL | ASR | BCHG | BCLR |
+ BSET | BTST | CHK | CLR | CMP | CMPA | CMPI | CMPM | DIVS | DIVU |
+ EOR | EORI | EXTW | LSL | LSR | MOVE | MOVEQ | MULS | MULU | NBCD |
+ NEG | NEGX | NOT_B | OR_B | ORI | ROTL | ROTR | ROXL | ROXR | SBCD |
+ SUB | SUBI | SUBX | SWAP | TAS | TST, '0' when others;
+
+ -- The 16 bit bus must be written in two portions: hi word and low word.
+ -- This control is not valid for MOVEP.
+ WR_HI <= '1' when (EXEC_STATE = WR_DEST_1_HI or EXEC_STATE = WR_DEST_2_HI) else
+ '1' when EXEC_STATE = WR_SP_HI else '0';
+
+ WR_BUS <= WR_BUS_I;
+ WR_BUS_I <= '1' when EXEC_STATE = WR_DEST_1 and OP /= TAS else
+ '1' when EXEC_STATE = WR_DEST_1_HI else
+ '1' when EXEC_STATE = WR_DEST_1_LO else
+ '1' when EXEC_STATE = WR_DEST_2_HI else
+ '1' when EXEC_STATE = WR_DEST_2_LO else
+ '1' when EXEC_STATE = WR_SP_HI else
+ '1' when EXEC_STATE = WR_SP_LO else '0';
+
+ RDWR_BUS <= RDWR_BUS_I;
+ RDWR_BUS_I <= '1' when OP = TAS and EXEC_STATE = RD_SRC_1 else '0';
+
+ RD_BUS <= RD_BUS_I;
+ RD_BUS_I <= '1' when EXEC_STATE = FETCH_BIW_1 and (CTRL_EN = '1' or TRAPLOCK = true) else
+ -- The previous condition disables the bus cycle if the controller
+ -- is disabled by the exception handler. This condtion occurs, when
+ -- an exception is detected during the last clock cycle of an
+ -- instruction. In this case, the EXEC_STATE changes to FETCH_BIW_1
+ -- and simultaneously, the EX_STATE machine changes from it's IDLE.
+ '1' when EXEC_STATE = FETCH_BIW_2 else
+ '1' when EXEC_STATE = FETCH_BIW_3 else
+ '1' when EXEC_STATE = FETCH_EXT else
+ '1' when EXEC_STATE = FETCH_DEST_EXT else
+ '1' when EXEC_STATE = RD_SRC_1 and OP /= TAS else
+ '1' when EXEC_STATE = RD_SRC_1_HI else
+ '1' when EXEC_STATE = RD_SRC_1_LO else
+ '1' when EXEC_STATE = RD_SRC_2 else
+ '1' when EXEC_STATE = RD_SRC_2_HI else
+ '1' when EXEC_STATE = RD_SRC_2_LO else
+ '1' when EXEC_STATE = RD_SP else
+ '1' when EXEC_STATE = RD_SP_HI else
+ '1' when EXEC_STATE = RD_SP_LO else '0';
+
+ P_STATUS_REG: process(RESETn, CLK, STATUS_REG)
+ -- This process is the status register with
+ -- it's related logic.
+ variable SREG_MEM : std_logic_vector(9 downto 0);
+ variable SREG_MEM_TMP : std_logic_vector(9 downto 0);
+ begin
+ if RESETn = '0' then
+ SREG_MEM := "0000000000";
+ SREG_MEM_TMP := "0000000000";
+ elsif CLK = '1' and CLK' event then
+ -- *. Store a temporary copy of the status register and restore it
+ -- in the end of the RTE instruction. This is important to
+ -- handle the correct stacks when the supervisor bit is modified
+ -- in the trap handler routine.
+ if OP = RTE and EXEC_STATE = RD_SP and BUS_CYC_RDY = '1' then
+ SREG_MEM_TMP := SR_CCR_IN(15) & SR_CCR_IN(13) & SR_CCR_IN(10 downto 8) & SR_CCR_IN(4 downto 0);
+ end if;
+ --
+ if INIT_STATUS = '1' then
+ SREG_MEM(9 downto 8) := "01";
+ end if;
+ --
+ if PRESET_IRQ_MASK = '1' then
+ SREG_MEM(7 downto 5) := "111";
+ end if;
+ --
+ if IRQ_SAVE = '1' then
+ SREG_MEM(7 downto 5) := IRQ;
+ end if;
+ --
+ if CC_UPDT = '1' then
+ SREG_MEM(4 downto 0) := XNZVC_IN;
+ end if;
+ --
+ if SR_WR = '1' and OP = RTE then -- *.
+ SREG_MEM := SREG_MEM_TMP;
+ elsif SR_WR = '1' then -- For ANDI_TO_SR, EORI_TO_SR, ORI_TO_SR, MOVE_TO_SR, STOP.
+ SREG_MEM := SR_CCR_IN(15) & SR_CCR_IN(13) & SR_CCR_IN(10 downto 8) & SR_CCR_IN(4 downto 0);
+ elsif CCR_WR = '1' then
+ SREG_MEM(4 downto 0) := SR_CCR_IN(4 downto 0);
+ end if;
+ end if;
+ --
+ STATUS_REG <= SREG_MEM(9) & '0' & SREG_MEM(8) & "00" & SREG_MEM(7 downto 5) & "000" & SREG_MEM(4 downto 0);
+ STATUS_REG_OUT <= STATUS_REG;
+ end process P_STATUS_REG;
+
+ EXWORD_COUNTER: process(RESETn, CLK, EXT_CNT, DEST_EXT_CNT, EXEC_STATE)
+ -- This process provides the temporary counting of the already read extension words.
+ -- The process is moddeled in a way, that the counters are incremented before the
+ -- bus cycle is ready. This kind of realization gives the correct number of counted
+ -- extension words, every time, when the BUS_CYC_RDY signal appears in the two states
+ -- FETCH_EXT and FETCH_DEST_EXT.
+ variable SRC_TMP : integer range 0 to 2;
+ variable DEST_TMP : integer range 0 to 2;
+ variable LOCK : boolean;
+ begin
+ if RESETn = '0' then
+ SRC_TMP := 0;
+ DEST_TMP := 0;
+ LOCK := false;
+ elsif CLK = '1' and CLK' event then
+ if EXEC_STATE = FETCH_BIW_1 then
+ SRC_TMP := 0;
+ DEST_TMP := 0;
+ LOCK := false;
+ -- For the extensions:
+ elsif EXEC_STATE = FETCH_EXT and BUS_CYC_RDY = '0' and LOCK = false then
+ SRC_TMP := SRC_TMP + 1;
+ LOCK := true;
+ elsif EXEC_STATE = FETCH_EXT and BUS_CYC_RDY = '1' then
+ LOCK := false;
+ -- And for the destination extensions:
+ elsif EXEC_STATE = FETCH_DEST_EXT and BUS_CYC_RDY = '0' and LOCK = false then
+ DEST_TMP := DEST_TMP + 1;
+ LOCK := true;
+ elsif EXEC_STATE = FETCH_DEST_EXT and BUS_CYC_RDY = '1' then
+ LOCK := false;
+ end if;
+ -- The extension word address:
+ if EXEC_STATE = FETCH_EXT and SRC_TMP > 0 then
+ EW_ADR <= SRC_TMP - 1;
+ elsif EXEC_STATE = FETCH_DEST_EXT and DEST_TMP > 0 then
+ EW_ADR <= DEST_TMP - 1;
+ else
+ EW_ADR <= 0;
+ end if;
+ end if;
+ --
+ if SRC_TMP = EXT_CNT then
+ GOT_EXT <= true;
+ else
+ GOT_EXT <= false;
+ end if;
+ --
+ if DEST_TMP = DEST_EXT_CNT then
+ GOT_DEST_EXT <= true;
+ else
+ GOT_DEST_EXT <= false;
+ end if;
+ --
+ end process EXWORD_COUNTER;
+
+ MOVEM_CTRL: process(RESETn, CLK, ADR_MODE, REGSEL_20, MOVEM_ADn_I, DR, REGLISTMASK)
+ -- The MOVEM command takes the REGLISTMASK flags to control, which registers
+ -- have to be written or not. The behavior of the reading or writing depends
+ -- on the MOVEM operation mode and is controlled in this process.
+ variable BIT_PNT : integer range 0 to 16; -- Bit pointer.
+ variable REGSEL_TMP : std_logic_vector(2 downto 0);
+ begin
+ if RESETn = '0' then
+ BIT_PNT := 0;
+ REGSEL_TMP := "000";
+ MOVEM_PI_CORR <= '0';
+ elsif CLK = '1' and CLK' event then
+ -- Be aware, that the bit pointer starts always at a value of zero. It points
+ -- to the register list mask, which's entries depend on the MOVEM addressing mode.
+ if EXEC_STATE = FETCH_BIW_1 then
+ BIT_PNT := 0; -- Clear at operation start.
+ case ADR_MODE is
+ when "100" => REGSEL_TMP := "111"; -- Predecrement mode.
+ when others => REGSEL_TMP := "000";
+ end case;
+ -- In the following two conditions, the bit
+ -- pointer is modified befor the MOVEM_TST state!
+ elsif NEXT_EXEC_STATE = MOVEM_TST then
+ BIT_PNT := BIT_PNT + 1;
+ case ADR_MODE is
+ when "100" => REGSEL_TMP := REGSEL_TMP - '1'; -- Predecrement mode.
+ when others => REGSEL_TMP := REGSEL_TMP + '1';
+ end case;
+ end if;
+ --
+ case BIT_PNT is
+ when 16 => MOVEM_EN <= '0';
+ when others => MOVEM_EN <= '1';
+ end case;
+ --
+ if BIT_PNT <= 7 and ADR_MODE = "100" then
+ MOVEM_ADn_I <= '1'; -- Predecrement address mode.
+ elsif BIT_PNT > 7 and ADR_MODE /= "100" then
+ MOVEM_ADn_I <= '1'; -- Other addressing modes.
+ else
+ MOVEM_ADn_I <= '0'; -- Select data registers.
+ end if;
+ --
+ if ADR_MODE = "011" and REGSEL_TMP = REGSEL_20 and BIT_PNT > 7 and REGLISTMASK(BIT_PNT) = '1' then
+ -- Special case: in the postincrement mode, the addressing register is written with the postincremented
+ -- effective address: suppress the respective memory access.
+ MOVEM_PI_CORR <= '1';
+ else
+ MOVEM_PI_CORR <= '0';
+ end if;
+ --
+ MOVEM_ADn <= MOVEM_ADn_I;
+ MOVEM_REGSEL <= REGSEL_TMP;
+ end if;
+ --
+ -- The MOVEM_CPY must be asserted asynchronous due to the latency of the REGLISTMASK
+ -- in the FETCH_BIW_2 control state:
+ if ADR_MODE = "011" and REGSEL_TMP = REGSEL_20 and MOVEM_ADn_I = '1' and DR = '1' then
+ MOVEM_CPY <= '0'; -- Do not overwrite the addressing register with the value from the stack.
+ else
+ MOVEM_CPY <= REGLISTMASK(BIT_PNT);
+ end if;
+ end process MOVEM_CTRL;
+
+ TRAP_LOCK: process
+ -- This flag enables the recognition of exceptions in the first
+ -- clock cycle of the main state FETCH_BIW_1. During all other
+ -- clock cycles, the recognition is disabled to avoid breaks of
+ -- started bus cycles.
+ begin
+ wait until CLK = '1' and CLK' event;
+ if EXEC_STATE /= FETCH_BIW_1 then
+ TRAPLOCK <= false;
+ elsif EXEC_STATE = FETCH_BIW_1 and BUS_CYC_RDY = '1' then
+ TRAPLOCK <= false;
+ elsif EXEC_STATE = FETCH_BIW_1 then
+ TRAPLOCK <= true;
+ end if;
+ end process TRAP_LOCK;
+
+ EXEC_REG: process(RESETn, CLK)
+ begin
+ if RESETn = '0' then
+ EXEC_STATE <= IDLE;
+ elsif CLK = '1' and CLK' event then
+ if EXEC_ABORT = '1' then
+ EXEC_STATE <= IDLE; -- Abort current execution.
+ else
+ EXEC_STATE <= NEXT_EXEC_STATE;
+ end if;
+ end if;
+ end process EXEC_REG;
+
+ EXEC_DEC: process(EXEC_STATE, CTRL_EN, TRAPLOCK, BUS_CYC_RDY, FORCE_BIW2, FORCE_BIW3, GOT_EXT, GOT_DEST_EXT, SHFT_BUSY, OP,
+ RM, RESET_RDY, OP_MODE, OP_SIZE, COND, EXEC_RESUME, ADR_MODE, DIV_MUL_32n64, OP_BUSY, STATUS_REG,
+ MOVE_D_AM, MOVEM_EN, MOVEM_CPY, DR, MEM_SHFT, DEST_EXT_CNT, REGLISTMASK, REGSEL_20, TRAP_PRIV)
+ begin
+ case EXEC_STATE is
+ when IDLE =>
+ if CTRL_EN = '1' then
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ else
+ NEXT_EXEC_STATE <= IDLE;
+ end if;
+ --------------------------- Fetch operation and extension words -----------------------------
+ -- The FETCH phase is used to simultaneously start several operations. The ADR_MODE and the
+ -- OP_SIZE etc. is not required because this information is included implicitely in the
+ -- FORCE_BIWx and the FETCH_x_EXT signals.
+ when FETCH_BIW_1 =>
+ if CTRL_EN = '0' and TRAPLOCK = false then
+ NEXT_EXEC_STATE <= IDLE; -- Break due to exceptions.
+ elsif BUS_CYC_RDY = '1' and TRAP_PRIV = '1' then
+ NEXT_EXEC_STATE <= IDLE; -- Exception without modifying any registers.
+ elsif BUS_CYC_RDY = '1' and FORCE_BIW2 = '1' then
+ NEXT_EXEC_STATE <= FETCH_BIW_2;
+ elsif BUS_CYC_RDY = '1' and GOT_EXT = false then
+ NEXT_EXEC_STATE <= FETCH_EXT; -- Source extension required.
+ elsif BUS_CYC_RDY = '1' and GOT_DEST_EXT = false then
+ NEXT_EXEC_STATE <= FETCH_DEST_EXT; -- Destination extension required.
+ elsif BUS_CYC_RDY = '1' then
+ case OP is
+ when RESET =>
+ NEXT_EXEC_STATE <= WAIT_OPERATION;
+ when ILLEGAL | UNIMPLEMENTED | RESERVED =>
+ NEXT_EXEC_STATE <= IDLE;
+ when TRAP | TRAPV =>
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ when ABCD | SBCD | ADDX | SUBX =>
+ if RM = '0' then -- Register direct.
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ elsif OP_SIZE = LONG then -- Memory to memory, long.
+ NEXT_EXEC_STATE <= RD_SRC_1_HI;
+ else -- Memory to memory, word or byte (Byte for ABCD, SBCD).
+ NEXT_EXEC_STATE <= RD_SRC_1;
+ end if;
+ when ADD | AND_B | EOR | SUB | OR_B =>
+ if ADR_MODE = "000" or ADR_MODE = "001" then
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ elsif (OP_MODE = "010" or OP_MODE = "110") then
+ NEXT_EXEC_STATE <= RD_SRC_1_HI;
+ else
+ NEXT_EXEC_STATE <= RD_SRC_1;
+ end if;
+ when ADDA | CMPA | SUBA =>
+ if ADR_MODE = "000" or ADR_MODE = "001" then
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ elsif OP_MODE = "111" then -- LONG.
+ NEXT_EXEC_STATE <= RD_SRC_1_HI;
+ else
+ NEXT_EXEC_STATE <= RD_SRC_1;
+ end if;
+ when ASL | ASR | LSL | LSR | ROTL | ROTR | ROXL | ROXR =>
+ if MEM_SHFT = '0' then -- Register shift.
+ NEXT_EXEC_STATE <= WAIT_OPERATION;
+ else -- Restricted to WORD.
+ NEXT_EXEC_STATE <= RD_SRC_1;
+ end if;
+ when Bcc | BRA | EXG | EXTW | JMP | LEA | MOVEQ | MOVE_USP | NOP | SWAP =>
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ when BCHG | BCLR | BSET | BTST =>
+ if ADR_MODE = "000" then
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ else -- Byte wide memory access.
+ NEXT_EXEC_STATE <= RD_SRC_1;
+ end if;
+ when BSR | JSR | PEA =>
+ NEXT_EXEC_STATE <= WR_SP_LO;
+ when CHK | NEG | NEGX | NOT_B =>
+ if ADR_MODE = "000" then
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ elsif OP_SIZE = LONG then
+ NEXT_EXEC_STATE <= RD_SRC_1_HI;
+ else
+ NEXT_EXEC_STATE <= RD_SRC_1;
+ end if;
+ when CLR =>
+ if ADR_MODE = "000" then
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ elsif OP_SIZE = LONG then
+ NEXT_EXEC_STATE <= WR_DEST_1_HI;
+ else
+ NEXT_EXEC_STATE <= WR_DEST_1;
+ end if;
+ when CMP =>
+ if ADR_MODE = "000" or ADR_MODE = "001" then
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ elsif OP_MODE = "010" then
+ NEXT_EXEC_STATE <= RD_SRC_1_HI;
+ else
+ NEXT_EXEC_STATE <= RD_SRC_1;
+ end if;
+ when CMPM =>
+ if OP_SIZE = LONG then
+ NEXT_EXEC_STATE <= RD_SRC_1_HI;
+ else
+ NEXT_EXEC_STATE <= RD_SRC_1;
+ end if;
+ when DIVS | DIVU | MULS | MULU =>
+ if ADR_MODE = "000" then
+ NEXT_EXEC_STATE <= WAIT_OPERATION;
+ else
+ -- In this state only OP_SIZE
+ -- = WORD is valid.
+ NEXT_EXEC_STATE <= RD_SRC_1;
+ end if;
+ when MOVE =>
+ if (ADR_MODE = "000" or ADR_MODE = "001") and MOVE_D_AM = "000" then
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ elsif ADR_MODE = "001" or ADR_MODE = "000" then
+ if OP_SIZE = LONG then
+ NEXT_EXEC_STATE <= WR_DEST_1_HI;
+ else
+ NEXT_EXEC_STATE <= WR_DEST_1;
+ end if;
+ else
+ if OP_SIZE = LONG then
+ NEXT_EXEC_STATE <= RD_SRC_1_HI;
+ else
+ NEXT_EXEC_STATE <= RD_SRC_1;
+ end if;
+ end if;
+ when MOVEA =>
+ if ADR_MODE = "000" or ADR_MODE = "001" then
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ else
+ case OP_SIZE is
+ when LONG => NEXT_EXEC_STATE <= RD_SRC_1_HI;
+ when others => NEXT_EXEC_STATE <= RD_SRC_1;
+ end case;
+ end if;
+ when MOVE_FROM_CCR | MOVE_FROM_SR | Scc =>
+ if ADR_MODE = "000" then
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ else
+ NEXT_EXEC_STATE <= WR_DEST_1;
+ end if;
+ when NBCD | MOVE_TO_CCR | MOVE_TO_SR | TAS =>
+ if ADR_MODE = "000" then
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ else
+ NEXT_EXEC_STATE <= RD_SRC_1;
+ end if;
+ when RTE | RTR =>
+ NEXT_EXEC_STATE <= RD_SP;
+ when RTS =>
+ NEXT_EXEC_STATE <= RD_SP_HI;
+ when ADDQ | SUBQ | TST =>
+ if ADR_MODE = "000" or ADR_MODE = "001" then
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ else
+ if OP_SIZE = LONG then
+ NEXT_EXEC_STATE <= RD_SRC_1_HI;
+ else
+ NEXT_EXEC_STATE <= RD_SRC_1;
+ end if;
+ end if;
+ when UNLK =>
+ NEXT_EXEC_STATE <= RD_SP_HI;
+ when others =>
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ end case;
+ else
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ end if;
+ when FETCH_BIW_2 =>
+ if BUS_CYC_RDY = '1' and FORCE_BIW3 = '1' then
+ NEXT_EXEC_STATE <= FETCH_BIW_3;
+ elsif BUS_CYC_RDY = '1' and GOT_EXT = false then
+ NEXT_EXEC_STATE <= FETCH_EXT;
+ elsif BUS_CYC_RDY = '1' then
+ case OP is
+ when ADDI | ANDI | CMPI | EORI | ORI | SUBI =>
+ if ADR_MODE = "000" then
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ else
+ case OP_SIZE is
+ when LONG => NEXT_EXEC_STATE <= RD_SRC_1_HI;
+ when others => NEXT_EXEC_STATE <= RD_SRC_1;
+ end case;
+ end if;
+ when Bcc | BRA =>
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ when ANDI_TO_SR | ANDI_TO_CCR | EORI_TO_SR | EORI_TO_CCR | ORI_TO_CCR | ORI_TO_SR =>
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ when BCHG | BCLR | BSET | BTST =>
+ if ADR_MODE = "000" then
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ else -- Byte wide access.
+ NEXT_EXEC_STATE <= RD_SRC_1;
+ end if;
+ when BSR | LINK =>
+ NEXT_EXEC_STATE <= WR_SP_LO;
+ when DBcc =>
+ if COND = true then
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ else
+ NEXT_EXEC_STATE <= WAIT_OPERATION;
+ end if;
+ when DIVS | DIVU | MULS | MULU =>
+ if ADR_MODE = "000" then
+ NEXT_EXEC_STATE <= WAIT_OPERATION;
+ else
+ -- In this state only OP_SIZE
+ -- = LONG is valid.
+ NEXT_EXEC_STATE <= RD_SRC_1_HI;
+ end if;
+ when MOVEM =>
+ if REGLISTMASK = x"0000" then
+ NEXT_EXEC_STATE <= FETCH_BIW_1; -- Do nothing.
+ elsif MOVEM_CPY = '1' and OP_SIZE = LONG and DR = '1' then
+ NEXT_EXEC_STATE <= RD_SRC_1_HI; -- Memory to register LONG.
+ elsif MOVEM_CPY = '1' and OP_SIZE = LONG then
+ NEXT_EXEC_STATE <= WR_DEST_1_HI; -- Register to memory LONG.
+ elsif MOVEM_CPY = '1' and DR = '1' then
+ NEXT_EXEC_STATE <= RD_SRC_1; -- Memory to register WORD.
+ elsif MOVEM_CPY = '1' then
+ NEXT_EXEC_STATE <= WR_DEST_1; -- Register to memory WORD.
+ else -- CPY = '0', modify the bit pointer in the MOVEM control logic.
+ NEXT_EXEC_STATE <= MOVEM_TST; -- No transfer.
+ end if;
+ when MOVEP =>
+ if OP_MODE = "101" then
+ NEXT_EXEC_STATE <= RD_SRC_1_HI; -- Memory to register, long.
+ elsif OP_MODE = "100" then
+ NEXT_EXEC_STATE <= RD_SRC_2_HI; -- Memory to register, word.
+ elsif OP_MODE = "111" then
+ NEXT_EXEC_STATE <= WR_DEST_1_HI; -- Register to memory, long.
+ else -- OP_MODE = "110"
+ NEXT_EXEC_STATE <= WR_DEST_2_HI; -- Register to memory, word.
+ end if;
+ when STOP =>
+ if STATUS_REG(15) = '1' then -- Trace condition.
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ else
+ NEXT_EXEC_STATE <= WAIT_OPERATION;
+ end if;
+ when others =>
+ NEXT_EXEC_STATE <= FETCH_BIW_1; -- Should never appear.
+ end case;
+ else
+ NEXT_EXEC_STATE <= FETCH_BIW_2;
+ end if;
+ when FETCH_BIW_3 =>
+ if BUS_CYC_RDY = '1' and GOT_EXT = false then
+ NEXT_EXEC_STATE <= FETCH_EXT;
+ elsif BUS_CYC_RDY = '1' then
+ case OP is
+ when ADDI | ANDI | CMPI | EORI | ORI | SUBI =>
+ if ADR_MODE = "000" then
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ else
+ case OP_SIZE is
+ when LONG => NEXT_EXEC_STATE <= RD_SRC_1_HI;
+ when others => NEXT_EXEC_STATE <= RD_SRC_1;
+ end case;
+ end if;
+ when Bcc | BRA =>
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ when BSR | LINK =>
+ NEXT_EXEC_STATE <= WR_SP_LO;
+ when others =>
+ NEXT_EXEC_STATE <= FETCH_BIW_1; -- Should never appear.
+ end case;
+ else
+ NEXT_EXEC_STATE <= FETCH_BIW_3;
+ end if;
+ when FETCH_EXT =>
+ if BUS_CYC_RDY = '1' and GOT_EXT = true and GOT_DEST_EXT = false then
+ NEXT_EXEC_STATE <= FETCH_DEST_EXT; -- This is for the MOVE operation.
+ elsif BUS_CYC_RDY = '1' and GOT_EXT = true then
+ case OP is
+ when ADD | AND_B | SUB | OR_B =>
+ if ADR_MODE = "111" and REGSEL_20 = "100" then
+ NEXT_EXEC_STATE <= FETCH_BIW_1; -- Immediate data.
+ else
+ if (OP_MODE = "010" or OP_MODE = "110") then
+ NEXT_EXEC_STATE <= RD_SRC_1_HI;
+ else
+ NEXT_EXEC_STATE <= RD_SRC_1;
+ end if;
+ end if;
+ when EOR =>
+ if (OP_MODE = "010" or OP_MODE = "110") then
+ NEXT_EXEC_STATE <= RD_SRC_1_HI;
+ else
+ NEXT_EXEC_STATE <= RD_SRC_1;
+ end if;
+ when ADDA | CMPA | SUBA =>
+ if ADR_MODE = "111" and REGSEL_20 = "100" then
+ NEXT_EXEC_STATE <= FETCH_BIW_1; -- Immediate data.
+ else
+ if OP_MODE = "111" then -- LONG.
+ NEXT_EXEC_STATE <= RD_SRC_1_HI;
+ else
+ NEXT_EXEC_STATE <= RD_SRC_1;
+ end if;
+ end if;
+ when ADDI | ADDQ | ANDI | CMPI | EORI | NEG | NEGX | NOT_B | ORI | SUBI | SUBQ =>
+ case OP_SIZE is
+ when LONG => NEXT_EXEC_STATE <= RD_SRC_1_HI;
+ when others => NEXT_EXEC_STATE <= RD_SRC_1;
+ end case;
+ when ASL | ASR | LSL | LSR | ROTL | ROTR | ROXL | ROXR =>
+ NEXT_EXEC_STATE <= RD_SRC_1;
+ when BTST | MOVE_TO_CCR | MOVE_TO_SR =>
+ if ADR_MODE = "111" and REGSEL_20 = "100" then
+ NEXT_EXEC_STATE <= FETCH_BIW_1; -- Immediate data.
+ else
+ NEXT_EXEC_STATE <= RD_SRC_1; -- A memory access is always BYTE wide.
+ end if;
+ when BCHG | BCLR | BSET =>
+ NEXT_EXEC_STATE <= RD_SRC_1; -- A memory access is always BYTE wide.
+ when CHK | MOVEA | TST =>
+ if ADR_MODE = "111" and REGSEL_20 = "100" then
+ NEXT_EXEC_STATE <= FETCH_BIW_1; -- Immediate data.
+ else
+ case OP_SIZE is
+ when LONG => NEXT_EXEC_STATE <= RD_SRC_1_HI;
+ when others => NEXT_EXEC_STATE <= RD_SRC_1;
+ end case;
+ end if;
+ when DIVS | DIVU | MULS | MULU =>
+ if ADR_MODE = "111" and REGSEL_20 = "100" then
+ NEXT_EXEC_STATE <= WAIT_OPERATION; -- Immediate data.
+ else
+ case OP_SIZE is
+ -- For DIVS, DIVU, MULS, MULU the OP_SIZE is
+ -- always LONG in this state.
+ when LONG => NEXT_EXEC_STATE <= RD_SRC_1_HI;
+ when others => NEXT_EXEC_STATE <= RD_SRC_1;
+ end case;
+ end if;
+ when CLR =>
+ if OP_SIZE = LONG then
+ NEXT_EXEC_STATE <= WR_DEST_1_HI;
+ else
+ NEXT_EXEC_STATE <= WR_DEST_1;
+ end if;
+ when CMP =>
+ if ADR_MODE = "111" and REGSEL_20 = "100" then
+ NEXT_EXEC_STATE <= FETCH_BIW_1; -- Immediate data.
+ else
+ if OP_MODE = "010" then
+ NEXT_EXEC_STATE <= RD_SRC_1_HI;
+ else
+ NEXT_EXEC_STATE <= RD_SRC_1;
+ end if;
+ end if;
+ when MOVE =>
+ if ADR_MODE = "111" and REGSEL_20 = "100" and MOVE_D_AM = "000" then
+ NEXT_EXEC_STATE <= FETCH_BIW_1; -- Immediate data to data registers.
+ elsif ADR_MODE = "111" and REGSEL_20 = "100" then
+ case OP_SIZE is
+ when LONG => NEXT_EXEC_STATE <= WR_DEST_1_HI; -- Immediate long to memory.
+ when others => NEXT_EXEC_STATE <= WR_DEST_1; -- Immediate word to memory.
+ end case;
+ else
+ case OP_SIZE is
+ when LONG => NEXT_EXEC_STATE <= RD_SRC_1_HI;
+ when others => NEXT_EXEC_STATE <= RD_SRC_1;
+ end case;
+ end if;
+ when MOVEM =>
+ if REGLISTMASK = x"0000" then
+ NEXT_EXEC_STATE <= FETCH_BIW_1; -- Do nothing.
+ elsif MOVEM_CPY = '1' and OP_SIZE = LONG and DR = '1' then
+ NEXT_EXEC_STATE <= RD_SRC_1_HI; -- Memory to register LONG.
+ elsif MOVEM_CPY = '1' and OP_SIZE = LONG then
+ NEXT_EXEC_STATE <= WR_DEST_1_HI; -- Register to memory LONG.
+ elsif MOVEM_CPY = '1' and DR = '1' then
+ NEXT_EXEC_STATE <= RD_SRC_1; -- Memory to register WORD.
+ elsif MOVEM_CPY = '1' then
+ NEXT_EXEC_STATE <= WR_DEST_1; -- Register to memory WORD.
+ else -- CPY = '0', modify the bit pointer in the MOVEM control logic.
+ NEXT_EXEC_STATE <= MOVEM_TST; -- No transfer.
+ end if;
+ when MOVE_FROM_CCR | MOVE_FROM_SR | Scc =>
+ NEXT_EXEC_STATE <= WR_DEST_1;
+ when NBCD | TAS =>
+ NEXT_EXEC_STATE <= RD_SRC_1; -- WORD or BYTE for NBCD, BYTE for TAS.
+ when JMP | LEA =>
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ when JSR | PEA =>
+ NEXT_EXEC_STATE <= WR_SP_LO;
+ when others =>
+ NEXT_EXEC_STATE <= FETCH_BIW_1; -- Should never appear.
+ end case;
+ else
+ NEXT_EXEC_STATE <= FETCH_EXT;
+ end if;
+ when FETCH_DEST_EXT => -- This state is exclusively used by the MOVE operation.
+ if BUS_CYC_RDY = '1' and GOT_DEST_EXT = true then
+ if ADR_MODE = "000" or ADR_MODE = "001" or (ADR_MODE = "111" and REGSEL_20 = "100") then -- No external source required.
+ if OP_SIZE = LONG then
+ NEXT_EXEC_STATE <= WR_DEST_1_HI;
+ else
+ NEXT_EXEC_STATE <= WR_DEST_1;
+ end if;
+ else
+ if OP_SIZE = LONG then
+ NEXT_EXEC_STATE <= RD_SRC_1_HI;
+ else
+ NEXT_EXEC_STATE <= RD_SRC_1;
+ end if;
+ end if;
+ else
+ NEXT_EXEC_STATE <= FETCH_DEST_EXT;
+ end if;
+ ------------------------- End fetch operation and extension words ---------------------------
+ when RD_SRC_1 =>
+ if BUS_CYC_RDY = '1' then
+ case OP is
+ when ABCD | SBCD | ADDX | SUBX | CMPM =>
+ NEXT_EXEC_STATE <= RD_SRC_2;
+ when ADD | AND_B | SUB | OR_B =>
+ if (OP_MODE = "100" or OP_MODE = "101") then
+ NEXT_EXEC_STATE <= WR_DEST_1;
+ else
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ end if;
+ when MOVE =>
+ if MOVE_D_AM = "000" then
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ else
+ NEXT_EXEC_STATE <= WR_DEST_1;
+ end if;
+ when ADDI | ADDQ | ANDI | EOR | EORI | NEG | NEGX | NOT_B | ORI | SUBI | SUBQ =>
+ NEXT_EXEC_STATE <= WR_DEST_1;
+ when ADDA | SUBA | BTST | CHK | CMP | CMPA | CMPI | MOVEA | MOVE_TO_CCR | MOVE_TO_SR | TAS | TST =>
+ -- The TAS performs a read modify write cycle in this state.
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ when ASL | ASR | LSL | LSR | ROTL | ROTR | ROXL | ROXR =>
+ NEXT_EXEC_STATE <= WAIT_OPERATION;
+ when BCHG | BCLR | BSET | NBCD =>
+ NEXT_EXEC_STATE <= WR_DEST_1;
+ when DIVS | DIVU | MULS | MULU =>
+ NEXT_EXEC_STATE <= WAIT_OPERATION;
+ when MOVEM =>
+ NEXT_EXEC_STATE <= MOVEM_TST;
+ when others =>
+ NEXT_EXEC_STATE <= FETCH_BIW_1; -- Should never appear.
+ end case;
+ else
+ NEXT_EXEC_STATE <= RD_SRC_1;
+ end if;
+ when RD_SRC_1_HI =>
+ if BUS_CYC_RDY = '1' then
+ NEXT_EXEC_STATE <= RD_SRC_1_LO;
+ else
+ NEXT_EXEC_STATE <= RD_SRC_1_HI;
+ end if;
+ when RD_SRC_1_LO =>
+ if BUS_CYC_RDY = '1' then
+ case OP is
+ when ADDI | ADDQ | ANDI | EOR | EORI | NEG | NEGX | NOT_B | SUBI | SUBQ | ORI =>
+ NEXT_EXEC_STATE <= WR_DEST_1_HI;
+ when ADD | AND_B | SUB | OR_B =>
+ if OP_MODE = "110" then
+ NEXT_EXEC_STATE <= WR_DEST_1_HI;
+ else
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ end if;
+ when MOVE =>
+ if MOVE_D_AM = "000" then
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ else
+ NEXT_EXEC_STATE <= WR_DEST_1_HI;
+ end if;
+ when ADDA | CHK | CMP | CMPA | CMPI | MOVEA | SUBA | TST =>
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ when ADDX | SUBX | CMPM | MOVEP =>
+ NEXT_EXEC_STATE <= RD_SRC_2_HI;
+ when DIVS | DIVU | MULS | MULU =>
+ NEXT_EXEC_STATE <= WAIT_OPERATION;
+ when MOVEM =>
+ NEXT_EXEC_STATE <= MOVEM_TST;
+ when others =>
+ NEXT_EXEC_STATE <= FETCH_BIW_1; -- Should never appear.
+ end case;
+ else
+ NEXT_EXEC_STATE <= RD_SRC_1_LO;
+ end if;
+ when RD_SRC_2 =>
+ if OP = CMPM and BUS_CYC_RDY = '1' then
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ elsif BUS_CYC_RDY = '1' then -- Used by ABCD, ADDX, SBCD, SUBX.
+ NEXT_EXEC_STATE <= WR_DEST_1;
+ else
+ NEXT_EXEC_STATE <= RD_SRC_2;
+ end if;
+ when RD_SRC_2_HI =>
+ if BUS_CYC_RDY = '1' then
+ NEXT_EXEC_STATE <= RD_SRC_2_LO;
+ else
+ NEXT_EXEC_STATE <= RD_SRC_2_HI;
+ end if;
+ when RD_SRC_2_LO =>
+ if (OP = ADDX or OP = SUBX) and BUS_CYC_RDY = '1' then
+ NEXT_EXEC_STATE <= WR_DEST_1_HI;
+ elsif (OP = CMPM or OP = MOVEP) and BUS_CYC_RDY = '1' then
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ else
+ NEXT_EXEC_STATE <= RD_SRC_2_LO;
+ end if;
+ when WR_DEST_1 =>
+ if OP = MOVEM and BUS_CYC_RDY = '1' then
+ NEXT_EXEC_STATE <= MOVEM_TST;
+ -- The default state is used by the following commands:
+ -- ABCD, ADD, ADDI, ADDQ, ADDX, AND_B, ANDI, ASL, ASR,
+ -- BCHG, BCLR, BSET, EOR, EORI, LSL, LSR, MOVE_FROM_CCR,
+ -- MOVE_FROM_SR, MOVE, NBCD, NEG, NEGX, NOT_B,OR_B,
+ -- ORI, ROTL, ROTR, ROXL, ROXR, SBCD, SScc, SUB, SUBI,
+ -- SUBQ, SUBX.
+ elsif BUS_CYC_RDY = '1' then
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ else
+ NEXT_EXEC_STATE <= WR_DEST_1;
+ end if;
+ when WR_DEST_1_HI =>
+ -- This state is used by the following commands:
+ -- ADD, ADDI, ADDQ, ADDX, AND_B, ANDI, CLR, EOR,
+ -- EORI, MOVE MOVEP, NEG, NEGX, NOT_B, OR_B,
+ -- OR_B, ORI, SUB, SUBI, SUBQ, SUBX.
+ if BUS_CYC_RDY = '1' then
+ NEXT_EXEC_STATE <= WR_DEST_1_LO;
+ else
+ NEXT_EXEC_STATE <= WR_DEST_1_HI;
+ end if;
+ when WR_DEST_1_LO =>
+ -- The last condition (Others) is used by the following operations:
+ -- ADD, AND_B, CLR, EOR, SUB, OR_B, ADDI, ADDQ, ADDX, SUBI, SUBQ, SUBX,
+ -- ANDI, EORI, ORI, CLR, MOVE, NEG, NEGX, NOT_B.
+ if OP = MOVEP and BUS_CYC_RDY = '1' then -- Long transfer.
+ NEXT_EXEC_STATE <= WR_DEST_2_HI;
+ elsif OP = MOVEM and BUS_CYC_RDY = '1' then
+ NEXT_EXEC_STATE <= MOVEM_TST;
+ elsif BUS_CYC_RDY = '1' then -- Others.
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ else
+ NEXT_EXEC_STATE <= WR_DEST_1_LO;
+ end if;
+ when WR_DEST_2_HI =>
+ -- Used by MOVEP.
+ if BUS_CYC_RDY = '1' then
+ NEXT_EXEC_STATE <= WR_DEST_2_LO;
+ else
+ NEXT_EXEC_STATE <= WR_DEST_2_HI;
+ end if;
+ when WR_DEST_2_LO =>
+ -- Used by MOVEP.
+ if BUS_CYC_RDY = '1' then
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ else
+ NEXT_EXEC_STATE <= WR_DEST_2_LO;
+ end if;
+ ---------------------------------- Special states -------------------------------------
+ when RD_SP =>
+ -- In this state, the 16 bit SR or the 8 bit CCR are affected.
+ if BUS_CYC_RDY = '1' then -- Used by RTE, RTR.
+ NEXT_EXEC_STATE <= RD_SP_HI;
+ else
+ NEXT_EXEC_STATE <= RD_SP;
+ end if;
+ when RD_SP_HI =>
+ if BUS_CYC_RDY = '1' then -- Used by RTE, RTR, RTS, UNLK.
+ NEXT_EXEC_STATE <= RD_SP_LO;
+ else
+ NEXT_EXEC_STATE <= RD_SP_HI;
+ end if;
+ when RD_SP_LO => -- Used by RTE, RTR, RTS, UNLK.
+ if BUS_CYC_RDY = '1' then
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ else
+ NEXT_EXEC_STATE <= RD_SP_LO;
+ end if;
+ when WR_SP_LO => -- Used by BSR, JSR, LINK, PEA.
+ if BUS_CYC_RDY = '1' then
+ NEXT_EXEC_STATE <= WR_SP_HI;
+ else
+ NEXT_EXEC_STATE <= WR_SP_LO;
+ end if;
+ when WR_SP_HI => -- Used by BSR, JSR, LINK, PEA.
+ if OP = JSR and BUS_CYC_RDY = '1' then
+ NEXT_EXEC_STATE <= RD_SRC_1_HI;
+ elsif BUS_CYC_RDY = '1' then
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ else
+ NEXT_EXEC_STATE <= WR_SP_HI;
+ end if;
+ when WAIT_OPERATION =>
+ case OP is
+ when RESET =>
+ if RESET_RDY = '1' then
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ else
+ NEXT_EXEC_STATE <= WAIT_OPERATION;
+ end if;
+ when STOP =>
+ -- This state is valid until an interrupt, a trace exception or a
+ -- reset occurs.
+ if EXEC_RESUME = '1' then
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ else
+ NEXT_EXEC_STATE <= WAIT_OPERATION;
+ end if;
+ when ASL | ASR | LSL | LSR | ROTL | ROTR | ROXL | ROXR =>
+ if SHFT_BUSY = '1' then
+ NEXT_EXEC_STATE <= WAIT_OPERATION;
+ elsif MEM_SHFT = '0' then
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ else
+ NEXT_EXEC_STATE <= WR_DEST_1;
+ end if;
+ when DIVS | DIVU | MULS | MULU =>
+ if OP_BUSY = '1' then
+ NEXT_EXEC_STATE <= WAIT_OPERATION;
+ else
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ end if;
+ when DBcc =>
+ NEXT_EXEC_STATE <= FETCH_BIW_1;
+ when others =>
+ NEXT_EXEC_STATE <= FETCH_BIW_1; -- Should never appear.
+ end case;
+ when MOVEM_TST =>
+ if MOVEM_EN = '0' then -- BSY = '0'.
+ NEXT_EXEC_STATE <= FETCH_BIW_1; -- Operation finished.
+ elsif MOVEM_CPY = '1' and OP_SIZE = LONG and DR = '1' then
+ NEXT_EXEC_STATE <= RD_SRC_1_HI; -- Memory to register LONG.
+ elsif MOVEM_CPY = '1' and OP_SIZE = LONG then
+ NEXT_EXEC_STATE <= WR_DEST_1_HI; -- Register to memory LONG.
+ elsif MOVEM_CPY = '1' and DR = '1' then
+ NEXT_EXEC_STATE <= RD_SRC_1; -- Memory to register WORD.
+ elsif MOVEM_CPY = '1' then
+ NEXT_EXEC_STATE <= WR_DEST_1; -- Register to memory WORD.
+ else -- CPY = '0', modify the bit pointer in the MOVEM control logic.
+ NEXT_EXEC_STATE <= MOVEM_TST; -- No transfer.
+ end if;
+ end case;
+ end process EXEC_DEC;
+end BEHAVIOR;
\ No newline at end of file
diff --git a/common/CPU/68000/wf_68k00_ip/wf68k00ip_data_registers.vhd b/common/CPU/68000/wf_68k00_ip/wf68k00ip_data_registers.vhd
new file mode 100644
index 00000000..158c95e9
--- /dev/null
+++ b/common/CPU/68000/wf_68k00_ip/wf68k00ip_data_registers.vhd
@@ -0,0 +1,193 @@
+----------------------------------------------------------------------
+---- ----
+---- MC68000 compatible IP Core ----
+---- ----
+---- This file is part of the SUSKA ATARI clone project. ----
+---- http://www.experiment-s.de ----
+---- ----
+---- Description: ----
+---- This model provides an opcode and bus timing compatible ip ----
+---- core compared to Motorola's MC68000 microprocessor. ----
+---- ----
+---- This file contains the 68Ks data registers. ----
+---- ----
+---- ----
+---- Description: ----
+---- Contains the 68K00 data registers D0 to D7 and related logic ----
+---- to perform byte, word and long data operations. ----
+---- ----
+---- ----
+---- Author(s): ----
+---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
+---- ----
+----------------------------------------------------------------------
+---- ----
+---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
+---- ----
+---- This source file 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 2 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, write to the Free ----
+---- Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ----
+---- Boston, MA 02110-1301, USA. ----
+---- ----
+----------------------------------------------------------------------
+--
+-- Revision History
+--
+-- Revision 2K6B 2006/12/24 WF
+-- Initial Release.
+-- Revision 2K7A 2007/05/31 WF
+-- Updated all modules.
+-- Revision 2K7B 2007/12/24 WF
+-- See the 68K00 top level file.
+-- Revision 2K8A 2008/07/14 WF
+-- See the 68K00 top level file.
+--
+
+use work.wf68k00ip_pkg.all;
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+
+entity WF68K00IP_DATA_REGISTERS is
+ port (
+ CLK : in bit;
+ RESETn : in bit;
+
+ -- Data lines:
+ DATA_IN_A : in std_logic_vector(31 downto 0);
+ DATA_IN_B : in std_logic_vector(31 downto 0);
+
+ -- Registers controls:
+ REGSEL_A : in std_logic_vector(2 downto 0);
+ REGSEL_B : in std_logic_vector(2 downto 0);
+ REGSEL_C : in std_logic_vector(2 downto 0);
+ DIV_MUL_32n64 : in bit;
+
+ -- Data outputs A and B:
+ DATA_OUT_A : out std_logic_vector(31 downto 0);
+ DATA_OUT_B : out std_logic_vector(31 downto 0);
+ DATA_OUT_C : out std_logic_vector(31 downto 0);
+
+ DR_EXG : in bit; -- Exchange a data register.
+ DR_DEC : in bit; -- Decrement by 1.
+ DR_WR : in bit; -- Data register write control.
+ OP : in OP_68K00;
+ OP_SIZE : in OP_SIZETYPE;
+ OP_MODE : in std_logic_vector(4 downto 0);
+
+ -- Miscellaneous:
+ DBcc_COND : out boolean -- Condition is true for Dn = -1.
+ );
+end entity WF68K00IP_DATA_REGISTERS;
+
+architecture BEHAVIOR of WF68K00IP_DATA_REGISTERS is
+type DR_TYPE is array(0 to 7) of std_logic_vector(31 downto 0);
+signal DR : DR_TYPE; -- Data registers D0 to D7.
+signal DR_NR_A : integer range 0 to 7;
+signal DR_NR_B : integer range 0 to 7;
+signal DR_NR_C : integer range 0 to 7;
+begin
+ -- Address pointers:
+ DR_NR_A <= conv_integer(REGSEL_A);
+ DR_NR_B <= conv_integer(REGSEL_B);
+ DR_NR_C <= conv_integer(REGSEL_C);
+
+ -- Output Multiplexer A and B:
+ DATA_OUT_A <= DR(DR_NR_A);
+ DATA_OUT_B <= DR(DR_NR_B);
+ DATA_OUT_C <= DR(DR_NR_C);
+
+ REGISTERS: process(RESETn, CLK, DR_NR_B, DR)
+ -- This process provides data transfer to the respective registers (write).
+ -- The MOVEM and MOVEQ require a sign extended source data.
+ -- The BYTE size is not allowed for MOVEM .
+ begin
+ if RESETn = '0' then
+ for i in 0 to 7 loop
+ DR(i) <= (others => '0');
+ end loop;
+ elsif CLK = '1' and CLK' event then
+ if DR_WR = '1' then
+ if OP = DIVS or OP = DIVU then
+ case OP_SIZE is
+ when WORD =>
+ DR(DR_NR_A) <= DATA_IN_A;
+ when others => -- LONG.
+ if DIV_MUL_32n64 = '0' and DR(DR_NR_A) = DR(DR_NR_B) then -- Long 1.
+ DR(DR_NR_A) <= DATA_IN_A; -- Quotient returned.
+ else -- Long 2, 3.
+ DR(DR_NR_A) <= DATA_IN_A;
+ DR(DR_NR_B) <= DATA_IN_B;
+ end if;
+ end case;
+ elsif OP = MULS or OP = MULU then
+ if OP_SIZE = WORD then
+ DR(DR_NR_A) <= DATA_IN_A;
+ elsif DIV_MUL_32n64 = '0' then -- Long 1.
+ DR(DR_NR_A) <= DATA_IN_A;
+ else -- Long 2.
+ DR(DR_NR_A) <= DATA_IN_A;
+ DR(DR_NR_B) <= DATA_IN_B;
+ end if;
+ elsif OP = MOVE or OP = MOVEP then
+ case OP_SIZE is
+ when LONG => DR(DR_NR_A) <= DATA_IN_A;
+ when WORD => DR(DR_NR_A)(15 downto 0) <= DATA_IN_A(15 downto 0);
+ when BYTE => DR(DR_NR_A)(7 downto 0) <= DATA_IN_A(7 downto 0);
+ end case;
+ elsif OP = MOVEQ then -- Sign extended.
+ for i in 31 downto 8 loop
+ DR(DR_NR_B)(i) <= DATA_IN_B(7);
+ end loop;
+ DR(DR_NR_B)(7 downto 0) <= DATA_IN_B(7 downto 0);
+ elsif OP = MOVEM then -- Sign extended.
+ if OP_SIZE = WORD then
+ for i in 31 downto 16 loop
+ DR(DR_NR_B)(i) <= DATA_IN_B(15);
+ end loop;
+ DR(DR_NR_B)(15 downto 0) <= DATA_IN_B(15 downto 0);
+ else
+ DR(DR_NR_B) <= DATA_IN_B;
+ end if;
+ elsif OP = EXTW or OP = SWAP then
+ DR(DR_NR_B) <= DATA_IN_B;
+ else
+ -- Depending on the size to be written, not all bits of a register
+ -- are affected.
+ case OP_SIZE is
+ when LONG => DR(DR_NR_B) <= DATA_IN_B;
+ when WORD => DR(DR_NR_B)(15 downto 0) <= DATA_IN_B(15 downto 0);
+ when Byte => DR(DR_NR_B)(7 downto 0) <= DATA_IN_B(7 downto 0);
+ end case;
+ end if;
+ -- Exchange the content of data registers:
+ elsif DR_EXG = '1' and OP_MODE = "01000" then -- Exchange two data registers.
+ DR(DR_NR_B) <= DATA_IN_A;
+ DR(DR_NR_A) <= DATA_IN_B;
+ elsif DR_EXG = '1' and OP_MODE = "10001" then -- Exchange a data and an address register.
+ DR(DR_NR_A) <= DATA_IN_A;
+ -- And decrement:
+ elsif DR_DEC = '1' then
+ DR(DR_NR_B)(15 downto 0) <= DR(DR_NR_B)(15 downto 0) - '1'; -- Used by the DBcc operation.
+ end if;
+ end if;
+ -- Test condition for the DBcc operation:
+ case DR(DR_NR_B)(15 downto 0) is
+ when x"FFFF" => DBcc_COND <= true; -- This is signed -1.
+ when others => DBcc_COND <= false;
+ end case;
+ end process REGISTERS;
+end BEHAVIOR;
diff --git a/common/CPU/68000/wf_68k00_ip/wf68k00ip_interrupt_controller.vhd b/common/CPU/68000/wf_68k00_ip/wf68k00ip_interrupt_controller.vhd
new file mode 100644
index 00000000..c578f019
--- /dev/null
+++ b/common/CPU/68000/wf_68k00_ip/wf68k00ip_interrupt_controller.vhd
@@ -0,0 +1,686 @@
+----------------------------------------------------------------------
+---- ----
+---- MC68000 compatible IP Core ----
+---- ----
+---- This file is part of the SUSKA ATARI clone project. ----
+---- http://www.experiment-s.de ----
+---- ----
+---- Description: ----
+---- This model provides an opcode and bus timing compatible ip ----
+---- core compared to Motorola's MC68000 microprocessor. ----
+---- ----
+---- This file contains the interrupt control unit. ----
+---- ----
+---- ----
+---- Description: ----
+---- The interrupt control module is responsible for the inter- ----
+---- rupt management of the external and internal interrupts and ----
+---- for EXCEPTIONs processing. It manages auto-vectored inter- ----
+---- rupt cycles, priority resolving and correct vector numbers ----
+---- creation. ----
+---- There are different kinds of interrupt sources which require ----
+---- some special treatment: the RESET_CPU is released by exter- ----
+---- nal logic. The exception state machine therefore has to ----
+---- wait, once released, until this interrupt is released again. ----
+---- Interrupts, allowing the operation processing to finish the ----
+---- current operation, have to wait for the CTRL_RDY signal. ----
+---- The bus error exception starts the exception handler state ----
+---- machine. In this case, there is no need to wait for the bus ----
+---- error to withdrawn. It is assumed, that the bus error is ----
+---- released by the bus interface logic during the exception ----
+---- processing takes place. Double bus errors / address errors ----
+---- cause the processor to enter the 'HALT' state. ----
+---- ----
+---- ----
+---- Author(s): ----
+---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
+---- ----
+----------------------------------------------------------------------
+---- ----
+---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
+---- ----
+---- This source file 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 2 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, write to the Free ----
+---- Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ----
+---- Boston, MA 02110-1301, USA. ----
+---- ----
+----------------------------------------------------------------------
+--
+-- Revision History
+--
+-- Revision 2K6B 2006/12/24 WF
+-- Initial Release.
+-- Revision 2K7A 2007/05/31 WF
+-- Updated all modules.
+-- Revision 2K7B 2007/12/24 WF
+-- See the 68K00 top level file.
+-- Revision 2K8A 2008/07/14 WF
+-- See the 68K00 top level file.
+--
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+
+entity WF68K00IP_INTERRUPT_CONTROL is
+ port (
+ CLK : in bit;
+ RESETn : in bit; -- Core reset.
+
+ RESET_CPUn : in bit; -- Internal reset used for CPU initialization.
+ BERR : in bit; -- Bus error detection.
+ HALTn : in std_logic;
+
+ -- Data and address bus:
+ ADR_IN : in std_logic_vector(31 downto 0);
+ USE_SSP_ADR : out bit;
+ ADR_EN_VECTOR : out bit;
+ DATA_IN : in std_logic_vector(7 downto 0);
+ DATA_OUT : out std_logic_vector(15 downto 0);
+ DATA_EN : out bit;
+
+ -- Bus interface controls:
+ RWn : in bit_vector(0 downto 0);
+ RD_BUS : out bit;
+ WR_BUS : out bit;
+ HALT_EN : out bit;
+ FC_IN : in std_logic_vector(2 downto 0);
+ FC_OUT : out std_logic_vector(2 downto 0);
+ FC_EN : out bit;
+ SEL_BUFF_A_LO : out bit; -- Select data A buffer low word.
+ SEL_BUFF_A_HI : out bit; -- Select data A buffer high word.
+
+ -- Address register controls
+ -- (Address reisters, status register and program counter):
+ STATUS_REG_IN : in std_logic_vector(15 downto 0);
+ PC : in std_logic_vector(31 downto 0);
+ INIT_STATUS : out bit;
+ PRESET_IRQ_MASK : out bit;
+ SSP_DEC : out bit;
+ SSP_INIT : out bit;
+ PC_INIT : out bit;
+
+ -- Operation decoder stuff:
+ BIW_0 : in std_logic_vector(15 downto 0); -- First instruction word.
+
+ -- Control state machine signals:
+ BUS_CYC_RDY : in bit;
+ CTRL_RDY : in bit; -- Main controller finished an execution.
+ CTRL_EN : out bit; -- Enable main controller.
+ EXEC_ABORT : out bit; -- Abort the current execution.
+ EXEC_RESUME : out bit; -- Resume operation processing (STOP).
+
+ -- Interrupt controls:
+ IRQ : in std_logic_vector(2 downto 0);
+ AVECn : in bit; -- Originally 68Ks use VPAn.
+ IRQ_SAVE : out bit;
+ INT_VECT : out std_logic_vector(9 downto 0); -- Interrupt vector number.
+ USE_INT_VECT : out bit;
+
+ -- Trap signals:
+ TRAP_AERR : in bit; -- Address error indication.
+ TRAP_OP : in bit; -- TRAP instruction.
+ TRAP_VECTOR : in std_logic_vector(3 downto 0); -- Vector of the TRAP instruction.
+ TRAP_V : in bit; -- TRAPV instruction.
+ TRAP_CHK : in bit;
+ TRAP_DIVZERO : in bit;
+ TRAP_ILLEGAL : in bit;
+ TRAP_1010 : in bit; -- Unimplemented instructions.
+ TRAP_1111 : in bit; -- Unimplemented instructions.
+ TRAP_TRACE : in bit;
+ TRAP_PRIV : in bit
+ );
+end entity WF68K00IP_INTERRUPT_CONTROL;
+
+architecture BEHAVIOR of WF68K00IP_INTERRUPT_CONTROL is
+type EX_STATES is (IDLE, WAIT_CTRL_RDY, INIT, VECT_NR, GET_VECTOR, STACK_MISC, STACK_ACCESS_ADR_HI,
+ STACK_ACCESS_ADR_LO, STACK_INSTRUCTION, STACK_STATUS, STACK_PC_HI, STACK_PC_LO,
+ UPDATE_SSP_HI, UPDATE_SSP_LO, UPDATE_PC_HI, UPDATE_PC_LO, HALT);
+type EXCEPTIONS is (EX_RESET, EX_BUS_ERR, EX_ADR_ERR, EX_ILLEGAL, EX_DIVZERO, EX_CHK, EX_TRAPV,
+ EX_PRIV, EX_TRACE, EX_1010, EX_1111, EX_TRAP, EX_INT, EX_NONE);
+signal EX_STATE : EX_STATES;
+signal NEXT_EX_STATE : EX_STATES;
+signal EXCEPTION_Q : EXCEPTIONS; -- Currently executed exception.
+signal TMP_CPY : bit;
+signal STATUS_REG_TMP : std_logic_vector(15 downto 0);
+signal RWn_TMP : std_logic_vector(0 downto 0);
+signal FC_TMP : std_logic_vector(2 downto 0);
+signal INSTRn : std_logic;
+signal ADR_TMP : std_logic_vector(31 downto 0);
+signal INC_TMP_VECTOR : bit;
+signal EX_P_RESET : bit; -- ..._P are the pending exceptions.
+signal EX_P_ADR_ERR : bit;
+signal EX_P_BUS_ERR : bit;
+signal EX_P_TRACE : bit;
+signal EX_P_INT : bit;
+signal EX_P_ILLEGAL : bit;
+signal EX_P_1010 : bit;
+signal EX_P_1111 : bit;
+signal EX_P_PRIV : bit;
+signal EX_P_TRAP : bit;
+signal EX_P_TRAPV : bit;
+signal EX_P_CHK : bit;
+signal EX_P_DIVZERO : bit;
+signal FORCE_HALT : boolean;
+begin
+ -- The processor gets halted, if a bus error occurs in the stacking or updating states during
+ -- the exception processing of a bus error, an address error or a reset.
+ HALT_EN <= '1' when EX_STATE = HALT else '0';
+ FORCE_HALT <= true when EX_STATE /= IDLE and (BERR = '1' or TRAP_AERR = '1') and
+ (EXCEPTION_Q = EX_RESET or EXCEPTION_Q = EX_ADR_ERR or EXCEPTION_Q = EX_BUS_ERR) else false;
+
+ -- This is the flag which enables the main execution processing state machine. It is enabled, if there
+ -- is no pending interrupt and if the interrupt exception handler state machine is inactive.
+ CTRL_EN <= '1' when EX_STATE = IDLE and
+ EX_P_RESET = '0' and EX_P_ADR_ERR = '0' and EX_P_BUS_ERR = '0' and
+ EX_P_TRACE = '0' and EX_P_INT = '0' and EX_P_ILLEGAL = '0' and EX_P_1010 = '0' and
+ EX_P_1111 = '0' and EX_P_PRIV = '0' and EX_P_TRAP = '0' and EX_P_TRAPV = '0' and
+ EX_P_CHK = '0' and EX_P_DIVZERO = '0' else '0';
+
+ -- Flag, if the processor is executing an instruction or a type 0 or 1 exception.
+ -- 0: instruction, 1: exception.
+ with EXCEPTION_Q select
+ INSTRn <= '1' when EX_RESET | EX_ADR_ERR | EX_BUS_ERR,
+ '0' when others;
+
+ -- IACK cycle resides in the CPU space, the RESET resides in the supervisor
+ -- program space and all others reside in the supervisor data space.
+ FC_OUT <= "111" when EX_STATE = GET_VECTOR else -- IACK space cycle.
+ "110" when EX_STATE = UPDATE_SSP_HI or EX_STATE = UPDATE_SSP_LO else
+ "110" when EX_STATE = UPDATE_PC_HI or EX_STATE = UPDATE_PC_LO else
+ "101";
+
+ FC_EN <= '0' when EX_STATE = IDLE else
+ '0' when EX_STATE = WAIT_CTRL_RDY else
+ '0' when EX_STATE = INIT else
+ '0' when EX_STATE = VECT_NR else '1';
+
+ USE_SSP_ADR <= '1' when EX_STATE = STACK_MISC else
+ '1' when EX_STATE = STACK_ACCESS_ADR_HI else
+ '1' when EX_STATE = STACK_ACCESS_ADR_LO else
+ '1' when EX_STATE = STACK_INSTRUCTION else
+ '1' when EX_STATE = STACK_STATUS else
+ '1' when EX_STATE = STACK_PC_HI else
+ '1' when EX_STATE = STACK_PC_LO else '0';
+
+ SEL_BUFF_A_LO <= '1' when EX_STATE = UPDATE_SSP_LO else
+ '1' when EX_STATE = UPDATE_PC_LO else '0';
+ SEL_BUFF_A_HI <= '1' when EX_STATE = UPDATE_SSP_HI else
+ '1' when EX_STATE = UPDATE_PC_HI else '0';
+
+ ADR_EN_VECTOR <= '1' when EX_STATE = GET_VECTOR else '0'; -- IACK space cycle.
+
+ with EX_STATE select
+ RD_BUS <= '1' when GET_VECTOR | UPDATE_SSP_HI | UPDATE_SSP_LO | UPDATE_PC_HI | UPDATE_PC_LO, '0' when others;
+
+ with EX_STATE select
+ WR_BUS <= '1' when STACK_MISC | STACK_ACCESS_ADR_HI | STACK_ACCESS_ADR_LO | STACK_INSTRUCTION,
+ '1' when STACK_STATUS | STACK_PC_HI | STACK_PC_LO, '0' when others;
+
+ DATA_OUT <= "00000000000" & RWn_TMP & INSTRn & FC_TMP when EX_STATE = STACK_MISC else
+ ADR_TMP(31 downto 16) when EX_STATE = STACK_ACCESS_ADR_HI else
+ ADR_TMP(15 downto 0) when EX_STATE = STACK_ACCESS_ADR_LO else
+ BIW_0 when EX_STATE = STACK_INSTRUCTION else
+ STATUS_REG_TMP when EX_STATE = STACK_STATUS else
+ PC(31 downto 16) when EX_STATE = STACK_PC_HI else
+ PC(15 downto 0) when EX_STATE = STACK_PC_LO else (others => '-'); -- Dummy, don't care.
+
+ DATA_EN <= '1' when EX_STATE = STACK_MISC else
+ '1' when EX_STATE = STACK_ACCESS_ADR_HI else
+ '1' when EX_STATE = STACK_ACCESS_ADR_LO else
+ '1' when EX_STATE = STACK_INSTRUCTION else
+ '1' when EX_STATE = STACK_STATUS else
+ '1' when EX_STATE = STACK_PC_HI else
+ '1' when EX_STATE = STACK_PC_LO else '0';
+
+ -- Resume the STOP operation, when an external interrupt is going
+ -- to be processed.
+ EXEC_RESUME <= '1' when EX_P_INT = '1' else '0';
+
+ PENDING: process(RESETn, CLK)
+ -- The exceptions which occurs are stored in this pending register until the
+ -- interrupt handler handled the respective exception.
+ -- The TRAP_PRIV, TRAP_1010, TRAP_1111, TRAP_ILLEGAL, TRAP_OP and TRAP_V may be a strobe
+ -- of 1 clock period. All others must be strobes of 1 clock period.
+ begin
+ if RESETn = '0' then
+ EX_P_RESET <= '0';
+ EX_P_ADR_ERR <= '0';
+ EX_P_BUS_ERR <= '0';
+ EX_P_TRACE <= '0';
+ EX_P_INT <= '0';
+ EX_P_ILLEGAL <= '0';
+ EX_P_1010 <= '0';
+ EX_P_1111 <= '0';
+ EX_P_PRIV <= '0';
+ EX_P_TRAP <= '0';
+ EX_P_TRAPV <= '0';
+ EX_P_CHK <= '0';
+ EX_P_DIVZERO <= '0';
+ elsif CLK = '1' and CLK' event then
+ if RESET_CPUn = '0' then
+ EX_P_RESET <= '1';
+ elsif EX_STATE = UPDATE_PC_HI and BUS_CYC_RDY = '1' and EXCEPTION_Q = EX_RESET then
+ EX_P_RESET <= '0';
+ end if;
+ --
+ if TRAP_AERR = '1' then
+ EX_P_ADR_ERR <= '1';
+ elsif EX_STATE = UPDATE_PC_HI and BUS_CYC_RDY = '1' and EXCEPTION_Q = EX_ADR_ERR then
+ EX_P_ADR_ERR <= '0';
+ elsif RESET_CPUn = '0' then
+ EX_P_ADR_ERR <= '0';
+ end if;
+ --
+ if BERR = '1' and HALTn = '1' and EX_STATE /= GET_VECTOR then
+ -- Do not store the bus error during the interrupt acknowledge
+ -- cycle (GET_VECTOR).
+ EX_P_BUS_ERR <= '1';
+ elsif EX_STATE = UPDATE_PC_HI and BUS_CYC_RDY = '1' and EXCEPTION_Q = EX_BUS_ERR then
+ EX_P_BUS_ERR <= '0';
+ elsif RESET_CPUn = '0' then
+ EX_P_BUS_ERR <= '0';
+ end if;
+ --
+ if TRAP_TRACE = '1' then
+ EX_P_TRACE <= '1';
+ elsif EX_STATE = UPDATE_PC_HI and BUS_CYC_RDY = '1' and EXCEPTION_Q = EX_TRACE then
+ EX_P_TRACE <= '0';
+ elsif RESET_CPUn = '0' then
+ EX_P_TRACE <= '0';
+ end if;
+ --
+ if IRQ = "111" then -- Level 7 is nonmaskable ...
+ EX_P_INT <= '1';
+ elsif STATUS_REG_IN(10 downto 8) < IRQ then
+ EX_P_INT <= '1';
+ elsif EX_STATE = GET_VECTOR then
+ EX_P_INT <= '0';
+ elsif RESET_CPUn = '0' then
+ EX_P_INT <= '0';
+ end if;
+ --
+ -- The following six traps never appear at the same time:
+ if TRAP_1010 = '1' then
+ EX_P_1010 <= '1';
+ elsif TRAP_1111 = '1' then
+ EX_P_1111 <= '1';
+ elsif TRAP_ILLEGAL = '1' then
+ EX_P_ILLEGAL <= '1';
+ elsif TRAP_PRIV = '1' then
+ EX_P_PRIV <= '1';
+ elsif TRAP_OP = '1' then
+ EX_P_TRAP <= '1';
+ elsif TRAP_V = '1' then
+ EX_P_TRAPV <= '1';
+ elsif (EX_STATE = UPDATE_PC_HI and BUS_CYC_RDY = '1') or RESET_CPUn = '0' then
+ case EXCEPTION_Q is
+ when EX_PRIV | EX_1010 | EX_1111 | EX_ILLEGAL | EX_TRAP | EX_TRAPV =>
+ EX_P_PRIV <= '0';
+ EX_P_1010 <= '0';
+ EX_P_1111 <= '0';
+ EX_P_ILLEGAL <= '0';
+ EX_P_TRAP <= '0';
+ EX_P_TRAPV <= '0';
+ when others =>
+ null;
+ end case;
+ end if;
+ --
+ if TRAP_CHK = '1' then
+ EX_P_CHK <= '1';
+ elsif EX_STATE = UPDATE_PC_HI and BUS_CYC_RDY = '1' and EXCEPTION_Q = EX_CHK then
+ EX_P_CHK <= '0';
+ elsif RESET_CPUn = '0' then
+ EX_P_CHK <= '0';
+ end if;
+ --
+ if TRAP_DIVZERO = '1' then
+ EX_P_DIVZERO <= '1';
+ elsif EX_STATE = UPDATE_PC_HI and BUS_CYC_RDY = '1' and EXCEPTION_Q = EX_DIVZERO then
+ EX_P_DIVZERO <= '0';
+ elsif RESET_CPUn = '0' then
+ EX_P_DIVZERO <= '0';
+ end if;
+ end if;
+ end process PENDING;
+
+ STORE_CURRENT_EXCEPTION: process(RESETn, CLK)
+ -- The exceptions which occurs are stored in the following flags until the
+ -- interrupt handler handled the respective exception.
+ -- This process also stores the current processed exception for further use.
+ -- The update takes place in the IDLE EX_STATE.
+ begin
+ if RESETn = '0' then
+ EXCEPTION_Q <= EX_NONE;
+ elsif CLK = '1' and CLK' event then
+ if EX_STATE = IDLE and EX_P_RESET = '1' then
+ EXCEPTION_Q <= EX_RESET;
+ elsif EX_STATE = IDLE and EX_P_ADR_ERR = '1' then
+ EXCEPTION_Q <= EX_ADR_ERR;
+ elsif EX_STATE = IDLE and EX_P_BUS_ERR = '1' and BERR = '1' then
+ EXCEPTION_Q <= EX_NONE; -- Wait until BERR is negated.
+ elsif EX_STATE = IDLE and EX_P_BUS_ERR = '1' then
+ EXCEPTION_Q <= EX_BUS_ERR;
+ elsif EX_STATE = WAIT_CTRL_RDY and CTRL_RDY = '1' and EX_P_ILLEGAL = '1' then
+ EXCEPTION_Q <= EX_ILLEGAL;
+ elsif EX_STATE = WAIT_CTRL_RDY and CTRL_RDY = '1' and EX_P_1010 = '1' then
+ EXCEPTION_Q <= EX_1010;
+ elsif EX_STATE = WAIT_CTRL_RDY and CTRL_RDY = '1' and EX_P_1111 = '1' then
+ EXCEPTION_Q <= EX_1111;
+ elsif EX_STATE = WAIT_CTRL_RDY and CTRL_RDY = '1' and EX_P_PRIV = '1' then
+ EXCEPTION_Q <= EX_PRIV;
+ elsif EX_STATE = WAIT_CTRL_RDY and CTRL_RDY = '1' and EX_P_TRAP = '1' then
+ EXCEPTION_Q <= EX_TRAP;
+ elsif EX_STATE = WAIT_CTRL_RDY and CTRL_RDY = '1' and EX_P_TRAPV = '1' then
+ EXCEPTION_Q <= EX_TRAPV;
+ elsif EX_STATE = WAIT_CTRL_RDY and CTRL_RDY = '1' and EX_P_CHK = '1' then
+ EXCEPTION_Q <=EX_CHK;
+ elsif EX_STATE = WAIT_CTRL_RDY and CTRL_RDY = '1' and EX_P_DIVZERO = '1' then
+ EXCEPTION_Q <= EX_DIVZERO;
+ elsif EX_STATE = WAIT_CTRL_RDY and CTRL_RDY = '1' and EX_P_TRACE = '1' then
+ EXCEPTION_Q <= EX_TRACE;
+ elsif EX_STATE = WAIT_CTRL_RDY and CTRL_RDY = '1' and EX_P_INT = '1' then
+ EXCEPTION_Q <= EX_INT;
+ elsif NEXT_EX_STATE = IDLE then
+ EXCEPTION_Q <= EX_NONE;
+ end if;
+ end if;
+ end process STORE_CURRENT_EXCEPTION;
+
+ P_TMP_CPY: process (CLK)
+ -- For the most interrupts, a status register copy is necessary.
+ -- This is the register for a temporary copy of the status register
+ -- made in the first step of the exception processing. This copy is
+ -- in the third step written to the stack pointer, together with the
+ -- other information.
+ -- In the same manner the read write, the function code and the
+ -- address information is saved.
+ -- The temporary copies are necessary to give the bus controller in
+ -- case of a bus error enough time to terminate the current bus cycle,
+ -- means, no other bus access like status register stacking should
+ -- appear immediately after the bus error occurs.
+ variable SR_MEM: std_logic_vector(9 downto 0);
+ begin
+ if CLK = '1' and CLK' event then
+ if TMP_CPY = '1' then
+ SR_MEM := STATUS_REG_IN(15) & STATUS_REG_IN(13) & STATUS_REG_IN(10 downto 8) & STATUS_REG_IN(4 downto 0);
+ RWn_TMP <= To_StdLogicVector(RWn);
+ FC_TMP <= FC_IN;
+ ADR_TMP <= ADR_IN;
+ end if;
+ end if;
+ STATUS_REG_TMP <= SR_MEM(9) & '0' & SR_MEM(8) & "00" & SR_MEM(7 downto 5) & "000" & SR_MEM(4 downto 0);
+ end process P_TMP_CPY;
+
+ INT_VECTOR: process(RESETn, CLK)
+ variable VECTOR_No : std_logic_vector(7 downto 0);
+ variable VECT_TMP : std_logic_vector(1 downto 0);
+ -- This process provides the interrupt vector number INT_VECT, which
+ -- is determined during interrupt processing.
+ begin
+ if RESETn = '0' then
+ VECTOR_No := (others => '0'); -- Dummy assignement.
+ elsif CLK = '1' and CLK' event then
+ if EX_STATE = VECT_NR or EX_STATE = GET_VECTOR then
+ case EXCEPTION_Q is
+ when EX_RESET => VECTOR_No := x"00";
+ when EX_BUS_ERR => VECTOR_No := x"02";
+ when EX_ADR_ERR => VECTOR_No := x"03";
+ when EX_ILLEGAL => VECTOR_No := x"04";
+ when EX_DIVZERO => VECTOR_No := x"05";
+ when EX_CHK => VECTOR_No := x"06";
+ when EX_TRAPV => VECTOR_No := x"07";
+ when EX_PRIV => VECTOR_No := x"08";
+ when EX_TRACE => VECTOR_No := x"09";
+ when EX_1010 => VECTOR_No := x"0A";
+ when EX_1111 => VECTOR_No := x"0B";
+ -- The uninitialized interrupt vector number x"0F"
+ -- is provided by the peripheral interrupt source
+ -- during the auto vector bus cycle.
+ when EX_INT =>
+ if BUS_CYC_RDY = '1' and BERR = '1' then
+ VECTOR_No := x"18"; -- Spurious interrupt.
+ elsif BUS_CYC_RDY = '1' and AVECn = '0' then
+ VECTOR_No := x"18" + STATUS_REG_IN(10 downto 8); -- Autovector.
+ elsif BUS_CYC_RDY = '1' then
+ -- This is the vector number provided by the device.
+ -- If the returned Vector Number is x"0F" then it is the
+ -- uninitialized interrupt vector due to non initia-
+ -- lized vector register of the peripheral device.
+ VECTOR_No := DATA_IN; -- Non autovector.
+ end if;
+ when EX_TRAP => VECTOR_No := x"2" & TRAP_VECTOR;
+ when others => VECTOR_No := (others => '-'); -- Don't care.
+ end case;
+ VECT_TMP := "00";
+ elsif INC_TMP_VECTOR = '1' then
+ -- Offset for the next two initial bytes during system initialisation.
+ VECT_TMP := VECT_TMP + '1'; -- Increment.
+ end if;
+ end if;
+ --
+ INT_VECT <= (VECTOR_No & "00") + (VECT_TMP & '0');
+ end process INT_VECTOR;
+
+ EXCEPTION_HANDLER_REG: process(RESETn, CLK)
+ -- This is the register portion of the exception control state machine.
+ begin
+ if RESETn = '0' then
+ EX_STATE <= IDLE;
+ elsif CLK = '1' and CLK' event then
+ if RESET_CPUn = '0' then
+ EX_STATE <= IDLE;
+ elsif FORCE_HALT = true then
+ EX_STATE <= HALT;
+ else
+ EX_STATE <= NEXT_EX_STATE;
+ end if;
+ end if;
+ end process EXCEPTION_HANDLER_REG;
+
+ EXCEPTION_HANDLER_DEC: process(EX_STATE, EX_P_RESET, EX_P_ADR_ERR, EX_P_BUS_ERR, EX_P_TRACE, EX_P_INT, EX_P_ILLEGAL,
+ EX_P_1010, EX_P_1111, EX_P_PRIV, EX_P_TRAP, EX_P_TRAPV, EX_P_CHK, EX_P_DIVZERO, EXCEPTION_Q,
+ BUS_CYC_RDY, CTRL_RDY, BERR)
+ -- This is the decoder portion of the exception control state machine.
+ begin
+ -- Default assignements:
+ EXEC_ABORT <= '0';
+ TMP_CPY <= '0';
+ IRQ_SAVE <= '0';
+ INIT_STATUS <= '0';
+ PRESET_IRQ_MASK <= '0';
+ SSP_INIT <= '0';
+ PC_INIT <= '0';
+ SSP_DEC <= '0';
+ USE_INT_VECT <= '0';
+ INC_TMP_VECTOR <= '0';
+ case EX_STATE is
+ when IDLE =>
+ -- The priority of the exception execution is given by the
+ -- following construct. Although type 3 commands do not require
+ -- a prioritization, there is no drawback using these conditions.
+ -- The spurious interrupt and uninitialized interrupt never appear
+ -- as basic interrupts and therefore are not an interrupt source.
+ -- During IDLE, when an interrupt occurs, the status register copy
+ -- control is asserted and the current interrupt controll is given
+ -- to the STORE_EXCEPTION process. During bus or address errors,
+ -- the status register must be copied immediately to recognize
+ -- the current status for RWn etc. (before the faulty bus cycle is
+ -- finished).
+ if EX_P_RESET = '1' then
+ EXEC_ABORT <= '1';
+ NEXT_EX_STATE <= INIT;
+ elsif EX_P_ADR_ERR = '1' then
+ EXEC_ABORT <= '1';
+ TMP_CPY <= '1'; -- Immediate copy of the status register.
+ NEXT_EX_STATE <= INIT;
+ elsif EX_P_BUS_ERR = '1' and BERR = '1' then -- Wait until BERR is negated.
+ NEXT_EX_STATE <= IDLE;
+ elsif EX_P_BUS_ERR = '1' then -- Enter after BERR is negated.
+ EXEC_ABORT <= '1';
+ TMP_CPY <= '1'; -- Immediate copy of the status register.
+ NEXT_EX_STATE <= INIT;
+ elsif EX_P_TRAP = '1' or EX_P_TRAPV = '1' or EX_P_CHK = '1' or EX_P_DIVZERO = '1' or EX_P_TRACE = '1' then
+ NEXT_EX_STATE <= WAIT_CTRL_RDY;
+ elsif EX_P_INT = '1' or EX_P_ILLEGAL = '1' or EX_P_1010 = '1' or EX_P_1111 = '1' or EX_P_PRIV = '1' then
+ NEXT_EX_STATE <= WAIT_CTRL_RDY;
+ else -- No exception.
+ NEXT_EX_STATE <= IDLE;
+ end if;
+ when WAIT_CTRL_RDY =>
+ -- In this state, the interrupt machine waits until the current
+ -- operation execution has finished. The copy of the status register
+ -- is made after the excecution has finished.
+ if CTRL_RDY = '1' then
+ TMP_CPY <= '1'; -- Copy the status register.
+ NEXT_EX_STATE <= INIT;
+ else
+ NEXT_EX_STATE <= WAIT_CTRL_RDY;
+ end if;
+ when INIT =>
+ -- In this state, the supervisor mode is switched on (the S bit is set)
+ -- and the trace mode is switched off (the T bit is cleared).
+ INIT_STATUS <= '1';
+ case EXCEPTION_Q is
+ when EX_RESET =>
+ PRESET_IRQ_MASK <= '1';
+ NEXT_EX_STATE <= VECT_NR;
+ when EX_INT =>
+ IRQ_SAVE <= '1';
+ NEXT_EX_STATE <= GET_VECTOR;
+ when others => NEXT_EX_STATE <= VECT_NR;
+ end case;
+ when VECT_NR =>
+ -- This state is introduced to control the generation of the vector number
+ -- for all exceptions except the external interrupts.
+ case EXCEPTION_Q is
+ when EX_RESET =>
+ NEXT_EX_STATE <= UPDATE_SSP_HI; -- Do not stack anything but update the SSP and PC.
+ when others =>
+ SSP_DEC <= '1';
+ NEXT_EX_STATE <= STACK_PC_LO;
+ end case;
+ when GET_VECTOR =>
+ -- This state is intended to determine the vector number for the current process.
+ -- See also the process EX_VECTOR for the handling of the vector determination.
+ if BUS_CYC_RDY = '1' then
+ SSP_DEC <= '1';
+ NEXT_EX_STATE <= STACK_PC_LO;
+ else
+ NEXT_EX_STATE <= GET_VECTOR;
+ end if;
+ -- The following states provide writing to the stack pointer or reading
+ -- the exception vector address from the memory. If there is a bus error
+ -- or an address error during the read or write cycles, the processor
+ -- proceeds in two different ways:
+ -- If the errors occur during a reset, bus error or address error
+ -- exception processing, there is the case of a double bus fault. In
+ -- consequence, the processor halts due to catastrophic system failure.
+ -- If the errors occur during other exception processings, the current
+ -- processing is aborted and this exception handler state machine will
+ -- immediately begin with the bus error exception handling.
+ when STACK_PC_LO =>
+ if BUS_CYC_RDY = '1' then
+ SSP_DEC <= '1';
+ NEXT_EX_STATE <= STACK_PC_HI;
+ else
+ NEXT_EX_STATE <= STACK_PC_LO;
+ end if;
+ when STACK_PC_HI =>
+ if BUS_CYC_RDY = '1' then
+ SSP_DEC <= '1';
+ NEXT_EX_STATE <= STACK_STATUS;
+ else
+ NEXT_EX_STATE <= STACK_PC_HI;
+ end if;
+ when STACK_STATUS =>
+ if BUS_CYC_RDY = '1' then
+ case EXCEPTION_Q is
+ when EX_BUS_ERR | EX_ADR_ERR =>
+ SSP_DEC <= '1';
+ NEXT_EX_STATE <= STACK_INSTRUCTION;
+ when others =>
+ NEXT_EX_STATE <= UPDATE_PC_HI;
+ end case;
+ else
+ NEXT_EX_STATE <= STACK_STATUS;
+ end if;
+ when STACK_INSTRUCTION =>
+ if BUS_CYC_RDY = '1' then
+ SSP_DEC <= '1';
+ NEXT_EX_STATE <= STACK_ACCESS_ADR_LO;
+ else
+ NEXT_EX_STATE <= STACK_INSTRUCTION;
+ end if;
+ when STACK_ACCESS_ADR_LO =>
+ if BUS_CYC_RDY = '1' then
+ SSP_DEC <= '1';
+ NEXT_EX_STATE <= STACK_ACCESS_ADR_HI;
+ else
+ NEXT_EX_STATE <= STACK_ACCESS_ADR_LO;
+ end if;
+ when STACK_ACCESS_ADR_HI =>
+ if BUS_CYC_RDY = '1' then
+ SSP_DEC <= '1';
+ NEXT_EX_STATE <= STACK_MISC;
+ else
+ NEXT_EX_STATE <= STACK_ACCESS_ADR_HI;
+ end if;
+ when STACK_MISC =>
+ if BUS_CYC_RDY = '1' then
+ NEXT_EX_STATE <= UPDATE_PC_HI;
+ else
+ NEXT_EX_STATE <= STACK_MISC;
+ end if;
+ when UPDATE_SSP_HI =>
+ if BUS_CYC_RDY = '1' then
+ INC_TMP_VECTOR <= '1';
+ NEXT_EX_STATE <= UPDATE_SSP_LO;
+ else
+ NEXT_EX_STATE <= UPDATE_SSP_HI;
+ end if;
+ USE_INT_VECT <= '1';
+ when UPDATE_SSP_LO =>
+ if BUS_CYC_RDY = '1' then
+ INC_TMP_VECTOR <= '1';
+ SSP_INIT <= '1';
+ NEXT_EX_STATE <= UPDATE_PC_HI;
+ else
+ NEXT_EX_STATE <= UPDATE_SSP_LO;
+ end if;
+ USE_INT_VECT <= '1';
+ when UPDATE_PC_HI =>
+ if BUS_CYC_RDY = '1' then
+ INC_TMP_VECTOR <= '1';
+ NEXT_EX_STATE <= UPDATE_PC_LO;
+ else
+ NEXT_EX_STATE <= UPDATE_PC_HI;
+ end if;
+ USE_INT_VECT <= '1';
+ when UPDATE_PC_LO =>
+ if BUS_CYC_RDY = '1' then
+ PC_INIT <= '1';
+ NEXT_EX_STATE <= IDLE;
+ else
+ NEXT_EX_STATE <= UPDATE_PC_LO;
+ end if;
+ USE_INT_VECT <= '1';
+ when HALT =>
+ -- Processor halted, Double bus error!
+ NEXT_EX_STATE <= HALT;
+ end case;
+ end process EXCEPTION_HANDLER_DEC;
+end BEHAVIOR;
diff --git a/common/CPU/68000/wf_68k00_ip/wf68k00ip_opcode_decoder.vhd b/common/CPU/68000/wf_68k00_ip/wf68k00ip_opcode_decoder.vhd
new file mode 100644
index 00000000..fa823a2f
--- /dev/null
+++ b/common/CPU/68000/wf_68k00_ip/wf68k00ip_opcode_decoder.vhd
@@ -0,0 +1,1016 @@
+----------------------------------------------------------------------
+---- ----
+---- MC68000 compatible IP Core ----
+---- ----
+---- This file is part of the SUSKA ATARI clone project. ----
+---- http://www.experiment-s.de ----
+---- ----
+---- Description: ----
+---- This model provides an opcode and bus timing compatible ip ----
+---- core compared to Motorola's MC68000 microprocessor. ----
+---- ----
+---- This file contains the opcode decoder. ----
+---- ----
+---- ----
+---- Description: ----
+---- Performs an instruction opcode decoding and the control ----
+---- functions for all other blocks. ----
+---- This Opcode decoder of the 68K00 decodes already the opera- ----
+---- tions long division (signed and unsigned (DIVL) and long ----
+---- multiplication (signed and unsigned) (MULL). ----
+---- ----
+---- ----
+---- Author(s): ----
+---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
+---- ----
+----------------------------------------------------------------------
+---- ----
+---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
+---- ----
+---- This source file 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 2 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, write to the Free ----
+---- Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ----
+---- Boston, MA 02110-1301, USA. ----
+---- ----
+----------------------------------------------------------------------
+--
+-- Revision History
+--
+-- Revision 2K6B 2006/12/24 WF
+-- Initial Release.
+-- Revision 2K7A 2007/05/31 WF
+-- Updated all modules.
+-- Revision 2K7B 2007/12/24 WF
+-- See the 68K00 top level file.
+-- Revision 2K8A 2008/07/14 WF
+-- See the 68K00 top level file.
+--
+
+use work.wf68k00ip_pkg.all;
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity WF68K00IP_OPCODE_DECODER is
+ port (
+ CLK : in bit;
+ RESETn : in bit;
+
+ DATA_IN : in std_logic_vector(15 downto 0);
+ SBIT : in bit;
+ OV : in std_logic; -- Overflow flag.
+
+ -- Instruction word controls:
+ IW_ADR : in integer range 0 to 2; -- Instruction word address.
+ IW_WR : in bit; -- Instruction word write control.
+
+ -- Further load controls (besides the first instruction word):
+ FORCE_BIW2 : out bit;
+ FORCE_BIW3 : out bit;
+ EXT_CNT : out integer range 0 to 2;
+ DEST_EXT_CNT : out integer range 0 to 2;
+
+ -- System control flags:
+ DR : out bit;
+ RM : out bit;
+ IR : out bit;
+
+ -- System control signals:
+ OP : out OP_68K00;
+ OP_SIZE : out OP_SIZETYPE; -- Operand size.
+ OP_MODE : out std_logic_vector(4 downto 0);
+ BIW_0 : out std_logic_vector(15 downto 0);
+ REGSEL_20 : out std_logic_vector(2 downto 0);
+ REGSEL_119 : out std_logic_vector(2 downto 0);
+ REGSEL_INDEX : out std_logic_vector(2 downto 0);
+ DATA_IMMEDIATE : out std_logic_vector(31 downto 0);
+ TRAP_VECTOR : out std_logic_vector(3 downto 0);
+ C_CODE : out bit_vector(3 downto 0);
+ MEM_SHFT : out bit; -- Shift operations in registers ('0') or in memory ('1').
+ REGLISTMASK : out std_logic_vector(15 downto 0); -- Used in MOVEM.
+
+ -- Bit operations:
+ BITPOS_IM : out bit; -- Immediate bit position select.
+ BIT_POS : out std_logic_vector(4 downto 0); -- The bit position.
+
+ -- Multiplication / Division:
+ DIV_MUL_32n64 : out bit;
+ REG_Dlq : out std_logic_vector(2 downto 0);
+ REG_Dhr : out std_logic_vector(2 downto 0);
+
+ -- Traps:
+ SCAN_TRAPS : in bit;
+ TRAP_ILLEGAL : out bit;
+ TRAP_1010 : out bit;
+ TRAP_1111 : out bit;
+ TRAP_PRIV : out bit;
+ TRAP_OP : out bit;
+ TRAP_V : out bit;
+
+ -- Extension word controls:
+ EW_WR : in bit; -- Write control.
+ EW_ADR : in integer range 0 to 1; -- Source extension word address.
+ SRC_DESTn : in bit; -- '1' for read operand from source, '0' store result to destination (MOVE).
+
+ -- Extension words:
+ EXWORD : out EXWORDTYPE;
+ DEST_EXWORD : out EXWORDTYPE;
+
+ -- Address computation stuff:
+ ADR_MODE : out std_logic_vector(2 downto 0); -- Address mode indicator.
+ MOVE_D_AM : out std_logic_vector(2 downto 0); -- Move statement destination address mode.
+ EXT_DSIZE : out D_SIZETYPE; -- Displacement size, BYTE or WORD.
+ SEL_DISPLACE_BIW : out bit; -- Select displacement from the basic instruction word BIW, when '1'.
+ DISPLACE_BIW : out std_logic_vector(31 downto 0) -- Displacement (direct encoded, 8 or 16 bit).
+ );
+end entity WF68K00IP_OPCODE_DECODER;
+
+architecture BEHAVIOR of WF68K00IP_OPCODE_DECODER is
+type BIW_TYPE is array(0 to 2) of std_logic_vector(15 downto 0);
+signal BIW : BIW_TYPE; -- Instruction word registers.
+signal EXT_EN : bit;
+signal OP_I : OP_68K00;
+signal OP_SIZE_I : OP_SIZETYPE;
+signal EXWORD_REG : EXWORDTYPE;
+signal DEST_EXWORD_REG : EXWORDTYPE;
+begin
+ EXTENSIONS: process(RESETn, CLK)
+ -- In this process the required source and destination extension words
+ -- for the operations are stored. This process works on the negative
+ -- clock edge to meet the timing requirements in conjunction with the
+ -- bus interface and the system control state machine.
+ begin
+ if RESETn = '0' then
+ for i in 0 to 1 loop
+ EXWORD_REG(i) <= (others => '0');
+ DEST_EXWORD_REG(i) <= (others => '0');
+ end loop;
+ elsif CLK = '0' and CLK' event then
+ -- The extension words are written but never initialized
+ -- during the operation. This does not take any negative
+ -- effect because the operations, using the extensions,
+ -- overwrite the respective words during instruction
+ -- load process.
+ if EW_WR = '1' and SRC_DESTn = '1' then
+ EXWORD_REG(EW_ADR) <= DATA_IN;
+ elsif EW_WR = '1' then -- SRC_DESTn = '0'.
+ DEST_EXWORD_REG(EW_ADR) <= DATA_IN;
+ end if;
+ end if;
+ end process EXTENSIONS;
+ --
+ EXWORD <= EXWORD_REG;
+ DEST_EXWORD <= DEST_EXWORD_REG;
+
+ -- Copy signal to port:
+ OP <= OP_I;
+
+ -- TRAPS:
+ TRAP_1010 <= '1' when SCAN_TRAPS = '1' and BIW(0)(15 downto 12) = "1010" else '0';
+ TRAP_1111 <= '1' when SCAN_TRAPS = '1' and BIW(0)(15 downto 12) = "1111" else '0';
+ TRAP_ILLEGAL <= '1' when SCAN_TRAPS = '1' and OP_I = ILLEGAL else '0';
+ TRAP_OP <= '1' when SCAN_TRAPS = '1' and OP_I = TRAP else '0';
+ TRAP_V <= '1' when SCAN_TRAPS = '1' and OP_I = TRAPV and OV = '1' else '0';
+ with OP_I select
+ TRAP_PRIV <= not SBIT and SCAN_TRAPS when ANDI_TO_SR | EORI_TO_SR | MOVE_TO_SR | MOVE_USP | ORI_TO_SR | RESET | RTE | STOP,
+ '0' when others;
+
+ OPCODE_REG: process(RESETn, CLK)
+ -- In this process the different OPCODE registers store all required information for
+ -- the instruction processing. Depending on the operation, at least the Basic Instruction
+ -- Word BIW(0) is stored followed by a second and third instruction word Word BIW(1) and
+ -- BIW(2), if required. This process works on the negative clock edge to meet the timing
+ -- requirements in conjunction with the bus interface and the system control state machine.
+ begin
+ if RESETn = '0' then
+ BIW(0) <= (others => '0');
+ BIW(1) <= (others => '0');
+ BIW(2) <= (others => '0');
+ elsif CLK = '0' and CLK' event then
+ if IW_WR = '1' then
+ BIW(IW_ADR) <= DATA_IN;
+ end if;
+ end if;
+ end process OPCODE_REG;
+
+ BIW_0 <= BIW(0);
+
+ DR <= To_Bit(BIW(0)(10)) when OP_I = MOVEM else
+ To_Bit(BIW(0)(3)) when OP_I = MOVE_USP else
+ To_Bit(BIW(0)(8)); -- Default is valid for ASL, ASR, LSL, LSR, ROL, ROR, ROXL, ROXR.
+ RM <= To_Bit(BIW(0)(3)); -- Valid for SBCD, SUBX, ABCD, ADDX.
+ IR <= To_Bit(BIW(0)(5)); -- Valid for ASL, ASR, LSL, LSR, ROL, ROR, ROXL, ROXR.
+
+ -- Addressing mode:
+ -- The Default is valid for ORI, ANDI, SUBI, CALLM, ADDI, EORI, CMPI, BTST, BCHG, BCLR, BSET,
+ -- MOVEA, MOVE_FROM_CCR, MOVE_FROM_SR, NEGX, CLR, MOVE_TO_CCR, NEG, NOT, MOVE_TO_SR, NBCD, PEA,
+ -- TAS, TST, MULYU, MULS, DIVU, DIVS, JSR, JMP, MOVEM, LEA, CHK, ADDQ, SUBQ, OR, SUB, SUBA,
+ -- CMP, CMPA, EOR, AND, ADDA, ADD, ASL, ASR, LSL, LSR, ROL, ROR, ROXL, ROXR.
+ ADR_MODE <= "100" when OP_I = ABCD or OP_I = SBCD or OP_I = ADDX or OP_I = SUBX else -- Predecrement.
+ "011" when OP_I = CMPM else -- Postincrement.
+ "101" when OP_I = MOVEP else -- Address register indirect plus 16 bit displacement.
+ BIW(0)(5 downto 3);
+
+ MOVE_D_AM <= BIW(0)(8 downto 6); -- Move statement destination address mode.
+
+ REGSEL_20 <= BIW(0)(2 downto 0); -- Valid for ORI, ANDI, SUBI, ADDI, EORI, CMPI, BTST, BCHG, BCLR
+ -- BCLR, BSET, MOVEP, MOVEA, MOVE, MOVE_FROM_CCR, MOVE_FROM_SR,
+ -- MOVE_TO_CCR, NEGX, CLR, NEG, NOT, MOVE_TO_SR, EXT, NBCD,
+ -- SWAP, PEA, TAS, TST, MULU, MULS, DIVU, DIVS, LINK, UNLK,
+ -- MOVE_USP, JSR, JMP, MOVEM, LEA, CHK, ADDQ, SUBQ, DBcc, Scc,
+ -- OR, SUBX, SUB, SUBA, CMPM, CMP, CMPA, EOR, ABCD, EXG, AND,
+ -- ADDX, ADDA, ADD, ASL, ASR, LSL, LSR, ROL, ROR, ROXL, ROXR.
+ REGSEL_119 <= BIW(0)(11 downto 9); -- Valid for BTST, BCHG, BCLR, BSET,MOVEP, MOVEA, MOVE, LEA,
+ -- CHK, MULU, MULS, DIVU, DIVS, SBCD, OR, SUBX, SUB, SUBA,
+ -- CMPM, CMP, CMPA, EOR, ABCD, EXG, AND, ADDX, ADDA, ADD.
+
+ REGSEL_INDEX <= EXWORD_REG(0)(14 downto 12) when SRC_DESTn = '1' else DEST_EXWORD_REG(0)(14 downto 12);
+
+ C_CODE <= To_BitVector(BIW(0)(11 downto 8)); -- Valid for Bcc, DBcc, Scc.
+
+ OP_MODE <= BIW(0)(7 downto 3) when OP_I = EXG else
+ "00" & BIW(0)(8 downto 6); -- Valid for EXT, OR, SUB, SUBA, CMP, CMPA, EOR, AND, ADDA, ADD.
+ TRAP_VECTOR <= BIW(0)(3 downto 0); -- Valid for TRAP.
+
+ with OP_I select
+ SEL_DISPLACE_BIW <= '1' when Bcc | BRA | BSR | DBcc | MOVEP | LINK, '0' when others;
+
+ DISPLACE_BIW <= x"0000" & BIW(1) when OP_I = BRA and BIW(0)(7 downto 0) = x"00" else -- Word displacement.
+ BIW(1) & BIW(2) when OP_I = BRA and BIW(0)(7 downto 0) = x"FF" else -- LONG displacement 68K20+.
+ x"0000" & BIW(1) when OP_I = BSR and BIW(0)(7 downto 0) = x"00" else
+ BIW(1) & BIW(2) when OP_I = BSR and BIW(0)(7 downto 0) = x"FF" else -- LONG displacement 68K20+.
+ x"0000" & BIW(1) when OP_I = Bcc and BIW(0)(7 downto 0) = x"00" else
+ x"000000" & BIW(0)(7 downto 0) when OP_I = BRA or OP_I = BSR or OP_I = Bcc else
+ BIW(1) & BIW(2) when OP_I = LINK and OP_SIZE_I = LONG else
+ x"0000" & BIW(1); -- Valid for DBcc, LINK, MOVEP.
+
+ EXT_DSIZE <= LONG when OP_I = LINK and OP_SIZE_I = LONG else
+ WORD when OP_I = DBcc or OP_I = MOVEP or OP_I = LINK else
+ WORD when OP_I = BRA and BIW(0)(7 downto 0) = x"00" else
+ LONG when OP_I = BRA and BIW(0)(7 downto 0) = x"FF" else -- 68K20+.
+ WORD when OP_I = BSR and BIW(0)(7 downto 0) = x"00" else
+ LONG when OP_I = BSR and BIW(0)(7 downto 0) = x"FF" else -- 68K20+.
+ LONG when OP_I = Bcc and BIW(0)(7 downto 0) = x"FF" else -- 68K20+.
+ WORD when OP_I = Bcc and BIW(0)(7 downto 0) = x"00" else
+ BYTE when OP_I = BRA or OP_I = BSR or OP_I = Bcc else
+ WORD when BIW(0)(8 downto 6) = "101" and SRC_DESTn = '0' else -- MOVE.
+ BYTE when BIW(0)(8 downto 6) = "110" and SRC_DESTn = '0' else -- MOVE.
+ WORD when BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) = "010" else
+ WORD when BIW(0)(5 downto 3) = "101" else BYTE;
+
+ -- The immediate data is modelled in a way, that not used bits are forced to zero. This requires
+ -- a bit more logic but makes the CPU immune against compiler behavior concerning the writing of the
+ -- none used bits in word and byte mode.
+ -- The last two assignments are valid (in the respective mode) for: ADD, ADDA, AND, BTST, CHK, CMP, CMPA,
+ -- DIVS, DIVU, MOVEA, MOVE_TO_CCR, MOVE_TO_SR, MULS, MULU, OR, SUB, SUBA, TST.
+ DATA_IMMEDIATE <= x"0000" & x"00" & BIW(1)(7 downto 0) when OP_I = ORI_TO_CCR or OP_I = EORI_TO_CCR else
+ x"0000" & BIW(1) when OP_I = EORI_TO_SR or OP_I = ORI_TO_SR or OP_I = ANDI_TO_SR else
+ x"00000008" when (OP_I = ADDQ or OP_I = SUBQ) and BIW(0)(11 downto 9) = "000" else
+ x"0000000" & '0' & BIW(0)(11 downto 9) when OP_I = ADDQ or OP_I = SUBQ else
+ BIW(1) & BIW(2) when (OP_I = ANDI or OP_I = ADDI) and BIW(0)(7 downto 6) = "10" else -- Long.
+ BIW(1) & BIW(2) when (OP_I = CMPI or OP_I = EORI) and BIW(0)(7 downto 6) = "10" else -- Long.
+ BIW(1) & BIW(2) when (OP_I = ORI or OP_I = SUBI) and BIW(0)(7 downto 6) = "10" else -- Long.
+ x"0000" & BIW(1) when (OP_I = ANDI or OP_I = ADDI) and BIW(0)(7 downto 6) = "01" else -- Word.
+ x"0000" & BIW(1) when (OP_I = CMPI or OP_I = EORI) and BIW(0)(7 downto 6) = "01" else -- Word.
+ x"0000" & BIW(1) when (OP_I = ORI or OP_I = SUBI) and BIW(0)(7 downto 6) = "01" else -- Word.
+ x"0000" & x"00" & BIW(1)(7 downto 0) when (OP_I = ANDI or OP_I = ADDI) else -- Byte;
+ x"0000" & x"00" & BIW(1)(7 downto 0) when (OP_I = CMPI or OP_I = EORI) else -- Byte;
+ x"0000" & x"00" & BIW(1)(7 downto 0) when (OP_I = ORI or OP_I = SUBI) else -- Byte;
+ x"0000" & BIW(1) when OP_I = STOP else
+ x"000000" & BIW(0)(7 downto 0) when OP_I = MOVEQ else
+ EXWORD_REG(0) & EXWORD_REG(1) when OP_SIZE_I = LONG else
+ x"0000" & EXWORD_REG(0);
+
+ -- Bit Position for the bit operations BCHG, BCLR, BSET, BTST:
+ -- The Bit position is valid if BITPOS_IM is '1'.
+ -- If BITPOS_IM is '1', the register selected by REGSEL_119 indicates the bit position.
+ BITPOS_IM <= '1' when (OP_I = BCHG or OP_I = BCLR or OP_I = BSET or OP_I = BTST) and BIW(0)(8) = '0' else '0';
+ BIT_POS <= BIW(1)(4 downto 0);
+
+ -- Multiplication / Division:
+ DIV_MUL_32n64 <= To_Bit(BIW(1)(10));
+ REG_Dlq <= BIW(1)(14 downto 12);
+ REG_Dhr <= BIW(1)(2 downto 0);
+
+
+ -- This signal indicates register or memory shifting.
+ MEM_SHFT <= '1' when (OP_I = ASL or OP_I = ASR) and BIW(0)(7 downto 6) = "11" else
+ '1' when (OP_I = LSL or OP_I = LSR) and BIW(0)(7 downto 6) = "11" else
+ '1' when (OP_I = ROTL or OP_I = ROTR) and BIW(0)(7 downto 6) = "11" else
+ '1' when (OP_I = ROXL or OP_I = ROXR) and BIW(0)(7 downto 6) = "11" else '0';
+
+ REGLISTMASK <= BIW(1);
+
+ OP_SIZE <= OP_SIZE_I;
+ OP_SIZE_I <= BYTE when OP_I = ABCD or OP_I = NBCD or OP_I = SBCD else
+ LONG when OP_I = ADDA and BIW(0)(8 downto 6) = "111" else
+ WORD when OP_I = ADDA and BIW(0)(8 downto 6) = "011" else
+ LONG when OP_I = BCHG and BIW(0)(5 downto 3) = "000" else
+ LONG when OP_I = BCLR and BIW(0)(5 downto 3) = "000" else
+ LONG when OP_I = BSET and BIW(0)(5 downto 3) = "000" else
+ LONG when OP_I = BTST and BIW(0)(5 downto 3) = "000" else
+ BYTE when (OP_I = BCHG or OP_I = BCLR) else -- Memory access is byte.
+ BYTE when (OP_I = BSET or OP_I = BTST) else -- Memory access is byte.
+ WORD when OP_I = CHK and BIW(0)(8 downto 7) = "11" else
+ LONG when OP_I = CHK and BIW(0)(8 downto 7) = "10" else
+ LONG when OP_I = CMPA and BIW(0)(8 downto 6) = "111" else
+ WORD when OP_I = CMPA and BIW(0)(8 downto 6) = "011" else
+ LONG when OP_I = DIVS and BIW(0)(8 downto 6) = "001" else
+ LONG when OP_I = DIVU and BIW(0)(8 downto 6) = "001" else
+ WORD when OP_I = DIVS and BIW(0)(8 downto 6) = "111" else
+ WORD when OP_I = DIVU and BIW(0)(8 downto 6) = "011" else
+ LONG when OP_I = EXTW and BIW(0)(7 downto 6) = "11" else
+ WORD when OP_I = EXTW and BIW(0)(7 downto 6) = "10" else
+ WORD when OP_I = LINK and BIW(0)(15 downto 3) = "0100111001010" else
+ LONG when OP_I = LINK and BIW(0)(15 downto 3) = "0100100000001" else
+ BYTE when OP_I = MOVE and BIW(0)(13 downto 12) = "01" else
+ WORD when OP_I = MOVE and BIW(0)(13 downto 12) = "11" else
+ LONG when OP_I = MOVE and BIW(0)(13 downto 12) = "10" else
+ WORD when OP_I = MOVEA and BIW(0)(13 downto 12) = "11" else
+ LONG when OP_I = MOVEA and BIW(0)(13 downto 12) = "10" else
+ LONG when OP_I = MOVEM and BIW(0)(6) = '1' else
+ WORD when OP_I = MOVEM and BIW(0)(6) = '0' else
+ LONG when OP_I = MOVEP and BIW(0)(8 downto 6) = "111" else
+ LONG when OP_I = MOVEP and BIW(0)(8 downto 6) = "101" else
+ WORD when OP_I = MOVEP and BIW(0)(8 downto 6) = "110" else
+ WORD when OP_I = MOVEP and BIW(0)(8 downto 6) = "100" else
+ WORD when OP_I = MOVE_FROM_CCR else
+ WORD when OP_I = MOVE_FROM_SR else
+ WORD when OP_I = MOVE_TO_CCR else
+ WORD when OP_I = MOVE_TO_SR else
+ LONG when OP_I = MULS and BIW(0)(8 downto 6) = "000" else
+ LONG when OP_I = MULU and BIW(0)(8 downto 6) = "000" else
+ WORD when OP_I = MULS and BIW(0)(8 downto 6) = "111" else
+ WORD when OP_I = MULU and BIW(0)(8 downto 6) = "011" else
+ LONG when OP_I = SUBA and BIW(0)(8 downto 6) = "111" else
+ WORD when OP_I = SUBA and BIW(0)(8 downto 6) = "011" else
+ BYTE when OP_I = Scc or OP_I = TAS else
+ WORD when (OP_I = ASL or OP_I = ASR) and BIW(0)(7 downto 6) = "11" else -- Memory Shifts.
+ WORD when (OP_I = LSL or OP_I = LSR) and BIW(0)(7 downto 6) = "11" else -- Memory Shifts.
+ WORD when (OP_I = ROTL or OP_I = ROTR) and BIW(0)(7 downto 6) = "11" else -- Memory Shifts.
+ WORD when (OP_I = ROXL or OP_I = ROXR) and BIW(0)(7 downto 6) = "11" else -- Memory Shifts.
+ LONG when OP_I = BSR or OP_I = PEA or OP_I = RTS else -- Long words to/from the stack.
+ -- The following three conditions are valid for the listed operations:
+ -- ADDI, ANDI, CMP, CMPI, EORI, ORI, SUBI, ADDQ, SUBQ, ADDX, NEGX, SUBX, ASR,
+ -- ASL, LSR, LSL, ROXR, ROXL, ROTR, ROTL, CLR, NEG, NOT_B, TST, CMPM, JSR.
+ BYTE when BIW(0)(7 downto 6) = "00" else
+ WORD when BIW(0)(7 downto 6) = "01" else
+ LONG when BIW(0)(7 downto 6) = "10" else LONG; -- The default is used for unsized operations LEA, MOVEQ ...
+
+ -- The FORCE_BIW2 indicates, that an operation needs obligatory a further instruction word.
+ FORCE_BIW2 <= '1' when OP_I = ORI_TO_CCR or OP_I = ORI_TO_SR or OP_I = ORI or OP_I = ANDI_TO_CCR else
+ '1' when OP_I = ANDI_TO_SR or OP_I = ANDI or OP_I = SUBI or OP_I = ADDI or OP_I = EORI_TO_CCR else
+ '1' when (OP_I = BCHG or OP_I = BCLR or OP_I = BSET or OP_I = BTST) and BIW(0)(8) = '0' else
+ '1' when OP_I = EORI_TO_SR or OP_I = EORI or OP_I = CMPI else
+ '1' when OP_I = MOVEP or OP_I = LINK or OP_I = STOP else
+ '1' when (OP_I = DIVS or OP_I = DIVU) and BIW(0)(8 downto 6) = "001" else
+ '1' when (OP_I = MULS or OP_I = MULU) and BIW(0)(8 downto 6) = "000" else
+ '1' when OP_I = MOVEM or OP_I = DBcc else
+ '1' when (OP_I = BRA or OP_I = BSR or OP_I = Bcc) and BIW(0)(7 downto 0) = x"00" else
+ '1' when (OP_I = BRA or OP_I = BSR or OP_I = Bcc) and BIW(0)(7 downto 0) = x"FF" else '0';
+
+ -- The FORCE_BIW3 indicates, that an operation needs obligatory a third instruction word.
+ FORCE_BIW3 <= '1' when OP_I = ORI and OP_SIZE_I = LONG else
+ '1' when OP_I = ANDI and OP_SIZE_I = LONG else
+ '1' when OP_I = SUBI and OP_SIZE_I = LONG else
+ '1' when OP_I = ADDI and OP_SIZE_I = LONG else
+ '1' when OP_I = EORI and OP_SIZE_I = LONG else
+ '1' when OP_I = CMPI and OP_SIZE_I = LONG else
+ '1' when OP_I = LINK and OP_SIZE_I = LONG else
+ '1' when (OP_I = BRA or OP_I = BSR or OP_I = Bcc) and BIW(0)(7 downto 0) = x"FF" else '0';
+
+ -- Enables extension word fetch for the respective commands.
+ EXT_EN <= '1' when OP_I = ADD or OP_I = ADDA or OP_I = ADDI or OP_I = ADDQ or OP_I = AND_B or OP_I = ANDI else
+ '1' when (OP_I = ASL or OP_I = ASR) and BIW(0)(7 downto 6) = "11" else -- Memory Shifts.
+ '1' when (OP_I = LSL or OP_I = LSR) and BIW(0)(7 downto 6) = "11" else -- Memory Shifts.
+ '1' when (OP_I = ROXL or OP_I = ROXR) and BIW(0)(7 downto 6) = "11" else -- Memory Shifts.
+ '1' when (OP_I = ROTL or OP_I = ROTR) and BIW(0)(7 downto 6) = "11" else -- Memory Shifts.
+ '1' when OP_I = BCHG or OP_I = BCLR or OP_I = BSET or OP_I = BTST or OP_I = CHK or OP_I = CLR else
+ '1' when OP_I = CMP or OP_I = CMPA or OP_I = CMPI or OP_I = DIVS or OP_I = DIVU or OP_I = EOR else
+ '1' when OP_I = EORI or OP_I = JMP or OP_I = JSR or OP_I = LEA or OP_I = MOVE or OP_I = MOVEA else
+ '1' when OP_I = MOVE_FROM_CCR or OP_I = MOVE_TO_CCR or OP_I = MOVE_FROM_SR or OP_I = MOVE_TO_SR else
+ '1' when OP_I = MOVEM or OP_I = MULS or OP_I = MULU or OP_I = NBCD or OP_I = NEG or OP_I = NEGX else
+ '1' when OP_I = NOT_B or OP_I = OR_B or OP_I = ORI or OP_I = PEA or OP_I = Scc or OP_I = SUB else
+ '1' when OP_I = SUBA or OP_I = SUBI or OP_I = SUBQ or OP_I = TAS or OP_I = TST else '0';
+
+ -- If extension word fetch is enabled, this is the number of source or/and destination extensions to fetch.
+ EXT_CNT <= 2 when BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) = "100" and OP_SIZE_I = LONG and EXT_EN = '1' else
+ 2 when BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) = "001" and EXT_EN = '1' else
+ 1 when BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) = "100" and EXT_EN = '1' else
+ 1 when BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) = "011" and EXT_EN = '1' else
+ 1 when BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) = "010" and EXT_EN = '1' else
+ 1 when BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) = "000" and EXT_EN = '1' else
+ 1 when BIW(0)(5 downto 3) = "110" and EXT_EN = '1' else
+ 1 when BIW(0)(5 downto 3) = "101" and EXT_EN = '1' else 0;
+
+ -- For the MOVE operation, we need a second set of extension words.
+ DEST_EXT_CNT <= 2 when BIW(0)(8 downto 6) = "111" and BIW(0)(11 downto 9) = "001" and OP_I = MOVE else
+ 1 when BIW(0)(8 downto 6) = "111" and BIW(0)(11 downto 9) = "000" and OP_I = MOVE else
+ 1 when BIW(0)(8 downto 6) = "110" and OP_I = MOVE else
+ 1 when BIW(0)(8 downto 6) = "101" and OP_I = MOVE else 0;
+
+ OP_DECODE: process(BIW)
+ begin
+ -- The default OPCODE is the ILLEGAL operation, if no of the following conditions are met.
+ -- If any not used bit pattern occurs, the CPU will result in an ILLEGAL trap. An exception of
+ -- this behavior is the OPCODE with the 1010 or the 1111 pattern in the four MSBs.
+ -- These lead to the respective traps.
+ OP_I <= ILLEGAL;
+ case BIW(0)(15 downto 12) is -- Operation code map.
+ when x"0" => -- Bit manipulation / MOVEP / Immediate.
+ if BIW(0)(11 downto 0) = x"03C" then
+ OP_I <= ORI_TO_CCR;
+ elsif BIW(0)(11 downto 0) = x"07C" then
+ OP_I <= ORI_TO_SR;
+ elsif BIW(0)(11 downto 0) = x"23C" then
+ OP_I <= ANDI_TO_CCR;
+ elsif BIW(0)(11 downto 0) = x"27C" then
+ OP_I <= ANDI_TO_SR;
+ elsif BIW(0)(11 downto 0) = x"A3C" then
+ OP_I <= EORI_TO_CCR;
+ elsif BIW(0)(11 downto 0) = x"A7C" then
+ OP_I <= EORI_TO_SR;
+ end if;
+
+ case BIW(0)(5 downto 3) is -- Addressing mode.
+ when "000" | "010" | "011" | "100" | "101" | "110" =>
+ -- Bit operations with static bit number:
+ if BIW(0)(11 downto 6) = "100000" then
+ OP_I <= BTST;
+ elsif BIW(0)(11 downto 6) = "100001" then
+ OP_I <= BCHG;
+ elsif BIW(0)(11 downto 6) = "100010" then
+ OP_I <= BCLR;
+ elsif BIW(0)(11 downto 6) = "100011" then
+ OP_I <= BSET;
+ -- Logic operations:
+ elsif BIW(0)(11 downto 8) = x"0" and BIW(0)(7 downto 6) < "11" then
+ OP_I <= ORI;
+ elsif BIW(0)(11 downto 8) = x"2" and BIW(0)(7 downto 6) < "11" then
+ OP_I <= ANDI;
+ elsif BIW(0)(11 downto 8) = x"4" and BIW(0)(7 downto 6) < "11" then
+ OP_I <= SUBI;
+ elsif BIW(0)(11 downto 8) = x"6" and BIW(0)(7 downto 6) < "11" then
+ OP_I <= ADDI;
+ elsif BIW(0)(11 downto 8) = x"A" and BIW(0)(7 downto 6) < "11" then
+ OP_I <= EORI;
+ elsif BIW(0)(11 downto 8) = x"C" and BIW(0)(7 downto 6) < "11" then
+ OP_I <= CMPI;
+ -- Bit operations with dynamic bit number:
+ elsif BIW(0)(8 downto 6) = "100" then
+ OP_I <= BTST;
+ elsif BIW(0)(8 downto 6) = "101" then
+ OP_I <= BCHG;
+ elsif BIW(0)(8 downto 6) = "110" then
+ OP_I <= BCLR;
+ elsif BIW(0)(8 downto 6) = "111" then
+ OP_I <= BSET;
+ end if;
+ when "111" =>
+ -- In the addressing mode "111" not all register selections are valid.
+ -- Bit operations with static bit number:
+ if BIW(0)(11 downto 6) = "100000" and BIW(0)(2 downto 0) < "100" then
+ OP_I <= BTST;
+ elsif BIW(0)(11 downto 6) = "100001" and BIW(0)(2 downto 0) < "010" then
+ OP_I <= BCHG;
+ elsif BIW(0)(11 downto 6) = "100010" and BIW(0)(2 downto 0) < "010" then
+ OP_I <= BCLR;
+ elsif BIW(0)(11 downto 6) = "100011" and BIW(0)(2 downto 0) < "010" then
+ OP_I <= BSET;
+ -- Logic operations:
+ elsif BIW(0)(11 downto 8) = x"0" and BIW(0)(7 downto 6) < "11" and BIW(0)(2 downto 0) < "010" then
+ OP_I <= ORI;
+ elsif BIW(0)(11 downto 8) = x"2" and BIW(0)(7 downto 6) < "11" and BIW(0)(2 downto 0) < "010" then
+ OP_I <= ANDI;
+ elsif BIW(0)(11 downto 8) = x"4" and BIW(0)(7 downto 6) < "11" and BIW(0)(2 downto 0) < "010" then
+ OP_I <= SUBI;
+ elsif BIW(0)(11 downto 8) = x"6" and BIW(0)(7 downto 6) < "11" and BIW(0)(2 downto 0) < "010" then
+ OP_I <= ADDI;
+ elsif BIW(0)(11 downto 8) = x"A" and BIW(0)(7 downto 6) < "11" and BIW(0)(2 downto 0) < "010" then
+ OP_I <= EORI;
+ --elsif BIW(0)(11 downto 8) = x"C" and BIW(0)(7 downto 6) < "11" and BIW(0)(2 downto 0) < "010" then -- 68K.
+ elsif BIW(0)(11 downto 8) = x"C" and BIW(0)(7 downto 6) < "11" and BIW(0)(2 downto 0) < "100" then -- 68K+
+ OP_I <= CMPI;
+ -- Bit operations with dynamic bit number:
+ elsif BIW(0)(8 downto 6) = "100" and BIW(0)(2 downto 0) < "101" then
+ OP_I <= BTST;
+ elsif BIW(0)(8 downto 6) = "101" and BIW(0)(2 downto 0) < "010" then
+ OP_I <= BCHG;
+ elsif BIW(0)(8 downto 6) = "110" and BIW(0)(2 downto 0) < "010" then
+ OP_I <= BCLR;
+ elsif BIW(0)(8 downto 6) = "111" and BIW(0)(2 downto 0) < "010" then
+ OP_I <= BSET;
+ end if;
+ when others =>
+ null;
+ end case;
+
+ if BIW(0)(8 downto 6) > "011" and BIW(0)(5 downto 3) = "001" then
+ OP_I <= MOVEP;
+ end if;
+ when x"1" => -- Move BYTE.
+ if BIW(0)(8 downto 6) = "111" and BIW(0)(11 downto 9) < "010"
+ and BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "101" then
+ OP_I <= MOVE;
+ elsif BIW(0)(8 downto 6) = "111" and BIW(0)(11 downto 9) < "010" and BIW(0)(5 downto 3) /= "001" and BIW(0)(5 downto 3) /= "111" then
+ OP_I <= MOVE;
+ elsif BIW(0)(8 downto 6) /= "001" and BIW(0)(8 downto 6) /= "111"
+ and BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "101" then
+ OP_I <= MOVE;
+ elsif BIW(0)(8 downto 6) /= "001" and BIW(0)(8 downto 6) /= "111" and BIW(0)(5 downto 3) /= "001" and BIW(0)(5 downto 3) /= "111" then
+ OP_I <= MOVE;
+ end if;
+ when x"2" | x"3" => -- Move WORD or LONG.
+ if BIW(0)(8 downto 6) = "111" and BIW(0)(11 downto 9) < "010"
+ and BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "101" then
+ OP_I <= MOVE;
+ elsif BIW(0)(8 downto 6) = "111" and BIW(0)(11 downto 9) < "010" and BIW(0)(5 downto 3) /= "111" then
+ OP_I <= MOVE;
+ elsif BIW(0)(8 downto 6) = "001" and BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "101" then
+ OP_I <= MOVEA;
+ elsif BIW(0)(8 downto 6) = "001" and BIW(0)(5 downto 3) /= "111" then
+ OP_I <= MOVEA;
+ elsif BIW(0)(8 downto 6) /= "111" and BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "101" then
+ OP_I <= MOVE;
+ elsif BIW(0)(8 downto 6) /= "111" and BIW(0)(5 downto 3) /= "111" then
+ OP_I <= MOVE;
+ end if;
+ when x"4" => -- Miscellaneous.
+ if BIW(0)(11 downto 0) = x"E70" then
+ OP_I <= RESET;
+ elsif BIW(0)(11 downto 0) = x"E71" then
+ OP_I <= NOP;
+ elsif BIW(0)(11 downto 0) = x"E72" then
+ OP_I <= STOP;
+ elsif BIW(0)(11 downto 0) = x"E73" then
+ OP_I <= RTE;
+ elsif BIW(0)(11 downto 0) = x"E75" then
+ OP_I <= RTS;
+ elsif BIW(0)(11 downto 0) = x"E76" then
+ OP_I <= TRAPV;
+ elsif BIW(0)(11 downto 0) = x"E77" then
+ OP_I <= RTR;
+ elsif BIW(0)(11 downto 0) = x"AFA" then
+ OP_I <= RESERVED;
+ elsif BIW(0)(11 downto 0) = x"AFB" then
+ OP_I <= RESERVED;
+ elsif BIW(0)(11 downto 0) = x"AFC" then
+ OP_I <= ILLEGAL;
+ elsif BIW(0)(11 downto 3) = "100000001" then -- 68K20, 68K30, 68K40
+ OP_I <= LINK; -- LONG.
+ elsif BIW(0)(11 downto 3) = "111001010" then
+ OP_I <= LINK; -- WORD.
+ elsif BIW(0)(11 downto 3) = "111001011" then
+ OP_I <= UNLK;
+ elsif BIW(0)(11 downto 3) = "100001000" then
+ OP_I <= SWAP;
+ elsif BIW(0)(11 downto 4) = x"E4" then
+ OP_I <= TRAP;
+ elsif BIW(0)(11 downto 4) = x"E6" then
+ OP_I <= MOVE_USP;
+ end if;
+
+ case BIW(0)(5 downto 3) is -- Addressing mode.
+ when "000" | "010" | "011" | "100" | "101" | "110" =>
+ if BIW(0)(11 downto 6) = "110001" then
+ if BIW(1)(11) = '1' then
+ OP_I <= DIVS; -- Long.
+ else
+ OP_I <= DIVU; -- Long.
+ end if;
+-- 68010 up stuff:
+-- elsif BIW(0)(11 downto 6) = "001011" then
+-- OP_I <= MOVE_FROM_CCR; -- 68K+ enhancement.
+ elsif BIW(0)(11 downto 6) = "000011" then
+ OP_I <= MOVE_FROM_SR;
+ elsif BIW(0)(11 downto 6) = "010011" then
+ OP_I <= MOVE_TO_CCR;
+ elsif BIW(0)(11 downto 6) = "011011" then
+ OP_I <= MOVE_TO_SR;
+ elsif BIW(0)(11 downto 6) = "110000" then
+ if BIW(1)(11) = '1' then
+ OP_I <= MULS; -- Long.
+ else
+ OP_I <= MULU; -- Long.
+ end if;
+ elsif BIW(0)(11 downto 6) = "100000" then
+ OP_I <= NBCD;
+ elsif BIW(0)(11 downto 6) = "101011" then
+ OP_I <= TAS;
+ end if;
+ when "111" => -- Not all registers are valid for this mode.
+ if BIW(0)(11 downto 6) = "110001" and BIW(0)(2 downto 0) < "101" then
+ if BIW(1)(11) = '1' then
+ OP_I <= DIVS; -- Long.
+ else
+ OP_I <= DIVU; -- Long.
+ end if;
+-- 68010 up stuff:
+-- elsif BIW(0)(11 downto 6) = "001011" and BIW(0)(2 downto 0) < "010" then
+-- OP_I <= MOVE_FROM_CCR; -- 68K+ enhancement.
+ elsif BIW(0)(11 downto 6) = "000011" and BIW(0)(2 downto 0) < "010" then
+ OP_I <= MOVE_FROM_SR;
+ elsif BIW(0)(11 downto 6) = "010011" and BIW(0)(2 downto 0) < "101" then
+ OP_I <= MOVE_TO_CCR;
+ elsif BIW(0)(11 downto 6) = "011011" and BIW(0)(2 downto 0) < "101" then
+ OP_I <= MOVE_TO_SR;
+ elsif BIW(0)(11 downto 6) = "110000" and BIW(0)(2 downto 0) < "101" then
+ if BIW(1)(11) = '1' then
+ OP_I <= MULS; -- Long.
+ else
+ OP_I <= MULU; -- Long.
+ end if;
+ elsif BIW(0)(11 downto 6) = "100000" and BIW(0)(2 downto 0) < "010" then
+ OP_I <= NBCD;
+ elsif BIW(0)(11 downto 6) = "101011" and BIW(0)(2 downto 0) < "010" then
+ OP_I <= TAS;
+ end if;
+ when others =>
+ null;
+ end case;
+
+ case BIW(0)(5 downto 3) is -- Addressing mode.
+ when "010" | "101" | "110" =>
+ if BIW(0)(11 downto 6) = "100001" then
+ OP_I <= PEA;
+ elsif BIW(0)(11 downto 6) = "111010" then
+ OP_I <= JSR;
+ elsif BIW(0)(11 downto 6) = "111011" then
+ OP_I <= JMP;
+ end if;
+ when "111" => -- Not all registers are valid for this mode.
+ if BIW(0)(11 downto 6) = "100001" and BIW(0)(2 downto 0) < "100" then
+ OP_I <= PEA;
+ elsif BIW(0)(11 downto 6) = "111010" and BIW(0)(2 downto 0) < "100" then
+ OP_I <= JSR;
+ elsif BIW(0)(11 downto 6) = "111011" and BIW(0)(2 downto 0) < "100" then
+ OP_I <= JMP;
+ end if;
+ when others =>
+ null;
+ end case;
+
+ -- For the following operation codes a SIZE (BIW(0)(7 downto 6)) is not valid.
+ -- For the following operation codes an addressing mode x"001" is not valid.
+ if BIW(0)(7 downto 6) < "11" and BIW(0)(5 downto 3) /= "001" and BIW(0)(5 downto 3) /= "111" then
+ case BIW(0)(11 downto 8) is
+ when x"0" => OP_I <= NEGX;
+ when x"2" => OP_I <= CLR;
+ when x"4" => OP_I <= NEG;
+ when x"6" => OP_I <= NOT_B;
+ when others => null;
+ end case;
+ -- Not all registers are valid for the addressing mode "111":
+ elsif BIW(0)(7 downto 6) < "11" and BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "010" then
+ case BIW(0)(11 downto 8) is
+ when x"0" => OP_I <= NEGX;
+ when x"2" => OP_I <= CLR;
+ when x"4" => OP_I <= NEG;
+ when x"6" => OP_I <= NOT_B;
+ when others => null;
+ end case;
+ end if;
+
+ -- if BIW(0)(11 downto 8) = x"A" and BIW(0)(7 downto 6) < "11" and BIW(0)(5 downto 3) = "111" and (BIW(0)(2 downto 0) < "010" or BIW(0)(2 downto 0) = "100") then -- 68K
+ if BIW(0)(11 downto 8) = x"A" and BIW(0)(7 downto 6) < "11" and BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "101" then -- 68K+
+ case BIW(0)(7 downto 6) is
+ when "01" | "10" => OP_I <= TST; -- Long or word, all addressing modes.
+ when others => -- Byte: Address register direct not allowed.
+ if BIW(0)(2 downto 0) /= "100" then
+ OP_I <= TST;
+ end if;
+ end case;
+ elsif BIW(0)(11 downto 8) = x"A" and BIW(0)(7 downto 6) < "11" and BIW(0)(5 downto 3) /= "111" then
+ case BIW(0)(7 downto 6) is
+ when "01" | "10" => OP_I <= TST; -- Long or word, all addressing modes.
+ when others => -- Byte: Address register direct not allowed.
+ if BIW(0)(5 downto 3) /= "001" then
+ OP_I <= TST;
+ end if;
+ end case;
+ end if;
+
+ if BIW(0)(11 downto 9) = "100" and BIW(0)(5 downto 3) = "000" then
+ case BIW(0)(8 downto 6) is -- Valid OPMODES for this operation code.
+ when "010" | "011" => OP_I <= EXTW;
+ when others => null;
+ end case;
+ end if;
+
+ if BIW(0)(8 downto 6) = "111" then
+ case BIW(0)(5 downto 3) is -- OPMODES.
+ when "010" | "101" | "110" =>
+ OP_I <= LEA;
+ when "111" =>
+ if BIW(0)(2 downto 0) < "100" then -- Not all registers are valid for this OPMODE.
+ OP_I <= LEA;
+ end if;
+ when others => null;
+ end case;
+ end if;
+
+ if BIW(0)(11) = '1' and BIW(0)(9 downto 7) = "001" then
+ if BIW(0)(10) = '0' then -- Register to memory transfer.
+ case BIW(0)(5 downto 3) is -- OPMODES, no postincrement addressing.
+ when "010" | "100" | "101" | "110" =>
+ OP_I <= MOVEM;
+ when "111" =>
+ if BIW(0)(2 downto 0) = "000" or BIW(0)(2 downto 0) = "001" then
+ OP_I <= MOVEM;
+ end if;
+ when others => null;
+ end case;
+ else -- Memory to register transfer, no predecrement addressing.
+ case BIW(0)(5 downto 3) is -- OPMODES.
+ when "010" | "011" | "101" | "110" =>
+ OP_I <= MOVEM;
+ when "111" =>
+ if BIW(0)(2 downto 0) < "100" then
+ OP_I <= MOVEM;
+ end if;
+ when others => null;
+ end case;
+ end if;
+ end if;
+ -- The size must be "10" or "11" and the OPMODE may not be "001".
+ if BIW(0)(8 downto 7) >= "10" and BIW(0)(6 downto 3) = x"7" and BIW(0)(2 downto 0) < "101" then
+ OP_I <= CHK;
+ elsif BIW(0)(8 downto 7) >= "10" and BIW(0)(6 downto 3) /= x"1" and BIW(0)(6 downto 3) < x"7" then
+ OP_I <= CHK;
+ end if;
+ when x"5" => -- ADDQ / SUBQ / Scc / DBcc.
+ if BIW(0)(7 downto 3) = "11001" then
+ OP_I <= DBcc;
+ elsif BIW(0)(7 downto 6) = "11" and BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "010" then
+ OP_I <= Scc;
+ elsif BIW(0)(7 downto 6) = "11" and BIW(0)(5 downto 3) /= "001" and BIW(0)(5 downto 3) /= "111" then
+ OP_I <= Scc;
+ --
+ elsif BIW(0)(8) = '0' and BIW(0)(7 downto 6) < "11" and BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "010" then
+ OP_I <= ADDQ;
+ elsif BIW(0)(8) = '0' and (BIW(0)(7 downto 6) = "01" or BIW(0)(7 downto 6) = "10") and BIW(0)(5 downto 3) /= "111" then
+ OP_I <= ADDQ;
+ elsif BIW(0)(8) = '0' and BIW(0)(7 downto 6) = "00" and BIW(0)(5 downto 3) /= "001" and BIW(0)(5 downto 3) /= "111" then
+ OP_I <= ADDQ;
+ --
+ elsif BIW(0)(8) = '1' and BIW(0)(7 downto 6) < "11" and BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "010" then
+ OP_I <= SUBQ;
+ elsif BIW(0)(8) = '1' and (BIW(0)(7 downto 6) = "01" or BIW(0)(7 downto 6) = "10") and BIW(0)(5 downto 3) /= "111" then
+ OP_I <= SUBQ;
+ elsif BIW(0)(8) = '1' and BIW(0)(7 downto 6) = "00" and BIW(0)(5 downto 3) /= "001" and BIW(0)(5 downto 3) /= "111" then
+ OP_I <= SUBQ;
+ end if;
+ when x"6" => -- Bcc / BSR / BRA.
+ if BIW(0)(11 downto 8) = x"0" then
+ OP_I <= BRA;
+ elsif BIW(0)(11 downto 8) = x"1" then
+ OP_I <= BSR;
+ else
+ OP_I <= Bcc;
+ end if;
+ when x"7" => -- MOVEQ.
+ if BIW(0)(8) = '0' then
+ OP_I <= MOVEQ;
+ end if;
+ when x"8" => -- OR / DIV / SBCD.
+ if BIW(0)(8 downto 6) = "011" and BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "101" then
+ OP_I <= DIVU; -- WORD.
+ elsif BIW(0)(8 downto 6) = "011" and BIW(0)(5 downto 3) /= "001" and BIW(0)(5 downto 3) /= "111" then
+ OP_I <= DIVU; -- WORD.
+ elsif BIW(0)(8 downto 6) = "111" and BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "101" then
+ OP_I <= DIVS; -- WORD.
+ elsif BIW(0)(8 downto 6) = "111" and BIW(0)(5 downto 3) /= "001" and BIW(0)(5 downto 3) /= "111" then
+ OP_I <= DIVS; -- WORD.
+ elsif BIW(0)(8 downto 4) = "10000" then
+ OP_I <= SBCD;
+ end if;
+
+ case BIW(0)(8 downto 6) is
+ when "000" | "001" | "010" =>
+ if BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "101" then
+ OP_I <= OR_B;
+ elsif BIW(0)(5 downto 3) /= "001" and BIW(0)(5 downto 3) /= "111" then
+ OP_I <= OR_B;
+ end if;
+ when "100" | "101" | "110" =>
+ if BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "010" then
+ OP_I <= OR_B;
+ elsif BIW(0)(5 downto 3) > "001" and BIW(0)(5 downto 3) /= "111" then
+ OP_I <= OR_B;
+ end if;
+ when others =>
+ null;
+ end case;
+ when x"9" => -- SUB / SUBX.
+ case BIW(0)(8 downto 6) is
+ when "000" =>
+ if BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "101" then
+ OP_I <= SUB;
+ elsif BIW(0)(5 downto 3) /= "111" and BIW(0)(5 downto 3) /= "001" then
+ OP_I <= SUB;
+ end if;
+ when "001" | "010" =>
+ if BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "101" then
+ OP_I <= SUB;
+ elsif BIW(0)(5 downto 3) /= "111" then
+ OP_I <= SUB;
+ end if;
+ when "100" =>
+ if BIW(0)(5 downto 3) = "000" or BIW(0)(5 downto 3) = "001" then
+ OP_I <= SUBX;
+ elsif BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "010" then
+ OP_I <= SUB;
+ elsif BIW(0)(5 downto 3) /= "111" and BIW(0)(5 downto 3) /= "001" then
+ OP_I <= SUB;
+ end if;
+ when "101" | "110" =>
+ if BIW(0)(5 downto 3) = "000" or BIW(0)(5 downto 3) = "001" then
+ OP_I <= SUBX;
+ elsif BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "010" then
+ OP_I <= SUB;
+ elsif BIW(0)(5 downto 3) /= "111" then
+ OP_I <= SUB;
+ end if;
+ when "011" | "111" =>
+ if BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "101" then
+ OP_I <= SUBA;
+ elsif BIW(0)(5 downto 3) /= "111" then
+ OP_I <= SUBA;
+ end if;
+ when others => -- U, X, Z, W, H, L, -.
+ null;
+ end case;
+ when x"A" => -- (1010, Unassigned, Reserved).
+ OP_I <= UNIMPLEMENTED; -- Dummy.
+ when x"B" => -- CMP / EOR.
+ if BIW(0)(8) = '1' and BIW(0)(7 downto 6) < "11" and BIW(0)(5 downto 3) = "001" then
+ OP_I <= CMPM;
+ else
+ case BIW(0)(8 downto 6) is -- OPMODE field.
+ when "000" =>
+ if BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "101" then
+ OP_I <= CMP;
+ elsif BIW(0)(5 downto 3) /= "001" and BIW(0)(5 downto 3) /= "111" then
+ OP_I <= CMP;
+ end if;
+ when "001" | "010" =>
+ if BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "101" then
+ OP_I <= CMP;
+ elsif BIW(0)(5 downto 3) /= "111" then
+ OP_I <= CMP;
+ end if;
+ when "011" | "111" =>
+ if BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "101" then
+ OP_I <= CMPA;
+ elsif BIW(0)(5 downto 3) /= "111" then
+ OP_I <= CMPA;
+ end if;
+ when "100" | "101" | "110" =>
+ if BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "101" then
+ OP_I <= EOR;
+ elsif BIW(0)(5 downto 3) /= "001" and BIW(0)(5 downto 3) /= "111" then
+ OP_I <= EOR;
+ end if;
+ when others => -- U, X, Z, W, H, L, -.
+ null;
+ end case;
+ end if;
+ when x"C" => -- AND / MUL / ABCD / EXG.
+ if BIW(0)(8 downto 4) = "10000" then
+ OP_I <= ABCD;
+ elsif BIW(0)(8 downto 6) = "011" and BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "101" then
+ OP_I <= MULU; -- WORD.
+ elsif BIW(0)(8 downto 6) = "011" and BIW(0)(5 downto 3) /= "001" and BIW(0)(5 downto 3) /= "111" then
+ OP_I <= MULU; -- WORD.
+ elsif BIW(0)(8 downto 6) = "111" and BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "101" then
+ OP_I <= MULS; -- WORD.
+ elsif BIW(0)(8 downto 6) = "111" and BIW(0)(5 downto 3) /= "001" and BIW(0)(5 downto 3) /= "111" then
+ OP_I <= MULS; -- WORD.
+ elsif BIW(0)(8 downto 3) = "101000" or BIW(0)(8 downto 3) = "101001" or BIW(0)(8 downto 3) = "110001" then
+ OP_I <= EXG;
+ else
+ case BIW(0)(8 downto 6) is -- OPMODE
+ when "000" | "001" | "010" =>
+ if BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "101" then
+ OP_I <= AND_B;
+ elsif BIW(0)(5 downto 3) /= "001" and BIW(0)(5 downto 3) /= "111" then
+ OP_I <= AND_B;
+ end if;
+ when "100" | "101" | "110" =>
+ if BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "010" then
+ OP_I <= AND_B;
+ elsif BIW(0)(5 downto 3) > "001" and BIW(0)(5 downto 3) /= "111" then
+ OP_I <= AND_B;
+ end if;
+ when others =>
+ null;
+ end case;
+ end if;
+ when x"D" => -- ADD / ADDX.
+ case BIW(0)(8 downto 6) is
+ when "000" =>
+ if BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "101" then
+ OP_I <= ADD;
+ elsif BIW(0)(5 downto 3) /= "111" and BIW(0)(5 downto 3) /= "001" then
+ OP_I <= ADD;
+ end if;
+ when "001" | "010" =>
+ if BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "101" then
+ OP_I <= ADD;
+ elsif BIW(0)(5 downto 3) /= "111" then
+ OP_I <= ADD;
+ end if;
+ when "100" =>
+ if BIW(0)(5 downto 3) = "000" or BIW(0)(5 downto 3) = "001" then
+ OP_I <= ADDX;
+ elsif BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "010" then
+ OP_I <= ADD;
+ elsif BIW(0)(5 downto 3) /= "111" and BIW(0)(5 downto 3) /= "001" then
+ OP_I <= ADD;
+ end if;
+ when "101" | "110" =>
+ if BIW(0)(5 downto 3) = "000" or BIW(0)(5 downto 3) = "001" then
+ OP_I <= ADDX;
+ elsif BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "010" then
+ OP_I <= ADD;
+ elsif BIW(0)(5 downto 3) /= "111" then
+ OP_I <= ADD;
+ end if;
+ when "011" | "111" =>
+ if BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "101" then
+ OP_I <= ADDA;
+ elsif BIW(0)(5 downto 3) /= "111" then
+ OP_I <= ADDA;
+ end if;
+ when others => -- U, X, Z, W, H, L, -.
+ null;
+ end case;
+ when x"E" => -- Shift / Rotate / Bit Field.
+ if BIW(0)(11 downto 6) = "000011" and BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "010" then
+ OP_I <= ASR; -- Memory shifts.
+ elsif BIW(0)(11 downto 6) = "000011" and BIW(0)(5 downto 3) > "001" and BIW(0)(5 downto 3) /= "111" then
+ OP_I <= ASR; -- Memory shifts.
+ elsif BIW(0)(11 downto 6) = "000111" and BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "010" then
+ OP_I <= ASL; -- Memory shifts.
+ elsif BIW(0)(11 downto 6) = "000111" and BIW(0)(5 downto 3) > "001" and BIW(0)(5 downto 3) /= "111" then
+ OP_I <= ASL; -- Memory shifts.
+ elsif BIW(0)(11 downto 6) = "001011" and BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "010" then
+ OP_I <= LSR; -- Memory shifts.
+ elsif BIW(0)(11 downto 6) = "001011" and BIW(0)(5 downto 3) > "001" and BIW(0)(5 downto 3) /= "111" then
+ OP_I <= LSR; -- Memory shifts.
+ elsif BIW(0)(11 downto 6) = "001111" and BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "010" then
+ OP_I <= LSL; -- Memory shifts.
+ elsif BIW(0)(11 downto 6) = "001111" and BIW(0)(5 downto 3) > "001" and BIW(0)(5 downto 3) /= "111" then
+ OP_I <= LSL; -- Memory shifts.
+ elsif BIW(0)(11 downto 6) = "010011" and BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "010" then
+ OP_I <= ROXR; -- Memory shifts.
+ elsif BIW(0)(11 downto 6) = "010011" and BIW(0)(5 downto 3) > "001" and BIW(0)(5 downto 3) /= "111" then
+ OP_I <= ROXR; -- Memory shifts.
+ elsif BIW(0)(11 downto 6) = "010111" and BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "010" then
+ OP_I <= ROXL; -- Memory shifts.
+ elsif BIW(0)(11 downto 6) = "010111" and BIW(0)(5 downto 3) > "001" and BIW(0)(5 downto 3) /= "111" then
+ OP_I <= ROXL; -- Memory shifts.
+ elsif BIW(0)(11 downto 6) = "011011" and BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "010" then
+ OP_I <= ROTR; -- Memory shifts.
+ elsif BIW(0)(11 downto 6) = "011011" and BIW(0)(5 downto 3) > "001" and BIW(0)(5 downto 3) /= "111" then
+ OP_I <= ROTR; -- Memory shifts.
+ elsif BIW(0)(11 downto 6) = "011111" and BIW(0)(5 downto 3) = "111" and BIW(0)(2 downto 0) < "010" then
+ OP_I <= ROTL; -- Memory shifts.
+ elsif BIW(0)(11 downto 6) = "011111" and BIW(0)(5 downto 3) > "001" and BIW(0)(5 downto 3) /= "111" then
+ OP_I <= ROTL; -- Memory shifts.
+ elsif BIW(0)(8) = '0' and BIW(0)(7 downto 6) < "11" and BIW(0)(4 downto 3) = "00" then
+ OP_I <= ASR; -- Register shifts.
+ elsif BIW(0)(8) = '1' and BIW(0)(7 downto 6) < "11" and BIW(0)(4 downto 3) = "00" then
+ OP_I <= ASL; -- Register shifts.
+ elsif BIW(0)(8) = '0' and BIW(0)(7 downto 6) < "11" and BIW(0)(4 downto 3) = "01" then
+ OP_I <= LSR; -- Register shifts.
+ elsif BIW(0)(8) = '1' and BIW(0)(7 downto 6) < "11" and BIW(0)(4 downto 3) = "01" then
+ OP_I <= LSL; -- Register shifts.
+ elsif BIW(0)(8) = '0' and BIW(0)(7 downto 6) < "11" and BIW(0)(4 downto 3) = "10" then
+ OP_I <= ROXR; -- Register shifts.
+ elsif BIW(0)(8) = '1' and BIW(0)(7 downto 6) < "11" and BIW(0)(4 downto 3) = "10" then
+ OP_I <= ROXL; -- Register shifts.
+ elsif BIW(0)(8) = '0' and BIW(0)(7 downto 6) < "11" and BIW(0)(4 downto 3) = "11" then
+ OP_I <= ROTR; -- Register shifts.
+ elsif BIW(0)(8) = '1' and BIW(0)(7 downto 6) < "11" and BIW(0)(4 downto 3) = "11" then
+ OP_I <= ROTL; -- Register shifts.
+ end if;
+ when x"F" => -- 1111, Coprocessor Interface / 68K40 Extensions.
+ OP_I <= UNIMPLEMENTED; -- Dummy.
+ when others => -- U, X, Z, W, H, L, -.
+ null;
+ end case;
+ end process OP_DECODE;
+end BEHAVIOR;
diff --git a/common/CPU/68000/wf_68k00_ip/wf68k00ip_pkg.vhd b/common/CPU/68000/wf_68k00_ip/wf68k00ip_pkg.vhd
new file mode 100644
index 00000000..e99e3900
--- /dev/null
+++ b/common/CPU/68000/wf_68k00_ip/wf68k00ip_pkg.vhd
@@ -0,0 +1,448 @@
+----------------------------------------------------------------------
+---- ----
+---- MC68000 compatible IP Core ----
+---- ----
+---- This file is part of the SUSKA ATARI clone project. ----
+---- http://www.experiment-s.de ----
+---- ----
+---- Description: ----
+---- This model provides an opcode and bus timing compatible ip ----
+---- core compared to Motorola's MC68000 microprocessor. ----
+---- ----
+---- This file is the package file of the ip core. ----
+---- ----
+---- ----
+---- ----
+---- ----
+---- Author(s): ----
+---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
+---- ----
+---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
+---- ----
+---- This source file 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 2 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, write to the Free ----
+---- Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ----
+---- Boston, MA 02110-1301, USA. ----
+---- ----
+----------------------------------------------------------------------
+--
+-- Revision History
+--
+-- Revision 2K6B 2006/12/24 WF
+-- Initial Release.
+-- Revision 2K7A 2007/05/31 WF
+-- Updated all modules.
+-- Revision 2K8A 2008/07/14 WF
+-- See the 68K00 top level file.
+--
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+package WF68K00IP_PKG is
+type EXWORDTYPE is array(0 to 1) of std_logic_vector(15 downto 0);
+type OP_SIZETYPE is (LONG, WORD, BYTE); -- Default is Byte.
+type D_SIZETYPE is (LONG, WORD, BYTE); -- Displacement size.
+-- The OPCODES AND, NOT, OR, ROR and ROL are defined keywords in VHDL. Therefore the assignment is
+-- AND_B, NOT_B, OR_B, ROTR and ROTL.
+type OP_68K00 is (ABCD, ADD, ADDA, ADDI, ADDQ, ADDX, AND_B, ANDI, ANDI_TO_CCR, ANDI_TO_SR, ASL, ASR, Bcc, BCHG, BCLR,
+ BRA, BSET, BSR, BTST, CHK, CLR, CMP, CMPA, CMPI, CMPM, DBcc, DIVS, DIVU, EOR, EORI, EORI_TO_CCR,
+ EORI_TO_SR, EXG, EXTW, ILLEGAL, JMP, JSR, LEA, LINK, LSL, LSR, MOVE, MOVEA, MOVE_FROM_CCR, MOVE_TO_CCR,
+ MOVE_FROM_SR, MOVE_TO_SR, MOVE_USP, MOVEM, MOVEP, MOVEQ, MULS, MULU, NBCD, NEG, NEGX, NOP, NOT_B,
+ OR_B, ORI, ORI_TO_CCR, ORI_TO_SR, PEA, RESET, ROTL, ROTR, ROXL, ROXR, RTE, RTR, RTS, SBCD, Scc, STOP,
+ SUB, SUBA, SUBI, SUBQ, SUBX, SWAP, TAS, TRAP, TRAPV, TST, UNLK, RESERVED, UNIMPLEMENTED);
+
+component WF68K00IP_CONTROL
+ port (
+ CLK : in bit;
+ RESETn : in bit;
+ SR_CCR_IN : in std_logic_vector(15 downto 0);
+ C_CODE : in bit_vector(3 downto 0);
+ REGLISTMASK : in std_logic_vector(15 downto 0);
+ CTRL_EN : in bit;
+ EXEC_ABORT : in bit;
+ DATA_VALID : in bit;
+ BUS_CYC_RDY : in bit;
+ CTRL_RDY : out bit;
+ INIT_STATUS : in bit;
+ PRESET_IRQ_MASK : in bit;
+ IRQ : in std_logic_vector(2 downto 0);
+ IRQ_SAVE : in bit;
+ XNZVC_IN : in std_logic_vector(4 downto 0);
+ STATUS_REG_OUT : out std_logic_vector(15 downto 0);
+ FORCE_BIW2 : in bit;
+ FORCE_BIW3 : in bit;
+ EXT_CNT : in integer range 0 to 2;
+ DEST_EXT_CNT : in integer range 0 to 2;
+ REGSEL_20 : in std_logic_vector(2 downto 0);
+ IW_ADR : out integer range 0 to 2;
+ IW_WR : out bit;
+ SRC_DESTn : out bit;
+ EW_WR : out bit;
+ EW_ADR : out integer range 0 to 1;
+ RD_BUS : out bit;
+ WR_BUS : out bit;
+ RDWR_BUS : out bit;
+ WR_HI : out bit;
+ SEL_A_HI : out bit;
+ SEL_A_MIDHI : out bit;
+ SEL_A_MIDLO : out bit;
+ SEL_A_LO : out bit;
+ SEL_BUFF_A_LO : out bit;
+ SEL_BUFF_A_HI : out bit;
+ SEL_BUFF_B_LO : out bit;
+ SEL_BUFF_B_HI : out bit;
+ FC_OUT : out std_logic_vector(2 downto 0);
+ FC_EN : out bit;
+ PC_INIT : out bit;
+ PC_WR : out bit;
+ PC_INC : out bit;
+ PC_TMP_CLR : out bit;
+ PC_TMP_INC : out bit;
+ PC_ADD_DISPL : out bit;
+ USP_INC : out bit;
+ SSP_INC : out bit;
+ USP_DEC : out bit;
+ SSP_DEC : out bit;
+ USP_CPY : out bit;
+ SP_ADD_DISPL : out bit;
+ ADR_TMP_CLR : out bit;
+ ADR_TMP_INC : out bit;
+ AR_INC : out bit;
+ AR_DEC : out bit;
+ AR_WR : out bit;
+ AR_DR_EXG : out bit;
+ DR_WR : out bit;
+ DR_DEC : out bit;
+ SCAN_TRAPS : out bit;
+ TRAP_PRIV : in bit;
+ TRAP_TRACE : out bit;
+ OP : in OP_68K00;
+ OP_MODE : in std_logic_vector(2 downto 0);
+ OP_SIZE : in OP_SIZETYPE;
+ ADR_MODE : in std_logic_vector(2 downto 0);
+ MOVE_D_AM : in std_logic_vector(2 downto 0);
+ RESET_RDY : in bit;
+ OP_BUSY : in bit;
+ MEM_SHFT : in bit;
+ SHFT_BUSY : in bit;
+ DR : in bit;
+ RM : in bit;
+ DIV_MUL_32n64 : in bit;
+ EXEC_RESUME : in bit;
+ DBcc_COND : in boolean;
+ USE_SP_ADR : out bit;
+ OP_START : out bit;
+ TRAP_CHK_EN : out bit;
+ MOVEM_REGSEL : out std_logic_vector(2 downto 0);
+ MOVEM_ADn : out bit;
+ Scc_COND : out boolean;
+ SHIFTER_LOAD : out bit;
+ CHK_PC : out bit;
+ CHK_ADR : out bit;
+ SBIT : out bit;
+ UNLK_SP_An : out bit;
+ RESET_EN : out bit
+ );
+end component;
+
+component WF68K00IP_OPCODE_DECODER
+ port (
+ CLK : in bit;
+ RESETn : in bit;
+ DATA_IN : in std_logic_vector(15 downto 0);
+ SBIT : in bit;
+ OV : in std_logic;
+ IW_ADR : in integer range 0 to 2;
+ IW_WR : in bit;
+ FORCE_BIW2 : out bit;
+ FORCE_BIW3 : out bit;
+ EXT_CNT : out integer range 0 to 2;
+ DEST_EXT_CNT : out integer range 0 to 2;
+ DR : out bit;
+ RM : out bit;
+ IR : out bit;
+ OP : out OP_68K00;
+ OP_SIZE : out OP_SIZETYPE;
+ OP_MODE : out std_logic_vector(4 downto 0);
+ BIW_0 : out std_logic_vector(15 downto 0);
+ REGSEL_20 : out std_logic_vector(2 downto 0);
+ REGSEL_119 : out std_logic_vector(2 downto 0);
+ REGSEL_INDEX : out std_logic_vector(2 downto 0);
+ DATA_IMMEDIATE : out std_logic_vector(31 downto 0);
+ TRAP_VECTOR : out std_logic_vector(3 downto 0);
+ C_CODE : out bit_vector(3 downto 0);
+ MEM_SHFT : out bit;
+ REGLISTMASK : out std_logic_vector(15 downto 0);
+ BITPOS_IM : out bit;
+ BIT_POS : out std_logic_vector(4 downto 0);
+ DIV_MUL_32n64 : out bit;
+ REG_Dlq : out std_logic_vector(2 downto 0);
+ REG_Dhr : out std_logic_vector(2 downto 0);
+ SCAN_TRAPS : in bit;
+ TRAP_ILLEGAL : out bit;
+ TRAP_1010 : out bit;
+ TRAP_1111 : out bit;
+ TRAP_PRIV : out bit;
+ TRAP_OP : out bit;
+ TRAP_V : out bit;
+ EW_WR : in bit;
+ EW_ADR : in integer range 0 to 1;
+ SRC_DESTn : in bit;
+ EXWORD : out EXWORDTYPE;
+ DEST_EXWORD : out EXWORDTYPE;
+ ADR_MODE : out std_logic_vector(2 downto 0);
+ MOVE_D_AM : out std_logic_vector(2 downto 0);
+ EXT_DSIZE : out D_SIZETYPE;
+ SEL_DISPLACE_BIW : out bit;
+ DISPLACE_BIW : out std_logic_vector(31 downto 0)
+ );
+end component;
+
+component WF68K00IP_ADDRESS_REGISTERS
+ port (
+ CLK : in bit;
+ RESETn : in bit;
+ ADATA_IN : in std_logic_vector(31 downto 0);
+ REGSEL_B : in std_logic_vector(2 downto 0);
+ REGSEL_A : in std_logic_vector(2 downto 0);
+ ADR_REG_QB : out std_logic_vector(31 downto 0);
+ ADR_REG_QA : out std_logic_vector(31 downto 0);
+ USP_OUT : out std_logic_vector(31 downto 0);
+ SSP_OUT : out std_logic_vector(31 downto 0);
+ PC_OUT : out std_logic_vector(31 downto 0);
+ EXWORD : in EXWORDTYPE;
+ DEST_EXWORD : in EXWORDTYPE;
+ DR : in bit;
+ USP_CPY : in bit;
+ AR_EXG : in bit;
+ AR_WR : in bit;
+ USP_INC : in bit;
+ USP_DEC : in bit;
+ ADR_TMP_CLR : in bit;
+ ADR_TMP_INC : in bit;
+ AR_INC : in bit;
+ AR_DEC : in bit;
+ SSP_INC : in bit;
+ SSP_DEC : in bit;
+ SSP_INIT : in bit;
+ SP_ADD_DISPL : in bit;
+ USE_SP_ADR : in bit;
+ USE_SSP_ADR : in bit;
+ PC_WR : in bit;
+ PC_INC : in bit;
+ PC_TMP_CLR : in bit;
+ PC_TMP_INC : in bit;
+ PC_INIT : in bit;
+ PC_ADD_DISPL : in bit;
+ SRC_DESTn : in bit;
+ SBIT : in bit;
+ OP : in OP_68K00;
+ OP_SIZE : in OP_SIZETYPE;
+ OP_MODE : in std_logic_vector(4 downto 0);
+ OP_START : in bit;
+ ADR_MODE : in std_logic_vector(2 downto 0);
+ MOVE_D_AM : in std_logic_vector(2 downto 0);
+ FORCE_BIW2 : in bit;
+ FORCE_BIW3 : in bit;
+ EXT_DSIZE : in D_SIZETYPE;
+ SEL_DISPLACE_BIW : in bit;
+ DISPLACE_BIW : in std_logic_vector(31 downto 0);
+ REGSEL_INDEX : in std_logic_vector(2 downto 0);
+ INDEX_D_IN : in std_logic_vector(31 downto 0);
+ CHK_PC : in bit;
+ CHK_ADR : in bit;
+ TRAP_AERR : out bit;
+ ADR_EFF : out std_logic_vector(31 downto 0)
+ );
+end component;
+
+component WF68K00IP_DATA_REGISTERS
+ port (
+ CLK : in bit;
+ RESETn : in bit;
+ DATA_IN_A : in std_logic_vector(31 downto 0);
+ DATA_IN_B : in std_logic_vector(31 downto 0);
+ REGSEL_A : in std_logic_vector(2 downto 0);
+ REGSEL_B : in std_logic_vector(2 downto 0);
+ REGSEL_C : in std_logic_vector(2 downto 0);
+ DIV_MUL_32n64 : in bit;
+ DATA_OUT_A : out std_logic_vector(31 downto 0);
+ DATA_OUT_B : out std_logic_vector(31 downto 0);
+ DATA_OUT_C : out std_logic_vector(31 downto 0);
+ DR_EXG : in bit;
+ DR_DEC : in bit;
+ DR_WR : in bit;
+ OP : in OP_68K00;
+ OP_SIZE : in OP_SIZETYPE;
+ OP_MODE : in std_logic_vector(4 downto 0);
+ DBcc_COND : out boolean
+ );
+end component;
+
+component WF68K00IP_ALU
+ port (
+ RESETn : in bit;
+ CLK : in bit;
+ ADR_MODE : in std_logic_vector(2 downto 0);
+ OP_SIZE : in OP_SIZETYPE;
+ OP : in OP_68K00;
+ XNZVC_IN : in std_logic_vector(4 downto 0);
+ XNZVC_OUT : out std_logic_vector(4 downto 0);
+ OP_IN_S : in std_logic_vector(31 downto 0);
+ OP_IN_D_HI : in std_logic_vector(31 downto 0);
+ OP_IN_D_LO : in std_logic_vector(31 downto 0);
+ RESULT_HI : out std_logic_vector(31 downto 0);
+ RESULT_LO : out std_logic_vector(31 downto 0);
+ OP_START : in bit;
+ TRAP_CHK_EN : in bit;
+ DIV_MUL_32n64 : in bit;
+ OP_BUSY : out bit;
+ TRAP_CHK : out bit;
+ TRAP_DIVZERO : out bit
+ );
+end component;
+
+component WF68K00IP_SHIFTER
+ port (
+ CLK : in bit;
+ RESETn : in bit;
+ DATA_IN : in std_logic_vector(31 downto 0);
+ DATA_OUT : out std_logic_vector(31 downto 0);
+ OP : in OP_68K00;
+ OP_SIZE : in OP_SIZETYPE;
+ BIT_POS : in std_logic_vector(4 downto 0);
+ CNT_NR : in std_logic_vector(5 downto 0);
+ SHFT_BREAKn : in bit;
+ SHIFTER_LOAD : in bit;
+ SHFT_BUSY : out bit;
+ XNZVC_IN : in std_logic_vector(4 downto 0);
+ XNZVC_OUT : out std_logic_vector(4 downto 0)
+ );
+end component;
+
+component WF68K00IP_INTERRUPT_CONTROL
+ port (
+ CLK : in bit;
+ RESETn : in bit;
+ RESET_CPUn : in bit;
+ BERR : in bit;
+ HALTn : in std_logic;
+ ADR_IN : in std_logic_vector(31 downto 0);
+ USE_SSP_ADR : out bit;
+ ADR_EN_VECTOR : out bit;
+ DATA_IN : in std_logic_vector(7 downto 0);
+ DATA_OUT : out std_logic_vector(15 downto 0);
+ DATA_EN : out bit;
+ RWn : in bit_vector(0 downto 0);
+ RD_BUS : out bit;
+ WR_BUS : out bit;
+ HALT_EN : out bit;
+ FC_IN : in std_logic_vector(2 downto 0);
+ FC_OUT : out std_logic_vector(2 downto 0);
+ FC_EN : out bit;
+ SEL_BUFF_A_LO : out bit;
+ SEL_BUFF_A_HI : out bit;
+ STATUS_REG_IN : in std_logic_vector(15 downto 0);
+ PC : in std_logic_vector(31 downto 0);
+ INIT_STATUS : out bit;
+ PRESET_IRQ_MASK : out bit;
+ SSP_DEC : out bit;
+ SSP_INIT : out bit;
+ PC_INIT : out bit;
+ BIW_0 : in std_logic_vector(15 downto 0);
+ BUS_CYC_RDY : in bit;
+ CTRL_RDY : in bit;
+ CTRL_EN : out bit;
+ EXEC_ABORT : out bit;
+ EXEC_RESUME : out bit;
+ IRQ : in std_logic_vector(2 downto 0);
+ AVECn : in bit;
+ IRQ_SAVE : out bit;
+ INT_VECT : out std_logic_vector(9 downto 0);
+ USE_INT_VECT : out bit;
+ TRAP_AERR : in bit;
+ TRAP_OP : in bit;
+ TRAP_VECTOR : in std_logic_vector(3 downto 0);
+ TRAP_V : in bit;
+ TRAP_CHK : in bit;
+ TRAP_DIVZERO : in bit;
+ TRAP_ILLEGAL : in bit;
+ TRAP_1010 : in bit;
+ TRAP_1111 : in bit;
+ TRAP_TRACE : in bit;
+ TRAP_PRIV : in bit
+ );
+end component;
+
+component WF68K00IP_BUS_INTERFACE
+ port (
+ CLK : in bit;
+ RESETn : in bit;
+ RESET_INn : in bit;
+ RESET_OUT_EN : out bit;
+ RESET_CPUn : out bit;
+ RESET_EN : in bit;
+ RESET_RDY : out bit;
+ DATA_IN : in std_logic_vector(15 downto 0);
+ SEL_A_HI : in bit;
+ SEL_A_MIDHI : in bit;
+ SEL_A_MIDLO : in bit;
+ SEL_A_LO : in bit;
+ SEL_BUFF_A_LO : in bit;
+ SEL_BUFF_A_HI : in bit;
+ SEL_BUFF_B_LO : in bit;
+ SEL_BUFF_B_HI : in bit;
+ SYS_INIT : in bit;
+ OP_SIZE : in OP_SIZETYPE;
+ BUFFER_A : out std_logic_vector(31 downto 0);
+ BUFFER_B : out std_logic_vector(31 downto 0);
+ DATA_CORE_OUT : out std_logic_vector(15 downto 0);
+ RD_BUS : in bit;
+ WR_BUS : in bit;
+ RDWR_BUS : in bit;
+ A0 : in std_logic;
+ BYTEn_WORD : in bit;
+ EXEC_ABORT : in bit;
+ BUS_CYC_RDY : out bit;
+ DATA_VALID : out bit;
+ DTACKn : in bit;
+ BERRn : in bit;
+ AVECn : in bit;
+ HALTn : in std_logic;
+ ADR_EN : out bit;
+ WR_HI : in bit;
+ HI_WORD_EN : out bit;
+ HI_BYTE_EN : out bit;
+ LO_BYTE_EN : out bit;
+ FC_EN : out bit;
+ ASn : out bit;
+ AS_EN : out bit;
+ UDSn : out bit;
+ UDS_EN : out bit;
+ LDSn : out bit;
+ LDS_EN : out bit;
+ RWn : out bit;
+ RW_EN : out bit;
+ VPAn : in bit;
+ VMAn : out bit;
+ VMA_EN : out bit;
+ E : out bit;
+ BRn : in bit;
+ BGACKn : in bit;
+ BGn : out bit
+ );
+end component;
+end WF68K00IP_PKG;
diff --git a/common/CPU/68000/wf_68k00_ip/wf68k00ip_shifter.vhd b/common/CPU/68000/wf_68k00_ip/wf68k00ip_shifter.vhd
new file mode 100644
index 00000000..d93b840f
--- /dev/null
+++ b/common/CPU/68000/wf_68k00_ip/wf68k00ip_shifter.vhd
@@ -0,0 +1,372 @@
+----------------------------------------------------------------------
+---- ----
+---- MC68000 compatible IP Core ----
+---- ----
+---- This file is part of the SUSKA ATARI clone project. ----
+---- http://www.experiment-s.de ----
+---- ----
+---- Description: ----
+---- This model provides an opcode and bus timing compatible ip ----
+---- core compared to Motorola's MC68000 microprocessor. ----
+---- ----
+---- This file contains the 68Ks shifter unit. ----
+---- ----
+---- ----
+---- Description: ----
+---- This module performs the shifting operations ASL, ASR, LSL, ----
+---- LSR, ROL, ROR, ROXL and ROXR as also the bit manipulation ----
+---- and test operations BCHG, BCLR, BSET and BTST. ----
+---- The timing of the core is as follows: ----
+---- All bit manipulation operations are performed by concurrent ----
+---- statement modelling which results in immediate bit process- ----
+---- ing. Thus, the result is valid one clock cycle after the ----
+---- settings for the operands are stable.
+---- The shift and rotate operations start with SHIFTER_LOAD. ----
+---- The data processing time is depending on the selected number ----
+---- of bits and is indicated by the SHFT_BUSY flag. During ----
+---- SHFT_BUSY is asserted, the data calculation is in progress. ----
+---- The execution time for these operations is n clock ----
+---- cycles +2 where n is the desired number of shifts or rotates.----
+---- ----
+---- ----
+---- Author(s): ----
+---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
+---- ----
+----------------------------------------------------------------------
+---- ----
+---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
+---- ----
+---- This source file 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 2 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, write to the Free ----
+---- Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ----
+---- Boston, MA 02110-1301, USA. ----
+---- ----
+----------------------------------------------------------------------
+--
+-- Revision History
+--
+-- Revision 2K6B 2006/12/24 WF
+-- Initial Release.
+-- Revision 2K7A 2007/05/31 WF
+-- Updated all modules.
+-- Revision 2K7B 2007/12/24 WF
+-- See the 68K00 top level file.
+-- Revision 2K8A 2008/07/14 WF
+-- See the 68K00 top level file.
+--
+
+use work.wf68k00ip_pkg.all;
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+
+entity WF68K00IP_SHIFTER is
+ port (
+ CLK : in bit;
+ RESETn : in bit;
+
+ DATA_IN : in std_logic_vector(31 downto 0); -- Operand data.
+ DATA_OUT : out std_logic_vector(31 downto 0); -- Shifted operand.
+
+ OP : in OP_68K00;
+
+ OP_SIZE : in OP_SIZETYPE; -- The operand's size.
+ BIT_POS : in std_logic_vector(4 downto 0); -- Bit position control.
+ CNT_NR : in std_logic_vector(5 downto 0); -- Count control.
+
+ -- Progress controls:
+ SHFT_BREAKn : in bit;
+ SHIFTER_LOAD : in bit; -- Strobe of 1 clock pulse.
+ SHFT_BUSY : out bit;
+
+ -- The FLAGS:
+ XNZVC_IN : in std_logic_vector(4 downto 0);
+ XNZVC_OUT : out std_logic_vector(4 downto 0)
+ );
+end entity WF68K00IP_SHIFTER;
+
+architecture BEHAVIOR of WF68K00IP_SHIFTER is
+type SHIFT_STATES is (IDLE, RUN);
+signal SHIFT_STATE : SHIFT_STATES;
+signal BIT_OP : std_logic_vector(31 downto 0);
+signal SHFT_OP : std_logic_vector(31 downto 0);
+signal SHFT_EN : bit;
+signal SHFT_X : std_logic;
+begin
+ -- Output multiplexer:
+ with OP select
+ DATA_OUT <= BIT_OP when BCHG | BCLR | BSET | BTST,
+ SHFT_OP when others; -- Valid for ASL | ASR | LSL | LSR | ROTL | ROTR | ROXL | ROXR.
+
+ BIT_PROC: process(BIT_POS, OP, BIT_OP, DATA_IN)
+ -- Bit manipulation operations.
+ variable BIT_POSITION : integer range 0 to 31;
+ begin
+ BIT_POSITION := Conv_Integer(BIT_POS);
+ --
+ BIT_OP <= DATA_IN; -- The default is the unmanipulated data.
+ --
+ case OP is
+ when BCHG =>
+ BIT_OP(BIT_POSITION) <= not DATA_IN(BIT_POSITION);
+ when BCLR =>
+ BIT_OP(BIT_POSITION) <= '0';
+ when BSET =>
+ BIT_OP(BIT_POSITION) <= '1';
+ when others =>
+ BIT_OP <= DATA_IN; -- Dummy, no result required for BTST.
+ end case;
+ end process BIT_PROC;
+
+ SHIFTER: process(RESETn, CLK)
+ begin
+ if RESETn = '0' then
+ SHFT_OP <= (others => '0');
+ elsif CLK = '1' and CLK' event then
+ if SHIFTER_LOAD = '1' then -- Load data in the shifter unit.
+ SHFT_OP <= DATA_IN; -- Load data for the shift or rotate operations.
+ elsif SHFT_EN = '1' then -- Shift and rotate operations:
+ case OP is
+ when ASL =>
+ if OP_SIZE = LONG then
+ SHFT_OP <= SHFT_OP(30 downto 0) & '0';
+ elsif OP_SIZE = WORD then
+ SHFT_OP <= x"0000" & SHFT_OP(14 downto 0) & '0';
+ else -- OP_SIZE = BYTE.
+ SHFT_OP <= x"000000" & SHFT_OP(6 downto 0) & '0';
+ end if;
+ when ASR =>
+ if OP_SIZE = LONG then
+ SHFT_OP <= SHFT_OP(31) & SHFT_OP(31 downto 1);
+ elsif OP_SIZE = WORD then
+ SHFT_OP <= x"0000" & SHFT_OP(15) & SHFT_OP(15 downto 1);
+ else -- OP_SIZE = BYTE.
+ SHFT_OP <= x"000000" & SHFT_OP(7) & SHFT_OP(7 downto 1);
+ end if;
+ when LSL =>
+ if OP_SIZE = LONG then
+ SHFT_OP <= SHFT_OP(30 downto 0) & '0';
+ elsif OP_SIZE = WORD then
+ SHFT_OP <= x"0000" & SHFT_OP(14 downto 0) & '0';
+ else -- OP_SIZE = BYTE.
+ SHFT_OP <= x"000000" & SHFT_OP(6 downto 0) & '0';
+ end if;
+ when LSR =>
+ if OP_SIZE = LONG then
+ SHFT_OP <= '0' & SHFT_OP(31 downto 1);
+ elsif OP_SIZE = WORD then
+ SHFT_OP <= x"0000" & '0' & SHFT_OP(15 downto 1);
+ else -- OP_SIZE = BYTE.
+ SHFT_OP <= x"000000" & '0' & SHFT_OP(7 downto 1);
+ end if;
+ when ROTL =>
+ if OP_SIZE = LONG then
+ SHFT_OP <= SHFT_OP(30 downto 0) & SHFT_OP(31);
+ elsif OP_SIZE = WORD then
+ SHFT_OP <= x"0000" & SHFT_OP(14 downto 0) & SHFT_OP(15);
+ else -- OP_SIZE = BYTE.
+ SHFT_OP <= x"000000" & SHFT_OP(6 downto 0) & SHFT_OP(7);
+ end if;
+ -- X not affected;
+ when ROTR =>
+ if OP_SIZE = LONG then
+ SHFT_OP <= SHFT_OP(0) & SHFT_OP(31 downto 1);
+ elsif OP_SIZE = WORD then
+ SHFT_OP <= x"0000" & SHFT_OP(0) & SHFT_OP(15 downto 1);
+ else -- OP_SIZE = BYTE.
+ SHFT_OP <= x"000000" & SHFT_OP(0) & SHFT_OP(7 downto 1);
+ end if;
+ -- X not affected;
+ when ROXL =>
+ if OP_SIZE = LONG then
+ SHFT_OP <= SHFT_OP(30 downto 0) & SHFT_X;
+ elsif OP_SIZE = WORD then
+ SHFT_OP <= x"0000" & SHFT_OP(14 downto 0) & SHFT_X;
+ else -- OP_SIZE = BYTE.
+ SHFT_OP <= x"000000" & SHFT_OP(6 downto 0) & SHFT_X;
+ end if;
+ when ROXR =>
+ if OP_SIZE = LONG then
+ SHFT_OP <= SHFT_X & SHFT_OP(31 downto 1);
+ elsif OP_SIZE = WORD then
+ SHFT_OP <= x"0000" & SHFT_X & SHFT_OP(15 downto 1);
+ else -- OP_SIZE = BYTE.
+ SHFT_OP <= x"000000" & SHFT_X & SHFT_OP(7 downto 1);
+ end if;
+ when others => null; -- Unaffected, forbidden.
+ end case;
+ end if;
+ end if;
+ end process SHIFTER;
+
+ P_SHFT_CTRL: process(RESETn, CLK, OP)
+ -- The variable shift or rotate length requires a control
+ -- to achieve the correct OPERAND manipulation. This
+ -- process controls the shift process and asserts the
+ -- SHFT_BUSY flag during shift or rotation.
+ variable BIT_CNT : std_logic_vector(5 downto 0);
+ begin
+ if RESETn = '0' then
+ SHIFT_STATE <= IDLE;
+ BIT_CNT := (others => '0');
+ SHFT_EN <= '0';
+ SHFT_BUSY <= '0';
+ elsif CLK = '1' and CLK' event then
+ if SHIFT_STATE = IDLE then
+ if SHIFTER_LOAD = '1' and CNT_NR /= "000000" then
+ SHIFT_STATE <= RUN;
+ BIT_CNT := CNT_NR;
+ SHFT_EN <= '1';
+ SHFT_BUSY <= '1';
+ else
+ SHIFT_STATE <= IDLE;
+ BIT_CNT := (others => '0');
+ SHFT_EN <= '0';
+ SHFT_BUSY <= '0';
+ end if;
+ elsif SHIFT_STATE = RUN then
+ -- A break condition for SHFT_BREAKn = '0'
+ -- occurs e.g. during interrupt handling.
+ if BIT_CNT = "000001" or SHFT_BREAKn = '0' then
+ SHIFT_STATE <= IDLE;
+ BIT_CNT := CNT_NR;
+ SHFT_EN <= '0';
+ SHFT_BUSY <= '0';
+ else
+ SHIFT_STATE <= RUN;
+ BIT_CNT := BIT_CNT - '1';
+ SHFT_EN <= '1';
+ SHFT_BUSY <= '1';
+ end if;
+ end if;
+ end if;
+ end process P_SHFT_CTRL;
+
+ COND_CODES: process(BIT_POS, OP, XNZVC_IN, DATA_IN, OP_SIZE, SHFT_OP, SHFT_X, CNT_NR, RESETn, CLK)
+ -- This process provides the flags for the shifter and the bit operations.
+ -- The flags for the shifter are valid after the shift operation, when the
+ -- SHFT_BUSY flag is not asserted. The flags of the bit operations are
+ -- valid immediately due to the one clock cycle process time.
+ variable BIT_POSITION : integer range 0 to 31;
+ variable SHFT_V : std_logic;
+ begin
+ BIT_POSITION := Conv_Integer(BIT_POS); -- Valid during the bit manipulation operations:
+ -- Negative and Zero flags:
+ case OP is
+ when BCHG | BCLR | BSET | BTST =>
+ XNZVC_OUT(3 downto 2) <= XNZVC_IN(3) & not DATA_IN(BIT_POSITION);
+ when ASL | ASR | LSL | LSR | ROTL | ROTR | ROXL | ROXR =>
+ -- Negative flag:
+ case OP_SIZE is
+ when LONG =>
+ XNZVC_OUT(3) <= SHFT_OP(31);
+ when WORD =>
+ XNZVC_OUT(3) <= SHFT_OP(15);
+ when others =>
+ XNZVC_OUT(3) <= SHFT_OP(7); -- Byte.
+ end case;
+ -- Zero flag:
+ if OP_SIZE = LONG and SHFT_OP = x"00000000" then
+ XNZVC_OUT(2) <= '1';
+ elsif OP_SIZE = WORD and SHFT_OP(15 downto 0) = x"0000" then
+ XNZVC_OUT(2) <= '1';
+ elsif OP_SIZE = BYTE and SHFT_OP(7 downto 0) = x"00" then
+ XNZVC_OUT(2) <= '1';
+ else
+ XNZVC_OUT(2) <= '0';
+ end if;
+ when others =>
+ XNZVC_OUT(3 downto 2) <= XNZVC_IN(3 downto 2);
+ end case;
+ -- Extended, Overflow and Carry flags:
+ if OP = BCHG or OP = BCLR or OP = BSET or OP = BTST then
+ XNZVC_OUT(4) <= XNZVC_IN(4);
+ XNZVC_OUT(1 downto 0) <= XNZVC_IN(1 downto 0);
+ elsif (OP = ROXL or OP = ROXR) and CNT_NR = "000000" then
+ XNZVC_OUT(4) <= XNZVC_IN(4);
+ XNZVC_OUT(1 downto 0) <= '0' & XNZVC_IN(4);
+ elsif CNT_NR = "000000" then
+ XNZVC_OUT(4) <= XNZVC_IN(4);
+ XNZVC_OUT(1 downto 0) <= "00";
+ else
+ -- Extended flag:
+ case OP is
+ when ASL | ASR | LSL | LSR | ROXL | ROXR =>
+ XNZVC_OUT(4) <= SHFT_X;
+ when others => -- Valid for ROTL, ROTR.
+ XNZVC_OUT(4) <= XNZVC_IN(4); -- Unaffected.
+ end case;
+ -- Overflow flag:
+ case OP is
+ when ASL | ASR =>
+ XNZVC_OUT(1) <= SHFT_V;
+ when others => -- Valid for LSL,LSR, ROL, ROR, ROXL, ROXR.
+ XNZVC_OUT(1) <= '0'; -- Unaffected.
+ end case;
+ -- Carry flag:
+ XNZVC_OUT(0) <= SHFT_X;
+ end if;
+ --
+ -- This register is a mirror for the X flag during the shift operation:
+ -- It is used as X flag for the ASL, ASR, LSL, LSR, ROXL and ROXR operations
+ -- as also as the C flag for all shift operations.
+ if RESETn = '0' then
+ SHFT_X <= '0';
+ elsif CLK = '1' and CLK' event then
+ if SHIFTER_LOAD = '1' then -- Load data in the shifter unit.
+ SHFT_X <= XNZVC_IN(4);
+ elsif SHFT_EN = '1' then -- Shift and rotate operations:
+ case OP is
+ when ASL | LSL | ROTL | ROXL =>
+ case OP_SIZE is
+ when LONG =>
+ SHFT_X <= SHFT_OP(31);
+ when WORD =>
+ SHFT_X <= SHFT_OP(15);
+ when BYTE =>
+ SHFT_X <= SHFT_OP(7);
+ end case;
+ when others =>
+ SHFT_X <= SHFT_OP(0);
+ end case;
+ end if;
+ end if;
+ --
+ if RESETn = '0' then
+ -- This process provides a detection of any toggling of the most significant
+ -- bit of the shifter unit during the ASL shift process. For all other shift
+ -- operations, the V flag is always zero.
+ SHFT_V := '0';
+ elsif CLK = '1' and CLK' event then
+ if SHIFTER_LOAD = '1' then
+ SHFT_V := '0';
+ elsif SHFT_EN = '1' then
+ case OP is
+ when ASL => -- ASR MSB is always unchanged.
+ if OP_SIZE = LONG then
+ SHFT_V := (SHFT_OP(31) xor SHFT_OP(30)) or SHFT_V;
+ elsif OP_SIZE = WORD then
+ SHFT_V := (SHFT_OP(15) xor SHFT_OP(14)) or SHFT_V;
+ else -- OP_SIZE = BYTE.
+ SHFT_V := (SHFT_OP(7) xor SHFT_OP(6)) or SHFT_V;
+ end if;
+ when others =>
+ SHFT_V := '0';
+ end case;
+ end if;
+ end if;
+ end process COND_CODES;
+end BEHAVIOR;
diff --git a/common/CPU/68000/wf_68k00_ip/wf68k00ip_top.vhd b/common/CPU/68000/wf_68k00_ip/wf68k00ip_top.vhd
new file mode 100644
index 00000000..52fb3deb
--- /dev/null
+++ b/common/CPU/68000/wf_68k00_ip/wf68k00ip_top.vhd
@@ -0,0 +1,1026 @@
+----------------------------------------------------------------------
+---- ----
+---- MC68000 compatible IP Core ----
+---- ----
+---- This file is part of the SUSKA ATARI clone project. ----
+---- http://www.experiment-s.de ----
+---- ----
+---- This file is the top level file of this ip core. ----
+---- ----
+---- ----
+---- Description: ----
+---- This model provides an opcode and bus timing compatible ip ----
+---- core compared to Motorola's MC68000 microprocessor. ----
+---- ----
+---- The following operations are additionally supported by this ----
+---- core: ----
+---- - LINK (long). ----
+---- - MOVE FROM CCR. ----
+---- - MULS, MULU: all operation modes word and long. ----
+---- - DIVS, DIVU: all operation modes word and long. ----
+---- - DIVSL, DIVUL. ----
+---- - Direct addressing mode enhancements for TST etc. ----
+---- - PC relative addressing modes for operations like TST. ----
+---- ----
+---- ----
+---- ----
+---- ----
+---- Author(s): ----
+---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
+---- ----
+----------------------------------------------------------------------
+---- ----
+---- Copyright (C) 2006 Wolfgang Foerster ----
+---- ----
+---- This source file may be used and distributed without ----
+---- restriction provided that this copyright statement is not ----
+---- removed from the file and that any derivative work contains ----
+---- the original copyright notice and the associated disclaimer. ----
+---- ----
+---- This source file is free software; you can redistribute it ----
+---- and/or modify it under the terms of the GNU Lesser General ----
+---- Public License as published by the Free Software Foundation; ----
+---- either version 2.1 of the License, or (at your option) any ----
+---- later version. ----
+---- ----
+---- This source 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 Lesser General Public License for more ----
+---- details. ----
+---- ----
+---- You should have received a copy of the GNU Lesser General ----
+---- Public License along with this source; if not, download it ----
+---- from http://www.gnu.org/licenses/lgpl.html ----
+---- ----
+----------------------------------------------------------------------
+--
+-- Revision History
+--
+-- Revision 2K6B 2006/12/24 WF
+-- Initial Release.
+-- Revision 2K7A 2007/05/31 WF
+-- Updated all modules.
+-- Revision 2K7B 2007/12/24 WF
+-- Several bugfixes in the modules.
+-- Optimized the core (reduced the core size 10%).
+--
+
+library work;
+use work.wf68k00ip_pkg.all;
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+
+entity WF68K00IP_TOP is
+ port (
+ CLK : in bit;
+ RESET_COREn : in bit; -- Core reset.
+
+ -- Address and data:
+ ADR : out std_logic_vector(23 downto 1);
+ DATA : inout std_logic_vector(15 downto 0);
+
+ -- System control:
+ BERRn : in bit;
+ RESETn : inout std_logic; -- Open drain.
+ HALTn : inout std_logic; -- Open drain.
+
+ -- Processor status:
+ FC : out std_logic_vector(2 downto 0);
+
+ -- Interrupt control:
+ AVECn : in bit; -- Originally 68Ks use VPAn.
+ IPLn : in std_logic_vector(2 downto 0);
+
+ -- Aynchronous bus control:
+ DTACKn : in bit;
+ ASn : out std_logic;
+ RWn : out std_logic;
+ UDSn : out std_logic;
+ LDSn : out std_logic;
+
+ -- Synchronous peripheral control:
+ E : out bit;
+ VMAn : out std_logic;
+ VPAn : in bit;
+
+ -- Bus arbitration control:
+ BRn : in bit;
+ BGn : out bit;
+ BGACKn : in bit
+ );
+end entity WF68K00IP_TOP;
+
+architecture STRUCTURE of WF68K00IP_TOP is
+signal ADR_EFF_I : std_logic_vector(31 downto 0);
+signal ADR_EN_I : bit;
+signal ADR_EN_VECTOR_I : bit;
+signal ADR_I : std_logic_vector(31 downto 0);
+signal ADR_MODE_I : std_logic_vector(2 downto 0);
+signal ADR_TMP_CLR_I : bit;
+signal ADR_TMP_INC_I : bit;
+signal ALU_OP_IN_S : std_logic_vector(31 downto 0);
+signal ALU_OP_IN_D_HI : std_logic_vector(31 downto 0);
+signal ALU_OP_IN_D_LO : std_logic_vector(31 downto 0);
+signal AR_INC_I : bit;
+signal AR_DEC_I : bit;
+signal AR_WR_I : bit;
+signal AR_DR_EXG_I : bit;
+signal AREG_DATA_IN : std_logic_vector(31 downto 0);
+signal AS_EN_I : bit;
+signal AS_In : bit;
+signal AVEC_In : bit;
+signal BERR_In : bit;
+signal BERR_I : bit;
+signal BGACK_In : bit;
+signal BIT_POS_I : std_logic_vector(4 downto 0);
+signal BIT_POS_OP : std_logic_vector(4 downto 0);
+signal BITPOS_IM_I : bit;
+signal BIW_0_I : std_logic_vector(15 downto 0);
+signal BR_In : bit;
+signal BUS_BUFFER_A : std_logic_vector(31 downto 0);
+signal BUS_BUFFER_B : std_logic_vector(31 downto 0);
+signal BUS_CYC_RDY_I : bit;
+signal BYTEn_WORD_I : bit;
+signal C_CODE_I : bit_vector(3 downto 0);
+signal CHK_ADR_I : bit;
+signal CHK_PC_I : bit;
+signal CNT_NR_I : std_logic_vector(5 downto 0);
+signal CTRL_EN_I : bit;
+signal CTRL_RDY_I : bit;
+signal DATA_CORE : std_logic_vector(15 downto 0);
+signal DATA_IMMEDIATE_I : std_logic_vector(31 downto 0);
+signal DATA_OUT_I : std_logic_vector(31 downto 0);
+signal DATA_VALID_I : bit;
+signal DBcc_COND_I : boolean;
+signal DEST_EXWORD_I : EXWORDTYPE;
+signal DEST_EXT_CNT_I : integer range 0 to 2;
+signal DISPLACE_BIW_I : std_logic_vector(31 downto 0);
+signal DIV_MUL_32n64_I : bit;
+signal DR_I : bit;
+signal DR_DEC_I : bit;
+signal DR_WR_I : bit;
+signal DREG_DATA_IN_A : std_logic_vector(31 downto 0);
+signal DREG_DATA_IN_B : std_logic_vector(31 downto 0);
+signal DTACK_In : bit;
+signal EW_WR_I : bit;
+signal EW_ADR_I : integer range 0 to 1;
+signal EXEC_ABORT_I : bit;
+signal EXEC_RESUME_I : bit;
+signal EXT_CNT_I : integer range 0 to 2;
+signal EXT_DSIZE_I : D_SIZETYPE;
+signal EXWORD_I : EXWORDTYPE;
+signal FC_EN_CTRL : bit;
+signal FC_EN_I : bit;
+signal FC_EN_IRQ : bit;
+signal FC_OUT_CTRL : std_logic_vector(2 downto 0);
+signal FC_OUT_I : std_logic_vector(2 downto 0);
+signal FC_OUT_IRQ : std_logic_vector(2 downto 0);
+signal FORCE_BIW2_I : bit;
+signal FORCE_BIW3_I : bit;
+signal HALT_EN_I : bit;
+signal HALT_In : std_logic;
+signal HI_BYTE_EN_I : bit;
+signal HI_WORD_EN_I : bit;
+signal INT_VECT_I : std_logic_vector(9 downto 0);
+signal INIT_STATUS_I : bit;
+signal IPL_In : std_logic_vector(2 downto 0);
+signal IPL_TMPn : std_logic_vector(2 downto 0);
+signal IR_I : bit;
+signal IRQ_DATA_EN : bit;
+signal IRQ_DOUT : std_logic_vector(15 downto 0);
+signal IRQ_SAVE_I : bit;
+signal IW_ADR_I : integer range 0 to 2;
+signal IW_WR_I : bit;
+signal LDS_EN_I : bit;
+signal LDS_In : bit;
+signal LO_BYTE_EN_I : bit;
+signal MOVE_D_AM_I : std_logic_vector(2 downto 0);
+signal MEM_SHFT_I : bit;
+signal MOVEM_ADn_I : bit;
+signal MOVEM_REGSEL_I : std_logic_vector(2 downto 0);
+signal PC_ADD_DISPL_I : bit;
+signal OP_BUSY_I : bit;
+signal OP_I : OP_68K00;
+signal OP_MODE_I : std_logic_vector(4 downto 0);
+signal OP_SIZE_I : OP_SIZETYPE;
+signal OP_START_I : bit;
+signal PC_INC_I : bit;
+signal PC_INIT_I : bit;
+signal PC_INIT_CTRL : bit;
+signal PC_INIT_IRQ : bit;
+signal PC_OUT : std_logic_vector(31 downto 0);
+signal PC_TMP_CLR_I : bit;
+signal PC_TMP_INC_I : bit;
+signal PC_WR_I : bit;
+signal PRESET_IRQ_MASK_I : bit;
+signal Q_AREG_A : std_logic_vector(31 downto 0);
+signal Q_AREG_B : std_logic_vector(31 downto 0);
+signal Q_DREG_A : std_logic_vector(31 downto 0);
+signal Q_DREG_B : std_logic_vector(31 downto 0);
+signal Q_DREG_C : std_logic_vector(31 downto 0);
+signal RD_BUS_CTRL : bit;
+signal RD_BUS_IRQ : bit;
+signal RD_BUS_I : bit;
+signal RDWR_BUS_I : bit;
+signal REGLISTMASK_I : std_logic_vector(15 downto 0);
+signal REGSEL_119_I : std_logic_vector(2 downto 0);
+signal REGSEL_20_I : std_logic_vector(2 downto 0);
+signal REGSEL_ADR_A : std_logic_vector(2 downto 0);
+signal REGSEL_ADR_B : std_logic_vector(2 downto 0);
+signal REGSEL_DATA_A : std_logic_vector(2 downto 0);
+signal REGSEL_DATA_B : std_logic_vector(2 downto 0);
+signal REGSEL_DATA_C : std_logic_vector(2 downto 0);
+signal REGSEL_Dhr : std_logic_vector(2 downto 0);
+signal REGSEL_Dlq : std_logic_vector(2 downto 0);
+signal REGSEL_INDEX : std_logic_vector(2 downto 0);
+signal RESET_CPU_In : bit;
+signal RESET_EN_I : bit;
+signal RESET_IN_In : bit;
+signal RESET_OUT_EN_I : bit;
+signal RESET_RDY_I : bit;
+signal RESULT_ALU_HI : std_logic_vector(31 downto 0);
+signal RESULT_ALU_LO : std_logic_vector(31 downto 0);
+signal RESULT_SHFT : std_logic_vector(31 downto 0);
+signal RM_I : bit;
+signal RW_EN_I : bit;
+signal RWn_I : bit;
+signal SBIT_I : bit;
+signal SCAN_TRAPS_I : bit;
+signal Scc_COND_I : boolean;
+signal SEL_A_LO : bit;
+signal SEL_A_HI : bit;
+signal SEL_A_MIDHI : bit;
+signal SEL_A_MIDLO : bit;
+signal SEL_BUF_A_LO_I : bit;
+signal SEL_BUF_A_HI_I : bit;
+signal SEL_BUF_A_LO_CTRL_I : bit;
+signal SEL_BUF_A_HI_CTRL_I : bit;
+signal SEL_BUF_A_LO_IRQ_I : bit;
+signal SEL_BUF_A_HI_IRQ_I : bit;
+signal SEL_BUF_B_LO_I : bit;
+signal SEL_BUF_B_HI_I : bit;
+signal SEL_DISPLACE_BIW_I : bit;
+signal SHFT_BUSY_I : bit;
+signal SHFT_OP_IN : std_logic_vector(31 downto 0);
+signal SHIFTER_LOAD_I : bit;
+signal SP_ADD_DISPL_I : bit;
+signal SR_CCR_MUX : std_logic_vector(15 downto 0);
+signal SRC_DESTn_I : bit;
+signal SSP_DEC_CTRL : bit;
+signal SSP_DEC_I : bit;
+signal SSP_DEC_IRQ : bit;
+signal SSP_INC_I : bit;
+signal SSP_INIT_I : bit;
+signal SSP_OUT : std_logic_vector(31 downto 0);
+signal STATUS_REG_I : std_logic_vector(15 downto 0);
+signal SYS_INIT_I : bit;
+signal TRAP_1010_I : bit;
+signal TRAP_1111_I : bit;
+signal TRAP_AERR_I : bit;
+signal TRAP_CHK_I : bit;
+signal TRAP_CHK_EN_I : bit;
+signal TRAP_DIVZERO_I : bit;
+signal TRAP_ILLEGAL_I : bit;
+signal TRAP_OP_I : bit;
+signal TRAP_PRIV_I : bit;
+signal TRAP_TRACE_I : bit;
+signal TRAP_V_I : bit;
+signal TRAP_VECTOR_I : std_logic_vector(3 downto 0);
+signal UDS_EN_I : bit;
+signal UDS_In : bit;
+signal UNLK_SP_An_I : bit;
+signal USE_INT_VECT_I : bit;
+signal USE_SP_ADR_I : bit;
+signal USE_SSP_ADR_I : bit;
+signal USP_CPY_I : bit;
+signal USP_DEC_I : bit;
+signal USP_INC_I : bit;
+signal USP_OUT : std_logic_vector(31 downto 0);
+signal VMA_EN_I : bit;
+signal VMA_In : bit;
+signal VPA_In : bit;
+signal WR_BUS_CTRL : bit;
+signal WR_BUS_I : bit;
+signal WR_BUS_IRQ : bit;
+signal WR_HI_I : bit;
+signal XNZVC_ALU : std_logic_vector(4 downto 0);
+signal XNZVC_I : std_logic_vector(4 downto 0);
+signal XNZVC_SHFT : std_logic_vector(4 downto 0);
+begin
+ SIGNAL_SAMPLE: process
+ -- The bus control signals used in this core are sampled on the negative clock
+ -- edge. Thus the signals are valid on the following positive clock edge. In the original
+ -- 68K machines, the input synchronisation is realized with three latches (see the 68K
+ -- user manual for more information). This concept is not suitable for a FPGA design
+ -- and therefore not used here.
+ begin
+ wait until CLK = '0' and CLK' event;
+ BERR_In <= BERRn;
+ HALT_In <= HALTn;
+ VPA_In <= VPAn;
+ BR_In <= BRn;
+ BGACK_In <= BGACKn;
+ RESET_IN_In <= To_Bit(RESETn);
+ AVEC_In <= AVECn;
+ end process SIGNAL_SAMPLE;
+
+ IPL_SAMPLE: process
+ -- This process provides a filter for the interrupt priority level. It
+ -- is valid, if it is stable for two consecutive falling clock edges.
+ begin
+ wait until CLK = '0' and CLK' event;
+ IPL_TMPn <= IPLn;
+ if IPL_TMPn = IPLn then
+ IPL_In <= IPLn;
+ else
+ IPL_In <= "111";
+ end if;
+ end process IPL_SAMPLE;
+
+ BERR_I <= '1' when BERR_In = '0' and HALT_In = '1' and DTACK_In = '1' else
+ '1' when BERR_In = '0' and HALT_In = '0' and RDWR_BUS_I = '1' else '0'; -- No retry during read modify write cycles.
+
+ -- The following input may not be sampled
+ -- due to bus timing constraints.
+ DTACK_In <= DTACKn;
+
+ -- Data output multiplexer (tri-state):
+ -- During long word access, the higher word is written always 16 bit wide. During word or byte access,
+ -- the access of the higher 8 bits or the lower 8 bits depends on the address boundary or on the
+ -- length of the operator defined in the operation (WORD, BYTE). Although the byte portions are doubled
+ -- to drive the whole bus low impedant.
+ DATA <= IRQ_DOUT when IRQ_DATA_EN = '1' else
+ DATA_OUT_I(31 downto 24) & DATA_OUT_I(31 downto 24) when SEL_A_HI = '1' else -- MOVEP
+ DATA_OUT_I(23 downto 16) & DATA_OUT_I(23 downto 16) when SEL_A_MIDHI = '1' else -- MOVEP
+ DATA_OUT_I(15 downto 8) & DATA_OUT_I(15 downto 8) when SEL_A_MIDLO = '1' else -- MOVEP.
+ DATA_OUT_I(7 downto 0) & DATA_OUT_I(7 downto 0) when SEL_A_LO = '1' else -- MOVEP.
+ DATA_OUT_I(31 downto 16) when HI_WORD_EN_I = '1' else
+ DATA_OUT_I(15 downto 0) when HI_BYTE_EN_I = '1' and LO_BYTE_EN_I = '1' else
+ DATA_OUT_I(7 downto 0) & DATA_OUT_I(7 downto 0) when HI_BYTE_EN_I = '1' or LO_BYTE_EN_I = '1' else (others => 'Z');
+
+ -- Open drain outputs:
+ RESETn <= '0' when RESET_OUT_EN_I = '1' else 'Z';
+ HALTn <= '0' when HALT_EN_I = '1' else 'Z';
+
+ -- Bus controls:
+ ASn <= '1' when AS_In = '1' and AS_EN_I = '1' else
+ '0' when AS_In = '0' and AS_EN_I = '1' else 'Z';
+ UDSn <= '1' when UDS_In = '1' and UDS_EN_I = '1' else
+ '0' when UDS_In = '0' and UDS_EN_I = '1' else 'Z';
+ LDSn <= '1' when LDS_In = '1' and LDS_EN_I = '1' else
+ '0' when LDS_In = '0' and LDS_EN_I = '1' else 'Z';
+ RWn <= '1' when RWn_I = '1' and RW_EN_I = '1' else
+ '0' when RWn_I = '0' and RW_EN_I = '1' else 'Z';
+ VMAn <= '1' when VMA_In = '1' and VMA_EN_I = '1' else
+ '0' when VMA_In = '0' and VMA_EN_I = '1' else 'Z';
+
+ -- The function code:
+ FC <= FC_OUT_I when FC_EN_I = '1' else (others => 'Z');
+ FC_OUT_I <= FC_OUT_CTRL when FC_EN_CTRL = '1' else
+ FC_OUT_IRQ when FC_EN_IRQ = '1' else (others => '0');
+
+ SYS_INIT_I <= '1' when SEL_BUF_A_HI_IRQ_I = '1' or SEL_BUF_A_LO_IRQ_I = '1' else '0';
+
+ -- Bus access control:
+ BYTEn_WORD_I <= '1' when FC_OUT_I = "110" else -- Supervisor program.
+ '1' when FC_OUT_I = "010" else -- User program.
+ '1' when USE_SP_ADR_I = '1' else -- During stacking.
+ '1' when USE_SSP_ADR_I = '1' else -- During stacking.
+ '1' when USE_INT_VECT_I = '1' else -- During interrupt handling.
+ '0' when OP_SIZE_I = BYTE else
+ '0' when OP_I = MOVEP else '1';
+
+ -- Bus buffer A control:
+ SEL_BUF_A_HI_I <= SEL_BUF_A_HI_CTRL_I or SEL_BUF_A_HI_IRQ_I;
+ SEL_BUF_A_LO_I <= SEL_BUF_A_LO_CTRL_I or SEL_BUF_A_LO_IRQ_I;
+
+ -- Some of the controls are asserted by the main control state machine or
+ -- by the interrupt control state machine but never by both at the same
+ -- time. So the related signal can be 'ored'; no malfuntion results.
+ SSP_DEC_I <= SSP_DEC_CTRL or SSP_DEC_IRQ;
+ RD_BUS_I <= RD_BUS_CTRL or RD_BUS_IRQ;
+ WR_BUS_I <= WR_BUS_CTRL or WR_BUS_IRQ;
+ PC_INIT_I <= PC_INIT_CTRL or PC_INIT_IRQ;
+
+ -- Count value for the shifter unit. It is valid during the shift operations:
+ CNT_NR_I <= "000001" when MEM_SHFT_I = '1' else -- Memory shifts are 1 bit only.
+ "000" & REGSEL_119_I when IR_I = '0' and REGSEL_119_I > "000" else
+ "001000" when IR_I = '0' else -- Shift 8 bits for REGSEL_119 = "000".
+ Q_DREG_A(5 downto 0); -- Register contents modulo 64.
+
+ -- Bit operation position multiplexer:
+ -- Register bit manipulations are modulo 32 whereas memory bit manipulations are modulo 8.
+ BIT_POS_I <= BIT_POS_OP when BITPOS_IM_I = '1' and ADR_MODE_I = "000" else
+ Q_DREG_A(4 downto 0) when ADR_MODE_I = "000" else
+ "00" & BIT_POS_OP(2 downto 0) when BITPOS_IM_I = '1' else "00" & Q_DREG_A(2 downto 0);
+
+ -- The condition codes:
+ with OP_I select
+ XNZVC_I <= XNZVC_SHFT when BCHG | BCLR | BSET | BTST,
+ XNZVC_SHFT when ASL | ASR | LSL | LSR | ROTL | ROTR | ROXL | ROXR,
+ XNZVC_ALU when others;
+
+ -- Address select stuff:
+ -- The internal address space is 32 bit long. The 68K00 has 23 addresslines.
+ -- The internal address space is therefore limited to 24 bit.
+ ADR <= ADR_I(23 downto 1) when ADR_EN_I = '1' else (others => 'Z');
+ ADR_I <= x"FFFFFFF" & STATUS_REG_I(10 downto 8)_I & '1' when ADR_EN_VECTOR_I = '1' else -- Interrupt acknowledge cycle.
+ SSP_OUT when USE_SSP_ADR_I = '1' else -- During exceptions stacking.
+ x"00000" & "00" & INT_VECT_I when USE_INT_VECT_I = '1' else -- During access to the exception vectors.
+ SSP_OUT when USE_SP_ADR_I = '1' and SBIT_I = '1' else -- During stack pointer operations.
+ USP_OUT when USE_SP_ADR_I = '1' and SBIT_I = '0' else -- During stack pointer operations.
+ PC_OUT when FC_OUT_CTRL = "010" or FC_OUT_CTRL = "110" else -- Program space.
+ ADR_EFF_I; -- Data space.
+
+ -- Status register multiplexer:
+ -- The default is valid for MOVE_TO_CCR from memory, MOVE_TO_SR from memory,
+ -- for the RTR and for stack restoring during exception handling.
+ SR_CCR_MUX <= RESULT_ALU_LO(15 downto 0) when OP_I = ANDI_TO_SR or OP_I = EORI_TO_SR or OP_I = ORI_TO_SR else
+ RESULT_ALU_LO(15 downto 0) when OP_I = ANDI_TO_CCR or OP_I = EORI_TO_CCR or OP_I = ORI_TO_CCR else
+ Q_DREG_B(15 downto 0) when (OP_I = MOVE_TO_CCR or OP_I = MOVE_TO_SR) and ADR_MODE_I = "000" else
+ DATA_IMMEDIATE_I(15 downto 0) when OP_I = MOVE_TO_CCR and ADR_MODE_I = "111" and REGSEL_20_I = "100" else
+ DATA_IMMEDIATE_I(15 downto 0) when OP_I = MOVE_TO_SR and ADR_MODE_I = "111" and REGSEL_20_I = "100" else
+ DATA_IMMEDIATE_I(15 downto 0) when OP_I = STOP else DATA_CORE;
+
+ -- Note: the address register is never destination during MOVE.
+ -- Note: The default is also valid for UNLK during writing to the stack pointer.h
+ REGSEL_ADR_A <= REGSEL_20_I when (OP_I = ADDQ or OP_I = SUBQ) and ADR_MODE_I = "001" else
+ REGSEL_20_I when (OP_I = LINK or OP_I = MOVE) else
+ REGSEL_20_I when OP_I = UNLK and UNLK_SP_An_I = '0' else
+ MOVEM_REGSEL_I when OP_I = MOVEM else REGSEL_119_I;
+
+ REGSEL_ADR_B <= REGSEL_119_I when SRC_DESTn_I = '0' else REGSEL_20_I;
+
+ REGSEL_DATA_A <= REGSEL_20_I when OP_I = ABCD or OP_I = ADDX or OP_I = SBCD or OP_I = SUBX else
+ REGSEL_20_I when OP_I = ADD or OP_I = SUB else
+ REGSEL_20_I when OP_I = AND_B or OP_I = OR_B else
+ REGSEL_Dlq when (OP_I = MULS or OP_I = MULU) and OP_SIZE_I = LONG else
+ REGSEL_Dlq when (OP_I = DIVS or OP_I = DIVU) and OP_SIZE_I = LONG else REGSEL_119_I;
+
+ REGSEL_DATA_B <= MOVEM_REGSEL_I when OP_I = MOVEM else
+ REGSEL_119_I when OP_I = ABCD or OP_I = ADDX or OP_I = SBCD or OP_I = SUBX else
+ REGSEL_119_I when OP_I = ADD or OP_I = SUB else
+ REGSEL_119_I when OP_I = AND_B or OP_I = OR_B else
+ REGSEL_Dhr when (OP_I = DIVS or OP_I = DIVU) and DR_WR_I = '1' else -- Used for write back the result.
+ REGSEL_Dhr when (OP_I = MULS or OP_I = MULU) and DR_WR_I = '1' else -- Used for write back the result.
+ REGSEL_119_I when OP_I = MOVEQ else REGSEL_20_I;
+
+ REGSEL_DATA_C <= REGSEL_Dhr when (OP_I = DIVS or OP_I = DIVU) and OP_START_I = '1' else REGSEL_INDEX;
+
+ DATA_OUT_I <= RESULT_ALU_LO when (OP_I = ABCD or OP_I = SBCD) else
+ RESULT_ALU_LO when (OP_I = ADDX or OP_I = NEGX or OP_I = SUBX) else
+ RESULT_ALU_LO when (OP_I = ADD or OP_I = SUB) else
+ RESULT_ALU_LO when (OP_I = ADDI or OP_I = SUBI) else
+ RESULT_ALU_LO when (OP_I = ADDQ or OP_I = SUBQ) else
+ RESULT_ALU_LO when (OP_I = AND_B or OP_I = OR_B) else
+ RESULT_ALU_LO when (OP_I = ANDI or OP_I = EORI or OP_I = ORI) else
+ RESULT_SHFT when (OP_I = ASL or OP_I = ASR) else
+ RESULT_SHFT when (OP_I = LSL or OP_I = LSR) else
+ RESULT_SHFT when (OP_I = ROTL or OP_I = ROTR) else
+ RESULT_SHFT when (OP_I = ROXL or OP_I = ROXR) else
+ RESULT_SHFT when (OP_I = BCHG or OP_I = BSET or OP_I = BCLR) else
+ x"00000000" when OP_I = CLR else
+ Q_DREG_B when OP_I = MOVE and ADR_MODE_I = "000" else
+ Q_AREG_A when OP_I = MOVE and ADR_MODE_I = "001" else
+ DATA_IMMEDIATE_I when OP_I = MOVE and ADR_MODE_I = "111" and REGSEL_20_I = "100" else
+ BUS_BUFFER_A when OP_I = MOVE else
+ x"000000" & "000" & STATUS_REG_I(4 downto 0) when OP_I = MOVE_FROM_CCR else
+ x"0000" & STATUS_REG_I when OP_I = MOVE_FROM_SR else
+ Q_DREG_B when OP_I = MOVEM and MOVEM_ADn_I = '0' else
+ Q_AREG_A when OP_I = MOVEM and MOVEM_ADn_I = '1' else
+ Q_DREG_A when OP_I = MOVEP else
+ RESULT_ALU_LO when (OP_I = NBCD or OP_I = NEG or OP_I = NOT_B) else
+ ADR_EFF_I when OP_I = PEA else
+ x"FFFFFFFF" when OP_I = Scc and Scc_COND_I = true else
+ x"00000000" when OP_I = Scc else
+ PC_OUT + "10" when (OP_I = JSR or OP_I = BSR) else -- Push the following address to the stack.
+ Q_AREG_B when OP_I = LINK else RESULT_ALU_LO; -- The default is valid for the TAS operation.
+
+
+ -- Data register source: The required sign extensions for the operation
+ -- MOVEM and MOVEQ are computed in the data register unit.
+ DREG_DATA_IN_B <= RESULT_ALU_LO when (OP_I = ABCD or OP_I = SBCD) else
+ RESULT_ALU_LO when (OP_I = ADDX or OP_I = NEGX or OP_I = SUBX) else
+ RESULT_ALU_LO when (OP_I = ADD or OP_I = SUB) else
+ RESULT_ALU_LO when (OP_I = ADDI or OP_I = SUBI) else
+ RESULT_ALU_LO when (OP_I = ADDQ or OP_I = SUBQ) else
+ RESULT_ALU_LO when (OP_I = AND_B or OP_I = OR_B) else
+ RESULT_ALU_LO when (OP_I = ANDI or OP_I = EORI or OP_I = ORI) else
+ RESULT_ALU_LO when (OP_I = NBCD or OP_I = NEG or OP_I = NOT_B) else
+ RESULT_ALU_HI when (OP_I = DIVS or OP_I = DIVU) else
+ RESULT_ALU_HI when (OP_I = MULS or OP_I = MULU) else
+ RESULT_SHFT when (OP_I = ASL or OP_I = ASR) else
+ RESULT_SHFT when (OP_I = LSL or OP_I = LSR) else
+ RESULT_SHFT when (OP_I = ROTL or OP_I = ROTR) else
+ RESULT_SHFT when (OP_I = ROXL or OP_I = ROXR) else
+ RESULT_SHFT when (OP_I = BCHG or OP_I = BSET or OP_I = BCLR) else
+ Q_DREG_B when OP_I = EXG and OP_MODE_I = "01000" else -- Exchange two data registers.
+ BUS_BUFFER_A when OP_I = MOVEM else
+ DATA_IMMEDIATE_I when OP_I = MOVEQ else
+ x"FFFFFFFF" when OP_I = Scc and Scc_COND_I = true else
+ x"00000000" when OP_I = Scc else
+ x"00000000" when OP_I = CLR else
+ x"000000" & "000" & STATUS_REG_I(4 downto 0) when OP_I = MOVE_FROM_CCR else
+ x"0000" & STATUS_REG_I when OP_I = MOVE_FROM_SR else RESULT_ALU_LO; -- Default used for EXT, SWAP, TAS.
+
+ DREG_DATA_IN_A <= Q_DREG_B when OP_I = MOVE and ADR_MODE_I = "000" else -- Data to data register.
+ Q_AREG_B when OP_I = MOVE and ADR_MODE_I = "001" else -- Address to data register.
+ Q_DREG_A when OP_I = EXG and OP_MODE_I = "01000" else -- Exchange two data registers.
+ Q_AREG_B when OP_I = EXG else -- Exchange data and address registers.
+ DATA_IMMEDIATE_I when OP_I = MOVE and ADR_MODE_I = "111" and REGSEL_20_I = "100" else
+ BUS_BUFFER_A when (OP_I = MOVE or OP_I = MOVEP) else RESULT_ALU_LO; -- Default for DIVS, MULS and MULU.
+
+ -- Address register source: The required sign extension for the operation
+ -- MOVEA and MOVEM are computed in the address register unit.
+ -- Note: this logic is priority sensitive!
+ AREG_DATA_IN <= BUS_BUFFER_A when CTRL_RDY_I = '1' else -- For interrupt handling (init PC, SSP).
+ RESULT_ALU_LO when (OP_I = ADDA or OP_I = SUBA) else
+ RESULT_ALU_LO when (OP_I = ADDQ or OP_I = SUBQ) else
+ Q_DREG_B when OP_I = MOVEA and ADR_MODE_I = "000" else
+ Q_AREG_B when OP_I = EXG and OP_MODE_I = "01001" else -- Exchange two address registers.
+ Q_DREG_A when OP_I = EXG else -- Exchange data and address registers.
+ Q_AREG_B when OP_I = MOVEA and ADR_MODE_I = "001" else
+ DATA_IMMEDIATE_I when OP_I = MOVEA and ADR_MODE_I = "111" and REGSEL_20_I = "100" else
+ SSP_OUT when OP_I = LINK and SBIT_I = '1' else
+ USP_OUT when OP_I = LINK else
+ BUS_BUFFER_A when (OP_I = RTE or OP_I = RTR or OP_I = RTS) else -- Init PC, CCR, SP.
+ Q_AREG_B when OP_I = UNLK and UNLK_SP_An_I = '1' else -- An to SP.
+ x"0000" & DATA_CORE when FC_OUT_I = "010" or FC_OUT_I = "110" else -- User program space.
+ BUS_BUFFER_A;
+
+ -- ALU source operand: The required sign extensions for the operations
+ -- ADDA, CMPA and SUBA are computed in the ALU unit.
+ ALU_OP_IN_S <= Q_DREG_A when (OP_I = ABCD or OP_I = SBCD) and RM_I = '0' else
+ BUS_BUFFER_A when (OP_I = ABCD or OP_I = SBCD) else
+ Q_DREG_A when (OP_I = ADDX or OP_I = SUBX) and RM_I = '0' else
+ BUS_BUFFER_A when (OP_I = ADDX or OP_I = SUBX) else
+ Q_DREG_A when (OP_I = ADD or OP_I = SUB) and OP_MODE_I(2) = '0' and ADR_MODE_I = "000" else
+ Q_AREG_B when (OP_I = ADD or OP_I = SUB) and OP_MODE_I(2) = '0' and ADR_MODE_I = "001" else
+ DATA_IMMEDIATE_I when (OP_I = ADD or OP_I = SUB) and ADR_MODE_I = "111" and REGSEL_20_I = "100" else
+ BUS_BUFFER_A when (OP_I = ADD or OP_I = SUB) and OP_MODE_I(2) = '0' else
+ Q_DREG_B when (OP_I = ADD or OP_I = SUB) and OP_MODE_I(2) = '1' else
+ Q_DREG_B when (OP_I = ADDA or OP_I = CMPA or OP_I = SUBA) and ADR_MODE_I = "000" else
+ Q_AREG_B when (OP_I = ADDA or OP_I = CMPA or OP_I = SUBA) and ADR_MODE_I = "001" else
+ DATA_IMMEDIATE_I when (OP_I = ADDA or OP_I = CMPA or OP_I = SUBA) and ADR_MODE_I = "111" and REGSEL_20_I = "100" else
+ BUS_BUFFER_A when (OP_I = ADDA or OP_I = CMPA or OP_I = SUBA) else
+ DATA_IMMEDIATE_I when (OP_I = ADDI or OP_I = SUBI) else
+ DATA_IMMEDIATE_I when (OP_I = ADDQ or OP_I = SUBQ) else
+ Q_DREG_A when (OP_I = AND_B or OP_I = OR_B) and OP_MODE_I(2) = '0' and ADR_MODE_I = "000" else
+ DATA_IMMEDIATE_I when (OP_I = AND_B or OP_I = OR_B) and ADR_MODE_I = "111" and REGSEL_20_I = "100" else
+ BUS_BUFFER_A when (OP_I = AND_B or OP_I = OR_B) and OP_MODE_I(2) = '0' else
+ Q_DREG_B when (OP_I = AND_B or OP_I = OR_B) and OP_MODE_I(2) = '1' else
+ DATA_IMMEDIATE_I when (OP_I = ANDI or OP_I = CMPI or OP_I = EORI or OP_I = ORI) else
+ DATA_IMMEDIATE_I when (OP_I = ANDI_TO_CCR or OP_I = ANDI_TO_SR) else
+ DATA_IMMEDIATE_I when (OP_I = EORI_TO_CCR or OP_I = EORI_TO_SR) else
+ DATA_IMMEDIATE_I when (OP_I = ORI_TO_CCR or OP_I = ORI_TO_SR) else
+ Q_DREG_B when (OP_I = CHK) and ADR_MODE_I = "000" else
+ DATA_IMMEDIATE_I when (OP_I = CHK) and ADR_MODE_I = "111" and REGSEL_20_I = "100" else
+ BUS_BUFFER_A when (OP_I = CHK) else
+ Q_DREG_B when OP_I = CMP and ADR_MODE_I = "000" else
+ Q_AREG_B when OP_I = CMP and ADR_MODE_I = "001" else
+ DATA_IMMEDIATE_I when OP_I = CMP and ADR_MODE_I = "111" and REGSEL_20_I = "100" else
+ BUS_BUFFER_A when OP_I = CMP or OP_I = CMPM else
+ Q_DREG_A when OP_I = EOR else
+ Q_DREG_B when (OP_I = EXTW or OP_I = SWAP) else
+ -- MOVE and MOVEQ are switched here for condition code calculation:
+ Q_DREG_B when OP_I = MOVE and ADR_MODE_I = "000" else
+ Q_DREG_B when OP_I = MOVE and ADR_MODE_I = "000" else
+ Q_AREG_A when OP_I = MOVE and ADR_MODE_I = "001" else
+ DATA_IMMEDIATE_I when OP_I = MOVE and ADR_MODE_I = "111" and REGSEL_20_I = "100" else
+ BUS_BUFFER_A when OP_I = MOVE else
+ DATA_IMMEDIATE_I when OP_I = MOVEQ else
+ --
+ Q_DREG_B when (OP_I = DIVS or OP_I = DIVU) and ADR_MODE_I = "000" else
+ DATA_IMMEDIATE_I when (OP_I = DIVS or OP_I = DIVU) and ADR_MODE_I = "111" and REGSEL_20_I = "100" else
+ BUS_BUFFER_A when (OP_I = DIVS or OP_I = DIVU) else
+ x"0000" & Q_DREG_B(15 downto 0) when OP_SIZE_I = WORD and (OP_I = MULS or OP_I = MULU) and ADR_MODE_I = "000" else
+ Q_DREG_B when (OP_I = MULS or OP_I = MULU) and ADR_MODE_I = "000" else
+ x"0000" & DATA_IMMEDIATE_I(15 downto 0) when OP_SIZE_I = WORD and (OP_I = MULS or OP_I = MULU) and ADR_MODE_I = "111" and REGSEL_20_I = "100" else
+ DATA_IMMEDIATE_I when (OP_I = MULS or OP_I = MULU) and ADR_MODE_I = "111" and REGSEL_20_I = "100" else
+ x"0000" & BUS_BUFFER_A(15 downto 0) when OP_SIZE_I = WORD and (OP_I = MULS or OP_I = MULU) else
+ BUS_BUFFER_A when (OP_I = MULS or OP_I = MULU) else x"00000000"; -- The default is valid for NBCD, NEG, NEGX.
+
+ ALU_OP_IN_D_LO <= Q_DREG_B when (OP_I = ABCD or OP_I = SBCD) and RM_I = '0' else
+ BUS_BUFFER_B when (OP_I = ABCD or OP_I = SBCD) else
+ Q_DREG_B when (OP_I = ADDX or OP_I = SUBX) and RM_I = '0' else
+ BUS_BUFFER_B when (OP_I = ADDX or OP_I = SUBX) else
+ Q_DREG_B when (OP_I = ADD or OP_I = SUB) and OP_MODE_I(2) = '0' else
+ BUS_BUFFER_A when (OP_I = ADD or OP_I = SUB) and OP_MODE_I(2) = '1' else
+ Q_AREG_A when (OP_I = ADDA or OP_I = CMPA or OP_I = SUBA) else
+ Q_DREG_B when (OP_I = ADDI or OP_I = SUBI) and ADR_MODE_I = "000" else
+ BUS_BUFFER_A when (OP_I = ADDI or OP_I = SUBI) else
+ Q_DREG_B when (OP_I = ADDQ or OP_I = SUBQ) and ADR_MODE_I = "000" else
+ Q_AREG_B when (OP_I = ADDQ or OP_I = SUBQ) and ADR_MODE_I = "001" else
+ BUS_BUFFER_A when (OP_I = ADDQ or OP_I = SUBQ) else
+ Q_DREG_B when (OP_I = AND_B or OP_I = OR_B) and OP_MODE_I(2) = '0' else
+ Q_DREG_B when OP_I = EOR and ADR_MODE_I = "000" else
+ BUS_BUFFER_A when (OP_I = AND_B or OP_I = EOR or OP_I = OR_B) and OP_MODE_I(2) = '1' else
+ Q_DREG_B when (OP_I = ANDI or OP_I = CMPI or OP_I = EORI or OP_I = ORI) and ADR_MODE_I = "000" else
+ BUS_BUFFER_A when (OP_I = ANDI or OP_I = CMPI or OP_I = EORI or OP_I = ORI) else
+ x"0000" & STATUS_REG_I when (OP_I = ANDI_TO_CCR or OP_I = ANDI_TO_SR) else
+ x"0000" & STATUS_REG_I when (OP_I = EORI_TO_CCR or OP_I = EORI_TO_SR) else
+ x"0000" & STATUS_REG_I when (OP_I = ORI_TO_CCR or OP_I = ORI_TO_SR) else
+ Q_DREG_A when OP_I = CHK else
+ Q_DREG_A when OP_I = CMP and OP_MODE_I(2) = '0' else
+ BUS_BUFFER_B when OP_I = CMPM else
+ Q_DREG_A when (OP_I = DIVS or OP_I = DIVU) else
+ x"0000" & Q_DREG_A(15 downto 0) when OP_SIZE_I = LONG and (OP_I = MULS or OP_I = MULU) else
+ Q_DREG_A when (OP_I = MULS or OP_I = MULU) else
+ Q_DREG_B when (OP_I = NBCD or OP_I = NEG or OP_I = NEGX or OP_I = NOT_B) and ADR_MODE_I = "000" else
+ BUS_BUFFER_A when (OP_I = NBCD or OP_I = NEG or OP_I = NEGX or OP_I = NOT_B) else
+ Q_DREG_B when OP_I = TAS and ADR_MODE_I = "000" else
+ BUS_BUFFER_A when OP_I = TAS else
+ Q_DREG_B when OP_I = TST and ADR_MODE_I = "000" else
+ Q_AREG_B when OP_I = TST and ADR_MODE_I = "001" else
+ DATA_IMMEDIATE_I when OP_I = TST and ADR_MODE_I = "111" and REGSEL_20_I = "100" else
+ BUS_BUFFER_A; -- Valid for TST.
+
+ ALU_OP_IN_D_HI <= Q_DREG_C; -- Used for DIVUL, DIVSL.
+
+ SHFT_OP_IN <= Q_DREG_B when (OP_I = ASL or OP_I = ASR) and MEM_SHFT_I = '0' else
+ BUS_BUFFER_A when (OP_I = ASL or OP_I = ASR) else
+ Q_DREG_B when (OP_I = LSL or OP_I = LSR) and MEM_SHFT_I = '0' else
+ BUS_BUFFER_A when (OP_I = LSL or OP_I = LSR) else
+ Q_DREG_B when (OP_I = ROTL or OP_I = ROTR) and MEM_SHFT_I = '0' else
+ BUS_BUFFER_A when (OP_I = ROTL or OP_I = ROTR) else
+ Q_DREG_B when (OP_I = ROXL or OP_I = ROXR) and MEM_SHFT_I = '0' else
+ BUS_BUFFER_A when (OP_I = ROXL or OP_I = ROXR) else
+ DATA_IMMEDIATE_I when OP_I = BTST and ADR_MODE_I = "111" and REGSEL_20_I = "100" else
+ Q_DREG_B when (OP_I = BCHG or OP_I = BCLR or OP_I = BSET or OP_I = BTST) and ADR_MODE_I = "000" else
+ BUS_BUFFER_A when (OP_I = BCHG or OP_I = BCLR or OP_I = BSET or OP_I = BTST) else
+ (others => '0'); -- Dummy.
+
+ I_CTRL: WF68K00IP_CONTROL
+ port map(
+ CLK => CLK,
+ RESETn => RESET_COREn,
+ C_CODE => C_CODE_I,
+ Scc_COND => Scc_COND_I,
+ REGLISTMASK => REGLISTMASK_I,
+ CTRL_EN => CTRL_EN_I,
+ EXEC_ABORT => EXEC_ABORT_I,
+ DATA_VALID => DATA_VALID_I,
+ BUS_CYC_RDY => BUS_CYC_RDY_I,
+ CTRL_RDY => CTRL_RDY_I,
+ INIT_STATUS => INIT_STATUS_I,
+ PRESET_IRQ_MASK => PRESET_IRQ_MASK_I,
+ SR_CCR_IN => SR_CCR_MUX,
+ IRQ => not IPL_In,
+ IRQ_SAVE => IRQ_SAVE_I,
+ XNZVC_IN => XNZVC_I,
+ STATUS_REG_OUT => STATUS_REG_I,
+ FORCE_BIW2 => FORCE_BIW2_I,
+ FORCE_BIW3 => FORCE_BIW3_I,
+ EXT_CNT => EXT_CNT_I,
+ DEST_EXT_CNT => DEST_EXT_CNT_I,
+ REGSEL_20 => REGSEL_20_I,
+ IW_ADR => IW_ADR_I,
+ IW_WR => IW_WR_I,
+ SRC_DESTn => SRC_DESTn_I,
+ EW_WR => EW_WR_I,
+ EW_ADR => EW_ADR_I,
+ RD_BUS => RD_BUS_CTRL,
+ WR_BUS => WR_BUS_CTRL,
+ RDWR_BUS => RDWR_BUS_I,
+ WR_HI => WR_HI_I,
+ SEL_A_HI => SEL_A_HI,
+ SEL_A_MIDHI => SEL_A_MIDHI,
+ SEL_A_MIDLO => SEL_A_MIDLO,
+ SEL_A_LO => SEL_A_LO,
+ SEL_BUFF_A_LO => SEL_BUF_A_LO_CTRL_I,
+ SEL_BUFF_A_HI => SEL_BUF_A_HI_CTRL_I,
+ SEL_BUFF_B_LO => SEL_BUF_B_LO_I,
+ SEL_BUFF_B_HI => SEL_BUF_B_HI_I,
+ FC_OUT => FC_OUT_CTRL,
+ FC_EN => FC_EN_CTRL,
+ PC_INIT => PC_INIT_CTRL,
+ PC_WR => PC_WR_I,
+ PC_INC => PC_INC_I,
+ PC_TMP_CLR => PC_TMP_CLR_I,
+ PC_TMP_INC => PC_TMP_INC_I,
+ SP_ADD_DISPL => SP_ADD_DISPL_I,
+ USP_INC => USP_INC_I,
+ SSP_INC => SSP_INC_I,
+ USP_DEC => USP_DEC_I,
+ SSP_DEC => SSP_DEC_CTRL,
+ USP_CPY => USP_CPY_I,
+ PC_ADD_DISPL => PC_ADD_DISPL_I,
+ ADR_TMP_CLR => ADR_TMP_CLR_I,
+ ADR_TMP_INC => ADR_TMP_INC_I,
+ AR_INC => AR_INC_I,
+ AR_DEC => AR_DEC_I,
+ AR_WR => AR_WR_I,
+ AR_DR_EXG => AR_DR_EXG_I,
+ DR_WR => DR_WR_I,
+ DR_DEC => DR_DEC_I,
+ SCAN_TRAPS => SCAN_TRAPS_I,
+ TRAP_PRIV => TRAP_PRIV_I,
+ TRAP_TRACE => TRAP_TRACE_I,
+ OP => OP_I,
+ OP_MODE => OP_MODE_I(2 downto 0),
+ OP_SIZE => OP_SIZE_I,
+ ADR_MODE => ADR_MODE_I,
+ MOVE_D_AM => MOVE_D_AM_I,
+ RESET_RDY => RESET_RDY_I,
+ OP_BUSY => OP_BUSY_I,
+ MEM_SHFT => MEM_SHFT_I,
+ SHFT_BUSY => SHFT_BUSY_I,
+ DR => DR_I,
+ RM => RM_I,
+ DIV_MUL_32n64 => DIV_MUL_32n64_I,
+ EXEC_RESUME => EXEC_RESUME_I,
+ MOVEM_REGSEL => MOVEM_REGSEL_I,
+ MOVEM_ADn => MOVEM_ADn_I,
+ DBcc_COND => DBcc_COND_I,
+ USE_SP_ADR => USE_SP_ADR_I,
+ OP_START => OP_START_I,
+ TRAP_CHK_EN => TRAP_CHK_EN_I,
+ SHIFTER_LOAD => SHIFTER_LOAD_I,
+ CHK_PC => CHK_PC_I,
+ CHK_ADR => CHK_ADR_I,
+ SBIT => SBIT_I,
+ UNLK_SP_An => UNLK_SP_An_I,
+ RESET_EN => RESET_EN_I
+ );
+
+ I_IRQ_CTRL: WF68K00IP_INTERRUPT_CONTROL
+ port map(
+ CLK => CLK,
+ RESETn => RESET_COREn,
+ RESET_CPUn => RESET_CPU_In,
+ BERR => BERR_I,
+ HALTn => HALT_In,
+ ADR_IN => ADR_I,
+ USE_SSP_ADR => USE_SSP_ADR_I,
+ ADR_EN_VECTOR => ADR_EN_VECTOR_I,
+ DATA_IN => DATA_CORE(7 downto 0),
+ DATA_OUT => IRQ_DOUT,
+ DATA_EN => IRQ_DATA_EN,
+ RWn(0) => RWn_I,
+ RD_BUS => RD_BUS_IRQ,
+ WR_BUS => WR_BUS_IRQ,
+ HALT_EN => HALT_EN_I,
+ FC_IN => FC_OUT_I,
+ FC_OUT => FC_OUT_IRQ,
+ FC_EN => FC_EN_IRQ,
+ SEL_BUFF_A_LO => SEL_BUF_A_LO_IRQ_I,
+ SEL_BUFF_A_HI => SEL_BUF_A_HI_IRQ_I,
+ STATUS_REG_IN => STATUS_REG_I,
+ PC => PC_OUT,
+ INIT_STATUS => INIT_STATUS_I,
+ PRESET_IRQ_MASK => PRESET_IRQ_MASK_I,
+ SSP_DEC => SSP_DEC_IRQ,
+ SSP_INIT => SSP_INIT_I,
+ PC_INIT => PC_INIT_IRQ,
+ BIW_0 => BIW_0_I,
+ BUS_CYC_RDY => BUS_CYC_RDY_I,
+ CTRL_RDY => CTRL_RDY_I,
+ CTRL_EN => CTRL_EN_I,
+ EXEC_ABORT => EXEC_ABORT_I,
+ EXEC_RESUME => EXEC_RESUME_I,
+ IRQ => not IPL_In,
+ AVECn => AVEC_In, -- Originally 68Ks use VPAn.
+ IRQ_SAVE => IRQ_SAVE_I,
+ INT_VECT => INT_VECT_I,
+ USE_INT_VECT => USE_INT_VECT_I,
+ TRAP_AERR => TRAP_AERR_I,
+ TRAP_OP => TRAP_OP_I,
+ TRAP_VECTOR => TRAP_VECTOR_I,
+ TRAP_V => TRAP_V_I,
+ TRAP_CHK => TRAP_CHK_I,
+ TRAP_DIVZERO => TRAP_DIVZERO_I,
+ TRAP_ILLEGAL => TRAP_ILLEGAL_I,
+ TRAP_1010 => TRAP_1010_I,
+ TRAP_1111 => TRAP_1111_I,
+ TRAP_PRIV => TRAP_PRIV_I,
+ TRAP_TRACE => TRAP_TRACE_I
+ );
+
+ I_OPCODE: WF68K00IP_OPCODE_DECODER
+ port map(
+ CLK => CLK,
+ RESETn => RESET_COREn,
+ DATA_IN => DATA,
+ SBIT => SBIT_I,
+ OV => STATUS_REG_I(1),
+ IW_ADR => IW_ADR_I,
+ IW_WR => IW_WR_I,
+ FORCE_BIW2 => FORCE_BIW2_I,
+ FORCE_BIW3 => FORCE_BIW3_I,
+ EXT_CNT => EXT_CNT_I,
+ DEST_EXT_CNT => DEST_EXT_CNT_I,
+ DR => DR_I,
+ RM => RM_I,
+ IR => IR_I,
+ OP => OP_I,
+ OP_MODE => OP_MODE_I,
+ OP_SIZE => OP_SIZE_I,
+ BIW_0 => BIW_0_I,
+ REGSEL_20 => REGSEL_20_I,
+ REGSEL_119 => REGSEL_119_I,
+ REGSEL_INDEX => REGSEL_INDEX,
+ DATA_IMMEDIATE => DATA_IMMEDIATE_I,
+ TRAP_VECTOR => TRAP_VECTOR_I,
+ C_CODE => C_CODE_I,
+ MEM_SHFT => MEM_SHFT_I,
+ REGLISTMASK => REGLISTMASK_I,
+ BITPOS_IM => BITPOS_IM_I,
+ BIT_POS => BIT_POS_OP,
+ DIV_MUL_32n64 => DIV_MUL_32n64_I,
+ REG_Dlq => REGSEL_Dlq,
+ REG_Dhr => REGSEL_Dhr,
+ SCAN_TRAPS => SCAN_TRAPS_I,
+ TRAP_ILLEGAL => TRAP_ILLEGAL_I,
+ TRAP_1010 => TRAP_1010_I,
+ TRAP_1111 => TRAP_1111_I,
+ TRAP_PRIV => TRAP_PRIV_I,
+ TRAP_OP => TRAP_OP_I,
+ TRAP_V => TRAP_V_I,
+ EW_WR => EW_WR_I,
+ EW_ADR => EW_ADR_I,
+ SRC_DESTn => SRC_DESTn_I,
+ EXWORD => EXWORD_I,
+ DEST_EXWORD => DEST_EXWORD_I,
+ ADR_MODE => ADR_MODE_I,
+ MOVE_D_AM => MOVE_D_AM_I,
+ EXT_DSIZE => EXT_DSIZE_I,
+ SEL_DISPLACE_BIW => SEL_DISPLACE_BIW_I,
+ DISPLACE_BIW => DISPLACE_BIW_I
+ );
+
+ I_ADRREG: WF68K00IP_ADDRESS_REGISTERS
+ port map(
+ CLK => CLK,
+ RESETn => RESET_COREn,
+ ADATA_IN => AREG_DATA_IN,
+ REGSEL_B => REGSEL_ADR_B,
+ REGSEL_A => REGSEL_ADR_A,
+ ADR_REG_QB => Q_AREG_B,
+ ADR_REG_QA => Q_AREG_A,
+ USP_OUT => USP_OUT,
+ SSP_OUT => SSP_OUT,
+ PC_OUT => PC_OUT,
+ EXWORD => EXWORD_I,
+ DEST_EXWORD => DEST_EXWORD_I,
+ DR => DR_I,
+ USP_CPY => USP_CPY_I,
+ AR_EXG => AR_DR_EXG_I,
+ USP_INC => USP_INC_I,
+ USP_DEC => USP_DEC_I,
+ ADR_TMP_CLR => ADR_TMP_CLR_I,
+ ADR_TMP_INC => ADR_TMP_INC_I,
+ AR_INC => AR_INC_I,
+ AR_DEC => AR_DEC_I,
+ AR_WR => AR_WR_I,
+ SSP_INC => SSP_INC_I,
+ SSP_DEC => SSP_DEC_I,
+ SSP_INIT => SSP_INIT_I,
+ SP_ADD_DISPL => SP_ADD_DISPL_I,
+ USE_SP_ADR => USE_SP_ADR_I,
+ USE_SSP_ADR => USE_SSP_ADR_I,
+ PC_WR => PC_WR_I,
+ PC_INC => PC_INC_I,
+ PC_TMP_CLR => PC_TMP_CLR_I,
+ PC_TMP_INC => PC_TMP_INC_I,
+ PC_INIT => PC_INIT_I,
+ PC_ADD_DISPL => PC_ADD_DISPL_I,
+ SRC_DESTn => SRC_DESTn_I,
+ SBIT => SBIT_I,
+ OP => OP_I,
+ OP_SIZE => OP_SIZE_I,
+ OP_MODE => OP_MODE_I,
+ OP_START => OP_START_I,
+ ADR_MODE => ADR_MODE_I,
+ MOVE_D_AM => MOVE_D_AM_I,
+ EXT_DSIZE => EXT_DSIZE_I,
+ SEL_DISPLACE_BIW => SEL_DISPLACE_BIW_I,
+ DISPLACE_BIW => DISPLACE_BIW_I,
+ REGSEL_INDEX => REGSEL_DATA_C,
+ INDEX_D_IN => Q_DREG_C,
+ CHK_PC => CHK_PC_I,
+ CHK_ADR => CHK_ADR_I,
+ TRAP_AERR => TRAP_AERR_I,
+ ADR_EFF => ADR_EFF_I
+ );
+
+ I_DATAREG: WF68K00IP_DATA_REGISTERS
+ port map(
+ CLK => CLK,
+ RESETn => RESET_COREn,
+ DATA_IN_A => DREG_DATA_IN_A,
+ DATA_IN_B => DREG_DATA_IN_B,
+ REGSEL_A => REGSEL_DATA_A,
+ REGSEL_B => REGSEL_DATA_B,
+ REGSEL_C => REGSEL_DATA_C,
+ DIV_MUL_32n64 => DIV_MUL_32n64_I,
+ DATA_OUT_A => Q_DREG_A,
+ DATA_OUT_B => Q_DREG_B,
+ DATA_OUT_C => Q_DREG_C,
+ DR_EXG => AR_DR_EXG_I,
+ DR_WR => DR_WR_I,
+ DR_DEC => DR_DEC_I,
+ OP => OP_I,
+ OP_SIZE => OP_SIZE_I,
+ OP_MODE => OP_MODE_I,
+ DBcc_COND => DBcc_COND_I
+ );
+
+ I_ALU: WF68K00IP_ALU
+ port map(
+ CLK => CLK,
+ RESETn => RESET_COREn,
+ OP_SIZE => OP_SIZE_I,
+ OP => OP_I,
+ XNZVC_IN => STATUS_REG_I(4 downto 0),
+ XNZVC_OUT => XNZVC_ALU,
+ OP_IN_S => ALU_OP_IN_S,
+ OP_IN_D_HI => ALU_OP_IN_D_HI,
+ OP_IN_D_LO => ALU_OP_IN_D_LO,
+ RESULT_HI => RESULT_ALU_HI,
+ RESULT_LO => RESULT_ALU_LO,
+ OP_START => OP_START_I,
+ TRAP_CHK_EN => TRAP_CHK_EN_I,
+ DIV_MUL_32n64 => DIV_MUL_32n64_I,
+ OP_BUSY => OP_BUSY_I,
+ TRAP_CHK => TRAP_CHK_I,
+ TRAP_DIVZERO => TRAP_DIVZERO_I
+ );
+
+ I_SHFT: WF68K00IP_SHIFTER
+ port map(
+ CLK => CLK,
+ RESETn => RESET_COREn,
+ DATA_IN => SHFT_OP_IN,
+ DATA_OUT => RESULT_SHFT,
+ OP => OP_I,
+ OP_SIZE => OP_SIZE_I,
+ BIT_POS => BIT_POS_I,
+ CNT_NR => CNT_NR_I,
+ SHFT_BREAKn => not EXEC_ABORT_I,
+ SHIFTER_LOAD => SHIFTER_LOAD_I,
+ SHFT_BUSY => SHFT_BUSY_I,
+ XNZVC_IN => STATUS_REG_I(4 downto 0),
+ XNZVC_OUT => XNZVC_SHFT
+ );
+
+ I_BUS_IF: WF68K00IP_BUS_INTERFACE
+ port map(
+ CLK => CLK,
+ RESETn => RESET_COREn,
+ RESET_INn => RESET_IN_In,
+ RESET_OUT_EN => RESET_OUT_EN_I,
+ RESET_CPUn => RESET_CPU_In,
+ RESET_EN => RESET_EN_I,
+ RESET_RDY => RESET_RDY_I,
+ DATA_IN => DATA,
+ SEL_A_HI => SEL_A_HI,
+ SEL_A_MIDHI => SEL_A_MIDHI,
+ SEL_A_MIDLO => SEL_A_MIDLO,
+ SEL_A_LO => SEL_A_LO,
+ SEL_BUFF_A_LO => SEL_BUF_A_LO_I,
+ SEL_BUFF_A_HI => SEL_BUF_A_HI_I,
+ SEL_BUFF_B_LO => SEL_BUF_B_LO_I,
+ SEL_BUFF_B_HI => SEL_BUF_B_HI_I,
+ SYS_INIT => SYS_INIT_I,
+ OP_SIZE => OP_SIZE_I,
+ BUFFER_A => BUS_BUFFER_A,
+ BUFFER_B => BUS_BUFFER_B,
+ DATA_CORE_OUT => DATA_CORE,
+ RD_BUS => RD_BUS_I,
+ WR_BUS => WR_BUS_I,
+ RDWR_BUS => RDWR_BUS_I,
+ A0 => ADR_I(0),
+ BYTEn_WORD => BYTEn_WORD_I,
+ EXEC_ABORT => EXEC_ABORT_I,
+ BUS_CYC_RDY => BUS_CYC_RDY_I,
+ DATA_VALID => DATA_VALID_I,
+ DTACKn => DTACK_In,
+ BERRn => BERR_In,
+ AVECn => AVEC_In,
+ HALTn => HALT_In,
+ ADR_EN => ADR_EN_I,
+ WR_HI => WR_HI_I,
+ HI_WORD_EN => HI_WORD_EN_I,
+ HI_BYTE_EN => HI_BYTE_EN_I,
+ LO_BYTE_EN => LO_BYTE_EN_I,
+ FC_EN => FC_EN_I,
+ ASn => AS_In,
+ AS_EN => AS_EN_I,
+ UDSn => UDS_In,
+ UDS_EN => UDS_EN_I,
+ LDSn => LDS_In,
+ LDS_EN => LDS_EN_I,
+ RWn => RWn_I,
+ RW_EN => RW_EN_I,
+ VPAn => VPA_In,
+ VMAn => VMA_In,
+ VMA_EN => VMA_EN_I,
+ E => E,
+ BRn => BR_In,
+ BGACKn => BGACK_In,
+ BGn => BGn
+ );
+end STRUCTURE;
diff --git a/common/CPU/68000/wf_68k00_ip/wf68k00ip_top_soc.vhd b/common/CPU/68000/wf_68k00_ip/wf68k00ip_top_soc.vhd
new file mode 100644
index 00000000..202b0841
--- /dev/null
+++ b/common/CPU/68000/wf_68k00_ip/wf68k00ip_top_soc.vhd
@@ -0,0 +1,1041 @@
+----------------------------------------------------------------------
+---- ----
+---- MC68000 compatible IP Core ----
+---- ----
+---- This file is part of the SUSKA ATARI clone project. ----
+---- http://www.experiment-s.de ----
+---- ----
+---- Description: ----
+---- This model provides an opcode and bus timing compatible ip ----
+---- core compared to Motorola's MC68000 microprocessor. ----
+---- ----
+---- The following operations are additionally supported by this ----
+---- core: ----
+---- - LINK (long). ----
+---- - MOVE FROM CCR. ----
+---- - MULS, MULU: all operation modes word and long. ----
+---- - DIVS, DIVU: all operation modes word and long. ----
+---- - DIVSL, DIVUL. ----
+---- - Direct addressing mode enhancements for TST etc. ----
+---- - PC relative addressing modes for operations like TST. ----
+---- ----
+---- This file is the top level file of the ip core. ----
+---- It is intended for use in systems on programmable chips. ----
+---- ----
+---- ----
+---- ----
+---- ----
+---- Author(s): ----
+---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
+---- ----
+----------------------------------------------------------------------
+---- ----
+---- Copyright (C) 2006 - 2008 Wolfgang Foerster ----
+---- ----
+---- This source file 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 2 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, write to the Free ----
+---- Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ----
+---- Boston, MA 02110-1301, USA. ----
+---- ----
+----------------------------------------------------------------------
+--
+-- Revision History
+--
+-- Revision 2K6B 2006/12/24 WF
+-- Initial Release.
+-- Top level file provided for SOC (systems on programmable chips).
+-- Revision 2K7B 2007/12/24 WF
+-- Several bugfixes in the modules.
+-- Optimized the core (reduced the core size 10%).
+-- Revision 2K8A 2008/07/14 WF
+-- Modified the interrupt controller behaviour.
+-- A couple of bug fixes in all modules.
+-- Deactivated the MOVE_FROM_CCR in the opcode decoder due to
+-- compatibility reasons.
+-- Some optimizations concerning core size.
+--
+
+library work;
+use work.wf68k00ip_pkg.all;
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+
+entity WF68K00IP_TOP_SOC is
+ port (
+ CLK : in bit;
+ RESET_COREn : in bit; -- Core reset.
+
+ -- Address and data:
+ ADR_OUT : out std_logic_vector(23 downto 1);
+ ADR_EN : out bit;
+ DATA_IN : in std_logic_vector(15 downto 0);
+ DATA_OUT : out std_logic_vector(15 downto 0);
+ DATA_EN : out bit;
+
+ -- System control:
+ BERRn : in bit;
+ RESET_INn : in bit;
+ RESET_OUT_EN : out bit; -- Open drain.
+ HALT_INn : in std_logic;
+ HALT_OUT_EN : out bit; -- Open drain.
+
+ -- Processor status:
+ FC_OUT : out std_logic_vector(2 downto 0);
+ FC_OUT_EN : out bit;
+
+ -- Interrupt control:
+ AVECn : in bit; -- Originally 68Ks use VPAn.
+ IPLn : in std_logic_vector(2 downto 0);
+
+ -- Aynchronous bus control:
+ DTACKn : in bit;
+ AS_OUTn : out bit;
+ AS_OUT_EN : out bit;
+ RWn_OUT : out bit;
+ RW_OUT_EN : out bit;
+ UDS_OUTn : out bit;
+ UDS_OUT_EN : out bit;
+ LDS_OUTn : out bit;
+ LDS_OUT_EN : out bit;
+
+ -- Synchronous peripheral control:
+ E : out bit;
+ VMA_OUTn : out bit;
+ VMA_OUT_EN : out bit;
+ VPAn : in bit;
+
+ -- Bus arbitration control:
+ BRn : in bit;
+ BGn : out bit;
+ BGACKn : in bit
+ );
+end entity WF68K00IP_TOP_SOC;
+
+architecture STRUCTURE of WF68K00IP_TOP_SOC is
+signal ADR_EFF_I : std_logic_vector(31 downto 0);
+signal ADR_EN_I : bit;
+signal ADR_EN_VECTOR_I : bit;
+signal ADR_I : std_logic_vector(31 downto 0);
+signal ADR_MODE_I : std_logic_vector(2 downto 0);
+signal ADR_TMP_CLR_I : bit;
+signal ADR_TMP_INC_I : bit;
+signal ALU_OP_IN_S : std_logic_vector(31 downto 0);
+signal ALU_OP_IN_D_HI : std_logic_vector(31 downto 0);
+signal ALU_OP_IN_D_LO : std_logic_vector(31 downto 0);
+signal AR_INC_I : bit;
+signal AR_DEC_I : bit;
+signal AR_WR_I : bit;
+signal AR_DR_EXG_I : bit;
+signal AREG_DATA_IN : std_logic_vector(31 downto 0);
+signal AS_EN_I : bit;
+signal AS_In : bit;
+signal AVEC_In : bit;
+signal BERR_In : bit;
+signal BERR_I : bit;
+signal BGACK_In : bit;
+signal BIT_POS_I : std_logic_vector(4 downto 0);
+signal BIT_POS_OP : std_logic_vector(4 downto 0);
+signal BITPOS_IM_I : bit;
+signal BIW_0_I : std_logic_vector(15 downto 0);
+signal BR_In : bit;
+signal BUS_BUFFER_A : std_logic_vector(31 downto 0);
+signal BUS_BUFFER_B : std_logic_vector(31 downto 0);
+signal BUS_CYC_RDY_I : bit;
+signal BYTEn_WORD_I : bit;
+signal C_CODE_I : bit_vector(3 downto 0);
+signal CHK_ADR_I : bit;
+signal CHK_PC_I : bit;
+signal CNT_NR_I : std_logic_vector(5 downto 0);
+signal CTRL_EN_I : bit;
+signal CTRL_RDY_I : bit;
+signal DATA_CORE : std_logic_vector(15 downto 0);
+signal DATA_IMMEDIATE_I : std_logic_vector(31 downto 0);
+signal DATA_OUT_I : std_logic_vector(31 downto 0);
+signal DATA_VALID_I : bit;
+signal DBcc_COND_I : boolean;
+signal DEST_EXWORD_I : EXWORDTYPE;
+signal DEST_EXT_CNT_I : integer range 0 to 2;
+signal DISPLACE_BIW_I : std_logic_vector(31 downto 0);
+signal DIV_MUL_32n64_I : bit;
+signal DR_I : bit;
+signal DR_DEC_I : bit;
+signal DR_WR_I : bit;
+signal DREG_DATA_IN_A : std_logic_vector(31 downto 0);
+signal DREG_DATA_IN_B : std_logic_vector(31 downto 0);
+signal DTACK_In : bit;
+signal EW_WR_I : bit;
+signal EW_ADR_I : integer range 0 to 1;
+signal EXEC_ABORT_I : bit;
+signal EXEC_RESUME_I : bit;
+signal EXT_CNT_I : integer range 0 to 2;
+signal EXT_DSIZE_I : D_SIZETYPE;
+signal EXWORD_I : EXWORDTYPE;
+signal FC_EN_CTRL : bit;
+signal FC_EN_I : bit;
+signal FC_EN_IRQ : bit;
+signal FC_OUT_CTRL : std_logic_vector(2 downto 0);
+signal FC_OUT_I : std_logic_vector(2 downto 0);
+signal FC_OUT_IRQ : std_logic_vector(2 downto 0);
+signal FORCE_BIW2_I : bit;
+signal FORCE_BIW3_I : bit;
+signal HALT_In : std_logic;
+signal HI_BYTE_EN_I : bit;
+signal HI_WORD_EN_I : bit;
+signal INT_VECT_I : std_logic_vector(9 downto 0);
+signal INIT_STATUS_I : bit;
+signal IPL_In : std_logic_vector(2 downto 0);
+signal IPL_TMPn : std_logic_vector(2 downto 0);
+signal IR_I : bit;
+signal IRQ_DATA_EN : bit;
+signal IRQ_DOUT : std_logic_vector(15 downto 0);
+signal IRQ_SAVE_I : bit;
+signal IW_ADR_I : integer range 0 to 2;
+signal IW_WR_I : bit;
+signal LDS_EN_I : bit;
+signal LDS_In : bit;
+signal LO_BYTE_EN_I : bit;
+signal MOVE_D_AM_I : std_logic_vector(2 downto 0);
+signal MEM_SHFT_I : bit;
+signal MOVEM_ADn_I : bit;
+signal MOVEM_REGSEL_I : std_logic_vector(2 downto 0);
+signal PC_ADD_DISPL_I : bit;
+signal OP_BUSY_I : bit;
+signal OP_I : OP_68K00;
+signal OP_MODE_I : std_logic_vector(4 downto 0);
+signal OP_SIZE_I : OP_SIZETYPE;
+signal OP_START_I : bit;
+signal PC_INC_I : bit;
+signal PC_INIT_I : bit;
+signal PC_INIT_CTRL : bit;
+signal PC_INIT_IRQ : bit;
+signal PC_OUT : std_logic_vector(31 downto 0);
+signal PC_TMP_CLR_I : bit;
+signal PC_TMP_INC_I : bit;
+signal PC_WR_I : bit;
+signal PRESET_IRQ_MASK_I : bit;
+signal Q_AREG_A : std_logic_vector(31 downto 0);
+signal Q_AREG_B : std_logic_vector(31 downto 0);
+signal Q_DREG_A : std_logic_vector(31 downto 0);
+signal Q_DREG_B : std_logic_vector(31 downto 0);
+signal Q_DREG_C : std_logic_vector(31 downto 0);
+signal RD_BUS_CTRL : bit;
+signal RD_BUS_IRQ : bit;
+signal RD_BUS_I : bit;
+signal RDWR_BUS_I : bit;
+signal REGLISTMASK_I : std_logic_vector(15 downto 0);
+signal REGSEL_119_I : std_logic_vector(2 downto 0);
+signal REGSEL_20_I : std_logic_vector(2 downto 0);
+signal REGSEL_ADR_A : std_logic_vector(2 downto 0);
+signal REGSEL_ADR_B : std_logic_vector(2 downto 0);
+signal REGSEL_DATA_A : std_logic_vector(2 downto 0);
+signal REGSEL_DATA_B : std_logic_vector(2 downto 0);
+signal REGSEL_DATA_C : std_logic_vector(2 downto 0);
+signal REGSEL_Dhr : std_logic_vector(2 downto 0);
+signal REGSEL_Dlq : std_logic_vector(2 downto 0);
+signal REGSEL_INDEX : std_logic_vector(2 downto 0);
+signal RESET_CPU_In : bit;
+signal RESET_EN_I : bit;
+signal RESET_IN_In : bit;
+signal RESET_RDY_I : bit;
+signal RESULT_ALU_HI : std_logic_vector(31 downto 0);
+signal RESULT_ALU_LO : std_logic_vector(31 downto 0);
+signal RESULT_SHFT : std_logic_vector(31 downto 0);
+signal RM_I : bit;
+signal RW_EN_I : bit;
+signal RWn_I : bit;
+signal SBIT_I : bit;
+signal SCAN_TRAPS_I : bit;
+signal Scc_COND_I : boolean;
+signal SEL_A_LO : bit;
+signal SEL_A_HI : bit;
+signal SEL_A_MIDHI : bit;
+signal SEL_A_MIDLO : bit;
+signal SEL_BUF_A_LO_I : bit;
+signal SEL_BUF_A_HI_I : bit;
+signal SEL_BUF_A_LO_CTRL_I : bit;
+signal SEL_BUF_A_HI_CTRL_I : bit;
+signal SEL_BUF_A_LO_IRQ_I : bit;
+signal SEL_BUF_A_HI_IRQ_I : bit;
+signal SEL_BUF_B_LO_I : bit;
+signal SEL_BUF_B_HI_I : bit;
+signal SEL_DISPLACE_BIW_I : bit;
+signal SHFT_BUSY_I : bit;
+signal SHFT_OP_IN : std_logic_vector(31 downto 0);
+signal SHIFTER_LOAD_I : bit;
+signal SP_ADD_DISPL_I : bit;
+signal SR_CCR_MUX : std_logic_vector(15 downto 0);
+signal SRC_DESTn_I : bit;
+signal SSP_DEC_CTRL : bit;
+signal SSP_DEC_I : bit;
+signal SSP_DEC_IRQ : bit;
+signal SSP_INC_I : bit;
+signal SSP_INIT_I : bit;
+signal SSP_OUT : std_logic_vector(31 downto 0);
+signal STATUS_REG_I : std_logic_vector(15 downto 0);
+signal SYS_INIT_I : bit;
+signal TRAP_1010_I : bit;
+signal TRAP_1111_I : bit;
+signal TRAP_AERR_I : bit;
+signal TRAP_CHK_I : bit;
+signal TRAP_CHK_EN_I : bit;
+signal TRAP_DIVZERO_I : bit;
+signal TRAP_ILLEGAL_I : bit;
+signal TRAP_OP_I : bit;
+signal TRAP_PRIV_I : bit;
+signal TRAP_TRACE_I : bit;
+signal TRAP_V_I : bit;
+signal TRAP_VECTOR_I : std_logic_vector(3 downto 0);
+signal UDS_EN_I : bit;
+signal UDS_In : bit;
+signal UNLK_SP_An_I : bit;
+signal USP_CPY_I : bit;
+signal USP_DEC_I : bit;
+signal USP_INC_I : bit;
+signal USE_INT_VECT_I : bit;
+signal USP_OUT : std_logic_vector(31 downto 0);
+signal USE_SP_ADR_I : bit;
+signal USE_SSP_ADR_I : bit;
+signal VMA_EN_I : bit;
+signal VMA_In : bit;
+signal VPA_In : bit;
+signal WR_BUS_CTRL : bit;
+signal WR_BUS_I : bit;
+signal WR_BUS_IRQ : bit;
+signal WR_HI_I : bit;
+signal XNZVC_ALU : std_logic_vector(4 downto 0);
+signal XNZVC_I : std_logic_vector(4 downto 0);
+signal XNZVC_SHFT : std_logic_vector(4 downto 0);
+begin
+ SIGNAL_SAMPLE: process
+ -- The bus control signals used in this core are sampled on the negative clock
+ -- edge. Thus the signals are valid on the following positive clock edge. In the original
+ -- 68K machines, the input synchronisation is realized with three latches (see the 68K
+ -- user manual for more information). This concept is not suitable for a FPGA design
+ -- and therefore not used here.
+ begin
+ wait until CLK = '0' and CLK' event;
+ BERR_In <= BERRn;
+ HALT_In <= HALT_INn;
+ VPA_In <= VPAn;
+ BR_In <= BRn;
+ BGACK_In <= BGACKn;
+ RESET_IN_In <= RESET_INn;
+ AVEC_In <= AVECn;
+ end process SIGNAL_SAMPLE;
+
+ IPL_SAMPLE: process
+ -- This process provides a filter for the interrupt priority level. It
+ -- is valid, if it is stable for two consecutive falling clock edges.
+ begin
+ wait until CLK = '0' and CLK' event;
+ IPL_TMPn <= IPLn;
+ if IPL_TMPn = IPLn then
+ IPL_In <= IPLn;
+ else
+ IPL_In <= "111";
+ end if;
+ end process IPL_SAMPLE;
+
+ BERR_I <= '1' when BERR_In = '0' and HALT_In = '1' and DTACK_In = '1' else
+ '1' when BERR_In = '0' and HALT_In = '0' and RDWR_BUS_I = '1' else '0'; -- No retry during read modify write cycles.
+
+ -- The following input may not be sampled
+ -- due to bus timing constraints.
+ DTACK_In <= DTACKn;
+
+ -- Data output multiplexer (tri-state):
+ -- During long word access, the higher word is written always 16 bit wide. During word or byte access,
+ -- the access of the higher 8 bits or the lower 8 bits depends on the address boundary or on the
+ -- length of the operator defined in the operation (WORD, BYTE).
+ DATA_EN <= IRQ_DATA_EN or HI_BYTE_EN_I or LO_BYTE_EN_I or HI_WORD_EN_I;
+ DATA_OUT <= IRQ_DOUT when IRQ_DATA_EN = '1' else
+ DATA_OUT_I(31 downto 24) & "00000000" when SEL_A_HI = '1' and HI_BYTE_EN_I = '1' else -- MOVEP.
+ "00000000" & DATA_OUT_I(31 downto 24) when SEL_A_HI = '1' and LO_BYTE_EN_I = '1' else -- MOVEP.
+ DATA_OUT_I(23 downto 16) & "00000000" when SEL_A_MIDHI = '1' and HI_BYTE_EN_I = '1' else -- MOVEP.
+ "00000000" & DATA_OUT_I(23 downto 16) when SEL_A_MIDHI = '1' and LO_BYTE_EN_I = '1' else -- MOVEP.
+ DATA_OUT_I(15 downto 8) & "00000000" when SEL_A_MIDLO = '1' and HI_BYTE_EN_I = '1' else -- MOVEP.
+ "00000000" & DATA_OUT_I(15 downto 8) when SEL_A_MIDLO = '1' and LO_BYTE_EN_I = '1' else -- MOVEP.
+ DATA_OUT_I(7 downto 0) & "00000000" when SEL_A_LO = '1' and HI_BYTE_EN_I = '1' else -- MOVEP.
+ "00000000" & DATA_OUT_I(7 downto 0) when SEL_A_LO = '1' and LO_BYTE_EN_I = '1' else -- MOVEP.
+ DATA_OUT_I(31 downto 16) when HI_WORD_EN_I = '1' else
+ DATA_OUT_I(15 downto 0) when HI_BYTE_EN_I = '1' and LO_BYTE_EN_I = '1' else
+ DATA_OUT_I(7 downto 0) & "00000000" when HI_BYTE_EN_I = '1' else
+ "00000000" & DATA_OUT_I(7 downto 0) when LO_BYTE_EN_I = '1' else (others => '0');
+
+ -- Bus controls:
+ AS_OUTn <= AS_In;
+ AS_OUT_EN <= AS_EN_I;
+ RWn_OUT <= RWn_I;
+ RW_OUT_EN <= RW_EN_I;
+ UDS_OUTn <= UDS_In;
+ UDS_OUT_EN <= UDS_EN_I;
+ LDS_OUTn <= LDS_In;
+ LDS_OUT_EN <= LDS_EN_I;
+
+ VMA_OUTn <= VMA_In;
+ VMA_OUT_EN <= VMA_EN_I;
+
+ -- The function code:
+ FC_OUT_EN <= FC_EN_I;
+ FC_OUT <= FC_OUT_I;
+ FC_OUT_I <= FC_OUT_CTRL when FC_EN_CTRL = '1' else
+ FC_OUT_IRQ when FC_EN_IRQ = '1' else (others => '0');
+
+ SYS_INIT_I <= '1' when SEL_BUF_A_HI_IRQ_I = '1' or SEL_BUF_A_LO_IRQ_I = '1' else '0';
+
+ -- Bus access control:
+ BYTEn_WORD_I <= '1' when FC_OUT_I = "110" else -- Supervisor program.
+ '1' when FC_OUT_I = "010" else -- User program.
+ '1' when USE_SP_ADR_I = '1' else -- During stacking.
+ '1' when USE_SSP_ADR_I = '1' else -- During stacking.
+ '1' when USE_INT_VECT_I = '1' else -- During interrupt handling.
+ '0' when OP_SIZE_I = BYTE else
+ '0' when OP_I = MOVEP else '1';
+
+ -- Bus buffer A control:
+ SEL_BUF_A_HI_I <= SEL_BUF_A_HI_CTRL_I or SEL_BUF_A_HI_IRQ_I;
+ SEL_BUF_A_LO_I <= SEL_BUF_A_LO_CTRL_I or SEL_BUF_A_LO_IRQ_I;
+
+ -- Some of the controls are asserted by the main control state machine or
+ -- by the interrupt control state machine but never by both at the same
+ -- time. So the related signal can be 'ored'; no malfuntion results.
+ SSP_DEC_I <= SSP_DEC_CTRL or SSP_DEC_IRQ;
+ RD_BUS_I <= RD_BUS_CTRL or RD_BUS_IRQ;
+ WR_BUS_I <= WR_BUS_CTRL or WR_BUS_IRQ;
+ PC_INIT_I <= PC_INIT_CTRL or PC_INIT_IRQ;
+
+ -- Count value for the shifter unit. It is valid during the shift operations:
+ CNT_NR_I <= "000001" when MEM_SHFT_I = '1' else -- Memory shifts are 1 bit only.
+ "000" & REGSEL_119_I when IR_I = '0' and REGSEL_119_I > "000" else
+ "001000" when IR_I = '0' else -- Shift 8 bits for REGSEL_119 = "000".
+ Q_DREG_A(5 downto 0); -- Register contents modulo 64.
+
+ -- Bit operation position multiplexer:
+ -- Register bit manipulations are modulo 32 whereas memory bit manipulations are modulo 8.
+ BIT_POS_I <= BIT_POS_OP when BITPOS_IM_I = '1' and ADR_MODE_I = "000" else
+ Q_DREG_A(4 downto 0) when ADR_MODE_I = "000" else
+ "00" & BIT_POS_OP(2 downto 0) when BITPOS_IM_I = '1' else "00" & Q_DREG_A(2 downto 0);
+
+ -- The condition codes:
+ with OP_I select
+ XNZVC_I <= XNZVC_SHFT when BCHG | BCLR | BSET | BTST,
+ XNZVC_SHFT when ASL | ASR | LSL | LSR | ROTL | ROTR | ROXL | ROXR,
+ XNZVC_ALU when others;
+
+ -- Address select stuff:
+ -- The internal address space is 32 bit long. The 68K00 has 23 addresslines.
+ -- The internal address space is therefore limited to 24 bit.
+ ADR_OUT <= ADR_I(23 downto 1);
+ ADR_EN <= ADR_EN_I;
+ ADR_I <= x"FFFFFFF" & STATUS_REG_I(10 downto 8) & '1' when ADR_EN_VECTOR_I = '1' else -- Interrupt acknowledge cycle.
+ SSP_OUT when USE_SSP_ADR_I = '1' else -- During exceptions stacking.
+ x"00000" & "00" & INT_VECT_I when USE_INT_VECT_I = '1' else -- During access to the exception vectors.
+ SSP_OUT when USE_SP_ADR_I = '1' and SBIT_I = '1' else -- During stack pointer operations.
+ USP_OUT when USE_SP_ADR_I = '1' and SBIT_I = '0' else -- During stack pointer operations.
+ PC_OUT when FC_OUT_CTRL = "010" or FC_OUT_CTRL = "110" else -- Program space.
+ ADR_EFF_I; -- Data space.
+
+ -- Status register multiplexer:
+ -- The default is valid for MOVE_TO_CCR from memory, MOVE_TO_SR from memory,
+ -- for the RTR and for stack restoring during exception handling.
+ SR_CCR_MUX <= RESULT_ALU_LO(15 downto 0) when OP_I = ANDI_TO_SR or OP_I = EORI_TO_SR or OP_I = ORI_TO_SR else
+ RESULT_ALU_LO(15 downto 0) when OP_I = ANDI_TO_CCR or OP_I = EORI_TO_CCR or OP_I = ORI_TO_CCR else
+ Q_DREG_B(15 downto 0) when (OP_I = MOVE_TO_CCR or OP_I = MOVE_TO_SR) and ADR_MODE_I = "000" else
+ DATA_IMMEDIATE_I(15 downto 0) when OP_I = MOVE_TO_CCR and ADR_MODE_I = "111" and REGSEL_20_I = "100" else
+ DATA_IMMEDIATE_I(15 downto 0) when OP_I = MOVE_TO_SR and ADR_MODE_I = "111" and REGSEL_20_I = "100" else
+ DATA_IMMEDIATE_I(15 downto 0) when OP_I = STOP else DATA_CORE;
+
+ -- Note: the address register is never destination during MOVE.
+ -- Note: The default is also valid for UNLK during writing to the stack pointer.h
+ REGSEL_ADR_A <= REGSEL_20_I when (OP_I = ADDQ or OP_I = SUBQ) and ADR_MODE_I = "001" else
+ REGSEL_20_I when (OP_I = LINK or OP_I = MOVE) else
+ REGSEL_20_I when OP_I = UNLK and UNLK_SP_An_I = '0' else
+ MOVEM_REGSEL_I when OP_I = MOVEM else REGSEL_119_I;
+
+ REGSEL_ADR_B <= REGSEL_119_I when SRC_DESTn_I = '0' else REGSEL_20_I;
+
+ REGSEL_DATA_A <= REGSEL_20_I when OP_I = ABCD or OP_I = ADDX or OP_I = SBCD or OP_I = SUBX else
+ REGSEL_20_I when OP_I = ADD or OP_I = SUB else
+ REGSEL_20_I when OP_I = AND_B or OP_I = OR_B else
+ REGSEL_Dlq when (OP_I = MULS or OP_I = MULU) and OP_SIZE_I = LONG else
+ REGSEL_Dlq when (OP_I = DIVS or OP_I = DIVU) and OP_SIZE_I = LONG else REGSEL_119_I;
+
+ REGSEL_DATA_B <= MOVEM_REGSEL_I when OP_I = MOVEM else
+ REGSEL_119_I when OP_I = ABCD or OP_I = ADDX or OP_I = SBCD or OP_I = SUBX else
+ REGSEL_119_I when OP_I = ADD or OP_I = SUB else
+ REGSEL_119_I when OP_I = AND_B or OP_I = OR_B else
+ REGSEL_Dhr when (OP_I = DIVS or OP_I = DIVU) and DR_WR_I = '1' else -- Used for write back the result.
+ REGSEL_Dhr when (OP_I = MULS or OP_I = MULU) and DR_WR_I = '1' else -- Used for write back the result.
+ REGSEL_119_I when OP_I = MOVEQ else REGSEL_20_I;
+
+ REGSEL_DATA_C <= REGSEL_Dhr when (OP_I = DIVS or OP_I = DIVU) and OP_START_I = '1' else REGSEL_INDEX;
+
+ DATA_OUT_I <= RESULT_ALU_LO when (OP_I = ABCD or OP_I = SBCD) else
+ RESULT_ALU_LO when (OP_I = ADDX or OP_I = NEGX or OP_I = SUBX) else
+ RESULT_ALU_LO when (OP_I = ADD or OP_I = SUB) else
+ RESULT_ALU_LO when (OP_I = ADDI or OP_I = SUBI) else
+ RESULT_ALU_LO when (OP_I = ADDQ or OP_I = SUBQ) else
+ RESULT_ALU_LO when (OP_I = AND_B or OP_I = OR_B) else
+ RESULT_ALU_LO when (OP_I = ANDI or OP_I = EORI or OP_I = ORI) else
+ RESULT_SHFT when (OP_I = ASL or OP_I = ASR) else
+ RESULT_SHFT when (OP_I = LSL or OP_I = LSR) else
+ RESULT_SHFT when (OP_I = ROTL or OP_I = ROTR) else
+ RESULT_SHFT when (OP_I = ROXL or OP_I = ROXR) else
+ RESULT_SHFT when (OP_I = BCHG or OP_I = BSET or OP_I = BCLR) else
+ x"00000000" when OP_I = CLR else
+ Q_DREG_B when OP_I = MOVE and ADR_MODE_I = "000" else
+ Q_AREG_A when OP_I = MOVE and ADR_MODE_I = "001" else
+ DATA_IMMEDIATE_I when OP_I = MOVE and ADR_MODE_I = "111" and REGSEL_20_I = "100" else
+ BUS_BUFFER_A when OP_I = MOVE else
+ x"000000" & "000" & STATUS_REG_I(4 downto 0) when OP_I = MOVE_FROM_CCR else
+ x"0000" & STATUS_REG_I when OP_I = MOVE_FROM_SR else
+ Q_DREG_B when OP_I = MOVEM and MOVEM_ADn_I = '0' else
+ Q_AREG_A when OP_I = MOVEM and MOVEM_ADn_I = '1' else
+ Q_DREG_A when OP_I = MOVEP else
+ RESULT_ALU_LO when (OP_I = NBCD or OP_I = NEG or OP_I = NOT_B) else
+ ADR_EFF_I when OP_I = PEA else
+ x"FFFFFFFF" when OP_I = Scc and Scc_COND_I = true else
+ x"00000000" when OP_I = Scc else
+ PC_OUT + "10" when (OP_I = JSR or OP_I = BSR) else -- Push the following address to the stack.
+ Q_AREG_B when OP_I = LINK else RESULT_ALU_LO; -- The default is valid for the TAS operation.
+
+ -- Data register source: The required sign extensions for the operation
+ -- MOVEM and MOVEQ are computed in the data register unit.
+ DREG_DATA_IN_B <= RESULT_ALU_LO when (OP_I = ABCD or OP_I = SBCD) else
+ RESULT_ALU_LO when (OP_I = ADDX or OP_I = NEGX or OP_I = SUBX) else
+ RESULT_ALU_LO when (OP_I = ADD or OP_I = SUB) else
+ RESULT_ALU_LO when (OP_I = ADDI or OP_I = SUBI) else
+ RESULT_ALU_LO when (OP_I = ADDQ or OP_I = SUBQ) else
+ RESULT_ALU_LO when (OP_I = AND_B or OP_I = OR_B) else
+ RESULT_ALU_LO when (OP_I = ANDI or OP_I = EORI or OP_I = ORI) else
+ RESULT_ALU_LO when (OP_I = NBCD or OP_I = NEG or OP_I = NOT_B) else
+ RESULT_ALU_HI when (OP_I = DIVS or OP_I = DIVU) else
+ RESULT_ALU_HI when (OP_I = MULS or OP_I = MULU) else
+ RESULT_SHFT when (OP_I = ASL or OP_I = ASR) else
+ RESULT_SHFT when (OP_I = LSL or OP_I = LSR) else
+ RESULT_SHFT when (OP_I = ROTL or OP_I = ROTR) else
+ RESULT_SHFT when (OP_I = ROXL or OP_I = ROXR) else
+ RESULT_SHFT when (OP_I = BCHG or OP_I = BSET or OP_I = BCLR) else
+ Q_DREG_B when OP_I = EXG and OP_MODE_I = "01000" else -- Exchange two data registers.
+ BUS_BUFFER_A when OP_I = MOVEM else
+ DATA_IMMEDIATE_I when OP_I = MOVEQ else
+ x"FFFFFFFF" when OP_I = Scc and Scc_COND_I = true else
+ x"00000000" when OP_I = Scc else
+ x"00000000" when OP_I = CLR else
+ x"000000" & "000" & STATUS_REG_I(4 downto 0) when OP_I = MOVE_FROM_CCR else
+ x"0000" & STATUS_REG_I when OP_I = MOVE_FROM_SR else RESULT_ALU_LO; -- Default used for EXT, SWAP, TAS.
+
+ DREG_DATA_IN_A <= Q_DREG_B when OP_I = MOVE and ADR_MODE_I = "000" else -- Data to data register.
+ Q_AREG_B when OP_I = MOVE and ADR_MODE_I = "001" else -- Address to data register.
+ Q_DREG_A when OP_I = EXG and OP_MODE_I = "01000" else -- Exchange two data registers.
+ Q_AREG_B when OP_I = EXG else -- Exchange data and address registers.
+ DATA_IMMEDIATE_I when OP_I = MOVE and ADR_MODE_I = "111" and REGSEL_20_I = "100" else
+ BUS_BUFFER_A when (OP_I = MOVE or OP_I = MOVEP) else RESULT_ALU_LO; -- Default for DIVS, MULS and MULU.
+
+ -- Address register source: The required sign extension for the operation
+ -- MOVEA and MOVEM are computed in the address register unit.
+ -- Note: this logic is priority sensitive!
+ AREG_DATA_IN <= BUS_BUFFER_A when CTRL_RDY_I = '1' else -- For interrupt handling (init PC, SSP).
+ RESULT_ALU_LO when (OP_I = ADDA or OP_I = SUBA) else
+ RESULT_ALU_LO when (OP_I = ADDQ or OP_I = SUBQ) else
+ Q_DREG_B when OP_I = MOVEA and ADR_MODE_I = "000" else
+ Q_AREG_B when OP_I = EXG and OP_MODE_I = "01001" else -- Exchange two address registers.
+ Q_DREG_A when OP_I = EXG else -- Exchange data and address registers.
+ Q_AREG_B when OP_I = MOVEA and ADR_MODE_I = "001" else
+ DATA_IMMEDIATE_I when OP_I = MOVEA and ADR_MODE_I = "111" and REGSEL_20_I = "100" else
+ SSP_OUT when OP_I = LINK and SBIT_I = '1' else
+ USP_OUT when OP_I = LINK else
+ BUS_BUFFER_A when (OP_I = RTE or OP_I = RTR or OP_I = RTS) else -- Init PC, CCR, SP.
+ Q_AREG_B when OP_I = UNLK and UNLK_SP_An_I = '1' else -- An to SP.
+ x"0000" & DATA_CORE when FC_OUT_I = "010" or FC_OUT_I = "110" else -- User program space.
+ BUS_BUFFER_A;
+
+ -- ALU source operand: The required sign extensions for the operations
+ -- ADDA, CMPA and SUBA are computed in the ALU unit.
+ ALU_OP_IN_S <= Q_DREG_A when (OP_I = ABCD or OP_I = SBCD) and RM_I = '0' else
+ BUS_BUFFER_A when (OP_I = ABCD or OP_I = SBCD) else
+ Q_DREG_A when (OP_I = ADDX or OP_I = SUBX) and RM_I = '0' else
+ BUS_BUFFER_A when (OP_I = ADDX or OP_I = SUBX) else
+ Q_DREG_A when (OP_I = ADD or OP_I = SUB) and OP_MODE_I(2) = '0' and ADR_MODE_I = "000" else
+ Q_AREG_B when (OP_I = ADD or OP_I = SUB) and OP_MODE_I(2) = '0' and ADR_MODE_I = "001" else
+ DATA_IMMEDIATE_I when (OP_I = ADD or OP_I = SUB) and ADR_MODE_I = "111" and REGSEL_20_I = "100" else
+ BUS_BUFFER_A when (OP_I = ADD or OP_I = SUB) and OP_MODE_I(2) = '0' else
+ Q_DREG_B when (OP_I = ADD or OP_I = SUB) and OP_MODE_I(2) = '1' else
+ Q_DREG_B when (OP_I = ADDA or OP_I = CMPA or OP_I = SUBA) and ADR_MODE_I = "000" else
+ Q_AREG_B when (OP_I = ADDA or OP_I = CMPA or OP_I = SUBA) and ADR_MODE_I = "001" else
+ DATA_IMMEDIATE_I when (OP_I = ADDA or OP_I = CMPA or OP_I = SUBA) and ADR_MODE_I = "111" and REGSEL_20_I = "100" else
+ BUS_BUFFER_A when (OP_I = ADDA or OP_I = CMPA or OP_I = SUBA) else
+ DATA_IMMEDIATE_I when (OP_I = ADDI or OP_I = SUBI) else
+ DATA_IMMEDIATE_I when (OP_I = ADDQ or OP_I = SUBQ) else
+ Q_DREG_A when (OP_I = AND_B or OP_I = OR_B) and OP_MODE_I(2) = '0' and ADR_MODE_I = "000" else
+ DATA_IMMEDIATE_I when (OP_I = AND_B or OP_I = OR_B) and ADR_MODE_I = "111" and REGSEL_20_I = "100" else
+ BUS_BUFFER_A when (OP_I = AND_B or OP_I = OR_B) and OP_MODE_I(2) = '0' else
+ Q_DREG_B when (OP_I = AND_B or OP_I = OR_B) and OP_MODE_I(2) = '1' else
+ DATA_IMMEDIATE_I when (OP_I = ANDI or OP_I = CMPI or OP_I = EORI or OP_I = ORI) else
+ DATA_IMMEDIATE_I when (OP_I = ANDI_TO_CCR or OP_I = ANDI_TO_SR) else
+ DATA_IMMEDIATE_I when (OP_I = EORI_TO_CCR or OP_I = EORI_TO_SR) else
+ DATA_IMMEDIATE_I when (OP_I = ORI_TO_CCR or OP_I = ORI_TO_SR) else
+ Q_DREG_B when (OP_I = CHK) and ADR_MODE_I = "000" else
+ DATA_IMMEDIATE_I when (OP_I = CHK) and ADR_MODE_I = "111" and REGSEL_20_I = "100" else
+ BUS_BUFFER_A when (OP_I = CHK) else
+ Q_DREG_B when OP_I = CMP and ADR_MODE_I = "000" else
+ Q_AREG_B when OP_I = CMP and ADR_MODE_I = "001" else
+ DATA_IMMEDIATE_I when OP_I = CMP and ADR_MODE_I = "111" and REGSEL_20_I = "100" else
+ BUS_BUFFER_A when OP_I = CMP or OP_I = CMPM else
+ Q_DREG_A when OP_I = EOR else
+ Q_DREG_B when (OP_I = EXTW or OP_I = SWAP) else
+ -- MOVE and MOVEQ are switched here for condition code calculation:
+ Q_DREG_B when OP_I = MOVE and ADR_MODE_I = "000" else
+ Q_DREG_B when OP_I = MOVE and ADR_MODE_I = "000" else
+ Q_AREG_A when OP_I = MOVE and ADR_MODE_I = "001" else
+ DATA_IMMEDIATE_I when OP_I = MOVEQ else
+ --
+ DATA_IMMEDIATE_I when OP_I = MOVE and ADR_MODE_I = "111" and REGSEL_20_I = "100" else
+ BUS_BUFFER_A when OP_I = MOVE else
+ Q_DREG_B when (OP_I = DIVS or OP_I = DIVU) and ADR_MODE_I = "000" else
+ DATA_IMMEDIATE_I when (OP_I = DIVS or OP_I = DIVU) and ADR_MODE_I = "111" and REGSEL_20_I = "100" else
+ BUS_BUFFER_A when (OP_I = DIVS or OP_I = DIVU) else
+ x"0000" & Q_DREG_B(15 downto 0) when OP_SIZE_I = WORD and (OP_I = MULS or OP_I = MULU) and ADR_MODE_I = "000" else
+ Q_DREG_B when (OP_I = MULS or OP_I = MULU) and ADR_MODE_I = "000" else
+ x"0000" & DATA_IMMEDIATE_I(15 downto 0) when OP_SIZE_I = WORD and (OP_I = MULS or OP_I = MULU) and ADR_MODE_I = "111" and REGSEL_20_I = "100" else
+ DATA_IMMEDIATE_I when (OP_I = MULS or OP_I = MULU) and ADR_MODE_I = "111" and REGSEL_20_I = "100" else
+ x"0000" & BUS_BUFFER_A(15 downto 0) when OP_SIZE_I = WORD and (OP_I = MULS or OP_I = MULU) else
+ BUS_BUFFER_A when (OP_I = MULS or OP_I = MULU) else x"00000000"; -- The default is valid for NBCD, NEG, NEGX.
+
+ ALU_OP_IN_D_LO <= Q_DREG_B when (OP_I = ABCD or OP_I = SBCD) and RM_I = '0' else
+ BUS_BUFFER_B when OP_I = ABCD or OP_I = SBCD else
+ Q_DREG_B when (OP_I = ADDX or OP_I = SUBX) and RM_I = '0' else
+ BUS_BUFFER_B when OP_I = ADDX or OP_I = SUBX else
+ Q_DREG_B when (OP_I = ADD or OP_I = SUB) and OP_MODE_I(2) = '0' else
+ BUS_BUFFER_A when (OP_I = ADD or OP_I = SUB) and OP_MODE_I(2) = '1' else
+ Q_AREG_A when OP_I = ADDA or OP_I = CMPA or OP_I = SUBA else
+ Q_DREG_B when (OP_I = ADDI or OP_I = SUBI) and ADR_MODE_I = "000" else
+ BUS_BUFFER_A when OP_I = ADDI or OP_I = SUBI else
+ Q_DREG_B when (OP_I = ADDQ or OP_I = SUBQ) and ADR_MODE_I = "000" else
+ Q_AREG_B when (OP_I = ADDQ or OP_I = SUBQ) and ADR_MODE_I = "001" else
+ BUS_BUFFER_A when OP_I = ADDQ or OP_I = SUBQ else
+ Q_DREG_B when (OP_I = AND_B or OP_I = OR_B) and OP_MODE_I(2) = '0' else
+ Q_DREG_B when OP_I = EOR and ADR_MODE_I = "000" else
+ BUS_BUFFER_A when (OP_I = AND_B or OP_I = EOR or OP_I = OR_B) and OP_MODE_I(2) = '1' else
+ Q_DREG_B when (OP_I = ANDI or OP_I = CMPI or OP_I = EORI or OP_I = ORI) and ADR_MODE_I = "000" else
+ BUS_BUFFER_A when OP_I = ANDI or OP_I = CMPI or OP_I = EORI or OP_I = ORI else
+ x"0000" & STATUS_REG_I when OP_I = ANDI_TO_CCR or OP_I = ANDI_TO_SR else
+ x"0000" & STATUS_REG_I when OP_I = EORI_TO_CCR or OP_I = EORI_TO_SR else
+ x"0000" & STATUS_REG_I when OP_I = ORI_TO_CCR or OP_I = ORI_TO_SR else
+ Q_DREG_A when OP_I = CHK or OP_I = CMP else
+ BUS_BUFFER_B when OP_I = CMPM else
+ Q_DREG_A when OP_I = DIVS or OP_I = DIVU else
+ x"0000" & Q_DREG_A(15 downto 0) when OP_SIZE_I = LONG and (OP_I = MULS or OP_I = MULU) else
+ Q_DREG_A when OP_I = MULS or OP_I = MULU else
+ Q_DREG_B when (OP_I = NBCD or OP_I = NEG or OP_I = NEGX or OP_I = NOT_B) and ADR_MODE_I = "000" else
+ BUS_BUFFER_A when OP_I = NBCD or OP_I = NEG or OP_I = NEGX or OP_I = NOT_B else
+ Q_DREG_B when OP_I = TAS and ADR_MODE_I = "000" else
+ BUS_BUFFER_A when OP_I = TAS else
+ Q_DREG_B when OP_I = TST and ADR_MODE_I = "000" else
+ Q_AREG_B when OP_I = TST and ADR_MODE_I = "001" else
+ DATA_IMMEDIATE_I when OP_I = TST and ADR_MODE_I = "111" and REGSEL_20_I = "100" else
+ BUS_BUFFER_A; -- Valid for TST.
+
+ ALU_OP_IN_D_HI <= Q_DREG_C; -- Used for DIVUL, DIVSL.
+
+ SHFT_OP_IN <= Q_DREG_B when (OP_I = ASL or OP_I = ASR) and MEM_SHFT_I = '0' else
+ BUS_BUFFER_A when (OP_I = ASL or OP_I = ASR) else
+ Q_DREG_B when (OP_I = LSL or OP_I = LSR) and MEM_SHFT_I = '0' else
+ BUS_BUFFER_A when (OP_I = LSL or OP_I = LSR) else
+ Q_DREG_B when (OP_I = ROTL or OP_I = ROTR) and MEM_SHFT_I = '0' else
+ BUS_BUFFER_A when (OP_I = ROTL or OP_I = ROTR) else
+ Q_DREG_B when (OP_I = ROXL or OP_I = ROXR) and MEM_SHFT_I = '0' else
+ BUS_BUFFER_A when (OP_I = ROXL or OP_I = ROXR) else
+ DATA_IMMEDIATE_I when OP_I = BTST and ADR_MODE_I = "111" and REGSEL_20_I = "100" else
+ Q_DREG_B when (OP_I = BCHG or OP_I = BCLR or OP_I = BSET or OP_I = BTST) and ADR_MODE_I = "000" else
+ BUS_BUFFER_A when (OP_I = BCHG or OP_I = BCLR or OP_I = BSET or OP_I = BTST) else
+ (others => '0'); -- Dummy.
+
+ I_CTRL: WF68K00IP_CONTROL
+ port map(
+ CLK => CLK,
+ RESETn => RESET_COREn,
+ C_CODE => C_CODE_I,
+ Scc_COND => Scc_COND_I,
+ REGLISTMASK => REGLISTMASK_I,
+ CTRL_EN => CTRL_EN_I,
+ EXEC_ABORT => EXEC_ABORT_I,
+ DATA_VALID => DATA_VALID_I,
+ BUS_CYC_RDY => BUS_CYC_RDY_I,
+ CTRL_RDY => CTRL_RDY_I,
+ INIT_STATUS => INIT_STATUS_I,
+ PRESET_IRQ_MASK => PRESET_IRQ_MASK_I,
+ SR_CCR_IN => SR_CCR_MUX,
+ IRQ => not IPL_In,
+ IRQ_SAVE => IRQ_SAVE_I,
+ XNZVC_IN => XNZVC_I,
+ STATUS_REG_OUT => STATUS_REG_I,
+ FORCE_BIW2 => FORCE_BIW2_I,
+ FORCE_BIW3 => FORCE_BIW3_I,
+ EXT_CNT => EXT_CNT_I,
+ DEST_EXT_CNT => DEST_EXT_CNT_I,
+ REGSEL_20 => REGSEL_20_I,
+ IW_ADR => IW_ADR_I,
+ IW_WR => IW_WR_I,
+ SRC_DESTn => SRC_DESTn_I,
+ EW_WR => EW_WR_I,
+ EW_ADR => EW_ADR_I,
+ RD_BUS => RD_BUS_CTRL,
+ WR_BUS => WR_BUS_CTRL,
+ RDWR_BUS => RDWR_BUS_I,
+ WR_HI => WR_HI_I,
+ SEL_A_HI => SEL_A_HI,
+ SEL_A_MIDHI => SEL_A_MIDHI,
+ SEL_A_MIDLO => SEL_A_MIDLO,
+ SEL_A_LO => SEL_A_LO,
+ SEL_BUFF_A_LO => SEL_BUF_A_LO_CTRL_I,
+ SEL_BUFF_A_HI => SEL_BUF_A_HI_CTRL_I,
+ SEL_BUFF_B_LO => SEL_BUF_B_LO_I,
+ SEL_BUFF_B_HI => SEL_BUF_B_HI_I,
+ FC_OUT => FC_OUT_CTRL,
+ FC_EN => FC_EN_CTRL,
+ PC_INIT => PC_INIT_CTRL,
+ PC_WR => PC_WR_I,
+ PC_INC => PC_INC_I,
+ PC_TMP_CLR => PC_TMP_CLR_I,
+ PC_TMP_INC => PC_TMP_INC_I,
+ SP_ADD_DISPL => SP_ADD_DISPL_I,
+ USP_INC => USP_INC_I,
+ SSP_INC => SSP_INC_I,
+ USP_DEC => USP_DEC_I,
+ SSP_DEC => SSP_DEC_CTRL,
+ USP_CPY => USP_CPY_I,
+ PC_ADD_DISPL => PC_ADD_DISPL_I,
+ ADR_TMP_CLR => ADR_TMP_CLR_I,
+ ADR_TMP_INC => ADR_TMP_INC_I,
+ AR_INC => AR_INC_I,
+ AR_DEC => AR_DEC_I,
+ AR_WR => AR_WR_I,
+ AR_DR_EXG => AR_DR_EXG_I,
+ DR_WR => DR_WR_I,
+ DR_DEC => DR_DEC_I,
+ SCAN_TRAPS => SCAN_TRAPS_I,
+ TRAP_PRIV => TRAP_PRIV_I,
+ TRAP_TRACE => TRAP_TRACE_I,
+ OP => OP_I,
+ OP_MODE => OP_MODE_I(2 downto 0),
+ OP_SIZE => OP_SIZE_I,
+ ADR_MODE => ADR_MODE_I,
+ MOVE_D_AM => MOVE_D_AM_I,
+ RESET_RDY => RESET_RDY_I,
+ OP_BUSY => OP_BUSY_I,
+ MEM_SHFT => MEM_SHFT_I,
+ SHFT_BUSY => SHFT_BUSY_I,
+ DR => DR_I,
+ RM => RM_I,
+ DIV_MUL_32n64 => DIV_MUL_32n64_I,
+ EXEC_RESUME => EXEC_RESUME_I,
+ MOVEM_REGSEL => MOVEM_REGSEL_I,
+ MOVEM_ADn => MOVEM_ADn_I,
+ DBcc_COND => DBcc_COND_I,
+ USE_SP_ADR => USE_SP_ADR_I,
+ OP_START => OP_START_I,
+ TRAP_CHK_EN => TRAP_CHK_EN_I,
+ SHIFTER_LOAD => SHIFTER_LOAD_I,
+ CHK_PC => CHK_PC_I,
+ CHK_ADR => CHK_ADR_I,
+ SBIT => SBIT_I,
+ UNLK_SP_An => UNLK_SP_An_I,
+ RESET_EN => RESET_EN_I
+ );
+
+ I_IRQ_CTRL: WF68K00IP_INTERRUPT_CONTROL
+ port map(
+ CLK => CLK,
+ RESETn => RESET_COREn,
+ RESET_CPUn => RESET_CPU_In,
+ BERR => BERR_I,
+ HALTn => HALT_In,
+ ADR_IN => ADR_I,
+ USE_SSP_ADR => USE_SSP_ADR_I,
+ ADR_EN_VECTOR => ADR_EN_VECTOR_I,
+ DATA_IN => DATA_CORE(7 downto 0),
+ DATA_OUT => IRQ_DOUT,
+ DATA_EN => IRQ_DATA_EN,
+ RWn(0) => RWn_I,
+ RD_BUS => RD_BUS_IRQ,
+ WR_BUS => WR_BUS_IRQ,
+ HALT_EN => HALT_OUT_EN,
+ FC_IN => FC_OUT_I,
+ FC_OUT => FC_OUT_IRQ,
+ FC_EN => FC_EN_IRQ,
+ SEL_BUFF_A_LO => SEL_BUF_A_LO_IRQ_I,
+ SEL_BUFF_A_HI => SEL_BUF_A_HI_IRQ_I,
+ STATUS_REG_IN => STATUS_REG_I,
+ PC => PC_OUT,
+ INIT_STATUS => INIT_STATUS_I,
+ PRESET_IRQ_MASK => PRESET_IRQ_MASK_I,
+ SSP_DEC => SSP_DEC_IRQ,
+ SSP_INIT => SSP_INIT_I,
+ PC_INIT => PC_INIT_IRQ,
+ BIW_0 => BIW_0_I,
+ BUS_CYC_RDY => BUS_CYC_RDY_I,
+ CTRL_RDY => CTRL_RDY_I,
+ CTRL_EN => CTRL_EN_I,
+ EXEC_ABORT => EXEC_ABORT_I,
+ EXEC_RESUME => EXEC_RESUME_I,
+ IRQ => not IPL_In,
+ AVECn => AVEC_In, -- Originally 68Ks use VPAn.
+ IRQ_SAVE => IRQ_SAVE_I,
+ INT_VECT => INT_VECT_I,
+ USE_INT_VECT => USE_INT_VECT_I,
+ TRAP_AERR => TRAP_AERR_I,
+ TRAP_OP => TRAP_OP_I,
+ TRAP_VECTOR => TRAP_VECTOR_I,
+ TRAP_V => TRAP_V_I,
+ TRAP_CHK => TRAP_CHK_I,
+ TRAP_DIVZERO => TRAP_DIVZERO_I,
+ TRAP_ILLEGAL => TRAP_ILLEGAL_I,
+ TRAP_1010 => TRAP_1010_I,
+ TRAP_1111 => TRAP_1111_I,
+ TRAP_PRIV => TRAP_PRIV_I,
+ TRAP_TRACE => TRAP_TRACE_I
+ );
+
+ I_OPCODE: WF68K00IP_OPCODE_DECODER
+ port map(
+ CLK => CLK,
+ RESETn => RESET_COREn,
+ DATA_IN => DATA_IN,
+ SBIT => SBIT_I,
+ OV => STATUS_REG_I(1),
+ IW_ADR => IW_ADR_I,
+ IW_WR => IW_WR_I,
+ FORCE_BIW2 => FORCE_BIW2_I,
+ FORCE_BIW3 => FORCE_BIW3_I,
+ EXT_CNT => EXT_CNT_I,
+ DEST_EXT_CNT => DEST_EXT_CNT_I,
+ DR => DR_I,
+ RM => RM_I,
+ IR => IR_I,
+ OP => OP_I,
+ OP_MODE => OP_MODE_I,
+ OP_SIZE => OP_SIZE_I,
+ BIW_0 => BIW_0_I,
+ REGSEL_20 => REGSEL_20_I,
+ REGSEL_119 => REGSEL_119_I,
+ REGSEL_INDEX => REGSEL_INDEX,
+ DATA_IMMEDIATE => DATA_IMMEDIATE_I,
+ TRAP_VECTOR => TRAP_VECTOR_I,
+ C_CODE => C_CODE_I,
+ MEM_SHFT => MEM_SHFT_I,
+ REGLISTMASK => REGLISTMASK_I,
+ BITPOS_IM => BITPOS_IM_I,
+ BIT_POS => BIT_POS_OP,
+ DIV_MUL_32n64 => DIV_MUL_32n64_I,
+ REG_Dlq => REGSEL_Dlq,
+ REG_Dhr => REGSEL_Dhr,
+ SCAN_TRAPS => SCAN_TRAPS_I,
+ TRAP_ILLEGAL => TRAP_ILLEGAL_I,
+ TRAP_1010 => TRAP_1010_I,
+ TRAP_1111 => TRAP_1111_I,
+ TRAP_PRIV => TRAP_PRIV_I,
+ TRAP_OP => TRAP_OP_I,
+ TRAP_V => TRAP_V_I,
+ EW_WR => EW_WR_I,
+ EW_ADR => EW_ADR_I,
+ SRC_DESTn => SRC_DESTn_I,
+ EXWORD => EXWORD_I,
+ DEST_EXWORD => DEST_EXWORD_I,
+ ADR_MODE => ADR_MODE_I,
+ MOVE_D_AM => MOVE_D_AM_I,
+ EXT_DSIZE => EXT_DSIZE_I,
+ SEL_DISPLACE_BIW => SEL_DISPLACE_BIW_I,
+ DISPLACE_BIW => DISPLACE_BIW_I
+ );
+
+ I_ADRREG: WF68K00IP_ADDRESS_REGISTERS
+ port map(
+ CLK => CLK,
+ RESETn => RESET_COREn,
+ ADATA_IN => AREG_DATA_IN,
+ REGSEL_B => REGSEL_ADR_B,
+ REGSEL_A => REGSEL_ADR_A,
+ ADR_REG_QB => Q_AREG_B,
+ ADR_REG_QA => Q_AREG_A,
+ USP_OUT => USP_OUT,
+ SSP_OUT => SSP_OUT,
+ PC_OUT => PC_OUT,
+ EXWORD => EXWORD_I,
+ DEST_EXWORD => DEST_EXWORD_I,
+ DR => DR_I,
+ USP_CPY => USP_CPY_I,
+ AR_EXG => AR_DR_EXG_I,
+ USP_INC => USP_INC_I,
+ USP_DEC => USP_DEC_I,
+ ADR_TMP_CLR => ADR_TMP_CLR_I,
+ ADR_TMP_INC => ADR_TMP_INC_I,
+ AR_INC => AR_INC_I,
+ AR_DEC => AR_DEC_I,
+ AR_WR => AR_WR_I,
+ SSP_INC => SSP_INC_I,
+ SSP_DEC => SSP_DEC_I,
+ SSP_INIT => SSP_INIT_I,
+ SP_ADD_DISPL => SP_ADD_DISPL_I,
+ USE_SP_ADR => USE_SP_ADR_I,
+ USE_SSP_ADR => USE_SSP_ADR_I,
+ PC_WR => PC_WR_I,
+ PC_INC => PC_INC_I,
+ PC_TMP_CLR => PC_TMP_CLR_I,
+ PC_TMP_INC => PC_TMP_INC_I,
+ PC_INIT => PC_INIT_I,
+ PC_ADD_DISPL => PC_ADD_DISPL_I,
+ SRC_DESTn => SRC_DESTn_I,
+ SBIT => SBIT_I,
+ OP => OP_I,
+ OP_SIZE => OP_SIZE_I,
+ OP_MODE => OP_MODE_I,
+ OP_START => OP_START_I,
+ ADR_MODE => ADR_MODE_I,
+ MOVE_D_AM => MOVE_D_AM_I,
+ FORCE_BIW2 => FORCE_BIW2_I,
+ FORCE_BIW3 => FORCE_BIW3_I,
+ EXT_DSIZE => EXT_DSIZE_I,
+ SEL_DISPLACE_BIW => SEL_DISPLACE_BIW_I,
+ DISPLACE_BIW => DISPLACE_BIW_I,
+ REGSEL_INDEX => REGSEL_DATA_C,
+ INDEX_D_IN => Q_DREG_C,
+ CHK_PC => CHK_PC_I,
+ CHK_ADR => CHK_ADR_I,
+ TRAP_AERR => TRAP_AERR_I,
+ ADR_EFF => ADR_EFF_I
+ );
+
+ I_DATAREG: WF68K00IP_DATA_REGISTERS
+ port map(
+ CLK => CLK,
+ RESETn => RESET_COREn,
+ DATA_IN_A => DREG_DATA_IN_A,
+ DATA_IN_B => DREG_DATA_IN_B,
+ REGSEL_A => REGSEL_DATA_A,
+ REGSEL_B => REGSEL_DATA_B,
+ REGSEL_C => REGSEL_DATA_C,
+ DIV_MUL_32n64 => DIV_MUL_32n64_I,
+ DATA_OUT_A => Q_DREG_A,
+ DATA_OUT_B => Q_DREG_B,
+ DATA_OUT_C => Q_DREG_C,
+ DR_EXG => AR_DR_EXG_I,
+ DR_WR => DR_WR_I,
+ DR_DEC => DR_DEC_I,
+ OP => OP_I,
+ OP_SIZE => OP_SIZE_I,
+ OP_MODE => OP_MODE_I,
+ DBcc_COND => DBcc_COND_I
+ );
+
+ I_ALU: WF68K00IP_ALU
+ port map(
+ CLK => CLK,
+ RESETn => RESET_COREn,
+ ADR_MODE => ADR_MODE_I,
+ OP_SIZE => OP_SIZE_I,
+ OP => OP_I,
+ XNZVC_IN => STATUS_REG_I(4 downto 0),
+ XNZVC_OUT => XNZVC_ALU,
+ OP_IN_S => ALU_OP_IN_S,
+ OP_IN_D_HI => ALU_OP_IN_D_HI,
+ OP_IN_D_LO => ALU_OP_IN_D_LO,
+ RESULT_HI => RESULT_ALU_HI,
+ RESULT_LO => RESULT_ALU_LO,
+ OP_START => OP_START_I,
+ TRAP_CHK_EN => TRAP_CHK_EN_I,
+ DIV_MUL_32n64 => DIV_MUL_32n64_I,
+ OP_BUSY => OP_BUSY_I,
+ TRAP_CHK => TRAP_CHK_I,
+ TRAP_DIVZERO => TRAP_DIVZERO_I
+ );
+
+ I_SHFT: WF68K00IP_SHIFTER
+ port map(
+ CLK => CLK,
+ RESETn => RESET_COREn,
+ DATA_IN => SHFT_OP_IN,
+ DATA_OUT => RESULT_SHFT,
+ OP => OP_I,
+ OP_SIZE => OP_SIZE_I,
+ BIT_POS => BIT_POS_I,
+ CNT_NR => CNT_NR_I,
+ SHFT_BREAKn => not EXEC_ABORT_I,
+ SHIFTER_LOAD => SHIFTER_LOAD_I,
+ SHFT_BUSY => SHFT_BUSY_I,
+ XNZVC_IN => STATUS_REG_I(4 downto 0),
+ XNZVC_OUT => XNZVC_SHFT
+ );
+
+ I_BUS_IF: WF68K00IP_BUS_INTERFACE
+ port map(
+ CLK => CLK,
+ RESETn => RESET_COREn,
+ RESET_INn => RESET_IN_In,
+ RESET_OUT_EN => RESET_OUT_EN,
+ RESET_CPUn => RESET_CPU_In,
+ RESET_EN => RESET_EN_I,
+ RESET_RDY => RESET_RDY_I,
+ DATA_IN => DATA_IN,
+ SEL_A_HI => SEL_A_HI,
+ SEL_A_MIDHI => SEL_A_MIDHI,
+ SEL_A_MIDLO => SEL_A_MIDLO,
+ SEL_A_LO => SEL_A_LO,
+ SEL_BUFF_A_LO => SEL_BUF_A_LO_I,
+ SEL_BUFF_A_HI => SEL_BUF_A_HI_I,
+ SEL_BUFF_B_LO => SEL_BUF_B_LO_I,
+ SEL_BUFF_B_HI => SEL_BUF_B_HI_I,
+ SYS_INIT => SYS_INIT_I,
+ OP_SIZE => OP_SIZE_I,
+ BUFFER_A => BUS_BUFFER_A,
+ BUFFER_B => BUS_BUFFER_B,
+ DATA_CORE_OUT => DATA_CORE,
+ RD_BUS => RD_BUS_I,
+ WR_BUS => WR_BUS_I,
+ RDWR_BUS => RDWR_BUS_I,
+ A0 => ADR_I(0),
+ BYTEn_WORD => BYTEn_WORD_I,
+ EXEC_ABORT => EXEC_ABORT_I,
+ BUS_CYC_RDY => BUS_CYC_RDY_I,
+ DATA_VALID => DATA_VALID_I,
+ DTACKn => DTACK_In,
+ BERRn => BERR_In,
+ AVECn => AVEC_In,
+ HALTn => HALT_In,
+ ADR_EN => ADR_EN_I,
+ WR_HI => WR_HI_I,
+ HI_WORD_EN => HI_WORD_EN_I,
+ HI_BYTE_EN => HI_BYTE_EN_I,
+ LO_BYTE_EN => LO_BYTE_EN_I,
+ FC_EN => FC_EN_I,
+ ASn => AS_In,
+ AS_EN => AS_EN_I,
+ UDSn => UDS_In,
+ UDS_EN => UDS_EN_I,
+ LDSn => LDS_In,
+ LDS_EN => LDS_EN_I,
+ RWn => RWn_I,
+ RW_EN => RW_EN_I,
+ VPAn => VPA_In,
+ VMAn => VMA_In,
+ VMA_EN => VMA_EN_I,
+ E => E,
+ BRn => BR_In,
+ BGACKn => BGACK_In,
+ BGn => BGn
+ );
+end STRUCTURE;
diff --git a/common/CPU/FZ80/fz80.v b/common/CPU/FZ80/fz80.v
new file mode 100644
index 00000000..e73fb529
--- /dev/null
+++ b/common/CPU/FZ80/fz80.v
@@ -0,0 +1,1460 @@
+// Z80 CPU binary compatible soft core
+// Copyright (C) 2004,2005 by Yasuo Kuwahara
+// version 1.04
+
+// This software is provided "AS IS", with NO WARRANTY.
+// NON-COMMERCIAL USE ONLY
+
+//`define DEBUG
+//`define ICE
+//`define M1
+
+module fz80(data_in, reset_in, clk, adr, intreq, nmireq, busreq, start,
+mreq, iorq, rd, wr, data_out, busack_out, intack_out, mr,
+`ifdef M1
+ m1, radr, nmiack_out,
+`endif
+`ifdef ICE
+ ice_enable, sclk, sdata,
+`endif
+ waitreq
+);
+`ifdef M1
+ output m1, nmiack_out;
+ output [15:0] radr;
+`endif
+`ifdef ICE
+ input sclk, ice_enable;
+ output sdata;
+`endif
+ input [7:0] data_in;
+ input reset_in, clk, intreq, nmireq, busreq, waitreq;
+ output start, mreq, iorq, rd, wr, busack_out, intack_out, mr;
+ output [7:0] data_out;
+ output [15:0] adr;
+ wire [7:0] q_f;
+ wire [7:0] q_a, q_b, q_c, q_d, q_e, q_h, q_l, q_sph, q_spl, q_pch, q_pcl, q_adrh, q_adrl, q_r, q_i, q_data;
+ reg sel_af, sel_exx;
+ wire g_if, g_imm2, g_mr1, g_mr2, g_disp, g_mw1, g_mw2, g_in, g_out;
+ wire sgate;
+ wire s_if, s_if2, s_imm1, s_imm2, s_mr1, s_mr2, s_disp, s_iack, s_mw1, s_mw2, s_in, s_out;
+ wire [1:0] intmode;
+ wire eschalt;
+ wire icb, idd, ied, ifd;
+ wire [7:0] inst_reg;
+ wire [7:0] q_f_out;
+ wire [7:0] d_f;
+ wire cond, cond2;
+`ifdef M1
+ wire [15:0] radr = { q_i, q_r };
+`endif
+//
+ function [3:0] decode2;
+ input [1:0] a;
+ begin
+ case (a)
+ 2'h0: decode2 = 4'b0001;
+ 2'h1: decode2 = 4'b0010;
+ 2'h2: decode2 = 4'b0100;
+ 2'h3: decode2 = 4'b1000;
+ endcase
+ end
+ endfunction
+ function [7:0] decode3;
+ input [2:0] a;
+ begin
+ case (a)
+ 3'h0: decode3 = 8'b00000001;
+ 3'h1: decode3 = 8'b00000010;
+ 3'h2: decode3 = 8'b00000100;
+ 3'h3: decode3 = 8'b00001000;
+ 3'h4: decode3 = 8'b00010000;
+ 3'h5: decode3 = 8'b00100000;
+ 3'h6: decode3 = 8'b01000000;
+ 3'h7: decode3 = 8'b10000000;
+ endcase
+ end
+ endfunction
+ function [7:0] select0;
+ input [1:0] sel;
+ input [15:0] a;
+ begin
+ case (sel)
+ 3'h1: select0 = a[15:8];
+ 3'h2: select0 = a[7:0];
+ default: select0 = 8'b00000000;
+ endcase
+ end
+ endfunction
+ function [3:0] select1h;
+ input [3:0] sel;
+ input [59:0] a;
+ begin
+ case (sel)
+ default: select1h = a[59:56];
+ 4'h1: select1h = a[55:52];
+ 4'h2: select1h = a[51:48];
+ 4'h3: select1h = a[47:44];
+ 4'h4: select1h = a[43:40];
+ 4'h5: select1h = a[39:36];
+ 4'h6: select1h = a[35:32];
+ 4'h7: select1h = a[31:28];
+ 4'h8: select1h = a[27:24];
+ 4'h9: select1h = a[23:20];
+ 4'ha: select1h = a[19:16];
+ 4'hb: select1h = a[15:12];
+ 4'hc: select1h = a[11:8];
+ 4'hd: select1h = a[7:4];
+ 4'hf: select1h = a[3:0];
+ endcase
+ end
+ endfunction
+ function [3:0] select1l;
+ input [3:0] sel;
+ input [63:0] a;
+ begin
+ case (sel)
+ 4'h0: select1l = a[63:60];
+ 4'h1: select1l = a[59:56];
+ 4'h2: select1l = a[55:52];
+ 4'h3: select1l = a[51:48];
+ 4'h4: select1l = a[47:44];
+ 4'h5: select1l = a[43:40];
+ 4'h6: select1l = a[39:36];
+ 4'h7: select1l = a[35:32];
+ 4'h8: select1l = a[31:28];
+ 4'h9: select1l = a[27:24];
+ 4'ha: select1l = a[23:20];
+ 4'hb: select1l = a[19:16];
+ 4'hc: select1l = a[15:12];
+ 4'hd: select1l = a[11:8];
+ 4'he: select1l = a[7:4];
+ 4'hf: select1l = a[3:0];
+ endcase
+ end
+ endfunction
+ function [15:0] select2;
+ input [2:0] sel;
+ input [95:0] a;
+ begin
+ case (sel)
+ 3'h0: select2 = a[95:80];
+ 3'h1: select2 = a[79:64];
+ 3'h2: select2 = a[63:48];
+ 3'h4: select2 = a[47:32];
+ 3'h5: select2 = a[31:16];
+ default: select2 = a[15:0];
+ endcase
+ end
+ endfunction
+ function [7:0] select3;
+ input [1:0] sel;
+ input [15:0] a;
+ begin
+ case (sel)
+ 2'h1: select3 = a[15:8];
+ 2'h2: select3 = a[7:0];
+ default: select3 = 8'b00000000;
+ endcase
+ end
+ endfunction
+ function [7:0] selectah;
+ input [2:0] sel;
+ input [63:0] a;
+ begin
+ case (sel)
+ 3'h1: selectah = a[63:56];
+ 3'h2: selectah = a[55:48];
+ 3'h3: selectah = a[47:40];
+ 3'h4: selectah = a[39:32];
+ 3'h5: selectah = a[31:24];
+ 3'h6: selectah = a[23:16];
+ 3'h7: selectah = a[15:8];
+ default: selectah = a[7:0];
+ endcase
+ end
+ endfunction
+ function [7:0] selectal;
+ input [2:0] sel;
+ input [47:0] a;
+ begin
+ case (sel)
+ 3'h1: selectal = a[47:40];
+ 3'h4: selectal = a[39:32];
+ 3'h5: selectal = a[31:24];
+ 3'h6: selectal = a[23:16];
+ 3'h7: selectal = a[15:8];
+ default: selectal = a[7:0];
+ endcase
+ end
+ endfunction
+ function [7:0] selectf;
+ input [1:0] sel;
+ input [31:0] a;
+ begin
+ case (sel)
+ 2'h0: selectf = a[31:24];
+ 2'h1: selectf = a[23:16];
+ 2'h2: selectf = a[15:8];
+ 2'h3: selectf = a[7:0];
+ endcase
+ end
+ endfunction
+`ifdef ICE
+ parameter INST_COUNT_TARGET = 0;
+ reg [6:0] rs_count = 0;
+ reg [5:0] rs_timing = 0;
+ reg ice_wait = 0, sclk1 = 0, sclk2 = 0;
+ reg [7:0] inst_count = 0;
+ wire [7:0] ice_data_tmp;
+ assign ice_data_tmp = rd ? data_in : data_out;
+ wire [111:0] sdata_sel = { 2'b00, g_if, mr, mreq, iorq, rd, wr, ice_data_tmp, adr, q_f_out, q_a, q_h, q_l, q_d, q_e, q_b, q_c, q_pch, q_pcl };
+ wire sdata = sdata_sel[rs_count];
+ wire waitreq1 = waitreq | start | ice_wait & inst_count == INST_COUNT_TARGET;
+ always @(posedge clk) begin
+ sclk1 <= sclk;
+ sclk2 <= sclk1;
+ if (sclk1 ^ sclk2) begin
+ if (rs_count == 111) ice_wait <= 0;
+ rs_count <= rs_count + 1;
+ end
+ else if (sclk2) begin
+ rs_timing <= rs_timing + 1;
+ if (rs_timing == 31) rs_count <= 0;
+ end
+ else rs_timing <= 0;
+ if (start & ice_enable) ice_wait <= 1;
+ if (s_if & ~s_if2 & inst_count != INST_COUNT_TARGET)
+ inst_count <= inst_count + 1;
+ end
+`else
+ wire waitreq1 = waitreq;
+`endif
+// instruction decoder
+ wire intack;
+ wire int1 = intmode == 2'b10 & intack;
+ wire [7:0] data = data_in | { 8 { int1 } };
+ wire [7:0] i = g_if ? data : inst_reg;
+ wire i0 = ~icb & ~ied;
+ wire [3:0] ih = decode2(i[7:6]);
+ wire [7:0] im = decode3(i[5:3]);
+ wire [7:0] il = decode3(i[2:0]);
+ // 8-bit load group
+ wire i_ldrr = i0 & ih[1] & ~im[6] & ~il[6];
+ wire i_ldrn = i0 & ih[0] & ~im[6] & il[6];
+ wire i_ldrhl = i0 & ih[1] & ~im[6] & il[6];
+ wire i_ldhlr = i0 & ih[1] & im[6] & ~il[6];
+ wire i_ldhln = i0 & ih[0] & im[6] & il[6];
+ wire i_ldabc = i0 & ih[0] & im[1] & il[2];
+ wire i_ldade = i0 & ih[0] & im[3] & il[2];
+ wire i_ldann = i0 & ih[0] & im[7] & il[2];
+ wire i_ldbca = i0 & ih[0] & im[0] & il[2];
+ wire i_lddea = i0 & ih[0] & im[2] & il[2];
+ wire i_ldnna = i0 & ih[0] & im[6] & il[2];
+ wire i_ldai = ied & ih[1] & im[2] & il[7];
+ wire i_ldar = ied & ih[1] & im[3] & il[7];
+ wire i_ldia = ied & ih[1] & im[0] & il[7];
+ wire i_ldra = ied & ih[1] & im[1] & il[7];
+ wire ldair = i_ldai | i_ldar;
+ // 16-bit load group
+ wire i_ldddnn = i0 & ih[0] & ~i[3] & il[1];
+ wire i_ldhl_nn = i0 & ih[0] & im[5] & il[2];
+ wire i_lddd_nn = ied & ih[1] & i[3] & il[3];
+ wire i_ldnnhl = i0 & ih[0] & im[4] & il[2];
+ wire i_ldnndd = ied & ih[1] & ~i[3] & il[3];
+ wire i_ldsphl = i0 & ih[3] & im[7] & il[1];
+ wire i_push = i0 & ih[3] & ~i[3] & il[5];
+ wire i_pop = i0 & ih[3] & ~i[3] & il[1];
+ // exchange, block
+ wire i_exdehl = i0 & ih[3] & im[5] & il[3];
+ wire i_exafaf = i0 & ih[0] & im[1] & il[0];
+ wire i_exx = i0 & ih[3] & im[3] & il[1];
+ wire i_exsphl = i0 & ih[3] & im[4] & il[3];
+ wire i_ldblock = ied & ih[2] & i[5] & il[0];
+ wire i_cpblock = ied & ih[2] & i[5] & il[1];
+ // 8-bit arithmetic & logical
+ wire al = i0 & (ih[2] | ih[3] & il[6]);
+ wire al_r = i0 & ih[2] & ~il[6];
+ wire al_n = i0 & ih[3] & il[6];
+ wire al_hl = i0 & ih[2] & il[6];
+ wire al_r_notcp = al_r & ~im[7];
+ wire al_n_notcp = al_n & ~im[7];
+ wire al_hl_notcp = al_hl & ~im[7];
+ wire arith8_notcp = al & ~i[5];
+ wire i_cp = al & im[7];
+ wire arith8 = arith8_notcp | i_cp;
+ wire logica = al & i[5] & (~i[4] | ~i[3]);
+ wire i_and = logica & im[4];
+ wire i_xor = logica & im[5];
+ wire i_or = logica & im[6];
+ wire incdec8 = i0 & ih[0] & i[2] & ~i[1];
+ wire dec8 = incdec8 & i[0];
+ wire incdec_hl = incdec8 & im[6];
+ // gen. arithmetic & CPU control
+ wire i_daa = i0 & ih[0] & im[4] & il[7];
+ wire i_cpl = i0 & ih[0] & im[5] & il[7];
+ wire i_neg = ied & ih[1] & im[0] & il[4];
+ wire i_ccf = i0 & ih[0] & im[7] & il[7];
+ wire i_scf = i0 & ih[0] & im[6] & il[7];
+ wire i_halt = i0 & ih[1] & im[6] & il[6];
+ wire i_eidi = i0 & ih[3] & i[5] & i[4] & il[3];
+ wire i_im = ied & ih[1] & ~i[5] & il[6];
+ // 16-bit arithmetic
+ wire add16 = i0 & ih[0] & i[3] & il[1];
+ wire arith16 = ied & ih[1] & il[2];
+ wire i_c16 = add16 | arith16;
+ wire i_incdec16 = i0 & ih[0] & il[3];
+ // rotate & shift
+ wire i_rotate1 = i0 & ih[0] & ~i[5] & il[7];
+ wire i_rs_r = icb & ih[0] & ~il[6];
+ wire i_rs_hl = icb & ih[0] & il[6];
+ wire i_rotate2 = icb & ih[0] & ~i[5];
+ wire rotate = i_rotate1 | i_rotate2;
+ wire shift = icb & ih[0] & i[5];
+ wire rs = rotate | shift;
+ wire i_rd = ied & ih[1] & i[5] & ~i[4] & il[7];
+ wire i_rld = i_rd & i[3];
+ wire i_rrd = i_rd & ~i[3];
+ wire l = rs & ~i[3];
+ wire r = rs & i[3];
+ // bit/set/res
+ wire i_bit_r = icb & ih[1] & ~il[6];
+ wire i_bit_hl = icb & ih[1] & il[6];
+ wire i_setres_r = icb & i[7] & ~il[6];
+ wire i_setres_hl = icb & i[7] & il[6];
+ wire ibit = icb & ih[1];
+ wire set = icb & ih[3];
+ wire res = icb & ih[2];
+ // jump
+ wire i_jpnn = i0 & ih[3] & im[0] & il[3];
+ wire i_jpccnn = i0 & ih[3] & il[2];
+ wire i_jr = i0 & ih[0] & im[3] & il[0];
+ wire i_jrcc = i0 & ih[0] & i[5] & il[0];
+ wire i_jphl = i0 & ih[3] & im[5] & il[1];
+ wire i_djnz = i0 & ih[0] & im[2] & il[0];
+ // call/return
+ wire i_call = i0 & ih[3] & im[1] & il[5];
+ wire i_callcc = i0 & ih[3] & il[4];
+ wire i_ret = i0 & ih[3] & im[1] & il[1];
+ wire i_retcc = i0 & ih[3] & il[0];
+ wire retin = ied & ih[1] & (im[1] | im[0]) & il[5];
+ wire i_rst = i0 & ih[3] & il[7];
+ // I/O
+ wire i_inan = i0 & ih[3] & im[3] & il[3];
+ wire i_inrc = ied & ih[1] & il[0];
+ wire i_outna = ih[3] & im[2] & il[3];
+ wire i_outcr = ied & ih[1] & il[1];
+ wire i_ioblock = ied & ih[2] & i[5] & ~i[2] & i[1];
+ wire i_inblock = i_ioblock & ~i[0];
+ wire i_outblock = i_ioblock & i[0];
+ // bus cycle decoder
+ wire nmiack, g_iack;
+ wire imm1 = i_ldrn | i_ldhln | al_n | i_inan | i_outna | i_jr | i_jrcc | i_djnz;
+ wire imm2 = i_ldddnn | i_ldann | i_ldnna | i_ldhl_nn | i_ldnnhl | i_ldnndd | i_lddd_nn
+ | i_jpnn | i_jpccnn | i_call | i_callcc;
+ wire mr1 = i_ldrhl | i_ldabc | i_ldade | i_ldann | i_ldblock | i_cpblock | al_hl | incdec_hl
+ | i_rs_hl | i_rd | i_bit_hl | i_setres_hl | i_outblock;
+ wire mr2 = i_ldhl_nn | i_lddd_nn | i_pop | i_exsphl
+ | i_ret | i_retcc & cond | retin
+ | intmode == 2'b11 & intack;
+ wire mw1 = i_ldhlr | i_ldbca | i_lddea | i_ldnna | i_ldhln | i_ldblock | incdec_hl
+ | i_rs_hl | i_rd | i_setres_hl | i_inblock;
+ wire mw2 = i_ldnnhl | i_ldnndd | i_exsphl | i_push | i_call | i_callcc & cond | i_rst
+ | intmode == 2'b11 & intack | nmiack;
+ wire disp = (idd | ifd) & (mr1 | mw1);
+ wire i_in = i_inan | i_inrc | i_inblock;
+ wire i_out = i_outna | i_outcr | i_outblock;
+ //
+ wire mr = g_mr1 | g_mr2; // for debug
+ wire intack_out = (g_if | g_iack) & intack;
+ `ifdef M1
+ wire nmiack_out = g_iack & nmiack;
+ `endif
+ // load
+ wire tmp0 = s_if & (i_rs_r | i_setres_r);
+ wire tmp1 = s_if & (i_ldrr | incdec8) | s_imm1 & i_ldrn | s_mr1 & i_ldrhl | s_in & i_inrc;
+ wire load_a = tmp1 & im[7]
+ | tmp0 & il[7]
+ | s_mr1 & (i_ldabc | i_ldade | i_ldann | al_hl_notcp)
+ | s_mr2 & i_pop & im[6]
+ | s_if & (ldair | al_r_notcp | i_daa | i_cpl | i_neg | i_rotate1)
+ | s_imm1 & al_n_notcp
+ | s_mw1 & i_rd
+ | s_in & i_inan;
+ wire load_f = s_mr1 & i_pop & im[6];
+ wire load_b = tmp1 & im[0]
+ | tmp0 & il[0]
+ | s_imm2 & i_ldddnn & im[0]
+ | s_mr2 & i_lddd_nn & im[1]
+ | s_mr2 & i_pop & im[0]
+ | s_imm1 & i_djnz;
+ wire load_c = tmp1 & im[1]
+ | tmp0 & il[1]
+ | s_imm1 & i_ldddnn & im[0]
+ | s_mr1 & i_lddd_nn & im[1]
+ | s_mr1 & i_pop & im[0];
+ wire load_d = tmp1 & im[2]
+ | tmp0 & il[2]
+ | s_imm2 & i_ldddnn & im[2]
+ | s_mr2 & i_lddd_nn & im[3]
+ | s_mr2 & i_pop & im[2];
+ wire load_e = tmp1 & im[3]
+ | tmp0 & il[3]
+ | s_imm1 & i_ldddnn & im[2]
+ | s_mr1 & i_lddd_nn & im[3]
+ | s_mr1 & i_pop & im[2];
+ wire load_h = tmp1 & im[4]
+ | tmp0 & il[4]
+ | s_imm2 & i_ldddnn & im[4]
+ | s_mr2 & i_ldhl_nn
+ | s_mr2 & i_lddd_nn & im[5]
+ | s_mr2 & i_pop & im[4]
+ | s_if & i_c16;
+ wire load_l = tmp1 & im[5]
+ | tmp0 & il[5]
+ | s_imm1 & i_ldddnn & im[4]
+ | s_mr1 & i_ldhl_nn
+ | s_mr1 & i_lddd_nn & im[5]
+ | s_mr1 & i_pop & im[4];
+ wire tmp_adr = i_ldann | i_ldnna | i_ldhl_nn | i_lddd_nn | i_ldnnhl | i_ldnndd | i_call | i_callcc | i_inan | i_outna;
+ wire load_adrh = s_mr2 & i_exsphl | s_imm2 & tmp_adr;
+ wire load_adrl = s_mr1 & i_exsphl | s_imm1 & tmp_adr | s_iack;
+ wire load_r = s_if & i_ldra;
+ wire load_i = s_if & i_ldia;
+ wire loadex = s_if & i_exdehl;
+ wire tmp2 = s_imm2 & (i_jpnn | i_jpccnn & cond);
+ wire load_pch = tmp2
+ | s_mr2 & (i_ret | i_retcc | retin | intack);
+ wire load_pcl = tmp2
+ | s_mr1 & (i_ret | i_retcc | retin | intack);
+ wire load_sph = s_imm2 & i_ldddnn & im[6]
+ | s_mr2 & i_lddd_nn & im[7];
+ wire load_spl = s_imm1 & i_ldddnn & im[6]
+ | s_mr1 & i_lddd_nn & im[7];
+ wire load_data = s_if & (i_rst | i_outcr)
+ | s_mr1 & (i_ldblock | incdec_hl | i_rd | i_rs_hl | i_setres_hl | i_outblock)
+ | s_imm1 & (i_ldhln | i_jpnn | i_jpccnn)
+ | s_in & i_inblock;
+ wire loada_bc = s_if & (i_ldblock | i_cpblock | i_incdec16 & ~i[5] & ~i[4])
+ | s_in & i_inblock | s_mr1 & i_outblock;
+ wire loada_de = s_if & (i_exdehl | (i_incdec16 & ~i[5] & i[4]))
+ | s_mw1 & i_ldblock;
+ wire loada_l = s_if & i_c16;
+ wire loada_hl = s_if & i_incdec16 & i[5] & ~i[4]
+ | s_mr1 & (i_ldblock | i_cpblock)
+ | s_out & i_outblock
+ | s_mw1 & i_inblock
+ | s_mw2 & i_exsphl;
+ wire loada_sp = s_if & (i_push | i_ldsphl | i_incdec16 & i[5] & i[4] | i_call | i_callcc & cond | i_rst | intack | nmiack)
+ | s_mw1 & (i_push | i_exsphl | i_call | i_callcc | i_rst | intack | nmiack)
+ | s_mr1 & (i_pop | i_exsphl | i_ret | i_retcc | retin)
+ | s_mr2 & (i_pop | i_ret | i_retcc | retin)
+ | s_iack;
+ wire alu_zero;
+ wire loada_pc = s_if & i_jphl
+ | s_imm1 & (i_jr | i_jrcc & cond2 | i_djnz & ~alu_zero)
+ | s_mw2 & (i_call | i_callcc);
+ wire loada_adr = s_disp
+ | s_mr1 & (i_ldhl_nn | i_lddd_nn | intack)
+ | s_mw1 & (i_ldnnhl | i_ldnndd);
+ wire load3_pc = s_mw2 & i_rst;
+ wire load66_pc = s_mw2 & nmiack;
+ wire clr_pch = s_mw2 & (i_rst | nmiack);
+ wire count_pc = (s_if | s_imm1 | s_imm2) & ~(i_halt | intack | nmiack) & ~(s_if2 & (i_ldblock | i_cpblock | i_ioblock))
+ | s_disp
+ | s_mr1 & (i_ldblock | i_cpblock)
+ | s_in & i_inblock
+ | s_out & i_outblock
+ | eschalt;
+ wire asu_zero;
+ reg q_asu_zero;
+ wire dec_pc = (i_ldblock | i_cpblock) & i[4] & ~q_asu_zero & ~(i_cpblock & alu_zero)
+ | i_inblock & i[4] & ~asu_zero
+ | i_outblock & i[4] & ~q_f[6];
+ wire count_r = s_if;
+ //
+ // ALU block
+ //
+ // selector 0 (for alu-input a)
+ wire sel0_a = i_cpblock | al | i_daa;
+ wire sel0_h = i_c16;
+ wire [1:0] sel0 = { sel0_h, sel0_a };
+ // selector 1 (for alu-input b)
+ wire sel1_tmp = i_ldrr | i_ldrhl | i_ldhlr | al_r | i_rs_r | i_bit_r | i_setres_r;
+ wire sel1_b = sel1_tmp & il[0]
+ | incdec8 & im[0]
+ | g_mw2 & i_ldnndd & im[0]
+ | g_mw1 & i_push & im[0]
+ | i_c16 & (im[0] | im[1])
+ | i_djnz
+ | i_outcr & im[0];
+ wire sel1_c = sel1_tmp & il[1]
+ | incdec8 & im[1]
+ | g_mw1 & i_ldnndd & im[0]
+ | g_mw2 & i_push & im[0]
+ | i_outcr & im[1];
+ wire sel1_d = sel1_tmp & il[2]
+ | incdec8 & im[2]
+ | g_mw2 & i_ldnndd & im[2]
+ | g_mw1 & i_push & im[2]
+ | i_c16 & (im[2] | im[3])
+ | i_outcr & im[2];
+ wire sel1_e = sel1_tmp & il[3]
+ | incdec8 & im[3]
+ | g_mw1 & i_ldnndd & im[2]
+ | g_mw2 & i_push & im[2]
+ | i_outcr & im[3];
+ wire sel1_h = sel1_tmp & il[4]
+ | incdec8 & im[4]
+ | g_mw2 & (i_ldnnhl | i_ldnndd & im[4])
+ | g_mw1 & (i_push & im[4] | i_exsphl)
+ | i_c16 & (im[4] | im[5])
+ | i_outcr & im[4];
+ wire sel1_l = sel1_tmp & il[5]
+ | incdec8 & im[5]
+ | g_mw1 & (i_ldnnhl | i_ldnndd & im[4])
+ | g_mw2 & (i_push & im[4] | i_exsphl)
+ | i_outcr & im[5];
+ wire sel1_a = sel1_tmp & il[7] | i_ldbca | i_lddea
+ | incdec8 & im[7]
+ | i_cpl | i_neg
+ | g_mw1 & (i_ldnna | i_push & im[6])
+ | i_rotate1
+ | i_outna
+ | i_outcr & im[7];
+ wire sel1_data = g_mw1 & (i_ldhln | i_ldblock | incdec_hl | i_rs_hl | i_setres_hl | i_inblock)
+ | g_imm2 & (i_jpnn | i_jpccnn)
+ | g_out & (i_outcr & im[6] | i_outblock);
+ wire sel1_sph = g_mw2 & i_ldnndd & im[6]
+ | i_c16 & (im[6] | im[7]);
+ wire sel1_spl = g_mw1 & i_ldnndd & im[6];
+ wire sel1_pch = g_mw1 & (i_call | i_callcc | i_rst | intack | nmiack);
+ wire sel1_pcl = g_mw2 & (i_call | i_callcc | i_rst | intack | nmiack);
+ wire sel1_i = i_ldai;
+ wire sel1_r = i_ldar;
+ wire [3:0] sel1 = {
+ sel1_b | sel1_c | sel1_d | sel1_e | sel1_h | sel1_l | sel1_a,
+ sel1_h | sel1_l | sel1_a | sel1_pch | sel1_pcl | sel1_i | sel1_r,
+ sel1_sph | sel1_spl | sel1_d | sel1_e | sel1_a | sel1_pch | sel1_pcl,
+ sel1_data | sel1_spl | sel1_c | sel1_e | sel1_l | sel1_a | sel1_pcl | sel1_r
+ };
+ wire sel_rld = g_mw1 & i_rld;
+ wire sel_rrd = g_mw1 & i_rrd;
+ wire [3:0] sel1h = {
+ sel1[3] | sel_rld | sel_rrd,
+ sel1[2] | sel_rld | sel_rrd,
+ sel1[1] | sel_rld | sel_rrd,
+ sel1[0] | sel_rld | sel_rrd
+ };
+ wire [3:0] sel1l = {
+ sel1[3] | sel_rld,
+ sel1[2] | sel_rld,
+ sel1[1] | sel_rld,
+ sel1[0] | sel_rrd
+ };
+ //initial $monitor($stime,, sel1_b, sel1_c, sel1_d, sel1_e, sel1_h, sel1_l, sel1_a, sel1_data, sel1_sph, sel1_spl, sel1_pch, sel1_pcl);
+ //
+ wire [7:0] alu_z, alu_c;
+ assign alu_zero = ~| alu_z;
+ wire inva = dec8 | i_djnz;
+ wire sub = i_cpblock | arith8 & i[4] | i_daa & q_f[1] | i_cpl | i_neg | arith16 & ~i[3];
+ wire asu_co;
+ wire ci = q_f[0] & arith8 & ~i[5] & i[3] | (add16 | arith16) & asu_co | incdec8 & ~i[0];
+ wire s_and = i_and;
+ wire s_xor = i_cpblock | i_cpl | arith8 | i_xor | incdec8 | i_c16 | i_daa | i_neg | i_djnz;
+ wire s_or = ~s_and & ~s_xor & ~rs & ~i_outcr;
+ wire ec = i_cpblock | arith8 & (~i[5] | i[3]) | incdec8 | i_c16 | i_daa | i_neg | i_djnz;
+ wire [7:0] alu_a = select0(sel0, { q_a, q_h });
+ wire [3:0] alu_bh = select1h(sel1h, { data[7:4], q_data[7:4], q_sph[7:4], q_spl[7:4], q_i[7:4], q_r[7:4], q_pch[7:4], q_pcl[7:4], q_b[7:4], q_c[7:4], q_d[7:4], q_e[7:4], q_h[7:4], q_l[7:4], q_a[7:4] });
+ wire [3:0] alu_bl = select1l(sel1l, { data[3:0], q_data[3:0], q_sph[3:0], q_spl[3:0], q_i[3:0], q_r[3:0], q_pch[3:0], q_pcl[3:0], q_b[3:0], q_c[3:0], q_d[3:0], q_e[3:0], q_h[3:0], q_l[3:0], q_data[7:4], q_a[3:0] });
+ wire [7:0] alu_b = { alu_bh, alu_bl };
+ alu alu(.c_in(ci), .im(im), .a(alu_a), .b(alu_b), .inva(inva), .invb(sub),
+ .reg_q_c(q_f[0]), .reg_q_h(q_f[4]),
+ .s_and(s_and), .s_or(s_or), .s_xor(s_xor), .ec(ec),
+ .i_daa(i_daa), .set(set), .res(res), .l(l), .r(r),
+ .z(alu_z), .co(alu_c));
+ //
+ // ASU block
+ //
+ // selector 2 (for asu-input a)
+ wire sel2_bc = g_if & (i_ldblock | i_cpblock | (i_c16 | i_incdec16) & ~i[5] & ~i[4])
+ | g_in & i_inblock
+ | g_mr1 & i_outblock;
+ wire sel2_de = g_mw1 & i_ldblock
+ | (i_c16 | i_incdec16) & ~i[5] & i[4];
+ wire sel2_hl = g_disp
+ | i_ldsphl | i_exdehl | (i_c16 | i_incdec16) & i[5] & ~i[4] | i_jphl
+ | g_mr1 & (i_ldblock | i_cpblock)
+ | g_out & i_outblock
+ | g_mw1 & i_inblock;
+ wire sel2_pc = i_jr | i_jrcc | i_djnz;
+ wire sel2_adr = i_ldhl_nn | i_lddd_nn | i_ldnnhl | i_ldnndd
+ | g_mr1 & intack
+ | g_mw2 & (i_exsphl | i_call | i_callcc);
+ wire [2:0] sel2 = {
+ sel2_bc | sel2_de | sel2_hl,
+ sel2_adr | sel2_hl,
+ sel2_pc | sel2_de
+ };
+ // selector 3 (for asu-input b)
+ wire sel3_l = i_c16;
+ wire sel3_data_in = g_disp | i_jr | i_jrcc | i_djnz;
+ wire [1:0] sel3 = {
+ sel3_data_in,
+ sel3_l
+ };
+ //
+ wire [15:0] asu_z;
+ assign asu_zero = ~| asu_z[15:8] & (i_ioblock | ~| asu_z[7:0]);
+ wire asu_ci = i_ldhl_nn | i_lddd_nn | i_ldnnhl | i_ldnndd | i_pop
+ | s_mr1 & (i_exsphl | intack)
+ | (s_mr1 | s_mw1) & (i_ldblock | i_cpblock) & ~i[3]
+ | (s_out | s_mw1) & i_ioblock & ~i[3]
+ | q_f[0] & arith16 | i_incdec16 & ~i[3] | i_jr | i_jrcc | i_djnz | i_ret | i_retcc | retin;
+ wire [2:0] asu_i = {
+ s_in & i_inblock | s_mr1 & i_outblock,
+ s_in & i_inblock | s_mr1 & i_outblock
+ | s_if & (i_push | i_ldblock | i_cpblock | i_incdec16 & i[3] | i_call | i_callcc | i_rst | intack | nmiack)
+ | s_mw1 & (i_push | i_exsphl | (i_ldblock | i_inblock) & i[3] | i_call | i_callcc | i_rst | intack | nmiack)
+ | s_mr1 & (i_ldblock | i_cpblock) & i[3]
+ | s_out & i_outblock & i[3]
+ | s_iack,
+ s_if & i_c16 & ~i[3]
+ };
+ wire [15:0] asu_a = select2(sel2, { q_sph, q_spl, q_pch, q_pcl, q_adrh, q_adrl, q_b, q_c, q_d, q_e, q_h, q_l });
+ wire [7:0] asu_b = select3(sel3, { q_l, data_in });
+ asu asu(.a(asu_a), .b(asu_b), .ci(asu_ci), .i(asu_i), .z(asu_z), .co(asu_co));
+ always @(posedge clk)
+ if (s_if | s_in) q_asu_zero <= asu_zero;
+ //
+ // address selector
+ //
+ wire sela_tmp = g_mr1 | g_mr2 | g_mw1 | g_mw2 | g_in | g_out;
+ wire sela_tmp2 = i_ldann | i_ldnna | i_ldhl_nn | i_lddd_nn | i_ldnnhl | i_ldnndd;
+ wire sela_tmp3 = (idd | ifd) & (g_mr1 | g_mw1);
+ wire selah_a = sela_tmp & (i_inan | i_outna);
+ wire sela_bc = sela_tmp & (i_ldabc | i_ldbca | i_inrc | i_outcr)
+ | g_in & i_inblock | g_out & i_outblock;
+ wire sela_de = g_mr1 & i_ldade | g_mw1 & (i_lddea | i_ldblock);
+ wire sela_hl = ~sela_tmp3 & (sela_tmp & (i_ldrhl | i_ldhlr | i_ldhln | i_cpblock | al_hl | incdec_hl | i_rs_hl | i_rd | i_bit_hl | i_setres_hl)
+ | g_mw1 & i_inblock
+ | g_mr1 & (i_ldblock | i_outblock));
+ wire selah_adr = sela_tmp3 | sela_tmp & sela_tmp2;
+ wire selal_adr = sela_tmp3
+ | sela_tmp & (sela_tmp2 | i_inan | i_outna)
+ | (g_mr1 | g_mr2) & intack;
+ wire sela_sp = sela_tmp & (i_push | i_pop | i_exsphl | i_call | i_callcc | i_ret | i_retcc | retin | i_rst)
+ | (g_mw1 | g_mw2) & (intack | nmiack);
+ wire selah_i = (g_mr1 | g_mr2) & intack;
+ wire [2:0] selah = {
+ sela_bc | sela_de | sela_hl | sela_sp,
+ selah_a | selah_i | sela_hl | sela_sp,
+ selah_adr | selah_i | sela_de | sela_sp
+ };
+ wire [2:0] selal = {
+ sela_bc | sela_de | sela_hl | sela_sp,
+ sela_hl | sela_sp,
+ selal_adr | sela_de | sela_sp
+ };
+ //initial $monitor($stime,, selal,, selah);
+ // final selector
+ wire sel_fr = g_mw2 & i_push & im[6];
+ wire [1:0] self = {
+ sel_rld | sel_rrd,
+ sel_fr | sel_rrd
+ };
+ wire iff2;
+ wire co_pc;
+ //initial $monitor($stime,, self);
+ // sequencer
+ seq seq(.data_in(data), .busreq(busreq), .waitreq(waitreq1), .intreq(intreq), .nmireq(nmireq), .reset_in(reset_in), .clk(clk),
+ .intack(intack), .nmiack(nmiack), .busack(busack_out), .iff2(iff2), .start(start),
+ .icb(icb), .idd(idd), .ied(ied), .ifd(ifd), .inst_reg(inst_reg),
+ .mreq(mreq), .iorq(iorq), .rd(rd), .wr(wr),
+ .imm1(imm1), .imm2(imm2), .mr1(mr1), .mr2(mr2), .mw1(mw1), .mw2(mw2), .disp(disp), .i_in(i_in), .i_out(i_out), .i_eidi(i_eidi), .i_im(i_im), .retin(retin), .i43(i[4:3]),
+ .g_if(g_if), .g_imm2(g_imm2), .g_mr1(g_mr1), .g_mr2(g_mr2), .g_mw1(g_mw1), .g_mw2(g_mw2), .g_disp(g_disp), .g_in(g_in), .g_out(g_out), .g_iack(g_iack),
+ .sgate(sgate),
+ .s_if(s_if), .s_if2(s_if2), .s_imm1(s_imm1), .s_imm2(s_imm2),
+ .s_mr1(s_mr1), .s_mr2(s_mr2), .s_mw1(s_mw1), .s_mw2(s_mw2),
+ .s_disp(s_disp), .s_in(s_in), .s_out(s_out), .s_iack(s_iack),
+`ifdef M1
+ .m1(m1),
+`endif
+ .intmode(intmode), .i_halt(i_halt), .eschalt(eschalt));
+// exchange register
+ always @(posedge clk) begin
+ if (reset_in) begin
+ sel_af <= 1'b0;
+ sel_exx <= 1'b0;
+ end
+ else begin
+ if (s_if & i_exafaf) sel_af <= ~sel_af;
+ if (s_if & i_exx) sel_exx <= ~sel_exx;
+ end
+ end
+//// F register
+ wire sel = alu_z[i[5:3]];
+ wire subf = incdec8 ? i[0] : sub;
+ wire cv0 = arith8 | arith16 | i_daa | i_neg | add16;
+ wire cv1 = i_ccf;
+ wire cv2 = i_scf;
+ wire cv3 = l;
+ wire cv4 = r;
+ wire cv5 = logica;
+ assign d_f[0] = data_in[0] & load_f
+ | (alu_c[7] ^ sub) & cv0
+ | ~q_f[0] & cv1
+ | cv2
+ | alu_b[7] & cv3
+ | alu_b[0] & cv4
+ | q_f[0] & ~(load_f | cv0 | cv1 | cv2 | cv3 | cv4 | cv5);
+ wire nv0 = i_ioblock;
+ wire nv1 = (arith8 | incdec8 | arith16) & subf | i_cpblock | i_cpl | i_neg;
+ wire nv2 = (arith8 | incdec8 | add16 | arith16) & ~subf | ldair | i_inrc | i_rd | i_ccf | i_scf | i_ldblock | logica | rs | ibit;
+ assign d_f[1] = data_in[1] & load_f
+ | alu_b[7] & nv0
+ | nv1
+ | q_f[1] & ~(load_f | nv0 | nv1 | nv2);
+ wire pv0 = ldair;
+ wire pv1 = i_ldblock | i_cpblock;
+ wire pv2 = arith8 | arith16 | i_neg | incdec8;
+ wire pv3 = logica | i_daa | i_rotate2 | shift | i_rd | i_inrc;
+ wire pv4 = ibit;
+ assign d_f[2] = data_in[2] & load_f
+ | iff2 & pv0
+ | ~q_asu_zero & pv1
+ | (alu_c[7] ^ alu_c[6]) & pv2
+ | ~^alu_z[7:0] & pv3
+ |~sel & pv4
+ | q_f[2] & ~(load_f | pv0 | pv1 | pv2 | pv3 | pv4);
+ wire xy0 = arith8_notcp | incdec8 | i_daa | i_cpl | i_neg | i_ccf | i_scf | add16 | arith16 | rs | i_rd | i_inrc;
+ wire xy1 = i_cp;
+ wire xy2 = ibit;
+ wire xy3 = i_ioblock;
+ assign d_f[3] = data_in[3] & load_f
+ | alu_z[3] & (xy0 | i_ldblock)
+ | alu_b[3] & xy1
+ | ~i[5] & i[4] & i[3] & sel & xy2
+ | q_b[3] & xy3
+ | q_f[3] & ~(load_f | xy0 | xy1 | xy2 | xy3);
+ wire hv0 = arith8 | arith16 | i_neg | i_cpblock | incdec8 | add16;
+ wire hv1 = i_and | i_cpl | ibit;
+ wire hv2 = i_ccf;
+ wire hv3 = ldair | i_inrc | i_rd | i_ldblock | i_or | i_xor | i_scf | rs;
+ assign d_f[4] = data_in[4] & load_f
+ | (alu_c[3] ^ subf) & hv0
+ | hv1
+ | q_f[0] & hv2
+ | (q_f[1] ? ~alu_b[3] & (~alu_b[2] | ~alu_b[1]) : alu_b[3] & (alu_b[2] | alu_b[1])) & i_daa
+ | q_f[4] & ~(load_f | hv0 | hv1 | hv2 | hv3 | i_daa);
+ assign d_f[5] = data_in[5] & load_f
+ | alu_z[5] & xy0
+ | alu_b[5] & xy1
+ | i[5] & ~i[4] & i[3] & sel & xy2
+ | q_b[5] & xy3
+ | alu_z[1] & i_ldblock
+ | q_f[5] & ~(load_f | xy0 | xy1 | xy2 | xy3 | i_ldblock);
+ wire zs0 = arith8 | arith16 | i_daa | i_neg | i_cpblock | incdec8 | ldair | i_inrc | i_rd | i_rotate2 | shift | logica;
+ wire zs1 = ibit;
+ wire zl = ~| alu_z[7:0];
+ wire zu = ~| asu_z[7:0];
+ assign d_f[6] = data_in[6] & load_f
+ | zl & zs0 & (~arith16 | zu)
+ | ~sel & zs1
+ | q_asu_zero & i_inblock
+ | asu_zero & i_outblock
+ | q_f[6] & ~(load_f | zs0 | zs1 | i_ioblock);
+ assign d_f[7] = data_in[7] & load_f
+ | alu_z[7] & zs0
+ | i[5] & i[4] & i[3] & sel & zs1
+ | q_b[7] & i_ioblock
+ | q_f[7] & ~(load_f | zs0 | zs1 | i_ioblock);
+// assign q_f_out = q_f;
+ assign q_f_out = { q_f[7:6], 1'b0, q_f[4], 1'b0, q_f[2:0] };
+ wire [7:0] cond3_sel = { q_f[7], ~q_f[7], q_f[2], ~q_f[2], q_f[0], ~q_f[0], q_f[6], ~q_f[6] };
+ assign cond = cond3_sel[i[5:3]];
+ wire [3:0] cond2_sel = { q_f[0], ~q_f[0], q_f[6], ~q_f[6] };
+ assign cond2 = cond2_sel[i[4:3]];
+//
+ wire [15:0] adr = {
+ selectah(selah, { q_adrh, q_a, q_i, q_b, q_d, q_h, q_sph, q_pch }),
+ selectal(selal, { q_adrl, q_c, q_e, q_l, q_spl, q_pcl })
+ };
+ wire [7:0] data_out = selectf(self, { alu_b, q_f_out, q_data[3:0], q_a[3:0], q_a[3:0], q_data[7:4] });
+ wire loadal = loada_hl | loada_l;
+ wire clr_pch1 = reset_in | clr_pch;
+ wire reg_load_f = sgate & ~((g_if | g_mw1) & (al_n | al_hl | incdec_hl | i_rs_hl)) & ~g_out & ~g_disp;
+ reg_a reg_a(.a(alu_z),
+ .load(load_a),
+ .set(reset_in), .regsel(sel_af), .clk(clk), .q(q_a));
+ reg_f reg_f(.a(d_f),
+ .load(reg_load_f),
+ .set(reset_in), .regsel(sel_af), .clk(clk), .q(q_f));
+ reg_dual2 reg_b(.a(alu_z), .a2(asu_z[15:8]),
+ .load(load_b), .load2(loada_bc),
+ .regsel(sel_exx), .clk(clk), .q(q_b));
+ reg_dual2 reg_c(.a(alu_z), .a2(asu_z[7:0]),
+ .load(load_c), .load2(loada_bc),
+ .regsel(sel_exx),
+ .clk(clk), .q(q_c));
+ reg_dual2 reg_d(.a(alu_z), .a2(asu_z[15:8]),
+ .load(load_d), .load2(loada_de),
+ .regsel(sel_exx),
+ .clk(clk), .q(q_d));
+ reg_dual2 reg_e(.a(alu_z), .a2(asu_z[7:0]),
+ .load(load_e), .load2(loada_de),
+ .regsel(sel_exx),
+ .clk(clk), .q(q_e));
+ wire indexvalid = ~(g_mr1 & i_ldrhl | g_mw1 & i_ldhlr);
+ reg_quad3 reg_h(.a(alu_z), .a2(asu_z[15:8]), .a3(q_d),
+ .load(load_h), .load2(loada_hl), .load3(loadex),
+ .regsel(sel_exx),
+ .i_dd(idd & indexvalid), .i_fd(ifd & indexvalid),
+ .clk(clk), .q(q_h));
+ reg_quad3 reg_l(.a(alu_z), .a2(asu_z[7:0]), .a3(q_e),
+ .load(load_l), .load2(loadal), .load3(loadex),
+ .regsel(sel_exx),
+ .i_dd(idd & indexvalid), .i_fd(ifd & indexvalid),
+ .clk(clk), .q(q_l));
+ reg_2s reg_sph(.a(data_in), .a2(asu_z[15:8]),
+ .load(load_sph), .load2(loada_sp),
+ .set(reset_in),
+ .clk(clk), .q(q_sph));
+ reg_2s reg_spl(.a(data_in), .a2(asu_z[7:0]),
+ .load(load_spl), .load2(loada_sp),
+ .set(reset_in),
+ .clk(clk),
+ .q(q_spl));
+ reg_pch reg_pch(.a(data_in), .a2(asu_z[15:8]),
+ .load(load_pch), .load2(loada_pc), .count(co_pc), .dec(dec_pc),
+ .clr(clr_pch1),
+ .clk(clk),
+ .q(q_pch));
+ reg_pcl reg_pcl(.a(alu_z), .a2(asu_z[7:0]), .a3(q_data[5:3]),
+ .load(load_pcl), .load2(loada_pc), .load3(load3_pc), .load66(load66_pc), .count(count_pc), .dec(dec_pc),
+ .clr(reset_in),
+ .clk(clk),
+ .q(q_pcl), .co(co_pc));
+ reg_2 reg_adrh(.a(data_in), .a2(asu_z[15:8]),
+ .load(load_adrh), .load2(loada_adr),
+ .clk(clk),
+ .q(q_adrh));
+ reg_2 reg_adrl(.a(data_in), .a2(asu_z[7:0]),
+ .load(load_adrl), .load2(loada_adr),
+ .clk(clk),
+ .q(q_adrl));
+ reg_r reg_r(.a(q_a),
+ .load(load_r),
+ .count(count_r),
+ .clr(reset_in),
+ .clk(clk),
+ .q(q_r));
+ reg_simplec reg_i(.a(q_a),
+ .load(load_i),
+ .clr(reset_in),
+ .clk(clk),
+ .q(q_i));
+ reg_simple reg_data(.a(alu_z),
+ .load(load_data),
+ .clk(clk),
+ .q(q_data));
+`ifdef DEBUG
+ wire [15:0] debug_pc, debug_sp, debug_bc, debug_de, debug_hl;
+ assign debug_pc = { q_pch, q_pcl };
+ assign debug_sp = { q_sph, q_spl };
+ assign debug_bc = { q_b, q_c };
+ assign debug_de = { q_d, q_e };
+ assign debug_hl = { q_h, q_l };
+ initial $monitor($stime, " %x %x %x %x %x %x %x %x", seq.state, debug_pc, debug_sp, debug_bc, debug_de, debug_hl, q_a, q_f_out);
+`endif
+endmodule
+
+module seq(data_in, busreq, waitreq, intreq, nmireq, reset_in, clk,
+ intack, nmiack, busack, iff2, icb, idd, ied, ifd, inst_reg, start,
+ mreq, iorq, rd, wr,
+ imm1, imm2, mr1, mr2, mw1, mw2, disp, i_in, i_out, i_eidi, i_im, retin, i43,
+ g_if, g_imm2, g_mr1, g_mr2, g_mw1, g_mw2, g_disp, g_in, g_out, g_iack,
+ sgate,
+ s_if, s_if2, s_imm1, s_imm2, s_mr1, s_mr2, s_mw1, s_mw2, s_disp, s_in, s_out, s_iack,
+`ifdef M1
+ m1,
+`endif
+ intmode, i_halt, eschalt);
+ input [7:0] data_in;
+ input [1:0] i43;
+ input busreq, waitreq, intreq, nmireq, reset_in, clk;
+ input imm1, imm2, mr1, mr2, mw1, mw2, disp, i_in, i_out, i_eidi, i_im, retin;
+ input i_halt;
+ output mreq, iorq, rd, wr;
+ output intack, nmiack, busack, iff2, icb, idd, ied, ifd, start;
+ output [7:0] inst_reg;
+ output g_if, g_imm2, g_mr1, g_mr2, g_mw1, g_mw2, g_disp, g_in, g_out, g_iack;
+ output sgate;
+ output s_if, s_if2, s_imm1, s_imm2, s_mr1, s_mr2, s_mw1, s_mw2, s_disp, s_in, s_out, s_iack;
+ output [1:0] intmode;
+ output eschalt;
+`ifdef M1
+ output m1;
+`endif
+ parameter S_IF1 = 4'b0000;
+ parameter S_IF2 = 4'b0001;
+ parameter S_IMM1 = 4'b0010;
+ parameter S_IMM2 = 4'b0011;
+ parameter S_MR1 = 4'b0100;
+ parameter S_MR2 = 4'b0101;
+ parameter S_DISP = 4'b0110;
+ parameter S_IN = 4'b0111;
+ parameter S_IACK = 4'b1000;
+ parameter S_MW1 = 4'b1100;
+ parameter S_MW2 = 4'b1101;
+ parameter S_OUT = 4'b1111;
+ reg [3:0] state;
+ reg [7:0] inst_reg;
+ reg icb, ied, idd, ifd, iff1, iff2, intack, nmiack, busack, eschalt;
+ reg [1:0] intmode;
+ reg start;
+ wire g_if = state[3:1] == 3'b000;
+ wire g_if1 = state == S_IF1;
+ wire g_if2 = state == S_IF2;
+ wire g_imm1 = state == S_IMM1;
+ wire g_imm2 = state == S_IMM2;
+ wire g_mr1 = state == S_MR1;
+ wire g_mr2 = state == S_MR2;
+ wire g_disp = state == S_DISP;
+ wire g_in = state == S_IN;
+ wire g_iack = state == S_IACK; // IM2 | NMI only
+ wire g_mw1 = state == S_MW1;
+ wire g_mw2 = state == S_MW2;
+ wire g_out = state == S_OUT;
+ wire sgate = ~reset_in & ~busack & ~waitreq;
+ wire s_if = sgate & g_if;
+ wire s_if2 = sgate & g_if2;
+ wire s_imm1 = sgate & g_imm1;
+ wire s_imm2 = sgate & g_imm2;
+ wire s_mr1 = sgate & g_mr1;
+ wire s_mr2 = sgate & g_mr2;
+ wire s_disp = sgate & g_disp;
+ wire s_in = sgate & g_in;
+ wire s_iack = sgate & g_iack;
+ wire s_mw1 = sgate & g_mw1;
+ wire s_mw2 = sgate & g_mw2;
+ wire s_out = sgate & g_out;
+ wire nextcycle = g_if1 & data_in != 8'hcb & data_in != 8'hdd & data_in != 8'hed & data_in != 8'hfd & ~intack & ~disp & ~imm1 & ~imm2 & ~mr1 & ~mr2 & ~mw1 & ~mw2 & ~i_in
+ | g_if2 & ~imm1 & ~imm2 & ~mr1 & ~mr2 & ~i_in & ~i_out
+ | g_imm1 & ~imm2 & ~mw1 & ~i_in & ~i_out
+ | g_imm2 & ~mr1 & ~mr2 & ~mw1 & ~mw2
+ | g_mr1 & ~mr2 & ~mw1 & ~mw2 & ~i_out
+ | g_mr2 & ~intack & ~mw1 & ~mw2
+ | g_mw1 & ~mw2
+ | g_mw2 & ~intack
+ | g_in & ~mw1
+ | g_out;
+ wire next_if2 = (g_if1 & (data_in == 8'hcb & ~idd & ~ifd | data_in == 8'hed)
+ | g_disp & icb);
+ wire next_imm1 = (g_if1 & ~disp & (imm1 | imm2)
+ | g_disp & ~icb & imm1
+ | g_if2 & (imm1 | imm2));
+ wire next_imm2 = g_imm1 & imm2;
+ wire next_mr1 = (g_if1 & ~disp & ~imm1 & ~imm2 & (mr1 | mr2)
+ | g_disp & ~icb & ~imm1 & mr1
+ | g_if2 & ~imm1 & ~imm2 & (mr1 | mr2)
+ | g_imm2 & (mr1 | mr2)
+ | g_mw2 & intack & intmode == 2'b11);
+ wire next_mr2 = g_mr1 & mr2;
+ wire next_disp = g_if1 & (data_in == 8'hcb & (idd | ifd) | disp);
+ wire next_in = i_in & (g_if1 & ~imm1 & ~mw1
+ | g_if2
+ | g_imm1);
+ wire next_iack = (nextcycle & (nmireq | intreq & iff1 & intmode == 2'b11));
+ wire next_mw1 = (g_if1 & ~disp & ~imm1 & ~imm2 & ~mr1 & ~mr2 & (mw1 | mw2)
+ | g_disp & ~icb & ~imm1 & ~mr1
+ | g_imm1 & ~imm2 & mw1
+ | g_imm2 & ~mr1 & ~mr2 & (mw1 | mw2)
+ | g_mr1 & ~mr2 & (mw1 | mw2)
+ | g_mr2 & ~intack & (mw1 | mw2)
+ | g_in & mw1
+ | g_iack);
+ wire next_mw2 = g_mw1 & mw2;
+ wire next_out = i_out & (g_if2 & ~imm1 & ~mr1
+ | g_imm1
+ | g_mr1);
+ always @(posedge clk) begin
+ if (reset_in) begin
+ state <= S_IF1;
+ start <= 1'b1;
+ icb <= 1'b0;
+ ied <= 1'b0;
+ idd <= 1'b0;
+ ifd <= 1'b0;
+ iff1 <= 1'b0;
+ iff2 <= 1'b0;
+ intmode <= 2'b00;
+ intack <= 1'b0;
+ nmiack <= 1'b0;
+ busack <= 1'b0;
+ eschalt <= 1'b0;
+ end
+ else if (busack) begin
+ if (~busreq) busack <= 1'b0;
+ end
+ else if (waitreq) start <= 1'b0;
+ else begin
+ state <= {
+ next_iack | next_mw1 | next_mw2 | next_out,
+ next_mr1 | next_mr2 | next_disp | next_in | next_mw1 | next_mw2 | next_out,
+ next_imm1 | next_imm2 | next_disp | next_in | next_out,
+ next_if2 | next_imm2 | next_mr2 | next_in | next_mw2 | next_out
+ };
+ start <= 1'b1;
+ if (g_if1) begin
+ inst_reg <= data_in;
+ intack <= 1'b0; // when IM0 | IM1
+ eschalt <= 1'b0;
+ if (data_in == 8'hcb) icb <= 1'b1;
+ if (data_in == 8'hed) ied <= 1'b1;
+ if (data_in == 8'hdd) begin
+ idd <= 1'b1;
+ ifd <= 1'b0;
+ end
+ if (data_in == 8'hfd) begin
+ ifd <= 1'b1;
+ idd <= 1'b0;
+ end
+ end
+ else if (g_if2) inst_reg <= data_in;
+ else if (g_mr2) intack <= 1'b0; // IM2
+ else if (g_mw2) begin
+ if (intack & intmode != 2'b11) intack <= 1'b0;
+ nmiack <= 1'b0;
+ end
+ else if (g_iack) eschalt <= 1'b0;
+ if (i_eidi) begin
+ iff1 <= i43[0];
+ iff2 <= i43[0];
+ end
+ if (retin) iff1 <= iff2;
+ if (i_im) intmode <= i43[1:0];
+ if (nextcycle) begin
+ icb <= 1'b0;
+ ied <= 1'b0;
+ idd <= 1'b0;
+ ifd <= 1'b0;
+ if (nmireq) begin
+ nmiack <= 1'b1;
+ iff1 <= 1'b0;
+ eschalt <= i_halt;
+ inst_reg <= 8'b00000000;
+ end
+ else if (intreq & iff1) begin
+ intack <= 1'b1;
+ iff1 <= 1'b0;
+ iff2 <= 1'b0;
+ eschalt <= i_halt;
+ inst_reg <= 8'b00000000;
+ end
+ end
+ if (busreq) busack <= 1'b1;
+ end
+ end
+ wire intack_r = (g_if | g_iack) & intack;
+ wire iorq_t = state[2:0] == 3'b111 | intack_r;
+ wire iorq = ~busack & iorq_t;
+ wire mreq = ~busack & ~iorq_t & ~intack_r;
+ wire rd = ~busack & (~state[3] | g_iack) & ~intack_r;
+ wire wr = ~busack & state[3] & ~g_iack;
+`ifdef M1
+ wire m1 = g_if | g_iack;
+`endif
+endmodule
+
+// ASU
+// z,co = a + b + ci 8bit/16bit i = 3'b000 for lower 8bit of 16bit arithmetic / 16bit increment
+// z,co = b - a - ci 8bit i = 3'b001 for lower 8bit of 16bit arithmetic
+// z = a - ~ci 16bit i = 3'b010 16bit decrement
+// z = a - 0x100 16bit i = 3'b110 upper 8bit decrement
+
+module asu(a, b, ci, i, z, co);
+ input [15:0] a;
+ input [7:0] b;
+ input ci;
+ input [2:0] i;
+ output [15:0] z;
+ output co;
+ wire [14:0] c;
+ wire [14:0] tand, tor;
+ wire [7:0] a1 = a ^ { 8 { i[0] } };
+ wire [7:0] b1 = b | { 8 { i[1] } };
+ wire c1 = ci ^ (i[2] | i[0]);
+ assign tand[7:0] = a1[7:0] & b1[7:0];
+ assign tor[7:0] = a1[7:0] | b1[7:0];
+ assign c[0] = tand[0] | tor[0] & c1;
+ assign c[1] = tand[1] | tor[1] & tand[0]
+ | &tor[1:0] & c1;
+ assign c[2] = tand[2] | tor[2] & tand[1]
+ | &tor[2:1] & tand[0]
+ | &tor[2:0] & c1;
+ assign c[3] = tand[3] | tor[3] & tand[2]
+ | &tor[3:2] & tand[1]
+ | &tor[3:1] & tand[0]
+ | &tor[3:0] & c1;
+ assign c[4] = tand[4] | tor[4] & tand[3]
+ | &tor[4:3] & tand[2]
+ | &tor[4:2] & tand[1]
+ | &tor[4:1] & tand[0]
+ | &tor[4:0] & c1;
+ assign c[5] = tand[5] | tor[5] & tand[4]
+ | &tor[5:4] & tand[3]
+ | &tor[5:3] & tand[2]
+ | &tor[5:2] & tand[1]
+ | &tor[5:1] & tand[0]
+ | &tor[5:0] & c1;
+ assign c[6] = tand[6] | tor[6] & tand[5]
+ | &tor[6:5] & tand[4]
+ | &tor[6:4] & tand[3]
+ | &tor[6:3] & tand[2]
+ | &tor[6:2] & tand[1]
+ | &tor[6:1] & tand[0]
+ | &tor[6:0] & c1;
+ assign c[7] = tand[7] | tor[7] & tand[6]
+ | &tor[7:6] & tand[5]
+ | &tor[7:5] & tand[4]
+ | &tor[7:4] & tand[3]
+ | &tor[7:3] & tand[2]
+ | &tor[7:2] & tand[1]
+ | &tor[7:1] & tand[0]
+ | &tor[7:0] & c1;
+ assign z[7:0] = a1[7:0] ^ b1[7:0] ^ { c[6:0], c1 };
+ wire co = c[7] ^ (i[2] | i[0]);
+ assign tand[14:8] = a[14:8] & { 8 { b1[7] } };
+ assign tor[14:8] = a[14:8] | { 8 { b1[7] } };
+ assign c[8] = tand[8] | tor[8] & co;
+ assign c[9] = tand[9] | tor[9] & tand[8]
+ | &tor[9:8] & co;
+ assign c[10] = tand[10] | tor[10] & tand[9]
+ | &tor[10:9] & tand[8]
+ | &tor[10:8] & co;
+ assign c[11] = tand[11] | tor[11] & tand[10]
+ | &tor[11:10] & tand[9]
+ | &tor[11:9] & tand[8]
+ | &tor[11:8] & co;
+ assign c[12] = tand[12] | tor[12] & tand[11]
+ | &tor[12:11] & tand[10]
+ | &tor[12:10] & tand[9]
+ | &tor[12:9] & tand[8]
+ | &tor[12:8] & co;
+ assign c[13] = tand[13] | tor[13] & tand[12]
+ | &tor[13:12] & tand[11]
+ | &tor[13:11] & tand[10]
+ | &tor[13:10] & tand[9]
+ | &tor[13:9] & tand[8]
+ | &tor[13:8] & co;
+ assign c[14] = tand[14] | tor[14] & tand[13]
+ | &tor[14:13] & tand[12]
+ | &tor[14:12] & tand[11]
+ | &tor[14:11] & tand[10]
+ | &tor[14:10] & tand[9]
+ | &tor[14:9] & tand[8]
+ | &tor[14:8] & co;
+ assign z[15:8] = a[15:8] ^ { 8 { b1[7] } } ^ { c[14:8], co };
+ //initial $monitor($stime,, a,, b,, ci,, i,, c,, z,, co);
+endmodule
+
+// ALU for general 8-bit arithmetic/logical
+
+module alu(c_in, im, a, b, inva, invb, reg_q_c, reg_q_h, s_and, s_or, s_xor, ec, i_daa, set, res, l, r, z, co);
+ input [7:0] im, a, b;
+ input inva, invb, c_in, reg_q_c, reg_q_h, s_and, s_or, s_xor, ec;
+ input i_daa, set, res, l, r;
+ output [7:0] z, co;
+ wire [7:0] b1, c;
+ wire [7:0] a1 = a ^ { 8 { inva } };
+ wire daah = a1[3] & (a1[2] | a1[1]);
+ wire daac = a1[7] & (a1[6] | a1[5]) | a1[7] & a1[4] & daah;
+ wire daa0 = i_daa & (reg_q_h | daah);
+ wire daa1 = i_daa & (reg_q_c | daac);
+ wire [7:0] b0 = b & { 8 { ~i_daa } };
+ assign b1[0] = (b0[0] ^ invb | set & im[0]) & ~(res & im[0]);
+ assign b1[1] = ((b0[1] | daa0) ^ invb | set & im[1]) & ~(res & im[1]);
+ assign b1[2] = ((b0[2] | daa0) ^ invb | set & im[2]) & ~(res & im[2]);
+ assign b1[3] = (b0[3] ^ invb | set & im[3]) & ~(res & im[3]);
+ assign b1[4] = (b0[4] ^ invb | set & im[4]) & ~(res & im[4]);
+ assign b1[5] = ((b0[5] | daa1) ^ invb | set & im[5]) & ~(res & im[5]);
+ assign b1[6] = ((b0[6] | daa1) ^ invb | set & im[6]) & ~(res & im[6]);
+ assign b1[7] = (b0[7] ^ invb | set & im[7]) & ~(res & im[7]);
+ wire [7:0] tand = a1 & b1;
+ wire [7:0] tor = a1 | b1;
+ wire rlc = l & im[0];
+ wire rrc = r & im[1];
+ wire rl = l & im[2];
+ wire rr = r & im[3];
+ wire sra = r & im[5];
+ wire ci = c_in ^ invb;
+ assign z[0] = s_and & tand[0] | s_or & tor[0] | s_xor & (a1[0] ^ b1[0] ^ ci & ec)
+ | rlc & b1[7] | rl & reg_q_c | r & b1[1];
+ assign c[0] = tand[0] | tor[0] & ci;
+ assign z[1] = s_and & tand[1] | s_or & tor[1] | s_xor & (a1[1] ^ b1[1] ^ c[0] & ec)
+ | l & b1[0] | r & b1[2];
+ assign c[1] = tand[1] | tor[1] & tand[0]
+ | &tor[1:0] & ci;
+ assign z[2] = s_and & tand[2] | s_or & tor[2] | s_xor & (a1[2] ^ b1[2] ^ c[1] & ec)
+ | l & b1[1] | r & b1[3];
+ assign c[2] = tand[2] | tor[2] & tand[1]
+ | &tor[2:1] & tand[0]
+ | &tor[2:0] & ci;
+ assign z[3] = s_and & tand[3] | s_or & tor[3] | s_xor & (a1[3] ^ b1[3] ^ c[2] & ec)
+ | l & b1[2] | r & b1[4];
+ assign c[3] = tand[3] | tor[3] & tand[2]
+ | &tor[3:2] & tand[1]
+ | &tor[3:1] & tand[0]
+ | &tor[3:0] & ci;
+ assign z[4] = s_and & tand[4] | s_or & tor[4] | s_xor & (a1[4] ^ b1[4] ^ c[3] & ec)
+ | l & b1[3] | r & b1[5];
+ assign c[4] = tand[4] | tor[4] & tand[3]
+ | &tor[4:3] & tand[2]
+ | &tor[4:2] & tand[1]
+ | &tor[4:1] & tand[0]
+ | &tor[4:0] & ci;
+ assign z[5] = s_and & tand[5] | s_or & tor[5] | s_xor & (a1[5] ^ b1[5] ^ c[4] & ec)
+ | l & b1[4] | r & b1[6];
+ assign c[5] = tand[5] | tor[5] & tand[4]
+ | &tor[5:4] & tand[3]
+ | &tor[5:3] & tand[2]
+ | &tor[5:2] & tand[1]
+ | &tor[5:1] & tand[0]
+ | &tor[5:0] & ci;
+ assign z[6] = s_and & tand[6] | s_or & tor[6] | s_xor & (a1[6] ^ b1[6] ^ c[5] & ec)
+ | l & b1[5] | r & b1[7];
+ assign c[6] = tand[6] | tor[6] & tand[5]
+ | &tor[6:5] & tand[4]
+ | &tor[6:4] & tand[3]
+ | &tor[6:3] & tand[2]
+ | &tor[6:2] & tand[1]
+ | &tor[6:1] & tand[0]
+ | &tor[6:0] & ci;
+ assign z[7] = s_and & tand[7] | s_or & tor[7] | s_xor & (a1[7] ^ b1[7] ^ c[6] & ec)
+ | l & b1[6] | rrc & b1[0] | rr & reg_q_c | sra & b1[7];
+ assign c[7] = tand[7] | tor[7] & tand[6]
+ | &tor[7:6] & tand[5]
+ | &tor[7:5] & tand[4]
+ | &tor[7:4] & tand[3]
+ | &tor[7:3] & tand[2]
+ | &tor[7:2] & tand[1]
+ | &tor[7:1] & tand[0]
+ | &tor[7:0] & ci;
+ assign co = { i_daa ? daa1 ^ invb : c[7], c[6:0] };
+ //initial $monitor($stime,, c_in, a1,, b1,, inva, invb, reg_q_c, reg_q_h, s_and, s_or, s_xor, ec, i_daa, set, res, l, r, z, co);
+endmodule
+
+// A register: dual register
+
+module reg_a(a, load, set, regsel, clk, q);
+ input [7:0] a;
+ input load, set, regsel, clk;
+ output [7:0] q;
+ reg [7:0] q0, q1;
+ always @(posedge clk) begin
+ if (set) begin
+ q0 <= 8'b11111111;
+ q1 <= 8'b11111111;
+ end
+ else if (load)
+ if (regsel) q1 <= a;
+ else q0 <= a;
+ end
+ assign q = regsel ? q1 : q0;
+endmodule
+
+// F register: dual register
+
+module reg_f(a, load, set, regsel, clk, q);
+ input [7:0] a;
+ input load, set, regsel, clk;
+ output [7:0] q;
+ reg [7:0] q0, q1;
+ always @(posedge clk) begin
+ if (set) begin
+ q0 <= 8'b11111111;
+ q1 <= 8'b11111111;
+ end
+ else if (load)
+ if (regsel) q1 <= a;
+ else q0 <= a;
+ end
+ assign q = regsel ? q1 : q0;
+endmodule
+
+// simple register
+
+module reg_simple(a, load, clk, q);
+ input [7:0] a;
+ input load, clk;
+ output [7:0] q;
+ reg [7:0] q;
+ always @(posedge clk) begin
+ if (load) q <= a;
+ end
+endmodule
+
+// simple register w/clear
+
+module reg_simplec(a, load, clr, clk, q);
+ input [7:0] a;
+ input load, clr, clk;
+ output [7:0] q;
+ reg [7:0] q;
+ always @(posedge clk) begin
+ if (clr) q <= 8'b00000000;
+ else if (load) q <= a;
+ end
+endmodule
+
+// 2 input dual register
+
+module reg_dual2(a, a2, load, load2, regsel, clk, q);
+ input [7:0] a, a2;
+ input load, load2, regsel, clk;
+ output [7:0] q;
+ reg [7:0] q0 = 8'b00000000, q1 = 8'b00000000;
+ always @(posedge clk) begin
+ if (load)
+ if (regsel) q1 <= a;
+ else q0 <= a;
+ else if (load2)
+ if (regsel) q1 <= a2;
+ else q0 <= a2;
+ end
+ assign q = regsel ? q1 : q0;
+endmodule
+
+// 2 input register
+
+module reg_2(a, a2, load, load2, clk, q);
+ input [7:0] a, a2;
+ input load, load2, clk;
+ output [7:0] q;
+ reg [7:0] q;
+ always @(posedge clk) begin
+ if (load) q <= a;
+ else if (load2) q <= a2;
+ end
+endmodule
+
+// 2 input register w/ set
+
+module reg_2s(a, a2, load, load2, set, clk, q);
+ input [7:0] a, a2;
+ input load, load2, set, clk;
+ output [7:0] q;
+ reg [7:0] q;
+ always @(posedge clk) begin
+ if (set) q <= 8'b11111111;
+ else if (load) q <= a;
+ else if (load2) q <= a2;
+ end
+endmodule
+
+// 3 input quad register
+
+module reg_quad3(a, a2, a3, load, load2, load3, regsel, i_dd, i_fd, clk, q);
+ input [7:0] a, a2, a3;
+ input load, load2, load3, regsel, i_dd, i_fd, clk;
+ output [7:0] q;
+ reg [7:0] q0 = 8'b00000000, q1 = 8'b00000000, qx = 8'b00000000, qy = 8'b00000000;
+ function [7:0] select;
+ input [1:0] sel;
+ input [31:0] a;
+ begin
+ case (sel)
+ 2'h0: select = a[31:24];
+ 2'h1: select = a[23:16];
+ 2'h2: select = a[15:8];
+ 2'h3: select = a[7:0];
+ endcase
+ end
+ endfunction
+ always @(posedge clk) begin
+ if (load)
+ if (i_dd) qx <= a;
+ else if (i_fd) qy <= a;
+ else if (regsel) q1 <= a;
+ else q0 <= a;
+ else if (load2)
+ if (i_dd) qx <= a2;
+ else if (i_fd) qy <= a2;
+ else if (regsel) q1 <= a2;
+ else q0 <= a2;
+ else if (load3)
+ if (i_dd) qx <= a3;
+ else if (i_fd) qy <= a3;
+ else if (regsel) q1 <= a3;
+ else q0 <= a3;
+ end
+ assign q = select({ i_dd | i_fd, ~i_dd & regsel | i_fd }, { q0, q1, qx, qy });
+endmodule
+
+// PCH register: 2 input register w/ increment, decrement, clear
+
+module reg_pch(a, a2, load, load2, count, dec, clr, clk, q);
+ input [7:0] a, a2;
+ input load, load2, count, dec, clr, clk;
+ output [7:0] q;
+ wire [6:0] c, qa;
+ reg [7:0] q;
+ wire notload = ~load & ~load2 & ~clr;
+ assign qa = q[6:0] ^ { 7 { dec } };
+ assign c[0] = qa[0] & count;
+ assign c[1] = &qa[1:0] & count;
+ assign c[2] = &qa[2:0] & count;
+ assign c[3] = &qa[3:0] & count;
+ assign c[4] = &qa[4:0] & count;
+ assign c[5] = &qa[5:0] & count;
+ assign c[6] = &qa[6:0] & count;
+ wire [7:0] d = { 8 { load } } & a | { 8 { load2 } } & a2 | { 8 { notload } } & (q ^ { c, count });
+ always @(posedge clk) q <= d;
+endmodule
+
+// PCL register: 3 input register w/ increment, decrement, clear, load 66
+
+module reg_pcl(a, a2, a3, load, load2, load3, count, dec, clr, load66, clk, q, co);
+ input [7:0] a, a2;
+ input [2:0] a3;
+ input load, load2, load3, count, dec, clr, load66, clk;
+ output [7:0] q;
+ output co;
+ wire [6:0] c;
+ wire [7:0] d, qa;
+ reg [7:0] q;
+ wire notload = ~load & ~load2 & ~load3 & ~load66 & ~clr;
+ assign qa = q ^ { 8 { dec } };
+ assign c[0] = qa[0] & count;
+ assign c[1] = &qa[1:0] & count;
+ assign c[2] = &qa[2:0] & count;
+ assign c[3] = &qa[3:0] & count;
+ assign c[4] = &qa[4:0] & count;
+ assign c[5] = &qa[5:0] & count;
+ assign c[6] = &qa[6:0] & count;
+ assign co = &qa[7:0] & count;
+ assign d[0] = load & a[0] | load2 & a2[0] | notload & (q[0] ^ count);
+ assign d[1] = load & a[1] | load2 & a2[1] | notload & (q[1] ^ c[0]) | load66;
+ assign d[2] = load & a[2] | load2 & a2[2] | notload & (q[2] ^ c[1]) | load66;
+ assign d[3] = load & a[3] | load2 & a2[3] | notload & (q[3] ^ c[2]) | load3 & a3[0];
+ assign d[4] = load & a[4] | load2 & a2[4] | notload & (q[4] ^ c[3]) | load3 & a3[1];
+ assign d[5] = load & a[5] | load2 & a2[5] | notload & (q[5] ^ c[4]) | load3 & a3[2] | load66;
+ assign d[6] = load & a[6] | load2 & a2[6] | notload & (q[6] ^ c[5]) | load66;
+ assign d[7] = load & a[7] | load2 & a2[7] | notload & (q[7] ^ c[6]);
+ always @(posedge clk) q <= d;
+endmodule
+
+// R register: up counter
+
+module reg_r(a, load, count, clr, clk, q);
+ input [7:0] a;
+ input load, count, clr, clk;
+ output [7:0] q;
+ reg [7:0] q;
+ always @(posedge clk)
+ if (clr) q <= 8'b00000000;
+ else if (load) q <= a;
+ else if (count) q[6:0] <= q[6:0] + 1;
+endmodule
+
diff --git a/common/CPU/FZ80/fz80c.v b/common/CPU/FZ80/fz80c.v
new file mode 100644
index 00000000..ae9d5aec
--- /dev/null
+++ b/common/CPU/FZ80/fz80c.v
@@ -0,0 +1,459 @@
+//
+// Z80 Compatible Bus wrapper for fz80 ver.0.52
+//
+// Version 0.52a
+//
+// Copyright (c) 2004 Tatsuyuki Sato
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+/*
+note:
+
+ It should be necessary to set "`define M1" inf fz80.
+ ---------------------------------------------------
+
+ -----------------------------
+ non-compatible spesification.
+ -----------------------------
+
+ 1.no internal cycle
+ A internal cycle without bus cycle doesn't exist.
+ So some instruction is faster than Z80.
+
+ 2.ealy tristate after reset
+ The "at" and "dt" assert after 1cycle from reset.
+ The Z80 is after 2cycles from reset.
+
+ 3.busreq/busack timming are not checked yet.
+
+ 4.halt always output 1(no supported).
+
+ -------------
+ state changes
+ -------------
++------+---+---+---+---+---+---+
+|state |t1w|t1 |t2w|t2 |t3 |t4 |
++------+---+---+---+---+---+---+
+| M1 | - | O | - | O*| O | O |
+| MEM | - | O | - | O*| x | O |
+| IO | - | O | - | O*| x | O |
+| SpM1 | O | O | O | O | O | O |
++------+---+---+---+---+---+---+
+ *:sense wait (wait cycle)
+
+histry:
+ 2004. 9.16 ver.0.52a
+ bugfix power on reset error.
+ halt_n output always 1 (do not supported yet)
+ change `MREQ_INSIDE_RD logic.
+
+ 2004. 9.10 ver.0.52
+ added power on reset
+ bugfix mreq inside rd mode
+ 2004. 9. 9 ver.0.51
+ 1st test version
+*/
+
+//`define FZ80C_NGC_LINK // xilinx XST link synthesized fz80c.v
+//`define DEBUG_OUTPUT
+
+// ----- design option -----
+`define MREQ_INSIDE_RD // for wr = (rfsh & ~mreq_n & rd_n);
+//`define FZ80C_POWER_ON_RESET // power on self reset
+//`define DISABLE_BUSREQ_SYNC // bypass busreq/busack syncronize.
+//`define DISABLE_REFRESH_CYCLE // no rfsh cycle & inst code fetch t4 raise
+//`define NMI_SYNC_SENSE // nmi fall sense with clk
+//`define DO_VAL_IF_DT 8'h00 // "do" set fixed value when output disable
+
+module fz80c (/*AUTOARG*/
+ // Inputs
+ reset_n, clk, wait_n, int_n, nmi_n, busrq_n, di,
+ // Outputs
+ m1_n, mreq_n, iorq_n, rd_n, wr_n, rfsh_n, halt_n, busak_n,
+`ifdef DEBUG_OUTPUT
+ ts,
+ wait_window,
+`endif
+ A, At,
+ do,dt
+);
+
+input reset_n,clk;
+input wait_n , busrq_n;
+input int_n,nmi_n;
+input [7:0] di;
+
+output m1_n;
+output mreq_n;
+output iorq_n;
+output rd_n;
+output wr_n;
+output rfsh_n;
+output halt_n;
+output busak_n; // (enable controll : mreq_n,iorq_n,rd_n,wr_n,rfsh_n)
+output [15:0] A; // Address Bus
+output [7:0] do; // Data Bus
+output dt; // tristate controll : do
+output At; // tristate controll : A
+
+`ifdef DEBUG_OUTPUT
+output [3:0] ts;
+output wait_window;
+`endif
+
+`ifndef FZ80C_NGC_LINK
+
+// internal register
+reg [15:0] A;
+reg [7:0] dinst_r;
+reg [7:0] do_r;
+reg [3:0] ts;
+reg reset_s;
+reg m1_r;
+`ifndef DISABLE_REFRESH_CYCLE
+ reg rfsh_r;
+`endif
+reg mreq_r;
+reg iorq_r;
+reg wr_r;
+reg rd_r;
+reg wait_r;
+reg dt_r,dt_t4;
+`ifndef DISABLE_BUSREQ_SYNC
+reg at_r;
+reg busack_r;
+reg busreq_r;
+`endif
+
+//reg halt_r;
+
+`ifdef NMI_SYNC_SENSE
+reg nmi_r1,nmi_r2;
+`endif
+
+// auto wait
+reg tw1,tw2;
+
+// gate signal base
+reg t3l;
+reg t04l;
+
+`ifdef FZ80C_POWER_ON_RESET
+reg por_n = 0;
+reg por2_n = 0;
+`endif
+
+//////////////////////////////////////////////////////////////
+// FZ80
+//////////////////////////////////////////////////////////////
+wire start;
+wire mreq;
+wire iorq;
+wire rd;
+wire wr;
+wire busack;
+wire waitreq;
+reg intreq;
+reg nmireq;
+wire busreq;
+wire m1;
+//wire [7:0] data_in = m1 ? dinst_r : di;
+wire [7:0] data_in = ~rfsh_n ? dinst_r : di;
+wire [7:0] data_out;
+wire [15:0] adr ,radr;
+wire nmiack;
+//wire halt;
+
+// mreq,iorq inside in rd_wr
+//wire req_mask =
+
+fz80 fz80(
+ .data_in(data_in),
+ .reset_in(reset_s),
+ .clk(~clk),
+ .adr(adr),
+ .intreq(intreq),
+ .nmireq(nmireq),
+ .busreq(busreq),
+ .start(start),
+ .mreq(mreq),
+ .iorq(iorq),
+ .rd(rd),
+ .wr(wr),
+ .data_out(data_out),
+ .busack_out(busack),
+ .intack_out(),
+ .mr(),
+
+ .m1(m1),
+// .halt(halt),
+ .radr(radr),
+ .nmiack_out(nmiack),
+ .waitreq(waitreq)
+);
+
+///////////////////////////////////////////////////////
+// wires
+///////////////////////////////////////////////////////
+
+// state value
+wire t0 = ts[3:0]==0; // t0 : reset cycle
+wire t1 = ts[0]; // t1 : spM1 = t1&t2
+wire t2 = ts[1]; // t2 : spM1 = tw(1,2)
+wire t3 = ts[2]; // M1.t3
+wire t4 = ts[3]; // M1.t4 or MEM/IO.t3
+
+wire t04 = ~t1 & ~t2 & ~t3; // T0 or T4
+
+`ifdef DEBUG_OUTPUT
+// wait input window
+assign wait_window = t2 & ~wait_r;
+`endif
+
+// RFSH assert timming
+`ifdef DISABLE_REFRESH_CYCLE
+wire nxt_rfsh = 1'b0;
+`else
+wire nxt_rfsh = (m1&t2&wait_r)|t3; // T3 and T4
+`endif
+
+///////////////////////////////////////////////////////
+// NMI eddge sense
+///////////////////////////////////////////////////////
+
+`ifndef NMI_SYNC_SENSE
+wire nmi_clr = nmiack | reset_s;
+always @(negedge nmi_n or posedge nmi_clr)
+begin
+ if(nmi_clr) nmireq <= #1 1'b0;
+ else nmireq <= #1 1'b1;
+end
+`endif
+
+///////////////////////////////////////////////////////
+// Timming state controll
+///////////////////////////////////////////////////////
+
+`ifdef FZ80C_POWER_ON_RESET
+always @(negedge clk)
+begin
+ por_n <= #1 por2_n;
+ por2_n <= #1 1'b1;
+end
+// with por
+always @(negedge clk or negedge por_n)
+ if(~por_n) reset_s <= #1 1'b1;
+ else reset_s <= #1 ~reset_n;
+`else
+// without por
+always @(negedge clk) reset_s <= #1 ~reset_n;
+`endif
+
+always @(posedge clk)
+begin
+ if (reset_s)
+ begin
+ dinst_r <= #1 8'h00;
+ ts <= #1 4'b0000; // reset cycle;
+ A <= #1 16'h0000;
+ m1_r <= #1 1'b1;
+`ifndef DISABLE_REFRESH_CYCLE
+ rfsh_r <= #1 1'b1;
+`endif
+ intreq <= #1 1'b0;
+`ifdef NMI_SYNC_SENSE
+ nmireq <= #1 1'b0;
+ nmi_r2 <= #1 1'b0;
+ nmi_r1 <= #1 1'b0;
+`endif
+ tw1 <= #1 1'b0;
+ tw2 <= #1 1'b0;
+ dt_t4 <= #1 1'b1;
+`ifndef DISABLE_BUSREQ_SYNC
+ busreq_r <= #1 1'b1;
+ busack_r <= #1 1'b1;
+ at_r <= #1 1'b1;
+`endif
+
+ iorq_r <= #1 1'b1;
+ rd_r <= #1 1'b1;
+ mreq_r <= #1 1'b1;
+
+// halt_r <= #1 1'b1;
+ end else begin
+ // T1 T2 on , T3 T4 off
+ m1_r <= #1 ~m1 | nxt_rfsh;
+
+`ifndef DISABLE_REFRESH_CYCLE
+ // T3 T4 on , T1 T2 off
+ rfsh_r <= #1 ~nxt_rfsh;
+`endif
+
+ // T1(M1),T2,T4(IO) on , T1(IO),T3,T4(M1) off
+ iorq_r <= #1 ~iorq | t04 | tw1 | nxt_rfsh;
+
+ // T1(MEM),T2,T4(MEM) on,T1(IO),T3,T4(M1) off
+ rd_r <= #1 ~rd | (iorq&t04) | nxt_rfsh;
+
+ // T1,T2,T4(MEM) on T3,T4(M1) off
+ mreq_r <= #1 ~mreq | nxt_rfsh;
+
+ // timming state controll
+ ts[0] <= #1 (t1&tw1) | t04; // t1
+ ts[1] <= #1 (t2& ~wait_r) | (t1&~tw1); // t2
+ ts[2] <= #1 (t2& wait_r& m1); // t3
+ ts[3] <= #1 (t2& wait_r&~m1) | t3; // t4
+
+ // auto wait state
+ tw1 <= #1 ~t1 & (m1&iorq); // TW for SpecialM1
+ tw2 <= #1 t1 & iorq; // TW for IO and SpecialM1
+
+ // address / refresh address
+ A <= #1 nxt_rfsh ? radr : adr;
+
+ // IRQ (T4 raise)
+ intreq <= #1 ~int_n;
+
+ // NMI eddge sense
+`ifdef NMI_SYNC_SENSE
+ nmi_r2 <= #1 nmi_r1;
+ nmi_r1 <= #1 ~nmi_n;
+ if(nmiack) nmireq <= #1 1'b0;
+ else if(~nmi_r2 & nmi_r1) nmireq <= #1 1'b1;
+`endif
+
+ // Opcode Latch = T3 raise
+ if(t2) dinst_r <= #1 di;
+
+ // data outpot tristate , HOLD half clock in T4
+ dt_t4 <= #1 dt_r;
+
+ // busreq / busack & Address tristate
+`ifndef DISABLE_BUSREQ_SYNC
+ busreq_r <= #1 ~busrq_n;
+ busack_r <= #1 ~busack;
+ at_r <= #1 ~busack;
+`endif
+
+ // halt fetch
+// if(m1&t4) halt_r <= #1 ~halt;
+
+ end
+end
+
+// clk fall event
+always @(negedge clk)
+begin
+ if (reset_s)
+ begin
+ t3l <= #1 1'b0;
+ t04l <= #1 1'b1;
+ wait_r <= #1 1'b1;
+ wr_r <= #1 1'b1;
+ dt_r <= #1 1'b1;
+ do_r <= #1 8'h00;
+ end else begin
+ // gate controll
+ t3l <= #1 t3;
+
+ // t4l-t0l | specialM1.t1l
+ t04l <= #1 t04 | (t1&m1&iorq);
+
+ // DataOutput
+ do_r <= #1 data_out;
+
+ // wait sense (T2 raise)
+ wait_r <= #1 (wait_n | (m1&iorq)) & ~tw2;
+
+ // data bus enable , T1,T2 on , T4 off
+ dt_r <= #1 ~wr | t04;
+
+ // T1(IO),T2 on , T1(MEM),T4 off
+ wr_r <= #1 ~wr | t4 | (mreq&t1);
+ end
+end
+
+
+/////////////////////////////////////////////////////////////////////////////
+// fz80 input
+/////////////////////////////////////////////////////////////////////////////
+assign waitreq = ~t4;
+`ifdef DISABLE_BUSREQ_SYNC
+assign busreq = ~busrq_n;
+`else
+assign busreq = busreq_r;
+`endif
+
+/////////////////////////////////////////////////////////////////////////////
+// output signal
+/////////////////////////////////////////////////////////////////////////////
+
+// MREQ glidge mask
+`ifdef MREQ_INSIDE_RD
+reg mreq_dly;
+always @(posedge clk or negedge rd_n)
+begin
+ if(~rd_n) mreq_dly <= #1 1'b0;
+ else if(t04) mreq_dly <= #1 rd;
+end
+
+reg rd_hold_n;
+always @(posedge clk or posedge mreq_n)
+begin
+ if(mreq_n) rd_hold_n <= #1 1'b1;
+ else rd_hold_n <= #1 mreq_n | rd_n;
+end
+
+`else
+wire mreq_dly = 0;
+wire rd_hold_n = 1;
+`endif
+
+assign m1_n = m1_r;
+`ifndef DISABLE_REFRESH_CYCLE
+ assign rfsh_n = rfsh_r;
+`else
+ assign rfsh_n = 1'b1;
+`endif
+assign mreq_n = (mreq_r| t04l | mreq_dly) & (~t3l | rfsh_n);
+assign iorq_n = iorq_r | t04l;
+assign rd_n = (rd_r | t04l) & rd_hold_n;
+assign wr_n = wr_r | t1;
+assign dt = dt_r & dt_t4;
+`ifndef DISABLE_BUSREQ_SYNC
+ assign At = at_r;
+ assign busak_n = busack_r;
+`else
+ assign At = busack | reset_s;
+ assign busak_n = busack;
+`endif
+
+`ifdef DO_VAL_IF_DT
+assign do = dt ? `DO_VAL_IF_DT : do_r;
+`else
+assign do = do_r;
+`endif
+
+//assign halt_n = halt_r;
+assign halt_n = 1'b1;
+
+`endif // FZ80C_USER_NGC_LINK
+
+endmodule
diff --git a/common/CPU/MC6809/cpu09l_128a.vhd b/common/CPU/MC6809/cpu09l_128a.vhd
new file mode 100644
index 00000000..6a07aacb
--- /dev/null
+++ b/common/CPU/MC6809/cpu09l_128a.vhd
@@ -0,0 +1,5978 @@
+--===========================================================================--
+-- --
+-- 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 .
+--
+--===========================================================================--
+-- --
+-- 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.20 - 8th October 2011 - John Kent
+-- added fetch output which should go high during the fetch cycle
+--
+-- Version 1.21 - 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
+--
+-- Version 1.22 - 2011-10-29 John Kent
+-- The halt state isn't correct.
+-- The halt state is entered into from the fetch_state
+-- It returned to the fetch state which may re-run an execute cycle
+-- on the accumulator and it won't necessarily be the last instruction cycle
+-- I've changed the halt state to return to the decode1_state
+--
+-- Version 1.23 - 2011-10-30 John Kent
+-- sample halt in the change_state process if lic is high (last instruction cycle)
+--
+-- Version 1.24 - 2011-11-01 John Kent
+-- Handle interrupts in change_state process
+-- Sample interrupt inputs on last instruction cycle
+-- Remove iv_ctrl and implement iv (interrupt vector) in change_state process.
+-- Generate fic (first instruction cycle) from lic (last instruction cycle)
+-- and use it to complete the dual operand execute cycle before servicing
+-- halt or interrupts requests.
+-- rename lic to lic_out on the entity declaration so that lic can be tested internally.
+-- add int_firq1_state and int_nmirq1_state to allow for the dual operand execute cycle
+-- integrated nmi_ctrl into change_state process
+-- Reduces the microcode state stack to one entry (saved_state)
+-- imm16_state jumps directly to the fetch_state
+-- pull_return_lo states jumps directly to the fetch_state
+-- duplicate andcc_state as cwai_state
+-- rename exg1_state as exg2 state and duplicate tfr_state as exg1_state
+--
+-- Version 1.25 - 2011-11-27 John Kent
+-- Changed the microcode for saving registers on an interrupt into a microcode subroutine.
+-- Removed SWI servicing from the change state process and made SWI, SWI2 & SWI3
+-- call the interrupt microcode subroutine.
+-- Added additional states for nmi, and irq for interrupt servicing.
+-- Added additional states for nmi/irq, firq, and swi interrupts to mask I & F flags.
+--
+-- Version 1.26 - 2013-03-18 John Kent
+-- pre-initialized cond_true variable to true in state sequencer
+-- re-arranged change_state process slightly
+--
+-- Version 1.27 - 2015-05-30 John Kent
+-- Added test in state machine for masked IRQ and FIRQ in Sync_state.
+--
+-- Version 1.28 - 2015-05-30 John Kent.
+-- Moved IRQ and FIRQ test from state machine to the state sequencer Sync_state.
+--
+-- Version 1.28a - Temporary tweaked release - 2018-02-08 DarFPGA
+-- Add wait_cycles process to retrieve original cycle count for some (few) instructions.
+-- Only those used by vectrex exec_rom (and spike rom) during drawing.
+-- Beware that external hold (hold_in) is no more active.
+--
+--
+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)
+ ce : in std_logic;
+ rst : in std_logic; -- reset input (active high)
+ vma : out std_logic; -- valid memory address (active high)
+ lic_out : out std_logic; -- last instruction cycle (active high)
+ ifetch : out std_logic; -- instruction fetch cycle (active high)
+ opfetch : out std_logic; -- opcode fetch (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
+ );
+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, vect_idle_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, cwai_state,
+ --
+ andcc_state, orcc_state,
+ tfr_state,
+ exg_state, exg1_state, exg2_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_nmi_state, int_nmi1_state,
+ int_irq_state, int_irq1_state,
+ int_firq_state, int_firq1_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_nmimask_state, int_firqmask_state, int_swimask_state, int_irqmask_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 st_type is (reset_st, push_st, idle_st );
+ type iv_type is (latch_iv, swi3_iv, swi2_iv, firq_iv, irq_iv, swi_iv, nmi_iv, reset_iv);
+ 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 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 fic: std_logic; -- first instruction cycle
+ signal lic: std_logic; -- last instruction cycle
+
+ signal state: state_type;
+ signal next_state: state_type;
+ signal return_state: state_type;
+ signal saved_state: state_type;
+ signal st_ctrl: st_type;
+ signal iv_ctrl: iv_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 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 cnt_cycles : std_logic_vector(3 downto 0) := "0000" ;
+ signal hold : std_logic;
+
+begin
+
+wait_cycles: process(clk)
+begin
+ if clk'event and clk = '0' then
+ if ce = '1' then
+ if lic = '1' then
+ case op_code is
+ when X"A6" => hold <= '1'; cnt_cycles <= X"1"; -- additional cycles for vectrex tuning
+ when X"97" => hold <= '1'; cnt_cycles <= X"1";
+ when X"8C" => hold <= '1'; cnt_cycles <= X"1";
+ when X"D7" => hold <= '1'; cnt_cycles <= X"1";
+ when X"1F" => hold <= '1'; cnt_cycles <= X"3";
+ when X"B3" => hold <= '1'; cnt_cycles <= X"2";
+ when X"0A" => hold <= '1'; cnt_cycles <= X"2";
+ when X"0C" => hold <= '1'; cnt_cycles <= X"2";
+ when X"1E" => hold <= '1'; cnt_cycles <= X"3"; -- exg @117A/7C spike (allow time enough for timer to end before pc=11A4)
+ when others=> null;
+ end case;
+ end if;
+
+ if hold = '1' then
+ if cnt_cycles = X"1" then
+ hold <= '0';
+ end if;
+ cnt_cycles <= cnt_cycles - '1';
+ end if;
+ end if;
+ end if;
+end process;
+
+----------------------------------
+--
+-- State machine stack
+--
+----------------------------------
+--state_stack_proc: process( clk, hold, state_stack, st_ctrl,
+-- return_state, fetch_state )
+state_stack_proc: process( clk, st_ctrl, return_state )
+begin
+ if clk'event and clk = '0' then
+ if ce = '1' then
+ if hold = '0' then
+ case st_ctrl is
+ when reset_st =>
+ saved_state <= fetch_state;
+ when push_st =>
+ saved_state <= return_state;
+ when others =>
+ null;
+ end case;
+ end if;
+ end if;
+ end if;
+end process;
+
+----------------------------------
+--
+-- Interrupt Vector control
+--
+----------------------------------
+--
+int_vec_proc: process( clk, iv_ctrl )
+begin
+ if clk'event and clk = '0' then
+ if ce = '1' then
+ if hold = '0' then
+ 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 others =>
+ null;
+ end case;
+ end if; -- hold
+ end if;
+ end if; -- clk
+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 ce = '1' then
+ if hold = '0' then
+ case pc_ctrl is
+ when reset_pc =>
+ pc <= (others=>'0');
+ 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 =>
+ null;
+ end case;
+ end if;
+ 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 ce = '1' then
+ if hold= '0' then
+ case ea_ctrl is
+ when reset_ea =>
+ ea <= (others=>'0');
+ 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 =>
+ null;
+ end case;
+ end if;
+ 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 ce = '1' then
+ if hold = '0' then
+ case acca_ctrl is
+ when reset_acca =>
+ acca <= (others=>'0');
+ 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 =>
+ null;
+ end case;
+ end if;
+ 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 ce = '1' then
+ if hold = '0' then
+ case accb_ctrl is
+ when reset_accb =>
+ accb <= (others=>'0');
+ when load_accb =>
+ accb <= out_alu(7 downto 0);
+ when pull_accb =>
+ accb <= data_in;
+ when others =>
+ null;
+ end case;
+ end if;
+ 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 ce = '1' then
+ if hold = '0' then
+ case ix_ctrl is
+ when reset_ix =>
+ xreg <= (others=>'0');
+ 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 =>
+ null;
+ end case;
+ end if;
+ 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 ce = '1' then
+ if hold = '0' then
+ case iy_ctrl is
+ when reset_iy =>
+ yreg <= (others=>'0');
+ 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 =>
+ null;
+ end case;
+ end if;
+ 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 ce = '1' then
+ if hold = '0' then
+ case sp_ctrl is
+ when reset_sp =>
+ sp <= (others=>'0');
+ 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;
+ when pull_lo_sp =>
+ sp(7 downto 0) <= data_in;
+ nmi_enable <= '1';
+ when others =>
+ null;
+ end case;
+ end if;
+ 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 ce = '1' then
+ if hold = '0' then
+ case up_ctrl is
+ when reset_up =>
+ up <= (others=>'0');
+ 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 =>
+ null;
+ end case;
+ end if;
+ 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 ce = '1' then
+ if hold = '0' then
+ case md_ctrl is
+ when reset_md =>
+ md <= (others=>'0');
+ 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 =>
+ null;
+ end case;
+ end if;
+ 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 ce = '1' then
+ if hold = '0' then
+ 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 =>
+ null;
+ end case;
+ end if;
+ 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 ce = '1' then
+ if hold = '0' then
+ case dp_ctrl is
+ when reset_dp =>
+ dp <= (others=>'0');
+ when load_dp =>
+ dp <= out_alu(7 downto 0);
+ when pull_dp =>
+ dp <= data_in;
+ when others =>
+ null;
+ end case;
+ end if;
+ 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 ce = '1' then
+ if hold = '0' then
+ case op_ctrl is
+ when reset_op =>
+ op_code <= "00010010";
+ when fetch_op =>
+ op_code <= data_in;
+ when others =>
+ null;
+ end case;
+ end if;
+ 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 ce = '1' then
+ if hold = '0' then
+ case pre_ctrl is
+ when reset_pre =>
+ pre_code <= (others=>'0');
+ when fetch_pre =>
+ pre_code <= data_in;
+ when others =>
+ null;
+ end case;
+ end if;
+ 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
+ fic <= '0';
+ nmi_ack <= '0';
+ state <= reset_state;
+ elsif ce = '1' and hold = '0' then
+
+ fic <= lic;
+ --
+ -- nmi request is not cleared until nmi input goes low
+ --
+ if (nmi_req = '0') and (nmi_ack='1') then
+ nmi_ack <= '0';
+ end if;
+
+ if (nmi_req = '1') and (nmi_ack = '0') and (state = int_nmimask_state) then
+ nmi_ack <= '1';
+ end if;
+
+ if lic = '1' then
+ if halt = '1' then
+ state <= halt_state;
+
+ -- service non maskable interrupts
+ elsif (nmi_req = '1') and (nmi_ack = '0') then
+ state <= int_nmi_state;
+ --
+ -- FIRQ & IRQ are level sensitive
+ --
+ elsif (firq = '1') and (cc(FBIT) = '0') then
+ state <= int_firq_state;
+
+ elsif (irq = '1') and (cc(IBIT) = '0') then
+ state <= int_irq_state;
+ --
+ -- Version 1.27 2015-05-30
+ -- Exit sync_state on masked interrupt.
+ --
+ -- Version 1.28 2015-05-30
+ -- Move this code to the state sequencer
+ -- near line 5566.
+ --
+ -- elsif (state = sync_state) and ((firq = '1') or (irq = '1'))then
+ -- state <= fetch_state;
+ --
+ else
+ state <= next_state;
+ end if; -- halt, nmi, firq, irq
+ else
+ state <= next_state;
+ end if; -- lic
+ end if; -- reset/hold
+ end if; -- clk
+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 ce = '1' 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 if;
+end process;
+
+
+----------------------------------
+--
+-- Address output multiplexer
+--
+----------------------------------
+
+addr_mux: process( addr_ctrl, pc, ea, up, sp, iv )
+begin
+ ifetch <= '0';
+ vma <= '1';
+ case addr_ctrl is
+ when fetch_ad =>
+ addr <= pc;
+ rw <= '1';
+ ifetch <= '1';
+ when read_ad =>
+ addr <= ea;
+ rw <= '1';
+ when write_ad =>
+ addr <= ea;
+ rw <= '0';
+ when pushs_ad =>
+ addr <= sp;
+ rw <= '0';
+ when pulls_ad =>
+ addr <= sp;
+ rw <= '1';
+ when pushu_ad =>
+ addr <= up;
+ rw <= '0';
+ when pullu_ad =>
+ addr <= up;
+ rw <= '1';
+ when int_hi_ad =>
+ addr <= "111111111111" & iv & "0";
+ rw <= '1';
+ when int_lo_ad =>
+ addr <= "111111111111" & iv & "1";
+ rw <= '1';
+ when others =>
+ addr <= "1111111111111111";
+ rw <= '1';
+ 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);
+ 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;
+
+ --
+ -- CBIT HBIT VHI VLO DAA
+ -- 0 0 0 0 66 (!VHI : hi_nybble>8)
+ -- 0 0 0 1 60
+ -- 0 0 1 1 00
+ -- 0 0 1 0 06 ( VHI : hi_nybble<=8)
+ --
+ -- 0 1 1 0 06
+ -- 0 1 1 1 06
+ -- 0 1 0 1 66
+ -- 0 1 0 0 66
+ --
+ -- 1 1 0 0 66
+ -- 1 1 0 1 66
+ -- 1 1 1 1 66
+ -- 1 1 1 0 66
+ --
+ -- 1 0 1 0 66
+ -- 1 0 1 1 60
+ -- 1 0 0 1 60
+ -- 1 0 0 0 66
+ --
+ -- 66 = (!VHI & !VLO) + (CBIT & HBIT) + (HBIT & !VHI) + (CBIT & !VLO)
+ -- = (CBIT & (HBIT + !VLO)) + (!VHI & (HBIT + !VLO))
+ -- = (!VLO & (CBIT + !VHI)) + (HBIT & (CBIT + !VHI))
+ -- 60 = (CBIT & !HBIT & VLO) + (!HBIT & !VHI & VLO)
+ -- = (!HBIT & VLO & (CBIT + !VHI))
+ -- 06 = (!CBIT & VHI & (!VLO + VHI)
+ -- 00 = (!CBIT & !HBIT & VHI & VLO)
+ --
+ if (cc(CBIT) = '0') then
+ -- CBIT=0
+ if( cc(HBIT) = '0' ) then
+ -- HBIT=0
+ if valid_lo then
+ -- lo <= 9 (no overflow in low nybble)
+ if valid_hi then
+ -- hi <= 9 (no overflow in either low or high nybble)
+ daa_reg := "00000000";
+ else
+ -- hi > 9 (overflow in high nybble only)
+ daa_reg := "01100000";
+ end if;
+ else
+ -- lo > 9 (overflow in low nybble)
+ --
+ -- since there is already an overflow in the low nybble
+ -- you need to make room in the high nybble for the low nybble carry
+ -- so compare the high nybble with 8 rather than 9
+ -- if the high nybble is 9 there will be an overflow on the high nybble
+ -- after the decimal adjust which means it will roll over to an invalid BCD digit
+ --
+ if( left(7 downto 4) <= 8 ) then
+ -- hi <= 8 (overflow in low nybble only)
+ daa_reg := "00000110";
+ else
+ -- hi > 8 (overflow in low and high nybble)
+ daa_reg := "01100110";
+ end if;
+ end if;
+ else
+ -- HBIT=1 (overflow in low nybble)
+ if valid_hi then
+ -- hi <= 9 (overflow in low nybble only)
+ daa_reg := "00000110";
+ else
+ -- hi > 9 (overflow in low and high nybble)
+ daa_reg := "01100110";
+ end if;
+ end if;
+ else
+ -- CBIT=1 (carry => overflow in high nybble)
+ if ( cc(HBIT) = '0' )then
+ -- HBIT=0 (half carry clear => may or may not be an overflow in the low nybble)
+ if valid_lo then
+ -- lo <=9 (overflow in high nybble only)
+ daa_reg := "01100000";
+ else
+ -- lo >9 (overflow in low and high nybble)
+ daa_reg := "01100110";
+ end if;
+ else
+ -- HBIT=1 (overflow in low and high nybble)
+ daa_reg := "01100110";
+ 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, fic, halt,
+ nmi_req, firq, irq, lic )
+variable cond_true : boolean; -- variable used to evaluate coditional branches
+begin
+ cond_true := (1=1);
+ ba <= '0';
+ bs <= '0';
+ lic <= '0';
+ opfetch <= '0';
+ iv_ctrl <= latch_iv;
+ -- 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;
+ op_ctrl <= latch_op;
+ pre_ctrl <= latch_pre;
+ -- 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
+ iv_ctrl <= reset_iv;
+ 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;
+ st_ctrl <= reset_st;
+ 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;
+
+ when vect_idle_state =>
+ --
+ -- Last Instruction Cycle for SWI, SWI2 & SWI3
+ --
+ if op_code = "00111111" then
+ lic <= '1';
+ end if;
+ next_state <= fetch_state;
+
+ --
+ -- Here to fetch an instruction
+ -- PC points to opcode
+ --
+ when fetch_state =>
+ -- fetch the op code
+ opfetch <= '1';
+ op_ctrl <= fetch_op;
+ pre_ctrl <= fetch_pre;
+ ea_ctrl <= reset_ea;
+ -- Fetch op code
+ addr_ctrl <= fetch_ad;
+ -- Advance the PC to fetch next instruction byte
+ pc_ctrl <= incr_pc;
+ next_state <= decode1_state;
+
+ --
+ -- 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
+ opfetch <= '1';
+ 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
+ opfetch <= '1';
+ 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;
+
+ --
+ -- Decimal Adjust Accumulator
+ --
+ 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;
+
+ --
+ -- OR Condition Codes
+ --
+ when "1010" => -- orcc
+ -- increment the pc
+ pc_ctrl <= incr_pc;
+ next_state <= orcc_state;
+
+ --
+ -- AND Condition Codes
+ --
+ when "1100" => -- andcc
+ -- increment the pc
+ pc_ctrl <= incr_pc;
+ next_state <= andcc_state;
+
+ --
+ -- Sign Extend
+ --
+ when "1101" => -- 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;
+
+ --
+ -- Exchange Registers
+ --
+ when "1110" => -- exg
+ -- increment the pc
+ pc_ctrl <= incr_pc;
+ next_state <= exg_state;
+
+ --
+ -- Transfer Registers
+ --
+ when "1111" => -- tfr
+ -- increment the pc
+ pc_ctrl <= incr_pc;
+ 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" =>
+ 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
+ lic <= '1';
+ left_ctrl <= ix_left;
+ right_ctrl <= accb_right;
+ alu_ctrl <= alu_abx;
+ ix_ctrl <= load_ix;
+ next_state <= fetch_state;
+
+ --
+ -- Return From Interrupt
+ --
+ when "1011" => -- rti
+ next_state <= rti_cc_state;
+
+ --
+ -- CWAI
+ --
+ when "1100" => -- cwai #$
+ -- pre decrement sp
+ left_ctrl <= sp_left;
+ right_ctrl <= one_right;
+ alu_ctrl <= alu_sub16;
+ sp_ctrl <= load_sp;
+ -- increment pc
+ pc_ctrl <= incr_pc;
+ next_state <= cwai_state;
+
+ --
+ -- MUL Multiply
+ --
+ when "1101" => -- mul
+ next_state <= mul_state;
+
+ --
+ -- SWI Software Interrupt
+ --
+ 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;
+ st_ctrl <= push_st;
+ return_state <= int_swimask_state;
+ 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 #
+ 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;
+
+ --
+ -- 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 "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;
+
+ 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 "1101" => -- jsr ,x
+ -- DO NOT pre decrement SP
+ st_ctrl <= push_st;
+ return_state <= jsr_state;
+ next_state <= indexed_state;
+
+ when "1111" => -- stx ,x
+ 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 "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 "1101" => -- jsr >extended
+ -- DO NOT pre decrement sp
+ st_ctrl <= push_st;
+ return_state <= jsr_state;
+ next_state <= extended_state;
+
+ when "1111" => -- stx >
+ 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 "1100" => -- accb immediate
+ -- increment the pc
+ pc_ctrl <= incr_pc;
+ case op_code(3 downto 0) is
+ when "0011" | -- addd #
+ "1100" | -- ldd #
+ "1110" => -- ldu #
+ 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;
+ --
+ -- not sure why I need this
+ --
+ when others =>
+ lic <= '1';
+ next_state <= fetch_state;
+ 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;
+ st_ctrl <= push_st;
+ return_state <= vect_hi_state;
+ 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 #
+ 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 #
+ 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;
+ st_ctrl <= push_st;
+ return_state <= vect_hi_state;
+ 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 #
+ 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 <
+ 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;
+ lic <= '1';
+ next_state <= fetch_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;
+ 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;
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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;
+ 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;
+ next_state <= saved_state;
+
+ --
+ -- RTS pull return address from stack
+ --
+ 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;
+ --
+ lic <= '1';
+ next_state <= fetch_state;
+
+ when andcc_state =>
+ -- AND CC with md
+ left_ctrl <= md_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_andcc;
+ cc_ctrl <= load_cc;
+ --
+ lic <= '1';
+ next_state <= fetch_state;
+
+ when orcc_state =>
+ -- OR CC with md
+ left_ctrl <= md_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_orcc;
+ cc_ctrl <= load_cc;
+ --
+ lic <= '1';
+ next_state <= fetch_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;
+ --
+ lic <= '1';
+ next_state <= fetch_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
+ next_state <= exg1_state;
+
+ when exg1_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;
+ next_state <= exg2_state;
+
+ when exg2_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 NMI interrupt
+ -- Complete execute cycle of the last instruction.
+ -- If it was a dual operand instruction
+ --
+ when int_nmi_state =>
+ next_state <= int_nmi1_state;
+
+ -- Idle bus cycle
+ when int_nmi1_state =>
+ -- pre decrement sp
+ left_ctrl <= sp_left;
+ right_ctrl <= one_right;
+ alu_ctrl <= alu_sub16;
+ sp_ctrl <= load_sp;
+ iv_ctrl <= nmi_iv;
+ st_ctrl <= push_st;
+ return_state <= int_nmimask_state;
+ next_state <= int_entire_state;
+
+ --
+ -- here on IRQ interrupt
+ -- Complete execute cycle of the last instruction.
+ -- If it was a dual operand instruction
+ --
+ when int_irq_state =>
+ next_state <= int_irq1_state;
+
+ -- pre decrement the sp
+ -- Idle bus cycle
+ when int_irq1_state =>
+ -- pre decrement sp
+ left_ctrl <= sp_left;
+ right_ctrl <= one_right;
+ alu_ctrl <= alu_sub16;
+ sp_ctrl <= load_sp;
+ iv_ctrl <= irq_iv;
+ st_ctrl <= push_st;
+ return_state <= int_irqmask_state;
+ next_state <= int_entire_state;
+
+ --
+ -- here on FIRQ interrupt
+ -- Complete execution cycle of the last instruction
+ -- if it was a dual operand instruction
+ --
+ when int_firq_state =>
+ next_state <= int_firq1_state;
+
+ -- Idle bus cycle
+ when int_firq1_state =>
+ -- pre decrement sp
+ left_ctrl <= sp_left;
+ right_ctrl <= one_right;
+ alu_ctrl <= alu_sub16;
+ sp_ctrl <= load_sp;
+ iv_ctrl <= firq_iv;
+ st_ctrl <= push_st;
+ return_state <= int_firqmask_state;
+ next_state <= int_fast_state;
+
+ --
+ -- CWAI entry point
+ -- stack pointer already pre-decremented
+ -- mask condition codes
+ --
+ when cwai_state =>
+ -- AND CC with md
+ left_ctrl <= md_left;
+ right_ctrl <= zero_right;
+ alu_ctrl <= alu_andcc;
+ cc_ctrl <= load_cc;
+ st_ctrl <= push_st;
+ return_state <= int_cwai_state;
+ next_state <= int_entire_state;
+
+ --
+ -- wait here for an interrupt
+ --
+ when int_cwai_state =>
+ if (nmi_req = '1') then
+ iv_ctrl <= nmi_iv;
+ next_state <= int_nmimask_state;
+ --
+ -- FIRQ & IRQ are level sensitive
+ --
+ elsif (firq = '1') and (cc(FBIT) = '0') then
+ iv_ctrl <= firq_iv;
+ next_state <= int_firqmask_state;
+
+ elsif (irq = '1') and (cc(IBIT) = '0') then
+ iv_ctrl <= irq_iv;
+ next_state <= int_irqmask_state;
+ else
+ next_state <= int_cwai_state;
+ end if;
+
+ --
+ -- State to mask I Flag and F Flag (NMI)
+ --
+ when int_nmimask_state =>
+ alu_ctrl <= alu_seif;
+ cc_ctrl <= load_cc;
+ next_state <= vect_hi_state;
+
+ --
+ -- State to mask I Flag and F Flag (FIRQ)
+ --
+ when int_firqmask_state =>
+ alu_ctrl <= alu_seif;
+ cc_ctrl <= load_cc;
+ next_state <= vect_hi_state;
+
+
+ --
+ -- State to mask I Flag and F Flag (SWI)
+ --
+ when int_swimask_state =>
+ alu_ctrl <= alu_seif;
+ cc_ctrl <= load_cc;
+ next_state <= vect_hi_state;
+
+ --
+ -- State to mask I Flag only (IRQ)
+ --
+ when int_irqmask_state =>
+ alu_ctrl <= alu_sei;
+ cc_ctrl <= load_cc;
+ next_state <= vect_hi_state;
+
+ --
+ -- set Entire Flag on SWI, SWI2, SWI3 and CWAI, IRQ and NMI
+ -- before stacking all registers
+ --
+ when int_entire_state =>
+ -- set entire flag
+ alu_ctrl <= alu_see;
+ cc_ctrl <= load_cc;
+ next_state <= int_pcl_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;
+ next_state <= saved_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 =>
+ lic <= '1';
+ ba <= '1';
+ --
+ -- Version 1.28 2015-05-30
+ -- Exit sync_state on interrupt.
+ -- If the interrupts are active
+ -- they will be caught in the state_machine process
+ -- and the interrupt service routine microcode will be executed.
+ -- Masked interrupts will exit the sync_state.
+ -- Moved from the state_machine process to the state_sequencer process
+ --
+ if (firq = '1') or (irq = '1') then
+ next_state <= fetch_state;
+ else
+ next_state <= sync_state;
+ end if;
+
+ when halt_state =>
+ --
+ -- 2011-10-30 John Kent
+ -- ba & bs should be high
+ ba <= '1';
+ bs <= '1';
+ if halt = '1' then
+ next_state <= halt_state;
+ else
+ next_state <= fetch_state;
+ end if;
+
+ end case;
+
+--
+-- Ver 1.23 2011-10-30 John Kent
+-- First instruction cycle might be
+-- fetch_state
+-- halt_state
+-- int_nmirq_state
+-- int_firq_state
+--
+ if fic = '1' then
+ --
+ 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;
+
+ end if; -- first instruction cycle (fic)
+ lic_out <= lic;
+end process;
+
+end rtl;
+
diff --git a/common/CPU/MC6809/mc6809.v b/common/CPU/MC6809/mc6809.v
new file mode 100644
index 00000000..338e9557
--- /dev/null
+++ b/common/CPU/MC6809/mc6809.v
@@ -0,0 +1,89 @@
+`timescale 1ns / 1ps
+module mc6809
+(
+ input CLK,
+ input CLKEN,
+ input nRESET,
+
+ input CPU,
+
+ output reg E,
+ output reg riseE,
+ output reg fallE, // everything except interrupts/dma registered/latched here
+
+ output reg Q,
+ output reg riseQ,
+ output reg fallQ, // NMI,IRQ,FIRQ,DMA,HALT registered here
+
+ input [7:0] Din,
+ output [7:0] Dout,
+ output [15:0] ADDR,
+ output RnW,
+
+ input nIRQ,
+ input nFIRQ,
+ input nNMI,
+ input nHALT
+);
+
+cpu09 cpu1
+(
+ .clk(CLK),
+ .ce(fallE),
+ .rst(~nRESET | CPU),
+ .addr(ADDR1),
+ .rw(RnW1),
+ .data_out(Dout1),
+ .data_in(Din),
+ .irq(~nIRQ),
+ .firq(~nFIRQ),
+ .nmi(~nNMI),
+ .halt(~nHALT)
+);
+
+mc6809is cpu2
+(
+ .CLK(CLK),
+ .D(Din),
+ .DOut(Dout2),
+ .ADDR(ADDR2),
+ .RnW(RnW2),
+ .fallE_en(fallE),
+ .fallQ_en(fallQ),
+ .nIRQ(nIRQ),
+ .nFIRQ(nFIRQ),
+ .nNMI(nNMI),
+ .nHALT(nHALT),
+ .nRESET(nRESET & CPU),
+ .nDMABREQ(1)
+);
+
+wire [7:0] Dout1,Dout2;
+wire [15:0] ADDR1,ADDR2;
+wire RnW1,RnW2;
+
+assign Dout = CPU ? Dout2 : Dout1;
+assign ADDR = CPU ? ADDR2 : ADDR1;
+assign RnW = CPU ? RnW2 : RnW1;
+
+always @(posedge CLK)
+begin
+ reg [1:0] clk_phase =0;
+
+ fallE <= 0;
+ fallQ <= 0;
+ riseE <= 0;
+ riseQ <= 0;
+
+ if (CLKEN) begin
+ clk_phase <= clk_phase + 1'd1;
+ case (clk_phase)
+ 2'b00: begin E <= 0; fallE <= 1; end
+ 2'b01: begin Q <= 1; riseQ <= 1; end
+ 2'b10: begin E <= 1; riseE <= 1; end
+ 2'b11: begin Q <= 0; fallQ <= 1; end
+ endcase
+ end
+end
+
+endmodule
diff --git a/common/CPU/MC6809/mc6809is.v b/common/CPU/MC6809/mc6809is.v
new file mode 100644
index 00000000..ebdc88be
--- /dev/null
+++ b/common/CPU/MC6809/mc6809is.v
@@ -0,0 +1,4154 @@
+`timescale 1ns / 1ns
+//////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer: Greg Miller
+// Copyright (c) 2016, Greg Miller
+//
+// Create Date: 14:26:59 08/13/2016
+// Design Name:
+// Module Name: mc6809
+// Project Name: Cycle-Accurate 6809 Core
+// Target Devices:
+// Tool versions:
+// Description:
+//
+// Dependencies: Intended to be standalone Vanilla Verilog.
+//
+// Revision:
+// Revision 1.0 - Initial Release
+// Revision 1.0s - Sinchronous version (by Sorgelig)
+// Additional Comments:
+//
+//////////////////////////////////////////////////////////////////////////////////
+
+
+//
+// The 6809 has incomplete instruction decoding. A collection of instructions, if met, end up actually behaving like
+// a binary-adjacent neighbor.
+//
+// The soft core permits three different behaviors for this situation, controlled by the instantiation parameter
+// ILLEGAL_INSTRUCTIONS
+//
+// "GHOST" - Mimic the 6809's incomplete decoding. This is as similar to a hard 6809 as is practical. [DEFAULT]
+//
+// "STOP" - Cause the soft core to cease execution, placing $DEAD on the address bus and R/W to 'read'. Interrupts,
+// bus control (/HALT, /DMABREQ), etc. are ignored. The core intentionally seizes in this instance.
+// (Frankly, this is useful when making changes to the core and you have a logic analyzer connected.)
+//
+// "IGNORE"- Cause the soft core to merely ignore illegal instructions. It will consider them 1-byte instructions and
+// attempt to fetch and run an exception 1 byte later.
+//
+
+module mc6809is
+#(
+ parameter ILLEGAL_INSTRUCTIONS="GHOST"
+)
+(
+ input CLK,
+ input fallE_en,
+ input fallQ_en,
+
+ input [7:0] D,
+ output [7:0] DOut,
+ output [15:0] ADDR,
+ output RnW,
+ output BS,
+ output BA,
+ input nIRQ,
+ input nFIRQ,
+ input nNMI,
+ output AVMA,
+ output BUSY,
+ output LIC,
+ input nHALT,
+ input nRESET,
+ input nDMABREQ,
+ output [111:0] RegData
+);
+
+reg [7:0] DOutput;
+
+assign DOut = DOutput;
+
+reg RnWOut; // Combinatorial
+
+reg rLIC;
+assign LIC = rLIC;
+
+reg rAVMA;
+assign AVMA = rAVMA;
+
+reg rBUSY;
+assign BUSY = rBUSY;
+
+// Bus control
+// BS BA
+// 0 0 normal (CPU running, CPU is master)
+// 0 1 Interrupt Ack
+// 1 0 Sync Ack
+// 1 1 CPU has gone high-Z on A, D, R/W
+//
+
+assign RnW = RnWOut;
+
+
+/////////////////////////////////////////////////
+// Vectors
+`define RESET_VECTOR 16'HFFFE
+`define NMI_VECTOR 16'HFFFC
+`define SWI_VECTOR 16'HFFFA
+`define IRQ_VECTOR 16'HFFF8
+`define FIRQ_VECTOR 16'HFFF6
+`define SWI2_VECTOR 16'HFFF4
+`define SWI3_VECTOR 16'HFFF2
+`define Reserved_VECTOR 16'HFFF0
+
+//////////////////////////////////////////////////////
+// Latched registers
+//
+
+// The last-latched copy.
+reg [7:0] a;
+reg [7:0] b;
+reg [15:0] x;
+reg [15:0] y;
+reg [15:0] u;
+reg [15:0] s;
+reg [15:0] pc;
+reg [7:0] dp;
+reg [7:0] cc;
+reg [15:0] tmp;
+reg [15:0] addr;
+reg [15:0] ea;
+
+
+// Debug ability to export register contents
+assign RegData[7:0] = a;
+assign RegData[15:8] = b;
+assign RegData[31:16] = x;
+assign RegData[47:32] = y;
+assign RegData[63:48] = s;
+assign RegData[79:64] = u;
+assign RegData[87:80] = cc;
+assign RegData[95:88] = dp;
+assign RegData[111:96] = pc;
+
+
+
+// The values as being calculated
+reg [7:0] a_nxt;
+reg [7:0] b_nxt;
+reg [15:0] x_nxt;
+reg [15:0] y_nxt;
+reg [15:0] u_nxt;
+reg [15:0] s_nxt;
+reg [15:0] pc_nxt;
+reg [7:0] dp_nxt;
+reg [7:0] cc_nxt;
+reg [15:0] addr_nxt;
+reg [15:0] ea_nxt;
+reg [15:0] tmp_nxt;
+
+reg BS_nxt;
+reg BA_nxt;
+
+// for ADDR, BS/BA, assign them to the flops
+assign BS = BS_nxt;
+assign BA = BA_nxt;
+assign ADDR=addr_nxt;
+
+localparam CC_E= 8'H80;
+localparam CC_F= 8'H40;
+localparam CC_H= 8'H20;
+localparam CC_I= 8'H10;
+localparam CC_N= 8'H08;
+localparam CC_Z= 8'H04;
+localparam CC_V= 8'H02;
+localparam CC_C= 8'H01;
+
+localparam CC_E_BIT= 3'd7;
+localparam CC_F_BIT= 3'd6;
+localparam CC_H_BIT= 3'd5;
+localparam CC_I_BIT= 3'd4;
+localparam CC_N_BIT= 3'd3;
+localparam CC_Z_BIT= 3'd2;
+localparam CC_V_BIT= 3'd1;
+localparam CC_C_BIT= 3'd0;
+
+// Convenience calculations
+reg [15:0] pc_p1;
+reg [15:0] pc_p2;
+reg [15:0] pc_p3;
+reg [15:0] s_p1;
+reg [15:0] s_m1;
+reg [15:0] u_p1;
+reg [15:0] u_m1;
+reg [15:0] addr_p1;
+reg [15:0] ea_p1;
+
+//////////////////////////////////////////////////////
+// NMI Mask
+//
+// NMI is supposed to be masked - despite the name - until the 6809 loads a value into S.
+// Frankly, I'm cheating slightly. If someone does a LDS #$0, it won't disable the mask. Pretty much anything else
+// that changes the value of S from the default (which is currently $0) will clear the mask. A reset will set the mask again.
+reg NMIMask;
+
+reg NMILatched;
+reg NMISample;
+reg NMISample2;
+reg NMIClear;
+reg NMIClear_nxt;
+wire wNMIClear = NMIClear;
+
+reg IRQLatched;
+
+reg IRQSample;
+reg IRQSample2;
+reg FIRQLatched;
+reg FIRQSample;
+reg FIRQSample2;
+reg HALTLatched;
+reg HALTSample;
+reg HALTSample2;
+reg DMABREQLatched;
+reg DMABREQSample;
+reg DMABREQSample2;
+
+// Interrupt types
+localparam INTTYPE_NMI = 3'H0 ;
+localparam INTTYPE_IRQ = 3'H1 ;
+localparam INTTYPE_FIRQ = 3'H2 ;
+localparam INTTYPE_SWI = 3'H3 ;
+localparam INTTYPE_SWI2 = 3'H4 ;
+localparam INTTYPE_SWI3 = 3'H5 ;
+
+reg [2:0] IntType;
+reg [2:0] IntType_nxt;
+
+//////////////////////////////////////////////////////
+// Instruction Fetch Details
+//
+reg InstPage2;
+reg InstPage3;
+reg InstPage2_nxt;
+reg InstPage3_nxt;
+
+reg [7:0] Inst1;
+reg [7:0] Inst2;
+reg [7:0] Inst3;
+reg [7:0] Inst1_nxt;
+reg [7:0] Inst2_nxt;
+reg [7:0] Inst3_nxt;
+
+
+localparam CPUSTATE_RESET = 7'd0;
+localparam CPUSTATE_RESET0 = 7'd1;
+
+localparam CPUSTATE_RESET2 = 7'd3;
+localparam CPUSTATE_FETCH_I1 = 7'd4;
+localparam CPUSTATE_FETCH_I1V2 = 7'd5;
+localparam CPUSTATE_FETCH_I2 = 7'd8;
+
+localparam CPUSTATE_LBRA_OFFSETLOW = 7'd17;
+localparam CPUSTATE_LBRA_DONTCARE = 7'd18;
+localparam CPUSTATE_LBRA_DONTCARE2 = 7'd19;
+
+
+
+localparam CPUSTATE_BRA_DONTCARE = 7'd20;
+
+localparam CPUSTATE_BSR_DONTCARE1 = 7'd21;
+localparam CPUSTATE_BSR_DONTCARE2 = 7'd22;
+localparam CPUSTATE_BSR_RETURNLOW = 7'd23;
+localparam CPUSTATE_BSR_RETURNHIGH = 7'd24;
+
+localparam CPUSTATE_TFR_DONTCARE1 = 7'd26;
+localparam CPUSTATE_TFR_DONTCARE2 = 7'd27;
+localparam CPUSTATE_TFR_DONTCARE3 = 7'd28;
+localparam CPUSTATE_TFR_DONTCARE4 = 7'd29;
+
+localparam CPUSTATE_EXG_DONTCARE1 = 7'd30;
+localparam CPUSTATE_EXG_DONTCARE2 = 7'd31;
+localparam CPUSTATE_EXG_DONTCARE3 = 7'd32;
+localparam CPUSTATE_EXG_DONTCARE4 = 7'd33;
+localparam CPUSTATE_EXG_DONTCARE5 = 7'd34;
+localparam CPUSTATE_EXG_DONTCARE6 = 7'd35;
+
+localparam CPUSTATE_ABX_DONTCARE = 7'd36;
+
+localparam CPUSTATE_RTS_HI = 7'd38;
+localparam CPUSTATE_RTS_LO = 7'd39;
+localparam CPUSTATE_RTS_DONTCARE2 = 7'd40;
+
+localparam CPUSTATE_16IMM_LO = 7'd41;
+localparam CPUSTATE_ALU16_DONTCARE = 7'd42;
+localparam CPUSTATE_DIRECT_DONTCARE = 7'd43;
+
+localparam CPUSTATE_ALU_EA = 7'd44;
+
+localparam CPUSTATE_ALU_DONTCARE = 7'd46;
+localparam CPUSTATE_ALU_WRITEBACK = 7'd47;
+
+localparam CPUSTATE_LD16_LO = 7'd48;
+
+localparam CPUSTATE_ST16_LO = 7'd49;
+localparam CPUSTATE_ALU16_LO = 7'd50;
+
+
+
+
+localparam CPUSTATE_JSR_DONTCARE = 7'd53;
+localparam CPUSTATE_JSR_RETLO = 7'd54;
+localparam CPUSTATE_JSR_RETHI = 7'd55;
+localparam CPUSTATE_EXTENDED_ADDRLO = 7'd56;
+localparam CPUSTATE_EXTENDED_DONTCARE = 7'd57;
+localparam CPUSTATE_INDEXED_BASE = 7'd58;
+
+
+localparam CPUSTATE_IDX_DONTCARE3 = 7'd60;
+
+localparam CPUSTATE_IDX_OFFSET_LO = 7'd61;
+localparam CPUSTATE_IDX_16OFFSET_LO = 7'd62;
+
+localparam CPUSTATE_IDX_16OFF_DONTCARE0= 7'd63;
+localparam CPUSTATE_IDX_16OFF_DONTCARE1= 7'd64;
+localparam CPUSTATE_IDX_16OFF_DONTCARE2= 7'd65;
+localparam CPUSTATE_IDX_16OFF_DONTCARE3= 7'd66;
+
+localparam CPUSTATE_IDX_DOFF_DONTCARE1 = 7'd68;
+localparam CPUSTATE_IDX_DOFF_DONTCARE2 = 7'd69;
+localparam CPUSTATE_IDX_DOFF_DONTCARE3 = 7'd70;
+localparam CPUSTATE_IDX_PC16OFF_DONTCARE = 7'd71;
+
+localparam CPUSTATE_IDX_EXTIND_LO = 7'd72;
+localparam CPUSTATE_IDX_EXTIND_DONTCARE = 7'd73;
+
+localparam CPUSTATE_INDIRECT_HI = 7'd74;
+localparam CPUSTATE_INDIRECT_LO = 7'd75;
+localparam CPUSTATE_INDIRECT_DONTCARE = 7'd76;
+localparam CPUSTATE_MUL_ACTION = 7'd77;
+
+localparam CPUSTATE_PSH_DONTCARE1 = 7'd80;
+localparam CPUSTATE_PSH_DONTCARE2 = 7'd81;
+localparam CPUSTATE_PSH_DONTCARE3 = 7'd82;
+localparam CPUSTATE_PSH_ACTION = 7'd83;
+
+localparam CPUSTATE_PUL_DONTCARE1 = 7'd84;
+localparam CPUSTATE_PUL_DONTCARE2 = 7'd85;
+localparam CPUSTATE_PUL_ACTION = 7'd86;
+
+localparam CPUSTATE_NMI_START = 7'd87;
+localparam CPUSTATE_IRQ_DONTCARE = 7'd88;
+localparam CPUSTATE_IRQ_START = 7'd89;
+localparam CPUSTATE_IRQ_DONTCARE2 = 7'd90;
+localparam CPUSTATE_IRQ_VECTOR_HI = 7'd91;
+localparam CPUSTATE_IRQ_VECTOR_LO = 7'd92;
+localparam CPUSTATE_FIRQ_START = 7'd93;
+localparam CPUSTATE_CC_DONTCARE = 7'd94;
+localparam CPUSTATE_SWI_START = 7'd95;
+
+localparam CPUSTATE_TST_DONTCARE1 = 7'd96;
+localparam CPUSTATE_TST_DONTCARE2 = 7'd97;
+
+localparam CPUSTATE_DEBUG = 7'd98;
+
+localparam CPUSTATE_16IMM_DONTCARE = 7'd99;
+
+localparam CPUSTATE_HALTED = 7'd100;
+
+localparam CPUSTATE_HALT_EXIT2 = 7'd102;
+localparam CPUSTATE_STOP = 7'd105;
+localparam CPUSTATE_STOP2 = 7'd106;
+localparam CPUSTATE_STOP3 = 7'd107;
+
+
+localparam CPUSTATE_CWAI = 7'd108;
+localparam CPUSTATE_CWAI_DONTCARE1 = 7'd109;
+localparam CPUSTATE_CWAI_POST = 7'd110;
+
+localparam CPUSTATE_DMABREQ = 7'd111;
+localparam CPUSTATE_DMABREQ_EXIT = 7'd112;
+localparam CPUSTATE_SYNC = 7'd113;
+localparam CPUSTATE_SYNC_EXIT = 7'd114;
+
+localparam CPUSTATE_INT_DONTCARE = 7'd115;
+
+
+reg [6:0] CpuState = CPUSTATE_RESET;
+reg [6:0] CpuState_nxt = CPUSTATE_RESET;
+
+reg [6:0] NextState = CPUSTATE_RESET;
+reg [6:0] NextState_nxt = CPUSTATE_RESET;
+
+wire [6:0] PostIllegalState;
+
+// If we encounter something like an illegal addressing mode (an index mode that's illegal for instance)
+// What state should we go to?
+generate
+if (ILLEGAL_INSTRUCTIONS=="STOP")
+begin : postillegal
+ assign PostIllegalState = CPUSTATE_STOP;
+end
+else
+begin
+ assign PostIllegalState = CPUSTATE_FETCH_I1;
+end
+endgenerate
+
+
+
+///////////////////////////////////////////////////////////////////////
+
+//
+// MapInstruction - Considering how the core was instantiated, this
+// will either directly return D[7:0] *or* remap values from D[7:0]
+// that relate to undefined instructions in the 6809 to the instructions
+// that the 6809 actually executed when these were encountered, due to
+// incomplete decoding.
+//
+// NEG, COM, LSR, DEC - these four instructions, in Direct, Inherent (A or B)
+// Indexed, or Extended addressing do not actually decode bit 0 on the instruction.
+// Thus, for instance, a $51 encountered will be executed as a $50, which is a NEGB.
+//
+
+// Specifically, the input is an instruction; if it matches an unknown instruction that the
+// 6809 is known to ghost to another instruction, the output of the function
+// is the the instruction that actually gets executed. Otherwise, the output is the
+// input.
+
+function [7:0] MapInstruction(input [7:0] i);
+reg [3:0] topnyb;
+reg [3:0] btmnyb;
+reg [7:0] newinst;
+begin
+ newinst = i;
+
+ topnyb = i[7:4];
+ btmnyb = i[3:0];
+
+ if ( (topnyb == 4'H0) ||
+ (topnyb == 4'H4) ||
+ (topnyb == 4'H5) ||
+ (topnyb == 4'H6) ||
+ (topnyb == 4'H7)
+ )
+ begin
+ if (btmnyb == 4'H1)
+ newinst = {topnyb, 4'H0};
+ if (btmnyb == 4'H2)
+ newinst = {topnyb, 4'H3};
+ if (btmnyb == 4'H5)
+ newinst = {topnyb, 4'H4};
+ if (btmnyb == 4'HB)
+ newinst = {topnyb, 4'HA};
+ end
+ MapInstruction = newinst;
+end
+endfunction
+
+
+wire [7:0] MappedInstruction;
+generate
+if (ILLEGAL_INSTRUCTIONS=="GHOST")
+begin : ghost
+ assign MappedInstruction = MapInstruction(D);
+end
+else
+begin
+ assign MappedInstruction = D;
+end
+endgenerate
+
+
+
+///////////////////////////////////////////////////////////////////////
+
+function IllegalInstruction(input [7:0] i);
+reg [3:0] hi;
+reg [3:0] lo;
+reg illegal;
+begin
+ illegal = 1'b0;
+ hi = i[7:4];
+ lo = i[3:0];
+ if ( (hi == 4'H0) || (hi == 4'H4) || (hi == 4'H5) || (hi == 4'H6) || (hi == 4'H7) )
+ begin
+ if ( (lo == 4'H1) || (lo == 4'H2) || (lo == 4'H5) || (lo == 4'HB) )
+ illegal = 1'b1;
+ if (lo == 4'HE)
+ if ( (hi == 4'H4) || (hi == 4'H5) )
+ illegal = 1'b1;
+ end
+ if (hi == 4'H3)
+ begin
+ if ( (lo == 4'H8) || (lo == 4'HE) )
+ illegal = 1'b1;
+ end
+ if (hi == 4'H1)
+ begin
+ if ( (lo == 4'H4) || (lo == 4'H5) || (lo == 4'H8) || (lo == 4'HB) )
+ illegal = 1'b1;
+ end
+ if ( (hi == 4'H8) || (hi == 4'HC) )
+ begin
+ if ( (lo == 4'H7) || (lo == 4'HF) )
+ illegal = 1'b1;
+ if ( lo == 4'HD )
+ if (hi == 4'HC)
+ illegal = 1'b1;
+ end
+ IllegalInstruction = illegal;
+end
+endfunction
+
+wire IsIllegalInstruction;
+
+generate
+if (ILLEGAL_INSTRUCTIONS=="GHOST")
+begin : never_illegal
+ assign IsIllegalInstruction = 1'b0;
+end
+else
+begin
+ assign IsIllegalInstruction = IllegalInstruction(Inst1);
+end
+endgenerate
+
+wire [6:0] IllegalInstructionState;
+generate
+if (ILLEGAL_INSTRUCTIONS=="IGNORE")
+begin : illegal_state
+ assign IllegalInstructionState = CPUSTATE_FETCH_I1;
+end
+else if (ILLEGAL_INSTRUCTIONS=="STOP")
+begin
+ assign IllegalInstructionState = CPUSTATE_STOP;
+end
+else
+begin
+ assign IllegalInstructionState = 7'd0;
+end
+endgenerate
+
+
+///////////////////////////////////////////////////////////////////////
+
+
+always @(posedge CLK)
+begin
+ reg old_sample;
+ old_sample <= NMISample2;
+
+ if (wNMIClear == 1) NMILatched <= 1;
+ else if(old_sample & ~NMISample2) NMILatched <= NMIMask;
+end
+
+//
+// The 6809 specs say that the CPU control signals are sampled on the falling edge of Q.
+// It also says that the interrupts require 1 cycle of synchronization time.
+// That's vague, as it doesn't say where "1 cycle" starts or ends. Starting from the
+// falling edge of Q, the next cycle notices an assertion. From checking a hard 6809 on
+// an analyzer, what they really mean is that it's sampled on the falling edge of Q,
+// but there's a one cycle delay from the falling edge of E (0.25 clocks from the falling edge of Q
+// where the signals were sampled) before it can be noticed.
+// So, SIGNALSample is the latched value at the falling edge of Q
+// SIGNALSample2 is the latched value at the falling edge of E (0.25 clocks after the line above)
+// SIGNALLatched is the latched value at the falling edge of E (1 cycle after the line above)
+//
+// /HALT and /DMABREQ are delayed one cycle less than interrupts. The 6809 specs infer these details,
+// but don't list the point-of-reference they're written from (for instance, they say that an interrupt requires
+// a cycle for synchronization; however, it isn't clear whether that's from the falling Q to the next falling Q,
+// a complete intermediate cycle, the falling E to the next falling E, etc.) - which, in the end, required an
+// analyzer on the 6809 to determine how many cycles before a new instruction an interrupt (or /HALT & /DMABREQ)
+// had to be asserted to be noted instead of the next instruction running start to finish.
+//
+always @(posedge CLK)
+begin
+ if(fallQ_en) begin
+ NMISample <= nNMI;
+ IRQSample <= nIRQ;
+ FIRQSample <= nFIRQ;
+ HALTSample <= nHALT;
+ DMABREQSample <= nDMABREQ;
+ end
+end
+
+
+reg rnRESET=0; // The latched version of /RESET, useful 1 clock after it's latched
+always @(posedge CLK)
+begin
+ if(fallE_en) begin
+ rnRESET <= nRESET;
+
+ NMISample2 <= NMISample;
+
+ IRQSample2 <= IRQSample;
+ IRQLatched <= IRQSample2;
+
+ FIRQSample2 <= FIRQSample;
+ FIRQLatched <= FIRQSample2;
+
+ HALTSample2 <= HALTSample;
+ HALTLatched <= HALTSample2;
+
+ DMABREQSample2 <= DMABREQSample;
+ DMABREQLatched <= DMABREQSample2;
+
+
+ if (rnRESET == 1)
+ begin
+ CpuState <= CpuState_nxt;
+
+ // Don't interpret this next item as "The Next State"; it's a special case 'after this
+ // generic state, go to this programmable state', so that a single state
+ // can be shared for many tasks. [Specifically, the stack push/pull code, which is used
+ // for PSH, PUL, Interrupts, RTI, etc.
+ NextState <= NextState_nxt;
+
+ // CPU registers latch from the combinatorial circuit
+ a <= a_nxt;
+ b <= b_nxt;
+ x <= x_nxt;
+ y <= y_nxt;
+ s <= s_nxt;
+ u <= u_nxt;
+ cc <= cc_nxt;
+ dp <= dp_nxt;
+ pc <= pc_nxt;
+ tmp <= tmp_nxt;
+ addr <= addr_nxt;
+ ea <= ea_nxt;
+
+ InstPage2 <= InstPage2_nxt;
+ InstPage3 <= InstPage3_nxt;
+ Inst1 <= Inst1_nxt;
+ Inst2 <= Inst2_nxt;
+ Inst3 <= Inst3_nxt;
+ NMIClear <= NMIClear_nxt;
+
+ IntType <= IntType_nxt;
+
+ // Once S changes at all (default is '0'), release the NMI Mask.
+ if (s != s_nxt) NMIMask <= 1'b0;
+ end
+ else
+ begin
+ CpuState <= CPUSTATE_RESET;
+ NMIMask <= 1'b1; // Mask NMI until S is loaded.
+ NMIClear <= 1'b0; // Mark us as not having serviced NMI
+ end
+ end
+end
+
+
+/////////////////////////////////////////////////////////////////
+// Decode the Index byte
+
+localparam IDX_REG_X = 3'd0;
+localparam IDX_REG_Y = 3'd1;
+localparam IDX_REG_U = 3'd2;
+localparam IDX_REG_S = 3'd3;
+localparam IDX_REG_PC = 3'd4;
+
+localparam IDX_MODE_POSTINC1 = 4'd0;
+localparam IDX_MODE_POSTINC2 = 4'd1;
+localparam IDX_MODE_PREDEC1 = 4'd2;
+localparam IDX_MODE_PREDEC2 = 4'd3;
+localparam IDX_MODE_NOOFFSET = 4'd4;
+localparam IDX_MODE_B_OFFSET = 4'd5;
+localparam IDX_MODE_A_OFFSET = 4'd6;
+localparam IDX_MODE_5BIT_OFFSET= 4'd7; // Special case, not bit pattern 7; the offset sits in the bit pattern
+localparam IDX_MODE_8BIT_OFFSET= 4'd8;
+localparam IDX_MODE_16BIT_OFFSET = 4'd9;
+localparam IDX_MODE_D_OFFSET = 4'd11;
+localparam IDX_MODE_8BIT_OFFSET_PC = 4'd12;
+localparam IDX_MODE_16BIT_OFFSET_PC= 4'd13;
+localparam IDX_MODE_EXTENDED_INDIRECT = 4'd15;
+
+// Return:
+// Register base [3 bits]
+// Indirect [1 bit]
+// Mode [4 bits]
+
+function [7:0] IndexDecode(input [7:0] postbyte);
+reg [2:0] regnum;
+reg indirect;
+reg [3:0] mode;
+begin
+ indirect = 0;
+ mode = 0;
+
+ if (postbyte[7] == 0) // 5-bit
+ begin
+ mode = IDX_MODE_5BIT_OFFSET;
+ end
+ else
+ begin
+ mode = postbyte[3:0];
+ indirect = postbyte[4];
+ end
+ if ((mode != IDX_MODE_8BIT_OFFSET_PC) && (mode != IDX_MODE_16BIT_OFFSET_PC))
+ regnum[2:0] = postbyte[6:5];
+ else
+ regnum[2:0] = IDX_REG_PC;
+
+ IndexDecode = {indirect, mode, regnum};
+end
+endfunction
+
+wire [3:0] IndexedMode;
+wire IndexedIndirect;
+wire [2:0] IndexedRegister;
+
+assign {IndexedIndirect, IndexedMode, IndexedRegister} = IndexDecode(Inst2);
+
+/////////////////////////////////////////////////////////////////
+// Is this a JMP instruction? (irrespective of addressing mode)
+function IsJMP(input [7:0] inst);
+reg [3:0] hi;
+reg [3:0] lo;
+begin
+ hi = inst[7:4];
+ lo = inst[3:0];
+
+ IsJMP = 0;
+ if ((hi == 4'H0) || (hi == 4'H6) || (hi == 4'H7))
+ if (lo == 4'HE)
+ IsJMP = 1;
+end
+endfunction
+
+///////////////////////////////////////////////////////////////////
+// Is this an 8-bit Store?
+
+localparam ST8_REG_A = 1'b0;
+localparam ST8_REG_B = 1'b1;
+
+function [1:0] IsST8(input [7:0] inst);
+reg regnum;
+reg IsStore;
+begin
+
+ IsStore = 1'b0;
+ regnum = 1'b1;
+
+ if ( (Inst1 == 8'H97) || (Inst1 == 8'HA7) || (Inst1 == 8'HB7) )
+ begin
+ IsStore = 1'b1;
+ regnum = 1'b0;
+ end
+ else if ( (Inst1 == 8'HD7) || (Inst1 == 8'HE7) || (Inst1 == 8'HF7) )
+ begin
+ IsStore = 1'b1;
+ regnum = 1'b1;
+ end
+ IsST8 = {IsStore, regnum};
+end
+endfunction
+
+wire IsStore8;
+wire Store8RegisterNum;
+
+assign {IsStore8, Store8RegisterNum} = IsST8(Inst1);
+
+
+/////////////////////////////////////////////////////////////////
+// Is this a 16-bit Store?
+
+localparam ST16_REG_X = 3'd0;
+localparam ST16_REG_Y = 3'd1;
+localparam ST16_REG_U = 3'd2;
+localparam ST16_REG_S = 3'd3;
+localparam ST16_REG_D = 3'd4;
+
+
+function [3:0] IsST16(input [7:0] inst);
+reg [3:0] hi;
+reg [3:0] lo;
+reg [2:0] regnum;
+reg IsStore;
+begin
+ hi = inst[7:4];
+ lo = inst[3:0];
+ IsStore = 1'b0;
+ regnum = 3'b111;
+
+ if ((inst == 8'H9F) || (inst == 8'HAF) || (inst == 8'HBF))
+ begin
+ IsStore = 1;
+ if (~InstPage2)
+ regnum = ST16_REG_X;
+ else
+ regnum = ST16_REG_Y;
+ end
+ else if ((inst == 8'HDF) || (inst == 8'HEF) || (inst == 8'HFF))
+ begin
+ IsStore = 1;
+ if (~InstPage2)
+ regnum = ST16_REG_U;
+ else
+ regnum = ST16_REG_S;
+ end
+ else if ((inst == 8'HDD) || (inst == 8'HED) || (inst == 8'HFD))
+ begin
+ IsStore = 1;
+ regnum = ST16_REG_D;
+ end
+
+ IsST16 = {IsStore, regnum};
+end
+endfunction
+
+wire IsStore16;
+wire [2:0] StoreRegisterNum;
+
+assign {IsStore16, StoreRegisterNum} = IsST16(Inst1);
+
+/////////////////////////////////////////////////////////////////
+// Is this a special Immediate mode instruction, ala
+// PSH, PUL, EXG, TFR, ANDCC, ORCC
+function IsSpecialImm(input [7:0] inst);
+reg is;
+reg [3:0] hi;
+reg [3:0] lo;
+begin
+ hi = inst[7:4];
+ lo = inst[3:0];
+ is = 0;
+
+ if (hi == 4'H1)
+ begin
+ if ( (lo == 4'HA) || (lo == 4'HC) || (lo == 4'HE) || (lo == 4'HF) ) // ORCC, ANDCC, EXG, TFR
+ is = 1;
+ end
+ else if (hi == 4'H3)
+ begin
+ if ( (lo >= 4'H3) && (lo <= 4'H7) ) // PSHS, PULS, PSHU, PULU
+ is = 1;
+ end
+ else
+ is = 0;
+
+ IsSpecialImm = is;
+end
+endfunction
+wire IsSpecialImmediate = IsSpecialImm(Inst1);
+
+/////////////////////////////////////////////////////////////////
+// Is this a one-byte instruction? [The 6809 reads 2 bytes for every instruction, minimum (it can read more). On a one-byte, we have to ensure that we haven't skipped the PC ahead.
+function IsOneByteInstruction(input [7:0] inst);
+reg is;
+reg [3:0] hi;
+reg [3:0] lo;
+begin
+ hi = inst[7:4];
+ lo = inst[3:0];
+ is = 1'b0;
+
+ if ( (hi == 4'H4) || (hi == 4'H5) )
+ is = 1'b1;
+ else if ( hi == 4'H1)
+ begin
+ if ( (lo == 4'H2) || (lo == 4'H3) || (lo == 4'H9) || (lo == 4'HD) )
+ is = 1'b1;
+ end
+ else if (hi == 4'H3)
+ begin
+ if ( (lo >= 4'H9) && (lo != 4'HC) )
+ is = 1'b1;
+ end
+ else
+ is = 1'b0;
+
+ IsOneByteInstruction = is;
+end
+endfunction
+
+/////////////////////////////////////////////////////////////////
+// ALU16 - Simpler than the 8 bit ALU
+
+localparam ALU16_REG_X = 3'd0;
+localparam ALU16_REG_Y = 3'd1;
+localparam ALU16_REG_U = 3'd2;
+localparam ALU16_REG_S = 3'd3;
+localparam ALU16_REG_D = 3'd4;
+
+function [2:0] ALU16RegFromInst(input Page2, input Page3, input [7:0] inst);
+reg [2:0] srcreg;
+begin
+ srcreg = 3'b111; // default
+ casex ({Page2, Page3, inst}) // Note pattern for the matching below
+ 10'b1010xx0011: // 1083, 1093, 10A3, 10B3 CMPD
+ srcreg = ALU16_REG_D;
+ 10'b1010xx1100: // 108C, 109C, 10AC, 10BC CMPY
+ srcreg = ALU16_REG_Y;
+ 10'b0110xx0011: // 1183, 1193, 11A3, 11B3 CMPU
+ srcreg = ALU16_REG_U;
+ 10'b0110xx1100: // 118C, 119C, 11AC, 11BC CMPS
+ srcreg = ALU16_REG_S;
+ 10'b0010xx1100: // 8C,9C,AC,BC CMPX
+ srcreg = ALU16_REG_X;
+
+ 10'b0011xx0011: // C3, D3, E3, F3 ADDD
+ srcreg = ALU16_REG_D;
+
+ 10'b0011xx1100: // CC, DC, EC, FC LDD
+ srcreg = ALU16_REG_D;
+ 10'b0010xx1110: // 8E LDX, 9E LDX, AE LDX, BE LDX
+ srcreg = ALU16_REG_X;
+ 10'b0011xx1110: // CE LDU, DE LDU, EE LDU, FE LDU
+ srcreg = ALU16_REG_U;
+ 10'b1010xx1110: // 108E LDY, 109E LDY, 10AE LDY, 10BE LDY
+ srcreg = ALU16_REG_Y;
+ 10'b1011xx1110: // 10CE LDS, 10DE LDS, 10EE LDS, 10FE LDS
+ srcreg = ALU16_REG_S;
+ 10'b0010xx0011: // 83, 93, A3, B3 SUBD
+ srcreg = ALU16_REG_D;
+
+ 10'H03A: // 3A ABX
+ srcreg = ALU16_REG_X;
+ 10'H030: // 30 LEAX
+ srcreg = ALU16_REG_X;
+ 10'H031: // 31 LEAY
+ srcreg = ALU16_REG_Y;
+ 10'H032: // 32 LEAS
+ srcreg = ALU16_REG_S;
+ 10'H033: // 32 LEAU
+ srcreg = ALU16_REG_U;
+ default:
+ srcreg = 3'b111;
+ endcase
+ ALU16RegFromInst = srcreg;
+end
+endfunction
+
+wire [2:0] ALU16Reg = ALU16RegFromInst(InstPage2, InstPage3, Inst1);
+
+localparam ALUOP16_SUB = 3'H0;
+localparam ALUOP16_ADD = 3'H1;
+localparam ALUOP16_LD = 3'H2;
+localparam ALUOP16_CMP = 3'H3;
+localparam ALUOP16_LEA = 3'H4;
+localparam ALUOP16_INVALID = 3'H7;
+
+function [3:0] ALU16OpFromInst(input Page2, input Page3, input [7:0] inst);
+reg [2:0] aluop;
+reg writeback;
+begin
+ aluop = 3'b111;
+ writeback = 1'b1;
+ casex ({Page2, Page3, inst})
+ 10'b1010xx0011: // 1083, 1093, 10A3, 10B3 CMPD
+ begin
+ aluop = ALUOP16_CMP;
+ writeback = 1'b0;
+ end
+ 10'b1010xx1100: // 108C, 109C, 10AC, 10BC CMPY
+ begin
+ aluop = ALUOP16_CMP;
+ writeback = 1'b0;
+ end
+ 10'b0110xx0011: // 1183, 1193, 11A3, 11B3 CMPU
+ begin
+ aluop = ALUOP16_CMP;
+ writeback = 1'b0;
+ end
+ 10'b0110xx1100: // 118C, 119C, 11AC, 11BC CMPS
+ begin
+ aluop = ALUOP16_CMP;
+ writeback = 1'b0;
+ end
+ 10'b0010xx1100: // 8C,9C,AC,BC CMPX
+ begin
+ aluop = ALUOP16_CMP;
+ writeback = 1'b0;
+ end
+
+ 10'b0011xx0011: // C3, D3, E3, F3 ADDD
+ aluop = ALUOP16_ADD;
+
+ 10'b0011xx1100: // CC, DC, EC, FC LDD
+ aluop = ALUOP16_LD;
+ 10'b001xxx1110: // 8E LDX, 9E LDX, AE LDX, BE LDX, CE LDU, DE LDU, EE LDU, FE LDU
+ aluop = ALUOP16_LD;
+ 10'b101xxx1110: // 108E LDY, 109E LDY, 10AE LDY, 10BE LDY, 10CE LDS, 10DE LDS, 10EE LDS, 10FE LDS
+ aluop = ALUOP16_LD;
+
+ 10'b0010xx0011: // 83, 93, A3, B3 SUBD
+ aluop = ALUOP16_SUB;
+
+ 10'H03A: // 3A ABX
+ aluop = ALUOP16_ADD;
+
+ 10'b00001100xx: // $30-$33, LEAX, LEAY, LEAS, LEAU
+ aluop = ALUOP16_LEA;
+
+ default:
+ aluop = ALUOP16_INVALID;
+ endcase
+ ALU16OpFromInst = {writeback, aluop};
+end
+endfunction
+
+wire ALU16OpWriteback;
+wire [2:0] ALU16Opcode;
+
+assign {ALU16OpWriteback, ALU16Opcode} = ALU16OpFromInst(InstPage2, InstPage3, Inst1);
+
+wire IsALU16Opcode = (ALU16Opcode != 3'b111);
+
+function [23:0] ALU16Inst(input [2:0] operation16, input [15:0] a_arg, input [15:0] b_arg, input [7:0] cc_arg);
+reg [7:0] cc_out;
+reg [15:0] ALUFn;
+reg carry;
+reg borrow;
+begin
+ cc_out = cc_arg;
+ case (operation16)
+ ALUOP16_ADD:
+ begin
+ {cc_out[CC_C_BIT], ALUFn} = {1'b0, a_arg} + b_arg;
+ cc_out[CC_V_BIT] = (a_arg[15] & b_arg[15] & ~ALUFn[15]) | (~a_arg[15] & ~b_arg[15] & ALUFn[15]);
+ end
+
+ ALUOP16_SUB:
+ begin
+ {cc_out[CC_C_BIT], ALUFn} = {1'b0, a_arg} - {1'b0, b_arg};
+ cc_out[CC_V_BIT] = (a_arg[15] & ~b_arg[15] & ~ALUFn[15]) | (~a_arg[15] & b_arg[15] & ALUFn[15]);
+ end
+
+ ALUOP16_LD:
+ begin
+ ALUFn = b_arg;
+ cc_out[CC_V_BIT] = 1'b0;
+ end
+
+ ALUOP16_CMP:
+ begin
+ {cc_out[CC_C_BIT], ALUFn} = {1'b0, a_arg} - {1'b0, b_arg};
+ cc_out[CC_V_BIT] = (a_arg[15] & ~b_arg[15] & ~ALUFn[15]) | (~a_arg[15] & b_arg[15] & ALUFn[15]);
+ end
+
+ ALUOP16_LEA:
+ begin
+ ALUFn = a_arg;
+ end
+
+ default:
+ ALUFn = 16'H0000;
+
+ endcase
+ cc_out[CC_Z_BIT] = (ALUFn[15:0] == 16'H0000);
+ if (operation16 != ALUOP16_LEA)
+ cc_out[CC_N_BIT] = ALUFn[15];
+ ALU16Inst = {cc_out, ALUFn};
+end
+endfunction
+
+reg [2:0] ALU16_OP;
+reg [15:0] ALU16_A;
+reg [15:0] ALU16_B;
+reg [7:0] ALU16_CC;
+
+// Top 8 bits == CC, bottom 8 bits = output value
+wire [23:0] ALU16 = ALU16Inst(ALU16_OP, ALU16_A, ALU16_B, ALU16_CC);
+
+
+/////////////////////////////////////////////////////////////////
+// ALU
+
+// The ops are organized from the 4 low-order bits of the instructions for the first set of ops, then 16-31 are the second set - even though bit 4 isn't representative.
+localparam ALUOP_NEG = 5'd0;
+localparam ALUOP_COM = 5'd3;
+localparam ALUOP_LSR = 5'd4;
+localparam ALUOP_ROR = 5'd6;
+localparam ALUOP_ASR = 5'd7;
+localparam ALUOP_ASL = 5'd8;
+localparam ALUOP_LSL = 5'd8;
+localparam ALUOP_ROL = 5'd9;
+localparam ALUOP_DEC = 5'd10;
+localparam ALUOP_INC = 5'd12;
+localparam ALUOP_TST = 5'd13;
+localparam ALUOP_CLR = 5'd15;
+
+localparam ALUOP_SUB = 5'd16;
+localparam ALUOP_CMP = 5'd17;
+localparam ALUOP_SBC = 5'd18;
+localparam ALUOP_AND = 5'd20;
+localparam ALUOP_BIT = 5'd21;
+localparam ALUOP_LD = 5'd22;
+localparam ALUOP_EOR = 5'd24;
+localparam ALUOP_ADC = 5'd25;
+localparam ALUOP_OR = 5'd26;
+localparam ALUOP_ADD = 5'd27;
+
+function [5:0] ALUOpFromInst(input [7:0] inst);
+reg [4:0] op;
+reg writeback;
+begin
+ // Okay, this turned out to be simpler than I expected ...
+ op = {inst[7], inst[3:0]};
+ case (op)
+ ALUOP_CMP:
+ writeback = 0;
+ ALUOP_TST:
+ writeback = 0;
+ ALUOP_BIT:
+ writeback = 0;
+ default:
+ writeback = 1;
+ endcase
+ ALUOpFromInst = {writeback, op};
+end
+endfunction
+
+wire [4:0] ALU8Op;
+wire ALU8Writeback;
+
+assign {ALU8Writeback, ALU8Op} = ALUOpFromInst(Inst1);
+
+reg [7:0] ALU_A;
+reg [7:0] ALU_B;
+reg [7:0] ALU_CC;
+reg [4:0] ALU_OP;
+
+
+function [15:0] ALUInst(input [4:0] operation, input [7:0] a_arg, input [7:0] b_arg, input [7:0] cc_arg);
+reg [7:0] cc_out;
+reg [7:0] ALUFn;
+reg borrow;
+begin
+ cc_out = cc_arg;
+ case (operation)
+ ALUOP_NEG:
+ begin
+ ALUFn = ~a_arg + 1'b1;
+ cc_out[CC_C_BIT] = (ALUFn != 8'H00);
+ cc_out[CC_V_BIT] = (a_arg == 8'H80);
+ end
+
+ ALUOP_LSL:
+ begin
+ {cc_out[CC_C_BIT], ALUFn} = {a_arg, 1'b0};
+ cc_out[CC_V_BIT] = a_arg[7] ^ a_arg[6];
+ end
+
+ ALUOP_LSR:
+ begin
+ {ALUFn, cc_out[CC_C_BIT]} = {1'b0, a_arg};
+ end
+
+ ALUOP_ASR:
+ begin
+ {ALUFn, cc_out[CC_C_BIT]} = {a_arg[7], a_arg};
+ end
+
+ ALUOP_ROL:
+ begin
+ {cc_out[CC_C_BIT], ALUFn} = {a_arg, cc_arg[CC_C_BIT]};
+ cc_out[CC_V_BIT] = a_arg[7] ^ a_arg[6];
+ end
+
+ ALUOP_ROR:
+ begin
+ {ALUFn, cc_out[CC_C_BIT]} = {cc_arg[CC_C_BIT], a_arg};
+ end
+
+ ALUOP_OR:
+ begin
+ ALUFn = (a_arg | b_arg);
+ cc_out[CC_V_BIT] = 0;
+ end
+
+ ALUOP_ADD:
+ begin
+ {cc_out[CC_C_BIT], ALUFn} = {1'b0, a_arg} + {1'b0, b_arg};
+ cc_out[CC_V_BIT] = (a_arg[7] & b_arg[7] & ~ALUFn[7]) | (~a_arg[7] & ~b_arg[7] & ALUFn[7]);
+ cc_out[CC_H_BIT] = a_arg[4] ^ b_arg[4] ^ ALUFn[4];
+ end
+
+ ALUOP_SUB:
+ begin
+ {cc_out[CC_C_BIT], ALUFn} = {1'b0, a_arg} - {1'b0, b_arg};
+ cc_out[CC_V_BIT] = (a_arg[7] & ~b_arg[7] & ~ALUFn[7]) | (~a_arg[7] & b_arg[7] & ALUFn[7]);
+ end
+
+ ALUOP_AND:
+ begin
+ ALUFn = (a_arg & b_arg);
+ cc_out[CC_V_BIT] = 0;
+ end
+
+ ALUOP_BIT:
+ begin
+ ALUFn = (a_arg & b_arg);
+ cc_out[CC_V_BIT] = 0;
+ end
+
+ ALUOP_EOR:
+ begin
+ ALUFn = (a_arg ^ b_arg);
+ cc_out[CC_V_BIT] = 0;
+ end
+
+ ALUOP_CMP:
+ begin
+ {cc_out[CC_C_BIT], ALUFn} = {1'b0, a_arg} - {1'b0, b_arg};
+ cc_out[CC_V_BIT] = (a_arg[7] & ~b_arg[7] & ~ALUFn[7]) | (~a_arg[7] & b_arg[7] & ALUFn[7]);
+ end
+
+ ALUOP_COM:
+ begin
+ ALUFn = ~a_arg;
+ cc_out[CC_V_BIT] = 0;
+ cc_out[CC_C_BIT] = 1;
+ end
+
+ ALUOP_ADC:
+ begin
+ {cc_out[CC_C_BIT], ALUFn} = {1'b0, a_arg} + {1'b0, b_arg} + cc_arg[CC_C_BIT];
+ cc_out[CC_V_BIT] = (a_arg[7] & b_arg[7] & ~ALUFn[7]) | (~a_arg[7] & ~b_arg[7] & ALUFn[7]);
+ cc_out[CC_H_BIT] = a_arg[4] ^ b_arg[4] ^ ALUFn[4];
+ end
+
+ ALUOP_LD:
+ begin
+ ALUFn = b_arg;
+ cc_out[CC_V_BIT] = 0;
+ end
+
+ ALUOP_INC:
+ begin
+ ALUFn = a_arg + 1'b1;
+ cc_out[CC_V_BIT] = (~a_arg[7] & ALUFn[7]);
+ end
+
+ ALUOP_DEC:
+ begin
+ ALUFn = a_arg - 1'b1;
+ cc_out[CC_V_BIT] = (a_arg[7] & ~ALUFn[7]);
+ end
+
+ ALUOP_CLR:
+ begin
+ ALUFn = 0;
+ cc_out[CC_V_BIT] = 0;
+ cc_out[CC_C_BIT] = 0;
+ end
+
+ ALUOP_TST:
+ begin
+ ALUFn = a_arg;
+ cc_out[CC_V_BIT] = 0;
+ end
+
+ ALUOP_SBC:
+ begin
+ {cc_out[CC_C_BIT], ALUFn} = {1'b0, a_arg} - {1'b0, b_arg} - cc_arg[CC_C_BIT];
+ cc_out[CC_V_BIT] = (a_arg[7] & ~b_arg[7] & ~ALUFn[7]) | (~a_arg[7] & b_arg[7] & ALUFn[7]);
+ end
+
+ default:
+ ALUFn = 0;
+
+ endcase
+
+ cc_out[CC_N_BIT] = ALUFn[7];
+ cc_out[CC_Z_BIT] = !ALUFn;
+ ALUInst = {cc_out[7:0], ALUFn};
+end
+endfunction
+
+
+// Top 8 bits == CC, bottom 8 bits = output value
+wire [15:0] ALU = ALUInst(ALU_OP, ALU_A, ALU_B, ALU_CC);
+
+////////////////////////////////////////////////////////////
+
+localparam TYPE_INHERENT = 3'd0;
+localparam TYPE_IMMEDIATE = 3'd1;
+localparam TYPE_DIRECT = 3'd2;
+localparam TYPE_RELATIVE = 3'd3;
+localparam TYPE_INDEXED = 3'd4;
+localparam TYPE_EXTENDED = 3'd5;
+
+localparam TYPE_INVALID = 3'd7;
+
+// Function to decode the addressing mode the instruction uses
+function [2:0] addressing_mode_type(input [7:0] inst);
+begin
+ casex (inst)
+ 8'b0000???? : addressing_mode_type = TYPE_DIRECT;
+ 8'b0001???? :
+ begin
+ casex (inst[3:0])
+ 4'b0010:
+ addressing_mode_type = TYPE_INHERENT;
+
+ 4'b0011:
+ addressing_mode_type = TYPE_INHERENT;
+
+ 4'b1001:
+ addressing_mode_type = TYPE_INHERENT;
+
+ 4'b1101:
+ addressing_mode_type = TYPE_INHERENT;
+
+ 4'b0110:
+ addressing_mode_type = TYPE_RELATIVE;
+
+ 4'b0111:
+ addressing_mode_type = TYPE_RELATIVE;
+
+ 4'b1010:
+ addressing_mode_type = TYPE_IMMEDIATE;
+
+ 4'b1100:
+ addressing_mode_type = TYPE_IMMEDIATE;
+
+ 4'b1110:
+ addressing_mode_type = TYPE_IMMEDIATE;
+
+ 4'b1111:
+ addressing_mode_type = TYPE_IMMEDIATE;
+
+ default:
+ addressing_mode_type = TYPE_INVALID;
+ endcase
+ end
+
+ 8'b0010????: addressing_mode_type = TYPE_RELATIVE;
+ 8'b0011????:
+ begin
+ casex(inst[3:0])
+ 4'b00??:
+ addressing_mode_type = TYPE_INDEXED;
+
+ 4'b01??:
+ addressing_mode_type = TYPE_IMMEDIATE;
+
+ 4'b1001:
+ addressing_mode_type = TYPE_INHERENT;
+
+ 4'b101?:
+ addressing_mode_type = TYPE_INHERENT;
+
+ 4'b1100:
+ addressing_mode_type = TYPE_INHERENT;
+
+ 4'b1101:
+ addressing_mode_type = TYPE_INHERENT;
+
+ 4'b1111:
+ addressing_mode_type = TYPE_INHERENT;
+
+ default:
+ addressing_mode_type = TYPE_INVALID;
+ endcase
+ end
+
+ 8'b010?????: addressing_mode_type = TYPE_INHERENT;
+
+ 8'b0110????: addressing_mode_type = TYPE_INDEXED;
+
+ 8'b0111????: addressing_mode_type = TYPE_EXTENDED;
+
+ 8'b1000????:
+ begin
+ casex (inst[3:0])
+ 4'b0111: addressing_mode_type = TYPE_INVALID;
+ 4'b1111: addressing_mode_type = TYPE_INVALID;
+ 4'b1101: addressing_mode_type = TYPE_RELATIVE;
+ default: addressing_mode_type = TYPE_IMMEDIATE;
+ endcase
+ end
+
+ 8'b1001????: addressing_mode_type = TYPE_DIRECT;
+ 8'b1010????: addressing_mode_type = TYPE_INDEXED;
+ 8'b1011????: addressing_mode_type = TYPE_EXTENDED;
+ 8'b1100????: addressing_mode_type = TYPE_IMMEDIATE;
+ 8'b1101????: addressing_mode_type = TYPE_DIRECT;
+ 8'b1110????: addressing_mode_type = TYPE_INDEXED;
+ 8'b1111????: addressing_mode_type = TYPE_EXTENDED;
+
+ endcase
+end
+endfunction
+
+wire [2:0] AddrModeType = addressing_mode_type(Inst1);
+
+//////////////////////////////////////////////////
+
+// Individual opcodes that are the top of a column of states.
+
+localparam OPCODE_INH_ABX = 8'H3A;
+localparam OPCODE_INH_RTS = 8'H39;
+localparam OPCODE_INH_RTI = 8'H3B;
+localparam OPCODE_INH_CWAI = 8'H3C;
+localparam OPCODE_INH_MUL = 8'H3D;
+localparam OPCODE_INH_SWI = 8'H3F;
+localparam OPCODE_INH_SEX = 8'H1D;
+localparam OPCODE_INH_NOP = 8'H12;
+localparam OPCODE_INH_SYNC = 8'H13;
+localparam OPCODE_INH_DAA = 8'H19;
+
+localparam OPCODE_IMM_ORCC = 8'H1A;
+localparam OPCODE_IMM_ANDCC = 8'H1C;
+localparam OPCODE_IMM_EXG = 8'H1E;
+localparam OPCODE_IMM_TFR = 8'H1F;
+localparam OPCODE_IMM_PSHS = 8'H34;
+localparam OPCODE_IMM_PULS = 8'H35;
+localparam OPCODE_IMM_PSHU = 8'H36;
+localparam OPCODE_IMM_PULU = 8'H37;
+
+localparam OPCODE_IMM_SUBD = 8'H83;
+localparam OPCODE_IMM_CMPX = 8'H8C;
+localparam OPCODE_IMM_LDX = 8'H8E;
+localparam OPCODE_IMM_ADDD = 8'HC3;
+localparam OPCODE_IMM_LDD = 8'HCC;
+localparam OPCODE_IMM_LDU = 8'HCE;
+localparam OPCODE_IMM_CMPD = 8'H83; // Page2
+localparam OPCODE_IMM_CMPY = 8'H8C; // Page2
+localparam OPCODE_IMM_LDY = 8'H8E; // Page2
+localparam OPCODE_IMM_LDS = 8'HCE; // Page2
+localparam OPCODE_IMM_CMPU = 8'H83; // Page3
+localparam OPCODE_IMM_CMPS = 8'H8C; // Page3
+
+localparam EXGTFR_REG_D = 4'H0;
+localparam EXGTFR_REG_X = 4'H1;
+localparam EXGTFR_REG_Y = 4'H2;
+localparam EXGTFR_REG_U = 4'H3;
+localparam EXGTFR_REG_S = 4'H4;
+localparam EXGTFR_REG_PC = 4'H5;
+localparam EXGTFR_REG_A = 4'H8;
+localparam EXGTFR_REG_B = 4'H9;
+localparam EXGTFR_REG_CC = 4'HA;
+localparam EXGTFR_REG_DP = 4'HB;
+
+function IsALU8Set0(input [7:0] instr);
+reg result;
+reg [3:0] hi;
+reg [3:0] lo;
+begin
+ hi = instr[7:4];
+ lo = instr[3:0];
+ if ( (hi == 4'H0) || (hi == 4'H4) || (hi == 4'H5) || (hi == 4'H6) || (hi == 4'H7) )
+ begin
+ if ( (lo != 4'H1) && (lo != 4'H2) && (lo != 4'H5) && (lo != 4'HB) && (lo != 4'HE) ) // permit NEG, COM, LSR, ROR, ASR, ASL/LSL, ROL, DEC, INC, TST, CLR
+ result = 1;
+ else
+ result = 0;
+ end
+ else
+ result = 0;
+ IsALU8Set0 = result;
+end
+endfunction
+
+function IsALU8Set1(input [7:0] instr);
+reg result;
+reg [3:0] hi;
+reg [3:0] lo;
+begin
+ hi = instr[7:4];
+ lo = instr[3:0];
+ if ( (hi >= 4'H8) )
+ begin
+ if ( (lo <= 4'HB) && (lo != 4'H3) && (lo != 4'H7) ) // 8-bit SUB, CMP, SBC, AND, BIT, LD, EOR, ADC, OR, ADD
+ result = 1;
+ else
+ result = 0;
+ end
+ else
+ result = 0;
+ IsALU8Set1 = result;
+end
+endfunction
+
+// Determine if the instruction is performing an 8-bit op (ALU only)
+function ALU8BitOp(input [7:0] instr);
+begin
+ ALU8BitOp = IsALU8Set0(instr) | IsALU8Set1(instr);
+end
+endfunction
+
+wire Is8BitInst = ALU8BitOp(Inst1);
+
+function IsRegA(input [7:0] instr);
+reg result;
+reg [3:0] hi;
+begin
+ hi = instr[7:4];
+ if ((hi == 4'H4) || (hi == 4'H8) || (hi == 4'H9) || (hi == 4'HA) || (hi == 4'HB) )
+ result = 1;
+ else
+ result = 0;
+ IsRegA = result;
+end
+endfunction
+
+wire IsTargetRegA = IsRegA(Inst1);
+
+//
+//
+// Decode
+// 00-0F = DIRECT
+// 10-1F = INHERENT, RELATIVE, IMMEDIATE
+// 20-2F = RELATIVE
+// 30-3F = INDEXED, IMMEDIATE (pus, pul), INHERENT
+// 40-4F = INHERENT
+// 50-5F = INHERENT
+// 60-6F = INDEXED
+// 70-7F = EXTENDED
+// 80-8F = IMMEDIATE, RELATIVE (BSR)
+// 90-9F = DIRECT
+// A0-AF = INDEXED
+// B0-BF = EXTENDED
+// C0-CF = IMMEDIATE
+// D0-DF = DIRECT
+// E0-EF = INDEXED
+// F0-FF = EXTENDED
+
+// DIRECT; 00-0F, 90-9F, D0-DF
+// INHERENT; 10-1F (12, 13, 19, 1D), 30-3F (39-3F), 40-4F, 50-5F,
+// RELATIVE: 10-1F (16, 17), 20-2F, 80-8F (8D)
+// IMMEDIATE: 10-1F (1A, 1C, 1E, 1F), 30-3F (34-37), 80-8F (80-8C, 8E), C0-CF
+// INDEXED: 60-6F, A0-AF, E0-EF
+// EXTENDED: 70-7F, B0-Bf, F0-FF
+
+localparam INST_LBRA = 8'H16; // always -- shitty numbering, damnit
+localparam INST_LBSR = 8'H17; //
+
+localparam INST_BRA = 8'H20; // always
+localparam INST_BRN = 8'H21; // never
+localparam INST_BHI = 8'H22; // CC.Z = 0 && CC.C = 0
+localparam INST_BLS = 8'H23; // CC.Z != 0 && CC.C != 0
+localparam INST_BCC = 8'H24; // CC.C = 0
+localparam INST_BHS = 8'H24; // same as BCC
+localparam INST_BCS = 8'H25; // CC.C = 1
+localparam INST_BLO = 8'H25; // same as BCS
+localparam INST_BNE = 8'H26; // CC.Z = 0
+localparam INST_BEQ = 8'H27; // CC.Z = 1
+localparam INST_BVC = 8'H28; // V = 1
+localparam INST_BVS = 8'H29; // V = 0
+localparam INST_BPL = 8'H2A; // CC.N = 0
+localparam INST_BMI = 8'H2B; // CC.N = 1
+localparam INST_BGE = 8'H2C; // CC.N = CC.V
+localparam INST_BLT = 8'H2D; // CC.N != CC.V
+localparam INST_BGT = 8'H2E; // CC.N = CC.V && CC.Z = 0
+localparam INST_BLE = 8'H2F; // CC.N != CC.V && CC.Z = 1
+localparam INST_BSR = 8'H8D; // always
+
+localparam NYB_BRA = 4'H0; // always
+localparam NYB_BRN = 4'H1; // never
+localparam NYB_BHI = 4'H2; // CC.Z = 0 && CC.C = 0
+localparam NYB_BLS = 4'H3; // CC.Z != 0 && CC.C != 0
+localparam NYB_BCC = 4'H4; // CC.C = 0
+localparam NYB_BHS = 4'H4; // same as BCC
+localparam NYB_BCS = 4'H5; // CC.C = 1
+localparam NYB_BLO = 4'H5; // same as BCS
+localparam NYB_BNE = 4'H6; // CC.Z = 0
+localparam NYB_BEQ = 4'H7; // CC.Z = 1
+localparam NYB_BVC = 4'H8; // V = 0
+localparam NYB_BVS = 4'H9; // V = 1
+localparam NYB_BPL = 4'HA; // CC.N = 0
+localparam NYB_BMI = 4'HB; // CC.N = 1
+localparam NYB_BGE = 4'HC; // CC.N = CC.V
+localparam NYB_BLT = 4'HD; // CC.N != CC.V
+localparam NYB_BGT = 4'HE; // CC.N = CC.V && CC.Z = 0
+localparam NYB_BLE = 4'HF; // CC.N != CC.V && CC.Z = 1
+
+
+
+function take_branch(input [7:0] Inst1, input [7:0] cc);
+begin
+ take_branch = 0; //default
+ if ( (Inst1 == INST_BSR) || (Inst1 == INST_LBSR) || (Inst1 == INST_LBRA) )
+ take_branch = 1;
+ else
+ case (Inst1[3:0])
+ NYB_BRA:
+ take_branch = 1;
+ NYB_BRN:
+ take_branch = 0;
+ NYB_BHI:
+ if ( ( cc[CC_Z_BIT] | cc[CC_C_BIT] ) == 0)
+ take_branch = 1;
+ NYB_BLS:
+ if ( cc[CC_Z_BIT] | cc[CC_C_BIT] )
+ take_branch = 1;
+ NYB_BCC:
+ if ( cc[CC_C_BIT] == 0 )
+ take_branch = 1;
+ NYB_BCS:
+ if ( cc[CC_C_BIT] == 1 )
+ take_branch = 1;
+ NYB_BNE:
+ if ( cc[CC_Z_BIT] == 0 )
+ take_branch = 1;
+ NYB_BEQ:
+ if ( cc[CC_Z_BIT] == 1 )
+ take_branch = 1;
+ NYB_BVC:
+ if ( cc[CC_V_BIT] == 0)
+ take_branch = 1;
+ NYB_BVS:
+ if ( cc[CC_V_BIT] == 1)
+ take_branch = 1;
+ NYB_BPL:
+ if ( cc[CC_N_BIT] == 0 )
+ take_branch = 1;
+ NYB_BMI:
+ if (cc[CC_N_BIT] == 1)
+ take_branch = 1;
+ NYB_BGE:
+ if ((cc[CC_N_BIT] ^ cc[CC_V_BIT]) == 0)
+ take_branch = 1;
+ NYB_BLT:
+ if ((cc[CC_N_BIT] ^ cc[CC_V_BIT]) == 1)
+ take_branch = 1;
+ NYB_BGT:
+ if ( ((cc[CC_N_BIT] ^ cc[CC_V_BIT]) == 0) & (cc[CC_Z_BIT] == 0) )
+ take_branch = 1;
+ NYB_BLE:
+ if ( ((cc[CC_N_BIT] ^ cc[CC_V_BIT]) == 1) | (cc[CC_Z_BIT] == 1) )
+ take_branch = 1;
+ endcase
+end
+endfunction
+
+wire TakeBranch = take_branch(Inst1, cc);
+
+/////////////////////////////////////////////////////////////////////
+// Convenience function for knowing the contents for TFR, EXG
+function [15:0] EXGTFRRegister(input [3:0] regid);
+begin
+ case (regid)
+ EXGTFR_REG_D:
+ EXGTFRRegister = {a, b};
+ EXGTFR_REG_X:
+ EXGTFRRegister = x;
+ EXGTFR_REG_Y:
+ EXGTFRRegister = y;
+ EXGTFR_REG_U:
+ EXGTFRRegister = u;
+ EXGTFR_REG_S:
+ EXGTFRRegister = s;
+ EXGTFR_REG_PC:
+ EXGTFRRegister = pc_p1; // For both EXG and TFR, this is used on the 2nd byte in the instruction's cycle. The PC intended to transfer is actually the next byte.
+ EXGTFR_REG_DP:
+ EXGTFRRegister = {8'HFF, dp};
+ EXGTFR_REG_A:
+ EXGTFRRegister = {8'HFF, a};
+ EXGTFR_REG_B:
+ EXGTFRRegister = {8'HFF, b};
+ EXGTFR_REG_CC:
+ EXGTFRRegister = {8'HFF, cc};
+ default:
+ EXGTFRRegister = 16'H0;
+ endcase
+end
+endfunction
+wire [15:0] EXGTFRRegA = EXGTFRRegister(D[7:4]);
+wire [15:0] EXGTFRRegB = EXGTFRRegister(D[3:0]);
+
+// CPU state machine
+always @(*)
+begin
+ rLIC = 1'b0;
+ rAVMA = 1'b1;
+ rBUSY = 1'b0;
+
+ addr_nxt = 16'HFFFF;
+ pc_p1 = (pc+16'H1);
+ pc_p2 = (pc+16'H2);
+ pc_p3 = (pc+16'H3);
+ s_p1 = (s+16'H1);
+ s_m1 = (s-16'H1);
+ u_p1 = (u+16'H1);
+ u_m1 = (u-16'H1);
+ addr_p1 = (addr+16'H1);
+ ea_p1 = (ea+16'H1);
+ BS_nxt = 1'b0;
+ BA_nxt = 1'b0;
+
+ // These may be overridden below, but the "next" version by default should be
+ // the last latched version.
+ IntType_nxt = IntType;
+ NMIClear_nxt = NMIClear;
+ NextState_nxt = NextState;
+ a_nxt = a;
+ b_nxt = b;
+ x_nxt = x;
+ y_nxt = y;
+ s_nxt = s;
+ u_nxt = u;
+ cc_nxt = cc;
+ dp_nxt = dp;
+ pc_nxt = pc;
+ tmp_nxt = tmp;
+ ea_nxt = ea;
+
+ ALU_A = 8'H00;
+ ALU_B = 8'H00;
+ ALU_CC = 8'H00;
+ ALU_OP = 5'H00;
+
+ ALU16_OP = 3'H0;
+ ALU16_A = 16'H0000;
+ ALU16_B = 16'H0000;
+ ALU16_CC = 8'H00;
+
+ DOutput = 8'H00;
+ RnWOut = 1'b1; // read
+
+ Inst1_nxt = Inst1;
+ Inst2_nxt = Inst2;
+ Inst3_nxt = Inst3;
+ InstPage2_nxt = InstPage2;
+ InstPage3_nxt = InstPage3;
+
+ CpuState_nxt = CpuState;
+
+ case (CpuState)
+ CPUSTATE_RESET:
+ begin
+ addr_nxt = 16'HFFFF;
+ a_nxt = 0;
+ b_nxt = 0;
+ x_nxt = 0;
+ y_nxt = 0;
+ s_nxt = 16'HFFFD; // Take care about removing the reset of S. There's logic depending on the delta between s and s_nxt to clear NMIMask.
+ u_nxt = 0;
+ cc_nxt = CC_F | CC_I; // reset disables interrupts
+ dp_nxt = 0;
+ ea_nxt = 16'HFFFF;
+
+ RnWOut = 1; // read
+ rLIC = 1'b0; // Instruction incomplete
+ NMIClear_nxt= 1'b0;
+ IntType_nxt = 3'b111;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_RESET0;
+ end
+
+ CPUSTATE_RESET0:
+ begin
+ addr_nxt = `RESET_VECTOR;
+ rBUSY = 1'b1;
+ pc_nxt[15:8] = D[7:0];
+ BS_nxt = 1'b1; // ACK RESET
+ rAVMA = 1'b1;
+ rLIC = 1'b1;
+ CpuState_nxt = CPUSTATE_RESET2;
+ end
+
+ CPUSTATE_RESET2:
+ begin
+ addr_nxt = addr_p1;
+ BS_nxt = 1'b1; // ACK RESET
+ pc_nxt[7:0] = D[7:0];
+ rAVMA = 1'b1;
+ rLIC = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ CPUSTATE_FETCH_I1:
+ begin
+ if (~DMABREQLatched)
+ begin
+ addr_nxt = pc;
+ RnWOut = 1'b1;
+ rAVMA = 1'b0;
+ tmp_nxt = {tmp[15:4], 4'b1111};
+ BS_nxt = 1'b1;
+ BA_nxt = 1'b1;
+ rLIC = 1'b1;
+ CpuState_nxt = CPUSTATE_DMABREQ;
+ end
+ else if (~HALTLatched)
+ begin
+ addr_nxt = pc;
+ RnWOut = 1'b1;
+ rAVMA = 1'b0;
+ BS_nxt = 1'b1;
+ BA_nxt = 1'b1;
+ rLIC = 1'b1;
+ CpuState_nxt = CPUSTATE_HALTED;
+ end
+ else // not halting, run the inst byte fetch
+ begin
+ addr_nxt = pc; // Set the address bus for the next instruction, first byte
+ pc_nxt = pc_p1;
+ RnWOut = 1; // Set for a READ
+ Inst1_nxt = MappedInstruction;
+ InstPage2_nxt = 0;
+ InstPage3_nxt = 0;
+
+ // New instruction fetch; service interrupts pending
+ if (NMILatched == 0)
+ begin
+ pc_nxt = pc;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_NMI_START;
+ end
+ else if ((FIRQLatched == 0) && (cc[CC_F_BIT] == 0))
+ begin
+ pc_nxt = pc;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FIRQ_START;
+ end
+ else if ((IRQLatched == 0) && (cc[CC_I_BIT] == 0))
+ begin
+ pc_nxt = pc;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_IRQ_START;
+ end
+
+ // The actual 1st byte checks
+ else if (Inst1_nxt == 8'H10) // Page 2 Note, like the 6809, $10 $10 $10 $10 has the same effect as a single $10.
+ begin
+ InstPage2_nxt = 1;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1V2;
+ end
+ else if (Inst1_nxt == 8'H11) // Page 3
+ begin
+ InstPage3_nxt = 1;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1V2;
+ end
+ else
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I2;
+ end
+ end // if not halting
+ end
+
+ CPUSTATE_FETCH_I1V2:
+ begin
+ addr_nxt = pc; // Set the address bus for the next instruction, first byte
+ pc_nxt = pc_p1;
+ RnWOut = 1; // Set for a READ
+ Inst1_nxt = MappedInstruction;
+
+ if (Inst1_nxt == 8'H10) // Page 2 Note, like the 6809, $10 $10 $10 $10 has the same effect as a single $10.
+ begin
+ if (InstPage3 == 0) // $11 $11 $11 $11 ... $11 $10 still = Page 3
+ InstPage2_nxt = 1;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1V2;
+ end
+ else if (Inst1_nxt == 8'H11) // Page 3
+ begin
+ if (InstPage2 == 0) // $10 $10 ... $10 $11 still = Page 2
+ InstPage3_nxt = 1;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1V2;
+ end
+ else
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I2;
+ end
+ end
+
+
+ CPUSTATE_FETCH_I2: // We've fetched the first byte. If a $10 or $11 (page select), mark those flags and fetch the next byte as instruction byte 1.
+ begin
+ addr_nxt = addr_p1; // Address bus++
+ pc_nxt = pc_p1;
+ Inst2_nxt = D[7:0];
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+
+ if (IsIllegalInstruction) // Skip illegal instructions
+ begin
+
+ rAVMA = 1'b1;
+ CpuState_nxt = IllegalInstructionState;
+ rLIC = 1'b1;
+ end
+ else
+ begin
+ // First byte Decode for this stage
+ case (AddrModeType)
+ TYPE_INDEXED:
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_INDEXED_BASE;
+ end
+
+
+ TYPE_EXTENDED:
+ begin
+ ea_nxt[15:8] = Inst2_nxt;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_EXTENDED_ADDRLO;
+ end
+ TYPE_DIRECT:
+ begin
+ ea_nxt = {dp, Inst2_nxt};
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_DIRECT_DONTCARE;
+ end
+
+ TYPE_INHERENT:
+ begin
+ if (Inst1 == OPCODE_INH_NOP)
+ begin
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ else if (Inst1 == OPCODE_INH_DAA) // Bcd lunacy
+ begin
+ if ( ((cc[CC_C_BIT]) || (a[7:4] > 4'H9)) ||
+ ((a[7:4] > 4'H8) && (a[3:0] > 4'H9)) )
+ tmp_nxt[7:4] = 4'H6;
+ else
+ tmp_nxt[7:4] = 4'H0;
+
+ if ((cc[CC_H_BIT]) || (a[3:0] > 4'H9))
+ tmp_nxt[3:0] = 4'H6;
+ else
+ tmp_nxt[3:0] = 4'H0;
+
+ // DAA handles carry in the weirdest way.
+ // If it's already set, it remains set, even if carry-out is 0.
+ // If it wasn't set, but the output of the operation is set, carry-out gets set.
+ {tmp_nxt[8], a_nxt} = {1'b0, a} + tmp_nxt[7:0];
+
+ cc_nxt[CC_C_BIT] = cc_nxt[CC_C_BIT] | tmp_nxt[8];
+
+ cc_nxt[CC_N_BIT] = a_nxt[7];
+ cc_nxt[CC_Z_BIT] = (a_nxt == 8'H00);
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ else if (Inst1 == OPCODE_INH_SYNC)
+ begin
+ CpuState_nxt = CPUSTATE_SYNC;
+ rLIC = 1'b1;
+ rAVMA = 1'b0;
+ end
+ else if (Inst1 == OPCODE_INH_MUL)
+ begin
+ tmp_nxt = 16'H0000;
+ ea_nxt[15:8] = 8'H00;
+ ea_nxt[7:0] = a;
+ a_nxt = 8;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_MUL_ACTION;
+ end
+ else if (Inst1 == OPCODE_INH_RTS)
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_RTS_HI;
+ end
+ else if (Inst1 == OPCODE_INH_RTI)
+ begin
+ rAVMA = 1'b1;
+ tmp_nxt = 16'H1001; // Set tmp[12] to indicate an RTI being processed, and at least pull CC.
+ CpuState_nxt = CPUSTATE_PUL_ACTION;
+ NextState_nxt = CPUSTATE_FETCH_I1;
+ end
+ else if (Inst1 == OPCODE_INH_SWI)
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_SWI_START;
+ end
+ else if (Inst1 == OPCODE_INH_CWAI)
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_CWAI;
+ end
+ else if (Inst1 == OPCODE_INH_SEX)
+ begin
+ a_nxt = {8{b[7]}};
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ else if (Inst1 == OPCODE_INH_ABX)
+ begin
+ x_nxt = x + b;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_ABX_DONTCARE;
+ end
+ else
+ begin
+ ALU_OP = ALU8Op;
+ if (IsTargetRegA)
+ ALU_A = a;
+ else
+ ALU_A = b;
+
+ ALU_B = 0;
+ ALU_CC = cc;
+ cc_nxt = ALU[15:8];
+
+ if (ALU8Writeback)
+ begin
+ if (IsTargetRegA)
+ a_nxt = ALU[7:0];
+ else
+ b_nxt = ALU[7:0];
+ end
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ if (IsOneByteInstruction(Inst1)) // This check is probably superfluous. Every inherent instruction is 1 byte on the 6809.
+ pc_nxt = pc; // The 6809 auto-reads 2 bytes for every instruction. :( Adjust by not incrementing PC on the 2nd byte read.
+ end
+
+ TYPE_IMMEDIATE:
+ begin
+ if (IsSpecialImmediate)
+ begin
+ if (Inst1 == OPCODE_IMM_ANDCC)
+ begin
+ pc_nxt = pc_p1;
+ cc_nxt = cc & D; //cc_nxt & Inst2_nxt;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_CC_DONTCARE;
+ end
+ else if (Inst1 == OPCODE_IMM_ORCC)
+ begin
+ pc_nxt = pc_p1;
+ cc_nxt = cc | D; //cc_nxt | Inst2_nxt;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_CC_DONTCARE;
+ end
+ else if ( (Inst1 == OPCODE_IMM_PSHS) | (Inst1 == OPCODE_IMM_PSHU) )
+ begin
+ pc_nxt = pc_p1;
+ tmp_nxt[15] = 1'b0;
+ tmp_nxt[14] = Inst1[1]; // Mark whether to save to U or S.
+ tmp_nxt[13] = 1'b0; // Not pushing due to an interrupt.
+ tmp_nxt[13:8] = 6'H00;
+ tmp_nxt[7:0] = Inst2_nxt;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_PSH_DONTCARE1;
+ NextState_nxt = CPUSTATE_FETCH_I1;
+ end
+ else if ( (Inst1 == OPCODE_IMM_PULS) | (Inst1 == OPCODE_IMM_PULU) )
+ begin
+ pc_nxt = pc_p1;
+ tmp_nxt[15] = 1'b0;
+ tmp_nxt[14] = Inst1[1]; // S (0) or U (1) stack in use.
+ tmp_nxt[13:8] = 6'H00;
+ tmp_nxt[7:0] = Inst2_nxt;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_PUL_DONTCARE1;
+ NextState_nxt = CPUSTATE_FETCH_I1;
+ end
+ else if (Inst1 == OPCODE_IMM_TFR)
+ begin
+ // The second byte lists the registers; Top nybble is reg #1, bottom is reg #2.
+
+ case (Inst2_nxt[3:0])
+ EXGTFR_REG_D:
+ {a_nxt,b_nxt} = EXGTFRRegA;
+ EXGTFR_REG_X:
+ x_nxt = EXGTFRRegA;
+ EXGTFR_REG_Y:
+ y_nxt = EXGTFRRegA;
+ EXGTFR_REG_U:
+ u_nxt = EXGTFRRegA;
+ EXGTFR_REG_S:
+ s_nxt = EXGTFRRegA;
+ EXGTFR_REG_PC:
+ pc_nxt = EXGTFRRegA;
+ EXGTFR_REG_DP:
+ dp_nxt = EXGTFRRegA[7:0];
+ EXGTFR_REG_A:
+ a_nxt = EXGTFRRegA[7:0];
+ EXGTFR_REG_B:
+ b_nxt = EXGTFRRegA[7:0];
+ EXGTFR_REG_CC:
+ cc_nxt = EXGTFRRegA[7:0];
+ default:
+ begin
+ end
+ endcase
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_TFR_DONTCARE1;
+
+ end
+ else if (Inst1 == OPCODE_IMM_EXG)
+ begin
+ // The second byte lists the registers; Top nybble is reg #1, bottom is reg #2.
+
+ case (Inst2_nxt[7:4])
+ EXGTFR_REG_D:
+ {a_nxt,b_nxt} = EXGTFRRegB;
+ EXGTFR_REG_X:
+ x_nxt = EXGTFRRegB;
+ EXGTFR_REG_Y:
+ y_nxt = EXGTFRRegB;
+ EXGTFR_REG_U:
+ u_nxt = EXGTFRRegB;
+ EXGTFR_REG_S:
+ s_nxt = EXGTFRRegB;
+ EXGTFR_REG_PC:
+ pc_nxt = EXGTFRRegB;
+ EXGTFR_REG_DP:
+ dp_nxt = EXGTFRRegB[7:0];
+ EXGTFR_REG_A:
+ a_nxt = EXGTFRRegB[7:0];
+ EXGTFR_REG_B:
+ b_nxt = EXGTFRRegB[7:0];
+ EXGTFR_REG_CC:
+ cc_nxt = EXGTFRRegB[7:0];
+ default:
+ begin
+ end
+ endcase
+ case (Inst2_nxt[3:0])
+ EXGTFR_REG_D:
+ {a_nxt,b_nxt} = EXGTFRRegA;
+ EXGTFR_REG_X:
+ x_nxt = EXGTFRRegA;
+ EXGTFR_REG_Y:
+ y_nxt = EXGTFRRegA;
+ EXGTFR_REG_U:
+ u_nxt = EXGTFRRegA;
+ EXGTFR_REG_S:
+ s_nxt = EXGTFRRegA;
+ EXGTFR_REG_PC:
+ pc_nxt = EXGTFRRegA;
+ EXGTFR_REG_DP:
+ dp_nxt = EXGTFRRegA[7:0];
+ EXGTFR_REG_A:
+ a_nxt = EXGTFRRegA[7:0];
+ EXGTFR_REG_B:
+ b_nxt = EXGTFRRegA[7:0];
+ EXGTFR_REG_CC:
+ cc_nxt = EXGTFRRegA[7:0];
+ default:
+ begin
+ end
+ endcase
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_EXG_DONTCARE1;
+ end
+ end
+ // Determine if this is an 8-bit ALU operation.
+ else if (Is8BitInst)
+ begin
+ ALU_OP = ALU8Op;
+ if (IsTargetRegA)
+ ALU_A = a;
+ else
+ ALU_A = b;
+
+ ALU_B = Inst2_nxt;
+ ALU_CC = cc;
+ cc_nxt = ALU[15:8];
+
+ if (ALU8Writeback)
+ begin
+ if (IsTargetRegA)
+ a_nxt = ALU[7:0];
+ else
+ b_nxt = ALU[7:0];
+ end
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ else // Then it must be a 16 bit instruction
+ begin
+ // 83 SUBD
+ // 8C CMPX
+ // 8E LDX
+ // C3 ADDD
+ // CC LDD
+ // CE LDU
+ // 108E CMPD
+ // 108C CMPY
+ // 108E LDY
+ // 10CE LDS
+ // 1183 CMPU
+ // 118C CMPS
+ // Wow, they were just stuffing them in willy-nilly ...
+
+ // LD* 16 bit immediate
+ if (IsALU16Opcode)
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_16IMM_LO;
+ end
+ // there's a dead zone here; I need an else to take us back to CPUSTATE_FETCHI1 if we want to ignore illegal instructions, to CPUSTATE_DEAD if we want to catch them.
+
+ end
+
+ end
+
+ TYPE_RELATIVE:
+ begin
+ // Is this a LB** or a B**?
+ // If InstPage2 is set, it's a long branch; if clear, a normal branch.
+ if ( (InstPage2) || (Inst1 == INST_LBRA) || (Inst1 == INST_LBSR) )
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_LBRA_OFFSETLOW;
+ end
+ else
+ begin
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_BRA_DONTCARE;
+ end
+
+ end
+ default:
+ begin
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ endcase
+ end
+ end
+
+
+ CPUSTATE_LBRA_OFFSETLOW:
+ begin
+ addr_nxt = pc;
+ pc_nxt = pc_p1;
+ Inst3_nxt = D[7:0];
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_LBRA_DONTCARE;
+ end
+
+ CPUSTATE_LBRA_DONTCARE:
+ begin
+ addr_nxt = 16'HFFFF;
+ if ( TakeBranch )
+ begin
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_LBRA_DONTCARE2;
+ end
+ else
+ begin
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ end
+
+ CPUSTATE_BRA_DONTCARE:
+ begin
+ addr_nxt = 16'HFFFF;
+ tmp_nxt = pc;
+ if (TakeBranch)
+ begin
+ pc_nxt = pc + { {8{Inst2[7]}}, Inst2[7:0]}; // Sign-extend the 8 bit offset to 16.
+
+ if (Inst1 == INST_BSR)
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_BSR_DONTCARE1;
+ end
+ else
+ begin
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ end
+ else
+ begin
+ rLIC = 1'b1;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ end
+
+ CPUSTATE_LBRA_DONTCARE2:
+ begin
+ tmp_nxt= pc;
+ addr_nxt = 16'HFFFF;
+
+ // Take branch
+ pc_nxt = pc + {Inst2[7:0], Inst3[7:0]};
+ if (Inst1 == INST_LBSR)
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_BSR_DONTCARE1;
+ end
+ else
+ begin
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ end
+
+ CPUSTATE_BSR_DONTCARE1:
+ begin
+ addr_nxt = pc;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_BSR_DONTCARE2;
+ end
+
+ CPUSTATE_BSR_DONTCARE2:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_BSR_RETURNLOW;
+ end
+
+ CPUSTATE_BSR_RETURNLOW:
+ begin
+ addr_nxt = s_m1;
+ s_nxt = s_m1;
+ DOutput[7:0] = tmp[7:0];
+ RnWOut = 0;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_BSR_RETURNHIGH;
+ end
+
+ CPUSTATE_BSR_RETURNHIGH:
+ begin
+ addr_nxt = s_m1;
+ s_nxt = s_m1;
+ DOutput[7:0] = tmp[15:8];
+ RnWOut = 0;
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1; // after this, RnWOut must go to 1, and the bus needs the PC placed on it.
+ end
+
+ CPUSTATE_TFR_DONTCARE1:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_TFR_DONTCARE2;
+ end
+
+ CPUSTATE_TFR_DONTCARE2:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_TFR_DONTCARE3;
+ end
+
+ CPUSTATE_TFR_DONTCARE3:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_TFR_DONTCARE4;
+ end
+
+ CPUSTATE_TFR_DONTCARE4:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b1;
+ rLIC = 1'b1; // Instruction done!
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ CPUSTATE_EXG_DONTCARE1:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_EXG_DONTCARE2;
+ end
+
+ CPUSTATE_EXG_DONTCARE2:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_EXG_DONTCARE3;
+ end
+
+ CPUSTATE_EXG_DONTCARE3:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_EXG_DONTCARE4;
+ end
+
+ CPUSTATE_EXG_DONTCARE4:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_EXG_DONTCARE5;
+ end
+
+ CPUSTATE_EXG_DONTCARE5:
+ begin
+ rAVMA = 1'b0;
+ addr_nxt = 16'HFFFF;
+ CpuState_nxt = CPUSTATE_EXG_DONTCARE6;
+ end
+
+ CPUSTATE_EXG_DONTCARE6:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b1;
+ rLIC = 1'b1; // Instruction done!
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ CPUSTATE_ABX_DONTCARE:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b1;
+ rLIC = 1'b1; // Instruction done!
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ CPUSTATE_RTS_HI:
+ begin
+ addr_nxt = s;
+ s_nxt = s_p1;
+ pc_nxt[15:8] = D[7:0];
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_RTS_LO;
+ end
+
+ CPUSTATE_RTS_LO:
+ begin
+ addr_nxt = s;
+ s_nxt = s_p1;
+ pc_nxt[7:0] = D[7:0];
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_RTS_DONTCARE2;
+ end
+
+ CPUSTATE_RTS_DONTCARE2:
+ begin
+ addr_nxt = 16'HFFFF;
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ CPUSTATE_16IMM_LO:
+ begin
+ addr_nxt = pc;
+ pc_nxt = pc_p1;
+
+ ALU16_OP = ALU16Opcode;
+ ALU16_CC = cc;
+ ALU16_B = {Inst2, D[7:0]};
+
+ case (ALU16Reg)
+ ALU16_REG_X:
+ ALU16_A = x;
+ ALU16_REG_D:
+ ALU16_A = {a, b};
+ ALU16_REG_Y:
+ ALU16_A = y;
+ ALU16_REG_U:
+ ALU16_A = u;
+ ALU16_REG_S:
+ ALU16_A = s;
+ default:
+ ALU16_A = 16'H0;
+ endcase
+
+ if (ALU16OpWriteback)
+ begin
+ case (ALU16Reg)
+ ALU16_REG_X:
+ {cc_nxt, x_nxt} = ALU16;
+ ALU16_REG_D:
+ {cc_nxt, a_nxt, b_nxt} = ALU16;
+ ALU16_REG_Y:
+ {cc_nxt, y_nxt} = ALU16;
+ ALU16_REG_U:
+ {cc_nxt, u_nxt} = ALU16;
+ ALU16_REG_S:
+ {cc_nxt, s_nxt} = ALU16;
+ default:
+ begin
+ end
+ endcase
+ end
+ else
+ cc_nxt = ALU16[23:16];
+
+ if (ALU16_OP == ALUOP16_LD)
+ begin
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ else
+ begin
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_16IMM_DONTCARE;
+ end
+ end
+
+ CPUSTATE_DIRECT_DONTCARE:
+ begin
+ addr_nxt = 16'HFFFF;
+
+ if (IsJMP(Inst1))
+ begin
+ pc_nxt = ea;
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ else
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_ALU_EA;
+ end
+ end
+
+ CPUSTATE_ALU_EA:
+ begin
+
+ // Is Figure 18/5 Column 2? JMP (not Immediate Mode)
+ // This actually isn't done here. All checks passing in to ALU_EA should check for a JMP; FIXME EVERYWHERE
+
+ // Is Figure 18/5 Column 8? TST (not immediate mode)
+ // THIS IS BURIED IN THE COLUMN 3 section with comparisons to ALUOP_TST.
+
+ // Is Figure 18/5 Column 3?
+ if (IsALU8Set1(Inst1))
+ begin
+ addr_nxt = ea;
+
+ ALU_OP = ALU8Op;
+ ALU_B = D[7:0];
+ ALU_CC = cc;
+
+ if (IsTargetRegA)
+ ALU_A = a;
+ else
+ ALU_A = b;
+
+ cc_nxt = ALU[15:8];
+
+ if ( (ALU8Writeback) )
+ begin
+ if (IsTargetRegA)
+ a_nxt = ALU[7:0];
+ else
+ b_nxt = ALU[7:0];
+ end
+
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ // Is Figure 18/5 Column 4? (Store, 8 bits)
+ else if (IsStore8)
+ begin
+ addr_nxt = ea;
+ RnWOut = 0; // write
+
+ ALU_OP = ALUOP_LD; // load has the same CC characteristics as store
+ ALU_A = 8'H00;
+ ALU_CC = cc;
+
+ case (Store8RegisterNum)
+ ST8_REG_A:
+ begin
+ DOutput = a;
+ ALU_B = a;
+ end
+ ST8_REG_B:
+ begin
+ DOutput = b;
+ ALU_B = b;
+ end
+
+
+ endcase
+
+ cc_nxt = ALU[15:8];
+
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ // Is Figure 18/5 Column 5? (Load, 16 bits)
+ else if (IsALU16Opcode & (ALU16Opcode == ALUOP16_LD))
+ begin
+ addr_nxt = ea;
+ ea_nxt = ea_p1;
+
+ case (ALU16Reg)
+ ALU16_REG_X:
+ x_nxt[15:8] = D[7:0];
+ ALU16_REG_D:
+ a_nxt = D[7:0];
+ ALU16_REG_Y:
+ y_nxt[15:8] = D[7:0];
+ ALU16_REG_S:
+ s_nxt[15:8] = D[7:0];
+ ALU16_REG_U:
+ u_nxt[15:8] = D[7:0];
+ default:
+ begin
+ end
+ endcase
+ rAVMA = 1'b1;
+ rBUSY = 1'b1;
+ CpuState_nxt = CPUSTATE_LD16_LO;
+
+ end
+
+ // Is Figure 18/5 Column 6? (Store, 16 bits)
+ else if (IsStore16)
+ begin
+ addr_nxt = ea;
+ ea_nxt = ea_p1;
+
+ ALU16_OP = ALUOP16_LD; // LD and ST have the same CC characteristics
+ ALU16_CC = cc;
+ ALU16_A = 8'H00;
+
+ case (StoreRegisterNum)
+ ST16_REG_X:
+ begin
+ DOutput[7:0] = x[15:8];
+ ALU16_B = x;
+ end
+ ST16_REG_Y:
+ begin
+ DOutput[7:0] = y[15:8];
+ ALU16_B = y;
+ end
+ ST16_REG_U:
+ begin
+ DOutput[7:0] = u[15:8];
+ ALU16_B = u;
+ end
+ ST16_REG_S:
+ begin
+ DOutput[7:0] = s[15:8];
+ ALU16_B = s;
+ end
+ ST16_REG_D:
+ begin
+ DOutput[7:0] = a[7:0];
+ ALU16_B = {a,b};
+ end
+ default:
+ begin
+ end
+ endcase
+
+ cc_nxt = ALU16[23:16];
+
+ RnWOut = 0; // Write
+ rAVMA = 1'b1;
+ rBUSY = 1'b1;
+ CpuState_nxt = CPUSTATE_ST16_LO;
+ end
+
+ // Is Figure 18/5 Column 7?
+ else if (IsALU8Set0(Inst1))
+ begin
+ // These are registerless instructions, ala
+ // ASL, ASR, CLR, COM, DEC, INC, (LSL), LSR, NEG, ROL, ROR
+ // and TST (special!)
+ // They require READ, Modify (the operation above), WRITE. Between the Read and the Write cycles, there's actually a /VMA
+ // cycle where the 6809 likely did the operation. We'll include a /VMA cycle for accuracy, but we'll do the work primarily in the first cycle.
+ addr_nxt = ea;
+
+ ALU_OP = ALU8Op;
+ ALU_A = D[7:0];
+ ALU_CC = cc;
+ tmp_nxt[15:8] = cc; // for debug only
+ tmp_nxt[7:0] = ALU[7:0];
+ cc_nxt = ALU[15:8];
+ if (ALU8Op == ALUOP_TST)
+ begin
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_TST_DONTCARE1;
+ end
+ else
+ begin
+ rAVMA = 1'b0;
+ rBUSY = 1'b1;
+ CpuState_nxt = CPUSTATE_ALU_DONTCARE;
+ end
+
+ end
+
+ // Is Figure 18/5 Column 8? TST
+ // NOTE:
+ // THIS IS BURIED IN THE COLUMN 3 section with comparisons to ALUOP_TST. [Directly above.]
+
+
+ // Is Figure 18/5 Column 9? (16-bit ALU ops, non-load)
+ else if (IsALU16Opcode && (ALU16Opcode != ALUOP16_LD) && ((Inst1 < 8'H30) || (Inst1 > 8'H33)) ) // 30-33 = LEAX, LEAY, LEAS, LEAU; don't include them here.
+ begin
+ addr_nxt = ea;
+ ea_nxt = ea_p1;
+
+ tmp_nxt[15:8] = D[7:0];
+ rAVMA = 1'b1;
+ rBUSY = 1'b1;
+ CpuState_nxt = CPUSTATE_ALU16_LO;
+
+ end
+
+ // Is Figure 18/5 Column 10? JSR (not Immediate Mode)
+ else if ((Inst1 == 8'H9D) || (Inst1 == 8'HAD) || (Inst1 == 8'HBD)) // JSR
+ begin
+ pc_nxt = ea;
+ addr_nxt = ea;
+ tmp_nxt = pc;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_JSR_DONTCARE;
+ end
+ // Is Figure 18/5 Column 11? LEA(X,Y,S,U)
+ else if ((Inst1 >= 8'H30) && (Inst1<= 8'H33))
+ begin
+ addr_nxt = 16'HFFFF; // Ack, actually a valid cycle, this isn't a dontcare (/VMA) cycle!
+
+ ALU16_OP = ALU16Opcode;
+ ALU16_CC = cc;
+ ALU16_A = ea;
+
+ case (ALU16Reg)
+ ALU16_REG_X:
+ {cc_nxt, x_nxt} = ALU16;
+ ALU16_REG_Y:
+ {cc_nxt, y_nxt} = ALU16;
+ ALU16_REG_U:
+ u_nxt = ALU16[15:0];
+ ALU16_REG_S:
+ s_nxt = ALU16[15:0];
+ default:
+ begin
+ end
+ endcase
+
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+
+ end
+
+ end
+
+
+ CPUSTATE_ALU_DONTCARE:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b1;
+ rBUSY = 1'b1; // We do nothing here, but on the real 6809, they did the modify phase here. :|
+ CpuState_nxt = CPUSTATE_ALU_WRITEBACK;
+ end
+
+ CPUSTATE_ALU_WRITEBACK:
+ begin
+ addr_nxt = ea;
+ RnWOut = 0; // Write
+ DOutput = tmp[7:0];
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ CPUSTATE_LD16_LO:
+ begin
+ addr_nxt = ea;
+
+ case (ALU16Reg)
+ ALU16_REG_X:
+ begin
+ x_nxt[7:0] = D[7:0];
+ ALU16_B[15:8] = x[15:8];
+ end
+ ALU16_REG_D:
+ begin
+ b_nxt = D[7:0];
+ ALU16_B[15:8] = a;
+ end
+ ALU16_REG_Y:
+ begin
+ y_nxt[7:0] = D[7:0];
+ ALU16_B[15:8] = y[15:8];
+ end
+ ALU16_REG_S:
+ begin
+ s_nxt[7:0] = D[7:0];
+ ALU16_B[15:8] = s[15:8];
+ end
+ ALU16_REG_U:
+ begin
+ u_nxt[7:0] = D[7:0];
+ ALU16_B[15:8] = u[15:8];
+ end
+ default:
+ begin
+ end
+
+ endcase
+
+ ALU16_OP = ALU16Opcode;
+ ALU16_CC = cc;
+ ALU16_A = 8'H00;
+ ALU16_B[7:0] = D[7:0];
+ cc_nxt = ALU16[23:16];
+
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ CPUSTATE_ST16_LO:
+ begin
+ addr_nxt = ea;
+ ea_nxt = ea_p1;
+ case (StoreRegisterNum)
+ ST16_REG_X:
+ DOutput[7:0] = x[7:0];
+ ST16_REG_Y:
+ DOutput[7:0] = y[7:0];
+ ST16_REG_U:
+ DOutput[7:0] = u[7:0];
+ ST16_REG_S:
+ DOutput[7:0] = s[7:0];
+ ST16_REG_D:
+ DOutput[7:0] = b[7:0];
+ default:
+ begin
+ end
+ endcase
+ RnWOut = 0; // write
+
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ CPUSTATE_ALU16_LO:
+ begin
+ addr_nxt = ea;
+
+ ALU16_OP = ALU16Opcode;
+ ALU16_CC = cc;
+
+ ALU16_B = {tmp[15:8], D[7:0]};
+
+ case (ALU16Reg)
+ ALU16_REG_X:
+ ALU16_A = x;
+ ALU16_REG_D:
+ ALU16_A = {a, b};
+ ALU16_REG_Y:
+ ALU16_A = y;
+ ALU16_REG_S:
+ ALU16_A = s;
+ ALU16_REG_U:
+ ALU16_A = u;
+ default:
+ ALU16_A = 16'H0;
+
+ endcase
+
+ if (ALU16OpWriteback)
+ begin
+ case (ALU16Reg)
+ ALU16_REG_X:
+ {cc_nxt, x_nxt} = ALU16;
+ ALU16_REG_D:
+ {cc_nxt, a_nxt, b_nxt} = ALU16;
+ ALU16_REG_Y:
+ {cc_nxt, y_nxt} = ALU16;
+ ALU16_REG_U:
+ {cc_nxt, u_nxt} = ALU16;
+ ALU16_REG_S:
+ {cc_nxt, s_nxt} = ALU16;
+ default:
+ begin
+ end
+ endcase
+ end
+ else
+ cc_nxt = ALU16[23:16];
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_ALU16_DONTCARE;
+ end
+
+ CPUSTATE_ALU16_DONTCARE:
+ begin
+ addr_nxt = 16'HFFFF;
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+
+ CPUSTATE_JSR_DONTCARE:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_JSR_RETLO;
+ end
+
+ CPUSTATE_JSR_RETLO:
+ begin
+ addr_nxt = s_m1;
+ s_nxt = s_m1;
+ RnWOut = 0;
+ DOutput = tmp[7:0];
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_JSR_RETHI;
+ end
+
+ CPUSTATE_JSR_RETHI:
+ begin
+ addr_nxt = s_m1;
+ s_nxt = s_m1;
+ RnWOut = 0;
+ DOutput = tmp[15:8];
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ CPUSTATE_EXTENDED_ADDRLO:
+ begin
+ addr_nxt = pc;
+ pc_nxt = pc_p1;
+ ea_nxt[7:0] = D[7:0];
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_EXTENDED_DONTCARE;
+ end
+
+ CPUSTATE_EXTENDED_DONTCARE:
+ begin
+ addr_nxt = 16'HFFFF;
+ if (IsJMP(Inst1))
+ begin
+ pc_nxt = ea;
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ else
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_ALU_EA;
+ end
+ end
+
+ CPUSTATE_INDEXED_BASE:
+ begin
+ addr_nxt = pc;
+
+ Inst3_nxt = D[7:0];
+
+ case (IndexedRegister)
+ IDX_REG_X:
+ ALU16_A = x;
+ IDX_REG_Y:
+ ALU16_A = y;
+ IDX_REG_U:
+ ALU16_A = u;
+ IDX_REG_S:
+ ALU16_A = s;
+ IDX_REG_PC:
+ ALU16_A = pc_p1;
+ default:
+ ALU16_A = 16'H0;
+ endcase
+ ALU16_OP = ALUOP16_ADD;
+
+ case (IndexedMode)
+ IDX_MODE_NOOFFSET:
+ begin
+ case (IndexedRegister)
+ IDX_REG_X:
+ ea_nxt = x;
+ IDX_REG_Y:
+ ea_nxt = y;
+ IDX_REG_U:
+ ea_nxt = u;
+ IDX_REG_S:
+ ea_nxt = s;
+ default:
+ ea_nxt = 16'H0;
+ endcase
+
+ if (IndexedIndirect)
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_INDIRECT_HI;
+ end
+ else
+ begin
+ if (IsJMP(Inst1))
+ begin
+ pc_nxt = ea_nxt;
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ else
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_ALU_EA;
+ end
+ end
+ end
+
+ IDX_MODE_5BIT_OFFSET:
+ begin
+ // The offset is the bottom 5 bits of the Index Postbyte, which is Inst2 here.
+ // We'll sign-extend it to 16 bits.
+ ALU16_B = { {11{Inst2[4]}}, Inst2[4:0] };
+ ea_nxt = ALU16[15:0];
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_IDX_DONTCARE3;
+ end
+
+
+ IDX_MODE_8BIT_OFFSET_PC:
+ begin
+ ALU16_B = { {8{D[7]}}, D[7:0] };
+ pc_nxt = pc_p1;
+ ea_nxt = ALU16[15:0];
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_IDX_DONTCARE3;
+ end
+
+ IDX_MODE_8BIT_OFFSET:
+ begin
+ ALU16_B = { {8{D[7]}}, D[7:0] };
+ pc_nxt = pc_p1;
+ ea_nxt = ALU16[15:0];
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_IDX_DONTCARE3;
+ end
+
+ IDX_MODE_A_OFFSET:
+ begin
+ ALU16_B = { {8{a[7]}}, a[7:0] };
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_IDX_DONTCARE3;
+ ea_nxt = ALU16[15:0];
+ end
+
+ IDX_MODE_B_OFFSET:
+ begin
+ ALU16_B = { {8{b[7]}}, b[7:0] };
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_IDX_DONTCARE3;
+ ea_nxt = ALU16[15:0];
+ end
+
+ IDX_MODE_D_OFFSET:
+ begin
+ ALU16_B = {a, b};
+
+ ea_nxt = ALU16[15:0];
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_IDX_DOFF_DONTCARE1;
+ end
+
+ IDX_MODE_POSTINC1:
+ begin
+ ALU16_B = 16'H1;
+ ea_nxt = ALU16_A;
+ case (IndexedRegister)
+ IDX_REG_X:
+ x_nxt = ALU16[15:0];
+ IDX_REG_Y:
+ y_nxt = ALU16[15:0];
+ IDX_REG_U:
+ u_nxt = ALU16[15:0];
+ IDX_REG_S:
+ s_nxt = ALU16[15:0];
+ default:
+ begin
+ end
+ endcase
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE2;
+ end
+
+ IDX_MODE_POSTINC2:
+ begin
+ ALU16_B = 16'H2;
+ ea_nxt = ALU16_A;
+ case (IndexedRegister)
+ IDX_REG_X:
+ x_nxt = ALU16[15:0];
+ IDX_REG_Y:
+ y_nxt = ALU16[15:0];
+ IDX_REG_U:
+ u_nxt = ALU16[15:0];
+ IDX_REG_S:
+ s_nxt = ALU16[15:0];
+ default:
+ begin
+ end
+ endcase
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE0;
+ end
+
+ IDX_MODE_PREDEC1:
+ begin
+ ALU16_B = 16'HFFFF; // -1
+ case (IndexedRegister)
+ IDX_REG_X:
+ x_nxt = ALU16[15:0];
+ IDX_REG_Y:
+ y_nxt = ALU16[15:0];
+ IDX_REG_U:
+ u_nxt = ALU16[15:0];
+ IDX_REG_S:
+ s_nxt = ALU16[15:0];
+ default:
+ begin
+ end
+ endcase
+ ea_nxt = ALU16[15:0];
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE2;
+ end
+
+ IDX_MODE_PREDEC2:
+ begin
+ ALU16_B = 16'HFFFE; // -2
+ case (IndexedRegister)
+ IDX_REG_X:
+ x_nxt = ALU16[15:0];
+ IDX_REG_Y:
+ y_nxt = ALU16[15:0];
+ IDX_REG_U:
+ u_nxt = ALU16[15:0];
+ IDX_REG_S:
+ s_nxt = ALU16[15:0];
+ default:
+ begin
+ end
+ endcase
+ ea_nxt = ALU16[15:0];
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE0;
+ end
+
+ IDX_MODE_16BIT_OFFSET_PC:
+ begin
+ tmp_nxt[15:8] = D[7:0];
+ pc_nxt = pc_p1;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_IDX_16OFFSET_LO;
+ end
+
+ IDX_MODE_16BIT_OFFSET:
+ begin
+ tmp_nxt[15:8] = D[7:0];
+ pc_nxt = pc_p1;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_IDX_16OFFSET_LO;
+ end
+
+ IDX_MODE_EXTENDED_INDIRECT:
+ begin
+ ea_nxt[15:8] = D[7:0];
+ pc_nxt = pc_p1;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_IDX_EXTIND_LO;
+ end
+
+ default:
+ begin
+ rLIC = 1'b1;
+ CpuState_nxt = PostIllegalState;
+ end
+
+ endcase
+ end
+
+ CPUSTATE_IDX_OFFSET_LO:
+ begin
+ tmp_nxt[7:0] = D[7:0];
+ addr_nxt = pc;
+ pc_nxt = pc_p1;
+ ALU16_B = tmp_nxt;
+
+ case (IndexedRegister)
+ IDX_REG_X:
+ ALU16_A = x;
+ IDX_REG_Y:
+ ALU16_A = y;
+ IDX_REG_U:
+ ALU16_A = u;
+ IDX_REG_S:
+ ALU16_A = s;
+ IDX_REG_PC:
+ ALU16_A = pc;
+ default:
+ ALU16_A = 16'H0;
+ endcase
+ ALU16_OP = ALUOP16_ADD;
+
+ ea_nxt = ALU16[15:0];
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE1;
+ end
+
+
+ CPUSTATE_IDX_DONTCARE3:
+ begin
+ addr_nxt = 16'HFFFF;
+ if (IndexedIndirect)
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_INDIRECT_HI;
+ end
+ else
+ begin
+ if (IsJMP(Inst1))
+ begin
+ pc_nxt = ea;
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ else
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_ALU_EA;
+ end
+ end
+
+ end
+
+ CPUSTATE_IDX_16OFFSET_LO:
+ begin
+ addr_nxt = pc;
+ pc_nxt = pc_p1;
+
+ case (IndexedRegister)
+ IDX_REG_X:
+ ALU16_A = x;
+ IDX_REG_Y:
+ ALU16_A = y;
+ IDX_REG_U:
+ ALU16_A = u;
+ IDX_REG_S:
+ ALU16_A = s;
+ IDX_REG_PC:
+ ALU16_A = pc_nxt; // Whups; tricky; not part of the actual pattern
+ default:
+ ALU16_A = x; // Default to something
+ endcase
+
+ ALU16_OP = ALUOP16_ADD;
+
+ ALU16_B = {tmp[15:8], D[7:0]};
+
+ ea_nxt = ALU16[15:0];
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE1;
+ end
+
+ CPUSTATE_IDX_16OFF_DONTCARE1:
+ begin
+ addr_nxt = pc;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE2;
+ end
+
+ CPUSTATE_IDX_16OFF_DONTCARE0:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE2;
+ end
+
+ CPUSTATE_IDX_16OFF_DONTCARE2:
+ begin
+ addr_nxt = 16'HFFFF;
+ if (IndexedRegister == IDX_REG_PC)
+ begin
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_IDX_PC16OFF_DONTCARE;
+ end
+ else
+ begin
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE3;
+ end
+ end
+
+ CPUSTATE_IDX_PC16OFF_DONTCARE:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE3;
+ end
+
+
+ CPUSTATE_IDX_16OFF_DONTCARE3:
+ begin
+ addr_nxt = 16'HFFFF;
+ if (IndexedIndirect)
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_INDIRECT_HI;
+ end
+ else
+ begin
+ if (IsJMP(Inst1))
+ begin
+ pc_nxt = ea;
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ else
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_ALU_EA;
+ end
+ end
+ end
+
+ CPUSTATE_IDX_DOFF_DONTCARE1:
+ begin
+ addr_nxt = pc_p1;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_IDX_DOFF_DONTCARE2;
+ end
+
+ CPUSTATE_IDX_DOFF_DONTCARE2:
+ begin
+ addr_nxt = pc_p2;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_IDX_16OFF_DONTCARE2;
+ end
+
+ CPUSTATE_IDX_DOFF_DONTCARE3:
+ begin
+ addr_nxt = pc_p3;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_IDX_DOFF_DONTCARE2;
+ end
+
+ CPUSTATE_IDX_EXTIND_LO:
+ begin
+ ea_nxt[7:0] = D[7:0];
+ addr_nxt = pc;
+ pc_nxt = pc_p1;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_IDX_EXTIND_DONTCARE;
+ end
+
+ CPUSTATE_IDX_EXTIND_DONTCARE:
+ begin
+ addr_nxt = pc;
+ if (IndexedIndirect)
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_INDIRECT_HI;
+ end
+ else
+ begin
+ if (IsJMP(Inst1))
+ begin
+ pc_nxt = ea;
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ else
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_ALU_EA;
+ end
+ end
+ end
+
+ CPUSTATE_INDIRECT_HI:
+ begin
+ addr_nxt = ea;
+ tmp_nxt[15:8] = D[7:0];
+ rAVMA = 1'b1;
+ rBUSY = 1'b1;
+ CpuState_nxt = CPUSTATE_INDIRECT_LO;
+ end
+
+ CPUSTATE_INDIRECT_LO:
+ begin
+ addr_nxt = ea_p1;
+ ea_nxt[15:8] = tmp_nxt[15:8];
+ ea_nxt[7:0] = D[7:0];
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_INDIRECT_DONTCARE;
+ end
+
+ CPUSTATE_INDIRECT_DONTCARE:
+ begin
+ addr_nxt = 16'HFFFF;
+ if (IsJMP(Inst1))
+ begin
+ pc_nxt = ea;
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ else
+ begin
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_ALU_EA;
+ end
+ end
+
+ CPUSTATE_MUL_ACTION:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b0;
+ // tmp = result
+ // ea = additor (the shifted multiplicand)
+ // a = counter
+ // b is the multiplier (which gets shifted right)
+ if (a != 8'H00)
+ begin
+ if (b[0])
+ begin
+ tmp_nxt = tmp + ea;
+ end
+ ea_nxt = {ea[14:0], 1'b0};
+ b_nxt = {1'b0, b[7:1]};
+ a_nxt = a - 8'H1;
+ end
+ else
+ begin
+ {a_nxt, b_nxt} = tmp;
+
+ cc_nxt[CC_Z_BIT] = (tmp == 0);
+ cc_nxt[CC_C_BIT] = tmp[7];
+ rLIC = 1'b1; // Instruction done!
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+ end
+
+ CPUSTATE_PSH_DONTCARE1:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_PSH_DONTCARE2;
+ end
+
+ CPUSTATE_PSH_DONTCARE2:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_PSH_DONTCARE3;
+ end
+
+ CPUSTATE_PSH_DONTCARE3:
+ begin
+ addr_nxt = (Inst1[1]) ? u : s;
+
+ CpuState_nxt = CPUSTATE_PSH_ACTION;
+ end
+
+ CPUSTATE_PSH_ACTION:
+ begin
+ rAVMA = 1'b1;
+ if (tmp[7] & ~(tmp[15])) // PC_LO
+ begin
+ addr_nxt = (tmp[14]) ? u_m1 : s_m1;
+ if (tmp[14])
+ u_nxt = u_m1;
+ else
+ s_nxt = s_m1;
+ DOutput = pc[7:0];
+ RnWOut = 1'b0; // write
+ tmp_nxt[15] = 1'b1;
+ end
+ else if (tmp[7] & (tmp[15])) // PC_HI
+ begin
+ addr_nxt = (tmp[14]) ? u_m1 : s_m1;
+ if (tmp[14])
+ u_nxt = u_m1;
+ else
+ s_nxt = s_m1;
+ DOutput = pc[15:8];
+ RnWOut = 1'b0; // write
+ tmp_nxt[7] = 1'b0;
+ tmp_nxt[15] = 1'b0;
+ end
+ else if (tmp[6] & ~(tmp[15])) // U/S_LO
+ begin
+ addr_nxt = (tmp[14]) ? u_m1 : s_m1;
+ if (tmp[14])
+ u_nxt = u_m1;
+ else
+ s_nxt = s_m1;
+ DOutput = (tmp[14]) ? s[7:0] : u[7:0];
+ RnWOut = 1'b0; // write
+ tmp_nxt[15] = 1'b1;
+ end
+ else if (tmp[6] & (tmp[15])) // U/S_HI
+ begin
+ addr_nxt = (tmp[14]) ? u_m1 : s_m1;
+ if (tmp[14])
+ u_nxt = u_m1;
+ else
+ s_nxt = s_m1;
+ DOutput = (tmp[14]) ? s[15:8] : u[15:8];
+ RnWOut = 1'b0; // write
+ tmp_nxt[6] = 1'b0;
+ tmp_nxt[15] = 1'b0;
+ end
+ else if (tmp[5] & ~(tmp[15])) // Y_LO
+ begin
+ addr_nxt = (tmp[14]) ? u_m1 : s_m1;
+ if (tmp[14])
+ u_nxt = u_m1;
+ else
+ s_nxt = s_m1;
+ DOutput = y[7:0];
+ RnWOut = 1'b0; // write
+ tmp_nxt[15] = 1'b1;
+ end
+ else if (tmp[5] & (tmp[15])) // Y_HI
+ begin
+ addr_nxt = (tmp[14]) ? u_m1 : s_m1;
+ if (tmp[14])
+ u_nxt = u_m1;
+ else
+ s_nxt = s_m1;
+ DOutput = y[15:8];
+ RnWOut = 1'b0; // write
+ tmp_nxt[5] = 1'b0;
+ tmp_nxt[15] = 1'b0;
+ end
+ else if (tmp[4] & ~(tmp[15])) // X_LO
+ begin
+ addr_nxt = (tmp[14]) ? u_m1 : s_m1;
+ if (tmp[14])
+ u_nxt = u_m1;
+ else
+ s_nxt = s_m1;
+ DOutput = x[7:0];
+ RnWOut = 1'b0; // write
+ tmp_nxt[15] = 1'b1;
+ end
+ else if (tmp[4] & (tmp[15])) // X_HI
+ begin
+ addr_nxt = (tmp[14]) ? u_m1 : s_m1;
+ if (tmp[14])
+ u_nxt = u_m1;
+ else
+ s_nxt = s_m1;
+ DOutput = x[15:8];
+ RnWOut = 1'b0; // write
+ tmp_nxt[4] = 1'b0;
+ tmp_nxt[15] = 1'b0;
+ end
+ else if (tmp[3]) // DP
+ begin
+ addr_nxt = (tmp[14]) ? u_m1 : s_m1;
+ if (tmp[14])
+ u_nxt = u_m1;
+ else
+ s_nxt = s_m1;
+ DOutput = dp;
+ RnWOut = 1'b0; // write
+ tmp_nxt[3] = 1'b0;
+ end
+ else if (tmp[2]) // B
+ begin
+ addr_nxt = (tmp[14]) ? u_m1 : s_m1;
+ if (tmp[14])
+ u_nxt = u_m1;
+ else
+ s_nxt = s_m1;
+ DOutput = b;
+ RnWOut = 1'b0; // write
+ tmp_nxt[2] = 1'b0;
+ end
+ else if (tmp[1]) // A
+ begin
+ addr_nxt = (tmp[14]) ? u_m1 : s_m1;
+ if (tmp[14])
+ u_nxt = u_m1;
+ else
+ s_nxt = s_m1;
+ DOutput = a;
+ RnWOut = 1'b0; // write
+ tmp_nxt[1] = 1'b0;
+ end
+ else if (tmp[0]) // CC
+ begin
+ addr_nxt = (tmp[14]) ? u_m1 : s_m1;
+ if (tmp[14])
+ u_nxt = u_m1;
+ else
+ s_nxt = s_m1;
+ DOutput = cc;
+ RnWOut = 1'b0; // write
+ tmp_nxt[0] = 1'b0;
+ end
+ if (tmp[13]) // Then we're pushing for an IRQ, and LIC is supposed to be set.
+ rLIC = 1'b1;
+ if (tmp_nxt[7:0] == 8'H00)
+ begin
+ if (NextState == CPUSTATE_FETCH_I1)
+ begin
+ rAVMA = 1'b1;
+ rLIC = 1'b1;
+ end
+ else
+ rAVMA = 1'b0;
+ CpuState_nxt = NextState;
+ end
+ end
+
+ CPUSTATE_PUL_DONTCARE1:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_PUL_DONTCARE2;
+ end
+
+ CPUSTATE_PUL_DONTCARE2:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_PUL_ACTION;
+ end
+
+ CPUSTATE_PUL_ACTION:
+ begin
+ rAVMA = 1'b1;
+ if (tmp[0]) // CC
+ begin
+ addr_nxt = (tmp[14]) ? u : s;
+ if (tmp[14])
+ u_nxt = u_p1;
+ else
+ s_nxt = s_p1;
+ cc_nxt = D[7:0];
+ if (tmp[12] == 1'b1) // This pull is from an RTI, the E flag comes from the retrieved CC, and set the tmp_nxt accordingly, indicating what other registers to retrieve
+ begin
+ if (D[CC_E_BIT])
+ tmp_nxt[7:0] = 8'HFE; // Retrieve all registers (ENTIRE) [CC is already retrieved]
+ else
+ tmp_nxt[7:0] = 8'H80; // Retrieve PC and CC [CC is already retrieved]
+ end
+ else
+ tmp_nxt[0] = 1'b0;
+ end
+ else if (tmp[1]) // A
+ begin
+ addr_nxt = (tmp[14]) ? u : s;
+ if (tmp[14])
+ u_nxt = u_p1;
+ else
+ s_nxt = s_p1;
+ a_nxt = D[7:0];
+ tmp_nxt[1] = 1'b0;
+ end
+ else if (tmp[2]) // B
+ begin
+ addr_nxt = (tmp[14]) ? u : s;
+ if (tmp[14])
+ u_nxt = u_p1;
+ else
+ s_nxt = s_p1;
+ b_nxt = D[7:0];
+ tmp_nxt[2] = 1'b0;
+ end
+ else if (tmp[3]) // DP
+ begin
+ addr_nxt = (tmp[14]) ? u : s;
+ if (tmp[14])
+ u_nxt = u_p1;
+ else
+ s_nxt = s_p1;
+ dp_nxt = D[7:0];
+ tmp_nxt[3] = 1'b0;
+ end
+ else if (tmp[4] & (~tmp[15])) // X_HI
+ begin
+ addr_nxt = (tmp[14]) ? u : s;
+ if (tmp[14])
+ u_nxt = u_p1;
+ else
+ s_nxt = s_p1;
+ x_nxt[15:8] = D[7:0];
+ tmp_nxt[15] = 1'b1;
+ end
+ else if (tmp[4] & tmp[15]) // X_LO
+ begin
+ addr_nxt = (tmp[14]) ? u : s;
+ if (tmp[14])
+ u_nxt = u_p1;
+ else
+ s_nxt = s_p1;
+ x_nxt[7:0] = D[7:0];
+ tmp_nxt[4] = 1'b0;
+ tmp_nxt[15] = 1'b0;
+ end
+ else if (tmp[5] & (~tmp[15])) // Y_HI
+ begin
+ addr_nxt = (tmp[14]) ? u : s;
+ if (tmp[14])
+ u_nxt = u_p1;
+ else
+ s_nxt = s_p1;
+ y_nxt[15:8] = D[7:0];
+ tmp_nxt[15] = 1'b1;
+ end
+ else if (tmp[5] & tmp[15]) // Y_LO
+ begin
+ addr_nxt = (tmp[14]) ? u : s;
+ if (tmp[14])
+ u_nxt = u_p1;
+ else
+ s_nxt = s_p1;
+ y_nxt[7:0] = D[7:0];
+ tmp_nxt[5] = 1'b0;
+ tmp_nxt[15] = 1'b0;
+ end
+ else if (tmp[6] & (~tmp[15])) // U/S_HI
+ begin
+ addr_nxt = (tmp[14]) ? u : s;
+ if (tmp[14])
+ u_nxt = u_p1;
+ else
+ s_nxt = s_p1;
+ if (tmp[14])
+ s_nxt[15:8] = D[7:0];
+ else
+ u_nxt[15:8] = D[7:0];
+ tmp_nxt[15] = 1'b1;
+ end
+ else if (tmp[6] & tmp[15]) // U/S_LO
+ begin
+ addr_nxt = (tmp[14]) ? u : s;
+ if (tmp[14])
+ u_nxt = u_p1;
+ else
+ s_nxt = s_p1;
+ if (tmp[14])
+ s_nxt[7:0] = D[7:0];
+ else
+ u_nxt[7:0] = D[7:0];
+ tmp_nxt[6] = 1'b0;
+ tmp_nxt[15] = 1'b0;
+ end
+ else if (tmp[7] & (~tmp[15])) // PC_HI
+ begin
+ addr_nxt = (tmp[14]) ? u : s;
+ if (tmp[14])
+ u_nxt = u_p1;
+ else
+ s_nxt = s_p1;
+ pc_nxt[15:8] = D[7:0];
+ tmp_nxt[15] = 1'b1;
+ end
+ else if (tmp[7] & tmp[15]) // PC_LO
+ begin
+ addr_nxt = (tmp[14]) ? u : s;
+ if (tmp[14])
+ u_nxt = u_p1;
+ else
+ s_nxt = s_p1;
+ pc_nxt[7:0] = D[7:0];
+ tmp_nxt[7] = 1'b0;
+ tmp_nxt[15] = 1'b0;
+ end
+ else
+ begin
+ addr_nxt = (tmp[14]) ? u : s;
+ if (NextState == CPUSTATE_FETCH_I1)
+ begin
+ rAVMA = 1'b1;
+ rLIC = 1'b1;
+ end
+ else
+ rAVMA = 1'b0;
+ CpuState_nxt = NextState;
+ end
+ end
+
+ CPUSTATE_NMI_START:
+ begin
+ NMIClear_nxt = 1'b1;
+ addr_nxt = pc;
+ // tmp stands as the bits to push to the stack
+ tmp_nxt = 16'H20FF; // Save to the S stack, PC, U, Y, X, DP, B, A, CC; set LIC on every push
+ NextState_nxt = CPUSTATE_IRQ_DONTCARE2;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_IRQ_DONTCARE;
+ IntType_nxt = INTTYPE_NMI;
+ cc_nxt[CC_E_BIT] = 1'b1;
+ end
+
+ CPUSTATE_IRQ_START:
+ begin
+ addr_nxt = pc;
+ tmp_nxt = 16'H20FF; // Save to the S stack, PC, U, Y, X, DP, B, A, CC; set LIC on every push
+ NextState_nxt = CPUSTATE_IRQ_DONTCARE2;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_IRQ_DONTCARE;
+ IntType_nxt = INTTYPE_IRQ;
+ cc_nxt[CC_E_BIT] = 1'b1;
+ end
+
+ CPUSTATE_FIRQ_START:
+ begin
+ addr_nxt = pc;
+ tmp_nxt = 16'H2081; // Save to the S stack, PC, CC; set LIC on every push
+ NextState_nxt = CPUSTATE_IRQ_DONTCARE2;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_IRQ_DONTCARE;
+ IntType_nxt = INTTYPE_FIRQ;
+ cc_nxt[CC_E_BIT] = 1'b0;
+ end
+
+ CPUSTATE_SWI_START:
+ begin
+ addr_nxt = pc;
+ tmp_nxt = 16'H00FF; // Save to the S stack, PC, U, Y, X, DP, B, A, CC
+
+ NextState_nxt = CPUSTATE_IRQ_DONTCARE2;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_IRQ_DONTCARE;
+ if (InstPage3)
+ IntType_nxt = INTTYPE_SWI3;
+ if (InstPage2)
+ IntType_nxt = INTTYPE_SWI2;
+ else
+ IntType_nxt = INTTYPE_SWI;
+
+ cc_nxt[CC_E_BIT] = 1'b1;
+ end
+
+ CPUSTATE_IRQ_DONTCARE:
+ begin
+ NMIClear_nxt = 1'b0;
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_PSH_ACTION;
+ end
+
+
+ CPUSTATE_IRQ_DONTCARE2:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_IRQ_VECTOR_HI;
+ rLIC = 1'b1;
+ end
+
+ CPUSTATE_IRQ_VECTOR_HI:
+ begin
+ case (IntType)
+ INTTYPE_NMI:
+ begin
+ addr_nxt = `NMI_VECTOR;
+ BS_nxt = 1'b1; // ACK Interrupt
+ end
+ INTTYPE_IRQ:
+ begin
+ addr_nxt = `IRQ_VECTOR;
+ BS_nxt = 1'b1; // ACK Interrupt
+ end
+ INTTYPE_SWI:
+ begin
+ addr_nxt = `SWI_VECTOR;
+ end
+ INTTYPE_FIRQ:
+ begin
+ addr_nxt = `FIRQ_VECTOR;
+ BS_nxt = 1'b1; // ACK Interrupt
+ end
+ INTTYPE_SWI2:
+ begin
+ addr_nxt = `SWI2_VECTOR;
+ end
+ INTTYPE_SWI3:
+ begin
+ addr_nxt = `SWI3_VECTOR;
+ end
+ default: // make the default an IRQ, even though it really should never happen
+ begin
+ addr_nxt = `IRQ_VECTOR;
+ BS_nxt = 1'b1; // ACK Interrupt
+ end
+ endcase
+
+ pc_nxt[15:8] = D[7:0];
+ rAVMA = 1'b1;
+ rBUSY = 1'b1;
+ rLIC = 1'b1;
+ CpuState_nxt = CPUSTATE_IRQ_VECTOR_LO;
+
+
+ end
+
+ CPUSTATE_IRQ_VECTOR_LO:
+ begin
+ case (IntType)
+ INTTYPE_NMI:
+ begin
+ addr_nxt = `NMI_VECTOR+16'H1;
+ cc_nxt[CC_I_BIT] = 1'b1;
+ cc_nxt[CC_F_BIT] = 1'b1;
+ BS_nxt = 1'b1; // ACK Interrupt
+ end
+ INTTYPE_IRQ:
+ begin
+ addr_nxt = `IRQ_VECTOR+16'H1;
+ cc_nxt[CC_I_BIT] = 1'b1;
+ BS_nxt = 1'b1; // ACK Interrupt
+ end
+ INTTYPE_SWI:
+ begin
+ addr_nxt = `SWI_VECTOR+16'H1;
+ cc_nxt[CC_F_BIT] = 1'b1;
+ cc_nxt[CC_I_BIT] = 1'b1;
+ rLIC = 1'b1;
+ end
+ INTTYPE_FIRQ:
+ begin
+ addr_nxt = `FIRQ_VECTOR+16'H1;
+ cc_nxt[CC_F_BIT] = 1'b1;
+ cc_nxt[CC_I_BIT] = 1'b1;
+ BS_nxt = 1'b1; // ACK Interrupt
+ end
+ INTTYPE_SWI2:
+ begin
+ addr_nxt = `SWI2_VECTOR+16'H1;
+ rLIC = 1'b1;
+ end
+ INTTYPE_SWI3:
+ begin
+ addr_nxt = `SWI3_VECTOR+16'H1;
+ rLIC = 1'b1;
+ end
+ default:
+ begin
+ end
+ endcase
+
+ pc_nxt[7:0] = D[7:0];
+ rAVMA = 1'b1;
+ rLIC = 1'b1;
+ CpuState_nxt = CPUSTATE_INT_DONTCARE;
+ end
+
+ CPUSTATE_INT_DONTCARE:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b1;
+ rLIC = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ CPUSTATE_CC_DONTCARE:
+ begin
+ addr_nxt = pc;
+ rLIC = 1'b1;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ CPUSTATE_TST_DONTCARE1:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_TST_DONTCARE2;
+ end
+
+ CPUSTATE_TST_DONTCARE2:
+ begin
+ addr_nxt = 16'HFFFF;
+ rLIC = 1'b1;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ CPUSTATE_DEBUG:
+ begin
+ addr_nxt = tmp;
+ rLIC = 1'b1;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ CPUSTATE_16IMM_DONTCARE:
+ begin
+ addr_nxt = 16'HFFFF;
+ rLIC = 1'b1;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ CPUSTATE_SYNC:
+ begin
+ addr_nxt = 16'HFFFF;
+ BA_nxt = 1'b1;
+ rLIC = 1'b1;
+ rAVMA = 1'b0;
+
+ if (~(NMILatched & FIRQLatched & IRQLatched))
+ begin
+ CpuState_nxt = CPUSTATE_SYNC_EXIT;
+ end
+ end
+
+ CPUSTATE_SYNC_EXIT:
+ begin
+ addr_nxt = 16'HFFFF;
+ BA_nxt = 1'b1;
+ rLIC = 1'b1;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+
+ CPUSTATE_DMABREQ:
+ begin
+ rAVMA = 1'b0;
+ addr_nxt = 16'HFFFF;
+ BS_nxt = 1'b1;
+ BA_nxt = 1'b1;
+ rLIC = 1'b1;
+ tmp_nxt[3:0] = tmp[3:0] - 1'b1;
+ if ( (tmp[3:0] == 4'H0) | (DMABREQSample2) )
+ begin
+ CpuState_nxt = CPUSTATE_DMABREQ_EXIT;
+ end
+ end
+
+ CPUSTATE_DMABREQ_EXIT:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ CPUSTATE_HALTED:
+ begin
+ rAVMA = 1'b0;
+ addr_nxt = 16'HFFFF;
+ BS_nxt = 1'b1;
+ BA_nxt = 1'b1;
+ rLIC = 1'b1;
+ if (HALTSample2)
+ begin
+ CpuState_nxt = CPUSTATE_HALT_EXIT2;
+ end
+ end
+
+
+ CPUSTATE_HALT_EXIT2:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_FETCH_I1;
+ end
+
+ CPUSTATE_STOP:
+ begin
+ addr_nxt = 16'HDEAD;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_STOP2;
+ end
+
+ CPUSTATE_STOP2:
+ begin
+ addr_nxt = pc;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_STOP3;
+ end
+
+ CPUSTATE_STOP3:
+ begin
+ addr_nxt = 16'H0000; //{Inst1, Inst2};
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_STOP;
+ end
+
+ // The otherwise critically useful Figure 18 in the 6809 datasheet contains an error;
+ // it lists that CWAI has a tri-stated bus while it waits for an interrupt.
+ // That is not true. SYNC tristates the bus, as do things like /HALT and /DMABREQ.
+ // CWAI does not. It waits with /VMA cycles on the bus until an interrupt occurs.
+ // The implementation here fits with the 6809 Programming Manual and other Motorola
+ // sources, not with that typo in Figure 18.
+ CPUSTATE_CWAI:
+ begin
+ addr_nxt = pc;
+ cc_nxt = {1'b1, (cc[6:0] & Inst2[6:0])}; // Set E flag, AND CC with CWAI argument
+ tmp_nxt = 16'H00FF; // Save to the S stack, PC, U, Y, X, DP, B, A, CC
+
+ NextState_nxt = CPUSTATE_CWAI_POST;
+ rAVMA = 1'b0;
+ CpuState_nxt = CPUSTATE_CWAI_DONTCARE1;
+ end
+
+ CPUSTATE_CWAI_DONTCARE1:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b1;
+ CpuState_nxt = CPUSTATE_PSH_ACTION;
+ end
+
+ CPUSTATE_CWAI_POST:
+ begin
+ addr_nxt = 16'HFFFF;
+ rAVMA = 1'b0;
+
+ CpuState_nxt = CPUSTATE_CWAI_POST;
+
+ // Wait for an interrupt
+ if (NMILatched == 0)
+ begin
+ rAVMA = 1'b1;
+ IntType_nxt = INTTYPE_NMI;
+ cc_nxt[CC_F_BIT] = 1'b1;
+ cc_nxt[CC_I_BIT] = 1'b1;
+ CpuState_nxt = CPUSTATE_IRQ_VECTOR_HI;
+ end
+ else if ((FIRQLatched == 0) && (cc[CC_F_BIT] == 0))
+ begin
+ rAVMA = 1'b1;
+ cc_nxt[CC_F_BIT] = 1'b1;
+ cc_nxt[CC_I_BIT] = 1'b1;
+ IntType_nxt = INTTYPE_FIRQ;
+ CpuState_nxt = CPUSTATE_IRQ_VECTOR_HI;
+ end
+ else if ((IRQLatched == 0) && (cc[CC_I_BIT] == 0))
+ begin
+ rAVMA = 1'b1;
+ cc_nxt[CC_I_BIT] = 1'b1;
+ IntType_nxt = INTTYPE_IRQ;
+ CpuState_nxt = CPUSTATE_IRQ_VECTOR_HI;
+ end
+ end
+
+ default: // Picky darned Verilog.
+ begin
+ CpuState_nxt = PostIllegalState;
+ end
+
+ endcase
+end
+
+endmodule
+
diff --git a/common/CPU/NextZ80/NextZ80ALU.v b/common/CPU/NextZ80/NextZ80ALU.v
new file mode 100644
index 00000000..610781a2
--- /dev/null
+++ b/common/CPU/NextZ80/NextZ80ALU.v
@@ -0,0 +1,372 @@
+//////////////////////////////////////////////////////////////////////////////////
+//
+// This file is part of the NextZ80 project
+// http://www.opencores.org/cores/nextz80/
+//
+// Filename: NextZ80ALU.v
+// Description: Implementation of Z80 compatible CPU - ALU
+// Version 1.0
+// Creation date: 28Jan2011 - 18Mar2011
+//
+// Author: Nicolae Dumitrache
+// e-mail: ndumitrache@opencores.org
+//
+/////////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2011 Nicolae Dumitrache
+//
+// This source file may be used and distributed without
+// restriction provided that this copyright statement is not
+// removed from the file and that any derivative work contains
+// the original copyright notice and the associated disclaimer.
+//
+// This source file is free software; you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation;
+// either version 2.1 of the License, or (at your option) any
+// later version.
+//
+// This source 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 Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General
+// Public License along with this source; if not, download it
+// from http://www.opencores.org/lgpl.shtml
+//
+///////////////////////////////////////////////////////////////////////////////////
+
+//FLAGS: S Z X1 N X2 PV N C
+// OP[4:0]
+// 00000 - ADD D0,D1
+// 00001 - ADC D0,D1
+// 00010 - SUB D0,D1
+// 00011 - SBC D0,D1
+// 00100 - AND D0,D1
+// 00101 - XOR D0,D1
+// 00110 - OR D0,D1
+// 00111 - CP D0,D1
+// 01000 - INC D0
+// 01001 - CPL D0
+// 01010 - DEC D0
+// 01011 - RRD
+// 01100 - RLD
+// 01101 - DAA
+// 01110 - INC16
+// 01111 - DEC16
+// 10000 - ADD16LO
+// 10001 - ADD16HI
+// 10010 -
+// 10011 -
+// 10100 - CCF, pass D0
+// 10101 - SCF, pass D0
+// 10110 -
+// 10111 -
+// 11000 - RLCA D0
+// 11001 - RRCA D0
+// 11010 - RLA D0
+// 11011 - RRA D0
+// 11100 - {ROT, BIT, SET, RES} D0,EXOP
+// RLC D0 C <-- D0 <-- D0[7]
+// RRC D0 D0[0] --> D0 --> C
+// RL D0 C <-- D0 <-- C
+// RR D0 C --> D0 --> C
+// SLA D0 C <-- D0 <-- 0
+// SRA D0 D0[7] --> D0 --> C
+// SLL D0 C <-- D0 <-- 1
+// SRL D0 0 --> D0 --> C
+// 11101 - IN, pass D1
+// 11110 - FLAGS <- D0
+// 11111 - NEG D1
+///////////////////////////////////////////////////////////////////////////////////
+`timescale 1ns / 1ps
+
+module ALU8(
+ input [7:0] D0,
+ input [7:0] D1,
+ input [7:0] FIN,
+ output reg[7:0] FOUT,
+ output reg [15:0] ALU8DOUT,
+ input [4:0] OP,
+ input [5:0] EXOP, // EXOP[5:4] = 2'b11 for CPI/D/R
+ input LDIFLAGS, // zero HF and NF on inc/dec16
+ input DSTHI // destination lo
+ );
+
+ wire [7:0] daaadjust;
+ wire cdaa, hdaa;
+ daa daa_adjust(.flags(FIN), .val(D0), .adjust(daaadjust), .cdaa(cdaa), .hdaa(hdaa));
+
+ wire parity = ~^ALU8DOUT[15:8];
+ wire zero = ALU8DOUT[15:8] == 0;
+ reg csin, cin;
+ wire [7:0]d0mux = OP[4:1] == 4'b1111 ? 0 : D0;
+ reg [7:0]_d1mux;
+ wire [7:0]d1mux = OP[1] ? ~_d1mux : _d1mux;
+ wire [8:0]sum;
+ wire hf;
+ assign {hf, sum[3:0]} = d0mux[3:0] + d1mux[3:0] + cin;
+ assign sum[8:4] = d0mux[7:4] + d1mux[7:4] + hf;
+ wire overflow = (d0mux[7] & d1mux[7] & !sum[7]) | (!d0mux[7] & !d1mux[7] & sum[7]);
+ reg [7:0]dbit;
+
+ always @* begin
+ ALU8DOUT = 16'hxxxx;
+ FOUT = 8'hxx;
+ case({OP[4:2]})
+ 0,1,4,7: _d1mux = D1;
+ 2: _d1mux = 1;
+ 3: _d1mux = daaadjust; // DAA
+ 6,5: _d1mux = 8'hxx;
+ endcase
+ case({OP[2:0], FIN[0]})
+ 0,1,2,7,8,9,10,11,12,13: cin = 0;
+ 3,4,5,6,14,15: cin = 1;
+ endcase
+ case(EXOP[3:0])
+ 0: dbit = 8'b11111110;
+ 1: dbit = 8'b11111101;
+ 2: dbit = 8'b11111011;
+ 3: dbit = 8'b11110111;
+ 4: dbit = 8'b11101111;
+ 5: dbit = 8'b11011111;
+ 6: dbit = 8'b10111111;
+ 7: dbit = 8'b01111111;
+ 8: dbit = 8'b00000001;
+ 9: dbit = 8'b00000010;
+ 10: dbit = 8'b00000100;
+ 11: dbit = 8'b00001000;
+ 12: dbit = 8'b00010000;
+ 13: dbit = 8'b00100000;
+ 14: dbit = 8'b01000000;
+ 15: dbit = 8'b10000000;
+ endcase
+ case(OP[3] ? EXOP[2:0] : OP[2:0])
+ 0,5: csin = D0[7];
+ 1: csin = D0[0];
+ 2,3: csin = FIN[0];
+ 4,7: csin = 0;
+ 6: csin = 1;
+ endcase
+ case(OP[4:0])
+ 0,1,2,3,8,10: begin // ADD, ADC, SUB, SBC, INC, DEC
+ ALU8DOUT[15:8] = sum[7:0];
+ ALU8DOUT[7:0] = sum[7:0];
+ FOUT[0] = OP[3] ? FIN[0] : (sum[8] ^ OP[1]); // inc/dec
+ FOUT[1] = OP[1];
+ FOUT[2] = overflow;
+ FOUT[3] = ALU8DOUT[11];
+ FOUT[4] = hf ^ OP[1];
+ FOUT[5] = ALU8DOUT[13];
+ FOUT[6] = zero & (FIN[6] | ~EXOP[5] | ~DSTHI | OP[3]); //(EXOP[5] & DSTHI) ? (zero & FIN[6]) : zero; // adc16/sbc16
+ FOUT[7] = ALU8DOUT[15];
+ end
+ 16,17: begin // ADD16LO, ADD16HI
+ ALU8DOUT[15:8] = sum[7:0];
+ ALU8DOUT[7:0] = sum[7:0];
+ FOUT[0] = sum[8];
+ FOUT[1] = OP[1];
+ FOUT[2] = FIN[2];
+ FOUT[3] = ALU8DOUT[11];
+ FOUT[4] = hf ^ OP[1];
+ FOUT[5] = ALU8DOUT[13];
+ FOUT[6] = FIN[6];
+ FOUT[7] = FIN[7];
+ end
+ 7: begin // CP
+ ALU8DOUT[15:8] = sum[7:0];
+ FOUT[0] = EXOP[5] ? FIN[0] : !sum[8]; // CPI/D/R
+ FOUT[1] = OP[1];
+ FOUT[2] = overflow;
+ FOUT[3] = D1[3];
+ FOUT[4] = !hf;
+ FOUT[5] = D1[5];
+ FOUT[6] = zero;
+ FOUT[7] = ALU8DOUT[15];
+ end
+ 31: begin // NEG
+ ALU8DOUT[15:8] = sum[7:0];
+ FOUT[0] = !sum[8];
+ FOUT[1] = OP[1];
+ FOUT[2] = overflow;
+ FOUT[3] = ALU8DOUT[11];
+ FOUT[4] = !hf;
+ FOUT[5] = ALU8DOUT[13];
+ FOUT[6] = zero;
+ FOUT[7] = ALU8DOUT[15];
+ end
+ 4: begin // AND
+ ALU8DOUT[15:8] = D0 & D1;
+ FOUT[0] = 0;
+ FOUT[1] = 0;
+ FOUT[2] = parity;
+ FOUT[3] = ALU8DOUT[11];
+ FOUT[4] = 1;
+ FOUT[5] = ALU8DOUT[13];
+ FOUT[6] = zero;
+ FOUT[7] = ALU8DOUT[15];
+ end
+ 5,6: begin //XOR, OR
+ ALU8DOUT[15:8] = OP[0] ? (D0 ^ D1) : (D0 | D1);
+ FOUT[0] = 0;
+ FOUT[1] = 0;
+ FOUT[2] = parity;
+ FOUT[3] = ALU8DOUT[11];
+ FOUT[4] = 0;
+ FOUT[5] = ALU8DOUT[13];
+ FOUT[6] = zero;
+ FOUT[7] = ALU8DOUT[15];
+ end
+ 9: begin // CPL
+ ALU8DOUT[15:8] = ~D0;
+ FOUT[0] = FIN[0];
+ FOUT[1] = 1;
+ FOUT[2] = FIN[2];
+ FOUT[3] = ALU8DOUT[11];
+ FOUT[4] = 1;
+ FOUT[5] = ALU8DOUT[13];
+ FOUT[7:6] = FIN[7:6];
+ end
+ 11,12: begin // RLD, RRD
+ if(OP[0]) ALU8DOUT = {D0[7:4], D1[3:0], D0[3:0], D1[7:4]};
+ else ALU8DOUT = {D0[7:4], D1[7:0], D0[3:0]};
+ FOUT[0] = FIN[0];
+ FOUT[1] = 0;
+ FOUT[2] = parity;
+ FOUT[3] = ALU8DOUT[11];
+ FOUT[4] = 0;
+ FOUT[5] = ALU8DOUT[13];
+ FOUT[6] = zero;
+ FOUT[7] = ALU8DOUT[15];
+ end
+ 13: begin // DAA
+ ALU8DOUT[15:8] = sum[7:0];
+ FOUT[0] = cdaa;
+ FOUT[1] = FIN[1];
+ FOUT[2] = parity;
+ FOUT[3] = ALU8DOUT[11];
+ FOUT[4] = hdaa;
+ FOUT[5] = ALU8DOUT[13];
+ FOUT[6] = zero;
+ FOUT[7] = ALU8DOUT[15];
+ end
+ 14,15: begin // inc/dec 16
+ ALU8DOUT = {D0, D1} + (OP[0] ? 16'hffff : 16'h0001);
+ FOUT[0] = FIN[0];
+ FOUT[1] = LDIFLAGS ? 1'b0 : FIN[1];
+ FOUT[2] = ALU8DOUT != 0;
+ FOUT[3] = FIN[3];
+ FOUT[4] = LDIFLAGS ? 1'b0 : FIN[4];
+ FOUT[5] = FIN[5];
+ FOUT[6] = FIN[6];
+ FOUT[7] = FIN[7];
+ end
+ 20,21: begin // CCF, SCF
+ ALU8DOUT[15:8] = D0;
+ FOUT[0] = OP[0] ? 1'b1 : !FIN[0];
+ FOUT[1] = 1'b0;
+ FOUT[2] = FIN[2];
+ FOUT[3] = ALU8DOUT[11];
+ FOUT[4] = OP[0] ? 1'b0 : FIN[0];
+ FOUT[5] = ALU8DOUT[13];
+ FOUT[6] = FIN[6];
+ FOUT[7] = FIN[7];
+ end
+ 24,25,26,27, 28: begin // ROT, BIT, RES, SET
+ case({OP[2], EXOP[4:3]})
+ 0,1,2,3,4: // rot - shift
+ if(OP[2] ? EXOP[0] : OP[0]){ALU8DOUT[15:8], FOUT[0]} = {csin, D0}; // right
+ else {FOUT[0], ALU8DOUT[15:8]} = {D0, csin}; // left
+ 5,6: begin // BIT, RES
+ FOUT[0] = FIN[0];
+ ALU8DOUT[15:8] = D0 & dbit;
+ end
+ 7: begin // SET
+ FOUT[0] = FIN[0];
+ ALU8DOUT[15:8] = D0 | dbit;
+ end
+ endcase
+ ALU8DOUT[7:0] = ALU8DOUT[15:8];
+ FOUT[1] = 0;
+ FOUT[2] = OP[2] ? (EXOP[3] ? zero : parity) : FIN[2];
+ FOUT[3] = ALU8DOUT[11];
+ FOUT[4] = OP[2] & EXOP[3];
+ FOUT[5] = ALU8DOUT[13];
+ FOUT[6] = OP[2] ? zero : FIN[6];
+ FOUT[7] = OP[2] ? ALU8DOUT[15] : FIN[7];
+ end
+ 29: begin // IN, pass D1
+ ALU8DOUT = {D1, D1};
+ FOUT[0] = FIN[0];
+ FOUT[1] = 0;
+ FOUT[2] = parity;
+ FOUT[3] = ALU8DOUT[11];
+ FOUT[4] = 0;
+ FOUT[5] = ALU8DOUT[13];
+ FOUT[6] = zero;
+ FOUT[7] = ALU8DOUT[15];
+ end
+ 30: FOUT = D0; // FLAGS <- D0
+ default:;
+ endcase
+ end
+endmodule
+
+module daa (
+ input [7:0]flags,
+ input [7:0]val,
+ output wire [7:0]adjust,
+ output reg cdaa,
+ output reg hdaa
+ );
+
+ wire h08 = val[7:4] < 9;
+ wire h09 = val[7:4] < 10;
+ wire l05 = val[3:0] < 6;
+ wire l09 = val[3:0] < 10;
+ reg [1:0]aa;
+ assign adjust = ({1'b0, aa[1], aa[1], 2'b0, aa[0], aa[0], 1'b0} ^ {8{flags[1]}}) + flags[1];
+
+ always @* begin
+ case({flags[0], h08, h09, flags[4], l09})
+ 5'b00101, 5'b01101: aa = 0;
+ 5'b00111, 5'b01111, 5'b01000, 5'b01010, 5'b01100, 5'b01110: aa = 1;
+ 5'b00001, 5'b01001, 5'b10001, 5'b10101, 5'b11001, 5'b11101: aa = 2;
+ default: aa = 3;
+ endcase
+ case({flags[0], h08, h09, l09})
+ 4'b0011, 4'b0111, 4'b0100, 4'b0110: cdaa = 0;
+ default: cdaa = 1;
+ endcase
+ case({flags[1], flags[4], l05, l09})
+ 4'b0000, 4'b0010, 4'b0100, 4'b0110, 4'b1110, 4'b1111: hdaa = 1;
+ default: hdaa = 0;
+ endcase
+ end
+endmodule
+
+
+module ALU16(
+ input [15:0] D0,
+ input [7:0] D1,
+ output wire[15:0] DOUT,
+ input [2:0]OP // 0-NOP, 1-INC, 2-INC2, 3-ADD, 4-NOP, 5-DEC, 6-DEC2
+ );
+
+ reg [15:0] mux;
+ always @*
+ case(OP)
+ 0: mux = 0; // post inc
+ 1: mux = 1; // post inc
+ 2: mux = 2; // post inc
+ 3: mux = {D1[7], D1[7], D1[7], D1[7], D1[7], D1[7], D1[7], D1[7], D1[7:0]}; // post inc
+ 4: mux = 0; // no post inc
+ 5: mux = 16'hffff; // no post inc
+ 6: mux = 16'hfffe; // no post inc
+ default: mux = 16'hxxxx;
+ endcase
+
+ assign DOUT = D0 + mux;
+endmodule
diff --git a/common/CPU/NextZ80/NextZ80CPU.v b/common/CPU/NextZ80/NextZ80CPU.v
new file mode 100644
index 00000000..25d26af8
--- /dev/null
+++ b/common/CPU/NextZ80/NextZ80CPU.v
@@ -0,0 +1,1499 @@
+//////////////////////////////////////////////////////////////////////////////////
+//
+// This file is part of the NextZ80 project
+// http://www.opencores.org/cores/nextz80/
+//
+// Filename: NextZ80CPU.v
+// Description: Implementation of Z80 compatible CPU
+// Version 1.0
+// Creation date: 28Jan2011 - 18Mar2011
+//
+// Author: Nicolae Dumitrache
+// e-mail: ndumitrache@opencores.org
+//
+/////////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2011 Nicolae Dumitrache
+//
+// This source file may be used and distributed without
+// restriction provided that this copyright statement is not
+// removed from the file and that any derivative work contains
+// the original copyright notice and the associated disclaimer.
+//
+// This source file is free software; you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation;
+// either version 2.1 of the License, or (at your option) any
+// later version.
+//
+// This source 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 Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General
+// Public License along with this source; if not, download it
+// from http://www.opencores.org/lgpl.shtml
+//
+///////////////////////////////////////////////////////////////////////////////////
+//
+// Comments:
+// This project was developed and tested on a XILINX Spartan3AN board.
+//
+// NextZ80 processor features:
+// All documented/undocumented intstructions are implemented
+// All documented/undocumented flags are implemented
+// All (doc/undoc)flags are changed accordingly by all (doc/undoc)instructions.
+// The block instructions (LDx, CPx, INx, OUTx) have only the documented effects on flags.
+// The Bit n,(IX/IY+d) and BIT n,(HL) undocumented flags XF and YF are implemented like the BIT n,r and not actually like on the real Z80 CPU.
+// All interrupt modes implemented: NMI, IM0, IM1, IM2
+// R register available
+// Fast conditional jump/call/ret takes only 1 T state if not executed
+// Fast block instructions: LDxR - 3 T states/byte, INxR/OTxR - 2 T states/byte, CPxR - 4 T states / byte
+// Each CPU machine cycle takes (mainly) one clock T state. This makes this processor over 4 times faster than a Z80 at the same
+// clock frequency (some instructions are up to 10 times faster).
+// Works at ~40MHZ on Spartan XC3S700AN speed grade -4)
+// Small size ( ~12% ~700 slices - on Spartan XC3S700AN )
+// Tested with ZEXDOC (fully compliant).
+// Tested with ZEXALL (all OK except CPx(R), LDx(R), BIT n, (IX/IY+d), BIT n, (HL) - fail because of the un-documented XF and YF flags).
+//
+///////////////////////////////////////////////////////////////////////////////////
+`timescale 1ns / 1ps
+
+module NextZ80
+(
+ input wire[7:0] DI,
+ output wire[7:0] DO,
+ output wire[15:0] ADDR,
+ output reg WR,
+ output reg MREQ,
+ output reg IORQ,
+ output reg HALT,
+ output reg M1,
+ input wire CLK,
+ input wire RESET,
+ input wire INT,
+ input wire NMI,
+ input wire WAIT
+);
+
+// connections and registers
+ reg [9:0] CPUStatus = 0; // 0=AF-AF', 1=HL-HL', 2=DE-HL, 3=DE'-HL', 4=HL-X, 5=IX-IY, 6=IFF1,7=IFF2, 9:8=IMODE
+ wire [7:0] ALU8FLAGS;
+ wire [7:0] FLAGS;
+ wire [7:0] ALU80;
+ wire [7:0] ALU81;
+ wire [15:0]ALU160;
+ wire [7:0] ALU161;
+ wire [15:0]ALU8OUT;
+
+ reg [9:0] FETCH = 0;
+ reg [2:0] STAGE = 0;
+ wire [5:0] opd;
+ wire [2:0] op16;
+ wire op0mem = FETCH[2:0] == 6;
+ wire op1mem = FETCH[5:3] == 6;
+ reg [1:0]fetch98;
+
+// stage status
+ reg [1:0]DO_SEL; // ALU80 - th - flags - ALU8OUT[7:0]
+ reg ALU160_SEL; // regs - pc
+ reg DINW_SEL; // ALU8OUT - DI
+ reg [5:0]WE; // 5 = flags, 4 = PC, 3 = SP, 2 = tmpHI, 1 = hi, 0 = lo
+ reg [4:0] ALU8OP;
+ reg [2:0] ALU16OP;
+ reg next_stage;
+ reg [3:0]REG_WSEL;
+ reg [3:0]REG_RSEL;
+ reg [11:0]status; // 0=AF-AF', 1=HL-HL', 2=DE-HL, 3=DE'-HL', 4=HL-X, 5=IX-IY, 7:6=IFFVAL, 9:8=imode, 10=setIMODE, 11=set IFFVAL
+// FETCH[5:3]: 000 NZ, 001 Z, 010 NC, 011 C, 100 PO, 101 PE, 110 P, 111 M
+ wire [7:0]FlagMux = {FLAGS[7], !FLAGS[7], FLAGS[2], !FLAGS[2], FLAGS[0], !FLAGS[0], FLAGS[6], !FLAGS[6]};
+ reg tzf;
+ reg FNMI = 0, SNMI = 0;
+ reg SRESET = 0;
+ reg SINT = 0;
+ wire [2:0]intop = FETCH[1] ? 4 : (FETCH[0] ? 5 : 6);
+ reg xmask;
+
+ Z80Reg CPU_REGS (
+ .rstatus(CPUStatus[7:0]),
+ .M1(M1),
+ .WE(WE),
+ .CLK(CLK),
+ .ALU8OUT(ALU8OUT),
+ .DI(DI),
+ .DO(DO),
+ .ADDR(ADDR),
+ .CONST(FETCH[7] ? {2'b00, FETCH[5:3], 3'b000} : 8'h66), // RST/NMI address
+ .ALU80(ALU80),
+ .ALU81(ALU81),
+ .ALU160(ALU160),
+ .ALU161(ALU161),
+ .ALU8FLAGS(ALU8FLAGS),
+ .FLAGS(FLAGS),
+ .DO_SEL(DO_SEL),
+ .ALU160_sel(ALU160_SEL),
+ .REG_WSEL(REG_WSEL),
+ .REG_RSEL(REG_RSEL),
+ .DINW_SEL(DINW_SEL),
+ .XMASK(xmask),
+ .ALU16OP(ALU16OP), // used for post increment for ADDR, SP mux re-direct
+ .WAIT(WAIT)
+ );
+
+ ALU8 CPU_ALU8 (
+ .D0(ALU80),
+ .D1(ALU81),
+ .FIN(FLAGS),
+ .FOUT(ALU8FLAGS),
+ .ALU8DOUT(ALU8OUT),
+ .OP(ALU8OP),
+ .EXOP(FETCH[8:3]),
+ .LDIFLAGS(REG_WSEL[2]), // inc16 HL
+ .DSTHI(!REG_WSEL[0])
+ );
+
+ ALU16 CPU_ALU16 (
+ .D0(ALU160),
+ .D1(ALU161),
+ .DOUT(ADDR),
+ .OP(ALU16OP)
+ );
+
+ always @(posedge CLK)
+ if(!WAIT) begin
+ SRESET <= RESET;
+ SNMI <= NMI;
+ SINT <= INT;
+ if(!SNMI) FNMI <= 0;
+ if(SRESET) FETCH <= 10'b1110000000;
+ else
+ if(FETCH[9:6] == 4'b1110) {FETCH[9:7]} <= 3'b000; // exit RESET state
+ else begin
+ if(M1 || (fetch98 == 2'b10)) // [DD/FD CB disp op] - M1 is inactive during byte read, but FETCH is performed
+ case({MREQ, CPUStatus[9:8]})
+ 3'b000, 3'b001, 3'b100, 3'b101, 3'b110, 3'b111: FETCH <= {fetch98, DI};
+ 3'b010: FETCH <= {fetch98, 8'hff}; // IM1 - RST38
+ 3'b011: ; // IM2 - get addrLO
+ endcase
+ if(~|{next_stage, fetch98[1:0], status[4]}) // INT or NMI sample
+ if(SNMI & !FNMI) begin // NMI posedge
+ {FETCH[9:6], FETCH[1:0]} <= {4'b1101, HALT, M1};
+ FNMI <= 1; // NMI acknowledged
+ end else if(SINT & CPUStatus[6] & !status[11]) {FETCH[9:6], FETCH[1:0]} <= {4'b1100, HALT, M1}; // INT request
+ end
+ if(next_stage) STAGE <= STAGE + 3'b001;
+ else STAGE <= 0;
+ if(status[4]) CPUStatus[5:4] <= status[5:4];
+ else if(~|{next_stage, fetch98[1]} | fetch98[0]) CPUStatus[4] <= 1'b0; // clear X
+ CPUStatus[3:0] <= CPUStatus[3:0] ^ status[3:0];
+ if(status[11]) CPUStatus[7:6] <= status[7:6]; // IFF2:1
+ if(status[10]) CPUStatus[9:8] <= status[9:8]; // IMM
+ tzf <= ALU8FLAGS[6];
+ end
+
+ assign opd[0] = FETCH[0] ^ &FETCH[2:1];
+ assign opd[2:1] = FETCH[2:1];
+ assign opd[3] = FETCH[3] ^ &FETCH[5:4];
+ assign opd[5:4] = FETCH[5:4];
+ assign op16[2:0] = &FETCH[5:4] ? 3'b101 : {1'b0, FETCH[5:4]};
+
+ always @* begin
+ DO_SEL = 2'bxx; // ALU80 - th - flags - ALU8OUT[7:0]
+ ALU160_SEL = 1'bx; // regs - pc
+ DINW_SEL = 1'bx; // ALU8OUT - DI
+ WE = 6'bxxxxxx; // 5 = flags, 4 = PC, 3 = SP, 2 = tmpHI, 1 = hi, 0 = lo
+ ALU8OP = 5'bxxxxx;
+ ALU16OP = 3'b000; // NOP, post inc
+ next_stage = 0;
+ REG_WSEL = 4'bxxxx;
+ REG_RSEL = 4'bx0xx; // prevents default 4'b0100 which leads to incorrect P flag value in some cases (like RLA)
+ M1 = 1;
+ MREQ = 1;
+ WR = 0;
+
+ HALT = 0;
+ IORQ = 0;
+ status = 12'b00xxxxx00000;
+ fetch98 = 2'b00;
+
+ case({FETCH[7:6], op1mem, op0mem})
+ 4'b0000, 4'b0001, 4'b0010, 4'b0011, 4'b0100, 4'b1000, 4'b1100: xmask = 1;
+ default: xmask = 0;
+ endcase
+
+ case(FETCH[9:6])
+//------------------------------------------- block 00 ----------------------------------------------------
+ 4'b0000:
+ case(FETCH[3:0])
+// ----------------------- NOP, EX AF, AF', DJNZ, JR, JR c --------------------
+ 4'b0000, 4'b1000:
+ case(FETCH[5:4])
+ 2'b00: begin // NOP, EX AF, AF'
+ DO_SEL = 2'bxx;
+ ALU160_SEL = 1; // PC
+ WE = 6'b010x00; // PC
+ status[0] = FETCH[3];
+ end
+ 2'b01:
+ if(!STAGE[0]) begin // DJNZ, JR - stage1
+ ALU160_SEL = 1; // pc
+ WE = 6'b010100; // PC, tmpHI
+ if(!FETCH[3]) begin
+ ALU8OP = 5'b01010; // DEC, for tzf only
+ REG_WSEL = 4'b0000; // B
+ end
+ next_stage = 1;
+ M1 = 0;
+ end else if(FETCH[3]) begin // JR - stage2
+ ALU160_SEL = 1; // pc
+ WE = 6'b010x00; // PC
+ ALU16OP = 3; // ADD
+ end else begin // DJNZ - stage2
+ ALU160_SEL = 1; // pc
+ DINW_SEL = 0; // ALU8OUT
+ WE = 6'b010x10; // PC, hi
+ ALU8OP = 5'b01010; // DEC
+ ALU16OP = tzf ? 3'd0 : 3'd3; // NOP/ADD
+ REG_WSEL = 4'b0000; // B
+ end
+ 2'b10, 2'b11: // JR cc, stage1, stage2
+ case({STAGE[0], FlagMux[{1'b0, FETCH[4:3]}]})
+ 2'b00, 2'b11: begin
+ ALU160_SEL = 1; // pc
+ WE = 6'b010x00; // PC
+ ALU16OP = STAGE[0] ? 3'd3 : 3'd1; // ADD/ INC, post inc
+ end
+ 2'b01: begin
+ ALU160_SEL = 1; // pc
+ WE = 6'b010100; // PC, tmpHI
+ next_stage = 1;
+ M1 = 0;
+ end
+ endcase
+ endcase
+// ----------------------- LD rr,nn --------------------
+ 4'b0001: // LD rr,nn, stage1
+ case({STAGE[1:0], op16[2]})
+ 3'b00_0, 3'b00_1, 3'b01_0, 3'b01_1: begin // LD rr,nn, stage1,2
+ ALU160_SEL = 1; // pc
+ DINW_SEL = 1; // DI
+ WE = {4'b010x, STAGE[0] ? 1'b1 : 1'bx, !STAGE[0]}; // PC, lo/HI
+ next_stage = 1;
+ REG_WSEL = {op16, 1'bx};
+ M1 = 0;
+ end
+ 3'b10_0, 3'b11_1: begin // BC, DE, HL, stage3, SP stage4
+ ALU160_SEL = 1; // pc
+ WE = 6'b010x00; // PC
+ end
+ 3'b10_1: begin // SP stage3
+ ALU160_SEL = 0; // regs
+ WE = 6'b001x00; // SP
+ ALU16OP = 4; // NOP
+ next_stage = 1;
+ REG_RSEL = 4'b101x; // tmpSP
+ M1 = 0;
+ MREQ = 0;
+ end
+ endcase
+// ----------------------- LD (BC) A - LD (DE) A - LD (nn) HL, LD (nn),A --------------------
+// ----------------------- LD A (BC) - LD A (DE) - LD HL (nn), LD A (nn) --------------------
+ 4'b0010, 4'b1010:
+ case(STAGE[2:0])
+ 3'b000:
+ if(FETCH[5] == 0) begin // LD (BC) A, LD (DE) A - stage1
+ if(FETCH[3]) DINW_SEL = 1; // DI
+ else DO_SEL = 2'b00; // ALU80
+ ALU160_SEL = 0; // regs
+ WE = {4'b000x, FETCH[3], 1'bx}; // hi
+ next_stage = 1;
+ REG_WSEL = FETCH[3] ? 4'b011x : 4'b0110; // A
+ REG_RSEL = {op16, 1'bx};
+ M1 = 0;
+ WR = !FETCH[3];
+ end else begin // LD (nn) A - LD (nn) HL - stage 1
+ ALU160_SEL = 1; // PC
+ DINW_SEL = 1; // DI
+ WE = 6'b010xx1; // PC, lo
+ next_stage = 1;
+ REG_WSEL = 4'b111x;
+ M1 = 0;
+ end
+ 3'b001:
+ if(FETCH[5] == 0) begin // LD (BC), A, LD (DE), A - stage2
+ ALU160_SEL = 1; // pc
+ WE = 6'b010x00; // PC
+ end else begin // LD (nn),A - LH (nn),HL - stage 2
+ ALU160_SEL = 1; // pc
+ DINW_SEL = 1; // DI
+ WE = 6'b010x10; // PC, hi
+ next_stage = 1;
+ REG_WSEL = 4'b111x;
+ M1 = 0;
+ end
+ 3'b010: begin
+ ALU160_SEL = 1'b0; // regs
+ REG_RSEL = 4'b111x;
+ M1 = 0;
+ WR = !FETCH[3];
+ next_stage = 1;
+ if(FETCH[3]) begin // LD A (nn) - LD HL (nn) - stage 3
+ DINW_SEL = 1; // DI
+ WE = {4'b000x, FETCH[4] ? 1'b1 : 1'bx, FETCH[4] ? 1'bx : 1'b1}; // lo/hi
+ REG_WSEL = FETCH[4] ? 4'b011x : 4'b010x; // A or L
+ end else begin // LD (nn),A - LD (nn),HL - stage 3
+ DO_SEL = 2'b00; // ALU80
+ WE = 6'b000x00; // nothing
+ REG_WSEL = FETCH[4] ? 4'b0110 : 4'b0101; // A or L
+ end
+ end
+ 3'b011:
+ if(FETCH[4]) begin // LD (nn),A - stage 4
+ ALU160_SEL = 1; // pc
+ WE = 6'b010x00; // PC
+ end else begin
+ REG_RSEL = 4'b111x;
+ M1 = 0;
+ WR = !FETCH[3];
+ ALU160_SEL = 1'b0; // regs
+ ALU16OP = 1; // INC
+ next_stage = 1;
+ if(FETCH[3]) begin // LD HL (nn) - stage 4
+ DINW_SEL = 1; // DI
+ WE = 6'b000x10; // hi
+ REG_WSEL = 4'b010x; // H
+ end else begin // LD (nn),HL - stage 4
+ DO_SEL = 2'b00; // ALU80
+ WE = 6'b000x00; // nothing
+ REG_WSEL = 4'b0100; // H
+ end
+ end
+ 3'b100: begin // LD (nn),HL - stage 5
+ ALU160_SEL = 1; // pc
+ WE = 6'b010x00; // PC
+ end
+ endcase
+// ----------------------- inc/dec rr --------------------
+ 4'b0011, 4'b1011:
+ if(!STAGE[0])
+ if(op16[2]) begin // SP - stage1
+ ALU160_SEL = 0; // regs
+ WE = 6'b001x00; // SP
+ ALU16OP = {FETCH[3], 1'b0, FETCH[3]}; // post inc, dec
+ next_stage = 1;
+ REG_RSEL = 4'b101x; // sp
+ M1 = 0;
+ MREQ = 0;
+ end else begin // BC, DE, HL - stage 1
+ ALU160_SEL = 1; // pc
+ DINW_SEL = 0; // ALU8OUT
+ WE = 6'b010x11; // PC, hi, lo
+ ALU8OP = {4'b0111, FETCH[3]}; // INC16 / DEC16
+ REG_WSEL = {op16, 1'b0}; // hi
+ REG_RSEL = {op16, 1'b1}; // lo
+ end
+ else begin // SP, stage2
+ ALU160_SEL = 1; // pc
+ WE = 6'b010x00; // PC
+ end
+// ----------------------- inc/dec 8 --------------------
+ 4'b0100, 4'b0101, 4'b1100, 4'b1101:
+ if(!op1mem) begin //regs
+ DINW_SEL = 0; // ALU8OUT
+ ALU160_SEL = 1; // pc
+ WE = opd[3] ? 6'b110x01 : 6'b110x10; // flags, PC, hi/lo
+ ALU8OP = {3'b010, FETCH[0], 1'b0}; // inc / dec
+ REG_WSEL = {1'b0, opd[5:3]};
+ end else case({STAGE[1:0], CPUStatus[4]})
+ 3'b00_0, 3'b01_1: begin // (HL) - stage1, (X) - stage2
+ ALU160_SEL = 0; // regs
+ DINW_SEL = 1; // DI
+ WE = 6'b000001; // lo
+ ALU16OP = CPUStatus[4] ? 3'd3 : 3'd0;
+ next_stage = 1;
+ REG_WSEL = 4'b011x; // tmpLO
+ REG_RSEL = 4'b010x; // HL
+ M1 = 0;
+ end
+ 3'b00_1: begin // (X) - stage1
+ ALU160_SEL = 1; // pc
+ WE = 6'b010100; // PC, tmpHI
+ next_stage = 1;
+ M1 = 0;
+ end
+ 3'b01_0, 3'b10_1: begin // (HL) stage2, (X) - stage3
+ DO_SEL = 2'b11; // ALU80OUT
+ ALU160_SEL = 0; // regs
+ WE = 6'b100x0x; // flags
+ ALU8OP = {3'b010, FETCH[0], 1'b0}; // inc / dec
+ ALU16OP = CPUStatus[4] ? 3'd3 : 3'd0;
+ next_stage = 1;
+ REG_WSEL = 4'b0111; // tmpLO
+ REG_RSEL = 4'b010x; // HL
+ M1 = 0;
+ WR = 1;
+ end
+ 3'b10_0, 3'b11_1: begin // (HL) - stage3, (X) - stage 4
+ ALU160_SEL = 1; // pc
+ WE = 6'b010x00; // PC
+ end
+ endcase
+// ----------------------- ld r/(HL-X), n --------------------
+ 4'b0110, 4'b1110:
+ case({STAGE[1:0], CPUStatus[4], op1mem})
+ 4'b00_0_0, 4'b00_0_1, 4'b00_1_0, 4'b01_1_1: begin // r, (HL) - stage1, (X) - stage2 (read n)
+ ALU160_SEL = 1; // pc
+ DINW_SEL = 1; // DI
+ WE = opd[3] ? 6'b010001 : 6'b010010; // PC, hi/lo
+ next_stage = 1;
+ REG_WSEL = {1'b0, opd[5:4], 1'bx};
+ M1 = 0;
+ end
+ 4'b01_0_0, 4'b01_1_0, 4'b10_0_1, 4'b11_1_1: begin // r - stage2, (HL) - stage3, (X) - stage4
+ ALU160_SEL = 1; // pc
+ WE = 6'b010x00; // PC
+ end
+ 4'b01_0_1, 4'b10_1_1: begin // (HL) - stage2, (X) - stage3
+ DO_SEL = 2'b00; // ALU80
+ ALU160_SEL = 0; // regs
+ WE = 6'b000x0x; // nothing
+ ALU16OP = CPUStatus[4] ? 3'd3 : 3'd0;
+ next_stage = 1;
+ REG_WSEL = 4'b0111; // tmpLO
+ REG_RSEL = 4'b010x; // HL
+ M1 = 0;
+ WR = 1;
+ end
+ 4'b00_1_1: begin // (X) - stage1
+ ALU160_SEL = 1; // pc
+ WE = 6'b010100; // PC, tmpHI
+ next_stage = 1;
+ M1 = 0;
+ end
+ endcase
+// ----------------------- rlca, rrca, rla, rra, daa, cpl, scf, ccf --------------------
+ 4'b0111, 4'b1111:
+ case(FETCH[5:3])
+ 3'b000, 3'b001, 3'b010, 3'b011, 3'b100, 3'b101: begin // rlca, rrca, rla, rra, daa, cpl
+ ALU160_SEL = 1; // pc
+ DINW_SEL = 0; // ALU8OUT
+ WE = 6'b110x1x; // flags, PC, hi
+ ALU8OP = FETCH[5] ? {2'b01, !FETCH[3], 2'b01} : {3'b110, FETCH[4:3]};
+ REG_WSEL = 4'b0110; // A
+ end
+ 3'b110, 3'b111: begin // scf, ccf
+ ALU160_SEL = 1; // pc
+ DINW_SEL = 0; // ALU8OUT
+ WE = 6'b110x0x; // flags, PC
+ ALU8OP = {4'b1010, !FETCH[3]};
+ end
+ endcase
+// ----------------------- add 16 --------------------
+ 4'b1001:
+ if(!STAGE[0]) begin
+ DINW_SEL = 0; // ALU8OUT
+ WE = 6'b100x01; // flags, lo
+ ALU8OP = 5'b10000; // ADD16LO
+ next_stage = 1;
+ REG_WSEL = 4'b0101; // L
+ REG_RSEL = {op16, 1'b1};
+ M1 = 0;
+ MREQ = 0;
+ end else begin
+ ALU160_SEL = 1; // pc
+ DINW_SEL = 0; // ALU8OUT
+ WE = 6'b110x10; // flags, PC, hi
+ ALU8OP = 5'b10001; // ADD16HI
+ REG_WSEL = 4'b0100; // H
+ REG_RSEL = {op16, 1'b0};
+ end
+ endcase
+
+// ---------------------------------------------- block 01 LD8 ---------------------------------------------------
+ 4'b0001:
+ case({STAGE[1:0], CPUStatus[4], op1mem, op0mem})
+ 5'b00_0_00, 5'b00_1_00, // LD r, r 1st stage
+ 5'b01_0_01, // LD r, (HL) 2nd stage
+ 5'b10_1_01: // LD r, (X) 3rd stage
+ begin
+ ALU160_SEL = 1; // PC
+ DINW_SEL = 0; // ALU8
+ WE = opd[3] ? 6'b010x01 : 6'b010x10; // PC and LO or HI
+ ALU8OP = 29; // PASS D1
+ REG_WSEL = {1'b0, opd[5:4], 1'bx};
+ REG_RSEL = {1'b0, opd[2:0]};
+ end
+ 5'b00_0_01, // LD r, (HL) 1st stage
+ 5'b01_1_01: // LD r, (X) 2nd stage
+ begin
+ ALU160_SEL = 0; // regs
+ DINW_SEL = 1; // DI
+ WE = 6'b000x01; // LO
+ ALU16OP = CPUStatus[4] ? 3'd3 : 3'd0; // ADD - NOP
+ next_stage = 1;
+ REG_WSEL = 4'b011x; // A - tmpLO
+ REG_RSEL = 4'b010x; // HL
+ M1 = 0;
+ end
+ 5'b00_1_01, // LD r, (X) 1st stage
+ 5'b00_1_10: // LD (X), r 1st stage
+ begin
+ ALU160_SEL = 1; // pc
+ WE = 6'b010100; // PC, tmpHI
+ next_stage = 1;
+ M1 = 0;
+ end
+ 5'b00_0_10, // LD (HL), r 1st stage
+ 5'b01_1_10: // LD (X), r 2nd stage
+ begin
+ DO_SEL = 0; // ALU80
+ ALU160_SEL = 0; // regs
+ WE = 6'b000x00; // no write
+ ALU16OP = CPUStatus[4] ? 3'd3 : 3'd0; // ADD - NOP
+ next_stage = 1;
+ REG_WSEL = {1'b0, opd[2:0]};
+ REG_RSEL = 4'b010x; // HL
+ M1 = 0;
+ WR = 1;
+ end
+ 5'b01_0_10, // LD (HL), r 2nd stage
+ 5'b10_1_10: // LD (X), r 3rd stage
+ begin
+ ALU160_SEL = 1; // pc
+ WE = 6'b010x00; // PC
+ end
+ 5'b00_0_11, 5'b00_1_11: begin // HALT
+ WE = 6'b000x00; // no write
+ M1 = 0;
+ MREQ = 0;
+ HALT = 1;
+ end
+ endcase
+// ---------------------------------------------- block 10 arith8 ---------------------------------------------------
+ 4'b0010:
+ case({STAGE[1:0], CPUStatus[4], op0mem})
+ 4'b00_0_0, 4'b00_1_0, // OP r,r 1st stage
+ 4'b01_0_1, // OP r, (HL) 2nd stage
+ 4'b10_1_1: // OP r, (X) 3rd stage
+ begin
+ ALU160_SEL = 1; // pc
+ DINW_SEL = 0; // ALU8OUT
+ WE = {4'b110x, ~&FETCH[5:3], 1'bx}; // flags, PC, hi
+ ALU8OP = {2'b00, FETCH[5:3]};
+ REG_WSEL = 4'b0110; // A
+ REG_RSEL = {1'b0, opd[2:0]};
+ end
+ 4'b00_0_1, // OP r, (HL) 1st stage
+ 4'b01_1_1: // OP r, (X) 2nd stage
+ begin
+ ALU160_SEL = 0; // HL
+ DINW_SEL = 1; // DI
+ WE = 6'b000x01; // lo
+ ALU16OP = CPUStatus[4] ? 3'd3 : 3'd0; // ADD - NOP
+ next_stage = 1;
+ REG_WSEL = 4'b011x; // A-tmpLO
+ REG_RSEL = 4'b010x; // HL
+ M1 = 0;
+ end
+ 4'b00_1_1: // OP r, (X) 1st stage
+ begin
+ ALU160_SEL = 1; // pc
+ WE = 6'b010100; // PC, tmpHI
+ next_stage = 1;
+ M1 = 0;
+ end
+ endcase
+//------------------------------------------- block 11 ----------------------------------------------------
+ 4'b0011:
+ case(FETCH[3:0])
+// ----------------------- RET cc --------------------
+ 4'b0000, 4'b1000:
+ case(STAGE[1:0])
+ 2'b00, 2'b01: // stage1, stage2
+ if(FlagMux[FETCH[5:3]]) begin // POP addr
+ ALU160_SEL = 0; // regs
+ DINW_SEL = 1; // DI
+ WE = {4'b001x, STAGE[0] ? 1'b1 : 1'bx, !STAGE[0]}; // SP, lo/hi
+ next_stage = 1;
+ REG_WSEL = 4'b111x; // tmp16
+ REG_RSEL = 4'b101x; // SP
+ M1 = 0;
+ end else begin
+ ALU160_SEL = 1; // pc
+ WE = 6'b010x00; // PC
+ end
+ 2'b10: begin // stage3
+ ALU160_SEL = 0; // regs
+ WE = 6'b010x00; // PC
+ REG_RSEL = 4'b111x; // tmp16
+ end
+ endcase
+// ----------------------- POP --------------------
+ 4'b0001:
+ case(STAGE[1:0])
+ 2'b00, 2'b01: begin
+ if(op16[2]) begin // AF
+ WE = STAGE[0] ? 6'b101x1x : 6'b001xx1; // flags, SP, lo/hi
+ REG_WSEL = {3'b011, STAGE[0] ? 1'b1 : 1'bx};
+ if(STAGE[0]) ALU8OP = 30; // FLAGS <- D0
+ end else begin // r16
+ WE = STAGE[0] ? 6'b001x10 : 6'b001xx1; // SP, lo/hi
+ REG_WSEL = {1'b0, FETCH[5:4], 1'bx};
+ end
+ ALU160_SEL = 0; // regs
+ DINW_SEL = 1; // DI
+ next_stage = 1;
+ REG_RSEL = 4'b101x; // SP
+ M1 = 0;
+ end
+ 2'b10: begin // stage3
+ ALU160_SEL = 1; // PC
+ WE = 6'b010x00; // PC
+ end
+ endcase
+// ----------------------- JP cc --------------------
+ 4'b0010, 4'b1010:
+ case(STAGE[1:0])
+ 2'b00, 2'b01: begin // stage1,2
+ if(FlagMux[FETCH[5:3]]) begin
+ ALU160_SEL = 1; // pc
+ DINW_SEL = 1; // DI
+ WE = {4'b010x, STAGE[0] ? 1'b1 : 1'bx, !STAGE[0]}; // PC, hi/lo
+ next_stage = 1;
+ REG_WSEL = 4'b111x; // tmp7
+ M1 = 0;
+ end else begin
+ ALU160_SEL = 1; // pc
+ WE = 6'b010x00; // PC
+ ALU16OP = 2; // add2
+ end
+ end
+ 2'b10: begin // stage3
+ ALU160_SEL = 0; // regs
+ WE = 6'b010x00; // PC
+ REG_RSEL = 4'b111x; // tmp7
+ end
+ endcase
+// ----------------------- JP, OUT (n) A, EX (SP) HL, DI --------------------
+ 4'b0011:
+ case(FETCH[5:4])
+ 2'b00: // JP
+ case(STAGE[1:0])
+ 2'b00, 2'b01: begin // stage1,2 - read addr
+ ALU160_SEL = 1; // pc
+ DINW_SEL = 1; // DI
+ WE = {4'b010x, STAGE[0] ? 1'b1 : 1'bx, !STAGE[0]}; // PC, hi/lo
+ next_stage = 1;
+ REG_WSEL = 4'b111x; // tmp7
+ M1 = 0;
+ end
+ 2'b10: begin // stage3
+ ALU160_SEL = 0; // regs
+ WE = 6'b010x00; // PC
+ REG_RSEL = 4'b111x; // tmp7
+ end
+ endcase
+ 2'b01: // OUT (n), a - stage1 - read n
+ case(STAGE[1:0])
+ 2'b00: begin
+ ALU160_SEL = 1; // pc
+ DINW_SEL = 1; // DI
+ WE = 6'b010x01; // PC, lo
+ next_stage = 1;
+ REG_WSEL = 4'b011x; // tmpLO
+ M1 = 0;
+ end
+ 2'b01: begin // stage2 - OUT
+ DO_SEL = 2'b00; // ALU80
+ ALU160_SEL = 0; // regs
+ WE = 6'b000x00; // nothing
+ next_stage = 1;
+ REG_WSEL = 4'b0110; // A
+ REG_RSEL = 4'b011x; // A-tmpLO
+ M1 = 0;
+ MREQ = 0;
+ WR = 1;
+ IORQ = 1;
+ end
+ 2'b10: begin // stage3 - fetch
+ ALU160_SEL = 1; // PC
+ WE = 6'b010x00; // PC
+ end
+ endcase
+ 2'b10: // EX (SP), HL
+ case(STAGE[2:0])
+ 3'b000, 3'b001: begin // stage1,2 - pop tmp16
+ ALU160_SEL = 0; // regs
+ DINW_SEL = 1; // DI
+ WE = {4'b001x, STAGE[0] ? 1'b1 : 1'bx, !STAGE[0]}; // SP, lo/hi
+ next_stage = 1;
+ REG_WSEL = 4'b111x; // tmp16
+ REG_RSEL = 4'b101x; // SP
+ M1 = 0;
+ end
+ 3'b010, 3'b011: begin // stage3,4 - push hl
+ DO_SEL = 2'b00; // ALU80
+ ALU160_SEL = 0; // regs
+ WE = 6'b001x00; // SP
+ ALU16OP = 5; // dec
+ next_stage = 1;
+ REG_WSEL = {3'b010, STAGE[0]};// H/L
+ REG_RSEL = 4'b101x; // SP
+ M1 = 0;
+ WR = 1;
+ end
+ 3'b100, 3'b101: begin // stage5,6
+ ALU160_SEL = 1; // pc
+ DINW_SEL = 0; // ALU8OUT
+ WE = {1'b0, STAGE[0], 2'b0x, STAGE[0] ? 1'b1 : 1'bx, !STAGE[0]}; // PC, lo/hi
+ ALU8OP = 29; // pass D1
+ next_stage = !STAGE[0];
+ REG_WSEL = 4'b010x; // HL
+ REG_RSEL = {3'b111, !STAGE[0]}; // tmp16
+ M1 = STAGE[0];
+ MREQ = STAGE[0];
+ end
+ endcase
+ 2'b11: begin // DI
+ ALU160_SEL = 1; // PC
+ WE = 6'b010x00; // PC
+ status[11] = 1'b1; // set IFF flags
+ status[7:6] = 2'b00;
+ end
+ endcase
+// ----------------------- CALL cc --------------------
+ 4'b0100, 4'b1100:
+ case(STAGE[2:0])
+ 3'b000, 3'b001: // stage 1,2 - load addr
+ if(FlagMux[FETCH[5:3]]) begin
+ ALU160_SEL = 1; // pc
+ DINW_SEL = 1; // DI
+ WE = {4'b010x, STAGE[0] ? 1'b1 : 1'bx, !STAGE[0]}; // PC, hi/lo
+ next_stage = 1;
+ REG_WSEL = 4'b111x; // tmp7
+ M1 = 0;
+ end else begin
+ ALU160_SEL = 1; // pc
+ WE = 6'b010x00; // PC
+ ALU16OP = 2; // add2
+ end
+ 3'b010, 3'b011: begin // stage 3,4 - push pc
+ DO_SEL = {1'b0, STAGE[0]}; // pc hi/lo
+ ALU160_SEL = 0; // regs
+ WE = 6'b001x00; // SP
+ ALU16OP = 5; // DEC
+ next_stage = 1;
+ REG_WSEL = 4'b1xxx; // pc
+ REG_RSEL = 4'b101x; // sp
+ M1 = 0;
+ WR = 1;
+ end
+ 3'b100: begin // stage5
+ ALU160_SEL = 0; // regs
+ WE = 6'b010x00; // PC
+ REG_RSEL = 4'b111x; // tmp7
+ end
+ endcase
+// ----------------------- PUSH --------------------
+ 4'b0101:
+ case(STAGE[1:0])
+ 2'b00, 2'b01: begin // stage1,2
+ DO_SEL = {STAGE[0] & op16[2], 1'b0}; // FLAGS/ALU80
+ ALU160_SEL = 0; // regs
+ WE = 6'b001x00; // SP
+ ALU16OP = 5; // dec
+ next_stage = 1;
+ REG_WSEL = {1'b0, FETCH[5:4], STAGE[0]};
+ REG_RSEL = 4'b101x; // SP
+ M1 = 0;
+ WR = 1;
+ end
+ 2'b10: begin //stage3
+ ALU160_SEL = 1; // PC
+ WE = 6'b010x00; // PC
+ end
+ endcase
+// ----------------------- op A, n --------------------
+ 4'b0110, 4'b1110:
+ if(!STAGE[0]) begin // stage1, read n
+ ALU160_SEL = 1; // pc
+ DINW_SEL = 1; // DI
+ WE = 6'b010x01; // PC, lo
+ next_stage = 1;
+ REG_WSEL = 4'b011x; // tmpLO
+ M1 = 0;
+ end else begin // stage 2
+ DINW_SEL = 0; // ALU8OUT[7:0]
+ ALU160_SEL = 1; // pc
+ WE = {4'b110x, ~&FETCH[5:3], 1'bx}; // flags, PC, hi
+ ALU8OP = {2'b00, FETCH[5:3]};
+ REG_WSEL = 4'b0110; // A
+ REG_RSEL = 4'b0111; // tmpLO
+ end
+// ----------------------- RST --------------------
+ 4'b0111, 4'b1111:
+ case(STAGE[1:0])
+ 2'b00, 2'b01: begin // stage 1,2 - push pc
+ DO_SEL = {1'b0, STAGE[0]}; // pc hi/lo
+ ALU160_SEL = 0; // regs
+ WE = 6'b001x00; // SP
+ ALU16OP = 5; // DEC
+ next_stage = 1;
+ REG_WSEL = 4'b1xxx; // pc
+ REG_RSEL = 4'b101x; // sp
+ M1 = 0;
+ WR = 1;
+ end
+ 2'b10: begin // stage3
+ ALU160_SEL = 0; // regs
+ WE = 6'b010x00; // PC
+ REG_RSEL = 4'b110x; // const
+ end
+ endcase
+// ----------------------- RET, EXX, JP (HL), LD SP HL --------------------
+ 4'b1001:
+ case(FETCH[5:4])
+ 2'b00: // RET
+ case(STAGE[1:0])
+ 2'b00, 2'b01: begin // stage1, stage2 - pop addr
+ ALU160_SEL = 0; // regs
+ DINW_SEL = 1; // DI
+ WE = {4'b001x, STAGE[0] ? 1'b1 : 1'bx, !STAGE[0]}; // SP, lo/hi
+ next_stage = 1;
+ REG_WSEL = 4'b111x; // tmp16
+ REG_RSEL = 4'b101x; // SP
+ M1 = 0;
+ end
+ 2'b10: begin // stage3 - jump
+ ALU160_SEL = 0; // regs
+ WE = 6'b010x00; // PC
+ REG_RSEL = 4'b111x; // tmp16
+ end
+ endcase
+ 2'b01: begin // EXX
+ ALU160_SEL = 1; // PC
+ WE = 6'b010x00; // PC
+ status[1] = 1;
+ end
+ 2'b10: begin // JP (HL)
+ ALU160_SEL = 0; // regs
+ WE = 6'b010x00; // PC
+ REG_RSEL = 4'b010x; // HL
+ end
+ 2'b11: begin // LD SP,HL
+ if(!STAGE[0]) begin // stage1
+ ALU160_SEL = 0; // regs
+ WE = 6'b001x00; // SP
+ ALU16OP = 4; // NOP, no post inc
+ next_stage = 1;
+ REG_RSEL = 4'b010x; // HL
+ M1 = 0;
+ MREQ = 0;
+ end else begin // stage2
+ ALU160_SEL = 1; // pc
+ WE = 6'b010x00; // PC
+ end
+ end
+ endcase
+// ----------------------- CB, IN A (n), EX DE HL, EI --------------------
+ 4'b1011:
+ case(FETCH[5:4])
+ 2'b00: // CB prefix
+ case({STAGE[0], CPUStatus[4]})
+ 2'b00, 2'b11: begin
+ ALU160_SEL = 1; // PC
+ WE = 6'b010000; // PC
+ fetch98 = 2'b10;
+ M1 = !CPUStatus[4]; // [DD/FD CB disp op] - M1 is inactive during byte read
+ end
+ 2'b01: begin
+ ALU160_SEL = 1; // PC
+ WE = 6'b010100; // PC, tmpHI
+ next_stage = 1;
+ M1 = 0;
+ end
+ endcase
+ 2'b01: // IN A, (n)
+ case(STAGE[1:0])
+ 2'b00: begin //stage1 - read n
+ ALU160_SEL = 1; // pc
+ DINW_SEL = 1; // DI
+ WE = 6'b010x01; // PC, lo
+ next_stage = 1;
+ REG_WSEL = 4'b011x; // tmpLO
+ M1 = 0;
+ end
+ 2'b01: begin // stage2 - IN
+ ALU160_SEL = 0; // regs
+ DINW_SEL = 1; // DI
+ WE = 6'b000x1x; // hi
+ next_stage = 1;
+ REG_WSEL = 4'b011x; // A
+ REG_RSEL = 4'b011x; // A - tmpLO
+ M1 = 0;
+ MREQ = 0;
+ IORQ = 1;
+ end
+ 2'b10: begin // stage3 - fetch
+ ALU160_SEL = 1; // PC
+ WE = 6'b010x00; // PC
+ end
+ endcase
+ 2'b10: begin // EX DE, HL
+ ALU160_SEL = 1; // PC
+ WE = 6'b010x00; // PC
+ if(CPUStatus[1]) status[3] = 1;
+ else status[2] = 1;
+ end
+ 2'b11: begin // EI
+ ALU160_SEL = 1; // PC
+ WE = 6'b010x00; // PC
+ status[11] = 1'b1;
+ status[7:6] = 2'b11;
+ end
+ endcase
+// ----------------------- CALL , IX, ED, IY --------------------
+ 4'b1101:
+ case(FETCH[5:4])
+ 2'b00: // CALL
+ case(STAGE[2:0])
+ 3'b000, 3'b001: begin // stage 1,2 - load addr
+ ALU160_SEL = 1; // pc
+ DINW_SEL = 1; // DI
+ WE = {4'b010x, STAGE[0] ? 1'b1 : 1'bx, !STAGE[0]}; // PC, hi/lo
+ next_stage = 1;
+ REG_WSEL = 4'b111x; // tmp7
+ M1 = 0;
+ end
+ 3'b010, 3'b011: begin // stage 3,4 - push pc
+ DO_SEL = {1'b0, STAGE[0]}; // pc hi/lo
+ ALU160_SEL = 0; // regs
+ WE = 6'b001x00; // SP
+ ALU16OP = 5; // DEC
+ next_stage = 1;
+ REG_WSEL = 4'b1xxx; // pc
+ REG_RSEL = 4'b101x; // sp
+ M1 = 0;
+ WR = 1;
+ end
+ 3'b100: begin // stage5 - jump
+ ALU160_SEL = 0; // regs
+ WE = 6'b010x00; // PC
+ REG_RSEL = 4'b111x; // tmp7
+ end
+ endcase
+ 2'b01: begin // DD - IX
+ ALU160_SEL = 1; // PC
+ WE = 6'b010x00; // PC
+ status[5:4] = 2'b01;
+ end
+ 2'b10: begin // ED prefix
+ ALU160_SEL = 1; // PC
+ WE = 6'b010x00; // PC
+ fetch98 = 2'b01;
+ end
+ 2'b11: begin // FD - IY
+ ALU160_SEL = 1; // PC
+ WE = 6'b010x00; // PC
+ status[5:4] = 2'b11;
+ end
+ endcase
+ endcase
+
+// ------------------------------------------- ED + opcode ----------------------------------------------------
+ 4'b0100, 4'b0111: begin // ED + 2'b00, ED + 2'b11 = NOP
+ ALU160_SEL = 1; // PC
+ WE = 6'b010x00; // PC
+ end
+ 4'b0101:
+ case(FETCH[2:0])
+// ----------------------- in r (C) --------------------
+ 3'b000:
+ if(!STAGE[0]) begin
+ ALU160_SEL = 0; // regs
+ DINW_SEL = 1; // DI
+ WE = {4'b000x, !opd[3], opd[3]} ; // hi/lo
+ next_stage = 1;
+ REG_WSEL = {1'b0, opd[5:4], 1'bx};
+ REG_RSEL = 4'b000x; // BC
+ M1 = 0;
+ MREQ = 0;
+ IORQ = 1;
+ end else begin
+ ALU160_SEL = 1; // pc
+ WE = 6'b110x00; // flags, PC
+ ALU8OP = 29; // IN
+ REG_RSEL = {1'b0, opd[5:3]}; // reg
+ end
+// ----------------------- out (C) r --------------------
+ 3'b001:
+ if(!STAGE[0]) begin
+ DO_SEL = 2'b00; // ALU80
+ ALU160_SEL = 0; // regs
+ WE = 6'b000x00; // nothing
+ next_stage = 1;
+ REG_WSEL = &opd[5:3] ? 4'b110x : {1'b0, opd[5:3]}; // zero/reg
+ REG_RSEL = 4'b000x; // BC
+ M1 = 0;
+ MREQ = 0;
+ WR = 1;
+ IORQ = 1;
+ end else begin
+ ALU160_SEL = 1; // pc
+ WE = 6'b010x00; // PC
+ end
+// ----------------------- SBC16, ADC16 --------------------
+ 3'b010:
+ if(!STAGE[0]) begin // stage1
+ DINW_SEL = 0; // ALU8OUT
+ WE = 6'b100x01; // flags, lo
+ ALU8OP = {3'b000, !FETCH[3], 1'b1}; // SBC/ADC
+ next_stage = 1;
+ REG_WSEL = 4'b0101; // L
+ REG_RSEL = {op16, 1'b1};
+ M1 = 0;
+ MREQ = 0;
+ end else begin
+ ALU160_SEL = 1; // pc
+ DINW_SEL = 0; // ALU8OUT
+ WE = 6'b110x10; // flags, PC, hi
+ ALU8OP = {3'b000, !FETCH[3], 1'b1};
+ REG_WSEL = 4'b0100; // H
+ REG_RSEL = {op16, 1'b0};
+ end
+// ----------------------- LD (nn) r16, ld r16 (nn) --------------------
+ 3'b011:
+ case(STAGE[2:1])
+ 2'b00: begin // stage 1,2 - read address
+ ALU160_SEL = 1; // pc
+ DINW_SEL = 1; // DI
+ WE = {4'b010x, STAGE[0] ? 1'b1 : 1'bx, !STAGE[0]}; // PC, hi/lo
+ next_stage = 1;
+ REG_WSEL = 4'b111x; // tmp16
+ M1 = 0;
+ end
+ 2'b01: begin
+ ALU160_SEL = 0; // regs
+ next_stage = 1;
+ ALU16OP = {2'b00, STAGE[0]};
+ REG_RSEL = 4'b111x; // tmp16
+ REG_WSEL = {op16, !STAGE[0]};
+ M1 = 0;
+ if(FETCH[3]) begin // LD rr, (nn) - stage3,4
+ DINW_SEL = 1; // DI
+ WE = {4'b000x, STAGE[0] ? 1'b1 : 1'bx, !STAGE[0]}; // lo
+ end else begin // LD (nn), rr - stage3,4
+ DO_SEL = op16[2] ? {1'b1, !STAGE[0]} : 2'b00; // ALU80/sp
+ WE = 6'b000x00; // nothing
+ WR = 1;
+ end
+ end
+ 2'b10: // stage5
+ if(FETCH[3] & op16[2] & !STAGE[0]) begin // LD sp, (nn) - stage5
+ ALU160_SEL = 0; // regs
+ WE = 6'b001x00; // SP
+ ALU16OP = 4; // NOP
+ next_stage = 1;
+ REG_RSEL = 4'b101x; // tmp SP
+ M1 = 0;
+ MREQ = 0;
+ end else begin
+ ALU160_SEL = 1; // pc
+ WE = 6'b010x00; // PC
+ end
+ endcase
+// ----------------------- NEG --------------------
+ 3'b100: begin
+ ALU160_SEL = 1; // pc
+ DINW_SEL = 0; // ALU8OUT
+ WE = 6'b110x10; // flags, PC, hi
+ ALU8OP = 5'b11111; // NEG
+ REG_WSEL = 4'b011x; // A
+ REG_RSEL = 4'b0110; // A
+ end
+// ----------------------- RETN, RETI --------------------
+ 3'b101:
+ case(STAGE[1:0])
+ 2'b00, 2'b01: begin // stage1, stage2 - pop addr
+ ALU160_SEL = 0; // regs
+ DINW_SEL = 1; // DI
+ WE = {4'b001x, STAGE[0] ? 1'b1 : 1'bx, !STAGE[0]}; // SP, lo/hi
+ next_stage = 1;
+ REG_WSEL = 4'b111x; // tmp16
+ REG_RSEL = 4'b101x; // SP
+ M1 = 0;
+ end
+ 2'b10: begin // stage3 - jump
+ ALU160_SEL = 0; // regs
+ WE = 6'b010x00; // PC
+ REG_RSEL = 4'b111x; // tmp16
+ status[11] = 1'b1;
+ status[7:6] = {CPUStatus[7], CPUStatus[7]};
+ end
+ endcase
+// ----------------------- IM --------------------
+ 3'b110: begin
+ ALU160_SEL = 1; // PC
+ WE = 6'b010x00; // PC
+ status[10:8] = {1'b1, FETCH[4:3]};
+ end
+// ----------------------- LD I A, LD R A, LD A I, LD A R, RRD, RLD --------------------
+ 3'b111:
+ case(FETCH[5:4])
+ 2'b00: begin // LD I/R A
+ ALU160_SEL = 1; // pc
+ DINW_SEL = 1'b0; // ALU8OUT
+ WE = {4'b010x, !FETCH[3], FETCH[3]}; // PC, hi/lo
+ ALU8OP = 29; // pass D1
+ REG_WSEL = 4'b1001; // IR, write r
+ REG_RSEL = 4'b0110; // A
+ end
+ 2'b01: begin // LD A I/R
+ ALU160_SEL = 1; // pc
+ DINW_SEL = 1'b0; // ALU8OUT
+ WE = 6'b110x1x; // flags, PC, hi
+ ALU8OP = 29; // PASS D1
+ REG_WSEL = 4'b011x; // A
+ REG_RSEL = {3'b100, FETCH[3]};// I/R
+ end
+ 2'b10: // RRD, RLD
+ case(STAGE[1:0])
+ 2'b00:begin // stage1, read data
+ ALU160_SEL = 0; // regs
+ DINW_SEL = 1; // DI
+ WE = 6'b000x01; // lo
+ next_stage = 1;
+ REG_WSEL = 4'b011x; // tmpLO
+ REG_RSEL = 4'b010x; // HL
+ M1 = 0;
+ end
+ 2'b01: begin // stage2, shift data
+ DINW_SEL = 0; // ALU8OUT
+ WE = 6'b100x11; // flags, hi, lo
+ ALU8OP = FETCH[3] ? 5'b01100 : 5'b01011; // RRD/RLD
+ next_stage = 1;
+ REG_WSEL = 4'b0110; // A
+ REG_RSEL = 4'b0111; // tmpLO
+ M1 = 0;
+ MREQ = 0;
+ end
+ 2'b10: begin // stage3 - write
+ DO_SEL = 2'b00; // ALU80
+ ALU160_SEL = 0; // regs
+ WE = 6'b000x0x; // nothing
+ next_stage = 1;
+ REG_WSEL = 4'b0111; // tmpLO
+ REG_RSEL = 4'b010x; // HL
+ M1 = 0;
+ WR = 1;
+ end
+ 2'b11: begin
+ ALU160_SEL = 1; // PC
+ WE = 6'b010x00; // PC
+ end
+ endcase
+ 2'b11: begin // NOP
+ ALU160_SEL = 1; // PC
+ WE = 6'b010x00; // PC
+ end
+ endcase
+ endcase
+// ----------------------- block instructions --------------------
+ 4'b0110:
+ if({FETCH[5], FETCH[2]} == 4'b10)
+ case(FETCH[1:0])
+ 2'b00: // LDI, LDD, LDIR, LDDR
+ case(STAGE[1:0])
+ 2'b00: begin // stage1, read data, inc/dec HL
+ ALU160_SEL = 0; // regs
+ DINW_SEL = 0; // ALU8OUT
+ WE = 6'b100111; // flags, tmpHI, hi, lo
+ ALU8OP = {4'b0111, FETCH[3]}; // INC/DEC16
+ next_stage = 1;
+ REG_WSEL = 4'b0100; // H
+ REG_RSEL = 4'b0101; // L
+ M1 = 0;
+ end
+ 2'b01: begin // stage2, dec BC
+ DINW_SEL = 0; // ALU8OUT
+ WE = 6'b100011; // flags, hi, lo (affects PF only)
+ ALU8OP = 5'b01111; // DEC
+ next_stage = 1;
+ REG_WSEL = 4'b0000; // B
+ REG_RSEL = 4'b0001; // C
+ M1 = 0;
+ MREQ = 0;
+ end
+ 2'b10: begin // stage2, write data, inc/dec DE
+ DO_SEL = 2'b01; // th
+ ALU160_SEL = 0; // regs
+ DINW_SEL = 0; // ALU8OUT
+ WE = 6'b000x11; // hi, lo
+ ALU8OP = {4'b0111, FETCH[3]}; // INC / DEC
+ next_stage = FETCH[4] ? !FLAGS[2] : 1'b1;
+ REG_WSEL = 4'b0010; // D
+ REG_RSEL = 4'b0011; // E
+ M1 = 0;
+ WR = 1;
+ end
+ 2'b11: begin
+ ALU160_SEL = 1; // PC
+ WE = 6'b010x00; // PC
+ end
+ endcase
+ 2'b01: // CPI, CPD, CPIR, CPDR
+ case(STAGE[1:0])
+ 2'b00: begin // stage1, load data
+ ALU160_SEL = 0; // regs
+ DINW_SEL = 1; // DI
+ WE = 6'b000x01; // lo
+ next_stage = 1;
+ REG_WSEL = 4'b011x; // tmpLO
+ REG_RSEL = 4'b010x; // HL
+ M1 = 0;
+ end
+ 2'b01: begin // stage2, CP
+ WE = 6'b100x0x; // flags
+ ALU8OP = 7; // CP
+ next_stage = 1;
+ REG_WSEL = 4'b0110; // A
+ REG_RSEL = 4'b0111; // tmpLO
+ M1 = 0;
+ MREQ = 0;
+ end
+ 2'b10: begin // stage3, dec BC
+ DINW_SEL = 0; // ALU8OUT
+ WE = 6'b100x11; // flags, hi, lo
+ ALU8OP = 5'b01111; // DEC16
+ next_stage = 1;
+ REG_WSEL = 4'b0000; // B
+ REG_RSEL = 4'b0001; // C
+ M1 = 0;
+ MREQ = 0;
+ end
+ 2'b11: begin // stage4, inc/dec HL
+ ALU160_SEL = 1; // pc
+ DINW_SEL = 0; // ALU8OUT
+ M1 = FETCH[4] ? (!FLAGS[2] || FLAGS[6]) : 1'b1;
+ WE = {1'b0, M1, 4'b0x11}; // PC, hi, lo
+ ALU8OP = {4'b0111, FETCH[3]}; // INC / DEC
+ REG_WSEL = 4'b0100; // H
+ REG_RSEL = 4'b0101; // L
+ MREQ = M1;
+ end
+ endcase
+ 2'b10: // INI, IND, INIR, INDR
+ case(STAGE[1:0])
+ 2'b00: begin // stage1, in data, dec B
+ ALU160_SEL = 0; // regs
+ DINW_SEL = 0; // ALU8OUT
+ WE = 6'b100110; // flags, tmpHI, hi
+ ALU8OP = 10; // DEC
+ next_stage = 1;
+ REG_WSEL = 4'b0000; // B
+ REG_RSEL = 4'b000x; // BC
+ M1 = 0;
+ MREQ = 0;
+ IORQ = 1;
+ end
+ 2'b01: begin // stage2, write data, inc/dec HL
+ DO_SEL = 2'b01; // th
+ ALU160_SEL = 0; // regs
+ DINW_SEL = 0; // ALU8OUT
+ WE = 6'b000x11; // hi, lo
+ ALU8OP = {4'b0111, FETCH[3]}; // INC / DEC
+ next_stage = FETCH[4] ? FLAGS[6] : 1'b1;
+ REG_WSEL = 4'b0100; // H
+ REG_RSEL = 4'b0101; // L
+ M1 = 0;
+ WR = 1;
+ end
+ 2'b10: begin // stage3
+ ALU160_SEL = 1; // pc
+ WE = 6'b010x00; // PC
+ end
+ endcase
+ 2'b11: // OUTI/OUTD/OTIR/OTDR
+ case(STAGE[1:0])
+ 2'b00: begin // stage1, load data, inc/dec HL
+ ALU160_SEL = 0; // regs
+ DINW_SEL = 0; // ALU8OUT
+ WE = 6'b000111; // tmpHI, hi, lo
+ ALU8OP = {4'b0111, FETCH[3]}; // INC / DEC
+ next_stage = 1;
+ REG_WSEL = 4'b0100; // H
+ REG_RSEL = 4'b0101; // L
+ M1 = 0;
+ end
+ 2'b01: begin // stage2, out data, dec B
+ DO_SEL = 2'b01; // th
+ ALU160_SEL = 0; // regs
+ DINW_SEL = 0; // ALU8OUT
+ WE = 6'b100x10; // flags, hi
+ ALU8OP = 10; // DEC
+ next_stage = FETCH[4] ? (ALU80 == 8'b00000001) : 1'b1;
+ REG_WSEL = 4'b0000; // B
+ REG_RSEL = 4'b000x; // BC
+ M1 = 0;
+ MREQ = 0;
+ IORQ = 1;
+ WR = 1;
+ end
+ 2'b10: begin // stage3
+ ALU160_SEL = 1; // pc
+ WE = 6'b010x00; // PC
+ end
+ endcase
+ endcase
+ else begin // NOP
+ ALU160_SEL = 1; // PC
+ WE = 6'b010x00; // PC
+ end
+//------------------------------------------- CB + opcode ----------------------------------------------------
+ 4'b1000, 4'b1001, 4'b1010, 4'b1011: // CB class (rot/shift, bit/res/set)
+ case({STAGE[1:0], CPUStatus[4], op0mem})
+ 4'b00_0_0: begin // execute reg-reg
+ DINW_SEL = 0; // ALU8OUT
+ ALU160_SEL = 1; // pc
+ WE = {!FETCH[7], 3'b10x, FETCH[7:6] == 2'b01 ? 2'b00 : {!opd[0], opd[0]}}; // flags, hi/lo
+ ALU8OP = 28; // BIT
+ REG_WSEL = {1'b0, opd[2:0]};
+ end
+ 4'b00_0_1, 4'b00_1_0, 4'b00_1_1: begin // stage1, (HL-X) - read data
+ ALU160_SEL = 0; // regs
+ DINW_SEL = 1; // DI
+ WE = opd[0] ? 6'b000001 : 6'b000010; // lo/hi
+ ALU16OP = CPUStatus[4] ? 3'd3 : 3'd0; // ADD - NOP
+ next_stage = 1;
+ REG_WSEL = FETCH[7:6] == 2'b01 ? 4'b111x : {1'b0, opd[2:0]}; // dest, tmp16 for BIT
+ REG_RSEL = 4'b010x; // HL
+ M1 = 0;
+ end
+ 4'b01_0_1, 4'b01_1_0, 4'b01_1_1: // stage2 (HL-X) - execute, write
+ case(FETCH[7:6])
+ 2'b00, 2'b10, 2'b11: begin // exec + write
+ DINW_SEL = 0; // ALU8OUT
+ DO_SEL = 2'b11; // ALU8OUT[7:0]
+ ALU160_SEL = 0; // regs
+ WE = {!FETCH[7], 3'b00x, !opd[0], opd[0]}; // flags, hi/lo
+ ALU8OP = 28;
+ ALU16OP = CPUStatus[4] ? 3'd3 : 3'd0;
+ next_stage = 1;
+ REG_WSEL = {1'b0, opd[2:0]};
+ REG_RSEL = 4'b010x; // HL
+ M1 = 0;
+ WR = 1;
+ end
+ 2'b01: begin // BIT, no write
+ ALU160_SEL = 1; // pc
+ WE = 6'b110xxx; // flags, PC
+ ALU8OP = 28; // BIT
+ REG_WSEL = {3'b111, opd[0]}; // tmp
+ end
+ endcase
+ 4'b10_0_1, 4'b10_1_0, 4'b10_1_1: begin // (HL-X) - load next op
+ ALU160_SEL = 1; // pc
+ WE = 6'b010x00; // PC
+ end
+ endcase
+//------------------------------------------- // RST, NMI, INT ----------------------------------------------------
+ 4'b1110: begin // RESET: IR <- 0, IM <- 0, IFF1,IFF2 <- 0, pC <- 0
+ ALU160_SEL = 0; // regs
+ DINW_SEL = 0; // ALU8OUT
+ WE = 6'bx1xx11; // PC, hi, lo
+ ALU8OP = 29; // pass D1
+ ALU16OP = 4; // NOP
+ REG_WSEL = 4'b1001; // IR, write r
+ REG_RSEL = 4'b110x; // const
+ M1 = 0;
+ MREQ = 0;
+ status[11:6] = 6'b110000; // IM0, DI
+ end
+ 4'b1101: // NMI
+ case(STAGE[1:0])
+ 2'b00: begin
+ ALU160_SEL = 1; // pc
+ WE = 6'b010x00; // PC
+ ALU16OP = intop; // DEC/DEC2 (if block instruction interrupted)
+ next_stage = 1;
+ M1 = 0;
+ MREQ = 0;
+ end
+ 2'b01, 2'b10: begin
+ DO_SEL = {1'b0, !STAGE[0]}; // pc hi/lo
+ ALU160_SEL = 0; // regs
+ WE = 6'b001x00; // SP
+ ALU16OP = 5; // DEC
+ next_stage = 1;
+ REG_WSEL = 4'b1xxx; // pc
+ REG_RSEL = 4'b101x; // sp
+ M1 = 0;
+ WR = 1;
+ status[11] = 1'b1;
+ status[7:6] = {CPUStatus[7], 1'b0}; // reset IFF1
+ end
+ 2'b11: begin
+ ALU160_SEL = 0; // regs
+ WE = 6'b010x00; // PC
+ REG_RSEL = 4'b110x; // const
+ end
+ endcase
+ 4'b1100: // INT
+ case(CPUStatus[9:8])
+ 2'b00, 2'b01, 2'b10: begin // IM0, IM1
+ ALU160_SEL = 1; // pc
+ WE = 6'b010x00; // PC
+ ALU16OP = intop; // DEC/DEC2 (if block instruction interrupted)
+ MREQ = 0;
+ IORQ = 1;
+ status[11] = 1'b1;
+ status[7:6] = 2'b0; // reset IFF1, IFF2
+ end
+ 2'b11: // IM2
+ case(STAGE[2:0])
+ 3'b000: begin
+ ALU160_SEL = 1; // pc
+ DINW_SEL = 1; // DI
+ WE = 6'b010x01; // PC, lo
+ ALU16OP = intop; // DEC/DEC2 (if block instruction interrupted)
+ next_stage = 1;
+ REG_WSEL = 4'b1000; // Itmp, no write r
+ MREQ = 0;
+ IORQ = 1;
+ status[11] = 1'b1;
+ status[7:6] = 2'b0; // reset IFF1, IFF2
+ end
+ 3'b001, 3'b010: begin // push pc
+ DO_SEL = {1'b0, !STAGE[0]}; // pc hi/lo
+ ALU160_SEL = 0; // regs
+ WE = 6'b001x00; // SP
+ ALU16OP = 5; // DEC
+ next_stage = 1;
+ REG_WSEL = 4'b1xxx; // pc
+ REG_RSEL = 4'b101x; // sp
+ M1 = 0;
+ WR = 1;
+ end
+ 3'b011, 3'b100: begin // read address
+ ALU160_SEL = 0; // regs
+ DINW_SEL = 1; // DI
+ WE = {4'b0x0x, STAGE[0] ? 1'bx : 1'b1, STAGE[0]}; // hi/lo
+ ALU16OP = {2'b00, !STAGE[0]};// NOP/INC
+ next_stage = 1;
+ REG_WSEL = 4'b111x; // tmp16
+ REG_RSEL = 4'b1000; // I-Itmp
+ M1 = 0;
+ end
+ 3'b101: begin // jump
+ ALU160_SEL = 0; // regs
+ WE = 6'b010x00; // PC
+ REG_RSEL = 4'b111x; // tmp16
+ end
+ endcase
+ endcase
+ endcase
+ end
+
+endmodule
diff --git a/common/CPU/NextZ80/NextZ80Reg.v b/common/CPU/NextZ80/NextZ80Reg.v
new file mode 100644
index 00000000..65d99661
--- /dev/null
+++ b/common/CPU/NextZ80/NextZ80Reg.v
@@ -0,0 +1,199 @@
+//////////////////////////////////////////////////////////////////////////////////
+//
+// This file is part of the NextZ80 project
+// http://www.opencores.org/cores/nextz80/
+//
+// Filename: NextZ80Regs.v
+// Description: Implementation of Z80 compatible CPU - registers
+// Version 1.0
+// Creation date: 28Jan2011 - 18Mar2011
+//
+// Author: Nicolae Dumitrache
+// e-mail: ndumitrache@opencores.org
+//
+/////////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2011 Nicolae Dumitrache
+//
+// This source file may be used and distributed without
+// restriction provided that this copyright statement is not
+// removed from the file and that any derivative work contains
+// the original copyright notice and the associated disclaimer.
+//
+// This source file is free software; you can redistribute it
+// and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation;
+// either version 2.1 of the License, or (at your option) any
+// later version.
+//
+// This source 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 Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General
+// Public License along with this source; if not, download it
+// from http://www.opencores.org/lgpl.shtml
+//
+///////////////////////////////////////////////////////////////////////////////////
+`timescale 1ns / 1ps
+
+module Z80Reg(
+ input wire [7:0]rstatus, // 0=af-af', 1=exx, 2=hl-de, 3=hl'-de',4=hl-ixy, 5=ix-iy, 6=IFF1, 7=IFF2
+ input wire M1,
+ input wire [5:0]WE, // 5 = flags, 4 = PC, 3 = SP, 2 = tmpHI, 1 = hi, 0 = lo
+ input wire CLK,
+ input wire [15:0]ALU8OUT, // CPU data out bus (output of alu8)
+ input wire [7:0]DI, // CPU data in bus
+ output reg [7:0]DO, // CPU data out bus
+ input wire [15:0]ADDR, // CPU addr bus
+ input wire [7:0]CONST,
+ output reg [7:0]ALU80,
+ output reg [7:0]ALU81,
+ output reg [15:0]ALU160,
+ output wire[7:0]ALU161,
+ input wire [7:0]ALU8FLAGS,
+ output wire [7:0]FLAGS,
+
+ input wire [1:0]DO_SEL, // select DO betwen ALU8OUT lo and th register
+ input wire ALU160_sel, // 0=REG_RSEL, 1=PC
+ input wire [3:0]REG_WSEL, // rdow: [3:1] 0=BC, 1=DE, 2=HL, 3=A-TL, 4=I-x ----- [0] = 0HI,1LO
+ input wire [3:0]REG_RSEL, // mux_rdor: [3:1] 0=BC, 1=DE, 2=HL, 3=A-TL, 4=I-R, 5=SP, 7=tmpSP ----- [0] = 0HI, 1LO
+ input wire DINW_SEL, // select RAM write data between (0)ALU8OUT, and 1(DI)
+ input wire XMASK, // 0 if REG_WSEL should not use IX, IY, even if rstatus[4] == 1
+ input wire [2:0]ALU16OP, // ALU16OP
+ input wire WAIT // wait
+ );
+
+// latch registers
+ reg [15:0]pc=0; // program counter
+ reg [15:0]sp; // stack pointer
+ reg [7:0]r; // refresh
+ reg [15:0]flg = 0;
+ reg [7:0]th; // temp high
+
+// internal wires
+ wire [15:0]rdor; // R out from RAM
+ wire [15:0]rdow; // W out from RAM
+ wire [3:0]SELW; // RAM W port sel
+ wire [3:0]SELR; // RAM R port sel
+ reg [15:0]DIN; // RAM W in data
+ reg [15:0]mux_rdor; // (3)A reversed mixed with TL, (4)I mixed with R (5)SP
+
+//------------------------------------ RAM block registers ----------------------------------
+// 0:BC, 1:DE, 2:HL, 3:A-x, 4:I-x, 5:IX, 6:IY, 7:x-x, 8:BC', 9:DE', 10:HL', 11:A'-x, 12: tmpSP, 13:zero
+ RAM16X8D_regs regs_lo (
+ .DPO(rdor[7:0]), // Read-only data output
+ .SPO(rdow[7:0]), // R/W data output
+ .A(SELW), // R/W address
+ .D(DIN[7:0]), // Write data input
+ .DPRA(SELR), // Read-only address
+ .WCLK(CLK), // Write clock input
+ .WE(WE[0] & !WAIT) // Write enable input
+ );
+
+ RAM16X8D_regs regs_hi (
+ .DPO(rdor[15:8]), // Read-only data output
+ .SPO(rdow[15:8]), // R/W data output
+ .A(SELW), // R/W address
+ .D(DIN[15:8]), // Write data input
+ .DPRA(SELR), // Read-only address
+ .WCLK(CLK), // Write clock input
+ .WE(WE[1] & !WAIT) // Write enable input
+ );
+
+ wire [15:0]ADDR1 = ADDR + !ALU16OP[2]; // address post increment
+ wire [7:0]flgmux = {ALU8FLAGS[7:3], SELR[3:0] == 4'b0100 ? rstatus[7] : ALU8FLAGS[2], ALU8FLAGS[1:0]}; // LD A, I/R IFF2 flag on parity
+ always @(posedge CLK)
+ if(!WAIT) begin
+ if(WE[2]) th <= DI;
+ if(WE[3]) sp <= ADDR1;
+ if(WE[4]) pc <= ADDR1;
+ if({REG_WSEL, WE[0]} == 5'b10011) r <= ALU8OUT[7:0];
+ else if(M1) r[6:0] <= r[6:0] + 1;
+ if(WE[5])
+ if(rstatus[0]) flg[15:8] <= flgmux;
+ else flg[7:0] <= flgmux;
+ end
+
+ assign ALU161 = th;
+ assign FLAGS = rstatus[0] ? flg[15:8] : flg[7:0];
+
+ always @* begin
+ DIN = DINW_SEL ? {DI, DI} : ALU8OUT;
+ ALU80 = REG_WSEL[0] ? rdow[7:0] : rdow[15:8];
+ ALU81 = REG_RSEL[0] ? mux_rdor[7:0] : mux_rdor[15:8];
+ ALU160 = ALU160_sel ? pc : mux_rdor;
+
+ case({REG_WSEL[3], DO_SEL})
+ 0: DO = ALU80;
+ 1: DO = th;
+ 2: DO = FLAGS;
+ 3: DO = ALU8OUT[7:0];
+ 4: DO = pc[15:8];
+ 5: DO = pc[7:0];
+ 6: DO = sp[15:8];
+ 7: DO = sp[7:0];
+ endcase
+ case({ALU16OP == 4, REG_RSEL[3:0]})
+ 5'b01001, 5'b11001: mux_rdor = {rdor[15:8], r};
+ 5'b01010, 5'b01011: mux_rdor = sp;
+ 5'b01100, 5'b01101, 5'b11100, 5'b11101: mux_rdor = {8'b0, CONST};
+ default: mux_rdor = rdor;
+ endcase
+ end
+
+ RegSelect WSelectW(.SEL(REG_WSEL[3:1]), .RAMSEL(SELW), .rstatus({rstatus[5], rstatus[4] & XMASK, rstatus[3:0]}));
+ RegSelect WSelectR(.SEL(REG_RSEL[3:1]), .RAMSEL(SELR), .rstatus(rstatus[5:0]));
+
+endmodule
+
+
+module RegSelect(
+ input [2:0]SEL,
+ output reg [3:0]RAMSEL,
+ input [5:0]rstatus // 0=af-af', 1=exx, 2=hl-de, 3=hl'-de',4=hl-ixy, 5=ix-iy
+ );
+
+ always @* begin
+ RAMSEL = 4'bxxxx;
+ case(SEL)
+ 0: RAMSEL = {rstatus[1], 3'b000}; // BC
+ 1: //DE
+ if(rstatus[{1'b1, rstatus[1]}]) RAMSEL = {rstatus[1], 3'b010}; // HL
+ else RAMSEL = {rstatus[1], 3'b001}; // DE
+ 2: // HL
+ case({rstatus[5:4], rstatus[{1'b1, rstatus[1]}]})
+ 0,4: RAMSEL = {rstatus[1], 3'b010}; // HL
+ 1,5: RAMSEL = {rstatus[1], 3'b001}; // DE
+ 2,3: RAMSEL = 4'b0101; // IX
+ 6,7: RAMSEL = 4'b0110; // IY
+ endcase
+ 3: RAMSEL = {rstatus[0], 3'b011}; // A-TL
+ 4: RAMSEL = 4; // I-R
+ 5: RAMSEL = 12; // tmp SP
+ 6: RAMSEL = 13; // zero
+ 7: RAMSEL = 7; // temp reg for BIT/SET/RES
+ endcase
+ end
+endmodule
+
+module RAM16X8D_regs(
+ output [7:0]DPO, // Read-only data output
+ output [7:0]SPO, // R/W data output
+ input [3:0]A, // R/W address
+ input [7:0]D, // Write data input
+ input [3:0]DPRA, // Read-only address
+ input WCLK, // Write clock
+ input WE // Write enable
+ );
+
+ reg [7:0]data[15:0];
+ assign DPO = data[DPRA];
+ assign SPO = data[A];
+
+ always @(posedge WCLK)
+ if(WE) data[A] <= D;
+
+endmodule
diff --git a/common/CPU/T65/pack_t65.vhd b/common/CPU/T65/pack_t65.vhd
new file mode 100644
index 00000000..fbe4afe1
--- /dev/null
+++ b/common/CPU/T65/pack_t65.vhd
@@ -0,0 +1,117 @@
+-- ****
+-- T65(b) core. In an effort to merge and maintain bug fixes ....
+--
+--
+-- Ver 300 Bugfixes by ehenciak added
+-- MikeJ March 2005
+-- Latest version from www.fpgaarcade.com (original www.opencores.org)
+--
+-- ****
+--
+-- 65xx compatible microprocessor core
+--
+-- Version : 0246
+--
+-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t65/
+--
+-- Limitations :
+--
+-- File history :
+--
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+
+package pack_t65 is
+
+ constant Flag_C : integer := 0;
+ constant Flag_Z : integer := 1;
+ constant Flag_I : integer := 2;
+ constant Flag_D : integer := 3;
+ constant Flag_B : integer := 4;
+ constant Flag_1 : integer := 5;
+ constant Flag_V : integer := 6;
+ constant Flag_N : integer := 7;
+
+ component T65_MCode
+ port(
+ Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816
+ IR : in std_logic_vector(7 downto 0);
+ MCycle : in std_logic_vector(2 downto 0);
+ P : in std_logic_vector(7 downto 0);
+ LCycle : out std_logic_vector(2 downto 0);
+ ALU_Op : out std_logic_vector(3 downto 0);
+ Set_BusA_To : out std_logic_vector(2 downto 0); -- DI,A,X,Y,S,P
+ Set_Addr_To : out std_logic_vector(1 downto 0); -- PC Adder,S,AD,BA
+ Write_Data : out std_logic_vector(2 downto 0); -- DL,A,X,Y,S,P,PCL,PCH
+ Jump : out std_logic_vector(1 downto 0); -- PC,++,DIDL,Rel
+ BAAdd : out std_logic_vector(1 downto 0); -- None,DB Inc,BA Add,BA Adj
+ BreakAtNA : out std_logic;
+ ADAdd : out std_logic;
+ AddY : out std_logic;
+ PCAdd : out std_logic;
+ Inc_S : out std_logic;
+ Dec_S : out std_logic;
+ LDA : out std_logic;
+ LDP : out std_logic;
+ LDX : out std_logic;
+ LDY : out std_logic;
+ LDS : out std_logic;
+ LDDI : out std_logic;
+ LDALU : out std_logic;
+ LDAD : out std_logic;
+ LDBAL : out std_logic;
+ LDBAH : out std_logic;
+ SaveP : out std_logic;
+ Write : out std_logic
+ );
+ end component;
+
+ component T65_ALU
+ port(
+ Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816
+ Op : in std_logic_vector(3 downto 0);
+ BusA : in std_logic_vector(7 downto 0);
+ BusB : in std_logic_vector(7 downto 0);
+ P_In : in std_logic_vector(7 downto 0);
+ P_Out : out std_logic_vector(7 downto 0);
+ Q : out std_logic_vector(7 downto 0)
+ );
+ end component;
+
+end;
\ No newline at end of file
diff --git a/common/CPU/T65/t65.vhd b/common/CPU/T65/t65.vhd
new file mode 100644
index 00000000..b0a11b50
--- /dev/null
+++ b/common/CPU/T65/t65.vhd
@@ -0,0 +1,553 @@
+-- ****
+-- T65(b) core. In an effort to merge and maintain bug fixes ....
+--
+--
+-- Ver 301 more merging
+-- Ver 300 Bugfixes by ehenciak added, started tidyup *bust*
+-- MikeJ March 2005
+-- Latest version from www.fpgaarcade.com (original www.opencores.org)
+--
+-- ****
+--
+-- 65xx compatible microprocessor core
+--
+-- Version : 0246
+--
+-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t65/
+--
+-- Limitations :
+--
+-- 65C02 and 65C816 modes are incomplete
+-- Undocumented instructions are not supported
+-- Some interface signals behaves incorrect
+--
+-- File history :
+--
+-- 0246 : First release
+--
+
+library IEEE;
+ use IEEE.std_logic_1164.all;
+ use IEEE.numeric_std.all;
+library work;
+ use work.pack_t65.all;
+
+-- ehenciak 2-23-2005 : Added the enable signal so that one doesn't have to use
+-- the ready signal to limit the CPU.
+entity T65 is
+ port(
+ Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816
+ Res_n : in std_logic;
+ Enable : in std_logic;
+ Clk : in std_logic;
+ Rdy : in std_logic;
+ Abort_n : in std_logic;
+ IRQ_n : in std_logic;
+ NMI_n : in std_logic;
+ SO_n : in std_logic;
+ R_W_n : out std_logic;
+ Sync : out std_logic;
+ EF : out std_logic;
+ MF : out std_logic;
+ XF : out std_logic;
+ ML_n : out std_logic;
+ VP_n : out std_logic;
+ VDA : out std_logic;
+ VPA : out std_logic;
+ A : out std_logic_vector(23 downto 0);
+ DI : in std_logic_vector(7 downto 0);
+ DO : out std_logic_vector(7 downto 0)
+ );
+end T65;
+
+architecture rtl of T65 is
+
+ -- Registers
+ signal ABC, X, Y, D : std_logic_vector(15 downto 0);
+ signal P, AD, DL : std_logic_vector(7 downto 0) := x"00";
+ signal BAH : std_logic_vector(7 downto 0);
+ signal BAL : std_logic_vector(8 downto 0);
+ signal PBR : std_logic_vector(7 downto 0);
+ signal DBR : std_logic_vector(7 downto 0);
+ signal PC : unsigned(15 downto 0);
+ signal S : unsigned(15 downto 0);
+ signal EF_i : std_logic;
+ signal MF_i : std_logic;
+ signal XF_i : std_logic;
+
+ signal IR : std_logic_vector(7 downto 0);
+ signal MCycle : std_logic_vector(2 downto 0);
+
+ signal Mode_r : std_logic_vector(1 downto 0);
+ signal ALU_Op_r : std_logic_vector(3 downto 0);
+ signal Write_Data_r : std_logic_vector(2 downto 0);
+ signal Set_Addr_To_r : std_logic_vector(1 downto 0);
+ signal PCAdder : unsigned(8 downto 0);
+
+ signal RstCycle : std_logic;
+ signal IRQCycle : std_logic;
+ signal NMICycle : std_logic;
+
+ signal B_o : std_logic;
+ signal SO_n_o : std_logic;
+ signal IRQ_n_o : std_logic;
+ signal NMI_n_o : std_logic;
+ signal NMIAct : std_logic;
+
+ signal Break : std_logic;
+
+ -- ALU signals
+ signal BusA : std_logic_vector(7 downto 0);
+ signal BusA_r : std_logic_vector(7 downto 0);
+ signal BusB : std_logic_vector(7 downto 0);
+ signal ALU_Q : std_logic_vector(7 downto 0);
+ signal P_Out : std_logic_vector(7 downto 0);
+
+ -- Micro code outputs
+ signal LCycle : std_logic_vector(2 downto 0);
+ signal ALU_Op : std_logic_vector(3 downto 0);
+ signal Set_BusA_To : std_logic_vector(2 downto 0);
+ signal Set_Addr_To : std_logic_vector(1 downto 0);
+ signal Write_Data : std_logic_vector(2 downto 0);
+ signal Jump : std_logic_vector(1 downto 0);
+ signal BAAdd : std_logic_vector(1 downto 0);
+ signal BreakAtNA : std_logic;
+ signal ADAdd : std_logic;
+ signal AddY : std_logic;
+ signal PCAdd : std_logic;
+ signal Inc_S : std_logic;
+ signal Dec_S : std_logic;
+ signal LDA : std_logic;
+ signal LDP : std_logic;
+ signal LDX : std_logic;
+ signal LDY : std_logic;
+ signal LDS : std_logic;
+ signal LDDI : std_logic;
+ signal LDALU : std_logic;
+ signal LDAD : std_logic;
+ signal LDBAL : std_logic;
+ signal LDBAH : std_logic;
+ signal SaveP : std_logic;
+ signal Write : std_logic;
+
+ signal really_rdy : std_logic;
+ signal R_W_n_i : std_logic;
+
+begin
+ -- ehenciak : gate Rdy with read/write to make an "OK, it's
+ -- really OK to stop the processor now if Rdy is
+ -- deasserted" signal
+ really_rdy <= Rdy or not(R_W_n_i);
+
+ -- ehenciak : Drive R_W_n_i off chip.
+ R_W_n <= R_W_n_i;
+
+ Sync <= '1' when MCycle = "000" else '0';
+ EF <= EF_i;
+ MF <= MF_i;
+ XF <= XF_i;
+ ML_n <= '0' when IR(7 downto 6) /= "10" and IR(2 downto 1) = "11" and MCycle(2 downto 1) /= "00" else '1';
+ VP_n <= '0' when IRQCycle = '1' and (MCycle = "101" or MCycle = "110") else '1';
+ VDA <= '1' when Set_Addr_To_r /= "000" else '0'; -- Incorrect !!!!!!!!!!!!
+ VPA <= '1' when Jump(1) = '0' else '0'; -- Incorrect !!!!!!!!!!!!
+
+ mcode : T65_MCode
+ port map(
+ Mode => Mode_r,
+ IR => IR,
+ MCycle => MCycle,
+ P => P,
+ LCycle => LCycle,
+ ALU_Op => ALU_Op,
+ Set_BusA_To => Set_BusA_To,
+ Set_Addr_To => Set_Addr_To,
+ Write_Data => Write_Data,
+ Jump => Jump,
+ BAAdd => BAAdd,
+ BreakAtNA => BreakAtNA,
+ ADAdd => ADAdd,
+ AddY => AddY,
+ PCAdd => PCAdd,
+ Inc_S => Inc_S,
+ Dec_S => Dec_S,
+ LDA => LDA,
+ LDP => LDP,
+ LDX => LDX,
+ LDY => LDY,
+ LDS => LDS,
+ LDDI => LDDI,
+ LDALU => LDALU,
+ LDAD => LDAD,
+ LDBAL => LDBAL,
+ LDBAH => LDBAH,
+ SaveP => SaveP,
+ Write => Write
+ );
+
+ alu : T65_ALU
+ port map(
+ Mode => Mode_r,
+ Op => ALU_Op_r,
+ BusA => BusA_r,
+ BusB => BusB,
+ P_In => P,
+ P_Out => P_Out,
+ Q => ALU_Q
+ );
+
+ process (Res_n, Clk)
+ begin
+ if Res_n = '0' then
+ PC <= (others => '0'); -- Program Counter
+ IR <= "00000000";
+ S <= (others => '0'); -- Dummy !!!!!!!!!!!!!!!!!!!!!
+ D <= (others => '0');
+ PBR <= (others => '0');
+ DBR <= (others => '0');
+
+ Mode_r <= (others => '0');
+ ALU_Op_r <= "1100";
+ Write_Data_r <= "000";
+ Set_Addr_To_r <= "00";
+
+ R_W_n_i <= '1';
+ EF_i <= '1';
+ MF_i <= '1';
+ XF_i <= '1';
+
+ elsif Clk'event and Clk = '1' then
+ if (Enable = '1') then
+ if (really_rdy = '1') then
+ R_W_n_i <= not Write or RstCycle;
+
+ D <= (others => '1'); -- Dummy
+ PBR <= (others => '1'); -- Dummy
+ DBR <= (others => '1'); -- Dummy
+ EF_i <= '0'; -- Dummy
+ MF_i <= '0'; -- Dummy
+ XF_i <= '0'; -- Dummy
+
+ if MCycle = "000" then
+ Mode_r <= Mode;
+
+ if IRQCycle = '0' and NMICycle = '0' then
+ PC <= PC + 1;
+ end if;
+
+ if IRQCycle = '1' or NMICycle = '1' then
+ IR <= "00000000";
+ else
+ IR <= DI;
+ end if;
+ end if;
+
+ ALU_Op_r <= ALU_Op;
+ Write_Data_r <= Write_Data;
+ if Break = '1' then
+ Set_Addr_To_r <= "00";
+ else
+ Set_Addr_To_r <= Set_Addr_To;
+ end if;
+
+ if Inc_S = '1' then
+ S <= S + 1;
+ end if;
+ if Dec_S = '1' and RstCycle = '0' then
+ S <= S - 1;
+ end if;
+ if LDS = '1' then
+ S(7 downto 0) <= unsigned(ALU_Q);
+ end if;
+
+ if IR = "00000000" and MCycle = "001" and IRQCycle = '0' and NMICycle = '0' then
+ PC <= PC + 1;
+ end if;
+ --
+ -- jump control logic
+ --
+ case Jump is
+ when "01" =>
+ PC <= PC + 1;
+
+ when "10" =>
+ PC <= unsigned(DI & DL);
+
+ when "11" =>
+ if PCAdder(8) = '1' then
+ if DL(7) = '0' then
+ PC(15 downto 8) <= PC(15 downto 8) + 1;
+ else
+ PC(15 downto 8) <= PC(15 downto 8) - 1;
+ end if;
+ end if;
+ PC(7 downto 0) <= PCAdder(7 downto 0);
+
+ when others => null;
+ end case;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ PCAdder <= resize(PC(7 downto 0),9) + resize(unsigned(DL(7) & DL),9) when PCAdd = '1'
+ else "0" & PC(7 downto 0);
+
+ process (Clk)
+ begin
+ if Clk'event and Clk = '1' then
+ if (Enable = '1') then
+ if (really_rdy = '1') then
+ if MCycle = "000" then
+ if LDA = '1' then
+ -- assert false report "Chargement A" severity warning;
+ ABC(7 downto 0) <= ALU_Q;
+ end if;
+ if LDX = '1' then
+ X(7 downto 0) <= ALU_Q;
+ end if;
+ if LDY = '1' then
+ Y(7 downto 0) <= ALU_Q;
+ end if;
+ if (LDA or LDX or LDY) = '1' then
+ P <= P_Out;
+ end if;
+ end if;
+ if SaveP = '1' then
+ P <= P_Out;
+ end if;
+ if LDP = '1' then
+ P <= ALU_Q;
+ end if;
+ if IR(4 downto 0) = "11000" then
+ case IR(7 downto 5) is
+ when "000" =>
+ P(Flag_C) <= '0';
+ when "001" =>
+ P(Flag_C) <= '1';
+ when "010" =>
+ P(Flag_I) <= '0';
+ when "011" =>
+ P(Flag_I) <= '1';
+ when "101" =>
+ P(Flag_V) <= '0';
+ when "110" =>
+ P(Flag_D) <= '0';
+ when "111" =>
+ P(Flag_D) <= '1';
+ when others =>
+ end case;
+ end if;
+ if IR = "00000000" and MCycle = "011" and RstCycle = '0' and NMICycle = '0' and IRQCycle = '0' then
+ P(Flag_B) <= '1';
+ end if;
+ if IR = "00000000" and MCycle = "100" and RstCycle = '0' and (NMICycle = '1' or IRQCycle = '1') then
+ P(Flag_I) <= '1';
+ P(Flag_B) <= B_o;
+ end if;
+ if SO_n_o = '1' and SO_n = '0' then
+ P(Flag_V) <= '1';
+ end if;
+ if RstCycle = '1' and Mode_r /= "00" then
+ P(Flag_1) <= '1';
+ P(Flag_D) <= '0';
+ P(Flag_I) <= '1';
+ end if;
+ P(Flag_1) <= '1';
+
+ B_o <= P(Flag_B);
+ SO_n_o <= SO_n;
+ IRQ_n_o <= IRQ_n;
+ NMI_n_o <= NMI_n;
+ end if;
+ end if;
+ end if;
+ end process;
+
+---------------------------------------------------------------------------
+--
+-- Buses
+--
+---------------------------------------------------------------------------
+
+ process (Res_n, Clk)
+ begin
+ if Res_n = '0' then
+ BusA_r <= (others => '0');
+ BusB <= (others => '0');
+ AD <= (others => '0');
+ BAL <= (others => '0');
+ BAH <= (others => '0');
+ DL <= (others => '0');
+ elsif Clk'event and Clk = '1' then
+ if (Enable = '1') then
+ if (Rdy = '1') then
+ BusA_r <= BusA;
+ BusB <= DI;
+
+ case BAAdd is
+ when "01" =>
+ -- BA Inc
+ AD <= std_logic_vector(unsigned(AD) + 1);
+ BAL <= std_logic_vector(unsigned(BAL) + 1);
+ when "10" =>
+ -- BA Add
+ BAL <= std_logic_vector(resize(unsigned(BAL(7 downto 0)),9) + resize(unsigned(BusA),9));
+ when "11" =>
+ -- BA Adj
+ if BAL(8) = '1' then
+ BAH <= std_logic_vector(unsigned(BAH) + 1);
+ end if;
+ when others =>
+ end case;
+
+ -- ehenciak : modified to use Y register as well (bugfix)
+ if ADAdd = '1' then
+ if (AddY = '1') then
+ AD <= std_logic_vector(unsigned(AD) + unsigned(Y(7 downto 0)));
+ else
+ AD <= std_logic_vector(unsigned(AD) + unsigned(X(7 downto 0)));
+ end if;
+ end if;
+
+ if IR = "00000000" then
+ BAL <= (others => '1');
+ BAH <= (others => '1');
+ if RstCycle = '1' then
+ BAL(2 downto 0) <= "100";
+ elsif NMICycle = '1' then
+ BAL(2 downto 0) <= "010";
+ else
+ BAL(2 downto 0) <= "110";
+ end if;
+ if Set_addr_To_r = "11" then
+ BAL(0) <= '1';
+ end if;
+ end if;
+
+
+ if LDDI = '1' then
+ DL <= DI;
+ end if;
+ if LDALU = '1' then
+ DL <= ALU_Q;
+ end if;
+ if LDAD = '1' then
+ AD <= DI;
+ end if;
+ if LDBAL = '1' then
+ BAL(7 downto 0) <= DI;
+ end if;
+ if LDBAH = '1' then
+ BAH <= DI;
+ end if;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ Break <= (BreakAtNA and not BAL(8)) or (PCAdd and not PCAdder(8));
+
+
+ with Set_BusA_To select
+ BusA <= DI when "000",
+ ABC(7 downto 0) when "001",
+ X(7 downto 0) when "010",
+ Y(7 downto 0) when "011",
+ std_logic_vector(S(7 downto 0)) when "100",
+ P when "101",
+ (others => '-') when others;
+
+ with Set_Addr_To_r select
+ A <= "0000000000000001" & std_logic_vector(S(7 downto 0)) when "01",
+ DBR & "00000000" & AD when "10",
+ "00000000" & BAH & BAL(7 downto 0) when "11",
+ PBR & std_logic_vector(PC(15 downto 8)) & std_logic_vector(PCAdder(7 downto 0)) when others;
+
+ with Write_Data_r select
+ DO <= DL when "000",
+ ABC(7 downto 0) when "001",
+ X(7 downto 0) when "010",
+ Y(7 downto 0) when "011",
+ std_logic_vector(S(7 downto 0)) when "100",
+ P when "101",
+ std_logic_vector(PC(7 downto 0)) when "110",
+ std_logic_vector(PC(15 downto 8)) when others;
+
+-------------------------------------------------------------------------
+--
+-- Main state machine
+--
+-------------------------------------------------------------------------
+
+ process (Res_n, Clk)
+ begin
+ if Res_n = '0' then
+ MCycle <= "001";
+ RstCycle <= '1';
+ IRQCycle <= '0';
+ NMICycle <= '0';
+ NMIAct <= '0';
+ elsif Clk'event and Clk = '1' then
+ if (Enable = '1') then
+ if (really_rdy = '1') then
+ if MCycle = LCycle or Break = '1' then
+ MCycle <= "000";
+ RstCycle <= '0';
+ IRQCycle <= '0';
+ NMICycle <= '0';
+ if NMIAct = '1' then
+ NMICycle <= '1';
+ elsif IRQ_n_o = '0' and P(Flag_I) = '0' then
+ IRQCycle <= '1';
+ end if;
+ else
+ MCycle <= std_logic_vector(unsigned(MCycle) + 1);
+ end if;
+
+ if NMICycle = '1' then
+ NMIAct <= '0';
+ end if;
+ if NMI_n_o = '1' and NMI_n = '0' then
+ NMIAct <= '1';
+ end if;
+ end if;
+ end if;
+ end if;
+ end process;
+
+end;
diff --git a/common/CPU/T65/t65_MCode.vhd b/common/CPU/T65/t65_MCode.vhd
new file mode 100644
index 00000000..68f9323e
--- /dev/null
+++ b/common/CPU/T65/t65_MCode.vhd
@@ -0,0 +1,1047 @@
+-- ****
+-- T65(b) core. In an effort to merge and maintain bug fixes ....
+--
+--
+-- Ver 301 Jump timing fixed
+-- Ver 300 Bugfixes by ehenciak added
+-- MikeJ March 2005
+-- Latest version from www.fpgaarcade.com (original www.opencores.org)
+--
+-- ****
+--
+-- 65xx compatible microprocessor core
+--
+-- Version : 0246 + fix
+--
+-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t65/
+--
+-- Limitations :
+--
+-- 65C02
+-- supported : inc, dec, phx, plx, phy, ply
+-- missing : bra, ora, lda, cmp, sbc, tsb*2, trb*2, stz*2, bit*2, wai, stp, jmp, bbr*8, bbs*8
+--
+-- File history :
+--
+-- 0246 : First release
+--
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+library work;
+use work.pack_t65.all;
+
+entity T65_MCode is
+ port(
+ Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816
+ IR : in std_logic_vector(7 downto 0);
+ MCycle : in std_logic_vector(2 downto 0);
+ P : in std_logic_vector(7 downto 0);
+ LCycle : out std_logic_vector(2 downto 0);
+ ALU_Op : out std_logic_vector(3 downto 0);
+ Set_BusA_To : out std_logic_vector(2 downto 0); -- DI,A,X,Y,S,P
+ Set_Addr_To : out std_logic_vector(1 downto 0); -- PC Adder,S,AD,BA
+ Write_Data : out std_logic_vector(2 downto 0); -- DL,A,X,Y,S,P,PCL,PCH
+ Jump : out std_logic_vector(1 downto 0); -- PC,++,DIDL,Rel
+ BAAdd : out std_logic_vector(1 downto 0); -- None,DB Inc,BA Add,BA Adj
+ BreakAtNA : out std_logic;
+ ADAdd : out std_logic;
+ AddY : out std_logic;
+ PCAdd : out std_logic;
+ Inc_S : out std_logic;
+ Dec_S : out std_logic;
+ LDA : out std_logic;
+ LDP : out std_logic;
+ LDX : out std_logic;
+ LDY : out std_logic;
+ LDS : out std_logic;
+ LDDI : out std_logic;
+ LDALU : out std_logic;
+ LDAD : out std_logic;
+ LDBAL : out std_logic;
+ LDBAH : out std_logic;
+ SaveP : out std_logic;
+ Write : out std_logic
+ );
+end T65_MCode;
+
+architecture rtl of T65_MCode is
+
+ signal Branch : std_logic;
+
+begin
+
+ with IR(7 downto 5) select
+ Branch <= not P(Flag_N) when "000",
+ P(Flag_N) when "001",
+ not P(Flag_V) when "010",
+ P(Flag_V) when "011",
+ not P(Flag_C) when "100",
+ P(Flag_C) when "101",
+ not P(Flag_Z) when "110",
+ P(Flag_Z) when others;
+
+ process (IR, MCycle, P, Branch, Mode)
+ begin
+ LCycle <= "001";
+ Set_BusA_To <= "001"; -- A
+ Set_Addr_To <= (others => '0');
+ Write_Data <= (others => '0');
+ Jump <= (others => '0');
+ BAAdd <= "00";
+ BreakAtNA <= '0';
+ ADAdd <= '0';
+ PCAdd <= '0';
+ Inc_S <= '0';
+ Dec_S <= '0';
+ LDA <= '0';
+ LDP <= '0';
+ LDX <= '0';
+ LDY <= '0';
+ LDS <= '0';
+ LDDI <= '0';
+ LDALU <= '0';
+ LDAD <= '0';
+ LDBAL <= '0';
+ LDBAH <= '0';
+ SaveP <= '0';
+ Write <= '0';
+ AddY <= '0';
+
+ case IR(7 downto 5) is
+ when "100" =>
+ --{{{
+ case IR(1 downto 0) is
+ when "00" =>
+ Set_BusA_To <= "011"; -- Y
+ Write_Data <= "011"; -- Y
+ when "10" =>
+ Set_BusA_To <= "010"; -- X
+ Write_Data <= "010"; -- X
+ when others =>
+ Write_Data <= "001"; -- A
+ end case;
+ --}}}
+ when "101" =>
+ --{{{
+ case IR(1 downto 0) is
+ when "00" =>
+ if IR(4) /= '1' or IR(2) /= '0' then
+ LDY <= '1';
+ end if;
+ when "10" =>
+ LDX <= '1';
+ when others =>
+ LDA <= '1';
+ end case;
+ Set_BusA_To <= "000"; -- DI
+ --}}}
+ when "110" =>
+ --{{{
+ case IR(1 downto 0) is
+ when "00" =>
+ if IR(4) = '0' then
+ LDY <= '1';
+ end if;
+ Set_BusA_To <= "011"; -- Y
+ when others =>
+ Set_BusA_To <= "001"; -- A
+ end case;
+ --}}}
+ when "111" =>
+ --{{{
+ case IR(1 downto 0) is
+ when "00" =>
+ if IR(4) = '0' then
+ LDX <= '1';
+ end if;
+ Set_BusA_To <= "010"; -- X
+ when others =>
+ Set_BusA_To <= "001"; -- A
+ end case;
+ --}}}
+ when others =>
+ end case;
+
+ if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then
+ Set_BusA_To <= "000"; -- DI
+ end if;
+
+ case IR(4 downto 0) is
+ when "00000" | "01000" | "01010" | "11000" | "11010" =>
+ --{{{
+ -- Implied
+ case IR is
+ when "00000000" =>
+ -- BRK
+ LCycle <= "110";
+ case to_integer(unsigned(MCycle)) is
+ when 1 =>
+ Set_Addr_To <= "01"; -- S
+ Write_Data <= "111"; -- PCH
+ Write <= '1';
+ when 2 =>
+ Dec_S <= '1';
+ Set_Addr_To <= "01"; -- S
+ Write_Data <= "110"; -- PCL
+ Write <= '1';
+ when 3 =>
+ Dec_S <= '1';
+ Set_Addr_To <= "01"; -- S
+ Write_Data <= "101"; -- P
+ Write <= '1';
+ when 4 =>
+ Dec_S <= '1';
+ Set_Addr_To <= "11"; -- BA
+ when 5 =>
+ LDDI <= '1';
+ Set_Addr_To <= "11"; -- BA
+ when 6 =>
+ Jump <= "10"; -- DIDL
+ when others =>
+ end case;
+ when "00100000" =>
+ -- JSR
+ LCycle <= "101";
+ case to_integer(unsigned(MCycle)) is
+ when 1 =>
+ Jump <= "01";
+ LDDI <= '1';
+ Set_Addr_To <= "01"; -- S
+ when 2 =>
+ Set_Addr_To <= "01"; -- S
+ Write_Data <= "111"; -- PCH
+ Write <= '1';
+ when 3 =>
+ Dec_S <= '1';
+ Set_Addr_To <= "01"; -- S
+ Write_Data <= "110"; -- PCL
+ Write <= '1';
+ when 4 =>
+ Dec_S <= '1';
+ when 5 =>
+ Jump <= "10"; -- DIDL
+ when others =>
+ end case;
+ when "01000000" =>
+ -- RTI
+ LCycle <= "101";
+ case to_integer(unsigned(MCycle)) is
+ when 1 =>
+ Set_Addr_To <= "01"; -- S
+ when 2 =>
+ Inc_S <= '1';
+ Set_Addr_To <= "01"; -- S
+ when 3 =>
+ Inc_S <= '1';
+ Set_Addr_To <= "01"; -- S
+ Set_BusA_To <= "000"; -- DI
+ when 4 =>
+ LDP <= '1';
+ Inc_S <= '1';
+ LDDI <= '1';
+ Set_Addr_To <= "01"; -- S
+ when 5 =>
+ Jump <= "10"; -- DIDL
+ when others =>
+ end case;
+ when "01100000" =>
+ -- RTS
+ LCycle <= "101";
+ case to_integer(unsigned(MCycle)) is
+ when 1 =>
+ Set_Addr_To <= "01"; -- S
+ when 2 =>
+ Inc_S <= '1';
+ Set_Addr_To <= "01"; -- S
+ when 3 =>
+ Inc_S <= '1';
+ LDDI <= '1';
+ Set_Addr_To <= "01"; -- S
+ when 4 =>
+ Jump <= "10"; -- DIDL
+ when 5 =>
+ Jump <= "01";
+ when others =>
+ end case;
+ when "00001000" | "01001000" | "01011010" | "11011010" =>
+ -- PHP, PHA, PHY*, PHX*
+ LCycle <= "010";
+ if Mode = "00" and IR(1) = '1' then
+ LCycle <= "001";
+ end if;
+ case to_integer(unsigned(MCycle)) is
+ when 1 =>
+ case IR(7 downto 4) is
+ when "0000" => Write_Data <= "101"; -- P
+ when "0100" => Write_Data <= "001"; -- A
+ when "0101" => Write_Data <= "011"; -- Y
+ when "1101" => Write_Data <= "010"; -- X
+ when others =>
+ end case;
+ Write <= '1';
+ Set_Addr_To <= "01"; -- S
+ when 2 =>
+ Dec_S <= '1';
+ when others =>
+ end case;
+ when "00101000" | "01101000" | "01111010" | "11111010" =>
+ -- PLP, PLA, PLY*, PLX*
+ LCycle <= "011";
+ if Mode = "00" and IR(1) = '1' then
+ LCycle <= "001";
+ end if;
+ case IR(7 downto 4) is
+ when "0010" =>
+ LDP <= '1';
+ when "0110" =>
+ LDA <= '1';
+ when "0111" =>
+ if Mode /= "00" then
+ LDY <= '1';
+ end if;
+ when "1111" =>
+ if Mode /= "00" then
+ LDX <= '1';
+ end if;
+ when others =>
+ end case;
+ case to_integer(unsigned(MCycle)) is
+ when 0 =>
+ SaveP <= '1';
+ when 1 =>
+ Set_Addr_To <= "01"; -- S
+ when 2 =>
+ Inc_S <= '1';
+ Set_Addr_To <= "01"; -- S
+ when 3 =>
+ Set_BusA_To <= "000"; -- DI
+ when others =>
+ end case;
+ when "10100000" | "11000000" | "11100000" =>
+ -- LDY, CPY, CPX
+ -- Immediate
+ case to_integer(unsigned(MCycle)) is
+ when 0 =>
+ when 1 =>
+ Jump <= "01";
+ when others =>
+ end case;
+ when "10001000" =>
+ -- DEY
+ LDY <= '1';
+ case to_integer(unsigned(MCycle)) is
+ when 0 =>
+ when 1 =>
+ Set_BusA_To <= "011"; -- Y
+ when others =>
+ end case;
+ when "11001010" =>
+ -- DEX
+ LDX <= '1';
+ case to_integer(unsigned(MCycle)) is
+ when 0 =>
+ when 1 =>
+ Set_BusA_To <= "010"; -- X
+ when others =>
+ end case;
+ when "00011010" | "00111010" =>
+ -- INC*, DEC*
+ if Mode /= "00" then
+ LDA <= '1'; -- A
+ end if;
+ case to_integer(unsigned(MCycle)) is
+ when 0 =>
+ when 1 =>
+ Set_BusA_To <= "100"; -- S
+ when others =>
+ end case;
+ when "00001010" | "00101010" | "01001010" | "01101010" =>
+ -- ASL, ROL, LSR, ROR
+ LDA <= '1'; -- A
+ Set_BusA_To <= "001"; -- A
+ case to_integer(unsigned(MCycle)) is
+ when 0 =>
+ when 1 =>
+ when others =>
+ end case;
+ when "10001010" | "10011000" =>
+ -- TYA, TXA
+ LDA <= '1'; -- A
+ case to_integer(unsigned(MCycle)) is
+ when 0 =>
+ when 1 =>
+ when others =>
+ end case;
+ when "10101010" | "10101000" =>
+ -- TAX, TAY
+ case to_integer(unsigned(MCycle)) is
+ when 0 =>
+ when 1 =>
+ Set_BusA_To <= "001"; -- A
+ when others =>
+ end case;
+ when "10011010" =>
+ -- TXS
+ case to_integer(unsigned(MCycle)) is
+ when 0 =>
+ LDS <= '1';
+ when 1 =>
+ when others =>
+ end case;
+ when "10111010" =>
+ -- TSX
+ LDX <= '1';
+ case to_integer(unsigned(MCycle)) is
+ when 0 =>
+ when 1 =>
+ Set_BusA_To <= "100"; -- S
+ when others =>
+ end case;
+
+ -- when "00011000" | "00111000" | "01011000" | "01111000" | "10111000" | "11011000" | "11111000" | "11001000" | "11101000" =>
+ -- -- CLC, SEC, CLI, SEI, CLV, CLD, SED, INY, INX
+ -- case to_integer(unsigned(MCycle)) is
+ -- when 1 =>
+ -- when others =>
+ -- end case;
+ when others =>
+ case to_integer(unsigned(MCycle)) is
+ when 0 =>
+ when others =>
+ end case;
+ end case;
+ --}}}
+
+ when "00001" | "00011" =>
+ --{{{
+ -- Zero Page Indexed Indirect (d,x)
+ LCycle <= "101";
+ if IR(7 downto 6) /= "10" then
+ LDA <= '1';
+ end if;
+ case to_integer(unsigned(MCycle)) is
+ when 0 =>
+ when 1 =>
+ Jump <= "01";
+ LDAD <= '1';
+ Set_Addr_To <= "10"; -- AD
+ when 2 =>
+ ADAdd <= '1';
+ Set_Addr_To <= "10"; -- AD
+ when 3 =>
+ BAAdd <= "01"; -- DB Inc
+ LDBAL <= '1';
+ Set_Addr_To <= "10"; -- AD
+ when 4 =>
+ LDBAH <= '1';
+ if IR(7 downto 5) = "100" then
+ Write <= '1';
+ end if;
+ Set_Addr_To <= "11"; -- BA
+ when 5 =>
+ when others =>
+ end case;
+ --}}}
+
+ when "01001" | "01011" =>
+ --{{{
+ -- Immediate
+ LDA <= '1';
+ case to_integer(unsigned(MCycle)) is
+ when 0 =>
+ when 1 =>
+ Jump <= "01";
+ when others =>
+ end case;
+
+ --}}}
+
+ when "00010" | "10010" =>
+ --{{{
+ -- Immediate, KIL
+ LDX <= '1';
+ case to_integer(unsigned(MCycle)) is
+ when 0 =>
+ when 1 =>
+ if IR = "10100010" then
+ -- LDX
+ Jump <= "01";
+ else
+ -- KIL !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ end if;
+ when others =>
+ end case;
+ --}}}
+
+ when "00100" =>
+ --{{{
+ -- Zero Page
+ LCycle <= "010";
+ case to_integer(unsigned(MCycle)) is
+ when 0 =>
+ if IR(7 downto 5) = "001" then
+ SaveP <= '1';
+ end if;
+ when 1 =>
+ Jump <= "01";
+ LDAD <= '1';
+ if IR(7 downto 5) = "100" then
+ Write <= '1';
+ end if;
+ Set_Addr_To <= "10"; -- AD
+ when 2 =>
+ when others =>
+ end case;
+ --}}}
+
+ when "00101" | "00110" | "00111" =>
+ --{{{
+ -- Zero Page
+ if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then
+ -- Read-Modify-Write
+ LCycle <= "100";
+ case to_integer(unsigned(MCycle)) is
+ when 1 =>
+ Jump <= "01";
+ LDAD <= '1';
+ Set_Addr_To <= "10"; -- AD
+ when 2 =>
+ LDDI <= '1';
+ Write <= '1';
+ Set_Addr_To <= "10"; -- AD
+ when 3 =>
+ LDALU <= '1';
+ SaveP <= '1';
+ Write <= '1';
+ Set_Addr_To <= "10"; -- AD
+ when 4 =>
+ when others =>
+ end case;
+ else
+ LCycle <= "010";
+ if IR(7 downto 6) /= "10" then
+ LDA <= '1';
+ end if;
+ case to_integer(unsigned(MCycle)) is
+ when 0 =>
+ when 1 =>
+ Jump <= "01";
+ LDAD <= '1';
+ if IR(7 downto 5) = "100" then
+ Write <= '1';
+ end if;
+ Set_Addr_To <= "10"; -- AD
+ when 2 =>
+ when others =>
+ end case;
+ end if;
+ --}}}
+
+ when "01100" =>
+ --{{{
+ -- Absolute
+ if IR(7 downto 6) = "01" and IR(4 downto 0) = "01100" then
+ -- JMP
+ if IR(5) = '0' then
+ --LCycle <= "011";
+ LCycle <= "010";
+ case to_integer(unsigned(MCycle)) is
+ when 1 =>
+ Jump <= "01";
+ LDDI <= '1';
+ when 2 =>
+ Jump <= "10"; -- DIDL
+ when others =>
+ end case;
+ else
+ LCycle <= "101";
+ case to_integer(unsigned(MCycle)) is
+ when 2 =>
+ Jump <= "01";
+ LDDI <= '1';
+ LDBAL <= '1';
+ when 3 =>
+ LDBAH <= '1';
+ if Mode /= "00" then
+ Jump <= "10"; -- DIDL
+ end if;
+ if Mode = "00" then
+ Set_Addr_To <= "11"; -- BA
+ end if;
+ when 4 =>
+ LDDI <= '1';
+ if Mode = "00" then
+ Set_Addr_To <= "11"; -- BA
+ BAAdd <= "01"; -- DB Inc
+ else
+ Jump <= "01";
+ end if;
+ when 5 =>
+ Jump <= "10"; -- DIDL
+ when others =>
+ end case;
+ end if;
+ else
+ LCycle <= "011";
+ case to_integer(unsigned(MCycle)) is
+ when 0 =>
+ if IR(7 downto 5) = "001" then
+ SaveP <= '1';
+ end if;
+ when 1 =>
+ Jump <= "01";
+ LDBAL <= '1';
+ when 2 =>
+ Jump <= "01";
+ LDBAH <= '1';
+ if IR(7 downto 5) = "100" then
+ Write <= '1';
+ end if;
+ Set_Addr_To <= "11"; -- BA
+ when 3 =>
+ when others =>
+ end case;
+ end if;
+ --}}}
+
+ when "01101" | "01110" | "01111" =>
+ --{{{
+ -- Absolute
+ if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then
+ -- Read-Modify-Write
+ LCycle <= "101";
+ case to_integer(unsigned(MCycle)) is
+ when 1 =>
+ Jump <= "01";
+ LDBAL <= '1';
+ when 2 =>
+ Jump <= "01";
+ LDBAH <= '1';
+ Set_Addr_To <= "11"; -- BA
+ when 3 =>
+ LDDI <= '1';
+ Write <= '1';
+ Set_Addr_To <= "11"; -- BA
+ when 4 =>
+ Write <= '1';
+ LDALU <= '1';
+ SaveP <= '1';
+ Set_Addr_To <= "11"; -- BA
+ when 5 =>
+ SaveP <= '0'; -- MIKEJ was 1
+ when others =>
+ end case;
+ else
+ LCycle <= "011";
+ if IR(7 downto 6) /= "10" then
+ LDA <= '1';
+ end if;
+ case to_integer(unsigned(MCycle)) is
+ when 0 =>
+ when 1 =>
+ Jump <= "01";
+ LDBAL <= '1';
+ when 2 =>
+ Jump <= "01";
+ LDBAH <= '1';
+ if IR(7 downto 5) = "100" then
+ Write <= '1';
+ end if;
+ Set_Addr_To <= "11"; -- BA
+ when 3 =>
+ when others =>
+ end case;
+ end if;
+ --}}}
+
+ when "10000" =>
+ --{{{
+ -- Relative
+
+ -- This circuit dictates when the last
+ -- microcycle occurs for the branch depending on
+ -- whether or not the branch is taken and if a page
+ -- is crossed...
+ if (Branch = '1') then
+
+ LCycle <= "011"; -- We're done @ T3 if branching...upper
+ -- level logic will stop at T2 if no page cross
+ -- (See the Break signal)
+ else
+
+ LCycle <= "001";
+
+ end if;
+
+ -- This decodes the current microcycle and takes the
+ -- proper course of action...
+ case to_integer(unsigned(MCycle)) is
+
+ -- On the T1 microcycle, increment the program counter
+ -- and instruct the upper level logic to fetch the offset
+ -- from the Din bus and store it in the data latches. This
+ -- will be the last microcycle if the branch isn't taken.
+ when 1 =>
+
+ Jump <= "01"; -- Increments the PC by one (PC will now be PC+2)
+ -- from microcycle T0.
+
+ LDDI <= '1'; -- Tells logic in top level (T65.vhd) to route
+ -- the Din bus to the memory data latch (DL)
+ -- so that the branch offset is fetched.
+
+ -- In microcycle T2, tell the logic in the top level to
+ -- add the offset. If the most significant byte of the
+ -- program counter (i.e. the current "page") does not need
+ -- updating, we are done here...the Break signal at the
+ -- T65.vhd level takes care of that...
+ when 2 =>
+
+ Jump <= "11"; -- Tell the PC Jump logic to use relative mode.
+
+ PCAdd <= '1'; -- This tells the PC adder to update itself with
+ -- the current offset recently fetched from
+ -- memory.
+
+ -- The following is microcycle T3 :
+ -- The program counter should be completely updated
+ -- on this cycle after the page cross is detected.
+ -- We don't need to do anything here...
+ when 3 =>
+
+
+ when others => null; -- Do nothing.
+
+ end case;
+ --}}}
+
+ when "10001" | "10011" =>
+ --{{{
+ -- Zero Page Indirect Indexed (d),y
+ LCycle <= "101";
+ if IR(7 downto 6) /= "10" then
+ LDA <= '1';
+ end if;
+ case to_integer(unsigned(MCycle)) is
+ when 0 =>
+ when 1 =>
+ Jump <= "01";
+ LDAD <= '1';
+ Set_Addr_To <= "10"; -- AD
+ when 2 =>
+ LDBAL <= '1';
+ BAAdd <= "01"; -- DB Inc
+ Set_Addr_To <= "10"; -- AD
+ when 3 =>
+ Set_BusA_To <= "011"; -- Y
+ BAAdd <= "10"; -- BA Add
+ LDBAH <= '1';
+ Set_Addr_To <= "11"; -- BA
+ when 4 =>
+ BAAdd <= "11"; -- BA Adj
+ if IR(7 downto 5) = "100" then
+ Write <= '1';
+ else
+ BreakAtNA <= '1';
+ end if;
+ Set_Addr_To <= "11"; -- BA
+ when 5 =>
+ when others =>
+ end case;
+ --}}}
+
+ when "10100" | "10101" | "10110" | "10111" =>
+ --{{{
+ -- Zero Page, X
+ if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then
+ -- Read-Modify-Write
+ LCycle <= "101";
+ case to_integer(unsigned(MCycle)) is
+ when 1 =>
+ Jump <= "01";
+ LDAD <= '1';
+ Set_Addr_To <= "10"; -- AD
+ when 2 =>
+ ADAdd <= '1';
+ Set_Addr_To <= "10"; -- AD
+ when 3 =>
+ LDDI <= '1';
+ Write <= '1';
+ Set_Addr_To <= "10"; -- AD
+ when 4 =>
+ LDALU <= '1';
+ SaveP <= '1';
+ Write <= '1';
+ Set_Addr_To <= "10"; -- AD
+ when 5 =>
+ when others =>
+ end case;
+ else
+ LCycle <= "011";
+ if IR(7 downto 6) /= "10" then
+ LDA <= '1';
+ end if;
+ case to_integer(unsigned(MCycle)) is
+ when 0 =>
+ when 1 =>
+ Jump <= "01";
+ LDAD <= '1';
+ Set_Addr_To <= "10"; -- AD
+ when 2 =>
+ ADAdd <= '1';
+ -- Added this check for Y reg. use...
+ if (IR(3 downto 0) = "0110") then
+ AddY <= '1';
+ end if;
+
+ if IR(7 downto 5) = "100" then
+ Write <= '1';
+ end if;
+ Set_Addr_To <= "10"; -- AD
+ when 3 => null;
+ when others =>
+ end case;
+ end if;
+ --}}}
+
+ when "11001" | "11011" =>
+ --{{{
+ -- Absolute Y
+ LCycle <= "100";
+ if IR(7 downto 6) /= "10" then
+ LDA <= '1';
+ end if;
+ case to_integer(unsigned(MCycle)) is
+ when 0 =>
+ when 1 =>
+ Jump <= "01";
+ LDBAL <= '1';
+ when 2 =>
+ Jump <= "01";
+ Set_BusA_To <= "011"; -- Y
+ BAAdd <= "10"; -- BA Add
+ LDBAH <= '1';
+ Set_Addr_To <= "11"; -- BA
+ when 3 =>
+ BAAdd <= "11"; -- BA adj
+ if IR(7 downto 5) = "100" then
+ Write <= '1';
+ else
+ BreakAtNA <= '1';
+ end if;
+ Set_Addr_To <= "11"; -- BA
+ when 4 =>
+ when others =>
+ end case;
+ --}}}
+
+ when "11100" | "11101" | "11110" | "11111" =>
+ --{{{
+ -- Absolute X
+
+ if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then
+ -- Read-Modify-Write
+ LCycle <= "110";
+ case to_integer(unsigned(MCycle)) is
+ when 1 =>
+ Jump <= "01";
+ LDBAL <= '1';
+ when 2 =>
+ Jump <= "01";
+ Set_BusA_To <= "010"; -- X
+ BAAdd <= "10"; -- BA Add
+ LDBAH <= '1';
+ Set_Addr_To <= "11"; -- BA
+ when 3 =>
+ BAAdd <= "11"; -- BA adj
+ Set_Addr_To <= "11"; -- BA
+ when 4 =>
+ LDDI <= '1';
+ Write <= '1';
+ Set_Addr_To <= "11"; -- BA
+ when 5 =>
+ LDALU <= '1';
+ SaveP <= '1';
+ Write <= '1';
+ Set_Addr_To <= "11"; -- BA
+ when 6 =>
+ when others =>
+ end case;
+ else
+ LCycle <= "100";
+ if IR(7 downto 6) /= "10" then
+ LDA <= '1';
+ end if;
+ case to_integer(unsigned(MCycle)) is
+ when 0 =>
+ when 1 =>
+ Jump <= "01";
+ LDBAL <= '1';
+ when 2 =>
+ Jump <= "01";
+ -- mikej
+ -- special case 0xBE which uses Y reg as index!!
+ if (IR = "10111110") then
+ Set_BusA_To <= "011"; -- Y
+ else
+ Set_BusA_To <= "010"; -- X
+ end if;
+ BAAdd <= "10"; -- BA Add
+ LDBAH <= '1';
+ Set_Addr_To <= "11"; -- BA
+ when 3 =>
+ BAAdd <= "11"; -- BA adj
+ if IR(7 downto 5) = "100" then
+ Write <= '1';
+ else
+ BreakAtNA <= '1';
+ end if;
+ Set_Addr_To <= "11"; -- BA
+ when 4 =>
+ when others =>
+ end case;
+ end if;
+ --}}}
+ when others =>
+ end case;
+ end process;
+
+ process (IR, MCycle)
+ begin
+ -- ORA, AND, EOR, ADC, NOP, LD, CMP, SBC
+ -- ASL, ROL, LSR, ROR, BIT, LD, DEC, INC
+ case IR(1 downto 0) is
+ when "00" =>
+ --{{{
+ case IR(4 downto 2) is
+ when "000" | "001" | "011" =>
+ case IR(7 downto 5) is
+ when "110" | "111" =>
+ -- CP
+ ALU_Op <= "0110";
+ when "101" =>
+ -- LD
+ ALU_Op <= "0101";
+ when "001" =>
+ -- BIT
+ ALU_Op <= "1100";
+ when others =>
+ -- NOP/ST
+ ALU_Op <= "0100";
+ end case;
+ when "010" =>
+ case IR(7 downto 5) is
+ when "111" | "110" =>
+ -- IN
+ ALU_Op <= "1111";
+ when "100" =>
+ -- DEY
+ ALU_Op <= "1110";
+ when others =>
+ -- LD
+ ALU_Op <= "1101";
+ end case;
+ when "110" =>
+ case IR(7 downto 5) is
+ when "100" =>
+ -- TYA
+ ALU_Op <= "1101";
+ when others =>
+ ALU_Op <= "----";
+ end case;
+ when others =>
+ case IR(7 downto 5) is
+ when "101" =>
+ -- LD
+ ALU_Op <= "1101";
+ when others =>
+ ALU_Op <= "0100";
+ end case;
+ end case;
+ --}}}
+ when "01" => -- OR
+ --{{{
+ ALU_Op(3) <= '0';
+ ALU_Op(2 downto 0) <= IR(7 downto 5);
+ --}}}
+ when "10" =>
+ --{{{
+ ALU_Op(3) <= '1';
+ ALU_Op(2 downto 0) <= IR(7 downto 5);
+ case IR(7 downto 5) is
+ when "000" =>
+ if IR(4 downto 2) = "110" then
+ -- INC
+ ALU_Op <= "1111";
+ end if;
+ when "001" =>
+ if IR(4 downto 2) = "110" then
+ -- DEC
+ ALU_Op <= "1110";
+ end if;
+ when "100" =>
+ if IR(4 downto 2) = "010" then
+ -- TXA
+ ALU_Op <= "0101";
+ else
+ ALU_Op <= "0100";
+ end if;
+ when others =>
+ end case;
+ --}}}
+ when others =>
+ --{{{
+ case IR(7 downto 5) is
+ when "100" =>
+ ALU_Op <= "0100";
+ when others =>
+ if MCycle = "000" then
+ ALU_Op(3) <= '0';
+ ALU_Op(2 downto 0) <= IR(7 downto 5);
+ else
+ ALU_Op(3) <= '1';
+ ALU_Op(2 downto 0) <= IR(7 downto 5);
+ end if;
+ end case;
+ --}}}
+ end case;
+ end process;
+
+end;
diff --git a/common/CPU/T65/t65_alu.vhd b/common/CPU/T65/t65_alu.vhd
new file mode 100644
index 00000000..38b84a06
--- /dev/null
+++ b/common/CPU/T65/t65_alu.vhd
@@ -0,0 +1,261 @@
+-- ****
+-- T65(b) core. In an effort to merge and maintain bug fixes ....
+--
+--
+-- Ver 300 Bugfixes by ehenciak added
+-- MikeJ March 2005
+-- Latest version from www.fpgaarcade.com (original www.opencores.org)
+--
+-- ****
+--
+-- 6502 compatible microprocessor core
+--
+-- Version : 0245
+--
+-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t65/
+--
+-- Limitations :
+--
+-- File history :
+--
+-- 0245 : First version
+--
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+library work;
+use work.pack_t65.all;
+
+entity T65_ALU is
+ port(
+ Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816
+ Op : in std_logic_vector(3 downto 0);
+ BusA : in std_logic_vector(7 downto 0);
+ BusB : in std_logic_vector(7 downto 0);
+ P_In : in std_logic_vector(7 downto 0);
+ P_Out : out std_logic_vector(7 downto 0);
+ Q : out std_logic_vector(7 downto 0)
+ );
+end T65_ALU;
+
+architecture rtl of T65_ALU is
+
+ -- AddSub variables (temporary signals)
+ signal ADC_Z : std_logic;
+ signal ADC_C : std_logic;
+ signal ADC_V : std_logic;
+ signal ADC_N : std_logic;
+ signal ADC_Q : std_logic_vector(7 downto 0);
+ signal SBC_Z : std_logic;
+ signal SBC_C : std_logic;
+ signal SBC_V : std_logic;
+ signal SBC_N : std_logic;
+ signal SBC_Q : std_logic_vector(7 downto 0);
+
+begin
+
+ process (P_In, BusA, BusB)
+ variable AL : unsigned(6 downto 0);
+ variable AH : unsigned(6 downto 0);
+ variable C : std_logic;
+ begin
+ AL := resize(unsigned(BusA(3 downto 0) & P_In(Flag_C)), 7) + resize(unsigned(BusB(3 downto 0) & "1"), 7);
+ AH := resize(unsigned(BusA(7 downto 4) & AL(5)), 7) + resize(unsigned(BusB(7 downto 4) & "1"), 7);
+
+-- pragma translate_off
+ if is_x(std_logic_vector(AL)) then AL := "0000000"; end if;
+ if is_x(std_logic_vector(AH)) then AH := "0000000"; end if;
+-- pragma translate_on
+
+ if AL(4 downto 1) = 0 and AH(4 downto 1) = 0 then
+ ADC_Z <= '1';
+ else
+ ADC_Z <= '0';
+ end if;
+
+ if AL(5 downto 1) > 9 and P_In(Flag_D) = '1' then
+ AL(6 downto 1) := AL(6 downto 1) + 6;
+ end if;
+
+ C := AL(6) or AL(5);
+ AH := resize(unsigned(BusA(7 downto 4) & C), 7) + resize(unsigned(BusB(7 downto 4) & "1"), 7);
+
+ ADC_N <= AH(4);
+ ADC_V <= (AH(4) xor BusA(7)) and not (BusA(7) xor BusB(7));
+
+-- pragma translate_off
+ if is_x(std_logic_vector(AH)) then AH := "0000000"; end if;
+-- pragma translate_on
+
+ if AH(5 downto 1) > 9 and P_In(Flag_D) = '1' then
+ AH(6 downto 1) := AH(6 downto 1) + 6;
+ end if;
+
+ ADC_C <= AH(6) or AH(5);
+
+ ADC_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1));
+ end process;
+
+ process (Op, P_In, BusA, BusB)
+ variable AL : unsigned(6 downto 0);
+ variable AH : unsigned(5 downto 0);
+ variable C : std_logic;
+ begin
+ C := P_In(Flag_C) or not Op(0);
+ AL := resize(unsigned(BusA(3 downto 0) & C), 7) - resize(unsigned(BusB(3 downto 0) & "1"), 6);
+ AH := resize(unsigned(BusA(7 downto 4) & "0"), 6) - resize(unsigned(BusB(7 downto 4) & AL(5)), 6);
+
+-- pragma translate_off
+ if is_x(std_logic_vector(AL)) then AL := "0000000"; end if;
+ if is_x(std_logic_vector(AH)) then AH := "000000"; end if;
+-- pragma translate_on
+
+ if AL(4 downto 1) = 0 and AH(4 downto 1) = 0 then
+ SBC_Z <= '1';
+ else
+ SBC_Z <= '0';
+ end if;
+
+ SBC_C <= not AH(5);
+ SBC_V <= (AH(4) xor BusA(7)) and (BusA(7) xor BusB(7));
+ SBC_N <= AH(4);
+
+ if P_In(Flag_D) = '1' then
+ if AL(5) = '1' then
+ AL(5 downto 1) := AL(5 downto 1) - 6;
+ end if;
+ AH := resize(unsigned(BusA(7 downto 4) & "0"), 6) - resize(unsigned(BusB(7 downto 4) & AL(6)), 6);
+ if AH(5) = '1' then
+ AH(5 downto 1) := AH(5 downto 1) - 6;
+ end if;
+ end if;
+
+ SBC_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1));
+ end process;
+
+ process (Op, P_In, BusA, BusB,
+ ADC_Z, ADC_C, ADC_V, ADC_N, ADC_Q,
+ SBC_Z, SBC_C, SBC_V, SBC_N, SBC_Q)
+ variable Q_t : std_logic_vector(7 downto 0);
+ begin
+ -- ORA, AND, EOR, ADC, NOP, LD, CMP, SBC
+ -- ASL, ROL, LSR, ROR, BIT, LD, DEC, INC
+ P_Out <= P_In;
+ Q_t := BusA;
+ case Op(3 downto 0) is
+ when "0000" =>
+ -- ORA
+ Q_t := BusA or BusB;
+ when "0001" =>
+ -- AND
+ Q_t := BusA and BusB;
+ when "0010" =>
+ -- EOR
+ Q_t := BusA xor BusB;
+ when "0011" =>
+ -- ADC
+ P_Out(Flag_V) <= ADC_V;
+ P_Out(Flag_C) <= ADC_C;
+ Q_t := ADC_Q;
+ when "0101" | "1101" =>
+ -- LDA
+ when "0110" =>
+ -- CMP
+ P_Out(Flag_C) <= SBC_C;
+ when "0111" =>
+ -- SBC
+ P_Out(Flag_V) <= SBC_V;
+ P_Out(Flag_C) <= SBC_C;
+ Q_t := SBC_Q;
+ when "1000" =>
+ -- ASL
+ Q_t := BusA(6 downto 0) & "0";
+ P_Out(Flag_C) <= BusA(7);
+ when "1001" =>
+ -- ROL
+ Q_t := BusA(6 downto 0) & P_In(Flag_C);
+ P_Out(Flag_C) <= BusA(7);
+ when "1010" =>
+ -- LSR
+ Q_t := "0" & BusA(7 downto 1);
+ P_Out(Flag_C) <= BusA(0);
+ when "1011" =>
+ -- ROR
+ Q_t := P_In(Flag_C) & BusA(7 downto 1);
+ P_Out(Flag_C) <= BusA(0);
+ when "1100" =>
+ -- BIT
+ P_Out(Flag_V) <= BusB(6);
+ when "1110" =>
+ -- DEC
+ Q_t := std_logic_vector(unsigned(BusA) - 1);
+ when "1111" =>
+ -- INC
+ Q_t := std_logic_vector(unsigned(BusA) + 1);
+ when others =>
+ end case;
+
+ case Op(3 downto 0) is
+ when "0011" =>
+ P_Out(Flag_N) <= ADC_N;
+ P_Out(Flag_Z) <= ADC_Z;
+ when "0110" | "0111" =>
+ P_Out(Flag_N) <= SBC_N;
+ P_Out(Flag_Z) <= SBC_Z;
+ when "0100" =>
+ when "1100" =>
+ P_Out(Flag_N) <= BusB(7);
+ if (BusA and BusB) = "00000000" then
+ P_Out(Flag_Z) <= '1';
+ else
+ P_Out(Flag_Z) <= '0';
+ end if;
+ when others =>
+ P_Out(Flag_N) <= Q_t(7);
+ if Q_t = "00000000" then
+ P_Out(Flag_Z) <= '1';
+ else
+ P_Out(Flag_Z) <= '0';
+ end if;
+ end case;
+
+ Q <= Q_t;
+ end process;
+
+end;
diff --git a/common/T80/T16450.vhd b/common/CPU/T80/T16450.vhd
similarity index 100%
rename from common/T80/T16450.vhd
rename to common/CPU/T80/T16450.vhd
diff --git a/common/T80/T80.qip b/common/CPU/T80/T80.qip
similarity index 100%
rename from common/T80/T80.qip
rename to common/CPU/T80/T80.qip
diff --git a/common/T80/T80.vhd b/common/CPU/T80/T80.vhd
similarity index 100%
rename from common/T80/T80.vhd
rename to common/CPU/T80/T80.vhd
diff --git a/common/T80/T8080se.vhd b/common/CPU/T80/T8080se.vhd
similarity index 100%
rename from common/T80/T8080se.vhd
rename to common/CPU/T80/T8080se.vhd
diff --git a/common/T80/T80_ALU.vhd b/common/CPU/T80/T80_ALU.vhd
similarity index 100%
rename from common/T80/T80_ALU.vhd
rename to common/CPU/T80/T80_ALU.vhd
diff --git a/common/T80/T80_MCode.vhd b/common/CPU/T80/T80_MCode.vhd
similarity index 100%
rename from common/T80/T80_MCode.vhd
rename to common/CPU/T80/T80_MCode.vhd
diff --git a/common/T80/T80_Pack.vhd b/common/CPU/T80/T80_Pack.vhd
similarity index 100%
rename from common/T80/T80_Pack.vhd
rename to common/CPU/T80/T80_Pack.vhd
diff --git a/common/T80/T80_Reg.vhd b/common/CPU/T80/T80_Reg.vhd
similarity index 100%
rename from common/T80/T80_Reg.vhd
rename to common/CPU/T80/T80_Reg.vhd
diff --git a/common/T80/T80a.vhd b/common/CPU/T80/T80a.vhd
similarity index 100%
rename from common/T80/T80a.vhd
rename to common/CPU/T80/T80a.vhd
diff --git a/common/T80/T80pa.vhd b/common/CPU/T80/T80pa.vhd
similarity index 100%
rename from common/T80/T80pa.vhd
rename to common/CPU/T80/T80pa.vhd
diff --git a/common/T80/T80s.vhd b/common/CPU/T80/T80s.vhd
similarity index 100%
rename from common/T80/T80s.vhd
rename to common/CPU/T80/T80s.vhd
diff --git a/common/T80/T80se.vhd b/common/CPU/T80/T80se.vhd
similarity index 100%
rename from common/T80/T80se.vhd
rename to common/CPU/T80/T80se.vhd
diff --git a/common/T80/T80sed.vhd b/common/CPU/T80/T80sed.vhd
similarity index 100%
rename from common/T80/T80sed.vhd
rename to common/CPU/T80/T80sed.vhd
diff --git a/common/T80/Z80.vhd b/common/CPU/T80/Z80.vhd
similarity index 100%
rename from common/T80/Z80.vhd
rename to common/CPU/T80/Z80.vhd
diff --git a/common/CPU/cpu86/a_table.vhd b/common/CPU/cpu86/a_table.vhd
new file mode 100644
index 00000000..12274c05
--- /dev/null
+++ b/common/CPU/cpu86/a_table.vhd
@@ -0,0 +1,720 @@
+-------------------------------------------------------------------------------
+-- CPU86 - VHDL CPU8088 IP core --
+-- Copyright (C) 2002-2008 HT-LAB --
+-- --
+-- Contact/bugs : http://www.ht-lab.com/misc/feedback.html --
+-- Web : http://www.ht-lab.com --
+-- --
+-- CPU86 is released as open-source under the GNU GPL license. This means --
+-- that designs based on CPU86 must be distributed in full source code --
+-- under the same license. Contact HT-Lab for commercial applications where --
+-- source-code distribution is not desirable. --
+-- --
+-------------------------------------------------------------------------------
+-- --
+-- This library is free software; you can redistribute it and/or --
+-- modify it under the terms of the GNU Lesser General Public --
+-- License as published by the Free Software Foundation; either --
+-- version 2.1 of the License, or (at your option) any later version. --
+-- --
+-- This library 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 --
+-- Lesser General Public License for more details. --
+-- --
+-- Full details of the license can be found in the file "copying.txt". --
+-- --
+-- You should have received a copy of the GNU Lesser General Public --
+-- License along with this library; if not, write to the Free Software --
+-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --
+-- --
+-------------------------------------------------------------------------------
+library IEEE;
+use IEEE.std_logic_1164.all;
+
+entity a_table is
+ port ( addr : in std_logic_vector(15 downto 0);
+ dout : out std_logic_vector(2 downto 0));
+end a_table;
+
+
+architecture rtl of a_table is
+begin
+ process(addr)
+ begin
+ case addr is
+ when "1110101100000000" => dout <= "001";
+ when "1110100100000000" => dout <= "010";
+ when "1111111111100000" => dout <= "000";
+ when "1111111100100110" => dout <= "100";
+ when "1111111100100000" => dout <= "000";
+ when "1111111101100000" => dout <= "011";
+ when "1111111110100000" => dout <= "100";
+ when "1110101000000000" => dout <= "010";
+ when "1111111100101110" => dout <= "100";
+ when "1111111100101000" => dout <= "000";
+ when "1111111101101000" => dout <= "011";
+ when "1111111110101000" => dout <= "100";
+ when "1110100000000000" => dout <= "010";
+ when "1111111111010000" => dout <= "000";
+ when "1111111100010110" => dout <= "100";
+ when "1111111100010000" => dout <= "000";
+ when "1111111101010000" => dout <= "011";
+ when "1111111110010000" => dout <= "100";
+ when "1001101000000000" => dout <= "010";
+ when "1111111100011110" => dout <= "100";
+ when "1111111100011000" => dout <= "000";
+ when "1111111101011000" => dout <= "011";
+ when "1111111110011000" => dout <= "100";
+ when "1100001100000000" => dout <= "000";
+ when "1100001000000000" => dout <= "000";
+ when "1100101100000000" => dout <= "000";
+ when "1100101000000000" => dout <= "000";
+ when "0111010000000000" => dout <= "001";
+ when "0111110000000000" => dout <= "001";
+ when "0111111000000000" => dout <= "001";
+ when "0111001000000000" => dout <= "001";
+ when "0111011000000000" => dout <= "001";
+ when "0111101000000000" => dout <= "001";
+ when "0111000000000000" => dout <= "001";
+ when "0111100000000000" => dout <= "001";
+ when "0111010100000000" => dout <= "001";
+ when "0111110100000000" => dout <= "001";
+ when "0111111100000000" => dout <= "001";
+ when "0111001100000000" => dout <= "001";
+ when "0111011100000000" => dout <= "001";
+ when "0111101100000000" => dout <= "001";
+ when "0111000100000000" => dout <= "001";
+ when "0111100100000000" => dout <= "001";
+ when "1110001100000000" => dout <= "001";
+ when "1110001000000000" => dout <= "001";
+ when "1110000100000000" => dout <= "001";
+ when "1110000000000000" => dout <= "001";
+ when "1100110100000000" => dout <= "101";
+ when "1100110000000000" => dout <= "110";
+ when "1100111000000000" => dout <= "111";
+ when "1100111100000000" => dout <= "000";
+ when "1111100000000000" => dout <= "000";
+ when "1111010100000000" => dout <= "000";
+ when "1111100100000000" => dout <= "000";
+ when "1111110000000000" => dout <= "000";
+ when "1111110100000000" => dout <= "000";
+ when "1111101000000000" => dout <= "000";
+ when "1111101100000000" => dout <= "000";
+ when "1111010000000000" => dout <= "000";
+ when "1001101100000000" => dout <= "000";
+ when "1111000000000000" => dout <= "000";
+ when "1001000000000000" => dout <= "000";
+ when "0010011000000000" => dout <= "000";
+ when "0010111000000000" => dout <= "000";
+ when "0011011000000000" => dout <= "000";
+ when "0011111000000000" => dout <= "000";
+ when "1000100011000000" => dout <= "000";
+ when "1000100000000000" => dout <= "000";
+ when "1000100001000000" => dout <= "011";
+ when "1000100010000000" => dout <= "100";
+ when "1000100000000110" => dout <= "100";
+ when "1000100111000000" => dout <= "000";
+ when "1000100100000000" => dout <= "000";
+ when "1000100101000000" => dout <= "011";
+ when "1000100110000000" => dout <= "100";
+ when "1000100100000110" => dout <= "100";
+ when "1000101011000000" => dout <= "000";
+ when "1000101000000000" => dout <= "000";
+ when "1000101001000000" => dout <= "011";
+ when "1000101010000000" => dout <= "100";
+ when "1000101000000110" => dout <= "100";
+ when "1000101111000000" => dout <= "000";
+ when "1000101100000000" => dout <= "000";
+ when "1000101101000000" => dout <= "011";
+ when "1000101110000000" => dout <= "100";
+ when "1000101100000110" => dout <= "100";
+ when "1100011000000000" => dout <= "000";
+ when "1100011001000000" => dout <= "011";
+ when "1100011010000000" => dout <= "100";
+ when "1100011000000110" => dout <= "100";
+ when "1100011100000000" => dout <= "000";
+ when "1100011101000000" => dout <= "011";
+ when "1100011110000000" => dout <= "100";
+ when "1100011100000110" => dout <= "100";
+ when "1011000000000000" => dout <= "000";
+ when "1011000100000000" => dout <= "000";
+ when "1011001000000000" => dout <= "000";
+ when "1011001100000000" => dout <= "000";
+ when "1011010000000000" => dout <= "000";
+ when "1011010100000000" => dout <= "000";
+ when "1011011000000000" => dout <= "000";
+ when "1011011100000000" => dout <= "000";
+ when "1011100000000000" => dout <= "000";
+ when "1011100100000000" => dout <= "000";
+ when "1011101000000000" => dout <= "000";
+ when "1011101100000000" => dout <= "000";
+ when "1011110000000000" => dout <= "000";
+ when "1011110100000000" => dout <= "000";
+ when "1011111000000000" => dout <= "000";
+ when "1011111100000000" => dout <= "000";
+ when "1010000000000000" => dout <= "010";
+ when "1010000100000000" => dout <= "010";
+ when "1010001000000000" => dout <= "010";
+ when "1010001100000000" => dout <= "010";
+ when "1000111011000000" => dout <= "000";
+ when "1000111000000000" => dout <= "000";
+ when "1000111001000000" => dout <= "011";
+ when "1000111010000000" => dout <= "100";
+ when "1000111000000110" => dout <= "100";
+ when "1000110011000000" => dout <= "000";
+ when "1000110000000000" => dout <= "000";
+ when "1000110001000000" => dout <= "011";
+ when "1000110010000000" => dout <= "100";
+ when "1000110000000110" => dout <= "100";
+ when "1111111100110000" => dout <= "000";
+ when "1111111101110000" => dout <= "011";
+ when "1111111110110000" => dout <= "100";
+ when "1111111100110110" => dout <= "100";
+ when "0101000000000000" => dout <= "000";
+ when "0101000100000000" => dout <= "000";
+ when "0101001000000000" => dout <= "000";
+ when "0101001100000000" => dout <= "000";
+ when "0101010000000000" => dout <= "000";
+ when "0101010100000000" => dout <= "000";
+ when "0101011000000000" => dout <= "000";
+ when "0101011100000000" => dout <= "000";
+ when "0000011000000000" => dout <= "000";
+ when "0000111000000000" => dout <= "000";
+ when "0001011000000000" => dout <= "000";
+ when "0001111000000000" => dout <= "000";
+ when "1000111100000000" => dout <= "000";
+ when "1000111101000000" => dout <= "011";
+ when "1000111110000000" => dout <= "100";
+ when "1000111100000110" => dout <= "100";
+ when "1000111111000000" => dout <= "000";
+ when "0101100000000000" => dout <= "000";
+ when "0101100100000000" => dout <= "000";
+ when "0101101000000000" => dout <= "000";
+ when "0101101100000000" => dout <= "000";
+ when "0101110000000000" => dout <= "000";
+ when "0101110100000000" => dout <= "000";
+ when "0101111000000000" => dout <= "000";
+ when "0101111100000000" => dout <= "000";
+ when "0000011100000000" => dout <= "000";
+ when "0001011100000000" => dout <= "000";
+ when "0001111100000000" => dout <= "000";
+ when "1000011011000000" => dout <= "000";
+ when "1000011000000000" => dout <= "000";
+ when "1000011001000000" => dout <= "011";
+ when "1000011010000000" => dout <= "100";
+ when "1000011000000110" => dout <= "100";
+ when "1000011111000000" => dout <= "000";
+ when "1000011100000000" => dout <= "000";
+ when "1000011101000000" => dout <= "011";
+ when "1000011110000000" => dout <= "100";
+ when "1000011100000110" => dout <= "100";
+ when "1001000100000000" => dout <= "000";
+ when "1001001000000000" => dout <= "000";
+ when "1001001100000000" => dout <= "000";
+ when "1001010000000000" => dout <= "000";
+ when "1001010100000000" => dout <= "000";
+ when "1001011000000000" => dout <= "000";
+ when "1001011100000000" => dout <= "000";
+ when "1110010000000000" => dout <= "101";
+ when "1110010100000000" => dout <= "101";
+ when "1110110000000000" => dout <= "000";
+ when "1110110100000000" => dout <= "000";
+ when "1110011000000000" => dout <= "101";
+ when "1110011100000000" => dout <= "101";
+ when "1110111100000000" => dout <= "000";
+ when "1110111000000000" => dout <= "000";
+ when "1101011100000000" => dout <= "000";
+ when "1001111100000000" => dout <= "000";
+ when "1001111000000000" => dout <= "000";
+ when "1001110000000000" => dout <= "000";
+ when "1001110100000000" => dout <= "000";
+ when "1000110100000110" => dout <= "100";
+ when "1000110111000000" => dout <= "000";
+ when "1000110100000000" => dout <= "000";
+ when "1000110101000000" => dout <= "011";
+ when "1000110110000000" => dout <= "100";
+ when "1100010100000110" => dout <= "100";
+ when "1100010100000000" => dout <= "000";
+ when "1100010101000000" => dout <= "011";
+ when "1100010110000000" => dout <= "100";
+ when "1100010000000110" => dout <= "100";
+ when "1100010000000000" => dout <= "000";
+ when "1100010001000000" => dout <= "011";
+ when "1100010010000000" => dout <= "100";
+ when "0000000011000000" => dout <= "000";
+ when "0000000000000110" => dout <= "100";
+ when "0000000000000000" => dout <= "000";
+ when "0000000001000000" => dout <= "011";
+ when "0000000010000000" => dout <= "100";
+ when "0000000111000000" => dout <= "000";
+ when "0000000100000110" => dout <= "100";
+ when "0000000100000000" => dout <= "000";
+ when "0000000101000000" => dout <= "011";
+ when "0000000110000000" => dout <= "100";
+ when "0000001011000000" => dout <= "000";
+ when "0000001000000110" => dout <= "100";
+ when "0000001000000000" => dout <= "000";
+ when "0000001001000000" => dout <= "011";
+ when "0000001010000000" => dout <= "100";
+ when "0000001111000000" => dout <= "000";
+ when "0000001100000110" => dout <= "100";
+ when "0000001100000000" => dout <= "000";
+ when "0000001101000000" => dout <= "011";
+ when "0000001110000000" => dout <= "100";
+ when "1000000011000000" => dout <= "000";
+ when "1000000000000110" => dout <= "100";
+ when "1000000000000000" => dout <= "000";
+ when "1000000001000000" => dout <= "011";
+ when "1000000010000000" => dout <= "100";
+ when "1000000111000000" => dout <= "000";
+ when "1000000100000110" => dout <= "100";
+ when "1000000100000000" => dout <= "000";
+ when "1000000101000000" => dout <= "011";
+ when "1000000110000000" => dout <= "100";
+ when "1000001111000000" => dout <= "000";
+ when "1000001100000110" => dout <= "100";
+ when "1000001100000000" => dout <= "000";
+ when "1000001101000000" => dout <= "011";
+ when "1000001110000000" => dout <= "100";
+ when "0000010000000000" => dout <= "000";
+ when "0000010100000000" => dout <= "000";
+ when "0001000011000000" => dout <= "000";
+ when "0001000000000110" => dout <= "100";
+ when "0001000000000000" => dout <= "000";
+ when "0001000001000000" => dout <= "011";
+ when "0001000010000000" => dout <= "100";
+ when "0001000111000000" => dout <= "000";
+ when "0001000100000110" => dout <= "100";
+ when "0001000100000000" => dout <= "000";
+ when "0001000101000000" => dout <= "011";
+ when "0001000110000000" => dout <= "100";
+ when "0001001011000000" => dout <= "000";
+ when "0001001000000110" => dout <= "100";
+ when "0001001000000000" => dout <= "000";
+ when "0001001001000000" => dout <= "011";
+ when "0001001010000000" => dout <= "100";
+ when "0001001111000000" => dout <= "000";
+ when "0001001100000110" => dout <= "100";
+ when "0001001100000000" => dout <= "000";
+ when "0001001101000000" => dout <= "011";
+ when "0001001110000000" => dout <= "100";
+ when "1000000011010000" => dout <= "000";
+ when "1000000000010110" => dout <= "100";
+ when "1000000000010000" => dout <= "000";
+ when "1000000001010000" => dout <= "011";
+ when "1000000010010000" => dout <= "100";
+ when "1000000111010000" => dout <= "000";
+ when "1000000100010110" => dout <= "100";
+ when "1000000100010000" => dout <= "000";
+ when "1000000101010000" => dout <= "011";
+ when "1000000110010000" => dout <= "100";
+ when "1000001111010000" => dout <= "000";
+ when "1000001100010110" => dout <= "100";
+ when "1000001100010000" => dout <= "000";
+ when "1000001101010000" => dout <= "011";
+ when "1000001110010000" => dout <= "100";
+ when "0001010000000000" => dout <= "000";
+ when "0001010100000000" => dout <= "000";
+ when "0010100011000000" => dout <= "000";
+ when "0010100000000110" => dout <= "100";
+ when "0010100000000000" => dout <= "000";
+ when "0010100001000000" => dout <= "011";
+ when "0010100010000000" => dout <= "100";
+ when "0010100111000000" => dout <= "000";
+ when "0010100100000110" => dout <= "100";
+ when "0010100100000000" => dout <= "000";
+ when "0010100101000000" => dout <= "011";
+ when "0010100110000000" => dout <= "100";
+ when "0010101011000000" => dout <= "000";
+ when "0010101000000110" => dout <= "100";
+ when "0010101000000000" => dout <= "000";
+ when "0010101001000000" => dout <= "011";
+ when "0010101010000000" => dout <= "100";
+ when "0010101111000000" => dout <= "000";
+ when "0010101100000110" => dout <= "100";
+ when "0010101100000000" => dout <= "000";
+ when "0010101101000000" => dout <= "011";
+ when "0010101110000000" => dout <= "100";
+ when "1000000011101000" => dout <= "000";
+ when "1000000000101110" => dout <= "100";
+ when "1000000000101000" => dout <= "000";
+ when "1000000001101000" => dout <= "011";
+ when "1000000010101000" => dout <= "100";
+ when "1000000111101000" => dout <= "000";
+ when "1000000100101110" => dout <= "100";
+ when "1000000100101000" => dout <= "000";
+ when "1000000101101000" => dout <= "011";
+ when "1000000110101000" => dout <= "100";
+ when "1000001111101000" => dout <= "000";
+ when "1000001100101110" => dout <= "100";
+ when "1000001100101000" => dout <= "000";
+ when "1000001101101000" => dout <= "011";
+ when "1000001110101000" => dout <= "100";
+ when "0010110000000000" => dout <= "000";
+ when "0010110100000000" => dout <= "000";
+ when "0001100011000000" => dout <= "000";
+ when "0001100000000110" => dout <= "100";
+ when "0001100000000000" => dout <= "000";
+ when "0001100001000000" => dout <= "011";
+ when "0001100010000000" => dout <= "100";
+ when "0001100111000000" => dout <= "000";
+ when "0001100100000110" => dout <= "100";
+ when "0001100100000000" => dout <= "000";
+ when "0001100101000000" => dout <= "011";
+ when "0001100110000000" => dout <= "100";
+ when "0001101011000000" => dout <= "000";
+ when "0001101000000110" => dout <= "100";
+ when "0001101000000000" => dout <= "000";
+ when "0001101001000000" => dout <= "011";
+ when "0001101010000000" => dout <= "100";
+ when "0001101111000000" => dout <= "000";
+ when "0001101100000110" => dout <= "100";
+ when "0001101100000000" => dout <= "000";
+ when "0001101101000000" => dout <= "011";
+ when "0001101110000000" => dout <= "100";
+ when "1000000011011000" => dout <= "000";
+ when "1000000000011110" => dout <= "100";
+ when "1000000000011000" => dout <= "000";
+ when "1000000001011000" => dout <= "011";
+ when "1000000010011000" => dout <= "100";
+ when "1000000111011000" => dout <= "000";
+ when "1000000100011110" => dout <= "100";
+ when "1000000100011000" => dout <= "000";
+ when "1000000101011000" => dout <= "011";
+ when "1000000110011000" => dout <= "100";
+ when "1000001111011000" => dout <= "000";
+ when "1000001100011110" => dout <= "100";
+ when "1000001100011000" => dout <= "000";
+ when "1000001101011000" => dout <= "011";
+ when "1000001110011000" => dout <= "100";
+ when "0001110000000000" => dout <= "000";
+ when "0001110100000000" => dout <= "000";
+ when "1111111011000000" => dout <= "000";
+ when "1111111000000110" => dout <= "100";
+ when "1111111000000000" => dout <= "000";
+ when "1111111001000000" => dout <= "011";
+ when "1111111010000000" => dout <= "100";
+ when "1111111100000110" => dout <= "100";
+ when "1111111100000000" => dout <= "000";
+ when "1111111101000000" => dout <= "011";
+ when "1111111110000000" => dout <= "100";
+ when "0100000000000000" => dout <= "000";
+ when "0100000100000000" => dout <= "000";
+ when "0100001000000000" => dout <= "000";
+ when "0100001100000000" => dout <= "000";
+ when "0100010000000000" => dout <= "000";
+ when "0100010100000000" => dout <= "000";
+ when "0100011000000000" => dout <= "000";
+ when "0100011100000000" => dout <= "000";
+ when "1111111011001000" => dout <= "000";
+ when "1111111000001110" => dout <= "100";
+ when "1111111000001000" => dout <= "000";
+ when "1111111001001000" => dout <= "011";
+ when "1111111010001000" => dout <= "100";
+ when "1111111100001110" => dout <= "100";
+ when "1111111100001000" => dout <= "000";
+ when "1111111101001000" => dout <= "011";
+ when "1111111110001000" => dout <= "100";
+ when "0100100000000000" => dout <= "000";
+ when "0100100100000000" => dout <= "000";
+ when "0100101000000000" => dout <= "000";
+ when "0100101100000000" => dout <= "000";
+ when "0100110000000000" => dout <= "000";
+ when "0100110100000000" => dout <= "000";
+ when "0100111000000000" => dout <= "000";
+ when "0100111100000000" => dout <= "000";
+ when "0011101011000000" => dout <= "000";
+ when "0011101000000110" => dout <= "100";
+ when "0011101000000000" => dout <= "000";
+ when "0011101001000000" => dout <= "011";
+ when "0011101010000000" => dout <= "100";
+ when "0011101111000000" => dout <= "000";
+ when "0011101100000110" => dout <= "100";
+ when "0011101100000000" => dout <= "000";
+ when "0011101101000000" => dout <= "011";
+ when "0011101110000000" => dout <= "100";
+ when "0011100000000110" => dout <= "100";
+ when "0011100000000000" => dout <= "000";
+ when "0011100001000000" => dout <= "011";
+ when "0011100010000000" => dout <= "100";
+ when "0011100011000000" => dout <= "000";
+ when "0011100100000110" => dout <= "100";
+ when "0011100100000000" => dout <= "000";
+ when "0011100101000000" => dout <= "011";
+ when "0011100110000000" => dout <= "100";
+ when "0011100111000000" => dout <= "000";
+ when "1000000011111000" => dout <= "000";
+ when "1000000000111110" => dout <= "100";
+ when "1000000000111000" => dout <= "000";
+ when "1000000001111000" => dout <= "011";
+ when "1000000010111000" => dout <= "100";
+ when "1000000111111000" => dout <= "000";
+ when "1000000100111110" => dout <= "100";
+ when "1000000100111000" => dout <= "000";
+ when "1000000101111000" => dout <= "011";
+ when "1000000110111000" => dout <= "100";
+ when "1000001111111000" => dout <= "000";
+ when "1000001100111110" => dout <= "100";
+ when "1000001100111000" => dout <= "000";
+ when "1000001101111000" => dout <= "011";
+ when "1000001110111000" => dout <= "100";
+ when "0011110000000000" => dout <= "000";
+ when "0011110100000000" => dout <= "000";
+ when "1111011011011000" => dout <= "000";
+ when "1111011000011110" => dout <= "100";
+ when "1111011000011000" => dout <= "000";
+ when "1111011001011000" => dout <= "011";
+ when "1111011010011000" => dout <= "100";
+ when "1111011111011000" => dout <= "000";
+ when "1111011100011110" => dout <= "100";
+ when "1111011100011000" => dout <= "000";
+ when "1111011101011000" => dout <= "011";
+ when "1111011110011000" => dout <= "100";
+ when "0011011100000000" => dout <= "001";
+ when "0010011100000000" => dout <= "001";
+ when "0011111100000000" => dout <= "001";
+ when "0010111100000000" => dout <= "001";
+ when "1111011011100000" => dout <= "000";
+ when "1111011000100110" => dout <= "100";
+ when "1111011000100000" => dout <= "000";
+ when "1111011001100000" => dout <= "011";
+ when "1111011010100000" => dout <= "100";
+ when "1111011111100000" => dout <= "000";
+ when "1111011100100110" => dout <= "100";
+ when "1111011100100000" => dout <= "000";
+ when "1111011101100000" => dout <= "011";
+ when "1111011110100000" => dout <= "100";
+ when "1111011011101000" => dout <= "000";
+ when "1111011000101110" => dout <= "100";
+ when "1111011000101000" => dout <= "000";
+ when "1111011001101000" => dout <= "011";
+ when "1111011010101000" => dout <= "100";
+ when "1111011111101000" => dout <= "000";
+ when "1111011100101110" => dout <= "100";
+ when "1111011100101000" => dout <= "000";
+ when "1111011101101000" => dout <= "011";
+ when "1111011110101000" => dout <= "100";
+ when "1111011011110000" => dout <= "000";
+ when "1111011000110110" => dout <= "100";
+ when "1111011000110000" => dout <= "000";
+ when "1111011001110000" => dout <= "011";
+ when "1111011010110000" => dout <= "100";
+ when "1111011111110000" => dout <= "000";
+ when "1111011100110110" => dout <= "100";
+ when "1111011100110000" => dout <= "000";
+ when "1111011101110000" => dout <= "011";
+ when "1111011110110000" => dout <= "100";
+ when "1111011011111000" => dout <= "000";
+ when "1111011000111110" => dout <= "100";
+ when "1111011000111000" => dout <= "000";
+ when "1111011001111000" => dout <= "011";
+ when "1111011010111000" => dout <= "100";
+ when "1111011111111000" => dout <= "000";
+ when "1111011100111110" => dout <= "100";
+ when "1111011100111000" => dout <= "000";
+ when "1111011101111000" => dout <= "011";
+ when "1111011110111000" => dout <= "100";
+ when "1101010000000000" => dout <= "000";
+ when "1101010100000000" => dout <= "000";
+ when "1001100000000000" => dout <= "000";
+ when "1001100100000000" => dout <= "000";
+ when "1101000011000000" => dout <= "000";
+ when "1101000000000110" => dout <= "100";
+ when "1101000000000000" => dout <= "000";
+ when "1101000001000000" => dout <= "011";
+ when "1101000010000000" => dout <= "100";
+ when "1101000111000000" => dout <= "000";
+ when "1101000100000110" => dout <= "100";
+ when "1101000100000000" => dout <= "000";
+ when "1101000101000000" => dout <= "011";
+ when "1101000110000000" => dout <= "100";
+ when "1101001011000000" => dout <= "000";
+ when "1101001000000110" => dout <= "100";
+ when "1101001000000000" => dout <= "000";
+ when "1101001001000000" => dout <= "011";
+ when "1101001010000000" => dout <= "100";
+ when "1101001111000000" => dout <= "000";
+ when "1101001100000110" => dout <= "100";
+ when "1101001100000000" => dout <= "000";
+ when "1101001101000000" => dout <= "011";
+ when "1101001110000000" => dout <= "100";
+ when "0010000011000000" => dout <= "000";
+ when "0010000000000110" => dout <= "100";
+ when "0010000000000000" => dout <= "000";
+ when "0010000001000000" => dout <= "011";
+ when "0010000010000000" => dout <= "100";
+ when "0010000111000000" => dout <= "000";
+ when "0010000100000110" => dout <= "100";
+ when "0010000100000000" => dout <= "000";
+ when "0010000101000000" => dout <= "011";
+ when "0010000110000000" => dout <= "100";
+ when "0010001011000000" => dout <= "000";
+ when "0010001000000110" => dout <= "100";
+ when "0010001000000000" => dout <= "000";
+ when "0010001001000000" => dout <= "011";
+ when "0010001010000000" => dout <= "100";
+ when "0010001111000000" => dout <= "000";
+ when "0010001100000110" => dout <= "100";
+ when "0010001100000000" => dout <= "000";
+ when "0010001101000000" => dout <= "011";
+ when "0010001110000000" => dout <= "100";
+ when "1000000011100000" => dout <= "000";
+ when "1000000000100110" => dout <= "100";
+ when "1000000000100000" => dout <= "000";
+ when "1000000001100000" => dout <= "011";
+ when "1000000010100000" => dout <= "100";
+ when "1000000111100000" => dout <= "000";
+ when "1000000100100110" => dout <= "100";
+ when "1000000100100000" => dout <= "000";
+ when "1000000101100000" => dout <= "011";
+ when "1000000110100000" => dout <= "100";
+ when "1000001111100000" => dout <= "000";
+ when "1000001100100110" => dout <= "100";
+ when "1000001100100000" => dout <= "000";
+ when "1000001101100000" => dout <= "011";
+ when "1000001110100000" => dout <= "100";
+ when "0010010000000000" => dout <= "000";
+ when "0010010100000000" => dout <= "000";
+ when "0000100000000110" => dout <= "100";
+ when "0000100000000000" => dout <= "000";
+ when "0000100001000000" => dout <= "011";
+ when "0000100010000000" => dout <= "100";
+ when "0000100011000000" => dout <= "000";
+ when "0000100100000110" => dout <= "100";
+ when "0000100100000000" => dout <= "000";
+ when "0000100101000000" => dout <= "011";
+ when "0000100110000000" => dout <= "100";
+ when "0000100111000000" => dout <= "000";
+ when "0000101011000000" => dout <= "000";
+ when "0000101000000110" => dout <= "100";
+ when "0000101000000000" => dout <= "000";
+ when "0000101001000000" => dout <= "011";
+ when "0000101010000000" => dout <= "100";
+ when "0000101111000000" => dout <= "000";
+ when "0000101100000110" => dout <= "100";
+ when "0000101100000000" => dout <= "000";
+ when "0000101101000000" => dout <= "011";
+ when "0000101110000000" => dout <= "100";
+ when "1000000011001000" => dout <= "000";
+ when "1000000000001110" => dout <= "100";
+ when "1000000000001000" => dout <= "000";
+ when "1000000001001000" => dout <= "011";
+ when "1000000010001000" => dout <= "100";
+ when "1000000111001000" => dout <= "000";
+ when "1000000100001110" => dout <= "100";
+ when "1000000100001000" => dout <= "000";
+ when "1000000101001000" => dout <= "011";
+ when "1000000110001000" => dout <= "100";
+ when "1000001111001000" => dout <= "000";
+ when "1000001100001110" => dout <= "100";
+ when "1000001100001000" => dout <= "000";
+ when "1000001101001000" => dout <= "011";
+ when "1000001110001000" => dout <= "100";
+ when "0000110000000000" => dout <= "000";
+ when "0000110100000000" => dout <= "000";
+ when "1000010000000110" => dout <= "100";
+ when "1000010000000000" => dout <= "000";
+ when "1000010001000000" => dout <= "011";
+ when "1000010010000000" => dout <= "100";
+ when "1000010100000110" => dout <= "100";
+ when "1000010100000000" => dout <= "000";
+ when "1000010101000000" => dout <= "011";
+ when "1000010110000000" => dout <= "100";
+ when "1000010011000000" => dout <= "000";
+ when "1000010111000000" => dout <= "000";
+ when "1111011011000000" => dout <= "000";
+ when "1111011000000110" => dout <= "100";
+ when "1111011000000000" => dout <= "000";
+ when "1111011001000000" => dout <= "011";
+ when "1111011010000000" => dout <= "100";
+ when "1111011111000000" => dout <= "000";
+ when "1111011100000110" => dout <= "100";
+ when "1111011100000000" => dout <= "000";
+ when "1111011101000000" => dout <= "011";
+ when "1111011110000000" => dout <= "100";
+ when "1010100000000000" => dout <= "000";
+ when "1010100100000000" => dout <= "000";
+ when "0011000000000110" => dout <= "100";
+ when "0011000000000000" => dout <= "000";
+ when "0011000001000000" => dout <= "011";
+ when "0011000010000000" => dout <= "100";
+ when "0011000011000000" => dout <= "000";
+ when "0011000100000110" => dout <= "100";
+ when "0011000100000000" => dout <= "000";
+ when "0011000101000000" => dout <= "011";
+ when "0011000110000000" => dout <= "100";
+ when "0011000111000000" => dout <= "000";
+ when "0011001011000000" => dout <= "000";
+ when "0011001000000110" => dout <= "100";
+ when "0011001000000000" => dout <= "000";
+ when "0011001001000000" => dout <= "011";
+ when "0011001010000000" => dout <= "100";
+ when "0011001111000000" => dout <= "000";
+ when "0011001100000110" => dout <= "100";
+ when "0011001100000000" => dout <= "000";
+ when "0011001101000000" => dout <= "011";
+ when "0011001110000000" => dout <= "100";
+ when "1000000011110000" => dout <= "000";
+ when "1000000000110110" => dout <= "100";
+ when "1000000000110000" => dout <= "000";
+ when "1000000001110000" => dout <= "011";
+ when "1000000010110000" => dout <= "100";
+ when "1000000111110000" => dout <= "000";
+ when "1000000100110110" => dout <= "100";
+ when "1000000100110000" => dout <= "000";
+ when "1000000101110000" => dout <= "011";
+ when "1000000110110000" => dout <= "100";
+ when "1000001111110000" => dout <= "000";
+ when "1000001100110110" => dout <= "100";
+ when "1000001100110000" => dout <= "000";
+ when "1000001101110000" => dout <= "011";
+ when "1000001110110000" => dout <= "100";
+ when "0011010000000000" => dout <= "000";
+ when "0011010100000000" => dout <= "000";
+ when "1111011011010000" => dout <= "000";
+ when "1111011000010110" => dout <= "100";
+ when "1111011000010000" => dout <= "000";
+ when "1111011001010000" => dout <= "011";
+ when "1111011010010000" => dout <= "100";
+ when "1111011111010000" => dout <= "000";
+ when "1111011100010110" => dout <= "100";
+ when "1111011100010000" => dout <= "000";
+ when "1111011101010000" => dout <= "011";
+ when "1111011110010000" => dout <= "100";
+ when "1010010000000000" => dout <= "000";
+ when "1010010100000000" => dout <= "000";
+ when "1010011000000000" => dout <= "000";
+ when "1010011100000000" => dout <= "000";
+ when "1010111000000000" => dout <= "000";
+ when "1010111100000000" => dout <= "000";
+ when "1010110000000000" => dout <= "000";
+ when "1010110100000000" => dout <= "000";
+ when "1010101000000000" => dout <= "000";
+ when "1010101100000000" => dout <= "000";
+ when "1111001000000000" => dout <= "000";
+ when "1111001100000000" => dout <= "000";
+ when "0110000000000000" => dout <= "000";
+ when "0110000100000000" => dout <= "000";
+ when "1100100000000000" => dout <= "000";
+ when "1100100100000000" => dout <= "000";
+ when "0110001000000000" => dout <= "000";
+ when "0110110000000000" => dout <= "000";
+ when "0110110100000000" => dout <= "000";
+ when "0110111000000000" => dout <= "000";
+ when "0110111100000000" => dout <= "000";
+ when "0000111100000000" => dout <= "000";
+ when "0110001100000000" => dout <= "000";
+ when "0110010000000000" => dout <= "000";
+ when "0110010100000000" => dout <= "000";
+ when "0110011000000000" => dout <= "000";
+ when "0110011100000000" => dout <= "000";
+ when "1000001000000000" => dout <= "000";
+ when "1101011000000000" => dout <= "000";
+ when "1111000100000000" => dout <= "000";
+ when "1100000000000000" => dout <= "000";
+ when "1100000100000000" => dout <= "000";
+ when others => dout <= "---";
+ end case;
+ end process;
+end rtl;
\ No newline at end of file
diff --git a/common/CPU/cpu86/alu_rtl.vhd b/common/CPU/cpu86/alu_rtl.vhd
new file mode 100644
index 00000000..e108af62
--- /dev/null
+++ b/common/CPU/cpu86/alu_rtl.vhd
@@ -0,0 +1,848 @@
+-------------------------------------------------------------------------------
+-- CPU86 - VHDL CPU8088 IP core --
+-- Copyright (C) 2002-2008 HT-LAB --
+-- --
+-- Contact/bugs : http://www.ht-lab.com/misc/feedback.html --
+-- Web : http://www.ht-lab.com --
+-- --
+-- CPU86 is released as open-source under the GNU GPL license. This means --
+-- that designs based on CPU86 must be distributed in full source code --
+-- under the same license. Contact HT-Lab for commercial applications where --
+-- source-code distribution is not desirable. --
+-- --
+-------------------------------------------------------------------------------
+-- --
+-- This library is free software; you can redistribute it and/or --
+-- modify it under the terms of the GNU Lesser General Public --
+-- License as published by the Free Software Foundation; either --
+-- version 2.1 of the License, or (at your option) any later version. --
+-- --
+-- This library 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 --
+-- Lesser General Public License for more details. --
+-- --
+-- Full details of the license can be found in the file "copying.txt". --
+-- --
+-- You should have received a copy of the GNU Lesser General Public --
+-- License along with this library; if not, write to the Free Software --
+-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --
+-- --
+-------------------------------------------------------------------------------
+-- Ver 0.82 Fixed RCR X,CL --
+-------------------------------------------------------------------------------
+
+LIBRARY ieee;
+USE ieee.std_logic_1164.ALL;
+USE ieee.std_logic_unsigned.ALL;
+USE ieee.std_logic_arith.ALL;
+
+USE work.cpu86pack.ALL;
+
+ENTITY ALU IS
+ PORT(
+ alu_inbusa : IN std_logic_vector (15 DOWNTO 0);
+ alu_inbusb : IN std_logic_vector (15 DOWNTO 0);
+ aluopr : IN std_logic_vector (6 DOWNTO 0);
+ ax_s : IN std_logic_vector (15 DOWNTO 0);
+ clk : IN std_logic;
+ cx_s : IN std_logic_vector (15 DOWNTO 0);
+ dx_s : IN std_logic_vector (15 DOWNTO 0);
+ reset : IN std_logic;
+ w : IN std_logic;
+ wralu : IN std_logic;
+ wrcc : IN std_logic;
+ wrtemp : IN std_logic;
+ alubus : OUT std_logic_vector (15 DOWNTO 0);
+ ccbus : OUT std_logic_vector (15 DOWNTO 0);
+ div_err : OUT std_logic
+ );
+END ALU ;
+
+architecture rtl of alu is
+
+component divider is -- Generic Divider
+
+generic(
+ WIDTH_DIVID : Integer := 32; -- Width Dividend
+ WIDTH_DIVIS : Integer := 16; -- Width Divisor
+ WIDTH_SHORT : Integer := 8); -- Check Overflow against short Byte/Word
+port(
+ clk : in std_logic; -- System Clock, not used in this architecture
+ reset : in std_logic; -- Active high, not used in this architecture
+ dividend : in std_logic_vector (WIDTH_DIVID-1 DOWNTO 0);
+ divisor : in std_logic_vector (WIDTH_DIVIS-1 DOWNTO 0);
+ quotient : out std_logic_vector (WIDTH_DIVIS-1 DOWNTO 0); -- changed to 16 bits!! (S not D)
+ remainder : out std_logic_vector (WIDTH_DIVIS-1 DOWNTO 0);
+ twocomp : in std_logic; -- '1' = 2's Complement, '0' = Unsigned
+ w : in std_logic; -- '0'=byte, '1'=word (cpu processor)
+ overflow : out std_logic; -- '1' if div by 0 or overflow
+ start : in std_logic; -- not used in this architecture
+ done : out std_logic); -- not used in this architecture
+end component divider;
+
+component multiplier is -- Generic Multiplier
+ generic (WIDTH : integer := 16);
+port (multiplicant : in std_logic_vector (WIDTH-1 downto 0);
+ multiplier : in std_logic_vector (WIDTH-1 downto 0);
+ product : out std_logic_vector (WIDTH+WIDTH-1 downto 0);-- result
+ twocomp : in std_logic);
+end component multiplier;
+
+signal product_s : std_logic_vector(31 downto 0); -- result multiplier
+
+signal dividend_s : std_logic_vector(31 downto 0); -- Input divider
+signal remainder_s : std_logic_vector(15 downto 0); -- Divider result
+signal quotient_s : std_logic_vector(15 downto 0); -- Divider result
+signal divresult_s : std_logic_vector(31 DOWNTO 0); -- Output divider to alubus
+signal div_err_s : std_logic; -- Divide by 0
+
+signal twocomp_s : std_logic; -- Sign Extend for IMUL and IDIV
+signal wl_s : std_logic; -- Latched w signal, used for muliplier/divider
+
+signal alubus_s : std_logic_vector (15 DOWNTO 0);
+
+signal abus_s : std_logic_vector(15 downto 0);
+signal bbus_s : std_logic_vector(15 downto 0);
+signal dxbus_s : std_logic_vector(15 downto 0); -- DX register
+
+signal addbbus_s : std_logic_vector(15 downto 0); -- bbus connected to full adder
+signal cbus_s : std_logic_vector(16 downto 0); -- Carry Bus
+signal outbus_s : std_logic_vector(15 downto 0); -- outbus=abus+bbus
+
+signal sign16a_s : std_logic_vector(15 downto 0); -- sign extended alu_busa(7 downto 0)
+signal sign16b_s : std_logic_vector(15 downto 0); -- sign extended alu_busb(7 downto 0)
+signal sign32a_s : std_logic_vector(15 downto 0); -- 16 bits alu_busa(15) vector (CWD)
+
+signal aasbus_s : std_logic_vector(15 downto 0); -- used for AAS instruction
+signal aas1bus_s : std_logic_vector(15 downto 0);
+
+signal daabus_s : std_logic_vector(7 downto 0); -- used for DAA instruction
+signal dasbus_s : std_logic_vector(7 downto 0); -- used for DAS instruction
+
+signal aaabus_s : std_logic_vector(15 downto 0); -- used for AAA instruction
+signal aaa1bus_s : std_logic_vector(15 downto 0);
+
+signal aadbus_s : std_logic_vector(15 downto 0); -- used for AAD instruction
+signal aad1bus_s : std_logic_vector(10 downto 0);
+signal aad2bus_s : std_logic_vector(10 downto 0);
+
+signal setaas_s : std_logic; -- '1' set CF & AF else both 0
+signal setaaa_s : std_logic; -- '1' set CF & AF else both 0
+signal setdaa_s : std_logic_vector(1 downto 0); -- "11" set CF & AF
+signal setdas_s : std_logic_vector(1 downto 0); -- "11" set CF & AF
+
+signal bit4_s : std_logic; -- used for AF flag
+signal cout_s : std_logic;
+
+signal psrreg_s : std_logic_vector(15 downto 0); -- 16 bits flag register
+
+signal zflaglow_s : std_logic; -- low byte zero flag (w=0)
+signal zflaghigh_s : std_logic; -- high byte zero flag (w=1)
+signal zeroflag_s : std_logic; -- zero flag, asserted when zero
+
+signal c1flag_s : std_logic; -- Asserted when CX=1(w=1) or CL=1(w=0)
+
+signal zflagdx_s : std_logic; -- Result (DX) zero flag, asserted when not zero (used for mul/imul)
+
+signal zflagah_s : std_logic; -- '1' if IMUL(15..8)/=0
+signal hflagah_s : std_logic; -- Used for IMUL
+signal hflagdx_s : std_logic; -- Used for IMUL
+
+signal overflow_s : std_logic;
+signal parityflag_s: std_logic;
+signal signflag_s : std_logic;
+
+alias OFLAG : std_logic is psrreg_s(11);
+alias DFLAG : std_logic is psrreg_s(10);
+alias IFLAG : std_logic is psrreg_s(9);
+alias TFLAG : std_logic is psrreg_s(8);
+alias SFLAG : std_logic is psrreg_s(7);
+alias ZFLAG : std_logic is psrreg_s(6);
+alias AFLAG : std_logic is psrreg_s(4);
+alias PFLAG : std_logic is psrreg_s(2);
+alias CFLAG : std_logic is psrreg_s(0);
+
+signal alureg_s : std_logic_vector(31 downto 0); -- 31 bits temp register for alu_inbusa & alu_inbusb
+signal alucout_s : std_logic; -- ALUREG Carry Out signal
+
+signal alu_temp_s : std_logic_vector(15 downto 0); -- Temp/scratchpad register, use ALU_TEMP to select
+
+signal done_s : std_logic; -- Serial divider conversion done
+signal startdiv_s : std_logic; -- Serial divider start pulse
+
+begin
+
+ALUU1 : divider
+ generic map (WIDTH_DIVID => 32, WIDTH_DIVIS => 16, WIDTH_SHORT => 8)
+ port map (clk => clk,
+ reset => reset,
+ dividend => dividend_s, -- DX:AX
+ divisor => alureg_s(15 downto 0), -- 0&byte/word
+ --divisor => bbus_s, -- byte/word
+ quotient => quotient_s, -- 16 bits
+ remainder => remainder_s, -- 16 bits
+ twocomp => twocomp_s,
+ w => wl_s, -- Byte/Word
+ overflow => div_err_s, -- Divider Overflow. generate int0
+ start => startdiv_s, -- start conversion, generated by proc
+ done => done_s); -- conversion done, latch results
+
+ALUU2 : multiplier
+ generic map (WIDTH => 16) -- Result is 2*WIDTH bits
+ port map (multiplicant=> alureg_s(31 downto 16),
+ multiplier => alureg_s(15 downto 0),
+ product => product_s, -- 32 bits!
+ twocomp => twocomp_s);
+
+dividend_s <= X"000000"&alureg_s(23 downto 16) when aluopr=ALU_AAM else dxbus_s & alureg_s(31 downto 16);-- DX is sign extended for byte IDIV
+
+-- start serial divider 1 cycle after wralu pulse received. The reason is that the dividend is loaded into the
+-- accumulator thus the data must be valid when this happens.
+process (clk, reset)
+ begin
+ if reset='1' then
+ startdiv_s <= '0';
+ elsif rising_edge(clk) then
+ if (wralu='1' and (aluopr=ALU_DIV or aluopr=ALU_IDIV OR aluopr=ALU_AAM)) then
+ startdiv_s <= '1';
+ else
+ startdiv_s <= '0';
+ end if;
+ end if;
+end process;
+
+----------------------------------------------------------------------------
+-- Create Full adder
+----------------------------------------------------------------------------
+fulladd: for bit_nr in 0 to 15 generate
+ outbus_s(bit_nr) <= abus_s(bit_nr) xor addbbus_s(bit_nr) xor cbus_s(bit_nr);
+
+ cbus_s(bit_nr+1) <= (abus_s(bit_nr) and addbbus_s(bit_nr)) or
+ (abus_s(bit_nr) and cbus_s(bit_nr)) or
+ (addbbus_s(bit_nr) and cbus_s(bit_nr));
+end generate fulladd;
+
+bit4_s <= cbus_s(4);
+
+sign16a_s <= alu_inbusa(7) &alu_inbusa(7) &alu_inbusa(7) &alu_inbusa(7)&alu_inbusa(7)&
+ alu_inbusa(7) &alu_inbusa(7) &alu_inbusa(7) &alu_inbusa(7 downto 0);
+sign16b_s <= alu_inbusb(7) &alu_inbusb(7) &alu_inbusb(7) &alu_inbusb(7)&alu_inbusb(7)&
+ alu_inbusb(7) &alu_inbusb(7) &alu_inbusb(7) &alu_inbusb(7 downto 0);
+sign32a_s <= alu_inbusa(15)&alu_inbusa(15)&alu_inbusa(15)&alu_inbusa(15)&alu_inbusa(15)&
+ alu_inbusa(15)&alu_inbusa(15)&alu_inbusa(15)&alu_inbusa(15)&alu_inbusa(15)&
+ alu_inbusa(15)&alu_inbusa(15)&alu_inbusa(15)&alu_inbusa(15)&alu_inbusa(15)&
+ alu_inbusa(15);
+
+-- Invert bus for subtract instructions
+addbbus_s <= not bbus_s when ((aluopr=ALU_CMP) or (aluopr=ALU_CMP_SE) or (aluopr=ALU_CMPS) or (aluopr=ALU_DEC)
+ or (aluopr=ALU_SBB) or (aluopr=ALU_SBB_SE) or (aluopr=ALU_PUSH) or (aluopr=ALU_SUB)
+ or (aluopr=ALU_SUB_SE) or (aluopr=ALU_SCAS)) else bbus_s;
+
+
+-- sign extend for IDIV and IMUL instructions
+twocomp_s <= '1' when ((aluopr=ALU_IDIV) or (aluopr=ALU_IMUL) or
+ (aluopr=ALU_IDIV2)or (aluopr=ALU_IMUL2)) else '0';
+
+----------------------------------------------------------------------------
+-- Sign Extend Logic abus & bbus & dxbus
+----------------------------------------------------------------------------
+process (w, alu_inbusa, alu_inbusb, sign16a_s, sign16b_s, aluopr, ax_s, alureg_s)
+ begin
+ if (w='1') then -- Word, no sign extend, unless signextend is specified
+ case aluopr is
+ when ALU_CMPS =>
+ abus_s <= alu_inbusa; -- no sign extend
+ bbus_s <= alureg_s(15 downto 0); -- previous read ES:[DI]
+ when ALU_NEG | ALU_NOT =>
+ abus_s <= not(alu_inbusa); -- NEG instruction, not(operand)+1
+ bbus_s <= alu_inbusb; -- 0001 (0000 for NOT)
+ when ALU_ADD_SE | ALU_ADC_SE | ALU_SBB_SE | ALU_SUB_SE | ALU_CMP_SE |
+ ALU_OR_SE | ALU_AND_SE | ALU_XOR_SE=>
+ abus_s <= alu_inbusa; -- no sign extend
+ bbus_s <= sign16b_s; -- Sign extend on 8 bits immediate values (see O80I2RM)
+ when others =>
+ abus_s <= alu_inbusa; -- no sign extend
+ bbus_s <= alu_inbusb;
+ end case;
+ else
+ case aluopr is
+ when ALU_CMPS =>
+ abus_s <= alu_inbusa;
+ bbus_s <= alureg_s(15 downto 0);
+ when ALU_DIV | ALU_DIV2 =>
+ abus_s <= ax_s;
+ bbus_s <= alu_inbusb;
+ when ALU_IDIV| ALU_IDIV2 =>
+ abus_s <= ax_s;
+ bbus_s <= sign16b_s;
+ when ALU_MUL | ALU_MUL2 | ALU_SCAS =>
+ abus_s <= alu_inbusa;
+ bbus_s <= alu_inbusb;
+ when ALU_NEG | ALU_NOT =>
+ abus_s <= not(alu_inbusa); -- NEG instruction, not(operand)+1
+ bbus_s <= alu_inbusb; -- 0001 (0000 for NOT)
+ when others =>
+ abus_s <= sign16a_s;
+ bbus_s <= sign16b_s;
+ end case;
+ end if;
+end process;
+
+process (wl_s, aluopr, dx_s, alu_inbusa) -- dxbus for DIV/IDIV only
+ begin
+ if (wl_s='1') then -- Word, no sign extend
+ dxbus_s <= dx_s;
+ else -- Byte
+ if (((aluopr=ALU_IDIV) or (aluopr=ALU_IDIV2)) and (alu_inbusa(15)='1')) then -- signed DX<-SE(AX)/bbus<-SE(byte)
+ dxbus_s <= X"FFFF"; -- DX=FFFF (ignored for mul)
+ else
+ dxbus_s <= X"0000"; -- DX=0000 (ignored for mul)
+ end if;
+ end if;
+end process;
+
+----------------------------------------------------------------------------
+-- Carry In logic
+----------------------------------------------------------------------------
+process (aluopr, psrreg_s)
+ begin
+ case aluopr is
+ when ALU_ADD | ALU_ADD_SE | ALU_INC | ALU_POP | ALU_NEG | ALU_NOT
+ => cbus_s(0) <= '0';
+ when ALU_SBB | ALU_SBB_SE
+ => cbus_s(0) <= not CFLAG;
+ when ALU_SUB | ALU_SUB_SE | ALU_DEC | ALU_PUSH | ALU_CMP | ALU_CMP_SE
+ | ALU_CMPS | ALU_SCAS
+ => cbus_s(0) <= '1';
+ when others => cbus_s(0) <= CFLAG; -- ALU_ADC, ALU_SUB, ALU_SBB
+ end case;
+end process;
+
+----------------------------------------------------------------------------
+-- Carry Out logic
+-- cout is inverted for ALU_SUB and ALU_SBB before written to psrreg_s
+----------------------------------------------------------------------------
+process (aluopr, w, psrreg_s, cbus_s, alu_inbusa)
+ begin
+ case aluopr is
+ when ALU_ADD | ALU_ADD_SE | ALU_ADC | ALU_ADC_SE | ALU_SUB | ALU_SUB_SE | ALU_SBB | ALU_SBB_SE |
+ ALU_CMP | ALU_CMP_SE | ALU_CMPS| ALU_SCAS =>
+ if (w='1') then cout_s <= cbus_s(16);
+ else cout_s <= cbus_s(8);
+ end if;
+ when ALU_NEG => -- CF=0 if operand=0, else 1
+ if (alu_inbusa=X"0000") then
+ cout_s <= '1'; -- Note CFLAG=NOT(cout_s)
+ else
+ cout_s <= '0'; -- Note CFLAG=NOT(cout_s)
+ end if;
+ when others =>
+ cout_s <= CFLAG; -- Keep previous value
+ end case;
+end process;
+
+----------------------------------------------------------------------------
+-- Overflow Logic
+----------------------------------------------------------------------------
+process (aluopr, w, psrreg_s, cbus_s, alureg_s, alucout_s, zflaghigh_s, zflagdx_s,hflagdx_s,zflagah_s,
+ hflagah_s, wl_s, product_s, c1flag_s)
+ begin
+ case aluopr is
+ when ALU_ADD | ALU_ADD_SE | ALU_ADC | ALU_ADC_SE | ALU_INC | ALU_DEC | ALU_SUB | ALU_SUB_SE |
+ ALU_SBB | ALU_SBB_SE | ALU_CMP | ALU_CMP_SE | ALU_CMPS | ALU_SCAS | ALU_NEG =>
+ if w='1' then -- 16 bits
+ overflow_s <= cbus_s(16) xor cbus_s(15);
+ else
+ overflow_s <= cbus_s(8) xor cbus_s(7);
+ end if;
+
+ when ALU_ROL1 | ALU_RCL1 | ALU_SHL1 => -- count=1 using constants as in rcl bx,1
+ if (((w='1') and (alureg_s(15)/=alucout_s)) or
+ ((w='0') and (alureg_s(7) /=alucout_s))) then
+ overflow_s <= '1';
+ else
+ overflow_s <= '0';
+ end if;
+ when ALU_ROL | ALU_RCL | ALU_SHL => -- cl/cx=1
+ if (( c1flag_s='1' and w='1' and (alureg_s(15)/=alucout_s)) or
+ ( c1flag_s='1' and w='0' and (alureg_s(7) /=alucout_s))) then
+ overflow_s <= '1';
+ else
+ overflow_s <= '0';
+ end if;
+
+
+ when ALU_ROR1 | ALU_RCR1 | ALU_SHR1 | ALU_SAR1 =>
+ if (((w='1') and (alureg_s(15)/=alureg_s(14))) or
+ ((w='0') and (alureg_s(7) /=alureg_s(6)))) then
+ overflow_s <= '1';
+ else
+ overflow_s <= '0';
+ end if;
+ when ALU_ROR | ALU_RCR | ALU_SHR | ALU_SAR => -- if cl/cx=1
+ if ((c1flag_s='1' and w='1' and (alureg_s(15)/=alureg_s(14))) or
+ (c1flag_s='1' and w='0' and (alureg_s(7) /=alureg_s(6)))) then
+ overflow_s <= '1';
+ else
+ overflow_s <= '0';
+ end if;
+
+
+ when ALU_MUL | ALU_MUL2 =>
+ if (wl_s='0') then
+ overflow_s <= zflaghigh_s;
+ else
+ overflow_s <= zflagdx_s; -- MSW multiply/divide result
+ end if;
+ when ALU_IMUL | ALU_IMUL2 => -- if MSbit(1)='1' & AH=FF/DX=FFFF
+ if ((wl_s='0' and product_s(7)='1' and hflagah_s='1') or
+ (wl_s='0' and product_s(7)='0' and zflagah_s='0') or
+ (wl_s='1' and product_s(15)='1' and hflagdx_s='1') or
+ (wl_s='1' and product_s(15)='0' and zflagdx_s='0')) then
+ overflow_s <= '0';
+ else
+ overflow_s <= '1';
+ end if;
+ when others =>
+ overflow_s <= OFLAG; -- Keep previous value
+ end case;
+end process;
+
+----------------------------------------------------------------------------
+-- Zeroflag set if result=0, zflagdx_s=1 when dx/=0, zflagah_s=1 when ah/=0
+----------------------------------------------------------------------------
+zflaglow_s <= alubus_s(7) or alubus_s(6) or alubus_s(5) or alubus_s(4) or
+ alubus_s(3) or alubus_s(2) or alubus_s(1) or alubus_s(0);
+zflaghigh_s <= alubus_s(15) or alubus_s(14) or alubus_s(13) or alubus_s(12) or
+ alubus_s(11) or alubus_s(10) or alubus_s(9) or alubus_s(8);
+zeroflag_s <= not(zflaghigh_s or zflaglow_s) when w='1' else not(zflaglow_s);
+
+zflagdx_s <= product_s(31) or product_s(30) or product_s(29) or product_s(28) or
+ product_s(27) or product_s(26) or product_s(25) or product_s(24) or
+ product_s(23) or product_s(22) or product_s(21) or product_s(20) or
+ product_s(19) or product_s(18) or product_s(17) or product_s(16);
+
+zflagah_s <= product_s(15) or product_s(14) or product_s(13) or product_s(12) or
+ product_s(11) or product_s(10) or product_s(09) or product_s(08);
+
+----------------------------------------------------------------------------
+-- hflag set if IMUL result AH=FF or DX=FFFF
+----------------------------------------------------------------------------
+hflagah_s <= product_s(15) and product_s(14) and product_s(13) and product_s(12) and
+ product_s(11) and product_s(10) and product_s(9) and product_s(8);
+
+hflagdx_s <= product_s(31) and product_s(30) and product_s(29) and product_s(28) and
+ product_s(27) and product_s(26) and product_s(25) and product_s(24) and
+ product_s(23) and product_s(22) and product_s(21) and product_s(20) and
+ product_s(19) and product_s(18) and product_s(17) and product_s(16);
+
+----------------------------------------------------------------------------
+-- Parity flag set if even number of bits in LSB
+----------------------------------------------------------------------------
+parityflag_s <=not(alubus_s(7) xor alubus_s(6) xor alubus_s(5) xor alubus_s(4) xor
+ alubus_s(3) xor alubus_s(2) xor alubus_s(1) xor alubus_s(0));
+
+----------------------------------------------------------------------------
+-- Sign flag
+----------------------------------------------------------------------------
+signflag_s <= alubus_s(15) when w='1' else alubus_s(7);
+
+----------------------------------------------------------------------------
+-- c1flag asserted if CL or CX=1, used to update the OF flags during
+-- rotate/shift instructions
+----------------------------------------------------------------------------
+c1flag_s <= '1' when (cx_s=X"0001" and w='1') OR (cx_s(7 downto 0)=X"01" and w='0') else '0';
+
+----------------------------------------------------------------------------
+-- Temp/ScratchPad Register
+-- alureg_s can also be used as temp storage
+-- temp<=bbus;
+----------------------------------------------------------------------------
+process (clk, reset)
+ begin
+ if reset='1' then
+ alu_temp_s<= (others => '0');
+ elsif rising_edge(clk) then
+ if (wrtemp='1') then
+ alu_temp_s <= bbus_s;
+ end if;
+ end if;
+end process;
+
+
+----------------------------------------------------------------------------
+-- ALU Register used for xchg and rotate/shift instruction
+-- latch Carry Out alucout_s signal
+----------------------------------------------------------------------------
+process (clk, reset)
+ begin
+ if reset='1' then
+ alureg_s <= (others => '0');
+ alucout_s<= '0';
+ wl_s <= '0';
+ elsif rising_edge(clk) then
+ if (wralu='1') then
+ alureg_s(31 downto 16) <= abus_s; -- alu_inbusa;
+ wl_s <= w; -- Latched w version
+ if w='1' then -- word operation
+ case aluopr is
+ when ALU_ROL | ALU_ROL1 => alureg_s(15 downto 0) <= alureg_s(14 downto 0) & alureg_s(15);
+ alucout_s<= alureg_s(15);
+ when ALU_ROR | ALU_ROR1 => alureg_s(15 downto 0) <= alureg_s(0) & alureg_s(15 downto 1);
+ alucout_s<= alureg_s(0);
+ when ALU_RCL | ALU_RCL1 => alureg_s(15 downto 0) <= alureg_s(14 downto 0) & alucout_s; -- shift carry in
+ alucout_s<= alureg_s(15);
+ when ALU_RCR | ALU_RCR1 => alureg_s(15 downto 0) <= alucout_s & alureg_s(15 downto 1);
+ alucout_s<= alureg_s(0);
+ when ALU_SHL | ALU_SHL1 => alureg_s(15 downto 0) <= alureg_s(14 downto 0) & '0';
+ alucout_s<= alureg_s(15);
+ when ALU_SHR | ALU_SHR1 => alureg_s(15 downto 0) <= '0' & alureg_s(15 downto 1);
+ alucout_s<= alureg_s(0);
+ when ALU_SAR | ALU_SAR1 => alureg_s(15 downto 0) <= alureg_s(15) & alureg_s(15 downto 1);
+ alucout_s<= alureg_s(0);
+ when ALU_TEMP => alureg_s(15 downto 0) <= bbus_s;
+ alucout_s<= '-'; -- Don't care!
+ when ALU_AAM => alureg_s(15 downto 0) <= X"000A";
+ alucout_s<= '-'; -- Don't care!
+
+ when others => alureg_s(15 downto 0) <= bbus_s ;--alu_inbusb; -- ALU_PASSB
+ alucout_s<= CFLAG;
+ end case;
+ else
+ case aluopr is -- To aid resource sharing add MSB byte as above
+ when ALU_ROL | ALU_ROL1 => alureg_s(15 downto 0) <= alureg_s(14 downto 7) & (alureg_s(6 downto 0) & alureg_s(7));
+ alucout_s<= alureg_s(7);
+ when ALU_ROR | ALU_ROR1 => alureg_s(15 downto 0) <= alureg_s(0) & alureg_s(15 downto 9) & (alureg_s(0) & alureg_s(7 downto 1));
+ alucout_s<= alureg_s(0);
+ when ALU_RCL | ALU_RCL1 => alureg_s(15 downto 0) <= alureg_s(14 downto 7) & (alureg_s(6 downto 0) & alucout_s); -- shift carry in
+ alucout_s<= alureg_s(7);
+ -- when ALU_RCR | ALU_RCR1 => alureg_s(15 downto 0) <= alucout_s & alureg_s(15 downto 9) & (psrreg_s(0) & alureg_s(7 downto 1));
+ when ALU_RCR | ALU_RCR1 => alureg_s(15 downto 0) <= alucout_s & alureg_s(15 downto 9) & (alucout_s & alureg_s(7 downto 1)); -- Ver 0.82
+ alucout_s<= alureg_s(0);
+ when ALU_SHL | ALU_SHL1 => alureg_s(15 downto 0) <= alureg_s(14 downto 7) & (alureg_s(6 downto 0) & '0');
+ alucout_s<= alureg_s(7);
+ when ALU_SHR | ALU_SHR1 => alureg_s(15 downto 0) <= '0' & alureg_s(15 downto 9) & ('0' & alureg_s(7 downto 1));
+ alucout_s<= alureg_s(0);
+ when ALU_SAR | ALU_SAR1 => alureg_s(15 downto 0) <= alureg_s(15) & alureg_s(15 downto 9)& (alureg_s(7) & alureg_s(7 downto 1));
+ alucout_s<= alureg_s(0);
+ when ALU_TEMP => alureg_s(15 downto 0) <= bbus_s;
+ alucout_s<= '-'; -- Don't care!
+ when ALU_AAM => alureg_s(15 downto 0) <= X"000A";
+ alucout_s<= '-'; -- Don't care!
+ when others => alureg_s(15 downto 0) <= bbus_s ;--alu_inbusb -- ALU_PASSB
+ alucout_s<= CFLAG;
+ end case;
+ end if;
+ end if;
+ end if;
+end process;
+
+----------------------------------------------------------------------------
+-- AAS Instruction 3F
+----------------------------------------------------------------------------
+process (alu_inbusa,psrreg_s,aas1bus_s)
+ begin
+ aas1bus_s<=alu_inbusa-X"0106";
+ if ((alu_inbusa(3 downto 0) > "1001") or (psrreg_s(4)='1')) then
+ aasbus_s <= aas1bus_s(15 downto 8)&X"0"&aas1bus_s(3 downto 0);
+ setaas_s <= '1'; -- Set CF and AF flag
+ else
+ aasbus_s(7 downto 0) <= X"0"&(alu_inbusa(3 downto 0)); -- AL=AL&0Fh
+ aasbus_s(15 downto 8)<= alu_inbusa(15 downto 8); -- leave AH unchanged
+ setaas_s <= '0'; -- Clear CF and AF flag
+ end if;
+end process;
+
+----------------------------------------------------------------------------
+-- AAA Instruction 37
+----------------------------------------------------------------------------
+process (alu_inbusa,psrreg_s,aaa1bus_s)
+ begin
+ aaa1bus_s<=alu_inbusa+X"0106";
+ if ((alu_inbusa(3 downto 0) > "1001") or (psrreg_s(4)='1')) then
+ aaabus_s <= aaa1bus_s(15 downto 8)&X"0"&aaa1bus_s(3 downto 0);
+ setaaa_s <= '1'; -- Set CF and AF flag
+ else
+ aaabus_s(7 downto 0) <= X"0"&alu_inbusa(3 downto 0); -- AL=AL&0Fh
+ aaabus_s(15 downto 8)<= alu_inbusa(15 downto 8); -- AH Unchanged
+ setaaa_s <= '0'; -- Clear CF and AF flag
+ end if;
+end process;
+
+----------------------------------------------------------------------------
+-- DAA Instruction 27
+----------------------------------------------------------------------------
+process (alu_inbusa,psrreg_s,setdaa_s)
+ begin
+ if ((alu_inbusa(3 downto 0) > X"9") or (psrreg_s(4)='1')) then
+ setdaa_s(0) <= '1'; -- set AF
+ else
+ setdaa_s(0) <= '0'; -- clr AF
+ end if;
+ if ((alu_inbusa(7 downto 0) > X"9F") or (psrreg_s(0)='1') or (alu_inbusa(7 downto 0) > X"99")) then
+ setdaa_s(1) <= '1'; -- set CF
+ else
+ setdaa_s(1) <= '0'; -- clr CF
+ end if;
+ case setdaa_s is
+ when "00" => daabus_s <= alu_inbusa(7 downto 0);
+ when "01" => daabus_s <= alu_inbusa(7 downto 0) + X"06";
+ when "10" => daabus_s <= alu_inbusa(7 downto 0) + X"60";
+ when others => daabus_s <= alu_inbusa(7 downto 0) + X"66";
+ end case;
+end process;
+
+----------------------------------------------------------------------------
+-- DAS Instruction 2F
+----------------------------------------------------------------------------
+process (alu_inbusa,psrreg_s,setdas_s)
+ begin
+ if ((alu_inbusa(3 downto 0) > X"9") or (psrreg_s(4)='1')) then
+ setdas_s(0) <= '1'; -- set AF
+ else
+ setdas_s(0) <= '0'; -- clr AF
+ end if;
+ if ((alu_inbusa(7 downto 0) > X"9F") or (psrreg_s(0)='1') or (alu_inbusa(7 downto 0) > X"99")) then
+ setdas_s(1) <= '1'; -- set CF
+ else
+ setdas_s(1) <= '0'; -- clr CF
+ end if;
+ case setdas_s is
+ when "00" => dasbus_s <= alu_inbusa(7 downto 0);
+ when "01" => dasbus_s <= alu_inbusa(7 downto 0) - X"06";
+ when "10" => dasbus_s <= alu_inbusa(7 downto 0) - X"60";
+ when others => dasbus_s <= alu_inbusa(7 downto 0) - X"66";
+ end case;
+end process;
+
+----------------------------------------------------------------------------
+-- AAD Instruction 5D 0A
+----------------------------------------------------------------------------
+process (alu_inbusa,aad1bus_s,aad2bus_s)
+ begin
+ aad1bus_s <= ("00" & alu_inbusa(15 downto 8) & '0') + (alu_inbusa(15 downto 8) & "000"); -- AH*2 + AH*8
+ aad2bus_s <= aad1bus_s + ("000" & alu_inbusa(7 downto 0)); -- + AL
+ aadbus_s<= "00000000" & aad2bus_s(7 downto 0);
+end process;
+
+----------------------------------------------------------------------------
+-- ALU Operation
+----------------------------------------------------------------------------
+process (aluopr,abus_s,bbus_s,outbus_s,psrreg_s,alureg_s,aasbus_s,aaabus_s,daabus_s,sign16a_s,
+ sign16b_s,sign32a_s,dasbus_s,product_s,divresult_s,alu_temp_s,aadbus_s,quotient_s,remainder_s)
+ begin
+ case aluopr is
+
+ when ALU_ADD | ALU_ADD_SE | ALU_INC | ALU_POP | ALU_SUB | ALU_SUB_SE | ALU_DEC | ALU_PUSH | ALU_CMP | ALU_CMP_SE |
+ ALU_CMPS | ALU_ADC | ALU_ADC_SE | ALU_SBB | ALU_SBB_SE | ALU_SCAS | ALU_NEG | ALU_NOT
+ => alubus_s <= outbus_s;
+
+ when ALU_OR | ALU_OR_SE
+ => alubus_s <= abus_s OR bbus_s;
+ when ALU_AND | ALU_AND_SE | ALU_TEST0 | ALU_TEST1 | ALU_TEST2
+ => alubus_s <= abus_s AND bbus_s;
+ when ALU_XOR | ALU_XOR_SE
+ => alubus_s <= abus_s XOR bbus_s;
+
+ when ALU_LAHF => alubus_s <= psrreg_s(15 downto 2)&'1'&psrreg_s(0);-- flags onto ALUBUS, note reserved bit1=1
+
+ when ALU_MUL | ALU_IMUL
+ => alubus_s <= product_s(15 downto 0); -- AX of Multiplier
+ when ALU_MUL2| ALU_IMUL2
+ => alubus_s <= product_s(31 downto 16); -- DX of Multiplier
+
+ when ALU_DIV | ALU_IDIV
+ => alubus_s <= divresult_s(15 downto 0);-- AX of Divider (quotient)
+ when ALU_DIV2| ALU_IDIV2
+ => alubus_s <= divresult_s(31 downto 16);-- DX of Divider (remainder)
+
+ when ALU_SEXT => alubus_s <= sign16a_s; -- Used for CBW Instruction
+ when ALU_SEXTW => alubus_s <= sign32a_s; -- Used for CWD Instruction
+
+ when ALU_AAS => alubus_s <= aasbus_s; -- Used for AAS Instruction
+ when ALU_AAA => alubus_s <= aaabus_s; -- Used for AAA Instruction
+ when ALU_DAA => alubus_s <= abus_s(15 downto 8) & daabus_s;-- Used for DAA Instruction
+ when ALU_DAS => alubus_s <= abus_s(15 downto 8) & dasbus_s;-- Used for DAS Instruction
+ when ALU_AAD => alubus_s <= aadbus_s; -- Used for AAD Instruction
+ when ALU_AAM => alubus_s <= quotient_s(7 downto 0) & remainder_s(7 downto 0); -- Used for AAM Instruction
+
+ when ALU_ROL | ALU_ROL1 | ALU_ROR | ALU_ROR1 | ALU_RCL | ALU_RCL1 | ALU_RCR | ALU_RCR1 |
+ ALU_SHL | ALU_SHL1 | ALU_SHR | ALU_SHR1 | ALU_SAR | ALU_SAR1 | ALU_REGL
+ => alubus_s <= alureg_s(15 downto 0); -- alu_inbusb to output
+
+ when ALU_REGH => alubus_s <= alureg_s(31 downto 16); -- alu_inbusa to output
+
+ when ALU_PASSA => alubus_s <= abus_s;
+ --when ALU_PASSB => alubus_s <= bbus_s;
+
+ when ALU_TEMP => alubus_s <= alu_temp_s;
+
+ when others => alubus_s <= DONTCARE(15 downto 0);
+ end case;
+end process;
+alubus <= alubus_s; -- Connect to entity
+
+
+----------------------------------------------------------------------------
+-- Processor Status Register (Flags)
+-- bit Flag
+-- 15 Reserved
+-- 14 Reserved
+-- 13 Reserved Set to 1?
+-- 12 Reserved Set to 1?
+-- 11 Overflow Flag OF
+-- 10 Direction Flag DF
+-- 9 Interrupt Flag IF
+-- 8 Trace Flag TF
+-- 7 Sign Flag SF
+-- 6 Zero Flag ZF
+-- 5 Reserved
+-- 4 Auxiliary Carry AF
+-- 3 Reserved
+-- 2 Parity Flag PF
+-- 1 Reserved Set to 1 ????
+-- 0 Carry Flag
+----------------------------------------------------------------------------
+process (clk, reset)
+ begin
+ if reset='1' then
+ psrreg_s <= "1111000000000010";
+ elsif rising_edge(clk) then
+ if (wrcc='1') then
+ case aluopr is
+ when ALU_ADD | ALU_ADD_SE | ALU_ADC | ALU_ADC_SE | ALU_INC =>
+ OFLAG <= overflow_s;
+ SFLAG <= signflag_s;
+ ZFLAG <= zeroflag_s;
+ AFLAG <= bit4_s;
+ PFLAG <= parityflag_s;
+ CFLAG <= cout_s;
+ when ALU_DEC => -- Same as for ALU_SUB exclusing the CFLAG :-(
+ OFLAG <= overflow_s;
+ SFLAG <= signflag_s;
+ ZFLAG <= zeroflag_s;
+ AFLAG <= not bit4_s;
+ PFLAG <= parityflag_s;
+ when ALU_SUB | ALU_SUB_SE | ALU_SBB | ALU_SBB_SE | ALU_CMP |
+ ALU_CMP_SE | ALU_CMPS | ALU_SCAS | ALU_NEG =>
+ OFLAG <= overflow_s;
+ SFLAG <= signflag_s;
+ ZFLAG <= zeroflag_s;
+ AFLAG <= not bit4_s;
+ PFLAG <= parityflag_s;
+ CFLAG <= not cout_s;
+ when ALU_OR | ALU_OR_SE | ALU_AND | ALU_AND_SE | ALU_XOR | ALU_XOR_SE | ALU_TEST0 | ALU_TEST1 | ALU_TEST2 =>
+ OFLAG <= '0';
+ SFLAG <= signflag_s;
+ ZFLAG <= zeroflag_s;
+ AFLAG <= '0'; -- None defined, set to 0 to be compatible with debug
+ PFLAG <= parityflag_s;
+ CFLAG <= '0';
+ when ALU_SHL | ALU_SHR | ALU_SAR |
+ ALU_SHR1 | ALU_SAR1 | ALU_SHL1 =>
+ OFLAG <= overflow_s;
+ PFLAG <= parityflag_s;
+ SFLAG <= signflag_s;
+ ZFLAG <= zeroflag_s;
+ CFLAG <= alucout_s;
+
+ when ALU_CLC =>
+ CFLAG <= '0';
+ when ALU_CMC =>
+ CFLAG <= not CFLAG;
+ when ALU_STC =>
+ CFLAG <= '1';
+ when ALU_CLD =>
+ DFLAG <= '0';
+ when ALU_STD =>
+ DFLAG <= '1';
+ when ALU_CLI =>
+ IFLAG <= '0';
+ when ALU_STI =>
+ IFLAG <= '1';
+ when ALU_POP => -- Note only POPF executes a WRCC command, thus save for other pops
+ psrreg_s <= "1111" & alu_inbusa(11 downto 0);
+ when ALU_SAHF => -- Write all AH bits (not compatible!)
+ psrreg_s(7 downto 0) <= alu_inbusa(7 downto 6) & '0' & alu_inbusa(4) & '0' &
+ alu_inbusa(2) & '0' & alu_inbusa(0);-- SAHF only writes bits 7,6,4,2,0
+
+ when ALU_AAS =>
+ AFLAG <= setaas_s; -- set or clear CF/AF flag
+ CFLAG <= setaas_s;
+ SFLAG <= '0';
+ when ALU_AAA =>
+ AFLAG <= setaaa_s; -- set or clear CF/AF flag
+ CFLAG <= setaaa_s;
+ when ALU_DAA =>
+ AFLAG <= setdaa_s(0); -- set or clear CF/AF flag
+ CFLAG <= setdaa_s(1);
+ PFLAG <= parityflag_s;
+ SFLAG <= signflag_s;
+ ZFLAG <= zeroflag_s;
+
+ when ALU_AAD =>
+ SFLAG <= alubus_s(7); --signflag_s;
+ PFLAG <= parityflag_s;
+ ZFLAG <= zeroflag_s;
+
+ when ALU_AAM =>
+ SFLAG <= signflag_s;
+ PFLAG <= parityflag_s;
+ ZFLAG <= not(zflaglow_s); -- signflag on AL only
+
+ when ALU_DAS =>
+ AFLAG <= setdas_s(0); -- set or clear CF/AF flag
+ CFLAG <= setdas_s(1);
+ PFLAG <= parityflag_s;
+ SFLAG <= signflag_s;
+ ZFLAG <= zeroflag_s;
+ -- Shift Rotate Instructions
+ when ALU_ROL | ALU_ROR | ALU_RCL | ALU_RCR |
+ ALU_ROL1 | ALU_RCL1 | ALU_ROR1 | ALU_RCR1 =>
+ CFLAG <= alucout_s;
+ OFLAG <= overflow_s;
+
+ when ALU_MUL | ALU_MUL2 | ALU_IMUL | ALU_IMUL2 => -- Multiply affects CF&OF only
+ CFLAG <= overflow_s;
+ OFLAG <= overflow_s;
+
+ when ALU_CLRTIF => -- Clear TF and IF flag
+ IFLAG <= '0';
+ TFLAG <= '0';
+
+ when others =>
+ psrreg_s <= psrreg_s;
+ end case;
+ end if;
+ end if;
+end process;
+
+ccbus <= psrreg_s; -- Connect to entity
+
+-- Latch Divide by 0 error flag & latched divresult.
+-- Requires a MCP from all registers to these endpoint registers!
+process (clk, reset)
+ begin
+ if reset='1' then
+ div_err <= '0';
+ divresult_s <= (others => '0');
+ elsif rising_edge(clk) then
+ if done_s='1' then -- Latched pulse generated by serial divider
+ div_err <= div_err_s; -- Divide Overflow
+ -- pragma synthesis_off
+ assert div_err_s='0' report "**** Divide Overflow ***" severity note;
+ -- pragma synthesis_on
+
+ if wl_s='1' then -- Latched version required?
+ divresult_s <= remainder_s & quotient_s;
+ else
+ divresult_s <= remainder_s & remainder_s(7 downto 0) & quotient_s(7 downto 0);
+ end if;
+ else
+ div_err <= '0';
+ end if;
+ end if;
+end process;
+
+end rtl;
diff --git a/common/CPU/cpu86/biu_struct.vhd b/common/CPU/cpu86/biu_struct.vhd
new file mode 100644
index 00000000..7123fdcd
--- /dev/null
+++ b/common/CPU/cpu86/biu_struct.vhd
@@ -0,0 +1,598 @@
+-------------------------------------------------------------------------------
+-- CPU86 - VHDL CPU8088 IP core --
+-- Copyright (C) 2002-2008 HT-LAB --
+-- --
+-- Contact/bugs : http://www.ht-lab.com/misc/feedback.html --
+-- Web : http://www.ht-lab.com --
+-- --
+-- CPU86 is released as open-source under the GNU GPL license. This means --
+-- that designs based on CPU86 must be distributed in full source code --
+-- under the same license. Contact HT-Lab for commercial applications where --
+-- source-code distribution is not desirable. --
+-- --
+-------------------------------------------------------------------------------
+-- --
+-- This library is free software; you can redistribute it and/or --
+-- modify it under the terms of the GNU Lesser General Public --
+-- License as published by the Free Software Foundation; either --
+-- version 2.1 of the License, or (at your option) any later version. --
+-- --
+-- This library 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 --
+-- Lesser General Public License for more details. --
+-- --
+-- Full details of the license can be found in the file "copying.txt". --
+-- --
+-- You should have received a copy of the GNU Lesser General Public --
+-- License along with this library; if not, write to the Free Software --
+-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --
+-- --
+-------------------------------------------------------------------------------
+LIBRARY ieee;
+USE ieee.std_logic_1164.ALL;
+USE ieee.std_logic_arith.ALL;
+USE ieee.std_logic_unsigned.ALL;
+
+USE work.cpu86pack.ALL;
+
+ENTITY biu IS
+ PORT(
+ clk : IN std_logic;
+ csbus : IN std_logic_vector (15 DOWNTO 0);
+ dbus_in : IN std_logic_vector (7 DOWNTO 0);
+ dbusdp_in : IN std_logic_vector (15 DOWNTO 0);
+ decode_state : IN std_logic;
+ flush_coming : IN std_logic;
+ flush_req : IN std_logic;
+ intack : IN std_logic;
+ intr : IN std_logic;
+ iomem : IN std_logic;
+ ipbus : IN std_logic_vector (15 DOWNTO 0);
+ irq_block : IN std_logic;
+ nmi : IN std_logic;
+ opc_req : IN std_logic;
+ read_req : IN std_logic;
+ reset : IN std_logic;
+ status : IN status_out_type;
+ word : IN std_logic;
+ write_req : IN std_logic;
+ abus : OUT std_logic_vector (19 DOWNTO 0);
+ biu_error : OUT std_logic;
+ dbus_out : OUT std_logic_vector (7 DOWNTO 0);
+ flush_ack : OUT std_logic;
+ instr : OUT instruction_type;
+ inta : OUT std_logic;
+ inta1 : OUT std_logic;
+ iom : OUT std_logic;
+ irq_req : OUT std_logic;
+ latcho : OUT std_logic;
+ mdbus_out : OUT std_logic_vector (15 DOWNTO 0);
+ rdn : OUT std_logic;
+ rw_ack : OUT std_logic;
+ wran : OUT std_logic;
+ wrn : OUT std_logic
+ );
+END biu ;
+
+
+ARCHITECTURE struct OF biu IS
+
+ SIGNAL abus_s : std_logic_vector(19 DOWNTO 0);
+ SIGNAL abusdp_in : std_logic_vector(19 DOWNTO 0);
+ SIGNAL addrplus4 : std_logic;
+ SIGNAL biu_status : std_logic_vector(2 DOWNTO 0);
+ SIGNAL csbusbiu_s : std_logic_vector(15 DOWNTO 0);
+ SIGNAL halt_instr : std_logic;
+ SIGNAL inta2_s : std_logic; -- Second INTA pulse, used to latch 8 bist vector
+ SIGNAL ipbusbiu_s : std_logic_vector(15 DOWNTO 0);
+ SIGNAL ipbusp1_s : std_logic_vector(15 DOWNTO 0);
+ SIGNAL irq_ack : std_logic;
+ SIGNAL irq_clr : std_logic;
+ SIGNAL irq_type : std_logic_vector(1 DOWNTO 0);
+ SIGNAL latchabus : std_logic;
+ SIGNAL latchclr : std_logic;
+ SIGNAL latchm : std_logic;
+ SIGNAL latchrw : std_logic;
+ SIGNAL ldposplus1 : std_logic;
+ SIGNAL lutbus : std_logic_vector(15 DOWNTO 0);
+ SIGNAL mux_addr : std_logic_vector(2 DOWNTO 0);
+ SIGNAL mux_data : std_logic_vector(3 DOWNTO 0);
+ SIGNAL mux_reg : std_logic_vector(2 DOWNTO 0);
+ SIGNAL muxabus : std_logic_vector(1 DOWNTO 0);
+ SIGNAL nbreq : std_logic_vector(2 DOWNTO 0);
+ SIGNAL rdcode_s : std_logic;
+ SIGNAL rddata_s : std_logic;
+ SIGNAL reg1freed : std_logic; -- Delayed version (1 clk) of reg1free
+ SIGNAL reg4free : std_logic;
+ SIGNAL regnbok : std_logic;
+ SIGNAL regplus1 : std_logic;
+ SIGNAL w_biufsm_s : std_logic;
+ SIGNAL wr_s : std_logic;
+
+ SIGNAL flush_ack_internal : std_logic;
+ SIGNAL inta1_internal : std_logic;
+ SIGNAL irq_req_internal : std_logic;
+ SIGNAL latcho_internal : std_logic;
+
+
+ signal nmi_s : std_logic;
+ signal nmipre_s : std_logic_vector(1 downto 0); -- metastability first FF for nmi
+ signal outbus_s : std_logic_vector(7 downto 0); -- used in out instr. bus streering
+ signal latchmd_s : std_logic; -- internal rdl_s signal
+ signal abusdp_inp1l_s: std_logic_vector(15 downto 0);
+ signal latchrw_d_s: std_logic; -- latchrw delayed 1 clk cycle
+ signal latchclr_d_s: std_logic; -- latchclr delayed 1 clk cycle
+ signal iom_s : std_logic;
+ signal instr_trace_s : std_logic; -- TF latched by exec_state pulse
+ signal irq_req_s : std_logic;
+
+ -- Component Declarations
+ COMPONENT biufsm
+ PORT (
+ clk : IN std_logic ;
+ flush_coming : IN std_logic ;
+ flush_req : IN std_logic ;
+ irq_req : IN std_logic ;
+ irq_type : IN std_logic_vector (1 DOWNTO 0);
+ opc_req : IN std_logic ;
+ read_req : IN std_logic ;
+ reg1freed : IN std_logic ;
+ reg4free : IN std_logic ;
+ regnbok : IN std_logic ;
+ reset : IN std_logic ;
+ w_biufsm_s : IN std_logic ;
+ write_req : IN std_logic ;
+ addrplus4 : OUT std_logic ;
+ biu_error : OUT std_logic ;
+ biu_status : OUT std_logic_vector (2 DOWNTO 0);
+ irq_ack : OUT std_logic ;
+ irq_clr : OUT std_logic ;
+ latchabus : OUT std_logic ;
+ latchclr : OUT std_logic ;
+ latchm : OUT std_logic ;
+ latcho : OUT std_logic ;
+ latchrw : OUT std_logic ;
+ ldposplus1 : OUT std_logic ;
+ muxabus : OUT std_logic_vector (1 DOWNTO 0);
+ rdcode_s : OUT std_logic ;
+ rddata_s : OUT std_logic ;
+ regplus1 : OUT std_logic ;
+ rw_ack : OUT std_logic ;
+ wr_s : OUT std_logic ;
+ flush_ack : BUFFER std_logic ;
+ inta1 : BUFFER std_logic
+ );
+ END COMPONENT;
+ COMPONENT formatter
+ PORT (
+ lutbus : IN std_logic_vector (15 DOWNTO 0);
+ mux_addr : OUT std_logic_vector (2 DOWNTO 0);
+ mux_data : OUT std_logic_vector (3 DOWNTO 0);
+ mux_reg : OUT std_logic_vector (2 DOWNTO 0);
+ nbreq : OUT std_logic_vector (2 DOWNTO 0)
+ );
+ END COMPONENT;
+ COMPONENT regshiftmux
+ PORT (
+ clk : IN std_logic ;
+ dbus_in : IN std_logic_vector (7 DOWNTO 0);
+ flush_req : IN std_logic ;
+ latchm : IN std_logic ;
+ latcho : IN std_logic ;
+ mux_addr : IN std_logic_vector (2 DOWNTO 0);
+ mux_data : IN std_logic_vector (3 DOWNTO 0);
+ mux_reg : IN std_logic_vector (2 DOWNTO 0);
+ nbreq : IN std_logic_vector (2 DOWNTO 0);
+ regplus1 : IN std_logic ;
+ ldposplus1 : IN std_logic ;
+ reset : IN std_logic ;
+ irq : IN std_logic ;
+ inta1 : IN std_logic ; -- Added for ver 0.71
+ inta2_s : IN std_logic ;
+ irq_type : IN std_logic_vector (1 DOWNTO 0);
+ instr : OUT instruction_type ;
+ halt_instr : OUT std_logic ;
+ lutbus : OUT std_logic_vector (15 DOWNTO 0);
+ reg1free : BUFFER std_logic ;
+ reg1freed : BUFFER std_logic ; -- Delayed version (1 clk) of reg1free
+ regnbok : OUT std_logic
+ );
+ END COMPONENT;
+
+
+BEGIN
+
+ -------------------------------------------------------------------------
+ -- Databus Latch
+ -------------------------------------------------------------------------
+ process(reset,clk)
+ begin
+ if reset='1' then
+ dbus_out <= DONTCARE(7 downto 0);
+ elsif rising_edge(clk) then
+ if latchrw='1' then -- Latch Data from DataPath
+ dbus_out <= outbus_s;
+ end if;
+ end if;
+ end process;
+
+ ---------------------------------------------------------------------------
+ -- OUT instruction bus steering
+ -- IO/~M & A[1:0]
+ ---------------------------------------------------------------------------
+ process(dbusdp_in,abus_s)
+ begin
+ if abus_s(0)='0' then
+ outbus_s <= dbusdp_in(7 downto 0); -- D0
+ else
+ outbus_s <= dbusdp_in(15 downto 8); -- D1
+ end if;
+ end process;
+
+ ---------------------------------------------------------------------------
+ -- Latch word for BIU FSM
+ ---------------------------------------------------------------------------
+ process(clk,reset)
+ begin
+ if reset='1' then
+ w_biufsm_s<='0';
+ elsif rising_edge(clk) then
+ if latchrw='1' then
+ w_biufsm_s<=word;
+ end if;
+ end if;
+ end process;
+
+ -- metastability sync
+ process(reset,clk) -- ireg
+ begin
+ if reset='1' then
+ nmipre_s <= "00";
+ elsif rising_edge(clk) then
+ nmipre_s <= nmipre_s(0) & nmi;
+ end if;
+ end process;
+
+ -- set/reset FF
+ process(reset, clk) -- ireg
+ begin
+ if (reset='1') then
+ nmi_s <= '0';
+ elsif rising_edge(clk) then
+ if (irq_clr='1') then
+ nmi_s <= '0';
+ else
+ nmi_s <= nmi_s or ((not nmipre_s(1)) and nmipre_s(0));
+ end if;
+ end if;
+ end process;
+
+ -- Instruction trace flag, the trace flag is latched by the decode_state signal. This will
+ -- result in the instruction after setting the trace flag not being traced (required).
+ -- The instr_trace_s flag is not set if the current instruction is a HLT
+ process(reset, clk)
+ begin
+ if (reset='1') then
+ instr_trace_s <= '0';
+ elsif rising_edge(clk) then
+ if (decode_state='1' and halt_instr='0') then
+ instr_trace_s <= status.flag(8);
+ end if;
+ end if;
+ end process;
+
+ -- int0_req=Divider/0 error
+ -- status(8)=TF
+ -- status(9)=IF
+ irq_req_s <= '1' when ((status.div_err='1' or instr_trace_s='1' or nmi_s='1' or (status.flag(9)='1' and intr='1')) and irq_block='0') else '0';
+
+ -- set/reset FF
+ process(reset, clk) -- ireg
+ begin
+ if (reset='1') then
+ irq_req_internal <= '0';
+ elsif rising_edge(clk) then
+ if (irq_clr='1') then
+ irq_req_internal <= '0';
+ elsif irq_req_s='1' then
+ irq_req_internal <= '1';
+ end if;
+ end if;
+ end process;
+
+ --process (nmi_s,status,intr)
+ process (reset,clk)
+ begin
+ if reset='1' then
+ irq_type <= (others => '0'); -- Don't care value
+ elsif rising_edge(clk) then
+ if irq_req_internal='1' then
+ if nmi_s='1' then
+ irq_type <= "10"; -- NMI result in INT2
+ elsif status.flag(8)='1' then
+ irq_type <= "01"; -- TF result in INT1
+ else
+ irq_type <= "00"; -- INTR result in INT
+ end if;
+ end if;
+ end if;
+ end process;
+
+ ---------------------------------------------------------------------------
+ -- Delayed signals
+ ---------------------------------------------------------------------------
+ process(clk,reset)
+ begin
+ if reset='1' then
+ latchrw_d_s <= '0';
+ latchclr_d_s <= '0';
+ elsif rising_edge(clk) then
+ latchrw_d_s <= latchrw;
+ latchclr_d_s <= latchclr;
+ end if;
+ end process;
+
+ ---------------------------------------------------------------------------
+ -- IO/~M strobe latch
+ ---------------------------------------------------------------------------
+ process(clk,reset)
+ begin
+ if reset='1' then
+ iom_s <= '0';
+ elsif rising_edge(clk) then
+ if latchrw='1' and muxabus/="00" then
+ iom_s <= iomem;
+ elsif latchrw='1' then
+ iom_s <= '0';
+ end if;
+ end if;
+ end process;
+ iom <= iom_s;
+
+ ---------------------------------------------------------------------------
+ -- Shifted WR strobe latch, to add some address and data hold time the WR
+ -- strobe is negated .5 clock cycles before address and data changes. This
+ -- is implemented using the falling edge of the clock. Generally using
+ -- both edges of a clock is not recommended. If this is not desirable
+ -- use the latchclr signal with the rising edge of clk. This will result
+ -- in a full clk cycle for the data hold.
+ ---------------------------------------------------------------------------
+ process(clk,reset) -- note wr should be 1 clk cycle after latchrw
+ begin
+ if reset='1' then
+ wran <= '1';
+
+ elsif falling_edge(clk) then -- wran is negated 0.5 cycle before data&address changes
+ if latchclr_d_s='1' then
+ wran <= '1';
+ elsif wr_s='1' then
+ wran<='0';
+ end if;
+
+ -- elsif rising_edge(clk) then -- wran negated 1 clk cycle before data&address changes
+ -- if latchclr='1' then
+ -- wran <= '1';
+ -- elsif wr_s='1' then
+ -- wran<='0';
+ -- end if;
+
+ end if;
+ end process;
+
+ ---------------------------------------------------------------------------
+ -- WR strobe latch. This signal can be use to drive the tri-state drivers
+ -- and will result in a data hold time until the end of the write cycle.
+ ---------------------------------------------------------------------------
+ process(clk,reset)
+ begin
+ if reset='1' then
+ wrn <= '1';
+ elsif rising_edge(clk) then
+ if latchclr_d_s='1' then -- Change wrn at the same time as addr changes
+ wrn <= '1';
+ elsif wr_s='1' then
+ wrn<='0';
+ end if;
+ end if;
+ end process;
+
+
+ ---------------------------------------------------------------------------
+ -- RD strobe latch
+ -- rd is active low and connected to top entity
+ -- Use 1 clk delayed latchrw_d_s signal
+ -- Original signals were rd_data_s and rd_code_s, new signals rddata_s and
+ -- rdcode_s.
+ -- Add flushreq_s, prevend rd signal from starting
+ ---------------------------------------------------------------------------
+ process(reset,clk)
+ begin
+ if reset='1' then
+ rdn <= '1';
+ latchmd_s <= '0';
+ elsif rising_edge(clk) then
+ if latchclr_d_s='1' then
+ rdn <= '1';
+ latchmd_s <= '0';
+ elsif latchrw_d_s='1' then
+ latchmd_s <= rddata_s;
+ -- Bug reported by Rick Kilgore
+ -- ver 0.69, stops RD from being asserted during second inta
+ rdn <= not((rdcode_s or rddata_s) AND NOT intack);
+
+ -- The next second was added to create a updown pulse on the rd strobe
+ -- during a flush action. This will result in a dummy read cycle (unavoidable?)
+ elsif latchrw='1' then
+ latchmd_s <= rddata_s;
+ rdn <= not(rdcode_s or rddata_s);
+ end if;
+ end if;
+ end process;
+
+ ---------------------------------------------------------------------------
+ -- Second INTA strobe latch
+ ---------------------------------------------------------------------------
+ process(reset,clk)
+ begin
+ if reset='1' then
+ inta2_s<= '0';
+ elsif rising_edge(clk) then
+ if latchclr_d_s='1' then
+ inta2_s <= '0';
+ elsif latchrw_d_s='1' then
+ inta2_s <= intack;
+ end if;
+ end if;
+ end process;
+
+ inta <= not (inta2_s OR inta1_internal);
+
+ ---------------------------------------------------------------------------
+ -- Databus stearing for the datapath input
+ -- mdbus_out(31..16) is only used for "int x", the value si used to load
+ -- ipreg at the same time as loading cs.
+ -- Note mdbus must be valid (i.e. contain dbus value) before rising edge
+ -- of wrn/rdn
+ ---------------------------------------------------------------------------
+ process(clk,reset)
+ begin
+ if reset='1' then
+ mdbus_out <= (others => '0');
+ elsif rising_edge(clk) then
+ if latchmd_s='1' then
+ if word='0' then -- byte read
+ mdbus_out <= X"00" & dbus_in;
+ else
+ if muxabus="00" then -- first cycle of word read
+ mdbus_out(15 downto 8) <= dbus_in;
+ else -- Second cycle
+ mdbus_out(7 downto 0) <= dbus_in;
+ end if;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ process(reset,clk)
+ begin
+ if reset='1' then
+ ipbusbiu_s <= RESET_IP_C; -- start 0x0000, CS=FFFF
+ csbusbiu_s <= RESET_CS_C;
+ elsif rising_edge(clk) then
+ if latchabus='1' then
+ if (addrplus4='1') then
+ ipbusbiu_s <= ipbusbiu_s+'1';
+ else
+ ipbusbiu_s <= ipbus; -- get new address after flush
+ csbusbiu_s <= csbus;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ -------------------------------------------------------------------------
+ -- Latch datapath address+4 for mis-aligned R/W
+ -------------------------------------------------------------------------
+ ipbusp1_s <= ipbus+'1';
+ abusdp_inp1l_s <= ipbus when latchrw='0' else ipbusp1_s;
+
+ process(abusdp_inp1l_s,muxabus,csbusbiu_s,ipbusbiu_s,csbus,ipbus)
+ begin
+ case muxabus is
+ when "01" => abus_s <= (csbus&"0000") + ("0000"&ipbus); --abusdp_in;
+ when "10" => abus_s <= (csbus&"0000") + ("0000"&abusdp_inp1l_s); -- Add 1 if odd address and write word
+ when others => abus_s <= (csbusbiu_s&"0000") + ("0000"&ipbusbiu_s); -- default to BIU word address
+ end case;
+ end process;
+
+ -------------------------------------------------------------------------
+ -- Address/Databus Latch
+ -------------------------------------------------------------------------
+ process(reset,clk)
+ begin
+ if reset='1' then
+ abus <= RESET_VECTOR_C;
+ elsif rising_edge(clk) then
+ if latchrw='1' then -- Latch Address
+ abus <= abus_s;
+ end if;
+ end if;
+ end process;
+
+ -- Instance port mappings.
+ fsm : biufsm
+ PORT MAP (
+ clk => clk,
+ flush_coming => flush_coming,
+ flush_req => flush_req,
+ irq_req => irq_req_internal,
+ irq_type => irq_type,
+ opc_req => opc_req,
+ read_req => read_req,
+ reg1freed => reg1freed,
+ reg4free => reg4free,
+ regnbok => regnbok,
+ reset => reset,
+ w_biufsm_s => w_biufsm_s,
+ write_req => write_req,
+ addrplus4 => addrplus4,
+ biu_error => biu_error,
+ biu_status => biu_status,
+ irq_ack => irq_ack,
+ irq_clr => irq_clr,
+ latchabus => latchabus,
+ latchclr => latchclr,
+ latchm => latchm,
+ latcho => latcho_internal,
+ latchrw => latchrw,
+ ldposplus1 => ldposplus1,
+ muxabus => muxabus,
+ rdcode_s => rdcode_s,
+ rddata_s => rddata_s,
+ regplus1 => regplus1,
+ rw_ack => rw_ack,
+ wr_s => wr_s,
+ flush_ack => flush_ack_internal,
+ inta1 => inta1_internal
+ );
+ I4 : formatter
+ PORT MAP (
+ lutbus => lutbus,
+ mux_addr => mux_addr,
+ mux_data => mux_data,
+ mux_reg => mux_reg,
+ nbreq => nbreq
+ );
+ shift : regshiftmux
+ PORT MAP (
+ clk => clk,
+ dbus_in => dbus_in,
+ flush_req => flush_req,
+ latchm => latchm,
+ latcho => latcho_internal,
+ mux_addr => mux_addr,
+ mux_data => mux_data,
+ mux_reg => mux_reg,
+ nbreq => nbreq,
+ regplus1 => regplus1,
+ ldposplus1 => ldposplus1,
+ reset => reset,
+ irq => irq_ack,
+ inta1 => inta1_internal,
+ inta2_s => inta2_s,
+ irq_type => irq_type,
+ instr => instr,
+ halt_instr => halt_instr,
+ lutbus => lutbus,
+ reg1free => reg4free,
+ reg1freed => reg1freed,
+ regnbok => regnbok
+ );
+
+ flush_ack <= flush_ack_internal;
+ inta1 <= inta1_internal;
+ irq_req <= irq_req_internal;
+ latcho <= latcho_internal;
+
+END struct;
diff --git a/common/CPU/cpu86/biufsm_fsm.vhd b/common/CPU/cpu86/biufsm_fsm.vhd
new file mode 100644
index 00000000..b3137cf8
--- /dev/null
+++ b/common/CPU/cpu86/biufsm_fsm.vhd
@@ -0,0 +1,494 @@
+-------------------------------------------------------------------------------
+-- CPU86 - VHDL CPU8088 IP core --
+-- Copyright (C) 2002-2008 HT-LAB --
+-- --
+-- Contact/bugs : http://www.ht-lab.com/misc/feedback.html --
+-- Web : http://www.ht-lab.com --
+-- --
+-- CPU86 is released as open-source under the GNU GPL license. This means --
+-- that designs based on CPU86 must be distributed in full source code --
+-- under the same license. Contact HT-Lab for commercial applications where --
+-- source-code distribution is not desirable. --
+-- --
+-------------------------------------------------------------------------------
+-- --
+-- This library is free software; you can redistribute it and/or --
+-- modify it under the terms of the GNU Lesser General Public --
+-- License as published by the Free Software Foundation; either --
+-- version 2.1 of the License, or (at your option) any later version. --
+-- --
+-- This library 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 --
+-- Lesser General Public License for more details. --
+-- --
+-- Full details of the license can be found in the file "copying.txt". --
+-- --
+-- You should have received a copy of the GNU Lesser General Public --
+-- License along with this library; if not, write to the Free Software --
+-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --
+-- --
+-------------------------------------------------------------------------------
+LIBRARY ieee;
+USE ieee.std_logic_1164.ALL;
+USE ieee.std_logic_unsigned.ALL;
+
+USE work.cpu86pack.ALL;
+USE work.cpu86instr.ALL;
+
+ENTITY biufsm IS
+ PORT(
+ clk : IN std_logic;
+ flush_coming : IN std_logic;
+ flush_req : IN std_logic;
+ irq_req : IN std_logic;
+ irq_type : IN std_logic_vector (1 DOWNTO 0);
+ opc_req : IN std_logic;
+ read_req : IN std_logic;
+ reg1freed : IN std_logic; -- Delayed version (1 clk) of reg1free
+ reg4free : IN std_logic;
+ regnbok : IN std_logic;
+ reset : IN std_logic;
+ w_biufsm_s : IN std_logic;
+ write_req : IN std_logic;
+ addrplus4 : OUT std_logic;
+ biu_error : OUT std_logic;
+ biu_status : OUT std_logic_vector (2 DOWNTO 0);
+ irq_ack : OUT std_logic;
+ irq_clr : OUT std_logic;
+ latchabus : OUT std_logic;
+ latchclr : OUT std_logic;
+ latchm : OUT std_logic;
+ latcho : OUT std_logic;
+ latchrw : OUT std_logic;
+ ldposplus1 : OUT std_logic;
+ muxabus : OUT std_logic_vector (1 DOWNTO 0);
+ rdcode_s : OUT std_logic;
+ rddata_s : OUT std_logic;
+ regplus1 : OUT std_logic;
+ rw_ack : OUT std_logic;
+ wr_s : OUT std_logic;
+ flush_ack : BUFFER std_logic;
+ inta1 : BUFFER std_logic
+ );
+END biufsm ;
+
+
+ARCHITECTURE fsm OF biufsm IS
+
+ signal ws_s : std_logic_vector(WS_WIDTH-1 downto 0);
+ signal oddflag_s : std_logic;
+ signal rwmem3_s : std_logic; -- Misaligned Read/Write cycle
+
+ TYPE STATE_TYPE IS (
+ Sreset,
+ Sws,
+ Smaxws,
+ Sack,
+ Srdopc,
+ Serror,
+ Swrite,
+ Swsw,
+ Smaxwsw,
+ Sackw,
+ Swrodd,
+ Sread,
+ Srdodd,
+ Swsr,
+ Smaxwsr,
+ Sackr,
+ Sflush1,
+ Sfull,
+ Sint,
+ Sintws2,
+ Sflush2,
+ Sintws1
+ );
+
+ SIGNAL current_state : STATE_TYPE;
+ SIGNAL next_state : STATE_TYPE;
+
+ SIGNAL biu_error_int : std_logic ;
+ SIGNAL biu_status_cld : std_logic_vector (2 DOWNTO 0);
+
+BEGIN
+
+ clocked_proc : PROCESS (clk,reset)
+ BEGIN
+ IF (reset = '1') THEN
+ current_state <= Sreset;
+ biu_error <= '0';
+ biu_status_cld <= "011";
+ oddflag_s <= '0';
+ ws_s <= (others=>'0');
+ ELSIF (clk'EVENT AND clk = '1') THEN
+ current_state <= next_state;
+ biu_error <= biu_error_int;
+ ws_s <= (others=>'0');
+
+ CASE current_state IS
+ WHEN Sreset =>
+ biu_status_cld<="000";
+ WHEN Sws =>
+ ws_s <= ws_s + '1';
+ IF (flush_req = '1') THEN
+ biu_status_cld<="011";
+ END IF;
+ WHEN Smaxws =>
+ IF (flush_req = '1') THEN
+ biu_status_cld<="011";
+ END IF;
+ WHEN Sack =>
+ oddflag_s<='0';
+ IF (write_req = '1') THEN
+ biu_status_cld<="010";
+ ELSIF (read_req = '1') THEN
+ biu_status_cld<="001";
+ ELSIF (flush_req = '1') THEN
+ biu_status_cld<="011";
+ ELSIF (irq_req='1' AND opc_req='1') THEN
+ biu_status_cld<="100";
+ ELSIF (reg4free = '1' AND
+ flush_coming='0' AND
+ irq_req='0') THEN
+ biu_status_cld<="000";
+ ELSIF (regnbok = '0' and
+ reg4free = '0') THEN
+ ELSE
+ biu_status_cld<="011";
+ END IF;
+ WHEN Srdopc =>
+ ws_s <= (others=>'0');
+ IF (flush_req = '1') THEN
+ biu_status_cld<="011";
+ END IF;
+ WHEN Swrite =>
+ ws_s <= (others=>'0');
+ oddflag_s<='0';
+ WHEN Swsw =>
+ ws_s <= ws_s + '1';
+ WHEN Sackw =>
+ IF (rwmem3_s = '1') THEN
+ ELSIF (flush_req = '1') THEN
+ biu_status_cld<="011";
+ ELSIF (irq_req='1' AND opc_req='1') THEN
+ biu_status_cld<="100";
+ ELSIF (reg4free = '1' ) THEN
+ biu_status_cld<="000";
+ ELSIF (flush_coming='1' OR
+ (irq_req='1' AND opc_req='0')) THEN
+ biu_status_cld<="011";
+ END IF;
+ WHEN Swrodd =>
+ ws_s <= (others=>'0');
+ oddflag_s<='1';
+ WHEN Sread =>
+ ws_s <= (others=>'0');
+ oddflag_s<='0';
+ WHEN Srdodd =>
+ ws_s <= (others=>'0');
+ oddflag_s<='1';
+ WHEN Swsr =>
+ ws_s <= ws_s + '1';
+ WHEN Sackr =>
+ IF (rwmem3_s = '1') THEN
+ ELSIF (flush_req='1') THEN
+ biu_status_cld<="011";
+ ELSIF (irq_req='1' AND opc_req='1') THEN
+ biu_status_cld<="100";
+ ELSIF (reg4free = '1' ) THEN
+ biu_status_cld<="000";
+ ELSIF (flush_coming='1' OR
+ (irq_req='1' AND opc_req='0')) THEN
+ biu_status_cld<="011";
+ END IF;
+ WHEN Sfull =>
+ IF (write_req='1') THEN
+ biu_status_cld<="010";
+ ELSIF (read_req='1') THEN
+ biu_status_cld<="001";
+ ELSIF (flush_req = '1') THEN
+ biu_status_cld<="011";
+ ELSIF (irq_req='1' AND opc_req='1') THEN
+ biu_status_cld<="100";
+ ELSIF (reg4free = '1' AND
+ flush_coming='0' AND
+ irq_req='0') THEN
+ biu_status_cld<="000";
+ END IF;
+ WHEN Sintws2 =>
+ biu_status_cld<="011";
+ WHEN Sflush2 =>
+ biu_status_cld<="000";
+ WHEN OTHERS =>
+ NULL;
+ END CASE;
+ END IF;
+ END PROCESS clocked_proc;
+
+ -----------------------------------------------------------------
+ nextstate_proc : PROCESS (
+ current_state,
+ flush_coming,
+ flush_req,
+ irq_req,
+ irq_type,
+ opc_req,
+ read_req,
+ reg1freed,
+ reg4free,
+ regnbok,
+ rwmem3_s,
+ write_req,
+ ws_s
+ )
+ -----------------------------------------------------------------
+ BEGIN
+ -- Default Assignment
+ addrplus4 <= '0';
+ biu_error_int <= '0';
+ irq_ack <= '0';
+ irq_clr <= '0';
+ latchabus <= '0';
+ latchclr <= '0';
+ latchm <= '0';
+ latcho <= '0';
+ latchrw <= '0';
+ ldposplus1 <= '0';
+ muxabus <= "00";
+ rdcode_s <= '0';
+ rddata_s <= '0';
+ regplus1 <= '0';
+ rw_ack <= '0';
+ wr_s <= '0';
+ flush_ack <= '0';
+ inta1 <= '0';
+
+ -- Combined Actions
+ CASE current_state IS
+ WHEN Sreset =>
+ latchrw <= '1' ;
+ next_state <= Srdopc;
+ WHEN Sws =>
+ IF (flush_req = '1') THEN
+ next_state <= Sflush1;
+ ELSIF (ws_s=MAX_WS-1) THEN
+ next_state <= Smaxws;
+ ELSE
+ next_state <= Sws;
+ END IF;
+ WHEN Smaxws =>
+ latchabus<='1';
+ addrplus4<='1';
+ latchclr <= '1' ;
+ ldposplus1<='1';
+ IF (flush_req = '1') THEN
+ next_state <= Sflush1;
+ ELSE
+ next_state <= Sack;
+ END IF;
+ WHEN Sack =>
+ latchm<=reg1freed;
+ regplus1<='1';
+ IF (write_req = '1') THEN
+ muxabus <="01";
+ latchrw <= '1' ;
+ next_state <= Swrite;
+ ELSIF (read_req = '1') THEN
+ muxabus <="01";
+ latchrw <= '1' ;
+ next_state <= Sread;
+ ELSIF (flush_req = '1') THEN
+ next_state <= Sflush1;
+ ELSIF (irq_req='1' AND opc_req='1') THEN
+ irq_ack<='1';
+ next_state <= Sint;
+ ELSIF (reg4free = '1' AND
+ flush_coming='0' AND
+ irq_req='0') THEN
+ latchrw <= '1' ;
+ next_state <= Srdopc;
+ ELSIF (regnbok = '0' and
+ reg4free = '0') THEN
+ next_state <= Serror;
+ ELSE
+ next_state <= Sfull;
+ END IF;
+ WHEN Srdopc =>
+ rdcode_s <= '1';
+ latcho <= regnbok and opc_req;
+ IF (flush_req = '1') THEN
+ next_state <= Sflush1;
+ ELSIF (ws_s/=MAX_WS) THEN
+ next_state <= Sws;
+ ELSE
+ next_state <= Smaxws;
+ END IF;
+ WHEN Serror =>
+ biu_error_int <= '1';
+ next_state <= Serror;
+ WHEN Swrite =>
+ wr_s <= '1';
+ IF (ws_s/=MAX_WS) THEN
+ next_state <= Swsw;
+ ELSE
+ next_state <= Smaxwsw;
+ END IF;
+ WHEN Swsw =>
+ latcho <= regnbok and opc_req;
+ IF (ws_s=MAX_WS-1) THEN
+ next_state <= Smaxwsw;
+ ELSE
+ next_state <= Swsw;
+ END IF;
+ WHEN Smaxwsw =>
+ latcho <= regnbok and opc_req;
+ latchclr <= '1' ;
+ rw_ack<= not rwmem3_s;
+ next_state <= Sackw;
+ WHEN Sackw =>
+ latcho <= regnbok and opc_req;
+ IF (rwmem3_s = '1') THEN
+ muxabus <="10";
+ latchrw<='1';
+ next_state <= Swrodd;
+ ELSIF (flush_req = '1') THEN
+ next_state <= Sflush1;
+ ELSIF (irq_req='1' AND opc_req='1') THEN
+ irq_ack<='1';
+ next_state <= Sint;
+ ELSIF (reg4free = '1' ) THEN
+ muxabus <="00";
+ latchrw<='1';
+ next_state <= Srdopc;
+ ELSIF (flush_coming='1' OR
+ (irq_req='1' AND opc_req='0')) THEN
+ next_state <= Sfull;
+ ELSIF (regnbok = '0' and
+ reg4free = '0') THEN
+ next_state <= Serror;
+ ELSE
+ muxabus <="00";
+ next_state <= Sack;
+ END IF;
+ WHEN Swrodd =>
+ latcho <= regnbok and opc_req;
+ wr_s <= '1';
+ IF (ws_s/=MAX_WS) THEN
+ next_state <= Swsw;
+ ELSE
+ next_state <= Smaxwsw;
+ END IF;
+ WHEN Sread =>
+ rddata_s <= '1';
+ IF (ws_s/=MAX_WS) THEN
+ next_state <= Swsr;
+ ELSE
+ next_state <= Smaxwsr;
+ END IF;
+ WHEN Srdodd =>
+ rddata_s <= '1';
+ IF (ws_s/=MAX_WS) THEN
+ next_state <= Swsr;
+ ELSE
+ next_state <= Smaxwsr;
+ END IF;
+ WHEN Swsr =>
+ IF (ws_s=MAX_WS-1) THEN
+ next_state <= Smaxwsr;
+ ELSE
+ next_state <= Swsr;
+ END IF;
+ WHEN Smaxwsr =>
+ latchclr <= '1' ;
+ rw_ack<= not rwmem3_s;
+ next_state <= Sackr;
+ WHEN Sackr =>
+ IF (rwmem3_s = '1') THEN
+ muxabus <="10";
+ latchrw <= '1';
+ next_state <= Srdodd;
+ ELSIF (flush_req='1') THEN
+ next_state <= Sflush1;
+ ELSIF (irq_req='1' AND opc_req='1') THEN
+ irq_ack<='1';
+ next_state <= Sint;
+ ELSIF (reg4free = '1' ) THEN
+ muxabus <="00";
+ latchrw<='1';
+ next_state <= Srdopc;
+ ELSIF (flush_coming='1' OR
+ (irq_req='1' AND opc_req='0')) THEN
+ next_state <= Sfull;
+ ELSIF (regnbok = '0' and
+ reg4free = '0') THEN
+ next_state <= Serror;
+ ELSE
+ muxabus <="00";
+ next_state <= Sack;
+ END IF;
+ WHEN Sflush1 =>
+ flush_ack<='1';
+ IF (flush_req='0') THEN
+ muxabus<="01";
+ next_state <= Sflush2;
+ ELSE
+ next_state <= Sflush1;
+ END IF;
+ WHEN Sfull =>
+ latcho <= regnbok and opc_req;
+ IF (write_req='1') THEN
+ muxabus <="01";
+ latchrw <= '1' ;
+ next_state <= Swrite;
+ ELSIF (read_req='1') THEN
+ muxabus <="01";
+ latchrw <= '1' ;
+ next_state <= Sread;
+ ELSIF (flush_req = '1') THEN
+ next_state <= Sflush1;
+ ELSIF (irq_req='1' AND opc_req='1') THEN
+ irq_ack<='1';
+ next_state <= Sint;
+ ELSIF (reg4free = '1' AND
+ flush_coming='0' AND
+ irq_req='0') THEN
+ latchrw <= '1' ;
+ next_state <= Srdopc;
+ ELSIF (regnbok = '0' and
+ reg4free = '0') THEN
+ next_state <= Serror;
+ ELSE
+ next_state <= Sfull;
+ END IF;
+ WHEN Sint =>
+ latcho <= opc_req;
+ if irq_type="00" then inta1<='1';
+ end if;
+ irq_ack<='1';
+ next_state <= Sintws1;
+ WHEN Sintws2 =>
+ if irq_type="00" then
+ inta1<='1';
+ end if;
+ irq_clr <= '1';
+ next_state <= Sfull;
+ WHEN Sflush2 =>
+ latchabus<='1';
+ addrplus4<='0';
+ latchrw <= '1' ;
+ muxabus <="01";
+ next_state <= Srdopc;
+ WHEN Sintws1 =>
+ if irq_type="00" then
+ inta1<='1';
+ end if;
+ next_state <= Sintws2;
+ WHEN OTHERS =>
+ next_state <= Sreset;
+ END CASE;
+ END PROCESS nextstate_proc;
+
+ biu_status <= biu_status_cld;
+ rwmem3_s <= '1' when (w_biufsm_s='1' and oddflag_s='0') else '0';
+END fsm;
diff --git a/common/CPU/cpu86/cpu86_struct.vhd b/common/CPU/cpu86/cpu86_struct.vhd
new file mode 100644
index 00000000..8df93f64
--- /dev/null
+++ b/common/CPU/cpu86/cpu86_struct.vhd
@@ -0,0 +1,273 @@
+-------------------------------------------------------------------------------
+-- CPU86 - VHDL CPU8088 IP core --
+-- Copyright (C) 2002-2008 HT-LAB --
+-- --
+-- Contact/bugs : http://www.ht-lab.com/misc/feedback.html --
+-- Web : http://www.ht-lab.com --
+-- --
+-- CPU86 is released as open-source under the GNU GPL license. This means --
+-- that designs based on CPU86 must be distributed in full source code --
+-- under the same license. Contact HT-Lab for commercial applications where --
+-- source-code distribution is not desirable. --
+-- --
+-------------------------------------------------------------------------------
+-- --
+-- This library is free software; you can redistribute it and/or --
+-- modify it under the terms of the GNU Lesser General Public --
+-- License as published by the Free Software Foundation; either --
+-- version 2.1 of the License, or (at your option) any later version. --
+-- --
+-- This library 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 --
+-- Lesser General Public License for more details. --
+-- --
+-- Full details of the license can be found in the file "copying.txt". --
+-- --
+-- You should have received a copy of the GNU Lesser General Public --
+-- License along with this library; if not, write to the Free Software --
+-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --
+-- --
+-------------------------------------------------------------------------------
+LIBRARY ieee;
+USE ieee.std_logic_1164.all;
+USE ieee.std_logic_unsigned.all;
+
+USE work.cpu86pack.ALL;
+USE work.cpu86instr.ALL;
+
+
+ENTITY cpu86 IS
+ PORT(
+ clk : IN std_logic;
+ dbus_in : IN std_logic_vector (7 DOWNTO 0);
+ intr : IN std_logic;
+ nmi : IN std_logic;
+ por : IN std_logic;
+ abus : OUT std_logic_vector (19 DOWNTO 0);
+ dbus_out : OUT std_logic_vector (7 DOWNTO 0);
+ cpuerror : OUT std_logic;
+ inta : OUT std_logic;
+ iom : OUT std_logic;
+ rdn : OUT std_logic;
+ resoutn : OUT std_logic;
+ wran : OUT std_logic;
+ wrn : OUT std_logic
+ );
+END cpu86 ;
+
+
+ARCHITECTURE struct OF cpu86 IS
+
+ SIGNAL biu_error : std_logic;
+ SIGNAL clrop : std_logic;
+ SIGNAL dbusdp_out : std_logic_vector(15 DOWNTO 0);
+ SIGNAL decode_state : std_logic;
+ SIGNAL eabus : std_logic_vector(15 DOWNTO 0);
+ SIGNAL flush_ack : std_logic;
+ SIGNAL flush_coming : std_logic;
+ SIGNAL flush_req : std_logic;
+ SIGNAL instr : instruction_type;
+ SIGNAL inta1 : std_logic;
+ SIGNAL intack : std_logic;
+ SIGNAL iomem : std_logic;
+ SIGNAL irq_blocked : std_logic;
+ SIGNAL irq_req : std_logic;
+ SIGNAL latcho : std_logic;
+ SIGNAL mdbus_out : std_logic_vector(15 DOWNTO 0);
+ SIGNAL opc_req : std_logic;
+ SIGNAL path : path_in_type;
+ SIGNAL proc_error : std_logic;
+ SIGNAL read_req : std_logic;
+ SIGNAL reset : std_logic;
+ SIGNAL rw_ack : std_logic;
+ SIGNAL segbus : std_logic_vector(15 DOWNTO 0);
+ SIGNAL status : status_out_type;
+ SIGNAL word : std_logic;
+ SIGNAL write_req : std_logic;
+ SIGNAL wrpath : write_in_type;
+
+
+ -- Component Declarations
+ COMPONENT biu
+ PORT (
+ clk : IN std_logic ;
+ csbus : IN std_logic_vector (15 DOWNTO 0);
+ dbus_in : IN std_logic_vector (7 DOWNTO 0);
+ dbusdp_in : IN std_logic_vector (15 DOWNTO 0);
+ decode_state : IN std_logic ;
+ flush_coming : IN std_logic ;
+ flush_req : IN std_logic ;
+ intack : IN std_logic ;
+ intr : IN std_logic ;
+ iomem : IN std_logic ;
+ ipbus : IN std_logic_vector (15 DOWNTO 0);
+ irq_block : IN std_logic ;
+ nmi : IN std_logic ;
+ opc_req : IN std_logic ;
+ read_req : IN std_logic ;
+ reset : IN std_logic ;
+ status : IN status_out_type ;
+ word : IN std_logic ;
+ write_req : IN std_logic ;
+ abus : OUT std_logic_vector (19 DOWNTO 0);
+ biu_error : OUT std_logic ;
+ dbus_out : OUT std_logic_vector (7 DOWNTO 0);
+ flush_ack : OUT std_logic ;
+ instr : OUT instruction_type ;
+ inta : OUT std_logic ;
+ inta1 : OUT std_logic ;
+ iom : OUT std_logic ;
+ irq_req : OUT std_logic ;
+ latcho : OUT std_logic ;
+ mdbus_out : OUT std_logic_vector (15 DOWNTO 0);
+ rdn : OUT std_logic ;
+ rw_ack : OUT std_logic ;
+ wran : OUT std_logic ;
+ wrn : OUT std_logic
+ );
+ END COMPONENT;
+ COMPONENT datapath
+ PORT (
+ clk : IN std_logic ;
+ clrop : IN std_logic ;
+ instr : IN instruction_type ;
+ iomem : IN std_logic ;
+ mdbus_in : IN std_logic_vector (15 DOWNTO 0);
+ path : IN path_in_type ;
+ reset : IN std_logic ;
+ wrpath : IN write_in_type ;
+ dbusdp_out : OUT std_logic_vector (15 DOWNTO 0);
+ eabus : OUT std_logic_vector (15 DOWNTO 0);
+ segbus : OUT std_logic_vector (15 DOWNTO 0);
+ status : OUT status_out_type
+ );
+ END COMPONENT;
+ COMPONENT proc
+ PORT (
+ clk : IN std_logic ;
+ flush_ack : IN std_logic ;
+ instr : IN instruction_type ;
+ inta1 : IN std_logic ;
+ irq_req : IN std_logic ;
+ latcho : IN std_logic ;
+ reset : IN std_logic ;
+ rw_ack : IN std_logic ;
+ status : IN status_out_type ;
+ clrop : OUT std_logic ;
+ decode_state : OUT std_logic ;
+ flush_coming : OUT std_logic ;
+ flush_req : OUT std_logic ;
+ intack : OUT std_logic ;
+ iomem : OUT std_logic ;
+ irq_blocked : OUT std_logic ;
+ opc_req : OUT std_logic ;
+ path : OUT path_in_type ;
+ proc_error : OUT std_logic ;
+ read_req : OUT std_logic ;
+ word : OUT std_logic ;
+ write_req : OUT std_logic ;
+ wrpath : OUT write_in_type
+ );
+ END COMPONENT;
+
+
+BEGIN
+
+ -- synchronous reset
+ -- Internal use active high, external use active low
+ -- Async Asserted, sync negated
+ process (clk, por)
+ begin
+ if por='1' then
+ reset <= '1';
+ resoutn <= '0';
+ elsif rising_edge(clk) then
+ reset <= '0';
+ resoutn <= '1';
+ end if;
+ end process;
+
+
+ cpuerror <= proc_error OR biu_error;
+
+ cpubiu : biu
+ PORT MAP (
+ clk => clk,
+ csbus => segbus,
+ dbus_in => dbus_in,
+ dbusdp_in => dbusdp_out,
+ decode_state => decode_state,
+ flush_coming => flush_coming,
+ flush_req => flush_req,
+ intack => intack,
+ intr => intr,
+ iomem => iomem,
+ ipbus => eabus,
+ irq_block => irq_blocked,
+ nmi => nmi,
+ opc_req => opc_req,
+ read_req => read_req,
+ reset => reset,
+ status => status,
+ word => word,
+ write_req => write_req,
+ abus => abus,
+ biu_error => biu_error,
+ dbus_out => dbus_out,
+ flush_ack => flush_ack,
+ instr => instr,
+ inta => inta,
+ inta1 => inta1,
+ iom => iom,
+ irq_req => irq_req,
+ latcho => latcho,
+ mdbus_out => mdbus_out,
+ rdn => rdn,
+ rw_ack => rw_ack,
+ wran => wran,
+ wrn => wrn
+ );
+ cpudpath : datapath
+ PORT MAP (
+ clk => clk,
+ clrop => clrop,
+ instr => instr,
+ iomem => iomem,
+ mdbus_in => mdbus_out,
+ path => path,
+ reset => reset,
+ wrpath => wrpath,
+ dbusdp_out => dbusdp_out,
+ eabus => eabus,
+ segbus => segbus,
+ status => status
+ );
+ cpuproc : proc
+ PORT MAP (
+ clk => clk,
+ flush_ack => flush_ack,
+ instr => instr,
+ inta1 => inta1,
+ irq_req => irq_req,
+ latcho => latcho,
+ reset => reset,
+ rw_ack => rw_ack,
+ status => status,
+ clrop => clrop,
+ decode_state => decode_state,
+ flush_coming => flush_coming,
+ flush_req => flush_req,
+ intack => intack,
+ iomem => iomem,
+ irq_blocked => irq_blocked,
+ opc_req => opc_req,
+ path => path,
+ proc_error => proc_error,
+ read_req => read_req,
+ word => word,
+ write_req => write_req,
+ wrpath => wrpath
+ );
+
+END struct;
diff --git a/common/CPU/cpu86/cpu86instr.vhd b/common/CPU/cpu86/cpu86instr.vhd
new file mode 100644
index 00000000..7aff9cf0
--- /dev/null
+++ b/common/CPU/cpu86/cpu86instr.vhd
@@ -0,0 +1,425 @@
+-------------------------------------------------------------------------------
+-- CPU86 - VHDL CPU8088 IP core --
+-- Copyright (C) 2002-2008 HT-LAB --
+-- --
+-- Contact/bugs : http://www.ht-lab.com/misc/feedback.html --
+-- Web : http://www.ht-lab.com --
+-- --
+-- CPU86 is released as open-source under the GNU GPL license. This means --
+-- that designs based on CPU86 must be distributed in full source code --
+-- under the same license. Contact HT-Lab for commercial applications where --
+-- source-code distribution is not desirable. --
+-- --
+-------------------------------------------------------------------------------
+-- --
+-- This library is free software; you can redistribute it and/or --
+-- modify it under the terms of the GNU Lesser General Public --
+-- License as published by the Free Software Foundation; either --
+-- version 2.1 of the License, or (at your option) any later version. --
+-- --
+-- This library 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 --
+-- Lesser General Public License for more details. --
+-- --
+-- Full details of the license can be found in the file "copying.txt". --
+-- --
+-- You should have received a copy of the GNU Lesser General Public --
+-- License along with this library; if not, write to the Free Software --
+-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --
+-- --
+-------------------------------------------------------------------------------
+LIBRARY ieee;
+USE ieee.std_logic_1164.all;
+
+PACKAGE cpu86instr IS
+
+-----------------------------------------------------------------------------
+-- INC/DEC Word Register
+-----------------------------------------------------------------------------
+constant INCREG0 : std_logic_vector(7 downto 0) := X"40"; -- Inc Register
+constant INCREG1 : std_logic_vector(7 downto 0) := X"41";
+constant INCREG2 : std_logic_vector(7 downto 0) := X"42";
+constant INCREG3 : std_logic_vector(7 downto 0) := X"43";
+constant INCREG4 : std_logic_vector(7 downto 0) := X"44";
+constant INCREG5 : std_logic_vector(7 downto 0) := X"45";
+constant INCREG6 : std_logic_vector(7 downto 0) := X"46";
+constant INCREG7 : std_logic_vector(7 downto 0) := X"47";
+constant DECREG0 : std_logic_vector(7 downto 0) := X"48"; -- DEC Register
+constant DECREG1 : std_logic_vector(7 downto 0) := X"49";
+constant DECREG2 : std_logic_vector(7 downto 0) := X"4A";
+constant DECREG3 : std_logic_vector(7 downto 0) := X"4B";
+constant DECREG4 : std_logic_vector(7 downto 0) := X"4C";
+constant DECREG5 : std_logic_vector(7 downto 0) := X"4D";
+constant DECREG6 : std_logic_vector(7 downto 0) := X"4E";
+constant DECREG7 : std_logic_vector(7 downto 0) := X"4F";
+
+-----------------------------------------------------------------------------
+-- IN
+-----------------------------------------------------------------------------
+constant INFIXED0 : std_logic_vector(7 downto 0) := X"E4"; -- Fixed Port Byte
+constant INFIXED1 : std_logic_vector(7 downto 0) := X"E5"; -- Fixed Port Word
+constant INDX0 : std_logic_vector(7 downto 0) := X"EC"; -- DX Byte
+constant INDX1 : std_logic_vector(7 downto 0) := X"ED"; -- DX Word
+
+-----------------------------------------------------------------------------
+-- OUT
+-----------------------------------------------------------------------------
+constant OUTFIXED0 : std_logic_vector(7 downto 0) := X"E6"; -- Fixed Port Byte
+constant OUTFIXED1 : std_logic_vector(7 downto 0) := X"E7"; -- Fixed Port Word
+constant OUTDX0 : std_logic_vector(7 downto 0) := X"EE"; -- DX Byte
+constant OUTDX1 : std_logic_vector(7 downto 0) := X"EF"; -- DX Word
+
+-----------------------------------------------------------------------------
+-- Move Immediate to Register
+-----------------------------------------------------------------------------
+constant MOVI2R0 : std_logic_vector(7 downto 0) := X"B0"; -- Immediate to Register
+constant MOVI2R1 : std_logic_vector(7 downto 0) := X"B1"; -- Byte
+constant MOVI2R2 : std_logic_vector(7 downto 0) := X"B2";
+constant MOVI2R3 : std_logic_vector(7 downto 0) := X"B3";
+constant MOVI2R4 : std_logic_vector(7 downto 0) := X"B4";
+constant MOVI2R5 : std_logic_vector(7 downto 0) := X"B5";
+constant MOVI2R6 : std_logic_vector(7 downto 0) := X"B6";
+constant MOVI2R7 : std_logic_vector(7 downto 0) := X"B7";
+constant MOVI2R8 : std_logic_vector(7 downto 0) := X"B8"; -- Word
+constant MOVI2R9 : std_logic_vector(7 downto 0) := X"B9";
+constant MOVI2R10 : std_logic_vector(7 downto 0) := X"BA";
+constant MOVI2R11 : std_logic_vector(7 downto 0) := X"BB";
+constant MOVI2R12 : std_logic_vector(7 downto 0) := X"BC";
+constant MOVI2R13 : std_logic_vector(7 downto 0) := X"BD";
+constant MOVI2R14 : std_logic_vector(7 downto 0) := X"BE";
+constant MOVI2R15 : std_logic_vector(7 downto 0) := X"BF";
+
+-----------------------------------------------------------------------------
+-- Move Immediate to Register/memory
+-----------------------------------------------------------------------------
+constant MOVI2RM0 : std_logic_vector(7 downto 0) := X"C6";
+constant MOVI2RM1 : std_logic_vector(7 downto 0) := X"C7"; -- Word
+
+-----------------------------------------------------------------------------
+-- Segment Register to Register or Memory
+-----------------------------------------------------------------------------
+constant MOVS2RM : std_logic_vector(7 downto 0) := X"8C";
+
+-----------------------------------------------------------------------------
+-- Register or Memory to Segment Register
+-----------------------------------------------------------------------------
+constant MOVRM2S : std_logic_vector(7 downto 0) := X"8E";
+
+-----------------------------------------------------------------------------
+-- Memory to Accumulator ADDRL,ADDRH
+-----------------------------------------------------------------------------
+constant MOVM2A0 : std_logic_vector(7 downto 0) := X"A0";
+constant MOVM2A1 : std_logic_vector(7 downto 0) := X"A1";
+
+-----------------------------------------------------------------------------
+-- Accumulator to Memory to Accumulator ADDRL,ADDRH
+-----------------------------------------------------------------------------
+constant MOVA2M0 : std_logic_vector(7 downto 0) := X"A2";
+constant MOVA2M1 : std_logic_vector(7 downto 0) := X"A3";
+
+-----------------------------------------------------------------------------
+-- Register/Memory to/from Register
+-----------------------------------------------------------------------------
+constant MOVRM2R0 : std_logic_vector(7 downto 0) := X"88";
+constant MOVRM2R1 : std_logic_vector(7 downto 0) := X"89";
+constant MOVRM2R2 : std_logic_vector(7 downto 0) := X"8A";
+constant MOVRM2R3 : std_logic_vector(7 downto 0) := X"8B";
+
+-----------------------------------------------------------------------------
+-- Segment Override Prefix
+-----------------------------------------------------------------------------
+constant SEGOPES : std_logic_vector(7 downto 0) := X"26";
+constant SEGOPCS : std_logic_vector(7 downto 0) := X"2E";
+constant SEGOPSS : std_logic_vector(7 downto 0) := X"36";
+constant SEGOPDS : std_logic_vector(7 downto 0) := X"3E";
+
+-----------------------------------------------------------------------------
+-- ADD/ADC/SUB/SBB/CMP/AND/OR/XOR Register/Memory to Register
+-----------------------------------------------------------------------------
+constant ADDRM2R0 : std_logic_vector(7 downto 0) := X"00";
+constant ADDRM2R1 : std_logic_vector(7 downto 0) := X"01";
+constant ADDRM2R2 : std_logic_vector(7 downto 0) := X"02";
+constant ADDRM2R3 : std_logic_vector(7 downto 0) := X"03";
+
+constant ADCRM2R0 : std_logic_vector(7 downto 0) := X"10";
+constant ADCRM2R1 : std_logic_vector(7 downto 0) := X"11";
+constant ADCRM2R2 : std_logic_vector(7 downto 0) := X"12";
+constant ADCRM2R3 : std_logic_vector(7 downto 0) := X"13";
+
+constant SUBRM2R0 : std_logic_vector(7 downto 0) := X"28";
+constant SUBRM2R1 : std_logic_vector(7 downto 0) := X"29";
+constant SUBRM2R2 : std_logic_vector(7 downto 0) := X"2A";
+constant SUBRM2R3 : std_logic_vector(7 downto 0) := X"2B";
+
+constant SBBRM2R0 : std_logic_vector(7 downto 0) := X"18";
+constant SBBRM2R1 : std_logic_vector(7 downto 0) := X"19";
+constant SBBRM2R2 : std_logic_vector(7 downto 0) := X"1A";
+constant SBBRM2R3 : std_logic_vector(7 downto 0) := X"1B";
+
+constant CMPRM2R0 : std_logic_vector(7 downto 0) := X"38";
+constant CMPRM2R1 : std_logic_vector(7 downto 0) := X"39";
+constant CMPRM2R2 : std_logic_vector(7 downto 0) := X"3A";
+constant CMPRM2R3 : std_logic_vector(7 downto 0) := X"3B";
+
+constant ANDRM2R0 : std_logic_vector(7 downto 0) := X"20";
+constant ANDRM2R1 : std_logic_vector(7 downto 0) := X"21";
+constant ANDRM2R2 : std_logic_vector(7 downto 0) := X"22";
+constant ANDRM2R3 : std_logic_vector(7 downto 0) := X"23";
+
+constant ORRM2R0 : std_logic_vector(7 downto 0) := X"08";
+constant ORRM2R1 : std_logic_vector(7 downto 0) := X"09";
+constant ORRM2R2 : std_logic_vector(7 downto 0) := X"0A";
+constant ORRM2R3 : std_logic_vector(7 downto 0) := X"0B";
+
+constant XORRM2R0 : std_logic_vector(7 downto 0) := X"30";
+constant XORRM2R1 : std_logic_vector(7 downto 0) := X"31";
+constant XORRM2R2 : std_logic_vector(7 downto 0) := X"32";
+constant XORRM2R3 : std_logic_vector(7 downto 0) := X"33";
+
+
+-----------------------------------------------------------------------------
+-- OPCODE 80,81,83, ADD/ADC/SUB/SBB/CMP/AND/OR/XOR Immediate to Reg/Mem
+-- Instruction defined in reg field
+-----------------------------------------------------------------------------
+constant O80I2RM : std_logic_vector(7 downto 0) := X"80";
+constant O81I2RM : std_logic_vector(7 downto 0) := X"81";
+constant O83I2RM : std_logic_vector(7 downto 0) := X"83";
+
+-----------------------------------------------------------------------------
+-- ADD/ADC/SUB/SBB/CMP/AND/OR/XOR Immediate with ACCU
+-----------------------------------------------------------------------------
+constant ADDI2AX0 : std_logic_vector(7 downto 0) := X"04";
+constant ADDI2AX1 : std_logic_vector(7 downto 0) := X"05";
+constant ADCI2AX0 : std_logic_vector(7 downto 0) := X"14";
+constant ADCI2AX1 : std_logic_vector(7 downto 0) := X"15";
+constant SUBI2AX0 : std_logic_vector(7 downto 0) := X"2C";
+constant SUBI2AX1 : std_logic_vector(7 downto 0) := X"2D";
+constant SBBI2AX0 : std_logic_vector(7 downto 0) := X"1C";
+constant SBBI2AX1 : std_logic_vector(7 downto 0) := X"1D";
+constant CMPI2AX0 : std_logic_vector(7 downto 0) := X"3C";
+constant CMPI2AX1 : std_logic_vector(7 downto 0) := X"3D";
+constant ANDI2AX0 : std_logic_vector(7 downto 0) := X"24";
+constant ANDI2AX1 : std_logic_vector(7 downto 0) := X"25";
+constant ORI2AX0 : std_logic_vector(7 downto 0) := X"0C";
+constant ORI2AX1 : std_logic_vector(7 downto 0) := X"0D";
+constant XORI2AX0 : std_logic_vector(7 downto 0) := X"34";
+constant XORI2AX1 : std_logic_vector(7 downto 0) := X"35";
+
+-----------------------------------------------------------------------------
+-- TEST (Same as AND but without returning any results)
+-----------------------------------------------------------------------------
+constant TESTRMR0 : std_logic_vector(7 downto 0) := X"84";
+constant TESTRMR1 : std_logic_vector(7 downto 0) := X"85";
+constant TESTI2AX0 : std_logic_vector(7 downto 0) := X"A8";
+constant TESTI2AX1 : std_logic_vector(7 downto 0) := X"A9";
+
+-----------------------------------------------------------------------------
+-- NOT/TEST F6/F7 Shared Instructions
+-- TEST regfield=000
+-- NOT regfield=010
+-- MUL regfield=100
+-- IMUL regfield=101
+-- DIV regfield=110
+-- IDIV regfield=111
+-----------------------------------------------------------------------------
+constant F6INSTR : std_logic_vector(7 downto 0) := X"F6"; -- Byte
+constant F7INSTR : std_logic_vector(7 downto 0) := X"F7"; -- Word
+
+-----------------------------------------------------------------------------
+-- Carry Flag CLC/CMC/STC
+-----------------------------------------------------------------------------
+constant CLC : std_logic_vector(7 downto 0) := X"F8";
+constant CMC : std_logic_vector(7 downto 0) := X"F5";
+constant STC : std_logic_vector(7 downto 0) := X"F9";
+constant CLD : std_logic_vector(7 downto 0) := X"FC";
+constant STDx : std_logic_vector(7 downto 0) := X"FD";
+constant CLI : std_logic_vector(7 downto 0) := X"FA";
+constant STI : std_logic_vector(7 downto 0) := X"FB";
+
+-----------------------------------------------------------------------------
+-- 8080 Instruction LAHF/SAHF
+-----------------------------------------------------------------------------
+constant LAHF : std_logic_vector(7 downto 0) := X"9F";
+constant SAHF : std_logic_vector(7 downto 0) := X"9E";
+
+-----------------------------------------------------------------------------
+-- Conditional Jumps Jxxx
+-----------------------------------------------------------------------------
+constant JZ : std_logic_vector(7 downto 0) := X"74";
+constant JL : std_logic_vector(7 downto 0) := X"7C";
+constant JLE : std_logic_vector(7 downto 0) := X"7E";
+constant JB : std_logic_vector(7 downto 0) := X"72";
+constant JBE : std_logic_vector(7 downto 0) := X"76";
+constant JP : std_logic_vector(7 downto 0) := X"7A";
+constant JO : std_logic_vector(7 downto 0) := X"70";
+constant JS : std_logic_vector(7 downto 0) := X"78";
+constant JNE : std_logic_vector(7 downto 0) := X"75";
+constant JNL : std_logic_vector(7 downto 0) := X"7D";
+constant JNLE : std_logic_vector(7 downto 0) := X"7F";
+constant JNB : std_logic_vector(7 downto 0) := X"73";
+constant JNBE : std_logic_vector(7 downto 0) := X"77";
+constant JNP : std_logic_vector(7 downto 0) := X"7B";
+constant JNO : std_logic_vector(7 downto 0) := X"71";
+constant JNS : std_logic_vector(7 downto 0) := X"79";
+
+constant JMPS : std_logic_vector(7 downto 0) := X"EB"; -- Short Jump within segment , SignExt DISPL
+constant JMP : std_logic_vector(7 downto 0) := X"E9"; -- Long Jump within segment, No SignExt DISPL
+constant JMPDIS : std_logic_vector(7 downto 0) := X"EA"; -- Jump Inter Segment (CS:IP given)
+
+-----------------------------------------------------------------------------
+-- Push/Pop Flags
+-----------------------------------------------------------------------------
+constant PUSHF : std_logic_vector(7 downto 0) := X"9C";
+constant POPF : std_logic_vector(7 downto 0) := X"9D";
+
+-----------------------------------------------------------------------------
+-- PUSH Register
+-----------------------------------------------------------------------------
+constant PUSHAX : std_logic_vector(7 downto 0) := X"50";
+constant PUSHCX : std_logic_vector(7 downto 0) := X"51";
+constant PUSHDX : std_logic_vector(7 downto 0) := X"52";
+constant PUSHBX : std_logic_vector(7 downto 0) := X"53";
+constant PUSHSP : std_logic_vector(7 downto 0) := X"54";
+constant PUSHBP : std_logic_vector(7 downto 0) := X"55";
+constant PUSHSI : std_logic_vector(7 downto 0) := X"56";
+constant PUSHDI : std_logic_vector(7 downto 0) := X"57";
+
+constant PUSHES : std_logic_vector(7 downto 0) := X"06";
+constant PUSHCS : std_logic_vector(7 downto 0) := X"0E";
+constant PUSHSS : std_logic_vector(7 downto 0) := X"16";
+constant PUSHDS : std_logic_vector(7 downto 0) := X"1E";
+
+-----------------------------------------------------------------------------
+-- Pop Register
+-----------------------------------------------------------------------------
+constant POPAX : std_logic_vector(7 downto 0) := X"58";
+constant POPCX : std_logic_vector(7 downto 0) := X"59";
+constant POPDX : std_logic_vector(7 downto 0) := X"5A";
+constant POPBX : std_logic_vector(7 downto 0) := X"5B";
+constant POPSP : std_logic_vector(7 downto 0) := X"5C";
+constant POPBP : std_logic_vector(7 downto 0) := X"5D";
+constant POPSI : std_logic_vector(7 downto 0) := X"5E";
+constant POPDI : std_logic_vector(7 downto 0) := X"5F";
+
+constant POPES : std_logic_vector(7 downto 0) := X"07";
+constant POPSS : std_logic_vector(7 downto 0) := X"17";
+constant POPDS : std_logic_vector(7 downto 0) := X"1F";
+
+constant POPRM : std_logic_vector(7 downto 0) := X"8F";
+
+-----------------------------------------------------------------------------
+-- Exchange Register
+-----------------------------------------------------------------------------
+constant XCHGW : std_logic_vector(7 downto 0) := X"86";
+constant XCHGB : std_logic_vector(7 downto 0) := X"87";
+
+constant XCHGAX : std_logic_vector(7 downto 0) := X"90";
+constant XCHGCX : std_logic_vector(7 downto 0) := X"91";
+constant XCHGDX : std_logic_vector(7 downto 0) := X"92";
+constant XCHGBX : std_logic_vector(7 downto 0) := X"93";
+constant XCHGSP : std_logic_vector(7 downto 0) := X"94";
+constant XCHGBP : std_logic_vector(7 downto 0) := X"95";
+constant XCHGSI : std_logic_vector(7 downto 0) := X"96";
+constant XCHGDI : std_logic_vector(7 downto 0) := X"97";
+
+-----------------------------------------------------------------------------
+-- Load Effective Address
+-----------------------------------------------------------------------------
+constant LEA : std_logic_vector(7 downto 0) := X"8D";
+constant LDS : std_logic_vector(7 downto 0) := X"C5";
+constant LES : std_logic_vector(7 downto 0) := X"C4";
+
+-----------------------------------------------------------------------------
+-- Convert Instructions
+-----------------------------------------------------------------------------
+constant CBW : std_logic_vector(7 downto 0) := X"98";
+constant CWD : std_logic_vector(7 downto 0) := X"99";
+constant AAS : std_logic_vector(7 downto 0) := X"3F";
+constant DAS : std_logic_vector(7 downto 0) := X"2F";
+constant AAA : std_logic_vector(7 downto 0) := X"37";
+constant DAA : std_logic_vector(7 downto 0) := X"27";
+
+constant AAM : std_logic_vector(7 downto 0) := X"D4";
+constant AAD : std_logic_vector(7 downto 0) := X"D5";
+
+constant XLAT : std_logic_vector(7 downto 0) := X"D7";
+
+-----------------------------------------------------------------------------
+-- Misc Instructions
+-----------------------------------------------------------------------------
+constant NOP : std_logic_vector(7 downto 0) := X"90"; -- No Operation
+constant HLT : std_logic_vector(7 downto 0) := X"F4"; -- Halt Instruction, wait NMI, INTR, Reset
+
+-----------------------------------------------------------------------------
+-- Loop Instructions
+-----------------------------------------------------------------------------
+constant LOOPCX : std_logic_vector(7 downto 0) := X"E2";
+constant LOOPZ : std_logic_vector(7 downto 0) := X"E1";
+constant LOOPNZ : std_logic_vector(7 downto 0) := X"E0";
+constant JCXZ : std_logic_vector(7 downto 0) := X"E3";
+
+-----------------------------------------------------------------------------
+-- CALL Instructions
+-----------------------------------------------------------------------------
+constant CALL : std_logic_vector(7 downto 0) := X"E8"; -- Direct within Segment
+constant CALLDIS : std_logic_vector(7 downto 0) := X"9A"; -- Direct Inter Segment
+
+-----------------------------------------------------------------------------
+-- RET Instructions
+-----------------------------------------------------------------------------
+constant RET : std_logic_vector(7 downto 0) := X"C3"; -- Within Segment
+constant RETDIS : std_logic_vector(7 downto 0) := X"CB"; -- Direct Inter Segment
+constant RETO : std_logic_vector(7 downto 0) := X"C2"; -- Within Segment + Offset
+constant RETDISO : std_logic_vector(7 downto 0) := X"CA"; -- Direct Inter Segment +Offset
+
+-----------------------------------------------------------------------------
+-- INT Instructions
+-----------------------------------------------------------------------------
+constant INT : std_logic_vector(7 downto 0) := X"CD"; -- type=second byte
+constant INT3 : std_logic_vector(7 downto 0) := X"CC"; -- type=3
+constant INTO : std_logic_vector(7 downto 0) := X"CE"; -- type=4
+constant IRET : std_logic_vector(7 downto 0) := X"CF"; -- Interrupt Return
+
+-----------------------------------------------------------------------------
+-- String/Repeat Instructions
+-----------------------------------------------------------------------------
+constant MOVSB : std_logic_vector(7 downto 0) := X"A4";
+constant MOVSW : std_logic_vector(7 downto 0) := X"A5";
+constant CMPSB : std_logic_vector(7 downto 0) := X"A6";
+constant CMPSW : std_logic_vector(7 downto 0) := X"A7";
+constant SCASB : std_logic_vector(7 downto 0) := X"AE";
+constant SCASW : std_logic_vector(7 downto 0) := X"AF";
+constant LODSB : std_logic_vector(7 downto 0) := X"AC";
+constant LODSW : std_logic_vector(7 downto 0) := X"AD";
+constant STOSB : std_logic_vector(7 downto 0) := X"AA";
+constant STOSW : std_logic_vector(7 downto 0) := X"AB";
+
+constant REPNE : std_logic_vector(7 downto 0) := X"F2"; -- stop if zf=1
+constant REPE : std_logic_vector(7 downto 0) := X"F3"; -- stop if zf/=1
+
+
+-----------------------------------------------------------------------------
+-- Shift/Rotate Instructions
+-- Operation define in MODRM REG bits
+-- Note REG=110 is undefined
+-----------------------------------------------------------------------------
+constant SHFTROT0 : std_logic_vector(7 downto 0) := X"D0";
+constant SHFTROT1 : std_logic_vector(7 downto 0) := X"D1";
+constant SHFTROT2 : std_logic_vector(7 downto 0) := X"D2";
+constant SHFTROT3 : std_logic_vector(7 downto 0) := X"D3";
+
+-----------------------------------------------------------------------------
+-- FF/FE Instructions. Use regfiled to decode operation
+-- INC reg=000 (FF/FE)
+-- DEC reg=001 (FF/FE)
+-- CALL reg=010 (FF) Indirect within segment
+-- CALL reg=011 (FF) Indirect Intersegment
+-- JMP reg=100 (FF) Indirect within segment
+-- JMP reg=101 (FF) Indirect Intersegment
+-- PUSH reg=110 (FF)
+-----------------------------------------------------------------------------
+constant FEINSTR : std_logic_vector(7 downto 0) := X"FE";
+constant FFINSTR : std_logic_vector(7 downto 0) := X"FF";
+
+END cpu86instr;
diff --git a/common/CPU/cpu86/cpu86pack.vhd b/common/CPU/cpu86/cpu86pack.vhd
new file mode 100644
index 00000000..070fc938
--- /dev/null
+++ b/common/CPU/cpu86/cpu86pack.vhd
@@ -0,0 +1,285 @@
+-------------------------------------------------------------------------------
+-- CPU86 - VHDL CPU8088 IP core --
+-- Copyright (C) 2002-2008 HT-LAB --
+-- --
+-- Contact/bugs : http://www.ht-lab.com/misc/feedback.html --
+-- Web : http://www.ht-lab.com --
+-- --
+-- CPU86 is released as open-source under the GNU GPL license. This means --
+-- that designs based on CPU86 must be distributed in full source code --
+-- under the same license. Contact HT-Lab for commercial applications where --
+-- source-code distribution is not desirable. --
+-- --
+-------------------------------------------------------------------------------
+-- --
+-- This library is free software; you can redistribute it and/or --
+-- modify it under the terms of the GNU Lesser General Public --
+-- License as published by the Free Software Foundation; either --
+-- version 2.1 of the License, or (at your option) any later version. --
+-- --
+-- This library 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 --
+-- Lesser General Public License for more details. --
+-- --
+-- Full details of the license can be found in the file "copying.txt". --
+-- --
+-- You should have received a copy of the GNU Lesser General Public --
+-- License along with this library; if not, write to the Free Software --
+-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --
+-- --
+-------------------------------------------------------------------------------
+LIBRARY ieee;
+USE ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+
+PACKAGE cpu86pack IS
+
+constant RESET_CS_C : std_logic_vector(15 downto 0) := (others => '1'); -- FFFF:0000
+constant RESET_IP_C : std_logic_vector(15 downto 0) := (others => '0');
+constant RESET_ES_C : std_logic_vector(15 downto 0) := (others => '0');
+constant RESET_SS_C : std_logic_vector(15 downto 0) := (others => '0');
+constant RESET_DS_C : std_logic_vector(15 downto 0) := (others => '0');
+
+constant RESET_VECTOR_C : std_logic_vector(19 downto 0) := (RESET_CS_C & X"0") + (X"0" & RESET_IP_C);
+
+constant MUL_MCD_C : std_logic_vector(4 downto 0) := "00010"; -- mul MCP
+-- Serial Divider delay
+-- changed later to done signal
+-- You can gain 1 clk cycle, done can be asserted 1 cycle earlier
+constant DIV_MCD_C : std_logic_vector(4 downto 0) := "10011"; -- div waitstates 19!
+
+constant ONE : std_logic := '1';
+constant ZERO : std_logic := '0';
+constant ZEROVECTOR_C : std_logic_vector(31 downto 0) := X"00000000";
+
+-- Minimum value for MAX_WS="000", this result in a 2 cycle rd/wr strobe
+-- Total Read cycle is 1 cycle for address setup + 2 cycles for rd/wr strobe, thus
+-- minimum bus cycle is 3 clk cycles.
+constant WS_WIDTH : integer := 3; -- 2^WS_WIDTH=MAX Waitstates
+constant MAX_WS : std_logic_vector(WS_WIDTH-1 downto 0) := "000"; -- 3 clk bus cycles
+
+constant DONTCARE : std_logic_vector(31 downto 0):=X"FFFFFFFF";
+
+
+-- Status record containing some data and flag register
+type instruction_type is record
+ ireg : std_logic_vector(7 downto 0); -- Instruction register
+ xmod : std_logic_vector(1 downto 0); -- mod is a reserved word
+ reg : std_logic_vector(2 downto 0); -- between mode and rm
+ rm : std_logic_vector(2 downto 0);
+ data : std_logic_vector(15 downto 0);
+ disp : std_logic_vector(15 downto 0);
+ nb : std_logic_vector(2 downto 0); -- Number of bytes
+end record;
+
+
+-- Status record containing some data and flag register
+type status_out_type is record
+ ax : std_logic_vector(15 downto 0);
+ cx_one : std_logic; -- '1' if CX=0001
+ cx_zero : std_logic; -- '1' if CX=0000
+ cl : std_logic_vector(7 downto 0); -- 5 bits shift/rotate counter
+ flag : std_logic_vector(15 downto 0);
+ div_err : std_logic; -- Divider overflow
+end record;
+
+--------------------------------------------------------------------------------------
+-- Data Path Records
+--------------------------------------------------------------------------------------
+type path_in_type is record
+ datareg_input : std_logic_vector(6 downto 0); -- dimux(3) & w & seldreg(3)
+ alu_operation : std_logic_vector(14 downto 0);-- selalua(4) & selalub(4) & aluopr(7)
+ dbus_output : std_logic_vector(1 downto 0); -- (Odd/Even) domux setting
+ segreg_input : std_logic_vector(3 downto 0); -- simux & selsreg
+ ea_output : std_logic_vector(9 downto 0); -- dispmux(3) & eamux(4) & [flag]&segop(2)
+end record;
+
+-- Write Strobe Record for Data Path
+type write_in_type is record
+ wrd : std_logic; -- Write datareg
+ wralu : std_logic; -- Write ALU result
+ wrcc : std_logic; -- Write Flag register
+ wrs : std_logic; -- Write Segment register
+ wrip : std_logic; -- Write Instruction Pointer
+ wrop : std_logic; -- Write Segment Prefix register, Set Prefix Flag
+ wrtemp: std_logic; -- Write to ALU_TEMP register
+end record;
+
+
+constant SET_OPFLAG : std_logic:='1'; -- Override Prefix Flag
+
+-- DIMUX
+constant DATAIN_IN : std_logic_vector(2 downto 0) := "000";
+constant EABUS_IN : std_logic_vector(2 downto 0) := "001";
+constant ALUBUS_IN : std_logic_vector(2 downto 0) := "010";
+constant MDBUS_IN : std_logic_vector(2 downto 0) := "011";
+constant ES_IN : std_logic_vector(2 downto 0) := "100";
+constant CS_IN : std_logic_vector(2 downto 0) := "101";
+constant SS_IN : std_logic_vector(2 downto 0) := "110";
+constant DS_IN : std_logic_vector(2 downto 0) := "111";
+
+-- SIMUX Segment Register input Mux
+constant SDATAIN_IN : std_logic_vector(1 downto 0) := "00";
+constant SEABUS_IN : std_logic_vector(1 downto 0) := "01"; -- Effective Address
+constant SALUBUS_IN : std_logic_vector(1 downto 0) := "10";
+constant SMDBUS_IN : std_logic_vector(1 downto 0) := "11";
+
+-- DOMUX (Note bit 2=odd/even)
+constant ALUBUS_OUT : std_logic_vector(1 downto 0) := "00";
+constant CCBUS_OUT : std_logic_vector(1 downto 0) := "01";
+constant DIBUS_OUT : std_logic_vector(1 downto 0) := "10";
+constant IPBUS_OUT : std_logic_vector(1 downto 0) := "11";
+
+
+-- dispmux(3) & eamux(4) & poflag & segop[1:0]
+-- note some bits may be dontcare!
+constant NB_ES_IP : std_logic_vector(9 downto 0) := "0000000000"; -- IPREG+NB ADDR=ES:IP
+constant NB_CS_IP : std_logic_vector(9 downto 0) := "0000000001";
+constant NB_SS_IP : std_logic_vector(9 downto 0) := "0000000010";
+constant NB_DS_IP : std_logic_vector(9 downto 0) := "0000000011";
+
+constant NB_ES_EA : std_logic_vector(9 downto 0) := "0000001000"; -- IPREG+NB ADDR=EA
+constant NB_CS_EA : std_logic_vector(9 downto 0) := "0000001001";
+constant NB_SS_EA : std_logic_vector(9 downto 0) := "0000001010";
+constant NB_DS_EA : std_logic_vector(9 downto 0) := "0000001011";
+constant DISP_ES_EA : std_logic_vector(9 downto 0) := "0010001000"; -- IPREG+DISP ADDR=EA
+constant DISP_CS_EA : std_logic_vector(9 downto 0) := "0010001001";
+constant DISP_SS_EA : std_logic_vector(9 downto 0) := "0010001010";
+constant DISP_DS_EA : std_logic_vector(9 downto 0) := "0010001011";
+
+constant DISP_CS_IP : std_logic_vector(9 downto 0) := "0010000001"; -- Used for Jx instructions
+
+constant PORT_00_DX : std_logic_vector(6 downto 0) := "0000010"; -- EAMUX IN/OUT instruction
+constant PORT_00_EA : std_logic_vector(6 downto 0) := "0000001"; -- EAMUX Segm=00 00:IP or 00:DISP
+
+constant NB_SS_SP : std_logic_vector(6 downto 0) := "0000100"; -- IP=IP+NBREQ, EAMUX=SS:SP , 100, 101, 110 unused
+constant LD_SS_SP : std_logic_vector(6 downto 0) := "0100100"; -- Load new IP from MDBUS & out=SS:SP
+
+constant LD_MD_IP : std_logic_vector(9 downto 0) := "0100000001"; -- Load new IP from MDBUS (e.g. RET instruction)
+constant LD_CS_IP : std_logic_vector(9 downto 0) := "0110000001"; -- Load new IP (e.g. RET instruction)
+constant EA_CS_IP : std_logic_vector(9 downto 0) := "1000001001"; -- Load new IP (e.g. RET instruction)
+constant IPB_CS_IP : std_logic_vector(9 downto 0) := "1110000001"; -- Select IPBUS=IPREG
+
+constant MD_EA2_DS : std_logic_vector(9 downto 0) := "0100011011"; -- IP<-MD, addr=DS:EA2
+
+-- SELALUA/B or SELDREG(2 downto 0)
+constant REG_AX : std_logic_vector(3 downto 0) := "0000"; -- W=1 Into ALUBUS A or B
+constant REG_CX : std_logic_vector(3 downto 0) := "0001";
+constant REG_DX : std_logic_vector(3 downto 0) := "0010";
+constant REG_BX : std_logic_vector(3 downto 0) := "0011";
+constant REG_SP : std_logic_vector(3 downto 0) := "0100";
+constant REG_BP : std_logic_vector(3 downto 0) := "0101";
+constant REG_SI : std_logic_vector(3 downto 0) := "0110";
+constant REG_DI : std_logic_vector(3 downto 0) := "0111";
+constant REG_DATAIN : std_logic_vector(3 downto 0) := "1000"; -- Pass data_in to ALU
+constant REG_MDBUS : std_logic_vector(3 downto 0) := "1111"; -- Pass memory bus (mdbus) to ALU
+
+-- Only for SELALUB
+constant REG_CONST1 : std_logic_vector(3 downto 0) := "1001"; -- Used for INC/DEC function, W=0/1
+constant REG_CONST2 : std_logic_vector(3 downto 0) := "1010"; -- Used for POP/PUSH function W=1
+
+-- W+SELDREG
+constant REG_AH : std_logic_vector(3 downto 0) := "0100"; -- W=1 SELDREG=AH
+
+
+---------------------------------------------------------------
+-- ALU Operations
+-- Use ireg(5 downto 3) / modrm(5 downto 3) / ireg(3 downto 0)
+-- Constants for
+---------------------------------------------------------------
+constant ALU_ADD : std_logic_vector(6 downto 0) := "0000000";
+constant ALU_OR : std_logic_vector(6 downto 0) := "0000001";
+constant ALU_ADC : std_logic_vector(6 downto 0) := "0000010";
+constant ALU_SBB : std_logic_vector(6 downto 0) := "0000011";
+constant ALU_AND : std_logic_vector(6 downto 0) := "0000100";
+constant ALU_SUB : std_logic_vector(6 downto 0) := "0000101";
+constant ALU_XOR : std_logic_vector(6 downto 0) := "0000110";
+constant ALU_CMP : std_logic_vector(6 downto 0) := "0000111"; -- See also ALU_CMPS
+constant ALU_TEST0 : std_logic_vector(6 downto 0) := "0001000";
+constant ALU_TEST1 : std_logic_vector(6 downto 0) := "0001101";
+
+-- Random assignment, these can be changed.
+constant ALU_PUSH : std_logic_vector(6 downto 0) := "0001001"; -- Used for PUSH (SUB)
+constant ALU_POP : std_logic_vector(6 downto 0) := "0001010"; -- Used for POP (ADD)
+constant ALU_REGL : std_logic_vector(6 downto 0) := "0001011"; -- alureg(15..0) (latched alu_busb)
+constant ALU_REGH : std_logic_vector(6 downto 0) := "0111011"; -- alureg(31..16) (latched alu_busa)
+constant ALU_PASSA : std_logic_vector(6 downto 0) := "0001100"; -- abus_s only
+constant ALU_TEMP : std_logic_vector(6 downto 0) := "1111001"; -- Used to select temp/scratchpad register (80186 only)
+
+-- CONST & instr.irg(3 downto 0)
+constant ALU_SAHF : std_logic_vector(6 downto 0) := "0001110"; -- AH -> Flags
+
+-- CONST & instr.irg(3 downto 0)
+constant ALU_LAHF : std_logic_vector(6 downto 0) := "0001111"; -- Flags->ALUBUS (->AH)
+
+-- CONSTANT & instr.ireg(1) & modrm.reg(5 downto 3)
+-- CONSTANT=001
+constant ALU_ROL1 : std_logic_vector(6 downto 0) := "0010000"; -- count=1
+constant ALU_ROR1 : std_logic_vector(6 downto 0) := "0010001";
+constant ALU_RCL1 : std_logic_vector(6 downto 0) := "0010010";
+constant ALU_RCR1 : std_logic_vector(6 downto 0) := "0010011";
+constant ALU_SHL1 : std_logic_vector(6 downto 0) := "0010100";
+constant ALU_SHR1 : std_logic_vector(6 downto 0) := "0010101";
+constant ALU_SAR1 : std_logic_vector(6 downto 0) := "0010111";
+constant ALU_ROL : std_logic_vector(6 downto 0) := "0011000"; -- Count in CL
+constant ALU_ROR : std_logic_vector(6 downto 0) := "0011001";
+constant ALU_RCL : std_logic_vector(6 downto 0) := "0011010";
+constant ALU_RCR : std_logic_vector(6 downto 0) := "0011011";
+constant ALU_SHL : std_logic_vector(6 downto 0) := "0011100";
+constant ALU_SHR : std_logic_vector(6 downto 0) := "0011101";
+constant ALU_SAR : std_logic_vector(6 downto 0) := "0011111";
+
+-- CONST & modrm.reg(5 downto 3)/instr.ireg(5 downto 3)
+constant ALU_INC : std_logic_vector(6 downto 0) := "0100000"; -- Increment
+constant ALU_DEC : std_logic_vector(6 downto 0) := "0100001"; -- Decrement also used for LOOP/JCXZ
+
+constant ALU_CLRTIF : std_logic_vector(6 downto 0) := "0100010"; -- Clear TF/IF flag, used for INT
+constant ALU_CMPS : std_logic_vector(6 downto 0) := "0100111"; -- Compare String ALUREG-MDBUS
+constant ALU_SCAS : std_logic_vector(6 downto 0) := "0101111"; -- AX/AL-MDBUS, no SEXT
+
+-- CONST & instr.irg(3 downto 0)
+constant ALU_CMC : std_logic_vector(6 downto 0) := "0100101"; -- Complement Carry
+constant ALU_CLC : std_logic_vector(6 downto 0) := "0101000"; -- Clear Carry
+constant ALU_STC : std_logic_vector(6 downto 0) := "0101001"; -- Set Carry
+constant ALU_CLI : std_logic_vector(6 downto 0) := "0101010"; -- Clear interrupt
+constant ALU_STI : std_logic_vector(6 downto 0) := "0101011"; -- Set Interrupt
+constant ALU_CLD : std_logic_vector(6 downto 0) := "0101100"; -- Clear Direction
+constant ALU_STD : std_logic_vector(6 downto 0) := "0101101"; -- Set Direction
+
+-- CONST & modrm.reg(5 downto 3)
+constant ALU_TEST2 : std_logic_vector(6 downto 0) := "0110000"; -- F6/F7
+constant ALU_NOT : std_logic_vector(6 downto 0) := "0110010"; -- F6/F7
+constant ALU_NEG : std_logic_vector(6 downto 0) := "0110011"; -- F6/F7
+constant ALU_MUL : std_logic_vector(6 downto 0) := "0110100"; -- F6/F7
+constant ALU_IMUL : std_logic_vector(6 downto 0) := "0110101"; -- F6/F7
+constant ALU_DIV : std_logic_vector(6 downto 0) := "0110110"; -- F6/F7
+constant ALU_IDIV : std_logic_vector(6 downto 0) := "0110111"; -- F6/F7
+-- Second cycle write DX
+constant ALU_MUL2 : std_logic_vector(6 downto 0) := "0111100"; -- F6/F7
+constant ALU_IMUL2 : std_logic_vector(6 downto 0) := "0111101"; -- F6/F7
+constant ALU_DIV2 : std_logic_vector(6 downto 0) := "0111110"; -- F6/F7
+constant ALU_IDIV2 : std_logic_vector(6 downto 0) := "0111111"; -- F6/F7
+
+-- CONST & instr.ireg(3 downto 0)
+constant ALU_SEXT : std_logic_vector(6 downto 0) := "0111000"; -- Used for CBW
+constant ALU_SEXTW : std_logic_vector(6 downto 0) := "0111001"; -- Used for CWD
+
+-- CONSTANT & & instr.ireg(1) & instr.ireg(5 downto 3)
+constant ALU_AAM : std_logic_vector(6 downto 0) := "1000010";
+constant ALU_AAD : std_logic_vector(6 downto 0) := "1001010";
+constant ALU_DAA : std_logic_vector(6 downto 0) := "1001100";
+constant ALU_DAS : std_logic_vector(6 downto 0) := "1001101";
+constant ALU_AAA : std_logic_vector(6 downto 0) := "1001110";
+constant ALU_AAS : std_logic_vector(6 downto 0) := "1001111";
+
+constant ALU_ADD_SE : std_logic_vector(6 downto 0) := "1100000";
+constant ALU_OR_SE : std_logic_vector(6 downto 0) := "1100001";
+constant ALU_ADC_SE : std_logic_vector(6 downto 0) := "1100010";
+constant ALU_SBB_SE : std_logic_vector(6 downto 0) := "1100011";
+constant ALU_AND_SE : std_logic_vector(6 downto 0) := "1100100";
+constant ALU_SUB_SE : std_logic_vector(6 downto 0) := "1100101";
+constant ALU_XOR_SE : std_logic_vector(6 downto 0) := "1100110";
+constant ALU_CMP_SE : std_logic_vector(6 downto 0) := "1100111";
+
+END cpu86pack;
diff --git a/common/CPU/cpu86/d_table.vhd b/common/CPU/cpu86/d_table.vhd
new file mode 100644
index 00000000..8a7e7ea4
--- /dev/null
+++ b/common/CPU/cpu86/d_table.vhd
@@ -0,0 +1,720 @@
+-------------------------------------------------------------------------------
+-- CPU86 - VHDL CPU8088 IP core --
+-- Copyright (C) 2002-2008 HT-LAB --
+-- --
+-- Contact/bugs : http://www.ht-lab.com/misc/feedback.html --
+-- Web : http://www.ht-lab.com --
+-- --
+-- CPU86 is released as open-source under the GNU GPL license. This means --
+-- that designs based on CPU86 must be distributed in full source code --
+-- under the same license. Contact HT-Lab for commercial applications where --
+-- source-code distribution is not desirable. --
+-- --
+-------------------------------------------------------------------------------
+-- --
+-- This library is free software; you can redistribute it and/or --
+-- modify it under the terms of the GNU Lesser General Public --
+-- License as published by the Free Software Foundation; either --
+-- version 2.1 of the License, or (at your option) any later version. --
+-- --
+-- This library 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 --
+-- Lesser General Public License for more details. --
+-- --
+-- Full details of the license can be found in the file "copying.txt". --
+-- --
+-- You should have received a copy of the GNU Lesser General Public --
+-- License along with this library; if not, write to the Free Software --
+-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --
+-- --
+-------------------------------------------------------------------------------
+library IEEE;
+use IEEE.std_logic_1164.all;
+
+entity d_table is
+ port ( addr : in std_logic_vector(15 downto 0);
+ dout : out std_logic_vector(3 downto 0));
+end d_table;
+
+
+architecture rtl of d_table is
+begin
+ process(addr)
+ begin
+ case addr is
+ when "1110101100000000" => dout <= "0000";
+ when "1110100100000000" => dout <= "0000";
+ when "1111111111100000" => dout <= "0000";
+ when "1111111100100110" => dout <= "0000";
+ when "1111111100100000" => dout <= "0000";
+ when "1111111101100000" => dout <= "0000";
+ when "1111111110100000" => dout <= "0000";
+ when "1110101000000000" => dout <= "0110";
+ when "1111111100101110" => dout <= "0000";
+ when "1111111100101000" => dout <= "0000";
+ when "1111111101101000" => dout <= "0000";
+ when "1111111110101000" => dout <= "0000";
+ when "1110100000000000" => dout <= "0000";
+ when "1111111111010000" => dout <= "0000";
+ when "1111111100010110" => dout <= "0000";
+ when "1111111100010000" => dout <= "0000";
+ when "1111111101010000" => dout <= "0000";
+ when "1111111110010000" => dout <= "0000";
+ when "1001101000000000" => dout <= "0110";
+ when "1111111100011110" => dout <= "0000";
+ when "1111111100011000" => dout <= "0000";
+ when "1111111101011000" => dout <= "0000";
+ when "1111111110011000" => dout <= "0000";
+ when "1100001100000000" => dout <= "0000";
+ when "1100001000000000" => dout <= "0010";
+ when "1100101100000000" => dout <= "0000";
+ when "1100101000000000" => dout <= "0010";
+ when "0111010000000000" => dout <= "0000";
+ when "0111110000000000" => dout <= "0000";
+ when "0111111000000000" => dout <= "0000";
+ when "0111001000000000" => dout <= "0000";
+ when "0111011000000000" => dout <= "0000";
+ when "0111101000000000" => dout <= "0000";
+ when "0111000000000000" => dout <= "0000";
+ when "0111100000000000" => dout <= "0000";
+ when "0111010100000000" => dout <= "0000";
+ when "0111110100000000" => dout <= "0000";
+ when "0111111100000000" => dout <= "0000";
+ when "0111001100000000" => dout <= "0000";
+ when "0111011100000000" => dout <= "0000";
+ when "0111101100000000" => dout <= "0000";
+ when "0111000100000000" => dout <= "0000";
+ when "0111100100000000" => dout <= "0000";
+ when "1110001100000000" => dout <= "0000";
+ when "1110001000000000" => dout <= "0000";
+ when "1110000100000000" => dout <= "0000";
+ when "1110000000000000" => dout <= "0000";
+ when "1100110100000000" => dout <= "0000";
+ when "1100110000000000" => dout <= "0000";
+ when "1100111000000000" => dout <= "0000";
+ when "1100111100000000" => dout <= "0000";
+ when "1111100000000000" => dout <= "0000";
+ when "1111010100000000" => dout <= "0000";
+ when "1111100100000000" => dout <= "0000";
+ when "1111110000000000" => dout <= "0000";
+ when "1111110100000000" => dout <= "0000";
+ when "1111101000000000" => dout <= "0000";
+ when "1111101100000000" => dout <= "0000";
+ when "1111010000000000" => dout <= "0000";
+ when "1001101100000000" => dout <= "0000";
+ when "1111000000000000" => dout <= "0000";
+ when "1001000000000000" => dout <= "0000";
+ when "0010011000000000" => dout <= "0000";
+ when "0010111000000000" => dout <= "0000";
+ when "0011011000000000" => dout <= "0000";
+ when "0011111000000000" => dout <= "0000";
+ when "1000100011000000" => dout <= "0000";
+ when "1000100000000000" => dout <= "0000";
+ when "1000100001000000" => dout <= "0000";
+ when "1000100010000000" => dout <= "0000";
+ when "1000100000000110" => dout <= "0000";
+ when "1000100111000000" => dout <= "0000";
+ when "1000100100000000" => dout <= "0000";
+ when "1000100101000000" => dout <= "0000";
+ when "1000100110000000" => dout <= "0000";
+ when "1000100100000110" => dout <= "0000";
+ when "1000101011000000" => dout <= "0000";
+ when "1000101000000000" => dout <= "0000";
+ when "1000101001000000" => dout <= "0000";
+ when "1000101010000000" => dout <= "0000";
+ when "1000101000000110" => dout <= "0000";
+ when "1000101111000000" => dout <= "0000";
+ when "1000101100000000" => dout <= "0000";
+ when "1000101101000000" => dout <= "0000";
+ when "1000101110000000" => dout <= "0000";
+ when "1000101100000110" => dout <= "0000";
+ when "1100011000000000" => dout <= "0011";
+ when "1100011001000000" => dout <= "0101";
+ when "1100011010000000" => dout <= "0111";
+ when "1100011000000110" => dout <= "0111";
+ when "1100011100000000" => dout <= "0100";
+ when "1100011101000000" => dout <= "0110";
+ when "1100011110000000" => dout <= "1000";
+ when "1100011100000110" => dout <= "1000";
+ when "1011000000000000" => dout <= "0001";
+ when "1011000100000000" => dout <= "0001";
+ when "1011001000000000" => dout <= "0001";
+ when "1011001100000000" => dout <= "0001";
+ when "1011010000000000" => dout <= "0001";
+ when "1011010100000000" => dout <= "0001";
+ when "1011011000000000" => dout <= "0001";
+ when "1011011100000000" => dout <= "0001";
+ when "1011100000000000" => dout <= "0010";
+ when "1011100100000000" => dout <= "0010";
+ when "1011101000000000" => dout <= "0010";
+ when "1011101100000000" => dout <= "0010";
+ when "1011110000000000" => dout <= "0010";
+ when "1011110100000000" => dout <= "0010";
+ when "1011111000000000" => dout <= "0010";
+ when "1011111100000000" => dout <= "0010";
+ when "1010000000000000" => dout <= "0000";
+ when "1010000100000000" => dout <= "0000";
+ when "1010001000000000" => dout <= "0000";
+ when "1010001100000000" => dout <= "0000";
+ when "1000111011000000" => dout <= "0000";
+ when "1000111000000000" => dout <= "0000";
+ when "1000111001000000" => dout <= "0000";
+ when "1000111010000000" => dout <= "0000";
+ when "1000111000000110" => dout <= "0000";
+ when "1000110011000000" => dout <= "0000";
+ when "1000110000000000" => dout <= "0000";
+ when "1000110001000000" => dout <= "0000";
+ when "1000110010000000" => dout <= "0000";
+ when "1000110000000110" => dout <= "0000";
+ when "1111111100110000" => dout <= "0000";
+ when "1111111101110000" => dout <= "0000";
+ when "1111111110110000" => dout <= "0000";
+ when "1111111100110110" => dout <= "0000";
+ when "0101000000000000" => dout <= "0000";
+ when "0101000100000000" => dout <= "0000";
+ when "0101001000000000" => dout <= "0000";
+ when "0101001100000000" => dout <= "0000";
+ when "0101010000000000" => dout <= "0000";
+ when "0101010100000000" => dout <= "0000";
+ when "0101011000000000" => dout <= "0000";
+ when "0101011100000000" => dout <= "0000";
+ when "0000011000000000" => dout <= "0000";
+ when "0000111000000000" => dout <= "0000";
+ when "0001011000000000" => dout <= "0000";
+ when "0001111000000000" => dout <= "0000";
+ when "1000111100000000" => dout <= "0000";
+ when "1000111101000000" => dout <= "0000";
+ when "1000111110000000" => dout <= "0000";
+ when "1000111100000110" => dout <= "0000";
+ when "1000111111000000" => dout <= "0000";
+ when "0101100000000000" => dout <= "0000";
+ when "0101100100000000" => dout <= "0000";
+ when "0101101000000000" => dout <= "0000";
+ when "0101101100000000" => dout <= "0000";
+ when "0101110000000000" => dout <= "0000";
+ when "0101110100000000" => dout <= "0000";
+ when "0101111000000000" => dout <= "0000";
+ when "0101111100000000" => dout <= "0000";
+ when "0000011100000000" => dout <= "0000";
+ when "0001011100000000" => dout <= "0000";
+ when "0001111100000000" => dout <= "0000";
+ when "1000011011000000" => dout <= "0000";
+ when "1000011000000000" => dout <= "0000";
+ when "1000011001000000" => dout <= "0000";
+ when "1000011010000000" => dout <= "0000";
+ when "1000011000000110" => dout <= "0000";
+ when "1000011111000000" => dout <= "0000";
+ when "1000011100000000" => dout <= "0000";
+ when "1000011101000000" => dout <= "0000";
+ when "1000011110000000" => dout <= "0000";
+ when "1000011100000110" => dout <= "0000";
+ when "1001000100000000" => dout <= "0000";
+ when "1001001000000000" => dout <= "0000";
+ when "1001001100000000" => dout <= "0000";
+ when "1001010000000000" => dout <= "0000";
+ when "1001010100000000" => dout <= "0000";
+ when "1001011000000000" => dout <= "0000";
+ when "1001011100000000" => dout <= "0000";
+ when "1110010000000000" => dout <= "0000";
+ when "1110010100000000" => dout <= "0000";
+ when "1110110000000000" => dout <= "0000";
+ when "1110110100000000" => dout <= "0000";
+ when "1110011000000000" => dout <= "0000";
+ when "1110011100000000" => dout <= "0000";
+ when "1110111100000000" => dout <= "0000";
+ when "1110111000000000" => dout <= "0000";
+ when "1101011100000000" => dout <= "0000";
+ when "1001111100000000" => dout <= "0000";
+ when "1001111000000000" => dout <= "0000";
+ when "1001110000000000" => dout <= "0000";
+ when "1001110100000000" => dout <= "0000";
+ when "1000110100000110" => dout <= "0000";
+ when "1000110111000000" => dout <= "0000";
+ when "1000110100000000" => dout <= "0000";
+ when "1000110101000000" => dout <= "0000";
+ when "1000110110000000" => dout <= "0000";
+ when "1100010100000110" => dout <= "0000";
+ when "1100010100000000" => dout <= "0000";
+ when "1100010101000000" => dout <= "0000";
+ when "1100010110000000" => dout <= "0000";
+ when "1100010000000110" => dout <= "0000";
+ when "1100010000000000" => dout <= "0000";
+ when "1100010001000000" => dout <= "0000";
+ when "1100010010000000" => dout <= "0000";
+ when "0000000011000000" => dout <= "0000";
+ when "0000000000000110" => dout <= "0000";
+ when "0000000000000000" => dout <= "0000";
+ when "0000000001000000" => dout <= "0000";
+ when "0000000010000000" => dout <= "0000";
+ when "0000000111000000" => dout <= "0000";
+ when "0000000100000110" => dout <= "0000";
+ when "0000000100000000" => dout <= "0000";
+ when "0000000101000000" => dout <= "0000";
+ when "0000000110000000" => dout <= "0000";
+ when "0000001011000000" => dout <= "0000";
+ when "0000001000000110" => dout <= "0000";
+ when "0000001000000000" => dout <= "0000";
+ when "0000001001000000" => dout <= "0000";
+ when "0000001010000000" => dout <= "0000";
+ when "0000001111000000" => dout <= "0000";
+ when "0000001100000110" => dout <= "0000";
+ when "0000001100000000" => dout <= "0000";
+ when "0000001101000000" => dout <= "0000";
+ when "0000001110000000" => dout <= "0000";
+ when "1000000011000000" => dout <= "0011";
+ when "1000000000000110" => dout <= "0111";
+ when "1000000000000000" => dout <= "0011";
+ when "1000000001000000" => dout <= "0101";
+ when "1000000010000000" => dout <= "0111";
+ when "1000000111000000" => dout <= "0100";
+ when "1000000100000110" => dout <= "1000";
+ when "1000000100000000" => dout <= "0100";
+ when "1000000101000000" => dout <= "0110";
+ when "1000000110000000" => dout <= "1000";
+ when "1000001111000000" => dout <= "0011";
+ when "1000001100000110" => dout <= "0111";
+ when "1000001100000000" => dout <= "0011";
+ when "1000001101000000" => dout <= "0101";
+ when "1000001110000000" => dout <= "0111";
+ when "0000010000000000" => dout <= "0001";
+ when "0000010100000000" => dout <= "0010";
+ when "0001000011000000" => dout <= "0000";
+ when "0001000000000110" => dout <= "0000";
+ when "0001000000000000" => dout <= "0000";
+ when "0001000001000000" => dout <= "0000";
+ when "0001000010000000" => dout <= "0000";
+ when "0001000111000000" => dout <= "0000";
+ when "0001000100000110" => dout <= "0000";
+ when "0001000100000000" => dout <= "0000";
+ when "0001000101000000" => dout <= "0000";
+ when "0001000110000000" => dout <= "0000";
+ when "0001001011000000" => dout <= "0000";
+ when "0001001000000110" => dout <= "0000";
+ when "0001001000000000" => dout <= "0000";
+ when "0001001001000000" => dout <= "0000";
+ when "0001001010000000" => dout <= "0000";
+ when "0001001111000000" => dout <= "0000";
+ when "0001001100000110" => dout <= "0000";
+ when "0001001100000000" => dout <= "0000";
+ when "0001001101000000" => dout <= "0000";
+ when "0001001110000000" => dout <= "0000";
+ when "1000000011010000" => dout <= "0011";
+ when "1000000000010110" => dout <= "0111";
+ when "1000000000010000" => dout <= "0011";
+ when "1000000001010000" => dout <= "0101";
+ when "1000000010010000" => dout <= "0111";
+ when "1000000111010000" => dout <= "0100";
+ when "1000000100010110" => dout <= "1000";
+ when "1000000100010000" => dout <= "0100";
+ when "1000000101010000" => dout <= "0110";
+ when "1000000110010000" => dout <= "1000";
+ when "1000001111010000" => dout <= "0011";
+ when "1000001100010110" => dout <= "0111";
+ when "1000001100010000" => dout <= "0011";
+ when "1000001101010000" => dout <= "0101";
+ when "1000001110010000" => dout <= "0111";
+ when "0001010000000000" => dout <= "0001";
+ when "0001010100000000" => dout <= "0010";
+ when "0010100011000000" => dout <= "0000";
+ when "0010100000000110" => dout <= "0000";
+ when "0010100000000000" => dout <= "0000";
+ when "0010100001000000" => dout <= "0000";
+ when "0010100010000000" => dout <= "0000";
+ when "0010100111000000" => dout <= "0000";
+ when "0010100100000110" => dout <= "0000";
+ when "0010100100000000" => dout <= "0000";
+ when "0010100101000000" => dout <= "0000";
+ when "0010100110000000" => dout <= "0000";
+ when "0010101011000000" => dout <= "0000";
+ when "0010101000000110" => dout <= "0000";
+ when "0010101000000000" => dout <= "0000";
+ when "0010101001000000" => dout <= "0000";
+ when "0010101010000000" => dout <= "0000";
+ when "0010101111000000" => dout <= "0000";
+ when "0010101100000110" => dout <= "0000";
+ when "0010101100000000" => dout <= "0000";
+ when "0010101101000000" => dout <= "0000";
+ when "0010101110000000" => dout <= "0000";
+ when "1000000011101000" => dout <= "0011";
+ when "1000000000101110" => dout <= "0111";
+ when "1000000000101000" => dout <= "0011";
+ when "1000000001101000" => dout <= "0101";
+ when "1000000010101000" => dout <= "0111";
+ when "1000000111101000" => dout <= "0100";
+ when "1000000100101110" => dout <= "1000";
+ when "1000000100101000" => dout <= "0100";
+ when "1000000101101000" => dout <= "0110";
+ when "1000000110101000" => dout <= "1000";
+ when "1000001111101000" => dout <= "0011";
+ when "1000001100101110" => dout <= "0111";
+ when "1000001100101000" => dout <= "0011";
+ when "1000001101101000" => dout <= "0101";
+ when "1000001110101000" => dout <= "0111";
+ when "0010110000000000" => dout <= "0001";
+ when "0010110100000000" => dout <= "0010";
+ when "0001100011000000" => dout <= "0000";
+ when "0001100000000110" => dout <= "0000";
+ when "0001100000000000" => dout <= "0000";
+ when "0001100001000000" => dout <= "0000";
+ when "0001100010000000" => dout <= "0000";
+ when "0001100111000000" => dout <= "0000";
+ when "0001100100000110" => dout <= "0000";
+ when "0001100100000000" => dout <= "0000";
+ when "0001100101000000" => dout <= "0000";
+ when "0001100110000000" => dout <= "0000";
+ when "0001101011000000" => dout <= "0000";
+ when "0001101000000110" => dout <= "0000";
+ when "0001101000000000" => dout <= "0000";
+ when "0001101001000000" => dout <= "0000";
+ when "0001101010000000" => dout <= "0000";
+ when "0001101111000000" => dout <= "0000";
+ when "0001101100000110" => dout <= "0000";
+ when "0001101100000000" => dout <= "0000";
+ when "0001101101000000" => dout <= "0000";
+ when "0001101110000000" => dout <= "0000";
+ when "1000000011011000" => dout <= "0011";
+ when "1000000000011110" => dout <= "0111";
+ when "1000000000011000" => dout <= "0011";
+ when "1000000001011000" => dout <= "0101";
+ when "1000000010011000" => dout <= "0111";
+ when "1000000111011000" => dout <= "0100";
+ when "1000000100011110" => dout <= "1000";
+ when "1000000100011000" => dout <= "0100";
+ when "1000000101011000" => dout <= "0110";
+ when "1000000110011000" => dout <= "1000";
+ when "1000001111011000" => dout <= "0011";
+ when "1000001100011110" => dout <= "0111";
+ when "1000001100011000" => dout <= "0011";
+ when "1000001101011000" => dout <= "0101";
+ when "1000001110011000" => dout <= "0111";
+ when "0001110000000000" => dout <= "0001";
+ when "0001110100000000" => dout <= "0010";
+ when "1111111011000000" => dout <= "0000";
+ when "1111111000000110" => dout <= "0000";
+ when "1111111000000000" => dout <= "0000";
+ when "1111111001000000" => dout <= "0000";
+ when "1111111010000000" => dout <= "0000";
+ when "1111111100000110" => dout <= "0000";
+ when "1111111100000000" => dout <= "0000";
+ when "1111111101000000" => dout <= "0000";
+ when "1111111110000000" => dout <= "0000";
+ when "0100000000000000" => dout <= "0000";
+ when "0100000100000000" => dout <= "0000";
+ when "0100001000000000" => dout <= "0000";
+ when "0100001100000000" => dout <= "0000";
+ when "0100010000000000" => dout <= "0000";
+ when "0100010100000000" => dout <= "0000";
+ when "0100011000000000" => dout <= "0000";
+ when "0100011100000000" => dout <= "0000";
+ when "1111111011001000" => dout <= "0000";
+ when "1111111000001110" => dout <= "0000";
+ when "1111111000001000" => dout <= "0000";
+ when "1111111001001000" => dout <= "0000";
+ when "1111111010001000" => dout <= "0000";
+ when "1111111100001110" => dout <= "0000";
+ when "1111111100001000" => dout <= "0000";
+ when "1111111101001000" => dout <= "0000";
+ when "1111111110001000" => dout <= "0000";
+ when "0100100000000000" => dout <= "0000";
+ when "0100100100000000" => dout <= "0000";
+ when "0100101000000000" => dout <= "0000";
+ when "0100101100000000" => dout <= "0000";
+ when "0100110000000000" => dout <= "0000";
+ when "0100110100000000" => dout <= "0000";
+ when "0100111000000000" => dout <= "0000";
+ when "0100111100000000" => dout <= "0000";
+ when "0011101011000000" => dout <= "0000";
+ when "0011101000000110" => dout <= "0000";
+ when "0011101000000000" => dout <= "0000";
+ when "0011101001000000" => dout <= "0000";
+ when "0011101010000000" => dout <= "0000";
+ when "0011101111000000" => dout <= "0000";
+ when "0011101100000110" => dout <= "0000";
+ when "0011101100000000" => dout <= "0000";
+ when "0011101101000000" => dout <= "0000";
+ when "0011101110000000" => dout <= "0000";
+ when "0011100000000110" => dout <= "0000";
+ when "0011100000000000" => dout <= "0000";
+ when "0011100001000000" => dout <= "0000";
+ when "0011100010000000" => dout <= "0000";
+ when "0011100011000000" => dout <= "0000";
+ when "0011100100000110" => dout <= "0000";
+ when "0011100100000000" => dout <= "0000";
+ when "0011100101000000" => dout <= "0000";
+ when "0011100110000000" => dout <= "0000";
+ when "0011100111000000" => dout <= "0000";
+ when "1000000011111000" => dout <= "0011";
+ when "1000000000111110" => dout <= "0111";
+ when "1000000000111000" => dout <= "0011";
+ when "1000000001111000" => dout <= "0101";
+ when "1000000010111000" => dout <= "0111";
+ when "1000000111111000" => dout <= "0100";
+ when "1000000100111110" => dout <= "1000";
+ when "1000000100111000" => dout <= "0100";
+ when "1000000101111000" => dout <= "0110";
+ when "1000000110111000" => dout <= "1000";
+ when "1000001111111000" => dout <= "0011";
+ when "1000001100111110" => dout <= "0111";
+ when "1000001100111000" => dout <= "0011";
+ when "1000001101111000" => dout <= "0101";
+ when "1000001110111000" => dout <= "0111";
+ when "0011110000000000" => dout <= "0001";
+ when "0011110100000000" => dout <= "0010";
+ when "1111011011011000" => dout <= "0000";
+ when "1111011000011110" => dout <= "0000";
+ when "1111011000011000" => dout <= "0000";
+ when "1111011001011000" => dout <= "0000";
+ when "1111011010011000" => dout <= "0000";
+ when "1111011111011000" => dout <= "0000";
+ when "1111011100011110" => dout <= "0000";
+ when "1111011100011000" => dout <= "0000";
+ when "1111011101011000" => dout <= "0000";
+ when "1111011110011000" => dout <= "0000";
+ when "0011011100000000" => dout <= "0000";
+ when "0010011100000000" => dout <= "0000";
+ when "0011111100000000" => dout <= "0000";
+ when "0010111100000000" => dout <= "0000";
+ when "1111011011100000" => dout <= "0000";
+ when "1111011000100110" => dout <= "0000";
+ when "1111011000100000" => dout <= "0000";
+ when "1111011001100000" => dout <= "0000";
+ when "1111011010100000" => dout <= "0000";
+ when "1111011111100000" => dout <= "0000";
+ when "1111011100100110" => dout <= "0000";
+ when "1111011100100000" => dout <= "0000";
+ when "1111011101100000" => dout <= "0000";
+ when "1111011110100000" => dout <= "0000";
+ when "1111011011101000" => dout <= "0000";
+ when "1111011000101110" => dout <= "0000";
+ when "1111011000101000" => dout <= "0000";
+ when "1111011001101000" => dout <= "0000";
+ when "1111011010101000" => dout <= "0000";
+ when "1111011111101000" => dout <= "0000";
+ when "1111011100101110" => dout <= "0000";
+ when "1111011100101000" => dout <= "0000";
+ when "1111011101101000" => dout <= "0000";
+ when "1111011110101000" => dout <= "0000";
+ when "1111011011110000" => dout <= "0000";
+ when "1111011000110110" => dout <= "0000";
+ when "1111011000110000" => dout <= "0000";
+ when "1111011001110000" => dout <= "0000";
+ when "1111011010110000" => dout <= "0000";
+ when "1111011111110000" => dout <= "0000";
+ when "1111011100110110" => dout <= "0000";
+ when "1111011100110000" => dout <= "0000";
+ when "1111011101110000" => dout <= "0000";
+ when "1111011110110000" => dout <= "0000";
+ when "1111011011111000" => dout <= "0000";
+ when "1111011000111110" => dout <= "0000";
+ when "1111011000111000" => dout <= "0000";
+ when "1111011001111000" => dout <= "0000";
+ when "1111011010111000" => dout <= "0000";
+ when "1111011111111000" => dout <= "0000";
+ when "1111011100111110" => dout <= "0000";
+ when "1111011100111000" => dout <= "0000";
+ when "1111011101111000" => dout <= "0000";
+ when "1111011110111000" => dout <= "0000";
+ when "1101010000000000" => dout <= "0000";
+ when "1101010100000000" => dout <= "0000";
+ when "1001100000000000" => dout <= "0000";
+ when "1001100100000000" => dout <= "0000";
+ when "1101000011000000" => dout <= "0000";
+ when "1101000000000110" => dout <= "0000";
+ when "1101000000000000" => dout <= "0000";
+ when "1101000001000000" => dout <= "0000";
+ when "1101000010000000" => dout <= "0000";
+ when "1101000111000000" => dout <= "0000";
+ when "1101000100000110" => dout <= "0000";
+ when "1101000100000000" => dout <= "0000";
+ when "1101000101000000" => dout <= "0000";
+ when "1101000110000000" => dout <= "0000";
+ when "1101001011000000" => dout <= "0000";
+ when "1101001000000110" => dout <= "0000";
+ when "1101001000000000" => dout <= "0000";
+ when "1101001001000000" => dout <= "0000";
+ when "1101001010000000" => dout <= "0000";
+ when "1101001111000000" => dout <= "0000";
+ when "1101001100000110" => dout <= "0000";
+ when "1101001100000000" => dout <= "0000";
+ when "1101001101000000" => dout <= "0000";
+ when "1101001110000000" => dout <= "0000";
+ when "0010000011000000" => dout <= "0000";
+ when "0010000000000110" => dout <= "0000";
+ when "0010000000000000" => dout <= "0000";
+ when "0010000001000000" => dout <= "0000";
+ when "0010000010000000" => dout <= "0000";
+ when "0010000111000000" => dout <= "0000";
+ when "0010000100000110" => dout <= "0000";
+ when "0010000100000000" => dout <= "0000";
+ when "0010000101000000" => dout <= "0000";
+ when "0010000110000000" => dout <= "0000";
+ when "0010001011000000" => dout <= "0000";
+ when "0010001000000110" => dout <= "0000";
+ when "0010001000000000" => dout <= "0000";
+ when "0010001001000000" => dout <= "0000";
+ when "0010001010000000" => dout <= "0000";
+ when "0010001111000000" => dout <= "0000";
+ when "0010001100000110" => dout <= "0000";
+ when "0010001100000000" => dout <= "0000";
+ when "0010001101000000" => dout <= "0000";
+ when "0010001110000000" => dout <= "0000";
+ when "1000000011100000" => dout <= "0011";
+ when "1000000000100110" => dout <= "0111";
+ when "1000000000100000" => dout <= "0011";
+ when "1000000001100000" => dout <= "0101";
+ when "1000000010100000" => dout <= "0111";
+ when "1000000111100000" => dout <= "0100";
+ when "1000000100100110" => dout <= "1000";
+ when "1000000100100000" => dout <= "0100";
+ when "1000000101100000" => dout <= "0110";
+ when "1000000110100000" => dout <= "1000";
+ when "1000001111100000" => dout <= "0011";
+ when "1000001100100110" => dout <= "0111";
+ when "1000001100100000" => dout <= "0011";
+ when "1000001101100000" => dout <= "0101";
+ when "1000001110100000" => dout <= "0111";
+ when "0010010000000000" => dout <= "0001";
+ when "0010010100000000" => dout <= "0010";
+ when "0000100000000110" => dout <= "0000";
+ when "0000100000000000" => dout <= "0000";
+ when "0000100001000000" => dout <= "0000";
+ when "0000100010000000" => dout <= "0000";
+ when "0000100011000000" => dout <= "0000";
+ when "0000100100000110" => dout <= "0000";
+ when "0000100100000000" => dout <= "0000";
+ when "0000100101000000" => dout <= "0000";
+ when "0000100110000000" => dout <= "0000";
+ when "0000100111000000" => dout <= "0000";
+ when "0000101011000000" => dout <= "0000";
+ when "0000101000000110" => dout <= "0000";
+ when "0000101000000000" => dout <= "0000";
+ when "0000101001000000" => dout <= "0000";
+ when "0000101010000000" => dout <= "0000";
+ when "0000101111000000" => dout <= "0000";
+ when "0000101100000110" => dout <= "0000";
+ when "0000101100000000" => dout <= "0000";
+ when "0000101101000000" => dout <= "0000";
+ when "0000101110000000" => dout <= "0000";
+ when "1000000011001000" => dout <= "0011";
+ when "1000000000001110" => dout <= "0111";
+ when "1000000000001000" => dout <= "0011";
+ when "1000000001001000" => dout <= "0101";
+ when "1000000010001000" => dout <= "0111";
+ when "1000000111001000" => dout <= "0100";
+ when "1000000100001110" => dout <= "1000";
+ when "1000000100001000" => dout <= "0100";
+ when "1000000101001000" => dout <= "0110";
+ when "1000000110001000" => dout <= "1000";
+ when "1000001111001000" => dout <= "0011";
+ when "1000001100001110" => dout <= "0111";
+ when "1000001100001000" => dout <= "0011";
+ when "1000001101001000" => dout <= "0101";
+ when "1000001110001000" => dout <= "0111";
+ when "0000110000000000" => dout <= "0001";
+ when "0000110100000000" => dout <= "0010";
+ when "1000010000000110" => dout <= "0000";
+ when "1000010000000000" => dout <= "0000";
+ when "1000010001000000" => dout <= "0000";
+ when "1000010010000000" => dout <= "0000";
+ when "1000010100000110" => dout <= "0000";
+ when "1000010100000000" => dout <= "0000";
+ when "1000010101000000" => dout <= "0000";
+ when "1000010110000000" => dout <= "0000";
+ when "1000010011000000" => dout <= "0000";
+ when "1000010111000000" => dout <= "0000";
+ when "1111011011000000" => dout <= "0011";
+ when "1111011000000110" => dout <= "0111";
+ when "1111011000000000" => dout <= "0011";
+ when "1111011001000000" => dout <= "0101";
+ when "1111011010000000" => dout <= "0111";
+ when "1111011111000000" => dout <= "0100";
+ when "1111011100000110" => dout <= "1000";
+ when "1111011100000000" => dout <= "0100";
+ when "1111011101000000" => dout <= "0110";
+ when "1111011110000000" => dout <= "1000";
+ when "1010100000000000" => dout <= "0001";
+ when "1010100100000000" => dout <= "0010";
+ when "0011000000000110" => dout <= "0000";
+ when "0011000000000000" => dout <= "0000";
+ when "0011000001000000" => dout <= "0000";
+ when "0011000010000000" => dout <= "0000";
+ when "0011000011000000" => dout <= "0000";
+ when "0011000100000110" => dout <= "0000";
+ when "0011000100000000" => dout <= "0000";
+ when "0011000101000000" => dout <= "0000";
+ when "0011000110000000" => dout <= "0000";
+ when "0011000111000000" => dout <= "0000";
+ when "0011001011000000" => dout <= "0000";
+ when "0011001000000110" => dout <= "0000";
+ when "0011001000000000" => dout <= "0000";
+ when "0011001001000000" => dout <= "0000";
+ when "0011001010000000" => dout <= "0000";
+ when "0011001111000000" => dout <= "0000";
+ when "0011001100000110" => dout <= "0000";
+ when "0011001100000000" => dout <= "0000";
+ when "0011001101000000" => dout <= "0000";
+ when "0011001110000000" => dout <= "0000";
+ when "1000000011110000" => dout <= "0011";
+ when "1000000000110110" => dout <= "0111";
+ when "1000000000110000" => dout <= "0011";
+ when "1000000001110000" => dout <= "0101";
+ when "1000000010110000" => dout <= "0111";
+ when "1000000111110000" => dout <= "0100";
+ when "1000000100110110" => dout <= "1000";
+ when "1000000100110000" => dout <= "0100";
+ when "1000000101110000" => dout <= "0110";
+ when "1000000110110000" => dout <= "1000";
+ when "1000001111110000" => dout <= "0011";
+ when "1000001100110110" => dout <= "0111";
+ when "1000001100110000" => dout <= "0011";
+ when "1000001101110000" => dout <= "0101";
+ when "1000001110110000" => dout <= "0111";
+ when "0011010000000000" => dout <= "0001";
+ when "0011010100000000" => dout <= "0010";
+ when "1111011011010000" => dout <= "0000";
+ when "1111011000010110" => dout <= "0000";
+ when "1111011000010000" => dout <= "0000";
+ when "1111011001010000" => dout <= "0000";
+ when "1111011010010000" => dout <= "0000";
+ when "1111011111010000" => dout <= "0000";
+ when "1111011100010110" => dout <= "0000";
+ when "1111011100010000" => dout <= "0000";
+ when "1111011101010000" => dout <= "0000";
+ when "1111011110010000" => dout <= "0000";
+ when "1010010000000000" => dout <= "0000";
+ when "1010010100000000" => dout <= "0000";
+ when "1010011000000000" => dout <= "0000";
+ when "1010011100000000" => dout <= "0000";
+ when "1010111000000000" => dout <= "0000";
+ when "1010111100000000" => dout <= "0000";
+ when "1010110000000000" => dout <= "0000";
+ when "1010110100000000" => dout <= "0000";
+ when "1010101000000000" => dout <= "0000";
+ when "1010101100000000" => dout <= "0000";
+ when "1111001000000000" => dout <= "0000";
+ when "1111001100000000" => dout <= "0000";
+ when "0110000000000000" => dout <= "0000";
+ when "0110000100000000" => dout <= "0000";
+ when "1100100000000000" => dout <= "0000";
+ when "1100100100000000" => dout <= "0000";
+ when "0110001000000000" => dout <= "0000";
+ when "0110110000000000" => dout <= "0000";
+ when "0110110100000000" => dout <= "0000";
+ when "0110111000000000" => dout <= "0000";
+ when "0110111100000000" => dout <= "0000";
+ when "0000111100000000" => dout <= "0000";
+ when "0110001100000000" => dout <= "0000";
+ when "0110010000000000" => dout <= "0000";
+ when "0110010100000000" => dout <= "0000";
+ when "0110011000000000" => dout <= "0000";
+ when "0110011100000000" => dout <= "0000";
+ when "1000001000000000" => dout <= "0000";
+ when "1101011000000000" => dout <= "0000";
+ when "1111000100000000" => dout <= "0000";
+ when "1100000000000000" => dout <= "0000";
+ when "1100000100000000" => dout <= "0000";
+ when others => dout <= "----";
+ end case;
+ end process;
+end rtl;
\ No newline at end of file
diff --git a/common/CPU/cpu86/datapath_struct.vhd b/common/CPU/cpu86/datapath_struct.vhd
new file mode 100644
index 00000000..a2b8b0f6
--- /dev/null
+++ b/common/CPU/cpu86/datapath_struct.vhd
@@ -0,0 +1,476 @@
+-------------------------------------------------------------------------------
+-- CPU86 - VHDL CPU8088 IP core --
+-- Copyright (C) 2002-2008 HT-LAB --
+-- --
+-- Contact/bugs : http://www.ht-lab.com/misc/feedback.html --
+-- Web : http://www.ht-lab.com --
+-- --
+-- CPU86 is released as open-source under the GNU GPL license. This means --
+-- that designs based on CPU86 must be distributed in full source code --
+-- under the same license. Contact HT-Lab for commercial applications where --
+-- source-code distribution is not desirable. --
+-- --
+-------------------------------------------------------------------------------
+-- --
+-- This library is free software; you can redistribute it and/or --
+-- modify it under the terms of the GNU Lesser General Public --
+-- License as published by the Free Software Foundation; either --
+-- version 2.1 of the License, or (at your option) any later version. --
+-- --
+-- This library 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 --
+-- Lesser General Public License for more details. --
+-- --
+-- Full details of the license can be found in the file "copying.txt". --
+-- --
+-- You should have received a copy of the GNU Lesser General Public --
+-- License along with this library; if not, write to the Free Software --
+-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --
+-- --
+-------------------------------------------------------------------------------
+
+LIBRARY ieee;
+USE ieee.std_logic_1164.ALL;
+USE ieee.std_logic_arith.ALL;
+USE ieee.std_logic_unsigned.ALL;
+
+USE work.cpu86pack.ALL;
+
+ENTITY datapath IS
+ PORT(
+ clk : IN std_logic;
+ clrop : IN std_logic;
+ instr : IN instruction_type;
+ iomem : IN std_logic;
+ mdbus_in : IN std_logic_vector (15 DOWNTO 0);
+ path : IN path_in_type;
+ reset : IN std_logic;
+ wrpath : IN write_in_type;
+ dbusdp_out : OUT std_logic_vector (15 DOWNTO 0);
+ eabus : OUT std_logic_vector (15 DOWNTO 0);
+ segbus : OUT std_logic_vector (15 DOWNTO 0);
+ status : OUT status_out_type
+ );
+END datapath ;
+
+
+ARCHITECTURE struct OF datapath IS
+
+ -- Internal signal declarations
+ SIGNAL alu_inbusa : std_logic_vector(15 DOWNTO 0);
+ SIGNAL alu_inbusb : std_logic_vector(15 DOWNTO 0);
+ SIGNAL alubus : std_logic_vector(15 DOWNTO 0);
+ SIGNAL aluopr : std_logic_vector(6 DOWNTO 0);
+ SIGNAL ax_s : std_logic_vector(15 DOWNTO 0);
+ SIGNAL bp_s : std_logic_vector(15 DOWNTO 0);
+ SIGNAL bx_s : std_logic_vector(15 DOWNTO 0);
+ SIGNAL ccbus : std_logic_vector(15 DOWNTO 0);
+ SIGNAL cs_s : std_logic_vector(15 DOWNTO 0);
+ SIGNAL cx_s : std_logic_vector(15 DOWNTO 0);
+ SIGNAL data_in : std_logic_vector(15 DOWNTO 0);
+ SIGNAL di_s : std_logic_vector(15 DOWNTO 0);
+ SIGNAL dibus : std_logic_vector(15 DOWNTO 0);
+ SIGNAL dimux : std_logic_vector(2 DOWNTO 0);
+ SIGNAL disp : std_logic_vector(15 DOWNTO 0);
+ SIGNAL dispmux : std_logic_vector(2 DOWNTO 0);
+ SIGNAL div_err : std_logic;
+ SIGNAL domux : std_logic_vector(1 DOWNTO 0);
+ SIGNAL ds_s : std_logic_vector(15 DOWNTO 0);
+ SIGNAL dx_s : std_logic_vector(15 DOWNTO 0);
+ SIGNAL ea : std_logic_vector(15 DOWNTO 0);
+ SIGNAL eamux : std_logic_vector(3 DOWNTO 0);
+ SIGNAL es_s : std_logic_vector(15 DOWNTO 0);
+ SIGNAL ipbus : std_logic_vector(15 DOWNTO 0);
+ SIGNAL ipreg : std_logic_vector(15 DOWNTO 0);
+ SIGNAL nbreq : std_logic_vector(2 DOWNTO 0);
+ SIGNAL opmux : std_logic_vector(1 DOWNTO 0);
+ SIGNAL rm : std_logic_vector(2 DOWNTO 0);
+ SIGNAL sdbus : std_logic_vector(15 DOWNTO 0);
+ SIGNAL segop : std_logic_vector(2 DOWNTO 0);
+ SIGNAL selalua : std_logic_vector(3 DOWNTO 0);
+ SIGNAL selalub : std_logic_vector(3 DOWNTO 0);
+ SIGNAL seldreg : std_logic_vector(2 DOWNTO 0);
+ SIGNAL selds : std_logic;
+ SIGNAL selsreg : std_logic_vector(1 DOWNTO 0);
+ SIGNAL si_s : std_logic_vector(15 DOWNTO 0);
+ SIGNAL sibus : std_logic_vector(15 DOWNTO 0);
+ SIGNAL simux : std_logic_vector(1 DOWNTO 0);
+ SIGNAL sp_s : std_logic_vector(15 DOWNTO 0);
+ SIGNAL ss_s : std_logic_vector(15 DOWNTO 0);
+ SIGNAL w : std_logic;
+ SIGNAL wralu : std_logic;
+ SIGNAL wrcc : std_logic;
+ SIGNAL wrd : std_logic;
+ SIGNAL wrip : std_logic;
+ SIGNAL wrop : std_logic;
+ SIGNAL wrs : std_logic;
+ SIGNAL wrtemp : std_logic;
+ SIGNAL xmod : std_logic_vector(1 DOWNTO 0);
+
+ -- Implicit buffer signal declarations
+ SIGNAL eabus_internal : std_logic_vector (15 DOWNTO 0);
+
+
+ signal domux_s : std_logic_vector(2 downto 0);
+ signal opreg_s : std_logic_vector(1 downto 0); -- Override Segment Register
+ signal opflag_s : std_logic; -- set if segment override in progress
+ signal eam_s : std_logic_vector(15 downto 0);
+ signal segsel_s : std_logic_vector(5 downto 0); -- segbus select
+ signal int0cs_s : std_logic;
+
+ -- Component Declarations
+ COMPONENT ALU
+ PORT (
+ alu_inbusa : IN std_logic_vector (15 DOWNTO 0);
+ alu_inbusb : IN std_logic_vector (15 DOWNTO 0);
+ aluopr : IN std_logic_vector (6 DOWNTO 0);
+ ax_s : IN std_logic_vector (15 DOWNTO 0);
+ clk : IN std_logic ;
+ cx_s : IN std_logic_vector (15 DOWNTO 0);
+ dx_s : IN std_logic_vector (15 DOWNTO 0);
+ reset : IN std_logic ;
+ w : IN std_logic ;
+ wralu : IN std_logic ;
+ wrcc : IN std_logic ;
+ wrtemp : IN std_logic ;
+ alubus : OUT std_logic_vector (15 DOWNTO 0);
+ ccbus : OUT std_logic_vector (15 DOWNTO 0);
+ div_err : OUT std_logic
+ );
+ END COMPONENT;
+ COMPONENT dataregfile
+ PORT (
+ dibus : IN std_logic_vector (15 DOWNTO 0);
+ selalua : IN std_logic_vector (3 DOWNTO 0);
+ selalub : IN std_logic_vector (3 DOWNTO 0);
+ seldreg : IN std_logic_vector (2 DOWNTO 0);
+ w : IN std_logic ;
+ wrd : IN std_logic ;
+ alu_inbusa : OUT std_logic_vector (15 DOWNTO 0);
+ alu_inbusb : OUT std_logic_vector (15 DOWNTO 0);
+ bp_s : OUT std_logic_vector (15 DOWNTO 0);
+ bx_s : OUT std_logic_vector (15 DOWNTO 0);
+ di_s : OUT std_logic_vector (15 DOWNTO 0);
+ si_s : OUT std_logic_vector (15 DOWNTO 0);
+ reset : IN std_logic ;
+ clk : IN std_logic ;
+ data_in : IN std_logic_vector (15 DOWNTO 0);
+ mdbus_in : IN std_logic_vector (15 DOWNTO 0);
+ sp_s : OUT std_logic_vector (15 DOWNTO 0);
+ ax_s : OUT std_logic_vector (15 DOWNTO 0);
+ cx_s : OUT std_logic_vector (15 DOWNTO 0);
+ dx_s : OUT std_logic_vector (15 DOWNTO 0)
+ );
+ END COMPONENT;
+ COMPONENT ipregister
+ PORT (
+ clk : IN std_logic ;
+ ipbus : IN std_logic_vector (15 DOWNTO 0);
+ reset : IN std_logic ;
+ wrip : IN std_logic ;
+ ipreg : OUT std_logic_vector (15 DOWNTO 0)
+ );
+ END COMPONENT;
+ COMPONENT segregfile
+ PORT (
+ selsreg : IN std_logic_vector (1 DOWNTO 0);
+ sibus : IN std_logic_vector (15 DOWNTO 0);
+ wrs : IN std_logic ;
+ reset : IN std_logic ;
+ clk : IN std_logic ;
+ sdbus : OUT std_logic_vector (15 DOWNTO 0);
+ dimux : IN std_logic_vector (2 DOWNTO 0);
+ es_s : OUT std_logic_vector (15 DOWNTO 0);
+ cs_s : OUT std_logic_vector (15 DOWNTO 0);
+ ss_s : OUT std_logic_vector (15 DOWNTO 0);
+ ds_s : OUT std_logic_vector (15 DOWNTO 0)
+ );
+ END COMPONENT;
+
+
+BEGIN
+
+ dimux <= path.datareg_input(6 downto 4); -- Data Register Input Path
+ w <= path.datareg_input(3);
+ seldreg <= path.datareg_input(2 downto 0);
+
+ selalua <= path.alu_operation(14 downto 11); -- ALU Path
+ selalub <= path.alu_operation(10 downto 7);
+ aluopr <= path.alu_operation(6 downto 0);
+
+ domux <= path.dbus_output; -- Data Output Path
+
+ simux <= path.segreg_input(3 downto 2); -- Segment Register Input Path
+ selsreg <= path.segreg_input(1 downto 0);
+
+ dispmux <= path.ea_output(9 downto 7); -- select ipreg addition
+ eamux <= path.ea_output(6 downto 3); -- 4 bits
+ segop <= path.ea_output(2 downto 0); -- segop(2)=override flag
+
+ wrd <= wrpath.wrd;
+ wralu <= wrpath.wralu;
+ wrcc <= wrpath.wrcc;
+ wrs <= wrpath.wrs;
+ wrip <= wrpath.wrip;
+ wrop <= wrpath.wrop;
+ wrtemp<= wrpath.wrtemp;
+
+ status.ax <= ax_s;
+ status.cx_one <= '1' when (cx_s=X"0001") else '0';
+ status.cx_zero <= '1' when (cx_s=X"0000") else '0';
+ status.cl <= cx_s(7 downto 0); -- used for shift/rotate
+ status.flag <= ccbus;
+ status.div_err <= div_err; -- Divider overflow
+
+ disp <= instr.disp;
+ data_in <= instr.data;
+ nbreq <= instr.nb;
+ rm <= instr.rm;
+ xmod <= instr.xmod;
+
+ ----------------------------------------------------------------------------
+ -- Determine effective address
+ ----------------------------------------------------------------------------
+ process (rm, ax_s,bx_s,cx_s,dx_s,bp_s,sp_s,si_s,di_s,disp,xmod)
+ begin
+ case rm is
+ when "000" => if xmod="11" then eam_s <= ax_s;
+ else eam_s <= bx_s + si_s + disp;
+ end if;
+ selds<='1';
+ when "001" => if xmod="11" then eam_s <= cx_s;
+ else eam_s <= bx_s + di_s + disp;
+ end if;
+ selds<='1';
+ when "010" => if xmod="11" then eam_s <= dx_s;
+ else eam_s <= bp_s + si_s + disp;
+ end if;
+ selds<='0';
+ when "011" => if xmod="11" then eam_s <= bx_s;
+ else eam_s <= bp_s + di_s + disp;
+ end if;
+ selds<='0';
+ when "100" => if xmod="11" then eam_s <= sp_s;
+ else eam_s <= si_s + disp;
+ end if;
+ selds<='1';
+ when "101" => if xmod="11" then eam_s <= bp_s;
+ else eam_s <= di_s + disp;
+ end if;
+ selds<='1';
+ when "110" => if xmod="00" then
+ eam_s <= disp;
+ selds <='1';
+ elsif xmod="11" then
+ eam_s <= si_s;
+ selds <='1';
+ else
+ eam_s <= bp_s + disp;
+ selds <='0'; -- Use SS
+ end if;
+
+ when others=> if xmod="11" then eam_s <= di_s;
+ else eam_s <= bx_s + disp;
+ end if;
+ selds<='1';
+ end case;
+ end process;
+
+ ea<=eam_s;
+
+ process(data_in,eabus_internal,alubus,mdbus_in,simux)
+ begin
+ case simux is
+ when "00" => sibus <= data_in;
+ when "01" => sibus <= eabus_internal;
+ when "10" => sibus <= alubus;
+ when others => sibus <= mdbus_in;
+ end case;
+ end process;
+
+ process(dispmux,nbreq,disp,mdbus_in,ipreg,eabus_internal)
+ begin
+ case dispmux is
+ when "000" => ipbus <= ("0000000000000"&nbreq) + ipreg;
+ when "001" => ipbus <= (("0000000000000"&nbreq)+disp) + ipreg;
+ when "011" => ipbus <= disp; -- disp contains new IP value
+ when "100" => ipbus <= eabus_internal; -- ipbus=effective address
+ when "101" => ipbus <= ipreg; -- bodge to get ipreg onto ipbus
+ when others => ipbus <= mdbus_in;
+ end case;
+ end process;
+
+ domux_s <= eabus_internal(0) & domux;
+
+ process(domux_s, alubus,ccbus, dibus, ipbus)
+ begin
+ case domux_s is
+ when "000" => dbusdp_out <= alubus; -- Even
+ when "001" => dbusdp_out <= ccbus;
+ when "010" => dbusdp_out <= dibus;
+ when "011" => dbusdp_out <= ipbus; -- CALL Instruction
+ when "100" => dbusdp_out <= alubus(7 downto 0)& alubus(15 downto 8); -- Odd
+ when "101" => dbusdp_out <= ccbus(7 downto 0) & ccbus(15 downto 8);
+ when "110" => dbusdp_out <= dibus(7 downto 0) & dibus(15 downto 8);
+ when others => dbusdp_out <= ipbus(7 downto 0) & ipbus(15 downto 8);
+ end case;
+ end process;
+
+ -- Write Prefix Register
+ process(clk,reset)
+ begin
+ if (reset = '1') then
+ opreg_s <= "01"; -- Default CS Register
+ opflag_s<= '0'; -- Clear Override Prefix Flag
+ elsif rising_edge(clk) then
+ if wrop='1' then
+ opreg_s <= segop(1 downto 0); -- Set override register
+ opflag_s<= '1'; -- segop(2); -- Set flag
+ elsif clrop='1' then
+ opreg_s <= "11"; -- Default Data Segment Register
+ opflag_s<= '0';
+ end if;
+ end if;
+ end process;
+
+ process (opflag_s,opreg_s,selds,eamux,segop)
+ begin
+ if opflag_s='1' and segop(2)='0' then -- Prefix register set and disable override not set?
+ opmux <= opreg_s(1 downto 0); -- Set mux to override prefix reg
+ elsif eamux(3)='1' then
+ opmux <= eamux(1 downto 0);
+ elsif eamux(0)='0' then
+ opmux <= "01"; -- Select CS for IP
+ else
+ opmux <= '1'&selds; -- DS if selds=1 else SS
+ end if;
+ end process;
+
+ process(dimux, data_in,alubus,mdbus_in,sdbus,eabus_internal)
+ begin
+ case dimux is
+ when "000" => dibus <= data_in; -- Operand
+ when "001" => dibus <= eabus_internal;-- Offset
+ when "010" => dibus <= alubus; -- Output ALU
+ when "011" => dibus <= mdbus_in; -- Memory Bus
+ when others => dibus <= sdbus; -- Segment registers
+ end case;
+ end process;
+
+ int0cs_s <= '1' when eamux(3 downto 1)="011" else '0';
+ segsel_s <= iomem & int0cs_s & eamux(2 downto 1) & opmux; -- 5 bits
+
+ process(segsel_s,es_s,cs_s,ss_s,ds_s) -- Segment Output Mux
+ begin
+ case segsel_s is
+ when "000000" => segbus <= es_s; -- 00**, opmux select register
+ when "000001" => segbus <= cs_s;
+ when "000010" => segbus <= ss_s;
+ when "000011" => segbus <= ds_s;
+ when "000100" => segbus <= es_s; -- 01**, opmux select register
+ when "000101" => segbus <= cs_s;
+ when "000110" => segbus <= ss_s;
+ when "000111" => segbus <= ds_s;
+ when "001000" => segbus <= ss_s; -- 10**=SS, used for PUSH& POP
+ when "001001" => segbus <= ss_s;
+ when "001010" => segbus <= ss_s;
+ when "001011" => segbus <= ss_s;
+ when "001100" => segbus <= es_s; -- 01**, opmux select register
+ when "001101" => segbus <= cs_s;
+ when "001110" => segbus <= ss_s;
+ when "001111" => segbus <= ds_s;
+ when others => segbus <= ZEROVECTOR_C(15 downto 0);-- IN/OUT instruction 0x0000:PORT/DX
+ end case;
+ end process;
+
+ -- Offset Mux
+ -- Note ea*4 required if non-32 bits memory access is used(?)
+ -- Currently CS &IP are read in one go (fits 32 bits)
+ process(ipreg,ea,sp_s,dx_s,eamux,si_s,di_s,bx_s,ax_s)
+ begin
+ case eamux is
+ when "0000" => eabus_internal <= ipreg;--ipbus;--ipreg;
+ when "0001" => eabus_internal <= ea;
+ when "0010" => eabus_internal <= dx_s;
+ when "0011" => eabus_internal <= ea + "10"; -- for call mem32/int
+ when "0100" => eabus_internal <= sp_s; -- 10* select SP_S
+ when "0101" => eabus_internal <= sp_s;
+ when "0110" => eabus_internal <= ea(13 downto 0)&"00";
+ when "0111" => eabus_internal <=(ea(13 downto 0)&"00") + "10"; -- for int
+ when "1000" => eabus_internal <= di_s; -- Select ES:DI
+ when "1011" => eabus_internal <= si_s; -- Select DS:SI
+ when "1001" => eabus_internal <= ea; -- added for JMP SI instruction
+ when "1111" => eabus_internal <= bx_s + (X"00"&ax_s(7 downto 0)); -- XLAT instruction
+ when others => eabus_internal <= DONTCARE(15 downto 0);
+ end case;
+ end process;
+
+ -- Instance port mappings.
+ I6 : ALU
+ PORT MAP (
+ alu_inbusa => alu_inbusa,
+ alu_inbusb => alu_inbusb,
+ aluopr => aluopr,
+ ax_s => ax_s,
+ clk => clk,
+ cx_s => cx_s,
+ dx_s => dx_s,
+ reset => reset,
+ w => w,
+ wralu => wralu,
+ wrcc => wrcc,
+ wrtemp => wrtemp,
+ alubus => alubus,
+ ccbus => ccbus,
+ div_err => div_err
+ );
+ I0 : dataregfile
+ PORT MAP (
+ dibus => dibus,
+ selalua => selalua,
+ selalub => selalub,
+ seldreg => seldreg,
+ w => w,
+ wrd => wrd,
+ alu_inbusa => alu_inbusa,
+ alu_inbusb => alu_inbusb,
+ bp_s => bp_s,
+ bx_s => bx_s,
+ di_s => di_s,
+ si_s => si_s,
+ reset => reset,
+ clk => clk,
+ data_in => data_in,
+ mdbus_in => mdbus_in,
+ sp_s => sp_s,
+ ax_s => ax_s,
+ cx_s => cx_s,
+ dx_s => dx_s
+ );
+ I9 : ipregister
+ PORT MAP (
+ clk => clk,
+ ipbus => ipbus,
+ reset => reset,
+ wrip => wrip,
+ ipreg => ipreg
+ );
+ I15 : segregfile
+ PORT MAP (
+ selsreg => selsreg,
+ sibus => sibus,
+ wrs => wrs,
+ reset => reset,
+ clk => clk,
+ sdbus => sdbus,
+ dimux => dimux,
+ es_s => es_s,
+ cs_s => cs_s,
+ ss_s => ss_s,
+ ds_s => ds_s
+ );
+
+ eabus <= eabus_internal;
+
+END struct;
diff --git a/common/CPU/cpu86/dataregfile_rtl.vhd b/common/CPU/cpu86/dataregfile_rtl.vhd
new file mode 100644
index 00000000..2849c180
--- /dev/null
+++ b/common/CPU/cpu86/dataregfile_rtl.vhd
@@ -0,0 +1,198 @@
+-------------------------------------------------------------------------------
+-- CPU86 - VHDL CPU8088 IP core --
+-- Copyright (C) 2002-2008 HT-LAB --
+-- --
+-- Contact/bugs : http://www.ht-lab.com/misc/feedback.html --
+-- Web : http://www.ht-lab.com --
+-- --
+-- CPU86 is released as open-source under the GNU GPL license. This means --
+-- that designs based on CPU86 must be distributed in full source code --
+-- under the same license. Contact HT-Lab for commercial applications where --
+-- source-code distribution is not desirable. --
+-- --
+-------------------------------------------------------------------------------
+-- --
+-- This library is free software; you can redistribute it and/or --
+-- modify it under the terms of the GNU Lesser General Public --
+-- License as published by the Free Software Foundation; either --
+-- version 2.1 of the License, or (at your option) any later version. --
+-- --
+-- This library 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 --
+-- Lesser General Public License for more details. --
+-- --
+-- Full details of the license can be found in the file "copying.txt". --
+-- --
+-- You should have received a copy of the GNU Lesser General Public --
+-- License along with this library; if not, write to the Free Software --
+-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --
+-- --
+-------------------------------------------------------------------------------
+LIBRARY ieee;
+USE ieee.std_logic_1164.ALL;
+USE ieee.std_logic_unsigned.ALL;
+USE ieee.std_logic_arith.ALL;
+
+USE work.cpu86pack.ALL;
+
+ENTITY dataregfile IS
+ PORT(
+ dibus : IN std_logic_vector (15 DOWNTO 0);
+ selalua : IN std_logic_vector (3 DOWNTO 0);
+ selalub : IN std_logic_vector (3 DOWNTO 0);
+ seldreg : IN std_logic_vector (2 DOWNTO 0);
+ w : IN std_logic;
+ wrd : IN std_logic;
+ alu_inbusa : OUT std_logic_vector (15 DOWNTO 0);
+ alu_inbusb : OUT std_logic_vector (15 DOWNTO 0);
+ bp_s : OUT std_logic_vector (15 DOWNTO 0);
+ bx_s : OUT std_logic_vector (15 DOWNTO 0);
+ di_s : OUT std_logic_vector (15 DOWNTO 0);
+ si_s : OUT std_logic_vector (15 DOWNTO 0);
+ reset : IN std_logic;
+ clk : IN std_logic;
+ data_in : IN std_logic_vector (15 DOWNTO 0);
+ mdbus_in : IN std_logic_vector (15 DOWNTO 0);
+ sp_s : OUT std_logic_vector (15 DOWNTO 0);
+ ax_s : OUT std_logic_vector (15 DOWNTO 0);
+ cx_s : OUT std_logic_vector (15 DOWNTO 0);
+ dx_s : OUT std_logic_vector (15 DOWNTO 0)
+ );
+END dataregfile ;
+
+architecture rtl of dataregfile is
+
+signal axreg_s : std_logic_vector(15 downto 0);
+signal cxreg_s : std_logic_vector(15 downto 0);
+signal dxreg_s : std_logic_vector(15 downto 0);
+signal bxreg_s : std_logic_vector(15 downto 0);
+signal spreg_s : std_logic_vector(15 downto 0);
+signal bpreg_s : std_logic_vector(15 downto 0);
+signal sireg_s : std_logic_vector(15 downto 0);
+signal direg_s : std_logic_vector(15 downto 0);
+
+signal seldreg_s : std_logic_vector(3 downto 0); -- w & seldreg
+signal selalua_s : std_logic_vector(4 downto 0); -- w & dibus & selalua
+signal selalub_s : std_logic_vector(4 downto 0); -- w & dibus & selalub
+
+signal alu_inbusb_s: std_logic_vector (15 downto 0);
+
+begin
+
+----------------------------------------------------------------------------
+-- 8 registers of 16 bits each
+----------------------------------------------------------------------------
+ seldreg_s <= w & seldreg;
+
+ process (clk,reset)
+ begin
+ if reset='1' then
+ axreg_s <= (others => '0');
+ cxreg_s <= (others => '0');
+ dxreg_s <= (others => '0');
+ bxreg_s <= (others => '0');
+ spreg_s <= (others => '0');
+ bpreg_s <= (others => '0');
+ sireg_s <= (others => '0');
+ direg_s <= (others => '0');
+ elsif rising_edge(clk) then
+ if (wrd='1') then
+ case seldreg_s is
+ when "0000" => axreg_s(7 downto 0) <= dibus(7 downto 0); -- w=0 8 bits write
+ when "0001" => cxreg_s(7 downto 0) <= dibus(7 downto 0);
+ when "0010" => dxreg_s(7 downto 0) <= dibus(7 downto 0);
+ when "0011" => bxreg_s(7 downto 0) <= dibus(7 downto 0);
+ when "0100" => axreg_s(15 downto 8) <= dibus(7 downto 0);
+ when "0101" => cxreg_s(15 downto 8) <= dibus(7 downto 0);
+ when "0110" => dxreg_s(15 downto 8) <= dibus(7 downto 0);
+ when "0111" => bxreg_s(15 downto 8) <= dibus(7 downto 0);
+
+ when "1000" => axreg_s <= dibus; -- w=1 16 bits write
+ when "1001" => cxreg_s <= dibus;
+ when "1010" => dxreg_s <= dibus;
+ when "1011" => bxreg_s <= dibus;
+ when "1100" => spreg_s <= dibus;
+ when "1101" => bpreg_s <= dibus;
+ when "1110" => sireg_s <= dibus;
+ when others => direg_s <= dibus;
+ end case;
+ end if;
+ end if;
+ end process;
+
+----------------------------------------------------------------------------
+-- Output Port A
+----------------------------------------------------------------------------
+ selalua_s <= w & selalua;
+
+ process (selalua_s,axreg_s,cxreg_s,dxreg_s,bxreg_s,spreg_s,bpreg_s,sireg_s,direg_s,mdbus_in)
+ begin
+ case selalua_s is
+ when "00000" => alu_inbusa <= X"00" & axreg_s(7 downto 0); -- Select 8 bits MSB=0
+ when "00001" => alu_inbusa <= X"00" & cxreg_s(7 downto 0);
+ when "00010" => alu_inbusa <= X"00" & dxreg_s(7 downto 0);
+ when "00011" => alu_inbusa <= X"00" & bxreg_s(7 downto 0);
+ when "00100" => alu_inbusa <= X"00" & axreg_s(15 downto 8); -- AH
+ when "00101" => alu_inbusa <= X"00" & cxreg_s(15 downto 8); -- CH
+ when "00110" => alu_inbusa <= X"00" & dxreg_s(15 downto 8); -- DH
+ when "00111" => alu_inbusa <= X"00" & bxreg_s(15 downto 8); -- BH
+ when "10000" => alu_inbusa <= axreg_s;
+ when "10001" => alu_inbusa <= cxreg_s;
+ when "10010" => alu_inbusa <= dxreg_s;
+ when "10011" => alu_inbusa <= bxreg_s;
+ when "10100" => alu_inbusa <= spreg_s;
+ when "10101" => alu_inbusa <= bpreg_s;
+ when "10110" => alu_inbusa <= sireg_s;
+ when "10111" => alu_inbusa <= direg_s;
+ when others => alu_inbusa <= mdbus_in(15 downto 0); -- Pass through
+ end case;
+ end process;
+
+----------------------------------------------------------------------------
+-- Output Port B
+----------------------------------------------------------------------------
+ selalub_s <= w & selalub;
+
+ process (selalub_s,axreg_s,cxreg_s,dxreg_s,bxreg_s,spreg_s,bpreg_s,sireg_s,direg_s,mdbus_in,data_in)
+ begin
+ case selalub_s is
+ when "00000" => alu_inbusb_s <= X"00" & axreg_s(7 downto 0);
+ when "00001" => alu_inbusb_s <= X"00" & cxreg_s(7 downto 0);
+ when "00010" => alu_inbusb_s <= X"00" & dxreg_s(7 downto 0);
+ when "00011" => alu_inbusb_s <= X"00" & bxreg_s(7 downto 0);
+ when "00100" => alu_inbusb_s <= X"00" & axreg_s(15 downto 8);
+ when "00101" => alu_inbusb_s <= X"00" & cxreg_s(15 downto 8);
+ when "00110" => alu_inbusb_s <= X"00" & dxreg_s(15 downto 8);
+ when "00111" => alu_inbusb_s <= X"00" & bxreg_s(15 downto 8);
+ when "10000" => alu_inbusb_s <= axreg_s;
+ when "10001" => alu_inbusb_s <= cxreg_s;
+ when "10010" => alu_inbusb_s <= dxreg_s;
+ when "10011" => alu_inbusb_s <= bxreg_s;
+ when "10100" => alu_inbusb_s <= spreg_s;
+ when "10101" => alu_inbusb_s <= bpreg_s;
+ when "10110" => alu_inbusb_s <= sireg_s;
+ when "10111" => alu_inbusb_s <= direg_s;
+ when "01000" => alu_inbusb_s <= X"00"& data_in(7 downto 0); -- Pass data_in to ALU (port B only)
+ when "11000" => alu_inbusb_s <= data_in; -- Pass data_in to ALU (port B only)
+ when "01001" => alu_inbusb_s <= X"0001"; -- Used for INC/DEC byte function
+ when "11001" => alu_inbusb_s <= X"0001"; -- Used for INC/DEC word function
+ when "11010" => alu_inbusb_s <= X"0002"; -- Used for POP/PUSH function
+ when others => alu_inbusb_s <= mdbus_in(15 downto 0); -- Pass through
+ end case;
+ end process;
+
+ alu_inbusb <= alu_inbusb_s; -- connect to entity
+
+ bx_s <= bxreg_s; -- Used for EA calculation
+ bp_s <= bpreg_s;
+ si_s <= sireg_s;
+ di_s <= direg_s;
+
+ sp_s <= spreg_s; -- Used for eamux, PUSH and POP instructions
+
+ ax_s <= axreg_s; -- Used for datapath FSM
+ cx_s <= cxreg_s;
+ dx_s <= dxreg_s; -- Used for IN/OUT instructions & Divider
+
+end rtl;
diff --git a/common/CPU/cpu86/divider_rtl_ser.vhd b/common/CPU/cpu86/divider_rtl_ser.vhd
new file mode 100644
index 00000000..854aab8c
--- /dev/null
+++ b/common/CPU/cpu86/divider_rtl_ser.vhd
@@ -0,0 +1,229 @@
+-------------------------------------------------------------------------------
+-- CPU86 - VHDL CPU8088 IP core --
+-- Copyright (C) 2002-2008 HT-LAB --
+-- --
+-- Contact/bugs : http://www.ht-lab.com/misc/feedback.html --
+-- Web : http://www.ht-lab.com --
+-- --
+-- CPU86 is released as open-source under the GNU GPL license. This means --
+-- that designs based on CPU86 must be distributed in full source code --
+-- under the same license. Contact HT-Lab for commercial applications where --
+-- source-code distribution is not desirable. --
+-- --
+-------------------------------------------------------------------------------
+-- --
+-- This library is free software; you can redistribute it and/or --
+-- modify it under the terms of the GNU Lesser General Public --
+-- License as published by the Free Software Foundation; either --
+-- version 2.1 of the License, or (at your option) any later version. --
+-- --
+-- This library 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 --
+-- Lesser General Public License for more details. --
+-- --
+-- Full details of the license can be found in the file "copying.txt". --
+-- --
+-- You should have received a copy of the GNU Lesser General Public --
+-- License along with this library; if not, write to the Free Software --
+-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --
+-- --
+-------------------------------------------------------------------------------
+
+LIBRARY ieee;
+USE ieee.std_logic_1164.all;
+USE ieee.std_logic_unsigned.all;
+use ieee.std_logic_arith.all;
+
+ENTITY divider IS
+ GENERIC(
+ WIDTH_DIVID : integer := 32; -- Width Dividend
+ WIDTH_DIVIS : integer := 16; -- Width Divisor
+ WIDTH_SHORT : Integer := 8 -- Check Overflow against short Byte/Word
+ );
+ PORT(
+ clk : IN std_logic; -- System Clock
+ reset : IN std_logic; -- Active high
+ dividend : IN std_logic_vector (WIDTH_DIVID-1 DOWNTO 0);
+ divisor : IN std_logic_vector (WIDTH_DIVIS-1 DOWNTO 0);
+ quotient : OUT std_logic_vector (WIDTH_DIVIS-1 DOWNTO 0);
+ remainder : OUT std_logic_vector (WIDTH_DIVIS-1 DOWNTO 0);
+ twocomp : IN std_logic;
+ w : IN std_logic; -- UNUSED!
+ overflow : OUT std_logic;
+ start : IN std_logic;
+ done : OUT std_logic
+ );
+END divider ;
+
+ARCHITECTURE rtl_ser OF divider IS
+
+signal dividend_s : std_logic_vector(WIDTH_DIVID downto 0);
+signal divisor_s : std_logic_vector(WIDTH_DIVIS downto 0);
+
+signal divis_rect_s : std_logic_vector(WIDTH_DIVIS-1 downto 0);
+
+signal signquot_s : std_logic;
+signal signremain_s : std_logic;
+
+signal accumulator_s : std_logic_vector(WIDTH_DIVID downto 0);
+signal aluout_s : std_logic_vector(WIDTH_DIVIS downto 0);
+signal newaccu_s : std_logic_vector(WIDTH_DIVID downto 0);
+
+signal quot_s : std_logic_vector (WIDTH_DIVIS-1 downto 0);
+signal remain_s : std_logic_vector (WIDTH_DIVIS-1 downto 0);
+
+constant null_s : std_logic_vector(31 downto 0) := X"00000000";
+
+signal count_s : std_logic_vector (3 downto 0); -- Number of iterations
+
+signal overflow_s : std_logic; --_vector (WIDTH_DIVIS downto 0);
+signal sremainder_s : std_logic_vector (WIDTH_DIVIS-1 downto 0);
+signal squotient_s : std_logic_vector (WIDTH_DIVIS-1 downto 0);
+
+signal signfailure_s : std_logic;
+
+signal zeroq_s : std_logic;
+signal zeror_s : std_logic;
+signal zerod_s : std_logic;
+signal pos_s : std_logic;
+signal neg_s : std_logic;
+
+type states is (s0,s1,s2);
+signal state,nextstate: states;
+
+function rectifyd (r : in std_logic_vector (WIDTH_DIVID downto 0); -- Rectifier for dividend + 1 bit
+ twoc: in std_logic) -- Signed/Unsigned
+ return std_logic_vector is
+ variable rec_v : std_logic_vector (WIDTH_DIVID downto 0);
+begin
+ if ((r(WIDTH_DIVID) and twoc)='1') then
+ rec_v := not(r);
+ else
+ rec_v := r;
+ end if;
+ return (rec_v + (r(WIDTH_DIVID) and twoc));
+end;
+
+function rectifys (r : in std_logic_vector (WIDTH_DIVIS-1 downto 0); -- Rectifier for divisor
+ twoc: in std_logic) -- Signed/Unsigned
+ return std_logic_vector is
+ variable rec_v : std_logic_vector (WIDTH_DIVIS-1 downto 0);
+begin
+ if ((r(WIDTH_DIVIS-1) and twoc)='1') then
+ rec_v := not(r);
+ else
+ rec_v := r;
+ end if;
+ return (rec_v + (r(WIDTH_DIVIS-1) and twoc));
+end;
+
+
+begin
+
+-- Sign Quotient
+ signquot_s <= (dividend(WIDTH_DIVID-1) xor divisor(WIDTH_DIVIS-1)) and twocomp;
+
+-- Sign Remainder
+ signremain_s <= dividend(WIDTH_DIVID-1) and twocomp;
+
+ dividend_s <= '0'÷nd when twocomp='0' else rectifyd(dividend(WIDTH_DIVID-1)÷nd, twocomp);
+
+ divisor_s <= ('1'&divisor) when (divisor(WIDTH_DIVIS-1) and twocomp)='1' else not('0'&divisor) + '1';
+
+-- Subtractor (Adder, WIDTH_DIVIS+1)
+ aluout_s <= accumulator_s(WIDTH_DIVID downto WIDTH_DIVID-WIDTH_DIVIS) + divisor_s;
+
+-- Append Quotient section to aluout_s
+ newaccu_s <= aluout_s & accumulator_s(WIDTH_DIVID-WIDTH_DIVIS-1 downto 0);
+
+process (clk,reset)
+ begin
+ if (reset='1') then
+ accumulator_s <= (others => '0');
+ elsif (rising_edge(clk)) then
+ if start='1' then
+ accumulator_s <= dividend_s(WIDTH_DIVID-1 downto 0) & '0'; -- Load Dividend in remainder +shl
+ elsif pos_s='1' then -- Positive, remain=shl(remain,1)
+ accumulator_s <= newaccu_s(WIDTH_DIVID-1 downto 0) & '1'; -- Use sub result
+ elsif neg_s='1' then -- Negative, shl(remainder,0)
+ accumulator_s <= accumulator_s(WIDTH_DIVID-1 downto 0) & '0';-- Use original remainder
+ end if;
+ end if;
+end process;
+
+-- 2 Process Control FSM
+process (clk,reset)
+ begin
+ if (reset = '1') then
+ state <= s0;
+ count_s <= (others => '0');
+ elsif (rising_edge(clk)) then
+ state <= nextstate;
+ if (state=s1) then
+ count_s <= count_s - '1';
+ elsif (state=s0) then
+ count_s <= CONV_STD_LOGIC_VECTOR(WIDTH_DIVIS-1, 4); -- extra step CAN REDUCE BY 1 since DONE is latched!!
+ end if;
+ end if;
+end process;
+
+process(state,start,aluout_s,count_s)
+ begin
+ case state is
+ when s0 =>
+ pos_s <= '0';
+ neg_s <= '0';
+ if start='1' then
+ nextstate <= s1;
+ else
+ nextstate <= s0;
+ end if;
+ when s1 =>
+ neg_s <= aluout_s(WIDTH_DIVIS);
+ pos_s <= not(aluout_s(WIDTH_DIVIS));
+ if (count_s=null_s(3 downto 0)) then nextstate <= s2; -- Done
+ else nextstate <= s1; -- Next sub&shift
+ end if;
+ when s2=>
+ pos_s <= '0';
+ neg_s <= '0';
+ nextstate <= s0;
+ when others =>
+ pos_s <= '0';
+ neg_s <= '0';
+ nextstate <= s0;
+ end case;
+end process;
+
+-- Correct remainder (SHR,1)
+remain_s <= accumulator_s(WIDTH_DIVID downto WIDTH_DIVID-WIDTH_DIVIS+1);
+
+-- Overflow if remainder>divisor or divide by 0 or sign error. Change all to positive.
+divis_rect_s <= rectifys(divisor, twocomp);
+overflow_s <= '1' when ((remain_s>=divis_rect_s) or (zerod_s='1')) else '0';
+
+-- bottom part of remainder is quotient
+quot_s <= accumulator_s(WIDTH_DIVIS-1 downto 0);
+
+-- Remainder Result
+sremainder_s <= ((not(remain_s)) + '1') when signremain_s='1' else remain_s;
+remainder <= sremainder_s;
+
+-- Qotient Result
+squotient_s <= ((not(quot_s)) + '1') when signquot_s='1' else quot_s;
+quotient <= squotient_s;
+
+-- Detect zero vector
+zeror_s <= '1' when (twocomp='1' and sremainder_s=null_s(WIDTH_DIVIS-1 downto 0)) else '0';
+zeroq_s <= '1' when (twocomp='1' and squotient_s=null_s(WIDTH_DIVIS-1 downto 0)) else '0';
+zerod_s <= '1' when (divisor=null_s(WIDTH_DIVIS-1 downto 0)) else '0';
+
+-- Detect Sign failure
+signfailure_s <= '1' when (signquot_s='1' and squotient_s(WIDTH_DIVIS-1)='0' and zeroq_s='0') or
+ (signremain_s='1' and sremainder_s(WIDTH_DIVIS-1)='0' and zeror_s='0') else '0';
+
+done <= '1' when state=s2 else '0';
+overflow <= '1' when (overflow_s='1' or signfailure_s='1') else '0';
+
+end architecture rtl_ser;
diff --git a/common/CPU/cpu86/formatter_struct.vhd b/common/CPU/cpu86/formatter_struct.vhd
new file mode 100644
index 00000000..f2f47e8d
--- /dev/null
+++ b/common/CPU/cpu86/formatter_struct.vhd
@@ -0,0 +1,132 @@
+-------------------------------------------------------------------------------
+-- CPU86 - VHDL CPU8088 IP core --
+-- Copyright (C) 2002-2008 HT-LAB --
+-- --
+-- Contact/bugs : http://www.ht-lab.com/misc/feedback.html --
+-- Web : http://www.ht-lab.com --
+-- --
+-- CPU86 is released as open-source under the GNU GPL license. This means --
+-- that designs based on CPU86 must be distributed in full source code --
+-- under the same license. Contact HT-Lab for commercial applications where --
+-- source-code distribution is not desirable. --
+-- --
+-------------------------------------------------------------------------------
+-- --
+-- This library is free software; you can redistribute it and/or --
+-- modify it under the terms of the GNU Lesser General Public --
+-- License as published by the Free Software Foundation; either --
+-- version 2.1 of the License, or (at your option) any later version. --
+-- --
+-- This library 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 --
+-- Lesser General Public License for more details. --
+-- --
+-- Full details of the license can be found in the file "copying.txt". --
+-- --
+-- You should have received a copy of the GNU Lesser General Public --
+-- License along with this library; if not, write to the Free Software --
+-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --
+-- --
+-------------------------------------------------------------------------------
+LIBRARY ieee;
+USE ieee.std_logic_1164.all;
+
+ENTITY formatter IS
+ PORT(
+ lutbus : IN std_logic_vector (15 DOWNTO 0);
+ mux_addr : OUT std_logic_vector (2 DOWNTO 0);
+ mux_data : OUT std_logic_vector (3 DOWNTO 0);
+ mux_reg : OUT std_logic_vector (2 DOWNTO 0);
+ nbreq : OUT std_logic_vector (2 DOWNTO 0)
+ );
+END formatter ;
+
+
+ARCHITECTURE struct OF formatter IS
+
+ -- Architecture declarations
+ SIGNAL dout : std_logic_vector(15 DOWNTO 0);
+ SIGNAL dout4 : std_logic_vector(7 DOWNTO 0);
+ SIGNAL dout5 : std_logic_vector(7 DOWNTO 0);
+ SIGNAL muxout : std_logic_vector(7 DOWNTO 0);
+
+
+ SIGNAL mw_I1temp_din : std_logic_vector(15 DOWNTO 0);
+
+ -- Component Declarations
+ COMPONENT a_table
+ PORT (
+ addr : IN std_logic_vector (15 DOWNTO 0);
+ dout : OUT std_logic_vector (2 DOWNTO 0)
+ );
+ END COMPONENT;
+ COMPONENT d_table
+ PORT (
+ addr : IN std_logic_vector (15 DOWNTO 0);
+ dout : OUT std_logic_vector (3 DOWNTO 0)
+ );
+ END COMPONENT;
+ COMPONENT m_table
+ PORT (
+ ireg : IN std_logic_vector (7 DOWNTO 0);
+ modrrm : IN std_logic_vector (7 DOWNTO 0);
+ muxout : OUT std_logic_vector (7 DOWNTO 0)
+ );
+ END COMPONENT;
+ COMPONENT n_table
+ PORT (
+ addr : IN std_logic_vector (15 DOWNTO 0);
+ dout : OUT std_logic_vector (2 DOWNTO 0)
+ );
+ END COMPONENT;
+ COMPONENT r_table
+ PORT (
+ addr : IN std_logic_vector (15 DOWNTO 0);
+ dout : OUT std_logic_vector (2 DOWNTO 0)
+ );
+ END COMPONENT;
+
+
+BEGIN
+
+ dout <= dout4 & muxout;
+
+ mw_I1temp_din <= lutbus;
+ i1combo_proc: PROCESS (mw_I1temp_din)
+ VARIABLE temp_din: std_logic_vector(15 DOWNTO 0);
+ BEGIN
+ temp_din := mw_I1temp_din(15 DOWNTO 0);
+ dout5 <= temp_din(7 DOWNTO 0);
+ dout4 <= temp_din(15 DOWNTO 8);
+ END PROCESS i1combo_proc;
+
+ -- Instance port mappings.
+ I2 : a_table
+ PORT MAP (
+ addr => dout,
+ dout => mux_addr
+ );
+ I3 : d_table
+ PORT MAP (
+ addr => dout,
+ dout => mux_data
+ );
+ I6 : m_table
+ PORT MAP (
+ ireg => dout4,
+ modrrm => dout5,
+ muxout => muxout
+ );
+ I4 : n_table
+ PORT MAP (
+ addr => dout,
+ dout => nbreq
+ );
+ I5 : r_table
+ PORT MAP (
+ addr => dout,
+ dout => mux_reg
+ );
+
+END struct;
diff --git a/common/CPU/cpu86/ipregister_rtl.vhd b/common/CPU/cpu86/ipregister_rtl.vhd
new file mode 100644
index 00000000..3ce602bf
--- /dev/null
+++ b/common/CPU/cpu86/ipregister_rtl.vhd
@@ -0,0 +1,72 @@
+-------------------------------------------------------------------------------
+-- CPU86 - VHDL CPU8088 IP core --
+-- Copyright (C) 2002-2008 HT-LAB --
+-- --
+-- Contact/bugs : http://www.ht-lab.com/misc/feedback.html --
+-- Web : http://www.ht-lab.com --
+-- --
+-- CPU86 is released as open-source under the GNU GPL license. This means --
+-- that designs based on CPU86 must be distributed in full source code --
+-- under the same license. Contact HT-Lab for commercial applications where --
+-- source-code distribution is not desirable. --
+-- --
+-------------------------------------------------------------------------------
+-- --
+-- This library is free software; you can redistribute it and/or --
+-- modify it under the terms of the GNU Lesser General Public --
+-- License as published by the Free Software Foundation; either --
+-- version 2.1 of the License, or (at your option) any later version. --
+-- --
+-- This library 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 --
+-- Lesser General Public License for more details. --
+-- --
+-- Full details of the license can be found in the file "copying.txt". --
+-- --
+-- You should have received a copy of the GNU Lesser General Public --
+-- License along with this library; if not, write to the Free Software --
+-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --
+-- --
+-------------------------------------------------------------------------------
+LIBRARY ieee;
+USE ieee.std_logic_1164.ALL;
+USE ieee.std_logic_unsigned.ALL;
+USE ieee.std_logic_arith.ALL;
+
+USE work.cpu86pack.ALL;
+
+ENTITY ipregister IS
+ PORT(
+ clk : IN std_logic;
+ ipbus : IN std_logic_vector (15 DOWNTO 0);
+ reset : IN std_logic;
+ wrip : IN std_logic;
+ ipreg : OUT std_logic_vector (15 DOWNTO 0)
+ );
+END ipregister ;
+
+
+architecture rtl of ipregister is
+
+signal ipreg_s : std_logic_vector(15 downto 0);
+
+begin
+
+----------------------------------------------------------------------------
+-- Instructon Pointer Register
+----------------------------------------------------------------------------
+process (clk, reset)
+ begin
+ if reset='1' then
+ ipreg_s <= RESET_IP_C; -- See cpu86pack
+ elsif rising_edge(clk) then
+ if (wrip='1') then
+ ipreg_s<= ipbus;
+ end if;
+ end if;
+end process;
+
+ipreg <= ipreg_s;
+
+end rtl;
diff --git a/common/CPU/cpu86/m_table.vhd b/common/CPU/cpu86/m_table.vhd
new file mode 100644
index 00000000..5548273b
--- /dev/null
+++ b/common/CPU/cpu86/m_table.vhd
@@ -0,0 +1,139 @@
+-------------------------------------------------------------------------------
+-- CPU86 - VHDL CPU8088 IP core --
+-- Copyright (C) 2002-2008 HT-LAB --
+-- --
+-- Contact/bugs : http://www.ht-lab.com/misc/feedback.html --
+-- Web : http://www.ht-lab.com --
+-- --
+-- CPU86 is released as open-source under the GNU GPL license. This means --
+-- that designs based on CPU86 must be distributed in full source code --
+-- under the same license. Contact HT-Lab for commercial applications where --
+-- source-code distribution is not desirable. --
+-- --
+-------------------------------------------------------------------------------
+-- --
+-- This library is free software; you can redistribute it and/or --
+-- modify it under the terms of the GNU Lesser General Public --
+-- License as published by the Free Software Foundation; either --
+-- version 2.1 of the License, or (at your option) any later version. --
+-- --
+-- This library 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 --
+-- Lesser General Public License for more details. --
+-- --
+-- Full details of the license can be found in the file "copying.txt". --
+-- --
+-- You should have received a copy of the GNU Lesser General Public --
+-- License along with this library; if not, write to the Free Software --
+-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --
+-- --
+-------------------------------------------------------------------------------
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.std_logic_arith.all;
+
+entity m_table is
+ port ( ireg : in std_logic_vector(7 downto 0);
+ modrrm: in std_logic_vector(7 downto 0);
+ muxout: out std_logic_vector(7 downto 0));
+end m_table;
+
+
+architecture rtl of m_table is
+
+ signal lutout_s: std_logic_vector(1 downto 0);
+ signal ea_s : std_logic; -- Asserted if mod=00 and rm=110
+ signal m11_s : std_logic; -- Asserted if mod=11
+ signal mux_s : std_logic_vector(3 downto 0);
+
+begin
+
+ ea_s <= '1' when (modrrm(7 downto 6)="00" and modrrm(2 downto 0)="110") else '0';
+
+ m11_s<= '1' when modrrm(7 downto 6)="11" else '0';
+
+ mux_s <= lutout_s & m11_s & ea_s;
+
+ process (mux_s,modrrm)
+ begin
+ case mux_s is
+ when "1000" => muxout <= modrrm(7 downto 6)&"000000";
+ when "1010" => muxout <= modrrm(7 downto 6)&"000000";
+ when "1001" => muxout <= "00000110";
+ when "1011" => muxout <= "00000110";
+ when "1100" => muxout <= modrrm(7 downto 3)&"000";
+ when "1101" => muxout <= "00"&modrrm(5 downto 3)&"110";
+ when "1110" => muxout <= "11"&modrrm(5 downto 3)&"000";
+ when others => muxout <= (others => '0');
+ end case;
+ end process;
+
+ process(ireg)
+ begin
+ case ireg is
+ when "11111111" => lutout_s <= "11";
+ when "10001000" => lutout_s <= "10";
+ when "10001001" => lutout_s <= "10";
+ when "10001010" => lutout_s <= "10";
+ when "10001011" => lutout_s <= "10";
+ when "11000110" => lutout_s <= "11";
+ when "11000111" => lutout_s <= "11";
+ when "10001110" => lutout_s <= "10";
+ when "10001100" => lutout_s <= "10";
+ when "10001111" => lutout_s <= "11";
+ when "10000110" => lutout_s <= "10";
+ when "10000111" => lutout_s <= "10";
+ when "10001101" => lutout_s <= "10";
+ when "11000101" => lutout_s <= "10";
+ when "11000100" => lutout_s <= "10";
+ when "00000000" => lutout_s <= "10";
+ when "00000001" => lutout_s <= "10";
+ when "00000010" => lutout_s <= "10";
+ when "00000011" => lutout_s <= "10";
+ when "10000000" => lutout_s <= "11";
+ when "10000001" => lutout_s <= "11";
+ when "10000011" => lutout_s <= "11";
+ when "00010000" => lutout_s <= "10";
+ when "00010001" => lutout_s <= "10";
+ when "00010010" => lutout_s <= "10";
+ when "00010011" => lutout_s <= "10";
+ when "00101000" => lutout_s <= "10";
+ when "00101001" => lutout_s <= "10";
+ when "00101010" => lutout_s <= "10";
+ when "00101011" => lutout_s <= "10";
+ when "00011000" => lutout_s <= "10";
+ when "00011001" => lutout_s <= "10";
+ when "00011010" => lutout_s <= "10";
+ when "00011011" => lutout_s <= "10";
+ when "11111110" => lutout_s <= "11";
+ when "00111010" => lutout_s <= "10";
+ when "00111011" => lutout_s <= "10";
+ when "00111000" => lutout_s <= "10";
+ when "00111001" => lutout_s <= "10";
+ when "11110110" => lutout_s <= "11";
+ when "11110111" => lutout_s <= "11";
+ when "11010000" => lutout_s <= "10";
+ when "11010001" => lutout_s <= "10";
+ when "11010010" => lutout_s <= "10";
+ when "11010011" => lutout_s <= "10";
+ when "00100000" => lutout_s <= "10";
+ when "00100001" => lutout_s <= "10";
+ when "00100010" => lutout_s <= "10";
+ when "00100011" => lutout_s <= "10";
+ when "00001000" => lutout_s <= "10";
+ when "00001001" => lutout_s <= "10";
+ when "00001010" => lutout_s <= "10";
+ when "00001011" => lutout_s <= "10";
+ when "10000100" => lutout_s <= "10";
+ when "10000101" => lutout_s <= "10";
+ when "00110000" => lutout_s <= "10";
+ when "00110001" => lutout_s <= "10";
+ when "00110010" => lutout_s <= "10";
+ when "00110011" => lutout_s <= "10";
+ when "10000010" => lutout_s <= "01";
+ when others => lutout_s <= "00";
+ end case;
+ end process;
+end rtl;
\ No newline at end of file
diff --git a/common/CPU/cpu86/multiplier_rtl.vhd b/common/CPU/cpu86/multiplier_rtl.vhd
new file mode 100644
index 00000000..4027a4a2
--- /dev/null
+++ b/common/CPU/cpu86/multiplier_rtl.vhd
@@ -0,0 +1,81 @@
+-------------------------------------------------------------------------------
+-- CPU86 - VHDL CPU8088 IP core --
+-- Copyright (C) 2002-2008 HT-LAB --
+-- --
+-- Contact/bugs : http://www.ht-lab.com/misc/feedback.html --
+-- Web : http://www.ht-lab.com --
+-- --
+-- CPU86 is released as open-source under the GNU GPL license. This means --
+-- that designs based on CPU86 must be distributed in full source code --
+-- under the same license. Contact HT-Lab for commercial applications where --
+-- source-code distribution is not desirable. --
+-- --
+-------------------------------------------------------------------------------
+-- --
+-- This library is free software; you can redistribute it and/or --
+-- modify it under the terms of the GNU Lesser General Public --
+-- License as published by the Free Software Foundation; either --
+-- version 2.1 of the License, or (at your option) any later version. --
+-- --
+-- This library 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 --
+-- Lesser General Public License for more details. --
+-- --
+-- Full details of the license can be found in the file "copying.txt". --
+-- --
+-- You should have received a copy of the GNU Lesser General Public --
+-- License along with this library; if not, write to the Free Software --
+-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --
+-- --
+-------------------------------------------------------------------------------
+LIBRARY ieee;
+USE ieee.std_logic_1164.all;
+USE ieee.std_logic_unsigned.all;
+
+ENTITY multiplier IS
+ GENERIC(
+ WIDTH : integer := 16
+ );
+ PORT(
+ multiplicant : IN std_logic_vector (WIDTH-1 DOWNTO 0);
+ multiplier : IN std_logic_vector (WIDTH-1 DOWNTO 0);
+ product : OUT std_logic_vector (WIDTH+WIDTH-1 DOWNTO 0); -- result
+ twocomp : IN std_logic
+ );
+END multiplier ;
+
+
+architecture rtl of multiplier is
+
+function rectify (r : in std_logic_vector (WIDTH-1 downto 0); -- Rectifier for signed multiplication
+ twoc : in std_logic) -- Signed/Unsigned
+ return std_logic_vector is
+ variable rec_v : std_logic_vector (WIDTH-1 downto 0);
+begin
+ if ((r(WIDTH-1) and twoc)='1') then
+ rec_v := not(r);
+ else
+ rec_v := r;
+ end if;
+ return (rec_v + (r(WIDTH-1) and twoc));
+end;
+
+signal multiplicant_s : std_logic_vector (WIDTH-1 downto 0);
+signal multiplier_s : std_logic_vector (WIDTH-1 downto 0);
+
+signal product_s : std_logic_vector (WIDTH+WIDTH-1 downto 0); -- Result
+signal sign_s : std_logic;
+
+begin
+
+ multiplicant_s <= rectify(multiplicant,twocomp);
+ multiplier_s <= rectify(multiplier,twocomp);
+
+ sign_s <= multiplicant(WIDTH-1) xor multiplier(WIDTH-1); -- sign product
+
+ product_s <= multiplicant_s * multiplier_s;
+
+ product <= ((not(product_s)) + '1') when (sign_s and twocomp)='1' else product_s;
+
+end rtl;
diff --git a/common/CPU/cpu86/n_table.vhd b/common/CPU/cpu86/n_table.vhd
new file mode 100644
index 00000000..58500b0a
--- /dev/null
+++ b/common/CPU/cpu86/n_table.vhd
@@ -0,0 +1,721 @@
+-------------------------------------------------------------------------------
+-- CPU86 - VHDL CPU8088 IP core --
+-- Copyright (C) 2002-2008 HT-LAB --
+-- --
+-- Contact/bugs : http://www.ht-lab.com/misc/feedback.html --
+-- Web : http://www.ht-lab.com --
+-- --
+-- CPU86 is released as open-source under the GNU GPL license. This means --
+-- that designs based on CPU86 must be distributed in full source code --
+-- under the same license. Contact HT-Lab for commercial applications where --
+-- source-code distribution is not desirable. --
+-- --
+-------------------------------------------------------------------------------
+-- --
+-- This library is free software; you can redistribute it and/or --
+-- modify it under the terms of the GNU Lesser General Public --
+-- License as published by the Free Software Foundation; either --
+-- version 2.1 of the License, or (at your option) any later version. --
+-- --
+-- This library 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 --
+-- Lesser General Public License for more details. --
+-- --
+-- Full details of the license can be found in the file "copying.txt". --
+-- --
+-- You should have received a copy of the GNU Lesser General Public --
+-- License along with this library; if not, write to the Free Software --
+-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --
+-- --
+-------------------------------------------------------------------------------
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+
+entity n_table is
+ port ( addr : in std_logic_vector(15 downto 0);
+ dout : out std_logic_vector(2 downto 0));
+end n_table;
+
+
+architecture rtl of n_table is
+begin
+ process(addr)
+ begin
+ case addr is
+ when "1110101100000000" => dout <= "010";
+ when "1110100100000000" => dout <= "011";
+ when "1111111111100000" => dout <= "010";
+ when "1111111100100110" => dout <= "100";
+ when "1111111100100000" => dout <= "010";
+ when "1111111101100000" => dout <= "011";
+ when "1111111110100000" => dout <= "100";
+ when "1110101000000000" => dout <= "101";
+ when "1111111100101110" => dout <= "100";
+ when "1111111100101000" => dout <= "010";
+ when "1111111101101000" => dout <= "011";
+ when "1111111110101000" => dout <= "100";
+ when "1110100000000000" => dout <= "011";
+ when "1111111111010000" => dout <= "010";
+ when "1111111100010110" => dout <= "100";
+ when "1111111100010000" => dout <= "010";
+ when "1111111101010000" => dout <= "011";
+ when "1111111110010000" => dout <= "100";
+ when "1001101000000000" => dout <= "101";
+ when "1111111100011110" => dout <= "100";
+ when "1111111100011000" => dout <= "010";
+ when "1111111101011000" => dout <= "011";
+ when "1111111110011000" => dout <= "100";
+ when "1100001100000000" => dout <= "001";
+ when "1100001000000000" => dout <= "011";
+ when "1100101100000000" => dout <= "001";
+ when "1100101000000000" => dout <= "011";
+ when "0111010000000000" => dout <= "010";
+ when "0111110000000000" => dout <= "010";
+ when "0111111000000000" => dout <= "010";
+ when "0111001000000000" => dout <= "010";
+ when "0111011000000000" => dout <= "010";
+ when "0111101000000000" => dout <= "010";
+ when "0111000000000000" => dout <= "010";
+ when "0111100000000000" => dout <= "010";
+ when "0111010100000000" => dout <= "010";
+ when "0111110100000000" => dout <= "010";
+ when "0111111100000000" => dout <= "010";
+ when "0111001100000000" => dout <= "010";
+ when "0111011100000000" => dout <= "010";
+ when "0111101100000000" => dout <= "010";
+ when "0111000100000000" => dout <= "010";
+ when "0111100100000000" => dout <= "010";
+ when "1110001100000000" => dout <= "010";
+ when "1110001000000000" => dout <= "010";
+ when "1110000100000000" => dout <= "010";
+ when "1110000000000000" => dout <= "010";
+ when "1100110100000000" => dout <= "010";
+ when "1100110000000000" => dout <= "001";
+ when "1100111000000000" => dout <= "001";
+ when "1100111100000000" => dout <= "001";
+ when "1111100000000000" => dout <= "001";
+ when "1111010100000000" => dout <= "001";
+ when "1111100100000000" => dout <= "001";
+ when "1111110000000000" => dout <= "001";
+ when "1111110100000000" => dout <= "001";
+ when "1111101000000000" => dout <= "001";
+ when "1111101100000000" => dout <= "001";
+ when "1111010000000000" => dout <= "001";
+ when "1001101100000000" => dout <= "001";
+ when "1111000000000000" => dout <= "001";
+ when "1001000000000000" => dout <= "001";
+ when "0010011000000000" => dout <= "001";
+ when "0010111000000000" => dout <= "001";
+ when "0011011000000000" => dout <= "001";
+ when "0011111000000000" => dout <= "001";
+ when "1000100011000000" => dout <= "010";
+ when "1000100000000000" => dout <= "010";
+ when "1000100001000000" => dout <= "011";
+ when "1000100010000000" => dout <= "100";
+ when "1000100000000110" => dout <= "100";
+ when "1000100111000000" => dout <= "010";
+ when "1000100100000000" => dout <= "010";
+ when "1000100101000000" => dout <= "011";
+ when "1000100110000000" => dout <= "100";
+ when "1000100100000110" => dout <= "100";
+ when "1000101011000000" => dout <= "010";
+ when "1000101000000000" => dout <= "010";
+ when "1000101001000000" => dout <= "011";
+ when "1000101010000000" => dout <= "100";
+ when "1000101000000110" => dout <= "100";
+ when "1000101111000000" => dout <= "010";
+ when "1000101100000000" => dout <= "010";
+ when "1000101101000000" => dout <= "011";
+ when "1000101110000000" => dout <= "100";
+ when "1000101100000110" => dout <= "100";
+ when "1100011000000000" => dout <= "011";
+ when "1100011001000000" => dout <= "100";
+ when "1100011010000000" => dout <= "101";
+ when "1100011000000110" => dout <= "101";
+ when "1100011100000000" => dout <= "100";
+ when "1100011101000000" => dout <= "101";
+ when "1100011110000000" => dout <= "110";
+ when "1100011100000110" => dout <= "110";
+ when "1011000000000000" => dout <= "010";
+ when "1011000100000000" => dout <= "010";
+ when "1011001000000000" => dout <= "010";
+ when "1011001100000000" => dout <= "010";
+ when "1011010000000000" => dout <= "010";
+ when "1011010100000000" => dout <= "010";
+ when "1011011000000000" => dout <= "010";
+ when "1011011100000000" => dout <= "010";
+ when "1011100000000000" => dout <= "011";
+ when "1011100100000000" => dout <= "011";
+ when "1011101000000000" => dout <= "011";
+ when "1011101100000000" => dout <= "011";
+ when "1011110000000000" => dout <= "011";
+ when "1011110100000000" => dout <= "011";
+ when "1011111000000000" => dout <= "011";
+ when "1011111100000000" => dout <= "011";
+ when "1010000000000000" => dout <= "011";
+ when "1010000100000000" => dout <= "011";
+ when "1010001000000000" => dout <= "011";
+ when "1010001100000000" => dout <= "011";
+ when "1000111011000000" => dout <= "010";
+ when "1000111000000000" => dout <= "010";
+ when "1000111001000000" => dout <= "011";
+ when "1000111010000000" => dout <= "100";
+ when "1000111000000110" => dout <= "100";
+ when "1000110011000000" => dout <= "010";
+ when "1000110000000000" => dout <= "010";
+ when "1000110001000000" => dout <= "011";
+ when "1000110010000000" => dout <= "100";
+ when "1000110000000110" => dout <= "100";
+ when "1111111100110000" => dout <= "010";
+ when "1111111101110000" => dout <= "011";
+ when "1111111110110000" => dout <= "100";
+ when "1111111100110110" => dout <= "100";
+ when "0101000000000000" => dout <= "001";
+ when "0101000100000000" => dout <= "001";
+ when "0101001000000000" => dout <= "001";
+ when "0101001100000000" => dout <= "001";
+ when "0101010000000000" => dout <= "001";
+ when "0101010100000000" => dout <= "001";
+ when "0101011000000000" => dout <= "001";
+ when "0101011100000000" => dout <= "001";
+ when "0000011000000000" => dout <= "001";
+ when "0000111000000000" => dout <= "001";
+ when "0001011000000000" => dout <= "001";
+ when "0001111000000000" => dout <= "001";
+ when "1000111100000000" => dout <= "010";
+ when "1000111101000000" => dout <= "011";
+ when "1000111110000000" => dout <= "100";
+ when "1000111100000110" => dout <= "100";
+ when "1000111111000000" => dout <= "010";
+ when "0101100000000000" => dout <= "001";
+ when "0101100100000000" => dout <= "001";
+ when "0101101000000000" => dout <= "001";
+ when "0101101100000000" => dout <= "001";
+ when "0101110000000000" => dout <= "001";
+ when "0101110100000000" => dout <= "001";
+ when "0101111000000000" => dout <= "001";
+ when "0101111100000000" => dout <= "001";
+ when "0000011100000000" => dout <= "001";
+ when "0001011100000000" => dout <= "001";
+ when "0001111100000000" => dout <= "001";
+ when "1000011011000000" => dout <= "010";
+ when "1000011000000000" => dout <= "010";
+ when "1000011001000000" => dout <= "011";
+ when "1000011010000000" => dout <= "100";
+ when "1000011000000110" => dout <= "100";
+ when "1000011111000000" => dout <= "010";
+ when "1000011100000000" => dout <= "010";
+ when "1000011101000000" => dout <= "011";
+ when "1000011110000000" => dout <= "100";
+ when "1000011100000110" => dout <= "100";
+ when "1001000100000000" => dout <= "001";
+ when "1001001000000000" => dout <= "001";
+ when "1001001100000000" => dout <= "001";
+ when "1001010000000000" => dout <= "001";
+ when "1001010100000000" => dout <= "001";
+ when "1001011000000000" => dout <= "001";
+ when "1001011100000000" => dout <= "001";
+ when "1110010000000000" => dout <= "010";
+ when "1110010100000000" => dout <= "010";
+ when "1110110000000000" => dout <= "001";
+ when "1110110100000000" => dout <= "001";
+ when "1110011000000000" => dout <= "010";
+ when "1110011100000000" => dout <= "010";
+ when "1110111100000000" => dout <= "001";
+ when "1110111000000000" => dout <= "001";
+ when "1101011100000000" => dout <= "001";
+ when "1001111100000000" => dout <= "001";
+ when "1001111000000000" => dout <= "001";
+ when "1001110000000000" => dout <= "001";
+ when "1001110100000000" => dout <= "001";
+ when "1000110100000110" => dout <= "100";
+ when "1000110111000000" => dout <= "010";
+ when "1000110100000000" => dout <= "010";
+ when "1000110101000000" => dout <= "011";
+ when "1000110110000000" => dout <= "100";
+ when "1100010100000110" => dout <= "100";
+ when "1100010100000000" => dout <= "010";
+ when "1100010101000000" => dout <= "011";
+ when "1100010110000000" => dout <= "100";
+ when "1100010000000110" => dout <= "100";
+ when "1100010000000000" => dout <= "010";
+ when "1100010001000000" => dout <= "011";
+ when "1100010010000000" => dout <= "100";
+ when "0000000011000000" => dout <= "010";
+ when "0000000000000110" => dout <= "100";
+ when "0000000000000000" => dout <= "010";
+ when "0000000001000000" => dout <= "011";
+ when "0000000010000000" => dout <= "100";
+ when "0000000111000000" => dout <= "010";
+ when "0000000100000110" => dout <= "100";
+ when "0000000100000000" => dout <= "010";
+ when "0000000101000000" => dout <= "011";
+ when "0000000110000000" => dout <= "100";
+ when "0000001011000000" => dout <= "010";
+ when "0000001000000110" => dout <= "100";
+ when "0000001000000000" => dout <= "010";
+ when "0000001001000000" => dout <= "011";
+ when "0000001010000000" => dout <= "100";
+ when "0000001111000000" => dout <= "010";
+ when "0000001100000110" => dout <= "100";
+ when "0000001100000000" => dout <= "010";
+ when "0000001101000000" => dout <= "011";
+ when "0000001110000000" => dout <= "100";
+ when "1000000011000000" => dout <= "011";
+ when "1000000000000110" => dout <= "101";
+ when "1000000000000000" => dout <= "011";
+ when "1000000001000000" => dout <= "100";
+ when "1000000010000000" => dout <= "101";
+ when "1000000111000000" => dout <= "100";
+ when "1000000100000110" => dout <= "110";
+ when "1000000100000000" => dout <= "100";
+ when "1000000101000000" => dout <= "101";
+ when "1000000110000000" => dout <= "110";
+ when "1000001111000000" => dout <= "011";
+ when "1000001100000110" => dout <= "101";
+ when "1000001100000000" => dout <= "011";
+ when "1000001101000000" => dout <= "100";
+ when "1000001110000000" => dout <= "101";
+ when "0000010000000000" => dout <= "010";
+ when "0000010100000000" => dout <= "011";
+ when "0001000011000000" => dout <= "010";
+ when "0001000000000110" => dout <= "100";
+ when "0001000000000000" => dout <= "010";
+ when "0001000001000000" => dout <= "011";
+ when "0001000010000000" => dout <= "100";
+ when "0001000111000000" => dout <= "010";
+ when "0001000100000110" => dout <= "100";
+ when "0001000100000000" => dout <= "010";
+ when "0001000101000000" => dout <= "011";
+ when "0001000110000000" => dout <= "100";
+ when "0001001011000000" => dout <= "010";
+ when "0001001000000110" => dout <= "100";
+ when "0001001000000000" => dout <= "010";
+ when "0001001001000000" => dout <= "011";
+ when "0001001010000000" => dout <= "100";
+ when "0001001111000000" => dout <= "010";
+ when "0001001100000110" => dout <= "100";
+ when "0001001100000000" => dout <= "010";
+ when "0001001101000000" => dout <= "011";
+ when "0001001110000000" => dout <= "100";
+ when "1000000011010000" => dout <= "011";
+ when "1000000000010110" => dout <= "101";
+ when "1000000000010000" => dout <= "011";
+ when "1000000001010000" => dout <= "100";
+ when "1000000010010000" => dout <= "101";
+ when "1000000111010000" => dout <= "100";
+ when "1000000100010110" => dout <= "110";
+ when "1000000100010000" => dout <= "100";
+ when "1000000101010000" => dout <= "101";
+ when "1000000110010000" => dout <= "110";
+ when "1000001111010000" => dout <= "011";
+ when "1000001100010110" => dout <= "101";
+ when "1000001100010000" => dout <= "011";
+ when "1000001101010000" => dout <= "100";
+ when "1000001110010000" => dout <= "101";
+ when "0001010000000000" => dout <= "010";
+ when "0001010100000000" => dout <= "011";
+ when "0010100011000000" => dout <= "010";
+ when "0010100000000110" => dout <= "100";
+ when "0010100000000000" => dout <= "010";
+ when "0010100001000000" => dout <= "011";
+ when "0010100010000000" => dout <= "100";
+ when "0010100111000000" => dout <= "010";
+ when "0010100100000110" => dout <= "100";
+ when "0010100100000000" => dout <= "010";
+ when "0010100101000000" => dout <= "011";
+ when "0010100110000000" => dout <= "100";
+ when "0010101011000000" => dout <= "010";
+ when "0010101000000110" => dout <= "100";
+ when "0010101000000000" => dout <= "010";
+ when "0010101001000000" => dout <= "011";
+ when "0010101010000000" => dout <= "100";
+ when "0010101111000000" => dout <= "010";
+ when "0010101100000110" => dout <= "100";
+ when "0010101100000000" => dout <= "010";
+ when "0010101101000000" => dout <= "011";
+ when "0010101110000000" => dout <= "100";
+ when "1000000011101000" => dout <= "011";
+ when "1000000000101110" => dout <= "101";
+ when "1000000000101000" => dout <= "011";
+ when "1000000001101000" => dout <= "100";
+ when "1000000010101000" => dout <= "101";
+ when "1000000111101000" => dout <= "100";
+ when "1000000100101110" => dout <= "110";
+ when "1000000100101000" => dout <= "100";
+ when "1000000101101000" => dout <= "101";
+ when "1000000110101000" => dout <= "110";
+ when "1000001111101000" => dout <= "011";
+ when "1000001100101110" => dout <= "101";
+ when "1000001100101000" => dout <= "011";
+ when "1000001101101000" => dout <= "100";
+ when "1000001110101000" => dout <= "101";
+ when "0010110000000000" => dout <= "010";
+ when "0010110100000000" => dout <= "011";
+ when "0001100011000000" => dout <= "010";
+ when "0001100000000110" => dout <= "100";
+ when "0001100000000000" => dout <= "010";
+ when "0001100001000000" => dout <= "011";
+ when "0001100010000000" => dout <= "100";
+ when "0001100111000000" => dout <= "010";
+ when "0001100100000110" => dout <= "100";
+ when "0001100100000000" => dout <= "010";
+ when "0001100101000000" => dout <= "011";
+ when "0001100110000000" => dout <= "100";
+ when "0001101011000000" => dout <= "010";
+ when "0001101000000110" => dout <= "100";
+ when "0001101000000000" => dout <= "010";
+ when "0001101001000000" => dout <= "011";
+ when "0001101010000000" => dout <= "100";
+ when "0001101111000000" => dout <= "010";
+ when "0001101100000110" => dout <= "100";
+ when "0001101100000000" => dout <= "010";
+ when "0001101101000000" => dout <= "011";
+ when "0001101110000000" => dout <= "100";
+ when "1000000011011000" => dout <= "011";
+ when "1000000000011110" => dout <= "101";
+ when "1000000000011000" => dout <= "011";
+ when "1000000001011000" => dout <= "100";
+ when "1000000010011000" => dout <= "101";
+ when "1000000111011000" => dout <= "100";
+ when "1000000100011110" => dout <= "110";
+ when "1000000100011000" => dout <= "100";
+ when "1000000101011000" => dout <= "101";
+ when "1000000110011000" => dout <= "110";
+ when "1000001111011000" => dout <= "011";
+ when "1000001100011110" => dout <= "101";
+ when "1000001100011000" => dout <= "011";
+ when "1000001101011000" => dout <= "100";
+ when "1000001110011000" => dout <= "101";
+ when "0001110000000000" => dout <= "010";
+ when "0001110100000000" => dout <= "011";
+ when "1111111011000000" => dout <= "010";
+ when "1111111000000110" => dout <= "100";
+ when "1111111000000000" => dout <= "010";
+ when "1111111001000000" => dout <= "011";
+ when "1111111010000000" => dout <= "100";
+ when "1111111100000110" => dout <= "100";
+ when "1111111100000000" => dout <= "010";
+ when "1111111101000000" => dout <= "011";
+ when "1111111110000000" => dout <= "100";
+ when "0100000000000000" => dout <= "001";
+ when "0100000100000000" => dout <= "001";
+ when "0100001000000000" => dout <= "001";
+ when "0100001100000000" => dout <= "001";
+ when "0100010000000000" => dout <= "001";
+ when "0100010100000000" => dout <= "001";
+ when "0100011000000000" => dout <= "001";
+ when "0100011100000000" => dout <= "001";
+ when "1111111011001000" => dout <= "010";
+ when "1111111000001110" => dout <= "100";
+ when "1111111000001000" => dout <= "010";
+ when "1111111001001000" => dout <= "011";
+ when "1111111010001000" => dout <= "100";
+ when "1111111100001110" => dout <= "100";
+ when "1111111100001000" => dout <= "010";
+ when "1111111101001000" => dout <= "011";
+ when "1111111110001000" => dout <= "100";
+ when "0100100000000000" => dout <= "001";
+ when "0100100100000000" => dout <= "001";
+ when "0100101000000000" => dout <= "001";
+ when "0100101100000000" => dout <= "001";
+ when "0100110000000000" => dout <= "001";
+ when "0100110100000000" => dout <= "001";
+ when "0100111000000000" => dout <= "001";
+ when "0100111100000000" => dout <= "001";
+ when "0011101011000000" => dout <= "010";
+ when "0011101000000110" => dout <= "100";
+ when "0011101000000000" => dout <= "010";
+ when "0011101001000000" => dout <= "011";
+ when "0011101010000000" => dout <= "100";
+ when "0011101111000000" => dout <= "010";
+ when "0011101100000110" => dout <= "100";
+ when "0011101100000000" => dout <= "010";
+ when "0011101101000000" => dout <= "011";
+ when "0011101110000000" => dout <= "100";
+ when "0011100000000110" => dout <= "100";
+ when "0011100000000000" => dout <= "010";
+ when "0011100001000000" => dout <= "011";
+ when "0011100010000000" => dout <= "100";
+ when "0011100011000000" => dout <= "010";
+ when "0011100100000110" => dout <= "100";
+ when "0011100100000000" => dout <= "010";
+ when "0011100101000000" => dout <= "011";
+ when "0011100110000000" => dout <= "100";
+ when "0011100111000000" => dout <= "010";
+ when "1000000011111000" => dout <= "011";
+ when "1000000000111110" => dout <= "101";
+ when "1000000000111000" => dout <= "011";
+ when "1000000001111000" => dout <= "100";
+ when "1000000010111000" => dout <= "101";
+ when "1000000111111000" => dout <= "100";
+ when "1000000100111110" => dout <= "110";
+ when "1000000100111000" => dout <= "100";
+ when "1000000101111000" => dout <= "101";
+ when "1000000110111000" => dout <= "110";
+ when "1000001111111000" => dout <= "011";
+ when "1000001100111110" => dout <= "101";
+ when "1000001100111000" => dout <= "011";
+ when "1000001101111000" => dout <= "100";
+ when "1000001110111000" => dout <= "101";
+ when "0011110000000000" => dout <= "010";
+ when "0011110100000000" => dout <= "011";
+ when "1111011011011000" => dout <= "010";
+ when "1111011000011110" => dout <= "100";
+ when "1111011000011000" => dout <= "010";
+ when "1111011001011000" => dout <= "011";
+ when "1111011010011000" => dout <= "100";
+ when "1111011111011000" => dout <= "010";
+ when "1111011100011110" => dout <= "100";
+ when "1111011100011000" => dout <= "010";
+ when "1111011101011000" => dout <= "011";
+ when "1111011110011000" => dout <= "100";
+ when "0011011100000000" => dout <= "001";
+ when "0010011100000000" => dout <= "001";
+ when "0011111100000000" => dout <= "001";
+ when "0010111100000000" => dout <= "001";
+ when "1111011011100000" => dout <= "010";
+ when "1111011000100110" => dout <= "100";
+ when "1111011000100000" => dout <= "010";
+ when "1111011001100000" => dout <= "011";
+ when "1111011010100000" => dout <= "100";
+ when "1111011111100000" => dout <= "010";
+ when "1111011100100110" => dout <= "100";
+ when "1111011100100000" => dout <= "010";
+ when "1111011101100000" => dout <= "011";
+ when "1111011110100000" => dout <= "100";
+ when "1111011011101000" => dout <= "010";
+ when "1111011000101110" => dout <= "100";
+ when "1111011000101000" => dout <= "010";
+ when "1111011001101000" => dout <= "011";
+ when "1111011010101000" => dout <= "100";
+ when "1111011111101000" => dout <= "010";
+ when "1111011100101110" => dout <= "100";
+ when "1111011100101000" => dout <= "010";
+ when "1111011101101000" => dout <= "011";
+ when "1111011110101000" => dout <= "100";
+ when "1111011011110000" => dout <= "010";
+ when "1111011000110110" => dout <= "100";
+ when "1111011000110000" => dout <= "010";
+ when "1111011001110000" => dout <= "011";
+ when "1111011010110000" => dout <= "100";
+ when "1111011111110000" => dout <= "010";
+ when "1111011100110110" => dout <= "100";
+ when "1111011100110000" => dout <= "010";
+ when "1111011101110000" => dout <= "011";
+ when "1111011110110000" => dout <= "100";
+ when "1111011011111000" => dout <= "010";
+ when "1111011000111110" => dout <= "100";
+ when "1111011000111000" => dout <= "010";
+ when "1111011001111000" => dout <= "011";
+ when "1111011010111000" => dout <= "100";
+ when "1111011111111000" => dout <= "010";
+ when "1111011100111110" => dout <= "100";
+ when "1111011100111000" => dout <= "010";
+ when "1111011101111000" => dout <= "011";
+ when "1111011110111000" => dout <= "100";
+ when "1101010000000000" => dout <= "010";
+ when "1101010100000000" => dout <= "010";
+ when "1001100000000000" => dout <= "001";
+ when "1001100100000000" => dout <= "001";
+ when "1101000011000000" => dout <= "010";
+ when "1101000000000110" => dout <= "100";
+ when "1101000000000000" => dout <= "010";
+ when "1101000001000000" => dout <= "011";
+ when "1101000010000000" => dout <= "100";
+ when "1101000111000000" => dout <= "010";
+ when "1101000100000110" => dout <= "100";
+ when "1101000100000000" => dout <= "010";
+ when "1101000101000000" => dout <= "011";
+ when "1101000110000000" => dout <= "100";
+ when "1101001011000000" => dout <= "010";
+ when "1101001000000110" => dout <= "100";
+ when "1101001000000000" => dout <= "010";
+ when "1101001001000000" => dout <= "011";
+ when "1101001010000000" => dout <= "100";
+ when "1101001111000000" => dout <= "010";
+ when "1101001100000110" => dout <= "100";
+ when "1101001100000000" => dout <= "010";
+ when "1101001101000000" => dout <= "011";
+ when "1101001110000000" => dout <= "100";
+ when "0010000011000000" => dout <= "010";
+ when "0010000000000110" => dout <= "100";
+ when "0010000000000000" => dout <= "010";
+ when "0010000001000000" => dout <= "011";
+ when "0010000010000000" => dout <= "100";
+ when "0010000111000000" => dout <= "010";
+ when "0010000100000110" => dout <= "100";
+ when "0010000100000000" => dout <= "010";
+ when "0010000101000000" => dout <= "011";
+ when "0010000110000000" => dout <= "100";
+ when "0010001011000000" => dout <= "010";
+ when "0010001000000110" => dout <= "100";
+ when "0010001000000000" => dout <= "010";
+ when "0010001001000000" => dout <= "011";
+ when "0010001010000000" => dout <= "100";
+ when "0010001111000000" => dout <= "010";
+ when "0010001100000110" => dout <= "100";
+ when "0010001100000000" => dout <= "010";
+ when "0010001101000000" => dout <= "011";
+ when "0010001110000000" => dout <= "100";
+ when "1000000011100000" => dout <= "011";
+ when "1000000000100110" => dout <= "101";
+ when "1000000000100000" => dout <= "011";
+ when "1000000001100000" => dout <= "100";
+ when "1000000010100000" => dout <= "101";
+ when "1000000111100000" => dout <= "100";
+ when "1000000100100110" => dout <= "110";
+ when "1000000100100000" => dout <= "100";
+ when "1000000101100000" => dout <= "101";
+ when "1000000110100000" => dout <= "110";
+ when "1000001111100000" => dout <= "011";
+ when "1000001100100110" => dout <= "101";
+ when "1000001100100000" => dout <= "011";
+ when "1000001101100000" => dout <= "100";
+ when "1000001110100000" => dout <= "101";
+ when "0010010000000000" => dout <= "010";
+ when "0010010100000000" => dout <= "011";
+ when "0000100000000110" => dout <= "100";
+ when "0000100000000000" => dout <= "010";
+ when "0000100001000000" => dout <= "011";
+ when "0000100010000000" => dout <= "100";
+ when "0000100011000000" => dout <= "010";
+ when "0000100100000110" => dout <= "100";
+ when "0000100100000000" => dout <= "010";
+ when "0000100101000000" => dout <= "011";
+ when "0000100110000000" => dout <= "100";
+ when "0000100111000000" => dout <= "010";
+ when "0000101011000000" => dout <= "010";
+ when "0000101000000110" => dout <= "100";
+ when "0000101000000000" => dout <= "010";
+ when "0000101001000000" => dout <= "011";
+ when "0000101010000000" => dout <= "100";
+ when "0000101111000000" => dout <= "010";
+ when "0000101100000110" => dout <= "100";
+ when "0000101100000000" => dout <= "010";
+ when "0000101101000000" => dout <= "011";
+ when "0000101110000000" => dout <= "100";
+ when "1000000011001000" => dout <= "011";
+ when "1000000000001110" => dout <= "101";
+ when "1000000000001000" => dout <= "011";
+ when "1000000001001000" => dout <= "100";
+ when "1000000010001000" => dout <= "101";
+ when "1000000111001000" => dout <= "100";
+ when "1000000100001110" => dout <= "110";
+ when "1000000100001000" => dout <= "100";
+ when "1000000101001000" => dout <= "101";
+ when "1000000110001000" => dout <= "110";
+ when "1000001111001000" => dout <= "011";
+ when "1000001100001110" => dout <= "101";
+ when "1000001100001000" => dout <= "011";
+ when "1000001101001000" => dout <= "100";
+ when "1000001110001000" => dout <= "101";
+ when "0000110000000000" => dout <= "010";
+ when "0000110100000000" => dout <= "011";
+ when "1000010000000110" => dout <= "100";
+ when "1000010000000000" => dout <= "010";
+ when "1000010001000000" => dout <= "011";
+ when "1000010010000000" => dout <= "100";
+ when "1000010100000110" => dout <= "100";
+ when "1000010100000000" => dout <= "010";
+ when "1000010101000000" => dout <= "011";
+ when "1000010110000000" => dout <= "100";
+ when "1000010011000000" => dout <= "010";
+ when "1000010111000000" => dout <= "010";
+ when "1111011011000000" => dout <= "011";
+ when "1111011000000110" => dout <= "101";
+ when "1111011000000000" => dout <= "011";
+ when "1111011001000000" => dout <= "100";
+ when "1111011010000000" => dout <= "101";
+ when "1111011111000000" => dout <= "100";
+ when "1111011100000110" => dout <= "110";
+ when "1111011100000000" => dout <= "100";
+ when "1111011101000000" => dout <= "101";
+ when "1111011110000000" => dout <= "110";
+ when "1010100000000000" => dout <= "010";
+ when "1010100100000000" => dout <= "011";
+ when "0011000000000110" => dout <= "100";
+ when "0011000000000000" => dout <= "010";
+ when "0011000001000000" => dout <= "011";
+ when "0011000010000000" => dout <= "100";
+ when "0011000011000000" => dout <= "010";
+ when "0011000100000110" => dout <= "100";
+ when "0011000100000000" => dout <= "010";
+ when "0011000101000000" => dout <= "011";
+ when "0011000110000000" => dout <= "100";
+ when "0011000111000000" => dout <= "010";
+ when "0011001011000000" => dout <= "010";
+ when "0011001000000110" => dout <= "100";
+ when "0011001000000000" => dout <= "010";
+ when "0011001001000000" => dout <= "011";
+ when "0011001010000000" => dout <= "100";
+ when "0011001111000000" => dout <= "010";
+ when "0011001100000110" => dout <= "100";
+ when "0011001100000000" => dout <= "010";
+ when "0011001101000000" => dout <= "011";
+ when "0011001110000000" => dout <= "100";
+ when "1000000011110000" => dout <= "011";
+ when "1000000000110110" => dout <= "101";
+ when "1000000000110000" => dout <= "011";
+ when "1000000001110000" => dout <= "100";
+ when "1000000010110000" => dout <= "101";
+ when "1000000111110000" => dout <= "100";
+ when "1000000100110110" => dout <= "110";
+ when "1000000100110000" => dout <= "100";
+ when "1000000101110000" => dout <= "101";
+ when "1000000110110000" => dout <= "110";
+ when "1000001111110000" => dout <= "011";
+ when "1000001100110110" => dout <= "101";
+ when "1000001100110000" => dout <= "011";
+ when "1000001101110000" => dout <= "100";
+ when "1000001110110000" => dout <= "101";
+ when "0011010000000000" => dout <= "010";
+ when "0011010100000000" => dout <= "011";
+ when "1111011011010000" => dout <= "010";
+ when "1111011000010110" => dout <= "100";
+ when "1111011000010000" => dout <= "010";
+ when "1111011001010000" => dout <= "011";
+ when "1111011010010000" => dout <= "100";
+ when "1111011111010000" => dout <= "010";
+ when "1111011100010110" => dout <= "100";
+ when "1111011100010000" => dout <= "010";
+ when "1111011101010000" => dout <= "011";
+ when "1111011110010000" => dout <= "100";
+ when "1010010000000000" => dout <= "001";
+ when "1010010100000000" => dout <= "001";
+ when "1010011000000000" => dout <= "001";
+ when "1010011100000000" => dout <= "001";
+ when "1010111000000000" => dout <= "001";
+ when "1010111100000000" => dout <= "001";
+ when "1010110000000000" => dout <= "001";
+ when "1010110100000000" => dout <= "001";
+ when "1010101000000000" => dout <= "001";
+ when "1010101100000000" => dout <= "001";
+ when "1111001000000000" => dout <= "001";
+ when "1111001100000000" => dout <= "001";
+ when "0110000000000000" => dout <= "001";
+ when "0110000100000000" => dout <= "001";
+ when "1100100000000000" => dout <= "001";
+ when "1100100100000000" => dout <= "001";
+ when "0110001000000000" => dout <= "001";
+ when "0110110000000000" => dout <= "010";
+ when "0110110100000000" => dout <= "001";
+ when "0110111000000000" => dout <= "001";
+ when "0110111100000000" => dout <= "001";
+ when "0000111100000000" => dout <= "001";
+ when "0110001100000000" => dout <= "001";
+ when "0110010000000000" => dout <= "001";
+ when "0110010100000000" => dout <= "001";
+ when "0110011000000000" => dout <= "001";
+ when "0110011100000000" => dout <= "001";
+ when "1000001000000000" => dout <= "001";
+ when "1101011000000000" => dout <= "001";
+ when "1111000100000000" => dout <= "001";
+ when "1100000000000000" => dout <= "001";
+ when "1100000100000000" => dout <= "001";
+ when others => dout <= "111";
+ end case;
+ end process;
+end rtl;
\ No newline at end of file
diff --git a/common/CPU/cpu86/proc_rtl.vhd b/common/CPU/cpu86/proc_rtl.vhd
new file mode 100644
index 00000000..e7cbbe7a
--- /dev/null
+++ b/common/CPU/cpu86/proc_rtl.vhd
@@ -0,0 +1,2758 @@
+-------------------------------------------------------------------------------
+-- CPU86 - VHDL CPU8088 IP core --
+-- Copyright (C) 2002-2008 HT-LAB --
+-- --
+-- Contact/bugs : http://www.ht-lab.com/misc/feedback.html --
+-- Web : http://www.ht-lab.com --
+-- --
+-- CPU86 is released as open-source under the GNU GPL license. This means --
+-- that designs based on CPU86 must be distributed in full source code --
+-- under the same license. Contact HT-Lab for commercial applications where --
+-- source-code distribution is not desirable. --
+-- --
+-------------------------------------------------------------------------------
+-- --
+-- This library is free software; you can redistribute it and/or --
+-- modify it under the terms of the GNU Lesser General Public --
+-- License as published by the Free Software Foundation; either --
+-- version 2.1 of the License, or (at your option) any later version. --
+-- --
+-- This library 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 --
+-- Lesser General Public License for more details. --
+-- --
+-- Full details of the license can be found in the file "copying.txt". --
+-- --
+-- You should have received a copy of the GNU Lesser General Public --
+-- License along with this library; if not, write to the Free Software --
+-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --
+-- --
+-------------------------------------------------------------------------------
+-- Version : 1.0a 02/08/2009 Fixed CALL [REG] Instruction --
+-------------------------------------------------------------------------------
+LIBRARY ieee;
+USE ieee.std_logic_1164.ALL;
+USE ieee.std_logic_unsigned.ALL;
+USE ieee.std_logic_arith.ALL;
+
+USE work.cpu86pack.ALL;
+USE work.cpu86instr.ALL;
+
+ENTITY proc IS
+ PORT(
+ clk : IN std_logic;
+ flush_ack : IN std_logic;
+ instr : IN instruction_type;
+ inta1 : IN std_logic;
+ irq_req : IN std_logic;
+ latcho : IN std_logic;
+ reset : IN std_logic;
+ rw_ack : IN std_logic;
+ status : IN status_out_type;
+ clrop : OUT std_logic;
+ decode_state : OUT std_logic;
+ flush_coming : OUT std_logic;
+ flush_req : OUT std_logic;
+ intack : OUT std_logic;
+ iomem : OUT std_logic;
+ irq_blocked : OUT std_logic;
+ opc_req : OUT std_logic;
+ path : OUT path_in_type;
+ proc_error : OUT std_logic;
+ read_req : OUT std_logic;
+ word : OUT std_logic;
+ write_req : OUT std_logic;
+ wrpath : OUT write_in_type
+ );
+END proc ;
+
+architecture rtl of proc is
+
+ type state_type is (
+ Sopcode,Sdecode,
+ Sreadmem,Swritemem,
+ Sexecute,Sflush,Shalt);
+
+ -- Declare current and next state signals
+ signal current_state: state_type ;
+ signal next_state : state_type ;
+ signal second_pass : std_logic; -- if 1 go round the loop again
+ signal second_pass_s: std_logic; -- Comb version
+
+ signal rep_set_s : std_logic; -- Start of REP Instruction, check CX when set
+ signal rep_clear_s : std_logic; -- Signal end of REP Instruction
+ signal rep_flag : std_logic; -- REPEAT Flag
+ signal rep_z_s : std_logic; -- Z value of REP instruction
+ signal rep_zl_s : std_logic; -- Latched Z value of REP
+
+ signal flush_coming_s : std_logic; -- Signal that a flush is imminent (don't bother filling the queue)
+ signal irq_blocked_s: std_logic; -- Indicate that IRQ will be blocked during the next instruction
+ -- This is required for pop segment etc instructions.
+
+ signal intack_s : std_logic; -- Signal asserted during 8 bits vector read, this occurs during
+ -- the second INTA cycle
+
+ signal passcnt_s : std_logic_vector(7 downto 0); -- Copy of CL register
+ signal passcnt : std_logic_vector(7 downto 0);
+
+ signal wrpath_s : write_in_type; -- combinatorial
+ signal wrpathl_s : write_in_type; -- Latched version of wrpath_s
+ signal path_s : path_in_type; -- combinatorial
+ signal proc_error_s : std_logic; -- Processor decode error
+ signal proc_err_s : std_logic; -- Processor decode error latch signal
+ signal iomem_s : std_logic; -- IO/~M cycle
+
+-- alias ZFLAG : std_logic is status.flag(6); -- doesn't work, why not??
+ signal flush_req_s : std_logic; -- Flush Prefetch queue request
+ signal flush_reql_s : std_logic; -- Latched version of Flush request
+
+begin
+
+ proc_error <= proc_err_s; -- connect to outside world
+ flush_req <= flush_req_s;
+
+ ----------------------------------------------------------------------------
+ clocked : process(clk,reset)
+ ----------------------------------------------------------------------------
+ begin
+ if (reset = '1') then
+ current_state <= Sopcode;
+ path <= ((others =>'0'),(others =>'0'),(others =>'0'),(others =>'0'),
+ (others =>'0'));
+ wrpathl_s <= ('0','0','0','0','0','0','0');
+ word <= '0'; -- default to 8 bits
+ proc_err_s <= '0'; -- Processor decode error
+ iomem <= '0'; -- default to memory access
+ second_pass <= '0'; -- default 1 pass
+ flush_reql_s<= '0'; -- flush prefetch queue
+ passcnt <= X"01"; -- Copy of CL register used in rot/shft
+ rep_flag <= '0'; -- REP instruction running flag
+ rep_zl_s <= '0'; -- REP latched z bit
+ flush_coming<= '0'; -- flush approaching
+ irq_blocked <= '1'; -- IRQ blocking for next instruction
+ intack <= '0'; -- Second INTA cycle signal
+
+ elsif rising_edge(clk) then
+ current_state<= next_state;
+ proc_err_s <= proc_error_s or proc_err_s; -- Latch Processor error, cleared by reset only
+ flush_reql_s <= flush_req_s; -- Latch Flush_request signal
+
+ if current_state=Sdecode then -- Latch write pulse and path settings
+ second_pass <= second_pass_s; -- latch pass signal
+ word <= path_s.datareg_input(3); -- word <= w bit
+ path <= path_s;
+ wrpathl_s <= wrpath_s;
+ passcnt <= passcnt_s;
+ irq_blocked <=irq_blocked_s; -- Signal to block IRQ during next instruction
+ intack <= intack_s; -- Second INTA cycle signal
+ end if;
+
+ if ((current_state=Sdecode) or (current_state=Sexecute)) then--Latch IOMEM signal
+ iomem <= iomem_s; -- Latch IOM signal
+ flush_coming<=flush_coming_s; -- flush approaching
+ end if;
+
+ if rep_set_s='1' then -- Set/Reset REP flag
+ rep_flag <= '1';
+ elsif rep_clear_s='1' then
+ rep_flag <= '0';
+ end if;
+
+ if rep_set_s='1' then
+ rep_zl_s <= rep_z_s; -- Latch Z value of REP instruction
+ end if;
+
+ end if;
+
+ end process clocked;
+
+ ----------------------------------------------------------------------------
+ nextstate : process (current_state, latcho, rw_ack, flush_ack, instr, status,wrpathl_s, second_pass,irq_req,
+ passcnt, flush_reql_s, rep_flag, rep_zl_s, inta1)
+ ----------------------------------------------------------------------------
+ begin
+ -- Default Assignment
+ opc_req <= '0';
+ read_req <= '0';
+ write_req <= '0';
+
+ wrpath_s <= ('0','0','0','0','0','0','0'); -- Default all writes disabled
+ wrpath <= ('0','0','0','0','0','0','0'); -- Combinatorial
+ path_s <= ((others =>'0'),(others =>'0'),(others =>'0'),(others =>'0'),
+ (others =>'0'));
+ proc_error_s<= '0';
+ iomem_s <= '0'; -- IO/~M default to memory access
+ flush_req_s <= '0'; -- Flush Prefetch queue request
+ passcnt_s <= X"01"; -- init to 1
+ rep_set_s <= '0'; -- default no repeat
+ rep_clear_s <= '0'; -- default no clear
+ rep_z_s <= '0'; -- REP instruction Z bit
+ flush_coming_s<='0'; -- don't fill the instruction queue
+ irq_blocked_s<='0'; -- default, no block IRQ
+ clrop <= '0'; -- Clear Segment override flag
+ second_pass_s<='0'; -- HT0912,
+ intack_s <= '0'; -- Signal asserted during INT second INTA cycle
+ decode_state<= '0'; -- Decode stage for signal spy only
+
+ case current_state is
+
+ ----------------------------------------------------------------------------
+ -- Get Opcode from BIU
+ ----------------------------------------------------------------------------
+ when Sopcode =>
+
+ second_pass_s<='0';
+ opc_req <= '1';
+
+ if (latcho = '0') then
+ next_state <= Sopcode; -- Wait
+ else
+ next_state <= Sdecode; -- Decode instruction
+ end if;
+
+ ----------------------------------------------------------------------------
+ -- Opcode received, decode instruction
+ -- Set Path (next state)
+ -- Set wrpath_s, lacthed as this stage, enabled only at Sexecute
+ ----------------------------------------------------------------------------
+ when Sdecode =>
+
+ if second_pass='1' then
+ wrpath <= wrpathl_s; -- Assert write strobe(s) during first & second pass
+ else
+ decode_state <= '1'; -- Asserted during first decode stage
+ end if;
+
+ case instr.ireg is
+
+ ---------------------------------------------------------------------------------
+ -- IN Port Instruction 0xE4..E5, 0xEC..ED
+ -- Use fake xmod and rm setting for fixed port number
+ ---------------------------------------------------------------------------------
+ when INFIXED0 | INFIXED1 | INDX0 | INDX1 =>
+ second_pass_s <= '0';
+ iomem_s <= '1'; -- Select IO cycle
+
+ path_s.datareg_input<= MDBUS_IN & instr.ireg(0) & "000"; -- dimux & w & seldreg AX/AL=000
+
+ if instr.ireg(3)='0' then -- 0=Fixed, 1=DX
+ path_s.ea_output <= PORT_00_EA & DONTCARE(2 downto 0);-- dispmux & eamux(4) & segop 11=00:EA
+ else -- 1=DX
+ path_s.ea_output <= PORT_00_DX & DONTCARE(2 downto 0);-- dispmux & eamux(4) & segop 10=00:DX
+ end if;
+
+ wrpath_s.wrd <= '1'; -- Write to Data Register
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+
+ next_state <= Sreadmem; -- start read cycle
+
+ ---------------------------------------------------------------------------------
+ -- XLAT Instruction
+ -- AL<= SEG:[BX+AL]
+ ---------------------------------------------------------------------------------
+ when XLAT =>
+ second_pass_s <= '0';
+
+ path_s.datareg_input<= MDBUS_IN & '0' & REG_AX(2 downto 0); -- dimux & w & seldreg AX/AL=000
+
+ path_s.ea_output<= "0001111011"; -- EA=BX+AL, dispmux(2) & eamux(4) & [flag]&segop(2)
+
+ wrpath_s.wrd <= '1'; -- Write to Data Register
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+
+ next_state <= Sreadmem; -- start read cycle
+
+ ---------------------------------------------------------------------------------
+ -- OUT Port Instruction 0xE6..E7, 0xEE..EF
+ -- Use fake xmod and rm setting for fixed port number
+ ---------------------------------------------------------------------------------
+ when OUTFIXED0 | OUTFIXED1 | OUTDX0 | OUTDX1 =>
+ second_pass_s <= '0';
+ iomem_s <= '1'; -- Select IO cycle
+
+ path_s.datareg_input<= DONTCARE(2 downto 0) & instr.ireg(0) & DONTCARE(2 downto 0); -- dimux & w & seldreg Only need to set W
+
+ path_s.alu_operation<= "0000" & DONTCARE(3 downto 0) & ALU_PASSA; -- selalua & selalub & aluopr selalua=AX/AL
+ path_s.dbus_output <= ALUBUS_OUT; --{eabus(0)&} domux setting
+
+ if instr.ireg(3)='0' then -- 0=Fixed, 1=DX
+ path_s.ea_output <= PORT_00_EA & DONTCARE(2 downto 0);-- dispmux & eamux(4) & segop 11=00:EA
+ else -- 1=DX
+ path_s.ea_output <= PORT_00_DX & DONTCARE(2 downto 0);-- dispmux & eamux(4) & segop 10=00:DX
+ end if;
+
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+
+ next_state <= Swritemem; -- start write cycle
+
+ ---------------------------------------------------------------------------------
+ -- Increment/Decrement Register, word only!
+ ---------------------------------------------------------------------------------
+ when INCREG0 |INCREG1 |INCREG2 |INCREG3 | INCREG4 |INCREG5 |INCREG6 |INCREG7 |
+ DECREG0 |DECREG1 |DECREG2 |DECREG3 | DECREG4 |DECREG5 |DECREG6 |DECREG7 =>
+ second_pass_s <= '0';
+
+ path_s.datareg_input<= ALUBUS_IN & '1' & instr.reg; -- dimux & w & seldreg
+
+ -- instr.ireg(5..3) contains the required operation, ALU_INBUSB=X"0001"
+ -- Note ALU_INC is generic for INC/DEC
+ path_s.alu_operation<= '0'&instr.reg & REG_CONST1 & ALU_INC(6 downto 3)&instr.ireg(5 downto 3); -- selalua & selalub & aluopr
+
+ path_s.ea_output <= NB_CS_IP; -- IPREG+NB ADDR=CS:IP
+
+ wrpath_s.wrd <= '1'; -- Update register
+ wrpath_s.wrcc <= '1'; -- Update Flag register
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+
+ next_state <= Sexecute;
+
+ -----------------------------------------------------------------------------
+ -- Shift/Rotate Instructions
+ -- Operation define in MODRM REG bits
+ -- Use MODRM reg bits
+ -- bit 0=b/w, bit1=0 then count=1 else count=cl
+ -- if cl=00 then don't write to CC register
+ -----------------------------------------------------------------------------
+ when SHFTROT0 | SHFTROT1 | SHFTROT2 | SHFTROT3 =>
+
+ if instr.reg="110" then -- Not supported/defined
+ proc_error_s<='1'; -- Assert Bus Error Signal
+ -- pragma synthesis_off
+ assert not (now > 0 ns) report "**** Illegal SHIFT/ROTATE instruction (proc) ***" severity warning;
+ -- pragma synthesis_on
+ end if;
+
+ if instr.xmod="11" then -- Immediate to Register r/m=reg field
+
+ path_s.datareg_input<= ALUBUS_IN & instr.ireg(0) & instr.rm; -- dimux & w & seldreg Note RM=Destination!!
+
+ path_s.ea_output <= NB_CS_IP; -- IPREG+NB ADDR=CS:IP
+
+ if (second_pass='0') then -- first pass, load reg into alureg
+
+ if (instr.ireg(1)='1' and status.cl=X"00") then
+ second_pass_s <= '0'; -- No second pass if cl=0
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Sexecute; -- terminate
+ else
+ second_pass_s <= '1'; -- need another pass
+ next_state <= Sdecode; -- round the loop again
+ end if;
+
+ -- Load instr.rm register into ALUREG
+ path_s.alu_operation<= DONTCARE(3 downto 0) & '0'&instr.rm & ALU_REGL; -- selalua(4) & selalub(4) & aluopr(7)
+ wrpath_s.wralu <= '1';
+
+ if (instr.ireg(1)='1') then
+ passcnt_s <= status.cl; -- Load CL loop counter
+ end if; -- else passcnt_s=1;
+
+
+ else -- second pass, terminate or go around the loop again
+
+ -- selalua & selalu are dontcare, instruction is V+001+instr.reg
+ -- ALU_ROL(6 downto 4) is generic for all shift/rotate
+ -- Instruction=Constant & V_Bit & modrm.reg(5 downto 3)
+ path_s.alu_operation<= DONTCARE(3 downto 0) & '0'&instr.rm & ALU_ROL(6 downto 4)& instr.ireg(1) & instr.reg; -- selalua(4) & selalub(4) & aluopr(7)
+
+ if (passcnt=X"00") then -- Check if end of shift/rotate
+ second_pass_s <= '0'; -- clear
+ wrpath_s.wrcc <= '1'; -- Update Status Register after last shift/rot
+ wrpath_s.wrd <= '1'; -- Write shift/rotate results to Data Register
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Sexecute; -- terminate
+ else
+ second_pass_s <= '1'; -- need another pass
+ wrpath_s.wralu <= '1';
+ wrpath_s.wrcc <= '1';
+ passcnt_s <= passcnt - '1';
+ next_state <= Sdecode; -- round the loop again
+ end if;
+
+ end if;
+
+ else -- Destination and source is memory, use ALUREG
+
+ path_s.datareg_input<= MDBUS_IN & instr.ireg(0) & DONTCARE(2 downto 0); -- ver 0.69, path& w! seldreg=don'tcare
+
+ path_s.dbus_output <= ALUBUS_OUT; -- {eabus(0)&} domux setting
+ path_s.ea_output <= NB_DS_EA; -- dispmux & eamux & segop
+
+ if (second_pass='0') then -- first pass, load memory operand into alureg
+
+ if (instr.ireg(1)='1' and status.cl=X"00") then
+ second_pass_s <= '0'; -- No second pass if cl=0
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Sexecute; -- terminate
+ else
+ second_pass_s <= '1'; -- need another pass
+ next_state <= Sreadmem; -- start read cycle
+ end if;
+
+ -- Load memory into ALUREG
+ path_s.alu_operation<= DONTCARE(3 downto 0) & REG_MDBUS & ALU_REGL; -- selalua(4) & selalub(4) & aluopr(7)
+ wrpath_s.wralu <= '1'; -- ver 0.69, write MDBUS to ALUREG
+
+ if (instr.ireg(1)='1') then
+ passcnt_s <= status.cl; -- Load CL loop counter
+ end if; -- else passcnt_s=1;
+
+ else -- second pass, MDBUS contains memory byte
+
+ -- selalua & selalu are dontcare
+ -- ALU_ROL(6 downto 4) is generic for all shift/rotate
+ path_s.alu_operation<= DONTCARE(3 downto 0) & '0'&instr.rm & ALU_ROL(6 downto 4)& instr.ireg(1) & instr.reg; -- selalua(4) & selalub(4) & aluopr(7)
+
+ wrpath_s.wrcc <= '1'; -- Update Status Register after each shift/rot
+
+ --if (passcnt=X"01") then -- Check if end of shift/rotate
+ if (passcnt=X"00") then -- ver 0.69, Check if end of shift/rotate
+ second_pass_s <= '0'; -- clear
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Swritemem; -- write result to memory & terminate
+ else
+ passcnt_s <= passcnt - '1';
+ second_pass_s <= '1';
+ wrpath_s.wralu<= '1'; -- Update ALUREG
+ next_state <= Sdecode; -- round the loop again
+ end if;
+
+ end if;
+
+ end if;
+
+ ---------------------------------------------------------------------------------
+ -- Immediate to Register
+ ---------------------------------------------------------------------------------
+ when MOVI2R0 | MOVI2R1 |MOVI2R2 |MOVI2R3 |MOVI2R4 | MOVI2R5 | MOVI2R6 | MOVI2R7 |
+ MOVI2R8 | MOVI2R9 |MOVI2R10|MOVI2R11|MOVI2R12| MOVI2R13| MOVI2R14| MOVI2R15 =>
+
+ second_pass_s <= '0';
+ path_s.datareg_input<= DATAIN_IN & instr.ireg(3) & instr.reg; -- dimux & w & seldreg
+ path_s.ea_output <= NB_CS_IP; -- IPREG+NB ADDR=CS:IP
+
+ wrpath_s.wrd <= '1'; -- Write to Data Register
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+
+ next_state <= Sexecute;
+
+ ---------------------------------------------------------------------------------
+ -- Immediate to Register/Memory 0xC6, 0xC7
+ -- Data is routed from drmux->dibus->dbusdp_out
+ ---------------------------------------------------------------------------------
+ when MOVI2RM0 | MOVI2RM1 =>
+
+ second_pass_s <= '0';
+ path_s.datareg_input<= DATAIN_IN & instr.ireg(0) & DONTCARE(2 downto 0); -- dimux & w & seldreg (only dimux, the rest is don't care)
+ -- change to instr.ireg(0) & instr.reg ???
+ path_s.dbus_output <= DIBUS_OUT; --{eabus(0)&} domux setting
+ path_s.ea_output <= NB_DS_EA; -- dispmux & eamux & segop (unless Segment OP flag is set)
+
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+
+ next_state <= Swritemem; -- start write cycle
+
+ ---------------------------------------------------------------------------------
+ -- Memory to Accu and Accu to Memory AL, AX, not AH! 0xA0..0xA3
+ -- Use fake xmod and rm setting
+ -- Use instruction but (4..3)=000 as register selector
+ ---------------------------------------------------------------------------------
+ when MOVM2A0 | MOVM2A1 | MOVA2M0 | MOVA2M1 =>
+
+ second_pass_s <= '0';
+ path_s.datareg_input<= MDBUS_IN & instr.ireg(0) & instr.reg; -- dimux & w & seldreg (don't care for write cycle)
+
+ path_s.alu_operation<= '0'&instr.reg & DONTCARE(3 downto 0) & ALU_PASSA; -- selalua & selalub & aluopr (don't care for read cycle)
+ path_s.dbus_output <= ALUBUS_OUT; --{eabus(0)&} domux setting (don't care for read cycle)
+
+ path_s.ea_output <= NB_DS_EA; -- dispmux & eamux & segop (unless Segment OP flag is set)
+
+ if instr.ireg(1)='0' then -- 0= memory to Accu, Read Cycle
+ wrpath_s.wrd <= '1'; -- Write Memory to Data Register
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+
+ next_state <= Sreadmem; -- start read cycle
+ else -- 1=Accu to Memory, Write cycle
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+
+ next_state <= Swritemem; -- start write cycle
+ end if;
+
+ ---------------------------------------------------------------------------------
+ -- Move Register/Memory to/from Register 0x88..0x8B
+ ---------------------------------------------------------------------------------
+ when MOVRM2R0 | MOVRM2R1 | MOVRM2R2 | MOVRM2R3 =>
+
+ second_pass_s <= '0';
+ if instr.xmod="11" then -- Register to Register rm=reg field
+ if instr.ireg(1)='0' then -- Check 'd' bit, 0-> SRC=Reg, DEST=rm
+ path_s.datareg_input<= ALUBUS_IN & instr.ireg(0) & instr.rm; -- dimux & w & seldreg
+ path_s.alu_operation<= '0'&instr.reg & DONTCARE(3 downto 0) & ALU_PASSA; -- selalua & selalub & aluopr
+ else -- 'd'=1 SRC=rm, DEST=Reg
+ path_s.datareg_input<= ALUBUS_IN & instr.ireg(0) & instr.reg; -- dimux & w & seldreg
+ path_s.alu_operation<= '0'&instr.rm & DONTCARE(3 downto 0) & ALU_PASSA; -- selalua & selalub & aluopr
+ end if;
+ path_s.ea_output <= NB_CS_IP; -- IPREG+NB ADDR=CS:IP
+
+ wrpath_s.wrd <= '1'; -- Write Data Register to Data Register
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+
+ next_state <= Sexecute;
+
+ else -- Source is memory
+ if instr.ireg(1)='0' then -- Check 'd' bit, 0-> SRC=Reg, DEST=rm, Write Cycle
+ path_s.alu_operation<= '0'&instr.reg & DONTCARE(3 downto 0) & ALU_PASSA; -- selalua & selalub & aluopr
+ path_s.dbus_output <= ALUBUS_OUT; --{eabus(0)&} domux setting
+ path_s.datareg_input<= DONTCARE(2 downto 0) & instr.ireg(0) & DONTCARE(2 downto 0); -- dimux & w & seldreg
+ -- (only need w, the reset don't care)
+ path_s.ea_output <= NB_DS_EA; -- dispmux & eamux & segop (unless Segment OP flag is set)
+
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+
+ next_state <= Swritemem; -- start write cycle
+
+ else -- 'd'=1 SRC=rm, DEST=Reg, Read Cycle
+ path_s.datareg_input<= MDBUS_IN & instr.ireg(0) & instr.reg; -- dimux & w & seldreg
+ path_s.alu_operation<= '0'&instr.rm & DONTCARE(3 downto 0) & ALU_PASSA; -- selalua & selalub & aluopr
+
+ path_s.ea_output <= NB_DS_EA; -- dispmux & eamux & segop (unless Segment OP flag is set)
+
+ wrpath_s.wrd <= '1'; -- Write Memory to Data Register
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+
+ next_state <= Sreadmem; -- start read cycle
+ end if;
+
+
+ end if;
+
+ ---------------------------------------------------------------------------------
+ -- Move Segment register to data register or memory
+ ---------------------------------------------------------------------------------
+ when MOVS2RM =>
+
+ second_pass_s <= '0';
+ if instr.xmod="11" then -- Segment Register to Data Register , rm=reg field
+
+ path_s.datareg_input<= '1'& instr.reg(1 downto 0) & '1' & instr.rm; -- dimux & w & seldreg
+ path_s.ea_output <= NB_CS_IP; -- IPREG+NB ADDR=CS:IP
+
+ wrpath_s.wrd <= '1'; -- Write Seg to Data Register
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+
+ next_state <= Sexecute;
+ else -- Segment Register to memory indexed by rm
+
+ path_s.datareg_input<= '1'& instr.reg(1 downto 0) & '1' & DONTCARE(2 downto 0); -- dimux only -- [dimux(3) & w & seldreg(3)]
+ path_s.dbus_output <= DIBUS_OUT; --(Odd/Even) domux setting
+ path_s.ea_output <= NB_DS_EA; -- dispmux & eamux & segop (unless Segment OP flag is set)
+
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+
+ next_state <= Swritemem; -- start write cycle
+ end if;
+
+ ---------------------------------------------------------------------------------
+ -- Register or Memory to Segment Register
+ -- In case of memory, stalls until operand is read from memory
+ ---------------------------------------------------------------------------------
+ when MOVRM2S =>
+
+ irq_blocked_s <= '1'; -- Block IRQ if asserted during next instr.
+
+ second_pass_s <= '0';
+ if instr.reg(1 downto 0)="01" then
+ proc_error_s<='1'; -- if segment register = CS report error
+ -- pragma synthesis_off
+ report "MOVRM2S : MOV CS,REG/Memory not valid" severity warning;
+ -- pragma synthesis_on
+ end if;
+
+ path_s.datareg_input<= DONTCARE(2 downto 0)& '1' & DONTCARE(2 downto 0); -- dimux & w=1 & seldreg
+
+ if instr.xmod="11" then -- Register to Segment Register , rm=reg field
+
+ path_s.alu_operation<= '0'&instr.rm & DONTCARE(3 downto 0) & ALU_PASSA; --selalua & selalub & aluopr
+ path_s.segreg_input <= SALUBUS_IN & instr.reg(1 downto 0); -- simux & selsreg
+
+ path_s.ea_output <= NB_CS_IP; -- IPREG+NB ADDR=CS:IP
+
+ wrpath_s.wrs <= '1'; -- Write Data Register to Segment Register
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+
+ next_state <= Sexecute;
+
+ else -- Memory to Segment Register
+
+ path_s.segreg_input <= SMDBUS_IN & instr.reg(1 downto 0); -- simux & selsreg
+
+ path_s.ea_output <= NB_DS_EA; -- dispmux & eamux & segop (unless Segment OP flag is set)
+
+ wrpath_s.wrs <= '1'; -- Write Memory to Segment Register
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+
+ next_state <= Sreadmem; -- start read cycle
+ end if;
+
+ ---------------------------------------------------------------------------------
+ -- Load Effective Address in Data Register
+ -- mod=11 result in proc_error
+ ---------------------------------------------------------------------------------
+ when LEA =>
+ second_pass_s <= '0';
+
+ if instr.xmod="11" then -- Register to Register rm=reg field
+ proc_error_s<='1'; -- Assert Bus Error Signal
+ -- pragma synthesis_off
+ assert not (now > 0 ns) report "**** Illegal LEA operand (mod=11) (proc) ***" severity warning;
+ -- pragma synthesis_on
+ end if; -- Transfer Effective addresss (EABUS) to data register
+
+ path_s.datareg_input<= EABUS_IN & '1' & instr.reg; -- dimux & w & seldreg
+ path_s.ea_output <= NB_DS_EA; -- dispmux & eamux & segop
+
+ wrpath_s.wrd <= '1'; -- Write EABUS to Data Register
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+
+ next_state <= Sexecute;
+
+ ---------------------------------------------------------------------------------
+ -- Load Effective Address in ES/DS:DEST_REGISTER
+ -- mod=11 result in proc_error
+ -- TEMP <= readmem(ea) ; PASS1 (required for cases like LES SI,[SI] )
+ -- REG <= TEMP ; PASS2
+ -- ES/DS<= readmem(ea+2)
+ ---------------------------------------------------------------------------------
+ when LES | LDS =>
+
+ if instr.xmod="11" then -- Register to Register rm=reg field
+ proc_error_s<='1'; -- Assert Bus Error Signal
+ -- pragma synthesis_off
+ assert not (now > 0 ns) report "**** Illegal LES/LDS operand (mod=11) (proc) ***" severity warning;
+ -- pragma synthesis_on
+ end if;
+
+ path_s.alu_operation<= DONTCARE(3 downto 0) & REG_MDBUS & ALU_TEMP;-- selalua(4) & selalub(4) & aluopr
+
+ if (second_pass='0') then -- first pass reg<=mem(ea)
+ second_pass_s <= '1'; -- need another pass
+
+ path_s.datareg_input<= MDBUS_IN & '1' & instr.reg;-- dimux & w & seldreg
+
+ path_s.ea_output<="0000001001"; -- dispmux(3) & eamux(4)=EA & dis_opflag & segop[1:0]
+ wrpath_s.wrtemp <= '1'; -- Write reg value to alu_temp first
+ next_state <= Sreadmem; -- start read to read temp<=EA
+ else
+ second_pass_s <= '0'; -- clear
+
+ path_s.datareg_input<= ALUBUS_IN & '1' & instr.reg;-- dimux & w & seldreg
+ path_s.ea_output<="0000011001"; -- dispmux(3) & eamux(4)=EA+2 & dis_opflag & segop[1:0]
+ -- Second Pass ES/DS<=mem(ea+2)
+ if instr.ireg(0)='0' then -- C4=LES
+ path_s.segreg_input <= SMDBUS_IN & ES_IN(1 downto 0); -- simux & selsreg=ES
+ else -- C5=LDS
+ path_s.segreg_input <= SMDBUS_IN & DS_IN(1 downto 0); -- simux & selsreg=DS
+ end if;
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ wrpath_s.wrd <= '1'; -- Update Reg<=temp
+ wrpath_s.wrs <= '1'; -- Update ES/DS Register
+ next_state <= Sreadmem;
+ end if;
+
+ ---------------------------------------------------------------------------------
+ -- Convert AL to AX, AX -> DX:AX
+ -- Flags are not affected
+ ---------------------------------------------------------------------------------
+ when CBW | CWD =>
+ second_pass_s <= '0';
+
+ -- Note ALU_SEXT(6 downto 4) is generic for CBW and CWD
+ path_s.alu_operation<= REG_AX & DONTCARE(3 downto 0) & ALU_SEXT(6 downto 4) & instr.ireg(3 downto 0) ;-- selalua & selalub & aluopr
+
+ if (instr.ireg(0)='0') then -- if 0 then CBW else CWD
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_AX(2 downto 0);-- dimux & w & seldreg Note RM=Destination!!
+ else
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_DX(2 downto 0);-- dimux & w & seldreg Note RM=Destination!!
+ end if;
+
+ path_s.ea_output <= NB_CS_IP; -- IPREG+NB ADDR=CS:IP
+
+ wrpath_s.wrd <= '1'; -- Write Data Register to Data Register
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+
+ next_state <= Sexecute;
+
+ ---------------------------------------------------------------------------------
+ -- Convert AL
+ -- Use bit 4 of instruction to drive W bit
+ ---------------------------------------------------------------------------------
+ when AAS | DAS | AAA | DAA | AAM | AAD =>
+
+ passcnt_s <= passcnt - '1';
+
+ path_s.ea_output <= NB_CS_IP; -- IPREG+NB ADDR=CS:IP
+ path_s.datareg_input<= ALUBUS_IN & instr.ireg(4) & REG_AX(2 downto 0);-- dimux & w & seldreg Note RM=Destination!!
+ path_s.alu_operation<= REG_AX & DONTCARE(3 downto 0) & ALU_DAA(6 downto 4)&instr.ireg(0)&instr.ireg(5 downto 3);-- selalua & selalub & aluopr
+
+ if (second_pass='0') then -- first pass
+
+ if (instr.ireg=AAM) then -- AAM instruction only
+ second_pass_s <= '1'; -- need another pass
+ wrpath_s.wralu <= '1'; -- Write Data to ALUREG, only used for AAM (uses divider)
+ passcnt_s <= "000"&DIV_MCD_C; -- Serial delay
+ next_state <= Sdecode; -- round the loop again
+ else
+ second_pass_s <= '0';
+ wrpath_s.wrcc <= '1'; -- Update Status Register
+ wrpath_s.wrd <= '1'; -- Write Data Register to Data Register
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Sexecute; -- terminate
+ end if;
+
+ else
+ second_pass_s <= '1';
+ if (passcnt=X"00") then -- Divider Done?
+ second_pass_s <= '0';
+ wrpath_s.wrcc <= '1'; -- Update Status Register
+ wrpath_s.wrd <= '1'; -- Write Data Register to Data Register
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Sexecute; -- terminate
+ else
+ next_state <= Sdecode; -- Version 0.78
+ end if;
+ end if;
+
+
+ ---------------------------------------------------------------------------------
+ -- Segment Override Prefix
+ ---------------------------------------------------------------------------------
+ when SEGOPES | SEGOPCS | SEGOPSS | SEGOPDS =>
+
+ irq_blocked_s <= '1'; -- Block IRQ if asserted during next instr.
+ second_pass_s <= '0';
+ path_s.datareg_input<= DONTCARE(2 downto 0) & instr.ireg(0) & DONTCARE(2 downto 0); -- dimux & w & seldreg
+
+ path_s.ea_output <= "000"&DONTCARE(3 downto 0) & '0' & instr.ireg(4 downto 3); -- dispmux & eamux(4) & [flag]&segop[1:0]
+
+ wrpath_s.wrop <= '1'; -- Write to Override Prefix Register
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+
+ next_state <= Sexecute;
+
+ ---------------------------------------------------------------------------------
+ -- Halt Instruction, wait for NMI, INTR, Reset
+ ---------------------------------------------------------------------------------
+ when HLT =>
+
+ second_pass_s <= '0';
+ path_s.ea_output<= NB_CS_IP;
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Sexecute;
+
+ ---------------------------------------------------------------------------------
+ -- ADD/ADC/SUB/SBB/CMP/AND/OR/XOR Register/Memory <- Register/Memory
+ -- TEST same as AND without returning any result (wrpath_s.wrd is not asserted)
+ ---------------------------------------------------------------------------------
+ when ADDRM2R0 | ADDRM2R1 | ADDRM2R2 | ADDRM2R3 | ADCRM2R0 | ADCRM2R1 | ADCRM2R2 | ADCRM2R3 |
+ SUBRM2R0 | SUBRM2R1 | SUBRM2R2 | SUBRM2R3 | SBBRM2R0 | SBBRM2R1 | SBBRM2R2 | SBBRM2R3 |
+ CMPRM2R0 | CMPRM2R1 | CMPRM2R2 | CMPRM2R3 | ANDRM2R0 | ANDRM2R1 | ANDRM2R2 | ANDRM2R3 |
+ ORRM2R0 | ORRM2R1 | ORRM2R2 | ORRM2R3 | XORRM2R0 | XORRM2R1 | XORRM2R2 | XORRM2R3 |
+ TESTRMR0 | TESTRMR1 =>
+
+ if instr.xmod="11" then -- Register to Register rm=reg field
+ second_pass_s <= '0';
+
+ if (instr.ireg(1)='1') then -- Check 'd' bit, if 1 dest=reg else r/m
+ path_s.datareg_input<= ALUBUS_IN & instr.ireg(0) & instr.reg; -- dimux & w & seldreg Note REG=Destination!
+ -- Note aluopr = bit 5 to 3 of opcode
+ -- Note ALU_ADD(6 downto 4) is generic for all sub types
+ -- Note the selalua and selalub values are important for the SUB and CMP instructions!
+ -- It would have been nice if the position was fixed in the opcode!
+ path_s.alu_operation<= '0'&instr.reg & '0'&instr.rm & ALU_ADD(6 downto 4)&instr.ireg(7)&instr.ireg(5 downto 3);-- selalua & selalub & aluopr
+ else
+ path_s.datareg_input<= ALUBUS_IN & instr.ireg(0) & instr.rm; -- dimux & w & seldreg Note RM=Destination!
+ path_s.alu_operation<= '0'&instr.rm & '0'&instr.reg & ALU_ADD(6 downto 4)&instr.ireg(7)&instr.ireg(5 downto 3);-- selalua & selalub & aluopr
+ end if;
+
+ path_s.ea_output <= NB_CS_IP; -- IPREG+NB ADDR=CS:IP
+
+ if ((instr.ireg(5 downto 3)/="111") and (instr.ireg(7)='0')) then -- Check if not CMP or TEST Instruction
+ wrpath_s.wrd <= '1'; -- Write Data Register to Data Register
+ end if;
+ wrpath_s.wrcc <= '1'; -- Update Status Register
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+
+ next_state <= Sexecute;
+
+ else -- Source/dest is memory
+ if instr.ireg(1)='0' then -- Check 'd' bit ->0 SRC=Reg, DEST=rm, Read & Write Cycle (mem<- mem, reg, AND)
+
+ path_s.datareg_input<= DONTCARE(2 downto 0) & instr.ireg(0) & DONTCARE(2 downto 0); -- dimux & w & seldreg (only w)
+
+ path_s.alu_operation<= REG_MDBUS & '0'&instr.reg & ALU_ADD(6 downto 4)&instr.ireg(7)&instr.ireg(5 downto 3); -- selalua & selalub & aluopr Path for ALU
+
+ path_s.dbus_output <= ALUBUS_OUT; --{eabus(0)&} domux setting
+ path_s.ea_output <= NB_DS_EA; -- dispmux & eamux & segop (unless Segment OP flag is set)
+
+ if (second_pass='0') then -- first pass read operand
+ second_pass_s <= '1'; -- need another pass
+ next_state <= Sreadmem; -- start read cycle
+ else
+ second_pass_s <= '0'; -- clear
+ wrpath_s.wrcc <= '1'; -- Update Status Register
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+
+ if ((instr.ireg(5 downto 3)/="111") and (instr.ireg(7)='0')) then-- Check if not CMP or TEST Instruction
+ next_state <= Swritemem; -- start write cycle
+ else
+ next_state <= Sexecute;
+ end if;
+ end if;
+
+ else -- 'd'=1 SRC=rm, DEST=Reg, Read Cycle (reg<- reg, mem, AND)
+ second_pass_s <= '0';
+ -- Select Data for result path
+ path_s.datareg_input<= ALUBUS_IN & instr.ireg(0) & instr.reg; -- dimux & w & seldreg
+ -- Select Path for ALU
+ path_s.alu_operation<= '0'&instr.reg & REG_MDBUS & ALU_ADD(6 downto 4)&instr.ireg(7)&instr.ireg(5 downto 3);-- selalua & selalub & aluopr
+
+ path_s.ea_output <= NB_DS_EA; -- dispmux & eamux & segop (unless Segment OP flag is set)
+
+ if ((instr.ireg(5 downto 3)/="111") and (instr.ireg(7)='0')) then-- Check if not CMP or TEST Instruction
+ wrpath_s.wrd <= '1'; -- Write Data Register to Data Register
+ end if;
+ wrpath_s.wrcc <= '1'; -- Update Status Register
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+
+ next_state <= Sreadmem; -- start read cycle
+ end if;
+
+ end if;
+
+
+ ---------------------------------------------------------------------------------
+ -- OPCODE 80,81,82,83, ADD/ADC/SUB/SBB/CMP/AND/OR/XOR Immediate to Reg/Mem
+ -- ALU operation is defined in reg field (3 bits) and not in bit 5-3 of opcode
+ -- Data is routed from drmux->dibus->dbusdp_out
+ -- If instr(1)=1 then signextend the data byte (SW=11)
+ ---------------------------------------------------------------------------------
+ when O80I2RM | O81I2RM | O83I2RM =>
+
+ if instr.xmod="11" then -- Immediate to Register r/m=reg field
+ second_pass_s <= '0';
+
+ path_s.datareg_input<= ALUBUS_IN & instr.ireg(0) & instr.rm; -- dimux & w & seldreg Note RM=Destination!!
+
+ -- instr.reg contains the required operation (Reg AND Constant)
+ -- If s-bit=0 then 000+REG else 110+REG, s-bit is bit 1 of instr.reg
+ path_s.alu_operation<= '0'&instr.rm & REG_DATAIN &instr.ireg(1)&instr.ireg(1)&"00"&instr.reg; -- selalua & selalub & aluopr
+ path_s.ea_output <= NB_CS_IP; -- IPREG+NB ADDR=CS:IP
+
+ if (instr.reg/="111") then -- Check if not CMP Instruction
+ wrpath_s.wrd <= '1'; -- Write Data Register to Data Register
+ end if;
+ wrpath_s.wrcc <= '1'; -- Update Status Register
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+
+ next_state <= Sexecute;
+
+ else -- Destination and source is memory (no wrpath_s.wrd)
+ -- This is nearly the same as AND with d=0, see above
+ -- only need W bit
+ path_s.datareg_input<= DONTCARE(2 downto 0) & instr.ireg(0) & DONTCARE(2 downto 0); -- dimux & w & seldreg (only dimux, the rest is don't care)
+ -- Memory AND Constant, need to read memory first
+ path_s.alu_operation<= REG_MDBUS & REG_DATAIN&instr.ireg(1)&instr.ireg(1)&"00"&instr.reg; -- selalua & selalub & aluopr
+
+ path_s.dbus_output <= ALUBUS_OUT; --{eabus(0)&} domux setting
+ path_s.ea_output <= NB_DS_EA; -- dispmux & eamux & segop (unless Segment OP flag is set)
+
+ if (second_pass='0') then -- first pass read operand
+ second_pass_s <= '1'; -- need another pass
+ next_state <= Sreadmem; -- start read cycle
+ else
+ second_pass_s <= '0'; -- clear
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ wrpath_s.wrcc <= '1'; -- Update Status Register
+ if (instr.reg/="111") then -- Check if not CMP Instruction
+ next_state <= Swritemem; -- start write cycle
+ else
+ next_state <= Sexecute; -- CMP, do not write results
+ end if;
+ end if;
+
+ end if;
+
+ -----------------------------------------------------------------------------
+ -- NOT/TEST F6/F7 Shared Instructions
+ -- TEST regfield=000
+ -- NOT regfield=010
+ -- NEG regfield=011
+ -- MUL regfield=100
+ -- IMUL regfield=101
+ -- DIV regfield=110
+ -- IDIV regfield=111
+ -- ALU operation is defined in bits 5-3 of modrm.reg
+ -- Same sequence as OPC80..83 instruction?
+ -- Note for NOT instruction DATAIN must be zero!!
+ -----------------------------------------------------------------------------
+ when F6INSTR | F7INSTR =>
+
+ -- case instr.reg(2 downto 0) is
+ case instr.reg is
+
+ when "000" => -- TEST instruction, Combine with NEG/NOT Instruction ?????????????
+ if instr.xmod="11" then -- Immediate to Register r/m=reg field
+ second_pass_s <= '0';
+
+ path_s.datareg_input<= ALUBUS_IN & instr.ireg(0) & instr.rm; -- dimux & w & seldreg
+ -- instr.reg contains the required operation
+ -- Note ALU_TEST2 is generic for all sub types
+ path_s.alu_operation<= '0'&instr.rm & REG_DATAIN & ALU_TEST2(6 downto 3)&instr.reg; -- selalua & selalub & aluopr
+
+ path_s.ea_output <= NB_CS_IP; -- IPREG+NB ADDR=CS:IP
+
+ wrpath_s.wrcc <= '1'; -- Update Status Register
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+
+ next_state <= Sexecute;
+
+ else -- Destination and source is memory (no wrpath_s.wrd)
+ -- This is nearly the same as AND with d=0, see above
+ -- only need W bit
+ path_s.datareg_input<= DONTCARE(2 downto 0) & instr.ireg(0) & DONTCARE(2 downto 0); -- dimux & w & seldreg (only dimux, the rest is don't care)
+ -- Memory AND Constant, need to read memory first
+ path_s.alu_operation<= REG_MDBUS & REG_DATAIN & ALU_TEST2(6 downto 3)&instr.reg; -- selalua & selalub & aluopr
+
+ path_s.dbus_output <= ALUBUS_OUT; --{eabus(0)&} domux setting
+ path_s.ea_output <= NB_DS_EA; -- dispmux & eamux & segop (unless Segment OP flag is set)
+
+ if (second_pass='0') then -- first pass read operand
+ second_pass_s <= '1'; -- need another pass
+ next_state <= Sreadmem; -- start read cycle
+ else
+ second_pass_s <= '0'; -- clear
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ wrpath_s.wrcc <= '1'; -- Update Status Register
+ next_state <= Sexecute; -- TEST, do not write results
+ end if;
+
+ end if;
+
+ when "010" | "011" => -- Invert NOT and 2s complement NEG
+ -- Check with others to see if can be combined!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ if instr.xmod="11" then -- Negate Register r/m=reg field
+ second_pass_s <= '0';
+
+ path_s.datareg_input<= ALUBUS_IN & instr.ireg(0) & instr.rm; -- dimux & w & seldreg
+ -- Note ALU_TEST2 is generic for all sub types
+ if (instr.reg(0)='1') then -- NEG instruction
+ path_s.alu_operation<= '0'&instr.rm & REG_CONST1 & ALU_TEST2(6 downto 3)&instr.reg; -- selalua & selalub & aluopr
+ else -- NOT instruction, note DATAIN must be zero!
+ path_s.alu_operation<= '0'&instr.rm & REG_DATAIN & ALU_TEST2(6 downto 3)&instr.reg; -- selalua & selalub & aluopr
+ end if;
+ path_s.ea_output <= NB_CS_IP; -- IPREG+NB ADDR=CS:IP
+
+ if (instr.reg(0)='1') then -- NEG instruction
+ wrpath_s.wrcc <= '1'; -- Update Status Register
+ end if;
+
+ wrpath_s.wrd <= '1'; -- Write Data Register to Data Register
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+
+ next_state <= Sexecute;
+
+ else -- Destination and source is memory
+ -- only need W bit
+ path_s.datareg_input<= DONTCARE(2 downto 0) & instr.ireg(0) & DONTCARE(2 downto 0); -- dimux & w & seldreg (only dimux, the rest is don't care)
+ -- need to read memory first
+ if (instr.reg(0)='1') then -- NEG instruction
+ path_s.alu_operation<= REG_MDBUS & REG_CONST1 & ALU_TEST2(6 downto 3)&instr.reg; -- selalua & selalub & aluopr
+ else -- NOT instruction, note DATAIN must be zero!
+ path_s.alu_operation<= REG_MDBUS & REG_DATAIN & ALU_TEST2(6 downto 3)&instr.reg; -- selalua & selalub & aluopr
+ end if;
+
+ path_s.dbus_output <= ALUBUS_OUT; --{eabus(0)&} domux setting
+ path_s.ea_output <= NB_DS_EA; -- dispmux & eamux & segop (unless Segment OP flag is set)
+
+ if (second_pass='0') then -- first pass read operand
+ second_pass_s <= '1'; -- need another pass
+ next_state <= Sreadmem; -- start read cycle
+ else
+ second_pass_s <= '0'; -- clear
+ if (instr.reg(0)='1') then -- NEG instruction
+ wrpath_s.wrcc <= '1'; -- Update Status Register
+ end if;
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Swritemem; -- write results
+ end if;
+
+ end if;
+
+
+ when "100" | "101" | "110" | "111" => -- DIV/IDIV/MUL/IMUL instruction
+
+ if (second_pass='0') then -- Set up multiply parameters
+ second_pass_s <= '1';
+
+
+ if (instr.reg(1)='1') then -- Only assert for DIV and IDIV, not for MUL/IMUL
+ passcnt_s <= "000"&DIV_MCD_C; -- Serial delay
+ else
+ passcnt_s <= "000"&MUL_MCD_C; -- Multiplier MCP
+ end if;
+
+ -- only need W bit
+ path_s.datareg_input<= DONTCARE(2 downto 0) & instr.ireg(0) & DONTCARE(2 downto 0); -- dimux & w & seldreg
+ -- Note ALU_TEST is generic for all sub types
+ if instr.xmod="11" then -- Immediate to Register, result to AX or DX:AX
+ path_s.ea_output <= NB_CS_IP; -- IPREG+NB ADDR=CS:IP
+ path_s.alu_operation<= REG_AX & '0'&instr.rm & ALU_TEST2(6 downto 4)&'0'&instr.reg; -- selalua & selalub & aluopr
+ next_state <= Sdecode; -- Next write remaining AX
+ else -- get byte/word from memory
+ path_s.ea_output <= NB_DS_EA;
+ path_s.alu_operation<= REG_AX & REG_MDBUS & ALU_TEST2(6 downto 4)&'0'&instr.reg; -- selalua & selalub & aluopr
+ next_state <= Sreadmem; -- Next write remaining AX
+ end if;
+ wrpath_s.wralu <= '1'; -- latch AX/AL and Byte/Word
+
+ else
+ passcnt_s <= passcnt - '1';
+ path_s.ea_output <= NB_CS_IP; -- IPREG+NB ADDR=CS:IP (required???????????)
+
+ if (passcnt=X"01") then --
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_AX(2 downto 0); -- dimux & w & seldreg
+ path_s.alu_operation<= REG_AX & '0'&instr.rm & ALU_TEST2(6 downto 4)&'0'&instr.reg; -- selalua & selalub & aluopr
+ wrpath_s.wrd <= '1'; -- Write AX
+ if (instr.ireg(0)='1') then
+ second_pass_s <= '1'; -- HT0912
+ next_state <= Sdecode; -- Continue, next cycle to write DX
+ else
+ second_pass_s <= '0';
+ wrpath_s.wrcc <= '1'; -- Update Status Register
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Sexecute; -- terminate
+ end if;
+ elsif (passcnt=X"00") then
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_DX(2 downto 0); -- dimux & w & seldreg
+ path_s.alu_operation<= REG_AX & '0'&instr.rm & ALU_TEST2(6 downto 4)&'1'&instr.reg; -- selalua & selalub & aluopr
+ second_pass_s <= '0';
+ wrpath_s.wrd <= '1'; -- Write DX
+ wrpath_s.wrcc <= '1'; -- Update Status Register
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Sexecute; -- terminate
+ else
+ second_pass_s <= '1'; -- HT0912
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_DX(2 downto 0); -- dimux & w & seldreg
+ path_s.alu_operation<= REG_AX & '0'&instr.rm & ALU_TEST2(6 downto 4)&'1'&instr.reg; -- selalua & selalub & aluopr
+ next_state <= Sdecode; -- round the loop again
+ end if;
+ end if;
+
+
+ when others =>
+ second_pass_s <= '0'; -- To avoid latch HT0912
+ proc_error_s <='1'; -- Assert Bus Error Signal
+ -- pragma synthesis_off
+ assert not (now > 0 ns) report "**** Illegal F7/F6 modrm field (proc) ***" severity warning;
+ -- pragma synthesis_on
+ next_state <= Sdecode; -- Reset State????
+
+ end case;
+
+ ---------------------------------------------------------------------------------
+ -- ADD/ADC/SUB/SBB/CMP/AND/OR/XOR Immediate to ACCU
+ -- ALU operation is defined in bits 5-3 of opcode
+ ---------------------------------------------------------------------------------
+ when ADDI2AX0 | ADDI2AX1 | ADCI2AX0 | ADCI2AX1 | SUBI2AX0 | SUBI2AX1 | SBBI2AX0 | SBBI2AX1 |
+ CMPI2AX0 | CMPI2AX1 | ANDI2AX0 | ANDI2AX1 | ORI2AX0 | ORI2AX1 | XORI2AX0 | XORI2AX1 |
+ TESTI2AX0| TESTI2AX1 =>
+
+ second_pass_s <= '0';
+ -- Note Destination reg is fixed to AX/AL/AH
+ path_s.datareg_input<= ALUBUS_IN & instr.ireg(0) & REG_AX(2 downto 0); -- dimux & w & seldreg(3)
+ -- note aluopr = bit 5 to 3 of opcode
+ path_s.alu_operation<= REG_AX & REG_DATAIN & ALU_ADD(6 downto 4)&instr.ireg(7)&instr.ireg(5 downto 3);-- selalua & selalub & aluopr
+
+ path_s.ea_output <= NB_CS_IP; -- IPREG+NB ADDR=CS:IP
+
+ if ((instr.ireg(5 downto 3)/="111") and (instr.ireg(7)='0')) then-- Check if not CMP or TEST Instruction
+ wrpath_s.wrd <= '1'; -- Write Data Register to Data Register
+ end if;
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ wrpath_s.wrcc <= '1'; -- Update Status Register
+
+ next_state <= Sexecute;
+
+ ---------------------------------------------------------------------------------
+ -- Exchange Register with Accu
+ ---------------------------------------------------------------------------------
+ when XCHGAX | XCHGCX | XCHGDX | XCHGBX | XCHGSP | XCHGBP | XCHGSI | XCHGDI =>
+
+ path_s.ea_output <= NB_CS_IP; -- IPREG+NB ADDR=CS:IP
+
+ if (second_pass='0') then -- first pass read operand
+ second_pass_s <= '1'; -- need another pass
+ -- First pass copy AX to reg and reg to ALUREG
+ path_s.datareg_input<= ALUBUS_IN & '1' & instr.ireg(2 downto 0); -- dimux & w & seldreg
+ path_s.alu_operation<= REG_AX & '0' & instr.ireg(2 downto 0) & ALU_PASSA; -- selalua(4) & selalub(4) & aluopr
+
+ wrpath_s.wrd <= '1'; -- Update AX & write reg to ALUREG
+ wrpath_s.wralu<= '1'; -- Write INBUSB to ALUREG
+ next_state <= Sdecode; -- second pass
+ else
+ second_pass_s <= '0'; -- clear
+ -- Second Pass, write ALU register to AX
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_AX(2 downto 0); -- dimux & w & seldreg
+ -- selalua and selalub are don't care, use previous values to reduce synth
+ path_s.alu_operation<= REG_AX & '0' & instr.ireg(2 downto 0) & ALU_REGL;-- selalua(4) & selalub(4) & aluopr
+
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ wrpath_s.wrd <= '1'; -- Write ALUREG to AX
+ next_state <= Sexecute;
+ end if;
+
+ ---------------------------------------------------------------------------------
+ -- Exchange Register with Register/Memory
+ ---------------------------------------------------------------------------------
+ when XCHGW | XCHGB =>
+
+ if instr.xmod="11" then -- Register to Register rm=reg field
+
+ path_s.ea_output <= NB_CS_IP; -- IPREG+NB ADDR=CS:IP
+
+ if (second_pass='0') then -- first pass read operand
+ second_pass_s <= '1'; -- need another pass
+ -- First pass copy rm to ireg and ireg to ALUREG
+ path_s.datareg_input<= ALUBUS_IN & instr.ireg(0) & instr.reg; -- dimux & w & seldreg
+ path_s.alu_operation<= '0'&instr.rm & '0'&instr.reg & ALU_PASSA; -- selalua(4) & selalub(4) & aluopr
+
+ wrpath_s.wrd <= '1'; -- Update AX & write reg to ALUREG
+ wrpath_s.wralu<= '1'; -- Write INBUSB to ALUREG (instr.reg)
+ next_state <= Sdecode; -- second pass
+ else
+ second_pass_s <= '0'; -- clear
+ -- Second Pass, write ALUREG(ireg) to rm
+ path_s.datareg_input<= ALUBUS_IN & instr.ireg(0) & instr.rm; -- dimux & w & seldreg
+
+ -- selalua and selalub are don't care
+ path_s.alu_operation<= DONTCARE(3 downto 0) & '0'&instr.reg & ALU_REGL; -- selalua(4) & selalub(4) & aluopr
+
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ wrpath_s.wrd <= '1'; -- Write ALUREG to AX
+ next_state <= Sexecute;
+ end if;
+
+ else
+ path_s.ea_output <= NB_DS_EA; -- dispmux & eamux & segop (unless Segment OP flag is set)
+
+ if (second_pass='0') then -- first pass read operand from memory
+ second_pass_s <= '1'; -- need another pass
+ -- First pass copy rm to ireg and ireg to ALUREG
+ path_s.datareg_input<= MDBUS_IN & instr.ireg(0) & instr.reg; -- dimux & w & seldreg
+ path_s.alu_operation<= '0'&instr.rm & '0'&instr.reg & ALU_PASSA; -- selalua(4) & selalub(4) & aluopr
+
+ wrpath_s.wrd <= '1'; -- Update AX & write reg to ALUREG
+ wrpath_s.wralu<= '1'; -- Write INBUSB to ALUREG (instr.reg)
+ next_state <= Sreadmem; -- get memory operand
+ else
+ second_pass_s <= '0'; -- clear
+ path_s.datareg_input<= DONTCARE(2 downto 0) & instr.ireg(0) & DONTCARE(2 downto 0); -- dimux & w & seldreg
+ -- selalua and selalub are don't care, use previous values to reduce synth?????
+ path_s.alu_operation<= '0'&instr.rm & '0'&instr.reg & ALU_REGL; -- selalua(4) & selalub(4) & aluopr
+
+ path_s.dbus_output <= ALUBUS_OUT; --{eabus(0)&} domux setting
+
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Swritemem;
+ end if;
+ end if;
+
+ ---------------------------------------------------------------------------------
+ -- Processor Control Instructions
+ -- ALU operation is defined in bits 5-0 of opcode
+ ---------------------------------------------------------------------------------
+ when CLC | CMC | STC | CLD | STDx | CLI | STI =>
+
+ second_pass_s <= '0';
+ path_s.datareg_input<= DONTCARE(6 downto 0) ; -- dimux(3) & w & seldreg(3)
+ -- Note aluopr = bit 3 to 0 of opcode
+ -- Note ALU_CMC(6 downto 4) is generic for all sub types
+ path_s.alu_operation<= DONTCARE(7 downto 0) & ALU_CMC(6 downto 4)&instr.ireg(3 downto 0);-- selalua(4) & selalub(4) & aluopr(7)
+
+ path_s.ea_output <= NB_CS_IP; -- IPREG+NB ADDR=CS:IP
+
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ wrpath_s.wrcc <= '1'; -- Update Status Register
+
+ next_state <= Sexecute;
+
+ ---------------------------------------------------------------------------------
+ -- Load AH with flags (7 downto 0)
+ -- Note orginal instruction only loads bit 7,6,4,2,0 (easy change if required)
+ -- ALU operation is defined in bits 6-0 of opcode
+ ---------------------------------------------------------------------------------
+ when LAHF =>
+
+ second_pass_s <= '0';
+ path_s.datareg_input<= ALUBUS_IN & REG_AH; -- dimux & w & seldreg(3)
+ -- note aluopr = bit 6 to 0 of opcode
+ path_s.alu_operation<= DONTCARE(7 downto 0) & ALU_LAHF(6 downto 4)&instr.ireg(3 downto 0);-- selalua & selalub & aluopr
+
+ path_s.ea_output <= NB_CS_IP; -- IPREG+NB ADDR=CS:IP
+
+ wrpath_s.wrd <= '1'; -- Write Result to AH
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+
+ next_state <= Sexecute;
+
+ ---------------------------------------------------------------------------------
+ -- Store AH into flags (7 downto 0)
+ -- Note orginal instruction only stores bit 7,6,4,2,0
+ -- ALU operation is defined in bits 6-0 of opcode
+ ---------------------------------------------------------------------------------
+ when SAHF =>
+
+ second_pass_s <= '0';
+ path_s.datareg_input<= DONTCARE(2 downto 0)&'0'& DONTCARE(2 downto 0); -- dimux(3) & w & seldreg(3)
+ -- note aluopr = bit 6 to 0 of opcode
+ path_s.alu_operation<= REG_AH & DONTCARE(3 downto 0) & ALU_SAHF(6 downto 4)&instr.ireg(3 downto 0);-- selalua & selalub & aluopr
+
+ path_s.ea_output <= NB_CS_IP; -- IPREG+NB ADDR=CS:IP
+
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ wrpath_s.wrcc <= '1'; -- Update Status Register with contents AH
+
+ next_state <= Sexecute;
+
+
+ ---------------------------------------------------------------------------------
+ -- PUSH Data Register
+ ---------------------------------------------------------------------------------
+ when PUSHAX | PUSHCX | PUSHDX | PUSHBX | PUSHSP | PUSHBP | PUSHSI | PUSHDI =>
+
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_SP(2 downto 0); -- dimux & w & seldreg
+ path_s.dbus_output <= ALUBUS_OUT; --{eabus(0)&} domux setting
+ path_s.ea_output <= NB_SS_SP & DONTCARE(2 downto 0); -- SS:SP+2
+
+ if (second_pass='0') then -- first pass SP-2
+ second_pass_s <= '1'; -- need another pass
+
+ path_s.alu_operation<= REG_SP & REG_CONST2 & ALU_PUSH;-- selalua(4) & selalub(4) & aluopr
+
+ wrpath_s.wrd <= '1'; -- Update SP
+ wrpath_s.wralu <= '1'; -- Save reg in alureg (required for PUSH SP)
+ next_state <= Sdecode; -- second pass
+ else
+ second_pass_s <= '0'; -- clear
+
+ path_s.alu_operation<= '0'&instr.reg & REG_CONST2 & ALU_PASSA;-- selalua(4) & selalub(4) & aluopr
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Swritemem; -- start write cycle
+ end if;
+
+
+ ---------------------------------------------------------------------------------
+ -- PUSH Flag Register
+ ---------------------------------------------------------------------------------
+ when PUSHF => -- Push flag register
+
+ path_s.dbus_output <= CCBUS_OUT; --{eabus(0)&} domux setting
+ path_s.alu_operation<= REG_SP & REG_CONST2 & ALU_PUSH;-- selalua(4) & selalub(4) & aluopr
+
+ if (second_pass='0') then -- first pass SP-2
+ second_pass_s <= '1'; -- need another pass
+
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_SP(2 downto 0); -- dimux & w & seldreg
+
+ path_s.ea_output <= NB_DS_EA; -- dispmux & eamux & segop (unless Segment OP flag is set)
+ wrpath_s.wrd <= '1'; -- Update SP
+ --next_state <= Sreadmem; -- start read cycle
+ next_state <= Sdecode; -- second pass
+ else
+ second_pass_s <= '0'; -- clear
+
+ -- Second Pass, write memory operand to stack
+ path_s.datareg_input<= MDBUS_IN & '1' & DONTCARE(2 downto 0); -- dimux & w & seldreg
+
+ path_s.ea_output <= NB_SS_SP & DONTCARE(2 downto 0); -- dispmux(2) & eamux(4) & [flag]&segop(2)
+
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Swritemem; -- start write cycle
+ end if;
+
+ ---------------------------------------------------------------------------------
+ -- POP Flag Register
+ ---------------------------------------------------------------------------------
+ when POPF => -- POP Flags
+ -- Setup datapath for SP<=SP-2, ea=SS:SP
+ -- Note datareg_input is don't care during second pass
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_SP(2 downto 0); -- dimux & w & seldreg
+ path_s.ea_output <= NB_SS_SP &DONTCARE(2 downto 0); -- SS:SP+2
+
+ if (second_pass='0') then -- first pass read operand
+ second_pass_s <= '1'; -- need another pass
+ -- First pass, start read and update SP
+ path_s.alu_operation<= REG_SP & REG_CONST2 & ALU_POP;-- selalua(4) & selalub(4) & aluopr
+
+ wrpath_s.wrd <= '1'; -- Update SP
+ next_state <= Sreadmem; -- start read cycle to get [SS:SP]
+ else
+ second_pass_s <= '0'; -- clear
+ -- Second Pass, write memory operand to CC register
+ path_s.alu_operation<= REG_MDBUS & REG_CONST2 & ALU_POP;-- selalua(4) & selalub(4) & aluopr
+
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ wrpath_s.wrcc <= '1'; -- Update Status Register
+ next_state <= Sexecute;
+ end if;
+
+ ---------------------------------------------------------------------------------
+ -- POP Data Register
+ ---------------------------------------------------------------------------------
+ when POPAX | POPCX | POPDX | POPBX | POPSP | POPBP | POPSI | POPDI =>
+
+ path_s.ea_output <= NB_SS_SP & DONTCARE(2 downto 0); -- SS:SP
+ path_s.alu_operation<= REG_SP & REG_CONST2 & ALU_POP;-- selalua(4) & selalub(4) & aluopr
+
+ if (second_pass='0') then -- first pass read operand
+ second_pass_s <= '1'; -- need another pass
+ -- First pass, start read and update SP
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_SP(2 downto 0); -- dimux & w & seldreg
+
+ wrpath_s.wrd <= '1'; -- Update SP
+ next_state <= Sreadmem; -- start read cycle to get [SS:SP]
+ else
+ second_pass_s <= '0'; -- clear
+ -- Second Pass, write memory operand to data register
+ path_s.datareg_input<= MDBUS_IN & '1' & instr.ireg(2 downto 0); -- dimux & w & seldreg
+
+ wrpath_s.wrd <= '1'; -- Update DataReg
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Sexecute;
+ end if;
+
+ ---------------------------------------------------------------------------------
+ -- POP TOS to Memory or Register
+ --
+ ---------------------------------------------------------------------------------
+ when POPRM =>
+
+ if (second_pass='0') then -- first pass read operand
+ second_pass_s <= '1'; -- need another pass
+
+ path_s.ea_output <= NB_SS_SP & DONTCARE(2 downto 0); -- SS:SP
+ path_s.alu_operation<= REG_SP & REG_CONST2 & ALU_POP;-- selalua(4) & selalub(4) & aluopr
+
+ -- First pass, start read and update SP
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_SP(2 downto 0); -- dimux & w & seldreg
+
+ wrpath_s.wrd <= '1'; -- Update SP
+ next_state <= Sreadmem; -- start read cycle to get [SS:SP]
+
+ else -- second pass, write to memory or register
+ second_pass_s <= '0'; -- no more passes
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+
+ -- Next are only used when xmod/=11, for xmod=11 they are don't care
+ path_s.dbus_output <= DIBUS_OUT; --{eabus(0)&} domux setting
+ path_s.ea_output <= NB_DS_EA; -- dispmux=000,eamux=0001, dis_opflag=0, segop=11
+
+ -- For xmod/=11 the last 3 bits are DONTCARE
+ path_s.datareg_input<= MDBUS_IN & '1' & instr.rm; -- dimux & w & seldreg ireg-> r=4, rm->r=1
+
+ if instr.xmod="11" then -- POP Register r/m=reg field
+ -- This is the same as POPAX, POPCX etc
+ wrpath_s.wrd <= '1'; -- Update DataReg
+ next_state <= Sexecute;
+ else
+ next_state <= Swritemem; -- Update memory location pointed to by EA
+ end if;
+ end if;
+
+ ---------------------------------------------------------------------------------
+ -- POP Segment Register
+ -- Note POP CS is illegal, result unknown instruction, assert bus error
+ -- Interrupts are disabled until the next instruction
+ ---------------------------------------------------------------------------------
+ when POPES | POPSS | POPDS =>
+
+ irq_blocked_s <= '1'; -- Block IRQ if asserted during next instr.
+
+ second_pass_s <= '0';
+ irq_blocked_s <= '1'; -- Block IRQ if asserted during next instr.
+
+ path_s.ea_output <= NB_SS_SP & DONTCARE(2 downto 0); -- SS:SP+2
+
+ -- Path to update SP
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_SP(2 downto 0); -- dimux & w & seldreg
+ path_s.alu_operation<= REG_SP & REG_CONST2 & ALU_POP;-- selalua(4) & selalub(4) & aluopr
+
+ -- Path to write operand to segment register
+ path_s.segreg_input <= SMDBUS_IN & instr.ireg(4 downto 3); -- simux(2) & selsreg(2)
+
+ wrpath_s.wrd <= '1'; -- Update SP
+ wrpath_s.wrs <= '1'; -- Update Segment Register
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+
+ next_state <= Sreadmem; -- start read cycle to get [SS:SP]
+
+ ---------------------------------------------------------------------------------
+ -- PUSH Segment Register
+ -- PUSH CS is legal
+ ---------------------------------------------------------------------------------
+ when PUSHES | PUSHCS | PUSHSS | PUSHDS =>
+
+ path_s.alu_operation<= REG_SP & REG_CONST2 & ALU_PUSH;-- selalua(4) & selalub(4) & aluopr
+ path_s.dbus_output <= DIBUS_OUT; --{eabus(0)&} domux setting
+ path_s.ea_output <= NB_SS_SP & DONTCARE(2 downto 0); -- SS:SP+2
+
+ if (second_pass='0') then -- first pass SP-2
+ second_pass_s <= '1'; -- need another pass
+
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_SP(2 downto 0); -- dimux & w & seldreg
+
+ wrpath_s.wrd <= '1'; -- Update SP
+ next_state <= Sdecode; -- second pass
+ else
+ second_pass_s <= '0'; -- clear
+ path_s.datareg_input<= '1' & instr.ireg(4 downto 3) & '1' & REG_SP(2 downto 0); -- dimux & w & seldreg
+
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Swritemem; -- start write cycle
+ end if;
+
+ ---------------------------------------------------------------------------------
+ -- Unconditional Jump
+ -- Short Jump within segment, SignExt DISPL
+ -- Long Jump within segment, No SignExt DISPL
+ -- Direct within segment (JMPDIS, new CS,IP on data_in and disp)
+ ---------------------------------------------------------------------------------
+ when JMPS| JMP | JMPDIS=>
+
+ second_pass_s <= '0';
+ flush_req_s <= '1'; -- Flush Prefetch queue, asserted during execute cycle
+ path_s.segreg_input <= SDATAIN_IN & CS_IN(1 downto 0);-- simux & selsreg, only for JMPDIS
+
+ if (instr.ireg(1 downto 0)="10") then -- JMPDIS Instruction
+ path_s.ea_output <= LD_CS_IP; -- dispmux & eamux & segop Load new CS:IP from memory
+ wrpath_s.wrs <= '1'; -- Update CS register
+ else
+ path_s.ea_output <= DISP_CS_IP; -- CS:IPREG+DISPL
+ end if;
+
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Sexecute;
+
+ ---------------------------------------------------------------------------------
+ -- LOOP Instruction
+ -- No flags are affected
+ -- Note: JCXZ can be speeded up by 1 clk cycle since the first pass is not
+ -- required!!
+ ---------------------------------------------------------------------------------
+ when LOOPCX | LOOPZ | LOOPNZ | JCXZ =>
+
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_CX(2 downto 0); -- dimux & w & seldreg
+ path_s.alu_operation<= REG_CX & REG_CONST1 & ALU_DEC;-- selalua(4) & selalub(4) & aluopr
+
+
+ if (second_pass='0') then -- first pass CX <= CX-1
+ second_pass_s <= '1'; -- need another pass
+
+ if (instr.ireg(1 downto 0)/="11") then
+ wrpath_s.wrd <= '1'; -- Update CX unless instr=JCXZ
+ end if;
+ next_state <= Sdecode; -- Next check CX value
+
+ else -- Next check CX and flag value
+ second_pass_s <= '0';
+ -- path ALU is don't care
+ -- ver 0.70 fixed loop!! status.cx_zero ro cx_one
+ if (((instr.ireg(1 downto 0)="00") and (status.flag(6)='0') and (status.cx_one='0')) or -- loopnz, jump if cx/=0 && zf=0
+ ((instr.ireg(1 downto 0)="01") and (status.flag(6)='1') and (status.cx_one='0')) or-- loopz, jump if cx/=0 && zf=1
+ ((instr.ireg(1 downto 0)="10") and (status.cx_one='0')) or -- loop, jump if cx/=0
+ ((instr.ireg(1 downto 0)="11") and (status.cx_zero='1'))) then -- jcxz jump if cx=0
+
+ flush_req_s <= '1';
+ path_s.ea_output <= DISP_CS_IP; -- jump
+ else
+ path_s.ea_output <= NB_CS_IP; -- Do not jump
+ end if;
+
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Sexecute;
+
+ end if;
+
+ -----------------------------------------------------------------------------
+ -- FF/FE Instructions. Use regfield to decode operation
+ -- INC reg=000 (FF/FE)
+ -- DEC reg=001 (FF/FE)
+ -- CALL reg=010 (FF) Indirect within segment
+ -- CALL reg=011 (FF) Indirect Intersegment
+ -- JMP reg=100 (FF) Indirect within segment
+ -- JMP reg=101 (FF) Indirect Intersegment
+ -- PUSH reg=110 (FF)
+ -----------------------------------------------------------------------------
+ when FEINSTR | FFINSTR =>
+
+ case instr.reg is
+
+ when "000" | "001" => -- INC or DEC instruction
+ if instr.xmod="11" then -- Immediate to Register r/m=reg field
+ second_pass_s <= '0';
+
+ path_s.datareg_input<= ALUBUS_IN & instr.ireg(0) & instr.rm; -- dimux & w & seldreg Note RM=Destination
+ -- instr.reg(5..3) contains the required operation, ALU_INBUSB=X"0001"
+ -- note ALU_INC(6 downto 3) is generic for both INC and DEC
+ path_s.alu_operation<= '0'&instr.rm & REG_CONST1 & ALU_INC(6 downto 3)&instr.reg; -- selalua & selalub & aluopr
+
+ path_s.ea_output <= NB_CS_IP; -- IPREG+NB ADDR=CS:IP
+
+ wrpath_s.wrd <= '1'; -- Write Data Register to Data Register
+ wrpath_s.wrcc <= '1'; -- Update Status Register
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+
+ next_state <= Sexecute;
+
+ else -- Destination and source is memory (no wrpath_s.wrd)
+ -- This is nearly the same as AND with d=0, see above
+ -- only need W bit
+ path_s.datareg_input<= DONTCARE(2 downto 0) & instr.ireg(0) & DONTCARE(2 downto 0); -- dimux & w & seldreg (only dimux, the rest is don't care)
+ -- INC/DEC Memory, need to read memory first
+ path_s.alu_operation<= REG_MDBUS & REG_CONST1 & ALU_INC(6 downto 3)&instr.reg; -- selalua & selalub & aluopr
+
+ path_s.dbus_output <= ALUBUS_OUT; --{eabus(0)&} domux setting
+ path_s.ea_output <= NB_DS_EA; -- dispmux & eamux & segop (unless Segment OP flag is set)
+
+ if (second_pass='0') then -- first pass read operand
+ second_pass_s <= '1'; -- need another pass
+ next_state <= Sreadmem; -- start read cycle
+ else
+ second_pass_s <= '0'; -- clear
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ wrpath_s.wrcc <= '1'; -- Update Status Register
+ next_state <= Swritemem; -- start write cycle
+ end if;
+
+ end if;
+
+
+ ---------------------------------------------------------------------------------
+ -- CALL Indirect within Segment
+ -- SP<=SP-2
+ -- Mem(SP)<=IP
+ -- IP<=EA
+ ---------------------------------------------------------------------------------
+ when "010" =>
+
+ flush_coming_s<= '1'; -- signal to the BIU that a flush is coming,
+ -- this will stop the BIU from filling the queue.
+
+ path_s.alu_operation<= REG_SP & REG_CONST2 & ALU_PUSH;-- selalua(4) & selalub(4) & aluopr
+ path_s.dbus_output <= IPBUS_OUT; --{eabus(0)&} domux setting
+
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_SP(2 downto 0); -- dimux & w & seldreg
+
+ if (second_pass='0') then -- first pass SP-2
+ second_pass_s <= '1';
+ path_s.ea_output<= NB_SS_SP & DONTCARE(2 downto 0); -- SS:SP+2
+ passcnt_s <= X"02";
+ wrpath_s.wrd <= '1'; -- Update SP
+ next_state <= Sdecode; -- second pass
+ else -- Second pass Mem
+ passcnt_s <= passcnt - '1';
+ if (passcnt=X"00") then
+ second_pass_s <= '0'; -- clear
+ flush_req_s <= '1'; -- Flush Prefetch queue, asserted during execute cycle
+ path_s.ea_output<=NB_CS_IP; -- select CS:IP before Flush;
+ next_state <= Sexecute;
+
+ elsif (passcnt=X"01") then -- Third pass
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ if instr.xmod="11" then
+ second_pass_s <= '0'; -- clear
+ flush_req_s <= '1'; -- Flush Prefetch queue, asserted during execute cycle
+ path_s.ea_output<= "1001001001";-- fix version 1.0a 02/08/09 EA_CS_IP;
+ next_state <= Sexecute;
+ else
+ second_pass_s <= '1'; -- need another pass
+ -- dispmux(3) & eamux(4) & dis_opflag & segop[1:0]
+ path_s.ea_output<= "0100001011"; -- Get indirect value
+ next_state <= Sreadmem;
+ end if;
+ else -- Second pass write MEM(SS:SP)<=IP
+ second_pass_s <= '1';
+ path_s.ea_output<= NB_SS_SP & DONTCARE(2 downto 0);-- ADDR=SS:SP
+ next_state <= Swritemem; -- start write cycle, MEM(SP)<=IP
+ end if;
+
+ end if;
+
+ ---------------------------------------------------------------------------------
+ -- CALL IntraSegment Indirect
+ -- SP<=SP-2
+ -- Mem(SP)<=CS
+ -- SP<=SP-2
+ -- Mem(SP)<=IP
+ -- CS<=DS:EA
+ -- IP<=DS:EA+2
+ -- Flush
+ ---------------------------------------------------------------------------------
+ when "011" =>
+
+ flush_coming_s<= '1'; -- signal to the BIU that a flush is coming,
+ -- this will stop the BIU from filling the queue.
+
+ path_s.alu_operation<= REG_SP & REG_CONST2 & ALU_PUSH;-- selalua(4) & selalub(4) & aluopr
+
+ if (second_pass='0') then -- first pass SP<=SP-2
+ second_pass_s <= '1';
+ path_s.dbus_output<=DONTCARE(1 downto 0);
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_SP(2 downto 0); -- dimux & w & seldreg
+ path_s.ea_output<= NB_SS_SP & DONTCARE(2 downto 0); -- SS:SP+2 (DONTCARE)
+ passcnt_s <= X"05";
+ wrpath_s.wrd <= '1'; -- Update SP
+ next_state <= Sdecode;
+ else
+ passcnt_s <= passcnt - '1';
+
+ if (passcnt=X"05") then -- Second pass write CS to ss:sp
+ second_pass_s <= '1';
+ path_s.segreg_input <= DONTCARE(1 downto 0) & CS_IN(1 downto 0); -- simux & selsreg
+ path_s.datareg_input<= CS_IN & '1' & DONTCARE(2 downto 0); -- dimux & w & seldreg
+ path_s.dbus_output <= DIBUS_OUT; --{eabus(0)&} domux setting CS out
+ path_s.ea_output<= NB_SS_SP & DONTCARE(2 downto 0);-- ADDR=SS:SP
+ next_state <= Swritemem; -- start write cycle, MEM(SP)<=CS
+
+ elsif (passcnt=X"04") then -- Third pass SP<=SP-2
+ second_pass_s <= '1';
+ path_s.dbus_output<=DONTCARE(1 downto 0);
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_SP(2 downto 0); -- dimux & w & seldreg
+ path_s.ea_output<= NB_SS_SP & DONTCARE(2 downto 0); -- SS:SP+2
+ wrpath_s.wrd <= '1'; -- Update SP
+ next_state <= Sdecode;
+
+ elsif (passcnt=X"03") then -- fourth pass, write IP
+ second_pass_s <= '1';
+ path_s.segreg_input <= DONTCARE(3 downto 0); -- simux & selsreg
+ path_s.datareg_input<= DONTCARE(2 downto 0)& '1' &DONTCARE(2 downto 0); -- dimux & w & seldreg
+ path_s.dbus_output <= IPBUS_OUT; --{eabus(0)&} domux setting CS out
+ path_s.ea_output<= NB_SS_SP & DONTCARE(2 downto 0);-- ADDR=SS:SP
+ next_state <= Swritemem; -- start write cycle, MEM(SP)<=CS
+
+ elsif (passcnt=X"02") then -- fifth pass, CS<=Mem(EA+2)
+ second_pass_s <= '1'; -- need another pass
+ path_s.segreg_input <= SMDBUS_IN & CS_IN(1 downto 0); -- simux & selsreg
+ path_s.datareg_input<= DONTCARE(2 downto 0)& '1' &DONTCARE(2 downto 0); -- dimux & w & seldreg
+ wrpath_s.wrs <= '1'; -- update cs
+ -- dispmux(3) & eamux(4) & dis_opflag & segop[1:0]
+ path_s.ea_output<= MD_EA2_DS; --"010110011"; -- Get indirect value EA+2
+ next_state <= Sreadmem; -- Get CS value from memory
+
+ elsif (passcnt=X"01") then -- sixth pass, IP<=Mem(EA)
+ second_pass_s <= '1'; -- need another pass
+ path_s.datareg_input<= DONTCARE(2 downto 0)& '1' &DONTCARE(2 downto 0); -- dimux & w & seldreg
+ wrpath_s.wrip <= '1'; -- update ip
+ -- dispmux(3) & eamux(4) & dis_opflag & segop[1:0]
+ path_s.ea_output<= "0100001011"; -- Get indirect value EA
+ next_state <= Sreadmem; -- Get CS value from memory
+
+ else -- Final pass, update IP & CS
+ second_pass_s <= '0'; -- clear
+ path_s.dbus_output <= IPBUS_OUT; --{eabus(0)&} domux setting
+ path_s.datareg_input<= DONTCARE(2 downto 0)& '1' &DONTCARE(2 downto 0); -- dimux & w & seldreg
+ flush_req_s <= '1'; -- Flush Prefetch queue, asserted during execute cycle
+ path_s.ea_output<=NB_CS_IP; -- dispmux & eamux & segop
+ next_state <= Sexecute;
+ end if;
+
+ end if;
+
+ ---------------------------------------------------------------------------------
+ -- JMP Indirect within Segment
+ -- IP<=EA
+ ---------------------------------------------------------------------------------
+ when "100" =>
+ path_s.datareg_input<= DONTCARE(2 downto 0)& '1' &DONTCARE(2 downto 0); -- dimux & w & seldreg
+
+ if instr.xmod="11" then -- Immediate to Register r/m=reg field
+ second_pass_s <= '0';
+ flush_req_s <= '1'; -- Flush Prefetch queue, asserted during execute cycle
+ path_s.ea_output<= "1001001001"; -- Select eabus with eamux(0)=0 (dispmux(3) & eamux(4) & segop(2)
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Sexecute;
+ else -- source is memory
+
+ if (second_pass='0') then -- first pass read operand
+ second_pass_s <= '1'; -- need another pass
+ path_s.ea_output<= "0100001011"; -- Get indirect value
+ wrpath_s.wrip <= '1'; -- Update IP register
+ next_state <= Sreadmem; -- start read cycle
+ else
+ second_pass_s <= '0'; -- clear
+ flush_req_s <= '1'; -- Flush Prefetch queue, asserted during execute cycle
+ path_s.ea_output<= "0100000011"; -- select CS:IPreg before Flush
+ next_state <= Sexecute;
+ end if;
+
+ end if;
+
+ ---------------------------------------------------------------------------------
+ -- JMP Indirect Inter Segment
+ -- IP<=EA
+ -- CS<=EA+2
+ ---------------------------------------------------------------------------------
+ when "101" =>
+ path_s.datareg_input<= DONTCARE(2 downto 0)& '1' &DONTCARE(2 downto 0); -- dimux & w & seldreg
+ path_s.segreg_input <= SMDBUS_IN & CS_IN(1 downto 0); -- simux & selsreg
+
+ if (second_pass='0') then -- first pass read IP
+ second_pass_s <= '1'; -- need another pass
+ passcnt_s <= X"01"; -- need extra pass
+ path_s.ea_output<= "0100001011"; -- Get indirect value
+ wrpath_s.wrip <= '1'; -- Update IP register
+ next_state <= Sreadmem; -- start read cycle
+ else
+ passcnt_s <= passcnt - '1';
+
+ if (passcnt=X"01") then
+ second_pass_s <= '1'; -- need another pass (HT0912)
+ -- path_s.segreg_input <= SMDBUS_IN & CS_IN(1 downto 0); -- simux & selsreg
+ -- path_s.datareg_input<= DONTCARE(2 downto 0)& '1' &DONTCARE(2 downto 0); -- dimux & w & seldreg
+ -- dispmux(3) & eamux(4) & dis_opflag & segop[1:0]
+ path_s.ea_output<= MD_EA2_DS; -- Get indirect value EA+2
+ wrpath_s.wrs <= '1'; -- update cs
+ next_state <= Sreadmem; -- Get CS value from memory
+ else
+ second_pass_s <= '0'; -- clear
+ flush_req_s <= '1'; -- Flush Prefetch queue, asserted during execute cycle
+ path_s.ea_output<= "0100000011"; -- select CS:IPreg before Flush
+ next_state <= Sexecute;
+ end if;
+ end if;
+
+
+ ---------------------------------------------------------------------------------
+ -- PUSH reg/memory
+ ---------------------------------------------------------------------------------
+ when "110" => -- PUSH MEM Instuction
+
+ path_s.dbus_output <= DIBUS_OUT; --{eabus(0)&} domux setting
+ path_s.alu_operation<= REG_SP & REG_CONST2 & ALU_PUSH;-- selalua(4) & selalub(4) & aluopr
+ -- change ALU_Push???
+
+ if (second_pass='0') then -- first pass read operand and execute SP-2
+ second_pass_s <= '1'; -- need another pass
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_SP(2 downto 0); -- dimux & w & seldreg
+ path_s.ea_output <= NB_DS_EA; -- dispmux & eamux & segop (unless Segment OP flag is set)
+ wrpath_s.wrd <= '1'; -- Update SP
+ next_state <= Sreadmem; -- start read cycle
+ else
+ second_pass_s <= '0'; -- clear
+ -- Second Pass, write memory operand to stack
+ path_s.datareg_input<= MDBUS_IN & '1' & DONTCARE(2 downto 0); -- dimux & w & seldreg
+ path_s.ea_output <= NB_SS_SP & DONTCARE(2 downto 0); -- dispmux(2) & eamux(4) & [flag]&segop(2)
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Swritemem; -- start write cycle
+ end if;
+
+
+ when others =>
+ next_state <= Sdecode; -- To avoid latches
+ -- pragma synthesis_off
+ assert not (now > 0 ns) report "**** FF/FE REGField=111 Illegal Instuction ***" severity warning;
+ -- pragma synthesis_on
+
+ end case;
+
+
+ ---------------------------------------------------------------------------------
+ -- CALL Direct within Segment
+ -- SP<=SP-2
+ -- Mem(SP)<=IP
+ -- IP<=IP+/-Disp
+ ---------------------------------------------------------------------------------
+ when CALL =>
+
+ flush_coming_s<= '1'; -- signal to the BIU that a flush is coming,
+ -- this will stop the BIU from filling the queue.
+ path_s.alu_operation<= REG_SP & REG_CONST2 & ALU_PUSH;-- selalua(4) & selalub(4) & aluopr
+ path_s.dbus_output <= IPBUS_OUT; --{eabus(0)&} domux setting
+
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_SP(2 downto 0); -- dimux & w & seldreg
+
+ if (second_pass='0') then -- first pass SP-2
+ second_pass_s <= '1';
+ path_s.ea_output<= NB_SS_SP & DONTCARE(2 downto 0); -- SS:SP+2
+ passcnt_s <= X"01";
+ wrpath_s.wrd <= '1'; -- Update SP
+ next_state <= Sdecode; -- second pass
+ else -- Second pass Mem
+ passcnt_s <= passcnt - '1';
+
+ if (passcnt=X"00") then
+ second_pass_s <= '0'; -- clear
+ flush_req_s <= '1'; -- Flush Prefetch queue, asserted during execute cycle
+ path_s.ea_output<= DISP_CS_IP; -- CS: IPREG+DISPL
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Sexecute;
+ else
+ second_pass_s <= '1';
+ path_s.ea_output <= NB_SS_SP & DONTCARE(2 downto 0);-- ADDR=SS:SP
+ next_state <= Swritemem; -- start write cycle, MEM(SP)<=IP
+ end if;
+
+ end if;
+
+ ---------------------------------------------------------------------------------
+ -- CALL Direct InterSegment
+ -- SP<=SP-2,
+ -- Mem(SP)<=CS, CS<=SEGMh/l
+ -- SP<=SP-2
+ -- Mem(SP)<=IP, IP<=OFFSETh/l & Flush
+ ---------------------------------------------------------------------------------
+ when CALLDIS =>
+
+ flush_coming_s<= '1'; -- signal to the BIU that a flush is coming,
+ -- this will stop the BIU from filling the queue.
+ path_s.alu_operation<= REG_SP & REG_CONST2 & ALU_PUSH;-- selalua(4) & selalub(4) & aluopr
+
+ if (second_pass='0') then -- first pass SP<=SP-2
+ second_pass_s <= '1';
+ path_s.dbus_output<=DONTCARE(1 downto 0);
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_SP(2 downto 0); -- dimux & w & seldreg
+ path_s.ea_output<= NB_SS_SP & DONTCARE(2 downto 0); -- SS:SP+2 (DONTCARE)
+ passcnt_s <= X"03";
+ wrpath_s.wrd <= '1'; -- Update SP
+ next_state <= Sdecode;
+ else
+ passcnt_s <= passcnt - '1';
+
+ if (passcnt=X"03") then -- Second pass write CS to ss:sp
+ second_pass_s <= '1';
+ path_s.segreg_input <= DONTCARE(1 downto 0) & CS_IN(1 downto 0); -- simux & selsreg
+ path_s.datareg_input<= CS_IN & '1' & DONTCARE(2 downto 0); -- dimux & w & seldreg
+ path_s.dbus_output <= DIBUS_OUT; --{eabus(0)&} domux setting CS out
+ path_s.ea_output<= NB_SS_SP & DONTCARE(2 downto 0);-- ADDR=SS:SP
+ next_state <= Swritemem; -- start write cycle, MEM(SP)<=CS
+ elsif (passcnt=X"02") then -- Third pass SP<=SP-2
+ second_pass_s <= '1';
+ path_s.dbus_output<=DONTCARE(1 downto 0);
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_SP(2 downto 0); -- dimux & w & seldreg
+ path_s.ea_output<= NB_SS_SP & DONTCARE(2 downto 0); -- SS:SP+2
+ wrpath_s.wrd <= '1'; -- Update SP
+ next_state <= Sdecode;
+ elsif (passcnt=X"01") then -- fourth pass, write IP
+ second_pass_s <= '1';
+ path_s.segreg_input <= DONTCARE(3 downto 0); -- simux & selsreg
+ path_s.datareg_input<= DONTCARE(6 downto 0); -- dimux & w & seldreg
+ path_s.dbus_output <= IPBUS_OUT; --{eabus(0)&} domux setting CS out
+ path_s.ea_output<= NB_SS_SP & DONTCARE(2 downto 0);-- ADDR=SS:SP
+ next_state <= Swritemem; -- start write cycle, MEM(SP)<=CS
+ else -- Final pass, update IP & CS
+ second_pass_s <= '0'; -- clear
+ path_s.dbus_output<=DONTCARE(1 downto 0);
+ flush_req_s <= '1'; -- Flush Prefetch queue, asserted during execute cycle
+ path_s.segreg_input <= SDATAIN_IN & CS_IN(1 downto 0); -- simux & selsreg
+ path_s.ea_output<=LD_CS_IP; -- dispmux & eamux & segop Load new IP from memory
+ wrpath_s.wrs <= '1'; -- Update CS register
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Sexecute;
+ end if;
+
+ end if;
+
+ ---------------------------------------------------------------------------------
+ -- RET Instructions
+ -- IP<=Mem(SS:SP),
+ -- SP<=SP+2 (RET)
+ -- CS<=Mem(SS:SP),
+ -- SP<=SP+2 (RETDIS)
+ ---------------------------------------------------------------------------------
+ when RET | RETDIS | RETO | RETDISO =>
+
+ flush_coming_s<= '1'; -- signal to the BIU that a flush is coming,
+ -- this will stop the BIU from filling the queue.
+ if (second_pass='1' and passcnt=X"00") then -- last stage, add data_in to SP
+ path_s.alu_operation<= REG_SP & REG_DATAIN & ALU_ADD;-- selalua(4) & selalub(4) & aluopr
+ else
+ path_s.alu_operation<= REG_SP & REG_CONST2 & ALU_POP;-- selalua(4) & selalub(4) & aluopr
+ end if;
+
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_SP(2 downto 0); -- dimux & w & seldreg
+ path_s.dbus_output <= IPBUS_OUT; --{eabus(0)&} domux setting
+ -- required to write to abusreg!!
+
+ if (second_pass='0') then -- first pass IP<=MEM(SS:SP)
+ second_pass_s <= '1';
+ path_s.ea_output<=LD_SS_SP&DONTCARE(2 downto 0);-- dispmux & eamux & segop, POP IP, SS:SP
+ passcnt_s <= X"03"; -- 4 cycles
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Sreadmem; -- Read Stack
+ else
+
+ if (passcnt=X"03") then -- Second pass Mem SP=SP+2
+
+ wrpath_s.wrd <= '1'; -- Update SP
+ if (instr.ireg(3 downto 0)="0011") then -- RET Instruction?
+ passcnt_s <= X"00"; -- Dontcare
+ second_pass_s <= '0'; -- clear
+ flush_req_s <= '1'; -- Flush Prefetch queue
+ path_s.ea_output<=NB_CS_IP; -- select CS:IP before Flush;
+ next_state <= Sexecute;
+ elsif (instr.ireg(3 downto 0)="0010") then -- RETO Instruction?
+ passcnt_s <= X"00"; -- Jump to last stage
+ second_pass_s <= '1';
+ path_s.ea_output<= DONTCARE(9 downto 0);-- dispmux & eamux & segop, ADDR=SS:SP
+ next_state <= Sdecode;
+ else -- else RETDIS, RETDISO, update CS
+ passcnt_s <= passcnt - '1'; -- Jump to 010
+ second_pass_s <= '1';
+ path_s.ea_output<= DONTCARE(9 downto 0);-- dispmux & eamux & segop, ADDR=SS:SP
+ next_state <= Sdecode;
+ end if;
+
+ elsif (passcnt=X"02") then -- Third pass, get CS from SS:SP
+
+ passcnt_s <= passcnt - '1'; -- Jump to 01
+ second_pass_s <= '1';
+ path_s.segreg_input <= SMDBUS_IN & CS_IN(1 downto 0); -- simux & selsreg
+ path_s.ea_output<= NB_SS_SP & DONTCARE(2 downto 0);-- ADDR=SS:SP
+ wrpath_s.wrs <= '1'; -- update cs
+ next_state <= Sreadmem; -- start write cycle, MEM(SP)<=CS
+
+ elsif (passcnt=X"01") then -- SP=SP+2
+
+ wrpath_s.wrd <= '1'; -- Update SPReg
+ passcnt_s <= passcnt - '1';
+
+ if (instr.ireg(3 downto 0)="1010") then -- RETDISO Instruction?
+ second_pass_s <= '1';
+ path_s.ea_output<= IPB_CS_IP; -- need ipbus
+ next_state <= Sdecode;
+ else
+ second_pass_s <= '0'; -- clear
+ flush_req_s <= '1'; -- Flush Prefetch queue, asserted during execute cycle
+ path_s.ea_output<= IPB_CS_IP; -- dispmux(3) & eamux(4) & dis_opflag & segop[1:0]
+ next_state <= Sexecute;
+ end if;
+
+ else -- Final pass, Add offset to SP
+ second_pass_s <= '0'; -- clear
+ flush_req_s <= '1'; -- Flush Prefetch queue, asserted during execute cycle
+ path_s.ea_output<=NB_CS_IP; -- select CS:IP for Flush;"100000000"; -- dispmux(3) & eamux(4) & dis_opflag & segop[1:0]
+ wrpath_s.wrd <= '1'; -- Update SPReg
+ next_state <= Sexecute;
+ end if;
+
+ end if;
+
+ ---------------------------------------------------------------------------------
+ -- Software/Hardware Interrupts
+ -- SP<=SP-2
+ -- MEM(SS:SP)<=FLAGS
+ -- SP<=SP-2
+ -- MEM(SS:SP)<=CS
+ -- SP<=SP-2
+ -- MEM(SS:SP)<=IP
+ -- CS<=MEM(type*4) IF=TF=0
+ -- IP<=MEM(type*4)+2
+ -- Note save 1 cycle by adding type*4+2 to dispmux, IP and CS can be updated at
+ -- the same time
+ ---------------------------------------------------------------------------------
+ when INT | INT3 | INTO =>
+
+ irq_blocked_s <= '1'; -- Block IRQ if asserted during next instr.
+
+ if (second_pass='0') then -- first pass SP<=SP-2
+
+ if (instr.ireg(1 downto 0)="10" and status.flag(11)='0') then -- if int0 & no Overflow then do nothing
+ second_pass_s <='0';
+ path_s.ea_output<= NB_CS_IP;
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Sexecute; -- no nothing
+ else
+ second_pass_s <= '1';
+ flush_coming_s <= '1'; -- Signal to the BIU that a flush is coming,
+ -- this will stop the BIU from filling the queue.
+ path_s.ea_output<= NB_SS_SP & DONTCARE(2 downto 0); -- SS:SP+2
+ wrpath_s.wrd <= '1'; -- Update SP
+ next_state <= Sdecode;
+ end if;
+ path_s.alu_operation<= REG_SP & REG_CONST2 & ALU_PUSH;-- selalua(4) & selalub(4) & aluopr
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_SP(2 downto 0); -- dimux & w & seldreg
+ passcnt_s <= X"07";
+
+ else
+ passcnt_s <= passcnt - '1';
+ flush_coming_s<= '1'; -- Signal to the BIU that a flush is coming,
+ -- this will stop the BIU from filling the queue.
+ if (passcnt=X"07") then -- Second pass write Flags to SS:SP
+ second_pass_s <= '1';
+ path_s.datareg_input<= DONTCARE(2 downto 0)& '1' &DONTCARE(2 downto 0); -- dimux & w & seldreg
+ path_s.dbus_output <= CCBUS_OUT; --{eabus(0)&} domux setting
+ path_s.ea_output<= NB_SS_SP & DONTCARE(2 downto 0);-- ADDR=SS:SP
+ next_state <= Swritemem; -- start write cycle, MEM(SP)<=CS
+
+ elsif (passcnt=X"06") then -- Third pass SP<=SP-2
+ second_pass_s <= '1';
+ path_s.alu_operation<= REG_SP & REG_CONST2 & ALU_PUSH;-- selalua(4) & selalub(4) & aluopr
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_SP(2 downto 0); -- dimux & w & seldreg
+ path_s.ea_output<= NB_SS_SP & DONTCARE(2 downto 0); -- SS:SP+2
+ wrpath_s.wrd <= '1'; -- Update SP
+ next_state <= Sdecode;
+
+ elsif (passcnt=X"05") then -- Fourth pass write CS to SS:SP
+ second_pass_s <= '1';
+ path_s.segreg_input <= DONTCARE(1 downto 0) & CS_IN(1 downto 0); -- simux & selsreg
+ path_s.alu_operation<= DONTCARE(7 downto 0) & ALU_CLRTIF;-- selalua(4) & selalub(4) & aluopr
+ path_s.datareg_input<= CS_IN & '1' & DONTCARE(2 downto 0); -- dimux & w & seldreg
+ path_s.dbus_output <= DIBUS_OUT; --{eabus(0)&} domux setting CS out
+ path_s.ea_output<= NB_SS_SP & DONTCARE(2 downto 0);-- ADDR=SS:SP
+ wrpath_s.wrcc <= '1'; -- Clear IF and TF flag
+ next_state <= Swritemem; -- start write cycle, MEM(SP)<=CS
+
+ elsif (passcnt=X"04") then -- Fifth pass SP<=SP-2
+ second_pass_s <= '1';
+ path_s.dbus_output<=DONTCARE(1 downto 0); -- make same as previous??????????
+ path_s.alu_operation<= REG_SP & REG_CONST2 & ALU_PUSH;-- selalua(4) & selalub(4) & aluopr
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_SP(2 downto 0); -- dimux & w & seldreg
+ path_s.ea_output<= NB_SS_SP & DONTCARE(2 downto 0); -- SS:SP+2
+ wrpath_s.wrd <= '1'; -- Update SP
+ next_state <= Sdecode;
+
+ elsif (passcnt=X"03") then -- Sixth pass, write IP
+ second_pass_s <= '1';
+ path_s.segreg_input <= DONTCARE(3 downto 0); -- simux & selsreg
+ path_s.datareg_input<= DONTCARE(2 downto 0)& '1' &DONTCARE(2 downto 0); -- dimux & w & seldreg
+ path_s.dbus_output <= IPBUS_OUT; --{eabus(0)&} domux setting CS out
+ path_s.ea_output<= NB_SS_SP & DONTCARE(2 downto 0);-- ADDR=SS:SP
+ next_state <= Swritemem; -- start write cycle, MEM(SP)<=CS
+
+ elsif (passcnt=X"02") then -- Seventh pass, CS<=Mem(EA*4+2)
+ second_pass_s <= '1'; -- need another pass
+ path_s.segreg_input <= SMDBUS_IN & CS_IN(1 downto 0); -- simux & selsreg read mem
+ path_s.datareg_input<= DONTCARE(2 downto 0)& '1' &DONTCARE(2 downto 0); -- dimux & w & seldreg
+ wrpath_s.wrs <= '1'; -- Update CS, NOTE THIS CHANGES SEGBUS THUS AFFECTING
+ -- THE NEXT READ ADDRESS, TO PREVEND THIS SEGBUS
+ -- IS FORCED TO ZERO.
+ path_s.ea_output<= "1100111001"; -- Get indirect value EA*4+2, ip<-mdbus_in
+
+ next_state <= Sreadmem; -- get CS value from MEM(type*4)
+
+ elsif (passcnt=X"01") then -- Eigth pass, IP<=MEM(EA*4+2)
+ second_pass_s <= '1'; -- need another pass
+ path_s.datareg_input<= DONTCARE(2 downto 0)& '1' &DONTCARE(2 downto 0); -- dimux & w & seldreg
+ path_s.dbus_output <= IPBUS_OUT; --{eabus(0)&} domux setting
+ wrpath_s.wrip <= '1'; -- update ip
+ -- dispmux(3) & eamux(4) & dis_opflag & segop[1:0]
+ path_s.ea_output<= "0100110001"; -- Get indirect value mem(EA*4)
+ next_state <= Sreadmem;
+
+ else -- Ninth pass, update IP & CS
+ second_pass_s <= '0'; -- clear
+ path_s.dbus_output <= IPBUS_OUT; --{eabus(0)&} domux setting
+ path_s.datareg_input<= DONTCARE(2 downto 0)& '1' &DONTCARE(2 downto 0); -- dimux & w & seldreg
+ flush_req_s <= '1'; -- Flush Prefetch queue, asserted during execute cycle
+ path_s.ea_output<=NB_CS_IP; -- dispmux & eamux & segop
+ next_state <= Sexecute;
+ end if;
+
+ end if;
+
+ ---------------------------------------------------------------------------------
+ -- IRET, Interrupt Return
+ -- IP <=MEM(SS:SP)
+ -- SP<=SP+2
+ -- CS<=MEM(SS:SP)
+ -- SP<=SP+2
+ -- FLAGS<=MEM(SS:SP)
+ -- SP<=SP+2
+ -- Flush
+ ---------------------------------------------------------------------------------
+ when IRET =>
+
+ flush_coming_s<= '1'; -- signal to the BIU that a flush is coming,
+ -- this will stop the BIU from filling the queue.
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_SP(2 downto 0); -- dimux & w & seldreg
+ path_s.dbus_output <= IPBUS_OUT; --{eabus(0)&} domux setting
+ -- required to write to abusreg!!
+
+ if (second_pass='0') then -- first pass IP<=MEM(SS:SP)
+ second_pass_s <= '1';
+ path_s.ea_output<=LD_SS_SP&DONTCARE(2 downto 0);-- dispmux & eamux & segop, POP IP, SS:SP
+ passcnt_s <= X"04"; -- 4 cycles
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Sreadmem; -- Read Stack
+ else
+ passcnt_s <= passcnt - '1';
+
+ if (passcnt=X"04") then -- Second pass Mem SP=SP+2
+ second_pass_s <= '1';
+ path_s.alu_operation<= REG_SP & REG_CONST2 & ALU_POP;-- selalua(4) & selalub(4) & aluopr
+ path_s.ea_output<= DONTCARE(9 downto 0); -- dispmux & eamux & segop, ADDR=SS:SP
+ wrpath_s.wrd <= '1'; -- Update SP
+ next_state <= Sdecode;
+
+ elsif (passcnt=X"03") then -- Third pass, get CS from SS:SP
+ second_pass_s <= '1';
+ path_s.segreg_input <= SMDBUS_IN & CS_IN(1 downto 0); -- simux & selsreg
+ path_s.ea_output<= NB_SS_SP & DONTCARE(2 downto 0);-- ADDR=SS:SP
+ wrpath_s.wrs <= '1'; -- update cs
+ next_state <= Sreadmem; -- start write cycle, MEM(SP)<=CS
+
+ elsif (passcnt=X"02") then -- SP=SP+2
+ second_pass_s <= '1';
+ path_s.alu_operation<= REG_SP & REG_CONST2 & ALU_POP;-- selalua(4) & selalub(4) & aluopr
+ wrpath_s.wrd <= '1'; -- Update SP
+ path_s.ea_output<= IPB_CS_IP; -- dispmux(3) & eamux(4) & dis_opflag & segop[1:0]
+ next_state <= Sdecode;
+
+ elsif (passcnt=X"01") then -- get FLAGS from memory
+ second_pass_s <= '1';
+ path_s.alu_operation<= REG_MDBUS & REG_CONST2 & ALU_POP;-- selalua(4) & selalub(4) & aluopr
+ path_s.ea_output <= NB_SS_SP &DONTCARE(2 downto 0); -- SS:SP+2
+ wrpath_s.wrcc <= '1'; -- Update FLAGS register
+ next_state <= Sreadmem;
+
+ else -- Final pass, SP<=SP+2
+ second_pass_s <= '0'; -- clear
+ path_s.alu_operation<= REG_SP & REG_CONST2 & ALU_POP;-- selalua(4) & selalub(4) & aluopr
+ wrpath_s.wrd <= '1'; -- Update SP
+ flush_req_s <= '1'; -- Flush Prefetch queue, asserted during execute cycle
+ path_s.ea_output<=NB_CS_IP; -- select CS:IP for Flush;"100000000";-- dispmux(3) & eamux(4) & dis_opflag & segop[1:0]
+ wrpath_s.wrd <= '1'; -- Update SPReg
+ next_state <= Sexecute;
+ end if;
+
+ end if;
+
+ ---------------------------------------------------------------------------------
+ -- Load String
+ -- AL/AX<=DS:[SI] SI++/--
+ -- if REP flag is set, then CX-1, check ZF,
+ -- for REP if zf=1 then exit
+ -- for REPZ if zf=0 then exit
+ -- NOTE: Debug does not seem to be able to handle this instruction on REPZ
+ -- To be compatable Z flag checking is removed, thus only depended on CX
+ ---------------------------------------------------------------------------------
+ when LODSB | LODSW =>
+
+ if (second_pass='0') then -- First pass, load AL/AX<=DS:[SI]
+ passcnt_s <= X"01"; -- jump to extra pass 1 (skip 10 first round)
+
+ path_s.datareg_input<= MDBUS_IN & instr.ireg(0) & REG_AX(2 downto 0); -- dimux & w & seldreg
+ path_s.alu_operation<= DONTCARE(14 downto 0); -- selalua(4) & selalub(4) & aluopr(7)
+ -- DS:[SI]
+ if (rep_flag='1' and status.cx_zero='1') then -- if CX=0 then skip instruction
+ second_pass_s <= '0';
+ rep_clear_s <= '1'; -- Clear Repeat flag
+ path_s.ea_output<=NB_CS_IP;
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Sexecute;
+ else
+ second_pass_s <= '1'; -- Need another pass
+ path_s.ea_output<="0001011001"; -- dispmux(3) & eamux(4) & dis_opflag & segop[1:0]
+ wrpath_s.wrd <= '1'; -- Update AX
+ next_state <= Sreadmem; -- start read cycle
+ end if;
+ else
+
+ if (passcnt=X"02") then -- load al/ax<= DS:[SI]
+ second_pass_s <= '1'; -- Need another pass
+ passcnt_s <= passcnt - '1';
+ path_s.datareg_input<= MDBUS_IN & instr.ireg(0) & REG_AX(2 downto 0); -- dimux & w & seldreg
+ path_s.alu_operation<= DONTCARE(14 downto 0);-- selalua(4) & selalub(4) & aluopr(7)
+ -- DS:[SI]
+ path_s.ea_output<="0001011001"; -- dispmux(3) & eamux(4) & dis_opflag & segop[1:0]
+
+ wrpath_s.wrd <= '1'; -- Update AX
+ next_state <= Sreadmem; -- start read cycle
+
+ elsif (passcnt=X"01") then -- Second PASS update SI
+ second_pass_s <= '1';
+ passcnt_s <= passcnt - '1';
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_SI(2 downto 0);-- dimux & w & seldreg
+
+ path_s.alu_operation<= REG_SI & -- selalua(4) & selalub(4) & aluopr
+ REG_CONST1(3 downto 2)&instr.ireg(0)&(not instr.ireg(0))& -- w selects 1 or 2
+ ALU_INC(6 downto 1)&status.flag(10); -- df flag select inc/dec
+
+ path_s.ea_output<=NB_CS_IP; -- dispmux(3) & eamux(4) & dis_opflag & segop[1:0]
+
+ wrpath_s.wrd <= '1'; -- Update SI
+ if rep_flag='1' then -- If repeat set, check CX-1
+ second_pass_s <= '1';
+ next_state <= Sdecode;
+ else -- no repeat end cycle
+ second_pass_s <= '0';
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Sexecute;
+ end if;
+ else -- third pass (only when rep_flag=1) CX-1
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_CX(2 downto 0);-- dimux & w & seldreg
+ path_s.alu_operation<= REG_CX & REG_CONST1 & ALU_DEC; -- selalua(4) & selalub(4) & aluopr
+ path_s.ea_output <= NB_CS_IP; -- dispmux(3) & eamux(4) & dis_opflag & segop[1:0]
+ wrpath_s.wrd <= '1'; -- Update CX
+ --if (status.cx_one='1' or rep_zl_s/=status.flag(6)) then -- quit on CX=1 or ZF=z_repeat_intr
+ if (status.cx_one='1') then -- quit on CX=1 IGNORE ZFLAG!!!!
+ second_pass_s <= '0';
+ rep_clear_s <= '1'; -- Clear Repeat flag
+ passcnt_s <= passcnt - '1'; -- not required, change to DONTCARE???????????????????????????????
+ wrpath_s.wrip <= '1';
+ next_state <= Sexecute;
+ else
+ second_pass_s <= '1';
+ passcnt_s <= X"02"; -- Next another read mem pass
+ next_state <= Sdecode;
+ end if;
+ end if;
+ end if;
+
+
+ ---------------------------------------------------------------------------------
+ -- Store String
+ -- ES:[DI] <=AL/AX DI++/--
+ -- if REP/REPZ then repeat on CX value only!
+ ---------------------------------------------------------------------------------
+ when STOSB | STOSW =>
+
+ if (second_pass='0') then -- First pass, load ES:[DI]<=AL/AX
+ passcnt_s <= X"01"; -- jump to extra pass 1 (skip 10 first round)
+
+ path_s.datareg_input<= DONTCARE(2 downto 0) & instr.ireg(0) & DONTCARE(2 downto 0);-- dimux & w & seldreg
+ path_s.alu_operation<= REG_AX&DONTCARE(3 downto 0)&ALU_PASSA;-- selalua(4) & selalub(4) & aluopr(7)
+ path_s.dbus_output <= ALUBUS_OUT; --{eabus(0)&} domux setting
+
+ if (rep_flag='1' and status.cx_zero='1') then -- if CX=0 then skip instruction
+ second_pass_s <= '0';
+ rep_clear_s <= '1'; -- Clear Repeat flag
+ path_s.ea_output<=NB_CS_IP;
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Sexecute;
+ else
+ second_pass_s <= '1'; -- Need another pass
+ path_s.ea_output<="0001000001"; -- dispmux(3) & eamux(4) & dis_opflag & segop[1:0]
+ next_state <= Swritemem; -- start write cycle
+ end if;
+
+ else
+
+ if (passcnt=X"02") then -- load ES:[DI]<=AL/AX
+ second_pass_s <= '1'; -- Need another pass
+ passcnt_s <= passcnt - '1';
+
+ path_s.datareg_input<= DONTCARE(2 downto 0) & instr.ireg(0) & DONTCARE(2 downto 0);-- dimux & w & seldreg
+ path_s.alu_operation<= REG_AX&DONTCARE(3 downto 0)&ALU_PASSA;-- selalua(4) & selalub(4) & aluopr(7)
+ path_s.dbus_output <= ALUBUS_OUT; --{eabus(0)&} domux setting
+
+ path_s.ea_output<="0001000001"; -- dispmux(3) & eamux(4) & dis_opflag & segop[1:0]
+ next_state <= Swritemem; -- start write cycle
+
+ elsif (passcnt=X"01") then -- Second PASS update DI
+ second_pass_s <= '1';
+ passcnt_s <= passcnt - '1';
+
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_DI(2 downto 0);-- dimux & w & seldreg
+
+ path_s.alu_operation<= REG_DI & -- selalua(4) & selalub(4) & aluopr
+ REG_CONST1(3 downto 2)&instr.ireg(0)&(not instr.ireg(0))& -- w selects 1 or 2
+ ALU_INC(6 downto 1)&status.flag(10); -- df flag select inc/dec
+
+ path_s.ea_output<=NB_CS_IP; -- dispmux(3) & eamux(4) & dis_opflag & segop[1:0]
+ wrpath_s.wrd <= '1'; -- Update DI
+
+ if rep_flag='1' then -- If repeat set, check CX-1
+ second_pass_s <= '1';
+ next_state <= Sdecode;
+ else -- no repeat end cycle
+ second_pass_s <= '0';
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Sexecute;
+ end if;
+ else -- third pass (only when rep_flag=1) CX-1
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_CX(2 downto 0);-- dimux & w & seldreg
+ path_s.alu_operation<= REG_CX & REG_CONST1 & ALU_DEC; -- selalua(4) & selalub(4) & aluopr
+ path_s.ea_output <= NB_CS_IP; -- dispmux(3) & eamux(4) & dis_opflag & segop[1:0]
+ wrpath_s.wrd <= '1'; -- Update CX
+
+ --if (status.cx_one='1' or rep_zl_s/=status.flag(6)) then -- quit on CX=1 or ZF=z_repeat_intr
+ if (status.cx_one='1') then -- quit on CX=1 IGNORE ZFLAG!!!!
+ second_pass_s <= '0';
+ rep_clear_s <= '1'; -- Clear Repeat flag
+ passcnt_s <= passcnt - '1'; -- not required, change to DONTCARE???????????????????????????????
+ wrpath_s.wrip <= '1';
+ next_state <= Sexecute;
+ else
+ second_pass_s <= '1';
+ passcnt_s <= X"02"; -- Next another read mem pass
+ next_state <= Sdecode;
+ end if;
+ end if;
+ end if;
+
+ ---------------------------------------------------------------------------------
+ -- MOV String
+ -- ES:[DI] <=SEG:[SI], SEG default to DS
+ -- DI++/-- ,SI++/--
+ ---------------------------------------------------------------------------------
+ when MOVSB | MOVSW =>
+
+ if (second_pass='0') then -- First pass, load ALUREG<=SEG:[SI]
+ passcnt_s <= X"03"; -- Jump to state 3
+
+ path_s.datareg_input<= MDBUS_IN & instr.ireg(0) & DONTCARE(2 downto 0); -- dimux & w & seldreg
+ -- Load memory into ALUREG
+ path_s.alu_operation<= DONTCARE(3 downto 0) & REG_MDBUS & ALU_REGL; -- selalua(4) & selalub(4) & aluopr(7)
+ wrpath_s.wralu <= '1'; -- Don't care if instruction is not executed
+
+ if (rep_flag='1' and status.cx_zero='1') then -- if CX=0 then skip instruction
+ second_pass_s <= '0';
+ rep_clear_s <= '1'; -- Clear Repeat flag
+ path_s.ea_output<=NB_CS_IP;
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Sexecute;
+ else
+ second_pass_s <= '1'; -- Need another pass
+ path_s.ea_output<="0001011001"; -- dispmux(3) & eamux(4) & dis_opflag & segop[1:0]
+ next_state <= Sreadmem; -- start read cycle
+ end if;
+
+ else
+
+ if (passcnt=X"04") then -- Same operation as second_pass=0, load ALUREG<=SEG:[SI]
+ second_pass_s <= '1'; -- Need another pass
+ passcnt_s <= passcnt - '1';
+
+ path_s.datareg_input<= MDBUS_IN & instr.ireg(0) & DONTCARE(2 downto 0); -- dimux & w & seldreg
+ -- Load memory into ALUREG
+ path_s.alu_operation<= DONTCARE(3 downto 0) & REG_MDBUS & ALU_REGL; -- selalua(4) & selalub(4) & aluopr(7)
+ wrpath_s.wralu <= '1'; -- Don't care if instruction is not executed
+
+ path_s.ea_output<="0001011001"; -- dispmux(3) & eamux(4) & dis_opflag & segop[1:0]
+ next_state <= Sreadmem; -- start read cycle
+
+ elsif (passcnt=X"03") then -- second pass write ALUREG to ES:DI
+ second_pass_s <= '1';
+ passcnt_s <= passcnt - '1';
+
+ path_s.datareg_input<= DONTCARE(2 downto 0) & instr.ireg(0) & DONTCARE(2 downto 0);-- dimux & w & seldreg
+
+ path_s.alu_operation<= DONTCARE(7 downto 0)&ALU_REGL;-- selalua(4) & selalub(4) & aluopr(7) ALUREG=>output
+ path_s.dbus_output <= ALUBUS_OUT; --{eabus(0)&} domux setting
+ -- ES:[DI]
+ path_s.ea_output<="0001000101"; -- dispmux(3) & eamux(4) & dis_opflag=1 & segop[1:0]
+
+ next_state <= Swritemem; -- start write cycle
+
+ elsif (passcnt=X"02") then -- Next update DI
+ second_pass_s <= '1';
+ passcnt_s <= passcnt - '1';
+
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_DI(2 downto 0);-- dimux & w & seldreg
+
+ path_s.alu_operation<= REG_DI & -- selalua(4) & selalub(4) & aluopr
+ REG_CONST1(3 downto 2)&instr.ireg(0)&(not instr.ireg(0))& -- w selects 1 or 2
+ ALU_INC(6 downto 1)&status.flag(10); -- df flag select inc/dec
+
+ path_s.ea_output<=DONTCARE(9 downto 0); -- dispmux(3) & eamux(4) & dis_opflag & segop[1:0]
+
+ wrpath_s.wrd <= '1'; -- Update DI
+ next_state <= Sdecode;
+
+ elsif (passcnt=X"01") then -- Final pass if no repeat update SI
+ second_pass_s <= '0'; -- clear
+ passcnt_s <= passcnt - '1';
+
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_SI(2 downto 0);-- dimux & w & seldreg
+
+ path_s.alu_operation<= REG_SI & -- selalua(4) & selalub(4) & aluopr
+ REG_CONST1(3 downto 2)&instr.ireg(0)&(not instr.ireg(0))& -- w selects 1 or 2
+ ALU_INC(6 downto 1)&status.flag(10); -- df flag select inc/dec
+
+ path_s.ea_output<=NB_CS_IP; -- dispmux(3) & eamux(4) & dis_opflag & segop[1:0]
+
+ wrpath_s.wrd <= '1'; -- Update SI
+
+ if rep_flag='1' then -- If repeat set, check CX-1
+ second_pass_s <= '1';
+ next_state <= Sdecode;
+ else -- no repeat end cycle
+ second_pass_s <= '0';
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Sexecute;
+ end if;
+
+ else -- third pass (only when rep_flag=1) CX-1
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_CX(2 downto 0);-- dimux & w & seldreg
+ path_s.alu_operation<= REG_CX & REG_CONST1 & ALU_DEC; -- selalua(4) & selalub(4) & aluopr
+ path_s.ea_output <= NB_CS_IP; -- dispmux(3) & eamux(4) & dis_opflag & segop[1:0]
+ wrpath_s.wrd <= '1'; -- Update CX
+
+ if (status.cx_one='1') then -- quit on CX=1 IGNORE ZFLAG!!!!
+ second_pass_s <= '0';
+ rep_clear_s <= '1'; -- Clear Repeat flag
+ passcnt_s <= passcnt - '1'; -- not required, change to DONTCARE???????????????????????????????
+ wrpath_s.wrip <= '1';
+ next_state <= Sexecute;
+ else
+ second_pass_s <= '1';
+ passcnt_s <= X"04"; -- Next another R/W mem pass
+ next_state <= Sdecode;
+ end if;
+
+ end if;
+
+ end if;
+
+ ---------------------------------------------------------------------------------
+ -- CMPS Destination, source
+ -- note source - destination
+ -- SEGM:[SI] - ES:[DI]
+ --
+ -- SEGM defaults to DS, can be overwritten
+ -- Destination is ALWAYS ES:[DI] (dis_opflag is asserted during the read cycle)
+ -- DI++/--, SI++/--
+ -- Note no signextend on operands (compared to the CMP instruction)
+ ---------------------------------------------------------------------------------
+ when CMPSB | CMPSW =>
+
+ if (second_pass='0') then -- First pass, load ALUREG<=ES:[DI] (fixed!)
+ passcnt_s <= X"03"; -- Jump to state 3
+
+ path_s.datareg_input<= MDBUS_IN & instr.ireg(0) & DONTCARE(2 downto 0); -- dimux & w & seldreg
+ -- Load memory into ALUREG
+ path_s.alu_operation<= DONTCARE(3 downto 0) & REG_MDBUS & ALU_REGL; -- selalua(4) & selalub(4) & aluopr(7)
+ wrpath_s.wralu <= '1'; -- Don't care if instruction is not executed
+
+ if (rep_flag='1' and status.cx_zero='1') then -- if CX=0 then skip instruction
+ second_pass_s <= '0';
+ rep_clear_s <= '1'; -- Clear Repeat flag
+ path_s.ea_output<=NB_CS_IP;
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Sexecute;
+ else
+ second_pass_s <= '1'; -- Need another pass, note dis_opflag=1
+ path_s.ea_output<="0001000101"; -- dispmux(3) & eamux(4) & dis_opflag=1 & segop[1:0]
+ next_state <= Sreadmem; -- start read cycle
+ end if;
+
+ else
+
+ if (passcnt=X"04") then -- Same operation as second_pass=0, load ALUREG<=SEG:[SI]
+ second_pass_s <= '1'; -- Need another pass
+ passcnt_s <= passcnt - '1';
+
+ path_s.datareg_input<= MDBUS_IN & instr.ireg(0) & DONTCARE(2 downto 0); -- dimux & w & seldreg
+ -- for CMPS load memory into ALUREG
+ path_s.alu_operation<= DONTCARE(3 downto 0) & REG_MDBUS & ALU_REGL; -- selalua(4) & selalub(4) & aluopr(7)
+ path_s.ea_output<="0001000101"; -- dispmux(3) & eamux(4) & dis_opflag=1 & segop[1:0]
+ wrpath_s.wralu <= '1';
+
+ next_state <= Sreadmem; -- start read cycle
+
+ elsif (passcnt="0011") then -- second pass read SEG:[SI], ALUREG-SEG:[SI]
+ second_pass_s <= '1';
+ passcnt_s <= passcnt - '1';
+
+ path_s.datareg_input<= DONTCARE(2 downto 0) & instr.ireg(0) & DONTCARE(2 downto 0);-- dimux & w & seldreg
+
+ path_s.alu_operation<= REG_MDBUS & DONTCARE(3 downto 0)&ALU_CMPS;-- selalua(4) & selalub(4) & aluopr(7) ALUREG=>output
+ -- ES:[DI]
+ path_s.ea_output<="0001011001"; -- dispmux(3) & eamux(4) & dis_opflag & segop[1:0]
+ wrpath_s.wrcc <= '1'; -- update flag register
+ next_state <= Sreadmem;
+
+ elsif (passcnt=X"02") then -- Next update DI
+ second_pass_s <= '1';
+ passcnt_s <= passcnt - '1';
+
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_DI(2 downto 0);-- dimux & w & seldreg
+
+ path_s.alu_operation<= REG_DI & -- selalua(4) & selalub(4) & aluopr
+ REG_CONST1(3 downto 2)&instr.ireg(0)&(not instr.ireg(0))& -- w selects 1 or 2
+ ALU_INC(6 downto 1)&status.flag(10); -- df flag select inc/dec
+
+ path_s.ea_output<=DONTCARE(9 downto 0); -- dispmux(3) & eamux(4) & dis_opflag & segop[1:0]
+
+ wrpath_s.wrd <= '1'; -- Update DI
+ next_state <= Sdecode;
+
+ elsif (passcnt=X"01") then -- Final pass if no repeat update SI
+ passcnt_s <= passcnt - '1';
+
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_SI(2 downto 0);-- dimux & w & seldreg
+
+ path_s.alu_operation<= REG_SI & -- selalua(4) & selalub(4) & aluopr
+ REG_CONST1(3 downto 2)&instr.ireg(0)&(not instr.ireg(0))& -- w selects 1 or 2
+ ALU_INC(6 downto 1)&status.flag(10); -- df flag select inc/dec
+
+ path_s.ea_output<=NB_CS_IP; -- dispmux(3) & eamux(4) & dis_opflag & segop[1:0]
+ wrpath_s.wrd <= '1'; -- yes, then update SI
+
+ if rep_flag='1' then -- If repeat set, check CX-1
+ second_pass_s <= '1';
+ next_state <= Sdecode;
+ else -- no repeat end cycle
+ second_pass_s <= '0';
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Sexecute;
+ end if;
+
+ else -- third pass (only when rep_flag=1) CX-1
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_CX(2 downto 0);-- dimux & w & seldreg
+ path_s.alu_operation<= REG_CX & REG_CONST1 & ALU_DEC; -- selalua(4) & selalub(4) & aluopr
+ path_s.ea_output <= NB_CS_IP; -- dispmux(3) & eamux(4) & dis_opflag & segop[1:0]
+ wrpath_s.wrd <= '1'; -- Update CX
+
+ if (status.cx_one='1' or rep_zl_s/=status.flag(6)) then -- quit on CX=1 or ZF=z_repeat_intr
+ second_pass_s <= '0';
+ rep_clear_s <= '1'; -- Clear Repeat flag
+ passcnt_s <= passcnt - '1'; -- not required, change to DONTCARE?
+ wrpath_s.wrip <= '1';
+ next_state <= Sexecute;
+ else
+ second_pass_s <= '1';
+ passcnt_s <= X"04"; -- Next another R/W mem pass
+ next_state <= Sdecode;
+ end if;
+
+ end if;
+
+ end if;
+
+ ---------------------------------------------------------------------------------
+ -- SCAS
+ -- SCAS -> AX/AL-ES[DI]
+ -- DI++/--
+ -- Note no signextend on operands (compared to the CMP instruction)
+ ---------------------------------------------------------------------------------
+ when SCASB | SCASW =>
+
+ if (second_pass='0') then -- First pass, AX-ES:[DI]
+ passcnt_s <= X"01"; -- Jump to state 1
+
+ path_s.datareg_input<= MDBUS_IN & instr.ireg(0) & DONTCARE(2 downto 0); -- dimux & w & seldreg
+ path_s.alu_operation<= REG_AX & REG_MDBUS & ALU_SCAS; -- selalua(4) & selalub(4) & aluopr(7)
+
+ if (rep_flag='1' and status.cx_zero='1') then -- if CX=0 then skip instruction
+ second_pass_s <= '0';
+ rep_clear_s <= '1'; -- Clear Repeat flag
+ path_s.ea_output<= NB_CS_IP;
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Sexecute;
+ else
+ second_pass_s <= '1'; -- Need another pass
+ path_s.ea_output<= "0001000001"; -- dispmux(3) & eamux(4) & dis_opflag & segop[1:0]
+ wrpath_s.wrcc <= '1'; -- update flag register
+ next_state <= Sreadmem; -- start read cycle
+ end if;
+
+ else
+
+ if (passcnt=X"02") then -- Same operation as second_pass=0, AX/AL-SEG:[SI]
+ second_pass_s <= '1'; -- Need another pass
+ passcnt_s <= passcnt - '1';
+
+ path_s.datareg_input<= MDBUS_IN & instr.ireg(0) & DONTCARE(2 downto 0); -- dimux & w & seldreg
+ path_s.alu_operation<= REG_AX & REG_MDBUS & ALU_SCAS; -- selalua(4) & selalub(4) & aluopr(7)
+
+ path_s.ea_output<= "0001000001"; -- dispmux(3) & eamux(4) & dis_opflag & segop[1:0]
+ wrpath_s.wrcc <= '1'; -- update flag register
+ next_state <= Sreadmem; -- start read cycle
+
+ elsif (passcnt=X"01") then -- Final pass if no repeat update DI
+ second_pass_s <= '0'; -- clear
+ passcnt_s <= passcnt - '1';
+
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_DI(2 downto 0);-- dimux & w & seldreg
+
+ path_s.alu_operation<= REG_DI & -- selalua(4) & selalub(4) & aluopr
+ REG_CONST1(3 downto 2)&instr.ireg(0)&(not instr.ireg(0))& -- w selects 1 or 2
+ ALU_INC(6 downto 1)&status.flag(10); -- df flag select inc/dec
+
+ path_s.ea_output<=NB_CS_IP; -- dispmux(3) & eamux(4) & dis_opflag & segop[1:0]
+
+ wrpath_s.wrd <= '1'; -- yes, then update DI
+
+ if rep_flag='1' then -- If repeat set, check CX-1
+ second_pass_s <= '1';
+ next_state <= Sdecode;
+ else -- no repeat end cycle
+ second_pass_s <= '0';
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Sexecute;
+ end if;
+
+ else -- third pass (only when rep_flag=1) CX-1
+ path_s.datareg_input<= ALUBUS_IN & '1' & REG_CX(2 downto 0);-- dimux & w & seldreg
+ path_s.alu_operation<= REG_CX & REG_CONST1 & ALU_DEC; -- selalua(4) & selalub(4) & aluopr
+ path_s.ea_output <= NB_CS_IP; -- dispmux(3) & eamux(4) & dis_opflag & segop[1:0]
+ wrpath_s.wrd <= '1'; -- Update CX
+
+ if (status.cx_one='1' or rep_zl_s/=status.flag(6)) then -- quit on CX=1 or ZF=z_repeat_intr
+ second_pass_s <= '0';
+ rep_clear_s <= '1'; -- Clear Repeat flag
+ passcnt_s <= passcnt - '1'; -- not required, change to DONTCARE???????????????????????????????
+ wrpath_s.wrip <= '1';
+ next_state <= Sexecute;
+ else
+ second_pass_s <= '1';
+ passcnt_s <= X"02"; -- Next another Read mem pass
+ next_state <= Sdecode;
+ end if;
+
+ end if;
+
+ end if;
+
+
+ ---------------------------------------------------------------------------------
+ -- REP/REPz Instruction
+ -- Set REPEAT Flag
+ ---------------------------------------------------------------------------------
+ when REPNE | REPE =>
+
+ irq_blocked_s <= '1'; -- Block IRQ if asserted during next instr.
+ second_pass_s <= '0';
+ rep_set_s <= '1';
+ rep_z_s <= instr.ireg(0); -- REPNE or REPE
+ path_s.ea_output<= NB_CS_IP;
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Sexecute;
+
+ ---------------------------------------------------------------------------------
+ -- Conditional Jump
+ ---------------------------------------------------------------------------------
+ when JZ | JL | JLE | JB | JBE| JP | JO | JS | JNE | JNL | JNLE | JNB| JNBE | JNP | JNO | JNS =>
+
+ second_pass_s <= '0';
+
+ if (((instr.ireg(3 downto 0)="0000") and (status.flag(11)='1')) or -- Jump on Overflow (OF=1)
+ ((instr.ireg(3 downto 0)="0001") and (status.flag(11)='0')) or -- Jump on not overflow (OF=0)
+ ((instr.ireg(3 downto 0)="0010") and (status.flag(0)='1')) or -- Jump on Below (CF=1)
+ ((instr.ireg(3 downto 0)="0011") and (status.flag(0)='0')) or -- Jump on not below (CF=0)
+ ((instr.ireg(3 downto 0)="0100") and (status.flag(6)='1')) or -- Jump on Zero ZF=1;
+ ((instr.ireg(3 downto 0)="0101") and (status.flag(6)='0')) or -- Jump on not zero ZF=0
+ ((instr.ireg(3 downto 0)="0110") and (status.flag(0)='1' or status.flag(6)='1')) or -- JBE, Jump on below or equal CF or ZF=1
+ ((instr.ireg(3 downto 0)="0111") and (status.flag(0)='0' and status.flag(6)='0')) or -- JNBE, Jump on not below or equal CF&ZF=0
+ ((instr.ireg(3 downto 0)="1000") and (status.flag(7)='1')) or -- JS, Jump on ZF=1
+ ((instr.ireg(3 downto 0)="1001") and (status.flag(7)='0')) or -- JNS, Jump on ZF=0
+ ((instr.ireg(3 downto 0)="1010") and (status.flag(2)='1')) or -- JP, Jump on Parity PF=1
+ ((instr.ireg(3 downto 0)="1011") and (status.flag(2)='0')) or -- JNP, Jump on not parity PF=0
+ ((instr.ireg(3 downto 0)="1100") and (status.flag(7)/=status.flag(11))) or -- JL, Jump on less or equal SF!=OF
+ ((instr.ireg(3 downto 0)="1101") and (status.flag(7)=status.flag(11))) or -- JNL, Jump on not less, SF=OF
+ ((instr.ireg(3 downto 0)="1110") and ((status.flag(7)/=status.flag(11)) or status.flag(6)='1')) or -- JLE, Jump on less or equal
+ ((instr.ireg(3 downto 0)="1111") and ((status.flag(7)=status.flag(11)) and status.flag(6)='0'))) -- JNLE, Jump on not less or equal SF=OF & zf=0
+ then
+ flush_req_s <= '1'; -- Flush Prefetch queue, asserted during execute cycle
+ path_s.ea_output <= DISP_CS_IP; -- CS: IPREG+DISPL
+ else
+ path_s.ea_output <= NB_CS_IP; -- IPREG+NB ADDR=CS:IP
+ end if;
+
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ next_state <= Sexecute;
+
+ when others =>
+ proc_error_s<='1'; -- Assert Bus Error Signal
+
+ wrpath_s.wrip <= '1'; -- Update IP+nbreq register
+ path_s.ea_output<= NB_CS_IP; -- Go to next opcode
+ next_state <= Sexecute; -- Ignore opcode, fetch next one
+
+ -- pragma synthesis_off
+ assert not (now > 0 ns) report "**** Unknown Instruction to decode (proc) ***" severity warning;
+ -- pragma synthesis_on
+
+ end case;
+
+ ----------------------------------------------------------------------------
+ -- Get Operand/Data from Memory
+ -- if second_pass=0 then execute else go for second pass
+ ----------------------------------------------------------------------------
+ when Sreadmem =>
+ read_req <= '1'; -- Request Read Cycle
+
+ if rw_ack='1' then -- read cycle completed?
+ if second_pass='0' then
+ next_state <= Sexecute; -- execute instruction
+ else
+ next_state <= Sdecode; -- second pass
+ end if;
+ else
+ next_state <= Sreadmem; -- Wait ack from BIU
+ end if;
+
+ ----------------------------------------------------------------------------
+ -- Write Data to Memory
+ -- if second_pass=0 then execute else go for second pass
+ ----------------------------------------------------------------------------
+ when Swritemem =>
+ write_req <= '1'; -- Request Write Cycle
+
+ if rw_ack='1' then -- read cycle completed?
+ if second_pass='0' then
+ next_state <= Sexecute; -- execute instruction
+ else
+ next_state <= Sdecode; -- second pass
+ end if;
+ else
+ next_state <= Swritemem; -- Wait ack from BIU
+ end if;
+
+ ----------------------------------------------------------------------------
+ -- Execute
+ -- wrpath get wrpathl_s signal
+ ----------------------------------------------------------------------------
+ when Sexecute =>
+
+ wrpath <= wrpathl_s; -- Assert write strobe(s)
+ iomem_s <= '0'; -- Clear IOMEM cycle
+
+ -- Do not clear if REP or LOCK is used as a prefix
+ if ((instr.ireg/=SEGOPES) and (instr.ireg/=SEGOPCS) and (instr.ireg/=SEGOPSS) and
+ (instr.ireg/=SEGOPDS) and (instr.ireg/=REPNE) and
+ (instr.ireg/=REPE)) then
+ clrop <= '1'; -- clear Segment Override Flag
+ end if;
+
+ if instr.ireg=HLT then -- If instr=HLT then wait for interrupt
+ next_state <= Shalt;
+ elsif (flush_reql_s='1' AND flush_ack='1') then -- Flush Request & ACK
+ next_state <= Sopcode;
+ elsif (flush_reql_s='1' AND flush_ack='0') then -- Flush request and no ack yet
+ flush_req_s <= '1';
+ next_state <= Sflush; -- wait for ack flush
+ else
+ next_state <= Sopcode;
+ end if;
+
+
+ ----------------------------------------------------------------------------
+ -- Flush State, wait until flush_ack is asserted
+ ----------------------------------------------------------------------------
+ when Sflush =>
+
+ if flush_ack='0' then
+ flush_req_s <= '1'; -- Continue asserting flush req
+ next_state <= Sflush; -- Wait until req is removed
+ else
+ next_state <= Sopcode; -- Next Opcode
+ end if;
+
+ when Shalt =>
+ if irq_req='1' then
+ next_state <= Sopcode; -- Next Opcode
+ else
+ next_state <= Shalt; -- wait for interrupt
+ end if;
+
+ when others =>
+ next_state <= Sopcode;
+
+ end case;
+ end process nextstate;
+
+end rtl;
diff --git a/common/CPU/cpu86/r_table.vhd b/common/CPU/cpu86/r_table.vhd
new file mode 100644
index 00000000..5e9dcc11
--- /dev/null
+++ b/common/CPU/cpu86/r_table.vhd
@@ -0,0 +1,721 @@
+-------------------------------------------------------------------------------
+-- CPU86 - VHDL CPU8088 IP core --
+-- Copyright (C) 2002-2008 HT-LAB --
+-- --
+-- Contact/bugs : http://www.ht-lab.com/misc/feedback.html --
+-- Web : http://www.ht-lab.com --
+-- --
+-- CPU86 is released as open-source under the GNU GPL license. This means --
+-- that designs based on CPU86 must be distributed in full source code --
+-- under the same license. Contact HT-Lab for commercial applications where --
+-- source-code distribution is not desirable. --
+-- --
+-------------------------------------------------------------------------------
+-- --
+-- This library is free software; you can redistribute it and/or --
+-- modify it under the terms of the GNU Lesser General Public --
+-- License as published by the Free Software Foundation; either --
+-- version 2.1 of the License, or (at your option) any later version. --
+-- --
+-- This library 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 --
+-- Lesser General Public License for more details. --
+-- --
+-- Full details of the license can be found in the file "copying.txt". --
+-- --
+-- You should have received a copy of the GNU Lesser General Public --
+-- License along with this library; if not, write to the Free Software --
+-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --
+-- --
+-------------------------------------------------------------------------------
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+
+entity r_table is
+ port ( addr : in std_logic_vector(15 downto 0);
+ dout : out std_logic_vector(2 downto 0));
+end r_table;
+
+
+architecture rtl of r_table is
+begin
+ process(addr)
+ begin
+ case addr is
+ when "1110101100000000" => dout <= "000";
+ when "1110100100000000" => dout <= "000";
+ when "1111111111100000" => dout <= "001";
+ when "1111111100100110" => dout <= "001";
+ when "1111111100100000" => dout <= "001";
+ when "1111111101100000" => dout <= "001";
+ when "1111111110100000" => dout <= "001";
+ when "1110101000000000" => dout <= "000";
+ when "1111111100101110" => dout <= "001";
+ when "1111111100101000" => dout <= "001";
+ when "1111111101101000" => dout <= "001";
+ when "1111111110101000" => dout <= "001";
+ when "1110100000000000" => dout <= "000";
+ when "1111111111010000" => dout <= "001";
+ when "1111111100010110" => dout <= "001";
+ when "1111111100010000" => dout <= "001";
+ when "1111111101010000" => dout <= "001";
+ when "1111111110010000" => dout <= "001";
+ when "1001101000000000" => dout <= "000";
+ when "1111111100011110" => dout <= "001";
+ when "1111111100011000" => dout <= "001";
+ when "1111111101011000" => dout <= "001";
+ when "1111111110011000" => dout <= "001";
+ when "1100001100000000" => dout <= "000";
+ when "1100001000000000" => dout <= "000";
+ when "1100101100000000" => dout <= "000";
+ when "1100101000000000" => dout <= "000";
+ when "0111010000000000" => dout <= "000";
+ when "0111110000000000" => dout <= "000";
+ when "0111111000000000" => dout <= "000";
+ when "0111001000000000" => dout <= "000";
+ when "0111011000000000" => dout <= "000";
+ when "0111101000000000" => dout <= "000";
+ when "0111000000000000" => dout <= "000";
+ when "0111100000000000" => dout <= "000";
+ when "0111010100000000" => dout <= "000";
+ when "0111110100000000" => dout <= "000";
+ when "0111111100000000" => dout <= "000";
+ when "0111001100000000" => dout <= "000";
+ when "0111011100000000" => dout <= "000";
+ when "0111101100000000" => dout <= "000";
+ when "0111000100000000" => dout <= "000";
+ when "0111100100000000" => dout <= "000";
+ when "1110001100000000" => dout <= "000";
+ when "1110001000000000" => dout <= "000";
+ when "1110000100000000" => dout <= "000";
+ when "1110000000000000" => dout <= "000";
+ when "1100110100000000" => dout <= "000";
+ when "1100110000000000" => dout <= "000";
+ when "1100111000000000" => dout <= "000";
+ when "1100111100000000" => dout <= "000";
+ when "1111100000000000" => dout <= "000";
+ when "1111010100000000" => dout <= "000";
+ when "1111100100000000" => dout <= "000";
+ when "1111110000000000" => dout <= "000";
+ when "1111110100000000" => dout <= "000";
+ when "1111101000000000" => dout <= "000";
+ when "1111101100000000" => dout <= "000";
+ when "1111010000000000" => dout <= "000";
+ when "1001101100000000" => dout <= "000";
+ when "1111000000000000" => dout <= "000";
+ when "1001000000000000" => dout <= "000";
+ when "0010011000000000" => dout <= "000";
+ when "0010111000000000" => dout <= "000";
+ when "0011011000000000" => dout <= "000";
+ when "0011111000000000" => dout <= "000";
+ when "1000100011000000" => dout <= "001";
+ when "1000100000000000" => dout <= "001";
+ when "1000100001000000" => dout <= "001";
+ when "1000100010000000" => dout <= "001";
+ when "1000100000000110" => dout <= "001";
+ when "1000100111000000" => dout <= "001";
+ when "1000100100000000" => dout <= "001";
+ when "1000100101000000" => dout <= "001";
+ when "1000100110000000" => dout <= "001";
+ when "1000100100000110" => dout <= "001";
+ when "1000101011000000" => dout <= "001";
+ when "1000101000000000" => dout <= "001";
+ when "1000101001000000" => dout <= "001";
+ when "1000101010000000" => dout <= "001";
+ when "1000101000000110" => dout <= "001";
+ when "1000101111000000" => dout <= "001";
+ when "1000101100000000" => dout <= "001";
+ when "1000101101000000" => dout <= "001";
+ when "1000101110000000" => dout <= "001";
+ when "1000101100000110" => dout <= "001";
+ when "1100011000000000" => dout <= "001";
+ when "1100011001000000" => dout <= "001";
+ when "1100011010000000" => dout <= "001";
+ when "1100011000000110" => dout <= "001";
+ when "1100011100000000" => dout <= "001";
+ when "1100011101000000" => dout <= "001";
+ when "1100011110000000" => dout <= "001";
+ when "1100011100000110" => dout <= "001";
+ when "1011000000000000" => dout <= "010";
+ when "1011000100000000" => dout <= "010";
+ when "1011001000000000" => dout <= "010";
+ when "1011001100000000" => dout <= "010";
+ when "1011010000000000" => dout <= "010";
+ when "1011010100000000" => dout <= "010";
+ when "1011011000000000" => dout <= "010";
+ when "1011011100000000" => dout <= "010";
+ when "1011100000000000" => dout <= "010";
+ when "1011100100000000" => dout <= "010";
+ when "1011101000000000" => dout <= "010";
+ when "1011101100000000" => dout <= "010";
+ when "1011110000000000" => dout <= "010";
+ when "1011110100000000" => dout <= "010";
+ when "1011111000000000" => dout <= "010";
+ when "1011111100000000" => dout <= "010";
+ when "1010000000000000" => dout <= "011";
+ when "1010000100000000" => dout <= "011";
+ when "1010001000000000" => dout <= "011";
+ when "1010001100000000" => dout <= "011";
+ when "1000111011000000" => dout <= "001";
+ when "1000111000000000" => dout <= "001";
+ when "1000111001000000" => dout <= "001";
+ when "1000111010000000" => dout <= "001";
+ when "1000111000000110" => dout <= "001";
+ when "1000110011000000" => dout <= "001";
+ when "1000110000000000" => dout <= "001";
+ when "1000110001000000" => dout <= "001";
+ when "1000110010000000" => dout <= "001";
+ when "1000110000000110" => dout <= "001";
+ when "1111111100110000" => dout <= "001";
+ when "1111111101110000" => dout <= "001";
+ when "1111111110110000" => dout <= "001";
+ when "1111111100110110" => dout <= "001";
+ when "0101000000000000" => dout <= "010";
+ when "0101000100000000" => dout <= "010";
+ when "0101001000000000" => dout <= "010";
+ when "0101001100000000" => dout <= "010";
+ when "0101010000000000" => dout <= "010";
+ when "0101010100000000" => dout <= "010";
+ when "0101011000000000" => dout <= "010";
+ when "0101011100000000" => dout <= "010";
+ when "0000011000000000" => dout <= "011";
+ when "0000111000000000" => dout <= "011";
+ when "0001011000000000" => dout <= "011";
+ when "0001111000000000" => dout <= "011";
+ when "1000111100000000" => dout <= "001";
+ when "1000111101000000" => dout <= "001";
+ when "1000111110000000" => dout <= "001";
+ when "1000111100000110" => dout <= "001";
+ when "1000111111000000" => dout <= "001";
+ when "0101100000000000" => dout <= "010";
+ when "0101100100000000" => dout <= "010";
+ when "0101101000000000" => dout <= "010";
+ when "0101101100000000" => dout <= "010";
+ when "0101110000000000" => dout <= "010";
+ when "0101110100000000" => dout <= "010";
+ when "0101111000000000" => dout <= "010";
+ when "0101111100000000" => dout <= "010";
+ when "0000011100000000" => dout <= "011";
+ when "0001011100000000" => dout <= "011";
+ when "0001111100000000" => dout <= "011";
+ when "1000011011000000" => dout <= "001";
+ when "1000011000000000" => dout <= "001";
+ when "1000011001000000" => dout <= "001";
+ when "1000011010000000" => dout <= "001";
+ when "1000011000000110" => dout <= "001";
+ when "1000011111000000" => dout <= "001";
+ when "1000011100000000" => dout <= "001";
+ when "1000011101000000" => dout <= "001";
+ when "1000011110000000" => dout <= "001";
+ when "1000011100000110" => dout <= "001";
+ when "1001000100000000" => dout <= "010";
+ when "1001001000000000" => dout <= "010";
+ when "1001001100000000" => dout <= "010";
+ when "1001010000000000" => dout <= "010";
+ when "1001010100000000" => dout <= "010";
+ when "1001011000000000" => dout <= "010";
+ when "1001011100000000" => dout <= "010";
+ when "1110010000000000" => dout <= "000";
+ when "1110010100000000" => dout <= "000";
+ when "1110110000000000" => dout <= "000";
+ when "1110110100000000" => dout <= "000";
+ when "1110011000000000" => dout <= "000";
+ when "1110011100000000" => dout <= "000";
+ when "1110111100000000" => dout <= "000";
+ when "1110111000000000" => dout <= "000";
+ when "1101011100000000" => dout <= "000";
+ when "1001111100000000" => dout <= "000";
+ when "1001111000000000" => dout <= "000";
+ when "1001110000000000" => dout <= "000";
+ when "1001110100000000" => dout <= "000";
+ when "1000110100000110" => dout <= "001";
+ when "1000110111000000" => dout <= "001";
+ when "1000110100000000" => dout <= "001";
+ when "1000110101000000" => dout <= "001";
+ when "1000110110000000" => dout <= "001";
+ when "1100010100000110" => dout <= "001";
+ when "1100010100000000" => dout <= "001";
+ when "1100010101000000" => dout <= "001";
+ when "1100010110000000" => dout <= "001";
+ when "1100010000000110" => dout <= "001";
+ when "1100010000000000" => dout <= "001";
+ when "1100010001000000" => dout <= "001";
+ when "1100010010000000" => dout <= "001";
+ when "0000000011000000" => dout <= "001";
+ when "0000000000000110" => dout <= "001";
+ when "0000000000000000" => dout <= "001";
+ when "0000000001000000" => dout <= "001";
+ when "0000000010000000" => dout <= "001";
+ when "0000000111000000" => dout <= "001";
+ when "0000000100000110" => dout <= "001";
+ when "0000000100000000" => dout <= "001";
+ when "0000000101000000" => dout <= "001";
+ when "0000000110000000" => dout <= "001";
+ when "0000001011000000" => dout <= "001";
+ when "0000001000000110" => dout <= "001";
+ when "0000001000000000" => dout <= "001";
+ when "0000001001000000" => dout <= "001";
+ when "0000001010000000" => dout <= "001";
+ when "0000001111000000" => dout <= "001";
+ when "0000001100000110" => dout <= "001";
+ when "0000001100000000" => dout <= "001";
+ when "0000001101000000" => dout <= "001";
+ when "0000001110000000" => dout <= "001";
+ when "1000000011000000" => dout <= "001";
+ when "1000000000000110" => dout <= "001";
+ when "1000000000000000" => dout <= "001";
+ when "1000000001000000" => dout <= "001";
+ when "1000000010000000" => dout <= "001";
+ when "1000000111000000" => dout <= "001";
+ when "1000000100000110" => dout <= "001";
+ when "1000000100000000" => dout <= "001";
+ when "1000000101000000" => dout <= "001";
+ when "1000000110000000" => dout <= "001";
+ when "1000001111000000" => dout <= "001";
+ when "1000001100000110" => dout <= "001";
+ when "1000001100000000" => dout <= "001";
+ when "1000001101000000" => dout <= "001";
+ when "1000001110000000" => dout <= "001";
+ when "0000010000000000" => dout <= "000";
+ when "0000010100000000" => dout <= "000";
+ when "0001000011000000" => dout <= "001";
+ when "0001000000000110" => dout <= "001";
+ when "0001000000000000" => dout <= "001";
+ when "0001000001000000" => dout <= "001";
+ when "0001000010000000" => dout <= "001";
+ when "0001000111000000" => dout <= "001";
+ when "0001000100000110" => dout <= "001";
+ when "0001000100000000" => dout <= "001";
+ when "0001000101000000" => dout <= "001";
+ when "0001000110000000" => dout <= "001";
+ when "0001001011000000" => dout <= "001";
+ when "0001001000000110" => dout <= "001";
+ when "0001001000000000" => dout <= "001";
+ when "0001001001000000" => dout <= "001";
+ when "0001001010000000" => dout <= "001";
+ when "0001001111000000" => dout <= "001";
+ when "0001001100000110" => dout <= "001";
+ when "0001001100000000" => dout <= "001";
+ when "0001001101000000" => dout <= "001";
+ when "0001001110000000" => dout <= "001";
+ when "1000000011010000" => dout <= "001";
+ when "1000000000010110" => dout <= "001";
+ when "1000000000010000" => dout <= "001";
+ when "1000000001010000" => dout <= "001";
+ when "1000000010010000" => dout <= "001";
+ when "1000000111010000" => dout <= "001";
+ when "1000000100010110" => dout <= "001";
+ when "1000000100010000" => dout <= "001";
+ when "1000000101010000" => dout <= "001";
+ when "1000000110010000" => dout <= "001";
+ when "1000001111010000" => dout <= "001";
+ when "1000001100010110" => dout <= "001";
+ when "1000001100010000" => dout <= "001";
+ when "1000001101010000" => dout <= "001";
+ when "1000001110010000" => dout <= "001";
+ when "0001010000000000" => dout <= "000";
+ when "0001010100000000" => dout <= "000";
+ when "0010100011000000" => dout <= "001";
+ when "0010100000000110" => dout <= "001";
+ when "0010100000000000" => dout <= "001";
+ when "0010100001000000" => dout <= "001";
+ when "0010100010000000" => dout <= "001";
+ when "0010100111000000" => dout <= "001";
+ when "0010100100000110" => dout <= "001";
+ when "0010100100000000" => dout <= "001";
+ when "0010100101000000" => dout <= "001";
+ when "0010100110000000" => dout <= "001";
+ when "0010101011000000" => dout <= "001";
+ when "0010101000000110" => dout <= "001";
+ when "0010101000000000" => dout <= "001";
+ when "0010101001000000" => dout <= "001";
+ when "0010101010000000" => dout <= "001";
+ when "0010101111000000" => dout <= "001";
+ when "0010101100000110" => dout <= "001";
+ when "0010101100000000" => dout <= "001";
+ when "0010101101000000" => dout <= "001";
+ when "0010101110000000" => dout <= "001";
+ when "1000000011101000" => dout <= "001";
+ when "1000000000101110" => dout <= "001";
+ when "1000000000101000" => dout <= "001";
+ when "1000000001101000" => dout <= "001";
+ when "1000000010101000" => dout <= "001";
+ when "1000000111101000" => dout <= "001";
+ when "1000000100101110" => dout <= "001";
+ when "1000000100101000" => dout <= "001";
+ when "1000000101101000" => dout <= "001";
+ when "1000000110101000" => dout <= "001";
+ when "1000001111101000" => dout <= "001";
+ when "1000001100101110" => dout <= "001";
+ when "1000001100101000" => dout <= "001";
+ when "1000001101101000" => dout <= "001";
+ when "1000001110101000" => dout <= "001";
+ when "0010110000000000" => dout <= "000";
+ when "0010110100000000" => dout <= "000";
+ when "0001100011000000" => dout <= "001";
+ when "0001100000000110" => dout <= "001";
+ when "0001100000000000" => dout <= "001";
+ when "0001100001000000" => dout <= "001";
+ when "0001100010000000" => dout <= "001";
+ when "0001100111000000" => dout <= "001";
+ when "0001100100000110" => dout <= "001";
+ when "0001100100000000" => dout <= "001";
+ when "0001100101000000" => dout <= "001";
+ when "0001100110000000" => dout <= "001";
+ when "0001101011000000" => dout <= "001";
+ when "0001101000000110" => dout <= "001";
+ when "0001101000000000" => dout <= "001";
+ when "0001101001000000" => dout <= "001";
+ when "0001101010000000" => dout <= "001";
+ when "0001101111000000" => dout <= "001";
+ when "0001101100000110" => dout <= "001";
+ when "0001101100000000" => dout <= "001";
+ when "0001101101000000" => dout <= "001";
+ when "0001101110000000" => dout <= "001";
+ when "1000000011011000" => dout <= "001";
+ when "1000000000011110" => dout <= "001";
+ when "1000000000011000" => dout <= "001";
+ when "1000000001011000" => dout <= "001";
+ when "1000000010011000" => dout <= "001";
+ when "1000000111011000" => dout <= "001";
+ when "1000000100011110" => dout <= "001";
+ when "1000000100011000" => dout <= "001";
+ when "1000000101011000" => dout <= "001";
+ when "1000000110011000" => dout <= "001";
+ when "1000001111011000" => dout <= "001";
+ when "1000001100011110" => dout <= "001";
+ when "1000001100011000" => dout <= "001";
+ when "1000001101011000" => dout <= "001";
+ when "1000001110011000" => dout <= "001";
+ when "0001110000000000" => dout <= "000";
+ when "0001110100000000" => dout <= "000";
+ when "1111111011000000" => dout <= "001";
+ when "1111111000000110" => dout <= "001";
+ when "1111111000000000" => dout <= "001";
+ when "1111111001000000" => dout <= "001";
+ when "1111111010000000" => dout <= "001";
+ when "1111111100000110" => dout <= "001";
+ when "1111111100000000" => dout <= "001";
+ when "1111111101000000" => dout <= "001";
+ when "1111111110000000" => dout <= "001";
+ when "0100000000000000" => dout <= "010";
+ when "0100000100000000" => dout <= "010";
+ when "0100001000000000" => dout <= "010";
+ when "0100001100000000" => dout <= "010";
+ when "0100010000000000" => dout <= "010";
+ when "0100010100000000" => dout <= "010";
+ when "0100011000000000" => dout <= "010";
+ when "0100011100000000" => dout <= "010";
+ when "1111111011001000" => dout <= "001";
+ when "1111111000001110" => dout <= "001";
+ when "1111111000001000" => dout <= "001";
+ when "1111111001001000" => dout <= "001";
+ when "1111111010001000" => dout <= "001";
+ when "1111111100001110" => dout <= "001";
+ when "1111111100001000" => dout <= "001";
+ when "1111111101001000" => dout <= "001";
+ when "1111111110001000" => dout <= "001";
+ when "0100100000000000" => dout <= "010";
+ when "0100100100000000" => dout <= "010";
+ when "0100101000000000" => dout <= "010";
+ when "0100101100000000" => dout <= "010";
+ when "0100110000000000" => dout <= "010";
+ when "0100110100000000" => dout <= "010";
+ when "0100111000000000" => dout <= "010";
+ when "0100111100000000" => dout <= "010";
+ when "0011101011000000" => dout <= "001";
+ when "0011101000000110" => dout <= "001";
+ when "0011101000000000" => dout <= "001";
+ when "0011101001000000" => dout <= "001";
+ when "0011101010000000" => dout <= "001";
+ when "0011101111000000" => dout <= "001";
+ when "0011101100000110" => dout <= "001";
+ when "0011101100000000" => dout <= "001";
+ when "0011101101000000" => dout <= "001";
+ when "0011101110000000" => dout <= "001";
+ when "0011100000000110" => dout <= "001";
+ when "0011100000000000" => dout <= "001";
+ when "0011100001000000" => dout <= "001";
+ when "0011100010000000" => dout <= "001";
+ when "0011100011000000" => dout <= "001";
+ when "0011100100000110" => dout <= "001";
+ when "0011100100000000" => dout <= "001";
+ when "0011100101000000" => dout <= "001";
+ when "0011100110000000" => dout <= "001";
+ when "0011100111000000" => dout <= "001";
+ when "1000000011111000" => dout <= "001";
+ when "1000000000111110" => dout <= "001";
+ when "1000000000111000" => dout <= "001";
+ when "1000000001111000" => dout <= "001";
+ when "1000000010111000" => dout <= "001";
+ when "1000000111111000" => dout <= "001";
+ when "1000000100111110" => dout <= "001";
+ when "1000000100111000" => dout <= "001";
+ when "1000000101111000" => dout <= "001";
+ when "1000000110111000" => dout <= "001";
+ when "1000001111111000" => dout <= "001";
+ when "1000001100111110" => dout <= "001";
+ when "1000001100111000" => dout <= "001";
+ when "1000001101111000" => dout <= "001";
+ when "1000001110111000" => dout <= "001";
+ when "0011110000000000" => dout <= "000";
+ when "0011110100000000" => dout <= "000";
+ when "1111011011011000" => dout <= "001";
+ when "1111011000011110" => dout <= "001";
+ when "1111011000011000" => dout <= "001";
+ when "1111011001011000" => dout <= "001";
+ when "1111011010011000" => dout <= "001";
+ when "1111011111011000" => dout <= "001";
+ when "1111011100011110" => dout <= "001";
+ when "1111011100011000" => dout <= "001";
+ when "1111011101011000" => dout <= "001";
+ when "1111011110011000" => dout <= "001";
+ when "0011011100000000" => dout <= "000";
+ when "0010011100000000" => dout <= "000";
+ when "0011111100000000" => dout <= "000";
+ when "0010111100000000" => dout <= "000";
+ when "1111011011100000" => dout <= "001";
+ when "1111011000100110" => dout <= "001";
+ when "1111011000100000" => dout <= "001";
+ when "1111011001100000" => dout <= "001";
+ when "1111011010100000" => dout <= "001";
+ when "1111011111100000" => dout <= "001";
+ when "1111011100100110" => dout <= "001";
+ when "1111011100100000" => dout <= "001";
+ when "1111011101100000" => dout <= "001";
+ when "1111011110100000" => dout <= "001";
+ when "1111011011101000" => dout <= "001";
+ when "1111011000101110" => dout <= "001";
+ when "1111011000101000" => dout <= "001";
+ when "1111011001101000" => dout <= "001";
+ when "1111011010101000" => dout <= "001";
+ when "1111011111101000" => dout <= "001";
+ when "1111011100101110" => dout <= "001";
+ when "1111011100101000" => dout <= "001";
+ when "1111011101101000" => dout <= "001";
+ when "1111011110101000" => dout <= "001";
+ when "1111011011110000" => dout <= "001";
+ when "1111011000110110" => dout <= "001";
+ when "1111011000110000" => dout <= "001";
+ when "1111011001110000" => dout <= "001";
+ when "1111011010110000" => dout <= "001";
+ when "1111011111110000" => dout <= "001";
+ when "1111011100110110" => dout <= "001";
+ when "1111011100110000" => dout <= "001";
+ when "1111011101110000" => dout <= "001";
+ when "1111011110110000" => dout <= "001";
+ when "1111011011111000" => dout <= "001";
+ when "1111011000111110" => dout <= "001";
+ when "1111011000111000" => dout <= "001";
+ when "1111011001111000" => dout <= "001";
+ when "1111011010111000" => dout <= "001";
+ when "1111011111111000" => dout <= "001";
+ when "1111011100111110" => dout <= "001";
+ when "1111011100111000" => dout <= "001";
+ when "1111011101111000" => dout <= "001";
+ when "1111011110111000" => dout <= "001";
+ when "1101010000000000" => dout <= "000";
+ when "1101010100000000" => dout <= "000";
+ when "1001100000000000" => dout <= "000";
+ when "1001100100000000" => dout <= "000";
+ when "1101000011000000" => dout <= "001";
+ when "1101000000000110" => dout <= "001";
+ when "1101000000000000" => dout <= "001";
+ when "1101000001000000" => dout <= "001";
+ when "1101000010000000" => dout <= "001";
+ when "1101000111000000" => dout <= "001";
+ when "1101000100000110" => dout <= "001";
+ when "1101000100000000" => dout <= "001";
+ when "1101000101000000" => dout <= "001";
+ when "1101000110000000" => dout <= "001";
+ when "1101001011000000" => dout <= "001";
+ when "1101001000000110" => dout <= "001";
+ when "1101001000000000" => dout <= "001";
+ when "1101001001000000" => dout <= "001";
+ when "1101001010000000" => dout <= "001";
+ when "1101001111000000" => dout <= "001";
+ when "1101001100000110" => dout <= "001";
+ when "1101001100000000" => dout <= "001";
+ when "1101001101000000" => dout <= "001";
+ when "1101001110000000" => dout <= "001";
+ when "0010000011000000" => dout <= "001";
+ when "0010000000000110" => dout <= "001";
+ when "0010000000000000" => dout <= "001";
+ when "0010000001000000" => dout <= "001";
+ when "0010000010000000" => dout <= "001";
+ when "0010000111000000" => dout <= "001";
+ when "0010000100000110" => dout <= "001";
+ when "0010000100000000" => dout <= "001";
+ when "0010000101000000" => dout <= "001";
+ when "0010000110000000" => dout <= "001";
+ when "0010001011000000" => dout <= "001";
+ when "0010001000000110" => dout <= "001";
+ when "0010001000000000" => dout <= "001";
+ when "0010001001000000" => dout <= "001";
+ when "0010001010000000" => dout <= "001";
+ when "0010001111000000" => dout <= "001";
+ when "0010001100000110" => dout <= "001";
+ when "0010001100000000" => dout <= "001";
+ when "0010001101000000" => dout <= "001";
+ when "0010001110000000" => dout <= "001";
+ when "1000000011100000" => dout <= "001";
+ when "1000000000100110" => dout <= "001";
+ when "1000000000100000" => dout <= "001";
+ when "1000000001100000" => dout <= "001";
+ when "1000000010100000" => dout <= "001";
+ when "1000000111100000" => dout <= "001";
+ when "1000000100100110" => dout <= "001";
+ when "1000000100100000" => dout <= "001";
+ when "1000000101100000" => dout <= "001";
+ when "1000000110100000" => dout <= "001";
+ when "1000001111100000" => dout <= "001";
+ when "1000001100100110" => dout <= "001";
+ when "1000001100100000" => dout <= "001";
+ when "1000001101100000" => dout <= "001";
+ when "1000001110100000" => dout <= "001";
+ when "0010010000000000" => dout <= "000";
+ when "0010010100000000" => dout <= "000";
+ when "0000100000000110" => dout <= "001";
+ when "0000100000000000" => dout <= "001";
+ when "0000100001000000" => dout <= "001";
+ when "0000100010000000" => dout <= "001";
+ when "0000100011000000" => dout <= "001";
+ when "0000100100000110" => dout <= "001";
+ when "0000100100000000" => dout <= "001";
+ when "0000100101000000" => dout <= "001";
+ when "0000100110000000" => dout <= "001";
+ when "0000100111000000" => dout <= "001";
+ when "0000101011000000" => dout <= "001";
+ when "0000101000000110" => dout <= "001";
+ when "0000101000000000" => dout <= "001";
+ when "0000101001000000" => dout <= "001";
+ when "0000101010000000" => dout <= "001";
+ when "0000101111000000" => dout <= "001";
+ when "0000101100000110" => dout <= "001";
+ when "0000101100000000" => dout <= "001";
+ when "0000101101000000" => dout <= "001";
+ when "0000101110000000" => dout <= "001";
+ when "1000000011001000" => dout <= "001";
+ when "1000000000001110" => dout <= "001";
+ when "1000000000001000" => dout <= "001";
+ when "1000000001001000" => dout <= "001";
+ when "1000000010001000" => dout <= "001";
+ when "1000000111001000" => dout <= "001";
+ when "1000000100001110" => dout <= "001";
+ when "1000000100001000" => dout <= "001";
+ when "1000000101001000" => dout <= "001";
+ when "1000000110001000" => dout <= "001";
+ when "1000001111001000" => dout <= "001";
+ when "1000001100001110" => dout <= "001";
+ when "1000001100001000" => dout <= "001";
+ when "1000001101001000" => dout <= "001";
+ when "1000001110001000" => dout <= "001";
+ when "0000110000000000" => dout <= "000";
+ when "0000110100000000" => dout <= "000";
+ when "1000010000000110" => dout <= "001";
+ when "1000010000000000" => dout <= "001";
+ when "1000010001000000" => dout <= "001";
+ when "1000010010000000" => dout <= "001";
+ when "1000010100000110" => dout <= "001";
+ when "1000010100000000" => dout <= "001";
+ when "1000010101000000" => dout <= "001";
+ when "1000010110000000" => dout <= "001";
+ when "1000010011000000" => dout <= "001";
+ when "1000010111000000" => dout <= "001";
+ when "1111011011000000" => dout <= "000";
+ when "1111011000000110" => dout <= "000";
+ when "1111011000000000" => dout <= "000";
+ when "1111011001000000" => dout <= "000";
+ when "1111011010000000" => dout <= "000";
+ when "1111011111000000" => dout <= "000";
+ when "1111011100000110" => dout <= "000";
+ when "1111011100000000" => dout <= "000";
+ when "1111011101000000" => dout <= "000";
+ when "1111011110000000" => dout <= "000";
+ when "1010100000000000" => dout <= "000";
+ when "1010100100000000" => dout <= "000";
+ when "0011000000000110" => dout <= "001";
+ when "0011000000000000" => dout <= "001";
+ when "0011000001000000" => dout <= "001";
+ when "0011000010000000" => dout <= "001";
+ when "0011000011000000" => dout <= "001";
+ when "0011000100000110" => dout <= "001";
+ when "0011000100000000" => dout <= "001";
+ when "0011000101000000" => dout <= "001";
+ when "0011000110000000" => dout <= "001";
+ when "0011000111000000" => dout <= "001";
+ when "0011001011000000" => dout <= "001";
+ when "0011001000000110" => dout <= "001";
+ when "0011001000000000" => dout <= "001";
+ when "0011001001000000" => dout <= "001";
+ when "0011001010000000" => dout <= "001";
+ when "0011001111000000" => dout <= "001";
+ when "0011001100000110" => dout <= "001";
+ when "0011001100000000" => dout <= "001";
+ when "0011001101000000" => dout <= "001";
+ when "0011001110000000" => dout <= "001";
+ when "1000000011110000" => dout <= "001";
+ when "1000000000110110" => dout <= "001";
+ when "1000000000110000" => dout <= "001";
+ when "1000000001110000" => dout <= "001";
+ when "1000000010110000" => dout <= "001";
+ when "1000000111110000" => dout <= "001";
+ when "1000000100110110" => dout <= "001";
+ when "1000000100110000" => dout <= "001";
+ when "1000000101110000" => dout <= "001";
+ when "1000000110110000" => dout <= "001";
+ when "1000001111110000" => dout <= "001";
+ when "1000001100110110" => dout <= "001";
+ when "1000001100110000" => dout <= "001";
+ when "1000001101110000" => dout <= "001";
+ when "1000001110110000" => dout <= "001";
+ when "0011010000000000" => dout <= "000";
+ when "0011010100000000" => dout <= "000";
+ when "1111011011010000" => dout <= "001";
+ when "1111011000010110" => dout <= "001";
+ when "1111011000010000" => dout <= "001";
+ when "1111011001010000" => dout <= "001";
+ when "1111011010010000" => dout <= "001";
+ when "1111011111010000" => dout <= "001";
+ when "1111011100010110" => dout <= "001";
+ when "1111011100010000" => dout <= "001";
+ when "1111011101010000" => dout <= "001";
+ when "1111011110010000" => dout <= "001";
+ when "1010010000000000" => dout <= "000";
+ when "1010010100000000" => dout <= "000";
+ when "1010011000000000" => dout <= "000";
+ when "1010011100000000" => dout <= "000";
+ when "1010111000000000" => dout <= "000";
+ when "1010111100000000" => dout <= "000";
+ when "1010110000000000" => dout <= "000";
+ when "1010110100000000" => dout <= "000";
+ when "1010101000000000" => dout <= "000";
+ when "1010101100000000" => dout <= "000";
+ when "1111001000000000" => dout <= "000";
+ when "1111001100000000" => dout <= "000";
+ when "0110000000000000" => dout <= "000";
+ when "0110000100000000" => dout <= "000";
+ when "1100100000000000" => dout <= "000";
+ when "1100100100000000" => dout <= "000";
+ when "0110001000000000" => dout <= "000";
+ when "0110110000000000" => dout <= "000";
+ when "0110110100000000" => dout <= "000";
+ when "0110111000000000" => dout <= "000";
+ when "0110111100000000" => dout <= "000";
+ when "0000111100000000" => dout <= "000";
+ when "0110001100000000" => dout <= "000";
+ when "0110010000000000" => dout <= "000";
+ when "0110010100000000" => dout <= "000";
+ when "0110011000000000" => dout <= "000";
+ when "0110011100000000" => dout <= "000";
+ when "1000001000000000" => dout <= "000";
+ when "1101011000000000" => dout <= "000";
+ when "1111000100000000" => dout <= "000";
+ when "1100000000000000" => dout <= "000";
+ when "1100000100000000" => dout <= "000";
+ when others => dout <= "---";
+ end case;
+ end process;
+end rtl;
\ No newline at end of file
diff --git a/common/CPU/cpu86/readme.txt b/common/CPU/cpu86/readme.txt
new file mode 100644
index 00000000..771f7040
--- /dev/null
+++ b/common/CPU/cpu86/readme.txt
@@ -0,0 +1,25 @@
+This directory contains the synthesizable CPU86 (8088) processor VHDL source files.
+
+File dependency order:
+
+cpu86pack.vhd
+cpu86instr.vhd
+biufsm_fsm.vhd
+a_table.vhd
+d_table.vhd
+n_table.vhd
+r_table.vhd
+m_table.vhd
+formatter_struct.vhd
+regshiftmux_regshift.vhd
+biu_struct.vhd
+dataregfile_rtl.vhd
+segregfile_rtl.vhd
+divider_rtl_ser.vhd
+multiplier_rtl.vhd
+alu_rtl.vhd
+ipregister_rtl.vhd
+datapath_struct.vhd
+proc_rtl.vhd
+cpu86_struct.vhd
+
diff --git a/common/CPU/cpu86/regshiftmux_regshift.vhd b/common/CPU/cpu86/regshiftmux_regshift.vhd
new file mode 100644
index 00000000..93ca2e49
--- /dev/null
+++ b/common/CPU/cpu86/regshiftmux_regshift.vhd
@@ -0,0 +1,305 @@
+-------------------------------------------------------------------------------
+-- CPU86 - VHDL CPU8088 IP core --
+-- Copyright (C) 2002-2008 HT-LAB --
+-- --
+-- Contact/bugs : http://www.ht-lab.com/misc/feedback.html --
+-- Web : http://www.ht-lab.com --
+-- --
+-- CPU86 is released as open-source under the GNU GPL license. This means --
+-- that designs based on CPU86 must be distributed in full source code --
+-- under the same license. Contact HT-Lab for commercial applications where --
+-- source-code distribution is not desirable. --
+-- --
+-------------------------------------------------------------------------------
+-- --
+-- This library is free software; you can redistribute it and/or --
+-- modify it under the terms of the GNU Lesser General Public --
+-- License as published by the Free Software Foundation; either --
+-- version 2.1 of the License, or (at your option) any later version. --
+-- --
+-- This library 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 --
+-- Lesser General Public License for more details. --
+-- --
+-- Full details of the license can be found in the file "copying.txt". --
+-- --
+-- You should have received a copy of the GNU Lesser General Public --
+-- License along with this library; if not, write to the Free Software --
+-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --
+-- --
+-------------------------------------------------------------------------------
+LIBRARY ieee;
+USE ieee.std_logic_1164.ALL;
+USE ieee.std_logic_unsigned.ALL;
+
+USE work.cpu86pack.ALL;
+USE work.cpu86instr.ALL;
+
+ENTITY regshiftmux IS
+ PORT(
+ clk : IN std_logic;
+ dbus_in : IN std_logic_vector (7 DOWNTO 0);
+ flush_req : IN std_logic;
+ latchm : IN std_logic;
+ latcho : IN std_logic;
+ mux_addr : IN std_logic_vector (2 DOWNTO 0);
+ mux_data : IN std_logic_vector (3 DOWNTO 0);
+ mux_reg : IN std_logic_vector (2 DOWNTO 0);
+ nbreq : IN std_logic_vector (2 DOWNTO 0);
+ regplus1 : IN std_logic;
+ ldposplus1 : IN std_logic;
+ reset : IN std_logic;
+ irq : IN std_logic;
+ inta1 : IN std_logic; -- Added for ver 0.71
+ inta2_s : IN std_logic;
+ irq_type : IN std_logic_vector (1 DOWNTO 0);
+ instr : OUT instruction_type;
+ halt_instr : OUT std_logic;
+ lutbus : OUT std_logic_vector (15 DOWNTO 0);
+ reg1free : BUFFER std_logic;
+ reg1freed : BUFFER std_logic; -- Delayed version (1 clk) of reg1free
+ regnbok : OUT std_logic
+ );
+END regshiftmux ;
+
+architecture regshift of regshiftmux is
+
+signal reg72_s : std_logic_vector(71 downto 0);
+signal regcnt_s : std_logic_vector(3 downto 0); -- Note need possible 9 byte positions
+signal ldpos_s : std_logic_vector(3 downto 0); -- redundant signal (=regcnt_s)
+
+signal ireg_s : std_logic_vector(7 downto 0);
+signal mod_s : std_logic_vector(1 downto 0);
+signal rm_s : std_logic_vector(2 downto 0);
+signal opcreg_s : std_logic_vector(2 downto 0);
+signal opcdata_s: std_logic_vector(15 downto 0);
+signal opcaddr_s: std_logic_vector(15 downto 0);
+signal nbreq_s : std_logic_vector(2 downto 0); -- latched nbreq only for instr
+
+signal flush_req1_s : std_logic; -- Delayed version of flush_req
+signal flush_req2_s : std_logic; -- Delayed version of flush_req (address setup requires 2 clk cycle)
+
+begin
+
+instr.ireg <= ireg_s;
+instr.xmod <= mod_s;
+instr.rm <= rm_s;
+instr.reg <= opcreg_s;
+instr.data <= opcdata_s(7 downto 0)&opcdata_s(15 downto 8);
+instr.disp <= opcaddr_s(7 downto 0)&opcaddr_s(15 downto 8);
+
+instr.nb <= nbreq_s; -- use latched version
+
+halt_instr <= '1' when ireg_s=HLT else '0';
+
+-------------------------------------------------------------------------
+-- reg counter (how many bytes available in pre-fetch queue)
+-- ldpos (load position in queue, if MSB=1 then ignore parts of word)
+-- Don't forget resource sharing during synthesis :-)
+-------------------------------------------------------------------------
+process(reset,clk)
+begin
+ if reset='1' then
+ regcnt_s <= (others => '0'); -- wrap around after first pulse!
+ ldpos_s <= (others => '1');
+ flush_req1_s <= '0';
+ flush_req2_s <= '0';
+ elsif rising_edge(clk) then
+ flush_req1_s <= flush_req; -- delay 1 cycle
+ flush_req2_s <= flush_req1_s; -- delay 2 cycles
+
+ if flush_req2_s='1' then
+ regcnt_s <= (others => '0'); -- Update during Smaxws state
+ elsif latcho='1' then
+ regcnt_s <= regcnt_s - ('0'&nbreq);
+ elsif regplus1='1' and reg1freed='1' then
+ regcnt_s <= regcnt_s + '1';
+ end if;
+
+ if flush_req2_s='1' then
+ ldpos_s <= (others => '1'); -- Result in part of dbus loaded into queue
+ elsif latcho='1' then
+ ldpos_s <= ldpos_s - ('0'&nbreq);
+ elsif ldposplus1='1' and reg1freed='1' then
+ ldpos_s <= ldpos_s + '1';
+ end if;
+ end if;
+end process;
+
+reg1free <= '1' when ldpos_s/="1000" else '0'; -- Note maxcnt=9!!
+
+process(reset,clk)
+begin
+ if reset='1' then
+ reg1freed <= '1';
+ elsif rising_edge(clk) then
+ reg1freed <= reg1free;
+ end if;
+end process;
+
+regnbok <= '1' when (regcnt_s>='0'&nbreq) else '0'; -- regcnt must be >= nb required
+
+lutbus <= reg72_s(71 downto 56); -- Only for opcode LUT decoder
+
+-------------------------------------------------------------------------
+-- Load 8 bits instruction into 72 bits prefetch queue (9 bytes)
+-- Latched by latchm signal (from biufsm)
+-- ldpos=0 means loading at 71 downto 64 etc
+-- Shiftn is connected to nbreq
+-------------------------------------------------------------------------
+process(reset,clk)
+begin
+ if reset='1' then
+ reg72_s <= NOP & X"0000000000000000"; --(others => '0');
+ elsif rising_edge(clk) then
+ if latchm='1' then
+ case ldpos_s is -- Load new data, shift in lsb byte first
+ when "0000" => reg72_s(71 downto 64) <= dbus_in;
+ when "0001" => reg72_s(63 downto 56) <= dbus_in;
+ when "0010" => reg72_s(55 downto 48) <= dbus_in;
+ when "0011" => reg72_s(47 downto 40) <= dbus_in;
+ when "0100" => reg72_s(39 downto 32) <= dbus_in;
+ when "0101" => reg72_s(31 downto 24) <= dbus_in;
+ when "0110" => reg72_s(23 downto 16) <= dbus_in;
+ when "0111" => reg72_s(15 downto 8) <= dbus_in;
+ when "1000" => reg72_s(7 downto 0) <= dbus_in;
+ when others => reg72_s <= reg72_s;
+ end case;
+ end if;
+ if latcho='1' then
+ case nbreq is -- remove nb byte(s) when latcho is active
+ when "001" => reg72_s <= reg72_s(63 downto 0) & "--------"; -- smaller synth results than "00000000"
+ when "010" => reg72_s <= reg72_s(55 downto 0) & "----------------";
+ when "011" => reg72_s <= reg72_s(47 downto 0) & "------------------------";
+ when "100" => reg72_s <= reg72_s(39 downto 0) & "--------------------------------";
+ when "101" => reg72_s <= reg72_s(31 downto 0) & "----------------------------------------";
+ when "110" => reg72_s <= reg72_s(23 downto 0) & "------------------------------------------------";
+ when others => reg72_s <= reg72_s;
+ end case;
+ end if;
+ end if;
+end process;
+
+-------------------------------------------------------------------------
+-- Opcode Data
+-- Note format LSB-MSB
+-------------------------------------------------------------------------
+process(reset,clk)
+begin
+ if reset='1' then
+ opcdata_s <= (others => '0');
+ elsif rising_edge(clk) then
+ if latcho='1' then
+ case mux_data is
+ when "0000" => opcdata_s <= (others => '0'); -- Correct???
+ when "0001" => opcdata_s <= reg72_s(63 downto 56) & X"00";
+ when "0010" => opcdata_s <= reg72_s(63 downto 48);
+ when "0011" => opcdata_s <= reg72_s(55 downto 48) & X"00";
+ when "0100" => opcdata_s <= reg72_s(55 downto 40);
+ when "0101" => opcdata_s <= reg72_s(47 downto 40) & X"00";
+ when "0110" => opcdata_s <= reg72_s(47 downto 32);
+ when "0111" => opcdata_s <= reg72_s(39 downto 32) & X"00";
+ when "1000" => opcdata_s <= reg72_s(39 downto 24);
+ when others => opcdata_s <= "----------------"; -- generate Error?
+ end case;
+ end if;
+ end if;
+end process;
+
+-------------------------------------------------------------------------
+-- Opcode Address/Offset/Displacement
+-- Format LSB, MSB!
+-- Single Displacement byte sign extended
+-------------------------------------------------------------------------
+process(reset,clk)
+begin
+ if reset='1' then
+ opcaddr_s <= (others => '0');
+ elsif rising_edge(clk) then
+ if inta2_s='1' then
+ opcaddr_s <= dbus_in & X"00"; -- Read 8 bits vector
+ elsif latcho='1' then
+ --if irq='1' then
+ if irq='1' or inta1='1' then -- added for ver 0.71
+ opcaddr_s <= "000000" & irq_type & X"00";
+ else
+ case mux_addr is
+ when "000" => opcaddr_s <= (others => '0'); -- Correct ????
+ when "001" => opcaddr_s <= reg72_s(63 downto 56) & reg72_s(63)& reg72_s(63)& reg72_s(63)& reg72_s(63)&
+ reg72_s(63)& reg72_s(63)& reg72_s(63)& reg72_s(63); -- MSB Sign extended
+ when "010" => opcaddr_s <= reg72_s(63 downto 48);
+ when "011" => opcaddr_s <= reg72_s(55 downto 48) & reg72_s(55)& reg72_s(55)& reg72_s(55)& reg72_s(55)&
+ reg72_s(55)& reg72_s(55)& reg72_s(55)& reg72_s(55); -- MSB Sign Extended
+ when "100" => opcaddr_s <= reg72_s(55 downto 40);
+ when "101" => opcaddr_s <= reg72_s(63 downto 56) & X"00"; -- No sign extend, MSB=0
+ when "110" => opcaddr_s <= X"0300"; -- INT3 type=3
+ when others => opcaddr_s <= X"0400"; -- INTO type=4
+ end case;
+ end if;
+ end if;
+ end if;
+
+end process;
+
+-------------------------------------------------------------------------
+-- Opcode Register
+-- Note : "11" is push segment reg[2]=0 reg[1..0]=reg
+-- : Note reg[2]=0 if mux_reg=011
+-------------------------------------------------------------------------
+process(reset,clk)
+begin
+ if reset='1' then
+ opcreg_s <= (others => '0');
+ elsif rising_edge(clk) then
+ if latcho='1' then
+ case mux_reg is
+ when "000" => opcreg_s <= (others => '0'); -- Correct ??
+ when "001" => opcreg_s <= reg72_s(61 downto 59);
+ when "010" => opcreg_s <= reg72_s(66 downto 64);
+ when "011" => opcreg_s <= '0' & reg72_s(68 downto 67); -- bit2 forced to 0
+ when "100" => opcreg_s <= reg72_s(58 downto 56);
+ when others => opcreg_s <= "---";
+ --assert FALSE report "**** Incorrect mux_reg in Opcode Regs Register" severity error;
+ end case;
+ end if;
+ end if;
+end process;
+
+-------------------------------------------------------------------------
+-- Opcode, Mod R/M Register, and latched nbreq!
+-- Create fake xmod and rm if offset (addr_mux) is 1,2,5,6,7. In this case
+-- there is no second opcode byte. The fake xmod and rm result in an
+-- EA=Displacement.
+-------------------------------------------------------------------------
+process(reset,clk) -- ireg
+begin
+ if reset='1' then
+ ireg_s <= NOP; -- default instr
+ mod_s <= (others => '0'); -- default mod
+ rm_s <= (others => '0'); -- default rm
+ nbreq_s <= "001"; -- single NOP
+ elsif rising_edge(clk) then
+ if latcho='1' then
+ if irq='1' or inta1='1' then -- force INT instruction, added for ver 0.71
+ ireg_s <= INT;
+ nbreq_s<= "000"; -- used in datapath to add to IP address
+ mod_s <= "00"; -- Fake mod (select displacement for int type
+ rm_s <= "110"; -- Fake rm
+ else
+ ireg_s <= reg72_s(71 downto 64);
+ nbreq_s<= nbreq;
+ if (mux_addr= "001" or mux_addr= "010" or mux_addr= "101"
+ or mux_addr= "110" or mux_addr= "111") then
+ mod_s <= "00"; -- Fake mod
+ rm_s <= "110"; -- Fake rm
+ else
+ mod_s <= reg72_s(63 downto 62);
+ rm_s <= reg72_s(58 downto 56);
+ end if;
+ end if;
+ end if;
+ end if;
+end process;
+
+end regshift;
diff --git a/common/CPU/cpu86/segregfile_rtl.vhd b/common/CPU/cpu86/segregfile_rtl.vhd
new file mode 100644
index 00000000..074a18e7
--- /dev/null
+++ b/common/CPU/cpu86/segregfile_rtl.vhd
@@ -0,0 +1,109 @@
+-------------------------------------------------------------------------------
+-- CPU86 - VHDL CPU8088 IP core --
+-- Copyright (C) 2002-2008 HT-LAB --
+-- --
+-- Contact/bugs : http://www.ht-lab.com/misc/feedback.html --
+-- Web : http://www.ht-lab.com --
+-- --
+-- CPU86 is released as open-source under the GNU GPL license. This means --
+-- that designs based on CPU86 must be distributed in full source code --
+-- under the same license. Contact HT-Lab for commercial applications where --
+-- source-code distribution is not desirable. --
+-- --
+-------------------------------------------------------------------------------
+-- --
+-- This library is free software; you can redistribute it and/or --
+-- modify it under the terms of the GNU Lesser General Public --
+-- License as published by the Free Software Foundation; either --
+-- version 2.1 of the License, or (at your option) any later version. --
+-- --
+-- This library 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 --
+-- Lesser General Public License for more details. --
+-- --
+-- Full details of the license can be found in the file "copying.txt". --
+-- --
+-- You should have received a copy of the GNU Lesser General Public --
+-- License along with this library; if not, write to the Free Software --
+-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --
+-- --
+-------------------------------------------------------------------------------
+LIBRARY ieee;
+USE ieee.std_logic_1164.ALL;
+USE ieee.std_logic_unsigned.ALL;
+USE ieee.std_logic_arith.ALL;
+
+USE work.cpu86pack.ALL;
+
+ENTITY segregfile IS
+ PORT(
+ selsreg : IN std_logic_vector (1 DOWNTO 0);
+ sibus : IN std_logic_vector (15 DOWNTO 0);
+ wrs : IN std_logic;
+ reset : IN std_logic;
+ clk : IN std_logic;
+ sdbus : OUT std_logic_vector (15 DOWNTO 0);
+ dimux : IN std_logic_vector (2 DOWNTO 0);
+ es_s : OUT std_logic_vector (15 DOWNTO 0);
+ cs_s : OUT std_logic_vector (15 DOWNTO 0);
+ ss_s : OUT std_logic_vector (15 DOWNTO 0);
+ ds_s : OUT std_logic_vector (15 DOWNTO 0)
+ );
+END segregfile ;
+
+architecture rtl of segregfile is
+
+signal esreg_s : std_logic_vector(15 downto 0);
+signal csreg_s : std_logic_vector(15 downto 0);
+signal ssreg_s : std_logic_vector(15 downto 0);
+signal dsreg_s : std_logic_vector(15 downto 0);
+
+signal sdbus_s : std_logic_vector (15 downto 0); -- internal sdbus
+signal dimux_s : std_logic_vector (2 downto 0); -- replaced dimux
+
+
+begin
+
+----------------------------------------------------------------------------
+-- 4 registers of 16 bits each
+----------------------------------------------------------------------------
+ process (clk,reset)
+ begin
+ if reset='1' then
+ esreg_s <= RESET_ES_C;
+ csreg_s <= RESET_CS_C; -- Only CS set after reset
+ ssreg_s <= RESET_SS_C;
+ dsreg_s <= RESET_DS_C;
+ elsif rising_edge(clk) then
+ if (wrs='1') then
+ case selsreg is
+ when "00" => esreg_s <= sibus;
+ when "01" => csreg_s <= sibus;
+ when "10" => ssreg_s <= sibus;
+ when others => dsreg_s <= sibus;
+ end case;
+ end if;
+ end if;
+ end process;
+
+ dimux_s <= dimux;
+
+ process (dimux_s,esreg_s,csreg_s,ssreg_s,dsreg_s)
+ begin
+ case dimux_s is -- Only 2 bits required
+ when "100" => sdbus_s <= esreg_s;
+ when "101" => sdbus_s <= csreg_s;
+ when "110" => sdbus_s <= ssreg_s;
+ when others => sdbus_s <= dsreg_s;
+ end case;
+ end process;
+
+ sdbus <= sdbus_s; -- Connect to entity
+
+ es_s <= esreg_s;
+ cs_s <= csreg_s;
+ ss_s <= ssreg_s;
+ ds_s <= dsreg_s;
+
+end rtl;
diff --git a/common/CPU/mos8501.v b/common/CPU/mos8501.v
new file mode 100644
index 00000000..26c43521
--- /dev/null
+++ b/common/CPU/mos8501.v
@@ -0,0 +1,104 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Copyright 2013-2016 Istvan Hegedus
+//
+// FPGATED 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.
+//
+// FPGATED 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 .
+//
+// Create Date: 16:36:31 12/10/2014
+// Module Name: mos8501
+// Project Name: FPGATED
+// Target Devices: Xilinx Spartan 3E
+//
+// Description:
+//
+// Dependencies:
+// This module contains an instance of Peter Wendrich's 6502 CPU core from FPGA64 project.
+// The CPU core is used and included with Peter's permission and not developed by me.
+// The mos8501 shell around the CPU core is written by me, but inspired by fpga64 6510 CPU
+// shell. It might shows certain similarities.
+//
+// Revision history:
+// 0.1 first release using incorrect 6502 core from fpga64 project
+// 1.0 CPU core replaced to cpu65xx_fast.vhd from fpga64 project
+//
+//////////////////////////////////////////////////////////////////////////////////
+module mos8501
+(
+ input clk,
+ input reset,
+ input enable,
+ input irq_n,
+ input [7:0] data_in,
+ output [7:0] data_out,
+ output [15:0] address,
+ input gate_in,
+ output rw,
+ input [7:0] port_in,
+ output [7:0] port_out,
+ input rdy,
+ input aec
+);
+
+wire we;
+wire [15:0] core_address;
+wire [7:0] core_data_out;
+reg [7:0] port_dir=8'b0;
+reg [7:0] port_data=8'b0;
+
+// 6502 CPU core
+cpu65xx #(.pipelineOpcode("\false"),.pipelineAluMux("\false"),.pipelineAluOut("\false")) cpu_core
+(
+ .clk(clk),
+ .reset(reset),
+ .enable((rdy | we) & enable), // When RDY is low and cpu would do a read, halt cpu
+ .nmi_n(1'b1),
+ .irq_n(irq_n),
+ .di(!port_access ? data_in : address[0] ? (port_dir & port_data) | (~port_dir & port_in) : port_dir),
+ .do(core_data_out),
+ .addr(core_address),
+ .we(we),
+ .so_n(1'b1),
+ .debugOpcode(),
+ .debugPc(),
+ .debugA(),
+ .debugX(),
+ .debugY(),
+ .debugS()
+);
+
+wire port_access = ~|core_address[15:1];
+
+assign address = aec ? core_address : 16'hffff; // address tri state emulated for easy bus signal combining
+assign port_out = port_data;
+assign rw = ~aec|~we|port_access;
+assign data_out = rw ? 8'hff : core_data_out; // when mux is low data out register is allowed to outside
+
+// IO port part of cpu
+// if direction bit is 0 then data is from chip's port
+// if direction bit is 1 then data is from data port register filled earlier by CPU
+
+always @(posedge clk) begin //writing port registers
+ if(reset) begin
+ port_dir<=0;
+ port_data<=0;
+ end
+ else if (enable) begin
+ if(port_access & we) begin
+ if(core_address[0]==0) port_dir<=core_data_out;
+ else port_data<=core_data_out;
+ end
+ end
+end
+
+endmodule
diff --git a/common/CPU/syntiac6502_6510/cpu65xx.v b/common/CPU/syntiac6502_6510/cpu65xx.v
new file mode 100644
index 00000000..7eee6c15
--- /dev/null
+++ b/common/CPU/syntiac6502_6510/cpu65xx.v
@@ -0,0 +1,1548 @@
+// -----------------------------------------------------------------------
+//
+// FPGA 64
+//
+// A fully functional commodore 64 implementation in a single FPGA
+//
+// -----------------------------------------------------------------------
+// Copyright 2005-2008 by Peter Wendrich (pwsoft@syntiac.com)
+// http://www.syntiac.com/fpga64.html
+// -----------------------------------------------------------------------
+//
+// Table driven, cycle exact 6502/6510 core
+//
+// -----------------------------------------------------------------------
+
+// -----------------------------------------------------------------------
+
+// Store Zp (3) => fetch, cycle2, cycleEnd
+// Store Zp,x (4) => fetch, cycle2, preWrite, cycleEnd
+// Read Zp,x (4) => fetch, cycle2, cycleRead, cycleRead2
+// Rmw Zp,x (6) => fetch, cycle2, cycleRead, cycleRead2, cycleRmw, cycleEnd
+// Store Abs (4) => fetch, cycle2, cycle3, cycleEnd
+// Store Abs,x (5) => fetch, cycle2, cycle3, preWrite, cycleEnd
+// Rts (6) => fetch, cycle2, cycle3, cycleRead, cycleJump, cycleIncrEnd
+// Rti (6) => fetch, cycle2, stack1, stack2, stack3, cycleJump
+// Jsr (6) => fetch, cycle2, .. cycle5, cycle6, cycleJump
+// Jmp abs (-) => fetch, cycle2, .., cycleJump
+// Jmp (ind) (-) => fetch, cycle2, .., cycleJump
+// Brk / irq (6) => fetch, cycle2, stack2, stack3, stack4
+// -----------------------------------------------------------------------
+
+module cpu65xx
+(
+ clk,
+ enable,
+ reset,
+ nmi_n,
+ irq_n,
+ so_n,
+
+ din,
+ dout,
+ addr,
+ we,
+
+ debugOpcode,
+ debugPc,
+ debugA,
+ debugX,
+ debugY,
+ debugS
+);
+
+parameter pipelineOpcode = 1'b0;
+parameter pipelineAluMux = 1'b0;
+parameter pipelineAluOut = 1'b0;
+
+
+input clk;
+input enable;
+input reset;
+input nmi_n;
+input irq_n;
+input so_n;
+
+input [7:0] din;
+output [7:0] dout;
+output [15:0] addr;
+output we;
+
+output [7:0] debugOpcode;
+output [15:0] debugPc;
+output [7:0] debugA;
+output [7:0] debugX;
+output [7:0] debugY;
+output [7:0] debugS;
+
+// type cpuCycles is
+localparam [4:0]
+ opcodeFetch = 5'b00000, // New opcode is read and registers updated
+ cycle2 = 5'b00001,
+ cycle3 = 5'b00010,
+ cyclePreIndirect = 5'b00011,
+ cycleIndirect = 5'b00100,
+ cycleBranchTaken = 5'b00101,
+ cycleBranchPage = 5'b00110,
+ cyclePreRead = 5'b00111, // Cycle before read while doing zeropage indexed addressing.
+ cycleRead = 5'b01000, // Read cycle
+ cycleRead2 = 5'b01001, // Second read cycle after page-boundary crossing.
+ cycleRmw = 5'b01010, // Calculate ALU output for read-modify-write instr.
+ cyclePreWrite = 5'b01011, // Cycle before write when doing indexed addressing.
+ cycleWrite = 5'b01100, // Write cycle for zeropage or absolute addressing.
+ cycleStack1 = 5'b01101,
+ cycleStack2 = 5'b01110,
+ cycleStack3 = 5'b01111,
+ cycleStack4 = 5'b10000,
+ cycleJump = 5'b10001, // Last cycle of Jsr, Jmp. Next fetch address is target addr.
+ cycleEnd = 5'b10010;
+
+ reg [4:0] theCpuCycle;
+ reg [4:0] nextCpuCycle;
+ reg updateRegisters;
+ reg processIrq;
+ reg nmiReg;
+ reg nmiEdge;
+ reg irqReg; // Delay IRQ input with one clock cycle.
+ reg soReg; // SO pin edge detection
+
+// Opcode decoding
+`define opcUpdateA 43
+`define opcUpdateX 42
+`define opcUpdateY 41
+`define opcUpdateS 40
+`define opcUpdateN 39
+`define opcUpdateV 38
+`define opcUpdateD 37
+`define opcUpdateI 36
+`define opcUpdateZ 35
+`define opcUpdateC 34
+
+`define opcSecondByte 33
+`define opcAbsolute 32
+`define opcZeroPage 31
+`define opcIndirect 30
+`define opcStackAddr 29 // Push/Pop address
+`define opcStackData 28 // Push/Pop status/data
+`define opcJump 27
+`define opcBranch 26
+`define indexX 25
+`define indexY 24
+`define opcStackUp 23
+`define opcWrite 22
+`define opcRmw 21
+`define opcIncrAfter 20 // Insert extra cycle to increment PC (RTS)
+`define opcRti 19
+`define opcIRQ 18
+
+`define opcInA 17
+`define opcInE 16
+`define opcInX 15
+`define opcInY 14
+`define opcInS 13
+`define opcInT 12
+`define opcInH 11
+`define opcInClear 10
+`define aluMode1From 9
+//
+`define aluMode1To 6
+`define aluMode2From 5
+//
+`define aluMode2To 3
+//
+`define opcInCmp 2
+`define opcInCpx 1
+`define opcInCpy 0
+
+// subtype addrDef is unsigned(0 to 15);
+localparam [15:0]
+//
+// is Interrupt -----------------+
+// instruction is RTI ----------------+|
+// PC++ on last cycle (RTS) ---------------+||
+// RMW --------------+|||
+// Write -------------+||||
+// Pop/Stack up -------------+|||||
+// Branch ---------+ ||||||
+// Jump ----------+| ||||||
+// Push or Pop data -------+|| ||||||
+// Push or Pop addr ------+||| ||||||
+// Indirect -----+|||| ||||||
+// ZeroPage ----+||||| ||||||
+// Absolute ---+|||||| ||||||
+// PC++ on cycle2 --+||||||| ||||||
+// |AZI||JBXY|WM|||
+ immediate = 16'b1000000000000000,
+ implied = 16'b0000000000000000,
+// Zero page
+ readZp = 16'b1010000000000000,
+ writeZp = 16'b1010000000010000,
+ rmwZp = 16'b1010000000001000,
+// Zero page indexed
+ readZpX = 16'b1010000010000000,
+ writeZpX = 16'b1010000010010000,
+ rmwZpX = 16'b1010000010001000,
+ readZpY = 16'b1010000001000000,
+ writeZpY = 16'b1010000001010000,
+ rmwZpY = 16'b1010000001001000,
+// Zero page indirect
+ readIndX = 16'b1001000010000000,
+ writeIndX = 16'b1001000010010000,
+ rmwIndX = 16'b1001000010001000,
+ readIndY = 16'b1001000001000000,
+ writeIndY = 16'b1001000001010000,
+ rmwIndY = 16'b1001000001001000,
+// |AZI||JBXY|WM||
+// Absolute
+ readAbs = 16'b1100000000000000,
+ writeAbs = 16'b1100000000010000,
+ rmwAbs = 16'b1100000000001000,
+ readAbsX = 16'b1100000010000000,
+ writeAbsX = 16'b1100000010010000,
+ rmwAbsX = 16'b1100000010001000,
+ readAbsY = 16'b1100000001000000,
+ writeAbsY = 16'b1100000001010000,
+ rmwAbsY = 16'b1100000001001000,
+// PHA PHP
+ push = 16'b0000010000000000,
+// PLA PLP
+ pop = 16'b0000010000100000,
+// Jumps
+ jsr = 16'b1000101000000000,
+ jumpAbs = 16'b1000001000000000,
+ jumpInd = 16'b1100001000000000,
+ relative = 16'b1000000100000000,
+// Specials
+ rts = 16'b0000101000100100,
+ rti = 16'b0000111000100010,
+ brk = 16'b1000111000000001,
+
+ xxxxxxxx = 16'bxxxxxxxxxxxxxxxx;
+
+localparam [7:0]
+ // A = accu
+ // E = Accu | 0xEE (for ANE, LXA)
+ // X = index X
+ // Y = index Y
+ // S = Stack pointer
+ // H = indexH
+ //
+ // AEXYSTHc
+ aluInA = 8'b10000000,
+ aluInE = 8'b01000000,
+ aluInEXT = 8'b01100100,
+ aluInET = 8'b01000100,
+ aluInX = 8'b00100000,
+ aluInXH = 8'b00100010,
+ aluInY = 8'b00010000,
+ aluInYH = 8'b00010010,
+ aluInS = 8'b00001000,
+ aluInT = 8'b00000100,
+ aluInAX = 8'b10100000,
+ aluInAXH = 8'b10100010,
+ aluInAT = 8'b10000100,
+ aluInXT = 8'b00100100,
+ aluInST = 8'b00001100,
+ aluInSet = 8'b00000000,
+ aluInClr = 8'b00000001,
+ aluInXXX = 8'bxxxxxxxx;
+
+ // Most of the aluModes are just like the opcodes.
+ // aluModeInp -> input is output. calculate N and Z
+ // aluModeCmp -> Compare for CMP, CPX, CPY
+ // aluModeFlg -> input to flags needed for PLP, RTI and CLC, SEC, CLV
+ // aluModeInc -> for INC but also INX, INY
+ // aluModeDec -> for DEC but also DEX, DEY
+
+ // subtype aluMode1 is unsigned(0 to 3);
+localparam [3:0]
+ // Logic/Shift ALU
+ aluModeInp = 4'b0000,
+ aluModeP = 4'b0001,
+ aluModeInc = 4'b0010,
+ aluModeDec = 4'b0011,
+ aluModeFlg = 4'b0100,
+ aluModeBit = 4'b0101,
+ // 0110
+ // 0111
+ aluModeLsr = 4'b1000,
+ aluModeRor = 4'b1001,
+ aluModeAsl = 4'b1010,
+ aluModeRol = 4'b1011,
+ // 1100
+ // 1101
+ // 1110
+ aluModeAnc = 4'b1111;
+
+ // subtype aluMode2 is unsigned(0 to 2);
+localparam [2:0]
+ // Arithmetic ALU
+ aluModePss = 3'b000,
+ aluModeCmp = 3'b001,
+ aluModeAdc = 3'b010,
+ aluModeSbc = 3'b011,
+ aluModeAnd = 3'b100,
+ aluModeOra = 3'b101,
+ aluModeEor = 3'b110,
+ aluModeArr = 3'b111;
+
+ // subtype aluMode is unsigned(0 to 9);
+localparam [9:0]
+ aluInp = { aluModeInp, aluModePss, 3'bxxx },
+ aluP = { aluModeP , aluModePss, 3'bxxx },
+ aluInc = { aluModeInc, aluModePss, 3'bxxx },
+ aluDec = { aluModeDec, aluModePss, 3'bxxx },
+ aluFlg = { aluModeFlg, aluModePss, 3'bxxx },
+ aluBit = { aluModeBit, aluModeAnd, 3'bxxx },
+ aluRor = { aluModeRor, aluModePss, 3'bxxx },
+ aluLsr = { aluModeLsr, aluModePss, 3'bxxx },
+ aluRol = { aluModeRol, aluModePss, 3'bxxx },
+ aluAsl = { aluModeAsl, aluModePss, 3'bxxx },
+
+ aluCmp = { aluModeInp, aluModeCmp, 3'b100 },
+ aluCpx = { aluModeInp, aluModeCmp, 3'b010 },
+ aluCpy = { aluModeInp, aluModeCmp, 3'b001 },
+ aluAdc = { aluModeInp, aluModeAdc, 3'bxxx },
+ aluSbc = { aluModeInp, aluModeSbc, 3'bxxx },
+ aluAnd = { aluModeInp, aluModeAnd, 3'bxxx },
+ aluOra = { aluModeInp, aluModeOra, 3'bxxx },
+ aluEor = { aluModeInp, aluModeEor, 3'bxxx },
+
+ aluSlo = { aluModeAsl, aluModeOra, 3'bxxx },
+ aluSre = { aluModeLsr, aluModeEor, 3'bxxx },
+ aluRra = { aluModeRor, aluModeAdc, 3'bxxx },
+ aluRla = { aluModeRol, aluModeAnd, 3'bxxx },
+ aluDcp = { aluModeDec, aluModeCmp, 3'b100 },
+ aluIsc = { aluModeInc, aluModeSbc, 3'bxxx },
+ aluAnc = { aluModeAnc, aluModeAnd, 3'bxxx },
+ aluArr = { aluModeRor, aluModeArr, 3'bxxx },
+ aluSbx = { aluModeInp, aluModeCmp, 3'b110 },
+
+ aluXXX = { 4'bxxxx , 3'bxxx , 3'bxxx };
+
+localparam [0:0]
+ // Stack operations. Push/Pop/None
+ stackInc = 1'b0,
+ stackDec = 1'b1,
+ stackXXX = 1'bx;
+
+ // subtype decodedBitsDef is unsigned(0 to 43);
+ // type opcodeInfoTableDef is array(0 to 255) of decodedBitsDef;
+ wire [43:0] opcodeInfoTable [0:255];
+ // // +------- Update register A
+ // // |+------ Update register X
+ // // ||+----- Update register Y
+ // // |||+---- Update register S
+ // // |||| +-- Update Flags
+ // // |||| |
+ // // |||| _|__
+ // // |||| / \
+ // // AXYS NVDIZC addressing aluInput aluMode
+ assign opcodeInfoTable[8'h00] = { 4'b0000, 6'b000100, brk , aluInXXX , aluP }; // 00 BRK
+ assign opcodeInfoTable[8'h01] = { 4'b1000, 6'b100010, readIndX , aluInT , aluOra }; // 01 ORA (zp,x)
+ assign opcodeInfoTable[8'h02] = { 4'bxxxx, 6'bxxxxxx, xxxxxxxx , aluInXXX , aluXXX }; // 02 *** JAM ***
+ assign opcodeInfoTable[8'h03] = { 4'b1000, 6'b100011, rmwIndX , aluInT , aluSlo }; // 03 iSLO (zp,x)
+ assign opcodeInfoTable[8'h04] = { 4'b0000, 6'b000000, readZp , aluInXXX , aluXXX }; // 04 iNOP zp
+ assign opcodeInfoTable[8'h05] = { 4'b1000, 6'b100010, readZp , aluInT , aluOra }; // 05 ORA zp
+ assign opcodeInfoTable[8'h06] = { 4'b0000, 6'b100011, rmwZp , aluInT , aluAsl }; // 06 ASL zp
+ assign opcodeInfoTable[8'h07] = { 4'b1000, 6'b100011, rmwZp , aluInT , aluSlo }; // 07 iSLO zp
+ assign opcodeInfoTable[8'h08] = { 4'b0000, 6'b000000, push , aluInXXX , aluP }; // 08 PHP
+ assign opcodeInfoTable[8'h09] = { 4'b1000, 6'b100010, immediate , aluInT , aluOra }; // 09 ORA imm
+ assign opcodeInfoTable[8'h0A] = { 4'b1000, 6'b100011, implied , aluInA , aluAsl }; // 0A ASL accu
+ assign opcodeInfoTable[8'h0B] = { 4'b1000, 6'b100011, immediate , aluInT , aluAnc }; // 0B iANC imm
+ assign opcodeInfoTable[8'h0C] = { 4'b0000, 6'b000000, readAbs , aluInXXX , aluXXX }; // 0C iNOP abs
+ assign opcodeInfoTable[8'h0D] = { 4'b1000, 6'b100010, readAbs , aluInT , aluOra }; // 0D ORA abs
+ assign opcodeInfoTable[8'h0E] = { 4'b0000, 6'b100011, rmwAbs , aluInT , aluAsl }; // 0E ASL abs
+ assign opcodeInfoTable[8'h0F] = { 4'b1000, 6'b100011, rmwAbs , aluInT , aluSlo }; // 0F iSLO abs
+ assign opcodeInfoTable[8'h10] = { 4'b0000, 6'b000000, relative , aluInXXX , aluXXX }; // 10 BPL
+ assign opcodeInfoTable[8'h11] = { 4'b1000, 6'b100010, readIndY , aluInT , aluOra }; // 11 ORA (zp),y
+ assign opcodeInfoTable[8'h12] = { 4'bxxxx, 6'bxxxxxx, xxxxxxxx , aluInXXX , aluXXX }; // 12 *** JAM ***
+ assign opcodeInfoTable[8'h13] = { 4'b1000, 6'b100011, rmwIndY , aluInT , aluSlo }; // 13 iSLO (zp),y
+ assign opcodeInfoTable[8'h14] = { 4'b0000, 6'b000000, readZpX , aluInXXX , aluXXX }; // 14 iNOP zp,x
+ assign opcodeInfoTable[8'h15] = { 4'b1000, 6'b100010, readZpX , aluInT , aluOra }; // 15 ORA zp,x
+ assign opcodeInfoTable[8'h16] = { 4'b0000, 6'b100011, rmwZpX , aluInT , aluAsl }; // 16 ASL zp,x
+ assign opcodeInfoTable[8'h17] = { 4'b1000, 6'b100011, rmwZpX , aluInT , aluSlo }; // 17 iSLO zp,x
+ assign opcodeInfoTable[8'h18] = { 4'b0000, 6'b000001, implied , aluInClr , aluFlg }; // 18 CLC
+ assign opcodeInfoTable[8'h19] = { 4'b1000, 6'b100010, readAbsY , aluInT , aluOra }; // 19 ORA abs,y
+ assign opcodeInfoTable[8'h1A] = { 4'b0000, 6'b000000, implied , aluInXXX , aluXXX }; // 1A iNOP implied
+ assign opcodeInfoTable[8'h1B] = { 4'b1000, 6'b100011, rmwAbsY , aluInT , aluSlo }; // 1B iSLO abs,y
+ assign opcodeInfoTable[8'h1C] = { 4'b0000, 6'b000000, readAbsX , aluInXXX , aluXXX }; // 1C iNOP abs,x
+ assign opcodeInfoTable[8'h1D] = { 4'b1000, 6'b100010, readAbsX , aluInT , aluOra }; // 1D ORA abs,x
+ assign opcodeInfoTable[8'h1E] = { 4'b0000, 6'b100011, rmwAbsX , aluInT , aluAsl }; // 1E ASL abs,x
+ assign opcodeInfoTable[8'h1F] = { 4'b1000, 6'b100011, rmwAbsX , aluInT , aluSlo }; // 1F iSLO abs,x
+ // // AXYS NVDIZC addressing aluInput aluMode
+ assign opcodeInfoTable[8'h20] = { 4'b0000, 6'b000000, jsr , aluInXXX , aluXXX }; // 20 JSR
+ assign opcodeInfoTable[8'h21] = { 4'b1000, 6'b100010, readIndX , aluInT , aluAnd }; // 21 AND (zp,x)
+ assign opcodeInfoTable[8'h22] = { 4'bxxxx, 6'bxxxxxx, xxxxxxxx , aluInXXX , aluXXX }; // 22 *** JAM ***
+ assign opcodeInfoTable[8'h23] = { 4'b1000, 6'b100011, rmwIndX , aluInT , aluRla }; // 23 iRLA (zp,x)
+ assign opcodeInfoTable[8'h24] = { 4'b0000, 6'b110010, readZp , aluInT , aluBit }; // 24 BIT zp
+ assign opcodeInfoTable[8'h25] = { 4'b1000, 6'b100010, readZp , aluInT , aluAnd }; // 25 AND zp
+ assign opcodeInfoTable[8'h26] = { 4'b0000, 6'b100011, rmwZp , aluInT , aluRol }; // 26 ROL zp
+ assign opcodeInfoTable[8'h27] = { 4'b1000, 6'b100011, rmwZp , aluInT , aluRla }; // 27 iRLA zp
+ assign opcodeInfoTable[8'h28] = { 4'b0000, 6'b111111, pop , aluInT , aluFlg }; // 28 PLP
+ assign opcodeInfoTable[8'h29] = { 4'b1000, 6'b100010, immediate , aluInT , aluAnd }; // 29 AND imm
+ assign opcodeInfoTable[8'h2A] = { 4'b1000, 6'b100011, implied , aluInA , aluRol }; // 2A ROL accu
+ assign opcodeInfoTable[8'h2B] = { 4'b1000, 6'b100011, immediate , aluInT , aluAnc }; // 2B iANC imm
+ assign opcodeInfoTable[8'h2C] = { 4'b0000, 6'b110010, readAbs , aluInT , aluBit }; // 2C BIT abs
+ assign opcodeInfoTable[8'h2D] = { 4'b1000, 6'b100010, readAbs , aluInT , aluAnd }; // 2D AND abs
+ assign opcodeInfoTable[8'h2E] = { 4'b0000, 6'b100011, rmwAbs , aluInT , aluRol }; // 2E ROL abs
+ assign opcodeInfoTable[8'h2F] = { 4'b1000, 6'b100011, rmwAbs , aluInT , aluRla }; // 2F iRLA abs
+ assign opcodeInfoTable[8'h30] = { 4'b0000, 6'b000000, relative , aluInXXX , aluXXX }; // 30 BMI
+ assign opcodeInfoTable[8'h31] = { 4'b1000, 6'b100010, readIndY , aluInT , aluAnd }; // 31 AND (zp),y
+ assign opcodeInfoTable[8'h32] = { 4'bxxxx, 6'bxxxxxx, xxxxxxxx , aluInXXX , aluXXX }; // 32 *** JAM ***
+ assign opcodeInfoTable[8'h33] = { 4'b1000, 6'b100011, rmwIndY , aluInT , aluRla }; // 33 iRLA (zp),y
+ assign opcodeInfoTable[8'h34] = { 4'b0000, 6'b000000, readZpX , aluInXXX , aluXXX }; // 34 iNOP zp,x
+ assign opcodeInfoTable[8'h35] = { 4'b1000, 6'b100010, readZpX , aluInT , aluAnd }; // 35 AND zp,x
+ assign opcodeInfoTable[8'h36] = { 4'b0000, 6'b100011, rmwZpX , aluInT , aluRol }; // 36 ROL zp,x
+ assign opcodeInfoTable[8'h37] = { 4'b1000, 6'b100011, rmwZpX , aluInT , aluRla }; // 37 iRLA zp,x
+ assign opcodeInfoTable[8'h38] = { 4'b0000, 6'b000001, implied , aluInSet , aluFlg }; // 38 SEC
+ assign opcodeInfoTable[8'h39] = { 4'b1000, 6'b100010, readAbsY , aluInT , aluAnd }; // 39 AND abs,y
+ assign opcodeInfoTable[8'h3A] = { 4'b0000, 6'b000000, implied , aluInXXX , aluXXX }; // 3A iNOP implied
+ assign opcodeInfoTable[8'h3B] = { 4'b1000, 6'b100011, rmwAbsY , aluInT , aluRla }; // 3B iRLA abs,y
+ assign opcodeInfoTable[8'h3C] = { 4'b0000, 6'b000000, readAbsX , aluInXXX , aluXXX }; // 3C iNOP abs,x
+ assign opcodeInfoTable[8'h3D] = { 4'b1000, 6'b100010, readAbsX , aluInT , aluAnd }; // 3D AND abs,x
+ assign opcodeInfoTable[8'h3E] = { 4'b0000, 6'b100011, rmwAbsX , aluInT , aluRol }; // 3E ROL abs,x
+ assign opcodeInfoTable[8'h3F] = { 4'b1000, 6'b100011, rmwAbsX , aluInT , aluRla }; // 3F iRLA abs,x
+ // // AXYS NVDIZC addressing aluInput aluMode
+ assign opcodeInfoTable[8'h40] = { 4'b0000, 6'b111111, rti , aluInT , aluFlg }; // 40 RTI
+ assign opcodeInfoTable[8'h41] = { 4'b1000, 6'b100010, readIndX , aluInT , aluEor }; // 41 EOR (zp,x)
+ assign opcodeInfoTable[8'h42] = { 4'bxxxx, 6'bxxxxxx, xxxxxxxx , aluInXXX , aluXXX }; // 42 *** JAM ***
+ assign opcodeInfoTable[8'h43] = { 4'b1000, 6'b100011, rmwIndX , aluInT , aluSre }; // 43 iSRE (zp,x)
+ assign opcodeInfoTable[8'h44] = { 4'b0000, 6'b000000, readZp , aluInXXX , aluXXX }; // 44 iNOP zp
+ assign opcodeInfoTable[8'h45] = { 4'b1000, 6'b100010, readZp , aluInT , aluEor }; // 45 EOR zp
+ assign opcodeInfoTable[8'h46] = { 4'b0000, 6'b100011, rmwZp , aluInT , aluLsr }; // 46 LSR zp
+ assign opcodeInfoTable[8'h47] = { 4'b1000, 6'b100011, rmwZp , aluInT , aluSre }; // 47 iSRE zp
+ assign opcodeInfoTable[8'h48] = { 4'b0000, 6'b000000, push , aluInA , aluInp }; // 48 PHA
+ assign opcodeInfoTable[8'h49] = { 4'b1000, 6'b100010, immediate , aluInT , aluEor }; // 49 EOR imm
+ assign opcodeInfoTable[8'h4A] = { 4'b1000, 6'b100011, implied , aluInA , aluLsr }; // 4A LSR accu
+ assign opcodeInfoTable[8'h4B] = { 4'b1000, 6'b100011, immediate , aluInAT , aluLsr }; // 4B iALR imm
+ assign opcodeInfoTable[8'h4C] = { 4'b0000, 6'b000000, jumpAbs , aluInXXX , aluXXX }; // 4C JMP abs
+ assign opcodeInfoTable[8'h4D] = { 4'b1000, 6'b100010, readAbs , aluInT , aluEor }; // 4D EOR abs
+ assign opcodeInfoTable[8'h4E] = { 4'b0000, 6'b100011, rmwAbs , aluInT , aluLsr }; // 4E LSR abs
+ assign opcodeInfoTable[8'h4F] = { 4'b1000, 6'b100011, rmwAbs , aluInT , aluSre }; // 4F iSRE abs
+ assign opcodeInfoTable[8'h50] = { 4'b0000, 6'b000000, relative , aluInXXX , aluXXX }; // 50 BVC
+ assign opcodeInfoTable[8'h51] = { 4'b1000, 6'b100010, readIndY , aluInT , aluEor }; // 51 EOR (zp),y
+ assign opcodeInfoTable[8'h52] = { 4'bxxxx, 6'bxxxxxx, xxxxxxxx , aluInXXX , aluXXX }; // 52 *** JAM ***
+ assign opcodeInfoTable[8'h53] = { 4'b1000, 6'b100011, rmwIndY , aluInT , aluSre }; // 53 iSRE (zp),y
+ assign opcodeInfoTable[8'h54] = { 4'b0000, 6'b000000, readZpX , aluInXXX , aluXXX }; // 54 iNOP zp,x
+ assign opcodeInfoTable[8'h55] = { 4'b1000, 6'b100010, readZpX , aluInT , aluEor }; // 55 EOR zp,x
+ assign opcodeInfoTable[8'h56] = { 4'b0000, 6'b100011, rmwZpX , aluInT , aluLsr }; // 56 LSR zp,x
+ assign opcodeInfoTable[8'h57] = { 4'b1000, 6'b100011, rmwZpX , aluInT , aluSre }; // 57 SRE zp,x
+ assign opcodeInfoTable[8'h58] = { 4'b0000, 6'b000100, implied , aluInClr , aluXXX }; // 58 CLI
+ assign opcodeInfoTable[8'h59] = { 4'b1000, 6'b100010, readAbsY , aluInT , aluEor }; // 59 EOR abs,y
+ assign opcodeInfoTable[8'h5A] = { 4'b0000, 6'b000000, implied , aluInXXX , aluXXX }; // 5A iNOP implied
+ assign opcodeInfoTable[8'h5B] = { 4'b1000, 6'b100011, rmwAbsY , aluInT , aluSre }; // 5B iSRE abs,y
+ assign opcodeInfoTable[8'h5C] = { 4'b0000, 6'b000000, readAbsX , aluInXXX , aluXXX }; // 5C iNOP abs,x
+ assign opcodeInfoTable[8'h5D] = { 4'b1000, 6'b100010, readAbsX , aluInT , aluEor }; // 5D EOR abs,x
+ assign opcodeInfoTable[8'h5E] = { 4'b0000, 6'b100011, rmwAbsX , aluInT , aluLsr }; // 5E LSR abs,x
+ assign opcodeInfoTable[8'h5F] = { 4'b1000, 6'b100011, rmwAbsX , aluInT , aluSre }; // 5F SRE abs,x
+ // // AXYS NVDIZC addressing aluInput aluMode
+ assign opcodeInfoTable[8'h60] = { 4'b0000, 6'b000000, rts , aluInXXX , aluXXX }; // 60 RTS
+ assign opcodeInfoTable[8'h61] = { 4'b1000, 6'b110011, readIndX , aluInT , aluAdc }; // 61 ADC (zp,x)
+ assign opcodeInfoTable[8'h62] = { 4'bxxxx, 6'bxxxxxx, xxxxxxxx , aluInXXX , aluXXX }; // 62 *** JAM ***
+ assign opcodeInfoTable[8'h63] = { 4'b1000, 6'b110011, rmwIndX , aluInT , aluRra }; // 63 iRRA (zp,x)
+ assign opcodeInfoTable[8'h64] = { 4'b0000, 6'b000000, readZp , aluInXXX , aluXXX }; // 64 iNOP zp
+ assign opcodeInfoTable[8'h65] = { 4'b1000, 6'b110011, readZp , aluInT , aluAdc }; // 65 ADC zp
+ assign opcodeInfoTable[8'h66] = { 4'b0000, 6'b100011, rmwZp , aluInT , aluRor }; // 66 ROR zp
+ assign opcodeInfoTable[8'h67] = { 4'b1000, 6'b110011, rmwZp , aluInT , aluRra }; // 67 iRRA zp
+ assign opcodeInfoTable[8'h68] = { 4'b1000, 6'b100010, pop , aluInT , aluInp }; // 68 PLA
+ assign opcodeInfoTable[8'h69] = { 4'b1000, 6'b110011, immediate , aluInT , aluAdc }; // 69 ADC imm
+ assign opcodeInfoTable[8'h6A] = { 4'b1000, 6'b100011, implied , aluInA , aluRor }; // 6A ROR accu
+ assign opcodeInfoTable[8'h6B] = { 4'b1000, 6'b110011, immediate , aluInAT , aluArr }; // 6B iARR imm
+ assign opcodeInfoTable[8'h6C] = { 4'b0000, 6'b000000, jumpInd , aluInXXX , aluXXX }; // 6C JMP indirect
+ assign opcodeInfoTable[8'h6D] = { 4'b1000, 6'b110011, readAbs , aluInT , aluAdc }; // 6D ADC abs
+ assign opcodeInfoTable[8'h6E] = { 4'b0000, 6'b100011, rmwAbs , aluInT , aluRor }; // 6E ROR abs
+ assign opcodeInfoTable[8'h6F] = { 4'b1000, 6'b110011, rmwAbs , aluInT , aluRra }; // 6F iRRA abs
+ assign opcodeInfoTable[8'h70] = { 4'b0000, 6'b000000, relative , aluInXXX , aluXXX }; // 70 BVS
+ assign opcodeInfoTable[8'h71] = { 4'b1000, 6'b110011, readIndY , aluInT , aluAdc }; // 71 ADC (zp),y
+ assign opcodeInfoTable[8'h72] = { 4'bxxxx, 6'bxxxxxx, xxxxxxxx , aluInXXX , aluXXX }; // 72 *** JAM ***
+ assign opcodeInfoTable[8'h73] = { 4'b1000, 6'b110011, rmwIndY , aluInT , aluRra }; // 73 iRRA (zp),y
+ assign opcodeInfoTable[8'h74] = { 4'b0000, 6'b000000, readZpX , aluInXXX , aluXXX }; // 74 iNOP zp,x
+ assign opcodeInfoTable[8'h75] = { 4'b1000, 6'b110011, readZpX , aluInT , aluAdc }; // 75 ADC zp,x
+ assign opcodeInfoTable[8'h76] = { 4'b0000, 6'b100011, rmwZpX , aluInT , aluRor }; // 76 ROR zp,x
+ assign opcodeInfoTable[8'h77] = { 4'b1000, 6'b110011, rmwZpX , aluInT , aluRra }; // 77 iRRA zp,x
+ assign opcodeInfoTable[8'h78] = { 4'b0000, 6'b000100, implied , aluInSet , aluXXX }; // 78 SEI
+ assign opcodeInfoTable[8'h79] = { 4'b1000, 6'b110011, readAbsY , aluInT , aluAdc }; // 79 ADC abs,y
+ assign opcodeInfoTable[8'h7A] = { 4'b0000, 6'b000000, implied , aluInXXX , aluXXX }; // 7A iNOP implied
+ assign opcodeInfoTable[8'h7B] = { 4'b1000, 6'b110011, rmwAbsY , aluInT , aluRra }; // 7B iRRA abs,y
+ assign opcodeInfoTable[8'h7C] = { 4'b0000, 6'b000000, readAbsX , aluInXXX , aluXXX }; // 7C iNOP abs,x
+ assign opcodeInfoTable[8'h7D] = { 4'b1000, 6'b110011, readAbsX , aluInT , aluAdc }; // 7D ADC abs,x
+ assign opcodeInfoTable[8'h7E] = { 4'b0000, 6'b100011, rmwAbsX , aluInT , aluRor }; // 7E ROR abs,x
+ assign opcodeInfoTable[8'h7F] = { 4'b1000, 6'b110011, rmwAbsX , aluInT , aluRra }; // 7F iRRA abs,x
+ // // AXYS NVDIZC addressing aluInput aluMode
+ assign opcodeInfoTable[8'h80] = { 4'b0000, 6'b000000, immediate , aluInXXX , aluXXX }; // 80 iNOP imm
+ assign opcodeInfoTable[8'h81] = { 4'b0000, 6'b000000, writeIndX , aluInA , aluInp }; // 81 STA (zp,x)
+ assign opcodeInfoTable[8'h82] = { 4'b0000, 6'b000000, immediate , aluInXXX , aluXXX }; // 82 iNOP imm
+ assign opcodeInfoTable[8'h83] = { 4'b0000, 6'b000000, writeIndX , aluInAX , aluInp }; // 83 iSAX (zp,x)
+ assign opcodeInfoTable[8'h84] = { 4'b0000, 6'b000000, writeZp , aluInY , aluInp }; // 84 STY zp
+ assign opcodeInfoTable[8'h85] = { 4'b0000, 6'b000000, writeZp , aluInA , aluInp }; // 85 STA zp
+ assign opcodeInfoTable[8'h86] = { 4'b0000, 6'b000000, writeZp , aluInX , aluInp }; // 86 STX zp
+ assign opcodeInfoTable[8'h87] = { 4'b0000, 6'b000000, writeZp , aluInAX , aluInp }; // 87 iSAX zp
+ assign opcodeInfoTable[8'h88] = { 4'b0010, 6'b100010, implied , aluInY , aluDec }; // 88 DEY
+ assign opcodeInfoTable[8'h89] = { 4'b0000, 6'b000000, immediate , aluInXXX , aluXXX }; // 84 iNOP imm
+ assign opcodeInfoTable[8'h8A] = { 4'b1000, 6'b100010, implied , aluInX , aluInp }; // 8A TXA
+ assign opcodeInfoTable[8'h8B] = { 4'b1000, 6'b100010, immediate , aluInEXT , aluInp }; // 8B iANE imm
+ assign opcodeInfoTable[8'h8C] = { 4'b0000, 6'b000000, writeAbs , aluInY , aluInp }; // 8C STY abs
+ assign opcodeInfoTable[8'h8D] = { 4'b0000, 6'b000000, writeAbs , aluInA , aluInp }; // 8D STA abs
+ assign opcodeInfoTable[8'h8E] = { 4'b0000, 6'b000000, writeAbs , aluInX , aluInp }; // 8E STX abs
+ assign opcodeInfoTable[8'h8F] = { 4'b0000, 6'b000000, writeAbs , aluInAX , aluInp }; // 8F iSAX abs
+ assign opcodeInfoTable[8'h90] = { 4'b0000, 6'b000000, relative , aluInXXX , aluXXX }; // 90 BCC
+ assign opcodeInfoTable[8'h91] = { 4'b0000, 6'b000000, writeIndY , aluInA , aluInp }; // 91 STA (zp),y
+ assign opcodeInfoTable[8'h92] = { 4'bxxxx, 6'bxxxxxx, xxxxxxxx , aluInXXX , aluXXX }; // 92 *** JAM ***
+ assign opcodeInfoTable[8'h93] = { 4'b0000, 6'b000000, writeIndY , aluInAXH , aluInp }; // 93 iAHX (zp),y
+ assign opcodeInfoTable[8'h94] = { 4'b0000, 6'b000000, writeZpX , aluInY , aluInp }; // 94 STY zp,x
+ assign opcodeInfoTable[8'h95] = { 4'b0000, 6'b000000, writeZpX , aluInA , aluInp }; // 95 STA zp,x
+ assign opcodeInfoTable[8'h96] = { 4'b0000, 6'b000000, writeZpY , aluInX , aluInp }; // 96 STX zp,y
+ assign opcodeInfoTable[8'h97] = { 4'b0000, 6'b000000, writeZpY , aluInAX , aluInp }; // 97 iSAX zp,y
+ assign opcodeInfoTable[8'h98] = { 4'b1000, 6'b100010, implied , aluInY , aluInp }; // 98 TYA
+ assign opcodeInfoTable[8'h99] = { 4'b0000, 6'b000000, writeAbsY , aluInA , aluInp }; // 99 STA abs,y
+ assign opcodeInfoTable[8'h9A] = { 4'b0001, 6'b000000, implied , aluInX , aluInp }; // 9A TXS
+ assign opcodeInfoTable[8'h9B] = { 4'b0001, 6'b000000, writeAbsY , aluInAXH , aluInp }; // 9B iSHS abs,y
+ assign opcodeInfoTable[8'h9C] = { 4'b0000, 6'b000000, writeAbsX , aluInYH , aluInp }; // 9C iSHY abs,x
+ assign opcodeInfoTable[8'h9D] = { 4'b0000, 6'b000000, writeAbsX , aluInA , aluInp }; // 9D STA abs,x
+ assign opcodeInfoTable[8'h9E] = { 4'b0000, 6'b000000, writeAbsY , aluInXH , aluInp }; // 9E iSHX abs,y
+ assign opcodeInfoTable[8'h9F] = { 4'b0000, 6'b000000, writeAbsY , aluInAXH , aluInp }; // 9F iAHX abs,y
+ // // AXYS NVDIZC addressing aluInput aluMode
+ assign opcodeInfoTable[8'hA0] = { 4'b0010, 6'b100010, immediate , aluInT , aluInp }; // A0 LDY imm
+ assign opcodeInfoTable[8'hA1] = { 4'b1000, 6'b100010, readIndX , aluInT , aluInp }; // A1 LDA (zp,x)
+ assign opcodeInfoTable[8'hA2] = { 4'b0100, 6'b100010, immediate , aluInT , aluInp }; // A2 LDX imm
+ assign opcodeInfoTable[8'hA3] = { 4'b1100, 6'b100010, readIndX , aluInT , aluInp }; // A3 LAX (zp,x)
+ assign opcodeInfoTable[8'hA4] = { 4'b0010, 6'b100010, readZp , aluInT , aluInp }; // A4 LDY zp
+ assign opcodeInfoTable[8'hA5] = { 4'b1000, 6'b100010, readZp , aluInT , aluInp }; // A5 LDA zp
+ assign opcodeInfoTable[8'hA6] = { 4'b0100, 6'b100010, readZp , aluInT , aluInp }; // A6 LDX zp
+ assign opcodeInfoTable[8'hA7] = { 4'b1100, 6'b100010, readZp , aluInT , aluInp }; // A7 iLAX zp
+ assign opcodeInfoTable[8'hA8] = { 4'b0010, 6'b100010, implied , aluInA , aluInp }; // A8 TAY
+ assign opcodeInfoTable[8'hA9] = { 4'b1000, 6'b100010, immediate , aluInT , aluInp }; // A9 LDA imm
+ assign opcodeInfoTable[8'hAA] = { 4'b0100, 6'b100010, implied , aluInA , aluInp }; // AA TAX
+ assign opcodeInfoTable[8'hAB] = { 4'b1100, 6'b100010, immediate , aluInET , aluInp }; // AB iLXA imm
+ assign opcodeInfoTable[8'hAC] = { 4'b0010, 6'b100010, readAbs , aluInT , aluInp }; // AC LDY abs
+ assign opcodeInfoTable[8'hAD] = { 4'b1000, 6'b100010, readAbs , aluInT , aluInp }; // AD LDA abs
+ assign opcodeInfoTable[8'hAE] = { 4'b0100, 6'b100010, readAbs , aluInT , aluInp }; // AE LDX abs
+ assign opcodeInfoTable[8'hAF] = { 4'b1100, 6'b100010, readAbs , aluInT , aluInp }; // AF iLAX abs
+ assign opcodeInfoTable[8'hB0] = { 4'b0000, 6'b000000, relative , aluInXXX , aluXXX }; // B0 BCS
+ assign opcodeInfoTable[8'hB1] = { 4'b1000, 6'b100010, readIndY , aluInT , aluInp }; // B1 LDA (zp),y
+ assign opcodeInfoTable[8'hB2] = { 4'bxxxx, 6'bxxxxxx, xxxxxxxx , aluInXXX , aluXXX }; // B2 *** JAM ***
+ assign opcodeInfoTable[8'hB3] = { 4'b1100, 6'b100010, readIndY , aluInT , aluInp }; // B3 iLAX (zp),y
+ assign opcodeInfoTable[8'hB4] = { 4'b0010, 6'b100010, readZpX , aluInT , aluInp }; // B4 LDY zp,x
+ assign opcodeInfoTable[8'hB5] = { 4'b1000, 6'b100010, readZpX , aluInT , aluInp }; // B5 LDA zp,x
+ assign opcodeInfoTable[8'hB6] = { 4'b0100, 6'b100010, readZpY , aluInT , aluInp }; // B6 LDX zp,y
+ assign opcodeInfoTable[8'hB7] = { 4'b1100, 6'b100010, readZpY , aluInT , aluInp }; // B7 iLAX zp,y
+ assign opcodeInfoTable[8'hB8] = { 4'b0000, 6'b010000, implied , aluInClr , aluFlg }; // B8 CLV
+ assign opcodeInfoTable[8'hB9] = { 4'b1000, 6'b100010, readAbsY , aluInT , aluInp }; // B9 LDA abs,y
+ assign opcodeInfoTable[8'hBA] = { 4'b0100, 6'b100010, implied , aluInS , aluInp }; // BA TSX
+ assign opcodeInfoTable[8'hBB] = { 4'b1101, 6'b100010, readAbsY , aluInST , aluInp }; // BB iLAS abs,y
+ assign opcodeInfoTable[8'hBC] = { 4'b0010, 6'b100010, readAbsX , aluInT , aluInp }; // BC LDY abs,x
+ assign opcodeInfoTable[8'hBD] = { 4'b1000, 6'b100010, readAbsX , aluInT , aluInp }; // BD LDA abs,x
+ assign opcodeInfoTable[8'hBE] = { 4'b0100, 6'b100010, readAbsY , aluInT , aluInp }; // BE LDX abs,y
+ assign opcodeInfoTable[8'hBF] = { 4'b1100, 6'b100010, readAbsY , aluInT , aluInp }; // BF iLAX abs,y
+ // // AXYS NVDIZC addressing aluInput aluMode
+ assign opcodeInfoTable[8'hC0] = { 4'b0000, 6'b100011, immediate , aluInT , aluCpy }; // C0 CPY imm
+ assign opcodeInfoTable[8'hC1] = { 4'b0000, 6'b100011, readIndX , aluInT , aluCmp }; // C1 CMP (zp,x)
+ assign opcodeInfoTable[8'hC2] = { 4'b0000, 6'b000000, immediate , aluInXXX , aluXXX }; // C2 iNOP imm
+ assign opcodeInfoTable[8'hC3] = { 4'b0000, 6'b100011, rmwIndX , aluInT , aluDcp }; // C3 iDCP (zp,x)
+ assign opcodeInfoTable[8'hC4] = { 4'b0000, 6'b100011, readZp , aluInT , aluCpy }; // C4 CPY zp
+ assign opcodeInfoTable[8'hC5] = { 4'b0000, 6'b100011, readZp , aluInT , aluCmp }; // C5 CMP zp
+ assign opcodeInfoTable[8'hC6] = { 4'b0000, 6'b100010, rmwZp , aluInT , aluDec }; // C6 DEC zp
+ assign opcodeInfoTable[8'hC7] = { 4'b0000, 6'b100011, rmwZp , aluInT , aluDcp }; // C7 iDCP zp
+ assign opcodeInfoTable[8'hC8] = { 4'b0010, 6'b100010, implied , aluInY , aluInc }; // C8 INY
+ assign opcodeInfoTable[8'hC9] = { 4'b0000, 6'b100011, immediate , aluInT , aluCmp }; // C9 CMP imm
+ assign opcodeInfoTable[8'hCA] = { 4'b0100, 6'b100010, implied , aluInX , aluDec }; // CA DEX
+ assign opcodeInfoTable[8'hCB] = { 4'b0100, 6'b100011, immediate , aluInT , aluSbx }; // CB SBX imm
+ assign opcodeInfoTable[8'hCC] = { 4'b0000, 6'b100011, readAbs , aluInT , aluCpy }; // CC CPY abs
+ assign opcodeInfoTable[8'hCD] = { 4'b0000, 6'b100011, readAbs , aluInT , aluCmp }; // CD CMP abs
+ assign opcodeInfoTable[8'hCE] = { 4'b0000, 6'b100010, rmwAbs , aluInT , aluDec }; // CE DEC abs
+ assign opcodeInfoTable[8'hCF] = { 4'b0000, 6'b100011, rmwAbs , aluInT , aluDcp }; // CF iDCP abs
+ assign opcodeInfoTable[8'hD0] = { 4'b0000, 6'b000000, relative , aluInXXX , aluXXX }; // D0 BNE
+ assign opcodeInfoTable[8'hD1] = { 4'b0000, 6'b100011, readIndY , aluInT , aluCmp }; // D1 CMP (zp),y
+ assign opcodeInfoTable[8'hD2] = { 4'bxxxx, 6'bxxxxxx, xxxxxxxx , aluInXXX , aluXXX }; // D2 *** JAM ***
+ assign opcodeInfoTable[8'hD3] = { 4'b0000, 6'b100011, rmwIndY , aluInT , aluDcp }; // D3 iDCP (zp),y
+ assign opcodeInfoTable[8'hD4] = { 4'b0000, 6'b000000, readZpX , aluInXXX , aluXXX }; // D4 iNOP zp,x
+ assign opcodeInfoTable[8'hD5] = { 4'b0000, 6'b100011, readZpX , aluInT , aluCmp }; // D5 CMP zp,x
+ assign opcodeInfoTable[8'hD6] = { 4'b0000, 6'b100010, rmwZpX , aluInT , aluDec }; // D6 DEC zp,x
+ assign opcodeInfoTable[8'hD7] = { 4'b0000, 6'b100011, rmwZpX , aluInT , aluDcp }; // D7 iDCP zp,x
+ assign opcodeInfoTable[8'hD8] = { 4'b0000, 6'b001000, implied , aluInClr , aluXXX }; // D8 CLD
+ assign opcodeInfoTable[8'hD9] = { 4'b0000, 6'b100011, readAbsY , aluInT , aluCmp }; // D9 CMP abs,y
+ assign opcodeInfoTable[8'hDA] = { 4'b0000, 6'b000000, implied , aluInXXX , aluXXX }; // DA iNOP implied
+ assign opcodeInfoTable[8'hDB] = { 4'b0000, 6'b100011, rmwAbsY , aluInT , aluDcp }; // DB iDCP abs,y
+ assign opcodeInfoTable[8'hDC] = { 4'b0000, 6'b000000, readAbsX , aluInXXX , aluXXX }; // DC iNOP abs,x
+ assign opcodeInfoTable[8'hDD] = { 4'b0000, 6'b100011, readAbsX , aluInT , aluCmp }; // DD CMP abs,x
+ assign opcodeInfoTable[8'hDE] = { 4'b0000, 6'b100010, rmwAbsX , aluInT , aluDec }; // DE DEC abs,x
+ assign opcodeInfoTable[8'hDF] = { 4'b0000, 6'b100011, rmwAbsX , aluInT , aluDcp }; // DF iDCP abs,x
+ // // AXYS NVDIZC addressing aluInput aluMode
+ assign opcodeInfoTable[8'hE0] = { 4'b0000, 6'b100011, immediate , aluInT , aluCpx }; // E0 CPX imm
+ assign opcodeInfoTable[8'hE1] = { 4'b1000, 6'b110011, readIndX , aluInT , aluSbc }; // E1 SBC (zp,x)
+ assign opcodeInfoTable[8'hE2] = { 4'b0000, 6'b000000, immediate , aluInXXX , aluXXX }; // E2 iNOP imm
+ assign opcodeInfoTable[8'hE3] = { 4'b1000, 6'b110011, rmwIndX , aluInT , aluIsc }; // E3 iISC (zp,x)
+ assign opcodeInfoTable[8'hE4] = { 4'b0000, 6'b100011, readZp , aluInT , aluCpx }; // E4 CPX zp
+ assign opcodeInfoTable[8'hE5] = { 4'b1000, 6'b110011, readZp , aluInT , aluSbc }; // E5 SBC zp
+ assign opcodeInfoTable[8'hE6] = { 4'b0000, 6'b100010, rmwZp , aluInT , aluInc }; // E6 INC zp
+ assign opcodeInfoTable[8'hE7] = { 4'b1000, 6'b110011, rmwZp , aluInT , aluIsc }; // E7 iISC zp
+ assign opcodeInfoTable[8'hE8] = { 4'b0100, 6'b100010, implied , aluInX , aluInc }; // E8 INX
+ assign opcodeInfoTable[8'hE9] = { 4'b1000, 6'b110011, immediate , aluInT , aluSbc }; // E9 SBC imm
+ assign opcodeInfoTable[8'hEA] = { 4'b0000, 6'b000000, implied , aluInXXX , aluXXX }; // EA NOP
+ assign opcodeInfoTable[8'hEB] = { 4'b1000, 6'b110011, immediate , aluInT , aluSbc }; // EB SBC imm (illegal opc)
+ assign opcodeInfoTable[8'hEC] = { 4'b0000, 6'b100011, readAbs , aluInT , aluCpx }; // EC CPX abs
+ assign opcodeInfoTable[8'hED] = { 4'b1000, 6'b110011, readAbs , aluInT , aluSbc }; // ED SBC abs
+ assign opcodeInfoTable[8'hEE] = { 4'b0000, 6'b100010, rmwAbs , aluInT , aluInc }; // EE INC abs
+ assign opcodeInfoTable[8'hEF] = { 4'b1000, 6'b110011, rmwAbs , aluInT , aluIsc }; // EF iISC abs
+ assign opcodeInfoTable[8'hF0] = { 4'b0000, 6'b000000, relative , aluInXXX , aluXXX }; // F0 BEQ
+ assign opcodeInfoTable[8'hF1] = { 4'b1000, 6'b110011, readIndY , aluInT , aluSbc }; // F1 SBC (zp),y
+ assign opcodeInfoTable[8'hF2] = { 4'bxxxx, 6'bxxxxxx, xxxxxxxx , aluInXXX , aluXXX }; // F2 *** JAM ***
+ assign opcodeInfoTable[8'hF3] = { 4'b1000, 6'b110011, rmwIndY , aluInT , aluIsc }; // F3 iISC (zp),y
+ assign opcodeInfoTable[8'hF4] = { 4'b0000, 6'b000000, readZpX , aluInXXX , aluXXX }; // F4 iNOP zp,x
+ assign opcodeInfoTable[8'hF5] = { 4'b1000, 6'b110011, readZpX , aluInT , aluSbc }; // F5 SBC zp,x
+ assign opcodeInfoTable[8'hF6] = { 4'b0000, 6'b100010, rmwZpX , aluInT , aluInc }; // F6 INC zp,x
+ assign opcodeInfoTable[8'hF7] = { 4'b1000, 6'b110011, rmwZpX , aluInT , aluIsc }; // F7 iISC zp,x
+ assign opcodeInfoTable[8'hF8] = { 4'b0000, 6'b001000, implied , aluInSet , aluXXX }; // F8 SED
+ assign opcodeInfoTable[8'hF9] = { 4'b1000, 6'b110011, readAbsY , aluInT , aluSbc }; // F9 SBC abs,y
+ assign opcodeInfoTable[8'hFA] = { 4'b0000, 6'b000000, implied , aluInXXX , aluXXX }; // FA iNOP implied
+ assign opcodeInfoTable[8'hFB] = { 4'b1000, 6'b110011, rmwAbsY , aluInT , aluIsc }; // FB iISC abs,y
+ assign opcodeInfoTable[8'hFC] = { 4'b0000, 6'b000000, readAbsX , aluInXXX , aluXXX }; // FC iNOP abs,x
+ assign opcodeInfoTable[8'hFD] = { 4'b1000, 6'b110011, readAbsX , aluInT , aluSbc }; // FD SBC abs,x
+ assign opcodeInfoTable[8'hFE] = { 4'b0000, 6'b100010, rmwAbsX , aluInT , aluInc }; // FE INC abs,x
+ assign opcodeInfoTable[8'hFF] = { 4'b1000, 6'b110011, rmwAbsX , aluInT , aluIsc }; // FF iISC abs,x
+
+ reg [43:0] opcInfo;
+ wire [43:0] nextOpcInfo; // Next opcode (decoded)
+ reg [43:0] nextOpcInfoReg; // Next opcode (decoded) pipelined
+ reg [ 7:0] theOpcode;
+ reg [ 7:0] nextOpcode;
+
+ reg [15:0] PC; // Program counter
+
+// Address generation
+// type nextAddrDef is
+localparam [3:0]
+ nextAddrHold = 4'b0000,
+ nextAddrIncr = 4'b0001,
+ nextAddrIncrL = 4'b0010, // Increment low bits only (zeropage accesses)
+ nextAddrIncrH = 4'b0011, // Increment high bits only (page-boundary)
+ nextAddrDecrH = 4'b0100, // Decrement high bits (branch backwards)
+ nextAddrPc = 4'b0101,
+ nextAddrIrq = 4'b0110,
+ nextAddrReset = 4'b0111,
+ nextAddrAbs = 4'b1000,
+ nextAddrAbsIndexed = 4'b1001,
+ nextAddrZeroPage = 4'b1010,
+ nextAddrZPIndexed = 4'b1011,
+ nextAddrStack = 4'b1100,
+ nextAddrRelative = 4'b1101;
+
+ reg [3:0] nextAddr;
+ reg [15:0] myAddr;
+ wire [15:0] myAddrIncr;
+ wire [7:0] myAddrIncrH;
+ wire [7:0] myAddrDecrH;
+ reg theWe;
+
+ reg irqActive;
+
+ // Output register
+ reg [7:0] doReg;
+
+ // Buffer register
+ reg [7:0] T;
+
+ // General registers
+ reg [7:0] A; // Accumulator
+ reg [7:0] X; // Index X
+ reg [7:0] Y; // Index Y
+ reg [7:0] S; // stack pointer
+
+ // Status register
+ reg C; // Carry
+ reg Z; // Zero flag
+ reg I; // Interrupt flag
+ reg D; // Decimal mode
+ reg V; // Overflow
+ reg N; // Negative
+
+ // ALU
+ // ALU input
+ wire [7:0] aluInput;
+ wire [7:0] aluCmpInput;
+ // ALU output
+ wire [7:0] aluRegisterOut;
+ wire [7:0] aluRmwOut;
+ wire aluC;
+ wire aluZ;
+ wire aluV;
+ wire aluN;
+ // Pipeline registers
+ reg [7:0] aluInputReg;
+ reg [7:0] aluCmpInputReg;
+ reg [7:0] aluRmwReg;
+ reg [7:0] aluNineReg;
+ reg aluCReg;
+ reg aluZReg;
+ reg aluVReg;
+ reg aluNReg;
+
+ // Indexing
+ reg [8:0] indexOut;
+
+ // Internals
+ wire [7:0] aluTemp;
+ wire [7:0] aluTemp0;
+ wire [7:0] aluTemp1;
+ wire [7:0] aluTemp2;
+ wire [7:0] aluTemp3;
+ wire [7:0] aluTemp4;
+ wire [7:0] aluTemp5;
+ wire [7:0] aluTemp6;
+
+ wire [7:0] cmpTemp;
+ wire [7:0] cmpTemp0;
+ wire [7:0] cmpTemp1;
+ wire [7:0] cmpTemp2;
+
+ wire [5:0] lowBits;
+
+ wire [8:0] nineBits;
+ wire [8:0] nineBits0;
+ wire [8:0] nineBits1;
+
+ wire [8:0] rmwBits;
+
+ wire varC;
+ wire varC0;
+
+ wire varZ;
+
+ wire varV;
+ wire varV0;
+ wire varV1;
+
+ wire varN;
+
+ wire [3:0] aluMode1;
+ wire [2:0] aluMode2;
+
+ wire [7:0] myNextOpcode;
+
+ reg [7:0] sIncDec;
+ reg updateFlag;
+
+ // processAluInput
+ assign aluTemp0 = 8'hFF;
+ assign aluTemp1 = opcInfo[`opcInA] ? (aluTemp0 & A) : aluTemp0;
+ assign aluTemp2 = opcInfo[`opcInE] ? (aluTemp1 & (A | 8'hEE)) : aluTemp1;
+ assign aluTemp3 = opcInfo[`opcInX] ? (aluTemp2 & X) : aluTemp2;
+ assign aluTemp4 = opcInfo[`opcInY] ? (aluTemp3 & Y) : aluTemp3;
+ assign aluTemp5 = opcInfo[`opcInS] ? (aluTemp4 & S) : aluTemp4;
+ assign aluTemp6 = opcInfo[`opcInT] ? (aluTemp5 & T) : aluTemp5;
+ assign aluTemp = opcInfo[`opcInClear] ? 8'h00 : aluTemp6;
+ always @(posedge clk)
+ begin
+ aluInputReg <= aluTemp;
+ end
+ assign aluInput = pipelineAluMux ? aluInputReg : aluTemp;
+
+ // processCmpInput
+ assign cmpTemp0 = 8'hFF;
+ assign cmpTemp1 = opcInfo[`opcInCmp] ? (cmpTemp0 & A) : cmpTemp0;
+ assign cmpTemp2 = opcInfo[`opcInCpx] ? (cmpTemp1 & X) : cmpTemp1;
+ assign cmpTemp = opcInfo[`opcInCpy] ? (cmpTemp2 & Y) : cmpTemp2;
+ always @(posedge clk)
+ begin
+ aluCmpInputReg <= cmpTemp;
+ end
+ assign aluCmpInput = pipelineAluMux ? aluCmpInputReg : cmpTemp;
+
+ // processAlu
+ assign varV0 = aluInput[6];
+
+ assign aluMode1 = opcInfo[`aluMode1From:`aluMode1To];
+ assign rmwBits = (aluMode1 == aluModeInp) ? {C, aluInput} :
+ (aluMode1 == aluModeP ) ? {C, N, V, 1'b1, ~irqActive, D, I, Z, C} :
+ (aluMode1 == aluModeInc) ? {C, aluInput + 8'd1} :
+ (aluMode1 == aluModeDec) ? {C, aluInput - 8'd1} :
+ (aluMode1 == aluModeAsl) ? {aluInput, 1'b0} :
+ (aluMode1 == aluModeFlg) ? {aluInput[0], aluInput} :
+ (aluMode1 == aluModeLsr) ? {aluInput[0], 1'b0, aluInput[7:1]} :
+ (aluMode1 == aluModeRol) ? {aluInput, C} :
+ (aluMode1 == aluModeRor) ? {aluInput[0], C, aluInput[7:1]} :
+ (aluMode1 == aluModeAnc) ? {aluInput[7] & A[7], aluInput} :
+ {C, aluInput};
+
+ assign aluMode2 = opcInfo[`aluMode2From:`aluMode2To];
+ assign lowBits = (aluMode2 == aluModeAdc) ? {1'b0, A[3:0], rmwBits[8]} + {1'b0, rmwBits[3:0], 1'b1} :
+ (aluMode2 == aluModeSbc) ? {1'b0, A[3:0], rmwBits[8]} + {1'b0, ~rmwBits[3:0], 1'b1} :
+ {6'b111111};
+
+ assign nineBits0 = (aluMode2 == aluModeAdc) ? {1'b0, A} + {1'b0, rmwBits[7:0]} + {8'b00000000, rmwBits[8]} :
+ (aluMode2 == aluModeSbc) ? {1'b0, A} + {1'b0, ~rmwBits[7:0]} + {8'b00000000, rmwBits[8]} :
+ (aluMode2 == aluModeCmp) ? {1'b0, aluCmpInput} + {1'b0, ~rmwBits[7:0]} + 9'd1 :
+ (aluMode2 == aluModeAnd) ? {rmwBits[8], A & rmwBits[7:0]} :
+ (aluMode2 == aluModeEor) ? {rmwBits[8], A ^ rmwBits[7:0]} :
+ (aluMode2 == aluModeOra) ? {rmwBits[8], A | rmwBits[7:0]} :
+ rmwBits;
+
+ assign varZ = (aluMode1 == aluModeFlg) ? rmwBits[1] :
+ (nineBits0[7:0] == 8'd0) ? 1'b1 :
+ 1'b0;
+
+ assign nineBits1[3:0] = (aluMode2 == aluModeAdc) & D & (lowBits[5:1] > 5'd9)
+ ? nineBits0[3:0] + 4'd6 : nineBits0[3:0];
+ assign nineBits1[8:4] = (aluMode2 == aluModeAdc) & D & (lowBits[5:1] > 5'd9)
+ & ~lowBits[5]
+ ? nineBits0[8:4] + 5'd1 : nineBits0[8:4];
+
+ assign varN = (aluMode1 == aluModeBit) || (aluMode1 == aluModeFlg) ? rmwBits[7] : nineBits1[7];
+
+ assign varC0 = (aluMode2 == aluModeArr) ? aluInput[7] : nineBits1[8];
+
+ assign varV1 = (aluMode2 == aluModeArr) ? aluInput[7] ^ aluInput[6] : varV0;
+
+ assign varV = (aluMode2 == aluModeAdc) ? (A[7] ^ nineBits1[7]) & (rmwBits[7] ^ nineBits1[7]) :
+ (aluMode2 == aluModeSbc) ? (A[7] ^ nineBits1[7]) & (~rmwBits[7] ^ nineBits1[7]) :
+ varV1;
+
+ assign nineBits[8:4] = (aluMode2 == aluModeAdc) & D & (nineBits1[8:4] > 5'd9) ? nineBits1[8:4] + 5'd6 :
+ (aluMode2 == aluModeSbc) & D & ~nineBits1[8] ? nineBits1[8:4] - 5'd6 :
+ (aluMode2 == aluModeArr) & D & (({1'b0, aluInput[7:4]} + {4'd0, aluInput[4]}) > 5'd5) ? nineBits1[8:4] + 5'd6 :
+ nineBits1[8:4];
+
+ assign nineBits[3:0] = (aluMode2 == aluModeSbc) & D & ~lowBits[5] ? nineBits1[3:0] - 4'd6 :
+ (aluMode2 == aluModeArr) & D & (({1'b0, aluInput[3:0]} + {4'd0, aluInput[0]}) > 5'd5) ? nineBits1[3:0] + 4'd6 :
+ nineBits1[3:0];
+
+ assign varC = (aluMode2 == aluModeAdc) & D & (nineBits1[8:4] > 5'd9) ? 1'b1 :
+ (aluMode2 == aluModeArr) & D & (({1'b0, aluInput[7:4]} + {4'd0, aluInput[4]}) > 5'd5) ? 1'b1 :
+ (aluMode2 == aluModeArr) & D ? 1'b0 :
+ varC0;
+
+ always @(posedge clk)
+ begin
+ aluRmwReg <= rmwBits[7:0];
+ aluNineReg <= nineBits[7:0];
+ aluCReg <= varC;
+ aluZReg <= varZ;
+ aluVReg <= varV;
+ aluNReg <= varN;
+ end
+
+ assign aluRmwOut = pipelineAluOut ? aluRmwReg : rmwBits[7:0];
+ assign aluRegisterOut = pipelineAluOut ? aluNineReg : nineBits[7:0];
+ assign aluC = pipelineAluOut ? aluCReg : varC;
+ assign aluZ = pipelineAluOut ? aluZReg : varZ;
+ assign aluV = pipelineAluOut ? aluVReg : varV;
+ assign aluN = pipelineAluOut ? aluNReg : varN;
+
+ // calcInterrupt: process(clk)
+ always @(posedge clk)
+ begin
+ if (enable) begin
+ if ((theCpuCycle == cycleStack4) || reset) begin
+ nmiReg <= 1'b1;
+ end
+
+ if ((nextCpuCycle != cycleBranchTaken) && (nextCpuCycle != opcodeFetch)) begin
+ irqReg <= irq_n;
+ nmiEdge <= nmi_n;
+ if (nmiEdge && !nmi_n) begin
+ nmiReg <= 1'b0;
+ end
+ end
+ // The 'or opcInfo(opcSetI)' prevents NMI immediately after BRK or IRQ.
+ // Presumably this is done in the real 6502/6510 to prevent a double IRQ.
+ processIrq <= !((nmiReg && (irqReg || I)) || opcInfo[`opcIRQ]);
+ end
+ end
+
+ // calcNextOpcode: process(clk, di, reset, processIrq)
+ assign myNextOpcode = reset ? 8'h4C :
+ processIrq ? 8'h00 :
+ din;
+
+ assign nextOpcode = myNextOpcode;
+
+ assign nextOpcInfo = opcodeInfoTable[nextOpcode];
+ always @(posedge clk)
+ begin
+ nextOpcInfoReg <= nextOpcInfo;
+ end
+
+ // Read bits and flags from opcodeInfoTable and store in opcInfo.
+ // This info is used to control the execution of the opcode.
+ // calcOpcInfo: process(clk)
+ always @(posedge clk)
+ begin
+ if (enable) begin
+ if (reset || (theCpuCycle == opcodeFetch)) begin
+ opcInfo <= nextOpcInfo;
+ if (pipelineOpcode) begin
+ opcInfo <= nextOpcInfoReg;
+ end
+ end
+ end
+ end
+
+ // calcTheOpcode: process(clk)
+ always @(posedge clk)
+ begin
+ if (enable) begin
+ if (theCpuCycle == opcodeFetch) begin
+ irqActive <= 1'b0;
+ if (processIrq) begin
+ irqActive <= 1'b1;
+ end
+ // Fetch opcode
+ theOpcode <= nextOpcode;
+ end
+ end
+ end
+
+ // -----------------------------------------------------------------------
+ // State machine
+ // -----------------------------------------------------------------------
+ // process(enable, theCpuCycle, opcInfo)
+ always @(enable or theCpuCycle or opcInfo)
+ begin
+ updateRegisters = 1'b0;
+ if (enable) begin
+ if (opcInfo[`opcRti]) begin
+ if (theCpuCycle == cycleRead) begin
+ updateRegisters = 1'b1;
+ end
+ end else if (theCpuCycle == opcodeFetch) begin
+ updateRegisters = 1'b1;
+ end
+ end
+ end
+
+ assign debugOpcode = theOpcode;
+
+ // process(clk)
+ always @(posedge clk)
+ begin
+ if (enable) begin
+ theCpuCycle <= nextCpuCycle;
+ end
+ if (reset) begin
+ theCpuCycle <= cycle2;
+ end
+ end
+
+ // Determine the next cpu cycle. After the last cycle we always
+ // go to opcodeFetch to get the next opcode.
+ // calcNextCpuCycle: process(theCpuCycle, opcInfo, theOpcode, indexOut, T, N, V, C, Z)
+ always @(theCpuCycle or opcInfo or theOpcode or indexOut or T or N or V or C or Z)
+ begin
+ nextCpuCycle = opcodeFetch;
+
+ case (theCpuCycle)
+ opcodeFetch : begin
+ nextCpuCycle = cycle2;
+ end
+ cycle2 : begin
+ if (opcInfo[`opcBranch]) begin
+ if ( ((N == theOpcode[5]) && (theOpcode[7:6] == 2'b00))
+ || ((V == theOpcode[5]) && (theOpcode[7:6] == 2'b01))
+ || ((C == theOpcode[5]) && (theOpcode[7:6] == 2'b10))
+ || ((Z == theOpcode[5]) && (theOpcode[7:6] == 2'b11)) ) begin
+ // Branch condition is true
+ nextCpuCycle = cycleBranchTaken;
+ end
+ end else if (opcInfo[`opcStackUp]) begin
+ nextCpuCycle = cycleStack1;
+ end else if (opcInfo[`opcStackAddr] && opcInfo[`opcStackData]) begin
+ nextCpuCycle = cycleStack2;
+ end else if (opcInfo[`opcStackAddr]) begin
+ nextCpuCycle = cycleStack1;
+ end else if (opcInfo[`opcStackData]) begin
+ nextCpuCycle = cycleWrite;
+ end else if (opcInfo[`opcAbsolute]) begin
+ nextCpuCycle = cycle3;
+ end else if (opcInfo[`opcIndirect]) begin
+ if (opcInfo[`indexX]) begin
+ nextCpuCycle = cyclePreIndirect;
+ end else begin
+ nextCpuCycle = cycleIndirect;
+ end
+ end else if (opcInfo[`opcZeroPage]) begin
+ if (opcInfo[`opcWrite]) begin
+ if (opcInfo[`indexX] || opcInfo[`indexY]) begin
+ nextCpuCycle = cyclePreWrite;
+ end else begin
+ nextCpuCycle = cycleWrite;
+ end
+ end else begin
+ if (opcInfo[`indexX] || opcInfo[`indexY]) begin
+ nextCpuCycle = cyclePreRead;
+ end else begin
+ nextCpuCycle = cycleRead2;
+ end
+ end
+ end else if (opcInfo[`opcJump]) begin
+ nextCpuCycle = cycleJump;
+ end
+ end
+ cycle3 : begin
+ nextCpuCycle = cycleRead;
+ if (opcInfo[`opcWrite]) begin
+ if (opcInfo[`indexX] || opcInfo[`indexY]) begin
+ nextCpuCycle = cyclePreWrite;
+ end else begin
+ nextCpuCycle = cycleWrite;
+ end
+ end
+ if (opcInfo[`opcIndirect] && opcInfo[`indexX]) begin
+ if (opcInfo[`opcWrite]) begin
+ nextCpuCycle = cycleWrite;
+ end else begin
+ nextCpuCycle = cycleRead2;
+ end
+ end
+ end
+ cyclePreIndirect : begin
+ nextCpuCycle = cycleIndirect;
+ end
+ cycleIndirect : begin
+ nextCpuCycle = cycle3;
+ end
+ cycleBranchTaken : begin
+ if (indexOut[8] != T[7]) begin
+ // Page boundary crossing during branch.
+ nextCpuCycle = cycleBranchPage;
+ end
+ end
+ cyclePreRead : begin
+ if (opcInfo[`opcZeroPage]) begin
+ nextCpuCycle = cycleRead2;
+ end
+ end
+ cycleRead : begin
+ if (opcInfo[`opcJump]) begin
+ nextCpuCycle = cycleJump;
+ end else if (indexOut[8]) begin
+ // Page boundary crossing while indexed addressing.
+ nextCpuCycle = cycleRead2;
+ end else if (opcInfo[`opcRmw]) begin
+ nextCpuCycle = cycleRmw;
+ if (opcInfo[`indexX] || opcInfo[`indexY]) begin
+ // 6510 needs extra cycle for indexed addressing
+ // combined with RMW indexing
+ nextCpuCycle = cycleRead2;
+ end
+ end
+ end
+ cycleRead2 : begin
+ if (opcInfo[`opcRmw]) begin
+ nextCpuCycle = cycleRmw;
+ end
+ end
+ cycleRmw : begin
+ nextCpuCycle = cycleWrite;
+ end
+ cyclePreWrite : begin
+ nextCpuCycle = cycleWrite;
+ end
+ cycleStack1 : begin
+ nextCpuCycle = cycleRead;
+ if (opcInfo[`opcStackAddr]) begin
+ nextCpuCycle = cycleStack2;
+ end
+ end
+ cycleStack2 : begin
+ nextCpuCycle = cycleStack3;
+ if (opcInfo[`opcRti]) begin
+ nextCpuCycle = cycleRead;
+ end
+ if (!opcInfo[`opcStackData] && opcInfo[`opcStackUp]) begin
+ nextCpuCycle = cycleJump;
+ end
+ end
+ cycleStack3 : begin
+ nextCpuCycle = cycleRead;
+ if (!opcInfo[`opcStackData] || opcInfo[`opcStackUp]) begin
+ nextCpuCycle = cycleJump;
+ end else if (opcInfo[`opcStackAddr]) begin
+ nextCpuCycle = cycleStack4;
+ end
+ end
+ cycleStack4 : begin
+ nextCpuCycle = cycleRead;
+ end
+ cycleJump : begin
+ if (opcInfo[`opcIncrAfter]) begin
+ // Insert extra cycle
+ nextCpuCycle = cycleEnd;
+ end
+ end
+ default : begin
+ end
+ endcase
+ end
+
+ // -----------------------------------------------------------------------
+ // T register
+ // -----------------------------------------------------------------------
+ // calcT: process(clk)
+ always @(posedge clk)
+ begin
+ if (enable) begin
+ case (theCpuCycle)
+ cycle2 : begin
+ T <= din;
+ end
+ cycleStack1, cycleStack2 : begin
+ if (opcInfo[`opcStackUp]) begin
+ // Read from stack
+ T <= din;
+ end
+ end
+ cycleIndirect, cycleRead, cycleRead2 : begin
+ T <= din;
+ end
+ default : begin
+ end
+ endcase
+ end
+ end
+
+ // -----------------------------------------------------------------------
+ // A register
+ // -----------------------------------------------------------------------
+ always @(posedge clk)
+ begin
+ if (updateRegisters) begin
+ if (opcInfo[`opcUpdateA]) begin
+ A <= aluRegisterOut;
+ end
+ end
+ end
+
+ // -----------------------------------------------------------------------
+ // X register
+ // -----------------------------------------------------------------------
+ always @(posedge clk)
+ begin
+ if (updateRegisters) begin
+ if (opcInfo[`opcUpdateX]) begin
+ X <= aluRegisterOut;
+ end
+ end
+ end
+
+ // -----------------------------------------------------------------------
+ // Y register
+ // -----------------------------------------------------------------------
+ always @(posedge clk)
+ begin
+ if (updateRegisters) begin
+ if (opcInfo[`opcUpdateY]) begin
+ Y <= aluRegisterOut;
+ end
+ end
+ end
+
+ // -----------------------------------------------------------------------
+ // C flag
+ // -----------------------------------------------------------------------
+ always @(posedge clk)
+ begin
+ if (updateRegisters) begin
+ if (opcInfo[`opcUpdateC]) begin
+ C <= aluC;
+ end
+ end
+ end
+
+ // -----------------------------------------------------------------------
+ // Z flag
+ // -----------------------------------------------------------------------
+ always @(posedge clk)
+ begin
+ if (updateRegisters) begin
+ if (opcInfo[`opcUpdateZ]) begin
+ Z <= aluZ;
+ end
+ end
+ end
+
+ // -----------------------------------------------------------------------
+ // I flag
+ // -----------------------------------------------------------------------
+ always @(posedge clk)
+ begin
+ if (updateRegisters) begin
+ if (opcInfo[`opcUpdateI]) begin
+ I <= aluInput[2];
+ end
+ end
+ end
+
+ // -----------------------------------------------------------------------
+ // D flag
+ // -----------------------------------------------------------------------
+ always @(posedge clk)
+ begin
+ if (updateRegisters) begin
+ if (opcInfo[`opcUpdateD]) begin
+ D <= aluInput[3];
+ end
+ end
+ end
+
+ // -----------------------------------------------------------------------
+ // V flag
+ // -----------------------------------------------------------------------
+ always @(posedge clk)
+ begin
+ if (updateRegisters) begin
+ if (opcInfo[`opcUpdateV]) begin
+ V <= aluV;
+ end
+ end
+ if (enable) begin
+ if (soReg && !so_n) begin
+ V <= 1'b1;
+ end
+ soReg <= so_n;
+ end
+ end
+
+
+ // -----------------------------------------------------------------------
+ // N flag
+ // -----------------------------------------------------------------------
+ always @(posedge clk)
+ begin
+ if (updateRegisters) begin
+ if (opcInfo[`opcUpdateN]) begin
+ N <= aluN;
+ end
+ end
+ end
+
+ // -----------------------------------------------------------------------
+ // Stack pointer
+ // -----------------------------------------------------------------------
+ always @(nextCpuCycle or opcInfo)
+ begin
+ if (opcInfo[`opcStackUp]) begin
+ sIncDec = S + 1;
+ end else begin
+ sIncDec = S - 1;
+ end
+
+ updateFlag = 1'b0;
+
+ case (nextCpuCycle)
+ cycleStack1 : begin
+ if (opcInfo[`opcStackUp] || opcInfo[`opcStackData]) begin
+ updateFlag = 1'b1;
+ end
+ end
+ cycleStack2, cycleStack3, cycleStack4 : begin
+ updateFlag = 1'b1;
+ end
+ cycleRead : begin
+ if (opcInfo[`opcRti]) begin
+ updateFlag = 1'b1;
+ end
+ end
+ cycleWrite : begin
+ if (opcInfo[`opcStackData]) begin
+ updateFlag = 1'b1;
+ end
+ end
+ default : begin
+ end
+ endcase
+ end
+
+ always @(posedge clk)
+ begin
+ if (enable) begin
+ if (updateFlag) begin
+ S <= sIncDec;
+ end
+ end
+ if (updateRegisters) begin
+ if (opcInfo[`opcUpdateS]) begin
+ S <= aluRegisterOut;
+ end
+ end
+ end
+
+ // -----------------------------------------------------------------------
+ // Data out
+ // -----------------------------------------------------------------------
+ // calcDo: process(clk)
+ always @(posedge clk)
+ begin
+ if (enable) begin
+ doReg <= aluRmwOut;
+ if (opcInfo[`opcInH]) begin
+ // For illegal opcodes SHA, SHX, SHY, SHS
+ doReg <= aluRmwOut & myAddrIncrH;
+ end
+
+ case (nextCpuCycle)
+ cycleStack2 : begin
+ if (opcInfo[`opcIRQ] && !irqActive) begin
+ doReg <= myAddrIncr[15:8];
+ end else begin
+ doReg <= PC[15:8];
+ end
+ end
+ cycleStack3 : begin
+ doReg <= PC[7:0];
+ end
+ cycleRmw : begin
+ doReg <= din; // Read-modify-write write old value first.
+ end
+ default : begin
+ end
+ endcase
+ end
+ end
+ assign dout = doReg;
+
+ // -----------------------------------------------------------------------
+ // Write enable
+ // -----------------------------------------------------------------------
+ // calcWe: process(clk)
+ always @(posedge clk)
+ begin
+ if (enable) begin
+ theWe <= 1'b0;
+ case (nextCpuCycle)
+ cycleStack1 : begin
+ if (!opcInfo[`opcStackUp]
+ && (!opcInfo[`opcStackAddr] || opcInfo[`opcStackData])) begin
+ theWe <= 1'b1;
+ end
+ end
+ cycleStack2, cycleStack3, cycleStack4 : begin
+ if (!opcInfo[`opcStackUp]) begin
+ theWe <= 1'b1;
+ end
+ end
+ cycleRmw, cycleWrite : begin
+ theWe <= 1'b1;
+ end
+ default : begin
+ end
+ endcase
+ end
+ end
+ assign we = theWe;
+
+ // -----------------------------------------------------------------------
+ // Program counter
+ // -----------------------------------------------------------------------
+ // calcPC: process(clk)
+ always @(posedge clk)
+ begin
+ if (enable) begin
+ case (theCpuCycle)
+ opcodeFetch : begin
+ PC <= myAddr;
+ end
+ cycle2 : begin
+ if (!irqActive) begin
+ if (opcInfo[`opcSecondByte]) begin
+ PC <= myAddrIncr;
+ end else begin
+ PC <= myAddr;
+ end
+ end
+ end
+ cycle3 : begin
+ if (opcInfo[`opcAbsolute]) begin
+ PC <= myAddrIncr;
+ end
+ end
+ default: begin
+ end
+ endcase
+ end
+ end
+ assign debugPc = PC;
+
+ // -----------------------------------------------------------------------
+ // Address generation
+ // -----------------------------------------------------------------------
+ // calcNextAddr: process(theCpuCycle, opcInfo, indexOut, T, reset)
+ always @(theCpuCycle or opcInfo or indexOut or reset)
+ begin
+ nextAddr = nextAddrIncr;
+ case (theCpuCycle)
+ cycle2 : begin
+ if (opcInfo[`opcStackAddr] || opcInfo[`opcStackData]) begin
+ nextAddr = nextAddrStack;
+ end else if (opcInfo[`opcAbsolute]) begin
+ nextAddr = nextAddrIncr;
+ end else if (opcInfo[`opcZeroPage]) begin
+ nextAddr = nextAddrZeroPage;
+ end else if (opcInfo[`opcIndirect]) begin
+ nextAddr = nextAddrZeroPage;
+ end else if (opcInfo[`opcSecondByte]) begin
+ nextAddr = nextAddrIncr;
+ end else begin
+ nextAddr = nextAddrHold;
+ end
+ end
+ cycle3 : begin
+ if (opcInfo[`opcIndirect] && opcInfo[`indexX]) begin
+ nextAddr = nextAddrAbs;
+ end else begin
+ nextAddr = nextAddrAbsIndexed;
+ end
+ end
+ cyclePreIndirect : begin
+ nextAddr = nextAddrZPIndexed;
+ end
+ cycleIndirect : begin
+ nextAddr = nextAddrIncrL;
+ end
+ cycleBranchTaken : begin
+ nextAddr = nextAddrRelative;
+ end
+ cycleBranchPage : begin
+ if (!T[7]) begin
+ nextAddr = nextAddrIncrH;
+ end else begin
+ nextAddr = nextAddrDecrH;
+ end
+ end
+ cyclePreRead : begin
+ nextAddr = nextAddrZPIndexed;
+ end
+ cycleRead : begin
+ nextAddr = nextAddrPc;
+ if (opcInfo[`opcJump]) begin
+ // Emulate 6510 bug, jmp(xxFF) fetches from same page.
+ // Replace with nextAddrIncr if emulating 65C02 or later cpu.
+ nextAddr = nextAddrIncrL;
+ end else if (indexOut[8]) begin
+ nextAddr = nextAddrIncrH;
+ end else if (opcInfo[`opcRmw]) begin
+ nextAddr = nextAddrHold;
+ end
+ end
+ cycleRead2 : begin
+ nextAddr = nextAddrPc;
+ if (opcInfo[`opcRmw]) begin
+ nextAddr = nextAddrHold;
+ end
+ end
+ cycleRmw : begin
+ nextAddr = nextAddrHold;
+ end
+ cyclePreWrite : begin
+ nextAddr = nextAddrHold;
+ if (opcInfo[`opcZeroPage]) begin
+ nextAddr = nextAddrZPIndexed;
+ end else if (indexOut[8]) begin
+ nextAddr = nextAddrIncrH;
+ end
+ end
+ cycleWrite : begin
+ nextAddr = nextAddrPc;
+ end
+ cycleStack1, cycleStack2 : begin
+ nextAddr = nextAddrStack;
+ end
+ cycleStack3 : begin
+ nextAddr = nextAddrStack;
+ if (!opcInfo[`opcStackData]) begin
+ nextAddr = nextAddrPc;
+ end
+ end
+ cycleStack4 : begin
+ nextAddr = nextAddrIrq;
+ end
+ cycleJump : begin
+ nextAddr = nextAddrAbs;
+ end
+ default : begin
+ end
+ endcase
+ if (reset) begin
+ nextAddr = nextAddrReset;
+ end
+ end
+
+ // indexAlu: process(opcInfo, myAddr, T, X, Y)
+ always @(opcInfo or myAddr or T or X or Y)
+ begin
+ if (opcInfo[`indexX]) begin
+ indexOut = {1'b0, T} + {1'b0, X};
+ end else if (opcInfo[`indexY]) begin
+ indexOut = {1'b0, T} + {1'b0, Y};
+ end else if (opcInfo[`opcBranch]) begin
+ indexOut = {1'b0, T} + {1'b0, myAddr[7:0]};
+ end else begin
+ indexOut = {1'b0, T};
+ end
+ end
+
+ // calcAddr: process(clk)
+ always @(posedge clk)
+ begin
+ if (enable) begin
+ case (nextAddr)
+ nextAddrIncr : begin
+ myAddr <= myAddrIncr;
+ end
+ nextAddrIncrL : begin
+ myAddr[7:0] <= myAddrIncr[7:0];
+ end
+ nextAddrIncrH : begin
+ myAddr[15:8] <= myAddrIncrH;
+ end
+ nextAddrDecrH : begin
+ myAddr[15:8] <= myAddrDecrH;
+ end
+ nextAddrPc : begin
+ myAddr <= PC;
+ end
+ nextAddrIrq : begin
+ myAddr <= 16'hFFFE;
+ if (!nmiReg) begin
+ myAddr <= 16'hFFFA;
+ end
+ end
+ nextAddrReset : begin
+ myAddr <= 16'hFFFC;
+ end
+ nextAddrAbs : begin
+ myAddr <= {din, T};
+ end
+ nextAddrAbsIndexed : begin
+ myAddr <= {din, indexOut[7:0]};
+ end
+ nextAddrZeroPage : begin
+ myAddr <= {8'd0, din};
+ end
+ nextAddrZPIndexed : begin
+ myAddr <= {8'd0, indexOut[7:0]};
+ end
+ nextAddrStack : begin
+ myAddr <= {8'd1, S};
+ end
+ nextAddrRelative : begin
+ myAddr[7:0] <= indexOut[7:0];
+ end
+ default : begin
+ end
+ endcase
+ end
+ end
+
+ assign myAddrIncr = myAddr + 1'b1;
+ assign myAddrIncrH = myAddr[15:8] + 1'b1;
+ assign myAddrDecrH = myAddr[15:8] - 1'b1;
+
+ assign addr = myAddr;
+
+ assign debugA = A;
+ assign debugX = X;
+ assign debugY = Y;
+ assign debugS = S;
+
+endmodule
diff --git a/common/CPU/syntiac6502_6510/cpu65xx_e.vhd b/common/CPU/syntiac6502_6510/cpu65xx_e.vhd
new file mode 100644
index 00000000..27166e7a
--- /dev/null
+++ b/common/CPU/syntiac6502_6510/cpu65xx_e.vhd
@@ -0,0 +1,49 @@
+-- -----------------------------------------------------------------------
+--
+-- FPGA 64
+--
+-- A fully functional commodore 64 implementation in a single FPGA
+--
+-- -----------------------------------------------------------------------
+-- Copyright 2005-2008 by Peter Wendrich (pwsoft@syntiac.com)
+-- http://www.syntiac.com/fpga64.html
+-- -----------------------------------------------------------------------
+--
+-- Interface to 6502/6510 core
+--
+-- -----------------------------------------------------------------------
+
+library IEEE;
+use ieee.std_logic_1164.ALL;
+use ieee.numeric_std.ALL;
+
+-- -----------------------------------------------------------------------
+
+entity cpu65xx is
+ generic (
+ pipelineOpcode : boolean;
+ pipelineAluMux : boolean;
+ pipelineAluOut : boolean
+ );
+ port (
+ clk : in std_logic;
+ enable : in std_logic;
+ reset : in std_logic;
+ nmi_n : in std_logic;
+ nmi_ack : out std_logic;
+ irq_n : in std_logic;
+ so_n : in std_logic := '1';
+
+ di : in unsigned(7 downto 0);
+ do : out unsigned(7 downto 0);
+ addr : out unsigned(15 downto 0);
+ we : out std_logic;
+
+ debugOpcode : out unsigned(7 downto 0);
+ debugPc : out unsigned(15 downto 0);
+ debugA : out unsigned(7 downto 0);
+ debugX : out unsigned(7 downto 0);
+ debugY : out unsigned(7 downto 0);
+ debugS : out unsigned(7 downto 0)
+ );
+end cpu65xx;
\ No newline at end of file
diff --git a/common/CPU/syntiac6502_6510/cpu65xx_fast.vhd b/common/CPU/syntiac6502_6510/cpu65xx_fast.vhd
new file mode 100644
index 00000000..a387b37d
--- /dev/null
+++ b/common/CPU/syntiac6502_6510/cpu65xx_fast.vhd
@@ -0,0 +1,1565 @@
+-- -----------------------------------------------------------------------
+--
+-- FPGA 64
+--
+-- A fully functional commodore 64 implementation in a single FPGA
+--
+-- -----------------------------------------------------------------------
+-- Copyright 2005-2008 by Peter Wendrich (pwsoft@syntiac.com)
+-- http://www.syntiac.com/fpga64.html
+-- -----------------------------------------------------------------------
+--
+-- Table driven, cycle exact 6502/6510 core
+--
+-- -----------------------------------------------------------------------
+
+library IEEE;
+use ieee.std_logic_1164.ALL;
+use ieee.std_logic_unsigned.ALL;
+use ieee.numeric_std.ALL;
+
+-- -----------------------------------------------------------------------
+
+-- Store Zp (3) => fetch, cycle2, cycleEnd
+-- Store Zp,x (4) => fetch, cycle2, preWrite, cycleEnd
+-- Read Zp,x (4) => fetch, cycle2, cycleRead, cycleRead2
+-- Rmw Zp,x (6) => fetch, cycle2, cycleRead, cycleRead2, cycleRmw, cycleEnd
+-- Store Abs (4) => fetch, cycle2, cycle3, cycleEnd
+-- Store Abs,x (5) => fetch, cycle2, cycle3, preWrite, cycleEnd
+-- Rts (6) => fetch, cycle2, cycle3, cycleRead, cycleJump, cycleIncrEnd
+-- Rti (6) => fetch, cycle2, stack1, stack2, stack3, cycleJump
+-- Jsr (6) => fetch, cycle2, .. cycle5, cycle6, cycleJump
+-- Jmp abs (-) => fetch, cycle2, .., cycleJump
+-- Jmp (ind) (-) => fetch, cycle2, .., cycleJump
+-- Brk / irq (6) => fetch, cycle2, stack2, stack3, stack4
+-- -----------------------------------------------------------------------
+
+architecture fast of cpu65xx is
+-- Statemachine
+ type cpuCycles is (
+ opcodeFetch, -- New opcode is read and registers updated
+ cycle2,
+ cycle3,
+ cyclePreIndirect,
+ cycleIndirect,
+ cycleBranchTaken,
+ cycleBranchPage,
+ cyclePreRead, -- Cycle before read while doing zeropage indexed addressing.
+ cycleRead, -- Read cycle
+ cycleRead2, -- Second read cycle after page-boundary crossing.
+ cycleRmw, -- Calculate ALU output for read-modify-write instr.
+ cyclePreWrite, -- Cycle before write when doing indexed addressing.
+ cycleWrite, -- Write cycle for zeropage or absolute addressing.
+ cycleStack1,
+ cycleStack2,
+ cycleStack3,
+ cycleStack4,
+ cycleJump, -- Last cycle of Jsr, Jmp. Next fetch address is target addr.
+ cycleEnd
+ );
+ signal theCpuCycle : cpuCycles;
+ signal nextCpuCycle : cpuCycles;
+ signal updateRegisters : boolean;
+ signal processIrq : std_logic;
+ signal nmiReg: std_logic;
+ signal nmiEdge: std_logic;
+ signal irqReg : std_logic; -- Delay IRQ input with one clock cycle.
+ signal soReg : std_logic; -- SO pin edge detection
+
+-- Opcode decoding
+ constant opcUpdateA : integer := 0;
+ constant opcUpdateX : integer := 1;
+ constant opcUpdateY : integer := 2;
+ constant opcUpdateS : integer := 3;
+ constant opcUpdateN : integer := 4;
+ constant opcUpdateV : integer := 5;
+ constant opcUpdateD : integer := 6;
+ constant opcUpdateI : integer := 7;
+ constant opcUpdateZ : integer := 8;
+ constant opcUpdateC : integer := 9;
+
+ constant opcSecondByte : integer := 10;
+ constant opcAbsolute : integer := 11;
+ constant opcZeroPage : integer := 12;
+ constant opcIndirect : integer := 13;
+ constant opcStackAddr : integer := 14; -- Push/Pop address
+ constant opcStackData : integer := 15; -- Push/Pop status/data
+ constant opcJump : integer := 16;
+ constant opcBranch : integer := 17;
+ constant indexX : integer := 18;
+ constant indexY : integer := 19;
+ constant opcStackUp : integer := 20;
+ constant opcWrite : integer := 21;
+ constant opcRmw : integer := 22;
+ constant opcIncrAfter : integer := 23; -- Insert extra cycle to increment PC (RTS)
+ constant opcRti : integer := 24;
+ constant opcIRQ : integer := 25;
+
+ constant opcInA : integer := 26;
+ constant opcInE : integer := 27;
+ constant opcInX : integer := 28;
+ constant opcInY : integer := 29;
+ constant opcInS : integer := 30;
+ constant opcInT : integer := 31;
+ constant opcInH : integer := 32;
+ constant opcInClear : integer := 33;
+ constant aluMode1From : integer := 34;
+ --
+ constant aluMode1To : integer := 37;
+ constant aluMode2From : integer := 38;
+ --
+ constant aluMode2To : integer := 40;
+ --
+ constant opcInCmp : integer := 41;
+ constant opcInCpx : integer := 42;
+ constant opcInCpy : integer := 43;
+
+
+ subtype addrDef is unsigned(0 to 15);
+ --
+ -- is Interrupt -----------------+
+ -- instruction is RTI ----------------+|
+ -- PC++ on last cycle (RTS) ---------------+||
+ -- RMW --------------+|||
+ -- Write -------------+||||
+ -- Pop/Stack up -------------+|||||
+ -- Branch ---------+ ||||||
+ -- Jump ----------+| ||||||
+ -- Push or Pop data -------+|| ||||||
+ -- Push or Pop addr ------+||| ||||||
+ -- Indirect -----+|||| ||||||
+ -- ZeroPage ----+||||| ||||||
+ -- Absolute ---+|||||| ||||||
+ -- PC++ on cycle2 --+||||||| ||||||
+ -- |AZI||JBXY|WM|||
+ constant immediate : addrDef := "1000000000000000";
+ constant implied : addrDef := "0000000000000000";
+ -- Zero page
+ constant readZp : addrDef := "1010000000000000";
+ constant writeZp : addrDef := "1010000000010000";
+ constant rmwZp : addrDef := "1010000000001000";
+ -- Zero page indexed
+ constant readZpX : addrDef := "1010000010000000";
+ constant writeZpX : addrDef := "1010000010010000";
+ constant rmwZpX : addrDef := "1010000010001000";
+ constant readZpY : addrDef := "1010000001000000";
+ constant writeZpY : addrDef := "1010000001010000";
+ constant rmwZpY : addrDef := "1010000001001000";
+ -- Zero page indirect
+ constant readIndX : addrDef := "1001000010000000";
+ constant writeIndX : addrDef := "1001000010010000";
+ constant rmwIndX : addrDef := "1001000010001000";
+ constant readIndY : addrDef := "1001000001000000";
+ constant writeIndY : addrDef := "1001000001010000";
+ constant rmwIndY : addrDef := "1001000001001000";
+ -- |AZI||JBXY|WM||
+ -- Absolute
+ constant readAbs : addrDef := "1100000000000000";
+ constant writeAbs : addrDef := "1100000000010000";
+ constant rmwAbs : addrDef := "1100000000001000";
+ constant readAbsX : addrDef := "1100000010000000";
+ constant writeAbsX : addrDef := "1100000010010000";
+ constant rmwAbsX : addrDef := "1100000010001000";
+ constant readAbsY : addrDef := "1100000001000000";
+ constant writeAbsY : addrDef := "1100000001010000";
+ constant rmwAbsY : addrDef := "1100000001001000";
+ -- PHA PHP
+ constant push : addrDef := "0000010000000000";
+ -- PLA PLP
+ constant pop : addrDef := "0000010000100000";
+ -- Jumps
+ constant jsr : addrDef := "1000101000000000";
+ constant jumpAbs : addrDef := "1000001000000000";
+ constant jumpInd : addrDef := "1100001000000000";
+ constant relative : addrDef := "1000000100000000";
+ -- Specials
+ constant rts : addrDef := "0000101000100100";
+ constant rti : addrDef := "0000111000100010";
+ constant brk : addrDef := "1000111000000001";
+-- constant : unsigned(0 to 0) := "0";
+ constant xxxxxxxx : addrDef := "----------0---00";
+
+ -- A = accu
+ -- E = Accu | 0xEE (for ANE, LXA)
+ -- X = index X
+ -- Y = index Y
+ -- S = Stack pointer
+ -- H = indexH
+ --
+ -- AEXYSTHc
+ constant aluInA : unsigned(0 to 7) := "10000000";
+ constant aluInE : unsigned(0 to 7) := "01000000";
+ constant aluInEXT : unsigned(0 to 7) := "01100100";
+ constant aluInET : unsigned(0 to 7) := "01000100";
+ constant aluInX : unsigned(0 to 7) := "00100000";
+ constant aluInXH : unsigned(0 to 7) := "00100010";
+ constant aluInY : unsigned(0 to 7) := "00010000";
+ constant aluInYH : unsigned(0 to 7) := "00010010";
+ constant aluInS : unsigned(0 to 7) := "00001000";
+ constant aluInT : unsigned(0 to 7) := "00000100";
+ constant aluInAX : unsigned(0 to 7) := "10100000";
+ constant aluInAXH : unsigned(0 to 7) := "10100010";
+ constant aluInAT : unsigned(0 to 7) := "10000100";
+ constant aluInXT : unsigned(0 to 7) := "00100100";
+ constant aluInST : unsigned(0 to 7) := "00001100";
+ constant aluInSet : unsigned(0 to 7) := "00000000";
+ constant aluInClr : unsigned(0 to 7) := "00000001";
+ constant aluInXXX : unsigned(0 to 7) := "--------";
+
+ -- Most of the aluModes are just like the opcodes.
+ -- aluModeInp -> input is output. calculate N and Z
+ -- aluModeCmp -> Compare for CMP, CPX, CPY
+ -- aluModeFlg -> input to flags needed for PLP, RTI and CLC, SEC, CLV
+ -- aluModeInc -> for INC but also INX, INY
+ -- aluModeDec -> for DEC but also DEX, DEY
+
+ subtype aluMode1 is unsigned(0 to 3);
+ subtype aluMode2 is unsigned(0 to 2);
+ subtype aluMode is unsigned(0 to 9);
+
+ -- Logic/Shift ALU
+ constant aluModeInp : aluMode1 := "0000";
+ constant aluModeP : aluMode1 := "0001";
+ constant aluModeInc : aluMode1 := "0010";
+ constant aluModeDec : aluMode1 := "0011";
+ constant aluModeFlg : aluMode1 := "0100";
+ constant aluModeBit : aluMode1 := "0101";
+ -- 0110
+ -- 0111
+ constant aluModeLsr : aluMode1 := "1000";
+ constant aluModeRor : aluMode1 := "1001";
+ constant aluModeAsl : aluMode1 := "1010";
+ constant aluModeRol : aluMode1 := "1011";
+ -- 1100
+ -- 1101
+ -- 1110
+ constant aluModeAnc : aluMode1 := "1111";
+
+ -- Arithmetic ALU
+ constant aluModePss : aluMode2 := "000";
+ constant aluModeCmp : aluMode2 := "001";
+ constant aluModeAdc : aluMode2 := "010";
+ constant aluModeSbc : aluMode2 := "011";
+ constant aluModeAnd : aluMode2 := "100";
+ constant aluModeOra : aluMode2 := "101";
+ constant aluModeEor : aluMode2 := "110";
+ constant aluModeArr : aluMode2 := "111";
+
+
+ constant aluInp : aluMode := aluModeInp & aluModePss & "---";
+ constant aluP : aluMode := aluModeP & aluModePss & "---";
+ constant aluInc : aluMode := aluModeInc & aluModePss & "---";
+ constant aluDec : aluMode := aluModeDec & aluModePss & "---";
+ constant aluFlg : aluMode := aluModeFlg & aluModePss & "---";
+ constant aluBit : aluMode := aluModeBit & aluModeAnd & "---";
+ constant aluRor : aluMode := aluModeRor & aluModePss & "---";
+ constant aluLsr : aluMode := aluModeLsr & aluModePss & "---";
+ constant aluRol : aluMode := aluModeRol & aluModePss & "---";
+ constant aluAsl : aluMode := aluModeAsl & aluModePss & "---";
+
+ constant aluCmp : aluMode := aluModeInp & aluModeCmp & "100";
+ constant aluCpx : aluMode := aluModeInp & aluModeCmp & "010";
+ constant aluCpy : aluMode := aluModeInp & aluModeCmp & "001";
+ constant aluAdc : aluMode := aluModeInp & aluModeAdc & "---";
+ constant aluSbc : aluMode := aluModeInp & aluModeSbc & "---";
+ constant aluAnd : aluMode := aluModeInp & aluModeAnd & "---";
+ constant aluOra : aluMode := aluModeInp & aluModeOra & "---";
+ constant aluEor : aluMode := aluModeInp & aluModeEor & "---";
+
+ constant aluSlo : aluMode := aluModeAsl & aluModeOra & "---";
+ constant aluSre : aluMode := aluModeLsr & aluModeEor & "---";
+ constant aluRra : aluMode := aluModeRor & aluModeAdc & "---";
+ constant aluRla : aluMode := aluModeRol & aluModeAnd & "---";
+ constant aluDcp : aluMode := aluModeDec & aluModeCmp & "100";
+ constant aluIsc : aluMode := aluModeInc & aluModeSbc & "---";
+ constant aluAnc : aluMode := aluModeAnc & aluModeAnd & "---";
+ constant aluArr : aluMode := aluModeRor & aluModeArr & "---";
+ constant aluSbx : aluMode := aluModeInp & aluModeCmp & "110";
+
+ constant aluXXX : aluMode := (others => '-');
+
+
+ -- Stack operations. Push/Pop/None
+ constant stackInc : unsigned(0 to 0) := "0";
+ constant stackDec : unsigned(0 to 0) := "1";
+ constant stackXXX : unsigned(0 to 0) := "-";
+
+ subtype decodedBitsDef is unsigned(0 to 43);
+ type opcodeInfoTableDef is array(0 to 255) of decodedBitsDef;
+ constant opcodeInfoTable : opcodeInfoTableDef := (
+ -- +------- Update register A
+ -- |+------ Update register X
+ -- ||+----- Update register Y
+ -- |||+---- Update register S
+ -- |||| +-- Update Flags
+ -- |||| |
+ -- |||| _|__
+ -- |||| / \
+ -- AXYS NVDIZC addressing aluInput aluMode
+ "0000" & "000100" & brk & aluInXXX & aluP, -- 00 BRK
+ "1000" & "100010" & readIndX & aluInT & aluOra, -- 01 ORA (zp,x)
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 02 *** JAM ***
+ "1000" & "100011" & rmwIndX & aluInT & aluSlo, -- 03 iSLO (zp,x)
+ "0000" & "000000" & readZp & aluInXXX & aluXXX, -- 04 iNOP zp
+ "1000" & "100010" & readZp & aluInT & aluOra, -- 05 ORA zp
+ "0000" & "100011" & rmwZp & aluInT & aluAsl, -- 06 ASL zp
+ "1000" & "100011" & rmwZp & aluInT & aluSlo, -- 07 iSLO zp
+ "0000" & "000000" & push & aluInXXX & aluP, -- 08 PHP
+ "1000" & "100010" & immediate & aluInT & aluOra, -- 09 ORA imm
+ "1000" & "100011" & implied & aluInA & aluAsl, -- 0A ASL accu
+ "1000" & "100011" & immediate & aluInT & aluAnc, -- 0B iANC imm
+ "0000" & "000000" & readAbs & aluInXXX & aluXXX, -- 0C iNOP abs
+ "1000" & "100010" & readAbs & aluInT & aluOra, -- 0D ORA abs
+ "0000" & "100011" & rmwAbs & aluInT & aluAsl, -- 0E ASL abs
+ "1000" & "100011" & rmwAbs & aluInT & aluSlo, -- 0F iSLO abs
+ "0000" & "000000" & relative & aluInXXX & aluXXX, -- 10 BPL
+ "1000" & "100010" & readIndY & aluInT & aluOra, -- 11 ORA (zp),y
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 12 *** JAM ***
+ "1000" & "100011" & rmwIndY & aluInT & aluSlo, -- 13 iSLO (zp),y
+ "0000" & "000000" & readZpX & aluInXXX & aluXXX, -- 14 iNOP zp,x
+ "1000" & "100010" & readZpX & aluInT & aluOra, -- 15 ORA zp,x
+ "0000" & "100011" & rmwZpX & aluInT & aluAsl, -- 16 ASL zp,x
+ "1000" & "100011" & rmwZpX & aluInT & aluSlo, -- 17 iSLO zp,x
+ "0000" & "000001" & implied & aluInClr & aluFlg, -- 18 CLC
+ "1000" & "100010" & readAbsY & aluInT & aluOra, -- 19 ORA abs,y
+ "0000" & "000000" & implied & aluInXXX & aluXXX, -- 1A iNOP implied
+ "1000" & "100011" & rmwAbsY & aluInT & aluSlo, -- 1B iSLO abs,y
+ "0000" & "000000" & readAbsX & aluInXXX & aluXXX, -- 1C iNOP abs,x
+ "1000" & "100010" & readAbsX & aluInT & aluOra, -- 1D ORA abs,x
+ "0000" & "100011" & rmwAbsX & aluInT & aluAsl, -- 1E ASL abs,x
+ "1000" & "100011" & rmwAbsX & aluInT & aluSlo, -- 1F iSLO abs,x
+ -- AXYS NVDIZC addressing aluInput aluMode
+ "0000" & "000000" & jsr & aluInXXX & aluXXX, -- 20 JSR
+ "1000" & "100010" & readIndX & aluInT & aluAnd, -- 21 AND (zp,x)
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 22 *** JAM ***
+ "1000" & "100011" & rmwIndX & aluInT & aluRla, -- 23 iRLA (zp,x)
+ "0000" & "110010" & readZp & aluInT & aluBit, -- 24 BIT zp
+ "1000" & "100010" & readZp & aluInT & aluAnd, -- 25 AND zp
+ "0000" & "100011" & rmwZp & aluInT & aluRol, -- 26 ROL zp
+ "1000" & "100011" & rmwZp & aluInT & aluRla, -- 27 iRLA zp
+ "0000" & "111111" & pop & aluInT & aluFlg, -- 28 PLP
+ "1000" & "100010" & immediate & aluInT & aluAnd, -- 29 AND imm
+ "1000" & "100011" & implied & aluInA & aluRol, -- 2A ROL accu
+ "1000" & "100011" & immediate & aluInT & aluAnc, -- 2B iANC imm
+ "0000" & "110010" & readAbs & aluInT & aluBit, -- 2C BIT abs
+ "1000" & "100010" & readAbs & aluInT & aluAnd, -- 2D AND abs
+ "0000" & "100011" & rmwAbs & aluInT & aluRol, -- 2E ROL abs
+ "1000" & "100011" & rmwAbs & aluInT & aluRla, -- 2F iRLA abs
+ "0000" & "000000" & relative & aluInXXX & aluXXX, -- 30 BMI
+ "1000" & "100010" & readIndY & aluInT & aluAnd, -- 31 AND (zp),y
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 32 *** JAM ***
+ "1000" & "100011" & rmwIndY & aluInT & aluRla, -- 33 iRLA (zp),y
+ "0000" & "000000" & readZpX & aluInXXX & aluXXX, -- 34 iNOP zp,x
+ "1000" & "100010" & readZpX & aluInT & aluAnd, -- 35 AND zp,x
+ "0000" & "100011" & rmwZpX & aluInT & aluRol, -- 36 ROL zp,x
+ "1000" & "100011" & rmwZpX & aluInT & aluRla, -- 37 iRLA zp,x
+ "0000" & "000001" & implied & aluInSet & aluFlg, -- 38 SEC
+ "1000" & "100010" & readAbsY & aluInT & aluAnd, -- 39 AND abs,y
+ "0000" & "000000" & implied & aluInXXX & aluXXX, -- 3A iNOP implied
+ "1000" & "100011" & rmwAbsY & aluInT & aluRla, -- 3B iRLA abs,y
+ "0000" & "000000" & readAbsX & aluInXXX & aluXXX, -- 3C iNOP abs,x
+ "1000" & "100010" & readAbsX & aluInT & aluAnd, -- 3D AND abs,x
+ "0000" & "100011" & rmwAbsX & aluInT & aluRol, -- 3E ROL abs,x
+ "1000" & "100011" & rmwAbsX & aluInT & aluRla, -- 3F iRLA abs,x
+ -- AXYS NVDIZC addressing aluInput aluMode
+ "0000" & "111111" & rti & aluInT & aluFlg, -- 40 RTI
+ "1000" & "100010" & readIndX & aluInT & aluEor, -- 41 EOR (zp,x)
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 42 *** JAM ***
+ "1000" & "100011" & rmwIndX & aluInT & aluSre, -- 43 iSRE (zp,x)
+ "0000" & "000000" & readZp & aluInXXX & aluXXX, -- 44 iNOP zp
+ "1000" & "100010" & readZp & aluInT & aluEor, -- 45 EOR zp
+ "0000" & "100011" & rmwZp & aluInT & aluLsr, -- 46 LSR zp
+ "1000" & "100011" & rmwZp & aluInT & aluSre, -- 47 iSRE zp
+ "0000" & "000000" & push & aluInA & aluInp, -- 48 PHA
+ "1000" & "100010" & immediate & aluInT & aluEor, -- 49 EOR imm
+ "1000" & "100011" & implied & aluInA & aluLsr, -- 4A LSR accu
+ "1000" & "100011" & immediate & aluInAT & aluLsr, -- 4B iALR imm
+ "0000" & "000000" & jumpAbs & aluInXXX & aluXXX, -- 4C JMP abs
+ "1000" & "100010" & readAbs & aluInT & aluEor, -- 4D EOR abs
+ "0000" & "100011" & rmwAbs & aluInT & aluLsr, -- 4E LSR abs
+ "1000" & "100011" & rmwAbs & aluInT & aluSre, -- 4F iSRE abs
+ "0000" & "000000" & relative & aluInXXX & aluXXX, -- 50 BVC
+ "1000" & "100010" & readIndY & aluInT & aluEor, -- 51 EOR (zp),y
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 52 *** JAM ***
+ "1000" & "100011" & rmwIndY & aluInT & aluSre, -- 53 iSRE (zp),y
+ "0000" & "000000" & readZpX & aluInXXX & aluXXX, -- 54 iNOP zp,x
+ "1000" & "100010" & readZpX & aluInT & aluEor, -- 55 EOR zp,x
+ "0000" & "100011" & rmwZpX & aluInT & aluLsr, -- 56 LSR zp,x
+ "1000" & "100011" & rmwZpX & aluInT & aluSre, -- 57 SRE zp,x
+ "0000" & "000100" & implied & aluInClr & aluXXX, -- 58 CLI
+ "1000" & "100010" & readAbsY & aluInT & aluEor, -- 59 EOR abs,y
+ "0000" & "000000" & implied & aluInXXX & aluXXX, -- 5A iNOP implied
+ "1000" & "100011" & rmwAbsY & aluInT & aluSre, -- 5B iSRE abs,y
+ "0000" & "000000" & readAbsX & aluInXXX & aluXXX, -- 5C iNOP abs,x
+ "1000" & "100010" & readAbsX & aluInT & aluEor, -- 5D EOR abs,x
+ "0000" & "100011" & rmwAbsX & aluInT & aluLsr, -- 5E LSR abs,x
+ "1000" & "100011" & rmwAbsX & aluInT & aluSre, -- 5F SRE abs,x
+ -- AXYS NVDIZC addressing aluInput aluMode
+ "0000" & "000000" & rts & aluInXXX & aluXXX, -- 60 RTS
+ "1000" & "110011" & readIndX & aluInT & aluAdc, -- 61 ADC (zp,x)
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 62 *** JAM ***
+ "1000" & "110011" & rmwIndX & aluInT & aluRra, -- 63 iRRA (zp,x)
+ "0000" & "000000" & readZp & aluInXXX & aluXXX, -- 64 iNOP zp
+ "1000" & "110011" & readZp & aluInT & aluAdc, -- 65 ADC zp
+ "0000" & "100011" & rmwZp & aluInT & aluRor, -- 66 ROR zp
+ "1000" & "110011" & rmwZp & aluInT & aluRra, -- 67 iRRA zp
+ "1000" & "100010" & pop & aluInT & aluInp, -- 68 PLA
+ "1000" & "110011" & immediate & aluInT & aluAdc, -- 69 ADC imm
+ "1000" & "100011" & implied & aluInA & aluRor, -- 6A ROR accu
+ "1000" & "110011" & immediate & aluInAT & aluArr, -- 6B iARR imm
+ "0000" & "000000" & jumpInd & aluInXXX & aluXXX, -- 6C JMP indirect
+ "1000" & "110011" & readAbs & aluInT & aluAdc, -- 6D ADC abs
+ "0000" & "100011" & rmwAbs & aluInT & aluRor, -- 6E ROR abs
+ "1000" & "110011" & rmwAbs & aluInT & aluRra, -- 6F iRRA abs
+ "0000" & "000000" & relative & aluInXXX & aluXXX, -- 70 BVS
+ "1000" & "110011" & readIndY & aluInT & aluAdc, -- 71 ADC (zp),y
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 72 *** JAM ***
+ "1000" & "110011" & rmwIndY & aluInT & aluRra, -- 73 iRRA (zp),y
+ "0000" & "000000" & readZpX & aluInXXX & aluXXX, -- 74 iNOP zp,x
+ "1000" & "110011" & readZpX & aluInT & aluAdc, -- 75 ADC zp,x
+ "0000" & "100011" & rmwZpX & aluInT & aluRor, -- 76 ROR zp,x
+ "1000" & "110011" & rmwZpX & aluInT & aluRra, -- 77 iRRA zp,x
+ "0000" & "000100" & implied & aluInSet & aluXXX, -- 78 SEI
+ "1000" & "110011" & readAbsY & aluInT & aluAdc, -- 79 ADC abs,y
+ "0000" & "000000" & implied & aluInXXX & aluXXX, -- 7A iNOP implied
+ "1000" & "110011" & rmwAbsY & aluInT & aluRra, -- 7B iRRA abs,y
+ "0000" & "000000" & readAbsX & aluInXXX & aluXXX, -- 7C iNOP abs,x
+ "1000" & "110011" & readAbsX & aluInT & aluAdc, -- 7D ADC abs,x
+ "0000" & "100011" & rmwAbsX & aluInT & aluRor, -- 7E ROR abs,x
+ "1000" & "110011" & rmwAbsX & aluInT & aluRra, -- 7F iRRA abs,x
+ -- AXYS NVDIZC addressing aluInput aluMode
+ "0000" & "000000" & immediate & aluInXXX & aluXXX, -- 80 iNOP imm
+ "0000" & "000000" & writeIndX & aluInA & aluInp, -- 81 STA (zp,x)
+ "0000" & "000000" & immediate & aluInXXX & aluXXX, -- 82 iNOP imm
+ "0000" & "000000" & writeIndX & aluInAX & aluInp, -- 83 iSAX (zp,x)
+ "0000" & "000000" & writeZp & aluInY & aluInp, -- 84 STY zp
+ "0000" & "000000" & writeZp & aluInA & aluInp, -- 85 STA zp
+ "0000" & "000000" & writeZp & aluInX & aluInp, -- 86 STX zp
+ "0000" & "000000" & writeZp & aluInAX & aluInp, -- 87 iSAX zp
+ "0010" & "100010" & implied & aluInY & aluDec, -- 88 DEY
+ "0000" & "000000" & immediate & aluInXXX & aluXXX, -- 84 iNOP imm
+ "1000" & "100010" & implied & aluInX & aluInp, -- 8A TXA
+ "1000" & "100010" & immediate & aluInEXT & aluInp, -- 8B iANE imm
+ "0000" & "000000" & writeAbs & aluInY & aluInp, -- 8C STY abs
+ "0000" & "000000" & writeAbs & aluInA & aluInp, -- 8D STA abs
+ "0000" & "000000" & writeAbs & aluInX & aluInp, -- 8E STX abs
+ "0000" & "000000" & writeAbs & aluInAX & aluInp, -- 8F iSAX abs
+ "0000" & "000000" & relative & aluInXXX & aluXXX, -- 90 BCC
+ "0000" & "000000" & writeIndY & aluInA & aluInp, -- 91 STA (zp),y
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 92 *** JAM ***
+ "0000" & "000000" & writeIndY & aluInAXH & aluInp, -- 93 iAHX (zp),y
+ "0000" & "000000" & writeZpX & aluInY & aluInp, -- 94 STY zp,x
+ "0000" & "000000" & writeZpX & aluInA & aluInp, -- 95 STA zp,x
+ "0000" & "000000" & writeZpY & aluInX & aluInp, -- 96 STX zp,y
+ "0000" & "000000" & writeZpY & aluInAX & aluInp, -- 97 iSAX zp,y
+ "1000" & "100010" & implied & aluInY & aluInp, -- 98 TYA
+ "0000" & "000000" & writeAbsY & aluInA & aluInp, -- 99 STA abs,y
+ "0001" & "000000" & implied & aluInX & aluInp, -- 9A TXS
+ "0001" & "000000" & writeAbsY & aluInAXH & aluInp, -- 9B iSHS abs,y
+ "0000" & "000000" & writeAbsX & aluInYH & aluInp, -- 9C iSHY abs,x
+ "0000" & "000000" & writeAbsX & aluInA & aluInp, -- 9D STA abs,x
+ "0000" & "000000" & writeAbsY & aluInXH & aluInp, -- 9E iSHX abs,y
+ "0000" & "000000" & writeAbsY & aluInAXH & aluInp, -- 9F iAHX abs,y
+ -- AXYS NVDIZC addressing aluInput aluMode
+ "0010" & "100010" & immediate & aluInT & aluInp, -- A0 LDY imm
+ "1000" & "100010" & readIndX & aluInT & aluInp, -- A1 LDA (zp,x)
+ "0100" & "100010" & immediate & aluInT & aluInp, -- A2 LDX imm
+ "1100" & "100010" & readIndX & aluInT & aluInp, -- A3 LAX (zp,x)
+ "0010" & "100010" & readZp & aluInT & aluInp, -- A4 LDY zp
+ "1000" & "100010" & readZp & aluInT & aluInp, -- A5 LDA zp
+ "0100" & "100010" & readZp & aluInT & aluInp, -- A6 LDX zp
+ "1100" & "100010" & readZp & aluInT & aluInp, -- A7 iLAX zp
+ "0010" & "100010" & implied & aluInA & aluInp, -- A8 TAY
+ "1000" & "100010" & immediate & aluInT & aluInp, -- A9 LDA imm
+ "0100" & "100010" & implied & aluInA & aluInp, -- AA TAX
+ "1100" & "100010" & immediate & aluInET & aluInp, -- AB iLXA imm
+ "0010" & "100010" & readAbs & aluInT & aluInp, -- AC LDY abs
+ "1000" & "100010" & readAbs & aluInT & aluInp, -- AD LDA abs
+ "0100" & "100010" & readAbs & aluInT & aluInp, -- AE LDX abs
+ "1100" & "100010" & readAbs & aluInT & aluInp, -- AF iLAX abs
+ "0000" & "000000" & relative & aluInXXX & aluXXX, -- B0 BCS
+ "1000" & "100010" & readIndY & aluInT & aluInp, -- B1 LDA (zp),y
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- B2 *** JAM ***
+ "1100" & "100010" & readIndY & aluInT & aluInp, -- B3 iLAX (zp),y
+ "0010" & "100010" & readZpX & aluInT & aluInp, -- B4 LDY zp,x
+ "1000" & "100010" & readZpX & aluInT & aluInp, -- B5 LDA zp,x
+ "0100" & "100010" & readZpY & aluInT & aluInp, -- B6 LDX zp,y
+ "1100" & "100010" & readZpY & aluInT & aluInp, -- B7 iLAX zp,y
+ "0000" & "010000" & implied & aluInClr & aluFlg, -- B8 CLV
+ "1000" & "100010" & readAbsY & aluInT & aluInp, -- B9 LDA abs,y
+ "0100" & "100010" & implied & aluInS & aluInp, -- BA TSX
+ "1101" & "100010" & readAbsY & aluInST & aluInp, -- BB iLAS abs,y
+ "0010" & "100010" & readAbsX & aluInT & aluInp, -- BC LDY abs,x
+ "1000" & "100010" & readAbsX & aluInT & aluInp, -- BD LDA abs,x
+ "0100" & "100010" & readAbsY & aluInT & aluInp, -- BE LDX abs,y
+ "1100" & "100010" & readAbsY & aluInT & aluInp, -- BF iLAX abs,y
+ -- AXYS NVDIZC addressing aluInput aluMode
+ "0000" & "100011" & immediate & aluInT & aluCpy, -- C0 CPY imm
+ "0000" & "100011" & readIndX & aluInT & aluCmp, -- C1 CMP (zp,x)
+ "0000" & "000000" & immediate & aluInXXX & aluXXX, -- C2 iNOP imm
+ "0000" & "100011" & rmwIndX & aluInT & aluDcp, -- C3 iDCP (zp,x)
+ "0000" & "100011" & readZp & aluInT & aluCpy, -- C4 CPY zp
+ "0000" & "100011" & readZp & aluInT & aluCmp, -- C5 CMP zp
+ "0000" & "100010" & rmwZp & aluInT & aluDec, -- C6 DEC zp
+ "0000" & "100011" & rmwZp & aluInT & aluDcp, -- C7 iDCP zp
+ "0010" & "100010" & implied & aluInY & aluInc, -- C8 INY
+ "0000" & "100011" & immediate & aluInT & aluCmp, -- C9 CMP imm
+ "0100" & "100010" & implied & aluInX & aluDec, -- CA DEX
+ "0100" & "100011" & immediate & aluInT & aluSbx, -- CB SBX imm
+ "0000" & "100011" & readAbs & aluInT & aluCpy, -- CC CPY abs
+ "0000" & "100011" & readAbs & aluInT & aluCmp, -- CD CMP abs
+ "0000" & "100010" & rmwAbs & aluInT & aluDec, -- CE DEC abs
+ "0000" & "100011" & rmwAbs & aluInT & aluDcp, -- CF iDCP abs
+ "0000" & "000000" & relative & aluInXXX & aluXXX, -- D0 BNE
+ "0000" & "100011" & readIndY & aluInT & aluCmp, -- D1 CMP (zp),y
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- D2 *** JAM ***
+ "0000" & "100011" & rmwIndY & aluInT & aluDcp, -- D3 iDCP (zp),y
+ "0000" & "000000" & readZpX & aluInXXX & aluXXX, -- D4 iNOP zp,x
+ "0000" & "100011" & readZpX & aluInT & aluCmp, -- D5 CMP zp,x
+ "0000" & "100010" & rmwZpX & aluInT & aluDec, -- D6 DEC zp,x
+ "0000" & "100011" & rmwZpX & aluInT & aluDcp, -- D7 iDCP zp,x
+ "0000" & "001000" & implied & aluInClr & aluXXX, -- D8 CLD
+ "0000" & "100011" & readAbsY & aluInT & aluCmp, -- D9 CMP abs,y
+ "0000" & "000000" & implied & aluInXXX & aluXXX, -- DA iNOP implied
+ "0000" & "100011" & rmwAbsY & aluInT & aluDcp, -- DB iDCP abs,y
+ "0000" & "000000" & readAbsX & aluInXXX & aluXXX, -- DC iNOP abs,x
+ "0000" & "100011" & readAbsX & aluInT & aluCmp, -- DD CMP abs,x
+ "0000" & "100010" & rmwAbsX & aluInT & aluDec, -- DE DEC abs,x
+ "0000" & "100011" & rmwAbsX & aluInT & aluDcp, -- DF iDCP abs,x
+ -- AXYS NVDIZC addressing aluInput aluMode
+ "0000" & "100011" & immediate & aluInT & aluCpx, -- E0 CPX imm
+ "1000" & "110011" & readIndX & aluInT & aluSbc, -- E1 SBC (zp,x)
+ "0000" & "000000" & immediate & aluInXXX & aluXXX, -- E2 iNOP imm
+ "1000" & "110011" & rmwIndX & aluInT & aluIsc, -- E3 iISC (zp,x)
+ "0000" & "100011" & readZp & aluInT & aluCpx, -- E4 CPX zp
+ "1000" & "110011" & readZp & aluInT & aluSbc, -- E5 SBC zp
+ "0000" & "100010" & rmwZp & aluInT & aluInc, -- E6 INC zp
+ "1000" & "110011" & rmwZp & aluInT & aluIsc, -- E7 iISC zp
+ "0100" & "100010" & implied & aluInX & aluInc, -- E8 INX
+ "1000" & "110011" & immediate & aluInT & aluSbc, -- E9 SBC imm
+ "0000" & "000000" & implied & aluInXXX & aluXXX, -- EA NOP
+ "1000" & "110011" & immediate & aluInT & aluSbc, -- EB SBC imm (illegal opc)
+ "0000" & "100011" & readAbs & aluInT & aluCpx, -- EC CPX abs
+ "1000" & "110011" & readAbs & aluInT & aluSbc, -- ED SBC abs
+ "0000" & "100010" & rmwAbs & aluInT & aluInc, -- EE INC abs
+ "1000" & "110011" & rmwAbs & aluInT & aluIsc, -- EF iISC abs
+ "0000" & "000000" & relative & aluInXXX & aluXXX, -- F0 BEQ
+ "1000" & "110011" & readIndY & aluInT & aluSbc, -- F1 SBC (zp),y
+ "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- F2 *** JAM ***
+ "1000" & "110011" & rmwIndY & aluInT & aluIsc, -- F3 iISC (zp),y
+ "0000" & "000000" & readZpX & aluInXXX & aluXXX, -- F4 iNOP zp,x
+ "1000" & "110011" & readZpX & aluInT & aluSbc, -- F5 SBC zp,x
+ "0000" & "100010" & rmwZpX & aluInT & aluInc, -- F6 INC zp,x
+ "1000" & "110011" & rmwZpX & aluInT & aluIsc, -- F7 iISC zp,x
+ "0000" & "001000" & implied & aluInSet & aluXXX, -- F8 SED
+ "1000" & "110011" & readAbsY & aluInT & aluSbc, -- F9 SBC abs,y
+ "0000" & "000000" & implied & aluInXXX & aluXXX, -- FA iNOP implied
+ "1000" & "110011" & rmwAbsY & aluInT & aluIsc, -- FB iISC abs,y
+ "0000" & "000000" & readAbsX & aluInXXX & aluXXX, -- FC iNOP abs,x
+ "1000" & "110011" & readAbsX & aluInT & aluSbc, -- FD SBC abs,x
+ "0000" & "100010" & rmwAbsX & aluInT & aluInc, -- FE INC abs,x
+ "1000" & "110011" & rmwAbsX & aluInT & aluIsc -- FF iISC abs,x
+ );
+ signal opcInfo : decodedBitsDef;
+ signal nextOpcInfo : decodedBitsDef; -- Next opcode (decoded)
+ signal nextOpcInfoReg : decodedBitsDef; -- Next opcode (decoded) pipelined
+ signal theOpcode : unsigned(7 downto 0);
+ signal nextOpcode : unsigned(7 downto 0);
+
+-- Program counter
+ signal PC : unsigned(15 downto 0); -- Program counter
+
+-- Address generation
+ type nextAddrDef is (
+ nextAddrHold,
+ nextAddrIncr,
+ nextAddrIncrL, -- Increment low bits only (zeropage accesses)
+ nextAddrIncrH, -- Increment high bits only (page-boundary)
+ nextAddrDecrH, -- Decrement high bits (branch backwards)
+ nextAddrPc,
+ nextAddrIrq,
+ nextAddrReset,
+ nextAddrAbs,
+ nextAddrAbsIndexed,
+ nextAddrZeroPage,
+ nextAddrZPIndexed,
+ nextAddrStack,
+ nextAddrRelative
+ );
+ signal nextAddr : nextAddrDef;
+ signal myAddr : unsigned(15 downto 0);
+ signal myAddrIncr : unsigned(15 downto 0);
+ signal myAddrIncrH : unsigned(7 downto 0);
+ signal myAddrDecrH : unsigned(7 downto 0);
+ signal theWe : std_logic;
+
+ signal irqActive : std_logic;
+
+-- Output register
+ signal doReg : unsigned(7 downto 0);
+
+-- Buffer register
+ signal T : unsigned(7 downto 0);
+
+-- General registers
+ signal A: unsigned(7 downto 0); -- Accumulator
+ signal X: unsigned(7 downto 0); -- Index X
+ signal Y: unsigned(7 downto 0); -- Index Y
+ signal S: unsigned(7 downto 0); -- stack pointer
+
+-- Status register
+ signal C: std_logic; -- Carry
+ signal Z: std_logic; -- Zero flag
+ signal I: std_logic; -- Interrupt flag
+ signal D: std_logic; -- Decimal mode
+ signal V: std_logic; -- Overflow
+ signal N: std_logic; -- Negative
+
+-- ALU
+ -- ALU input
+ signal aluInput : unsigned(7 downto 0);
+ signal aluCmpInput : unsigned(7 downto 0);
+ -- ALU output
+ signal aluRegisterOut : unsigned(7 downto 0);
+ signal aluRmwOut : unsigned(7 downto 0);
+ signal aluC : std_logic;
+ signal aluZ : std_logic;
+ signal aluV : std_logic;
+ signal aluN : std_logic;
+ -- Pipeline registers
+ signal aluInputReg : unsigned(7 downto 0);
+ signal aluCmpInputReg : unsigned(7 downto 0);
+ signal aluRmwReg : unsigned(7 downto 0);
+ signal aluNineReg : unsigned(7 downto 0);
+ signal aluCReg : std_logic;
+ signal aluZReg : std_logic;
+ signal aluVReg : std_logic;
+ signal aluNReg : std_logic;
+
+-- Indexing
+ signal indexOut : unsigned(8 downto 0);
+
+begin
+processAluInput: process(clk, opcInfo, A, X, Y, T, S)
+ variable temp : unsigned(7 downto 0);
+ begin
+ temp := (others => '1');
+ if opcInfo(opcInA) = '1' then
+ temp := temp and A;
+ end if;
+ if opcInfo(opcInE) = '1' then
+ temp := temp and (A or X"EE");
+ end if;
+ if opcInfo(opcInX) = '1' then
+ temp := temp and X;
+ end if;
+ if opcInfo(opcInY) = '1' then
+ temp := temp and Y;
+ end if;
+ if opcInfo(opcInS) = '1' then
+ temp := temp and S;
+ end if;
+ if opcInfo(opcInT) = '1' then
+ temp := temp and T;
+ end if;
+ if opcInfo(opcInClear) = '1' then
+ temp := (others => '0');
+ end if;
+ if rising_edge(clk) then
+ aluInputReg <= temp;
+ end if;
+
+ aluInput <= temp;
+ if pipelineAluMux then
+ aluInput <= aluInputReg;
+ end if;
+ end process;
+
+processCmpInput: process(clk, opcInfo, A, X, Y)
+ variable temp : unsigned(7 downto 0);
+ begin
+ temp := (others => '1');
+ if opcInfo(opcInCmp) = '1' then
+ temp := temp and A;
+ end if;
+ if opcInfo(opcInCpx) = '1' then
+ temp := temp and X;
+ end if;
+ if opcInfo(opcInCpy) = '1' then
+ temp := temp and Y;
+ end if;
+ if rising_edge(clk) then
+ aluCmpInputReg <= temp;
+ end if;
+
+ aluCmpInput <= temp;
+ if pipelineAluMux then
+ aluCmpInput <= aluCmpInputReg;
+ end if;
+ end process;
+
+ -- ALU consists of two parts
+ -- Read-Modify-Write or index instructions: INC/DEC/ASL/LSR/ROR/ROL
+ -- Accumulator instructions: ADC, SBC, EOR, AND, EOR, ORA
+ -- Some instructions are both RMW and accumulator so for most
+ -- instructions the rmw results are routed through accu alu too.
+processAlu: process(clk, opcInfo, aluInput, aluCmpInput, A, T, irqActive, N, V, D, I, Z, C)
+ variable lowBits: unsigned(5 downto 0);
+ variable nineBits: unsigned(8 downto 0);
+ variable rmwBits: unsigned(8 downto 0);
+
+ variable varC : std_logic;
+ variable varZ : std_logic;
+ variable varV : std_logic;
+ variable varN : std_logic;
+ begin
+ lowBits := (others => '-');
+ nineBits := (others => '-');
+ rmwBits := (others => '-');
+ varV := aluInput(6); -- Default for BIT / PLP / RTI
+
+ -- Shift unit
+ case opcInfo(aluMode1From to aluMode1To) is
+ when aluModeInp =>
+ rmwBits := C & aluInput;
+ when aluModeP =>
+ rmwBits := C & N & V & '1' & (not irqActive) & D & I & Z & C;
+ when aluModeInc =>
+ rmwBits := C & (aluInput + 1);
+ when aluModeDec =>
+ rmwBits := C & (aluInput - 1);
+ when aluModeAsl =>
+ rmwBits := aluInput & "0";
+ when aluModeFlg =>
+ rmwBits := aluInput(0) & aluInput;
+ when aluModeLsr =>
+ rmwBits := aluInput(0) & "0" & aluInput(7 downto 1);
+ when aluModeRol =>
+ rmwBits := aluInput & C;
+ when aluModeRoR =>
+ rmwBits := aluInput(0) & C & aluInput(7 downto 1);
+ when aluModeAnc =>
+ rmwBits := (aluInput(7) and A(7)) & aluInput;
+ when others =>
+ rmwBits := C & aluInput;
+ end case;
+
+ -- ALU
+ case opcInfo(aluMode2From to aluMode2To) is
+ when aluModeAdc =>
+ lowBits := ("0" & A(3 downto 0) & rmwBits(8)) + ("0" & rmwBits(3 downto 0) & "1");
+ ninebits := ("0" & A) + ("0" & rmwBits(7 downto 0)) + (B"00000000" & rmwBits(8));
+ when aluModeSbc =>
+ lowBits := ("0" & A(3 downto 0) & rmwBits(8)) + ("0" & (not rmwBits(3 downto 0)) & "1");
+ ninebits := ("0" & A) + ("0" & (not rmwBits(7 downto 0))) + (B"00000000" & rmwBits(8));
+ when aluModeCmp =>
+ ninebits := ("0" & aluCmpInput) + ("0" & (not rmwBits(7 downto 0))) + "000000001";
+ when aluModeAnd =>
+ ninebits := rmwBits(8) & (A and rmwBits(7 downto 0));
+ when aluModeEor =>
+ ninebits := rmwBits(8) & (A xor rmwBits(7 downto 0));
+ when aluModeOra =>
+ ninebits := rmwBits(8) & (A or rmwBits(7 downto 0));
+ when others =>
+ ninebits := rmwBits;
+ end case;
+
+ if (opcInfo(aluMode1From to aluMode1To) = aluModeFlg) then
+ varZ := rmwBits(1);
+ elsif ninebits(7 downto 0) = X"00" then
+ varZ := '1';
+ else
+ varZ := '0';
+ end if;
+
+ case opcInfo(aluMode2From to aluMode2To) is
+ when aluModeAdc =>
+ -- decimal mode low bits correction, is done after setting Z flag.
+ if D = '1' then
+ if lowBits(5 downto 1) > 9 then
+ ninebits(3 downto 0) := ninebits(3 downto 0) + 6;
+ if lowBits(5) = '0' then
+ ninebits(8 downto 4) := ninebits(8 downto 4) + 1;
+ end if;
+ end if;
+ end if;
+ when others =>
+ null;
+ end case;
+
+ if (opcInfo(aluMode1From to aluMode1To) = aluModeBit)
+ or (opcInfo(aluMode1From to aluMode1To) = aluModeFlg) then
+ varN := rmwBits(7);
+ else
+ varN := nineBits(7);
+ end if;
+ varC := ninebits(8);
+ if opcInfo(aluMode2From to aluMode2To) = aluModeArr then
+ varC := aluInput(7);
+ varV := aluInput(7) xor aluInput(6);
+ end if;
+
+ case opcInfo(aluMode2From to aluMode2To) is
+ when aluModeAdc =>
+ -- decimal mode high bits correction, is done after setting Z and N flags
+ varV := (A(7) xor ninebits(7)) and (rmwBits(7) xor ninebits(7));
+ if D = '1' then
+ if ninebits(8 downto 4) > 9 then
+ ninebits(8 downto 4) := ninebits(8 downto 4) + 6;
+ varC := '1';
+ end if;
+ end if;
+ when aluModeSbc =>
+ varV := (A(7) xor ninebits(7)) and ((not rmwBits(7)) xor ninebits(7));
+ if D = '1' then
+ -- Check for borrow (lower 4 bits)
+ if lowBits(5) = '0' then
+ ninebits(3 downto 0) := ninebits(3 downto 0) - 6;
+ end if;
+ -- Check for borrow (upper 4 bits)
+ if ninebits(8) = '0' then
+ ninebits(8 downto 4) := ninebits(8 downto 4) - 6;
+ end if;
+ end if;
+ when aluModeArr =>
+ if D = '1' then
+ if (("0" & aluInput(3 downto 0)) + ("0000" & aluInput(0))) > 5 then
+ ninebits(3 downto 0) := ninebits(3 downto 0) + 6;
+ end if;
+ if (("0" & aluInput(7 downto 4)) + ("0000" & aluInput(4))) > 5 then
+ ninebits(8 downto 4) := ninebits(8 downto 4) + 6;
+ varC := '1';
+ else
+ varC := '0';
+ end if;
+ end if;
+ when others =>
+ null;
+ end case;
+
+ if rising_edge(clk) then
+ aluRmwReg <= rmwBits(7 downto 0);
+ aluNineReg <= ninebits(7 downto 0);
+ aluCReg <= varC;
+ aluZReg <= varZ;
+ aluVReg <= varV;
+ aluNReg <= varN;
+ end if;
+
+ aluRmwOut <= rmwBits(7 downto 0);
+ aluRegisterOut <= ninebits(7 downto 0);
+ aluC <= varC;
+ aluZ <= varZ;
+ aluV <= varV;
+ aluN <= varN;
+ if pipelineAluOut then
+ aluRmwOut <= aluRmwReg;
+ aluRegisterOut <= aluNineReg;
+ aluC <= aluCReg;
+ aluZ <= aluZReg;
+ aluV <= aluVReg;
+ aluN <= aluNReg;
+ end if;
+ end process;
+
+calcInterrupt: process(clk)
+ begin
+ if rising_edge(clk) then
+ if enable = '1' then
+ if theCpuCycle = cycleStack4
+ or reset = '1' then
+ nmiReg <= '1';
+ end if;
+
+ if nextCpuCycle /= cycleBranchTaken
+ and nextCpuCycle /= opcodeFetch then
+ irqReg <= irq_n;
+ nmiEdge <= nmi_n;
+ if (nmiEdge = '1') and (nmi_n = '0') then
+ nmiReg <= '0';
+ end if;
+ end if;
+ -- The 'or opcInfo(opcSetI)' prevents NMI immediately after BRK or IRQ.
+ -- Presumably this is done in the real 6502/6510 to prevent a double IRQ.
+ processIrq <= not ((nmiReg and (irqReg or I)) or opcInfo(opcIRQ));
+ end if;
+ end if;
+ end process;
+
+calcNextOpcode: process(clk, di, reset, processIrq)
+ variable myNextOpcode : unsigned(7 downto 0);
+ begin
+ -- Next opcode is read from input unless a reset or IRQ is pending.
+ myNextOpcode := di;
+ if reset = '1' then
+ myNextOpcode := X"4C";
+ elsif processIrq = '1' then
+ myNextOpcode := X"00";
+ end if;
+
+ nextOpcode <= myNextOpcode;
+ end process;
+
+ nextOpcInfo <= opcodeInfoTable(to_integer(nextOpcode));
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ nextOpcInfoReg <= nextOpcInfo;
+ end if;
+ end process;
+
+ -- Read bits and flags from opcodeInfoTable and store in opcInfo.
+ -- This info is used to control the execution of the opcode.
+calcOpcInfo: process(clk)
+ begin
+ if rising_edge(clk) then
+ if enable = '1' then
+ if (reset = '1') or (theCpuCycle = opcodeFetch) then
+ opcInfo <= nextOpcInfo;
+ if pipelineOpcode then
+ opcInfo <= nextOpcInfoReg;
+ end if;
+ end if;
+ end if;
+ end if;
+ end process;
+
+calcTheOpcode: process(clk)
+ begin
+ if rising_edge(clk) then
+ if enable = '1' then
+ if theCpuCycle = opcodeFetch then
+ irqActive <= '0';
+ if processIrq = '1' then
+ irqActive <= '1';
+ end if;
+ -- Fetch opcode
+ theOpcode <= nextOpcode;
+ end if;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- State machine
+-- -----------------------------------------------------------------------
+ process(enable, theCpuCycle, opcInfo)
+ begin
+ updateRegisters <= false;
+ if enable = '1' then
+ if opcInfo(opcRti) = '1' then
+ if theCpuCycle = cycleRead then
+ updateRegisters <= true;
+ end if;
+ elsif theCpuCycle = opcodeFetch then
+ updateRegisters <= true;
+ end if;
+ end if;
+ end process;
+
+ debugOpcode <= theOpcode;
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if enable = '1' then
+ theCpuCycle <= nextCpuCycle;
+ end if;
+ if reset = '1' then
+ theCpuCycle <= cycle2;
+ end if;
+ end if;
+ end process;
+
+ -- Determine the next cpu cycle. After the last cycle we always
+ -- go to opcodeFetch to get the next opcode.
+calcNextCpuCycle: process(theCpuCycle, opcInfo, theOpcode, indexOut, T, N, V, C, Z)
+ begin
+ nextCpuCycle <= opcodeFetch;
+
+ case theCpuCycle is
+ when opcodeFetch =>
+ nextCpuCycle <= cycle2;
+ when cycle2 =>
+ if opcInfo(opcBranch) = '1' then
+ if (N = theOpcode(5) and theOpcode(7 downto 6) = "00")
+ or (V = theOpcode(5) and theOpcode(7 downto 6) = "01")
+ or (C = theOpcode(5) and theOpcode(7 downto 6) = "10")
+ or (Z = theOpcode(5) and theOpcode(7 downto 6) = "11") then
+ -- Branch condition is true
+ nextCpuCycle <= cycleBranchTaken;
+ end if;
+ elsif (opcInfo(opcStackUp) = '1') then
+ nextCpuCycle <= cycleStack1;
+ elsif opcInfo(opcStackAddr) = '1'
+ and opcInfo(opcStackData) = '1' then
+ nextCpuCycle <= cycleStack2;
+ elsif opcInfo(opcStackAddr) = '1' then
+ nextCpuCycle <= cycleStack1;
+ elsif opcInfo(opcStackData) = '1' then
+ nextCpuCycle <= cycleWrite;
+ elsif opcInfo(opcAbsolute) = '1' then
+ nextCpuCycle <= cycle3;
+ elsif opcInfo(opcIndirect) = '1' then
+ if opcInfo(indexX) = '1' then
+ nextCpuCycle <= cyclePreIndirect;
+ else
+ nextCpuCycle <= cycleIndirect;
+ end if;
+ elsif opcInfo(opcZeroPage) = '1' then
+ if opcInfo(opcWrite) = '1' then
+ if (opcInfo(indexX) = '1')
+ or (opcInfo(indexY) = '1') then
+ nextCpuCycle <= cyclePreWrite;
+ else
+ nextCpuCycle <= cycleWrite;
+ end if;
+ else
+ if (opcInfo(indexX) = '1')
+ or (opcInfo(indexY) = '1') then
+ nextCpuCycle <= cyclePreRead;
+ else
+ nextCpuCycle <= cycleRead2;
+ end if;
+ end if;
+ elsif opcInfo(opcJump) = '1' then
+ nextCpuCycle <= cycleJump;
+ end if;
+ when cycle3 =>
+ nextCpuCycle <= cycleRead;
+ if opcInfo(opcWrite) = '1' then
+ if (opcInfo(indexX) = '1')
+ or (opcInfo(indexY) = '1') then
+ nextCpuCycle <= cyclePreWrite;
+ else
+ nextCpuCycle <= cycleWrite;
+ end if;
+ end if;
+ if (opcInfo(opcIndirect) = '1')
+ and (opcInfo(indexX) = '1') then
+ if opcInfo(opcWrite) = '1' then
+ nextCpuCycle <= cycleWrite;
+ else
+ nextCpuCycle <= cycleRead2;
+ end if;
+ end if;
+ when cyclePreIndirect =>
+ nextCpuCycle <= cycleIndirect;
+ when cycleIndirect =>
+ nextCpuCycle <= cycle3;
+ when cycleBranchTaken =>
+ if indexOut(8) /= T(7) then
+ -- Page boundary crossing during branch.
+ nextCpuCycle <= cycleBranchPage;
+ end if;
+ when cyclePreRead =>
+ if opcInfo(opcZeroPage) = '1' then
+ nextCpuCycle <= cycleRead2;
+ end if;
+ when cycleRead =>
+ if opcInfo(opcJump) = '1' then
+ nextCpuCycle <= cycleJump;
+ elsif indexOut(8) = '1' then
+ -- Page boundary crossing while indexed addressing.
+ nextCpuCycle <= cycleRead2;
+ elsif opcInfo(opcRmw) = '1' then
+ nextCpuCycle <= cycleRmw;
+ if opcInfo(indexX) = '1'
+ or opcInfo(indexY) = '1' then
+ -- 6510 needs extra cycle for indexed addressing
+ -- combined with RMW indexing
+ nextCpuCycle <= cycleRead2;
+ end if;
+ end if;
+ when cycleRead2 =>
+ if opcInfo(opcRmw) = '1' then
+ nextCpuCycle <= cycleRmw;
+ end if;
+ when cycleRmw =>
+ nextCpuCycle <= cycleWrite;
+ when cyclePreWrite =>
+ nextCpuCycle <= cycleWrite;
+ when cycleStack1 =>
+ nextCpuCycle <= cycleRead;
+ if opcInfo(opcStackAddr) = '1' then
+ nextCpuCycle <= cycleStack2;
+ end if;
+ when cycleStack2 =>
+ nextCpuCycle <= cycleStack3;
+ if opcInfo(opcRti) = '1' then
+ nextCpuCycle <= cycleRead;
+ end if;
+ if opcInfo(opcStackData) = '0'
+ and opcInfo(opcStackUp) = '1' then
+ nextCpuCycle <= cycleJump;
+ end if;
+ when cycleStack3 =>
+ nextCpuCycle <= cycleRead;
+ if opcInfo(opcStackData) = '0'
+ or opcInfo(opcStackUp) = '1' then
+ nextCpuCycle <= cycleJump;
+ elsif opcInfo(opcStackAddr) = '1' then
+ nextCpuCycle <= cycleStack4;
+ end if;
+ when cycleStack4 =>
+ nextCpuCycle <= cycleRead;
+ when cycleJump =>
+ if opcInfo(opcIncrAfter) = '1' then
+ -- Insert extra cycle
+ nextCpuCycle <= cycleEnd;
+ end if;
+ when others =>
+ null;
+ end case;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- T register
+-- -----------------------------------------------------------------------
+calcT: process(clk)
+ begin
+ if rising_edge(clk) then
+ if enable = '1' then
+ case theCpuCycle is
+ when cycle2 =>
+ T <= di;
+ when cycleStack1 | cycleStack2 =>
+ if opcInfo(opcStackUp) = '1' then
+ -- Read from stack
+ T <= di;
+ end if;
+ when cycleIndirect | cycleRead | cycleRead2 =>
+ T <= di;
+ when others =>
+ null;
+ end case;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- A register
+-- -----------------------------------------------------------------------
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if updateRegisters then
+ if opcInfo(opcUpdateA) = '1' then
+ A <= aluRegisterOut;
+ end if;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- X register
+-- -----------------------------------------------------------------------
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if updateRegisters then
+ if opcInfo(opcUpdateX) = '1' then
+ X <= aluRegisterOut;
+ end if;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- Y register
+-- -----------------------------------------------------------------------
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if updateRegisters then
+ if opcInfo(opcUpdateY) = '1' then
+ Y <= aluRegisterOut;
+ end if;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- C flag
+-- -----------------------------------------------------------------------
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if updateRegisters then
+ if opcInfo(opcUpdateC) = '1' then
+ C <= aluC;
+ end if;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- Z flag
+-- -----------------------------------------------------------------------
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if updateRegisters then
+ if opcInfo(opcUpdateZ) = '1' then
+ Z <= aluZ;
+ end if;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- I flag
+-- -----------------------------------------------------------------------
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if updateRegisters then
+ if opcInfo(opcUpdateI) = '1' then
+ I <= aluInput(2);
+ end if;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- D flag
+-- -----------------------------------------------------------------------
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if updateRegisters then
+ if opcInfo(opcUpdateD) = '1' then
+ D <= aluInput(3);
+ end if;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- V flag
+-- -----------------------------------------------------------------------
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if updateRegisters then
+ if opcInfo(opcUpdateV) = '1' then
+ V <= aluV;
+ end if;
+ end if;
+ if enable = '1' then
+ if soReg = '1' and so_n = '0' then
+ V <= '1';
+ end if;
+ soReg <= so_n;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- N flag
+-- -----------------------------------------------------------------------
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if updateRegisters then
+ if opcInfo(opcUpdateN) = '1' then
+ N <= aluN;
+ end if;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- Stack pointer
+-- -----------------------------------------------------------------------
+ process(clk)
+ variable sIncDec : unsigned(7 downto 0);
+ variable updateFlag : boolean;
+ begin
+ if rising_edge(clk) then
+
+ if opcInfo(opcStackUp) = '1' then
+ sIncDec := S + 1;
+ else
+ sIncDec := S - 1;
+ end if;
+
+ if enable = '1' then
+ updateFlag := false;
+ case nextCpuCycle is
+ when cycleStack1 =>
+ if (opcInfo(opcStackUp) = '1')
+ or (opcInfo(opcStackData) = '1') then
+ updateFlag := true;
+ end if;
+ when cycleStack2 =>
+ updateFlag := true;
+ when cycleStack3 =>
+ updateFlag := true;
+ when cycleStack4 =>
+ updateFlag := true;
+ when cycleRead =>
+ if opcInfo(opcRti) = '1' then
+ updateFlag := true;
+ end if;
+ when cycleWrite =>
+ if opcInfo(opcStackData) = '1' then
+ updateFlag := true;
+ end if;
+ when others =>
+ null;
+ end case;
+ if updateFlag then
+ S <= sIncDec;
+ end if;
+ end if;
+ if updateRegisters then
+ if opcInfo(opcUpdateS) = '1' then
+ S <= aluRegisterOut;
+ end if;
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- Data out
+-- -----------------------------------------------------------------------
+--calcDo: process(cpuNo, theCpuCycle, aluOut, PC, T)
+calcDo: process(clk)
+ begin
+ if rising_edge(clk) then
+ if enable = '1' then
+ doReg <= aluRmwOut;
+ if opcInfo(opcInH) = '1' then
+ -- For illegal opcodes SHA, SHX, SHY, SHS
+ doReg <= aluRmwOut and myAddrIncrH;
+ end if;
+
+ case nextCpuCycle is
+ when cycleStack2 =>
+ if opcInfo(opcIRQ) = '1'
+ and irqActive = '0' then
+ doReg <= myAddrIncr(15 downto 8);
+ else
+ doReg <= PC(15 downto 8);
+ end if;
+ when cycleStack3 =>
+ doReg <= PC(7 downto 0);
+ when cycleRmw =>
+-- do <= T; -- Read-modify-write write old value first.
+ doReg <= di; -- Read-modify-write write old value first.
+ when others => null;
+ end case;
+ end if;
+ end if;
+ end process;
+ do <= doReg;
+
+
+
+-- -----------------------------------------------------------------------
+-- Write enable
+-- -----------------------------------------------------------------------
+calcWe: process(clk)
+ begin
+ if rising_edge(clk) then
+ if enable = '1' then
+ theWe <= '0';
+ case nextCpuCycle is
+ when cycleStack1 =>
+ if opcInfo(opcStackUp) = '0'
+ and ((opcInfo(opcStackAddr) = '0')
+ or (opcInfo(opcStackData) = '1')) then
+ theWe <= '1';
+ end if;
+ when cycleStack2 | cycleStack3 | cycleStack4 =>
+ if opcInfo(opcStackUp) = '0' then
+ theWe <= '1';
+ end if;
+ when cycleRmw =>
+ theWe <= '1';
+ when cycleWrite =>
+ theWe <= '1';
+ when others =>
+ null;
+ end case;
+ end if;
+ end if;
+ end process;
+ we <= theWe;
+
+-- -----------------------------------------------------------------------
+-- Program counter
+-- -----------------------------------------------------------------------
+calcPC: process(clk)
+ begin
+ if rising_edge(clk) then
+ if enable = '1' then
+ case theCpuCycle is
+ when opcodeFetch =>
+ PC <= myAddr;
+ when cycle2 =>
+ if irqActive = '0' then
+ if opcInfo(opcSecondByte) = '1' then
+ PC <= myAddrIncr;
+ else
+ PC <= myAddr;
+ end if;
+ end if;
+ when cycle3 =>
+ if opcInfo(opcAbsolute) = '1' then
+ PC <= myAddrIncr;
+ end if;
+ when others =>
+ null;
+ end case;
+ end if;
+ end if;
+ end process;
+ debugPc <= PC;
+
+-- -----------------------------------------------------------------------
+-- Address generation
+-- -----------------------------------------------------------------------
+calcNextAddr: process(theCpuCycle, opcInfo, indexOut, T, reset)
+ begin
+ nextAddr <= nextAddrIncr;
+ case theCpuCycle is
+ when cycle2 =>
+ if opcInfo(opcStackAddr) = '1'
+ or opcInfo(opcStackData) = '1' then
+ nextAddr <= nextAddrStack;
+ elsif opcInfo(opcAbsolute) = '1' then
+ nextAddr <= nextAddrIncr;
+ elsif opcInfo(opcZeroPage) = '1' then
+ nextAddr <= nextAddrZeroPage;
+ elsif opcInfo(opcIndirect) = '1' then
+ nextAddr <= nextAddrZeroPage;
+ elsif opcInfo(opcSecondByte) = '1' then
+ nextAddr <= nextAddrIncr;
+ else
+ nextAddr <= nextAddrHold;
+ end if;
+ when cycle3 =>
+ if (opcInfo(opcIndirect) = '1')
+ and (opcInfo(indexX) = '1') then
+ nextAddr <= nextAddrAbs;
+ else
+ nextAddr <= nextAddrAbsIndexed;
+ end if;
+ when cyclePreIndirect =>
+ nextAddr <= nextAddrZPIndexed;
+ when cycleIndirect =>
+ nextAddr <= nextAddrIncrL;
+ when cycleBranchTaken =>
+ nextAddr <= nextAddrRelative;
+ when cycleBranchPage =>
+ if T(7) = '0' then
+ nextAddr <= nextAddrIncrH;
+ else
+ nextAddr <= nextAddrDecrH;
+ end if;
+ when cyclePreRead =>
+ nextAddr <= nextAddrZPIndexed;
+ when cycleRead =>
+ nextAddr <= nextAddrPc;
+ if opcInfo(opcJump) = '1' then
+ -- Emulate 6510 bug, jmp(xxFF) fetches from same page.
+ -- Replace with nextAddrIncr if emulating 65C02 or later cpu.
+ nextAddr <= nextAddrIncrL;
+ elsif indexOut(8) = '1' then
+ nextAddr <= nextAddrIncrH;
+ elsif opcInfo(opcRmw) = '1' then
+ nextAddr <= nextAddrHold;
+ end if;
+ when cycleRead2 =>
+ nextAddr <= nextAddrPc;
+ if opcInfo(opcRmw) = '1' then
+ nextAddr <= nextAddrHold;
+ end if;
+ when cycleRmw =>
+ nextAddr <= nextAddrHold;
+ when cyclePreWrite =>
+ nextAddr <= nextAddrHold;
+ if opcInfo(opcZeroPage) = '1' then
+ nextAddr <= nextAddrZPIndexed;
+ elsif indexOut(8) = '1' then
+ nextAddr <= nextAddrIncrH;
+ end if;
+ when cycleWrite =>
+ nextAddr <= nextAddrPc;
+ when cycleStack1 =>
+ nextAddr <= nextAddrStack;
+ when cycleStack2 =>
+ nextAddr <= nextAddrStack;
+ when cycleStack3 =>
+ nextAddr <= nextAddrStack;
+ if opcInfo(opcStackData) = '0' then
+ nextAddr <= nextAddrPc;
+ end if;
+ when cycleStack4 =>
+ nextAddr <= nextAddrIrq;
+ when cycleJump =>
+ nextAddr <= nextAddrAbs;
+ when others =>
+ null;
+ end case;
+ if reset = '1' then
+ nextAddr <= nextAddrReset;
+ end if;
+ end process;
+
+indexAlu: process(opcInfo, myAddr, T, X, Y)
+ begin
+ if opcInfo(indexX) = '1' then
+ indexOut <= (B"0" & T) + (B"0" & X);
+ elsif opcInfo(indexY) = '1' then
+ indexOut <= (B"0" & T) + (B"0" & Y);
+ elsif opcInfo(opcBranch) = '1' then
+ indexOut <= (B"0" & T) + (B"0" & myAddr(7 downto 0));
+ else
+ indexOut <= B"0" & T;
+ end if;
+ end process;
+
+calcAddr: process(clk)
+ begin
+ if rising_edge(clk) then
+ if enable = '1' then
+ case nextAddr is
+ when nextAddrIncr => myAddr <= myAddrIncr;
+ when nextAddrIncrL => myAddr(7 downto 0) <= myAddrIncr(7 downto 0);
+ when nextAddrIncrH => myAddr(15 downto 8) <= myAddrIncrH;
+ when nextAddrDecrH => myAddr(15 downto 8) <= myAddrDecrH;
+ when nextAddrPc => myAddr <= PC;
+ when nextAddrIrq =>
+ myAddr <= X"FFFE";
+ if nmiReg = '0' then
+ myAddr <= X"FFFA";
+ end if;
+ when nextAddrReset => myAddr <= X"FFFC";
+ when nextAddrAbs => myAddr <= di & T;
+ when nextAddrAbsIndexed => myAddr <= di & indexOut(7 downto 0);
+ when nextAddrZeroPage => myAddr <= "00000000" & di;
+ when nextAddrZPIndexed => myAddr <= "00000000" & indexOut(7 downto 0);
+ when nextAddrStack => myAddr <= "00000001" & S;
+ when nextAddrRelative => myAddr(7 downto 0) <= indexOut(7 downto 0);
+ when others => null;
+ end case;
+ end if;
+ end if;
+ end process;
+
+ myAddrIncr <= myAddr + 1;
+ myAddrIncrH <= myAddr(15 downto 8) + 1;
+ myAddrDecrH <= myAddr(15 downto 8) - 1;
+
+ addr <= myAddr;
+
+ debugA <= A;
+ debugX <= X;
+ debugY <= Y;
+ debugS <= S;
+
+end architecture;
+
+
diff --git a/common/CPU/syntiac6502_6510/cpu_6510.vhd b/common/CPU/syntiac6502_6510/cpu_6510.vhd
new file mode 100644
index 00000000..a1a8d2ba
--- /dev/null
+++ b/common/CPU/syntiac6502_6510/cpu_6510.vhd
@@ -0,0 +1,150 @@
+-- -----------------------------------------------------------------------
+--
+-- FPGA 64
+--
+-- A fully functional commodore 64 implementation in a single FPGA
+--
+-- -----------------------------------------------------------------------
+-- Copyright 2005-2008 by Peter Wendrich (pwsoft@syntiac.com)
+-- http://www.syntiac.com/fpga64.html
+-- -----------------------------------------------------------------------
+--
+-- 6510 wrapper for 65xx core
+-- Adds 8 bit I/O port mapped at addresses $0000 to $0001
+--
+-- -----------------------------------------------------------------------
+
+library IEEE;
+use ieee.std_logic_1164.ALL;
+use ieee.numeric_std.ALL;
+
+-- -----------------------------------------------------------------------
+
+entity cpu_6510 is
+ generic (
+ pipelineOpcode : boolean;
+ pipelineAluMux : boolean;
+ pipelineAluOut : boolean
+ );
+ port (
+ clk : in std_logic;
+ enable : in std_logic;
+ reset : in std_logic;
+ nmi_n : in std_logic;
+ nmi_ack : out std_logic;
+ irq_n : in std_logic;
+
+ di : in unsigned(7 downto 0);
+ do : out unsigned(7 downto 0);
+ addr : out unsigned(15 downto 0);
+ we : out std_logic;
+
+ diIO : in unsigned(7 downto 0);
+ doIO : out unsigned(7 downto 0);
+
+ debugOpcode : out unsigned(7 downto 0);
+ debugPc : out unsigned(15 downto 0);
+ debugA : out unsigned(7 downto 0);
+ debugX : out unsigned(7 downto 0);
+ debugY : out unsigned(7 downto 0);
+ debugS : out unsigned(7 downto 0)
+ );
+end cpu_6510;
+
+-- -----------------------------------------------------------------------
+
+architecture rtl of cpu_6510 is
+ signal localA : unsigned(15 downto 0);
+ signal localDi : unsigned(7 downto 0);
+ signal localDo : unsigned(7 downto 0);
+ signal localWe : std_logic;
+
+ signal currentIO : unsigned(7 downto 0);
+ signal ioDir : unsigned(7 downto 0);
+ signal ioData : unsigned(7 downto 0);
+
+ signal accessIO : std_logic;
+begin
+ cpuInstance: entity work.cpu65xx(fast)
+ generic map (
+ pipelineOpcode => pipelineOpcode,
+ pipelineAluMux => pipelineAluMux,
+ pipelineAluOut => pipelineAluOut
+ )
+ port map (
+ clk => clk,
+ enable => enable,
+ reset => reset,
+ nmi_n => nmi_n,
+ nmi_ack => nmi_ack,
+ irq_n => irq_n,
+
+ di => localDi,
+ do => localDo,
+ addr => localA,
+ we => localWe,
+
+ debugOpcode => debugOpcode,
+ debugPc => debugPc,
+ debugA => debugA,
+ debugX => debugX,
+ debugY => debugY,
+ debugS => debugS
+ );
+
+ process(localA)
+ begin
+ accessIO <= '0';
+ if localA(15 downto 1) = 0 then
+ accessIO <= '1';
+ end if;
+ end process;
+
+ process(di, localA, ioDir, currentIO, accessIO)
+ begin
+ localDi <= di;
+ if accessIO = '1' then
+ if localA(0) = '0' then
+ localDi <= ioDir;
+ else
+ localDi <= currentIO;
+ end if;
+ end if;
+ end process;
+
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if accessIO = '1' then
+ if localWe = '1'
+ and enable = '1' then
+ if localA(0) = '0' then
+ ioDir <= localDo;
+ else
+ ioData <= localDo;
+ end if;
+ end if;
+ end if;
+ if reset = '1' then
+ ioDir <= (others => '0');
+ end if;
+ end if;
+ end process;
+
+ process(ioDir, ioData, diIO)
+ begin
+ for i in 0 to 7 loop
+ if ioDir(i) = '0' then
+ currentIO(i) <= diIO(i);
+ else
+ currentIO(i) <= ioData(i);
+ end if;
+ end loop;
+ end process;
+
+ -- Cunnect zee wires
+ addr <= localA;
+ do <= localDo;
+ we <= localWe;
+ doIO <= currentIO;
+end architecture;
diff --git a/common/CPU/t48/COPYING b/common/CPU/t48/COPYING
new file mode 100644
index 00000000..60549be5
--- /dev/null
+++ b/common/CPU/t48/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C) 19yy
+
+ 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 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ , 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/common/CPU/t48/README b/common/CPU/t48/README
new file mode 100644
index 00000000..eaf9b150
--- /dev/null
+++ b/common/CPU/t48/README
@@ -0,0 +1,263 @@
+
+README for the T48 uController project
+======================================
+Version: $Date: 2006/07/16 01:59:23 $
+$Name: $
+
+
+Introduction
+------------
+
+The T48 Controller core is an implementation of the MCS-48 microcontroller
+family architecture. While being a controller core for SoC, it also aims for
+code-compatability and cycle-accuracy so that it can be used as a drop-in
+replacement for any MCS-48 controller.
+It can be configured to better suit the requirements and characteristics of
+the integrating system. On the other hand, nearly the full functionality of a
+stock 8048/8049 is available.
+
+
+Download
+--------
+
+Download the latest stable release from the project homepage at OpenCores.org:
+
+ http://www.opencores.org/projects.cgi/web/t48/overview/
+
+You can get the latest version of the design files from CVS:
+
+ http://www.opencores.org/pdownloads.cgi/list/t48
+
+Please keep in mind that this is work in progress and might contain smaller or
+bigger problems.
+You should also check the Tracker for known bugs and see if they affect your
+work.
+
+
+Installation
+------------
+
+Once the directory structure is generated either by check-out from CVS or by
+unpacking the tar-archive, the central project initialization file should be
+set up. A template called init_project.template.sh is located in the sw
+directory where a copy can be edited. Normally, only the definition for the
+variable PROJECT_DIR has to be adjusted to the path where the directory
+structure is located.
+The commands for setting the necessary variables assume a bash/sh-like
+shell. In case you run a different shell like csh or ksh, you should adjust
+these commands as well.
+
+The meaning of the variables is as follows:
+
+ * PROJECT_DIR
+ Points to the root of the project installation. All further references are
+ derived from its setting.
+
+ * VERIF_DIR
+ Location of the verification suite.
+
+ * SIM_DIR
+ Directory for running simulations.
+
+These variables must be properly set whenever scripts or makefiles of the T48
+project are executed. Otherwise, you will most likely encounter error
+messages.
+
+NOTE: The concepts of the mentioned shells require that the init_project.sh is
+ run in the context of the shell. I.e. you should 'source' the script
+ instead of executing it like a command. This will make sure that the
+ variable settings are really effective in the calling shell instance.
+
+
+Directory Structure
+-------------------
+
+The project's directory structure follows the proposal of OpenCores.org.
+
+t48
+ |
+ \--+-- rtl
+ | |
+ | \-- vhdl : VHDL code containing the RTL description
+ | | of the core.
+ | +-- system : RTL VHDL code of sample systems.
+ | |
+ | \-- t8243 : RTL VHDL code of 8243 core.
+ |
+ +-- bench
+ | |
+ | \-- vhdl : VHDL testbench code.
+ |
+ +-- sim
+ | |
+ | \-- rtl_sim : Directory for running simulations.
+ |
+ \-- sw : General purpose scripts and files.
+ |
+ +-- i8039emu : An MCS-48 emulator written in C.
+ |
+ \-- verif : The verification suite.
+ |
+ +-- include : Global includes and makefiles.
+ |
+ +-- black_box : Black-box verification tests.
+ |
+ +-- white_box : White-box verification tests.
+ |
+ \-- gp_sw : General purpose software.
+
+
+Compiling the VHDL Code
+-----------------------
+
+VHDL compilation and simulation tasks take place inside in sim/rtl_sim
+directory. The project setup supports only the batch mode of certain
+simulators. However, there should be no problems to integrate the testbench
+and RTL code into arbitrary simulation environments.
+
+The main file for compilation is Makefile.hier which contains all information
+regarding the dependencies of the source files and their compilation
+order. There is a dedicated file for each supported simulator that maps the
+generic information of Makefile.hier to object files specific to the given
+simulator.
+
+Compilation is based on the make-utility, thus invocation looks like this:
+
+$ make -f Makefile.
+
+where denotes one of the supported simulators:
+
+ * Makefile.ghdl
+ Tristan Gingold's GHDL simulator/compiler, a VHDL front-end for gcc.
+ http://ghdl.free.fr/
+
+ * Makefile.simili
+ DISCONTINUED
+ VHDL Simili, a VHDL simulator by Symphony EDA
+ http://www.symphonyeda.com/
+
+Make will analyze all VHDL files (RTL and testbench code) and elaborate all
+three testbench top-levels if appropriate for the chosen simulator:
+
+ * tb_behav_c0
+ The main testbench for regression testing.
+ Instantiates the plain t48_core and provides internal RAM (256 bytes) and
+ ROM (2k bytes) plus 2k bytes of external ROM.
+
+ * tb_t8048_behav_c0
+ The testbench for the t8048 sample system.
+
+ * tb_t8039_behav_c0
+ The testbench for the 8039 sample system.
+
+ * tb_t8243_behav_c0
+ Testbench containing the t48_core and the synchronous t8243 flavour.
+
+ * tb_t8048_t8243_behav_c0
+ Testbench containing the t8048 and the asynchronous t8243 toplevel.
+
+Each Makefile has a 'clean' target to delete all intermediate data:
+
+$ make -f Makefile. clean
+
+The basic simple sequence list can be found in COMPILE_LIST. This can be
+useful to quickly set up the analyze stage of any compiler or
+synthesizer. Especially when synthesizing the code, you want to skip the VHDL
+configurations in *-c.vhd and everything below the bench/ directory.
+
+Preparation of the ROM Files
+----------------------------
+
+All testbenches listed above need two files in hex-format. They contain the
+program for the T48 core and are loaded into internal and external ROM at
+simulation startup. Their existance is mandatory as they are referenced in the
+VHDL code of the ROM model lpm_rom.vhd. In case they are missing, the
+simulation will stop immediately after elaborating the design.
+
+These files are:
+
+ * rom_t49.hex
+ Internal ROM contents for 8x49 derivatives,
+ address range 000H to 7FFH.
+ Intel hex format, starting at address 000H.
+
+ * rom_t49_ext.hex
+ External ROM contents for t8x49 derivatives,
+ address range 800H to FFFH.
+ Intel hex format, starting at address 800H.
+
+ * rom_t48.hex
+ Internal ROM contents for t8x48 derivatives,
+ address range 000H to 3FFH.
+ Intel hex format, starting at address 000H.
+
+ * rom_t48_ext.hex
+ External ROM contents for t8x48 derivatives,
+ address range 400H to FFFH.
+ Intel hex format, starting at address 000H.
+
+ * rom_t3x.hex
+ Internal ROM contents for t803x derivatives,
+ empty.
+
+ * rom_t3x_ext.hex
+ External ROM contents for t803x derivatives,
+ address range 000H to FFFH.
+ Intel hex format, starting at address 000H.
+
+The verification flow for the T48 project generates these files
+automatically from the assembler source files.
+
+All regression tests and the general purpose software is organized in a cell
+structure. Currently, this means that the software for a cell is contained in
+a dedicated directory where the assembler run takes place. In the future,
+there will be more aspects to a cell.
+
+Assembling, linking and putting the hex-files in place is under the control of
+the make-mechanism. E.g. to assemble the source code of a cell, issue the
+following command:
+
+$ make -f $VERIF_DIR/include/Makefile.cell
+
+This generates the linker file (test.p) and distributes its contents to the
+required ROM files for internal and external program ROM. The target 'simu'
+copies these files automatically to the simulation directory. So most likely,
+for running a test case or any other software, you will want to issue:
+
+$ make -f VERIF_DIR/include/Makefile.cell simu clean
+
+The only supported assembler is Alfred Arnold's macroassembler AS. See
+
+ http://john.ccac.rwth-aachen.de:8000/as/
+
+
+Verification Environment
+------------------------
+
+The verification environment consists of a number of test programs. They are
+all self-checking. I.e. after testing the targeted functionality, they emit a
+pass/fail information. This information is detected by the testbench which
+stops the simulation and prints out the simulation result. This is the default
+mechanism for stopping the VHDL simulation.
+
+Pass/fail is signalled by a certain sequence of the accumulator contents:
+
+ 1) Accumulator contains AAH
+ 2) Accumulator contains 55H
+ 3) Accumulator contains 01H -> Pass
+ Accumulator contains 00H -> Fail
+
+The detection is modelled like a state machine and in case the sequence is of
+bytes inside the accumulator does not match, the detection process restarts
+from the beginning. This mechanism is part of all verification tests.
+
+The complete regression suite can be executed with the run_regression.pl
+script. For each test cell, it steps through the sequence
+
+ 1) Assemble the source code
+ 2) Run the compiled VHDL design (currently only GHDL)
+ 3) Optionally perform a dump compare against the C-model
+
+It is highly recommended to redirect the output of run_regression.pl into a
+file. Otherwise, analyzing the messages related to each test cell is almost
+impossible.
diff --git a/common/CPU/t48/rtl/vhdl/alu-c.vhd b/common/CPU/t48/rtl/vhdl/alu-c.vhd
new file mode 100644
index 00000000..93fe8528
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/alu-c.vhd
@@ -0,0 +1,19 @@
+-------------------------------------------------------------------------------
+--
+-- The Arithmetic Logic Unit (ALU).
+-- It contains the ALU core plus the Accumulator and the Temp Reg.
+--
+-- $Id: alu-c.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+configuration t48_alu_rtl_c0 of t48_alu is
+
+ for rtl
+ end for;
+
+end t48_alu_rtl_c0;
diff --git a/common/CPU/t48/rtl/vhdl/alu.vhd b/common/CPU/t48/rtl/vhdl/alu.vhd
new file mode 100644
index 00000000..140bd4c8
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/alu.vhd
@@ -0,0 +1,449 @@
+-------------------------------------------------------------------------------
+--
+-- The Arithmetic Logic Unit (ALU).
+-- It contains the ALU core plus the Accumulator and the Temp Reg.
+--
+-- $Id: alu.vhd,v 1.9 2005/06/11 10:08:43 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.word_t;
+use work.t48_alu_pack.alu_op_t;
+
+entity t48_alu is
+
+ port (
+ -- Global Interface -------------------------------------------------------
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ -- T48 Bus Interface ------------------------------------------------------
+ data_i : in word_t;
+ data_o : out word_t;
+ write_accu_i : in boolean;
+ write_shadow_i : in boolean;
+ write_temp_reg_i : in boolean;
+ read_alu_i : in boolean;
+ -- Decoder Interface ------------------------------------------------------
+ carry_i : in std_logic;
+ carry_o : out std_logic;
+ aux_carry_o : out std_logic;
+ alu_op_i : in alu_op_t;
+ use_carry_i : in boolean;
+ da_high_i : in boolean;
+ da_overflow_o : out boolean;
+ accu_low_i : in boolean;
+ p06_temp_reg_i : in boolean;
+ p60_temp_reg_i : in boolean
+ );
+
+end t48_alu;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+use work.t48_pack.clk_active_c;
+use work.t48_pack.res_active_c;
+use work.t48_pack.bus_idle_level_c;
+use work.t48_pack.nibble_t;
+use work.t48_alu_pack.all;
+
+-- pragma translate_off
+use work.t48_tb_pack.tb_accu_s;
+-- pragma translate_on
+
+architecture rtl of t48_alu is
+
+ -- the Accumulator and Temp Reg
+ signal accumulator_q,
+ accu_shadow_q,
+ temp_req_q : word_t;
+ -- inputs to the ALU core
+ signal in_a_s,
+ in_b_s : word_t;
+ -- output of the ALU core
+ signal data_s : word_t;
+
+ signal add_result_s : alu_operand_t;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process working_regs
+ --
+ -- Purpose:
+ -- Implements the working registers:
+ -- + Accumulator
+ -- + Temp Reg
+ --
+ working_regs: process (res_i, clk_i)
+ begin
+ if res_i = res_active_c then
+ accumulator_q <= (others => '0');
+ accu_shadow_q <= (others => '0');
+ temp_req_q <= (others => '0');
+
+ elsif clk_i'event and clk_i = clk_active_c then
+ if en_clk_i then
+
+ if write_accu_i then
+ if accu_low_i then
+ accumulator_q(nibble_t'range) <= data_i(nibble_t'range);
+ else
+ accumulator_q <= data_i;
+ end if;
+ end if;
+
+ if write_shadow_i then
+ -- write shadow directly from t48 data bus
+ accu_shadow_q <= data_i;
+ else
+ -- default: update shadow Accumulator from real Accumulator
+ accu_shadow_q <= accumulator_q;
+ end if;
+
+ if p06_temp_reg_i then
+ -- low nibble of DA sequence
+ temp_req_q <= "00000110";
+ elsif p60_temp_reg_i then
+ -- high nibble of DA sequence
+ temp_req_q <= "01100000";
+ elsif write_temp_reg_i then
+ -- normal load from T48 bus
+ temp_req_q <= data_i;
+ end if;
+
+ end if;
+
+ end if;
+
+ end process working_regs;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Build the inputs to the ALU core.
+ -- Input A:
+ -- Unary operators use only Input A.
+ -- Is always fed from the shadow Accumulator.
+ -- Assumption: It never happens that the Accumulator is written and then
+ -- read for an ALU operation in the next cycle.
+ -- Its contents can thus be staged through the shadow Accu.
+ -- Input B:
+ -- Is always fed from the Temp Reg.
+ -----------------------------------------------------------------------------
+ in_a_s <= accu_shadow_q;
+ in_b_s <= temp_req_q;
+
+
+ -----------------------------------------------------------------------------
+ -- Process alu_core
+ --
+ -- Purpose:
+ -- Implements the ALU core.
+ -- All operations defined in alu_op_t are handled here.
+ --
+ alu_core: process (in_a_s,
+ in_b_s,
+ alu_op_i,
+ carry_i,
+ use_carry_i,
+ add_result_s)
+
+ begin
+ -- default assigments
+ data_s <= (others => '0');
+ carry_o <= '0';
+
+ case alu_op_i is
+ -- Operation: AND -------------------------------------------------------
+ when ALU_AND =>
+ data_s <= in_a_s and in_b_s;
+
+ -- Operation: OR --------------------------------------------------------
+ when ALU_OR =>
+ data_s <= in_a_s or in_b_s;
+
+ -- Operation: XOR -------------------------------------------------------
+ when ALU_XOR =>
+ data_s <= in_a_s xor in_b_s;
+
+ -- Operation: Add -------------------------------------------------------
+ when ALU_ADD =>
+ data_s <= add_result_s(data_s'range);
+ carry_o <= add_result_s(add_result_s'high);
+
+ -- Operation: CPL -------------------------------------------------------
+ when ALU_CPL =>
+ data_s <= not in_a_s;
+
+ -- Operation: CLR -------------------------------------------------------
+ when ALU_CLR =>
+ data_s <= (others => '0');
+
+ -- Operation: RL --------------------------------------------------------
+ when ALU_RL =>
+ data_s(7 downto 1) <= in_a_s(6 downto 0);
+ carry_o <= in_a_s(7);
+
+ if use_carry_i then
+ data_s(0) <= carry_i;
+ else
+ data_s(0) <= in_a_s(7);
+ end if;
+
+ -- Operation: RR --------------------------------------------------------
+ when ALU_RR =>
+ data_s(6 downto 0) <= in_a_s(7 downto 1);
+ carry_o <= in_a_s(0);
+
+ if use_carry_i then
+ data_s(7) <= carry_i;
+ else
+ data_s(7) <= in_a_s(0);
+ end if;
+
+ -- Operation: Swap ------------------------------------------------------
+ when ALU_SWAP =>
+ data_s(3 downto 0) <= in_a_s(7 downto 4);
+ data_s(7 downto 4) <= in_a_s(3 downto 0);
+
+ -- Operation: DEC -------------------------------------------------------
+ when ALU_DEC =>
+ data_s <= add_result_s(data_s'range);
+
+ -- Operation: INC -------------------------------------------------------
+ when ALU_INC =>
+ data_s <= add_result_s(data_s'range);
+
+ -- Operation CONCAT -----------------------------------------------------
+ when ALU_CONCAT =>
+ data_s <= in_b_s(7 downto 4) & in_a_s(3 downto 0);
+
+ -- Operation: NOP -------------------------------------------------------
+ when ALU_NOP =>
+ data_s <= in_a_s;
+
+ when others =>
+ -- pragma translate_off
+ assert false
+ report "Unknown ALU operation selected!"
+ severity error;
+ -- pragma translate_on
+
+ end case;
+
+ end process alu_core;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process adder
+ --
+ -- Purpose:
+ -- Implements the adder used by several instructions.
+ -- This way of modelling the adder forces resource sharing of:
+ -- * ADD
+ -- * INC
+ -- * DEC
+ --
+ adder: process (in_a_s,
+ in_b_s,
+ alu_op_i,
+ carry_i,
+ use_carry_i)
+
+ variable add_a_v, add_b_v : alu_operand_t;
+ variable c_v : alu_operand_t;
+ variable result_v : UNSIGNED(alu_operand_t'range);
+ variable aux_c_v : std_logic_vector(1 downto 0);
+
+ begin
+ -- Carry Selection --------------------------------------------------------
+ c_v := (others => '0');
+ if use_carry_i and carry_i = '1' then
+ c_v(0) := '1';
+ end if;
+
+ -- Operand Selection ------------------------------------------------------
+ -- defaults for ADD
+ add_a_v := '0' & in_a_s;
+ add_b_v := '0' & in_b_s;
+
+ case alu_op_i is
+ when ALU_INC =>
+ add_b_v := (others => '0');
+ add_b_v(0) := '1';
+ when ALU_DEC =>
+ add_b_v := (others => '1');
+ when others =>
+ null;
+ end case;
+
+ -- The Adder --------------------------------------------------------------
+ result_v := UNSIGNED(add_a_v) +
+ UNSIGNED(add_b_v) +
+ UNSIGNED(c_v);
+
+ add_result_s <= std_logic_vector(result_v);
+
+ -- Auxiliary Carry --------------------------------------------------------
+ aux_c_v := in_a_s(4) & in_b_s(4);
+
+ aux_carry_o <= '0';
+ case aux_c_v is
+ when "00" | "11" =>
+ if result_v(4) = '1' then
+ aux_carry_o <= '1';
+ end if;
+
+ when "01" | "10" =>
+ if result_v(4) = '0' then
+ aux_carry_o <= '1';
+ end if;
+
+ when others =>
+ null;
+
+ end case;
+
+ end process adder;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process da_overflow
+ --
+ -- Purpose:
+ -- Detect overflow situation during DA sequence.
+ --
+ da_overflow: process (accu_shadow_q,
+ da_high_i)
+
+ variable da_nibble_v : nibble_t;
+
+ function da_overflow_f(data : in nibble_t) return boolean is
+ variable overflow_v : boolean;
+ begin
+ case data is
+ when "1010" |
+ "1011" |
+ "1100" |
+ "1101" |
+ "1110" |
+ "1111" =>
+ overflow_v := true;
+ when others =>
+ overflow_v := false;
+ end case;
+
+ return(overflow_v);
+ end;
+
+ begin
+ if da_high_i then
+ da_nibble_v := accu_shadow_q(7 downto 4);
+ else
+ da_nibble_v := accu_shadow_q(3 downto 0);
+ end if;
+
+ da_overflow_o <= da_overflow_f(da_nibble_v);
+
+ end process da_overflow;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -- pragma translate_off
+ -----------------------------------------------------------------------------
+ -- Testbench support.
+ -----------------------------------------------------------------------------
+ tb_accu_s <= accumulator_q;
+ -- pragma translate_on
+
+ -----------------------------------------------------------------------------
+ -- Output Multiplexer.
+ -----------------------------------------------------------------------------
+ data_o <= data_s
+ when read_alu_i else
+ (others => bus_idle_level_c);
+
+end rtl;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: alu.vhd,v $
+-- Revision 1.9 2005/06/11 10:08:43 arniml
+-- introduce prefix 't48_' for all packages, entities and configurations
+--
+-- Revision 1.8 2004/04/24 23:43:56 arniml
+-- move from std_logic_arith to numeric_std
+--
+-- Revision 1.7 2004/04/07 22:09:03 arniml
+-- remove unused signals
+--
+-- Revision 1.6 2004/04/07 20:56:23 arniml
+-- default assignment for aux_carry_o
+--
+-- Revision 1.5 2004/04/06 20:21:53 arniml
+-- fix sensitivity list
+--
+-- Revision 1.4 2004/04/06 18:10:41 arniml
+-- rework adder and force resource sharing between ADD, INC and DEC
+--
+-- Revision 1.3 2004/04/04 14:18:52 arniml
+-- add measures to implement XCHD
+--
+-- Revision 1.2 2004/03/28 21:08:51 arniml
+-- support for DA instruction
+--
+-- Revision 1.1 2004/03/23 21:31:52 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/CPU/t48/rtl/vhdl/alu_pack-p.vhd b/common/CPU/t48/rtl/vhdl/alu_pack-p.vhd
new file mode 100644
index 00000000..71c1e4ba
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/alu_pack-p.vhd
@@ -0,0 +1,51 @@
+-------------------------------------------------------------------------------
+--
+-- $Id: alu_pack-p.vhd,v 1.3 2005/06/11 10:08:43 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.word_width_c;
+
+package t48_alu_pack is
+
+ -----------------------------------------------------------------------------
+ -- The ALU operations
+ -----------------------------------------------------------------------------
+ type alu_op_t is (ALU_AND, ALU_OR, ALU_XOR,
+ ALU_CPL, ALU_CLR,
+ ALU_RL, ALU_RR,
+ ALU_SWAP,
+ ALU_DEC, ALU_INC,
+ ALU_ADD,
+ ALU_CONCAT,
+ ALU_NOP);
+
+ -----------------------------------------------------------------------------
+ -- The dedicated ALU arithmetic types.
+ -----------------------------------------------------------------------------
+ subtype alu_operand_t is std_logic_vector(word_width_c downto 0);
+
+end t48_alu_pack;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: alu_pack-p.vhd,v $
+-- Revision 1.3 2005/06/11 10:08:43 arniml
+-- introduce prefix 't48_' for all packages, entities and configurations
+--
+-- Revision 1.2 2004/04/04 14:18:53 arniml
+-- add measures to implement XCHD
+--
+-- Revision 1.1 2004/03/23 21:31:52 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/CPU/t48/rtl/vhdl/bus_mux-c.vhd b/common/CPU/t48/rtl/vhdl/bus_mux-c.vhd
new file mode 100644
index 00000000..ccec86af
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/bus_mux-c.vhd
@@ -0,0 +1,19 @@
+-------------------------------------------------------------------------------
+--
+-- The T48 Bus Connector.
+-- Multiplexes all drivers of the T48 bus.
+--
+-- $Id: bus_mux-c.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+configuration t48_bus_mux_rtl_c0 of t48_bus_mux is
+
+ for rtl
+ end for;
+
+end t48_bus_mux_rtl_c0;
diff --git a/common/CPU/t48/rtl/vhdl/bus_mux.vhd b/common/CPU/t48/rtl/vhdl/bus_mux.vhd
new file mode 100644
index 00000000..8d09b331
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/bus_mux.vhd
@@ -0,0 +1,113 @@
+-------------------------------------------------------------------------------
+--
+-- The T48 Bus Connector.
+-- Multiplexes all drivers of the T48 bus.
+--
+-- $Id: bus_mux.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.word_t;
+
+entity t48_bus_mux is
+
+ port (
+ alu_data_i : in word_t;
+ bus_data_i : in word_t;
+ dec_data_i : in word_t;
+ dm_data_i : in word_t;
+ pm_data_i : in word_t;
+ p1_data_i : in word_t;
+ p2_data_i : in word_t;
+ psw_data_i : in word_t;
+ tim_data_i : in word_t;
+ data_o : out word_t
+ );
+
+end t48_bus_mux;
+
+
+use work.t48_pack.bus_idle_level_c;
+
+architecture rtl of t48_bus_mux is
+
+begin
+
+ or_tree: if bus_idle_level_c = '0' generate
+ data_o <= alu_data_i or
+ bus_data_i or
+ dec_data_i or
+ dm_data_i or
+ pm_data_i or
+ p1_data_i or
+ p2_data_i or
+ psw_data_i or
+ tim_data_i;
+ end generate;
+
+ and_tree: if bus_idle_level_c = '1' generate
+ data_o <= alu_data_i and
+ bus_data_i and
+ dec_data_i and
+ dm_data_i and
+ pm_data_i and
+ p1_data_i and
+ p2_data_i and
+ psw_data_i and
+ tim_data_i;
+ end generate;
+
+end rtl;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: bus_mux.vhd,v $
+-- Revision 1.2 2005/06/11 10:08:43 arniml
+-- introduce prefix 't48_' for all packages, entities and configurations
+--
+-- Revision 1.1 2004/03/23 21:31:52 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/CPU/t48/rtl/vhdl/clock_ctrl-c.vhd b/common/CPU/t48/rtl/vhdl/clock_ctrl-c.vhd
new file mode 100644
index 00000000..b36b70eb
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/clock_ctrl-c.vhd
@@ -0,0 +1,14 @@
+-------------------------------------------------------------------------------
+--
+-- $Id: clock_ctrl-c.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $
+--
+-- The clock control unit.
+--
+-------------------------------------------------------------------------------
+
+configuration t48_clock_ctrl_rtl_c0 of t48_clock_ctrl is
+
+ for rtl
+ end for;
+
+end t48_clock_ctrl_rtl_c0;
diff --git a/common/CPU/t48/rtl/vhdl/clock_ctrl.vhd b/common/CPU/t48/rtl/vhdl/clock_ctrl.vhd
new file mode 100644
index 00000000..3fd967ee
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/clock_ctrl.vhd
@@ -0,0 +1,449 @@
+-------------------------------------------------------------------------------
+--
+-- The Clock Control unit.
+-- Clock States and Machine Cycles are generated here.
+--
+-- $Id: clock_ctrl.vhd,v 1.12 2006/07/14 01:04:35 arniml Exp $
+--
+-- Copyright (c) 2004, 2005, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.all;
+
+entity t48_clock_ctrl is
+
+ generic (
+ -- divide XTAL1 by 3 to derive Clock States
+ xtal_div_3_g : integer := 1
+ );
+
+ port (
+ clk_i : in std_logic;
+ xtal_i : in std_logic;
+ xtal_en_i : in boolean;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ xtal3_o : out boolean;
+ t0_o : out std_logic;
+ multi_cycle_i : in boolean;
+ assert_psen_i : in boolean;
+ assert_prog_i : in boolean;
+ assert_rd_i : in boolean;
+ assert_wr_i : in boolean;
+ mstate_o : out mstate_t;
+ second_cycle_o : out boolean;
+ ale_o : out boolean;
+ psen_o : out boolean;
+ prog_o : out boolean;
+ rd_o : out boolean;
+ wr_o : out boolean
+ );
+
+end t48_clock_ctrl;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+architecture rtl of t48_clock_ctrl is
+
+ -- The three XTAL1 cycles.
+ signal xtal_q : unsigned(1 downto 0);
+ signal xtal1_s,
+ xtal2_s,
+ xtal3_s : boolean;
+ signal x1_s,
+ x2_s,
+ x3_s : std_logic;
+
+ signal t0_q : std_logic;
+
+
+ -- The five clock states.
+ signal mstate_q : mstate_t;
+
+ signal ale_q : boolean;
+ signal psen_q : boolean;
+ signal prog_q : boolean;
+ signal rd_q : boolean;
+ signal wr_q : boolean;
+
+
+ -- The Machine Cycle marker.
+ signal second_cycle_q : boolean;
+ signal multi_cycle_q : boolean;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Verify the generics
+ -----------------------------------------------------------------------------
+
+ -- pragma translate_off
+
+ -- XTAL1 divide by 3 --------------------------------------------------------
+ assert (xtal_div_3_g = 1) or (xtal_div_3_g = 0)
+ report "xtal_div_3_g must be either 1 or 0!"
+ severity failure;
+
+ -- pragma translate_on
+
+
+ -----------------------------------------------------------------------------
+ -- Divide XTAL1 by 3 to derive Clock States.
+ -----------------------------------------------------------------------------
+ use_xtal_div: if xtal_div_3_g = 1 generate
+ xtal: process (res_i, xtal_i)
+ begin
+ if res_i = res_active_c then
+ xtal_q <= TO_UNSIGNED(0, 2);
+ t0_q <= '0';
+
+ elsif xtal_i'event and xtal_i = clk_active_c then
+ if xtal_en_i then
+ if xtal_q < 2 then
+ xtal_q <= xtal_q + 1;
+ else
+ xtal_q <= TO_UNSIGNED(0, 2);
+ end if;
+
+ if xtal3_s then
+ t0_q <= '1';
+ else
+ t0_q <= '0';
+ end if;
+
+ end if;
+
+ end if;
+ end process xtal;
+
+ x1_s <= '1'
+ when xtal_q = 0 and xtal_en_i else
+ '0';
+ x2_s <= '1'
+ when xtal_q = 1 and xtal_en_i else
+ '0';
+ x3_s <= '1'
+ when xtal_q = 2 and xtal_en_i else
+ '0';
+ t0_o <= t0_q;
+
+ end generate;
+
+ -----------------------------------------------------------------------------
+ -- XTAL1 is used directly for Clock States.
+ -----------------------------------------------------------------------------
+ no_xtal_div: if xtal_div_3_g = 0 generate
+ xtal_q <= TO_UNSIGNED(0, 2);
+
+ x1_s <= '1'
+ when xtal_en_i else
+ '0';
+ x2_s <= '1'
+ when xtal_en_i else
+ '0';
+ x3_s <= '1'
+ when xtal_en_i else
+ '0';
+ t0_o <= xtal_i;
+
+ end generate;
+
+ -- And finally the boolean flags --------------------------------------------
+ xtal1_s <= to_boolean(x1_s);
+ xtal2_s <= to_boolean(x2_s);
+ xtal3_s <= to_boolean(x3_s);
+
+
+ -----------------------------------------------------------------------------
+ -- Process external_signal
+ --
+ -- Purpose:
+ -- Control signals ALE, PSEN, PROG and RD/WR are generated here.
+ --
+ external_signals: process (res_i, xtal_i)
+ begin
+ if res_i = res_active_c then
+ ale_q <= false;
+ psen_q <= false;
+ prog_q <= false;
+ rd_q <= false;
+ wr_q <= false;
+
+ elsif xtal_i'event and xtal_i = clk_active_c then
+
+ case mstate_q is
+ when MSTATE5 =>
+ -- RD, WR are set at the end of XTAL2 of first machine cycle
+ if xtal2_s and not second_cycle_q then
+ if assert_rd_i then
+ rd_q <= true;
+ end if;
+ if assert_wr_i then
+ wr_q <= true;
+ end if;
+ end if;
+
+ when MSTATE1 =>
+ if xtal3_s then
+ psen_q <= false;
+ end if;
+
+ when MSTATE2 =>
+ if xtal3_s then
+ -- RD, WR are removed at the end of XTAL3 of second machine cycle
+ rd_q <= false;
+ wr_q <= false;
+ -- so is PROG
+ prog_q <= false;
+ end if;
+
+ when MSTATE3 =>
+ -- ALE is set at the end of XTAL3 of every machine cycle
+ if xtal3_s then
+ ale_q <= true;
+ end if;
+
+ when MSTATE4 =>
+ if xtal3_s then
+ -- PSEN is set at the end of XTAL3
+ if assert_psen_i then
+ psen_q <= true;
+ end if;
+
+ end if;
+
+ -- PROG is set at the end of XTAL3
+ if xtal3_s and
+ multi_cycle_q and not second_cycle_q and assert_prog_i then
+ prog_q <= true;
+ end if;
+
+ -- ALE is removed at the end of XTAL2 of every machine cycle
+ if xtal2_s then
+ ale_q <= false;
+ end if;
+
+ when others =>
+ -- recover when states are out of sync
+ ale_q <= false;
+ psen_q <= false;
+ prog_q <= false;
+ rd_q <= false;
+ wr_q <= false;
+
+ end case;
+
+ end if;
+
+ end process external_signals;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process states
+ --
+ -- Purpose:
+ -- The Clock State controller.
+ --
+ states: process (res_i, clk_i)
+ begin
+ if res_i = res_active_c then
+ -- Reset machine state to MSTATE3
+ -- This allows a proper instruction fetch for the first real instruction
+ -- after reset.
+ -- The MSTATE3 is part of a virtual NOP that has no MSTATE1 and MSTATE2.
+ mstate_q <= MSTATE3;
+
+ elsif clk_i'event and clk_i = clk_active_c then
+ if en_clk_i then
+
+ case mstate_q is
+ when MSTATE5 =>
+ mstate_q <= MSTATE1;
+
+ when MSTATE1 =>
+ mstate_q <= MSTATE2;
+
+ when MSTATE2 =>
+ mstate_q <= MSTATE3;
+
+ when MSTATE3 =>
+ mstate_q <= MSTATE4;
+
+ when MSTATE4 =>
+ mstate_q <= MSTATE5;
+
+ when others =>
+ -- recover when states are out of sync
+ mstate_q <= MSTATE1;
+
+ -- pragma translate_off
+ assert false
+ report "Encoding of Clock States failed!"
+ severity error;
+ -- pragma translate_on
+
+ end case;
+
+ end if;
+
+ end if;
+
+ end process states;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process machine_cycle
+ --
+ -- Purpose:
+ -- Keep track of machine cycles.
+ -- Basically, this means to differ between first and second cycle.
+ --
+ machine_cycle: process (res_i, clk_i)
+ variable state2_v, state5_v : boolean;
+ begin
+ if res_i = res_active_c then
+ multi_cycle_q <= false;
+ second_cycle_q <= false;
+
+ elsif clk_i'event and clk_i = clk_active_c then
+ if en_clk_i then
+
+ state2_v := mstate_q = MSTATE2;
+ state5_v := mstate_q = MSTATE5;
+
+ -- multi cycle information is delivered in State 2 from the decoder
+ if state2_v and multi_cycle_i then
+ multi_cycle_q <= true;
+ end if;
+
+ -- mark second machine cycle
+ if multi_cycle_q and state5_v then
+ second_cycle_q <= true;
+ end if;
+
+ -- reset at end of second machine cycle
+ if state5_v and
+ (multi_cycle_q and second_cycle_q) then
+ multi_cycle_q <= false;
+ second_cycle_q <= false;
+ end if;
+
+ end if;
+
+ end if;
+
+ end process machine_cycle;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Output assignments
+ -----------------------------------------------------------------------------
+ xtal3_o <= xtal3_s;
+ mstate_o <= mstate_q;
+ second_cycle_o <= second_cycle_q;
+ ale_o <= ale_q;
+ psen_o <= psen_q;
+ prog_o <= prog_q;
+ rd_o <= rd_q;
+ wr_o <= wr_q;
+
+end rtl;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: clock_ctrl.vhd,v $
+-- Revision 1.12 2006/07/14 01:04:35 arniml
+-- Fix bug report
+-- "Deassertion of PROG too early"
+-- PROG is deasserted at end of XTAL3 now
+--
+-- Revision 1.11 2006/06/20 00:46:38 arniml
+-- new input xtal_en_i gates xtal_i base clock
+--
+-- Revision 1.10 2005/11/01 21:24:21 arniml
+-- * shift assertion of ALE and PROG to xtal3
+-- * correct change of revision 1.8
+--
+-- Revision 1.9 2005/06/11 10:08:43 arniml
+-- introduce prefix 't48_' for all packages, entities and configurations
+--
+-- Revision 1.8 2005/06/09 22:15:10 arniml
+-- Use en_clk_i instead of xtal3_s for generation of external signals.
+-- This is required when the core runs with full xtal clock instead
+-- of xtal/3 (xtal_div_3_g = 0).
+--
+-- Revision 1.7 2005/05/04 20:12:36 arniml
+-- Fix bug report:
+-- "Wrong clock applied to T0"
+-- t0_o is generated inside clock_ctrl with a separate flip-flop running
+-- with xtal_i
+--
+-- Revision 1.6 2004/10/25 20:31:12 arniml
+-- remove PROG and end of XTAL2, see comment for details
+--
+-- Revision 1.5 2004/10/25 19:35:41 arniml
+-- deassert rd_q, wr_q and prog_q at end of XTAL3
+--
+-- Revision 1.4 2004/04/24 23:44:25 arniml
+-- move from std_logic_arith to numeric_std
+--
+-- Revision 1.3 2004/04/18 18:56:23 arniml
+-- reset machine state to MSTATE3 to allow proper instruction fetch
+-- after reset
+--
+-- Revision 1.2 2004/03/28 12:55:06 arniml
+-- move code for PROG out of if-branch for xtal3_s
+--
+-- Revision 1.1 2004/03/23 21:31:52 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/CPU/t48/rtl/vhdl/cond_branch-c.vhd b/common/CPU/t48/rtl/vhdl/cond_branch-c.vhd
new file mode 100644
index 00000000..15a0b7e7
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/cond_branch-c.vhd
@@ -0,0 +1,19 @@
+-------------------------------------------------------------------------------
+--
+-- The Conditional Branch Logic unit.
+-- Decisions whether to take a jump or not are made here.
+--
+-- $Id: cond_branch-c.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+configuration t48_cond_branch_rtl_c0 of t48_cond_branch is
+
+ for rtl
+ end for;
+
+end t48_cond_branch_rtl_c0;
diff --git a/common/CPU/t48/rtl/vhdl/cond_branch.vhd b/common/CPU/t48/rtl/vhdl/cond_branch.vhd
new file mode 100644
index 00000000..a97f871c
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/cond_branch.vhd
@@ -0,0 +1,217 @@
+-------------------------------------------------------------------------------
+--
+-- The Conditional Branch Logic unit.
+-- Decisions whether to take a jump or not are made here.
+--
+-- $Id: cond_branch.vhd,v 1.3 2005/06/11 10:08:43 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.word_t;
+
+use work.t48_cond_branch_pack.all;
+
+entity t48_cond_branch is
+
+ port (
+ -- Global Interface -------------------------------------------------------
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ -- Decoder Interface ------------------------------------------------------
+ compute_take_i : in boolean;
+ branch_cond_i : in branch_conditions_t;
+ take_branch_o : out boolean;
+ accu_i : in word_t;
+ t0_i : in std_logic;
+ t1_i : in std_logic;
+ int_n_i : in std_logic;
+ f0_i : in std_logic;
+ f1_i : in std_logic;
+ tf_i : in std_logic;
+ carry_i : in std_logic;
+ comp_value_i : in comp_value_t
+ );
+
+end t48_cond_branch;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+use work.t48_pack.res_active_c;
+use work.t48_pack.clk_active_c;
+
+architecture rtl of t48_cond_branch is
+
+ -- marker for branch taken
+ signal take_branch_s,
+ take_branch_q : boolean;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process decide_take
+ --
+ -- Purpose:
+ -- Decides whether a branch has to be taken or not.
+ --
+ decide_take: process (accu_i,
+ branch_cond_i,
+ t0_i, t1_i,
+ int_n_i,
+ f0_i, f1_i,
+ tf_i,
+ carry_i,
+ comp_value_i)
+ variable or_v : std_logic;
+ begin
+ -- default assignment
+ take_branch_s <= false;
+ or_v := '0';
+
+ case branch_cond_i is
+ -- Branch On: Accumulator Bit -------------------------------------------
+ when COND_ON_BIT =>
+ if accu_i(TO_INTEGER(UNSIGNED(comp_value_i))) = '1' then
+ take_branch_s <= true;
+ end if;
+
+ -- Branch On: Accumulator Zero ------------------------------------------
+ when COND_Z =>
+ for i in accu_i'range loop
+ or_v := or_v or accu_i(i);
+ end loop;
+ take_branch_s <= or_v = not comp_value_i(0);
+
+ -- Branch On: Carry -----------------------------------------------------
+ when COND_C =>
+ take_branch_s <= carry_i = comp_value_i(0);
+
+ -- Branch On: Flag 0 ----------------------------------------------------
+ when COND_F0 =>
+ take_branch_s <= f0_i = '1';
+
+ -- Branch On: Flag 1 ----------------------------------------------------
+ when COND_F1 =>
+ take_branch_s <= f1_i = '1';
+
+ -- Branch On: Interrupt -------------------------------------------------
+ when COND_INT =>
+ take_branch_s <= int_n_i = '0';
+
+ -- Branch On: Test 0 ----------------------------------------------------
+ when COND_T0 =>
+ take_branch_s <= t0_i = comp_value_i(0);
+
+ -- Branch On: Test 1 ----------------------------------------------------
+ when COND_T1 =>
+ take_branch_s <= t1_i = comp_value_i(0);
+
+ -- Branch On: Timer Flag ------------------------------------------------
+ when COND_TF =>
+ take_branch_s <= tf_i = '1';
+
+ when others =>
+ -- pragma translate_off
+ assert false
+ report "Unknown branch condition specified!"
+ severity error;
+ -- pragma translate_on
+
+ end case;
+
+ end process decide_take;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process reg
+ --
+ -- Purpose:
+ -- Implement the marker register.
+ --
+ reg: process (res_i, clk_i)
+ begin
+ if res_i = res_active_c then
+ take_branch_q <= false;
+
+ elsif clk_i'event and clk_i = clk_active_c then
+ if en_clk_i then
+
+ if compute_take_i then
+ take_branch_q <= take_branch_s;
+ end if;
+
+ end if;
+
+ end if;
+
+ end process reg;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Output Mapping.
+ -----------------------------------------------------------------------------
+ take_branch_o <= take_branch_q;
+
+end rtl;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: cond_branch.vhd,v $
+-- Revision 1.3 2005/06/11 10:08:43 arniml
+-- introduce prefix 't48_' for all packages, entities and configurations
+--
+-- Revision 1.2 2004/04/24 23:44:25 arniml
+-- move from std_logic_arith to numeric_std
+--
+-- Revision 1.1 2004/03/23 21:31:52 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/CPU/t48/rtl/vhdl/cond_branch_pack-p.vhd b/common/CPU/t48/rtl/vhdl/cond_branch_pack-p.vhd
new file mode 100644
index 00000000..e6a029f3
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/cond_branch_pack-p.vhd
@@ -0,0 +1,41 @@
+-------------------------------------------------------------------------------
+--
+-- $Id: cond_branch_pack-p.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+package t48_cond_branch_pack is
+
+ -----------------------------------------------------------------------------
+ -- The branch conditions.
+ -----------------------------------------------------------------------------
+ type branch_conditions_t is (COND_ON_BIT, COND_Z,
+ COND_C,
+ COND_F0, COND_F1,
+ COND_INT,
+ COND_T0, COND_T1,
+ COND_TF);
+
+ subtype comp_value_t is std_logic_vector(2 downto 0);
+
+end t48_cond_branch_pack;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: cond_branch_pack-p.vhd,v $
+-- Revision 1.2 2005/06/11 10:08:43 arniml
+-- introduce prefix 't48_' for all packages, entities and configurations
+--
+-- Revision 1.1 2004/03/23 21:31:52 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/CPU/t48/rtl/vhdl/db_bus-c.vhd b/common/CPU/t48/rtl/vhdl/db_bus-c.vhd
new file mode 100644
index 00000000..2047eb9f
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/db_bus-c.vhd
@@ -0,0 +1,19 @@
+-------------------------------------------------------------------------------
+--
+-- The BUS unit.
+-- Implements the BUS port logic.
+--
+-- $Id: db_bus-c.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+configuration t48_db_bus_rtl_c0 of t48_db_bus is
+
+ for rtl
+ end for;
+
+end t48_db_bus_rtl_c0;
diff --git a/common/CPU/t48/rtl/vhdl/db_bus.vhd b/common/CPU/t48/rtl/vhdl/db_bus.vhd
new file mode 100644
index 00000000..54e6b199
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/db_bus.vhd
@@ -0,0 +1,169 @@
+-------------------------------------------------------------------------------
+--
+-- The BUS unit.
+-- Implements the BUS port logic.
+--
+-- $Id: db_bus.vhd,v 1.5 2005/06/11 10:08:43 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.word_t;
+
+entity t48_db_bus is
+
+ port (
+ -- Global Interface -------------------------------------------------------
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ ea_i : in std_logic;
+ -- T48 Bus Interface ------------------------------------------------------
+ data_i : in word_t;
+ data_o : out word_t;
+ write_bus_i : in boolean;
+ read_bus_i : in boolean;
+ -- BUS Interface ----------------------------------------------------------
+ output_pcl_i : in boolean;
+ bidir_bus_i : in boolean;
+ pcl_i : in word_t;
+ db_i : in word_t;
+ db_o : out word_t;
+ db_dir_o : out std_logic
+ );
+
+end t48_db_bus;
+
+
+use work.t48_pack.clk_active_c;
+use work.t48_pack.res_active_c;
+use work.t48_pack.bus_idle_level_c;
+use work.t48_pack.to_stdLogic;
+
+architecture rtl of t48_db_bus is
+
+ -- the BUS output register
+ signal bus_q : word_t;
+
+ -- BUS direction marker
+ signal db_dir_q,
+ db_dir_qq : std_logic;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process bus_regs
+ --
+ -- Purpose:
+ -- Implements the BUS output register.
+ --
+ bus_regs: process (res_i, clk_i)
+ begin
+ if res_i = res_active_c then
+ bus_q <= (others => '0');
+ db_dir_q <= '0';
+ db_dir_qq <= '0';
+
+ elsif clk_i'event and clk_i = clk_active_c then
+ if en_clk_i then
+ if write_bus_i then
+ db_dir_qq <= '1';
+ else
+ -- extend bus direction by one machine cycle
+ db_dir_qq <= db_dir_q;
+ end if;
+
+ if write_bus_i then
+ bus_q <= data_i;
+
+ db_dir_q <= '1';
+
+ elsif ea_i = '1' or bidir_bus_i then
+ db_dir_q <= '0';
+
+ end if;
+
+ end if;
+
+ end if;
+
+ end process bus_regs;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Output Mapping.
+ -----------------------------------------------------------------------------
+ db_o <= pcl_i
+ when output_pcl_i else
+ bus_q;
+ db_dir_o <= db_dir_qq or
+ to_stdLogic(output_pcl_i);
+ data_o <= (others => bus_idle_level_c)
+ when not read_bus_i else
+ db_i;
+
+end rtl;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: db_bus.vhd,v $
+-- Revision 1.5 2005/06/11 10:08:43 arniml
+-- introduce prefix 't48_' for all packages, entities and configurations
+--
+-- Revision 1.4 2005/06/09 22:16:26 arniml
+-- Implement db_dir_o glitch-safe
+--
+-- Revision 1.3 2004/10/25 20:30:18 arniml
+-- delay db_dir_o by one machine cycle
+-- this fixes the timing relation between BUS data and WR'
+--
+-- Revision 1.2 2004/04/04 14:15:45 arniml
+-- add dump_compare support
+--
+-- Revision 1.1 2004/03/23 21:31:52 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/CPU/t48/rtl/vhdl/decoder-c.vhd b/common/CPU/t48/rtl/vhdl/decoder-c.vhd
new file mode 100644
index 00000000..efcebaf0
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/decoder-c.vhd
@@ -0,0 +1,28 @@
+-------------------------------------------------------------------------------
+--
+-- The Decoder unit.
+-- It decodes the instruction opcodes and executes them.
+--
+-- $Id: decoder-c.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+configuration t48_decoder_rtl_c0 of t48_decoder is
+
+ for rtl
+
+ for opc_decoder_b: t48_opc_decoder
+ use configuration work.t48_opc_decoder_rtl_c0;
+ end for;
+
+ for int_b: t48_int
+ use configuration work.t48_int_rtl_c0;
+ end for;
+
+ end for;
+
+end t48_decoder_rtl_c0;
diff --git a/common/CPU/t48/rtl/vhdl/decoder.vhd b/common/CPU/t48/rtl/vhdl/decoder.vhd
new file mode 100644
index 00000000..49dc2b3f
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/decoder.vhd
@@ -0,0 +1,2074 @@
+-------------------------------------------------------------------------------
+--
+-- The Decoder unit.
+-- It decodes the instruction opcodes and executes them.
+--
+-- $Id: decoder.vhd,v 1.25 2006/06/20 00:46:03 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.word_t;
+use work.t48_pack.mstate_t;
+use work.t48_alu_pack.alu_op_t;
+use work.t48_cond_branch_pack.all;
+use work.t48_dmem_ctrl_pack.all;
+use work.t48_pmem_ctrl_pack.all;
+
+entity t48_decoder is
+
+ generic (
+ -- store mnemonic in flip-flops (registered-out)
+ register_mnemonic_g : integer := 1
+ );
+
+ port (
+ -- Global Interface -------------------------------------------------------
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ xtal_i : in std_logic;
+ xtal_en_i : in boolean;
+ ea_i : in std_logic;
+ ale_i : in boolean;
+ int_n_i : in std_logic;
+ t0_dir_o : out std_logic;
+ -- T48 Bus Interface ------------------------------------------------------
+ data_i : in word_t;
+ data_o : out word_t;
+ alu_write_accu_o : out boolean;
+ alu_write_shadow_o : out boolean;
+ alu_write_temp_reg_o : out boolean;
+ alu_read_alu_o : out boolean;
+ bus_write_bus_o : out boolean;
+ bus_read_bus_o : out boolean;
+ dm_write_dmem_addr_o : out boolean;
+ dm_write_dmem_o : out boolean;
+ dm_read_dmem_o : out boolean;
+ p1_write_p1_o : out boolean;
+ p1_read_p1_o : out boolean;
+ p2_write_p2_o : out boolean;
+ p2_write_exp_o : out boolean;
+ p2_read_p2_o : out boolean;
+ p2_read_exp_o : out boolean;
+ pm_write_pcl_o : out boolean;
+ pm_read_pcl_o : out boolean;
+ pm_write_pch_o : out boolean;
+ pm_read_pch_o : out boolean;
+ pm_read_pmem_o : out boolean;
+ psw_read_psw_o : out boolean;
+ psw_read_sp_o : out boolean;
+ psw_write_psw_o : out boolean;
+ psw_write_sp_o : out boolean;
+ -- ALU Interface ----------------------------------------------------------
+ alu_carry_i : in std_logic;
+ alu_op_o : out alu_op_t;
+ alu_use_carry_o : out boolean;
+ alu_da_high_o : out boolean;
+ alu_accu_low_o : out boolean;
+ alu_p06_temp_reg_o : out boolean;
+ alu_p60_temp_reg_o : out boolean;
+ alu_da_overflow_i : in boolean;
+ -- BUS Interface ----------------------------------------------------------
+ bus_output_pcl_o : out boolean;
+ bus_bidir_bus_o : out boolean;
+ -- Clock Controller Interface ---------------------------------------------
+ clk_multi_cycle_o : out boolean;
+ clk_assert_psen_o : out boolean;
+ clk_assert_prog_o : out boolean;
+ clk_assert_rd_o : out boolean;
+ clk_assert_wr_o : out boolean;
+ clk_mstate_i : in mstate_t;
+ clk_second_cycle_i : in boolean;
+ -- Conditional Branch Logic Interface -------------------------------------
+ cnd_compute_take_o : out boolean;
+ cnd_branch_cond_o : out branch_conditions_t;
+ cnd_take_branch_i : in boolean;
+ cnd_comp_value_o : out comp_value_t;
+ cnd_f1_o : out std_logic;
+ cnd_tf_o : out std_logic;
+ -- Data Memory Controller Interface ---------------------------------------
+ dm_addr_type_o : out dmem_addr_ident_t;
+ -- Port 1 Interface -------------------------------------------------------
+ p1_read_reg_o : out boolean;
+ -- Port 2 Interface -------------------------------------------------------
+ p2_read_reg_o : out boolean;
+ p2_output_pch_o : out boolean;
+ -- Program Memory Controller Interface ------------------------------------
+ pm_inc_pc_o : out boolean;
+ pm_write_pmem_addr_o : out boolean;
+ pm_addr_type_o : out pmem_addr_ident_t;
+ -- Program Status Word Interface ------------------------------------------
+ psw_special_data_o : out std_logic;
+ psw_carry_i : in std_logic;
+ psw_aux_carry_i : in std_logic;
+ psw_f0_i : in std_logic;
+ psw_inc_stackp_o : out boolean;
+ psw_dec_stackp_o : out boolean;
+ psw_write_carry_o : out boolean;
+ psw_write_aux_carry_o : out boolean;
+ psw_write_f0_o : out boolean;
+ psw_write_bs_o : out boolean;
+ -- Timer Interface --------------------------------------------------------
+ tim_read_timer_o : out boolean;
+ tim_write_timer_o : out boolean;
+ tim_start_t_o : out boolean;
+ tim_start_cnt_o : out boolean;
+ tim_stop_tcnt_o : out boolean;
+ tim_overflow_i : in boolean
+ );
+
+end t48_decoder;
+
+
+use work.t48_pack.all;
+use work.t48_alu_pack.all;
+use work.t48_decoder_pack.all;
+
+use work.t48_comp_pack.t48_opc_decoder;
+use work.t48_comp_pack.t48_int;
+
+-- pragma translate_off
+use work.t48_tb_pack.tb_istrobe_s;
+-- pragma translate_on
+
+architecture rtl of t48_decoder is
+
+ -- Enable fixing a bug of Quartus II 4.0
+ constant enable_quartus_bugfix_c : boolean := true;
+
+ -- Opcode Decoder
+ signal opc_multi_cycle_s : boolean;
+ signal opc_read_bus_s : boolean;
+ signal opc_inj_int_s : boolean;
+ signal opc_opcode_s : word_t;
+ signal opc_mnemonic_s : mnemonic_t;
+ signal last_cycle_s : boolean;
+
+ -- state translators
+ signal assert_psen_s : boolean;
+
+ -- branch taken handshake
+ signal branch_taken_s,
+ branch_taken_q : boolean;
+ signal pm_inc_pc_s : boolean;
+ signal pm_write_pmem_addr_s : boolean;
+ -- additional signal to increment PC during CALL
+ signal add_inc_pc_s : boolean;
+ -- addtional signal to set PC during RET(R)
+ signal add_write_pmem_addr_s : boolean;
+
+ -- Flag 1
+ signal clear_f1_s,
+ cpl_f1_s : boolean;
+ signal f1_q : std_logic;
+ -- memory bank select
+ signal clear_mb_s,
+ set_mb_s : boolean;
+ signal mb_q : std_logic;
+
+ -- T0 direction selection
+ signal ent0_clk_s : boolean;
+ signal t0_dir_q : std_logic;
+
+ signal data_s : word_t;
+ signal read_dec_s : boolean;
+
+ signal tf_s : std_logic;
+
+ signal bus_read_bus_s : boolean;
+ signal add_read_bus_s : boolean;
+
+ signal dm_write_dmem_s : boolean;
+
+ signal p2_output_exp_s : boolean;
+
+ signal movx_first_cycle_s : boolean;
+
+ -- interrupt handling
+ signal jtf_executed_s : boolean;
+ signal en_tcnti_s : boolean;
+ signal dis_tcnti_s : boolean;
+ signal en_i_s : boolean;
+ signal dis_i_s : boolean;
+ signal tim_int_s : boolean;
+ signal retr_executed_s : boolean;
+ signal int_executed_s : boolean;
+ signal int_pending_s : boolean;
+ signal int_in_progress_s : boolean;
+
+ -- pragma translate_off
+ signal istrobe_res_q : std_logic;
+ signal istrobe_q : std_logic;
+ signal injected_int_q : std_logic;
+ -- pragma translate_on
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Opcode Decoder
+ -----------------------------------------------------------------------------
+ opc_decoder_b : t48_opc_decoder
+ generic map (
+ register_mnemonic_g => register_mnemonic_g
+ )
+ port map (
+ clk_i => clk_i,
+ res_i => res_i,
+ en_clk_i => en_clk_i,
+ data_i => data_i,
+ read_bus_i => opc_read_bus_s,
+ inj_int_i => opc_inj_int_s,
+ opcode_o => opc_opcode_s,
+ mnemonic_o => opc_mnemonic_s,
+ multi_cycle_o => opc_multi_cycle_s
+ );
+
+
+ -----------------------------------------------------------------------------
+ -- Interrupt Controller.
+ -----------------------------------------------------------------------------
+ int_b : t48_int
+ port map (
+ clk_i => clk_i,
+ res_i => res_i,
+ en_clk_i => en_clk_i,
+ xtal_i => xtal_i,
+ xtal_en_i => xtal_en_i,
+ clk_mstate_i => clk_mstate_i,
+ jtf_executed_i => jtf_executed_s,
+ tim_overflow_i => tim_overflow_i,
+ tf_o => tf_s,
+ en_tcnti_i => en_tcnti_s,
+ dis_tcnti_i => dis_tcnti_s,
+ int_n_i => int_n_i,
+ ale_i => ale_i,
+ last_cycle_i => last_cycle_s,
+ en_i_i => en_i_s,
+ dis_i_i => dis_i_s,
+ ext_int_o => open,
+ tim_int_o => tim_int_s,
+ retr_executed_i => retr_executed_s,
+ int_executed_i => int_executed_s,
+ int_pending_o => int_pending_s,
+ int_in_progress_o => int_in_progress_s
+ );
+
+ last_cycle_s <= not opc_multi_cycle_s or
+ (opc_multi_cycle_s and clk_second_cycle_i);
+
+ -----------------------------------------------------------------------------
+ -- Process machine_cycle
+ --
+ -- Purpose:
+ -- Generates the control signals that are basically needed for the
+ -- handling of a machine cycle.
+ --
+ machine_cycle: process (clk_mstate_i,
+ clk_second_cycle_i,
+ last_cycle_s,
+ ea_i,
+ assert_psen_s,
+ branch_taken_q,
+ int_pending_s,
+ p2_output_exp_s,
+ movx_first_cycle_s)
+
+ variable need_address_v : boolean;
+
+ begin
+ -- default assignments
+ clk_assert_psen_o <= false;
+ pm_inc_pc_s <= false;
+ pm_write_pmem_addr_s <= false;
+ pm_read_pmem_o <= false;
+ bus_output_pcl_o <= false;
+ p2_output_pch_o <= false;
+ opc_read_bus_s <= false;
+ opc_inj_int_s <= false;
+ bus_read_bus_s <= false;
+
+ need_address_v := not clk_second_cycle_i or
+ (clk_second_cycle_i and assert_psen_s);
+
+ case clk_mstate_i is
+ when MSTATE1 =>
+ if need_address_v then
+ if ea_i = '0' then
+ if not int_pending_s then
+ pm_read_pmem_o <= true;
+ end if;
+
+ else
+ if not int_pending_s then
+ bus_read_bus_s <= true;
+ end if;
+ p2_output_pch_o <= true;
+ end if;
+
+ end if;
+
+ if not clk_second_cycle_i then
+ if not int_pending_s then
+ opc_read_bus_s <= true;
+ else
+ opc_inj_int_s <= true; -- inject interrupt call
+ end if;
+ end if;
+
+ when MSTATE2 =>
+ if need_address_v and not branch_taken_q and
+ not int_pending_s then
+ pm_inc_pc_s <= true;
+ end if;
+
+ when MSTATE3 =>
+ if need_address_v then
+ -- Theory of operation:
+ -- Program Memory address is updated at end of State 3 (or end of
+ -- State 2 in case of a RET). Address information is thus available
+ -- latest with State 4.
+ -- This is the time where we need information about access target
+ -- (internal or external = EA). EA information needs to be stable
+ -- until end of State 1.
+ pm_write_pmem_addr_s <= true;
+ end if;
+
+ when MSTATE4 =>
+ if ea_i = '1' and
+ ((not clk_second_cycle_i and assert_psen_s)
+ or last_cycle_s) then
+ clk_assert_psen_o <= true;
+ p2_output_pch_o <= true;
+ bus_output_pcl_o <= true;
+ end if;
+
+ when MSTATE5 =>
+ if ea_i = '1' and
+ (need_address_v or last_cycle_s) and
+ -- Suppress output of PCH when either
+ -- a) expander port is driven on P2, has priority
+ not p2_output_exp_s and
+ -- b) first cycle of MOVX, don't disturb external access
+ not movx_first_cycle_s then
+ p2_output_pch_o <= true;
+ end if;
+
+ when others =>
+ -- pragma translate_off
+ assert false
+ report "Unkown machine state!"
+ severity error;
+ -- pragma translate_on
+
+ end case;
+
+ end process machine_cycle;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process decode
+ --
+ -- Purpose:
+ -- Indentifies each single instruction and steps through the related
+ -- execution sequence.
+ --
+ decode: process (alu_carry_i,
+ psw_aux_carry_i,
+ alu_da_overflow_i,
+ clk_mstate_i,
+ clk_second_cycle_i,
+ cnd_take_branch_i,
+ opc_opcode_s,
+ opc_mnemonic_s,
+ psw_carry_i,
+ psw_f0_i,
+ f1_q,
+ mb_q,
+ tim_int_s,
+ int_pending_s,
+ int_in_progress_s)
+
+ procedure address_indirect_3_f is
+ begin
+ -- apply dmem address from selected register for indirect mode
+ if opc_opcode_s(3) = '0' or enable_quartus_bugfix_c then
+ dm_read_dmem_o <= true;
+ dm_write_dmem_addr_o <= true;
+ dm_addr_type_o <= DM_PLAIN;
+ end if;
+ end;
+
+ procedure and_or_xor_add_4_f is
+ begin
+ -- write dmem contents to Temp Reg
+ dm_read_dmem_o <= true;
+ alu_write_temp_reg_o <= true;
+ end;
+
+ procedure and_or_xor_add_5_f (alu_op : alu_op_t) is
+ begin
+ -- perform ALU operation and store in Accumulator
+ alu_op_o <= alu_op;
+ alu_read_alu_o <= true;
+ alu_write_accu_o <= true;
+ end;
+
+ procedure cond_jump_c2_m1_f is
+ begin
+ -- store address in Program Counter low byte if branch has to
+ -- be taken
+-- if clk_mstate_i = MSTATE1 and cnd_take_branch_i then
+ pm_write_pcl_o <= true;
+ branch_taken_s <= true;
+-- end if;
+ end;
+
+ -- intermediate value of the Program Memory Bank Flag
+ variable mb_v : std_logic;
+
+ begin
+ -- default assignments
+ data_s <= (others => '-');
+ read_dec_s <= false;
+ branch_taken_s <= false;
+ clear_f1_s <= false;
+ cpl_f1_s <= false;
+ clear_mb_s <= false;
+ set_mb_s <= false;
+ add_inc_pc_s <= false;
+ assert_psen_s <= false;
+ alu_write_accu_o <= false;
+ alu_write_shadow_o <= false;
+ alu_write_temp_reg_o <= false;
+ alu_p06_temp_reg_o <= false;
+ alu_p60_temp_reg_o <= false;
+ alu_read_alu_o <= false;
+ bus_write_bus_o <= false;
+ bus_bidir_bus_o <= false;
+ dm_write_dmem_addr_o <= false;
+ dm_write_dmem_s <= false;
+ dm_read_dmem_o <= false;
+ pm_write_pcl_o <= false;
+ pm_read_pcl_o <= false;
+ pm_write_pch_o <= false;
+ pm_read_pch_o <= false;
+ pm_addr_type_o <= PM_PC;
+ psw_read_psw_o <= false;
+ psw_read_sp_o <= false;
+ psw_write_psw_o <= false;
+ psw_write_sp_o <= false;
+ alu_op_o <= ALU_NOP;
+ alu_use_carry_o <= false;
+ alu_da_high_o <= false;
+ alu_accu_low_o <= false;
+ clk_assert_prog_o <= false;
+ clk_assert_rd_o <= false;
+ clk_assert_wr_o <= false;
+ cnd_branch_cond_o <= COND_ON_BIT;
+ cnd_compute_take_o <= false;
+ cnd_comp_value_o <= opc_opcode_s(7 downto 5);
+ dm_addr_type_o <= DM_REG;
+ tim_read_timer_o <= false;
+ tim_write_timer_o <= false;
+ tim_start_t_o <= false;
+ tim_start_cnt_o <= false;
+ tim_stop_tcnt_o <= false;
+ p1_write_p1_o <= false;
+ p1_read_p1_o <= false;
+ p1_read_reg_o <= false;
+ p2_write_p2_o <= false;
+ p2_write_exp_o <= false;
+ p2_read_p2_o <= false;
+ p2_read_reg_o <= false;
+ p2_read_exp_o <= false;
+ p2_output_exp_s <= false;
+ psw_special_data_o <= '0';
+ psw_inc_stackp_o <= false;
+ psw_dec_stackp_o <= false;
+ psw_write_carry_o <= false;
+ psw_write_aux_carry_o <= false;
+ psw_write_f0_o <= false;
+ psw_write_bs_o <= false;
+ jtf_executed_s <= false;
+ en_tcnti_s <= false;
+ dis_tcnti_s <= false;
+ en_i_s <= false;
+ dis_i_s <= false;
+ retr_executed_s <= false;
+ int_executed_s <= false;
+ add_write_pmem_addr_s <= false;
+ ent0_clk_s <= false;
+ add_read_bus_s <= false;
+ movx_first_cycle_s <= false;
+
+ -- the Program Memory Bank Flag is held low when interrupts are in progress
+ -- according to the MCS-48 User's Manual
+ if int_in_progress_s then
+ mb_v := '0';
+ else
+ mb_v := mb_q;
+ end if;
+
+ -- prepare potential register indirect address mode
+ if not clk_second_cycle_i and clk_mstate_i = MSTATE2 then
+ data_s <= (others => '0');
+ if opc_opcode_s(3) = '1' then
+ data_s(2 downto 0) <= opc_opcode_s(2 downto 0);
+ else
+ data_s(2 downto 0) <= "00" & opc_opcode_s(0);
+ end if;
+
+ read_dec_s <= true;
+ dm_write_dmem_addr_o <= true;
+ dm_addr_type_o <= DM_REG;
+ end if;
+
+ case opc_mnemonic_s is
+
+ -- Mnemonic ADD ---------------------------------------------------------
+ when MN_ADD =>
+ case clk_mstate_i is
+ -- read RAM once for indirect address mode
+ when MSTATE3 =>
+ if not enable_quartus_bugfix_c or
+ opc_opcode_s(3) = '0' then
+ address_indirect_3_f;
+ end if;
+
+ -- store data from RAM to Temp Reg
+ when MSTATE4 =>
+ and_or_xor_add_4_f;
+
+ -- perform ADD and store in Accumulator
+ when MSTATE5 =>
+ and_or_xor_add_5_f(alu_op => ALU_ADD);
+
+ if opc_opcode_s(4) = '1' then
+ alu_use_carry_o <= true;
+ end if;
+
+ psw_special_data_o <= alu_carry_i;
+ psw_write_carry_o <= true;
+ psw_write_aux_carry_o <= true;
+
+ when others =>
+ null;
+
+ end case;
+
+ -- Mnemonic ADD_A_DATA --------------------------------------------------
+ when MN_ADD_A_DATA =>
+ assert_psen_s <= true;
+
+ if clk_second_cycle_i then
+ case clk_mstate_i is
+ -- write Temp Reg when contents of Program Memory is on bus
+ when MSTATE1 =>
+ alu_write_temp_reg_o <= true;
+
+ -- perform ADD and store in Accumulator
+ when MSTATE3 =>
+ and_or_xor_add_5_f(alu_op => ALU_ADD);
+
+ if opc_opcode_s(4) = '1' then
+ alu_use_carry_o <= true;
+ end if;
+
+ psw_special_data_o <= alu_carry_i;
+ psw_write_carry_o <= true;
+ psw_write_aux_carry_o <= true;
+
+ when others =>
+ null;
+
+ end case;
+
+ end if;
+
+ -- Mnemonic ANL ---------------------------------------------------------
+ when MN_ANL =>
+ case clk_mstate_i is
+ -- read RAM once for indirect address mode
+ when MSTATE3 =>
+ if not enable_quartus_bugfix_c or
+ opc_opcode_s(3) = '0' then
+ address_indirect_3_f;
+ end if;
+
+ -- store data from RAM to Temp Reg
+ when MSTATE4 =>
+ and_or_xor_add_4_f;
+
+ -- perform AND and store in Accumulator
+ when MSTATE5 =>
+ and_or_xor_add_5_f(alu_op => ALU_AND);
+
+ when others =>
+ null;
+
+ end case;
+
+ -- Mnemonic ANL_A_DATA --------------------------------------------------
+ when MN_ANL_A_DATA =>
+ assert_psen_s <= true;
+
+ if clk_second_cycle_i then
+ case clk_mstate_i is
+ -- write Temp Reg when contents of Program Memory is on bus
+ when MSTATE1 =>
+ alu_write_temp_reg_o <= true;
+
+ -- perform AND and store in Accumulator
+ when MSTATE3 =>
+ and_or_xor_add_5_f(alu_op => ALU_AND);
+
+ when others =>
+ null;
+
+ end case;
+
+ end if;
+
+ -- Mnemonic ANL_EXT -----------------------------------------------------
+ when MN_ANL_EXT =>
+ assert_psen_s <= true;
+
+ if not clk_second_cycle_i then
+ -- read port to Temp Reg
+ if clk_mstate_i = MSTATE5 then
+ if opc_opcode_s(1 downto 0) = "00" then
+ add_read_bus_s <= true;
+ elsif opc_opcode_s(1) = '0' then
+ p1_read_p1_o <= true;
+ p1_read_reg_o <= true;
+ else
+ p2_read_p2_o <= true;
+ p2_read_reg_o <= true;
+ end if;
+
+ alu_write_temp_reg_o <= true;
+ end if;
+
+ else
+ case clk_mstate_i is
+ -- write shadow Accumulator when contents of Program Memory is
+ -- on bus
+ when MSTATE1 =>
+ alu_write_shadow_o <= true;
+
+ -- loop shadow Accumulator through ALU to prevent update from
+ -- real Accumulator
+ when MSTATE2 =>
+ alu_read_alu_o <= true;
+ alu_write_shadow_o <= true;
+
+ -- write result of AND operation back to port
+ when MSTATE3 =>
+ alu_op_o <= ALU_AND;
+ alu_read_alu_o <= true;
+
+ if opc_opcode_s(1 downto 0) = "00" then
+ bus_write_bus_o <= true;
+ elsif opc_opcode_s(1) = '0' then
+ p1_write_p1_o <= true;
+ else
+ p2_write_p2_o <= true;
+ end if;
+
+ when others =>
+ null;
+
+ end case;
+
+ end if;
+
+ -- Mnemonic CALL --------------------------------------------------------
+ when MN_CALL =>
+ assert_psen_s <= true;
+
+ if not clk_second_cycle_i then
+ case clk_mstate_i is
+ -- read Stack Pointer and address Data Memory for low byte
+ -- also increment Program Counter to point to next instruction
+ when MSTATE3 =>
+ psw_read_sp_o <= true;
+ dm_write_dmem_addr_o <= true;
+ dm_addr_type_o <= DM_STACK;
+
+ -- only increment PC if this is not an injected CALL
+ -- injected CALLS are not located in Program Memory,
+ -- the PC points already to the instruction to be executed
+ -- after the interrupt
+ if not int_pending_s then
+ add_inc_pc_s <= true;
+ end if;
+
+ -- store Program Counter low byte on stack
+ when MSTATE4 =>
+ pm_read_pcl_o <= true;
+ dm_write_dmem_s <= true;
+
+ -- store Program Counter high byte and PSW on stack
+ -- increment Stack pointer
+ when MSTATE5 =>
+ psw_read_psw_o <= true;
+ pm_read_pch_o <= true;
+ dm_write_dmem_addr_o <= true;
+ dm_addr_type_o <= DM_STACK_HIGH;
+ dm_write_dmem_s <= true;
+ psw_inc_stackp_o <= true;
+
+ when others =>
+ null;
+
+ end case;
+
+ else
+ case clk_mstate_i is
+ -- store address in Program Counter low byte
+ when MSTATE1 =>
+ pm_write_pcl_o <= true;
+ branch_taken_s <= true;
+ if int_pending_s then
+ -- apply low part of vector address manually
+ data_s <= (others => '0');
+ data_s(1 downto 0) <= "11";
+ if tim_int_s then
+ data_s(2) <= '1';
+ end if;
+ read_dec_s <= true;
+ end if;
+
+ when MSTATE2 =>
+ pm_write_pch_o <= true;
+ read_dec_s <= true;
+ if not int_pending_s then
+ -- store high part of target address in Program Counter
+ data_s <= "0000" & mb_v & opc_opcode_s(7 downto 5);
+ else
+ -- apply high part of vector address manually
+ data_s <= (others => '0');
+ int_executed_s <= true;
+ end if;
+
+ when others =>
+ null;
+
+ end case;
+
+ end if;
+
+ -- Mnemonic CLR_A -------------------------------------------------------
+ when MN_CLR_A =>
+ -- write CLR output of ALU to Accumulator
+ if clk_mstate_i = MSTATE3 then
+ alu_op_o <= ALU_CLR;
+ alu_read_alu_o <= true;
+ alu_write_accu_o <= true;
+ end if;
+
+ -- Mnemonic CLR_C -------------------------------------------------------
+ when MN_CLR_C =>
+ -- store 0 to Carry
+ if clk_mstate_i = MSTATE3 then
+ psw_special_data_o <= '0';
+ psw_write_carry_o <= true;
+ end if;
+
+ -- Mnemonic CLR_F -------------------------------------------------------
+ when MN_CLR_F =>
+ -- store 0 to selected flag
+ if clk_mstate_i = MSTATE3 then
+ if opc_opcode_s(5) = '0' then
+ psw_special_data_o <= '0';
+ psw_write_f0_o <= true;
+ else
+ clear_f1_s <= true;
+ end if;
+
+ end if;
+
+ -- Mnemonic CPL_A -------------------------------------------------------
+ when MN_CPL_A =>
+ -- write CPL output of ALU to Accumulator
+ if clk_mstate_i = MSTATE3 then
+ alu_op_o <= ALU_CPL;
+ alu_read_alu_o <= true;
+ alu_write_accu_o <= true;
+ end if;
+
+ -- Mnemnonic CPL_C ------------------------------------------------------
+ when MN_CPL_C =>
+ -- write inverse of Carry to PSW
+ if clk_mstate_i = MSTATE3 then
+ psw_special_data_o <= not psw_carry_i;
+ psw_write_carry_o <= true;
+ end if;
+
+ -- Mnemonic CPL_F -------------------------------------------------------
+ when MN_CPL_f =>
+ -- write inverse of selected flag back to flag
+ if clk_mstate_i = MSTATE3 then
+ if opc_opcode_s(5) = '0' then
+ psw_special_data_o <= not psw_f0_i;
+ psw_write_f0_o <= true;
+ else
+ cpl_f1_s <= true;
+ end if;
+
+ end if;
+
+ -- Mnemonic DA ----------------------------------------------------------
+ when MN_DA =>
+ alu_op_o <= ALU_ADD;
+
+ case clk_mstate_i is
+ -- Step 1: Preload Temp Reg with 0x06
+ when MSTATE3 =>
+ alu_p06_temp_reg_o <= true;
+
+ -- Step 2: Check Auxiliary Carry and overflow on low nibble
+ -- Add 0x06 to shadow Accumulator if one is true
+ when MSTATE4 =>
+ if psw_aux_carry_i = '1' or alu_da_overflow_i then
+ alu_read_alu_o <= true;
+ alu_write_shadow_o <= true;
+ end if;
+
+ -- preload Temp Reg with 0x60
+ alu_p60_temp_reg_o <= true;
+
+ -- Step 3: Check overflow on high nibble
+ -- Add 0x60 to shadow Accumulator if true and store result
+ -- in Accumulator and PSW (only Carry)
+ when MSTATE5 =>
+ alu_da_high_o <= true;
+
+ if alu_da_overflow_i then
+ psw_special_data_o <= alu_carry_i;
+ else
+ alu_op_o <= ALU_NOP;
+ psw_special_data_o <= '0';
+ end if;
+ alu_read_alu_o <= true;
+ alu_write_accu_o <= true;
+ psw_write_carry_o <= true;
+
+ when others =>
+ null;
+
+ end case;
+
+ -- Mnemonic DEC ---------------------------------------------------------
+ when MN_DEC =>
+ case clk_mstate_i is
+ when MSTATE4 =>
+ -- DEC Rr: store data from RAM to shadow Accumulator
+ if opc_opcode_s(6) = '1' then
+ dm_read_dmem_o <= true;
+ alu_write_shadow_o <= true;
+ end if;
+
+ when MSTATE5 =>
+ alu_op_o <= ALU_DEC;
+ alu_read_alu_o <= true;
+
+ if opc_opcode_s(6) = '0' then
+ -- write DEC of Accumulator to Accumulator
+ alu_write_accu_o <= true;
+ else
+ -- store DEC of shadow Accumulator back to dmem
+ dm_write_dmem_s <= true;
+ end if;
+
+ when others =>
+ null;
+
+ end case;
+
+ -- Mnemonic DIS_EN_I ----------------------------------------------------
+ when MN_DIS_EN_I =>
+ if clk_mstate_i = MSTATE3 then
+ if opc_opcode_s(4) = '1' then
+ dis_i_s <= true;
+ else
+ en_i_s <= true;
+ end if;
+ end if;
+
+ -- Mnemonic DIS_EN_TCNTI ------------------------------------------------
+ when MN_DIS_EN_TCNTI =>
+ if clk_mstate_i = MSTATE3 then
+ if opc_opcode_s(4) = '1' then
+ dis_tcnti_s <= true;
+ else
+ en_tcnti_s <= true;
+ end if;
+ end if;
+
+ -- Mnemonic DJNZ --------------------------------------------------------
+ when MN_DJNZ =>
+ assert_psen_s <= true;
+
+ if not clk_second_cycle_i then
+ case clk_mstate_i is
+ -- store data from RAM to shadow Accumulator
+ when MSTATE4 =>
+ dm_read_dmem_o <= true;
+ alu_write_shadow_o <= true;
+
+ -- write DEC result of shadow Accumulator back to dmem and
+ -- conditional branch logic
+ when MSTATE5 =>
+ alu_op_o <= ALU_DEC;
+ alu_read_alu_o <= true;
+ dm_write_dmem_s <= true;
+
+ cnd_compute_take_o <= true;
+ cnd_branch_cond_o <= COND_Z;
+ cnd_comp_value_o(0) <= '0';
+
+ when others =>
+ null;
+
+ end case;
+
+ else
+ -- store address in Program Counter low byte if branch has to
+ -- be taken
+ if clk_mstate_i = MSTATE1 and cnd_take_branch_i then
+ cond_jump_c2_m1_f;
+ end if;
+
+ end if;
+
+ -- Mnemonic ENT0_CLK ----------------------------------------------------
+ when MN_ENT0_CLK =>
+ if clk_mstate_i = MSTATE3 then
+ ent0_clk_s <= true;
+ end if;
+
+ -- Mnemonic IN ----------------------------------------------------------
+ when MN_IN =>
+ -- read Port and store in Accumulator
+ if clk_second_cycle_i and clk_mstate_i = MSTATE2 then
+ alu_write_accu_o <= true;
+
+ if opc_opcode_s(1) = '0' then
+ p1_read_p1_o <= true;
+ else
+ p2_read_p2_o <= true;
+ end if;
+ end if;
+
+ -- Mnemonic INS ---------------------------------------------------------
+ when MN_INS =>
+ clk_assert_rd_o <= true;
+
+ -- read BUS and store in Accumulator
+ if clk_second_cycle_i and clk_mstate_i = MSTATE2 then
+ alu_write_accu_o <= true;
+
+ add_read_bus_s <= true;
+ end if;
+
+ -- Mnemonic INC ---------------------------------------------------------
+ when MN_INC =>
+ case clk_mstate_i is
+ -- read RAM once for indirect address mode
+ when MSTATE3 =>
+ if not enable_quartus_bugfix_c or
+ opc_opcode_s(3) = '0' then
+ address_indirect_3_f;
+ end if;
+
+ when MSTATE4 =>
+ -- INC Rr; INC @ Rr: store data from RAM to shadow Accumulator
+ if opc_opcode_s(3 downto 2) /= "01" then
+ dm_read_dmem_o <= true;
+ alu_write_shadow_o <= true;
+ end if;
+
+ when MSTATE5 =>
+ alu_op_o <= ALU_INC;
+ alu_read_alu_o <= true;
+
+ if opc_opcode_s(3 downto 2) = "01" then
+ -- write INC output of ALU to Accumulator
+ alu_write_accu_o <= true;
+ else
+ -- store INC of shadow Accumulator back to dmem
+ dm_write_dmem_s <= true;
+ end if;
+
+ when others =>
+ null;
+
+ end case;
+
+ -- Mnemonic JBB ---------------------------------------------------------
+ when MN_JBB =>
+ assert_psen_s <= true;
+ cnd_branch_cond_o <= COND_ON_BIT;
+
+ if not clk_second_cycle_i then
+ -- read Accumulator and start branch calculation
+ if clk_mstate_i = MSTATE3 then
+ alu_read_alu_o <= true;
+ cnd_compute_take_o <= true;
+ -- cnd_comp_value_o is ok by default assignment
+ end if;
+
+ else
+ -- store address in Program Counter low byte if branch has to
+ -- be taken
+ if clk_mstate_i = MSTATE1 and cnd_take_branch_i then
+ cond_jump_c2_m1_f;
+ end if;
+
+ end if;
+
+ -- Mnemonic JC ----------------------------------------------------------
+ when MN_JC =>
+ assert_psen_s <= true;
+ cnd_branch_cond_o <= COND_C;
+
+ if not clk_second_cycle_i then
+ -- start branch calculation
+ if clk_mstate_i = MSTATE3 then
+ cnd_compute_take_o <= true;
+ cnd_comp_value_o(0) <= opc_opcode_s(4);
+ end if;
+
+ else
+ -- store address in Program Counter low byte if branch has to
+ -- be taken
+ if clk_mstate_i = MSTATE1 and cnd_take_branch_i then
+ cond_jump_c2_m1_f;
+ end if;
+
+ end if;
+
+ -- Mnemonic JF ----------------------------------------------------------
+ when MN_JF =>
+ assert_psen_s <= true;
+
+ if not clk_second_cycle_i then
+ -- start branch calculation
+ if clk_mstate_i = MSTATE3 then
+ cnd_compute_take_o <= true;
+ if opc_opcode_s(7) = '1' then
+ -- JF0
+ cnd_branch_cond_o <= COND_F0;
+ else
+ -- JF1
+ cnd_branch_cond_o <= COND_F1;
+ end if;
+
+ end if;
+
+ else
+ -- store address in Program Counter low byte if branch has to
+ -- be taken
+ if clk_mstate_i = MSTATE1 and cnd_take_branch_i then
+ cond_jump_c2_m1_f;
+ end if;
+
+ end if;
+
+
+ -- Mnemonic JMP ---------------------------------------------------------
+ when MN_JMP =>
+ assert_psen_s <= true;
+
+ if clk_second_cycle_i then
+ case clk_mstate_i is
+ -- store address in Program Counter low byte
+ when MSTATE1 =>
+ pm_write_pcl_o <= true;
+ branch_taken_s <= true;
+
+ -- store high part of target address in Program Counter
+ when MSTATE2 =>
+ data_s <= "0000" & mb_v & opc_opcode_s(7 downto 5);
+ read_dec_s <= true;
+ pm_write_pch_o <= true;
+
+ when others =>
+ null;
+
+ end case;
+
+ end if;
+
+ -- Mnemonic JMPP --------------------------------------------------------
+ when MN_JMPP =>
+ assert_psen_s <= true;
+
+ if not clk_second_cycle_i then
+ -- write Accumulator to Program Memory address
+ -- (skip page offset update from Program Counter)
+ if clk_mstate_i = MSTATE3 then
+ alu_read_alu_o <= true;
+ pm_addr_type_o <= PM_PAGE;
+ end if;
+
+ else
+ if clk_mstate_i = MSTATE1 then
+ -- store address in Program Counter low byte
+ pm_write_pcl_o <= true;
+ branch_taken_s <= true;
+ end if;
+
+ end if;
+
+ -- Mnemonic JNI ---------------------------------------------------------
+ when MN_JNI =>
+ assert_psen_s <= true;
+ cnd_branch_cond_o <= COND_INT;
+
+ if not clk_second_cycle_i then
+ -- start branch calculation
+ if clk_mstate_i = MSTATE3 then
+ cnd_compute_take_o <= true;
+ end if;
+
+ else
+ -- store address in Program Counter low byte if branch has to
+ -- be taken
+ if clk_mstate_i = MSTATE1 and cnd_take_branch_i then
+ cond_jump_c2_m1_f;
+ end if;
+
+ end if;
+
+ -- Mnemonic JT ----------------------------------------------------------
+ when MN_JT =>
+ assert_psen_s <= true;
+ if opc_opcode_s(6) = '0' then
+ cnd_branch_cond_o <= COND_T0;
+ else
+ cnd_branch_cond_o <= COND_T1;
+ end if;
+
+ if not clk_second_cycle_i then
+ -- start branch calculation
+ if clk_mstate_i = MSTATE3 then
+ cnd_compute_take_o <= true;
+ cnd_comp_value_o(0) <= opc_opcode_s(4);
+ end if;
+
+ else
+ -- store address in Program Counter low byte if branch has to
+ -- be taken
+ if clk_mstate_i = MSTATE1 and cnd_take_branch_i then
+ cond_jump_c2_m1_f;
+ end if;
+
+ end if;
+
+ -- Mnemonic JTF ---------------------------------------------------------
+ when MN_JTF =>
+ assert_psen_s <= true;
+ cnd_branch_cond_o <= COND_TF;
+
+ if not clk_second_cycle_i then
+ -- start branch calculation
+ if clk_mstate_i = MSTATE3 then
+ cnd_compute_take_o <= true;
+ jtf_executed_s <= true;
+ end if;
+
+ else
+ -- store address in Program Counter low byte if branch has to
+ -- be taken
+ if clk_mstate_i = MSTATE1 and cnd_take_branch_i then
+ cond_jump_c2_m1_f;
+ end if;
+
+ end if;
+
+ -- Mnemonic JZ ----------------------------------------------------------
+ when MN_JZ =>
+ assert_psen_s <= true;
+ cnd_branch_cond_o <= COND_Z;
+
+ if not clk_second_cycle_i then
+ -- read Accumulator and start branch calculation
+ if clk_mstate_i = MSTATE3 then
+ alu_read_alu_o <= true;
+ cnd_compute_take_o <= true;
+ cnd_comp_value_o(0) <= opc_opcode_s(6);
+ end if;
+
+ else
+ -- store address in Program Counter low byte if branch has to
+ -- be taken
+ if clk_mstate_i = MSTATE1 and cnd_take_branch_i then
+ cond_jump_c2_m1_f;
+ end if;
+
+ end if;
+
+ -- Mnemonic MOV_A_DATA --------------------------------------------------
+ when MN_MOV_A_DATA =>
+ assert_psen_s <= true;
+
+ -- Write Accumulator when contents of Program Memory is on bus
+ -- during machine state 1 of second cycle.
+ if clk_second_cycle_i and clk_mstate_i = MSTATE1 then
+ alu_write_accu_o <= true;
+ end if;
+
+ -- Mnemonic MOV_A_RR ----------------------------------------------------
+ when MN_MOV_A_RR =>
+ case clk_mstate_i is
+ -- read RAM once for indirect address mode
+ when MSTATE3 =>
+ if not enable_quartus_bugfix_c or
+ opc_opcode_s(3) = '0' then
+ address_indirect_3_f;
+ end if;
+
+ -- read data from RAM and store in Accumulator
+ when MSTATE4 =>
+ and_or_xor_add_4_f;
+ alu_write_accu_o <= true;
+
+ when others =>
+ null;
+
+ end case;
+
+ -- Mnemonic MOV_A_PSW ---------------------------------------------------
+ when MN_MOV_A_PSW =>
+ if clk_mstate_i = MSTATE3 then
+ psw_read_psw_o <= true;
+ psw_read_sp_o <= true;
+ alu_write_accu_o <= true;
+ end if;
+
+ -- Mnemoniv MOV_PSW_A ---------------------------------------------------
+ when MN_MOV_PSW_A =>
+ if clk_mstate_i = MSTATE3 then
+ alu_read_alu_o <= true;
+ psw_write_psw_o <= true;
+ psw_write_sp_o <= true;
+ end if;
+
+ -- Mnemonic MOV_RR ------------------------------------------------------
+ when MN_MOV_RR =>
+ case clk_mstate_i is
+ -- read RAM once for indirect address mode
+ when MSTATE3 =>
+ if not enable_quartus_bugfix_c or
+ opc_opcode_s(3) = '0' then
+ address_indirect_3_f;
+ end if;
+
+ -- write Accumulator to dmem
+ when MSTATE5 =>
+ alu_read_alu_o <= true;
+ dm_write_dmem_s <= true;
+
+ when others =>
+ null;
+
+ end case;
+
+ -- Mnemonic MOV_RR_DATA -------------------------------------------------
+ when MN_MOV_RR_DATA =>
+ assert_psen_s <= true;
+
+ -- read RAM once for indirect address mode
+ if not clk_second_cycle_i and clk_mstate_i = MSTATE3 then
+ if not enable_quartus_bugfix_c or
+ opc_opcode_s(3) = '0' then
+ address_indirect_3_f;
+ end if;
+ end if;
+
+ -- Write Data Memory when contents of Program Memory is on bus
+ -- during machine state 1 of second cycle.
+ if clk_second_cycle_i and clk_mstate_i = MSTATE1 then
+ dm_write_dmem_s <= true;
+ end if;
+
+ -- Mnemonic MOV_T -------------------------------------------------------
+ when MN_MOV_T =>
+ if clk_mstate_i = MSTATE3 then
+ if opc_opcode_s(5) = '1' then
+ alu_read_alu_o <= true; -- MOV T, A
+ tim_write_timer_o <= true;
+ else
+ tim_read_timer_o <= true; -- MOV A, T
+ alu_write_accu_o <= true;
+ end if;
+ end if;
+
+ -- Mnemonic OUTD_PP_A ---------------------------------------------------
+ when MN_OUTD_PP_A =>
+ clk_assert_prog_o <= true;
+
+ if not clk_second_cycle_i then
+ case clk_mstate_i is
+ -- propagate expander port number to Port 2
+ when MSTATE3 =>
+
+ data_s(7 downto 4) <= (others => '0');
+ data_s(1 downto 0) <= opc_opcode_s(1 downto 0);
+ -- decide which 8243 command to use
+ case opc_opcode_s(7 downto 4) is
+ when "1001" =>
+ data_s(3 downto 2) <= "11"; -- ANLD command
+ when "1000" =>
+ data_s(3 downto 2) <= "10"; -- ORLD command
+ when "0011" =>
+ data_s(3 downto 2) <= "01"; -- MOVD command
+ when others =>
+ null;
+ end case;
+
+ read_dec_s <= true;
+ p2_write_exp_o <= true;
+
+ -- output expander port number on Port 2 while active edge of PROG
+ -- write Accumulator to expander port
+ when MSTATE4 =>
+ p2_output_exp_s <= true;
+
+ alu_read_alu_o <= true;
+ p2_write_exp_o <= true;
+
+ when MSTATE5 =>
+ p2_output_exp_s <= true;
+
+ when others =>
+ null;
+
+ end case;
+
+ else
+ -- hold expander port until inactive edge of PROG
+ if clk_mstate_i = MSTATE1 or clk_mstate_i = MSTATE2 then
+ p2_output_exp_s <= true;
+ end if;
+
+ end if;
+
+ -- Mnemonic MOVD_A_PP ---------------------------------------------------
+ when MN_MOVD_A_PP =>
+ clk_assert_prog_o <= true;
+
+ if not clk_second_cycle_i then
+ case clk_mstate_i is
+ -- propagate expander port number to Port 2
+ when MSTATE3 =>
+ data_s <= "0000" &
+ "00" & -- 8243 command: read
+ opc_opcode_s(1 downto 0);
+ read_dec_s <= true;
+ p2_write_exp_o <= true;
+
+ -- output expander port number on Port 2 while active edge of PROG
+ -- write 1's to expander port to set lower nibble of Port 2 to input
+ when MSTATE4 =>
+ p2_output_exp_s <= true;
+
+ data_s(nibble_t'range) <= (others => '1');
+ read_dec_s <= true;
+ p2_write_exp_o <= true;
+
+ when MSTATE5 =>
+ p2_output_exp_s <= true;
+
+ when others =>
+ null;
+
+ end case;
+
+ else
+ case clk_mstate_i is
+ -- hold expander port until inactive edge of PROG
+ when MSTATE1 =>
+ p2_output_exp_s <= true;
+
+ -- hold expander port until inactive edge of PROG
+ -- write Accumulator with nibble of expander port
+ when MSTATE2 =>
+ p2_read_p2_o <= true;
+ p2_output_exp_s <= true;
+ p2_read_exp_o <= true;
+ alu_write_accu_o <= true;
+
+ when others =>
+ null;
+
+ end case;
+
+ end if;
+
+ -- Mnemonic MOVP --------------------------------------------------------
+ when MN_MOVP =>
+ assert_psen_s <= true;
+
+ if not clk_second_cycle_i then
+ -- write Accumulator to Program Memory address
+ -- (skip page offset update from Program Counter)
+ if clk_mstate_i = MSTATE3 then
+ alu_read_alu_o <= true;
+ if opc_opcode_s(6) = '0' then
+ pm_addr_type_o <= PM_PAGE;
+ else
+ pm_addr_type_o <= PM_PAGE3;
+ end if;
+ end if;
+
+ else
+ if clk_mstate_i = MSTATE1 then
+ -- store data from Program Memory in Accumulator
+ alu_write_accu_o <= true;
+ -- trick & treat to prevent additional PC increment
+ -- our branch target is the previously incremented PC!
+ branch_taken_s <= true;
+ end if;
+
+ end if;
+
+ -- Mnemonic MOVX --------------------------------------------------------
+ when MN_MOVX =>
+ bus_bidir_bus_o <= true;
+
+ if opc_opcode_s(4) = '0' then
+ clk_assert_rd_o <= true;
+ else
+ clk_assert_wr_o <= true;
+ end if;
+
+ if not clk_second_cycle_i then
+ movx_first_cycle_s <= true;
+ case clk_mstate_i is
+ -- read dmem and put contents on BUS as external address
+ when MSTATE3 =>
+ dm_read_dmem_o <= true;
+ bus_write_bus_o <= true;
+
+ -- store contents of Accumulator to BUS
+ when MSTATE5 =>
+ if opc_opcode_s(4) = '1' then
+ alu_read_alu_o <= true;
+ bus_write_bus_o <= true;
+ end if;
+
+ when others =>
+ null;
+ end case;
+
+ else
+ if clk_mstate_i = MSTATE2 then
+ if opc_opcode_s(4) = '0' then
+ -- store contents of BUS in Accumulator
+ add_read_bus_s <= true;
+ alu_write_accu_o <= true;
+ else
+ -- store contents of Accumulator to BUS
+ -- to this to keep bus in output direction
+ alu_read_alu_o <= true;
+ bus_write_bus_o <= true;
+ end if;
+ end if;
+
+ end if;
+
+ -- Mnemonic NOP ---------------------------------------------------------
+ when MN_NOP =>
+ -- nothing to do
+
+ -- Mnemonic ORL ---------------------------------------------------------
+ when MN_ORL =>
+ case clk_mstate_i is
+ -- read RAM once for indirect address mode
+ when MSTATE3 =>
+ if not enable_quartus_bugfix_c or
+ opc_opcode_s(3) = '0' then
+ address_indirect_3_f;
+ end if;
+
+ -- store data from RAM to Temp Reg
+ when MSTATE4 =>
+ and_or_xor_add_4_f;
+
+ -- perform OR and store in Accumulator
+ when MSTATE5 =>
+ and_or_xor_add_5_f(alu_op => ALU_OR);
+
+ when others =>
+ null;
+
+ end case;
+
+ -- Mnemonic ORL_A_DATA --------------------------------------------------
+ when MN_ORL_A_DATA =>
+ assert_psen_s <= true;
+
+ if clk_second_cycle_i then
+ case clk_mstate_i is
+ -- write Temp Reg when contents of Program Memory is on bus
+ when MSTATE1 =>
+ alu_write_temp_reg_o <= true;
+
+ -- perform OR and store in Accumulator
+ when MSTATE3 =>
+ and_or_xor_add_5_f(alu_op => ALU_OR);
+
+ when others =>
+ null;
+
+ end case;
+
+ end if;
+
+ -- Mnemonic ORL_EXT -----------------------------------------------------
+ when MN_ORL_EXT =>
+ assert_psen_s <= true;
+
+ if not clk_second_cycle_i then
+ -- read port to Temp Reg
+ if clk_mstate_i = MSTATE5 then
+ if opc_opcode_s(1 downto 0) = "00" then
+ add_read_bus_s <= true;
+ elsif opc_opcode_s(1) = '0' then
+ p1_read_p1_o <= true;
+ p1_read_reg_o <= true;
+ else
+ p2_read_p2_o <= true;
+ p2_read_reg_o <= true;
+ end if;
+
+ alu_write_temp_reg_o <= true;
+ end if;
+
+ else
+ case clk_mstate_i is
+ -- write shadow Accumulator when contents of Program Memory is
+ -- on bus
+ when MSTATE1 =>
+ alu_write_shadow_o <= true;
+
+ -- loop shadow Accumulator through ALU to prevent update from
+ -- real Accumulator
+ when MSTATE2 =>
+ alu_read_alu_o <= true;
+ alu_write_shadow_o <= true;
+
+ -- write result of OR operation back to port
+ when MSTATE3 =>
+ alu_op_o <= ALU_OR;
+ alu_read_alu_o <= true;
+
+ if opc_opcode_s(1 downto 0) = "00" then
+ bus_write_bus_o <= true;
+ elsif opc_opcode_s(1) = '0' then
+ p1_write_p1_o <= true;
+ else
+ p2_write_p2_o <= true;
+ end if;
+
+ when others =>
+ null;
+
+ end case;
+
+ end if;
+
+ -- Mnemonic OUTL_EXT ----------------------------------------------------
+ when MN_OUTL_EXT =>
+ if opc_opcode_s(4) = '0' then
+ clk_assert_wr_o <= true;
+ end if;
+
+ -- read Accumulator and store in Port/BUS output register
+ if not clk_second_cycle_i and clk_mstate_i = MSTATE4 then
+ alu_read_alu_o <= true;
+
+ if opc_opcode_s(4) = '1' then
+ if opc_opcode_s(1) = '0' then
+ p1_write_p1_o <= true;
+ else
+ p2_write_p2_o <= true;
+ end if;
+
+ else
+ bus_write_bus_o <= true;
+
+ end if;
+
+ end if;
+
+ -- Mnemonic RET ---------------------------------------------------------
+ when MN_RET =>
+ if not clk_second_cycle_i then
+ case clk_mstate_i is
+ -- decrement Stack Pointer
+ when MSTATE3 =>
+ psw_dec_stackp_o <= true;
+
+ -- read Stack Pointer and address Data Memory for low byte
+ when MSTATE4 =>
+ psw_read_sp_o <= true;
+ dm_write_dmem_addr_o <= true;
+ dm_addr_type_o <= DM_STACK;
+
+ -- read Data Memory and store to Program Counter low
+ -- prepare address to Data memory for high byte
+ when MSTATE5 =>
+ dm_read_dmem_o <= true;
+ pm_write_pcl_o <= true;
+ dm_write_dmem_addr_o <= true;
+ dm_addr_type_o <= DM_STACK_HIGH;
+
+ when others =>
+ null;
+
+ end case;
+
+ else
+ case clk_mstate_i is
+ -- read Data Memory and store to Program Counter high and PSW
+ when MSTATE1 =>
+ dm_read_dmem_o <= true;
+ pm_write_pch_o <= true;
+ if opc_opcode_s(4) = '1' then
+ psw_write_psw_o <= true;
+ retr_executed_s <= true;
+ end if;
+
+ when MSTATE2 =>
+ add_write_pmem_addr_s <= true;
+
+ when others =>
+ null;
+
+ end case;
+
+ end if;
+
+ -- Mnemonic RL ----------------------------------------------------------
+ when MN_RL =>
+ if clk_mstate_i = MSTATE3 then
+ alu_op_o <= ALU_RL;
+ alu_read_alu_o <= true;
+ alu_write_accu_o <= true;
+
+ if opc_opcode_s(4) = '1' then
+ psw_special_data_o <= alu_carry_i;
+ psw_write_carry_o <= true;
+ alu_use_carry_o <= true;
+ end if;
+ end if;
+
+ -- Mnemonic RR ----------------------------------------------------------
+ when MN_RR =>
+ if clk_mstate_i = MSTATE3 then
+ alu_op_o <= ALU_RR;
+ alu_read_alu_o <= true;
+ alu_write_accu_o <= true;
+
+ if opc_opcode_s(4) = '0' then
+ psw_special_data_o <= alu_carry_i;
+ psw_write_carry_o <= true;
+ alu_use_carry_o <= true;
+ end if;
+ end if;
+
+ -- Mnemonic SEL_MB ------------------------------------------------------
+ when MN_SEL_MB =>
+ if clk_mstate_i = MSTATE3 then
+ if opc_opcode_s(4) = '1' then
+ set_mb_s <= true;
+ else
+ clear_mb_s <= true;
+ end if;
+ end if;
+
+ -- Mnemonic SEL_RB ------------------------------------------------------
+ when MN_SEL_RB =>
+ if clk_mstate_i = MSTATE3 then
+ psw_special_data_o <= opc_opcode_s(4);
+ psw_write_bs_o <= true;
+ end if;
+
+ -- Mnemonic STOP_TCNT ---------------------------------------------------
+ when MN_STOP_TCNT =>
+ if clk_mstate_i = MSTATE3 then
+ tim_stop_tcnt_o <= true;
+ end if;
+
+ -- Mnemonic STRT --------------------------------------------------------
+ when MN_STRT =>
+ if clk_mstate_i = MSTATE3 then
+ if opc_opcode_s(4) = '1' then
+ tim_start_t_o <= true;
+ else
+ tim_start_cnt_o <= true;
+ end if;
+ end if;
+
+ -- Mnemonic SWAP --------------------------------------------------------
+ when MN_SWAP =>
+ alu_op_o <= ALU_SWAP;
+
+ if clk_mstate_i = MSTATE3 then
+ alu_read_alu_o <= true;
+ alu_write_accu_o <= true;
+ end if;
+
+ -- Mnemonic XCH ---------------------------------------------------------
+ when MN_XCH =>
+ case clk_mstate_i is
+ -- read RAM once for indirect address mode
+ when MSTATE3 =>
+ if not enable_quartus_bugfix_c or
+ opc_opcode_s(3) = '0' then
+ address_indirect_3_f;
+ end if;
+
+ -- store data from RAM in Accumulator and Temp Reg
+ -- Accumulator is already shadowed!
+ when MSTATE4 =>
+ dm_read_dmem_o <= true;
+ alu_write_accu_o <= true;
+ alu_write_temp_reg_o <= true;
+ if opc_opcode_s(4) = '1' then
+ -- XCHD
+ -- only write lower nibble of Accumulator
+ alu_accu_low_o <= true;
+ end if;
+
+ -- store data from shadow (previous) Accumulator to dmem
+ when MSTATE5 =>
+ dm_write_dmem_s <= true;
+ alu_read_alu_o <= true;
+ if opc_opcode_s(4) = '1' then
+ -- XCHD
+ -- concatenate shadow Accumulator and Temp Reg
+ alu_op_o <= ALU_CONCAT;
+ end if;
+
+ when others =>
+ null;
+
+ end case;
+
+ -- Mnemonic XRL ---------------------------------------------------------
+ when MN_XRL =>
+ case clk_mstate_i is
+ -- read RAM once for indirect address mode
+ when MSTATE3 =>
+ if not enable_quartus_bugfix_c or
+ opc_opcode_s(3) = '0' then
+ address_indirect_3_f;
+ end if;
+
+ -- store data from RAM to Temp Reg
+ when MSTATE4 =>
+ and_or_xor_add_4_f;
+
+ -- perform XOR and store in Accumulator
+ when MSTATE5 =>
+ and_or_xor_add_5_f(alu_op => ALU_XOR);
+
+ when others =>
+ null;
+
+ end case;
+
+ -- Mnemonic XRL_A_DATA --------------------------------------------------
+ when MN_XRL_A_DATA =>
+ assert_psen_s <= true;
+
+ if clk_second_cycle_i then
+ case clk_mstate_i is
+ -- write Temp Reg when contents of Program Memory is on bus
+ when MSTATE1 =>
+ alu_write_temp_reg_o <= true;
+
+ -- perform XOR and store in Accumulator
+ when MSTATE3 =>
+ and_or_xor_add_5_f(alu_op => ALU_XOR);
+
+ when others =>
+ null;
+
+ end case;
+
+ end if;
+
+ -- Unimplemented mnemonic -----------------------------------------------
+ when others =>
+ -- this will behave like a NOP
+
+ -- pragma translate_off
+ assert false
+ report "Mnemonic not yet implemented."
+ severity warning;
+ -- pragma translate_on
+
+ end case;
+
+ end process decode;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process regs
+ --
+ -- Purpose:
+ -- Implements the various registes.
+ --
+ regs: process (res_i, clk_i)
+ begin
+ if res_i = res_active_c then
+ branch_taken_q <= false;
+ f1_q <= '0';
+ mb_q <= '0';
+ t0_dir_q <= '0';
+ -- pragma translate_off
+ istrobe_res_q <= '1';
+ istrobe_q <= '0';
+ injected_int_q <= '0';
+ -- pragma translate_on
+
+ elsif clk_i'event and clk_i = clk_active_c then
+ if en_clk_i then
+
+ -- branch taken flag
+ if branch_taken_s then
+ branch_taken_q <= true;
+ elsif clk_mstate_i = MSTATE5 then
+ -- release flag when new instruction starts
+ branch_taken_q <= false;
+ end if;
+
+ -- Flag 1
+ if clear_f1_s then
+ f1_q <= '0';
+ elsif cpl_f1_s then
+ f1_q <= not f1_q;
+ end if;
+
+ -- Memory Bank select
+ if clear_mb_s then
+ mb_q <= '0';
+ elsif set_mb_s then
+ mb_q <= '1';
+ end if;
+
+ -- T0 direction selection
+ if ent0_clk_s then
+ t0_dir_q <= '1';
+ end if;
+
+ -- pragma translate_off
+ -- Marker for injected instruction ------------------------------------
+ if opc_inj_int_s then
+ injected_int_q <= '1';
+ elsif clk_mstate_i = MSTATE5 and last_cycle_s then
+ injected_int_q <= '0';
+ end if;
+
+ -- Remove istrobe after reset suppression -----------------------------
+ if clk_mstate_i = MSTATE5 and last_cycle_s then
+ istrobe_res_q <= '0';
+ end if;
+ -- pragma translate_on
+
+ end if;
+
+ -- pragma translate_off
+ -- Instruction Strobe ---------------------------------------------------
+ if clk_mstate_i = MSTATE5 and last_cycle_s and
+ injected_int_q = '0' then
+ if istrobe_res_q = '0' then
+ istrobe_q <= '1';
+ end if;
+ else
+ istrobe_q <= '0';
+ end if;
+ -- pragma translate_on
+
+ end if;
+
+ end process regs;
+ --
+ -----------------------------------------------------------------------------
+
+ -- pragma translate_off
+ -- assign to global signal for testbench
+ tb_istrobe_s <= istrobe_q;
+ -- pragma translate_on
+
+
+ -----------------------------------------------------------------------------
+ -- Output Mapping.
+ -----------------------------------------------------------------------------
+ clk_multi_cycle_o <= opc_multi_cycle_s;
+ cnd_f1_o <= f1_q;
+ cnd_tf_o <= tf_s;
+ data_o <= data_s
+ when read_dec_s else
+ (others => bus_idle_level_c);
+ dm_write_dmem_o <= dm_write_dmem_s and en_clk_i;
+ pm_inc_pc_o <= pm_inc_pc_s or add_inc_pc_s;
+ pm_write_pmem_addr_o <= pm_write_pmem_addr_s or add_write_pmem_addr_s;
+ t0_dir_o <= t0_dir_q;
+ bus_read_bus_o <= bus_read_bus_s or add_read_bus_s;
+
+end rtl;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: decoder.vhd,v $
+-- Revision 1.25 2006/06/20 00:46:03 arniml
+-- new input xtal_en_i
+--
+-- Revision 1.24 2005/11/14 21:12:29 arniml
+-- suppress p2_output_pch_o when MOVX operation is accessing the
+-- external memory
+--
+-- Revision 1.23 2005/11/07 19:25:01 arniml
+-- fix sensitivity list
+--
+-- Revision 1.22 2005/11/01 21:25:37 arniml
+-- * suppress p2_output_pch_o when p2_output_exp is active
+-- * wire xtal_i to interrupt module
+--
+-- Revision 1.21 2005/10/31 10:08:33 arniml
+-- Suppress assertion of bus_read_bus_s when interrupt is pending.
+-- This should fix bug report
+-- "PROBLEM WHEN INT AND JMP"
+--
+-- Revision 1.20 2005/09/13 21:08:34 arniml
+-- move check for int_pending_s into ea_i_='0' branch
+-- this fixes a glitch on PCH when an interrutp occurs
+-- during external program memory fetch
+--
+-- Revision 1.19 2005/06/11 10:08:43 arniml
+-- introduce prefix 't48_' for all packages, entities and configurations
+--
+-- Revision 1.18 2005/06/09 22:18:28 arniml
+-- Move latching of BUS to MSTATE2
+-- -> sample BUS at the end of RD'
+--
+-- Revision 1.17 2005/05/09 22:26:08 arniml
+-- remove obsolete output stack_high_o
+--
+-- Revision 1.16 2004/10/25 19:39:24 arniml
+-- Fix bug report:
+-- "RD' and WR' not asserted for INS A, BUS and OUTL BUS, A"
+-- rd is asserted for INS A, BUS
+-- wr is asserted for OUTL BUS, A
+-- P1, P2 and BUS are written in first instruction cycle
+--
+-- Revision 1.15 2004/09/12 00:35:44 arniml
+-- Fix bug report:
+-- "PSENn Timing"
+-- PSEN is now only asserted for the second cycle if explicitely
+-- requested by assert_psen_s.
+-- The previous implementation asserted PSEN together with RD or WR.
+--
+-- Revision 1.14 2004/06/30 21:18:28 arniml
+-- Fix bug report:
+-- "Program Memory bank can be switched during interrupt"
+-- int module emits int_in_progress signal that is used inside the decoder
+-- to hold mb low for JMP and CALL during interrupts
+--
+-- Revision 1.13 2004/05/20 21:51:40 arniml
+-- clean-up use of ea_i
+--
+-- Revision 1.12 2004/05/17 14:40:09 arniml
+-- assert p2_read_p2_o when expander port is read
+--
+-- Revision 1.11 2004/05/16 15:33:39 arniml
+-- work around bug in Quartus II 4.0
+--
+-- Revision 1.10 2004/04/25 16:22:03 arniml
+-- adjust external timing of BUS
+--
+-- Revision 1.9 2004/04/24 11:22:55 arniml
+-- removed superfluous signal from sensitivity list
+--
+-- Revision 1.8 2004/04/18 18:57:43 arniml
+-- + enhance instruction strobe generation
+-- + rework address output under EA=1 conditions
+--
+-- Revision 1.7 2004/04/15 22:06:05 arniml
+-- + add marker for injected calls
+-- + suppress intstruction strobes for injected calls
+--
+-- Revision 1.6 2004/04/14 20:53:33 arniml
+-- make istrobe visible through testbench package
+--
+-- Revision 1.5 2004/04/07 22:09:03 arniml
+-- remove unused signals
+--
+-- Revision 1.4 2004/04/04 14:18:53 arniml
+-- add measures to implement XCHD
+--
+-- Revision 1.3 2004/03/28 21:15:48 arniml
+-- implemented mnemonic DA
+--
+-- Revision 1.2 2004/03/28 13:06:32 arniml
+-- implement mnemonics:
+-- + MOVD_A_PP
+-- + OUTD_PP_A -> ANLD PP, A; MOVD PP, A; ORLD PP, A
+--
+-- Revision 1.1 2004/03/23 21:31:52 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/CPU/t48/rtl/vhdl/decoder_pack-p.vhd b/common/CPU/t48/rtl/vhdl/decoder_pack-p.vhd
new file mode 100644
index 00000000..5051e3d5
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/decoder_pack-p.vhd
@@ -0,0 +1,90 @@
+-------------------------------------------------------------------------------
+--
+-- $Id: decoder_pack-p.vhd,v 1.3 2005/06/11 10:08:43 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+package t48_decoder_pack is
+
+ -----------------------------------------------------------------------------
+ -- The Mnemonics.
+ -----------------------------------------------------------------------------
+ type mnemonic_t is (MN_ADD,
+ MN_ADD_A_DATA,
+ MN_ANL,
+ MN_ANL_A_DATA,
+ MN_ANL_EXT,
+ MN_CALL,
+ MN_CLR_A,
+ MN_CLR_C,
+ MN_CLR_F,
+ MN_CPL_A,
+ MN_CPL_C,
+ MN_CPL_F,
+ MN_DA,
+ MN_DEC,
+ MN_DIS_EN_I,
+ MN_DIS_EN_TCNTI,
+ MN_DJNZ,
+ MN_ENT0_CLK,
+ MN_IN,
+ MN_INC,
+ MN_INS,
+ MN_JBB,
+ MN_JC,
+ MN_JF,
+ MN_JMP,
+ MN_JMPP,
+ MN_JNI,
+ MN_JT,
+ MN_JTF,
+ MN_JZ,
+ MN_MOV_A_DATA,
+ MN_MOV_A_PSW,
+ MN_MOV_A_RR,
+ MN_MOV_PSW_A,
+ MN_MOV_RR,
+ MN_MOV_RR_DATA,
+ MN_MOV_T,
+ MN_MOVD_A_PP,
+ MN_MOVP,
+ MN_MOVX,
+ MN_NOP,
+ MN_ORL,
+ MN_ORL_A_DATA,
+ MN_ORL_EXT,
+ MN_OUTD_PP_A,
+ MN_OUTL_EXT,
+ MN_RET,
+ MN_RL,
+ MN_RR,
+ MN_SEL_MB,
+ MN_SEL_RB,
+ MN_STOP_TCNT,
+ MN_STRT,
+ MN_SWAP,
+ MN_XCH,
+ MN_XRL,
+ MN_XRL_A_DATA);
+
+end t48_decoder_pack;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: decoder_pack-p.vhd,v $
+-- Revision 1.3 2005/06/11 10:08:43 arniml
+-- introduce prefix 't48_' for all packages, entities and configurations
+--
+-- Revision 1.2 2004/03/28 13:09:53 arniml
+-- merge MN_ANLD, MN_MOVD_PP_A and MN_ORLD_PP_A to OUTLD_PP_A
+--
+-- Revision 1.1 2004/03/23 21:31:52 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/CPU/t48/rtl/vhdl/dmem_ctrl-c.vhd b/common/CPU/t48/rtl/vhdl/dmem_ctrl-c.vhd
new file mode 100644
index 00000000..c82948c1
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/dmem_ctrl-c.vhd
@@ -0,0 +1,19 @@
+-------------------------------------------------------------------------------
+--
+-- The Data Memory control unit.
+-- All accesses to the Data Memory are managed here.
+--
+-- $Id: dmem_ctrl-c.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+configuration t48_dmem_ctrl_rtl_c0 of t48_dmem_ctrl is
+
+ for rtl
+ end for;
+
+end t48_dmem_ctrl_rtl_c0;
diff --git a/common/CPU/t48/rtl/vhdl/dmem_ctrl.vhd b/common/CPU/t48/rtl/vhdl/dmem_ctrl.vhd
new file mode 100644
index 00000000..9b42861a
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/dmem_ctrl.vhd
@@ -0,0 +1,224 @@
+-------------------------------------------------------------------------------
+--
+-- The Data Memory control unit.
+-- All accesses to the Data Memory are managed here.
+--
+-- $Id: dmem_ctrl.vhd,v 1.5 2006/06/20 01:07:16 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.dmem_addr_t;
+use work.t48_pack.word_t;
+use work.t48_dmem_ctrl_pack.dmem_addr_ident_t;
+
+entity t48_dmem_ctrl is
+
+ port (
+ -- Global Interface -------------------------------------------------------
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ -- Control Interface ------------------------------------------------------
+ data_i : in word_t;
+ write_dmem_addr_i : in boolean;
+ write_dmem_i : in boolean;
+ read_dmem_i : in boolean;
+ addr_type_i : in dmem_addr_ident_t;
+ bank_select_i : in std_logic;
+ data_o : out word_t;
+ -- Data Memory Interface --------------------------------------------------
+ dmem_data_i : in word_t;
+ dmem_addr_o : out dmem_addr_t;
+ dmem_we_o : out std_logic;
+ dmem_data_o : out word_t
+ );
+
+end t48_dmem_ctrl;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+use work.t48_pack.clk_active_c;
+use work.t48_pack.res_active_c;
+use work.t48_pack.bus_idle_level_c;
+use work.t48_pack.to_stdLogic;
+
+use work.t48_dmem_ctrl_pack.all;
+
+architecture rtl of t48_dmem_ctrl is
+
+ signal dmem_addr_s,
+ dmem_addr_q : dmem_addr_t;
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process addr_decode
+ --
+ -- Purpose:
+ -- Decode/multiplex the address information for the Data Memory.
+ --
+ addr_decode: process (data_i,
+ addr_type_i,
+ bank_select_i,
+ dmem_addr_q)
+ variable stack_addr_v : unsigned(5 downto 0);
+ begin
+ -- default assignment
+ dmem_addr_s <= dmem_addr_q;
+ stack_addr_v := (others => '0');
+
+ case addr_type_i is
+ when DM_PLAIN =>
+ dmem_addr_s <= data_i;
+
+ when DM_REG =>
+ dmem_addr_s <= (others => '0');
+ dmem_addr_s(2 downto 0) <= data_i(2 downto 0);
+ -- implement bank switching
+ if bank_select_i = '1' then
+ -- dmem address 24 - 31: access proper set
+ dmem_addr_s(4 downto 3) <= "11";
+ end if;
+
+ when DM_STACK =>
+ -- build address from stack pointer
+ stack_addr_v(3 downto 1) := unsigned(data_i(2 downto 0));
+ -- dmem address 8 - 23
+ stack_addr_v := stack_addr_v + 8;
+
+ dmem_addr_s <= (others => '0');
+ dmem_addr_s(5 downto 0) <= std_logic_vector(stack_addr_v);
+
+ when DM_STACK_HIGH =>
+ dmem_addr_s(0) <= '1';
+
+ when others =>
+ -- do nothing
+
+ -- pragma translate_off
+ assert false
+ report "Unknown address type identification for Data Memory controller!"
+ severity error;
+ -- pragma translate_on
+
+ end case;
+
+ end process addr_decode;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process dmem_addr_reg
+ --
+ -- Purpose:
+ -- Implements the Data Memory Address Register.
+ -- This register is required to hold the address during a write operation
+ -- as we cannot hold the address in the input register of the
+ -- synchronous RAM (no clock suppression/gating).
+ --
+ -- NOTE: May be obsoleted by clock enable feature of generic RTL RAM.
+ --
+ dmem_addr_reg: process (res_i, clk_i)
+ begin
+ if res_i = res_active_c then
+ dmem_addr_q <= (others => '0');
+
+ elsif clk_i'event and clk_i = clk_active_c then
+ if en_clk_i then
+
+ if write_dmem_addr_i then
+ dmem_addr_q <= dmem_addr_s;
+ end if;
+
+ end if;
+
+ end if;
+
+ end process dmem_addr_reg;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Output mapping.
+ -----------------------------------------------------------------------------
+ dmem_addr_o <= dmem_addr_s
+ when write_dmem_addr_i and en_clk_i else
+ dmem_addr_q;
+
+ -- data from bus is fed through
+ dmem_data_o <= data_i;
+
+ -- data to bus is enabled upon read request
+ data_o <= dmem_data_i
+ when read_dmem_i else
+ (others => bus_idle_level_c);
+
+ -- write enable to Data Memory is fed through
+ dmem_we_o <= to_stdLogic(write_dmem_i);
+
+end rtl;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: dmem_ctrl.vhd,v $
+-- Revision 1.5 2006/06/20 01:07:16 arniml
+-- add note about clock enable for data memory RAM macro
+--
+-- Revision 1.4 2005/06/11 10:08:43 arniml
+-- introduce prefix 't48_' for all packages, entities and configurations
+--
+-- Revision 1.3 2004/04/24 23:44:25 arniml
+-- move from std_logic_arith to numeric_std
+--
+-- Revision 1.2 2004/04/18 18:58:29 arniml
+-- clean up sensitivity list
+--
+-- Revision 1.1 2004/03/23 21:31:52 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/CPU/t48/rtl/vhdl/dmem_ctrl_pack-p.vhd b/common/CPU/t48/rtl/vhdl/dmem_ctrl_pack-p.vhd
new file mode 100644
index 00000000..3bde1b7c
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/dmem_ctrl_pack-p.vhd
@@ -0,0 +1,34 @@
+-------------------------------------------------------------------------------
+--
+-- $Id: dmem_ctrl_pack-p.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+package t48_dmem_ctrl_pack is
+
+ -----------------------------------------------------------------------------
+ -- Address Type Identifier
+ -----------------------------------------------------------------------------
+ type dmem_addr_ident_t is (DM_PLAIN,
+ DM_REG,
+ DM_STACK,
+ DM_STACK_HIGH);
+
+end t48_dmem_ctrl_pack;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: dmem_ctrl_pack-p.vhd,v $
+-- Revision 1.2 2005/06/11 10:08:43 arniml
+-- introduce prefix 't48_' for all packages, entities and configurations
+--
+-- Revision 1.1 2004/03/23 21:31:52 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/CPU/t48/rtl/vhdl/int-c.vhd b/common/CPU/t48/rtl/vhdl/int-c.vhd
new file mode 100644
index 00000000..6f7d4d8f
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/int-c.vhd
@@ -0,0 +1,17 @@
+-------------------------------------------------------------------------------
+--
+-- The Interrupt Controller.
+-- It collects the interrupt sources and notifies the decoder.
+--
+-- $Id: int-c.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+configuration t48_int_rtl_c0 of t48_int is
+
+ for rtl
+ end for;
+
+end t48_int_rtl_c0;
diff --git a/common/CPU/t48/rtl/vhdl/int.vhd b/common/CPU/t48/rtl/vhdl/int.vhd
new file mode 100644
index 00000000..170d4982
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/int.vhd
@@ -0,0 +1,289 @@
+-------------------------------------------------------------------------------
+--
+-- The Interrupt Controller.
+-- It collects the interrupt sources and notifies the decoder.
+--
+-- $Id: int.vhd,v 1.7 2006/06/20 00:46:03 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.mstate_t;
+
+entity t48_int is
+
+ port (
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ xtal_i : in std_logic;
+ xtal_en_i : in boolean;
+ clk_mstate_i : in mstate_t;
+ jtf_executed_i : in boolean;
+ tim_overflow_i : in boolean;
+ tf_o : out std_logic;
+ en_tcnti_i : in boolean;
+ dis_tcnti_i : in boolean;
+ int_n_i : in std_logic;
+ ale_i : in boolean;
+ last_cycle_i : in boolean;
+ en_i_i : in boolean;
+ dis_i_i : in boolean;
+ ext_int_o : out boolean;
+ tim_int_o : out boolean;
+ retr_executed_i : in boolean;
+ int_executed_i : in boolean;
+ int_pending_o : out boolean;
+ int_in_progress_o : out boolean
+ );
+
+end t48_int;
+
+
+use work.t48_pack.all;
+
+architecture rtl of t48_int is
+
+ constant tim_int_c : std_logic := '0';
+ constant ext_int_c : std_logic := '1';
+
+ type int_state_t is (IDLE, PENDING, INT);
+
+ signal int_state_s,
+ int_state_q : int_state_t;
+
+ signal timer_flag_q : boolean;
+ signal timer_overflow_q : boolean;
+ signal timer_int_enable_q : boolean;
+ signal int_q : boolean;
+ signal int_enable_q : boolean;
+ signal ale_q : boolean;
+ signal int_type_q : std_logic;
+ signal int_in_progress_q : boolean;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process nstate
+ --
+ -- Purpose:
+ -- Determines the next state of the Interrupt controller FSM.
+ --
+ nstate: process (int_state_q,
+ int_type_q,
+ int_in_progress_q,
+ int_executed_i,
+ retr_executed_i,
+ clk_mstate_i,
+ last_cycle_i)
+ begin
+ int_state_s <= int_state_q;
+
+ case int_state_q is
+ when IDLE =>
+ if int_in_progress_q and
+ last_cycle_i and clk_mstate_i = MSTATE5 then
+ int_state_s <= PENDING;
+ end if;
+
+ when PENDING =>
+ if int_executed_i then
+ int_state_s <= INT;
+ end if;
+
+ when INT =>
+ if retr_executed_i then
+ int_state_s <= IDLE;
+ end if;
+
+ when others =>
+ int_state_s <= IDLE;
+
+ end case;
+
+ end process nstate;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process regs
+ --
+ -- Purpose:
+ -- Implement the various registers.
+ -- They are designed according Figure "Interrupt Logic" of
+ -- "The Single Component MCS-48 System".
+ --
+ regs: process (res_i, clk_i)
+ begin
+ if res_i = res_active_c then
+ timer_flag_q <= false;
+ timer_overflow_q <= false;
+ timer_int_enable_q <= false;
+ int_enable_q <= false;
+ int_type_q <= '0';
+ int_state_q <= IDLE;
+ int_in_progress_q <= false;
+
+ elsif clk_i'event and clk_i = clk_active_c then
+ if en_clk_i then
+
+ int_state_q <= int_state_s;
+
+ if jtf_executed_i then
+ timer_flag_q <= false;
+ elsif tim_overflow_i then
+ timer_flag_q <= true;
+ end if;
+
+ if (int_type_q = tim_int_c and int_executed_i) or
+ not timer_int_enable_q then
+ timer_overflow_q <= false;
+ elsif tim_overflow_i then
+ timer_overflow_q <= true;
+ end if;
+
+ if dis_tcnti_i then
+ timer_int_enable_q <= false;
+ elsif en_tcnti_i then
+ timer_int_enable_q <= true;
+ end if;
+
+ if dis_i_i then
+ int_enable_q <= false;
+ elsif en_i_i then
+ int_enable_q <= true;
+ end if;
+
+ if retr_executed_i then
+ int_in_progress_q <= false;
+ elsif (int_q and int_enable_q) or
+ timer_overflow_q then
+ int_in_progress_q <= true;
+ if not int_in_progress_q then
+ int_type_q <= to_stdLogic(int_q and int_enable_q);
+ end if;
+ end if;
+
+ end if;
+
+ end if;
+
+ end process regs;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process xtal_regs
+ --
+ -- Purpose:
+ -- Implements the sequential registers clocked with XTAL.
+ --
+ xtal_regs: process (res_i, xtal_i)
+ begin
+ if res_i = res_active_c then
+ int_q <= false;
+ ale_q <= false;
+
+ elsif xtal_i'event and xtal_i = clk_active_c then
+ if xtal_en_i then
+ ale_q <= ale_i;
+
+ if last_cycle_i and
+ ale_q and not ale_i then
+ int_q <= not to_boolean(int_n_i);
+ end if;
+
+ end if;
+ end if;
+ end process xtal_regs;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Output Mapping.
+ -----------------------------------------------------------------------------
+ tf_o <= to_stdLogic(timer_flag_q);
+ ext_int_o <= int_type_q = ext_int_c;
+ tim_int_o <= int_type_q = tim_int_c;
+ int_pending_o <= int_state_q = PENDING;
+ int_in_progress_o <= int_in_progress_q and int_state_q /= IDLE;
+
+end rtl;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: int.vhd,v $
+-- Revision 1.7 2006/06/20 00:46:03 arniml
+-- new input xtal_en_i
+--
+-- Revision 1.6 2005/11/01 21:26:24 arniml
+-- operate ale_q and int_q with xtal_i after shift of ALE assertion to XTAL3
+--
+-- Revision 1.5 2005/09/13 21:00:16 arniml
+-- Fix bug reports:
+-- "Target address of JMP to Program Memory Bank 1 corrupted by interrupt"
+-- "Return address of CALL to Program Memory Bank 1 corrupted by interrupt"
+-- int_in_progress_o was active one cycle before int_pending_o is
+-- asserted. this confused the mb multiplexer which determines the state of
+-- the memory bank selection flag
+--
+-- Revision 1.4 2005/06/11 10:08:43 arniml
+-- introduce prefix 't48_' for all packages, entities and configurations
+--
+-- Revision 1.3 2004/07/11 16:51:33 arniml
+-- cleanup copyright notice
+--
+-- Revision 1.2 2004/06/30 21:18:28 arniml
+-- Fix bug report:
+-- "Program Memory bank can be switched during interrupt"
+-- int module emits int_in_progress signal that is used inside the decoder
+-- to hold mb low for JMP and CALL during interrupts
+--
+-- Revision 1.1 2004/03/23 21:31:52 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/CPU/t48/rtl/vhdl/opc_decoder-c.vhd b/common/CPU/t48/rtl/vhdl/opc_decoder-c.vhd
new file mode 100644
index 00000000..d8888988
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/opc_decoder-c.vhd
@@ -0,0 +1,23 @@
+-------------------------------------------------------------------------------
+--
+-- The Opcode Decoder.
+-- Derives instruction mnemonics and multicycle information
+-- using the OPC table unit.
+--
+-- $Id: opc_decoder-c.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+configuration t48_opc_decoder_rtl_c0 of t48_opc_decoder is
+
+ for rtl
+
+ for opc_table_b: t48_opc_table
+ use configuration work.t48_opc_table_rtl_c0;
+ end for;
+
+ end for;
+
+end t48_opc_decoder_rtl_c0;
diff --git a/common/CPU/t48/rtl/vhdl/opc_decoder.vhd b/common/CPU/t48/rtl/vhdl/opc_decoder.vhd
new file mode 100644
index 00000000..c002232c
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/opc_decoder.vhd
@@ -0,0 +1,182 @@
+-------------------------------------------------------------------------------
+--
+-- The Opcode Decoder.
+-- Derives instruction mnemonics and multicycle information
+-- using the OPC table unit.
+--
+-- $Id: opc_decoder.vhd,v 1.3 2005/06/11 10:08:43 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.word_t;
+use work.t48_decoder_pack.mnemonic_t;
+
+entity t48_opc_decoder is
+
+ generic (
+ -- store mnemonic in flip-flops (registered-out)
+ register_mnemonic_g : integer := 1
+ );
+
+ port (
+ -- Global Interface -------------------------------------------------------
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ -- T48 Bus Interface ------------------------------------------------------
+ data_i : in word_t;
+ read_bus_i : in boolean;
+ -- Decoder Interface ------------------------------------------------------
+ inj_int_i : in boolean;
+ opcode_o : out word_t;
+ mnemonic_o : out mnemonic_t;
+ multi_cycle_o : out boolean
+ );
+
+end t48_opc_decoder;
+
+
+use work.t48_pack.clk_active_c;
+use work.t48_pack.res_active_c;
+use work.t48_pack.to_boolean;
+--use work.decoder_pack.MN_NOP;
+use work.t48_decoder_pack.all;
+
+use work.t48_comp_pack.t48_opc_table;
+
+architecture rtl of t48_opc_decoder is
+
+ -- the opcode register
+ signal opcode_q : word_t;
+
+ -- the mnemonic
+ signal mnemonic_s,
+ mnemonic_q : mnemonic_t;
+
+ signal multi_cycle_s : std_logic;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Verify the generics
+ -----------------------------------------------------------------------------
+
+ -- pragma translate_off
+
+ -- Register Mnemonic --------------------------------------------------------
+ assert (register_mnemonic_g = 1) or (register_mnemonic_g = 0)
+ report "register_mnemonic_g must be either 1 or 0!"
+ severity failure;
+
+ -- pragma translate_on
+
+
+ -----------------------------------------------------------------------------
+ -- Opcode Decoder Table
+ -----------------------------------------------------------------------------
+ opc_table_b : t48_opc_table
+ port map (
+ opcode_i => opcode_q,
+ multi_cycle_o => multi_cycle_s,
+ mnemonic_o => mnemonic_s
+ );
+
+
+ -----------------------------------------------------------------------------
+ -- Process regs
+ --
+ -- Purpose:
+ -- Implements the opcode and mnemonic registers.
+ --
+ regs: process (res_i, clk_i)
+ begin
+ if res_i = res_active_c then
+ opcode_q <= (others => '0'); -- NOP
+ mnemonic_q <= MN_NOP;
+
+ elsif clk_i'event and clk_i = clk_active_c then
+ if en_clk_i then
+
+ if read_bus_i then
+ opcode_q <= data_i;
+ elsif inj_int_i then
+ opcode_q <= "00010100";
+ else
+ mnemonic_q <= mnemonic_s;
+ end if;
+
+ end if;
+
+ end if;
+
+ end process regs;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Output Mapping.
+ -----------------------------------------------------------------------------
+ opcode_o <= opcode_q;
+ multi_cycle_o <= to_boolean(multi_cycle_s);
+ mnemonic_o <= mnemonic_q
+ when register_mnemonic_g = 1 else
+ mnemonic_s;
+
+end rtl;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: opc_decoder.vhd,v $
+-- Revision 1.3 2005/06/11 10:08:43 arniml
+-- introduce prefix 't48_' for all packages, entities and configurations
+--
+-- Revision 1.2 2004/07/11 16:51:33 arniml
+-- cleanup copyright notice
+--
+-- Revision 1.1 2004/03/23 21:31:52 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/CPU/t48/rtl/vhdl/opc_table-c.vhd b/common/CPU/t48/rtl/vhdl/opc_table-c.vhd
new file mode 100644
index 00000000..96c1de95
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/opc_table-c.vhd
@@ -0,0 +1,18 @@
+-------------------------------------------------------------------------------
+--
+-- The Opcode Decoder Table.
+-- Decodes the given opcode to instruction mnemonics.
+-- Also derives the multicycle information.
+--
+-- $Id: opc_table-c.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+configuration t48_opc_table_rtl_c0 of t48_opc_table is
+
+ for rtl
+ end for;
+
+end t48_opc_table_rtl_c0;
diff --git a/common/CPU/t48/rtl/vhdl/opc_table.vhd b/common/CPU/t48/rtl/vhdl/opc_table.vhd
new file mode 100644
index 00000000..883f4887
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/opc_table.vhd
@@ -0,0 +1,425 @@
+-------------------------------------------------------------------------------
+--
+-- The Opcode Decoder Table.
+-- Decodes the given opcode to instruction mnemonics.
+-- Also derives the multicycle information.
+--
+-- $Id: opc_table.vhd,v 1.4 2005/06/11 10:08:43 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.word_t;
+use work.t48_decoder_pack.mnemonic_t;
+
+entity t48_opc_table is
+
+ port (
+ opcode_i : in word_t;
+ multi_cycle_o : out std_logic;
+ mnemonic_o : out mnemonic_t
+ );
+
+end t48_opc_table;
+
+
+use work.t48_decoder_pack.all;
+
+architecture rtl of t48_opc_table is
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process opc_decode
+ --
+ -- Purpose:
+ -- Decode the opcode to the set of mnemonics.
+ --
+ opc_decode: process (opcode_i)
+ begin
+ -- default assignment
+ mnemonic_o <= MN_NOP;
+ multi_cycle_o <= '0';
+
+ case opcode_i is
+ -- Mnemonic ADD ---------------------------------------------------------
+ when "01101000" | "01101001" | "01101010" | "01101011" | -- ADD A, Rr
+ "01101100" | "01101101" | "01101110" | "01101111" | --
+ "01100000" | "01100001" | -- ADD A, @ Rr
+ "01111000" | "01111001" | "01111010" | "01111011" | -- ADDC A, Rr
+ "01111100" | "01111101" | "01111110" | "01111111" | --
+ "01110000" | "01110001" => -- ADDC A, @ Rr
+ mnemonic_o <= MN_ADD;
+
+ -- Mnemonic ADD_A_DATA --------------------------------------------------
+ when "00000011" | -- ADD A, data
+ "00010011" => -- ADDC A, data
+ mnemonic_o <= MN_ADD_A_DATA;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic ANL ---------------------------------------------------------
+ when "01011000" | "01011001" | "01011010" | "01011011" | -- ANL A, Rr
+ "01011100" | "01011101" | "01011110" | "01011111" | --
+ "01010000" | "01010001" => -- ANL A, @ Rr
+ mnemonic_o <= MN_ANL;
+
+ -- Mnemonic ANL_A_DATA --------------------------------------------------
+ when "01010011" => -- ANL A, data
+ mnemonic_o <= MN_ANL_A_DATA;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic ANL_EXT -----------------------------------------------------
+ when "10011000" | -- ANL BUS, data
+ "10011001" | "10011010" => -- ANL PP, data
+ mnemonic_o <= MN_ANL_EXT;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic CALL --------------------------------------------------------
+ when "00010100" | "00110100" | "01010100" | "01110100" | -- CALL addr
+ "10010100" | "10110100" | "11010100" | "11110100" => --
+ mnemonic_o <= MN_CALL;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic CLR_A -------------------------------------------------------
+ when "00100111" => -- CLR A
+ mnemonic_o <= MN_CLR_A;
+
+ -- Mnemonic CLR_C -------------------------------------------------------
+ when "10010111" => -- CLR C
+ mnemonic_o <= MN_CLR_C;
+
+ -- Mnemonic CLR_F -------------------------------------------------------
+ when "10000101" | -- CLR F0
+ "10100101" =>
+ mnemonic_o <= MN_CLR_F;
+
+ -- Mnemonic CPL_A -------------------------------------------------------
+ when "00110111" => -- CPL A
+ mnemonic_o <= MN_CPL_A;
+
+ -- Mnemonic CPL_C -------------------------------------------------------
+ when "10100111" => -- CPL C
+ mnemonic_o <= MN_CPL_C;
+
+ -- Mnemonic CPL_F -------------------------------------------------------
+ when "10010101" | -- CPL F0
+ "10110101" => -- CPL F1
+ mnemonic_o <= MN_CPL_F;
+
+ -- Mnemonic DA ----------------------------------------------------------
+ when "01010111" => -- DA D
+ mnemonic_o <= MN_DA;
+
+ -- Mnemonic DEC ---------------------------------------------------------
+ when "11001000" | "11001001" | "11001010" | "11001011" | -- DEC Rr
+ "11001100" | "11001101" | "11001110" | "11001111" | --
+ "00000111" => -- DEC A
+ mnemonic_o <= MN_DEC;
+
+ -- Mnemonic DIS_EN_I ----------------------------------------------------
+ when "00010101" | -- DIS I
+ "00000101" => -- EN I
+ mnemonic_o <= MN_DIS_EN_I;
+
+ -- Mnemonic DIS_EN_TCNTI ------------------------------------------------
+ when "00110101" | -- DIS TCNTI
+ "00100101" => -- EN TCNTI
+ mnemonic_o <= MN_DIS_EN_TCNTI;
+
+ -- Mnemonic DJNZ --------------------------------------------------------
+ when "11101000" | "11101001" | "11101010" | "11101011" | -- DJNZ Rr, addr
+ "11101100" | "11101101" | "11101110" | "11101111" => --
+ mnemonic_o <= MN_DJNZ;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic ENT0_CLK ----------------------------------------------------
+ when "01110101" => -- ENT0 CLK
+ mnemonic_o <= MN_ENT0_CLK;
+
+ -- Mnemonic IN ----------------------------------------------------------
+ when "00001001" | "00001010" => -- IN A, Pp
+ mnemonic_o <= MN_IN;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic INC ---------------------------------------------------------
+ when "00010111" | -- INC A
+ "00011000" | "00011001" | "00011010" | "00011011" | -- INC Rr
+ "00011100" | "00011101" | "00011110" | "00011111" | --
+ "00010000" | "00010001" => -- INC @ Rr
+ mnemonic_o <= MN_INC;
+
+ -- Mnemonic INS ---------------------------------------------------------
+ when "00001000" => -- INS A, BUS
+ mnemonic_o <= MN_INS;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic JBB ---------------------------------------------------------
+ when "00010010" | "00110010" | "01010010" | "01110010" | -- JBb addr
+ "10010010" | "10110010" | "11010010" | "11110010" => --
+ mnemonic_o <= MN_JBB;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic JC ----------------------------------------------------------
+ when "11110110" | -- JC addr
+ "11100110" => -- JNC addr
+ mnemonic_o <= MN_JC;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic JF ----------------------------------------------------------
+ when "10110110" | -- JF0 addr
+ "01110110" => -- JF1 addr
+ mnemonic_o <= MN_JF;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic JMP ---------------------------------------------------------
+ when "00000100" | "00100100" | "01000100" | "01100100" | -- JMP addr
+ "10000100" | "10100100" | "11000100" | "11100100" => --
+ mnemonic_o <= MN_JMP;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic JMPP --------------------------------------------------------
+ when "10110011" => -- JMPP @ A
+ mnemonic_o <= MN_JMPP;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic JNI ---------------------------------------------------------
+ when "10000110" => -- JNI addr
+ mnemonic_o <= MN_JNI;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic JT ----------------------------------------------------------
+ when "00100110" | -- JNT0 addr
+ "01000110" | -- JNT1 addr
+ "00110110" | -- JT0 addr
+ "01010110" => -- JT1 addr
+ mnemonic_o <= MN_JT;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic JTF ---------------------------------------------------------
+ when "00010110" => -- JTF addr
+ mnemonic_o <= MN_JTF;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic JZ ----------------------------------------------------------
+ when "10010110" | -- JNZ addr
+ "11000110" => -- JZ addr
+ mnemonic_o <= MN_JZ;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic MOV_A_DATA --------------------------------------------------
+ when "00100011" => -- MOV A, data
+ mnemonic_o <= MN_MOV_A_DATA;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic MOV_A_PSW ---------------------------------------------------
+ when "11000111" => -- MOV A, PSW
+ mnemonic_o <= MN_MOV_A_PSW;
+
+ -- Mnemonic MOV_A_RR ----------------------------------------------------
+ when "11111000" | "11111001" | "11111010" | "11111011" | -- MOV A, Rr
+ "11111100" | "11111101" | "11111110" | "11111111" | --
+ "11110000" | "11110001" => -- MOV A, @ Rr
+ mnemonic_o <= MN_MOV_A_RR;
+
+ -- Mnemonic MOV_PSW_A ---------------------------------------------------
+ when "11010111" => -- MOV PSW, A
+ mnemonic_o <= MN_MOV_PSW_A;
+
+ -- Mnemonic MOV_RR ------------------------------------------------------
+ when "10101000" | "10101001" | "10101010" | "10101011" | -- MOV Rr, A
+ "10101100" | "10101101" | "10101110" | "10101111" | --
+ "10100000" | "10100001" => -- MOV @ Rr, A
+ mnemonic_o <= MN_MOV_RR;
+
+ -- Mnemonic MOV_RR_DATA -------------------------------------------------
+ when "10111000" | "10111001" | "10111010" | "10111011" | -- MOV Rr, data
+ "10111100" | "10111101" | "10111110" | "10111111" | --
+ "10110000" | "10110001" => -- MOV @ Rr, data
+ mnemonic_o <= MN_MOV_RR_DATA;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic MOV_T -------------------------------------------------------
+ when "01100010" | -- MOV T, A
+ "01000010" => -- MOV A, T
+ mnemonic_o <= MN_MOV_T;
+
+ -- Mnemonic MOVD_A_PP ---------------------------------------------------
+ when "00001100" | "00001101" | "00001110" | "00001111" => -- MOVD A, Pp
+ mnemonic_o <= MN_MOVD_A_PP;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic MOVP --------------------------------------------------------
+ when "10100011" | -- MOVP A, @ A
+ "11100011" => -- MOVP3 A, @ A
+ mnemonic_o <= MN_MOVP;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic MOVX --------------------------------------------------------
+ when "10000000" | "10000001" | -- MOVX A, @ Rr
+ "10010000" | "10010001" => -- MOVX @ Rr, A
+ mnemonic_o <= MN_MOVX;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic NOP ---------------------------------------------------------
+ when "00000000" => -- NOP
+ mnemonic_o <= MN_NOP;
+
+ -- Mnemonic ORL ---------------------------------------------------------
+ when "01001000" | "01001001" | "01001010" | "01001011" | -- ORL A, Rr
+ "01001100" | "01001101" | "01001110" | "01001111" | --
+ "01000000" | "01000001" => -- ORL A, @ Rr
+ mnemonic_o <= MN_ORL;
+
+ -- Mnemonic ORL_A_DATA --------------------------------------------------
+ when "01000011" => -- ORL A, data
+ mnemonic_o <= MN_ORL_A_DATA;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic ORL_EXT -----------------------------------------------------
+ when "10001000" | -- ORL BUS, data
+ "10001001" | "10001010" => -- ORL Pp, data
+ mnemonic_o <= MN_ORL_EXT;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic OUTD_PP_A ---------------------------------------------------
+ when "00111100" | "00111101" | "00111110" | "00111111" | -- MOVD Pp, A
+ "10011100" | "10011101" | "10011110" | "10011111" | -- ANLD PP, A
+ "10001100" | "10001101" | "10001110" | "10001111" => -- ORLD Pp, A
+ mnemonic_o <= MN_OUTD_PP_A;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic OUTL_EXT ----------------------------------------------------
+ when "00111001" | "00111010" | -- OUTL Pp, A
+ "00000010" => -- OUTL BUS, A
+ mnemonic_o <= MN_OUTL_EXT;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic RET ---------------------------------------------------------
+ when "10000011" | -- RET
+ "10010011" => -- RETR
+ mnemonic_o <= MN_RET;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic RL ----------------------------------------------------------
+ when "11100111" | -- RL A
+ "11110111" => -- RLC A
+ mnemonic_o <= MN_RL;
+
+ -- Mnemonic RR ----------------------------------------------------------
+ when "01110111" | -- RR A
+ "01100111" => -- RRC A
+ mnemonic_o <= MN_RR;
+
+ -- Mnemonic SEL_MB ------------------------------------------------------
+ when "11100101" | -- SEL MB0
+ "11110101" => -- SEL MB1
+ mnemonic_o <= MN_SEL_MB;
+
+ -- Mnemonic SEL_RB ------------------------------------------------------
+ when "11000101" | -- SEL RB0
+ "11010101" => -- SEL RB1
+ mnemonic_o <= MN_SEL_RB;
+
+ -- Mnemonic STOP_TCNT ---------------------------------------------------
+ when "01100101" => -- STOP TCNT
+ mnemonic_o <= MN_STOP_TCNT;
+
+ -- Mnemonic START -------------------------------------------------------
+ when "01000101" | -- STRT CNT
+ "01010101" => -- STRT T
+ mnemonic_o <= MN_STRT;
+
+ -- Mnemonic SWAP --------------------------------------------------------
+ when "01000111" => -- SWAP A
+ mnemonic_o <= MN_SWAP;
+
+ -- Mnemonic XCH ---------------------------------------------------------
+ when "00101000" | "00101001" | "00101010" | "00101011" | -- XCH A, Rr
+ "00101100" | "00101101" | "00101110" | "00101111" | --
+ "00100000" | "00100001" | -- XCH A, @ Rr
+ "00110000" | "00110001" => -- XCHD A, @ Rr
+ mnemonic_o <= MN_XCH;
+
+ -- Mnemonic XRL ---------------------------------------------------------
+ when "11011000" | "11011001" | "11011010" | "11011011" | -- XRL A, Rr
+ "11011100" | "11011101" | "11011110" | "11011111" | --
+ "11010000" | "11010001" => -- XRL A, @ Rr
+ mnemonic_o <= MN_XRL;
+
+ -- Mnemonic XRL_A_DATA --------------------------------------------------
+ when "11010011" => -- XRL A, data
+ mnemonic_o <= MN_XRL_A_DATA;
+ multi_cycle_o <= '1';
+
+ when others =>
+ -- pragma translate_off
+ assert now = 0 ns
+ report "Unknown opcode."
+ severity warning;
+ -- pragma translate_on
+
+ end case;
+
+ end process opc_decode;
+ --
+ -----------------------------------------------------------------------------
+
+end rtl;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: opc_table.vhd,v $
+-- Revision 1.4 2005/06/11 10:08:43 arniml
+-- introduce prefix 't48_' for all packages, entities and configurations
+--
+-- Revision 1.3 2004/07/11 16:51:33 arniml
+-- cleanup copyright notice
+--
+-- Revision 1.2 2004/03/28 13:10:48 arniml
+-- merge MN_ANLD, MN_MOVD_PP_A and MN_ORLD_PP_A to OUTLD_PP_A
+--
+-- Revision 1.1 2004/03/23 21:31:52 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/CPU/t48/rtl/vhdl/p1-c.vhd b/common/CPU/t48/rtl/vhdl/p1-c.vhd
new file mode 100644
index 00000000..246a296b
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/p1-c.vhd
@@ -0,0 +1,17 @@
+-------------------------------------------------------------------------------
+--
+-- The Port 1 unit.
+-- Implements the Port 1 logic.
+--
+-- $Id: p1-c.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+configuration t48_p1_rtl_c0 of t48_p1 is
+
+ for rtl
+ end for;
+
+end t48_p1_rtl_c0;
diff --git a/common/CPU/t48/rtl/vhdl/p1.vhd b/common/CPU/t48/rtl/vhdl/p1.vhd
new file mode 100644
index 00000000..694846a9
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/p1.vhd
@@ -0,0 +1,173 @@
+-------------------------------------------------------------------------------
+--
+-- The Port 1 unit.
+-- Implements the Port 1 logic.
+--
+-- $Id: p1.vhd,v 1.5 2005/06/11 10:08:43 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.word_t;
+
+entity t48_p1 is
+
+ port (
+ -- Global Interface -------------------------------------------------------
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ -- T48 Bus Interface ------------------------------------------------------
+ data_i : in word_t;
+ data_o : out word_t;
+ write_p1_i : in boolean;
+ read_p1_i : in boolean;
+ read_reg_i : in boolean;
+ -- Port 1 Interface -------------------------------------------------------
+ p1_i : in word_t;
+ p1_o : out word_t;
+ p1_low_imp_o : out std_logic
+ );
+
+end t48_p1;
+
+
+use work.t48_pack.clk_active_c;
+use work.t48_pack.res_active_c;
+use work.t48_pack.bus_idle_level_c;
+
+architecture rtl of t48_p1 is
+
+ -- the port output register
+ signal p1_q : word_t;
+
+ -- the low impedance marker
+ signal low_imp_q : std_logic;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process p1_reg
+ --
+ -- Purpose:
+ -- Implements the port output register.
+ --
+ p1_reg: process (res_i, clk_i)
+ begin
+ if res_i = res_active_c then
+ p1_q <= (others => '1');
+ low_imp_q <= '0';
+
+ elsif clk_i'event and clk_i = clk_active_c then
+ if en_clk_i then
+
+ if write_p1_i then
+ p1_q <= data_i;
+ low_imp_q <= '1';
+ else
+ low_imp_q <= '0';
+ end if;
+
+ end if;
+
+ end if;
+
+ end process p1_reg;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process p1_data
+ --
+ -- Purpose:
+ -- Generates the T48 bus data.
+ --
+ p1_data: process (read_p1_i,
+ p1_i,
+ read_reg_i,
+ p1_q)
+ begin
+ data_o <= (others => bus_idle_level_c);
+
+ if read_p1_i then
+ if read_reg_i then
+ data_o <= p1_q;
+ else
+ data_o <= p1_i;
+ end if;
+ end if;
+
+ end process p1_data;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Output Mapping.
+ -----------------------------------------------------------------------------
+ p1_o <= p1_q;
+ p1_low_imp_o <= low_imp_q;
+
+end rtl;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: p1.vhd,v $
+-- Revision 1.5 2005/06/11 10:08:43 arniml
+-- introduce prefix 't48_' for all packages, entities and configurations
+--
+-- Revision 1.4 2004/07/11 16:51:33 arniml
+-- cleanup copyright notice
+--
+-- Revision 1.3 2004/05/17 14:37:53 arniml
+-- reorder data_o generation
+--
+-- Revision 1.2 2004/03/29 19:39:58 arniml
+-- rename pX_limp to pX_low_imp
+--
+-- Revision 1.1 2004/03/23 21:31:52 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/CPU/t48/rtl/vhdl/p2-c.vhd b/common/CPU/t48/rtl/vhdl/p2-c.vhd
new file mode 100644
index 00000000..dff1c4cf
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/p2-c.vhd
@@ -0,0 +1,17 @@
+-------------------------------------------------------------------------------
+--
+-- The Port 2 unit.
+-- Implements the Port 2 logic.
+--
+-- $Id: p2-c.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+configuration t48_p2_rtl_c0 of t48_p2 is
+
+ for rtl
+ end for;
+
+end t48_p2_rtl_c0;
diff --git a/common/CPU/t48/rtl/vhdl/p2.vhd b/common/CPU/t48/rtl/vhdl/p2.vhd
new file mode 100644
index 00000000..fed0e344
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/p2.vhd
@@ -0,0 +1,275 @@
+-------------------------------------------------------------------------------
+--
+-- The Port 2 unit.
+-- Implements the Port 2 logic.
+--
+-- $Id: p2.vhd,v 1.9 2006/06/20 00:46:04 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.word_t;
+use work.t48_pack.nibble_t;
+
+entity t48_p2 is
+
+ port (
+ -- Global Interface -------------------------------------------------------
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ xtal_i : in std_logic;
+ xtal_en_i : in boolean;
+ -- T48 Bus Interface ------------------------------------------------------
+ data_i : in word_t;
+ data_o : out word_t;
+ write_p2_i : in boolean;
+ write_exp_i : in boolean;
+ read_p2_i : in boolean;
+ read_reg_i : in boolean;
+ read_exp_i : in boolean;
+ -- Port 2 Interface -------------------------------------------------------
+ output_pch_i : in boolean;
+ pch_i : in nibble_t;
+ p2_i : in word_t;
+ p2_o : out word_t;
+ p2l_low_imp_o : out std_logic;
+ p2h_low_imp_o : out std_logic
+ );
+
+end t48_p2;
+
+
+use work.t48_pack.clk_active_c;
+use work.t48_pack.res_active_c;
+use work.t48_pack.bus_idle_level_c;
+
+architecture rtl of t48_p2 is
+
+ -- the port output register
+ signal p2_q : word_t;
+
+ -- the low impedance markers
+ signal l_low_imp_q,
+ h_low_imp_q : std_logic;
+
+ signal en_clk_q : boolean;
+ signal l_low_imp_del_q,
+ h_low_imp_del_q : std_logic;
+ signal output_pch_q : boolean;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process p2_regs
+ --
+ -- Purpose:
+ -- Implements the port output and expander registers.
+ --
+ p2_regs: process (res_i, clk_i)
+ begin
+ if res_i = res_active_c then
+ p2_q <= (others => '1');
+ l_low_imp_q <= '0';
+ h_low_imp_q <= '0';
+
+ elsif clk_i'event and clk_i = clk_active_c then
+ if en_clk_i then
+ -- default: reset low impedance marker
+ l_low_imp_q <= '0';
+ h_low_imp_q <= '0';
+
+ if write_p2_i then
+ -- write whole P2
+ p2_q <= data_i;
+ l_low_imp_q <= '1';
+ h_low_imp_q <= '1';
+
+ elsif write_exp_i then
+ -- write lower nibble of P2
+ p2_q(nibble_t'range) <= data_i(nibble_t'range);
+ l_low_imp_q <= '1';
+
+ end if;
+
+ end if;
+
+ end if;
+
+ end process p2_regs;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process p2_port
+ --
+ -- Purpose:
+ -- Generates the output byte vector for Port 2.
+ -- It is a synchronous process clocked with XTAL. This ensures that
+ -- P2 data and low impedance markers are free of glitches and stabilize
+ -- during the same clock/machine state.
+ -- On the other hand, P2 is delayed by 1 XTAL cycle.
+ --
+ p2_port: process (res_i, xtal_i)
+ begin
+ if res_i = res_active_c then
+ p2_o <= (others => '1');
+ l_low_imp_del_q <= '0';
+ h_low_imp_del_q <= '0';
+ output_pch_q <= false;
+ en_clk_q <= false;
+
+ elsif xtal_i'event and xtal_i = clk_active_c then
+ if xtal_en_i then
+ -- delay clock enable by one XTAL period
+ en_clk_q <= en_clk_i;
+
+ p2_o <= p2_q;
+ output_pch_q <= output_pch_i;
+
+ if output_pch_i then
+ p2_o(nibble_t'range) <= pch_i;
+ end if;
+
+ -- generate low impedance trigger for one XTAL clock period after
+ -- global clock enable when
+ -- a) switching to or from PCH
+ -- b) l_low_imp_q is active
+ if en_clk_q and
+ ((output_pch_q xor output_pch_i) or
+ l_low_imp_q = '1') then
+ l_low_imp_del_q <= '1';
+ else
+ l_low_imp_del_q <= '0';
+ end if;
+
+ -- generate low impedance trigger for on XTAL clock period after
+ -- global clock enable when
+ -- h_low_imp_q is active
+ if en_clk_q and
+ h_low_imp_q = '1' then
+ h_low_imp_del_q <= '1';
+ else
+ h_low_imp_del_q <= '0';
+ end if;
+
+ end if;
+ end if;
+ end process p2_port;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process p2_data
+ --
+ -- Purpose:
+ -- Generates the T48 bus data.
+ --
+ p2_data: process (read_p2_i,
+ p2_i,
+ read_reg_i,
+ p2_q,
+ read_exp_i)
+ begin
+ data_o <= (others => bus_idle_level_c);
+
+ if read_p2_i then
+ if read_reg_i then
+ data_o <= p2_q;
+ elsif read_exp_i then
+ data_o <= "0000" & p2_i(nibble_t'range);
+ else
+ data_o <= p2_i;
+ end if;
+ end if;
+
+ end process p2_data;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Output Mapping.
+ -----------------------------------------------------------------------------
+ p2l_low_imp_o <= l_low_imp_del_q;
+ p2h_low_imp_o <= h_low_imp_del_q;
+
+end rtl;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: p2.vhd,v $
+-- Revision 1.9 2006/06/20 00:46:04 arniml
+-- new input xtal_en_i
+--
+-- Revision 1.8 2005/11/01 21:27:55 arniml
+-- * change low impedance markers for P2
+-- separate marker for low and high part
+-- * p2_o output is also registered to prevent combinational
+-- output to pads
+--
+-- Revision 1.7 2005/06/11 10:08:43 arniml
+-- introduce prefix 't48_' for all packages, entities and configurations
+--
+-- Revision 1.6 2004/07/11 16:51:33 arniml
+-- cleanup copyright notice
+--
+-- Revision 1.5 2004/05/17 13:52:46 arniml
+-- Fix bug "ANL and ORL to P1/P2 read port status instead of port output register"
+--
+-- Revision 1.4 2004/04/24 23:44:25 arniml
+-- move from std_logic_arith to numeric_std
+--
+-- Revision 1.3 2004/03/29 19:39:58 arniml
+-- rename pX_limp to pX_low_imp
+--
+-- Revision 1.2 2004/03/28 13:11:43 arniml
+-- rework Port 2 expander handling
+--
+-- Revision 1.1 2004/03/23 21:31:53 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/CPU/t48/rtl/vhdl/pmem_ctrl-c.vhd b/common/CPU/t48/rtl/vhdl/pmem_ctrl-c.vhd
new file mode 100644
index 00000000..8cadaaaf
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/pmem_ctrl-c.vhd
@@ -0,0 +1,17 @@
+-------------------------------------------------------------------------------
+--
+-- The Program Memory control unit.
+-- All operations related to the Program Memory are managed here.
+--
+-- $Id: pmem_ctrl-c.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+configuration t48_pmem_ctrl_rtl_c0 of t48_pmem_ctrl is
+
+ for rtl
+ end for;
+
+end t48_pmem_ctrl_rtl_c0;
diff --git a/common/CPU/t48/rtl/vhdl/pmem_ctrl.vhd b/common/CPU/t48/rtl/vhdl/pmem_ctrl.vhd
new file mode 100644
index 00000000..51c801fa
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/pmem_ctrl.vhd
@@ -0,0 +1,245 @@
+-------------------------------------------------------------------------------
+--
+-- The Program Memory control unit.
+-- All operations related to the Program Memory are managed here.
+--
+-- $Id: pmem_ctrl.vhd,v 1.5 2005/06/11 10:08:43 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.pmem_addr_t;
+use work.t48_pack.word_t;
+use work.t48_pmem_ctrl_pack.pmem_addr_ident_t;
+
+entity t48_pmem_ctrl is
+
+ port (
+ -- Global Interface -------------------------------------------------------
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ -- T48 Bus Interface ------------------------------------------------------
+ data_i : in word_t;
+ data_o : out word_t;
+ write_pcl_i : in boolean;
+ read_pcl_i : in boolean;
+ write_pch_i : in boolean;
+ read_pch_i : in boolean;
+ inc_pc_i : in boolean;
+ write_pmem_addr_i : in boolean;
+ addr_type_i : in pmem_addr_ident_t;
+ read_pmem_i : in boolean;
+ -- Porgram Memroy Interface -----------------------------------------------
+ pmem_addr_o : out pmem_addr_t;
+ pmem_data_i : in word_t
+ );
+
+end t48_pmem_ctrl;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+use work.t48_pmem_ctrl_pack.all;
+use work.t48_pack.res_active_c;
+use work.t48_pack.clk_active_c;
+use work.t48_pack.bus_idle_level_c;
+use work.t48_pack.pmem_addr_width_c;
+use work.t48_pack.dmem_addr_width_c;
+use work.t48_pack.page_t;
+
+architecture rtl of t48_pmem_ctrl is
+
+ -- implemented counter width of Program Counter
+ -- the upper bit is only altered by JMP, CALL and RET(R)
+ subtype pc_count_range_t is natural range pmem_addr_width_c-2 downto 0;
+
+ -- the Program Counter
+ signal program_counter_q : unsigned(pmem_addr_t'range);
+
+
+ -- the Program Memory address
+ signal pmem_addr_s,
+ pmem_addr_q : std_logic_vector(pmem_addr_t'range);
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process program_counter
+ --
+ -- Purpose:
+ -- Implements the Program Counter.
+ --
+ program_counter: process (res_i, clk_i)
+ begin
+ if res_i = res_active_c then
+ program_counter_q <= (others => '0');
+ pmem_addr_q <= (others => '0');
+
+ elsif clk_i'event and clk_i = clk_active_c then
+ if en_clk_i then
+
+ -- parallel load mode
+ if write_pcl_i then
+ program_counter_q(data_i'range) <= UNSIGNED(data_i);
+ elsif write_pch_i then
+ program_counter_q(pmem_addr_width_c-1 downto data_i'high+1) <=
+ UNSIGNED(data_i(pmem_addr_width_c - dmem_addr_width_c - 1 downto 0));
+ elsif inc_pc_i then
+ -- increment mode
+ -- the MSB is not modified by linear increments
+ -- it can only be altered by JMP, CALL or RET(R)
+ program_counter_q(pc_count_range_t) <=
+ program_counter_q(pc_count_range_t) + 1;
+ end if;
+
+ -- set pmem address
+ if write_pmem_addr_i then
+ pmem_addr_q <= pmem_addr_s;
+ end if;
+
+ end if;
+
+ end if;
+
+ end process program_counter;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process pmem_addr
+ --
+ -- Purpose:
+ -- Multiplex the Program Memory address.
+ --
+ pmem_addr: process (program_counter_q,
+ addr_type_i,
+ pmem_addr_q,
+ data_i)
+ begin
+ -- default assignment
+ pmem_addr_s <= STD_LOGIC_VECTOR(program_counter_q);
+
+ case addr_type_i is
+ when PM_PC =>
+ -- default is ok
+ null;
+
+ when PM_PAGE =>
+ pmem_addr_s(word_t'range) <= data_i;
+ -- take page address from program counter
+ -- => important for JMPP, MOVP!
+ -- they must wrap to next page when at FF!
+
+ when PM_PAGE3 =>
+ pmem_addr_s(word_t'range) <= data_i;
+ -- page address is explicitely specified
+ pmem_addr_s(page_t'range) <= "0011";
+
+ when others =>
+ null;
+
+ end case;
+
+ end process pmem_addr;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process data_output
+ --
+ -- Purpose:
+ -- Multiplex the data bus output.
+ --
+ data_output: process (read_pmem_i,
+ read_pcl_i,
+ read_pch_i,
+ pmem_data_i,
+ program_counter_q)
+ begin
+ data_o <= (others => bus_idle_level_c);
+
+ if read_pmem_i then
+ data_o <= pmem_data_i;
+ elsif read_pcl_i then
+ data_o <= STD_LOGIC_VECTOR(program_counter_q(data_o'range));
+ elsif read_pch_i then
+ data_o(3 downto 0) <= STD_LOGIC_VECTOR(program_counter_q(pmem_addr_width_c-1 downto data_o'high+1));
+ end if;
+
+ end process data_output;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Output Mapping.
+ -----------------------------------------------------------------------------
+ pmem_addr_o <= pmem_addr_q;
+
+end rtl;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: pmem_ctrl.vhd,v $
+-- Revision 1.5 2005/06/11 10:08:43 arniml
+-- introduce prefix 't48_' for all packages, entities and configurations
+--
+-- Revision 1.4 2005/06/08 19:13:53 arniml
+-- fix bug report
+-- "MSB of Program Counter changed upon PC increment"
+--
+-- Revision 1.3 2004/07/11 16:51:33 arniml
+-- cleanup copyright notice
+--
+-- Revision 1.2 2004/04/24 23:44:25 arniml
+-- move from std_logic_arith to numeric_std
+--
+-- Revision 1.1 2004/03/23 21:31:53 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/CPU/t48/rtl/vhdl/pmem_ctrl_pack-p.vhd b/common/CPU/t48/rtl/vhdl/pmem_ctrl_pack-p.vhd
new file mode 100644
index 00000000..c1d45d69
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/pmem_ctrl_pack-p.vhd
@@ -0,0 +1,33 @@
+-------------------------------------------------------------------------------
+--
+-- $Id: pmem_ctrl_pack-p.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+package t48_pmem_ctrl_pack is
+
+ -----------------------------------------------------------------------------
+ -- Address Type Identifier
+ -----------------------------------------------------------------------------
+ type pmem_addr_ident_t is (PM_PC,
+ PM_PAGE,
+ PM_PAGE3);
+
+end t48_pmem_ctrl_pack;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: pmem_ctrl_pack-p.vhd,v $
+-- Revision 1.2 2005/06/11 10:08:43 arniml
+-- introduce prefix 't48_' for all packages, entities and configurations
+--
+-- Revision 1.1 2004/03/23 21:31:53 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/CPU/t48/rtl/vhdl/psw-c.vhd b/common/CPU/t48/rtl/vhdl/psw-c.vhd
new file mode 100644
index 00000000..049e8f5a
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/psw-c.vhd
@@ -0,0 +1,17 @@
+-------------------------------------------------------------------------------
+--
+-- The Program Status Word (PSW).
+-- Implements the PSW with its special bits.
+--
+-- $Id: psw-c.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+configuration t48_psw_rtl_c0 of t48_psw is
+
+ for rtl
+ end for;
+
+end t48_psw_rtl_c0;
diff --git a/common/CPU/t48/rtl/vhdl/psw.vhd b/common/CPU/t48/rtl/vhdl/psw.vhd
new file mode 100644
index 00000000..87664f82
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/psw.vhd
@@ -0,0 +1,243 @@
+-------------------------------------------------------------------------------
+--
+-- The Program Status Word (PSW).
+-- Implements the PSW with its special bits.
+--
+-- $Id: psw.vhd,v 1.8 2005/06/11 10:08:43 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.word_t;
+
+entity t48_psw is
+
+ port (
+ -- Global Interface -------------------------------------------------------
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ -- T48 Bus Interface ------------------------------------------------------
+ data_i : in word_t;
+ data_o : out word_t;
+ read_psw_i : in boolean;
+ read_sp_i : in boolean;
+ write_psw_i : in boolean;
+ write_sp_i : in boolean;
+ -- Decoder Interface ------------------------------------------------------
+ special_data_i : in std_logic;
+ inc_stackp_i : in boolean;
+ dec_stackp_i : in boolean;
+ write_carry_i : in boolean;
+ write_aux_carry_i : in boolean;
+ write_f0_i : in boolean;
+ write_bs_i : in boolean;
+ carry_o : out std_logic;
+ aux_carry_i : in std_logic;
+ aux_carry_o : out std_logic;
+ f0_o : out std_logic;
+ bs_o : out std_logic
+ );
+
+end t48_psw;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+use work.t48_pack.clk_active_c;
+use work.t48_pack.res_active_c;
+use work.t48_pack.bus_idle_level_c;
+use work.t48_pack.nibble_t;
+
+architecture rtl of t48_psw is
+
+ -- special bit positions in PSW
+ constant carry_c : natural := 3;
+ constant aux_carry_c : natural := 2;
+ constant f0_c : natural := 1;
+ constant bs_c : natural := 0;
+
+ -- the PSW register
+ signal psw_q : nibble_t;
+ -- the Stack Pointer
+ signal sp_q : unsigned(2 downto 0);
+
+ -- pragma translate_off
+ signal psw_s : word_t;
+ -- pragma translate_on
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process psw_reg
+ --
+ -- Purpose:
+ -- Implements the PSW register.
+ --
+ psw_reg: process (res_i, clk_i)
+ begin
+ if res_i = res_active_c then
+ psw_q <= (others => '0');
+ sp_q <= (others => '0');
+
+ elsif clk_i'event and clk_i = clk_active_c then
+ if en_clk_i then
+
+ -- T48 bus access
+ if write_psw_i then
+ psw_q <= data_i(7 downto 4);
+ end if;
+ if write_sp_i then
+ sp_q <= unsigned(data_i(2 downto 0));
+ end if;
+
+ -- increment Stack Pointer
+ if inc_stackp_i then
+ sp_q <= sp_q + 1;
+ end if;
+ -- decrement Stack Pointer
+ if dec_stackp_i then
+ sp_q <= sp_q - 1;
+ end if;
+
+ -- access to special bits
+ if write_carry_i then
+ psw_q(carry_c) <= special_data_i;
+ end if;
+ --
+ if write_aux_carry_i then
+ psw_q(aux_carry_c) <= aux_carry_i;
+ end if;
+ --
+ if write_f0_i then
+ psw_q(f0_c) <= special_data_i;
+ end if;
+ --
+ if write_bs_i then
+ psw_q(bs_c) <= special_data_i;
+ end if;
+
+ end if;
+
+ end if;
+
+ end process psw_reg;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process data_out
+ --
+ -- Purpose:
+ -- Output multiplexer for T48 Data Bus.
+ --
+ data_out: process (read_psw_i,
+ read_sp_i,
+ psw_q,
+ sp_q)
+ begin
+ data_o <= (others => bus_idle_level_c);
+
+ if read_psw_i then
+ data_o(7 downto 4) <= psw_q;
+ end if;
+
+ if read_sp_i then
+ data_o(3 downto 0) <= '1' & std_logic_vector(sp_q);
+ end if;
+
+ end process data_out;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -- pragma translate_off
+ tb: process (psw_q, sp_q)
+ begin
+ psw_s(7 downto 4) <= psw_q;
+ psw_s(3) <= '1';
+ psw_s(2 downto 0) <= std_logic_vector(sp_q);
+ end process tb;
+ -- pragma translate_on
+
+ -----------------------------------------------------------------------------
+ -- Output mapping.
+ -----------------------------------------------------------------------------
+ carry_o <= psw_q(carry_c);
+ aux_carry_o <= psw_q(aux_carry_c);
+ f0_o <= psw_q(f0_c);
+ bs_o <= psw_q(bs_c);
+
+end rtl;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: psw.vhd,v $
+-- Revision 1.8 2005/06/11 10:08:43 arniml
+-- introduce prefix 't48_' for all packages, entities and configurations
+--
+-- Revision 1.7 2004/07/11 16:51:33 arniml
+-- cleanup copyright notice
+--
+-- Revision 1.6 2004/04/24 23:44:25 arniml
+-- move from std_logic_arith to numeric_std
+--
+-- Revision 1.5 2004/04/24 11:25:39 arniml
+-- removed dummy_s - workaround not longer needed for GHDL 0.11.1
+--
+-- Revision 1.4 2004/04/18 18:59:01 arniml
+-- add temporary workaround for GHDL 0.11
+--
+-- Revision 1.3 2004/04/04 14:15:45 arniml
+-- add dump_compare support
+--
+-- Revision 1.2 2004/03/28 21:28:13 arniml
+-- take auxiliary carry from direct ALU connection
+--
+-- Revision 1.1 2004/03/23 21:31:53 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/CPU/t48/rtl/vhdl/system/generic_ram_ena-c.vhd b/common/CPU/t48/rtl/vhdl/system/generic_ram_ena-c.vhd
new file mode 100644
index 00000000..29506088
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/system/generic_ram_ena-c.vhd
@@ -0,0 +1,18 @@
+-------------------------------------------------------------------------------
+--
+-- Parametrizable, generic RAM with enable.
+--
+-- $Id: generic_ram_ena-c.vhd,v 1.1.1.1 2006/11/25 22:15:41 arnim Exp $
+--
+-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+configuration generic_ram_ena_rtl_c0 of generic_ram_ena is
+
+ for rtl
+ end for;
+
+end generic_ram_ena_rtl_c0;
diff --git a/common/CPU/t48/rtl/vhdl/system/generic_ram_ena.vhd b/common/CPU/t48/rtl/vhdl/system/generic_ram_ena.vhd
new file mode 100644
index 00000000..299e2b43
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/system/generic_ram_ena.vhd
@@ -0,0 +1,100 @@
+-------------------------------------------------------------------------------
+--
+-- Parametrizable, generic RAM with enable.
+--
+-- $Id: generic_ram_ena.vhd,v 1.1.1.1 2006/11/25 22:15:41 arnim Exp $
+--
+-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity generic_ram_ena is
+
+ generic (
+ addr_width_g : integer := 10;
+ data_width_g : integer := 8
+ );
+ port (
+ clk_i : in std_logic;
+ a_i : in std_logic_vector(addr_width_g-1 downto 0);
+ we_i : in std_logic;
+ ena_i : in std_logic;
+ d_i : in std_logic_vector(data_width_g-1 downto 0);
+ d_o : out std_logic_vector(data_width_g-1 downto 0)
+ );
+
+end generic_ram_ena;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+architecture rtl of generic_ram_ena is
+
+ type mem_t is array (natural range 0 to 2**addr_width_g-1) of
+ std_logic_vector(d_i'range);
+ signal mem_q : mem_t
+ -- pragma translate_off
+ := (others => (others => '0'))
+ -- pragma translate_on
+ ;
+ signal a_q : std_logic_vector(a_i'range);
+
+begin
+
+ mem: process (clk_i)
+ begin
+
+ if clk_i'event and clk_i = '1' then
+ if ena_i = '1' then
+ if we_i = '1' then
+ mem_q(to_integer(unsigned(a_i))) <= d_i;
+ end if;
+
+ a_q <= a_i;
+ end if;
+
+ end if;
+ end process mem;
+
+ d_o <= mem_q(to_integer(unsigned(a_q)));
+
+end rtl;
diff --git a/common/CPU/t48/rtl/vhdl/system/lpm_ram_dq.vhd b/common/CPU/t48/rtl/vhdl/system/lpm_ram_dq.vhd
new file mode 100644
index 00000000..8b2a30b4
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/system/lpm_ram_dq.vhd
@@ -0,0 +1,439 @@
+--------------------------------------------------------------------------
+-- This VHDL file was developed by Altera Corporation. It may be
+-- freely copied and/or distributed at no cost. Any persons using this
+-- file for any purpose do so at their own risk, and are responsible for
+-- the results of such use. Altera Corporation does not guarantee that
+-- this file is complete, correct, or fit for any particular purpose.
+-- NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED. This notice must
+-- accompany any copy of this file.
+--
+--------------------------------------------------------------------------
+-- LPM Synthesizable Models (Support string type generic)
+--------------------------------------------------------------------------
+-- Version 2.0 (lpm 220) Date 01/04/00
+--
+-- 1. Fixed LPM_RAM_DQ, LPM_RAM_DP, LPM_RAM_IO and LPM_ROM to correctly
+-- read in values from LPM_FILE (*.hex) when the DATA width is greater
+-- than 16 bits.
+-- 2. Explicit sign conversions are added to standard logic vector
+-- comparisons in LPM_RAM_DQ, LPM_RAM_DP, LPM_RAM_IO, LPM_ROM, and
+-- LPM_COMPARE.
+-- 3. LPM_FIFO_DC is rewritten to have correct outputs.
+-- 4. LPM_FIFO outputs zeros when nothing has been read from it, and
+-- outputs LPM_NUMWORDS mod exp(2, LPM_WIDTHU) when it is full.
+-- 5. Fixed LPM_DIVIDE to divide correctly.
+--------------------------------------------------------------------------
+-- Version 1.9 (lpm 220) Date 11/30/99
+--
+-- 1. Fixed UNUSED file not found problem and initialization problem
+-- with LPM_RAM_DP, LPM_RAM_DQ, and LPM_RAM_IO.
+-- 2. Fixed LPM_MULT when SUM port is not used.
+-- 3. Fixed LPM_FIFO_DC to enable read when rdclock and wrclock rise
+-- at the same time.
+-- 4. Fixed LPM_COUNTER comparison problem when signed library is loaded
+-- and counter is incrementing.
+-- 5. Got rid of "Illegal Character" error message at time = 0 ns when
+-- simulating LPM_COUNTER.
+--------------------------------------------------------------------------
+-- Version 1.8 (lpm 220) Date 10/25/99
+--
+-- 1. Some LPM_PVALUE implementations were missing, and now implemented.
+-- 2. Fixed LPM_COUNTER to count correctly without conversion overflow,
+-- that is, when LPM_MODULUS = 2 ** LPM_WIDTH.
+-- 3. Fixed LPM_RAM_DP sync process sensitivity list to detect wraddress
+-- changes.
+--------------------------------------------------------------------------
+-- Version 1.7 (lpm 220) Date 07/13/99
+--
+-- Changed LPM_RAM_IO so that it can be used to simulate both MP2 and
+-- Quartus behaviour and LPM220-compliant behaviour.
+--------------------------------------------------------------------------
+-- Version 1.6 (lpm 220) Date 06/15/99
+--
+-- 1. Fixed LPM_ADD_SUB sign extension problem and subtraction bug.
+-- 2. Fixed LPM_COUNTER to use LPM_MODULUS value.
+-- 3. Added CIN and COUT port, and discarded EQ port in LPM_COUNTER to
+-- comply with the specfication.
+-- 4. Included LPM_RAM_DP, LPM_RAM_DQ, LPM_RAM_IO, LPM_ROM, LPM_FIFO, and
+-- LPM_FIFO_DC; they are all initialized to 0's.
+--------------------------------------------------------------------------
+-- Version 1.5 (lpm 220) Date 05/10/99
+--
+-- Changed LPM_MODULUS from string type to integer.
+--------------------------------------------------------------------------
+-- Version 1.4 (lpm 220) Date 02/05/99
+--
+-- 1. Added LPM_DIVIDE module.
+-- 2. Added CLKEN port to LPM_MUX, LPM_DECODE, LPM_ADD_SUB, LPM_MULT
+-- and LPM_COMPARE
+-- 3. Replaced the constants holding string with the actual string.
+--------------------------------------------------------------------------
+-- Version 1.3 Date 07/30/96
+--
+-- Modification History
+--
+-- 1. Changed the DEFAULT value to "UNUSED" for LPM_SVALUE, LPM_AVALUE,
+-- LPM_MODULUS, and LPM_NUMWORDS, LPM_HINT,LPM_STRENGTH, LPM_DIRECTION,
+-- and LPM_PVALUE
+--
+-- 2. Added the two dimentional port components (AND, OR, XOR, and MUX).
+--------------------------------------------------------------------------
+-- Excluded Functions:
+--
+-- LPM_FSM and LPM_TTABLE
+--
+--------------------------------------------------------------------------
+-- Assumptions:
+--
+-- 1. All ports and signal types are std_logic or std_logic_vector
+-- from IEEE 1164 package.
+-- 2. Synopsys std_logic_arith, std_logic_unsigned, and std_logic_signed
+-- package are assumed to be accessible from IEEE library.
+-- 3. lpm_component_package must be accessible from library work.
+-- 4. The default value of LPM_SVALUE, LPM_AVALUE, LPM_MODULUS, LPM_HINT,
+-- LPM_NUMWORDS, LPM_STRENGTH, LPM_DIRECTION, and LPM_PVALUE is
+-- string "UNUSED".
+--------------------------------------------------------------------------
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+--use IEEE.std_logic_unsigned.all;
+use std.textio.all;
+
+entity LPM_RAM_DQ is
+ generic (LPM_WIDTH : positive;
+ LPM_WIDTHAD : positive;
+ LPM_NUMWORDS : natural := 0;
+ LPM_INDATA : string := "REGISTERED";
+ LPM_ADDRESS_CONTROL: string := "REGISTERED";
+ LPM_OUTDATA : string := "REGISTERED";
+ LPM_FILE : string := "UNUSED";
+ LPM_TYPE : string := "LPM_RAM_DQ";
+ LPM_HINT : string := "UNUSED");
+ port (DATA : in std_logic_vector(LPM_WIDTH-1 downto 0);
+ ADDRESS : in std_logic_vector(LPM_WIDTHAD-1 downto 0);
+ INCLOCK : in std_logic := '0';
+ OUTCLOCK : in std_logic := '0';
+ WE : in std_logic;
+ Q : out std_logic_vector(LPM_WIDTH-1 downto 0));
+
+ function int_to_str( value : integer ) return string is
+ variable ivalue,index : integer;
+ variable digit : integer;
+ variable line_no: string(8 downto 1) := " ";
+ begin
+ ivalue := value;
+ index := 1;
+ while (ivalue > 0) loop
+ digit := ivalue MOD 10;
+ ivalue := ivalue/10;
+ case digit is
+ when 0 =>
+ line_no(index) := '0';
+ when 1 =>
+ line_no(index) := '1';
+ when 2 =>
+ line_no(index) := '2';
+ when 3 =>
+ line_no(index) := '3';
+ when 4 =>
+ line_no(index) := '4';
+ when 5 =>
+ line_no(index) := '5';
+ when 6 =>
+ line_no(index) := '6';
+ when 7 =>
+ line_no(index) := '7';
+ when 8 =>
+ line_no(index) := '8';
+ when 9 =>
+ line_no(index) := '9';
+ when others =>
+ ASSERT FALSE
+ REPORT "Illegal number!"
+ SEVERITY ERROR;
+ end case;
+ index := index + 1;
+ end loop;
+ return line_no;
+ end;
+
+ function hex_str_to_int( str : string ) return integer is
+ variable len : integer := str'length;
+ variable ivalue : integer := 0;
+ variable digit : integer;
+ begin
+ for i in len downto 1 loop
+ case str(i) is
+ when '0' =>
+ digit := 0;
+ when '1' =>
+ digit := 1;
+ when '2' =>
+ digit := 2;
+ when '3' =>
+ digit := 3;
+ when '4' =>
+ digit := 4;
+ when '5' =>
+ digit := 5;
+ when '6' =>
+ digit := 6;
+ when '7' =>
+ digit := 7;
+ when '8' =>
+ digit := 8;
+ when '9' =>
+ digit := 9;
+ when 'A' =>
+ digit := 10;
+ when 'a' =>
+ digit := 10;
+ when 'B' =>
+ digit := 11;
+ when 'b' =>
+ digit := 11;
+ when 'C' =>
+ digit := 12;
+ when 'c' =>
+ digit := 12;
+ when 'D' =>
+ digit := 13;
+ when 'd' =>
+ digit := 13;
+ when 'E' =>
+ digit := 14;
+ when 'e' =>
+ digit := 14;
+ when 'F' =>
+ digit := 15;
+ when 'f' =>
+ digit := 15;
+ when others =>
+ ASSERT FALSE
+ REPORT "Illegal character "& str(i) & "in Intel Hex File! "
+ SEVERITY ERROR;
+ end case;
+ ivalue := ivalue * 16 + digit;
+ end loop;
+ return ivalue;
+ end;
+
+ procedure Shrink_line(L : inout LINE; pos : in integer) is
+ subtype nstring is string(1 to pos);
+ variable stmp : nstring;
+ begin
+ if pos >= 1 then
+ read(l, stmp);
+ end if;
+ end;
+
+end LPM_RAM_DQ;
+
+architecture LPM_SYN of lpm_ram_dq is
+
+--type lpm_memory is array(lpm_numwords-1 downto 0) of std_logic_vector(lpm_width-1 downto 0);
+type lpm_memory is array(integer range (2**lpm_widthad)-1 downto 0) of std_logic_vector(lpm_width-1 downto 0);
+
+signal data_tmp, data_reg : std_logic_vector(lpm_width-1 downto 0);
+signal q_tmp, q_reg : std_logic_vector(lpm_width-1 downto 0) := (others => '0');
+signal address_tmp, address_reg : std_logic_vector(lpm_widthad-1 downto 0);
+signal we_tmp, we_reg : std_logic;
+
+begin
+
+ sync: process(data, data_reg, address, address_reg,
+ we, we_reg, q_tmp, q_reg)
+ begin
+ if (lpm_address_control = "REGISTERED") then
+ address_tmp <= address_reg;
+ we_tmp <= we_reg;
+ else
+ address_tmp <= address;
+ we_tmp <= we;
+ end if;
+ if (lpm_indata = "REGISTERED") then
+ data_tmp <= data_reg;
+ else
+ data_tmp <= data;
+ end if;
+ if (lpm_outdata = "REGISTERED") then
+ q <= q_reg;
+ else
+ q <= q_tmp;
+ end if;
+ end process;
+
+ input_reg: process (inclock)
+ begin
+ if inclock'event and inclock = '1' then
+ data_reg <= data;
+ address_reg <= address;
+ we_reg <= we;
+ end if;
+ end process;
+
+ output_reg: process (outclock)
+ begin
+ if outclock'event and outclock = '1' then
+ q_reg <= q_tmp;
+ end if;
+ end process;
+
+ memory: process(data_tmp, we_tmp, address_tmp)
+ variable mem_data : lpm_memory;
+ variable mem_data_tmp : integer := 0;
+ variable mem_init: boolean := false;
+ variable i,j,k,lineno: integer := 0;
+ variable buf: line ;
+ variable booval: boolean ;
+ FILE unused_file: TEXT IS OUT "UNUSED";
+ FILE mem_data_file: TEXT IS IN LPM_FILE;
+ variable base, byte, rec_type, datain, addr, checksum: string(2 downto 1);
+ variable startadd: string(4 downto 1);
+ variable ibase: integer := 0;
+ variable ibyte: integer := 0;
+ variable istartadd: integer := 0;
+ variable check_sum_vec, check_sum_vec_tmp: unsigned(7 downto 0);
+ begin
+ -- INITIALIZE --
+ if NOT(mem_init) then
+ -- INITIALIZE TO 0 --
+ for i in mem_data'LOW to mem_data'HIGH loop
+ mem_data(i) := (OTHERS => '0');
+ end loop;
+
+ if (LPM_FILE = "UNUSED") then
+ ASSERT FALSE
+ REPORT "Initialization file not found!"
+ SEVERITY WARNING;
+ else
+ WHILE NOT ENDFILE(mem_data_file) loop
+ booval := true;
+ READLINE(mem_data_file, buf);
+ lineno := lineno + 1;
+ check_sum_vec := (OTHERS => '0');
+ if (buf(buf'LOW) = ':') then
+ i := 1;
+ shrink_line(buf, i);
+ READ(L=>buf, VALUE=>byte, good=>booval);
+ if not (booval) then
+ ASSERT FALSE
+ REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format!"
+ SEVERITY ERROR;
+ end if;
+ ibyte := hex_str_to_int(byte);
+ check_sum_vec := unsigned(check_sum_vec) + to_unsigned(ibyte, check_sum_vec'length);
+ READ(L=>buf, VALUE=>startadd, good=>booval);
+ if not (booval) then
+ ASSERT FALSE
+ REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! "
+ SEVERITY ERROR;
+ end if;
+ istartadd := hex_str_to_int(startadd);
+ addr(2) := startadd(4);
+ addr(1) := startadd(3);
+ check_sum_vec := unsigned(check_sum_vec) + to_unsigned(hex_str_to_int(addr), check_sum_vec'length);
+ addr(2) := startadd(2);
+ addr(1) := startadd(1);
+ check_sum_vec := unsigned(check_sum_vec) + to_unsigned(hex_str_to_int(addr), check_sum_vec'length);
+ READ(L=>buf, VALUE=>rec_type, good=>booval);
+ if not (booval) then
+ ASSERT FALSE
+ REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! "
+ SEVERITY ERROR;
+ end if;
+ check_sum_vec := unsigned(check_sum_vec) + to_unsigned(hex_str_to_int(rec_type), check_sum_vec'length);
+ else
+ ASSERT FALSE
+ REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! "
+ SEVERITY ERROR;
+ end if;
+ case rec_type is
+ when "00"=> -- Data record
+ i := 0;
+ k := lpm_width / 8;
+ if ((lpm_width MOD 8) /= 0) then
+ k := k + 1;
+ end if;
+ -- k = no. of bytes per CAM entry.
+ while (i < ibyte) loop
+ mem_data_tmp := 0;
+ for j in 1 to k loop
+ READ(L=>buf, VALUE=>datain,good=>booval); -- read in data a byte (2 hex chars) at a time.
+ if not (booval) then
+ ASSERT FALSE
+ REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! "
+ SEVERITY ERROR;
+ end if;
+ check_sum_vec := unsigned(check_sum_vec) + to_unsigned(hex_str_to_int(datain), check_sum_vec'length);
+ mem_data_tmp := mem_data_tmp * 256 + hex_str_to_int(datain);
+ end loop;
+ i := i + k;
+ mem_data(ibase + istartadd) := STD_LOGIC_VECTOR(to_unsigned(mem_data_tmp, lpm_width));
+ istartadd := istartadd + 1;
+ end loop;
+ when "01"=>
+ exit;
+ when "02"=>
+ ibase := 0;
+ if (ibyte /= 2) then
+ ASSERT FALSE
+ REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format for record type 02! "
+ SEVERITY ERROR;
+ end if;
+ for i in 0 to (ibyte-1) loop
+ READ(L=>buf, VALUE=>base,good=>booval);
+ ibase := ibase * 256 + hex_str_to_int(base);
+ if not (booval) then
+ ASSERT FALSE
+ REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! "
+ SEVERITY ERROR;
+ end if;
+ check_sum_vec := unsigned(check_sum_vec) + to_unsigned(hex_str_to_int(base), check_sum_vec'length);
+ end loop;
+ ibase := ibase * 16;
+ when OTHERS =>
+ ASSERT FALSE
+ REPORT "[Line "& int_to_str(lineno) & "]:Illegal record type in Intel Hex File! "
+ SEVERITY ERROR;
+ end case;
+ READ(L=>buf, VALUE=>checksum,good=>booval);
+ if not (booval) then
+ ASSERT FALSE
+ REPORT "[Line "& int_to_str(lineno) & "]:Checksum is missing! "
+ SEVERITY ERROR;
+ end if;
+
+ check_sum_vec := unsigned(not (check_sum_vec)) + 1 ;
+ check_sum_vec_tmp := to_unsigned(hex_str_to_int(checksum), check_sum_vec_tmp'length);
+
+ if (unsigned(check_sum_vec) /= unsigned(check_sum_vec_tmp)) then
+ ASSERT FALSE
+ REPORT "[Line "& int_to_str(lineno) & "]:Incorrect checksum!"
+ SEVERITY ERROR;
+ end if;
+ end loop;
+ end if;
+ mem_init := TRUE;
+ end if;
+
+ -- MEMORY FUNCTION --
+ if we_tmp = '1' then
+ mem_data (to_integer(unsigned(address_tmp))) := data_tmp;
+ end if;
+ q_tmp <= mem_data(to_integer(unsigned(address_tmp)));
+ end process;
+
+end LPM_SYN;
+
+
+-- pragma translate_off
+configuration lpm_ram_dq_c0 of lpm_ram_dq is
+
+ for lpm_syn
+ end for;
+
+end lpm_ram_dq_c0;
+-- pragma translate_on
diff --git a/common/CPU/t48/rtl/vhdl/system/lpm_rom.vhd b/common/CPU/t48/rtl/vhdl/system/lpm_rom.vhd
new file mode 100644
index 00000000..b9450d6b
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/system/lpm_rom.vhd
@@ -0,0 +1,437 @@
+--------------------------------------------------------------------------
+-- This VHDL file was developed by Altera Corporation. It may be
+-- freely copied and/or distributed at no cost. Any persons using this
+-- file for any purpose do so at their own risk, and are responsible for
+-- the results of such use. Altera Corporation does not guarantee that
+-- this file is complete, correct, or fit for any particular purpose.
+-- NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED. This notice must
+-- accompany any copy of this file.
+--
+--------------------------------------------------------------------------
+-- LPM Synthesizable Models (Support string type generic)
+--------------------------------------------------------------------------
+-- Version 2.0 (lpm 220) Date 01/04/00
+--
+-- 1. Fixed LPM_RAM_DQ, LPM_RAM_DP, LPM_RAM_IO and LPM_ROM to correctly
+-- read in values from LPM_FILE (*.hex) when the DATA width is greater
+-- than 16 bits.
+-- 2. Explicit sign conversions are added to standard logic vector
+-- comparisons in LPM_RAM_DQ, LPM_RAM_DP, LPM_RAM_IO, LPM_ROM, and
+-- LPM_COMPARE.
+-- 3. LPM_FIFO_DC is rewritten to have correct outputs.
+-- 4. LPM_FIFO outputs zeros when nothing has been read from it, and
+-- outputs LPM_NUMWORDS mod exp(2, LPM_WIDTHU) when it is full.
+-- 5. Fixed LPM_DIVIDE to divide correctly.
+--------------------------------------------------------------------------
+-- Version 1.9 (lpm 220) Date 11/30/99
+--
+-- 1. Fixed UNUSED file not found problem and initialization problem
+-- with LPM_RAM_DP, LPM_RAM_DQ, and LPM_RAM_IO.
+-- 2. Fixed LPM_MULT when SUM port is not used.
+-- 3. Fixed LPM_FIFO_DC to enable read when rdclock and wrclock rise
+-- at the same time.
+-- 4. Fixed LPM_COUNTER comparison problem when signed library is loaded
+-- and counter is incrementing.
+-- 5. Got rid of "Illegal Character" error message at time = 0 ns when
+-- simulating LPM_COUNTER.
+--------------------------------------------------------------------------
+-- Version 1.8 (lpm 220) Date 10/25/99
+--
+-- 1. Some LPM_PVALUE implementations were missing, and now implemented.
+-- 2. Fixed LPM_COUNTER to count correctly without conversion overflow,
+-- that is, when LPM_MODULUS = 2 ** LPM_WIDTH.
+-- 3. Fixed LPM_RAM_DP sync process sensitivity list to detect wraddress
+-- changes.
+--------------------------------------------------------------------------
+-- Version 1.7 (lpm 220) Date 07/13/99
+--
+-- Changed LPM_RAM_IO so that it can be used to simulate both MP2 and
+-- Quartus behaviour and LPM220-compliant behaviour.
+--------------------------------------------------------------------------
+-- Version 1.6 (lpm 220) Date 06/15/99
+--
+-- 1. Fixed LPM_ADD_SUB sign extension problem and subtraction bug.
+-- 2. Fixed LPM_COUNTER to use LPM_MODULUS value.
+-- 3. Added CIN and COUT port, and discarded EQ port in LPM_COUNTER to
+-- comply with the specfication.
+-- 4. Included LPM_RAM_DP, LPM_RAM_DQ, LPM_RAM_IO, LPM_ROM, LPM_FIFO, and
+-- LPM_FIFO_DC; they are all initialized to 0's.
+--------------------------------------------------------------------------
+-- Version 1.5 (lpm 220) Date 05/10/99
+--
+-- Changed LPM_MODULUS from string type to integer.
+--------------------------------------------------------------------------
+-- Version 1.4 (lpm 220) Date 02/05/99
+--
+-- 1. Added LPM_DIVIDE module.
+-- 2. Added CLKEN port to LPM_MUX, LPM_DECODE, LPM_ADD_SUB, LPM_MULT
+-- and LPM_COMPARE
+-- 3. Replaced the constants holding string with the actual string.
+--------------------------------------------------------------------------
+-- Version 1.3 Date 07/30/96
+--
+-- Modification History
+--
+-- 1. Changed the DEFAULT value to "UNUSED" for LPM_SVALUE, LPM_AVALUE,
+-- LPM_MODULUS, and LPM_NUMWORDS, LPM_HINT,LPM_STRENGTH, LPM_DIRECTION,
+-- and LPM_PVALUE
+--
+-- 2. Added the two dimentional port components (AND, OR, XOR, and MUX).
+--------------------------------------------------------------------------
+-- Excluded Functions:
+--
+-- LPM_FSM and LPM_TTABLE
+--
+--------------------------------------------------------------------------
+-- Assumptions:
+--
+-- 1. All ports and signal types are std_logic or std_logic_vector
+-- from IEEE 1164 package.
+-- 2. Synopsys std_logic_arith, std_logic_unsigned, and std_logic_signed
+-- package are assumed to be accessible from IEEE library.
+-- 3. lpm_component_package must be accessible from library work.
+-- 4. The default value of LPM_SVALUE, LPM_AVALUE, LPM_MODULUS, LPM_HINT,
+-- LPM_NUMWORDS, LPM_STRENGTH, LPM_DIRECTION, and LPM_PVALUE is
+-- string "UNUSED".
+--------------------------------------------------------------------------
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+--use work.LPM_COMPONENTS.all;
+use std.textio.all;
+
+entity LPM_ROM is
+ generic (LPM_WIDTH : positive;
+ LPM_WIDTHAD : positive;
+ LPM_NUMWORDS : natural := 0;
+ LPM_ADDRESS_CONTROL : string := "REGISTERED";
+ LPM_OUTDATA : string := "REGISTERED";
+ LPM_FILE : string;
+ LPM_TYPE : string := "LPM_ROM";
+ LPM_HINT : string := "UNUSED");
+ port (ADDRESS : in STD_LOGIC_VECTOR(LPM_WIDTHAD-1 downto 0);
+ INCLOCK : in STD_LOGIC := '0';
+ OUTCLOCK : in STD_LOGIC := '0';
+ MEMENAB : in STD_LOGIC := '1';
+ Q : out STD_LOGIC_VECTOR(LPM_WIDTH-1 downto 0));
+
+ function int_to_str( value : integer ) return string is
+ variable ivalue,index : integer;
+ variable digit : integer;
+ variable line_no: string(8 downto 1) := " ";
+ begin
+ ivalue := value;
+ index := 1;
+ while (ivalue > 0 ) loop
+ digit := ivalue MOD 10;
+ ivalue := ivalue/10;
+ case digit is
+ when 0 =>
+ line_no(index) := '0';
+ when 1 =>
+ line_no(index) := '1';
+ when 2 =>
+ line_no(index) := '2';
+ when 3 =>
+ line_no(index) := '3';
+ when 4 =>
+ line_no(index) := '4';
+ when 5 =>
+ line_no(index) := '5';
+ when 6 =>
+ line_no(index) := '6';
+ when 7 =>
+ line_no(index) := '7';
+ when 8 =>
+ line_no(index) := '8';
+ when 9 =>
+ line_no(index) := '9';
+ when others =>
+ ASSERT FALSE
+ REPORT "Illegal number!"
+ SEVERITY ERROR;
+ end case;
+ index := index + 1;
+ end loop;
+ return line_no;
+ end;
+
+ function hex_str_to_int( str : string ) return integer is
+ variable len : integer := str'length;
+ variable ivalue : integer := 0;
+ variable digit : integer;
+ begin
+ for i in len downto 1 loop
+ case str(i) is
+ when '0' =>
+ digit := 0;
+ when '1' =>
+ digit := 1;
+ when '2' =>
+ digit := 2;
+ when '3' =>
+ digit := 3;
+ when '4' =>
+ digit := 4;
+ when '5' =>
+ digit := 5;
+ when '6' =>
+ digit := 6;
+ when '7' =>
+ digit := 7;
+ when '8' =>
+ digit := 8;
+ when '9' =>
+ digit := 9;
+ when 'A' =>
+ digit := 10;
+ when 'a' =>
+ digit := 10;
+ when 'B' =>
+ digit := 11;
+ when 'b' =>
+ digit := 11;
+ when 'C' =>
+ digit := 12;
+ when 'c' =>
+ digit := 12;
+ when 'D' =>
+ digit := 13;
+ when 'd' =>
+ digit := 13;
+ when 'E' =>
+ digit := 14;
+ when 'e' =>
+ digit := 14;
+ when 'F' =>
+ digit := 15;
+ when 'f' =>
+ digit := 15;
+ when others =>
+ ASSERT FALSE
+ REPORT "Illegal character "& str(i) & "in Intel Hex File! "
+ SEVERITY ERROR;
+ end case;
+ ivalue := ivalue * 16 + digit;
+ end loop;
+ return ivalue;
+ end;
+
+ procedure Shrink_line(L : inout LINE; pos : in integer) is
+ subtype nstring is string(1 to pos);
+ variable stmp : nstring;
+ begin
+ if pos >= 1 then
+ read(l, stmp);
+ end if;
+ end;
+
+end LPM_ROM;
+
+architecture LPM_SYN of lpm_rom is
+
+--type lpm_memory is array(lpm_numwords-1 downto 0) of std_logic_vector(lpm_width-1 downto 0);
+type lpm_memory is array(integer range (2**lpm_widthad)-1 downto 0) of std_logic_vector(lpm_width-1 downto 0);
+
+signal q2, q_tmp, q_reg : std_logic_vector(lpm_width-1 downto 0);
+signal address_tmp, address_reg : std_logic_vector(lpm_widthad-1 downto 0);
+
+begin
+
+ enable_mem: process(memenab, q2)
+ begin
+ if (memenab = '1') then
+ q <= q2;
+ else
+ q <= (OTHERS => 'Z');
+ end if;
+ end process;
+
+ sync: process(address, address_reg, q_tmp, q_reg)
+ begin
+ if (lpm_address_control = "REGISTERED") then
+ address_tmp <= address_reg;
+ else
+ address_tmp <= address;
+ end if;
+ if (lpm_outdata = "REGISTERED") then
+ q2 <= q_reg;
+ else
+ q2 <= q_tmp;
+ end if;
+ end process;
+
+ input_reg: process (inclock)
+ begin
+ if inclock'event and inclock = '1' then
+ address_reg <= address;
+ end if;
+ end process;
+
+ output_reg: process (outclock)
+ begin
+ if outclock'event and outclock = '1' then
+ q_reg <= q_tmp;
+ end if;
+ end process;
+
+ memory: process(memenab, address_tmp)
+ variable mem_data : lpm_memory;
+ variable mem_data_tmp : integer := 0;
+ variable mem_init: boolean := false;
+ variable i, j, k, lineno : integer := 0;
+ variable buf: line ;
+ variable booval: boolean ;
+ FILE mem_data_file: TEXT IS IN LPM_FILE;
+ variable base, byte, rec_type, datain, addr, checksum: string(2 downto 1);
+ variable startadd: string(4 downto 1);
+ variable ibase: integer := 0;
+ variable ibyte: integer := 0;
+ variable istartadd: integer := 0;
+ variable check_sum_vec, check_sum_vec_tmp: unsigned(7 downto 0);
+ begin
+ -- INITIALIZE --
+ if NOT(mem_init) then
+ -- INITIALIZE TO 0 --
+ for i in mem_data'LOW to mem_data'HIGH loop
+ mem_data(i) := (OTHERS => '0');
+ end loop;
+
+ if (LPM_FILE = "UNUSED") then
+ ASSERT FALSE
+ REPORT "Initialization file not found!"
+ SEVERITY ERROR;
+ else
+ WHILE NOT ENDFILE(mem_data_file) loop
+ booval := true;
+ READLINE(mem_data_file, buf);
+ lineno := lineno + 1;
+ check_sum_vec := (OTHERS => '0');
+ if (buf(buf'LOW) = ':') then
+ i := 1;
+ shrink_line(buf, i);
+ READ(L=>buf, VALUE=>byte, good=>booval);
+ if not (booval) then
+ ASSERT FALSE
+ REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format!"
+ SEVERITY ERROR;
+ end if;
+ ibyte := hex_str_to_int(byte);
+ check_sum_vec := unsigned(check_sum_vec) + to_unsigned(ibyte, 8);
+ READ(L=>buf, VALUE=>startadd, good=>booval);
+ if not (booval) then
+ ASSERT FALSE
+ REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! "
+ SEVERITY ERROR;
+ end if;
+ istartadd := hex_str_to_int(startadd);
+ addr(2) := startadd(4);
+ addr(1) := startadd(3);
+ check_sum_vec := unsigned(check_sum_vec) + to_unsigned(hex_str_to_int(addr), check_sum_vec'length);
+ addr(2) := startadd(2);
+ addr(1) := startadd(1);
+ check_sum_vec := unsigned(check_sum_vec) + to_unsigned(hex_str_to_int(addr), check_sum_vec'length);
+ READ(L=>buf, VALUE=>rec_type, good=>booval);
+ if not (booval) then
+ ASSERT FALSE
+ REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! "
+ SEVERITY ERROR;
+ end if;
+ check_sum_vec := unsigned(check_sum_vec) + to_unsigned(hex_str_to_int(rec_type), check_sum_vec'length);
+ else
+ ASSERT FALSE
+ REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! "
+ SEVERITY ERROR;
+ end if;
+ case rec_type is
+ when "00"=> -- Data record
+ i := 0;
+ k := lpm_width / 8;
+ if ((lpm_width MOD 8) /= 0) then
+ k := k + 1;
+ end if;
+ -- k = no. of bytes per CAM entry.
+ while (i < ibyte) loop
+ mem_data_tmp := 0;
+ for j in 1 to k loop
+ READ(L=>buf, VALUE=>datain,good=>booval); -- read in data a byte (2 hex chars) at a time.
+ if not (booval) then
+ ASSERT FALSE
+ REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! "
+ SEVERITY ERROR;
+ end if;
+ check_sum_vec := unsigned(check_sum_vec) + to_unsigned(hex_str_to_int(datain), check_sum_vec'length);
+ mem_data_tmp := mem_data_tmp * 256 + hex_str_to_int(datain);
+ end loop;
+ i := i + k;
+ mem_data(ibase + istartadd) := STD_LOGIC_VECTOR(to_unsigned(mem_data_tmp, lpm_width));
+ istartadd := istartadd + 1;
+ end loop;
+ when "01"=>
+ exit;
+ when "02"=>
+ ibase := 0;
+ if (ibyte /= 2) then
+ ASSERT FALSE
+ REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format for record type 02! "
+ SEVERITY ERROR;
+ end if;
+ for i in 0 to (ibyte-1) loop
+ READ(L=>buf, VALUE=>base,good=>booval);
+ ibase := ibase * 256 + hex_str_to_int(base);
+ if not (booval) then
+ ASSERT FALSE
+ REPORT "[Line "& int_to_str(lineno) & "]:Illegal Intel Hex Format! "
+ SEVERITY ERROR;
+ end if;
+ check_sum_vec := unsigned(check_sum_vec) + to_unsigned(hex_str_to_int(base), check_sum_vec'length);
+ end loop;
+ ibase := ibase * 16;
+ when OTHERS =>
+ ASSERT FALSE
+ REPORT "[Line "& int_to_str(lineno) & "]:Illegal record type in Intel Hex File! "
+ SEVERITY ERROR;
+ end case;
+ READ(L=>buf, VALUE=>checksum,good=>booval);
+ if not (booval) then
+ ASSERT FALSE
+ REPORT "[Line "& int_to_str(lineno) & "]:Checksum is missing! "
+ SEVERITY ERROR;
+ end if;
+
+ check_sum_vec := unsigned(not (check_sum_vec)) + 1 ;
+ check_sum_vec_tmp := to_unsigned(hex_str_to_int(checksum),8);
+
+ if (unsigned(check_sum_vec) /= unsigned(check_sum_vec_tmp)) then
+ ASSERT FALSE
+ REPORT "[Line "& int_to_str(lineno) & "]:Incorrect checksum!"
+ SEVERITY ERROR;
+ end if;
+ end loop;
+ end if;
+ mem_init := TRUE;
+ end if;
+
+ -- MEMORY FUNCTION --
+ --if memenab = '1' then
+ q_tmp <= mem_data(to_integer(UNSIGNED(address_tmp)));
+ --else
+ -- q_tmp <= (OTHERS => 'Z');
+ --end if;
+ end process;
+
+end LPM_SYN;
+
+
+---------------------------------------------------------------------------
+
+
+-- pragma translate_off
+configuration lpm_rom_c0 of lpm_rom is
+
+ for lpm_syn
+ end for;
+
+end lpm_rom_c0;
+-- pragma translate_on
diff --git a/common/CPU/t48/rtl/vhdl/system/t48_rom-e.vhd b/common/CPU/t48/rtl/vhdl/system/t48_rom-e.vhd
new file mode 100644
index 00000000..f2bc147c
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/system/t48_rom-e.vhd
@@ -0,0 +1,70 @@
+-------------------------------------------------------------------------------
+--
+-- T8x48 ROM
+--
+-- $Id: t48_rom-e.vhd,v 1.1.1.1 2006/11/25 22:15:41 arnim Exp $
+--
+-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity t48_rom is
+
+ port (
+ clk_i : in std_logic;
+ rom_addr_i : in std_logic_vector(9 downto 0);
+ rom_data_o : out std_logic_vector(7 downto 0)
+ );
+
+end t48_rom;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: t48_rom-e.vhd,v $
+-- Revision 1.1.1.1 2006/11/25 22:15:41 arnim
+-- copied from opencores.org repository release 1.0
+--
+-- Revision 1.1 2006/06/21 00:59:15 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/CPU/t48/rtl/vhdl/system/t48_rom-struct-a.vhd b/common/CPU/t48/rtl/vhdl/system/t48_rom-struct-a.vhd
new file mode 100644
index 00000000..0735cc38
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/system/t48_rom-struct-a.vhd
@@ -0,0 +1,84 @@
+-------------------------------------------------------------------------------
+--
+-- T8x48 ROM
+--
+-- $Id: t48_rom-struct-a.vhd,v 1.1.1.3 2006/11/26 10:07:52 arnim Exp $
+--
+-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+architecture struct of t48_rom is
+
+ component rom_t48
+ port(
+ Clk : in std_logic;
+ A : in std_logic_vector(9 downto 0);
+ D : out std_logic_vector(7 downto 0)
+ );
+ end component;
+
+begin
+
+ rom_b : rom_t48
+ port map (
+ Clk => clk_i,
+ A => rom_addr_i,
+ D => rom_data_o
+ );
+
+end struct;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: t48_rom-struct-a.vhd,v $
+-- Revision 1.1.1.3 2006/11/26 10:07:52 arnim
+-- incremental import for release 1.0
+--
+-- Revision 1.3 2006/11/26 12:53:28 arniml
+-- fix entity port names
+--
+-- Revision 1.2 2006/11/26 11:58:28 arniml
+-- fix component name
+--
+-- Revision 1.1 2006/06/21 00:59:15 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/CPU/t48/rtl/vhdl/system/t48_rom-struct-c.vhd b/common/CPU/t48/rtl/vhdl/system/t48_rom-struct-c.vhd
new file mode 100644
index 00000000..3c9602fa
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/system/t48_rom-struct-c.vhd
@@ -0,0 +1,23 @@
+-------------------------------------------------------------------------------
+--
+-- T8x48 ROM
+--
+-- $Id: t48_rom-struct-c.vhd,v 1.1.1.1 2006/11/26 10:07:52 arnim Exp $
+--
+-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+configuration t48_rom_struct_c0 of t48_rom is
+
+ for struct
+
+ for rom_b: rom_t48
+ use configuration work.rom_t48_rtl_c0;
+ end for;
+
+ end for;
+
+end t48_rom_struct_c0;
diff --git a/common/CPU/t48/rtl/vhdl/system/t48_system_comp_pack-p.vhd b/common/CPU/t48/rtl/vhdl/system/t48_system_comp_pack-p.vhd
new file mode 100644
index 00000000..ac28bb3c
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/system/t48_system_comp_pack-p.vhd
@@ -0,0 +1,177 @@
+-------------------------------------------------------------------------------
+--
+-- $Id: t48_system_comp_pack-p.vhd,v 1.8 2006/06/20 00:47:08 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+package t48_system_comp_pack is
+
+ component t48_wb_master
+ port (
+ xtal_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_o : out std_logic;
+ ale_i : in std_logic;
+ rd_n_i : in std_logic;
+ wr_n_i : in std_logic;
+ adr_i : in std_logic;
+ db_bus_i : in std_logic_vector( 7 downto 0);
+ db_bus_o : out std_logic_vector( 7 downto 0);
+ wb_cyc_o : out std_logic;
+ wb_stb_o : out std_logic;
+ wb_we_o : out std_logic;
+ wb_adr_o : out std_logic_vector(23 downto 0);
+ wb_ack_i : in std_logic;
+ wb_dat_i : in std_logic_vector( 7 downto 0);
+ wb_dat_o : out std_logic_vector( 7 downto 0)
+ );
+ end component;
+
+ component t8048_notri
+ generic (
+ gate_port_input_g : integer := 1
+ );
+
+ port (
+ xtal_i : in std_logic;
+ xtal_en_i : in std_logic;
+ reset_n_i : in std_logic;
+ t0_i : in std_logic;
+ t0_o : out std_logic;
+ t0_dir_o : out std_logic;
+ int_n_i : in std_logic;
+ ea_i : in std_logic;
+ rd_n_o : out std_logic;
+ psen_n_o : out std_logic;
+ wr_n_o : out std_logic;
+ ale_o : out std_logic;
+ db_i : in std_logic_vector( 7 downto 0);
+ db_o : out std_logic_vector( 7 downto 0);
+ db_dir_o : out std_logic;
+ t1_i : in std_logic;
+ p2_i : in std_logic_vector( 7 downto 0);
+ p2_o : out std_logic_vector( 7 downto 0);
+ p2l_low_imp_o : out std_logic;
+ p2h_low_imp_o : out std_logic;
+ p1_i : in std_logic_vector( 7 downto 0);
+ p1_o : out std_logic_vector( 7 downto 0);
+ p1_low_imp_o : out std_logic;
+ prog_n_o : out std_logic
+ );
+ end component;
+
+ component t8039_notri
+ generic (
+ gate_port_input_g : integer := 1
+ );
+
+ port (
+ xtal_i : in std_logic;
+ xtal_en_i : in std_logic;
+ reset_n_i : in std_logic;
+ t0_i : in std_logic;
+ t0_o : out std_logic;
+ t0_dir_o : out std_logic;
+ int_n_i : in std_logic;
+ ea_i : in std_logic;
+ rd_n_o : out std_logic;
+ psen_n_o : out std_logic;
+ wr_n_o : out std_logic;
+ ale_o : out std_logic;
+ db_i : in std_logic_vector( 7 downto 0);
+ db_o : out std_logic_vector( 7 downto 0);
+ db_dir_o : out std_logic;
+ t1_i : in std_logic;
+ p2_i : in std_logic_vector( 7 downto 0);
+ p2_o : out std_logic_vector( 7 downto 0);
+ p2l_low_imp_o : out std_logic;
+ p2h_low_imp_o : out std_logic;
+ p1_i : in std_logic_vector( 7 downto 0);
+ p1_o : out std_logic_vector( 7 downto 0);
+ p1_low_imp_o : out std_logic;
+ prog_n_o : out std_logic
+ );
+ end component;
+
+ component t8050_wb
+ generic (
+ gate_port_input_g : integer := 1
+ );
+
+ port (
+ xtal_i : in std_logic;
+ reset_n_i : in std_logic;
+ t0_i : in std_logic;
+ t0_o : out std_logic;
+ t0_dir_o : out std_logic;
+ int_n_i : in std_logic;
+ ea_i : in std_logic;
+ rd_n_o : out std_logic;
+ psen_n_o : out std_logic;
+ wr_n_o : out std_logic;
+ ale_o : out std_logic;
+ t1_i : in std_logic;
+ p2_i : in std_logic_vector( 7 downto 0);
+ p2_o : out std_logic_vector( 7 downto 0);
+ p2l_low_imp_o : out std_logic;
+ p2h_low_imp_o : out std_logic;
+ p1_i : in std_logic_vector( 7 downto 0);
+ p1_o : out std_logic_vector( 7 downto 0);
+ p1_low_imp_o : out std_logic;
+ prog_n_o : out std_logic;
+ wb_cyc_o : out std_logic;
+ wb_stb_o : out std_logic;
+ wb_we_o : out std_logic;
+ wb_adr_o : out std_logic_vector(23 downto 0);
+ wb_ack_i : in std_logic;
+ wb_dat_i : in std_logic_vector( 7 downto 0);
+ wb_dat_o : out std_logic_vector( 7 downto 0)
+ );
+ end component;
+
+ component t8048
+ port (
+ xtal_i : in std_logic;
+ reset_n_i : in std_logic;
+ t0_b : inout std_logic;
+ int_n_i : in std_logic;
+ ea_i : in std_logic;
+ rd_n_o : out std_logic;
+ psen_n_o : out std_logic;
+ wr_n_o : out std_logic;
+ ale_o : out std_logic;
+ db_b : inout std_logic_vector( 7 downto 0);
+ t1_i : in std_logic;
+ p2_b : inout std_logic_vector( 7 downto 0);
+ p1_b : inout std_logic_vector( 7 downto 0);
+ prog_n_o : out std_logic
+ );
+ end component;
+
+ component t8039
+ port (
+ xtal_i : in std_logic;
+ reset_n_i : in std_logic;
+ t0_b : inout std_logic;
+ int_n_i : in std_logic;
+ ea_i : in std_logic;
+ rd_n_o : out std_logic;
+ psen_n_o : out std_logic;
+ wr_n_o : out std_logic;
+ ale_o : out std_logic;
+ db_b : inout std_logic_vector( 7 downto 0);
+ t1_i : in std_logic;
+ p2_b : inout std_logic_vector( 7 downto 0);
+ p1_b : inout std_logic_vector( 7 downto 0);
+ prog_n_o : out std_logic
+ );
+ end component;
+
+end t48_system_comp_pack;
diff --git a/common/CPU/t48/rtl/vhdl/system/t49_rom-e.vhd b/common/CPU/t48/rtl/vhdl/system/t49_rom-e.vhd
new file mode 100644
index 00000000..2fd569dd
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/system/t49_rom-e.vhd
@@ -0,0 +1,70 @@
+-------------------------------------------------------------------------------
+--
+-- T8x49 ROM
+--
+-- $Id: t49_rom-e.vhd,v 1.1.1.1 2006/11/25 22:15:41 arnim Exp $
+--
+-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity t49_rom is
+
+ port (
+ clk_i : in std_logic;
+ rom_addr_i : in std_logic_vector(10 downto 0);
+ rom_data_o : out std_logic_vector( 7 downto 0)
+ );
+
+end t49_rom;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: t49_rom-e.vhd,v $
+-- Revision 1.1.1.1 2006/11/25 22:15:41 arnim
+-- copied from opencores.org repository release 1.0
+--
+-- Revision 1.1 2006/06/21 00:59:15 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/CPU/t48/rtl/vhdl/system/t49_rom-struct-a.vhd b/common/CPU/t48/rtl/vhdl/system/t49_rom-struct-a.vhd
new file mode 100644
index 00000000..e60ebe37
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/system/t49_rom-struct-a.vhd
@@ -0,0 +1,84 @@
+-------------------------------------------------------------------------------
+--
+-- T8x49 ROM
+--
+-- $Id: t49_rom-struct-a.vhd,v 1.1.1.3 2006/11/26 10:07:52 arnim Exp $
+--
+-- Copyright (c) 2006 Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+architecture struct of t49_rom is
+
+ component rom_t49
+ port(
+ Clk : in std_logic;
+ A : in std_logic_vector(10 downto 0);
+ D : out std_logic_vector( 7 downto 0)
+ );
+ end component;
+
+begin
+
+ rom_b : rom_t49
+ port map (
+ Clk => clk_i,
+ A => rom_addr_i,
+ D => rom_data_o
+ );
+
+end struct;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: t49_rom-struct-a.vhd,v $
+-- Revision 1.1.1.3 2006/11/26 10:07:52 arnim
+-- incremental import for release 1.0
+--
+-- Revision 1.3 2006/11/26 12:53:28 arniml
+-- fix entity port names
+--
+-- Revision 1.2 2006/11/26 11:58:28 arniml
+-- fix component name
+--
+-- Revision 1.1 2006/06/21 00:59:15 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/CPU/t48/rtl/vhdl/system/t49_rom-struct-c.vhd b/common/CPU/t48/rtl/vhdl/system/t49_rom-struct-c.vhd
new file mode 100644
index 00000000..33294688
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/system/t49_rom-struct-c.vhd
@@ -0,0 +1,23 @@
+-------------------------------------------------------------------------------
+--
+-- T8x49 ROM
+--
+-- $Id: t49_rom-struct-c.vhd,v 1.1.1.1 2006/11/26 10:07:52 arnim Exp $
+--
+-- Copyright (c) 2006, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+configuration t49_rom_struct_c0 of t49_rom is
+
+ for struct
+
+ for rom_b: rom_t49
+ use configuration work.rom_t49_rtl_c0;
+ end for;
+
+ end for;
+
+end t49_rom_struct_c0;
diff --git a/common/CPU/t48/rtl/vhdl/system/t8039-c.vhd b/common/CPU/t48/rtl/vhdl/system/t8039-c.vhd
new file mode 100644
index 00000000..1daac1ad
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/system/t8039-c.vhd
@@ -0,0 +1,23 @@
+-------------------------------------------------------------------------------
+--
+-- T8039 Microcontroller System
+--
+-- $Id: t8039-c.vhd,v 1.2 2004/12/03 19:43:12 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+configuration t8039_struct_c0 of t8039 is
+
+ for struct
+
+ for t8039_notri_b : t8039_notri
+ use configuration work.t8039_notri_struct_c0;
+ end for;
+
+ end for;
+
+end t8039_struct_c0;
diff --git a/common/CPU/t48/rtl/vhdl/system/t8039.vhd b/common/CPU/t48/rtl/vhdl/system/t8039.vhd
new file mode 100644
index 00000000..f9c4bc54
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/system/t8039.vhd
@@ -0,0 +1,205 @@
+-------------------------------------------------------------------------------
+--
+-- T8039 Microcontroller System
+--
+-- $Id: t8039.vhd,v 1.7 2006/07/14 01:13:32 arniml Exp $
+-- $Name: $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity t8039 is
+
+ port (
+ xtal_i : in std_logic;
+ reset_n_i : in std_logic;
+ t0_b : inout std_logic;
+ int_n_i : in std_logic;
+ ea_i : in std_logic;
+ rd_n_o : out std_logic;
+ psen_n_o : out std_logic;
+ wr_n_o : out std_logic;
+ ale_o : out std_logic;
+ db_b : inout std_logic_vector( 7 downto 0);
+ t1_i : in std_logic;
+ p2_b : inout std_logic_vector( 7 downto 0);
+ p1_b : inout std_logic_vector( 7 downto 0);
+ prog_n_o : out std_logic
+ );
+
+end t8039;
+
+
+use work.t48_system_comp_pack.t8039_notri;
+
+architecture struct of t8039 is
+
+ signal t0_s : std_logic;
+ signal t0_dir_s : std_logic;
+ signal db_s : std_logic_vector( 7 downto 0);
+ signal db_dir_s : std_logic;
+ signal p2_s : std_logic_vector( 7 downto 0);
+ signal p2l_low_imp_s : std_logic;
+ signal p2h_low_imp_s : std_logic;
+ signal p1_s : std_logic_vector( 7 downto 0);
+ signal p1_low_imp_s : std_logic;
+
+ signal vdd_s : std_logic;
+
+begin
+
+ vdd_s <= '1';
+
+ t8039_notri_b : t8039_notri
+ generic map (
+ -- we don't need explicit gating of input ports
+ -- this is done implicitely by the bidirectional pads
+ gate_port_input_g => 0
+ )
+
+ port map (
+ xtal_i => xtal_i,
+ xtal_en_i => vdd_s,
+ reset_n_i => reset_n_i,
+ t0_i => t0_b,
+ t0_o => t0_s,
+ t0_dir_o => t0_dir_s,
+ int_n_i => int_n_i,
+ ea_i => ea_i,
+ rd_n_o => rd_n_o,
+ psen_n_o => psen_n_o,
+ wr_n_o => wr_n_o,
+ ale_o => ale_o,
+ db_i => db_b,
+ db_o => db_s,
+ db_dir_o => db_dir_s,
+ t1_i => t1_i,
+ p2_i => p2_b,
+ p2_o => p2_s,
+ p2l_low_imp_o => p2l_low_imp_s,
+ p2h_low_imp_o => p2h_low_imp_s,
+ p1_i => p1_b,
+ p1_o => p1_s,
+ p1_low_imp_o => p1_low_imp_s,
+ prog_n_o => prog_n_o
+ );
+
+ -----------------------------------------------------------------------------
+ -- Process bidirs
+ --
+ -- Purpose:
+ -- Assign bidirectional signals.
+ --
+ bidirs: process (t0_b, t0_s, t0_dir_s,
+ db_b, db_s, db_dir_s,
+ p1_b, p1_s, p1_low_imp_s,
+ p2_b, p2_s, p2l_low_imp_s, p2h_low_imp_s)
+
+ function port_bidir_f(port_value : in std_logic_vector;
+ low_imp : in std_logic) return std_logic_vector is
+ variable result_v : std_logic_vector(port_value'range);
+ begin
+ for idx in port_value'high downto port_value'low loop
+ if low_imp = '1' then
+ result_v(idx) := port_value(idx);
+ elsif port_value(idx) = '0' then
+ result_v(idx) := '0';
+ else
+ result_v(idx) := 'Z';
+ end if;
+ end loop;
+
+ return result_v;
+ end;
+
+ begin
+ -- Test 0 -----------------------------------------------------------------
+ if t0_dir_s = '1' then
+ t0_b <= t0_s;
+ else
+ t0_b <= 'Z';
+ end if;
+
+ -- Data Bus ---------------------------------------------------------------
+ if db_dir_s = '1' then
+ db_b <= db_s;
+ else
+ db_b <= (others => 'Z');
+ end if;
+
+ -- Port 1 -----------------------------------------------------------------
+ p1_b <= port_bidir_f(port_value => p1_s,
+ low_imp => p1_low_imp_s);
+
+ -- Port 2 -----------------------------------------------------------------
+ p2_b(3 downto 0) <= port_bidir_f(port_value => p2_s(3 downto 0),
+ low_imp => p2l_low_imp_s);
+ p2_b(7 downto 4) <= port_bidir_f(port_value => p2_s(7 downto 4),
+ low_imp => p2h_low_imp_s);
+
+ end process bidirs;
+ --
+ -----------------------------------------------------------------------------
+
+end struct;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: t8039.vhd,v $
+-- Revision 1.7 2006/07/14 01:13:32 arniml
+-- name keyword added
+--
+-- Revision 1.6 2006/06/20 00:47:08 arniml
+-- new input xtal_en_i
+--
+-- Revision 1.5 2005/11/02 23:41:43 arniml
+-- properly drive P1 and P2 with low impedance markers
+--
+-- Revision 1.4 2005/11/01 21:37:45 arniml
+-- wire signals for P2 low impedance marker issue
+--
+-- Revision 1.3 2004/12/03 19:43:12 arniml
+-- added hierarchy t8039_notri
+--
+-------------------------------------------------------------------------------
diff --git a/common/CPU/t48/rtl/vhdl/system/t8039_notri-c.vhd b/common/CPU/t48/rtl/vhdl/system/t8039_notri-c.vhd
new file mode 100644
index 00000000..0bf090f5
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/system/t8039_notri-c.vhd
@@ -0,0 +1,28 @@
+-------------------------------------------------------------------------------
+--
+-- T8039 Microcontroller System
+-- 8039 toplevel without tri-states
+--
+-- $Id: t8039_notri-c.vhd,v 1.2 2006/06/21 01:02:35 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+configuration t8039_notri_struct_c0 of t8039_notri is
+
+ for struct
+
+ for ram_128_b : generic_ram_ena
+ use configuration work.generic_ram_ena_rtl_c0;
+ end for;
+
+ for t48_core_b : t48_core
+ use configuration work.t48_core_struct_c0;
+ end for;
+
+ end for;
+
+end t8039_notri_struct_c0;
diff --git a/common/CPU/t48/rtl/vhdl/system/t8039_notri.vhd b/common/CPU/t48/rtl/vhdl/system/t8039_notri.vhd
new file mode 100644
index 00000000..e88da2cd
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/system/t8039_notri.vhd
@@ -0,0 +1,227 @@
+-------------------------------------------------------------------------------
+--
+-- T8039 Microcontroller System
+-- 8039 toplevel without tri-states
+--
+-- $Id: t8039_notri.vhd,v 1.5 2006/07/14 01:13:32 arniml Exp $
+-- $Name: $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity t8039_notri is
+
+ generic (
+ gate_port_input_g : integer := 1
+ );
+
+ port (
+ xtal_i : in std_logic;
+ xtal_en_i : in std_logic;
+ reset_n_i : in std_logic;
+ t0_i : in std_logic;
+ t0_o : out std_logic;
+ t0_dir_o : out std_logic;
+ int_n_i : in std_logic;
+ ea_i : in std_logic;
+ rd_n_o : out std_logic;
+ psen_n_o : out std_logic;
+ wr_n_o : out std_logic;
+ ale_o : out std_logic;
+ db_i : in std_logic_vector( 7 downto 0);
+ db_o : out std_logic_vector( 7 downto 0);
+ db_dir_o : out std_logic;
+ t1_i : in std_logic;
+ p2_i : in std_logic_vector( 7 downto 0);
+ p2_o : out std_logic_vector( 7 downto 0);
+ p2l_low_imp_o : out std_logic;
+ p2h_low_imp_o : out std_logic;
+ p1_i : in std_logic_vector( 7 downto 0);
+ p1_o : out std_logic_vector( 7 downto 0);
+ p1_low_imp_o : out std_logic;
+ prog_n_o : out std_logic
+ );
+
+end t8039_notri;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+use work.t48_core_comp_pack.t48_core;
+use work.t48_core_comp_pack.generic_ram_ena;
+
+architecture struct of t8039_notri is
+
+ signal xtal3_s : std_logic;
+ signal dmem_addr_s : std_logic_vector( 7 downto 0);
+ signal dmem_we_s : std_logic;
+ signal dmem_data_from_s : std_logic_vector( 7 downto 0);
+ signal dmem_data_to_s : std_logic_vector( 7 downto 0);
+ signal pmem_data_s : std_logic_vector( 7 downto 0);
+
+ signal p1_in_s,
+ p1_out_s : std_logic_vector( 7 downto 0);
+ signal p2_in_s,
+ p2_out_s : std_logic_vector( 7 downto 0);
+
+ signal vdd_s : std_logic;
+
+begin
+
+ vdd_s <= '1';
+
+ -----------------------------------------------------------------------------
+ -- Check generics for valid values.
+ -----------------------------------------------------------------------------
+ -- pragma translate_off
+ assert gate_port_input_g = 0 or gate_port_input_g = 1
+ report "gate_port_input_g must be either 1 or 0!"
+ severity failure;
+ -- pragma translate_on
+
+
+ -- no Program memory available
+ pmem_data_s <= (others => '0');
+
+
+ t48_core_b : t48_core
+ generic map (
+ xtal_div_3_g => 1,
+ register_mnemonic_g => 1,
+ include_port1_g => 1,
+ include_port2_g => 1,
+ include_bus_g => 1,
+ include_timer_g => 1,
+ sample_t1_state_g => 4
+ )
+ port map (
+ xtal_i => xtal_i,
+ xtal_en_i => xtal_en_i,
+ reset_i => reset_n_i,
+ t0_i => t0_i,
+ t0_o => t0_o,
+ t0_dir_o => t0_dir_o,
+ int_n_i => int_n_i,
+ ea_i => ea_i,
+ rd_n_o => rd_n_o,
+ psen_n_o => psen_n_o,
+ wr_n_o => wr_n_o,
+ ale_o => ale_o,
+ db_i => db_i,
+ db_o => db_o,
+ db_dir_o => db_dir_o,
+ t1_i => t1_i,
+ p2_i => p2_in_s,
+ p2_o => p2_out_s,
+ p2l_low_imp_o => p2l_low_imp_o,
+ p2h_low_imp_o => p2h_low_imp_o,
+ p1_i => p1_in_s,
+ p1_o => p1_out_s,
+ p1_low_imp_o => p1_low_imp_o,
+ prog_n_o => prog_n_o,
+ clk_i => xtal_i,
+ en_clk_i => xtal3_s,
+ xtal3_o => xtal3_s,
+ dmem_addr_o => dmem_addr_s,
+ dmem_we_o => dmem_we_s,
+ dmem_data_i => dmem_data_from_s,
+ dmem_data_o => dmem_data_to_s,
+ pmem_addr_o => open,
+ pmem_data_i => pmem_data_s
+ );
+
+
+ -----------------------------------------------------------------------------
+ -- Gate port 1 and 2 input bus with respetive output value
+ -----------------------------------------------------------------------------
+ gate_ports: if gate_port_input_g = 1 generate
+ p1_in_s <= p1_i and p1_out_s;
+ p2_in_s <= p2_i and p2_out_s;
+ end generate;
+
+ pass_ports: if gate_port_input_g = 0 generate
+ p1_in_s <= p1_i;
+ p2_in_s <= p2_i;
+ end generate;
+
+ p1_o <= p1_out_s;
+ p2_o <= p2_out_s;
+
+
+ ram_128_b : generic_ram_ena
+ generic map (
+ addr_width_g => 7,
+ data_width_g => 8
+ )
+ port map (
+ clk_i => xtal_i,
+ a_i => dmem_addr_s(6 downto 0),
+ we_i => dmem_we_s,
+ ena_i => vdd_s,
+ d_i => dmem_data_to_s,
+ d_o => dmem_data_from_s
+ );
+
+end struct;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: t8039_notri.vhd,v $
+-- Revision 1.5 2006/07/14 01:13:32 arniml
+-- name keyword added
+--
+-- Revision 1.4 2006/06/21 01:02:35 arniml
+-- replaced syn_ram with generic_ram_ena
+--
+-- Revision 1.3 2006/06/20 00:47:08 arniml
+-- new input xtal_en_i
+--
+-- Revision 1.2 2005/11/01 21:38:10 arniml
+-- wire signals for P2 low impedance marker issue
+--
+-- Revision 1.1 2004/12/03 19:42:34 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/CPU/t48/rtl/vhdl/system/t8048-c.vhd b/common/CPU/t48/rtl/vhdl/system/t8048-c.vhd
new file mode 100644
index 00000000..b3d7d0a7
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/system/t8048-c.vhd
@@ -0,0 +1,23 @@
+-------------------------------------------------------------------------------
+--
+-- T8048 Microcontroller System
+--
+-- $Id: t8048-c.vhd,v 1.2 2004/12/01 23:09:47 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+configuration t8048_struct_c0 of t8048 is
+
+ for struct
+
+ for t8048_notri_b : t8048_notri
+ use configuration work.t8048_notri_struct_c0;
+ end for;
+
+ end for;
+
+end t8048_struct_c0;
diff --git a/common/CPU/t48/rtl/vhdl/system/t8048.vhd b/common/CPU/t48/rtl/vhdl/system/t8048.vhd
new file mode 100644
index 00000000..4222cefa
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/system/t8048.vhd
@@ -0,0 +1,231 @@
+-------------------------------------------------------------------------------
+--
+-- T8048 Microcontroller System
+--
+-- $Id: t8048.vhd,v 1.11 2006/07/14 01:13:32 arniml Exp $
+-- $Name: $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity t8048 is
+
+ port (
+ xtal_i : in std_logic;
+ reset_n_i : in std_logic;
+ t0_b : inout std_logic;
+ int_n_i : in std_logic;
+ ea_i : in std_logic;
+ rd_n_o : out std_logic;
+ psen_n_o : out std_logic;
+ wr_n_o : out std_logic;
+ ale_o : out std_logic;
+ db_b : inout std_logic_vector( 7 downto 0);
+ t1_i : in std_logic;
+ p2_b : inout std_logic_vector( 7 downto 0);
+ p1_b : inout std_logic_vector( 7 downto 0);
+ prog_n_o : out std_logic
+ );
+
+end t8048;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+use work.t48_system_comp_pack.t8048_notri;
+
+architecture struct of t8048 is
+
+ signal t0_s : std_logic;
+ signal t0_dir_s : std_logic;
+ signal db_s : std_logic_vector( 7 downto 0);
+ signal db_dir_s : std_logic;
+ signal p2_s : std_logic_vector( 7 downto 0);
+ signal p2l_low_imp_s : std_logic;
+ signal p2h_low_imp_s : std_logic;
+ signal p1_s : std_logic_vector( 7 downto 0);
+ signal p1_low_imp_s : std_logic;
+
+ signal vdd_s : std_logic;
+
+begin
+
+ vdd_s <= '1';
+
+ t8048_notri_b : t8048_notri
+ generic map (
+ -- we don't need explicit gating of input ports
+ -- this is done implicitely by the bidirectional pads
+ gate_port_input_g => 0
+ )
+
+ port map (
+ xtal_i => xtal_i,
+ xtal_en_i => vdd_s,
+ reset_n_i => reset_n_i,
+ t0_i => t0_b,
+ t0_o => t0_s,
+ t0_dir_o => t0_dir_s,
+ int_n_i => int_n_i,
+ ea_i => ea_i,
+ rd_n_o => rd_n_o,
+ psen_n_o => psen_n_o,
+ wr_n_o => wr_n_o,
+ ale_o => ale_o,
+ db_i => db_b,
+ db_o => db_s,
+ db_dir_o => db_dir_s,
+ t1_i => t1_i,
+ p2_i => p2_b,
+ p2_o => p2_s,
+ p2l_low_imp_o => p2l_low_imp_s,
+ p2h_low_imp_o => p2h_low_imp_s,
+ p1_i => p1_b,
+ p1_o => p1_s,
+ p1_low_imp_o => p1_low_imp_s,
+ prog_n_o => prog_n_o
+ );
+
+ -----------------------------------------------------------------------------
+ -- Process bidirs
+ --
+ -- Purpose:
+ -- Assign bidirectional signals.
+ --
+ bidirs: process (t0_b, t0_s, t0_dir_s,
+ db_b, db_s, db_dir_s,
+ p1_b, p1_s, p1_low_imp_s,
+ p2_b, p2_s, p2l_low_imp_s, p2h_low_imp_s)
+
+ function port_bidir_f(port_value : in std_logic_vector;
+ low_imp : in std_logic) return std_logic_vector is
+ variable result_v : std_logic_vector(port_value'range);
+ begin
+ for idx in port_value'high downto port_value'low loop
+ if low_imp = '1' then
+ result_v(idx) := port_value(idx);
+ elsif port_value(idx) = '0' then
+ result_v(idx) := '0';
+ else
+ result_v(idx) := 'Z';
+ end if;
+ end loop;
+
+ return result_v;
+ end;
+
+ begin
+ -- Test 0 -----------------------------------------------------------------
+ if t0_dir_s = '1' then
+ t0_b <= t0_s;
+ else
+ t0_b <= 'Z';
+ end if;
+
+ -- Data Bus ---------------------------------------------------------------
+ if db_dir_s = '1' then
+ db_b <= db_s;
+ else
+ db_b <= (others => 'Z');
+ end if;
+
+ -- Port 1 -----------------------------------------------------------------
+ p1_b <= port_bidir_f(port_value => p1_s,
+ low_imp => p1_low_imp_s);
+
+ -- Port 2 -----------------------------------------------------------------
+ p2_b(3 downto 0) <= port_bidir_f(port_value => p2_s(3 downto 0),
+ low_imp => p2l_low_imp_s);
+ p2_b(7 downto 4) <= port_bidir_f(port_value => p2_s(7 downto 4),
+ low_imp => p2h_low_imp_s);
+
+ end process bidirs;
+ --
+ -----------------------------------------------------------------------------
+
+
+end struct;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: t8048.vhd,v $
+-- Revision 1.11 2006/07/14 01:13:32 arniml
+-- name keyword added
+--
+-- Revision 1.10 2006/06/20 00:47:08 arniml
+-- new input xtal_en_i
+--
+-- Revision 1.9 2005/11/02 23:41:43 arniml
+-- properly drive P1 and P2 with low impedance markers
+--
+-- Revision 1.8 2005/11/01 21:38:31 arniml
+-- wire signals for P2 low impedance marker issue
+--
+-- Revision 1.7 2004/12/03 19:44:36 arniml
+-- removed obsolete constant
+--
+-- Revision 1.6 2004/12/02 22:08:42 arniml
+-- introduced generic gate_port_input_g
+-- forces masking of P1 and P2 input bus
+--
+-- Revision 1.5 2004/12/01 23:09:47 arniml
+-- intruduced hierarchy t8048_notri where all system functionality
+-- except bidirectional ports is handled
+--
+-- Revision 1.4 2004/10/24 09:10:16 arniml
+-- Fix for:
+-- P1 constantly in push-pull mode in t8048
+--
+-- Revision 1.3 2004/05/20 21:58:26 arniml
+-- Fix for:
+-- External Program Memory ignored when EA = 0
+--
+-- Revision 1.2 2004/03/29 19:40:14 arniml
+-- rename pX_limp to pX_low_imp
+--
+-- Revision 1.1 2004/03/24 21:32:27 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/CPU/t48/rtl/vhdl/system/t8048_notri-c.vhd b/common/CPU/t48/rtl/vhdl/system/t8048_notri-c.vhd
new file mode 100644
index 00000000..03e7ec8d
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/system/t8048_notri-c.vhd
@@ -0,0 +1,31 @@
+-------------------------------------------------------------------------------
+--
+-- T8048 Microcontroller System
+--
+-- $Id: t8048_notri-c.vhd,v 1.2 2006/06/21 01:02:16 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+configuration t8048_notri_struct_c0 of t8048_notri is
+
+ for struct
+
+ for rom_1k_b : t48_rom
+ use configuration work.t48_rom_lpm_c0;
+ end for;
+
+ for ram_64_b : generic_ram_ena
+ use configuration work.generic_ram_ena_rtl_c0;
+ end for;
+
+ for t48_core_b : t48_core
+ use configuration work.t48_core_struct_c0;
+ end for;
+
+ end for;
+
+end t8048_notri_struct_c0;
diff --git a/common/CPU/t48/rtl/vhdl/system/t8048_notri.vhd b/common/CPU/t48/rtl/vhdl/system/t8048_notri.vhd
new file mode 100644
index 00000000..891ba5a9
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/system/t8048_notri.vhd
@@ -0,0 +1,271 @@
+-------------------------------------------------------------------------------
+--
+-- T8048 Microcontroller System
+-- 8048 toplevel without tri-states
+--
+-- $Id: t8048_notri.vhd,v 1.7 2006/07/14 01:13:32 arniml Exp $
+-- $Name: $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity t8048_notri is
+
+ generic (
+ gate_port_input_g : integer := 1
+ );
+
+ port (
+ xtal_i : in std_logic;
+ xtal_en_i : in std_logic;
+ reset_n_i : in std_logic;
+ t0_i : in std_logic;
+ t0_o : out std_logic;
+ t0_dir_o : out std_logic;
+ int_n_i : in std_logic;
+ ea_i : in std_logic;
+ rd_n_o : out std_logic;
+ psen_n_o : out std_logic;
+ wr_n_o : out std_logic;
+ ale_o : out std_logic;
+ db_i : in std_logic_vector( 7 downto 0);
+ db_o : out std_logic_vector( 7 downto 0);
+ db_dir_o : out std_logic;
+ t1_i : in std_logic;
+ p2_i : in std_logic_vector( 7 downto 0);
+ p2_o : out std_logic_vector( 7 downto 0);
+ p2l_low_imp_o : out std_logic;
+ p2h_low_imp_o : out std_logic;
+ p1_i : in std_logic_vector( 7 downto 0);
+ p1_o : out std_logic_vector( 7 downto 0);
+ p1_low_imp_o : out std_logic;
+ prog_n_o : out std_logic
+ );
+
+end t8048_notri;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+use work.t48_core_comp_pack.t48_core;
+use work.t48_core_comp_pack.t48_rom;
+use work.t48_core_comp_pack.generic_ram_ena;
+
+architecture struct of t8048_notri is
+
+ -- Address width of internal ROM
+ constant rom_addr_width_c : natural := 10;
+
+ signal xtal3_s : std_logic;
+ signal dmem_addr_s : std_logic_vector( 7 downto 0);
+ signal dmem_we_s : std_logic;
+ signal dmem_data_from_s : std_logic_vector( 7 downto 0);
+ signal dmem_data_to_s : std_logic_vector( 7 downto 0);
+ signal pmem_addr_s : std_logic_vector(11 downto 0);
+ signal pmem_data_s : std_logic_vector( 7 downto 0);
+
+ signal ea_s : std_logic;
+
+ signal p1_in_s,
+ p1_out_s : std_logic_vector( 7 downto 0);
+ signal p2_in_s,
+ p2_out_s : std_logic_vector( 7 downto 0);
+
+ signal vdd_s : std_logic;
+
+begin
+
+ vdd_s <= '1';
+
+ -----------------------------------------------------------------------------
+ -- Check generics for valid values.
+ -----------------------------------------------------------------------------
+ -- pragma translate_off
+ assert gate_port_input_g = 0 or gate_port_input_g = 1
+ report "gate_port_input_g must be either 1 or 0!"
+ severity failure;
+ -- pragma translate_on
+
+
+ t48_core_b : t48_core
+ generic map (
+ xtal_div_3_g => 1,
+ register_mnemonic_g => 1,
+ include_port1_g => 1,
+ include_port2_g => 1,
+ include_bus_g => 1,
+ include_timer_g => 1,
+ sample_t1_state_g => 4
+ )
+ port map (
+ xtal_i => xtal_i,
+ xtal_en_i => xtal_en_i,
+ reset_i => reset_n_i,
+ t0_i => t0_i,
+ t0_o => t0_o,
+ t0_dir_o => t0_dir_o,
+ int_n_i => int_n_i,
+ ea_i => ea_s,
+ rd_n_o => rd_n_o,
+ psen_n_o => psen_n_o,
+ wr_n_o => wr_n_o,
+ ale_o => ale_o,
+ db_i => db_i,
+ db_o => db_o,
+ db_dir_o => db_dir_o,
+ t1_i => t1_i,
+ p2_i => p2_in_s,
+ p2_o => p2_out_s,
+ p2l_low_imp_o => p2l_low_imp_o,
+ p2h_low_imp_o => p2h_low_imp_o,
+ p1_i => p1_in_s,
+ p1_o => p1_out_s,
+ p1_low_imp_o => p1_low_imp_o,
+ prog_n_o => prog_n_o,
+ clk_i => xtal_i,
+ en_clk_i => xtal3_s,
+ xtal3_o => xtal3_s,
+ dmem_addr_o => dmem_addr_s,
+ dmem_we_o => dmem_we_s,
+ dmem_data_i => dmem_data_from_s,
+ dmem_data_o => dmem_data_to_s,
+ pmem_addr_o => pmem_addr_s,
+ pmem_data_i => pmem_data_s
+ );
+
+
+ -----------------------------------------------------------------------------
+ -- Gate port 1 and 2 input bus with respetive output value
+ -----------------------------------------------------------------------------
+ gate_ports: if gate_port_input_g = 1 generate
+ p1_in_s <= p1_i and p1_out_s;
+ p2_in_s <= p2_i and p2_out_s;
+ end generate;
+
+ pass_ports: if gate_port_input_g = 0 generate
+ p1_in_s <= p1_i;
+ p2_in_s <= p2_i;
+ end generate;
+
+ p1_o <= p1_out_s;
+ p2_o <= p2_out_s;
+
+
+ -----------------------------------------------------------------------------
+ -- Process ea
+ --
+ -- Purpose:
+ -- Detects access to external program memory.
+ -- Either by ea_i = '1' or when program memory address leaves address
+ -- range of internal ROM.
+ --
+ ea: process (ea_i,
+ pmem_addr_s)
+ begin
+ if ea_i = '1' then
+ -- Forced external access
+ ea_s <= '1';
+
+ elsif unsigned(pmem_addr_s(11 downto rom_addr_width_c)) = 0 then
+ -- Internal access
+ ea_s <= '0';
+
+ else
+ -- Access to program memory out of internal range
+ ea_s <= '1';
+
+ end if;
+
+ end process ea;
+ --
+ -----------------------------------------------------------------------------
+
+
+ rom_1k_b : t48_rom
+ port map (
+ clk_i => xtal_i,
+ rom_addr_i => pmem_addr_s(rom_addr_width_c-1 downto 0),
+ rom_data_o => pmem_data_s
+ );
+
+ ram_64_b : generic_ram_ena
+ generic map (
+ addr_width_g => 6,
+ data_width_g => 8
+ )
+ port map (
+ clk_i => xtal_i,
+ a_i => dmem_addr_s(5 downto 0),
+ we_i => dmem_we_s,
+ ena_i => vdd_s,
+ d_i => dmem_data_to_s,
+ d_o => dmem_data_from_s
+ );
+
+end struct;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: t8048_notri.vhd,v $
+-- Revision 1.7 2006/07/14 01:13:32 arniml
+-- name keyword added
+--
+-- Revision 1.6 2006/06/21 01:02:16 arniml
+-- replaced syn_rom and syn_ram with t48_rom and generic_ram_ena
+--
+-- Revision 1.5 2006/06/20 00:47:08 arniml
+-- new input xtal_en_i
+--
+-- Revision 1.4 2005/11/01 21:38:48 arniml
+-- wire signals for P2 low impedance marker issue
+--
+-- Revision 1.3 2004/12/02 22:08:42 arniml
+-- introduced generic gate_port_input_g
+-- forces masking of P1 and P2 input bus
+--
+-- Revision 1.2 2004/12/01 23:08:08 arniml
+-- update
+--
+-------------------------------------------------------------------------------
diff --git a/common/CPU/t48/rtl/vhdl/system/t8050_wb-c.vhd b/common/CPU/t48/rtl/vhdl/system/t8050_wb-c.vhd
new file mode 100644
index 00000000..1fe1ccc3
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/system/t8050_wb-c.vhd
@@ -0,0 +1,35 @@
+-------------------------------------------------------------------------------
+--
+-- T8048 Microcontroller System
+--
+-- $Id: t8050_wb-c.vhd,v 1.2 2005/06/11 10:19:14 arniml Exp $
+--
+-- Copyright (c) 2005, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+configuration t8050_wb_struct_c0 of t8050_wb is
+
+ for struct
+
+ for rom_4k_b : syn_rom
+ use configuration work.syn_rom_lpm_c0;
+ end for;
+
+ for ram_256_b : syn_ram
+ use configuration work.syn_ram_lpm_c0;
+ end for;
+
+ for wb_master_b : t48_wb_master
+ use configuration work.t48_wb_master_rtl_c0;
+ end for;
+
+ for t48_core_b : t48_core
+ use configuration work.t48_core_struct_c0;
+ end for;
+
+ end for;
+
+end t8050_wb_struct_c0;
diff --git a/common/CPU/t48/rtl/vhdl/system/t8050_wb.vhd b/common/CPU/t48/rtl/vhdl/system/t8050_wb.vhd
new file mode 100644
index 00000000..348db797
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/system/t8050_wb.vhd
@@ -0,0 +1,313 @@
+-------------------------------------------------------------------------------
+--
+-- T8048 Microcontroller System
+-- 8050 toplevel with Wishbone interface
+--
+-- $Id: t8050_wb.vhd,v 1.5 2006/07/14 01:14:22 arniml Exp $
+-- $Name: $
+--
+-- Copyright (c) 2005, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity t8050_wb is
+
+ generic (
+ gate_port_input_g : integer := 1
+ );
+
+ port (
+ -- T48 Interface ----------------------------------------------------------
+ xtal_i : in std_logic;
+ reset_n_i : in std_logic;
+ t0_i : in std_logic;
+ t0_o : out std_logic;
+ t0_dir_o : out std_logic;
+ int_n_i : in std_logic;
+ ea_i : in std_logic;
+ rd_n_o : out std_logic;
+ psen_n_o : out std_logic;
+ wr_n_o : out std_logic;
+ ale_o : out std_logic;
+ t1_i : in std_logic;
+ p2_i : in std_logic_vector( 7 downto 0);
+ p2_o : out std_logic_vector( 7 downto 0);
+ p2l_low_imp_o : out std_logic;
+ p2h_low_imp_o : out std_logic;
+ p1_i : in std_logic_vector( 7 downto 0);
+ p1_o : out std_logic_vector( 7 downto 0);
+ p1_low_imp_o : out std_logic;
+ prog_n_o : out std_logic;
+ -- Wishbone Interface -----------------------------------------------------
+ wb_cyc_o : out std_logic;
+ wb_stb_o : out std_logic;
+ wb_we_o : out std_logic;
+ wb_adr_o : out std_logic_vector(23 downto 0);
+ wb_ack_i : in std_logic;
+ wb_dat_i : in std_logic_vector( 7 downto 0);
+ wb_dat_o : out std_logic_vector( 7 downto 0)
+
+ );
+
+end t8050_wb;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+use work.t48_core_comp_pack.t48_core;
+use work.t48_core_comp_pack.syn_rom;
+use work.t48_core_comp_pack.syn_ram;
+use work.t48_system_comp_pack.t48_wb_master;
+
+architecture struct of t8050_wb is
+
+ -- Address width of internal ROM
+ constant rom_addr_width_c : natural := 12;
+
+ signal xtal3_s : std_logic;
+ signal dmem_addr_s : std_logic_vector( 7 downto 0);
+ signal dmem_we_s : std_logic;
+ signal dmem_data_from_s : std_logic_vector( 7 downto 0);
+ signal dmem_data_to_s : std_logic_vector( 7 downto 0);
+ signal pmem_addr_s : std_logic_vector(11 downto 0);
+ signal pmem_data_s : std_logic_vector( 7 downto 0);
+
+ signal ea_s : std_logic;
+
+ signal ale_s : std_logic;
+ signal wr_n_s : std_logic;
+ signal rd_n_s : std_logic;
+ signal db_bus_to_t48,
+ db_bus_from_t48 : std_logic_vector( 7 downto 0);
+
+ signal wb_en_clk_s : std_logic;
+ signal xtal_en_s : std_logic;
+
+ signal p1_in_s,
+ p1_out_s : std_logic_vector( 7 downto 0);
+ signal p2_in_s,
+ p2_out_s : std_logic_vector( 7 downto 0);
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Check generics for valid values.
+ -----------------------------------------------------------------------------
+ -- pragma translate_off
+ assert gate_port_input_g = 0 or gate_port_input_g = 1
+ report "gate_port_input_g must be either 1 or 0!"
+ severity failure;
+ -- pragma translate_on
+
+
+ t48_core_b : t48_core
+ generic map (
+ xtal_div_3_g => 1,
+ register_mnemonic_g => 1,
+ include_port1_g => 1,
+ include_port2_g => 1,
+ include_bus_g => 1,
+ include_timer_g => 1,
+ sample_t1_state_g => 4
+ )
+ port map (
+ xtal_i => xtal_i,
+ xtal_en_i => xtal_en_s,
+ reset_i => reset_n_i,
+ t0_i => t0_i,
+ t0_o => t0_o,
+ t0_dir_o => t0_dir_o,
+ int_n_i => int_n_i,
+ ea_i => ea_s,
+ rd_n_o => rd_n_s,
+ psen_n_o => psen_n_o,
+ wr_n_o => wr_n_s,
+ ale_o => ale_s,
+ db_i => db_bus_to_t48,
+ db_o => db_bus_from_t48,
+ db_dir_o => open,
+ t1_i => t1_i,
+ p2_i => p2_in_s,
+ p2_o => p2_out_s,
+ p2l_low_imp_o => p2l_low_imp_o,
+ p2h_low_imp_o => p2h_low_imp_o,
+ p1_i => p1_in_s,
+ p1_o => p1_out_s,
+ p1_low_imp_o => p1_low_imp_o,
+ prog_n_o => prog_n_o,
+ clk_i => xtal_i,
+ en_clk_i => xtal3_s,
+ xtal3_o => xtal3_s,
+ dmem_addr_o => dmem_addr_s,
+ dmem_we_o => dmem_we_s,
+ dmem_data_i => dmem_data_from_s,
+ dmem_data_o => dmem_data_to_s,
+ pmem_addr_o => pmem_addr_s,
+ pmem_data_i => pmem_data_s
+ );
+
+
+ -----------------------------------------------------------------------------
+ -- Gate port 1 and 2 input bus with respetive output value
+ -----------------------------------------------------------------------------
+ gate_ports: if gate_port_input_g = 1 generate
+ p1_in_s <= p1_i and p1_out_s;
+ p2_in_s <= p2_i and p2_out_s;
+ end generate;
+
+ pass_ports: if gate_port_input_g = 0 generate
+ p1_in_s <= p1_i;
+ p2_in_s <= p2_i;
+ end generate;
+
+ p1_o <= p1_out_s;
+ p2_o <= p2_out_s;
+
+ ale_o <= ale_s;
+ wr_n_o <= wr_n_s;
+ rd_n_o <= rd_n_s;
+
+
+ -----------------------------------------------------------------------------
+ -- Generate clock enable
+ -----------------------------------------------------------------------------
+ xtal_en_s <= wb_en_clk_s;
+
+
+ -----------------------------------------------------------------------------
+ -- Process ea
+ --
+ -- Purpose:
+ -- Detects access to external program memory.
+ -- Either by ea_i = '1' or when program memory address leaves address
+ -- range of internal ROM.
+ --
+ ea: process (ea_i,
+ pmem_addr_s)
+ begin
+ if ea_i = '1' then
+ -- Forced external access
+ ea_s <= '1';
+
+-- elsif unsigned(pmem_addr_s(11 downto rom_addr_width_c)) = 0 then
+ else
+ -- Internal access
+ ea_s <= '0';
+
+-- else
+-- -- Access to program memory out of internal range
+-- ea_s <= '1';
+
+ end if;
+
+ end process ea;
+ --
+ -----------------------------------------------------------------------------
+
+
+ wb_master_b : t48_wb_master
+ port map (
+ xtal_i => xtal_i,
+ res_i => reset_n_i,
+ en_clk_o => wb_en_clk_s,
+ ale_i => ale_s,
+ rd_n_i => rd_n_s,
+ wr_n_i => wr_n_s,
+ adr_i => p2_out_s(4),
+ db_bus_i => db_bus_from_t48,
+ db_bus_o => db_bus_to_t48,
+ wb_cyc_o => wb_cyc_o,
+ wb_stb_o => wb_stb_o,
+ wb_we_o => wb_we_o,
+ wb_adr_o => wb_adr_o,
+ wb_ack_i => wb_ack_i,
+ wb_dat_i => wb_dat_i,
+ wb_dat_o => wb_dat_o
+ );
+
+
+ rom_4k_b : syn_rom
+ generic map (
+ address_width_g => rom_addr_width_c
+ )
+ port map (
+ clk_i => xtal_i,
+ rom_addr_i => pmem_addr_s(rom_addr_width_c-1 downto 0),
+ rom_data_o => pmem_data_s
+ );
+
+ ram_256_b : syn_ram
+ generic map (
+ address_width_g => 8
+ )
+ port map (
+ clk_i => xtal_i,
+ res_i => reset_n_i,
+ ram_addr_i => dmem_addr_s(7 downto 0),
+ ram_data_i => dmem_data_to_s,
+ ram_we_i => dmem_we_s,
+ ram_data_o => dmem_data_from_s
+ );
+
+end struct;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: t8050_wb.vhd,v $
+-- Revision 1.5 2006/07/14 01:14:22 arniml
+-- name keyword added
+--
+-- Revision 1.4 2006/06/20 00:58:49 arniml
+-- new input xtal_en_i
+--
+-- Revision 1.3 2005/11/01 21:39:14 arniml
+-- wire signals for P2 low impedance marker issue
+--
+-- Revision 1.2 2005/06/11 10:16:05 arniml
+-- introduce prefix 't48_' for wb_master entity and configuration
+--
+-- Revision 1.1 2005/05/08 10:36:59 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/CPU/t48/rtl/vhdl/system/wb_master-c.vhd b/common/CPU/t48/rtl/vhdl/system/wb_master-c.vhd
new file mode 100644
index 00000000..89673ecb
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/system/wb_master-c.vhd
@@ -0,0 +1,18 @@
+-------------------------------------------------------------------------------
+--
+-- The Wishbone master module.
+--
+-- $Id: wb_master-c.vhd,v 1.2 2005/06/11 10:16:05 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+configuration t48_wb_master_rtl_c0 of t48_wb_master is
+
+ for rtl
+ end for;
+
+end t48_wb_master_rtl_c0;
diff --git a/common/CPU/t48/rtl/vhdl/system/wb_master.vhd b/common/CPU/t48/rtl/vhdl/system/wb_master.vhd
new file mode 100644
index 00000000..f1f6993e
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/system/wb_master.vhd
@@ -0,0 +1,274 @@
+-------------------------------------------------------------------------------
+--
+-- The Wishbone master module.
+--
+-- $Id: wb_master.vhd,v 1.5 2005/06/11 10:16:05 arniml Exp $
+--
+-- Copyright (c) 2005, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+--
+-- Short description:
+-- This design implements a simple Wishbone bus master. It connects to the
+-- BUS interface of the T48 uController core.
+--
+-- The CPU clock is suppressed with en_clk_o to stall the CPU until the
+-- acknowledge signal from the peripheral is detected.
+--
+-- The adr_i input selects between configuration and Wishbone address range:
+-- 1 - configuration range
+-- 0 - Wishbone range
+--
+-- When configuration range is selected, two address register are accessible.
+-- 000h -> adr1
+-- 001h -> adr2
+-- These registers can be read and written with movx to their addresses.
+--
+-- When Wishbone range is selected, all movx generate Wishbone bus cycles
+-- (either read or write) at following address:
+-- Wishbone address = adr2 & adr1 & address of movx
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.all;
+
+entity t48_wb_master is
+
+ port (
+ xtal_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_o : out std_logic;
+ -- T48 Interface ----------------------------------------------------------
+ ale_i : in std_logic;
+ rd_n_i : in std_logic;
+ wr_n_i : in std_logic;
+ adr_i : in std_logic;
+ db_bus_i : in std_logic_vector( 7 downto 0);
+ db_bus_o : out std_logic_vector( 7 downto 0);
+ -- Wishbone Interface -----------------------------------------------------
+ wb_cyc_o : out std_logic;
+ wb_stb_o : out std_logic;
+ wb_we_o : out std_logic;
+ wb_adr_o : out std_logic_vector(23 downto 0);
+ wb_ack_i : in std_logic;
+ wb_dat_i : in std_logic_vector( 7 downto 0);
+ wb_dat_o : out std_logic_vector( 7 downto 0)
+ );
+
+end t48_wb_master;
+
+
+architecture rtl of t48_wb_master is
+
+ -----------------------------------------------------------------------------
+ -- Controller FSM
+ -----------------------------------------------------------------------------
+ type state_t is (IDLE, CYC, WAIT_INACT);
+ signal state_s,
+ state_q : state_t;
+
+ -----------------------------------------------------------------------------
+ -- Select signals for each range
+ -----------------------------------------------------------------------------
+ signal sel_adr1_s,
+ sel_adr2_s,
+ sel_wb_s : boolean;
+
+ signal wr_s,
+ rd_s : boolean;
+
+ signal adr_q : std_logic_vector(23 downto 0);
+ signal wb_dat_q : std_logic_vector( 7 downto 0);
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Select signal generation
+ -----------------------------------------------------------------------------
+ sel_adr1_s <= adr_i = '1' and adr_q(word_t'range) = "00000000";
+ sel_adr2_s <= adr_i = '1' and adr_q(word_t'range) = "00000001";
+ sel_wb_s <= adr_i = '0';
+
+ wr_s <= wr_n_i = '0';
+ rd_s <= rd_n_i = '0';
+
+
+ -----------------------------------------------------------------------------
+ -- Process seq
+ --
+ -- Purpose:
+ -- Implements the sequential elements.
+ --
+ seq: process (res_i, xtal_i)
+ begin
+ if res_i = res_active_c then
+ adr_q <= (others => '0');
+ wb_dat_q <= (others => '0');
+ state_q <= IDLE;
+
+ elsif xtal_i'event and xtal_i = clk_active_c then
+ -- Address register -----------------------------------------------------
+ -- update lowest address byte
+ if ale_i = '1' then
+ adr_q(word_t'range) <= db_bus_i;
+ end if;
+ -- set adr1 part
+ if wr_s and sel_adr1_s then
+ adr_q(word_t'length*2 - 1 downto word_t'length) <= db_bus_i;
+ end if;
+ -- set adr2 part
+ if wr_s and sel_adr2_s then
+ adr_q(word_t'length*3 - 1 downto word_t'length*2) <= db_bus_i;
+ end if;
+
+ -- Data from peripheral has to be saved ---------------------------------
+ if wb_ack_i = '1' then
+ wb_dat_q <= wb_dat_i;
+ end if;
+
+ -- FSM state ------------------------------------------------------------
+ state_q <= state_s;
+
+ end if;
+ end process seq;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process fsm
+ --
+ -- Purpose:
+ -- Implements the state transitions of the controller FSM.
+ --
+ fsm: process (state_q,
+ wr_s,
+ rd_s,
+ sel_wb_s,
+ wb_ack_i)
+ begin
+ -- default assignments
+ wb_cyc_o <= '0';
+ wb_stb_o <= '0';
+ en_clk_o <= '1';
+ state_s <= IDLE;
+
+ case state_q is
+ -- Idle State: Wait for read or write access ----------------------------
+ when IDLE =>
+ if sel_wb_s and (wr_s or rd_s) then
+ state_s <= CYC;
+ end if;
+
+ -- WB Cycle State: Start Wishbone cycle and wait for ack ----------------
+ when CYC =>
+ wb_cyc_o <= '1';
+ wb_stb_o <= '1';
+ en_clk_o <= '0';
+
+ if wb_ack_i = '1' then
+ state_s <= WAIT_INACT;
+ else
+ state_s <= CYC;
+ end if;
+
+ -- Wait inact State: Wait for end of T48 access -------------------------
+ when WAIT_INACT =>
+ if not wr_s and not rd_s then
+ state_s <= IDLE;
+ else
+ state_s <= WAIT_INACT;
+ end if;
+
+ when others =>
+ null;
+
+ end case;
+
+ end process fsm;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Output multiplexer
+ -----------------------------------------------------------------------------
+ db_bus_o <= adr_q(word_t'length*2 - 1 downto word_t'length)
+ when sel_adr1_s else
+ adr_q(word_t'length*3 - 1 downto word_t'length*2)
+ when sel_adr2_s else
+ wb_dat_q;
+
+
+ -----------------------------------------------------------------------------
+ -- Output mapping
+ -----------------------------------------------------------------------------
+ wb_adr_o <= adr_q;
+ wb_dat_o <= db_bus_i;
+ wb_we_o <= '1'
+ when wr_s and sel_wb_s else
+ '0';
+
+end rtl;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: wb_master.vhd,v $
+-- Revision 1.5 2005/06/11 10:16:05 arniml
+-- introduce prefix 't48_' for wb_master entity and configuration
+--
+-- Revision 1.4 2005/05/10 22:36:23 arniml
+-- save data from wishbone bus in register bank with wb_ack
+-- necessary to hold data from peripheral/memory until it is read by T48
+--
+-- Revision 1.3 2005/05/08 10:36:07 arniml
+-- simplify address range:
+-- - configuration range
+-- - Wishbone range
+--
+-- Revision 1.2 2005/05/06 18:54:03 arniml
+-- assign default for state_s
+--
+-- Revision 1.1 2005/05/05 19:49:03 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/CPU/t48/rtl/vhdl/t48_comp_pack-p.vhd b/common/CPU/t48/rtl/vhdl/t48_comp_pack-p.vhd
new file mode 100644
index 00000000..6ac4ae5e
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/t48_comp_pack-p.vhd
@@ -0,0 +1,399 @@
+-------------------------------------------------------------------------------
+--
+-- $Id: t48_comp_pack-p.vhd,v 1.11 2006/06/20 00:46:04 arniml Exp $
+--
+-- Copyright (c) 2004, 2005, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_alu_pack.alu_op_t;
+use work.t48_cond_branch_pack.branch_conditions_t;
+use work.t48_cond_branch_pack.comp_value_t;
+use work.t48_decoder_pack.mnemonic_t;
+use work.t48_dmem_ctrl_pack.dmem_addr_ident_t;
+use work.t48_pmem_ctrl_pack.pmem_addr_ident_t;
+use work.t48_pack.dmem_addr_t;
+use work.t48_pack.pmem_addr_t;
+use work.t48_pack.mstate_t;
+use work.t48_pack.word_t;
+use work.t48_pack.nibble_t;
+
+package t48_comp_pack is
+
+ component t48_alu
+ port (
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ data_i : in word_t;
+ data_o : out word_t;
+ write_accu_i : in boolean;
+ write_shadow_i : in boolean;
+ write_temp_reg_i : in boolean;
+ read_alu_i : in boolean;
+ carry_i : in std_logic;
+ carry_o : out std_logic;
+ aux_carry_o : out std_logic;
+ alu_op_i : in alu_op_t;
+ use_carry_i : in boolean;
+ da_high_i : in boolean;
+ da_overflow_o : out boolean;
+ accu_low_i : in boolean;
+ p06_temp_reg_i : in boolean;
+ p60_temp_reg_i : in boolean
+ );
+ end component;
+
+ component t48_bus_mux
+ port (
+ alu_data_i : in word_t;
+ bus_data_i : in word_t;
+ dec_data_i : in word_t;
+ dm_data_i : in word_t;
+ pm_data_i : in word_t;
+ p1_data_i : in word_t;
+ p2_data_i : in word_t;
+ psw_data_i : in word_t;
+ tim_data_i : in word_t;
+ data_o : out word_t
+ );
+ end component;
+
+ component t48_clock_ctrl
+ generic (
+ xtal_div_3_g : integer := 1
+ );
+ port (
+ clk_i : in std_logic;
+ xtal_i : in std_logic;
+ xtal_en_i : in boolean;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ xtal3_o : out boolean;
+ t0_o : out std_logic;
+ multi_cycle_i : in boolean;
+ assert_psen_i : in boolean;
+ assert_prog_i : in boolean;
+ assert_rd_i : in boolean;
+ assert_wr_i : in boolean;
+ mstate_o : out mstate_t;
+ second_cycle_o : out boolean;
+ ale_o : out boolean;
+ psen_o : out boolean;
+ prog_o : out boolean;
+ rd_o : out boolean;
+ wr_o : out boolean
+ );
+ end component;
+
+ component t48_cond_branch
+ port (
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ compute_take_i : in boolean;
+ branch_cond_i : in branch_conditions_t;
+ take_branch_o : out boolean;
+ accu_i : in word_t;
+ t0_i : in std_logic;
+ t1_i : in std_logic;
+ int_n_i : in std_logic;
+ f0_i : in std_logic;
+ f1_i : in std_logic;
+ tf_i : in std_logic;
+ carry_i : in std_logic;
+ comp_value_i : in comp_value_t
+ );
+ end component;
+
+ component t48_db_bus
+ port (
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ ea_i : in std_logic;
+ data_i : in word_t;
+ data_o : out word_t;
+ write_bus_i : in boolean;
+ read_bus_i : in boolean;
+ output_pcl_i : in boolean;
+ bidir_bus_i : in boolean;
+ pcl_i : in word_t;
+ db_i : in word_t;
+ db_o : out word_t;
+ db_dir_o : out std_logic
+ );
+ end component;
+
+ component t48_decoder
+ generic (
+ register_mnemonic_g : integer := 1
+ );
+ port (
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ xtal_i : in std_logic;
+ xtal_en_i : in boolean;
+ ea_i : in std_logic;
+ ale_i : in boolean;
+ int_n_i : in std_logic;
+ t0_dir_o : out std_logic;
+ data_i : in word_t;
+ data_o : out word_t;
+ alu_write_accu_o : out boolean;
+ alu_write_shadow_o : out boolean;
+ alu_write_temp_reg_o : out boolean;
+ alu_read_alu_o : out boolean;
+ bus_write_bus_o : out boolean;
+ bus_read_bus_o : out boolean;
+ dm_write_dmem_addr_o : out boolean;
+ dm_write_dmem_o : out boolean;
+ dm_read_dmem_o : out boolean;
+ p1_write_p1_o : out boolean;
+ p1_read_p1_o : out boolean;
+ p2_write_p2_o : out boolean;
+ p2_write_exp_o : out boolean;
+ p2_read_p2_o : out boolean;
+ pm_write_pcl_o : out boolean;
+ pm_read_pcl_o : out boolean;
+ pm_write_pch_o : out boolean;
+ pm_read_pch_o : out boolean;
+ pm_read_pmem_o : out boolean;
+ psw_read_psw_o : out boolean;
+ psw_read_sp_o : out boolean;
+ psw_write_psw_o : out boolean;
+ psw_write_sp_o : out boolean;
+ alu_carry_i : in std_logic;
+ alu_op_o : out alu_op_t;
+ alu_da_high_o : out boolean;
+ alu_accu_low_o : out boolean;
+ alu_da_overflow_i : in boolean;
+ alu_p06_temp_reg_o : out boolean;
+ alu_p60_temp_reg_o : out boolean;
+ alu_use_carry_o : out boolean;
+ bus_output_pcl_o : out boolean;
+ bus_bidir_bus_o : out boolean;
+ clk_multi_cycle_o : out boolean;
+ clk_assert_psen_o : out boolean;
+ clk_assert_prog_o : out boolean;
+ clk_assert_rd_o : out boolean;
+ clk_assert_wr_o : out boolean;
+ clk_mstate_i : in mstate_t;
+ clk_second_cycle_i : in boolean;
+ cnd_compute_take_o : out boolean;
+ cnd_branch_cond_o : out branch_conditions_t;
+ cnd_take_branch_i : in boolean;
+ cnd_comp_value_o : out comp_value_t;
+ cnd_f1_o : out std_logic;
+ cnd_tf_o : out std_logic;
+ dm_addr_type_o : out dmem_addr_ident_t;
+ tim_read_timer_o : out boolean;
+ tim_write_timer_o : out boolean;
+ tim_start_t_o : out boolean;
+ tim_start_cnt_o : out boolean;
+ tim_stop_tcnt_o : out boolean;
+ p1_read_reg_o : out boolean;
+ p2_read_reg_o : out boolean;
+ p2_read_exp_o : out boolean;
+ p2_output_pch_o : out boolean;
+ pm_inc_pc_o : out boolean;
+ pm_write_pmem_addr_o : out boolean;
+ pm_addr_type_o : out pmem_addr_ident_t;
+ psw_special_data_o : out std_logic;
+ psw_carry_i : in std_logic;
+ psw_aux_carry_i : in std_logic;
+ psw_f0_i : in std_logic;
+ psw_inc_stackp_o : out boolean;
+ psw_dec_stackp_o : out boolean;
+ psw_write_carry_o : out boolean;
+ psw_write_aux_carry_o : out boolean;
+ psw_write_f0_o : out boolean;
+ psw_write_bs_o : out boolean;
+ tim_overflow_i : in boolean
+ );
+ end component;
+
+ component t48_dmem_ctrl
+ port (
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ data_i : in word_t;
+ write_dmem_addr_i : in boolean;
+ write_dmem_i : in boolean;
+ read_dmem_i : in boolean;
+ addr_type_i : in dmem_addr_ident_t;
+ bank_select_i : in std_logic;
+ data_o : out word_t;
+ dmem_data_i : in word_t;
+ dmem_addr_o : out dmem_addr_t;
+ dmem_we_o : out std_logic;
+ dmem_data_o : out word_t
+ );
+ end component;
+
+ component t48_int
+ port (
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ xtal_i : in std_logic;
+ xtal_en_i : in boolean;
+ clk_mstate_i : in mstate_t;
+ jtf_executed_i : in boolean;
+ tim_overflow_i : in boolean;
+ tf_o : out std_logic;
+ en_tcnti_i : in boolean;
+ dis_tcnti_i : in boolean;
+ int_n_i : in std_logic;
+ ale_i : in boolean;
+ last_cycle_i : in boolean;
+ en_i_i : in boolean;
+ dis_i_i : in boolean;
+ ext_int_o : out boolean;
+ tim_int_o : out boolean;
+ retr_executed_i : in boolean;
+ int_executed_i : in boolean;
+ int_pending_o : out boolean;
+ int_in_progress_o : out boolean
+ );
+ end component;
+
+ component t48_opc_table
+ port (
+ opcode_i : in word_t;
+ multi_cycle_o : out std_logic;
+ mnemonic_o : out mnemonic_t
+ );
+ end component;
+
+ component t48_opc_decoder
+ generic (
+ register_mnemonic_g : integer := 1
+ );
+ port (
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ data_i : in word_t;
+ read_bus_i : in boolean;
+ inj_int_i : in boolean;
+ opcode_o : out word_t;
+ mnemonic_o : out mnemonic_t;
+ multi_cycle_o : out boolean
+ );
+ end component;
+
+ component t48_timer
+ generic (
+ sample_t1_state_g : integer := 4
+ );
+ port (
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ t1_i : in std_logic;
+ clk_mstate_i : in mstate_t;
+ data_i : in word_t;
+ data_o : out word_t;
+ read_timer_i : in boolean;
+ write_timer_i : in boolean;
+ start_t_i : in boolean;
+ start_cnt_i : in boolean;
+ stop_tcnt_i : in boolean;
+ overflow_o : out std_logic
+ );
+ end component;
+
+ component t48_p1
+ port (
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ data_i : in word_t;
+ data_o : out word_t;
+ write_p1_i : in boolean;
+ read_p1_i : in boolean;
+ read_reg_i : in boolean;
+ p1_i : in word_t;
+ p1_o : out word_t;
+ p1_low_imp_o : out std_logic
+ );
+ end component;
+
+ component t48_p2
+ port (
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ xtal_i : in std_logic;
+ xtal_en_i : in boolean;
+ data_i : in word_t;
+ data_o : out word_t;
+ write_p2_i : in boolean;
+ write_exp_i : in boolean;
+ read_p2_i : in boolean;
+ read_reg_i : in boolean;
+ read_exp_i : in boolean;
+ output_pch_i : in boolean;
+ pch_i : in nibble_t;
+ p2_i : in word_t;
+ p2_o : out word_t;
+ p2l_low_imp_o : out std_logic;
+ p2h_low_imp_o : out std_logic
+ );
+ end component;
+
+ component t48_pmem_ctrl
+ port (
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ data_i : in word_t;
+ data_o : out word_t;
+ write_pcl_i : in boolean;
+ read_pcl_i : in boolean;
+ write_pch_i : in boolean;
+ read_pch_i : in boolean;
+ inc_pc_i : in boolean;
+ write_pmem_addr_i : in boolean;
+ addr_type_i : in pmem_addr_ident_t;
+ read_pmem_i : in boolean;
+ pmem_addr_o : out pmem_addr_t;
+ pmem_data_i : in word_t
+ );
+ end component;
+
+ component t48_psw
+ port (
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ data_i : in word_t;
+ data_o : out word_t;
+ read_psw_i : in boolean;
+ read_sp_i : in boolean;
+ write_psw_i : in boolean;
+ write_sp_i : in boolean;
+ special_data_i : in std_logic;
+ inc_stackp_i : in boolean;
+ dec_stackp_i : in boolean;
+ write_carry_i : in boolean;
+ write_aux_carry_i : in boolean;
+ write_f0_i : in boolean;
+ write_bs_i : in boolean;
+ carry_o : out std_logic;
+ aux_carry_i : in std_logic;
+ aux_carry_o : out std_logic;
+ f0_o : out std_logic;
+ bs_o : out std_logic
+ );
+ end component;
+
+end t48_comp_pack;
diff --git a/common/CPU/t48/rtl/vhdl/t48_core-c.vhd b/common/CPU/t48/rtl/vhdl/t48_core-c.vhd
new file mode 100644
index 00000000..8f0d3595
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/t48_core-c.vhd
@@ -0,0 +1,71 @@
+-------------------------------------------------------------------------------
+--
+-- T48 Microcontroller Core
+--
+-- $Id: t48_core-c.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $
+--
+-------------------------------------------------------------------------------
+
+configuration t48_core_struct_c0 of t48_core is
+
+ for struct
+
+ for alu_b : t48_alu
+ use configuration work.t48_alu_rtl_c0;
+ end for;
+
+ for bus_mux_b : t48_bus_mux
+ use configuration work.t48_bus_mux_rtl_c0;
+ end for;
+
+ for clock_ctrl_b : t48_clock_ctrl
+ use configuration work.t48_clock_ctrl_rtl_c0;
+ end for;
+
+ for cond_branch_b : t48_cond_branch
+ use configuration work.t48_cond_branch_rtl_c0;
+ end for;
+
+ for use_db_bus
+ for db_bus_b : t48_db_bus
+ use configuration work.t48_db_bus_rtl_c0;
+ end for;
+ end for;
+
+ for decoder_b : t48_decoder
+ use configuration work.t48_decoder_rtl_c0;
+ end for;
+
+ for dmem_ctrl_b : t48_dmem_ctrl
+ use configuration work.t48_dmem_ctrl_rtl_c0;
+ end for;
+
+ for use_timer
+ for timer_b : t48_timer
+ use configuration work.t48_timer_rtl_c0;
+ end for;
+ end for;
+
+ for use_p1
+ for p1_b : t48_p1
+ use configuration work.t48_p1_rtl_c0;
+ end for;
+ end for;
+
+ for use_p2
+ for p2_b : t48_p2
+ use configuration work.t48_p2_rtl_c0;
+ end for;
+ end for;
+
+ for pmem_ctrl_b : t48_pmem_ctrl
+ use configuration work.t48_pmem_ctrl_rtl_c0;
+ end for;
+
+ for psw_b : t48_psw
+ use configuration work.t48_psw_rtl_c0;
+ end for;
+
+ end for;
+
+end t48_core_struct_c0;
diff --git a/common/CPU/t48/rtl/vhdl/t48_core.vhd b/common/CPU/t48/rtl/vhdl/t48_core.vhd
new file mode 100644
index 00000000..b1b1cb33
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/t48_core.vhd
@@ -0,0 +1,680 @@
+-------------------------------------------------------------------------------
+--
+-- T48 Microcontroller Core
+--
+-- $Id: t48_core.vhd,v 1.12 2006/07/14 01:12:08 arniml Exp $
+-- $Name: $
+--
+-- Copyright (c) 2004, 2005, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-- Limitations :
+-- =============
+--
+-- Compared to the original MCS-48 architecture, the following limitations
+-- apply:
+--
+-- * Single-step mode not implemented.
+-- Not selected for future implementation.
+--
+-- * Reading of internal Program Memory not implemented.
+-- Not selected for future implementation.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity t48_core is
+
+ generic (
+ -- divide XTAL1 by 3 to derive Clock States
+ xtal_div_3_g : integer := 1;
+ -- store mnemonic in flip-flops (registered-out)
+ register_mnemonic_g : integer := 1;
+ -- include the port 1 module
+ include_port1_g : integer := 1;
+ -- include the port 2 module
+ include_port2_g : integer := 1;
+ -- include the BUS module
+ include_bus_g : integer := 1;
+ -- include the timer module
+ include_timer_g : integer := 1;
+ -- state in which T1 is sampled (3 or 4)
+ sample_t1_state_g : integer := 4
+ );
+
+ port (
+ -- T48 Interface ----------------------------------------------------------
+ xtal_i : in std_logic;
+ xtal_en_i : in std_logic;
+ reset_i : in std_logic;
+ t0_i : in std_logic;
+ t0_o : out std_logic;
+ t0_dir_o : out std_logic;
+ int_n_i : in std_logic;
+ ea_i : in std_logic;
+ rd_n_o : out std_logic;
+ psen_n_o : out std_logic;
+ wr_n_o : out std_logic;
+ ale_o : out std_logic;
+ db_i : in std_logic_vector( 7 downto 0);
+ db_o : out std_logic_vector( 7 downto 0);
+ db_dir_o : out std_logic;
+ t1_i : in std_logic;
+ p2_i : in std_logic_vector( 7 downto 0);
+ p2_o : out std_logic_vector( 7 downto 0);
+ p2l_low_imp_o : out std_logic;
+ p2h_low_imp_o : out std_logic;
+ p1_i : in std_logic_vector( 7 downto 0);
+ p1_o : out std_logic_vector( 7 downto 0);
+ p1_low_imp_o : out std_logic;
+ prog_n_o : out std_logic;
+ -- Core Interface ---------------------------------------------------------
+ clk_i : in std_logic;
+ en_clk_i : in std_logic;
+ xtal3_o : out std_logic;
+ dmem_addr_o : out std_logic_vector( 7 downto 0);
+ dmem_we_o : out std_logic;
+ dmem_data_i : in std_logic_vector( 7 downto 0);
+ dmem_data_o : out std_logic_vector( 7 downto 0);
+ pmem_addr_o : out std_logic_vector(11 downto 0);
+ pmem_data_i : in std_logic_vector( 7 downto 0)
+ );
+
+end t48_core;
+
+
+use work.t48_alu_pack.alu_op_t;
+use work.t48_cond_branch_pack.branch_conditions_t;
+use work.t48_cond_branch_pack.comp_value_t;
+use work.t48_dmem_ctrl_pack.dmem_addr_ident_t;
+use work.t48_pmem_ctrl_pack.pmem_addr_ident_t;
+use work.t48_comp_pack.all;
+use work.t48_pack.bus_idle_level_c;
+use work.t48_pack.word_t;
+use work.t48_pack.pmem_addr_t;
+use work.t48_pack.mstate_t;
+use work.t48_pack.to_stdLogic;
+use work.t48_pack.to_boolean;
+
+architecture struct of t48_core is
+
+ signal t48_data_s : word_t;
+
+ signal xtal_en_s : boolean;
+ signal en_clk_s : boolean;
+
+ -- ALU signals
+ signal alu_data_s : word_t;
+ signal alu_write_accu_s : boolean;
+ signal alu_write_shadow_s : boolean;
+ signal alu_write_temp_reg_s : boolean;
+ signal alu_read_alu_s : boolean;
+ signal alu_carry_s : std_logic;
+ signal alu_aux_carry_s : std_logic;
+ signal alu_op_s : alu_op_t;
+ signal alu_use_carry_s : boolean;
+ signal alu_da_high_s : boolean;
+ signal alu_da_overflow_s : boolean;
+ signal alu_accu_low_s : boolean;
+ signal alu_p06_temp_reg_s : boolean;
+ signal alu_p60_temp_reg_s : boolean;
+
+ -- BUS signals
+ signal bus_write_bus_s : boolean;
+ signal bus_read_bus_s : boolean;
+ signal bus_output_pcl_s : boolean;
+ signal bus_bidir_bus_s : boolean;
+ signal bus_data_s : word_t;
+
+ -- Clock Controller signals
+ signal clk_multi_cycle_s : boolean;
+ signal clk_assert_psen_s : boolean;
+ signal clk_assert_prog_s : boolean;
+ signal clk_assert_rd_s : boolean;
+ signal clk_assert_wr_s : boolean;
+ signal clk_mstate_s : mstate_t;
+ signal clk_second_cycle_s : boolean;
+ signal psen_s : boolean;
+ signal prog_s : boolean;
+ signal rd_s : boolean;
+ signal wr_s : boolean;
+ signal ale_s : boolean;
+ signal xtal3_s : boolean;
+
+ -- Conditional Branch Logic signals
+ signal cnd_compute_take_s : boolean;
+ signal cnd_branch_cond_s : branch_conditions_t;
+ signal cnd_take_branch_s : boolean;
+ signal cnd_comp_value_s : comp_value_t;
+ signal cnd_f1_s : std_logic;
+ signal cnd_tf_s : std_logic;
+
+ -- Data Memory Controller signals
+ signal dm_write_dmem_addr_s : boolean;
+ signal dm_write_dmem_s : boolean;
+ signal dm_read_dmem_s : boolean;
+ signal dm_addr_type_s : dmem_addr_ident_t;
+ signal dm_data_s : word_t;
+
+ -- Decoder signals
+ signal dec_data_s : word_t;
+
+ -- Port 1 signals
+ signal p1_write_p1_s : boolean;
+ signal p1_read_p1_s : boolean;
+ signal p1_read_reg_s : boolean;
+ signal p1_data_s : word_t;
+
+ -- Port 2 signals
+ signal p2_write_p2_s : boolean;
+ signal p2_write_exp_s : boolean;
+ signal p2_read_p2_s : boolean;
+ signal p2_read_reg_s : boolean;
+ signal p2_read_exp_s : boolean;
+ signal p2_output_pch_s : boolean;
+ signal p2_data_s : word_t;
+
+ -- Program Memory Controller signals
+ signal pm_write_pcl_s : boolean;
+ signal pm_read_pcl_s : boolean;
+ signal pm_write_pch_s : boolean;
+ signal pm_read_pch_s : boolean;
+ signal pm_read_pmem_s : boolean;
+ signal pm_inc_pc_s : boolean;
+ signal pm_write_pmem_addr_s : boolean;
+ signal pm_data_s : word_t;
+ signal pm_addr_type_s : pmem_addr_ident_t;
+ signal pmem_addr_s : pmem_addr_t;
+
+ -- PSW signals
+ signal psw_read_psw_s : boolean;
+ signal psw_read_sp_s : boolean;
+ signal psw_write_psw_s : boolean;
+ signal psw_write_sp_s : boolean;
+ signal psw_carry_s : std_logic;
+ signal psw_aux_carry_s : std_logic;
+ signal psw_f0_s : std_logic;
+ signal psw_bs_s : std_logic;
+ signal psw_special_data_s : std_logic;
+ signal psw_inc_stackp_s : boolean;
+ signal psw_dec_stackp_s : boolean;
+ signal psw_write_carry_s : boolean;
+ signal psw_write_aux_carry_s : boolean;
+ signal psw_write_f0_s : boolean;
+ signal psw_write_bs_s : boolean;
+ signal psw_data_s : word_t;
+
+ -- Timer signals
+ signal tim_overflow_s : boolean;
+ signal tim_of_s : std_logic;
+ signal tim_read_timer_s : boolean;
+ signal tim_write_timer_s : boolean;
+ signal tim_start_t_s : boolean;
+ signal tim_start_cnt_s : boolean;
+ signal tim_stop_tcnt_s : boolean;
+ signal tim_data_s : word_t;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Check generics for valid values.
+ -----------------------------------------------------------------------------
+ -- pragma translate_off
+ assert include_timer_g = 0 or include_timer_g = 1
+ report "include_timer_g must be either 1 or 0!"
+ severity failure;
+
+ assert include_port1_g = 0 or include_port1_g = 1
+ report "include_port1_g must be either 1 or 0!"
+ severity failure;
+
+ assert include_port2_g = 0 or include_port2_g = 1
+ report "include_port2_g must be either 1 or 0!"
+ severity failure;
+
+ assert include_bus_g = 0 or include_bus_g = 1
+ report "include_bus_g must be either 1 or 0!"
+ severity failure;
+ -- pragma translate_on
+
+
+ xtal_en_s <= to_boolean(xtal_en_i);
+ en_clk_s <= to_boolean(en_clk_i);
+
+ alu_b : t48_alu
+ port map (
+ clk_i => clk_i,
+ res_i => reset_i,
+ en_clk_i => en_clk_s,
+ data_i => t48_data_s,
+ data_o => alu_data_s,
+ write_accu_i => alu_write_accu_s,
+ write_shadow_i => alu_write_shadow_s,
+ write_temp_reg_i => alu_write_temp_reg_s,
+ read_alu_i => alu_read_alu_s,
+ carry_i => psw_carry_s,
+ carry_o => alu_carry_s,
+ aux_carry_o => alu_aux_carry_s,
+ alu_op_i => alu_op_s,
+ use_carry_i => alu_use_carry_s,
+ da_high_i => alu_da_high_s,
+ da_overflow_o => alu_da_overflow_s,
+ accu_low_i => alu_accu_low_s,
+ p06_temp_reg_i => alu_p06_temp_reg_s,
+ p60_temp_reg_i => alu_p60_temp_reg_s
+ );
+
+ bus_mux_b : t48_bus_mux
+ port map (
+ alu_data_i => alu_data_s,
+ bus_data_i => bus_data_s,
+ dec_data_i => dec_data_s,
+ dm_data_i => dm_data_s,
+ pm_data_i => pm_data_s,
+ p1_data_i => p1_data_s,
+ p2_data_i => p2_data_s,
+ psw_data_i => psw_data_s,
+ tim_data_i => tim_data_s,
+ data_o => t48_data_s
+ );
+
+ clock_ctrl_b : t48_clock_ctrl
+ generic map (
+ xtal_div_3_g => xtal_div_3_g
+ )
+ port map (
+ clk_i => clk_i,
+ xtal_i => xtal_i,
+ xtal_en_i => xtal_en_s,
+ res_i => reset_i,
+ en_clk_i => en_clk_s,
+ xtal3_o => xtal3_s,
+ t0_o => t0_o,
+ multi_cycle_i => clk_multi_cycle_s,
+ assert_psen_i => clk_assert_psen_s,
+ assert_prog_i => clk_assert_prog_s,
+ assert_rd_i => clk_assert_rd_s,
+ assert_wr_i => clk_assert_wr_s,
+ mstate_o => clk_mstate_s,
+ second_cycle_o => clk_second_cycle_s,
+ ale_o => ale_s,
+ psen_o => psen_s,
+ prog_o => prog_s,
+ rd_o => rd_s,
+ wr_o => wr_s
+ );
+
+ cond_branch_b : t48_cond_branch
+ port map (
+ clk_i => clk_i,
+ res_i => reset_i,
+ en_clk_i => en_clk_s,
+ compute_take_i => cnd_compute_take_s,
+ branch_cond_i => cnd_branch_cond_s,
+ take_branch_o => cnd_take_branch_s,
+ accu_i => alu_data_s,
+ t0_i => To_X01Z(t0_i),
+ t1_i => To_X01Z(t1_i),
+ int_n_i => int_n_i,
+ f0_i => psw_f0_s,
+ f1_i => cnd_f1_s,
+ tf_i => cnd_tf_s,
+ carry_i => psw_carry_s,
+ comp_value_i => cnd_comp_value_s
+ );
+
+ use_db_bus: if include_bus_g = 1 generate
+ db_bus_b : t48_db_bus
+ port map (
+ clk_i => clk_i,
+ res_i => reset_i,
+ en_clk_i => en_clk_s,
+ ea_i => ea_i,
+ data_i => t48_data_s,
+ data_o => bus_data_s,
+ write_bus_i => bus_write_bus_s,
+ read_bus_i => bus_read_bus_s,
+ output_pcl_i => bus_output_pcl_s,
+ bidir_bus_i => bus_bidir_bus_s,
+ pcl_i => pmem_addr_s(word_t'range),
+ db_i => db_i,
+ db_o => db_o,
+ db_dir_o => db_dir_o
+ );
+ end generate;
+
+ skip_db_bus: if include_bus_g = 0 generate
+ bus_data_s <= (others => bus_idle_level_c);
+ db_o <= (others => '0');
+ db_dir_o <= '0';
+ end generate;
+
+ decoder_b : t48_decoder
+ generic map (
+ register_mnemonic_g => register_mnemonic_g
+ )
+ port map (
+ clk_i => clk_i,
+ res_i => reset_i,
+ en_clk_i => en_clk_s,
+ xtal_i => xtal_i,
+ xtal_en_i => xtal_en_s,
+ ea_i => ea_i,
+ ale_i => ale_s,
+ int_n_i => int_n_i,
+ t0_dir_o => t0_dir_o,
+ data_i => t48_data_s,
+ data_o => dec_data_s,
+ alu_write_accu_o => alu_write_accu_s,
+ alu_write_shadow_o => alu_write_shadow_s,
+ alu_write_temp_reg_o => alu_write_temp_reg_s,
+ alu_read_alu_o => alu_read_alu_s,
+ bus_write_bus_o => bus_write_bus_s,
+ bus_read_bus_o => bus_read_bus_s,
+ dm_write_dmem_addr_o => dm_write_dmem_addr_s,
+ dm_write_dmem_o => dm_write_dmem_s,
+ dm_read_dmem_o => dm_read_dmem_s,
+ p1_write_p1_o => p1_write_p1_s,
+ p1_read_p1_o => p1_read_p1_s,
+ pm_write_pcl_o => pm_write_pcl_s,
+ p2_write_p2_o => p2_write_p2_s,
+ p2_write_exp_o => p2_write_exp_s,
+ p2_read_p2_o => p2_read_p2_s,
+ pm_read_pcl_o => pm_read_pcl_s,
+ pm_write_pch_o => pm_write_pch_s,
+ pm_read_pch_o => pm_read_pch_s,
+ pm_read_pmem_o => pm_read_pmem_s,
+ psw_read_psw_o => psw_read_psw_s,
+ psw_read_sp_o => psw_read_sp_s,
+ psw_write_psw_o => psw_write_psw_s,
+ psw_write_sp_o => psw_write_sp_s,
+ alu_carry_i => alu_carry_s,
+ alu_op_o => alu_op_s,
+ alu_use_carry_o => alu_use_carry_s,
+ alu_da_high_o => alu_da_high_s,
+ alu_da_overflow_i => alu_da_overflow_s,
+ alu_accu_low_o => alu_accu_low_s,
+ alu_p06_temp_reg_o => alu_p06_temp_reg_s,
+ alu_p60_temp_reg_o => alu_p60_temp_reg_s,
+ bus_output_pcl_o => bus_output_pcl_s,
+ bus_bidir_bus_o => bus_bidir_bus_s,
+ clk_multi_cycle_o => clk_multi_cycle_s,
+ clk_assert_psen_o => clk_assert_psen_s,
+ clk_assert_prog_o => clk_assert_prog_s,
+ clk_assert_rd_o => clk_assert_rd_s,
+ clk_assert_wr_o => clk_assert_wr_s,
+ clk_mstate_i => clk_mstate_s,
+ clk_second_cycle_i => clk_second_cycle_s,
+ cnd_compute_take_o => cnd_compute_take_s,
+ cnd_branch_cond_o => cnd_branch_cond_s,
+ cnd_take_branch_i => cnd_take_branch_s,
+ cnd_comp_value_o => cnd_comp_value_s,
+ cnd_f1_o => cnd_f1_s,
+ cnd_tf_o => cnd_tf_s,
+ dm_addr_type_o => dm_addr_type_s,
+ tim_read_timer_o => tim_read_timer_s,
+ tim_write_timer_o => tim_write_timer_s,
+ tim_start_t_o => tim_start_t_s,
+ tim_start_cnt_o => tim_start_cnt_s,
+ tim_stop_tcnt_o => tim_stop_tcnt_s,
+ p1_read_reg_o => p1_read_reg_s,
+ p2_read_reg_o => p2_read_reg_s,
+ p2_read_exp_o => p2_read_exp_s,
+ p2_output_pch_o => p2_output_pch_s,
+ pm_inc_pc_o => pm_inc_pc_s,
+ pm_write_pmem_addr_o => pm_write_pmem_addr_s,
+ pm_addr_type_o => pm_addr_type_s,
+ psw_special_data_o => psw_special_data_s,
+ psw_carry_i => psw_carry_s,
+ psw_aux_carry_i => psw_aux_carry_s,
+ psw_f0_i => psw_f0_s,
+ psw_inc_stackp_o => psw_inc_stackp_s,
+ psw_dec_stackp_o => psw_dec_stackp_s,
+ psw_write_carry_o => psw_write_carry_s,
+ psw_write_aux_carry_o => psw_write_aux_carry_s,
+ psw_write_f0_o => psw_write_f0_s,
+ psw_write_bs_o => psw_write_bs_s,
+ tim_overflow_i => tim_overflow_s
+ );
+
+ dmem_ctrl_b : t48_dmem_ctrl
+ port map (
+ clk_i => clk_i,
+ res_i => reset_i,
+ en_clk_i => en_clk_s,
+ data_i => t48_data_s,
+ write_dmem_addr_i => dm_write_dmem_addr_s,
+ write_dmem_i => dm_write_dmem_s,
+ read_dmem_i => dm_read_dmem_s,
+ addr_type_i => dm_addr_type_s,
+ bank_select_i => psw_bs_s,
+ data_o => dm_data_s,
+ dmem_data_i => dmem_data_i,
+ dmem_addr_o => dmem_addr_o,
+ dmem_we_o => dmem_we_o,
+ dmem_data_o => dmem_data_o
+ );
+
+ use_timer: if include_timer_g = 1 generate
+ timer_b : t48_timer
+ generic map (
+ sample_t1_state_g => sample_t1_state_g
+ )
+ port map (
+ clk_i => clk_i,
+ res_i => reset_i,
+ en_clk_i => en_clk_s,
+ t1_i => To_X01Z(t1_i),
+ clk_mstate_i => clk_mstate_s,
+ data_i => t48_data_s,
+ data_o => tim_data_s,
+ read_timer_i => tim_read_timer_s,
+ write_timer_i => tim_write_timer_s,
+ start_t_i => tim_start_t_s,
+ start_cnt_i => tim_start_cnt_s,
+ stop_tcnt_i => tim_stop_tcnt_s,
+ overflow_o => tim_of_s
+ );
+ end generate;
+
+ skip_timer: if include_timer_g = 0 generate
+ tim_data_s <= (others => bus_idle_level_c);
+ tim_of_s <= '0';
+ end generate;
+
+ tim_overflow_s <= to_boolean(tim_of_s);
+
+ use_p1: if include_port1_g = 1 generate
+ p1_b : t48_p1
+ port map (
+ clk_i => clk_i,
+ res_i => reset_i,
+ en_clk_i => en_clk_s,
+ data_i => t48_data_s,
+ data_o => p1_data_s,
+ write_p1_i => p1_write_p1_s,
+ read_p1_i => p1_read_p1_s,
+ read_reg_i => p1_read_reg_s,
+ p1_i => p1_i,
+ p1_o => p1_o,
+ p1_low_imp_o => p1_low_imp_o
+ );
+ end generate;
+
+ skip_p1: if include_port1_g = 0 generate
+ p1_data_s <= (others => bus_idle_level_c);
+ p1_o <= (others => '0');
+ p1_low_imp_o <= '0';
+ end generate;
+
+ use_p2: if include_port2_g = 1 generate
+ p2_b : t48_p2
+ port map (
+ clk_i => clk_i,
+ res_i => reset_i,
+ en_clk_i => en_clk_s,
+ xtal_i => xtal_i,
+ xtal_en_i => xtal_en_s,
+ data_i => t48_data_s,
+ data_o => p2_data_s,
+ write_p2_i => p2_write_p2_s,
+ write_exp_i => p2_write_exp_s,
+ read_p2_i => p2_read_p2_s,
+ read_reg_i => p2_read_reg_s,
+ read_exp_i => p2_read_exp_s,
+ output_pch_i => p2_output_pch_s,
+ pch_i => pmem_addr_s(11 downto 8),
+ p2_i => p2_i,
+ p2_o => p2_o,
+ p2l_low_imp_o => p2l_low_imp_o,
+ p2h_low_imp_o => p2h_low_imp_o
+ );
+ end generate;
+
+ skip_p2: if include_port2_g = 0 generate
+ p2_data_s <= (others => bus_idle_level_c);
+ p2_o <= (others => '0');
+ p2l_low_imp_o <= '0';
+ p2h_low_imp_o <= '0';
+ end generate;
+
+ pmem_ctrl_b : t48_pmem_ctrl
+ port map (
+ clk_i => clk_i,
+ res_i => reset_i,
+ en_clk_i => en_clk_s,
+ data_i => t48_data_s,
+ data_o => pm_data_s,
+ write_pcl_i => pm_write_pcl_s,
+ read_pcl_i => pm_read_pcl_s,
+ write_pch_i => pm_write_pch_s,
+ read_pch_i => pm_read_pch_s,
+ inc_pc_i => pm_inc_pc_s,
+ write_pmem_addr_i => pm_write_pmem_addr_s,
+ addr_type_i => pm_addr_type_s,
+ read_pmem_i => pm_read_pmem_s,
+ pmem_addr_o => pmem_addr_s,
+ pmem_data_i => pmem_data_i
+ );
+
+ psw_b : t48_psw
+ port map (
+ clk_i => clk_i,
+ res_i => reset_i,
+ en_clk_i => en_clk_s,
+ data_i => t48_data_s,
+ data_o => psw_data_s,
+ read_psw_i => psw_read_psw_s,
+ read_sp_i => psw_read_sp_s,
+ write_psw_i => psw_write_psw_s,
+ write_sp_i => psw_write_sp_s,
+ special_data_i => psw_special_data_s,
+ inc_stackp_i => psw_inc_stackp_s,
+ dec_stackp_i => psw_dec_stackp_s,
+ write_carry_i => psw_write_carry_s,
+ write_aux_carry_i => psw_write_aux_carry_s,
+ write_f0_i => psw_write_f0_s,
+ write_bs_i => psw_write_bs_s,
+ carry_o => psw_carry_s,
+ aux_carry_i => alu_aux_carry_s,
+ aux_carry_o => psw_aux_carry_s,
+ f0_o => psw_f0_s,
+ bs_o => psw_bs_s
+ );
+
+
+ -----------------------------------------------------------------------------
+ -- Output Mapping.
+ -----------------------------------------------------------------------------
+ ale_o <= to_stdLogic(ale_s);
+ psen_n_o <= to_stdLogic(not psen_s);
+ prog_n_o <= to_stdLogic(not prog_s);
+ rd_n_o <= to_stdLogic(not rd_s);
+ wr_n_o <= to_stdLogic(not wr_s);
+ xtal3_o <= to_stdLogic(xtal3_s);
+ pmem_addr_o <= pmem_addr_s;
+
+end struct;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: t48_core.vhd,v $
+-- Revision 1.12 2006/07/14 01:12:08 arniml
+-- * name tag added
+-- * restriction concerning expander port removed
+--
+-- Revision 1.11 2006/06/20 00:46:04 arniml
+-- new input xtal_en_i
+--
+-- Revision 1.10 2005/11/01 21:32:58 arniml
+-- wire signals for P2 low impeddance marker issue
+--
+-- Revision 1.9 2005/06/11 10:08:43 arniml
+-- introduce prefix 't48_' for all packages, entities and configurations
+--
+-- Revision 1.8 2005/05/04 20:12:37 arniml
+-- Fix bug report:
+-- "Wrong clock applied to T0"
+-- t0_o is generated inside clock_ctrl with a separate flip-flop running
+-- with xtal_i
+--
+-- Revision 1.7 2004/05/01 11:58:04 arniml
+-- update notice about expander port instructions
+--
+-- Revision 1.6 2004/04/07 22:09:03 arniml
+-- remove unused signals
+--
+-- Revision 1.5 2004/04/04 14:18:53 arniml
+-- add measures to implement XCHD
+--
+-- Revision 1.4 2004/03/29 19:39:58 arniml
+-- rename pX_limp to pX_low_imp
+--
+-- Revision 1.3 2004/03/28 21:27:50 arniml
+-- update wiring for DA support
+--
+-- Revision 1.2 2004/03/28 13:13:20 arniml
+-- connect control signal for Port 2 expander
+--
+-- Revision 1.1 2004/03/23 21:31:53 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/CPU/t48/rtl/vhdl/t48_core_comp_pack-p.vhd b/common/CPU/t48/rtl/vhdl/t48_core_comp_pack-p.vhd
new file mode 100644
index 00000000..c633f5bc
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/t48_core_comp_pack-p.vhd
@@ -0,0 +1,95 @@
+-------------------------------------------------------------------------------
+--
+-- $Id: t48_core_comp_pack-p.vhd,v 1.5 2006/06/21 01:03:28 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+package t48_core_comp_pack is
+
+ component t48_core
+ generic (
+ xtal_div_3_g : integer := 1;
+ register_mnemonic_g : integer := 1;
+ include_port1_g : integer := 1;
+ include_port2_g : integer := 1;
+ include_bus_g : integer := 1;
+ include_timer_g : integer := 1;
+ sample_t1_state_g : integer := 4
+ );
+
+ port (
+ xtal_i : in std_logic;
+ xtal_en_i : in std_logic;
+ reset_i : in std_logic;
+ t0_i : in std_logic;
+ t0_o : out std_logic;
+ t0_dir_o : out std_logic;
+ int_n_i : in std_logic;
+ ea_i : in std_logic;
+ rd_n_o : out std_logic;
+ psen_n_o : out std_logic;
+ wr_n_o : out std_logic;
+ ale_o : out std_logic;
+ db_i : in std_logic_vector( 7 downto 0);
+ db_o : out std_logic_vector( 7 downto 0);
+ db_dir_o : out std_logic;
+ t1_i : in std_logic;
+ p2_i : in std_logic_vector( 7 downto 0);
+ p2_o : out std_logic_vector( 7 downto 0);
+ p2l_low_imp_o : out std_logic;
+ p2h_low_imp_o : out std_logic;
+ p1_i : in std_logic_vector( 7 downto 0);
+ p1_o : out std_logic_vector( 7 downto 0);
+ p1_low_imp_o : out std_logic;
+ prog_n_o : out std_logic;
+ clk_i : in std_logic;
+ en_clk_i : in std_logic;
+ xtal3_o : out std_logic;
+ dmem_addr_o : out std_logic_vector( 7 downto 0);
+ dmem_we_o : out std_logic;
+ dmem_data_i : in std_logic_vector( 7 downto 0);
+ dmem_data_o : out std_logic_vector( 7 downto 0);
+ pmem_addr_o : out std_logic_vector(11 downto 0);
+ pmem_data_i : in std_logic_vector( 7 downto 0)
+ );
+ end component;
+
+ component generic_ram_ena
+ generic (
+ addr_width_g : integer := 10;
+ data_width_g : integer := 8
+ );
+ port (
+ clk_i : in std_logic;
+ a_i : in std_logic_vector(addr_width_g-1 downto 0);
+ we_i : in std_logic;
+ ena_i : in std_logic;
+ d_i : in std_logic_vector(data_width_g-1 downto 0);
+ d_o : out std_logic_vector(data_width_g-1 downto 0)
+ );
+ end component;
+
+ component t48_rom
+ port (
+ clk_i : in std_logic;
+ rom_addr_i : in std_logic_vector(9 downto 0);
+ rom_data_o : out std_logic_vector(7 downto 0)
+ );
+ end component;
+
+ component t49_rom
+ port (
+ clk_i : in std_logic;
+ rom_addr_i : in std_logic_vector(10 downto 0);
+ rom_data_o : out std_logic_vector( 7 downto 0)
+ );
+ end component;
+
+end t48_core_comp_pack;
diff --git a/common/CPU/t48/rtl/vhdl/t48_pack-p.vhd b/common/CPU/t48/rtl/vhdl/t48_pack-p.vhd
new file mode 100644
index 00000000..f95fa752
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/t48_pack-p.vhd
@@ -0,0 +1,82 @@
+-------------------------------------------------------------------------------
+--
+-- $Id: t48_pack-p.vhd,v 1.1 2004/03/23 21:31:53 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+package t48_pack is
+
+ -----------------------------------------------------------------------------
+ -- Global constants
+ -----------------------------------------------------------------------------
+
+ -- clock active level
+ constant clk_active_c : std_logic := '1';
+ -- reset active level
+ constant res_active_c : std_logic := '0';
+ -- idle level on internal data bus
+ constant bus_idle_level_c : std_logic := '1';
+
+ -- global data word width
+ constant word_width_c : natural := 8;
+
+ -- data memory address width
+ constant dmem_addr_width_c : natural := 8;
+ -- program memory address width
+ constant pmem_addr_width_c : natural := 12;
+
+
+ -----------------------------------------------------------------------------
+ -- Global data types
+ -----------------------------------------------------------------------------
+
+ -- the global data word width type
+ subtype word_t is std_logic_vector(word_width_c-1 downto 0);
+ subtype nibble_t is std_logic_vector(word_width_c/2-1 downto 0);
+ -- the global data memory address type
+ subtype dmem_addr_t is std_logic_vector(dmem_addr_width_c-1 downto 0);
+ -- the global program memory address type
+ subtype pmem_addr_t is std_logic_vector(pmem_addr_width_c-1 downto 0);
+ subtype page_t is std_logic_vector(pmem_addr_width_c-1 downto word_width_c);
+
+ -- the machine states
+ type mstate_t is (MSTATE1, MSTATE2, MSTATE3, MSTATE4, MSTATE5);
+
+
+ -----------------------------------------------------------------------------
+ -- Global functions
+ -----------------------------------------------------------------------------
+
+ function to_stdLogic(input: boolean) return std_logic;
+ function to_boolean(input: std_logic) return boolean;
+
+end t48_pack;
+
+package body t48_pack is
+
+ function to_stdLogic(input: boolean) return std_logic is
+ begin
+ if input then
+ return '1';
+ else
+ return '0';
+ end if;
+ end to_stdLogic;
+
+ function to_boolean(input: std_logic) return boolean is
+ begin
+ if input = '1' then
+ return true;
+ else
+ return false;
+ end if;
+ end to_boolean;
+
+end t48_pack;
diff --git a/common/CPU/t48/rtl/vhdl/t48_tb_pack-p.vhd b/common/CPU/t48/rtl/vhdl/t48_tb_pack-p.vhd
new file mode 100644
index 00000000..3b0d3a16
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/t48_tb_pack-p.vhd
@@ -0,0 +1,22 @@
+-------------------------------------------------------------------------------
+--
+-- $Id: t48_tb_pack-p.vhd,v 1.2 2004/04/14 20:53:54 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+package t48_tb_pack is
+
+ -- Instruction strobe visibility
+ signal tb_istrobe_s : std_logic;
+
+ -- Accumulator visibilty
+ signal tb_accu_s : std_logic_vector(7 downto 0);
+
+end t48_tb_pack;
diff --git a/common/CPU/t48/rtl/vhdl/timer-c.vhd b/common/CPU/t48/rtl/vhdl/timer-c.vhd
new file mode 100644
index 00000000..8304089e
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/timer-c.vhd
@@ -0,0 +1,16 @@
+-------------------------------------------------------------------------------
+--
+-- The Timer/Counter unit.
+--
+-- $Id: timer-c.vhd,v 1.2 2005/06/11 10:08:43 arniml Exp $
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+configuration t48_timer_rtl_c0 of t48_timer is
+
+ for rtl
+ end for;
+
+end t48_timer_rtl_c0;
diff --git a/common/CPU/t48/rtl/vhdl/timer.vhd b/common/CPU/t48/rtl/vhdl/timer.vhd
new file mode 100644
index 00000000..5edb5c15
--- /dev/null
+++ b/common/CPU/t48/rtl/vhdl/timer.vhd
@@ -0,0 +1,284 @@
+-------------------------------------------------------------------------------
+--
+-- The Timer/Counter unit.
+--
+-- $Id: timer.vhd,v 1.7 2006/11/30 14:31:59 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.word_t;
+use work.t48_pack.mstate_t;
+
+entity t48_timer is
+
+ generic (
+ -- state in which T1 is sampled (3 or 4)
+ sample_t1_state_g : integer := 4
+ );
+
+ port (
+ -- Global Interface -------------------------------------------------------
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ t1_i : in std_logic;
+ clk_mstate_i : in mstate_t;
+ -- T48 Bus Interface ------------------------------------------------------
+ data_i : in word_t;
+ data_o : out word_t;
+ read_timer_i : in boolean;
+ write_timer_i : in boolean;
+ -- Decoder Interface ------------------------------------------------------
+ start_t_i : in boolean;
+ start_cnt_i : in boolean;
+ stop_tcnt_i : in boolean;
+ overflow_o : out std_logic
+ );
+
+end t48_timer;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+use work.t48_pack.all;
+
+architecture rtl of t48_timer is
+
+ -- the 8 bit counter core
+ signal counter_q : unsigned(word_t'range);
+ signal overflow_q : boolean;
+
+ -- increment signal for the counter core
+ type inc_type_t is (NONE, TIMER, COUNTER);
+ signal increment_s : boolean;
+ signal inc_sel_q : inc_type_t;
+
+ -- T1 edge detector
+ signal t1_q : std_logic;
+ signal t1_inc_s : boolean;
+
+ -- timer prescaler
+ signal prescaler_q : unsigned(4 downto 0);
+ signal pre_inc_s : boolean;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Verify the generics
+ -----------------------------------------------------------------------------
+
+ -- pragma translate_off
+ assert (sample_t1_state_g = 3) or (sample_t1_state_g = 4)
+ report "sample_t1_state_g must be either 3 or 4!"
+ severity failure;
+ -- pragma translate_on
+
+
+ -----------------------------------------------------------------------------
+ -- Process t1_edge
+ --
+ -- Purpose:
+ -- Implements the edge detector for T1.
+ --
+ t1_edge: process (t1_i,
+ t1_q,
+ clk_mstate_i)
+ begin
+ t1_inc_s <= false;
+
+ -- sample in state according to generic
+ -- Old devices: sample at the beginning of state 3
+ -- New devices: sample in state 4
+ if (sample_t1_state_g = 3 and clk_mstate_i = MSTATE3) or
+ (sample_t1_state_g = 4 and clk_mstate_i = MSTATE4) then
+ -- detect falling edge
+ if t1_q = '1' and t1_i = '0' then
+ t1_inc_s <= true;
+ end if;
+ end if;
+
+ end process t1_edge;
+ --
+ -----------------------------------------------------------------------------
+
+
+ pre_inc_s <= clk_mstate_i = MSTATE4 and prescaler_q = 31;
+
+
+ -----------------------------------------------------------------------------
+ -- Process inc_sel
+ --
+ -- Purpose:
+ -- Select increment source (timer, counter or none).
+ --
+ inc_sel: process (inc_sel_q,
+ pre_inc_s,
+ t1_inc_s)
+ begin
+ -- default assignment
+ increment_s <= false;
+
+ case inc_sel_q is
+ when NONE =>
+ increment_s <= false;
+ when TIMER =>
+ increment_s <= pre_inc_s;
+ when COUNTER =>
+ increment_s <= t1_inc_s;
+ when others =>
+ null;
+ end case;
+
+ end process inc_sel;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process regs
+ --
+ -- Purpose:
+ -- Implements the counter, the prescaler and other registers.
+ --
+ regs: process (res_i, clk_i)
+ begin
+ if res_i = res_active_c then
+ overflow_q <= false;
+ t1_q <= '0';
+ prescaler_q <= (others => '0');
+ inc_sel_q <= NONE;
+ counter_q <= (others => '0');
+
+ elsif clk_i'event and clk_i = clk_active_c then
+ if en_clk_i then
+
+ -- Counter Core and overflow ------------------------------------------
+ overflow_q <= false;
+
+ if write_timer_i then
+ counter_q <= unsigned(data_i);
+
+ elsif increment_s then
+ counter_q <= counter_q + 1;
+
+ if counter_q = 255 then
+ overflow_q <= true;
+ end if;
+
+ end if;
+
+ -- T1 edge detector ---------------------------------------------------
+ if (sample_t1_state_g = 3 and clk_mstate_i = MSTATE3) or
+ (sample_t1_state_g = 4 and clk_mstate_i = MSTATE4) then
+ t1_q <= t1_i;
+ end if;
+
+ -- Prescaler ----------------------------------------------------------
+ if start_t_i then
+ prescaler_q <= (others => '0');
+
+ elsif clk_mstate_i = MSTATE3 then
+ prescaler_q <= prescaler_q + 1;
+
+ end if;
+
+ -- Increment Selector -------------------------------------------------
+ if start_t_i then
+ inc_sel_q <= TIMER;
+ elsif start_cnt_i then
+ inc_sel_q <= COUNTER;
+ elsif stop_tcnt_i then
+ inc_sel_q <= NONE;
+ end if;
+
+ end if;
+
+ end if;
+
+ end process regs;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Output Mapping.
+ -----------------------------------------------------------------------------
+ data_o <= std_logic_vector(counter_q)
+ when read_timer_i else
+ (others => bus_idle_level_c);
+ overflow_o <= to_stdLogic(overflow_q);
+
+end rtl;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: timer.vhd,v $
+-- Revision 1.7 2006/11/30 14:31:59 arniml
+-- reset counter_q
+--
+-- Revision 1.6 2005/06/11 10:08:43 arniml
+-- introduce prefix 't48_' for all packages, entities and configurations
+--
+-- Revision 1.5 2004/07/11 16:51:33 arniml
+-- cleanup copyright notice
+--
+-- Revision 1.4 2004/07/04 13:06:45 arniml
+-- counter_q is not cleared during reset
+-- this would match all different descriptions of the Counter as
+-- a) if the software assumes that the Counter is modified during reset, it
+-- will initialize the Counter anyhow
+-- b) the special case 'Counter not modified during reset' is covered
+--
+-- Revision 1.3 2004/05/16 15:32:57 arniml
+-- fix edge detector bug for counter
+--
+-- Revision 1.2 2004/04/15 22:05:13 arniml
+-- increment prescaler with MSTATE4
+--
+-- Revision 1.1 2004/03/23 21:31:53 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/CPU/tv80/tv80_alu.v b/common/CPU/tv80/tv80_alu.v
new file mode 100644
index 00000000..f90bc70a
--- /dev/null
+++ b/common/CPU/tv80/tv80_alu.v
@@ -0,0 +1,442 @@
+//
+// TV80 8-Bit Microprocessor Core
+// Based on the VHDL T80 core by Daniel Wallner (jesus@opencores.org)
+//
+// Copyright (c) 2004 Guy Hutchison (ghutchis@opencores.org)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+module tv80_alu (/*AUTOARG*/
+ // Outputs
+ Q, F_Out,
+ // Inputs
+ Arith16, Z16, ALU_Op, IR, ISet, BusA, BusB, F_In
+ );
+
+ parameter Mode = 0;
+ parameter Flag_C = 0;
+ parameter Flag_N = 1;
+ parameter Flag_P = 2;
+ parameter Flag_X = 3;
+ parameter Flag_H = 4;
+ parameter Flag_Y = 5;
+ parameter Flag_Z = 6;
+ parameter Flag_S = 7;
+
+ input Arith16;
+ input Z16;
+ input [3:0] ALU_Op ;
+ input [5:0] IR;
+ input [1:0] ISet;
+ input [7:0] BusA;
+ input [7:0] BusB;
+ input [7:0] F_In;
+ output [7:0] Q;
+ output [7:0] F_Out;
+ reg [7:0] Q;
+ reg [7:0] F_Out;
+
+ function [4:0] AddSub4;
+ input [3:0] A;
+ input [3:0] B;
+ input Sub;
+ input Carry_In;
+ begin
+ AddSub4 = { 1'b0, A } + { 1'b0, (Sub)?~B:B } + {4'h0,Carry_In};
+ end
+ endfunction // AddSub4
+
+ function [3:0] AddSub3;
+ input [2:0] A;
+ input [2:0] B;
+ input Sub;
+ input Carry_In;
+ begin
+ AddSub3 = { 1'b0, A } + { 1'b0, (Sub)?~B:B } + {3'h0,Carry_In};
+ end
+ endfunction // AddSub4
+
+ function [1:0] AddSub1;
+ input A;
+ input B;
+ input Sub;
+ input Carry_In;
+ begin
+ AddSub1 = { 1'b0, A } + { 1'b0, (Sub)?~B:B } + {1'h0,Carry_In};
+ end
+ endfunction // AddSub4
+
+ // AddSub variables (temporary signals)
+ reg UseCarry;
+ reg Carry7_v;
+ reg OverFlow_v;
+ reg HalfCarry_v;
+ reg Carry_v;
+ reg [7:0] Q_v;
+
+ reg [7:0] BitMask;
+
+
+ always @(/*AUTOSENSE*/ALU_Op or BusA or BusB or F_In or IR)
+ begin
+ case (IR[5:3])
+ 3'b000 : BitMask = 8'b00000001;
+ 3'b001 : BitMask = 8'b00000010;
+ 3'b010 : BitMask = 8'b00000100;
+ 3'b011 : BitMask = 8'b00001000;
+ 3'b100 : BitMask = 8'b00010000;
+ 3'b101 : BitMask = 8'b00100000;
+ 3'b110 : BitMask = 8'b01000000;
+ default: BitMask = 8'b10000000;
+ endcase // case(IR[5:3])
+
+ UseCarry = ~ ALU_Op[2] && ALU_Op[0];
+ { HalfCarry_v, Q_v[3:0] } = AddSub4(BusA[3:0], BusB[3:0], ALU_Op[1], ALU_Op[1] ^ (UseCarry && F_In[Flag_C]) );
+ { Carry7_v, Q_v[6:4] } = AddSub3(BusA[6:4], BusB[6:4], ALU_Op[1], HalfCarry_v);
+ { Carry_v, Q_v[7] } = AddSub1(BusA[7], BusB[7], ALU_Op[1], Carry7_v);
+ OverFlow_v = Carry_v ^ Carry7_v;
+ end // always @ *
+
+ reg [7:0] Q_t;
+ reg [8:0] DAA_Q;
+
+ always @ (/*AUTOSENSE*/ALU_Op or Arith16 or BitMask or BusA or BusB
+ or Carry_v or F_In or HalfCarry_v or IR or ISet
+ or OverFlow_v or Q_v or Z16)
+ begin
+ Q_t = 8'hxx;
+ DAA_Q = {9{1'bx}};
+
+ F_Out = F_In;
+ case (ALU_Op)
+ 4'b0000, 4'b0001, 4'b0010, 4'b0011, 4'b0100, 4'b0101, 4'b0110, 4'b0111 :
+ begin
+ F_Out[Flag_N] = 1'b0;
+ F_Out[Flag_C] = 1'b0;
+
+ case (ALU_Op[2:0])
+
+ 3'b000, 3'b001 : // ADD, ADC
+ begin
+ Q_t = Q_v;
+ F_Out[Flag_C] = Carry_v;
+ F_Out[Flag_H] = HalfCarry_v;
+ F_Out[Flag_P] = OverFlow_v;
+ end
+
+ 3'b010, 3'b011, 3'b111 : // SUB, SBC, CP
+ begin
+ Q_t = Q_v;
+ F_Out[Flag_N] = 1'b1;
+ F_Out[Flag_C] = ~ Carry_v;
+ F_Out[Flag_H] = ~ HalfCarry_v;
+ F_Out[Flag_P] = OverFlow_v;
+ end
+
+ 3'b100 : // AND
+ begin
+ Q_t[7:0] = BusA & BusB;
+ F_Out[Flag_H] = 1'b1;
+ end
+
+ 3'b101 : // XOR
+ begin
+ Q_t[7:0] = BusA ^ BusB;
+ F_Out[Flag_H] = 1'b0;
+ end
+
+ default : // OR 3'b110
+ begin
+ Q_t[7:0] = BusA | BusB;
+ F_Out[Flag_H] = 1'b0;
+ end
+
+ endcase // case(ALU_OP[2:0])
+
+ if (ALU_Op[2:0] == 3'b111 )
+ begin // CP
+ F_Out[Flag_X] = BusB[3];
+ F_Out[Flag_Y] = BusB[5];
+ end
+ else
+ begin
+ F_Out[Flag_X] = Q_t[3];
+ F_Out[Flag_Y] = Q_t[5];
+ end
+
+ if (Q_t[7:0] == 8'b00000000 )
+ begin
+ F_Out[Flag_Z] = 1'b1;
+ if (Z16 == 1'b1 )
+ begin
+ F_Out[Flag_Z] = F_In[Flag_Z]; // 16 bit ADC,SBC
+ end
+ end
+ else
+ begin
+ F_Out[Flag_Z] = 1'b0;
+ end // else: !if(Q_t[7:0] == 8'b00000000 )
+
+ F_Out[Flag_S] = Q_t[7];
+ case (ALU_Op[2:0])
+ 3'b000, 3'b001, 3'b010, 3'b011, 3'b111 : // ADD, ADC, SUB, SBC, CP
+ ;
+
+ default :
+ F_Out[Flag_P] = ~(^Q_t);
+ endcase // case(ALU_Op[2:0])
+
+ if (Arith16 == 1'b1 )
+ begin
+ F_Out[Flag_S] = F_In[Flag_S];
+ F_Out[Flag_Z] = F_In[Flag_Z];
+ F_Out[Flag_P] = F_In[Flag_P];
+ end
+ end // case: 4'b0000, 4'b0001, 4'b0010, 4'b0011, 4'b0100, 4'b0101, 4'b0110, 4'b0111
+
+ 4'b1100 :
+ begin
+ // DAA
+ F_Out[Flag_H] = F_In[Flag_H];
+ F_Out[Flag_C] = F_In[Flag_C];
+ DAA_Q[7:0] = BusA;
+ DAA_Q[8] = 1'b0;
+ if (F_In[Flag_N] == 1'b0 )
+ begin
+ // After addition
+ // Alow > 9 || H == 1
+ if (DAA_Q[3:0] > 9 || F_In[Flag_H] == 1'b1 )
+ begin
+ if ((DAA_Q[3:0] > 9) )
+ begin
+ F_Out[Flag_H] = 1'b1;
+ end
+ else
+ begin
+ F_Out[Flag_H] = 1'b0;
+ end
+ DAA_Q = DAA_Q + 6;
+ end // if (DAA_Q[3:0] > 9 || F_In[Flag_H] == 1'b1 )
+
+ // new Ahigh > 9 || C == 1
+ if (DAA_Q[8:4] > 9 || F_In[Flag_C] == 1'b1 )
+ begin
+ DAA_Q = DAA_Q + 96; // 0x60
+ end
+ end
+ else
+ begin
+ // After subtraction
+ if (DAA_Q[3:0] > 9 || F_In[Flag_H] == 1'b1 )
+ begin
+ if (DAA_Q[3:0] > 5 )
+ begin
+ F_Out[Flag_H] = 1'b0;
+ end
+ DAA_Q[7:0] = DAA_Q[7:0] - 6;
+ end
+ if (BusA > 153 || F_In[Flag_C] == 1'b1 )
+ begin
+ DAA_Q = DAA_Q - 352; // 0x160
+ end
+ end // else: !if(F_In[Flag_N] == 1'b0 )
+
+ F_Out[Flag_X] = DAA_Q[3];
+ F_Out[Flag_Y] = DAA_Q[5];
+ F_Out[Flag_C] = F_In[Flag_C] || DAA_Q[8];
+ Q_t = DAA_Q[7:0];
+
+ if (DAA_Q[7:0] == 8'b00000000 )
+ begin
+ F_Out[Flag_Z] = 1'b1;
+ end
+ else
+ begin
+ F_Out[Flag_Z] = 1'b0;
+ end
+
+ F_Out[Flag_S] = DAA_Q[7];
+ F_Out[Flag_P] = ~ (^DAA_Q);
+ end // case: 4'b1100
+
+ 4'b1101, 4'b1110 :
+ begin
+ // RLD, RRD
+ Q_t[7:4] = BusA[7:4];
+ if (ALU_Op[0] == 1'b1 )
+ begin
+ Q_t[3:0] = BusB[7:4];
+ end
+ else
+ begin
+ Q_t[3:0] = BusB[3:0];
+ end
+ F_Out[Flag_H] = 1'b0;
+ F_Out[Flag_N] = 1'b0;
+ F_Out[Flag_X] = Q_t[3];
+ F_Out[Flag_Y] = Q_t[5];
+ if (Q_t[7:0] == 8'b00000000 )
+ begin
+ F_Out[Flag_Z] = 1'b1;
+ end
+ else
+ begin
+ F_Out[Flag_Z] = 1'b0;
+ end
+ F_Out[Flag_S] = Q_t[7];
+ F_Out[Flag_P] = ~(^Q_t);
+ end // case: when 4'b1101, 4'b1110
+
+ 4'b1001 :
+ begin
+ // BIT
+ Q_t[7:0] = BusB & BitMask;
+ F_Out[Flag_S] = Q_t[7];
+ if (Q_t[7:0] == 8'b00000000 )
+ begin
+ F_Out[Flag_Z] = 1'b1;
+ F_Out[Flag_P] = 1'b1;
+ end
+ else
+ begin
+ F_Out[Flag_Z] = 1'b0;
+ F_Out[Flag_P] = 1'b0;
+ end
+ F_Out[Flag_H] = 1'b1;
+ F_Out[Flag_N] = 1'b0;
+ F_Out[Flag_X] = 1'b0;
+ F_Out[Flag_Y] = 1'b0;
+ if (IR[2:0] != 3'b110 )
+ begin
+ F_Out[Flag_X] = BusB[3];
+ F_Out[Flag_Y] = BusB[5];
+ end
+ end // case: when 4'b1001
+
+ 4'b1010 :
+ // SET
+ Q_t[7:0] = BusB | BitMask;
+
+ 4'b1011 :
+ // RES
+ Q_t[7:0] = BusB & ~ BitMask;
+
+ 4'b1000 :
+ begin
+ // ROT
+ case (IR[5:3])
+ 3'b000 : // RLC
+ begin
+ Q_t[7:1] = BusA[6:0];
+ Q_t[0] = BusA[7];
+ F_Out[Flag_C] = BusA[7];
+ end
+
+ 3'b010 : // RL
+ begin
+ Q_t[7:1] = BusA[6:0];
+ Q_t[0] = F_In[Flag_C];
+ F_Out[Flag_C] = BusA[7];
+ end
+
+ 3'b001 : // RRC
+ begin
+ Q_t[6:0] = BusA[7:1];
+ Q_t[7] = BusA[0];
+ F_Out[Flag_C] = BusA[0];
+ end
+
+ 3'b011 : // RR
+ begin
+ Q_t[6:0] = BusA[7:1];
+ Q_t[7] = F_In[Flag_C];
+ F_Out[Flag_C] = BusA[0];
+ end
+
+ 3'b100 : // SLA
+ begin
+ Q_t[7:1] = BusA[6:0];
+ Q_t[0] = 1'b0;
+ F_Out[Flag_C] = BusA[7];
+ end
+
+ 3'b110 : // SLL (Undocumented) / SWAP
+ begin
+ if (Mode == 3 )
+ begin
+ Q_t[7:4] = BusA[3:0];
+ Q_t[3:0] = BusA[7:4];
+ F_Out[Flag_C] = 1'b0;
+ end
+ else
+ begin
+ Q_t[7:1] = BusA[6:0];
+ Q_t[0] = 1'b1;
+ F_Out[Flag_C] = BusA[7];
+ end // else: !if(Mode == 3 )
+ end // case: 3'b110
+
+ 3'b101 : // SRA
+ begin
+ Q_t[6:0] = BusA[7:1];
+ Q_t[7] = BusA[7];
+ F_Out[Flag_C] = BusA[0];
+ end
+
+ default : // SRL
+ begin
+ Q_t[6:0] = BusA[7:1];
+ Q_t[7] = 1'b0;
+ F_Out[Flag_C] = BusA[0];
+ end
+ endcase // case(IR[5:3])
+
+ F_Out[Flag_H] = 1'b0;
+ F_Out[Flag_N] = 1'b0;
+ F_Out[Flag_X] = Q_t[3];
+ F_Out[Flag_Y] = Q_t[5];
+ F_Out[Flag_S] = Q_t[7];
+ if (Q_t[7:0] == 8'b00000000 )
+ begin
+ F_Out[Flag_Z] = 1'b1;
+ end
+ else
+ begin
+ F_Out[Flag_Z] = 1'b0;
+ end
+ F_Out[Flag_P] = ~(^Q_t);
+
+ if (ISet == 2'b00 )
+ begin
+ F_Out[Flag_P] = F_In[Flag_P];
+ F_Out[Flag_S] = F_In[Flag_S];
+ F_Out[Flag_Z] = F_In[Flag_Z];
+ end
+ end // case: 4'b1000
+
+
+ default :
+ ;
+
+ endcase // case(ALU_Op)
+
+ Q = Q_t;
+ end // always @ (Arith16, ALU_OP, F_In, BusA, BusB, IR, Q_v, Carry_v, HalfCarry_v, OverFlow_v, BitMask, ISet, Z16)
+
+endmodule // T80_ALU
diff --git a/common/CPU/tv80/tv80_core.v b/common/CPU/tv80/tv80_core.v
new file mode 100644
index 00000000..e3f7d247
--- /dev/null
+++ b/common/CPU/tv80/tv80_core.v
@@ -0,0 +1,1389 @@
+//
+// TV80 8-Bit Microprocessor Core
+// Based on the VHDL T80 core by Daniel Wallner (jesus@opencores.org)
+//
+// Copyright (c) 2004 Guy Hutchison (ghutchis@opencores.org)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+module tv80_core (/*AUTOARG*/
+ // Outputs
+ m1_n, iorq, no_read, write, rfsh_n, halt_n, busak_n, A, dout, mc,
+ ts, intcycle_n, IntE, stop,
+ // Inputs
+ reset_n, clk, cen, wait_n, int_n, nmi_n, busrq_n, dinst, di
+ );
+ // Beginning of automatic inputs (from unused autoinst inputs)
+ // End of automatics
+
+ parameter Mode = 1; // 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB
+ parameter IOWait = 1; // 0 => Single cycle I/O, 1 => Std I/O cycle
+ parameter Flag_C = 0;
+ parameter Flag_N = 1;
+ parameter Flag_P = 2;
+ parameter Flag_X = 3;
+ parameter Flag_H = 4;
+ parameter Flag_Y = 5;
+ parameter Flag_Z = 6;
+ parameter Flag_S = 7;
+
+ input reset_n;
+ input clk;
+ input cen;
+ input wait_n;
+ input int_n;
+ input nmi_n;
+ input busrq_n;
+ output m1_n;
+ output iorq;
+ output no_read;
+ output write;
+ output rfsh_n;
+ output halt_n;
+ output busak_n;
+ output [15:0] A;
+ input [7:0] dinst;
+ input [7:0] di;
+ output [7:0] dout;
+ output [6:0] mc;
+ output [6:0] ts;
+ output intcycle_n;
+ output IntE;
+ output stop;
+
+ reg m1_n;
+ reg iorq;
+`ifdef TV80_REFRESH
+ reg rfsh_n;
+`endif
+ reg halt_n;
+ reg busak_n;
+ reg [15:0] A;
+ reg [7:0] dout;
+ reg [6:0] mc;
+ reg [6:0] ts;
+ reg intcycle_n;
+ reg IntE;
+ reg stop;
+
+ parameter aNone = 3'b111;
+ parameter aBC = 3'b000;
+ parameter aDE = 3'b001;
+ parameter aXY = 3'b010;
+ parameter aIOA = 3'b100;
+ parameter aSP = 3'b101;
+ parameter aZI = 3'b110;
+
+ // Registers
+ reg [7:0] ACC, F;
+ reg [7:0] Ap, Fp;
+ reg [7:0] I;
+`ifdef TV80_REFRESH
+ reg [7:0] R;
+`endif
+ reg [15:0] SP, PC;
+ reg [7:0] RegDIH;
+ reg [7:0] RegDIL;
+ wire [15:0] RegBusA;
+ wire [15:0] RegBusB;
+ wire [15:0] RegBusC;
+ reg [2:0] RegAddrA_r;
+ reg [2:0] RegAddrA;
+ reg [2:0] RegAddrB_r;
+ reg [2:0] RegAddrB;
+ reg [2:0] RegAddrC;
+ reg RegWEH;
+ reg RegWEL;
+ reg Alternate;
+
+ // Help Registers
+ reg [15:0] TmpAddr; // Temporary address register
+ reg [7:0] IR; // Instruction register
+ reg [1:0] ISet; // Instruction set selector
+ reg [15:0] RegBusA_r;
+
+ reg [15:0] ID16;
+ reg [7:0] Save_Mux;
+
+ reg [6:0] tstate;
+ reg [6:0] mcycle;
+ reg last_mcycle, last_tstate;
+ reg IntE_FF1;
+ reg IntE_FF2;
+ reg Halt_FF;
+ reg BusReq_s;
+ reg BusAck;
+ reg ClkEn;
+ reg NMI_s;
+ reg INT_s;
+ reg [1:0] IStatus;
+
+ reg [7:0] DI_Reg;
+ reg T_Res;
+ reg [1:0] XY_State;
+ reg [2:0] Pre_XY_F_M;
+ reg NextIs_XY_Fetch;
+ reg XY_Ind;
+ reg No_BTR;
+ reg BTR_r;
+ reg Auto_Wait;
+ reg Auto_Wait_t1;
+ reg Auto_Wait_t2;
+ reg IncDecZ;
+
+ // ALU signals
+ reg [7:0] BusB;
+ reg [7:0] BusA;
+ wire [7:0] ALU_Q;
+ wire [7:0] F_Out;
+
+ // Registered micro code outputs
+ reg [4:0] Read_To_Reg_r;
+ reg Arith16_r;
+ reg Z16_r;
+ reg [3:0] ALU_Op_r;
+ reg Save_ALU_r;
+ reg PreserveC_r;
+ reg [2:0] mcycles;
+
+ // Micro code outputs
+ wire [2:0] mcycles_d;
+ wire [2:0] tstates;
+ reg IntCycle;
+ reg NMICycle;
+ wire Inc_PC;
+ wire Inc_WZ;
+ wire [3:0] IncDec_16;
+ wire [1:0] Prefix;
+ wire Read_To_Acc;
+ wire Read_To_Reg;
+ wire [3:0] Set_BusB_To;
+ wire [3:0] Set_BusA_To;
+ wire [3:0] ALU_Op;
+ wire Save_ALU;
+ wire PreserveC;
+ wire Arith16;
+ wire [2:0] Set_Addr_To;
+ wire Jump;
+ wire JumpE;
+ wire JumpXY;
+ wire Call;
+ wire RstP;
+ wire LDZ;
+ wire LDW;
+ wire LDSPHL;
+ wire iorq_i;
+ wire [2:0] Special_LD;
+ wire ExchangeDH;
+ wire ExchangeRp;
+ wire ExchangeAF;
+ wire ExchangeRS;
+ wire I_DJNZ;
+ wire I_CPL;
+ wire I_CCF;
+ wire I_SCF;
+ wire I_RETN;
+ wire I_BT;
+ wire I_BC;
+ wire I_BTR;
+ wire I_RLD;
+ wire I_RRD;
+ wire I_INRC;
+ wire SetDI;
+ wire SetEI;
+ wire [1:0] IMode;
+ wire Halt;
+
+ reg [15:0] PC16;
+ reg [15:0] PC16_B;
+ reg [15:0] SP16, SP16_A, SP16_B;
+ reg [15:0] ID16_B;
+ reg Oldnmi_n;
+
+ tv80_mcode #(Mode, Flag_C, Flag_N, Flag_P, Flag_X, Flag_H, Flag_Y, Flag_Z, Flag_S) i_mcode
+ (
+ .IR (IR),
+ .ISet (ISet),
+ .MCycle (mcycle),
+ .F (F),
+ .NMICycle (NMICycle),
+ .IntCycle (IntCycle),
+ .MCycles (mcycles_d),
+ .TStates (tstates),
+ .Prefix (Prefix),
+ .Inc_PC (Inc_PC),
+ .Inc_WZ (Inc_WZ),
+ .IncDec_16 (IncDec_16),
+ .Read_To_Acc (Read_To_Acc),
+ .Read_To_Reg (Read_To_Reg),
+ .Set_BusB_To (Set_BusB_To),
+ .Set_BusA_To (Set_BusA_To),
+ .ALU_Op (ALU_Op),
+ .Save_ALU (Save_ALU),
+ .PreserveC (PreserveC),
+ .Arith16 (Arith16),
+ .Set_Addr_To (Set_Addr_To),
+ .IORQ (iorq_i),
+ .Jump (Jump),
+ .JumpE (JumpE),
+ .JumpXY (JumpXY),
+ .Call (Call),
+ .RstP (RstP),
+ .LDZ (LDZ),
+ .LDW (LDW),
+ .LDSPHL (LDSPHL),
+ .Special_LD (Special_LD),
+ .ExchangeDH (ExchangeDH),
+ .ExchangeRp (ExchangeRp),
+ .ExchangeAF (ExchangeAF),
+ .ExchangeRS (ExchangeRS),
+ .I_DJNZ (I_DJNZ),
+ .I_CPL (I_CPL),
+ .I_CCF (I_CCF),
+ .I_SCF (I_SCF),
+ .I_RETN (I_RETN),
+ .I_BT (I_BT),
+ .I_BC (I_BC),
+ .I_BTR (I_BTR),
+ .I_RLD (I_RLD),
+ .I_RRD (I_RRD),
+ .I_INRC (I_INRC),
+ .SetDI (SetDI),
+ .SetEI (SetEI),
+ .IMode (IMode),
+ .Halt (Halt),
+ .NoRead (no_read),
+ .Write (write)
+ );
+
+ tv80_alu #(Mode, Flag_C, Flag_N, Flag_P, Flag_X, Flag_H, Flag_Y, Flag_Z, Flag_S) i_alu
+ (
+ .Arith16 (Arith16_r),
+ .Z16 (Z16_r),
+ .ALU_Op (ALU_Op_r),
+ .IR (IR[5:0]),
+ .ISet (ISet),
+ .BusA (BusA),
+ .BusB (BusB),
+ .F_In (F),
+ .Q (ALU_Q),
+ .F_Out (F_Out)
+ );
+
+ function [6:0] number_to_bitvec;
+ input [2:0] num;
+ begin
+ case (num)
+ 1 : number_to_bitvec = 7'b0000001;
+ 2 : number_to_bitvec = 7'b0000010;
+ 3 : number_to_bitvec = 7'b0000100;
+ 4 : number_to_bitvec = 7'b0001000;
+ 5 : number_to_bitvec = 7'b0010000;
+ 6 : number_to_bitvec = 7'b0100000;
+ 7 : number_to_bitvec = 7'b1000000;
+ default : number_to_bitvec = 7'bx;
+ endcase // case(num)
+ end
+ endfunction // number_to_bitvec
+
+ function [2:0] mcyc_to_number;
+ input [6:0] mcyc;
+ begin
+ casez (mcyc)
+ 7'b1zzzzzz : mcyc_to_number = 3'h7;
+ 7'b01zzzzz : mcyc_to_number = 3'h6;
+ 7'b001zzzz : mcyc_to_number = 3'h5;
+ 7'b0001zzz : mcyc_to_number = 3'h4;
+ 7'b00001zz : mcyc_to_number = 3'h3;
+ 7'b000001z : mcyc_to_number = 3'h2;
+ 7'b0000001 : mcyc_to_number = 3'h1;
+ default : mcyc_to_number = 3'h1;
+ endcase
+ end
+ endfunction
+
+ always @(/*AUTOSENSE*/mcycle or mcycles or tstate or tstates)
+ begin
+ case (mcycles)
+ 1 : last_mcycle = mcycle[0];
+ 2 : last_mcycle = mcycle[1];
+ 3 : last_mcycle = mcycle[2];
+ 4 : last_mcycle = mcycle[3];
+ 5 : last_mcycle = mcycle[4];
+ 6 : last_mcycle = mcycle[5];
+ 7 : last_mcycle = mcycle[6];
+ default : last_mcycle = 1'bx;
+ endcase // case(mcycles)
+
+ case (tstates)
+ 0 : last_tstate = tstate[0];
+ 1 : last_tstate = tstate[1];
+ 2 : last_tstate = tstate[2];
+ 3 : last_tstate = tstate[3];
+ 4 : last_tstate = tstate[4];
+ 5 : last_tstate = tstate[5];
+ 6 : last_tstate = tstate[6];
+ default : last_tstate = 1'bx;
+ endcase
+ end // always @ (...
+
+
+ always @(/*AUTOSENSE*/ALU_Q or BusAck or BusB or DI_Reg
+ or ExchangeRp or IR or Save_ALU_r or Set_Addr_To or XY_Ind
+ or XY_State or cen or last_tstate or mcycle)
+ begin
+ ClkEn = cen && ~ BusAck;
+
+ if (last_tstate)
+ T_Res = 1'b1;
+ else T_Res = 1'b0;
+
+ if (XY_State != 2'b00 && XY_Ind == 1'b0 &&
+ ((Set_Addr_To == aXY) ||
+ (mcycle[0] && IR == 8'b11001011) ||
+ (mcycle[0] && IR == 8'b00110110)))
+ NextIs_XY_Fetch = 1'b1;
+ else
+ NextIs_XY_Fetch = 1'b0;
+
+ if (ExchangeRp)
+ Save_Mux = BusB;
+ else if (!Save_ALU_r)
+ Save_Mux = DI_Reg;
+ else
+ Save_Mux = ALU_Q;
+ end // always @ *
+
+ always @ (posedge clk or negedge reset_n)
+ begin
+ if (reset_n == 1'b0 )
+ begin
+ PC <= #1 0; // Program Counter
+ A <= #1 0;
+ TmpAddr <= #1 0;
+ IR <= #1 8'b00000000;
+ ISet <= #1 2'b00;
+ XY_State <= #1 2'b00;
+ IStatus <= #1 2'b00;
+ mcycles <= #1 3'b000;
+ dout <= #1 8'b00000000;
+
+ ACC <= #1 8'hFF;
+ F <= #1 8'hFF;
+ Ap <= #1 8'hFF;
+ Fp <= #1 8'hFF;
+ I <= #1 0;
+ `ifdef TV80_REFRESH
+ R <= #1 0;
+ `endif
+ SP <= #1 16'hFFFF;
+ Alternate <= #1 1'b0;
+
+ Read_To_Reg_r <= #1 5'b00000;
+ Arith16_r <= #1 1'b0;
+ BTR_r <= #1 1'b0;
+ Z16_r <= #1 1'b0;
+ ALU_Op_r <= #1 4'b0000;
+ Save_ALU_r <= #1 1'b0;
+ PreserveC_r <= #1 1'b0;
+ XY_Ind <= #1 1'b0;
+ end
+ else
+ begin
+
+ if (ClkEn == 1'b1 )
+ begin
+
+ ALU_Op_r <= #1 4'b0000;
+ Save_ALU_r <= #1 1'b0;
+ Read_To_Reg_r <= #1 5'b00000;
+
+ mcycles <= #1 mcycles_d;
+
+ if (IMode != 2'b11 )
+ begin
+ IStatus <= #1 IMode;
+ end
+
+ Arith16_r <= #1 Arith16;
+ PreserveC_r <= #1 PreserveC;
+ if (ISet == 2'b10 && ALU_Op[2] == 1'b0 && ALU_Op[0] == 1'b1 && mcycle[2] )
+ begin
+ Z16_r <= #1 1'b1;
+ end
+ else
+ begin
+ Z16_r <= #1 1'b0;
+ end
+
+ if (mcycle[0] && (tstate[1] | tstate[2] | tstate[3] ))
+ begin
+ // mcycle == 1 && tstate == 1, 2, || 3
+ if (tstate[2] && wait_n == 1'b1 )
+ begin
+ `ifdef TV80_REFRESH
+ if (Mode < 2 )
+ begin
+ A[7:0] <= #1 R;
+ A[15:8] <= #1 I;
+ R[6:0] <= #1 R[6:0] + 1;
+ end
+ `endif
+ if (Jump == 1'b0 && Call == 1'b0 && NMICycle == 1'b0 && IntCycle == 1'b0 && ~ (Halt_FF == 1'b1 || Halt == 1'b1) )
+ begin
+ PC <= #1 PC16;
+ end
+
+ if (IntCycle == 1'b1 && IStatus == 2'b01 )
+ begin
+ IR <= #1 8'b11111111;
+ end
+ else if (Halt_FF == 1'b1 || (IntCycle == 1'b1 && IStatus == 2'b10) || NMICycle == 1'b1 )
+ begin
+ IR <= #1 8'b00000000;
+ TmpAddr[7:0] <= #1 dinst; // Special M1 vector fetch
+ end
+ else
+ begin
+ IR <= #1 dinst;
+ end
+
+ ISet <= #1 2'b00;
+ if (Prefix != 2'b00 )
+ begin
+ if (Prefix == 2'b11 )
+ begin
+ if (IR[5] == 1'b1 )
+ begin
+ XY_State <= #1 2'b10;
+ end
+ else
+ begin
+ XY_State <= #1 2'b01;
+ end
+ end
+ else
+ begin
+ if (Prefix == 2'b10 )
+ begin
+ XY_State <= #1 2'b00;
+ XY_Ind <= #1 1'b0;
+ end
+ ISet <= #1 Prefix;
+ end
+ end
+ else
+ begin
+ XY_State <= #1 2'b00;
+ XY_Ind <= #1 1'b0;
+ end
+ end // if (tstate == 2 && wait_n == 1'b1 )
+
+
+ end
+ else
+ begin
+ // either (mcycle > 1) OR (mcycle == 1 AND tstate > 3)
+
+ if (mcycle[5] )
+ begin
+ XY_Ind <= #1 1'b1;
+ if (Prefix == 2'b01 )
+ begin
+ ISet <= #1 2'b01;
+ end
+ end
+
+ if (T_Res == 1'b1 )
+ begin
+ BTR_r <= #1 (I_BT || I_BC || I_BTR) && ~ No_BTR;
+ if (Jump == 1'b1 )
+ begin
+ A[15:8] <= #1 DI_Reg;
+ A[7:0] <= #1 TmpAddr[7:0];
+ PC[15:8] <= #1 DI_Reg;
+ PC[7:0] <= #1 TmpAddr[7:0];
+ end
+ else if (JumpXY == 1'b1 )
+ begin
+ A <= #1 RegBusC;
+ PC <= #1 RegBusC;
+ end else if (Call == 1'b1 || RstP == 1'b1 )
+ begin
+ A <= #1 TmpAddr;
+ PC <= #1 TmpAddr;
+ end
+ else if (last_mcycle && NMICycle == 1'b1 )
+ begin
+ A <= #1 16'b0000000001100110;
+ PC <= #1 16'b0000000001100110;
+ end
+ else if (mcycle[2] && IntCycle == 1'b1 && IStatus == 2'b10 )
+ begin
+ A[15:8] <= #1 I;
+ A[7:0] <= #1 TmpAddr[7:0];
+ PC[15:8] <= #1 I;
+ PC[7:0] <= #1 TmpAddr[7:0];
+ end
+ else
+ begin
+ case (Set_Addr_To)
+ aXY :
+ begin
+ if (XY_State == 2'b00 )
+ begin
+ A <= #1 RegBusC;
+ end
+ else
+ begin
+ if (NextIs_XY_Fetch == 1'b1 )
+ begin
+ A <= #1 PC;
+ end
+ else
+ begin
+ A <= #1 TmpAddr;
+ end
+ end // else: !if(XY_State == 2'b00 )
+ end // case: aXY
+
+ aIOA :
+ begin
+ if (Mode == 3 )
+ begin
+ // Memory map I/O on GBZ80
+ A[15:8] <= #1 8'hFF;
+ end
+ else if (Mode == 2 )
+ begin
+ // Duplicate I/O address on 8080
+ A[15:8] <= #1 DI_Reg;
+ end
+ else
+ begin
+ A[15:8] <= #1 ACC;
+ end
+ A[7:0] <= #1 DI_Reg;
+ end // case: aIOA
+
+
+ aSP :
+ begin
+ A <= #1 SP;
+ end
+
+ aBC :
+ begin
+ if (Mode == 3 && iorq_i == 1'b1 )
+ begin
+ // Memory map I/O on GBZ80
+ A[15:8] <= #1 8'hFF;
+ A[7:0] <= #1 RegBusC[7:0];
+ end
+ else
+ begin
+ A <= #1 RegBusC;
+ end
+ end // case: aBC
+
+ aDE :
+ begin
+ A <= #1 RegBusC;
+ end
+
+ aZI :
+ begin
+ if (Inc_WZ == 1'b1 )
+ begin
+ A <= #1 TmpAddr + 1;
+ end
+ else
+ begin
+ A[15:8] <= #1 DI_Reg;
+ A[7:0] <= #1 TmpAddr[7:0];
+ end
+ end // case: aZI
+
+ default :
+ begin
+ A <= #1 PC;
+ end
+ endcase // case(Set_Addr_To)
+
+ end // else: !if(mcycle[2] && IntCycle == 1'b1 && IStatus == 2'b10 )
+
+
+ Save_ALU_r <= #1 Save_ALU;
+ ALU_Op_r <= #1 ALU_Op;
+
+ if (I_CPL == 1'b1 )
+ begin
+ // CPL
+ ACC <= #1 ~ ACC;
+ F[Flag_Y] <= #1 ~ ACC[5];
+ F[Flag_H] <= #1 1'b1;
+ F[Flag_X] <= #1 ~ ACC[3];
+ F[Flag_N] <= #1 1'b1;
+ end
+ if (I_CCF == 1'b1 )
+ begin
+ // CCF
+ F[Flag_C] <= #1 ~ F[Flag_C];
+ F[Flag_Y] <= #1 ACC[5];
+ F[Flag_H] <= #1 F[Flag_C];
+ F[Flag_X] <= #1 ACC[3];
+ F[Flag_N] <= #1 1'b0;
+ end
+ if (I_SCF == 1'b1 )
+ begin
+ // SCF
+ F[Flag_C] <= #1 1'b1;
+ F[Flag_Y] <= #1 ACC[5];
+ F[Flag_H] <= #1 1'b0;
+ F[Flag_X] <= #1 ACC[3];
+ F[Flag_N] <= #1 1'b0;
+ end
+ end // if (T_Res == 1'b1 )
+
+
+ if (tstate[2] && wait_n == 1'b1 )
+ begin
+ if (ISet == 2'b01 && mcycle[6] )
+ begin
+ IR <= #1 dinst;
+ end
+ if (JumpE == 1'b1 )
+ begin
+ PC <= #1 PC16;
+ end
+ else if (Inc_PC == 1'b1 )
+ begin
+ //PC <= #1 PC + 1;
+ PC <= #1 PC16;
+ end
+ if (BTR_r == 1'b1 )
+ begin
+ //PC <= #1 PC - 2;
+ PC <= #1 PC16;
+ end
+ if (RstP == 1'b1 )
+ begin
+ TmpAddr <= #1 { 10'h0, IR[5:3], 3'h0 };
+ //TmpAddr <= #1 (others =>1'b0);
+ //TmpAddr[5:3] <= #1 IR[5:3];
+ end
+ end
+ if (tstate[3] && mcycle[5] )
+ begin
+ TmpAddr <= #1 SP16;
+ end
+
+ if ((tstate[2] && wait_n == 1'b1) || (tstate[4] && mcycle[0]) )
+ begin
+ if (IncDec_16[2:0] == 3'b111 )
+ begin
+ SP <= #1 SP16;
+ end
+ end
+
+ if (LDSPHL == 1'b1 )
+ begin
+ SP <= #1 RegBusC;
+ end
+ if (ExchangeAF == 1'b1 )
+ begin
+ Ap <= #1 ACC;
+ ACC <= #1 Ap;
+ Fp <= #1 F;
+ F <= #1 Fp;
+ end
+ if (ExchangeRS == 1'b1 )
+ begin
+ Alternate <= #1 ~ Alternate;
+ end
+ end // else: !if(mcycle == 3'b001 && tstate(2) == 1'b0 )
+
+
+ if (tstate[3] )
+ begin
+ if (LDZ == 1'b1 )
+ begin
+ TmpAddr[7:0] <= #1 DI_Reg;
+ end
+ if (LDW == 1'b1 )
+ begin
+ TmpAddr[15:8] <= #1 DI_Reg;
+ end
+
+ if (Special_LD[2] == 1'b1 )
+ begin
+ case (Special_LD[1:0])
+ 2'b00 :
+ begin
+ ACC <= #1 I;
+ F[Flag_P] <= #1 IntE_FF2;
+ F[Flag_Z] <= (I == 0);
+ F[Flag_S] <= I[7];
+ F[Flag_H] <= 0;
+ F[Flag_N] <= 0;
+ end
+
+ 2'b01 :
+ begin
+ `ifdef TV80_REFRESH
+ ACC <= #1 R;
+ `else
+ ACC <= #1 0;
+ `endif
+ F[Flag_P] <= #1 IntE_FF2;
+ F[Flag_Z] <= (I == 0);
+ F[Flag_S] <= I[7];
+ F[Flag_H] <= 0;
+ F[Flag_N] <= 0;
+ end
+
+ 2'b10 :
+ I <= #1 ACC;
+
+ `ifdef TV80_REFRESH
+ default :
+ R <= #1 ACC;
+ `else
+ default : ;
+ `endif
+ endcase
+ end
+ end // if (tstate == 3 )
+
+
+ if ((I_DJNZ == 1'b0 && Save_ALU_r == 1'b1) || ALU_Op_r == 4'b1001 )
+ begin
+ if (Mode == 3 )
+ begin
+ F[6] <= #1 F_Out[6];
+ F[5] <= #1 F_Out[5];
+ F[7] <= #1 F_Out[7];
+ if (PreserveC_r == 1'b0 )
+ begin
+ F[4] <= #1 F_Out[4];
+ end
+ end
+ else
+ begin
+ F[7:1] <= #1 F_Out[7:1];
+ if (PreserveC_r == 1'b0 )
+ begin
+ F[Flag_C] <= #1 F_Out[0];
+ end
+ end
+ end // if ((I_DJNZ == 1'b0 && Save_ALU_r == 1'b1) || ALU_Op_r == 4'b1001 )
+
+ if (T_Res == 1'b1 && I_INRC == 1'b1 )
+ begin
+ F[Flag_H] <= #1 1'b0;
+ F[Flag_N] <= #1 1'b0;
+ if (DI_Reg[7:0] == 8'b00000000 )
+ begin
+ F[Flag_Z] <= #1 1'b1;
+ end
+ else
+ begin
+ F[Flag_Z] <= #1 1'b0;
+ end
+ F[Flag_S] <= #1 DI_Reg[7];
+ F[Flag_P] <= #1 ~ (^DI_Reg[7:0]);
+ end // if (T_Res == 1'b1 && I_INRC == 1'b1 )
+
+
+ if (tstate[1] && Auto_Wait_t1 == 1'b0 )
+ begin
+ dout <= #1 BusB;
+ if (I_RLD == 1'b1 )
+ begin
+ dout[3:0] <= #1 BusA[3:0];
+ dout[7:4] <= #1 BusB[3:0];
+ end
+ if (I_RRD == 1'b1 )
+ begin
+ dout[3:0] <= #1 BusB[7:4];
+ dout[7:4] <= #1 BusA[3:0];
+ end
+ end
+
+ if (T_Res == 1'b1 )
+ begin
+ Read_To_Reg_r[3:0] <= #1 Set_BusA_To;
+ Read_To_Reg_r[4] <= #1 Read_To_Reg;
+ if (Read_To_Acc == 1'b1 )
+ begin
+ Read_To_Reg_r[3:0] <= #1 4'b0111;
+ Read_To_Reg_r[4] <= #1 1'b1;
+ end
+ end
+
+ if (tstate[1] && I_BT == 1'b1 )
+ begin
+ F[Flag_X] <= #1 ALU_Q[3];
+ F[Flag_Y] <= #1 ALU_Q[1];
+ F[Flag_H] <= #1 1'b0;
+ F[Flag_N] <= #1 1'b0;
+ end
+ if (I_BC == 1'b1 || I_BT == 1'b1 )
+ begin
+ F[Flag_P] <= #1 IncDecZ;
+ end
+
+ if ((tstate[1] && Save_ALU_r == 1'b0 && Auto_Wait_t1 == 1'b0) ||
+ (Save_ALU_r == 1'b1 && ALU_Op_r != 4'b0111) )
+ begin
+ case (Read_To_Reg_r)
+ 5'b10111 :
+ ACC <= #1 Save_Mux;
+ 5'b10110 :
+ dout <= #1 Save_Mux;
+ 5'b11000 :
+ SP[7:0] <= #1 Save_Mux;
+ 5'b11001 :
+ SP[15:8] <= #1 Save_Mux;
+ 5'b11011 :
+ F <= #1 Save_Mux;
+ default : ;
+ endcase
+ end // if ((tstate == 1 && Save_ALU_r == 1'b0 && Auto_Wait_t1 == 1'b0) ||...
+ end // if (ClkEn == 1'b1 )
+ end // else: !if(reset_n == 1'b0 )
+ end
+
+
+ //-------------------------------------------------------------------------
+ //
+ // BC('), DE('), HL('), IX && IY
+ //
+ //-------------------------------------------------------------------------
+ always @ (posedge clk)
+ begin
+ if (ClkEn == 1'b1 )
+ begin
+ // Bus A / Write
+ RegAddrA_r <= #1 { Alternate, Set_BusA_To[2:1] };
+ if (XY_Ind == 1'b0 && XY_State != 2'b00 && Set_BusA_To[2:1] == 2'b10 )
+ begin
+ RegAddrA_r <= #1 { XY_State[1], 2'b11 };
+ end
+
+ // Bus B
+ RegAddrB_r <= #1 { Alternate, Set_BusB_To[2:1] };
+ if (XY_Ind == 1'b0 && XY_State != 2'b00 && Set_BusB_To[2:1] == 2'b10 )
+ begin
+ RegAddrB_r <= #1 { XY_State[1], 2'b11 };
+ end
+
+ // Address from register
+ RegAddrC <= #1 { Alternate, Set_Addr_To[1:0] };
+ // Jump (HL), LD SP,HL
+ if ((JumpXY == 1'b1 || LDSPHL == 1'b1) )
+ begin
+ RegAddrC <= #1 { Alternate, 2'b10 };
+ end
+ if (((JumpXY == 1'b1 || LDSPHL == 1'b1) && XY_State != 2'b00) || (mcycle[5]) )
+ begin
+ RegAddrC <= #1 { XY_State[1], 2'b11 };
+ end
+
+ if (I_DJNZ == 1'b1 && Save_ALU_r == 1'b1 && Mode < 2 )
+ begin
+ IncDecZ <= #1 F_Out[Flag_Z];
+ end
+ if ((tstate[2] || (tstate[3] && mcycle[0])) && IncDec_16[2:0] == 3'b100 )
+ begin
+ if (ID16 == 0 )
+ begin
+ IncDecZ <= #1 1'b0;
+ end
+ else
+ begin
+ IncDecZ <= #1 1'b1;
+ end
+ end
+
+ RegBusA_r <= #1 RegBusA;
+ end
+
+ end // always @ (posedge clk)
+
+
+ always @(/*AUTOSENSE*/Alternate or ExchangeDH or IncDec_16
+ or RegAddrA_r or RegAddrB_r or XY_State or mcycle or tstate)
+ begin
+ if ((tstate[2] || (tstate[3] && mcycle[0] && IncDec_16[2] == 1'b1)) && XY_State == 2'b00)
+ RegAddrA = { Alternate, IncDec_16[1:0] };
+ else if ((tstate[2] || (tstate[3] && mcycle[0] && IncDec_16[2] == 1'b1)) && IncDec_16[1:0] == 2'b10)
+ RegAddrA = { XY_State[1], 2'b11 };
+ else if (ExchangeDH == 1'b1 && tstate[3])
+ RegAddrA = { Alternate, 2'b10 };
+ else if (ExchangeDH == 1'b1 && tstate[4])
+ RegAddrA = { Alternate, 2'b01 };
+ else
+ RegAddrA = RegAddrA_r;
+
+ if (ExchangeDH == 1'b1 && tstate[3])
+ RegAddrB = { Alternate, 2'b01 };
+ else
+ RegAddrB = RegAddrB_r;
+ end // always @ *
+
+
+ always @(/*AUTOSENSE*/ALU_Op_r or Auto_Wait_t1 or ExchangeDH
+ or IncDec_16 or Read_To_Reg_r or Save_ALU_r or mcycle
+ or tstate or wait_n)
+ begin
+ RegWEH = 1'b0;
+ RegWEL = 1'b0;
+ if ((tstate[1] && ~Save_ALU_r && ~Auto_Wait_t1) ||
+ (Save_ALU_r && (ALU_Op_r != 4'b0111)) )
+ begin
+ case (Read_To_Reg_r)
+ 5'b10000 , 5'b10001 , 5'b10010 , 5'b10011 , 5'b10100 , 5'b10101 :
+ begin
+ RegWEH = ~ Read_To_Reg_r[0];
+ RegWEL = Read_To_Reg_r[0];
+ end // UNMATCHED !!
+ default : ;
+ endcase // case(Read_To_Reg_r)
+
+ end // if ((tstate == 1 && Save_ALU_r == 1'b0 && Auto_Wait_t1 == 1'b0) ||...
+
+
+ if (ExchangeDH && (tstate[3] || tstate[4]) )
+ begin
+ RegWEH = 1'b1;
+ RegWEL = 1'b1;
+ end
+
+ if (IncDec_16[2] && ((tstate[2] && wait_n && ~mcycle[0]) || (tstate[3] && mcycle[0])) )
+ begin
+ case (IncDec_16[1:0])
+ 2'b00 , 2'b01 , 2'b10 :
+ begin
+ RegWEH = 1'b1;
+ RegWEL = 1'b1;
+ end // UNMATCHED !!
+ default : ;
+ endcase
+ end
+ end // always @ *
+
+
+ always @(/*AUTOSENSE*/ExchangeDH or ID16 or IncDec_16 or RegBusA_r
+ or RegBusB or Save_Mux or mcycle or tstate)
+ begin
+ RegDIH = Save_Mux;
+ RegDIL = Save_Mux;
+
+ if (ExchangeDH == 1'b1 && tstate[3] )
+ begin
+ RegDIH = RegBusB[15:8];
+ RegDIL = RegBusB[7:0];
+ end
+ else if (ExchangeDH == 1'b1 && tstate[4] )
+ begin
+ RegDIH = RegBusA_r[15:8];
+ RegDIL = RegBusA_r[7:0];
+ end
+ else if (IncDec_16[2] == 1'b1 && ((tstate[2] && ~mcycle[0]) || (tstate[3] && mcycle[0])) )
+ begin
+ RegDIH = ID16[15:8];
+ RegDIL = ID16[7:0];
+ end
+ end
+
+ tv80_reg i_reg
+ (
+ .clk (clk),
+ .CEN (ClkEn),
+ .WEH (RegWEH),
+ .WEL (RegWEL),
+ .AddrA (RegAddrA),
+ .AddrB (RegAddrB),
+ .AddrC (RegAddrC),
+ .DIH (RegDIH),
+ .DIL (RegDIL),
+ .DOAH (RegBusA[15:8]),
+ .DOAL (RegBusA[7:0]),
+ .DOBH (RegBusB[15:8]),
+ .DOBL (RegBusB[7:0]),
+ .DOCH (RegBusC[15:8]),
+ .DOCL (RegBusC[7:0])
+ );
+
+ //-------------------------------------------------------------------------
+ //
+ // Buses
+ //
+ //-------------------------------------------------------------------------
+
+ always @ (posedge clk)
+ begin
+ if (ClkEn == 1'b1 )
+ begin
+ case (Set_BusB_To)
+ 4'b0111 :
+ BusB <= #1 ACC;
+ 4'b0000 , 4'b0001 , 4'b0010 , 4'b0011 , 4'b0100 , 4'b0101 :
+ begin
+ if (Set_BusB_To[0] == 1'b1 )
+ begin
+ BusB <= #1 RegBusB[7:0];
+ end
+ else
+ begin
+ BusB <= #1 RegBusB[15:8];
+ end
+ end
+ 4'b0110 :
+ BusB <= #1 DI_Reg;
+ 4'b1000 :
+ BusB <= #1 SP[7:0];
+ 4'b1001 :
+ BusB <= #1 SP[15:8];
+ 4'b1010 :
+ BusB <= #1 8'b00000001;
+ 4'b1011 :
+ BusB <= #1 F;
+ 4'b1100 :
+ BusB <= #1 PC[7:0];
+ 4'b1101 :
+ BusB <= #1 PC[15:8];
+ 4'b1110 :
+ BusB <= #1 8'b00000000;
+ default :
+ BusB <= #1 8'h0;
+ endcase
+
+ case (Set_BusA_To)
+ 4'b0111 :
+ BusA <= #1 ACC;
+ 4'b0000 , 4'b0001 , 4'b0010 , 4'b0011 , 4'b0100 , 4'b0101 :
+ begin
+ if (Set_BusA_To[0] == 1'b1 )
+ begin
+ BusA <= #1 RegBusA[7:0];
+ end
+ else
+ begin
+ BusA <= #1 RegBusA[15:8];
+ end
+ end
+ 4'b0110 :
+ BusA <= #1 DI_Reg;
+ 4'b1000 :
+ BusA <= #1 SP[7:0];
+ 4'b1001 :
+ BusA <= #1 SP[15:8];
+ 4'b1010 :
+ BusA <= #1 8'b00000000;
+ default :
+ BusA <= #1 8'h0;
+ endcase
+ end
+ end
+
+ //-------------------------------------------------------------------------
+ //
+ // Generate external control signals
+ //
+ //-------------------------------------------------------------------------
+`ifdef TV80_REFRESH
+ always @ (posedge clk or negedge reset_n)
+ begin
+ if (reset_n == 1'b0 )
+ begin
+ rfsh_n <= #1 1'b1;
+ end
+ else
+ begin
+ if (cen == 1'b1 )
+ begin
+ if (mcycle[0] && ((tstate[2] && wait_n == 1'b1) || tstate[3]) )
+ begin
+ rfsh_n <= #1 1'b0;
+ end
+ else
+ begin
+ rfsh_n <= #1 1'b1;
+ end
+ end
+ end
+ end // always @ (posedge clk or negedge reset_n)
+`else // !`ifdef TV80_REFRESH
+ assign rfsh_n = 1'b1;
+`endif
+
+ always @(/*AUTOSENSE*/BusAck or Halt_FF or I_DJNZ or IntCycle
+ or IntE_FF1 or di or iorq_i or mcycle or tstate)
+ begin
+ mc = mcycle;
+ ts = tstate;
+ DI_Reg = di;
+ halt_n = ~ Halt_FF;
+ busak_n = ~ BusAck;
+ intcycle_n = ~ IntCycle;
+ IntE = IntE_FF1;
+ iorq = iorq_i;
+ stop = I_DJNZ;
+ end
+
+ //-----------------------------------------------------------------------
+ //
+ // Syncronise inputs
+ //
+ //-----------------------------------------------------------------------
+
+ always @ (posedge clk or negedge reset_n)
+ begin : sync_inputs
+ if (~reset_n)
+ begin
+ BusReq_s <= #1 1'b0;
+ INT_s <= #1 1'b0;
+ NMI_s <= #1 1'b0;
+ Oldnmi_n <= #1 1'b0;
+ end
+ else
+ begin
+ if (cen == 1'b1 )
+ begin
+ BusReq_s <= #1 ~ busrq_n;
+ INT_s <= #1 ~ int_n;
+ if (NMICycle == 1'b1 )
+ begin
+ NMI_s <= #1 1'b0;
+ end
+ else if (nmi_n == 1'b0 && Oldnmi_n == 1'b1 )
+ begin
+ NMI_s <= #1 1'b1;
+ end
+ Oldnmi_n <= #1 nmi_n;
+ end
+ end
+ end
+
+ //-----------------------------------------------------------------------
+ //
+ // Main state machine
+ //
+ //-----------------------------------------------------------------------
+
+ always @ (posedge clk or negedge reset_n)
+ begin
+ if (reset_n == 1'b0 )
+ begin
+ mcycle <= #1 7'b0000001;
+ tstate <= #1 7'b0000001;
+ Pre_XY_F_M <= #1 3'b000;
+ Halt_FF <= #1 1'b0;
+ BusAck <= #1 1'b0;
+ NMICycle <= #1 1'b0;
+ IntCycle <= #1 1'b0;
+ IntE_FF1 <= #1 1'b0;
+ IntE_FF2 <= #1 1'b0;
+ No_BTR <= #1 1'b0;
+ Auto_Wait_t1 <= #1 1'b0;
+ Auto_Wait_t2 <= #1 1'b0;
+ m1_n <= #1 1'b1;
+ end
+ else
+ begin
+ if (cen == 1'b1 )
+ begin
+ if (T_Res == 1'b1 )
+ begin
+ Auto_Wait_t1 <= #1 1'b0;
+ end
+ else
+ begin
+ Auto_Wait_t1 <= #1 Auto_Wait || (iorq_i & ~Auto_Wait_t2);
+ end
+ Auto_Wait_t2 <= #1 Auto_Wait_t1 & !T_Res;
+ No_BTR <= #1 (I_BT && (~ IR[4] || ~ F[Flag_P])) ||
+ (I_BC && (~ IR[4] || F[Flag_Z] || ~ F[Flag_P])) ||
+ (I_BTR && (~ IR[4] || F[Flag_Z]));
+ if (tstate[2] )
+ begin
+ if (SetEI == 1'b1 )
+ begin
+ if (!NMICycle)
+ IntE_FF1 <= #1 1'b1;
+ IntE_FF2 <= #1 1'b1;
+ end
+ if (I_RETN == 1'b1 )
+ begin
+ IntE_FF1 <= #1 IntE_FF2;
+ end
+ end
+ if (tstate[3] )
+ begin
+ if (SetDI == 1'b1 )
+ begin
+ IntE_FF1 <= #1 1'b0;
+ IntE_FF2 <= #1 1'b0;
+ end
+ end
+ if (IntCycle == 1'b1 || NMICycle == 1'b1 )
+ begin
+ Halt_FF <= #1 1'b0;
+ end
+ if (mcycle[0] && tstate[2] && wait_n == 1'b1 )
+ begin
+ m1_n <= #1 1'b1;
+ end
+ if (BusReq_s == 1'b1 && BusAck == 1'b1 )
+ begin
+ end
+ else
+ begin
+ BusAck <= #1 1'b0;
+ if (tstate[2] && wait_n == 1'b0 )
+ begin
+ end
+ else if (T_Res == 1'b1 )
+ begin
+ if (Halt == 1'b1 )
+ begin
+ Halt_FF <= #1 1'b1;
+ end
+ if (BusReq_s == 1'b1 )
+ begin
+ BusAck <= #1 1'b1;
+ end
+ else
+ begin
+ tstate <= #1 7'b0000010;
+ if (NextIs_XY_Fetch == 1'b1 )
+ begin
+ mcycle <= #1 7'b0100000;
+ Pre_XY_F_M <= #1 mcyc_to_number(mcycle);
+ if (IR == 8'b00110110 && Mode == 0 )
+ begin
+ Pre_XY_F_M <= #1 3'b010;
+ end
+ end
+ else if ((mcycle[6]) || (mcycle[5] && Mode == 1 && ISet != 2'b01) )
+ begin
+ mcycle <= #1 number_to_bitvec(Pre_XY_F_M + 1);
+ end
+ else if ((last_mcycle) ||
+ No_BTR == 1'b1 ||
+ (mcycle[1] && I_DJNZ == 1'b1 && IncDecZ == 1'b1) )
+ begin
+ m1_n <= #1 1'b0;
+ mcycle <= #1 7'b0000001;
+ IntCycle <= #1 1'b0;
+ NMICycle <= #1 1'b0;
+ if (NMI_s == 1'b1 && Prefix == 2'b00 )
+ begin
+ NMICycle <= #1 1'b1;
+ IntE_FF1 <= #1 1'b0;
+ end
+ else if ((IntE_FF1 == 1'b1 && INT_s == 1'b1) && Prefix == 2'b00 && SetEI == 1'b0 )
+ begin
+ IntCycle <= #1 1'b1;
+ IntE_FF1 <= #1 1'b0;
+ IntE_FF2 <= #1 1'b0;
+ end
+ end
+ else
+ begin
+ mcycle <= #1 { mcycle[5:0], mcycle[6] };
+ end
+ end
+ end
+ else
+ begin // verilog has no "nor" operator
+ if ( ~(Auto_Wait == 1'b1 && Auto_Wait_t2 == 1'b0) &&
+ ~(IOWait == 1 && iorq_i == 1'b1 && Auto_Wait_t1 == 1'b0) )
+ begin
+ tstate <= #1 { tstate[5:0], tstate[6] };
+ end
+ end
+ end
+ if (tstate[0])
+ begin
+ m1_n <= #1 1'b0;
+ end
+ end
+ end
+ end
+
+ always @(/*AUTOSENSE*/BTR_r or DI_Reg or IncDec_16 or JumpE or PC
+ or RegBusA or RegBusC or SP or tstate)
+ begin
+ if (JumpE == 1'b1 )
+ begin
+ PC16_B = { {8{DI_Reg[7]}}, DI_Reg };
+ end
+ else if (BTR_r == 1'b1 )
+ begin
+ PC16_B = -2;
+ end
+ else
+ begin
+ PC16_B = 1;
+ end
+
+ if (tstate[3])
+ begin
+ SP16_A = RegBusC;
+ SP16_B = { {8{DI_Reg[7]}}, DI_Reg };
+ end
+ else
+ begin
+ // suspect that ID16 and SP16 could be shared
+ SP16_A = SP;
+
+ if (IncDec_16[3] == 1'b1)
+ SP16_B = -1;
+ else
+ SP16_B = 1;
+ end
+
+ if (IncDec_16[3])
+ ID16_B = -1;
+ else
+ ID16_B = 1;
+
+ ID16 = RegBusA + ID16_B;
+ PC16 = PC + PC16_B;
+ SP16 = SP16_A + SP16_B;
+ end // always @ *
+
+
+ always @(/*AUTOSENSE*/IntCycle or NMICycle or mcycle)
+ begin
+ Auto_Wait = 1'b0;
+ if (IntCycle == 1'b1 || NMICycle == 1'b1 )
+ begin
+ if (mcycle[0] )
+ begin
+ Auto_Wait = 1'b1;
+ end
+ end
+ end // always @ *
+
+endmodule // T80
+
diff --git a/common/CPU/tv80/tv80_mcode.v b/common/CPU/tv80/tv80_mcode.v
new file mode 100644
index 00000000..40622d2b
--- /dev/null
+++ b/common/CPU/tv80/tv80_mcode.v
@@ -0,0 +1,2650 @@
+//
+// TV80 8-Bit Microprocessor Core
+// Based on the VHDL T80 core by Daniel Wallner (jesus@opencores.org)
+//
+// Copyright (c) 2004,2007 Guy Hutchison (ghutchis@opencores.org)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+module tv80_mcode
+ (/*AUTOARG*/
+ // Outputs
+ MCycles, TStates, Prefix, Inc_PC, Inc_WZ, IncDec_16, Read_To_Reg,
+ Read_To_Acc, Set_BusA_To, Set_BusB_To, ALU_Op, Save_ALU, PreserveC,
+ Arith16, Set_Addr_To, IORQ, Jump, JumpE, JumpXY, Call, RstP, LDZ,
+ LDW, LDSPHL, Special_LD, ExchangeDH, ExchangeRp, ExchangeAF,
+ ExchangeRS, I_DJNZ, I_CPL, I_CCF, I_SCF, I_RETN, I_BT, I_BC, I_BTR,
+ I_RLD, I_RRD, I_INRC, SetDI, SetEI, IMode, Halt, NoRead, Write,
+ // Inputs
+ IR, ISet, MCycle, F, NMICycle, IntCycle
+ );
+
+ parameter Mode = 0;
+ parameter Flag_C = 0;
+ parameter Flag_N = 1;
+ parameter Flag_P = 2;
+ parameter Flag_X = 3;
+ parameter Flag_H = 4;
+ parameter Flag_Y = 5;
+ parameter Flag_Z = 6;
+ parameter Flag_S = 7;
+
+ input [7:0] IR;
+ input [1:0] ISet ;
+ input [6:0] MCycle ;
+ input [7:0] F ;
+ input NMICycle ;
+ input IntCycle ;
+ output [2:0] MCycles ;
+ output [2:0] TStates ;
+ output [1:0] Prefix ; // None,BC,ED,DD/FD
+ output Inc_PC ;
+ output Inc_WZ ;
+ output [3:0] IncDec_16 ; // BC,DE,HL,SP 0 is inc
+ output Read_To_Reg ;
+ output Read_To_Acc ;
+ output [3:0] Set_BusA_To ; // B,C,D,E,H,L,DI/DB,A,SP(L),SP(M),0,F
+ output [3:0] Set_BusB_To ; // B,C,D,E,H,L,DI,A,SP(L),SP(M),1,F,PC(L),PC(M),0
+ output [3:0] ALU_Op ;
+ output Save_ALU ;
+ output PreserveC ;
+ output Arith16 ;
+ output [2:0] Set_Addr_To ; // aNone,aXY,aIOA,aSP,aBC,aDE,aZI
+ output IORQ ;
+ output Jump ;
+ output JumpE ;
+ output JumpXY ;
+ output Call ;
+ output RstP ;
+ output LDZ ;
+ output LDW ;
+ output LDSPHL ;
+ output [2:0] Special_LD ; // A,I;A,R;I,A;R,A;None
+ output ExchangeDH ;
+ output ExchangeRp ;
+ output ExchangeAF ;
+ output ExchangeRS ;
+ output I_DJNZ ;
+ output I_CPL ;
+ output I_CCF ;
+ output I_SCF ;
+ output I_RETN ;
+ output I_BT ;
+ output I_BC ;
+ output I_BTR ;
+ output I_RLD ;
+ output I_RRD ;
+ output I_INRC ;
+ output SetDI ;
+ output SetEI ;
+ output [1:0] IMode ;
+ output Halt ;
+ output NoRead ;
+ output Write ;
+
+ // regs
+ reg [2:0] MCycles ;
+ reg [2:0] TStates ;
+ reg [1:0] Prefix ; // None,BC,ED,DD/FD
+ reg Inc_PC ;
+ reg Inc_WZ ;
+ reg [3:0] IncDec_16 ; // BC,DE,HL,SP 0 is inc
+ reg Read_To_Reg ;
+ reg Read_To_Acc ;
+ reg [3:0] Set_BusA_To ; // B,C,D,E,H,L,DI/DB,A,SP(L),SP(M),0,F
+ reg [3:0] Set_BusB_To ; // B,C,D,E,H,L,DI,A,SP(L),SP(M),1,F,PC(L),PC(M),0
+ reg [3:0] ALU_Op ;
+ reg Save_ALU ;
+ reg PreserveC ;
+ reg Arith16 ;
+ reg [2:0] Set_Addr_To ; // aNone,aXY,aIOA,aSP,aBC,aDE,aZI
+ reg IORQ ;
+ reg Jump ;
+ reg JumpE ;
+ reg JumpXY ;
+ reg Call ;
+ reg RstP ;
+ reg LDZ ;
+ reg LDW ;
+ reg LDSPHL ;
+ reg [2:0] Special_LD ; // A,I;A,R;I,A;R,A;None
+ reg ExchangeDH ;
+ reg ExchangeRp ;
+ reg ExchangeAF ;
+ reg ExchangeRS ;
+ reg I_DJNZ ;
+ reg I_CPL ;
+ reg I_CCF ;
+ reg I_SCF ;
+ reg I_RETN ;
+ reg I_BT ;
+ reg I_BC ;
+ reg I_BTR ;
+ reg I_RLD ;
+ reg I_RRD ;
+ reg I_INRC ;
+ reg SetDI ;
+ reg SetEI ;
+ reg [1:0] IMode ;
+ reg Halt ;
+ reg NoRead ;
+ reg Write ;
+
+ parameter aNone = 3'b111;
+ parameter aBC = 3'b000;
+ parameter aDE = 3'b001;
+ parameter aXY = 3'b010;
+ parameter aIOA = 3'b100;
+ parameter aSP = 3'b101;
+ parameter aZI = 3'b110;
+ // constant aNone : std_logic_vector[2:0] = 3'b000;
+ // constant aXY : std_logic_vector[2:0] = 3'b001;
+ // constant aIOA : std_logic_vector[2:0] = 3'b010;
+ // constant aSP : std_logic_vector[2:0] = 3'b011;
+ // constant aBC : std_logic_vector[2:0] = 3'b100;
+ // constant aDE : std_logic_vector[2:0] = 3'b101;
+ // constant aZI : std_logic_vector[2:0] = 3'b110;
+
+ function is_cc_true;
+ input [7:0] FF;
+ input [2:0] cc;
+ begin
+ if (Mode == 3 )
+ begin
+ case (cc)
+ 3'b000 : is_cc_true = FF[7] == 1'b0; // NZ
+ 3'b001 : is_cc_true = FF[7] == 1'b1; // Z
+ 3'b010 : is_cc_true = FF[4] == 1'b0; // NC
+ 3'b011 : is_cc_true = FF[4] == 1'b1; // C
+ 3'b100 : is_cc_true = 0;
+ 3'b101 : is_cc_true = 0;
+ 3'b110 : is_cc_true = 0;
+ 3'b111 : is_cc_true = 0;
+ endcase
+ end
+ else
+ begin
+ case (cc)
+ 3'b000 : is_cc_true = FF[6] == 1'b0; // NZ
+ 3'b001 : is_cc_true = FF[6] == 1'b1; // Z
+ 3'b010 : is_cc_true = FF[0] == 1'b0; // NC
+ 3'b011 : is_cc_true = FF[0] == 1'b1; // C
+ 3'b100 : is_cc_true = FF[2] == 1'b0; // PO
+ 3'b101 : is_cc_true = FF[2] == 1'b1; // PE
+ 3'b110 : is_cc_true = FF[7] == 1'b0; // P
+ 3'b111 : is_cc_true = FF[7] == 1'b1; // M
+ endcase
+ end
+ end
+ endfunction // is_cc_true
+
+
+ reg [2:0] DDD;
+ reg [2:0] SSS;
+ reg [1:0] DPAIR;
+
+ always @ (/*AUTOSENSE*/F or IR or ISet or IntCycle or MCycle
+ or NMICycle)
+ begin
+ DDD = IR[5:3];
+ SSS = IR[2:0];
+ DPAIR = IR[5:4];
+
+ MCycles = 3'b001;
+ if (MCycle[0] )
+ begin
+ TStates = 3'b100;
+ end
+ else
+ begin
+ TStates = 3'b011;
+ end
+ Prefix = 2'b00;
+ Inc_PC = 1'b0;
+ Inc_WZ = 1'b0;
+ IncDec_16 = 4'b0000;
+ Read_To_Acc = 1'b0;
+ Read_To_Reg = 1'b0;
+ Set_BusB_To = 4'b0000;
+ Set_BusA_To = 4'b0000;
+ ALU_Op = { 1'b0, IR[5:3] };
+ Save_ALU = 1'b0;
+ PreserveC = 1'b0;
+ Arith16 = 1'b0;
+ IORQ = 1'b0;
+ Set_Addr_To = aNone;
+ Jump = 1'b0;
+ JumpE = 1'b0;
+ JumpXY = 1'b0;
+ Call = 1'b0;
+ RstP = 1'b0;
+ LDZ = 1'b0;
+ LDW = 1'b0;
+ LDSPHL = 1'b0;
+ Special_LD = 3'b000;
+ ExchangeDH = 1'b0;
+ ExchangeRp = 1'b0;
+ ExchangeAF = 1'b0;
+ ExchangeRS = 1'b0;
+ I_DJNZ = 1'b0;
+ I_CPL = 1'b0;
+ I_CCF = 1'b0;
+ I_SCF = 1'b0;
+ I_RETN = 1'b0;
+ I_BT = 1'b0;
+ I_BC = 1'b0;
+ I_BTR = 1'b0;
+ I_RLD = 1'b0;
+ I_RRD = 1'b0;
+ I_INRC = 1'b0;
+ SetDI = 1'b0;
+ SetEI = 1'b0;
+ IMode = 2'b11;
+ Halt = 1'b0;
+ NoRead = 1'b0;
+ Write = 1'b0;
+
+ case (ISet)
+ 2'b00 :
+ begin
+
+ //----------------------------------------------------------------------------
+ //
+ // Unprefixed instructions
+ //
+ //----------------------------------------------------------------------------
+
+ casez (IR)
+ // 8 BIT LOAD GROUP
+ 8'b01zzzzzz :
+ begin
+ if (IR[5:0] == 6'b110110)
+ Halt = 1'b1;
+ else if (IR[2:0] == 3'b110)
+ begin
+ // LD r,(HL)
+ MCycles = 3'b010;
+ if (MCycle[0])
+ Set_Addr_To = aXY;
+ if (MCycle[1])
+ begin
+ Set_BusA_To[2:0] = DDD;
+ Read_To_Reg = 1'b1;
+ end
+ end // if (IR[2:0] == 3'b110)
+ else if (IR[5:3] == 3'b110)
+ begin
+ // LD (HL),r
+ MCycles = 3'b010;
+ if (MCycle[0])
+ begin
+ Set_Addr_To = aXY;
+ Set_BusB_To[2:0] = SSS;
+ Set_BusB_To[3] = 1'b0;
+ end
+ if (MCycle[1])
+ Write = 1'b1;
+ end // if (IR[5:3] == 3'b110)
+ else
+ begin
+ Set_BusB_To[2:0] = SSS;
+ ExchangeRp = 1'b1;
+ Set_BusA_To[2:0] = DDD;
+ Read_To_Reg = 1'b1;
+ end // else: !if(IR[5:3] == 3'b110)
+ end // case: 8'b01zzzzzz
+
+ 8'b00zzz110 :
+ begin
+ if (IR[5:3] == 3'b110)
+ begin
+ // LD (HL),n
+ MCycles = 3'b011;
+ if (MCycle[1])
+ begin
+ Inc_PC = 1'b1;
+ Set_Addr_To = aXY;
+ Set_BusB_To[2:0] = SSS;
+ Set_BusB_To[3] = 1'b0;
+ end
+ if (MCycle[2])
+ Write = 1'b1;
+ end // if (IR[5:3] == 3'b110)
+ else
+ begin
+ // LD r,n
+ MCycles = 3'b010;
+ if (MCycle[1])
+ begin
+ Inc_PC = 1'b1;
+ Set_BusA_To[2:0] = DDD;
+ Read_To_Reg = 1'b1;
+ end
+ end
+ end
+
+ 8'b00001010 :
+ begin
+ // LD A,(BC)
+ MCycles = 3'b010;
+ if (MCycle[0])
+ Set_Addr_To = aBC;
+ if (MCycle[1])
+ Read_To_Acc = 1'b1;
+ end // case: 8'b00001010
+
+ 8'b00011010 :
+ begin
+ // LD A,(DE)
+ MCycles = 3'b010;
+ if (MCycle[0])
+ Set_Addr_To = aDE;
+ if (MCycle[1])
+ Read_To_Acc = 1'b1;
+ end // case: 8'b00011010
+
+ 8'b00111010 :
+ begin
+ if (Mode == 3 )
+ begin
+ // LDD A,(HL)
+ MCycles = 3'b010;
+ if (MCycle[0])
+ Set_Addr_To = aXY;
+ if (MCycle[1])
+ begin
+ Read_To_Acc = 1'b1;
+ IncDec_16 = 4'b1110;
+ end
+ end
+ else
+ begin
+ // LD A,(nn)
+ MCycles = 3'b100;
+ if (MCycle[1])
+ begin
+ Inc_PC = 1'b1;
+ LDZ = 1'b1;
+ end
+ if (MCycle[2])
+ begin
+ Set_Addr_To = aZI;
+ Inc_PC = 1'b1;
+ end
+ if (MCycle[3])
+ begin
+ Read_To_Acc = 1'b1;
+ end
+ end // else: !if(Mode == 3 )
+ end // case: 8'b00111010
+
+ 8'b00000010 :
+ begin
+ // LD (BC),A
+ MCycles = 3'b010;
+ if (MCycle[0])
+ begin
+ Set_Addr_To = aBC;
+ Set_BusB_To = 4'b0111;
+ end
+ if (MCycle[1])
+ begin
+ Write = 1'b1;
+ end
+ end // case: 8'b00000010
+
+ 8'b00010010 :
+ begin
+ // LD (DE),A
+ MCycles = 3'b010;
+ case (1'b1) // MCycle
+ MCycle[0] :
+ begin
+ Set_Addr_To = aDE;
+ Set_BusB_To = 4'b0111;
+ end
+ MCycle[1] :
+ Write = 1'b1;
+ default :;
+ endcase // case(MCycle)
+ end // case: 8'b00010010
+
+ 8'b00110010 :
+ begin
+ if (Mode == 3 )
+ begin
+ // LDD (HL),A
+ MCycles = 3'b010;
+ case (1'b1) // MCycle
+ MCycle[0] :
+ begin
+ Set_Addr_To = aXY;
+ Set_BusB_To = 4'b0111;
+ end
+ MCycle[1] :
+ begin
+ Write = 1'b1;
+ IncDec_16 = 4'b1110;
+ end
+ default :;
+ endcase // case(MCycle)
+
+ end
+ else
+ begin
+ // LD (nn),A
+ MCycles = 3'b100;
+ case (1'b1) // MCycle
+ MCycle[1] :
+ begin
+ Inc_PC = 1'b1;
+ LDZ = 1'b1;
+ end
+ MCycle[2] :
+ begin
+ Set_Addr_To = aZI;
+ Inc_PC = 1'b1;
+ Set_BusB_To = 4'b0111;
+ end
+ MCycle[3] :
+ begin
+ Write = 1'b1;
+ end
+ default :;
+ endcase
+ end // else: !if(Mode == 3 )
+ end // case: 8'b00110010
+
+
+ // 16 BIT LOAD GROUP
+ 8'b00000001,8'b00010001,8'b00100001,8'b00110001 :
+ begin
+ // LD dd,nn
+ MCycles = 3'b011;
+ case (1'b1) // MCycle
+ MCycle[1] :
+ begin
+ Inc_PC = 1'b1;
+ Read_To_Reg = 1'b1;
+ if (DPAIR == 2'b11 )
+ begin
+ Set_BusA_To[3:0] = 4'b1000;
+ end
+ else
+ begin
+ Set_BusA_To[2:1] = DPAIR;
+ Set_BusA_To[0] = 1'b1;
+ end
+ end // case: 2
+
+ MCycle[2] :
+ begin
+ Inc_PC = 1'b1;
+ Read_To_Reg = 1'b1;
+ if (DPAIR == 2'b11 )
+ begin
+ Set_BusA_To[3:0] = 4'b1001;
+ end
+ else
+ begin
+ Set_BusA_To[2:1] = DPAIR;
+ Set_BusA_To[0] = 1'b0;
+ end
+ end // case: 3
+
+ default :;
+ endcase // case(MCycle)
+ end // case: 8'b00000001,8'b00010001,8'b00100001,8'b00110001
+
+ 8'b00101010 :
+ begin
+ if (Mode == 3 )
+ begin
+ // LDI A,(HL)
+ MCycles = 3'b010;
+ case (1'b1) // MCycle
+ MCycle[0] :
+ Set_Addr_To = aXY;
+ MCycle[1] :
+ begin
+ Read_To_Acc = 1'b1;
+ IncDec_16 = 4'b0110;
+ end
+
+ default :;
+ endcase
+ end
+ else
+ begin
+ // LD HL,(nn)
+ MCycles = 3'b101;
+ case (1'b1) // MCycle
+ MCycle[1] :
+ begin
+ Inc_PC = 1'b1;
+ LDZ = 1'b1;
+ end
+ MCycle[2] :
+ begin
+ Set_Addr_To = aZI;
+ Inc_PC = 1'b1;
+ LDW = 1'b1;
+ end
+ MCycle[3] :
+ begin
+ Set_BusA_To[2:0] = 3'b101; // L
+ Read_To_Reg = 1'b1;
+ Inc_WZ = 1'b1;
+ Set_Addr_To = aZI;
+ end
+ MCycle[4] :
+ begin
+ Set_BusA_To[2:0] = 3'b100; // H
+ Read_To_Reg = 1'b1;
+ end
+ default :;
+ endcase
+ end // else: !if(Mode == 3 )
+ end // case: 8'b00101010
+
+ 8'b00100010 :
+ begin
+ if (Mode == 3 )
+ begin
+ // LDI (HL),A
+ MCycles = 3'b010;
+ case (1'b1) // MCycle
+ MCycle[0] :
+ begin
+ Set_Addr_To = aXY;
+ Set_BusB_To = 4'b0111;
+ end
+ MCycle[1] :
+ begin
+ Write = 1'b1;
+ IncDec_16 = 4'b0110;
+ end
+ default :;
+ endcase
+ end
+ else
+ begin
+ // LD (nn),HL
+ MCycles = 3'b101;
+ case (1'b1) // MCycle
+ MCycle[1] :
+ begin
+ Inc_PC = 1'b1;
+ LDZ = 1'b1;
+ end
+
+ MCycle[2] :
+ begin
+ Set_Addr_To = aZI;
+ Inc_PC = 1'b1;
+ LDW = 1'b1;
+ Set_BusB_To = 4'b0101; // L
+ end
+
+ MCycle[3] :
+ begin
+ Inc_WZ = 1'b1;
+ Set_Addr_To = aZI;
+ Write = 1'b1;
+ Set_BusB_To = 4'b0100; // H
+ end
+ MCycle[4] :
+ Write = 1'b1;
+ default :;
+ endcase
+ end // else: !if(Mode == 3 )
+ end // case: 8'b00100010
+
+ 8'b11111001 :
+ begin
+ // LD SP,HL
+ TStates = 3'b110;
+ LDSPHL = 1'b1;
+ end
+
+ 8'b11zz0101 :
+ begin
+ // PUSH qq
+ MCycles = 3'b011;
+ case (1'b1) // MCycle
+ MCycle[0] :
+ begin
+ TStates = 3'b101;
+ IncDec_16 = 4'b1111;
+ Set_Addr_To = aSP;
+ if (DPAIR == 2'b11 )
+ begin
+ Set_BusB_To = 4'b0111;
+ end
+ else
+ begin
+ Set_BusB_To[2:1] = DPAIR;
+ Set_BusB_To[0] = 1'b0;
+ Set_BusB_To[3] = 1'b0;
+ end
+ end // case: 1
+
+ MCycle[1] :
+ begin
+ IncDec_16 = 4'b1111;
+ Set_Addr_To = aSP;
+ if (DPAIR == 2'b11 )
+ begin
+ Set_BusB_To = 4'b1011;
+ end
+ else
+ begin
+ Set_BusB_To[2:1] = DPAIR;
+ Set_BusB_To[0] = 1'b1;
+ Set_BusB_To[3] = 1'b0;
+ end
+ Write = 1'b1;
+ end // case: 2
+
+ MCycle[2] :
+ Write = 1'b1;
+ default :;
+ endcase // case(MCycle)
+ end // case: 8'b11000101,8'b11010101,8'b11100101,8'b11110101
+
+ 8'b11zz0001 :
+ begin
+ // POP qq
+ MCycles = 3'b011;
+ case (1'b1) // MCycle
+ MCycle[0] :
+ Set_Addr_To = aSP;
+ MCycle[1] :
+ begin
+ IncDec_16 = 4'b0111;
+ Set_Addr_To = aSP;
+ Read_To_Reg = 1'b1;
+ if (DPAIR == 2'b11 )
+ begin
+ Set_BusA_To[3:0] = 4'b1011;
+ end
+ else
+ begin
+ Set_BusA_To[2:1] = DPAIR;
+ Set_BusA_To[0] = 1'b1;
+ end
+ end // case: 2
+
+ MCycle[2] :
+ begin
+ IncDec_16 = 4'b0111;
+ Read_To_Reg = 1'b1;
+ if (DPAIR == 2'b11 )
+ begin
+ Set_BusA_To[3:0] = 4'b0111;
+ end
+ else
+ begin
+ Set_BusA_To[2:1] = DPAIR;
+ Set_BusA_To[0] = 1'b0;
+ end
+ end // case: 3
+
+ default :;
+ endcase // case(MCycle)
+ end // case: 8'b11000001,8'b11010001,8'b11100001,8'b11110001
+
+
+ // EXCHANGE, BLOCK TRANSFER AND SEARCH GROUP
+ 8'b11101011 :
+ begin
+ if (Mode != 3 )
+ begin
+ // EX DE,HL
+ ExchangeDH = 1'b1;
+ end
+ end
+
+ 8'b00001000 :
+ begin
+ if (Mode == 3 )
+ begin
+ // LD (nn),SP
+ MCycles = 3'b101;
+ case (1'b1) // MCycle
+ MCycle[1] :
+ begin
+ Inc_PC = 1'b1;
+ LDZ = 1'b1;
+ end
+
+ MCycle[2] :
+ begin
+ Set_Addr_To = aZI;
+ Inc_PC = 1'b1;
+ LDW = 1'b1;
+ Set_BusB_To = 4'b1000;
+ end
+
+ MCycle[3] :
+ begin
+ Inc_WZ = 1'b1;
+ Set_Addr_To = aZI;
+ Write = 1'b1;
+ Set_BusB_To = 4'b1001;
+ end
+
+ MCycle[4] :
+ Write = 1'b1;
+ default :;
+ endcase
+ end
+ else if (Mode < 2 )
+ begin
+ // EX AF,AF'
+ ExchangeAF = 1'b1;
+ end
+ end // case: 8'b00001000
+
+ 8'b11011001 :
+ begin
+ if (Mode == 3 )
+ begin
+ // RETI
+ MCycles = 3'b011;
+ case (1'b1) // MCycle
+ MCycle[0] :
+ Set_Addr_To = aSP;
+ MCycle[1] :
+ begin
+ IncDec_16 = 4'b0111;
+ Set_Addr_To = aSP;
+ LDZ = 1'b1;
+ end
+
+ MCycle[2] :
+ begin
+ Jump = 1'b1;
+ IncDec_16 = 4'b0111;
+ I_RETN = 1'b1;
+ SetEI = 1'b1;
+ end
+ default :;
+ endcase
+ end
+ else if (Mode < 2 )
+ begin
+ // EXX
+ ExchangeRS = 1'b1;
+ end
+ end // case: 8'b11011001
+
+ 8'b11100011 :
+ begin
+ if (Mode != 3 )
+ begin
+ // EX (SP),HL
+ MCycles = 3'b101;
+ case (1'b1) // MCycle
+ MCycle[0] :
+ Set_Addr_To = aSP;
+ MCycle[1] :
+ begin
+ Read_To_Reg = 1'b1;
+ Set_BusA_To = 4'b0101;
+ Set_BusB_To = 4'b0101;
+ Set_Addr_To = aSP;
+ end
+ MCycle[2] :
+ begin
+ IncDec_16 = 4'b0111;
+ Set_Addr_To = aSP;
+ TStates = 3'b100;
+ Write = 1'b1;
+ end
+ MCycle[3] :
+ begin
+ Read_To_Reg = 1'b1;
+ Set_BusA_To = 4'b0100;
+ Set_BusB_To = 4'b0100;
+ Set_Addr_To = aSP;
+ end
+ MCycle[4] :
+ begin
+ IncDec_16 = 4'b1111;
+ TStates = 3'b101;
+ Write = 1'b1;
+ end
+
+ default :;
+ endcase
+ end // if (Mode != 3 )
+ end // case: 8'b11100011
+
+
+ // 8 BIT ARITHMETIC AND LOGICAL GROUP
+ 8'b10zzzzzz :
+ begin
+ if (IR[2:0] == 3'b110)
+ begin
+ // ADD A,(HL)
+ // ADC A,(HL)
+ // SUB A,(HL)
+ // SBC A,(HL)
+ // AND A,(HL)
+ // OR A,(HL)
+ // XOR A,(HL)
+ // CP A,(HL)
+ MCycles = 3'b010;
+ case (1'b1) // MCycle
+ MCycle[0] :
+ Set_Addr_To = aXY;
+ MCycle[1] :
+ begin
+ Read_To_Reg = 1'b1;
+ Save_ALU = 1'b1;
+ Set_BusB_To[2:0] = SSS;
+ Set_BusA_To[2:0] = 3'b111;
+ end
+
+ default :;
+ endcase // case(MCycle)
+ end // if (IR[2:0] == 3'b110)
+ else
+ begin
+ // ADD A,r
+ // ADC A,r
+ // SUB A,r
+ // SBC A,r
+ // AND A,r
+ // OR A,r
+ // XOR A,r
+ // CP A,r
+ Set_BusB_To[2:0] = SSS;
+ Set_BusA_To[2:0] = 3'b111;
+ Read_To_Reg = 1'b1;
+ Save_ALU = 1'b1;
+ end // else: !if(IR[2:0] == 3'b110)
+ end // case: 8'b10000000,8'b10000001,8'b10000010,8'b10000011,8'b10000100,8'b10000101,8'b10000111,...
+
+ 8'b11zzz110 :
+ begin
+ // ADD A,n
+ // ADC A,n
+ // SUB A,n
+ // SBC A,n
+ // AND A,n
+ // OR A,n
+ // XOR A,n
+ // CP A,n
+ MCycles = 3'b010;
+ if (MCycle[1] )
+ begin
+ Inc_PC = 1'b1;
+ Read_To_Reg = 1'b1;
+ Save_ALU = 1'b1;
+ Set_BusB_To[2:0] = SSS;
+ Set_BusA_To[2:0] = 3'b111;
+ end
+ end
+
+ 8'b00zzz100 :
+ begin
+ if (IR[5:3] == 3'b110)
+ begin
+ // INC (HL)
+ MCycles = 3'b011;
+ case (1'b1) // MCycle
+ MCycle[0] :
+ Set_Addr_To = aXY;
+ MCycle[1] :
+ begin
+ TStates = 3'b100;
+ Set_Addr_To = aXY;
+ Read_To_Reg = 1'b1;
+ Save_ALU = 1'b1;
+ PreserveC = 1'b1;
+ ALU_Op = 4'b0000;
+ Set_BusB_To = 4'b1010;
+ Set_BusA_To[2:0] = DDD;
+ end // case: 2
+
+ MCycle[2] :
+ Write = 1'b1;
+ default :;
+ endcase // case(MCycle)
+ end // case: 8'b00110100
+ else
+ begin
+ // INC r
+ Set_BusB_To = 4'b1010;
+ Set_BusA_To[2:0] = DDD;
+ Read_To_Reg = 1'b1;
+ Save_ALU = 1'b1;
+ PreserveC = 1'b1;
+ ALU_Op = 4'b0000;
+ end
+ end
+
+ 8'b00zzz101 :
+ begin
+ if (IR[5:3] == 3'b110)
+ begin
+ // DEC (HL)
+ MCycles = 3'b011;
+ case (1'b1) // MCycle
+ MCycle[0] :
+ Set_Addr_To = aXY;
+ MCycle[1] :
+ begin
+ TStates = 3'b100;
+ Set_Addr_To = aXY;
+ ALU_Op = 4'b0010;
+ Read_To_Reg = 1'b1;
+ Save_ALU = 1'b1;
+ PreserveC = 1'b1;
+ Set_BusB_To = 4'b1010;
+ Set_BusA_To[2:0] = DDD;
+ end // case: 2
+
+ MCycle[2] :
+ Write = 1'b1;
+ default :;
+ endcase // case(MCycle)
+ end
+ else
+ begin
+ // DEC r
+ Set_BusB_To = 4'b1010;
+ Set_BusA_To[2:0] = DDD;
+ Read_To_Reg = 1'b1;
+ Save_ALU = 1'b1;
+ PreserveC = 1'b1;
+ ALU_Op = 4'b0010;
+ end
+ end
+
+ // GENERAL PURPOSE ARITHMETIC AND CPU CONTROL GROUPS
+ 8'b00100111 :
+ begin
+ // DAA
+ Set_BusA_To[2:0] = 3'b111;
+ Read_To_Reg = 1'b1;
+ ALU_Op = 4'b1100;
+ Save_ALU = 1'b1;
+ end
+
+ 8'b00101111 :
+ // CPL
+ I_CPL = 1'b1;
+
+ 8'b00111111 :
+ // CCF
+ I_CCF = 1'b1;
+
+ 8'b00110111 :
+ // SCF
+ I_SCF = 1'b1;
+
+ 8'b00000000 :
+ begin
+ if (NMICycle == 1'b1 )
+ begin
+ // NMI
+ MCycles = 3'b011;
+ case (1'b1) // MCycle
+ MCycle[0] :
+ begin
+ TStates = 3'b101;
+ IncDec_16 = 4'b1111;
+ Set_Addr_To = aSP;
+ Set_BusB_To = 4'b1101;
+ end
+
+ MCycle[1] :
+ begin
+ TStates = 3'b100;
+ Write = 1'b1;
+ IncDec_16 = 4'b1111;
+ Set_Addr_To = aSP;
+ Set_BusB_To = 4'b1100;
+ end
+
+ MCycle[2] :
+ begin
+ TStates = 3'b100;
+ Write = 1'b1;
+ end
+
+ default :;
+ endcase // case(MCycle)
+
+ end
+ else if (IntCycle == 1'b1 )
+ begin
+ // INT (IM 2)
+ MCycles = 3'b101;
+ case (1'b1) // MCycle
+ MCycle[0] :
+ begin
+ LDZ = 1'b1;
+ TStates = 3'b101;
+ IncDec_16 = 4'b1111;
+ Set_Addr_To = aSP;
+ Set_BusB_To = 4'b1101;
+ end
+
+ MCycle[1] :
+ begin
+ TStates = 3'b100;
+ Write = 1'b1;
+ IncDec_16 = 4'b1111;
+ Set_Addr_To = aSP;
+ Set_BusB_To = 4'b1100;
+ end
+
+ MCycle[2] :
+ begin
+ TStates = 3'b100;
+ Write = 1'b1;
+ end
+
+ MCycle[3] :
+ begin
+ Inc_PC = 1'b1;
+ LDZ = 1'b1;
+ end
+
+ MCycle[4] :
+ Jump = 1'b1;
+ default :;
+ endcase
+ end
+ end // case: 8'b00000000
+
+ 8'b11110011 :
+ // DI
+ SetDI = 1'b1;
+
+ 8'b11111011 :
+ // EI
+ SetEI = 1'b1;
+
+ // 16 BIT ARITHMETIC GROUP
+ 8'b00zz1001 :
+ begin
+ // ADD HL,ss
+ MCycles = 3'b011;
+ case (1'b1) // MCycle
+ MCycle[1] :
+ begin
+ NoRead = 1'b1;
+ ALU_Op = 4'b0000;
+ Read_To_Reg = 1'b1;
+ Save_ALU = 1'b1;
+ Set_BusA_To[2:0] = 3'b101;
+ case (IR[5:4])
+ 0,1,2 :
+ begin
+ Set_BusB_To[2:1] = IR[5:4];
+ Set_BusB_To[0] = 1'b1;
+ end
+
+ default :
+ Set_BusB_To = 4'b1000;
+ endcase // case(IR[5:4])
+
+ TStates = 3'b100;
+ Arith16 = 1'b1;
+ end // case: 2
+
+ MCycle[2] :
+ begin
+ NoRead = 1'b1;
+ Read_To_Reg = 1'b1;
+ Save_ALU = 1'b1;
+ ALU_Op = 4'b0001;
+ Set_BusA_To[2:0] = 3'b100;
+ case (IR[5:4])
+ 0,1,2 :
+ Set_BusB_To[2:1] = IR[5:4];
+ default :
+ Set_BusB_To = 4'b1001;
+ endcase
+ Arith16 = 1'b1;
+ end // case: 3
+
+ default :;
+ endcase // case(MCycle)
+ end // case: 8'b00001001,8'b00011001,8'b00101001,8'b00111001
+
+ 8'b00zz0011 :
+ begin
+ // INC ss
+ TStates = 3'b110;
+ IncDec_16[3:2] = 2'b01;
+ IncDec_16[1:0] = DPAIR;
+ end
+
+ 8'b00zz1011 :
+ begin
+ // DEC ss
+ TStates = 3'b110;
+ IncDec_16[3:2] = 2'b11;
+ IncDec_16[1:0] = DPAIR;
+ end
+
+ // ROTATE AND SHIFT GROUP
+ 8'b00000111,
+ // RLCA
+ 8'b00010111,
+ // RLA
+ 8'b00001111,
+ // RRCA
+ 8'b00011111 :
+ // RRA
+ begin
+ Set_BusA_To[2:0] = 3'b111;
+ ALU_Op = 4'b1000;
+ Read_To_Reg = 1'b1;
+ Save_ALU = 1'b1;
+ end // case: 8'b00000111,...
+
+
+ // JUMP GROUP
+ 8'b11000011 :
+ begin
+ // JP nn
+ MCycles = 3'b011;
+ if (MCycle[1])
+ begin
+ Inc_PC = 1'b1;
+ LDZ = 1'b1;
+ end
+
+ if (MCycle[2])
+ begin
+ Inc_PC = 1'b1;
+ Jump = 1'b1;
+ end
+
+ end // case: 8'b11000011
+
+ 8'b11zzz010 :
+ begin
+ if (IR[5] == 1'b1 && Mode == 3 )
+ begin
+ case (IR[4:3])
+ 2'b00 :
+ begin
+ // LD ($FF00+C),A
+ MCycles = 3'b010;
+ case (1'b1) // MCycle
+ MCycle[0] :
+ begin
+ Set_Addr_To = aBC;
+ Set_BusB_To = 4'b0111;
+ end
+ MCycle[1] :
+ begin
+ Write = 1'b1;
+ IORQ = 1'b1;
+ end
+
+ default :;
+ endcase // case(MCycle)
+ end // case: 2'b00
+
+ 2'b01 :
+ begin
+ // LD (nn),A
+ MCycles = 3'b100;
+ case (1'b1) // MCycle
+ MCycle[1] :
+ begin
+ Inc_PC = 1'b1;
+ LDZ = 1'b1;
+ end
+
+ MCycle[2] :
+ begin
+ Set_Addr_To = aZI;
+ Inc_PC = 1'b1;
+ Set_BusB_To = 4'b0111;
+ end
+
+ MCycle[3] :
+ Write = 1'b1;
+ default :;
+ endcase // case(MCycle)
+ end // case: default :...
+
+ 2'b10 :
+ begin
+ // LD A,($FF00+C)
+ MCycles = 3'b010;
+ case (1'b1) // MCycle
+ MCycle[0] :
+ Set_Addr_To = aBC;
+ MCycle[1] :
+ begin
+ Read_To_Acc = 1'b1;
+ IORQ = 1'b1;
+ end
+ default :;
+ endcase // case(MCycle)
+ end // case: 2'b10
+
+ 2'b11 :
+ begin
+ // LD A,(nn)
+ MCycles = 3'b100;
+ case (1'b1) // MCycle
+ MCycle[1] :
+ begin
+ Inc_PC = 1'b1;
+ LDZ = 1'b1;
+ end
+ MCycle[2] :
+ begin
+ Set_Addr_To = aZI;
+ Inc_PC = 1'b1;
+ end
+ MCycle[3] :
+ Read_To_Acc = 1'b1;
+ default :;
+ endcase // case(MCycle)
+ end
+ endcase
+ end
+ else
+ begin
+ // JP cc,nn
+ MCycles = 3'b011;
+ case (1'b1) // MCycle
+ MCycle[1] :
+ begin
+ Inc_PC = 1'b1;
+ LDZ = 1'b1;
+ end
+ MCycle[2] :
+ begin
+ Inc_PC = 1'b1;
+ if (is_cc_true(F, IR[5:3]) )
+ begin
+ Jump = 1'b1;
+ end
+ end
+
+ default :;
+ endcase
+ end // else: !if(DPAIR == 2'b11 )
+ end // case: 8'b11000010,8'b11001010,8'b11010010,8'b11011010,8'b11100010,8'b11101010,8'b11110010,8'b11111010
+
+ 8'b00011000 :
+ begin
+ if (Mode != 2 )
+ begin
+ // JR e
+ MCycles = 3'b011;
+ case (1'b1) // MCycle
+ MCycle[1] :
+ Inc_PC = 1'b1;
+ MCycle[2] :
+ begin
+ NoRead = 1'b1;
+ JumpE = 1'b1;
+ TStates = 3'b101;
+ end
+ default :;
+ endcase
+ end // if (Mode != 2 )
+ end // case: 8'b00011000
+
+ // Conditional relative jumps (JR [C/NC/Z/NZ], e)
+ 8'b001zz000 :
+ begin
+ if (Mode != 2 )
+ begin
+ MCycles = 3'd3;
+ case (1'b1) // MCycle
+ MCycle[1] :
+ begin
+ Inc_PC = 1'b1;
+
+ case (IR[4:3])
+ 0 : MCycles = (F[Flag_Z]) ? 3'd2 : 3'd3;
+ 1 : MCycles = (!F[Flag_Z]) ? 3'd2 : 3'd3;
+ 2 : MCycles = (F[Flag_C]) ? 3'd2 : 3'd3;
+ 3 : MCycles = (!F[Flag_C]) ? 3'd2 : 3'd3;
+ endcase
+ end
+
+ MCycle[2] :
+ begin
+ NoRead = 1'b1;
+ JumpE = 1'b1;
+ TStates = 3'd5;
+ end
+ default :;
+ endcase
+ end // if (Mode != 2 )
+ end // case: 8'b00111000
+
+ 8'b11101001 :
+ // JP (HL)
+ JumpXY = 1'b1;
+
+ 8'b00010000 :
+ begin
+ if (Mode == 3 )
+ begin
+ I_DJNZ = 1'b1;
+ end
+ else if (Mode < 2 )
+ begin
+ // DJNZ,e
+ MCycles = 3'b011;
+ case (1'b1) // MCycle
+ MCycle[0] :
+ begin
+ TStates = 3'b101;
+ I_DJNZ = 1'b1;
+ Set_BusB_To = 4'b1010;
+ Set_BusA_To[2:0] = 3'b000;
+ Read_To_Reg = 1'b1;
+ Save_ALU = 1'b1;
+ ALU_Op = 4'b0010;
+ end
+ MCycle[1] :
+ begin
+ I_DJNZ = 1'b1;
+ Inc_PC = 1'b1;
+ end
+ MCycle[2] :
+ begin
+ NoRead = 1'b1;
+ JumpE = 1'b1;
+ TStates = 3'b101;
+ end
+ default :;
+ endcase
+ end // if (Mode < 2 )
+ end // case: 8'b00010000
+
+
+ // CALL AND RETURN GROUP
+ 8'b11001101 :
+ begin
+ // CALL nn
+ MCycles = 3'b101;
+ case (1'b1) // MCycle
+ MCycle[1] :
+ begin
+ Inc_PC = 1'b1;
+ LDZ = 1'b1;
+ end
+ MCycle[2] :
+ begin
+ IncDec_16 = 4'b1111;
+ Inc_PC = 1'b1;
+ TStates = 3'b100;
+ Set_Addr_To = aSP;
+ LDW = 1'b1;
+ Set_BusB_To = 4'b1101;
+ end
+ MCycle[3] :
+ begin
+ Write = 1'b1;
+ IncDec_16 = 4'b1111;
+ Set_Addr_To = aSP;
+ Set_BusB_To = 4'b1100;
+ end
+ MCycle[4] :
+ begin
+ Write = 1'b1;
+ Call = 1'b1;
+ end
+ default :;
+ endcase // case(MCycle)
+ end // case: 8'b11001101
+
+ 8'b11zzz100 :
+ begin
+ if (IR[5] == 1'b0 || Mode != 3 )
+ begin
+ // CALL cc,nn
+ MCycles = 3'b101;
+ case (1'b1) // MCycle
+ MCycle[1] :
+ begin
+ Inc_PC = 1'b1;
+ LDZ = 1'b1;
+ end
+ MCycle[2] :
+ begin
+ Inc_PC = 1'b1;
+ LDW = 1'b1;
+ if (is_cc_true(F, IR[5:3]) )
+ begin
+ IncDec_16 = 4'b1111;
+ Set_Addr_To = aSP;
+ TStates = 3'b100;
+ Set_BusB_To = 4'b1101;
+ end
+ else
+ begin
+ MCycles = 3'b011;
+ end // else: !if(is_cc_true(F, IR[5:3]) )
+ end // case: 3
+
+ MCycle[3] :
+ begin
+ Write = 1'b1;
+ IncDec_16 = 4'b1111;
+ Set_Addr_To = aSP;
+ Set_BusB_To = 4'b1100;
+ end
+
+ MCycle[4] :
+ begin
+ Write = 1'b1;
+ Call = 1'b1;
+ end
+
+ default :;
+ endcase
+ end // if (IR[5] == 1'b0 || Mode != 3 )
+ end // case: 8'b11000100,8'b11001100,8'b11010100,8'b11011100,8'b11100100,8'b11101100,8'b11110100,8'b11111100
+
+ 8'b11001001 :
+ begin
+ // RET
+ MCycles = 3'b011;
+ case (1'b1) // MCycle
+ MCycle[0] :
+ begin
+ TStates = 3'b101;
+ Set_Addr_To = aSP;
+ end
+
+ MCycle[1] :
+ begin
+ IncDec_16 = 4'b0111;
+ Set_Addr_To = aSP;
+ LDZ = 1'b1;
+ end
+
+ MCycle[2] :
+ begin
+ Jump = 1'b1;
+ IncDec_16 = 4'b0111;
+ end
+
+ default :;
+ endcase // case(MCycle)
+ end // case: 8'b11001001
+
+ 8'b11000000,8'b11001000,8'b11010000,8'b11011000,8'b11100000,8'b11101000,8'b11110000,8'b11111000 :
+ begin
+ if (IR[5] == 1'b1 && Mode == 3 )
+ begin
+ case (IR[4:3])
+ 2'b00 :
+ begin
+ // LD ($FF00+nn),A
+ MCycles = 3'b011;
+ case (1'b1) // MCycle
+ MCycle[1] :
+ begin
+ Inc_PC = 1'b1;
+ Set_Addr_To = aIOA;
+ Set_BusB_To = 4'b0111;
+ end
+
+ MCycle[2] :
+ Write = 1'b1;
+ default :;
+ endcase // case(MCycle)
+ end // case: 2'b00
+
+ 2'b01 :
+ begin
+ // ADD SP,n
+ MCycles = 3'b011;
+ case (1'b1) // MCycle
+ MCycle[1] :
+ begin
+ ALU_Op = 4'b0000;
+ Inc_PC = 1'b1;
+ Read_To_Reg = 1'b1;
+ Save_ALU = 1'b1;
+ Set_BusA_To = 4'b1000;
+ Set_BusB_To = 4'b0110;
+ end
+
+ MCycle[2] :
+ begin
+ NoRead = 1'b1;
+ Read_To_Reg = 1'b1;
+ Save_ALU = 1'b1;
+ ALU_Op = 4'b0001;
+ Set_BusA_To = 4'b1001;
+ Set_BusB_To = 4'b1110; // Incorrect unsigned !!!!!!!!!!!!!!!!!!!!!
+ end
+
+ default :;
+ endcase // case(MCycle)
+ end // case: 2'b01
+
+ 2'b10 :
+ begin
+ // LD A,($FF00+nn)
+ MCycles = 3'b011;
+ case (1'b1) // MCycle
+ MCycle[1] :
+ begin
+ Inc_PC = 1'b1;
+ Set_Addr_To = aIOA;
+ end
+
+ MCycle[2] :
+ Read_To_Acc = 1'b1;
+ default :;
+ endcase // case(MCycle)
+ end // case: 2'b10
+
+ 2'b11 :
+ begin
+ // LD HL,SP+n -- Not correct !!!!!!!!!!!!!!!!!!!
+ MCycles = 3'b101;
+ case (1'b1) // MCycle
+ MCycle[1] :
+ begin
+ Inc_PC = 1'b1;
+ LDZ = 1'b1;
+ end
+
+ MCycle[2] :
+ begin
+ Set_Addr_To = aZI;
+ Inc_PC = 1'b1;
+ LDW = 1'b1;
+ end
+
+ MCycle[3] :
+ begin
+ Set_BusA_To[2:0] = 3'b101; // L
+ Read_To_Reg = 1'b1;
+ Inc_WZ = 1'b1;
+ Set_Addr_To = aZI;
+ end
+
+ MCycle[4] :
+ begin
+ Set_BusA_To[2:0] = 3'b100; // H
+ Read_To_Reg = 1'b1;
+ end
+
+ default :;
+ endcase // case(MCycle)
+ end // case: 2'b11
+
+ endcase // case(IR[4:3])
+
+ end
+ else
+ begin
+ // RET cc
+ MCycles = 3'b011;
+ case (1'b1) // MCycle
+ MCycle[0] :
+ begin
+ if (is_cc_true(F, IR[5:3]) )
+ begin
+ Set_Addr_To = aSP;
+ end
+ else
+ begin
+ MCycles = 3'b001;
+ end
+ TStates = 3'b101;
+ end // case: 1
+
+ MCycle[1] :
+ begin
+ IncDec_16 = 4'b0111;
+ Set_Addr_To = aSP;
+ LDZ = 1'b1;
+ end
+ MCycle[2] :
+ begin
+ Jump = 1'b1;
+ IncDec_16 = 4'b0111;
+ end
+ default :;
+ endcase
+ end // else: !if(IR[5] == 1'b1 && Mode == 3 )
+ end // case: 8'b11000000,8'b11001000,8'b11010000,8'b11011000,8'b11100000,8'b11101000,8'b11110000,8'b11111000
+
+ 8'b11000111,8'b11001111,8'b11010111,8'b11011111,8'b11100111,8'b11101111,8'b11110111,8'b11111111 :
+ begin
+ // RST p
+ MCycles = 3'b011;
+ case (1'b1) // MCycle
+ MCycle[0] :
+ begin
+ TStates = 3'b101;
+ IncDec_16 = 4'b1111;
+ Set_Addr_To = aSP;
+ Set_BusB_To = 4'b1101;
+ end
+
+ MCycle[1] :
+ begin
+ Write = 1'b1;
+ IncDec_16 = 4'b1111;
+ Set_Addr_To = aSP;
+ Set_BusB_To = 4'b1100;
+ end
+
+ MCycle[2] :
+ begin
+ Write = 1'b1;
+ RstP = 1'b1;
+ end
+
+ default :;
+ endcase // case(MCycle)
+ end // case: 8'b11000111,8'b11001111,8'b11010111,8'b11011111,8'b11100111,8'b11101111,8'b11110111,8'b11111111
+
+ // INPUT AND OUTPUT GROUP
+ 8'b11011011 :
+ begin
+ if (Mode != 3 )
+ begin
+ // IN A,(n)
+ MCycles = 3'b011;
+ case (1'b1) // MCycle
+ MCycle[1] :
+ begin
+ Inc_PC = 1'b1;
+ Set_Addr_To = aIOA;
+ end
+
+ MCycle[2] :
+ begin
+ Read_To_Acc = 1'b1;
+ IORQ = 1'b1;
+ end
+
+ default :;
+ endcase
+ end // if (Mode != 3 )
+ end // case: 8'b11011011
+
+ 8'b11010011 :
+ begin
+ if (Mode != 3 )
+ begin
+ // OUT (n),A
+ MCycles = 3'b011;
+ case (1'b1) // MCycle
+ MCycle[1] :
+ begin
+ Inc_PC = 1'b1;
+ Set_Addr_To = aIOA;
+ Set_BusB_To = 4'b0111;
+ end
+
+ MCycle[2] :
+ begin
+ Write = 1'b1;
+ IORQ = 1'b1;
+ end
+
+ default :;
+ endcase
+ end // if (Mode != 3 )
+ end // case: 8'b11010011
+
+
+ //----------------------------------------------------------------------------
+ //----------------------------------------------------------------------------
+ // MULTIBYTE INSTRUCTIONS
+ //----------------------------------------------------------------------------
+ //----------------------------------------------------------------------------
+
+ 8'b11001011 :
+ begin
+ if (Mode != 2 )
+ begin
+ Prefix = 2'b01;
+ end
+ end
+
+ 8'b11101101 :
+ begin
+ if (Mode < 2 )
+ begin
+ Prefix = 2'b10;
+ end
+ end
+
+ 8'b11011101,8'b11111101 :
+ begin
+ if (Mode < 2 )
+ begin
+ Prefix = 2'b11;
+ end
+ end
+
+ endcase // case(IR)
+ end // case: 2'b00
+
+
+ 2'b01 :
+ begin
+
+
+ //----------------------------------------------------------------------------
+ //
+ // CB prefixed instructions
+ //
+ //----------------------------------------------------------------------------
+
+ Set_BusA_To[2:0] = IR[2:0];
+ Set_BusB_To[2:0] = IR[2:0];
+
+ casez (IR)
+ 8'b00000000,8'b00000001,8'b00000010,8'b00000011,8'b00000100,8'b00000101,8'b00000111,
+ 8'b00010000,8'b00010001,8'b00010010,8'b00010011,8'b00010100,8'b00010101,8'b00010111,
+ 8'b00001000,8'b00001001,8'b00001010,8'b00001011,8'b00001100,8'b00001101,8'b00001111,
+ 8'b00011000,8'b00011001,8'b00011010,8'b00011011,8'b00011100,8'b00011101,8'b00011111,
+ 8'b00100000,8'b00100001,8'b00100010,8'b00100011,8'b00100100,8'b00100101,8'b00100111,
+ 8'b00101000,8'b00101001,8'b00101010,8'b00101011,8'b00101100,8'b00101101,8'b00101111,
+ 8'b00110000,8'b00110001,8'b00110010,8'b00110011,8'b00110100,8'b00110101,8'b00110111,
+ 8'b00111000,8'b00111001,8'b00111010,8'b00111011,8'b00111100,8'b00111101,8'b00111111 :
+ begin
+ // RLC r
+ // RL r
+ // RRC r
+ // RR r
+ // SLA r
+ // SRA r
+ // SRL r
+ // SLL r (Undocumented) / SWAP r
+ if (MCycle[0] ) begin
+ ALU_Op = 4'b1000;
+ Read_To_Reg = 1'b1;
+ Save_ALU = 1'b1;
+ end
+ end // case: 8'b00000000,8'b00000001,8'b00000010,8'b00000011,8'b00000100,8'b00000101,8'b00000111,...
+
+ 8'b00zzz110 :
+ begin
+ // RLC (HL)
+ // RL (HL)
+ // RRC (HL)
+ // RR (HL)
+ // SRA (HL)
+ // SRL (HL)
+ // SLA (HL)
+ // SLL (HL) (Undocumented) / SWAP (HL)
+ MCycles = 3'b011;
+ case (1'b1) // MCycle
+ MCycle[0], MCycle[6] :
+ Set_Addr_To = aXY;
+ MCycle[1] :
+ begin
+ ALU_Op = 4'b1000;
+ Read_To_Reg = 1'b1;
+ Save_ALU = 1'b1;
+ Set_Addr_To = aXY;
+ TStates = 3'b100;
+ end
+
+ MCycle[2] :
+ Write = 1'b1;
+ default :;
+ endcase // case(MCycle)
+ end // case: 8'b00000110,8'b00010110,8'b00001110,8'b00011110,8'b00101110,8'b00111110,8'b00100110,8'b00110110
+
+ 8'b01000000,8'b01000001,8'b01000010,8'b01000011,8'b01000100,8'b01000101,8'b01000111,
+ 8'b01001000,8'b01001001,8'b01001010,8'b01001011,8'b01001100,8'b01001101,8'b01001111,
+ 8'b01010000,8'b01010001,8'b01010010,8'b01010011,8'b01010100,8'b01010101,8'b01010111,
+ 8'b01011000,8'b01011001,8'b01011010,8'b01011011,8'b01011100,8'b01011101,8'b01011111,
+ 8'b01100000,8'b01100001,8'b01100010,8'b01100011,8'b01100100,8'b01100101,8'b01100111,
+ 8'b01101000,8'b01101001,8'b01101010,8'b01101011,8'b01101100,8'b01101101,8'b01101111,
+ 8'b01110000,8'b01110001,8'b01110010,8'b01110011,8'b01110100,8'b01110101,8'b01110111,
+ 8'b01111000,8'b01111001,8'b01111010,8'b01111011,8'b01111100,8'b01111101,8'b01111111 :
+ begin
+ // BIT b,r
+ if (MCycle[0] )
+ begin
+ Set_BusB_To[2:0] = IR[2:0];
+ ALU_Op = 4'b1001;
+ end
+ end // case: 8'b01000000,8'b01000001,8'b01000010,8'b01000011,8'b01000100,8'b01000101,8'b01000111,...
+
+ 8'b01000110,8'b01001110,8'b01010110,8'b01011110,8'b01100110,8'b01101110,8'b01110110,8'b01111110 :
+ begin
+ // BIT b,(HL)
+ MCycles = 3'b010;
+ case (1'b1) // MCycle
+ MCycle[0], MCycle[6] :
+ Set_Addr_To = aXY;
+ MCycle[1] :
+ begin
+ ALU_Op = 4'b1001;
+ TStates = 3'b100;
+ end
+
+ default :;
+ endcase // case(MCycle)
+ end // case: 8'b01000110,8'b01001110,8'b01010110,8'b01011110,8'b01100110,8'b01101110,8'b01110110,8'b01111110
+
+ 8'b11000000,8'b11000001,8'b11000010,8'b11000011,8'b11000100,8'b11000101,8'b11000111,
+ 8'b11001000,8'b11001001,8'b11001010,8'b11001011,8'b11001100,8'b11001101,8'b11001111,
+ 8'b11010000,8'b11010001,8'b11010010,8'b11010011,8'b11010100,8'b11010101,8'b11010111,
+ 8'b11011000,8'b11011001,8'b11011010,8'b11011011,8'b11011100,8'b11011101,8'b11011111,
+ 8'b11100000,8'b11100001,8'b11100010,8'b11100011,8'b11100100,8'b11100101,8'b11100111,
+ 8'b11101000,8'b11101001,8'b11101010,8'b11101011,8'b11101100,8'b11101101,8'b11101111,
+ 8'b11110000,8'b11110001,8'b11110010,8'b11110011,8'b11110100,8'b11110101,8'b11110111,
+ 8'b11111000,8'b11111001,8'b11111010,8'b11111011,8'b11111100,8'b11111101,8'b11111111 :
+ begin
+ // SET b,r
+ if (MCycle[0] )
+ begin
+ ALU_Op = 4'b1010;
+ Read_To_Reg = 1'b1;
+ Save_ALU = 1'b1;
+ end
+ end // case: 8'b11000000,8'b11000001,8'b11000010,8'b11000011,8'b11000100,8'b11000101,8'b11000111,...
+
+ 8'b11000110,8'b11001110,8'b11010110,8'b11011110,8'b11100110,8'b11101110,8'b11110110,8'b11111110 :
+ begin
+ // SET b,(HL)
+ MCycles = 3'b011;
+ case (1'b1) // MCycle
+ MCycle[0], MCycle[6] :
+ Set_Addr_To = aXY;
+ MCycle[1] :
+ begin
+ ALU_Op = 4'b1010;
+ Read_To_Reg = 1'b1;
+ Save_ALU = 1'b1;
+ Set_Addr_To = aXY;
+ TStates = 3'b100;
+ end
+ MCycle[2] :
+ Write = 1'b1;
+ default :;
+ endcase // case(MCycle)
+ end // case: 8'b11000110,8'b11001110,8'b11010110,8'b11011110,8'b11100110,8'b11101110,8'b11110110,8'b11111110
+
+ 8'b10000000,8'b10000001,8'b10000010,8'b10000011,8'b10000100,8'b10000101,8'b10000111,
+ 8'b10001000,8'b10001001,8'b10001010,8'b10001011,8'b10001100,8'b10001101,8'b10001111,
+ 8'b10010000,8'b10010001,8'b10010010,8'b10010011,8'b10010100,8'b10010101,8'b10010111,
+ 8'b10011000,8'b10011001,8'b10011010,8'b10011011,8'b10011100,8'b10011101,8'b10011111,
+ 8'b10100000,8'b10100001,8'b10100010,8'b10100011,8'b10100100,8'b10100101,8'b10100111,
+ 8'b10101000,8'b10101001,8'b10101010,8'b10101011,8'b10101100,8'b10101101,8'b10101111,
+ 8'b10110000,8'b10110001,8'b10110010,8'b10110011,8'b10110100,8'b10110101,8'b10110111,
+ 8'b10111000,8'b10111001,8'b10111010,8'b10111011,8'b10111100,8'b10111101,8'b10111111 :
+ begin
+ // RES b,r
+ if (MCycle[0] )
+ begin
+ ALU_Op = 4'b1011;
+ Read_To_Reg = 1'b1;
+ Save_ALU = 1'b1;
+ end
+ end // case: 8'b10000000,8'b10000001,8'b10000010,8'b10000011,8'b10000100,8'b10000101,8'b10000111,...
+
+ 8'b10000110,8'b10001110,8'b10010110,8'b10011110,8'b10100110,8'b10101110,8'b10110110,8'b10111110 :
+ begin
+ // RES b,(HL)
+ MCycles = 3'b011;
+ case (1'b1) // MCycle
+ MCycle[0], MCycle[6] :
+ Set_Addr_To = aXY;
+ MCycle[1] :
+ begin
+ ALU_Op = 4'b1011;
+ Read_To_Reg = 1'b1;
+ Save_ALU = 1'b1;
+ Set_Addr_To = aXY;
+ TStates = 3'b100;
+ end
+
+ MCycle[2] :
+ Write = 1'b1;
+ default :;
+ endcase // case(MCycle)
+ end // case: 8'b10000110,8'b10001110,8'b10010110,8'b10011110,8'b10100110,8'b10101110,8'b10110110,8'b10111110
+
+ endcase // case(IR)
+ end // case: 2'b01
+
+
+ default :
+ begin : default_ed_block
+
+ //----------------------------------------------------------------------------
+ //
+ // ED prefixed instructions
+ //
+ //----------------------------------------------------------------------------
+
+ casez (IR)
+ /*
+ * Undocumented NOP instructions commented out to reduce size of mcode
+ *
+ 8'b00000000,8'b00000001,8'b00000010,8'b00000011,8'b00000100,8'b00000101,8'b00000110,8'b00000111
+ ,8'b00001000,8'b00001001,8'b00001010,8'b00001011,8'b00001100,8'b00001101,8'b00001110,8'b00001111
+ ,8'b00010000,8'b00010001,8'b00010010,8'b00010011,8'b00010100,8'b00010101,8'b00010110,8'b00010111
+ ,8'b00011000,8'b00011001,8'b00011010,8'b00011011,8'b00011100,8'b00011101,8'b00011110,8'b00011111
+ ,8'b00100000,8'b00100001,8'b00100010,8'b00100011,8'b00100100,8'b00100101,8'b00100110,8'b00100111
+ ,8'b00101000,8'b00101001,8'b00101010,8'b00101011,8'b00101100,8'b00101101,8'b00101110,8'b00101111
+ ,8'b00110000,8'b00110001,8'b00110010,8'b00110011,8'b00110100,8'b00110101,8'b00110110,8'b00110111
+ ,8'b00111000,8'b00111001,8'b00111010,8'b00111011,8'b00111100,8'b00111101,8'b00111110,8'b00111111
+
+
+ ,8'b10000000,8'b10000001,8'b10000010,8'b10000011,8'b10000100,8'b10000101,8'b10000110,8'b10000111
+ ,8'b10001000,8'b10001001,8'b10001010,8'b10001011,8'b10001100,8'b10001101,8'b10001110,8'b10001111
+ ,8'b10010000,8'b10010001,8'b10010010,8'b10010011,8'b10010100,8'b10010101,8'b10010110,8'b10010111
+ ,8'b10011000,8'b10011001,8'b10011010,8'b10011011,8'b10011100,8'b10011101,8'b10011110,8'b10011111
+ , 8'b10100100,8'b10100101,8'b10100110,8'b10100111
+ , 8'b10101100,8'b10101101,8'b10101110,8'b10101111
+ , 8'b10110100,8'b10110101,8'b10110110,8'b10110111
+ , 8'b10111100,8'b10111101,8'b10111110,8'b10111111
+ ,8'b11000000,8'b11000001,8'b11000010,8'b11000011,8'b11000100,8'b11000101,8'b11000110,8'b11000111
+ ,8'b11001000,8'b11001001,8'b11001010,8'b11001011,8'b11001100,8'b11001101,8'b11001110,8'b11001111
+ ,8'b11010000,8'b11010001,8'b11010010,8'b11010011,8'b11010100,8'b11010101,8'b11010110,8'b11010111
+ ,8'b11011000,8'b11011001,8'b11011010,8'b11011011,8'b11011100,8'b11011101,8'b11011110,8'b11011111
+ ,8'b11100000,8'b11100001,8'b11100010,8'b11100011,8'b11100100,8'b11100101,8'b11100110,8'b11100111
+ ,8'b11101000,8'b11101001,8'b11101010,8'b11101011,8'b11101100,8'b11101101,8'b11101110,8'b11101111
+ ,8'b11110000,8'b11110001,8'b11110010,8'b11110011,8'b11110100,8'b11110101,8'b11110110,8'b11110111
+ ,8'b11111000,8'b11111001,8'b11111010,8'b11111011,8'b11111100,8'b11111101,8'b11111110,8'b11111111 :
+ ; // NOP, undocumented
+
+ 8'b01111110,8'b01111111 :
+ // NOP, undocumented
+ ;
+ */
+
+ // 8 BIT LOAD GROUP
+ 8'b01010111 :
+ begin
+ // LD A,I
+ Special_LD = 3'b100;
+ TStates = 3'b101;
+ end
+
+ 8'b01011111 :
+ begin
+ // LD A,R
+ Special_LD = 3'b101;
+ TStates = 3'b101;
+ end
+
+ 8'b01000111 :
+ begin
+ // LD I,A
+ Special_LD = 3'b110;
+ TStates = 3'b101;
+ end
+
+ 8'b01001111 :
+ begin
+ // LD R,A
+ Special_LD = 3'b111;
+ TStates = 3'b101;
+ end
+
+ // 16 BIT LOAD GROUP
+ 8'b01001011,8'b01011011,8'b01101011,8'b01111011 :
+ begin
+ // LD dd,(nn)
+ MCycles = 3'b101;
+ case (1'b1) // MCycle
+ MCycle[1] :
+ begin
+ Inc_PC = 1'b1;
+ LDZ = 1'b1;
+ end
+
+ MCycle[2] :
+ begin
+ Set_Addr_To = aZI;
+ Inc_PC = 1'b1;
+ LDW = 1'b1;
+ end
+
+ MCycle[3] :
+ begin
+ Read_To_Reg = 1'b1;
+ if (IR[5:4] == 2'b11 )
+ begin
+ Set_BusA_To = 4'b1000;
+ end
+ else
+ begin
+ Set_BusA_To[2:1] = IR[5:4];
+ Set_BusA_To[0] = 1'b1;
+ end
+ Inc_WZ = 1'b1;
+ Set_Addr_To = aZI;
+ end // case: 4
+
+ MCycle[4] :
+ begin
+ Read_To_Reg = 1'b1;
+ if (IR[5:4] == 2'b11 )
+ begin
+ Set_BusA_To = 4'b1001;
+ end
+ else
+ begin
+ Set_BusA_To[2:1] = IR[5:4];
+ Set_BusA_To[0] = 1'b0;
+ end
+ end // case: 5
+
+ default :;
+ endcase // case(MCycle)
+ end // case: 8'b01001011,8'b01011011,8'b01101011,8'b01111011
+
+
+ 8'b01000011,8'b01010011,8'b01100011,8'b01110011 :
+ begin
+ // LD (nn),dd
+ MCycles = 3'b101;
+ case (1'b1) // MCycle
+ MCycle[1] :
+ begin
+ Inc_PC = 1'b1;
+ LDZ = 1'b1;
+ end
+
+ MCycle[2] :
+ begin
+ Set_Addr_To = aZI;
+ Inc_PC = 1'b1;
+ LDW = 1'b1;
+ if (IR[5:4] == 2'b11 )
+ begin
+ Set_BusB_To = 4'b1000;
+ end
+ else
+ begin
+ Set_BusB_To[2:1] = IR[5:4];
+ Set_BusB_To[0] = 1'b1;
+ Set_BusB_To[3] = 1'b0;
+ end
+ end // case: 3
+
+ MCycle[3] :
+ begin
+ Inc_WZ = 1'b1;
+ Set_Addr_To = aZI;
+ Write = 1'b1;
+ if (IR[5:4] == 2'b11 )
+ begin
+ Set_BusB_To = 4'b1001;
+ end
+ else
+ begin
+ Set_BusB_To[2:1] = IR[5:4];
+ Set_BusB_To[0] = 1'b0;
+ Set_BusB_To[3] = 1'b0;
+ end
+ end // case: 4
+
+ MCycle[4] :
+ begin
+ Write = 1'b1;
+ end
+
+ default :;
+ endcase // case(MCycle)
+ end // case: 8'b01000011,8'b01010011,8'b01100011,8'b01110011
+
+ 8'b10100000 , 8'b10101000 , 8'b10110000 , 8'b10111000 :
+ begin
+ // LDI, LDD, LDIR, LDDR
+ MCycles = 3'b100;
+ case (1'b1) // MCycle
+ MCycle[0] :
+ begin
+ Set_Addr_To = aXY;
+ IncDec_16 = 4'b1100; // BC
+ end
+
+ MCycle[1] :
+ begin
+ Set_BusB_To = 4'b0110;
+ Set_BusA_To[2:0] = 3'b111;
+ ALU_Op = 4'b0000;
+ Set_Addr_To = aDE;
+ if (IR[3] == 1'b0 )
+ begin
+ IncDec_16 = 4'b0110; // IX
+ end
+ else
+ begin
+ IncDec_16 = 4'b1110;
+ end
+ end // case: 2
+
+ MCycle[2] :
+ begin
+ I_BT = 1'b1;
+ TStates = 3'b101;
+ Write = 1'b1;
+ if (IR[3] == 1'b0 )
+ begin
+ IncDec_16 = 4'b0101; // DE
+ end
+ else
+ begin
+ IncDec_16 = 4'b1101;
+ end
+ end // case: 3
+
+ MCycle[3] :
+ begin
+ NoRead = 1'b1;
+ TStates = 3'b101;
+ end
+
+ default :;
+ endcase // case(MCycle)
+ end // case: 8'b10100000 , 8'b10101000 , 8'b10110000 , 8'b10111000
+
+ 8'b10100001 , 8'b10101001 , 8'b10110001 , 8'b10111001 :
+ begin
+ // CPI, CPD, CPIR, CPDR
+ MCycles = 3'b100;
+ case (1'b1) // MCycle
+ MCycle[0] :
+ begin
+ Set_Addr_To = aXY;
+ IncDec_16 = 4'b1100; // BC
+ end
+
+ MCycle[1] :
+ begin
+ Set_BusB_To = 4'b0110;
+ Set_BusA_To[2:0] = 3'b111;
+ ALU_Op = 4'b0111;
+ Save_ALU = 1'b1;
+ PreserveC = 1'b1;
+ if (IR[3] == 1'b0 )
+ begin
+ IncDec_16 = 4'b0110;
+ end
+ else
+ begin
+ IncDec_16 = 4'b1110;
+ end
+ end // case: 2
+
+ MCycle[2] :
+ begin
+ NoRead = 1'b1;
+ I_BC = 1'b1;
+ TStates = 3'b101;
+ end
+
+ MCycle[3] :
+ begin
+ NoRead = 1'b1;
+ TStates = 3'b101;
+ end
+
+ default :;
+ endcase // case(MCycle)
+ end // case: 8'b10100001 , 8'b10101001 , 8'b10110001 , 8'b10111001
+
+ 8'b01000100,8'b01001100,8'b01010100,8'b01011100,8'b01100100,8'b01101100,8'b01110100,8'b01111100 :
+ begin
+ // NEG
+ ALU_Op = 4'b0010;
+ Set_BusB_To = 4'b0111;
+ Set_BusA_To = 4'b1010;
+ Read_To_Acc = 1'b1;
+ Save_ALU = 1'b1;
+ end
+
+ 8'b01000110,8'b01001110,8'b01100110,8'b01101110 :
+ begin
+ // IM 0
+ IMode = 2'b00;
+ end
+
+ 8'b01010110,8'b01110110 :
+ // IM 1
+ IMode = 2'b01;
+
+ 8'b01011110,8'b01110111 :
+ // IM 2
+ IMode = 2'b10;
+
+ // 16 bit arithmetic
+ 8'b01001010,8'b01011010,8'b01101010,8'b01111010 :
+ begin
+ // ADC HL,ss
+ MCycles = 3'b011;
+ case (1'b1) // MCycle
+ MCycle[1] :
+ begin
+ NoRead = 1'b1;
+ ALU_Op = 4'b0001;
+ Read_To_Reg = 1'b1;
+ Save_ALU = 1'b1;
+ Set_BusA_To[2:0] = 3'b101;
+ case (IR[5:4])
+ 0,1,2 :
+ begin
+ Set_BusB_To[2:1] = IR[5:4];
+ Set_BusB_To[0] = 1'b1;
+ end
+ default :
+ Set_BusB_To = 4'b1000;
+ endcase
+ TStates = 3'b100;
+ end // case: 2
+
+ MCycle[2] :
+ begin
+ NoRead = 1'b1;
+ Read_To_Reg = 1'b1;
+ Save_ALU = 1'b1;
+ ALU_Op = 4'b0001;
+ Set_BusA_To[2:0] = 3'b100;
+ case (IR[5:4])
+ 0,1,2 :
+ begin
+ Set_BusB_To[2:1] = IR[5:4];
+ Set_BusB_To[0] = 1'b0;
+ end
+ default :
+ Set_BusB_To = 4'b1001;
+ endcase // case(IR[5:4])
+ end // case: 3
+
+ default :;
+ endcase // case(MCycle)
+ end // case: 8'b01001010,8'b01011010,8'b01101010,8'b01111010
+
+ 8'b01000010,8'b01010010,8'b01100010,8'b01110010 :
+ begin
+ // SBC HL,ss
+ MCycles = 3'b011;
+ case (1'b1) // MCycle
+ MCycle[1] :
+ begin
+ NoRead = 1'b1;
+ ALU_Op = 4'b0011;
+ Read_To_Reg = 1'b1;
+ Save_ALU = 1'b1;
+ Set_BusA_To[2:0] = 3'b101;
+ case (IR[5:4])
+ 0,1,2 :
+ begin
+ Set_BusB_To[2:1] = IR[5:4];
+ Set_BusB_To[0] = 1'b1;
+ end
+ default :
+ Set_BusB_To = 4'b1000;
+ endcase
+ TStates = 3'b100;
+ end // case: 2
+
+ MCycle[2] :
+ begin
+ NoRead = 1'b1;
+ ALU_Op = 4'b0011;
+ Read_To_Reg = 1'b1;
+ Save_ALU = 1'b1;
+ Set_BusA_To[2:0] = 3'b100;
+ case (IR[5:4])
+ 0,1,2 :
+ Set_BusB_To[2:1] = IR[5:4];
+ default :
+ Set_BusB_To = 4'b1001;
+ endcase
+ end // case: 3
+
+ default :;
+
+ endcase // case(MCycle)
+ end // case: 8'b01000010,8'b01010010,8'b01100010,8'b01110010
+
+ 8'b01101111 :
+ begin
+ // RLD
+ MCycles = 3'b100;
+ case (1'b1) // MCycle
+ MCycle[1] :
+ begin
+ NoRead = 1'b1;
+ Set_Addr_To = aXY;
+ end
+
+ MCycle[2] :
+ begin
+ Read_To_Reg = 1'b1;
+ Set_BusB_To[2:0] = 3'b110;
+ Set_BusA_To[2:0] = 3'b111;
+ ALU_Op = 4'b1101;
+ TStates = 3'b100;
+ Set_Addr_To = aXY;
+ Save_ALU = 1'b1;
+ end
+
+ MCycle[3] :
+ begin
+ I_RLD = 1'b1;
+ Write = 1'b1;
+ end
+
+ default :;
+ endcase // case(MCycle)
+ end // case: 8'b01101111
+
+ 8'b01100111 :
+ begin
+ // RRD
+ MCycles = 3'b100;
+ case (1'b1) // MCycle
+ MCycle[1] :
+ Set_Addr_To = aXY;
+ MCycle[2] :
+ begin
+ Read_To_Reg = 1'b1;
+ Set_BusB_To[2:0] = 3'b110;
+ Set_BusA_To[2:0] = 3'b111;
+ ALU_Op = 4'b1110;
+ TStates = 3'b100;
+ Set_Addr_To = aXY;
+ Save_ALU = 1'b1;
+ end
+
+ MCycle[3] :
+ begin
+ I_RRD = 1'b1;
+ Write = 1'b1;
+ end
+
+ default :;
+ endcase // case(MCycle)
+ end // case: 8'b01100111
+
+ 8'b01000101,8'b01001101,8'b01010101,8'b01011101,8'b01100101,8'b01101101,8'b01110101,8'b01111101 :
+ begin
+ // RETI, RETN
+ MCycles = 3'b011;
+ case (1'b1) // MCycle
+ MCycle[0] :
+ Set_Addr_To = aSP;
+
+ MCycle[1] :
+ begin
+ IncDec_16 = 4'b0111;
+ Set_Addr_To = aSP;
+ LDZ = 1'b1;
+ end
+
+ MCycle[2] :
+ begin
+ Jump = 1'b1;
+ IncDec_16 = 4'b0111;
+ I_RETN = 1'b1;
+ end
+
+ default :;
+ endcase // case(MCycle)
+ end // case: 8'b01000101,8'b01001101,8'b01010101,8'b01011101,8'b01100101,8'b01101101,8'b01110101,8'b01111101
+
+ 8'b01000000,8'b01001000,8'b01010000,8'b01011000,8'b01100000,8'b01101000,8'b01110000,8'b01111000 :
+ begin
+ // IN r,(C)
+ MCycles = 3'b010;
+ case (1'b1) // MCycle
+ MCycle[0] :
+ Set_Addr_To = aBC;
+
+ MCycle[1] :
+ begin
+ IORQ = 1'b1;
+ if (IR[5:3] != 3'b110 )
+ begin
+ Read_To_Reg = 1'b1;
+ Set_BusA_To[2:0] = IR[5:3];
+ end
+ I_INRC = 1'b1;
+ end
+
+ default :;
+ endcase // case(MCycle)
+ end // case: 8'b01000000,8'b01001000,8'b01010000,8'b01011000,8'b01100000,8'b01101000,8'b01110000,8'b01111000
+
+ 8'b01000001,8'b01001001,8'b01010001,8'b01011001,8'b01100001,8'b01101001,8'b01110001,8'b01111001 :
+ begin
+ // OUT (C),r
+ // OUT (C),0
+ MCycles = 3'b010;
+ case (1'b1) // MCycle
+ MCycle[0] :
+ begin
+ Set_Addr_To = aBC;
+ Set_BusB_To[2:0] = IR[5:3];
+ if (IR[5:3] == 3'b110 )
+ begin
+ Set_BusB_To[3] = 1'b1;
+ end
+ end
+
+ MCycle[1] :
+ begin
+ Write = 1'b1;
+ IORQ = 1'b1;
+ end
+
+ default :;
+ endcase // case(MCycle)
+ end // case: 8'b01000001,8'b01001001,8'b01010001,8'b01011001,8'b01100001,8'b01101001,8'b01110001,8'b01111001
+
+ 8'b10100010 , 8'b10101010 , 8'b10110010 , 8'b10111010 :
+ begin
+ // INI, IND, INIR, INDR
+ MCycles = 3'b100;
+ case (1'b1) // MCycle
+ MCycle[0] :
+ begin
+ Set_Addr_To = aBC;
+ Set_BusB_To = 4'b1010;
+ Set_BusA_To = 4'b0000;
+ Read_To_Reg = 1'b1;
+ Save_ALU = 1'b1;
+ ALU_Op = 4'b0010;
+ end
+
+ MCycle[1] :
+ begin
+ IORQ = 1'b1;
+ Set_BusB_To = 4'b0110;
+ Set_Addr_To = aXY;
+ end
+
+ MCycle[2] :
+ begin
+ if (IR[3] == 1'b0 )
+ begin
+ IncDec_16 = 4'b0110;
+ end
+ else
+ begin
+ IncDec_16 = 4'b1110;
+ end
+ TStates = 3'b100;
+ Write = 1'b1;
+ I_BTR = 1'b1;
+ end // case: 3
+
+ MCycle[3] :
+ begin
+ NoRead = 1'b1;
+ TStates = 3'b101;
+ end
+
+ default :;
+ endcase // case(MCycle)
+ end // case: 8'b10100010 , 8'b10101010 , 8'b10110010 , 8'b10111010
+
+ 8'b10100011 , 8'b10101011 , 8'b10110011 , 8'b10111011 :
+ begin
+ // OUTI, OUTD, OTIR, OTDR
+ MCycles = 3'b100;
+ case (1'b1) // MCycle
+ MCycle[0] :
+ begin
+ TStates = 3'b101;
+ Set_Addr_To = aXY;
+ Set_BusB_To = 4'b1010;
+ Set_BusA_To = 4'b0000;
+ Read_To_Reg = 1'b1;
+ Save_ALU = 1'b1;
+ ALU_Op = 4'b0010;
+ end
+
+ MCycle[1] :
+ begin
+ Set_BusB_To = 4'b0110;
+ Set_Addr_To = aBC;
+ if (IR[3] == 1'b0 )
+ begin
+ IncDec_16 = 4'b0110;
+ end
+ else
+ begin
+ IncDec_16 = 4'b1110;
+ end
+ end
+
+ MCycle[2] :
+ begin
+ if (IR[3] == 1'b0 )
+ begin
+ IncDec_16 = 4'b0010;
+ end
+ else
+ begin
+ IncDec_16 = 4'b1010;
+ end
+ IORQ = 1'b1;
+ Write = 1'b1;
+ I_BTR = 1'b1;
+ end // case: 3
+
+ MCycle[3] :
+ begin
+ NoRead = 1'b1;
+ TStates = 3'b101;
+ end
+
+ default :;
+ endcase // case(MCycle)
+ end // case: 8'b10100011 , 8'b10101011 , 8'b10110011 , 8'b10111011
+
+ default : ;
+
+ endcase // case(IR)
+ end // block: default_ed_block
+ endcase // case(ISet)
+
+ if (Mode == 1 )
+ begin
+ if (MCycle[0] )
+ begin
+ //TStates = 3'b100;
+ end
+ else
+ begin
+ TStates = 3'b011;
+ end
+ end
+
+ if (Mode == 3 )
+ begin
+ if (MCycle[0] )
+ begin
+ //TStates = 3'b100;
+ end
+ else
+ begin
+ TStates = 3'b100;
+ end
+ end
+
+ if (Mode < 2 )
+ begin
+ if (MCycle[5] )
+ begin
+ Inc_PC = 1'b1;
+ if (Mode == 1 )
+ begin
+ Set_Addr_To = aXY;
+ TStates = 3'b100;
+ Set_BusB_To[2:0] = SSS;
+ Set_BusB_To[3] = 1'b0;
+ end
+ if (IR == 8'b00110110 || IR == 8'b11001011 )
+ begin
+ Set_Addr_To = aNone;
+ end
+ end
+ if (MCycle[6] )
+ begin
+ if (Mode == 0 )
+ begin
+ TStates = 3'b101;
+ end
+ if (ISet != 2'b01 )
+ begin
+ Set_Addr_To = aXY;
+ end
+ Set_BusB_To[2:0] = SSS;
+ Set_BusB_To[3] = 1'b0;
+ if (IR == 8'b00110110 || ISet == 2'b01 )
+ begin
+ // LD (HL),n
+ Inc_PC = 1'b1;
+ end
+ else
+ begin
+ NoRead = 1'b1;
+ end
+ end
+ end // if (Mode < 2 )
+
+ end // always @ (IR, ISet, MCycle, F, NMICycle, IntCycle)
+endmodule // T80_MCode
diff --git a/common/CPU/tv80/tv80_reg.v b/common/CPU/tv80/tv80_reg.v
new file mode 100644
index 00000000..889766cf
--- /dev/null
+++ b/common/CPU/tv80/tv80_reg.v
@@ -0,0 +1,77 @@
+//
+// TV80 8-Bit Microprocessor Core
+// Based on the VHDL T80 core by Daniel Wallner (jesus@opencores.org)
+//
+// Copyright (c) 2004 Guy Hutchison (ghutchis@opencores.org)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+module tv80_reg (/*AUTOARG*/
+ // Outputs
+ DOBH, DOAL, DOCL, DOBL, DOCH, DOAH,
+ // Inputs
+ AddrC, AddrA, AddrB, DIH, DIL, clk, CEN, WEH, WEL
+ );
+ input [2:0] AddrC;
+ output [7:0] DOBH;
+ input [2:0] AddrA;
+ input [2:0] AddrB;
+ input [7:0] DIH;
+ output [7:0] DOAL;
+ output [7:0] DOCL;
+ input [7:0] DIL;
+ output [7:0] DOBL;
+ output [7:0] DOCH;
+ output [7:0] DOAH;
+ input clk, CEN, WEH, WEL;
+
+ reg [7:0] RegsH [0:7];
+ reg [7:0] RegsL [0:7];
+
+ always @(posedge clk)
+ begin
+ if (CEN)
+ begin
+ if (WEH) RegsH[AddrA] <= DIH;
+ if (WEL) RegsL[AddrA] <= DIL;
+ end
+ end
+
+ assign DOAH = RegsH[AddrA];
+ assign DOAL = RegsL[AddrA];
+ assign DOBH = RegsH[AddrB];
+ assign DOBL = RegsL[AddrB];
+ assign DOCH = RegsH[AddrC];
+ assign DOCL = RegsL[AddrC];
+
+ // break out ram bits for waveform debug
+// synopsys translate_off
+ wire [7:0] B = RegsH[0];
+ wire [7:0] C = RegsL[0];
+ wire [7:0] D = RegsH[1];
+ wire [7:0] E = RegsL[1];
+ wire [7:0] H = RegsH[2];
+ wire [7:0] L = RegsL[2];
+
+ wire [15:0] IX = { RegsH[3], RegsL[3] };
+ wire [15:0] IY = { RegsH[7], RegsL[7] };
+// synopsys translate_on
+
+endmodule
+
diff --git a/common/CPU/tv80/tv80n.v b/common/CPU/tv80/tv80n.v
new file mode 100644
index 00000000..d672608e
--- /dev/null
+++ b/common/CPU/tv80/tv80n.v
@@ -0,0 +1,182 @@
+//
+// TV80 8-Bit Microprocessor Core
+// Based on the VHDL T80 core by Daniel Wallner (jesus@opencores.org)
+//
+// Copyright (c) 2004 Guy Hutchison (ghutchis@opencores.org)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+// Negative-edge based wrapper allows memory wait_n signal to work
+// correctly without resorting to asynchronous logic.
+
+module tv80n (/*AUTOARG*/
+ // Outputs
+ m1_n, mreq_n, iorq_n, rd_n, wr_n, rfsh_n, halt_n, busak_n, A, dout,
+ // Inputs
+ reset_n, clk, wait_n, int_n, nmi_n, busrq_n, di
+ );
+
+ parameter Mode = 0; // 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB
+ parameter T2Write = 0; // 0 => wr_n active in T3, /=0 => wr_n active in T2
+ parameter IOWait = 1; // 0 => Single cycle I/O, 1 => Std I/O cycle
+
+
+ input reset_n;
+ input clk;
+ input wait_n;
+ input int_n;
+ input nmi_n;
+ input busrq_n;
+ output m1_n;
+ output mreq_n;
+ output iorq_n;
+ output rd_n;
+ output wr_n;
+ output rfsh_n;
+ output halt_n;
+ output busak_n;
+ output [15:0] A;
+ input [7:0] di;
+ output [7:0] dout;
+
+ reg mreq_n;
+ reg iorq_n;
+ reg rd_n;
+ reg wr_n;
+ reg nxt_mreq_n;
+ reg nxt_iorq_n;
+ reg nxt_rd_n;
+ reg nxt_wr_n;
+
+ wire cen;
+ wire intcycle_n;
+ wire no_read;
+ wire write;
+ wire iorq;
+ reg [7:0] di_reg;
+ wire [6:0] mcycle;
+ wire [6:0] tstate;
+
+ assign cen = 1;
+
+ tv80_core #(Mode, IOWait) i_tv80_core
+ (
+ .cen (cen),
+ .m1_n (m1_n),
+ .iorq (iorq),
+ .no_read (no_read),
+ .write (write),
+ .rfsh_n (rfsh_n),
+ .halt_n (halt_n),
+ .wait_n (wait_n),
+ .int_n (int_n),
+ .nmi_n (nmi_n),
+ .reset_n (reset_n),
+ .busrq_n (busrq_n),
+ .busak_n (busak_n),
+ .clk (clk),
+ .IntE (),
+ .stop (),
+ .A (A),
+ .dinst (di),
+ .di (di_reg),
+ .dout (dout),
+ .mc (mcycle),
+ .ts (tstate),
+ .intcycle_n (intcycle_n)
+ );
+
+ always @*
+ begin
+ nxt_mreq_n = 1;
+ nxt_rd_n = 1;
+ nxt_iorq_n = 1;
+ nxt_wr_n = 1;
+
+ if (mcycle[0])
+ begin
+ if (tstate[1] || tstate[2])
+ begin
+ nxt_rd_n = ~ intcycle_n;
+ nxt_mreq_n = ~ intcycle_n;
+ nxt_iorq_n = intcycle_n;
+ end
+ end // if (mcycle[0])
+ else
+ begin
+ if ((tstate[1] || tstate[2]) && !no_read && !write)
+ begin
+ nxt_rd_n = 1'b0;
+ nxt_iorq_n = ~ iorq;
+ nxt_mreq_n = iorq;
+ end
+ if (T2Write == 0)
+ begin
+ if (tstate[2] && write)
+ begin
+ nxt_wr_n = 1'b0;
+ nxt_iorq_n = ~ iorq;
+ nxt_mreq_n = iorq;
+ end
+ end
+ else
+ begin
+ if ((tstate[1] || (tstate[2] && !wait_n)) && write)
+ begin
+ nxt_wr_n = 1'b0;
+ nxt_iorq_n = ~ iorq;
+ nxt_mreq_n = iorq;
+ end
+ end // else: !if(T2write == 0)
+ end // else: !if(mcycle[0])
+ end // always @ *
+
+ always @(negedge clk)
+ begin
+ if (!reset_n)
+ begin
+ rd_n <= #1 1'b1;
+ wr_n <= #1 1'b1;
+ iorq_n <= #1 1'b1;
+ mreq_n <= #1 1'b1;
+ end
+ else
+ begin
+ rd_n <= #1 nxt_rd_n;
+ wr_n <= #1 nxt_wr_n;
+ iorq_n <= #1 nxt_iorq_n;
+ mreq_n <= #1 nxt_mreq_n;
+ end // else: !if(!reset_n)
+ end // always @ (posedge clk or negedge reset_n)
+
+ always @(posedge clk)
+ begin
+ if (!reset_n)
+ begin
+ di_reg <= #1 0;
+ end
+ else
+ begin
+ if (tstate[2] && wait_n == 1'b1)
+ di_reg <= #1 di;
+ end // else: !if(!reset_n)
+ end // always @ (posedge clk)
+
+endmodule // t80n
+
diff --git a/common/CPU/tv80/tv80s.v b/common/CPU/tv80/tv80s.v
new file mode 100644
index 00000000..3d825cb7
--- /dev/null
+++ b/common/CPU/tv80/tv80s.v
@@ -0,0 +1,162 @@
+//
+// TV80 8-Bit Microprocessor Core
+// Based on the VHDL T80 core by Daniel Wallner (jesus@opencores.org)
+//
+// Copyright (c) 2004 Guy Hutchison (ghutchis@opencores.org)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+module tv80s (/*AUTOARG*/
+ // Outputs
+ m1_n, mreq_n, iorq_n, rd_n, wr_n, rfsh_n, halt_n, busak_n, A, dout,
+ // Inputs
+ reset_n, clk, wait_n, int_n, nmi_n, busrq_n, di
+ );
+
+ parameter Mode = 0; // 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB
+ parameter T2Write = 1; // 0 => wr_n active in T3, /=0 => wr_n active in T2
+ parameter IOWait = 1; // 0 => Single cycle I/O, 1 => Std I/O cycle
+
+
+ input reset_n;
+ input clk;
+ input wait_n;
+ input int_n;
+ input nmi_n;
+ input busrq_n;
+ output m1_n;
+ output mreq_n;
+ output iorq_n;
+ output rd_n;
+ output wr_n;
+ output rfsh_n;
+ output halt_n;
+ output busak_n;
+ output [15:0] A;
+ input [7:0] di;
+ output [7:0] dout;
+
+ reg mreq_n;
+ reg iorq_n;
+ reg rd_n;
+ reg wr_n;
+
+ wire cen;
+ wire intcycle_n;
+ wire no_read;
+ wire write;
+ wire iorq;
+ reg [7:0] di_reg;
+ wire [6:0] mcycle;
+ wire [6:0] tstate;
+
+ assign cen = 1;
+
+ tv80_core #(Mode, IOWait) i_tv80_core
+ (
+ .cen (cen),
+ .m1_n (m1_n),
+ .iorq (iorq),
+ .no_read (no_read),
+ .write (write),
+ .rfsh_n (rfsh_n),
+ .halt_n (halt_n),
+ .wait_n (wait_n),
+ .int_n (int_n),
+ .nmi_n (nmi_n),
+ .reset_n (reset_n),
+ .busrq_n (busrq_n),
+ .busak_n (busak_n),
+ .clk (clk),
+ .IntE (),
+ .stop (),
+ .A (A),
+ .dinst (di),
+ .di (di_reg),
+ .dout (dout),
+ .mc (mcycle),
+ .ts (tstate),
+ .intcycle_n (intcycle_n)
+ );
+
+ always @(posedge clk or negedge reset_n)
+ begin
+ if (!reset_n)
+ begin
+ rd_n <= #1 1'b1;
+ wr_n <= #1 1'b1;
+ iorq_n <= #1 1'b1;
+ mreq_n <= #1 1'b1;
+ di_reg <= #1 0;
+ end
+ else
+ begin
+ rd_n <= #1 1'b1;
+ wr_n <= #1 1'b1;
+ iorq_n <= #1 1'b1;
+ mreq_n <= #1 1'b1;
+ if (mcycle[0])
+ begin
+ if (tstate[1] || (tstate[2] && wait_n == 1'b0))
+ begin
+ rd_n <= #1 ~ intcycle_n;
+ mreq_n <= #1 ~ intcycle_n;
+ iorq_n <= #1 intcycle_n;
+ end
+ `ifdef TV80_REFRESH
+ if (tstate[3])
+ mreq_n <= #1 1'b0;
+ `endif
+ end // if (mcycle[0])
+ else
+ begin
+ if ((tstate[1] || (tstate[2] && wait_n == 1'b0)) && no_read == 1'b0 && write == 1'b0)
+ begin
+ rd_n <= #1 1'b0;
+ iorq_n <= #1 ~ iorq;
+ mreq_n <= #1 iorq;
+ end
+ if (T2Write == 0)
+ begin
+ if (tstate[2] && write == 1'b1)
+ begin
+ wr_n <= #1 1'b0;
+ iorq_n <= #1 ~ iorq;
+ mreq_n <= #1 iorq;
+ end
+ end
+ else
+ begin
+ if ((tstate[1] || (tstate[2] && wait_n == 1'b0)) && write == 1'b1)
+ begin
+ wr_n <= #1 1'b0;
+ iorq_n <= #1 ~ iorq;
+ mreq_n <= #1 iorq;
+ end
+ end // else: !if(T2write == 0)
+
+ end // else: !if(mcycle[0])
+
+ if (tstate[2] && wait_n == 1'b1)
+ di_reg <= #1 di;
+ end // else: !if(!reset_n)
+ end // always @ (posedge clk or negedge reset_n)
+
+endmodule // t80s
+
diff --git a/common/Intel8080/vm80a.v b/common/CPU/vm80a/vm80a.v
similarity index 100%
rename from common/Intel8080/vm80a.v
rename to common/CPU/vm80a/vm80a.v
diff --git a/common/CPU/x86/CMakeLists.txt b/common/CPU/x86/CMakeLists.txt
new file mode 100644
index 00000000..0ce35a07
--- /dev/null
+++ b/common/CPU/x86/CMakeLists.txt
@@ -0,0 +1,95 @@
+# Copyright Jamie Iles, 2017
+#
+# This file is part of s80x86.
+#
+# s80x86 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.
+#
+# s80x86 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 s80x86. If not, see .
+
+include(Verilator)
+
+add_subdirectory(microcode)
+set_source_files_properties(${VERILATED_DPI_CPP} PROPERTIES COMPILE_FLAGS "-Wno-unused-parameter -Wno-error")
+set_source_files_properties(${VERILATED_CPP} PROPERTIES COMPILE_FLAGS "-Wno-unused-parameter -Wno-error")
+add_library(verilator SHARED ${VERILATOR_LIB_SOURCES})
+
+set(ALU_SOURCES
+ ${CMAKE_CURRENT_SOURCE_DIR}/alu/aaa.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/alu/aas.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/alu/adc.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/alu/add.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/alu/and.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/alu/bound.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/alu/daa.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/alu/das.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/alu/enter.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/alu/extend.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/alu/flags.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/alu/mul.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/alu/or.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/alu/not.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/alu/rcl.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/alu/rcr.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/alu/rol.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/alu/ror.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/alu/sar.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/alu/shift_flags.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/alu/shl.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/alu/shr.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/alu/sub.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/alu/xor.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/alu/ALU.sv)
+
+add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/InstructionDefinitions.sv
+ COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/gen-instructions-functions
+ ${CMAKE_CURRENT_BINARY_DIR}/InstructionDefinitions.sv
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/../documentation/instructions.yaml
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/InstructionDefinitions.sv.templ
+ ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/gen-instructions-functions)
+
+add_custom_target(generate_instruction_definitions
+ DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/InstructionDefinitions.sv)
+
+set(CORE_SOURCES
+ ${CMAKE_CURRENT_BINARY_DIR}/../config.v
+ ${CMAKE_CURRENT_BINARY_DIR}/microcode/MicrocodeTypes.sv
+ ${ALU_SOURCES}
+ ${CMAKE_CURRENT_SOURCE_DIR}/RegisterEnum.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/Instruction.sv
+ ${CMAKE_CURRENT_BINARY_DIR}/InstructionDefinitions.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/InsnDecoder.sv
+ ${CMAKE_CURRENT_BINARY_DIR}/microcode/Microcode.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/FlagsEnum.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/Core.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/CSIPSync.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/Divider.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/Fifo.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/Flags.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/ImmediateReader.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/IP.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/JumpTest.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/LoadStore.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/LoopCounter.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/ModRMDecode.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/PosedgeToPulse.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/Prefetch.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/RegisterFile.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/SegmentOverride.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/SegmentRegisterFile.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/TempReg.sv)
+
+set_property(GLOBAL PROPERTY G_ALU_SOURCES "${ALU_SOURCES}")
+set_property(GLOBAL PROPERTY G_CORE_SOURCES "${CORE_SOURCES}")
+
+install(TARGETS verilator
+ LIBRARY DESTINATION lib
+ COMPONENT simulator)
diff --git a/common/CPU/x86/CSIPSync.sv b/common/CPU/x86/CSIPSync.sv
new file mode 100644
index 00000000..0f008577
--- /dev/null
+++ b/common/CPU/x86/CSIPSync.sv
@@ -0,0 +1,67 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+// Synchronize CS and IP updates so that they can be deployed to the
+// prefetcher atomically. For something like a far jump, the microcode would
+// first update the IP and then update CS. If this happens during the
+// microcode execution then potentially the prefetcher can start prefetching
+// from an invalid address - CS remains the same but IP changes and we fetch
+// from invalid/unmapped memory.
+//
+// This simple module just defers the output until propagation is ready, in
+// this case, on completion of the microinstruction when CS:IP can be
+// delivered to the prefetcher in a single cycle.
+`default_nettype none
+module CSIPSync(input logic clk,
+ input logic reset,
+ input logic cs_update,
+ input logic ip_update,
+ input logic [15:0] ip_in,
+ input logic [15:0] new_ip,
+ input logic propagate,
+ output logic [15:0] ip_out,
+ output logic update_out);
+
+reg [15:0] ip;
+reg ip_updated;
+reg cs_updated;
+
+assign ip_out = ip_updated ? ip : ip_update ? new_ip : ip_in;
+assign update_out = propagate &
+ (ip_updated | cs_updated | cs_update | ip_update);
+
+always @(posedge clk or posedge reset) begin
+ if (reset) begin
+ ip_updated <= 1'b0;
+ cs_updated <= 1'b0;
+ end else begin
+ if (propagate) begin
+ ip_updated <= 1'b0;
+ cs_updated <= 1'b0;
+ end
+
+ if (ip_update && !ip_updated && !propagate) begin
+ ip <= new_ip;
+ ip_updated <= 1'b1;
+ end
+
+ if (cs_update && !propagate)
+ cs_updated <= 1'b1;
+ end
+end
+
+endmodule
diff --git a/common/CPU/x86/Core.sv b/common/CPU/x86/Core.sv
new file mode 100644
index 00000000..8d005880
--- /dev/null
+++ b/common/CPU/x86/Core.sv
@@ -0,0 +1,536 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+`default_nettype none
+module Core(input logic clk,
+ input logic reset,
+ // Interrupts
+ input logic nmi,
+ input logic intr,
+ input logic [7:0] irq,
+ output logic inta,
+ // Instruction bus
+ output logic [19:1] instr_m_addr,
+ input logic [15:0] instr_m_data_in,
+ output logic instr_m_access,
+ input logic instr_m_ack,
+ // Data bus
+ output logic [19:1] data_m_addr,
+ input logic [15:0] data_m_data_in,
+ output logic [15:0] data_m_data_out,
+ output logic data_m_access,
+ input logic data_m_ack,
+ output logic data_m_wr_en,
+ output logic [1:0] data_m_bytesel,
+ output logic d_io,
+ output logic lock,
+ // Debug
+ output logic debug_stopped,
+ input logic debug_seize,
+ input logic [7:0] debug_addr,
+ input logic debug_run,
+ output logic [15:0] debug_val,
+ input logic [15:0] debug_wr_val,
+ input logic debug_wr_en);
+
+// verilator lint_off UNUSED
+Instruction wr_instruction, cur_instruction, next_instruction_value;
+// verilator lint_on UNUSED
+
+// Internal busses.
+wire [15:0] a_bus =
+ a_sel == ADriver_RA ? reg_rd_val[0] :
+ a_sel == ADriver_IP ? ip_current :
+ a_sel == ADriver_MAR ? mar : mdr;
+wire [15:0] b_bus =
+ b_sel == BDriver_RB ? reg_rd_val[1] :
+ b_sel == BDriver_IMMEDIATE ? immediate :
+ b_sel == BDriver_IMMEDIATE2 ? cur_instruction.immediates[1] :
+ b_sel == BDriver_SR ? seg_rd_val : tmp_val;
+
+// Register file.
+wire [15:0] si, di, bp, bx;
+wire reg_is_8_bit = is_8_bit;
+wire [2:0] reg_rd_sel[2];
+assign reg_rd_sel[0] = ra_modrm_rm_reg ? rm_regnum : microcode_reg_rd_sel[0];
+assign reg_rd_sel[1] = rb_cl ? CL : regnum;
+wire [2:0] reg_wr_sel =
+ rd_sel_source == RDSelSource_MODRM_REG ? regnum :
+ rd_sel_source == RDSelSource_MODRM_RM_REG ? rm_regnum :
+ microcode_reg_wr_sel;
+wire [15:0] reg_wr_val =
+ reg_wr_source == RegWrSource_Q ? alu_out[15:0] :
+ reg_wr_source == RegWrSource_QUOTIENT ? quotient : remainder;
+wire reg_wr_en;
+wire [15:0] reg_rd_val[2];
+wire rb_cl;
+wire [`MC_RDSelSource_t_BITS-1:0] rd_sel_source;
+
+// Segment register file.
+wire io_operation;
+assign d_io = io_operation;
+wire segment_force;
+assign seg_wr_sel = segment_force ?
+ microcode_segment : reg_wr_sel[1:0];
+wire [15:0] seg_rd_val;
+wire [15:0] seg_wr_val = alu_out[15:0];
+wire [15:0] cs;
+wire [1:0] segment;
+wire segment_wr_en;
+
+wire decode_immed_start;
+wire decode_immed_is_8bit;
+wire decode_fifo_rd_en;
+wire decode_complete;
+wire instruction_empty;
+wire instruction_fifo_full;
+wire instruction_fifo_nearly_full;
+
+// Prefetch FIFO
+wire fifo_wr_en;
+wire fifo_rd_en = immed_fifo_rd_en | decode_fifo_rd_en;
+wire [7:0] fifo_rd_data;
+wire [7:0] fifo_wr_data;
+wire fifo_empty;
+wire fifo_full;
+wire fifo_reset;
+
+// CS:IP Synchronizer
+wire cs_updating = seg_wr_sel == CS && segment_wr_en;
+wire [15:0] prefetch_cs = cs_updating ? seg_wr_val : cs;
+wire ip_wr_en;
+wire [15:0] ip_current;
+wire prefetch_load_new_ip;
+wire [15:0] prefetch_new_ip;
+
+// Immediate Reader
+wire immed_start = decode_immed_start;
+wire immed_complete;
+wire immed_is_8bit = decode_immed_is_8bit;
+wire [15:0] immediate_reader_immediate;
+wire [15:0] immediate = use_microcode_immediate ? microcode_immediate :
+ cur_instruction.immediates[0];
+wire immed_fifo_rd_en;
+
+wire instruction_fifo_rd_en;
+
+// ModRM Decoder
+wire modrm_clear = reset | do_next_instruction | start_interrupt | fifo_reset;
+wire modrm_start;
+wire modrm_uses_bp_as_base;
+wire [2:0] regnum;
+wire rm_is_reg;
+wire [2:0] rm_regnum;
+wire ra_modrm_rm_reg;
+
+// Flags
+wire [15:0] flags;
+wire [8:0] update_flags;
+
+// LoadStore
+wire [15:0] mar;
+wire [15:0] mdr;
+wire microcode_write_mdr;
+wire write_mdr = microcode_write_mdr | irq_to_mdr;
+wire [15:0] mdr_in = microcode_write_mdr ? alu_out[15:0] : {8'b0, irq};
+wire microcode_write_mar;
+wire write_mar = microcode_write_mar & next_microinstruction;
+wire mem_read;
+wire mem_write;
+wire mar_wr_sel;
+wire [15:0] mar_wr_val;
+wire loadstore_start = (mem_read | mem_write) & ~loadstore_complete;
+wire loadstore_is_store = mem_write;
+wire loadstore_complete;
+wire loadstore_busy;
+assign mar_wr_val = mar_wr_sel == MARWrSel_EA ?
+ effective_address : alu_out[15:0];
+
+// ALU
+wire [`MC_ALUOp_t_BITS-1:0] alu_op;
+wire [31:0] alu_out;
+wire [15:0] alu_flags_out;
+wire alu_busy;
+
+// Microcode
+wire [2:0] microcode_reg_rd_sel[2];
+wire [2:0] microcode_reg_wr_sel;
+wire [1:0] reg_wr_source;
+wire [1:0] seg_wr_sel;
+wire [1:0] a_sel;
+wire [2:0] b_sel;
+wire next_instruction;
+wire is_8_bit;
+wire [15:0] effective_address;
+wire microcode_tmp_wr_en;
+wire tmp_wr_en = microcode_tmp_wr_en | (debug_wr_en && debug_stopped);
+wire [15:0] tmp_wr_val = debug_stopped && debug_wr_en ? debug_wr_val :
+ (tmp_wr_sel == TEMPWrSel_Q_LOW) ? alu_out[15:0] :
+ alu_out[31:16];
+wire tmp_wr_sel;
+wire [15:0] tmp_val;
+wire [15:0] microcode_immediate;
+wire use_microcode_immediate;
+wire [1:0] microcode_segment;
+wire [7:0] opcode;
+wire jump_taken;
+wire multibit_shift;
+wire rb_zero = ~|reg_rd_val[1];
+wire nmi_pulse;
+wire ext_int_yield;
+wire irq_to_mdr;
+wire loop_next;
+wire loop_done;
+wire is_hlt;
+wire next_microinstruction;
+
+// Misc control signals
+wire debug_set_ip = debug_stopped && ip_wr_en;
+wire do_next_instruction = (next_instruction & ~do_stall) | debug_set_ip;
+wire do_stall = loadstore_busy | divide_busy | alu_busy;
+wire start_interrupt;
+
+// IP
+wire do_escape_fault;
+wire starting_instruction;
+wire ip_rollback = (start_interrupt & ext_int_yield & ~is_hlt) | do_escape_fault;
+
+// Divider
+wire [31:0] dividend8 = divide_signed ? {{16{tmp_val[15]}}, tmp_val} : {16'b0, tmp_val};
+wire [31:0] dividend = is_8_bit ? dividend8 : {reg_rd_val[0], tmp_val};
+wire [15:0] divisor8 = divide_signed ? {{8{mdr[7]}}, mdr[7:0]} : mdr;
+wire [15:0] divisor = is_8_bit ? divisor8 : mdr;
+wire [15:0] quotient;
+wire [15:0] remainder;
+wire divide_error;
+wire divide_busy;
+wire divide = alu_op == ALUOp_DIV || alu_op == ALUOp_IDIV;
+wire divide_signed = alu_op == ALUOp_IDIV;
+wire divide_complete;
+wire do_divide = divide & ~divide_complete;
+
+assign debug_val = tmp_val;
+
+RegisterFile RegisterFile(.clk(clk),
+ .reset(reset),
+ .si(si),
+ .di(di),
+ .bp(bp),
+ .bx(bx),
+ .is_8_bit(reg_is_8_bit),
+ .rd_sel(reg_rd_sel),
+ .rd_val(reg_rd_val),
+ .wr_sel(reg_wr_sel),
+ .wr_val(reg_wr_val),
+ .wr_en(reg_wr_en));
+
+SegmentOverride SegmentOverride(.clk(clk),
+ .reset(reset),
+ .flush(fifo_reset),
+ .next_instruction(do_next_instruction),
+ .force_segment(segment_force),
+ .bp_is_base(modrm_uses_bp_as_base),
+ .update(starting_instruction),
+ .segment_override(next_instruction_value.has_segment_override),
+ .override_in(next_instruction_value.segment),
+ .microcode_sr_rd_sel(microcode_segment),
+ .sr_rd_sel(segment));
+
+SegmentRegisterFile SegmentRegisterFile(.clk(clk),
+ .reset(reset),
+ .rd_sel(segment),
+ .rd_val(seg_rd_val),
+ .wr_en(segment_wr_en),
+ .wr_sel(seg_wr_sel),
+ .wr_val(seg_wr_val),
+ .cs(cs));
+
+Fifo #(.data_width(8),
+ .depth(6))
+ PrefetchFifo(.clk(clk),
+ .reset(reset),
+ .flush(fifo_reset),
+ .wr_en(fifo_wr_en),
+ .wr_data(fifo_wr_data),
+ .rd_en(fifo_rd_en),
+ .rd_data(fifo_rd_data),
+ .empty(fifo_empty),
+ .nearly_full(fifo_full),
+ // verilator lint_off PINCONNECTEMPTY
+ .full()
+ // verilator lint_on PINCONNECTEMPTY
+ );
+
+CSIPSync CSIPSync(.clk(clk),
+ .reset(reset),
+ .cs_update(cs_updating),
+ .ip_update(ip_wr_en),
+ .ip_in(ip_current),
+ .new_ip(alu_out[15:0]),
+ .propagate(do_next_instruction),
+ .ip_out(prefetch_new_ip),
+ .update_out(prefetch_load_new_ip));
+
+TempReg TempReg(.clk(clk),
+ .reset(reset),
+ .wr_val(tmp_wr_val),
+ .wr_en(tmp_wr_en),
+ .val(tmp_val));
+
+Prefetch Prefetch(.clk(clk),
+ .reset(reset),
+ .new_cs(prefetch_cs),
+ .new_ip(prefetch_new_ip),
+ .load_new_ip(prefetch_load_new_ip),
+ .fifo_wr_en(fifo_wr_en),
+ .fifo_wr_data(fifo_wr_data),
+ .fifo_reset(fifo_reset),
+ .fifo_full(fifo_full),
+ .mem_access(instr_m_access),
+ .mem_ack(instr_m_ack),
+ .mem_address(instr_m_addr),
+ .mem_data(instr_m_data_in));
+
+ImmediateReader ImmediateReader(.clk(clk),
+ .reset(reset),
+ // Control
+ .start(immed_start),
+ .flush(fifo_reset),
+ // verilator lint_off PINCONNECTEMPTY
+ .busy(),
+ // verilator lint_on PINCONNECTEMPTY
+ .complete(immed_complete),
+ .is_8bit(immed_is_8bit),
+ // Result
+ .immediate(immediate_reader_immediate),
+ // Fifo read port
+ .fifo_rd_en(immed_fifo_rd_en),
+ .fifo_rd_data(fifo_rd_data),
+ .fifo_empty(fifo_empty));
+
+LoopCounter LoopCounter(.clk(clk),
+ .count_in(next_instruction_value.immediates[1][4:0]),
+ .load(instruction_fifo_rd_en),
+ .next(loop_next),
+ .done(loop_done));
+
+Fifo #(.data_width($bits(Instruction)),
+ .depth(4),
+ .full_threshold(1))
+ InstructionFifo(.clk(clk),
+ .reset(reset),
+ .flush(fifo_reset),
+ .wr_en(decode_complete),
+ .wr_data(wr_instruction),
+ .rd_en(instruction_fifo_rd_en),
+ .rd_data(next_instruction_value),
+ .empty(instruction_empty),
+ .nearly_full(instruction_fifo_nearly_full),
+ .full(instruction_fifo_full));
+
+InsnDecoder InsnDecoder(.clk(clk),
+ .reset(reset),
+ .flush(fifo_reset),
+ .stall(instruction_fifo_full),
+ .nearly_full(instruction_fifo_nearly_full),
+ .fifo_rd_en(decode_fifo_rd_en),
+ .fifo_rd_data(fifo_rd_data),
+ .fifo_empty(fifo_empty),
+ .instruction(wr_instruction),
+ .complete(decode_complete),
+ .immed_start(decode_immed_start),
+ .immed_complete(immed_complete),
+ .immed_is_8bit(decode_immed_is_8bit),
+ .immediate(immediate_reader_immediate));
+
+ModRMDecode ModRMDecode(.clk(clk),
+ .reset(reset),
+ .si(si),
+ .di(di),
+ .bp(bp),
+ .bx(bx),
+ // Control
+ .start(modrm_start),
+ .clear(modrm_clear),
+ .modrm(next_instruction_value.mod_rm),
+ .displacement(next_instruction_value.displacement),
+ // Results
+ .effective_address(effective_address),
+ .regnum(regnum),
+ .rm_is_reg(rm_is_reg),
+ .rm_regnum(rm_regnum),
+ .bp_as_base(modrm_uses_bp_as_base));
+
+Flags Flags(.clk(clk),
+ .reset(reset),
+ .flags_in(alu_flags_out),
+ .flags_out(flags),
+ .update_flags(update_flags));
+
+JumpTest JumpTest(.opcode(opcode),
+ .flags(flags),
+ .taken(jump_taken));
+
+LoadStore LoadStore(.clk(clk),
+ .reset(reset),
+ // MAR
+ .write_mar(write_mar),
+ .segment(seg_rd_val),
+ .mar_in(mar_wr_val),
+ // MDR
+ .mar_out(mar),
+ .mdr_out(mdr),
+ .write_mdr(write_mdr),
+ .mdr_in(mdr_in),
+ // Memory bus
+ .m_addr(data_m_addr),
+ .m_data_in(data_m_data_in),
+ .m_data_out(data_m_data_out),
+ .m_access(data_m_access),
+ .m_ack(data_m_ack),
+ .m_wr_en(data_m_wr_en),
+ .m_bytesel(data_m_bytesel),
+ // Control
+ .start(loadstore_start),
+ .is_8bit(is_8_bit),
+ .wr_en(loadstore_is_store),
+ .busy(loadstore_busy),
+ .complete(loadstore_complete),
+ .io(io_operation));
+
+PosedgeToPulse PosedgeToPulse(.d(nmi),
+ .q(nmi_pulse),
+ .*);
+
+Microcode Microcode(.clk(clk),
+ .reset(reset),
+ .nmi_pulse(nmi_pulse),
+ .intr(intr),
+ .inta(inta),
+ .irq_to_mdr(irq_to_mdr),
+ .start_interrupt(start_interrupt),
+ .do_escape_fault(do_escape_fault),
+ .starting_instruction(starting_instruction),
+ .stall(do_stall),
+ .divide_error(divide_error),
+ .modrm_reg(regnum),
+ .int_enabled(flags[IF_IDX]),
+ .zf(flags[ZF_IDX]),
+ .tf(flags[TF_IDX]),
+ .microcode_immediate(microcode_immediate),
+ .use_microcode_immediate(use_microcode_immediate),
+ .opcode(opcode),
+ .jump_taken(jump_taken),
+ .rb_zero(rb_zero),
+ .lock(lock),
+ .multibit_shift(multibit_shift),
+ .rm_is_reg(rm_is_reg),
+ .a_sel(a_sel),
+ .alu_op(alu_op),
+ .b_sel(b_sel),
+ .ext_int_yield(ext_int_yield),
+ .io(io_operation),
+ .next_instruction(next_instruction),
+ .load_ip(ip_wr_en),
+ .mar_wr_sel(mar_wr_sel),
+ .mar_write(microcode_write_mar),
+ .mdr_write(microcode_write_mdr),
+ .mem_read(mem_read),
+ .mem_write(mem_write),
+ .modrm_start(modrm_start),
+ .ra_modrm_rm_reg(ra_modrm_rm_reg),
+ .ra_sel(microcode_reg_rd_sel[0]),
+ .rb_cl(rb_cl),
+ .rd_sel_source(rd_sel_source),
+ .rd_sel(microcode_reg_wr_sel),
+ .reg_wr_en(reg_wr_en),
+ .reg_wr_source(reg_wr_source),
+ .segment(microcode_segment),
+ .segment_force(segment_force),
+ .segment_wr_en(segment_wr_en),
+ .tmp_wr_en(microcode_tmp_wr_en),
+ .tmp_wr_sel(tmp_wr_sel),
+ .update_flags(update_flags),
+ .width(is_8_bit),
+ .fifo_rd_en(instruction_fifo_rd_en),
+ .cur_instruction(cur_instruction),
+ .next_instruction_value(next_instruction_value),
+ .fifo_empty(instruction_empty),
+ .fifo_resetting(fifo_reset),
+ .loop_next(loop_next),
+ .loop_done(loop_done),
+ .is_hlt(is_hlt),
+ .next_microinstruction(next_microinstruction),
+ // Debug
+ .debug_stopped(debug_stopped),
+ .debug_seize(debug_seize),
+ .debug_addr(debug_addr),
+ .debug_run(debug_run));
+
+IP IP(.clk(clk),
+ .reset(reset),
+ .inc(next_instruction_value.length),
+ .start_instruction(instruction_fifo_rd_en),
+ .next_instruction(do_next_instruction),
+ .rollback(ip_rollback),
+ .wr_en(prefetch_load_new_ip),
+ .wr_val(prefetch_new_ip),
+ .val(ip_current));
+
+ALU ALU(.a(a_bus),
+ .b(b_bus),
+ .out(alu_out),
+ .op(alu_op),
+ .is_8_bit(is_8_bit),
+ .flags_in(flags),
+ .flags_out(alu_flags_out),
+ .multibit_shift(multibit_shift),
+ .shift_count(tmp_val[4:0]),
+ .busy(alu_busy));
+
+Divider Divider(.clk(clk),
+ .reset(reset),
+ .start(do_divide),
+ .is_8_bit(is_8_bit),
+ .is_signed(divide_signed),
+ .busy(divide_busy),
+ .complete(divide_complete),
+ .error(divide_error),
+ .dividend(dividend),
+ .divisor(divisor),
+ .quotient(quotient),
+ .remainder(remainder));
+
+`ifdef verilator
+// verilator lint_off BLKANDNBLK
+int instr_length;
+// verilator lint_on BLKANDNBLK
+
+always @(posedge clk)
+ if (instruction_fifo_rd_en)
+ instr_length <= {28'b0, next_instruction_value.length};
+
+export "DPI-C" function get_and_clear_instr_length;
+
+function int get_and_clear_instr_length;
+ get_and_clear_instr_length = instr_length;
+ instr_length = 0;
+endfunction
+
+`endif
+
+endmodule
diff --git a/common/CPU/x86/Divider.sv b/common/CPU/x86/Divider.sv
new file mode 100644
index 00000000..f603ecb8
--- /dev/null
+++ b/common/CPU/x86/Divider.sv
@@ -0,0 +1,172 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+// Non-restoring division
+`default_nettype none
+module Divider(input logic clk,
+ input logic reset,
+ input logic start,
+ input logic is_8_bit,
+ input logic is_signed,
+ output logic busy,
+ output logic complete,
+ output logic error,
+ input logic [31:0] dividend,
+ input logic [15:0] divisor,
+ output logic [15:0] quotient,
+ output logic [15:0] remainder);
+
+typedef enum bit[1:0] {
+ INIT,
+ WORKING,
+ RESTORE,
+ FIX_SIGN
+} DivState_t;
+
+DivState_t state, next_state;
+
+// Remainder
+wire [15:0] rem8 = {{8{P[15]}}, P[15:8]};
+wire [15:0] rem16 = P[31:16];
+assign remainder = is_8_bit ? rem8 : rem16;
+
+// Shifted divisor
+wire [31:0] udivshift8 = {16'b0, divisor[7:0], 8'b0};
+wire [31:0] udivshift16 = {divisor, 16'b0};
+wire [31:0] udivshift = is_8_bit ? udivshift8 : udivshift16;
+
+wire [31:0] sdivshift8 = {16'b0, divisor_mag[7:0], 8'b0};
+wire [31:0] sdivshift16 = {divisor_mag, 16'b0};
+wire [31:0] sdivshift = is_8_bit ? sdivshift8 : sdivshift16;
+
+wire [31:0] D = is_signed ? sdivshift : udivshift;
+
+// Overflow
+wire unsigned_overflow8 = dividend[15:0] >= {divisor[7:0], 8'b0};
+wire unsigned_overflow16 = dividend >= {divisor, 16'b0};
+wire unsigned_overflow = is_8_bit ? unsigned_overflow8 : unsigned_overflow16;
+
+wire signed_overflow8 = in_signs_equal && dividend_mag[14:7] >= divisor_mag[7:0];
+wire signed_overflow16 = in_signs_equal && dividend_mag[30:15] >= divisor_mag;
+wire signed_overflow = is_8_bit ? signed_overflow8 : signed_overflow16;
+
+wire overflow = is_signed ? signed_overflow : unsigned_overflow;
+wire div_by_zero = divisor == 16'b0;
+
+// Magnitudes
+wire [31:0] dividend_mag = (dividend + {32{dividend[31]}}) ^ {32{dividend[31]}};
+wire [15:0] divisor_mag = (divisor + {16{divisor[15]}}) ^ {16{divisor[15]}};
+
+// Dividend
+wire [63:0] P16 = is_signed ?
+ {32'b0, dividend_mag} : {32'b0, dividend};
+wire [63:0] P8 = is_signed ?
+ {48'b0, dividend_mag[15:0]} : {48'b0, dividend[15:0]};
+wire [63:0] P_init = is_8_bit ? P8 : P16;
+
+// Sign bits
+wire in_signs_equal8 = ~(dividend[15] ^ divisor[7]);
+wire in_signs_equal16 = ~(dividend[31] ^ divisor[15]);
+wire in_signs_equal = is_8_bit ? in_signs_equal8 : in_signs_equal16;
+wire dividend_negative = is_8_bit ? dividend[15] : dividend[31];
+
+reg [63:0] P;
+reg [3:0] idx;
+reg [15:0] restored_quotient;
+wire [15:0] negative_quotient = ~quotient + 1'b1;
+
+// Error condition
+wire raise_error = div_by_zero | overflow;
+
+assign busy = (start || (state != INIT) && !complete);
+
+always_comb begin
+ if (is_8_bit) begin
+ restored_quotient = {8'b0, P[63] ?
+ quotient[7:0] - ~quotient[7:0] - 8'b1 : quotient[7:0] - ~quotient[7:0]};
+ end else begin
+ restored_quotient = P[63] ?
+ quotient - ~quotient - 16'b1 : quotient - ~quotient;
+ end
+end
+
+always_comb begin
+ case (state)
+ INIT: next_state = start && !error && !raise_error ? WORKING : INIT;
+ WORKING: next_state = idx == 4'b0 ? RESTORE : WORKING;
+ RESTORE: next_state = is_signed ? FIX_SIGN : INIT;
+ FIX_SIGN: next_state = INIT;
+ endcase
+
+ if (reset)
+ next_state = INIT;
+end
+
+always_ff @(posedge clk or posedge reset) begin
+ if (reset) begin
+ error <= 1'b0;
+ complete <= 1'b0;
+ end else begin
+ case (state)
+ INIT: begin
+ error <= 1'b0;
+
+ if (start) begin
+ quotient <= 16'b0;
+ P <= P_init;
+ idx <= !is_8_bit ? 4'hf : 4'h7;
+ error <= raise_error;
+ end
+
+ complete <= start && raise_error;
+ end
+ WORKING: begin
+ if (!P[63]) begin
+ quotient[idx] <= 1'b1;
+ P <= (P * 2) - {32'b0, D};
+ end else begin
+ P <= (P * 2) + {32'b0, D};
+ end
+ idx <= idx - 1'b1;
+ end
+ RESTORE: begin
+ quotient <= restored_quotient;
+ if (P[63])
+ P <= P + {{32{D[31]}}, D};
+ complete <= ~is_signed;
+ end
+ FIX_SIGN: begin
+ if (~in_signs_equal) begin
+ quotient <= negative_quotient;
+ error <= |quotient & is_signed & ~negative_quotient[is_8_bit ? 7 : 15];
+ end else begin
+ error <= |quotient & is_signed & quotient[is_8_bit ? 7 : 15];
+ end
+ if (dividend_negative && is_8_bit)
+ P[15:8] <= ~P[15:8] + 1'b1;
+ else if (dividend_negative)
+ P[31:16] <= ~P[31:16] + 1'b1;
+ complete <= 1'b1;
+ end
+ endcase
+ end
+end
+
+always_ff @(posedge clk)
+ state <= next_state;
+
+endmodule
diff --git a/common/CPU/x86/Fifo.sv b/common/CPU/x86/Fifo.sv
new file mode 100644
index 00000000..49a83f4e
--- /dev/null
+++ b/common/CPU/x86/Fifo.sv
@@ -0,0 +1,93 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+`default_nettype none
+module Fifo(input logic clk,
+ input logic reset,
+ input logic flush,
+ // Write port
+ input logic wr_en,
+ input logic [data_width-1:0] wr_data,
+ // Read port
+ input logic rd_en,
+ output logic [data_width-1:0] rd_data,
+ output logic empty,
+ output logic nearly_full,
+ output logic full);
+
+parameter data_width = 32;
+parameter depth = 6;
+parameter full_threshold = 2; // Number of entries free to be not-full
+
+localparam ptr_bits = $clog2(depth);
+
+reg [data_width-1:0] mem[depth-1:0] /* synthesis syn_ramstyle = "no_rw_check"*/;
+reg [ptr_bits-1:0] rd_ptr;
+reg [ptr_bits-1:0] wr_ptr;
+reg [ptr_bits:0] count;
+
+assign empty = count == 0;
+assign full = count == depth;
+assign nearly_full = count >= depth - full_threshold;
+
+assign rd_data = mem[rd_ptr];
+
+always_ff @(posedge clk or posedge reset) begin
+ if (reset) begin
+ wr_ptr <= {ptr_bits{1'b0}};
+ end else begin
+ if (flush)
+ wr_ptr <= {ptr_bits{1'b0}};
+ else if (wr_en && !full) begin
+ mem[wr_ptr] <= wr_data;
+ wr_ptr <= wr_ptr + 1'b1;
+ if (wr_ptr == depth[ptr_bits-1:0] - 1'b1)
+ wr_ptr <= {ptr_bits{1'b0}};
+ end
+ end
+end
+
+always_ff @(posedge clk or posedge reset) begin
+ if (reset) begin
+ rd_ptr <= {ptr_bits{1'b0}};
+ end else begin
+ if (flush)
+ rd_ptr <= {ptr_bits{1'b0}};
+ else if (rd_en && !empty) begin
+ rd_ptr <= rd_ptr + 1'b1;
+ if (rd_ptr == depth[ptr_bits-1:0] - 1'b1)
+ rd_ptr <= {ptr_bits{1'b0}};
+ end
+ end
+end
+
+always_ff @(posedge clk or posedge reset) begin
+ if (reset)
+ count <= {ptr_bits + 1{1'b0}};
+ else begin
+ if (flush)
+ count <= {ptr_bits + 1{1'b0}};
+ else if (wr_en && !full && rd_en && !empty)
+ ;
+ else if (wr_en && !full)
+ count <= count + 1'b1;
+ else if (rd_en && !empty)
+ count <= count - 1'b1;
+ end
+end
+
+endmodule
diff --git a/common/CPU/x86/Flags.sv b/common/CPU/x86/Flags.sv
new file mode 100644
index 00000000..09eec0a7
--- /dev/null
+++ b/common/CPU/x86/Flags.sv
@@ -0,0 +1,60 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+`default_nettype none
+module Flags(input logic clk,
+ input logic reset,
+ // verilator lint_off UNUSED
+ input logic [15:0] flags_in,
+ // verilator lint_on UNUSED
+ input logic [8:0] update_flags,
+ output logic [15:0] flags_out);
+
+reg C, P, A, Z, S, T, I, D, O;
+
+generate
+if (`S80X86_PSEUDO_286_INT == 1)
+ assign flags_out = {4'b0000, O, D, I, T, S, Z, 1'b0, A, 1'b0, P, 1'b1, C};
+else
+ assign flags_out = {4'b1111, O, D, I, T, S, Z, 1'b0, A, 1'b0, P, 1'b1, C};
+endgenerate
+
+always_ff @(posedge clk or posedge reset) begin
+ if (reset) begin
+ C <= 1'b0;
+ P <= 1'b0;
+ A <= 1'b0;
+ Z <= 1'b0;
+ S <= 1'b0;
+ T <= 1'b0;
+ I <= 1'b0;
+ D <= 1'b0;
+ O <= 1'b0;
+ end else begin
+ C <= update_flags[UpdateFlags_CF] ? flags_in[CF_IDX] : C;
+ P <= update_flags[UpdateFlags_PF] ? flags_in[PF_IDX] : P;
+ A <= update_flags[UpdateFlags_AF] ? flags_in[AF_IDX] : A;
+ Z <= update_flags[UpdateFlags_ZF] ? flags_in[ZF_IDX] : Z;
+ S <= update_flags[UpdateFlags_SF] ? flags_in[SF_IDX] : S;
+ T <= update_flags[UpdateFlags_TF] ? flags_in[TF_IDX] : T;
+ I <= update_flags[UpdateFlags_IF] ? flags_in[IF_IDX] : I;
+ D <= update_flags[UpdateFlags_DF] ? flags_in[DF_IDX] : D;
+ O <= update_flags[UpdateFlags_OF] ? flags_in[OF_IDX] : O;
+ end
+end
+
+endmodule
diff --git a/common/CPU/x86/FlagsEnum.sv b/common/CPU/x86/FlagsEnum.sv
new file mode 100644
index 00000000..b48acfad
--- /dev/null
+++ b/common/CPU/x86/FlagsEnum.sv
@@ -0,0 +1,33 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+`ifndef FLAGSENUM
+`define FLAGSENUM
+
+typedef enum bit [3:0] {
+ CF_IDX = 4'd0,
+ PF_IDX = 4'd2,
+ AF_IDX = 4'd4,
+ ZF_IDX = 4'd6,
+ SF_IDX = 4'd7,
+ TF_IDX = 4'd8,
+ IF_IDX = 4'd9,
+ DF_IDX = 4'd10,
+ OF_IDX = 4'd11
+} FLAG_t;
+
+`endif // FLAGSENUM
diff --git a/common/CPU/x86/IP.sv b/common/CPU/x86/IP.sv
new file mode 100644
index 00000000..c31495d4
--- /dev/null
+++ b/common/CPU/x86/IP.sv
@@ -0,0 +1,51 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+`default_nettype none
+module IP(input logic clk,
+ input logic reset,
+ input logic start_instruction,
+ input logic next_instruction,
+ input logic rollback,
+ input logic [3:0] inc,
+ input logic wr_en,
+ input logic [15:0] wr_val,
+ output logic [15:0] val);
+
+reg [15:0] cur_val;
+reg [15:0] instruction_start_addr;
+assign val = cur_val;
+
+always_ff @(posedge clk or posedge reset)
+ if (reset)
+ instruction_start_addr <= 16'b0;
+ else if (start_instruction || next_instruction)
+ instruction_start_addr <= wr_en ? wr_val : cur_val;
+ else if (next_instruction)
+ instruction_start_addr <= cur_val;
+
+always @(posedge clk or posedge reset)
+ if (reset)
+ cur_val <= 16'b0;
+ else if (wr_en)
+ cur_val <= wr_val;
+ else if (rollback)
+ cur_val <= instruction_start_addr;
+ else if (start_instruction)
+ cur_val <= cur_val + {12'b0, inc};
+
+endmodule
diff --git a/common/CPU/x86/ImmediateReader.sv b/common/CPU/x86/ImmediateReader.sv
new file mode 100644
index 00000000..cc6809d6
--- /dev/null
+++ b/common/CPU/x86/ImmediateReader.sv
@@ -0,0 +1,96 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+`default_nettype none
+module ImmediateReader(input logic clk,
+ input logic reset,
+ // Control.
+ input logic start,
+ input logic flush,
+ output logic busy,
+ output logic complete,
+ input logic is_8bit,
+ // Result.
+ output logic [15:0] immediate,
+ // Fifo Read Port.
+ output logic fifo_rd_en,
+ input logic [7:0] fifo_rd_data,
+ input logic fifo_empty);
+
+assign fifo_rd_en = ~fifo_empty & (start | (_fetching & ~complete));
+
+reg [15:0] _immediate_buf;
+
+wire [1:0] _num_bytes = is_8bit ? 2'h1 : 2'h2;
+reg [1:0] _bytes_read;
+
+reg _fetch_busy;
+wire _fetching = _fetch_busy & ~complete;
+
+assign complete = reset ? 1'b0 : _bytes_read == _num_bytes - 1'b1 &&
+ ~fifo_empty && (start || _fetch_busy);
+
+assign busy = (start | _fetch_busy) & ~complete;
+
+always_comb begin
+ if (_bytes_read == 2'd0 && ~fifo_empty && start)
+ immediate = {{8{fifo_rd_data[7]}}, fifo_rd_data[7:0]};
+ else if (_bytes_read == 2'd1 && ~fifo_empty && !is_8bit)
+ immediate = {fifo_rd_data, _immediate_buf[7:0]};
+ else
+ immediate = _immediate_buf;
+end
+
+always_ff @(posedge clk or posedge reset)
+ if (reset)
+ _fetch_busy <= 1'b0;
+ else if (complete || flush)
+ _fetch_busy <= 1'b0;
+ else if (start)
+ _fetch_busy <= 1'b1;
+
+always_ff @(posedge clk or posedge reset) begin
+ if (reset) begin
+ _bytes_read <= 2'b0;
+ end else begin
+ if ((start && !_fetch_busy) || complete || flush)
+ _bytes_read <= 2'b0;
+ if (fifo_rd_en && !complete && !flush)
+ _bytes_read <= _bytes_read + 2'b1;
+ end
+end
+
+always_ff @(posedge clk or posedge reset) begin
+ if (reset) begin
+ _immediate_buf <= 16'b0;
+ end else begin
+ if (start && !_fetch_busy)
+ _immediate_buf <= 16'b0;
+
+ if (_bytes_read == 2'b0 && ~fifo_empty && start) begin
+ _immediate_buf[7:0] <= fifo_rd_data;
+ if (is_8bit)
+ _immediate_buf[15:8] <= {8{fifo_rd_data[7]}};
+ end else if (_bytes_read == 2'd1 && ~fifo_empty)
+ _immediate_buf[15:8] <= fifo_rd_data;
+
+ if (flush)
+ _immediate_buf <= 16'b0;
+ end
+end
+
+endmodule
diff --git a/common/CPU/x86/InsnDecoder.sv b/common/CPU/x86/InsnDecoder.sv
new file mode 100644
index 00000000..c9251f7d
--- /dev/null
+++ b/common/CPU/x86/InsnDecoder.sv
@@ -0,0 +1,237 @@
+// Copyright Jamie Iles, 2018
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+module InsnDecoder(input logic clk,
+ input logic reset,
+ input logic flush,
+ input logic stall,
+ input logic nearly_full,
+ output logic fifo_rd_en,
+ input logic [7:0] fifo_rd_data,
+ input logic fifo_empty,
+ output Instruction instruction,
+ output logic complete,
+ output logic immed_start,
+ input logic immed_complete,
+ output logic immed_is_8bit,
+ input logic [15:0] immediate);
+
+typedef enum bit[2:0] {
+ STATE_OPCODE,
+ STATE_MODRM,
+ STATE_DISPLACEMENT,
+ STATE_IMMED1,
+ STATE_IMMED2,
+ STATE_WAIT_SPACE
+} state_t;
+
+state_t state, next_state;
+
+logic insn_complete;
+assign fifo_rd_en = ~reset & ~fifo_empty & ~immed_start & state != STATE_WAIT_SPACE;
+
+function logic has_displacement;
+ // verilator lint_off UNUSED
+ input logic [7:0] mbyte;
+ // verilator lint_on UNUSED
+
+ has_displacement = (mbyte[2:0] == 3'b110 && mbyte[7:6] == 2'b00) || ^mbyte[7:6];
+endfunction
+
+function logic is_prefix;
+ input logic [7:0] b;
+
+ case (b)
+ 8'h26, 8'h2e, 8'h36, 8'h3e, 8'hf2, 8'hf3, 8'hf0: is_prefix = 1'b1;
+ default: is_prefix = 1'b0;
+ endcase
+endfunction
+
+function state_t next_instr;
+ next_instr = (nearly_full || stall) && insn_complete ? STATE_WAIT_SPACE : STATE_OPCODE;
+endfunction
+
+always_comb begin
+ insn_complete = 1'b0;
+
+ case (state)
+ STATE_OPCODE: begin
+ insn_complete = (!fifo_empty && !is_prefix(fifo_rd_data) &&
+ !insn_has_modrm(fifo_rd_data) &&
+ insn_immed_count(fifo_rd_data, 3'b0) == 2'b00) ||
+ instruction.invalid;
+ next_state = fifo_empty ? STATE_OPCODE :
+ is_prefix(fifo_rd_data) ? STATE_OPCODE :
+ insn_has_modrm(fifo_rd_data) ? STATE_MODRM :
+ insn_immed_count(fifo_rd_data, 3'b0) != 2'b00 ? STATE_IMMED1 :
+ insn_complete ? next_instr() : STATE_OPCODE;
+ end
+ STATE_MODRM: begin
+ insn_complete = !fifo_empty && !has_displacement(fifo_rd_data) &&
+ insn_immed_count(instruction.opcode, fifo_rd_data[5:3]) == 2'b00;
+ next_state = fifo_empty ? STATE_MODRM :
+ has_displacement(fifo_rd_data) ? STATE_DISPLACEMENT :
+ insn_immed_count(instruction.opcode, fifo_rd_data[5:3]) != 2'b00 ?
+ STATE_IMMED1 : next_instr();
+ end
+ STATE_DISPLACEMENT: begin
+ insn_complete = immed_complete &&
+ insn_immed_count(instruction.opcode, instruction.mod_rm[5:3]) == 2'b0;
+ next_state = immed_complete ?
+ (insn_immed_count(instruction.opcode, instruction.mod_rm[5:3]) != 2'b00 ?
+ STATE_IMMED1 : next_instr()) : STATE_DISPLACEMENT;
+ end
+ STATE_IMMED1: begin
+ insn_complete = insn_immed_count(instruction.opcode,
+ instruction.mod_rm[5:3]) == 2'b01 &&
+ immed_complete;
+ next_state = immed_complete ?
+ (insn_immed_count(instruction.opcode, instruction.mod_rm[5:3]) == 2'd2 ?
+ STATE_IMMED2 : next_instr()) :
+ STATE_IMMED1;
+ end
+ STATE_IMMED2: begin
+ insn_complete = immed_complete;
+ next_state = immed_complete ? next_instr(): STATE_IMMED2;
+ end
+ STATE_WAIT_SPACE: begin
+ next_state = stall ? STATE_WAIT_SPACE : STATE_OPCODE;
+ end
+ default: next_state = STATE_OPCODE;
+ endcase
+
+ if (reset || flush)
+ next_state = STATE_OPCODE;
+end
+
+task add_segment_override;
+ input logic [1:0] seg;
+begin
+ instruction.has_segment_override <= 1'b1;
+ instruction.segment <= SR_t'(seg);
+end
+endtask
+
+always_ff @(posedge clk or posedge reset) begin
+ if (reset) begin
+ complete <= 1'b0;
+ instruction <= Instruction'(1'b0);
+ immed_start <= 1'b0;
+ end else if (flush) begin
+ complete <= 1'b0;
+ instruction <= Instruction'(1'b0);
+ immed_start <= 1'b0;
+ end else begin
+ if (complete && !stall) begin
+ instruction <= Instruction'(1'b0);
+ complete <= 1'b0;
+ end
+
+ if (insn_complete)
+ complete <= 1'b1;
+
+ case (state)
+ STATE_OPCODE: begin
+ if (!fifo_empty) begin
+ case (fifo_rd_data)
+ 8'hf0: instruction.lock <= 1'b1;
+ 8'hf2: instruction.rep <= REP_PREFIX_NE;
+ 8'hf3: instruction.rep <= REP_PREFIX_E;
+ 8'h26: add_segment_override(ES);
+ 8'h2e: add_segment_override(CS);
+ 8'h36: add_segment_override(SS);
+ 8'h3e: add_segment_override(DS);
+ default: begin
+ instruction.opcode <= fifo_rd_data;
+ instruction.has_modrm <= insn_has_modrm(fifo_rd_data);
+ end
+ endcase
+
+ if (complete)
+ instruction.length <= 4'b1;
+ else if (!fifo_empty)
+ {instruction.invalid, instruction.length} <=
+ {instruction.invalid, instruction.length} + 5'b1;
+
+ if (next_state == STATE_IMMED1) begin
+ immed_start <= 1'b1;
+ immed_is_8bit <= insn_immed_is_8bit(fifo_rd_data,
+ 3'b0, 1'b0);
+ end
+ end
+ end
+ STATE_MODRM: begin
+ if (!fifo_empty) begin
+ {instruction.invalid, instruction.length} <=
+ {instruction.invalid, instruction.length} + 5'b1;
+ instruction.mod_rm <= fifo_rd_data;
+ end
+ if (next_state == STATE_DISPLACEMENT) begin
+ immed_start <= 1'b1;
+ immed_is_8bit <= fifo_rd_data[7:6] == 2'b01;
+ end else if (next_state == STATE_IMMED1) begin
+ immed_start <= 1'b1;
+ immed_is_8bit <= insn_immed_is_8bit(instruction.opcode,
+ fifo_rd_data[5:3], 1'b0);
+ end
+ end
+ STATE_DISPLACEMENT: begin
+ if (immed_complete) begin
+ instruction.displacement <= immediate;
+ {instruction.invalid, instruction.length} <=
+ {instruction.invalid, instruction.length} +
+ (immed_is_8bit ? 5'd1 : 5'd2);
+ immed_start <= 1'b0;
+ end
+ if (next_state == STATE_IMMED1) begin
+ immed_start <= 1'b1;
+ immed_is_8bit <= insn_immed_is_8bit(instruction.opcode,
+ instruction.mod_rm[5:3], 1'b0);
+ end
+ end
+ STATE_IMMED1: begin
+ if (immed_complete) begin
+ instruction.immediates[0] <= immediate;
+ {instruction.invalid, instruction.length} <=
+ {instruction.invalid, instruction.length} +
+ (immed_is_8bit ? 5'd1 : 5'd2);
+ immed_start <= 1'b0;
+ end
+ if (next_state == STATE_IMMED2) begin
+ immed_start <= 1'b1;
+ immed_is_8bit <= insn_immed_is_8bit(instruction.opcode,
+ instruction.mod_rm[5:3], 1'b1);
+ end
+ end
+ STATE_IMMED2: begin
+ if (immed_complete) begin
+ instruction.immediates[1] <= immediate;
+ {instruction.invalid, instruction.length} <=
+ {instruction.invalid, instruction.length} +
+ (immed_is_8bit ? 5'd1 : 5'd2);
+ immed_start <= 1'b0;
+ end
+ end
+ default: ;
+ endcase
+ end
+end
+
+always_ff @(posedge clk)
+ state <= next_state;
+
+endmodule
diff --git a/common/CPU/x86/Instruction.sv b/common/CPU/x86/Instruction.sv
new file mode 100644
index 00000000..d32f020a
--- /dev/null
+++ b/common/CPU/x86/Instruction.sv
@@ -0,0 +1,30 @@
+// Copyright Jamie Iles, 2018
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+typedef struct packed {
+ logic invalid;
+ logic [3:0] length;
+ logic lock;
+ RepPrefix rep;
+ SR_t segment;
+ logic has_segment_override;
+ logic has_modrm;
+ logic [1:0][15:0] immediates;
+ logic [15:0] displacement;
+ logic [7:0] mod_rm;
+ logic [7:0] opcode;
+} Instruction;
diff --git a/common/CPU/x86/InstructionDefinitions.sv.templ b/common/CPU/x86/InstructionDefinitions.sv.templ
new file mode 100644
index 00000000..06b6acc6
--- /dev/null
+++ b/common/CPU/x86/InstructionDefinitions.sv.templ
@@ -0,0 +1,52 @@
+// Copyright Jamie Iles, 2018
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+function logic insn_has_modrm;
+ input logic [7:0] opcode;
+
+ casez (opcode)
+ <%#modrm_opcodes%>
+ <%opc%>: insn_has_modrm = 1'b1;
+ <%/modrm_opcodes%>
+ default: insn_has_modrm = 1'b0;
+ endcase
+endfunction
+
+function logic [1:0] insn_immed_count;
+ input logic [7:0] opcode;
+ input logic [2:0] modrm_reg;
+
+ unique casez ({opcode, modrm_reg})
+ <%#instructions%>
+ {<%opcode%>, <%reg%>}: insn_immed_count = 2'd<%immediate_count%>;
+ <%/instructions%>
+ default: insn_immed_count = 2'b0;
+ endcase
+endfunction
+
+function logic insn_immed_is_8bit;
+ input logic [7:0] opcode;
+ input logic [2:0] modrm_reg;
+ input logic immed_num;
+
+ unique casez ({opcode, modrm_reg})
+ <%#instructions%>
+ {<%opcode%>, <%reg%>}: insn_immed_is_8bit = ~|(<%immediate_sizes%> & (2'b1 << immed_num));
+ <%/instructions%>
+ default: insn_immed_is_8bit = 1'b0;
+ endcase
+endfunction
diff --git a/common/CPU/x86/JumpTest.sv b/common/CPU/x86/JumpTest.sv
new file mode 100644
index 00000000..efab82d4
--- /dev/null
+++ b/common/CPU/x86/JumpTest.sv
@@ -0,0 +1,51 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+`default_nettype none
+module JumpTest(input logic [7:0] opcode,
+ // verilator lint_off UNUSED
+ input logic [15:0] flags,
+ // verilator lint_on UNUSED
+ output logic taken);
+
+always_comb begin
+ taken = 1'b0;
+
+ unique casez(opcode)
+ 8'b01100010: taken = flags[CF_IDX]; // BOUND
+ 8'b01110000: taken = flags[OF_IDX]; // JO
+ 8'b01110001: taken = ~flags[OF_IDX]; // JNO
+ 8'b01110010: taken = flags[CF_IDX]; // JB
+ 8'b01110011: taken = ~flags[CF_IDX]; // JNB
+ 8'b01110100: taken = flags[ZF_IDX]; // JE
+ 8'b01110101: taken = ~flags[ZF_IDX]; // JNE
+ 8'b01110110: taken = flags[CF_IDX] | flags[ZF_IDX]; // JBE
+ 8'b01110111: taken = ~(flags[CF_IDX] | flags[ZF_IDX]); // JNBE
+ 8'b01111000: taken = flags[SF_IDX]; // JS
+ 8'b01111001: taken = ~flags[SF_IDX]; // JNS
+ 8'b01111010: taken = flags[PF_IDX]; // JP
+ 8'b01111011: taken = ~flags[PF_IDX]; // JNP
+ 8'b01111100: taken = flags[OF_IDX] ^ flags[SF_IDX]; // JL
+ 8'b01111101: taken = ~(flags[SF_IDX] ^ flags[OF_IDX]); // JNL
+ 8'b01111110: taken = (flags[OF_IDX] ^ flags[SF_IDX]) | flags[ZF_IDX]; // JLE
+ 8'b01111111: taken = ~((flags[SF_IDX] ^ flags[OF_IDX]) | flags[ZF_IDX]); // JNLE
+ 8'b11001110: taken = flags[OF_IDX]; // INTO
+ default: taken = 1'b0;
+ endcase
+end
+
+endmodule
diff --git a/common/CPU/x86/LoadStore.sv b/common/CPU/x86/LoadStore.sv
new file mode 100644
index 00000000..f9273e4d
--- /dev/null
+++ b/common/CPU/x86/LoadStore.sv
@@ -0,0 +1,120 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+`default_nettype none
+module LoadStore(input logic clk,
+ input logic reset,
+ // Memory Address Register
+ input logic write_mar,
+ input logic [15:0] segment,
+ input [15:0] mar_in,
+ // Memory Data Register
+ output [15:0] mar_out,
+ output [15:0] mdr_out,
+ input logic write_mdr,
+ input [15:0] mdr_in,
+ // Memory bus
+ output logic [19:1] m_addr,
+ input logic [15:0] m_data_in,
+ output logic [15:0] m_data_out,
+ output logic m_access,
+ input logic m_ack,
+ output logic m_wr_en,
+ output logic [1:0] m_bytesel,
+ // Control
+ input logic io,
+ input logic start,
+ input logic is_8bit,
+ input logic wr_en,
+ output logic busy,
+ output logic complete);
+
+reg [15:0] mar;
+reg [15:0] mdr;
+
+assign busy = (start | fetching | second_byte) & ~complete;
+assign m_access = (start | fetching | second_byte) & ~complete & ~m_ack;
+assign m_addr = !io ?
+ {segment, 3'b0} + {3'b0, mar[15:1]} + {18'b0, second_byte} :
+ {3'b0, mar[15:1]} + {18'b0, second_byte};
+assign m_wr_en = wr_en;
+assign mdr_out = mdr;
+assign mar_out = mar;
+
+always_comb begin
+ if (unaligned && !second_byte)
+ m_data_out = {mdr[7:0], 8'b0};
+ else if (unaligned && second_byte)
+ m_data_out = {8'b0, mdr[15:8]};
+ else
+ m_data_out = mdr;
+end
+
+always_comb begin
+ if (!is_8bit && !unaligned)
+ m_bytesel = 2'b11;
+ else if (unaligned && !second_byte)
+ m_bytesel = 2'b10;
+ else
+ m_bytesel = 2'b01;
+end
+
+wire unaligned = mar[0];
+reg fetching;
+reg second_byte;
+
+always_ff @(posedge clk or posedge reset)
+ if (reset)
+ fetching <= 1'b0;
+ else
+ fetching <= start ? 1'b1 : complete ? 1'b0 : fetching;
+
+always_ff @(posedge clk or posedge reset)
+ if (reset)
+ mar <= 16'b0;
+ else
+ mar <= write_mar ? mar_in : mar;
+
+always_ff @(posedge clk)
+ complete <= m_ack && (is_8bit || (unaligned && second_byte) || !unaligned);
+
+always_ff @(posedge clk or posedge reset)
+ if (reset) begin
+ second_byte <= 1'b0;
+ end else begin
+ if (m_ack && unaligned && !second_byte && !is_8bit)
+ second_byte <= 1'b1;
+ else if ((start && !fetching) || complete)
+ second_byte <= 1'b0;
+ end
+
+always_ff @(posedge clk or posedge reset) begin
+ if (reset)
+ mdr <= 16'b0;
+ else if (start && !fetching && !wr_en)
+ mdr <= 16'b0;
+ else if (write_mdr)
+ mdr <= mdr_in;
+ else if (!wr_en && m_ack && !unaligned)
+ mdr <= is_8bit ? {8'b0, m_data_in[7:0]} : m_data_in;
+ else if (!wr_en && m_ack && unaligned && !second_byte)
+ mdr[7:0] <= unaligned ? m_data_in[15:8] : m_data_in[7:0];
+ else if (!wr_en && m_ack && unaligned && second_byte)
+ mdr[15:8] <= unaligned ? m_data_in[7:0] : m_data_in[15:8];
+end
+
+endmodule
diff --git a/common/CPU/x86/LoopCounter.sv b/common/CPU/x86/LoopCounter.sv
new file mode 100644
index 00000000..d4ada14a
--- /dev/null
+++ b/common/CPU/x86/LoopCounter.sv
@@ -0,0 +1,35 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+`default_nettype none
+module LoopCounter(input logic clk,
+ input logic [4:0] count_in,
+ input logic load,
+ input logic next,
+ output logic done);
+
+reg [4:0] count;
+
+assign done = ~|count;
+
+always_ff @(posedge clk)
+ if (load)
+ count <= count_in;
+ else if (next && |count)
+ count <= count - 1'b1;
+
+endmodule
diff --git a/common/CPU/x86/MemArbiter.sv b/common/CPU/x86/MemArbiter.sv
new file mode 100644
index 00000000..d3798664
--- /dev/null
+++ b/common/CPU/x86/MemArbiter.sv
@@ -0,0 +1,76 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+`default_nettype none
+module MemArbiter(input logic clk,
+ input logic reset,
+ // Instruction bus
+ input logic [19:1] a_m_addr,
+ output logic [15:0] a_m_data_in,
+ input logic [15:0] a_m_data_out,
+ input logic a_m_access,
+ output logic a_m_ack,
+ input logic a_m_wr_en,
+ input logic [1:0] a_m_bytesel,
+ // Data bus
+ input logic [19:1] b_m_addr,
+ output logic [15:0] b_m_data_in,
+ input logic [15:0] b_m_data_out,
+ input logic b_m_access,
+ output logic b_m_ack,
+ input logic b_m_wr_en,
+ input logic [1:0] b_m_bytesel,
+ // Output bus
+ output logic [19:1] q_m_addr,
+ input logic [15:0] q_m_data_in,
+ output logic [15:0] q_m_data_out,
+ output logic q_m_access,
+ input logic q_m_ack,
+ output logic q_m_wr_en,
+ output logic [1:0] q_m_bytesel,
+ output logic q_b);
+
+reg grant_to_b;
+reg grant_active;
+
+assign q_b = (grant_active && grant_to_b) || (!grant_active && b_m_access);
+
+assign q_m_addr = q_b ? b_m_addr : a_m_addr;
+assign q_m_data_out = q_b ? b_m_data_out : a_m_data_out;
+assign q_m_access = ~q_m_ack & (b_m_access | a_m_access);
+assign q_m_wr_en = q_b ? b_m_wr_en : a_m_wr_en;
+assign q_m_bytesel = q_b ? b_m_bytesel : a_m_bytesel;
+
+assign a_m_data_in = grant_active & ~grant_to_b ? q_m_data_in : 16'b0;
+assign a_m_ack = grant_active & ~grant_to_b & q_m_ack;
+assign b_m_data_in = grant_active & grant_to_b ? q_m_data_in : 16'b0;
+assign b_m_ack = grant_active & grant_to_b & q_m_ack;
+
+always_ff @(posedge clk or posedge reset) begin
+ if (reset) begin
+ grant_active <= 1'b0;
+ end else begin
+ if (q_m_ack)
+ grant_active <= 1'b0;
+ else if (!grant_active && (b_m_access || a_m_access)) begin
+ grant_active <= 1'b1;
+ grant_to_b <= b_m_access;
+ end
+ end
+end
+
+endmodule
diff --git a/common/CPU/x86/ModRMDecode.sv b/common/CPU/x86/ModRMDecode.sv
new file mode 100644
index 00000000..007b1404
--- /dev/null
+++ b/common/CPU/x86/ModRMDecode.sv
@@ -0,0 +1,103 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+`default_nettype none
+module ModRMDecode(input logic clk,
+ input logic reset,
+ // Control.
+ input logic start,
+ input logic clear,
+ input logic [7:0] modrm,
+ input logic [15:0] displacement,
+ input logic [15:0] si,
+ input logic [15:0] di,
+ input logic [15:0] bp,
+ input logic [15:0] bx,
+ // Results
+ output logic [15:0] effective_address,
+ output logic [2:0] regnum,
+ output logic rm_is_reg,
+ output logic [2:0] rm_regnum,
+ output logic bp_as_base);
+
+wire [1:0] _mod = modrm[7:6];
+wire [2:0] _reg = modrm[5:3];
+wire [2:0] _rm = modrm[2:0];
+
+always_ff @(posedge clk or posedge reset) begin
+ if (reset) begin
+ bp_as_base <= 1'b0;
+ rm_is_reg <= 1'b0;
+ regnum <= 3'b0;
+ rm_regnum <= 3'b0;
+ end else begin
+ if (clear)
+ bp_as_base <= 1'b0;
+ if (start) begin
+ regnum <= _reg;
+ rm_regnum <= _rm;
+ rm_is_reg <= _mod == 2'b11;
+
+ case (_mod)
+ 2'b00: bp_as_base <= (_rm == 3'b010 || _rm == 3'b011);
+ 2'b01: bp_as_base <= (_rm == 3'b010 || _rm == 3'b011 || _rm == 3'b110);
+ 2'b10: bp_as_base <= (_rm == 3'b010 || _rm == 3'b011 || _rm == 3'b110);
+ default: bp_as_base <= 1'b0;
+ endcase
+ end
+ end
+end
+
+always_ff @(posedge clk or posedge reset) begin
+ if (reset)
+ effective_address <= 16'b0;
+ else begin
+ if (start) begin
+ effective_address <= 16'b0;
+
+ case (_mod)
+ 2'b00: begin
+ case (_rm)
+ 3'd0: effective_address <= bx + si;
+ 3'd1: effective_address <= bx + di;
+ 3'd2: effective_address <= bp + si;
+ 3'd3: effective_address <= bp + di;
+ 3'd4: effective_address <= si;
+ 3'd5: effective_address <= di;
+ 3'd6: effective_address <= displacement;
+ 3'd7: effective_address <= bx;
+ endcase
+ end
+ 2'b01, 2'b10: begin
+ case (_rm)
+ 3'd0: effective_address <= bx + si + displacement;
+ 3'd1: effective_address <= bx + di + displacement;
+ 3'd2: effective_address <= bp + si + displacement;
+ 3'd3: effective_address <= bp + di + displacement;
+ 3'd4: effective_address <= si + displacement;
+ 3'd5: effective_address <= di + displacement;
+ 3'd6: effective_address <= bp + displacement;
+ 3'd7: effective_address <= bx + displacement;
+ endcase
+ end
+ 2'b11: effective_address <= 16'b0;
+ endcase
+ end
+ end
+end
+
+endmodule
diff --git a/common/CPU/x86/PosedgeToPulse.sv b/common/CPU/x86/PosedgeToPulse.sv
new file mode 100644
index 00000000..4695296e
--- /dev/null
+++ b/common/CPU/x86/PosedgeToPulse.sv
@@ -0,0 +1,36 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+`default_nettype none
+module PosedgeToPulse(input logic clk,
+ input logic reset,
+ input logic d,
+ output logic q);
+
+reg d_prev;
+
+always_ff @(posedge clk)
+ d_prev <= d;
+
+always_ff @(posedge clk or posedge reset)
+ if (reset) begin
+ q <= 1'b0;
+ end else begin
+ q <= (d ^ d_prev) & d;
+ end
+
+endmodule
diff --git a/common/CPU/x86/Prefetch.sv b/common/CPU/x86/Prefetch.sv
new file mode 100644
index 00000000..effd55bb
--- /dev/null
+++ b/common/CPU/x86/Prefetch.sv
@@ -0,0 +1,128 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+// Prefetcher
+//
+// This module is responsible for fetching bytes from the memory and pushing
+// them into the instruction stream FIFO. The CS is stored outside of the
+// Prefetch unit and passed in to be combined with the internal IP which is
+// wired out. This means that IP wrapping works correctly, and can be updated
+// under external control. The fetching can be stalled when servicing
+// a branch, updating the IP will flush the FIFO.
+`default_nettype none
+module Prefetch(input logic clk,
+ input logic reset,
+ // Address control.
+ input logic [15:0] new_cs,
+ input logic [15:0] new_ip,
+ input logic load_new_ip,
+ // FIFO write port.
+ output logic fifo_wr_en,
+ output logic [7:0] fifo_wr_data,
+ output logic fifo_reset,
+ input logic fifo_full,
+ // Memory port.
+ output logic mem_access,
+ input logic mem_ack,
+ output logic [19:1] mem_address,
+ input logic [15:0] mem_data);
+
+reg [15:0] next_fetch_address, fetch_address;
+reg [15:0] next_cs, cs;
+reg abort_cur;
+reg [7:0] fetched_high_byte;
+reg write_second;
+reg [15:0] next_sequential_fetch;
+
+wire should_write_second_byte = mem_ack && !abort_cur && !fetch_address[0] && !fifo_reset;
+
+// verilator lint_off UNUSED
+wire [15:0] next_address = mem_ack ? next_sequential_fetch : fetch_address;
+// verilator lint_on UNUSED
+
+wire [19:1] _mem_address = {cs, 3'b0} + {4'b0, next_address[15:1]};
+wire _mem_access = !reset && !fifo_full && !mem_ack && !write_second && ~(~mem_access && load_new_ip);
+
+reg mem_access2;
+assign mem_access = mem_access2 & !mem_ack;
+
+always_ff @(posedge clk) begin
+mem_address <= _mem_address;
+mem_access2 <= _mem_access;
+end
+
+assign fifo_wr_en = !abort_cur && !load_new_ip && (mem_ack || write_second);
+assign fifo_reset = load_new_ip | (abort_cur & mem_ack);
+assign fifo_wr_data = mem_ack ?
+ (fetch_address[0] ? mem_data[15:8] : mem_data[7:0]) : fetched_high_byte;
+
+always_ff @(posedge clk or posedge reset) begin
+ if (reset) begin
+ abort_cur <= 1'b0;
+ end else begin
+ if (abort_cur && mem_ack)
+ abort_cur <= 1'b0;
+ else if (mem_access && load_new_ip)
+ abort_cur <= 1'b1;
+ end
+end
+
+always_ff @(posedge clk or posedge reset)
+ write_second <= reset ? 1'b0 : should_write_second_byte;
+
+always_ff @(posedge clk or posedge reset)
+ if (reset) begin
+ cs <= 16'hffff;
+ end else begin
+ if (abort_cur && mem_ack)
+ cs <= next_cs;
+ else if (load_new_ip && !mem_access)
+ cs <= new_cs;
+ end
+
+always_ff @(posedge clk or posedge reset)
+ if (reset)
+ next_cs <= 16'hffff;
+ else if (load_new_ip)
+ next_cs <= new_cs;
+
+always_ff @(posedge clk or posedge reset) begin
+ if (reset)
+ fetch_address <= 16'b0;
+ else if (abort_cur && mem_ack)
+ fetch_address <= next_fetch_address;
+ else if (load_new_ip && !mem_access)
+ fetch_address <= new_ip;
+ else if (!abort_cur && !load_new_ip && (mem_ack || write_second))
+ fetch_address <= fetch_address + 1'b1;
+end
+
+always_ff @(posedge clk or posedge reset) begin
+ if (reset)
+ next_fetch_address <= 16'b0;
+ else if (load_new_ip)
+ next_fetch_address <= new_ip;
+end
+
+always_ff @(posedge clk)
+ if (mem_ack)
+ fetched_high_byte <= mem_data[15:8];
+
+always_ff @(posedge clk)
+ next_sequential_fetch <= fetch_address + 1'b1;
+
+endmodule
diff --git a/common/CPU/x86/RegisterEnum.sv b/common/CPU/x86/RegisterEnum.sv
new file mode 100644
index 00000000..36143acb
--- /dev/null
+++ b/common/CPU/x86/RegisterEnum.sv
@@ -0,0 +1,56 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+`ifndef REGISTERENUM
+`define REGISTERENUM
+
+typedef enum bit [2:0] {
+ AX,
+ CX,
+ DX,
+ BX,
+ SP,
+ BP,
+ SI,
+ DI
+} GPR16_t;
+
+typedef enum bit [2:0] {
+ AL,
+ CL,
+ DL,
+ BL,
+ AH,
+ CH,
+ DH,
+ BH
+} GPR8_t;
+
+typedef enum bit [1:0] {
+ ES,
+ CS,
+ SS,
+ DS
+} SR_t;
+
+typedef enum bit [1:0] {
+ REP_PREFIX_NONE,
+ REP_PREFIX_E,
+ REP_PREFIX_NE
+} RepPrefix;
+
+`endif
diff --git a/common/CPU/x86/RegisterFile.sv b/common/CPU/x86/RegisterFile.sv
new file mode 100644
index 00000000..7ee98da2
--- /dev/null
+++ b/common/CPU/x86/RegisterFile.sv
@@ -0,0 +1,89 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+`default_nettype none
+module RegisterFile(input logic clk,
+ input logic reset,
+ input logic is_8_bit,
+ output logic [15:0] si,
+ output logic [15:0] di,
+ output logic [15:0] bp,
+ output logic [15:0] bx,
+ // Read port.
+ input logic [2:0] rd_sel[2],
+ output logic [15:0] rd_val[2],
+ // Write port.
+ input logic [2:0] wr_sel,
+ input logic [15:0] wr_val,
+ input logic wr_en);
+
+reg [15:0] gprs[8];
+
+wire wr_sel_low_byte = ~wr_sel[2];
+wire [2:0] wr_8_bit_sel = {1'b0, wr_sel[1:0]};
+
+always_ff @(posedge reset)
+ ; // Reset is handled by the microcode.
+
+always_ff @(posedge clk) begin
+ if (wr_en) begin
+ if (is_8_bit) begin
+ if (wr_sel_low_byte)
+ gprs[wr_8_bit_sel][7:0] <= wr_val[7:0];
+ else
+ gprs[wr_8_bit_sel][15:8] <= wr_val[7:0];
+ end else begin
+ gprs[wr_sel] <= wr_val;
+ end
+ end
+end
+
+always_ff @(posedge clk) begin
+ si <= wr_en && !is_8_bit && wr_sel == SI ? wr_val : gprs[SI];
+ di <= wr_en && !is_8_bit && wr_sel == DI ? wr_val : gprs[DI];
+ bp <= wr_en && !is_8_bit && wr_sel == BP ? wr_val : gprs[BP];
+
+ bx <= gprs[BX];
+ if (wr_en && !is_8_bit && wr_sel == BX)
+ bx <= wr_val;
+ if (wr_en && is_8_bit && wr_sel == BL)
+ bx <= {gprs[BX][15:8], wr_val[7:0]};
+ if (wr_en && is_8_bit && wr_sel == BH)
+ bx <= {wr_val[7:0], gprs[BX][7:0]};
+end
+
+genvar rd_port;
+
+generate
+for (rd_port = 0; rd_port < 2; ++rd_port) begin: read_port
+ wire rd_sel_low_byte = ~rd_sel[rd_port][2];
+ wire [2:0] rd_8_bit_sel = {1'b0, rd_sel[rd_port][1:0]};
+ wire bypass = wr_en && wr_sel == rd_sel[rd_port];
+
+ always_ff @(posedge clk) begin
+ if (is_8_bit)
+ rd_val[rd_port] <= bypass ? {8'b0, wr_val[7:0]} :
+ {8'b0, rd_sel_low_byte ?
+ gprs[rd_8_bit_sel][7:0] : gprs[rd_8_bit_sel][15:8]};
+ else
+ rd_val[rd_port] <= bypass ? wr_val :
+ gprs[rd_sel[rd_port]];
+ end
+end
+endgenerate
+
+endmodule
diff --git a/common/CPU/x86/SegmentOverride.sv b/common/CPU/x86/SegmentOverride.sv
new file mode 100644
index 00000000..fb222a00
--- /dev/null
+++ b/common/CPU/x86/SegmentOverride.sv
@@ -0,0 +1,63 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+`default_nettype none
+module SegmentOverride(input logic clk,
+ input logic reset,
+ input logic next_instruction,
+ input logic flush,
+ input logic update,
+ input logic force_segment,
+ input logic bp_is_base,
+ input logic segment_override,
+ input logic [1:0] override_in,
+ input logic [1:0] microcode_sr_rd_sel,
+ output logic [1:0] sr_rd_sel);
+
+reg [1:0] override;
+reg override_active;
+
+always_comb begin
+ if (force_segment)
+ sr_rd_sel = microcode_sr_rd_sel;
+ else if (update && segment_override)
+ sr_rd_sel = override_in;
+ else if (override_active)
+ sr_rd_sel = override;
+ else if (bp_is_base)
+ sr_rd_sel = SS;
+ else
+ sr_rd_sel = microcode_sr_rd_sel;
+end
+
+always_ff @(posedge clk or posedge reset) begin
+ if (reset) begin
+ override_active <= 1'b0;
+ override <= 2'b00;
+ end else begin
+ if (next_instruction || flush) begin
+ override_active <= 1'b0;
+ override <= 2'b00;
+ end
+ if (update && segment_override) begin
+ override <= override_in;
+ override_active <= 1'b1;
+ end
+ end
+end
+
+endmodule
diff --git a/common/CPU/x86/SegmentRegisterFile.sv b/common/CPU/x86/SegmentRegisterFile.sv
new file mode 100644
index 00000000..95da8ad4
--- /dev/null
+++ b/common/CPU/x86/SegmentRegisterFile.sv
@@ -0,0 +1,48 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+`default_nettype none
+module SegmentRegisterFile(input logic clk,
+ input logic reset,
+ // Read port.
+ input logic [1:0] rd_sel,
+ output logic [15:0] rd_val,
+ // Write port.
+ input logic wr_en,
+ input logic [1:0] wr_sel,
+ input logic [15:0] wr_val,
+ // CS port.
+ output logic [15:0] cs);
+
+reg [15:0] registers[4];
+
+wire rd_bypass = wr_en && wr_sel == rd_sel;
+
+assign cs = registers[CS];
+
+always_ff @(posedge reset)
+ ; // Reset is handled by the microcode
+
+always_ff @(posedge clk) begin
+ if (wr_en)
+ registers[wr_sel] <= wr_val;
+end
+
+always_ff @(posedge clk)
+ rd_val <= rd_bypass ? wr_val : registers[rd_sel];
+
+endmodule
diff --git a/common/CPU/x86/TempReg.sv b/common/CPU/x86/TempReg.sv
new file mode 100644
index 00000000..3289a10d
--- /dev/null
+++ b/common/CPU/x86/TempReg.sv
@@ -0,0 +1,35 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+`default_nettype none
+module TempReg(input logic clk,
+ input logic reset,
+ input logic [15:0] wr_val,
+ input logic wr_en,
+ output logic [15:0] val);
+
+reg [15:0] r;
+
+assign val = r;
+
+always @(posedge clk or posedge reset)
+ if (reset)
+ r <= 16'b0;
+ else if (wr_en)
+ r <= wr_val;
+
+endmodule
diff --git a/common/CPU/x86/alu/ALU.sv b/common/CPU/x86/alu/ALU.sv
new file mode 100644
index 00000000..7d26e6fe
--- /dev/null
+++ b/common/CPU/x86/alu/ALU.sv
@@ -0,0 +1,96 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+`default_nettype none
+module ALU(input logic [15:0] a,
+ input logic [15:0] b,
+ output logic [31:0] out,
+ input logic is_8_bit,
+ input logic [`MC_ALUOp_t_BITS-1:0] op,
+ input logic [15:0] flags_in,
+ output logic [15:0] flags_out,
+ input logic multibit_shift,
+ input logic [4:0] shift_count,
+ output logic busy);
+
+always_comb begin
+ flags_out = flags_in;
+ out = 32'b0;
+ busy = 1'b0;
+
+ case (op)
+ ALUOp_SELA: out[15:0] = a;
+ ALUOp_SELB: out[15:0] = b;
+ ALUOp_ADD: do_add(out[15:0], is_8_bit, a, b, flags_in, flags_out);
+ ALUOp_ADC: do_adc(out[15:0], is_8_bit, a, b, flags_in, flags_out);
+ ALUOp_AND: do_and(out[15:0], is_8_bit, a, b, flags_in, flags_out);
+ ALUOp_XOR: do_xor(out[15:0], is_8_bit, a, b, flags_in, flags_out);
+ ALUOp_OR: do_or(out[15:0], is_8_bit, a, b, flags_in, flags_out);
+ ALUOp_BOUNDH: do_bound(a, b, flags_in, flags_out);
+ ALUOp_BOUNDL: do_bound(b, a, flags_in, flags_out);
+ ALUOp_SUB: do_sub(out[15:0], is_8_bit, a, b, flags_in, flags_out);
+ ALUOp_SUBREV: do_sub(out[15:0], is_8_bit, b, a, flags_in, flags_out);
+ ALUOp_SBB: do_sbb(out[15:0], is_8_bit, a, b, flags_in, flags_out);
+ ALUOp_SBBREV: do_sbb(out[15:0], is_8_bit, b, a, flags_in, flags_out);
+ ALUOp_ENTER_FRAME_TEMP_ADDR: do_enter_frame_temp_addr(out[15:0], a, b[4:0]);
+ ALUOp_GETFLAGS: out[15:0] = flags_in;
+ ALUOp_SETFLAGSA: flags_out = a;
+ ALUOp_SETFLAGSB: flags_out = b;
+ ALUOp_CMC: flags_out[CF_IDX] = ~flags_in[CF_IDX];
+ ALUOp_SHR: do_shr(out, is_8_bit, a, shift_count, flags_in, flags_out, busy,
+ multibit_shift);
+ ALUOp_SHL: do_shl(out, is_8_bit, a, shift_count, flags_in, flags_out, busy,
+ multibit_shift);
+ ALUOp_SAR: do_sar(out, is_8_bit, a, shift_count, flags_in, flags_out, busy,
+ multibit_shift);
+ ALUOp_ROR: do_ror(out, is_8_bit, a, shift_count, flags_in, flags_out, busy,
+ multibit_shift);
+ ALUOp_ROL: do_rol(out, is_8_bit, a, shift_count, flags_in, flags_out, busy,
+ multibit_shift);
+ ALUOp_RCL: do_rcl(out, is_8_bit, a, shift_count, flags_in, flags_out, busy,
+ multibit_shift);
+ ALUOp_RCR: do_rcr(out, is_8_bit, a, shift_count, flags_in, flags_out, busy,
+ multibit_shift);
+ ALUOp_NOT: do_not(out[15:0], a, flags_in, flags_out);
+ ALUOp_AAA: do_aaa(out[15:0], a, flags_in, flags_out);
+ ALUOp_AAS: do_aas(out[15:0], a, flags_in, flags_out);
+ ALUOp_DAA: do_daa(out[15:0], a, flags_in, flags_out);
+ ALUOp_DAS: do_das(out[15:0], a, flags_in, flags_out);
+ ALUOp_MUL: do_mul(out, is_8_bit, a, b, flags_in, flags_out, 1'b0);
+ ALUOp_IMUL: do_mul(out, is_8_bit, a, b, flags_in, flags_out, 1'b1);
+ ALUOp_EXTEND: do_extend(out[15:0], is_8_bit, a);
+ ALUOp_DIV: ; // Handled by Divider, shares the enumeration.
+ ALUOp_IDIV: ; // Handled by Divider, shares the enumeration.
+ ALUOp_NEXT: begin
+ if (flags_in[DF_IDX])
+ do_sub(out[15:0], 1'b0, a, b, flags_in, flags_out);
+ else
+ do_add(out[15:0], 1'b0, a, b, flags_in, flags_out);
+ end
+ // verilator coverage_off
+ default: begin
+`ifdef verilator
+ invalid_opcode_assertion: assert(0) begin
+ $display("oops!");
+ end
+`endif // verilator
+ end
+ // verilator coverage_on
+ endcase
+end
+
+endmodule
diff --git a/common/CPU/x86/alu/aaa.sv b/common/CPU/x86/alu/aaa.sv
new file mode 100644
index 00000000..373b374f
--- /dev/null
+++ b/common/CPU/x86/alu/aaa.sv
@@ -0,0 +1,38 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+task do_aaa;
+ output [15:0] out;
+ input [15:0] a;
+ input [15:0] flags_in;
+ output [15:0] flags_out;
+
+ begin
+ flags_out = flags_in;
+ out = a;
+ if (a[3:0] > 4'd9 || flags_in[AF_IDX]) begin
+ out[3:0] += 4'd6;
+ out[7:4] = 4'b0;
+ out[15:8] += 8'b1;
+ flags_out[CF_IDX] = 1'b1;
+ flags_out[AF_IDX] = 1'b1;
+ end else begin
+ flags_out[CF_IDX] = 1'b0;
+ flags_out[AF_IDX] = 1'b0;
+ end
+ end
+endtask
diff --git a/common/CPU/x86/alu/aas.sv b/common/CPU/x86/alu/aas.sv
new file mode 100644
index 00000000..f0ef77dd
--- /dev/null
+++ b/common/CPU/x86/alu/aas.sv
@@ -0,0 +1,38 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+task do_aas;
+ output [15:0] out;
+ input [15:0] a;
+ input [15:0] flags_in;
+ output [15:0] flags_out;
+
+ begin
+ flags_out = flags_in;
+ out = a;
+ if (a[3:0] > 4'd9 || flags_in[AF_IDX]) begin
+ out[3:0] -= 4'd6;
+ out[7:4] = 4'b0;
+ out[15:8] -= 8'b1;
+ flags_out[CF_IDX] = 1'b1;
+ flags_out[AF_IDX] = 1'b1;
+ end else begin
+ flags_out[CF_IDX] = 1'b0;
+ flags_out[AF_IDX] = 1'b0;
+ end
+ end
+endtask
diff --git a/common/CPU/x86/alu/adc.sv b/common/CPU/x86/alu/adc.sv
new file mode 100644
index 00000000..072f189d
--- /dev/null
+++ b/common/CPU/x86/alu/adc.sv
@@ -0,0 +1,38 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+task do_adc;
+ output [15:0] out;
+ input is_8_bit;
+ input [15:0] a;
+ input [15:0] b;
+ input [15:0] flags_in;
+ output [15:0] flags_out;
+
+ begin
+ flags_out = flags_in;
+ if (!is_8_bit) begin
+ {flags_out[CF_IDX], out} = a + b + {15'b0, flags_in[CF_IDX]};
+ flags_out[OF_IDX] = ~(a[15] ^ b[15]) & (out[15] ^ b[15]);
+ end else begin
+ out = a + b + {15'b0, flags_in[CF_IDX]};
+ flags_out[CF_IDX] = a[8] ^ b[8] ^ out[8];
+ flags_out[OF_IDX] = ~(a[7] ^ b[7]) & (out[7] ^ b[7]);
+ end
+ common_flags(flags_out, is_8_bit, out, a, b);
+ end
+endtask
diff --git a/common/CPU/x86/alu/add.sv b/common/CPU/x86/alu/add.sv
new file mode 100644
index 00000000..ddfca31d
--- /dev/null
+++ b/common/CPU/x86/alu/add.sv
@@ -0,0 +1,38 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+task do_add;
+ output [15:0] out;
+ input is_8_bit;
+ input [15:0] a;
+ input [15:0] b;
+ input [15:0] flags_in;
+ output [15:0] flags_out;
+
+ begin
+ flags_out = flags_in;
+ if (!is_8_bit) begin
+ {flags_out[CF_IDX], out} = a + b;
+ flags_out[OF_IDX] = ~(a[15] ^ b[15]) & (out[15] ^ b[15]);
+ end else begin
+ out = a + b;
+ flags_out[CF_IDX] = a[8] ^ b[8] ^ out[8];
+ flags_out[OF_IDX] = ~(a[7] ^ b[7]) & (out[7] ^ b[7]);
+ end
+ common_flags(flags_out, is_8_bit, out, a, b);
+ end
+endtask
diff --git a/common/CPU/x86/alu/and.sv b/common/CPU/x86/alu/and.sv
new file mode 100644
index 00000000..8aab83d7
--- /dev/null
+++ b/common/CPU/x86/alu/and.sv
@@ -0,0 +1,32 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+task do_and;
+ output [15:0] out;
+ input is_8_bit;
+ input [15:0] a;
+ input [15:0] b;
+ input [15:0] flags_in;
+ output [15:0] flags_out;
+
+ begin
+ flags_out = flags_in;
+ out = a & b;
+ {flags_out[CF_IDX], flags_out[OF_IDX]} = 2'b0;
+ common_flags(flags_out, is_8_bit, out, a, b);
+ end
+endtask
diff --git a/common/CPU/x86/alu/bound.sv b/common/CPU/x86/alu/bound.sv
new file mode 100644
index 00000000..0838c0c7
--- /dev/null
+++ b/common/CPU/x86/alu/bound.sv
@@ -0,0 +1,27 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+task do_bound;
+ input [15:0] a;
+ input [15:0] b;
+ input [15:0] flags_in;
+ output [15:0] flags_out;
+ begin
+ flags_out = flags_in;
+ flags_out[CF_IDX] = $signed(a) < $signed(b);
+ end
+endtask
diff --git a/common/CPU/x86/alu/daa.sv b/common/CPU/x86/alu/daa.sv
new file mode 100644
index 00000000..51f9a1a6
--- /dev/null
+++ b/common/CPU/x86/alu/daa.sv
@@ -0,0 +1,47 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+task do_daa;
+ output [15:0] out;
+ input [15:0] a;
+ input [15:0] flags_in;
+ output [15:0] flags_out;
+
+ begin
+ flags_out = flags_in;
+ out = a;
+ if (a[3:0] > 4'd9 || flags_in[AF_IDX]) begin
+ reg [15:0] tmp = {8'b0, a[7:0]} + 16'd6;
+
+ out[7:0] = tmp[7:0];
+ flags_out[AF_IDX] = 1'b1;
+ if (|tmp[15:8])
+ flags_out[CF_IDX] = 1'b1;
+ end else begin
+ flags_out[AF_IDX] = 1'b0;
+ end
+
+ if (out[7:0] > 8'h9f || flags_out[CF_IDX]) begin
+ out[7:0] += 8'h60;
+ flags_out[CF_IDX] = 1'b1;
+ end
+
+ // Only AL is updated, but AX is an input so it's a 16-bit input, and
+ // we should preserve AH so that it isn't modified.
+ out = {a[15:8], out[7:0]};
+ end
+endtask
diff --git a/common/CPU/x86/alu/das.sv b/common/CPU/x86/alu/das.sv
new file mode 100644
index 00000000..73a986b9
--- /dev/null
+++ b/common/CPU/x86/alu/das.sv
@@ -0,0 +1,49 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+task do_das;
+ output [15:0] out;
+ input [15:0] a;
+ input [15:0] flags_in;
+ output [15:0] flags_out;
+
+ begin
+ flags_out = flags_in;
+ out = a;
+ if (a[3:0] > 4'd9 || flags_in[AF_IDX]) begin
+ reg [15:0] tmp = {8'b0, a[7:0]} - 16'd6;
+
+ out[7:0] = tmp[7:0];
+ flags_out[AF_IDX] = 1'b1;
+ if (|tmp[15:8])
+ flags_out[CF_IDX] = 1'b1;
+ end else begin
+ flags_out[AF_IDX] = 1'b0;
+ end
+
+ if (out[7:0] > 8'h9f || flags_out[CF_IDX]) begin
+ out[7:0] -= 8'h60;
+ flags_out[CF_IDX] = 1'b1;
+ end else begin
+ flags_out[CF_IDX] = 1'b0;
+ end
+
+ flags_out[PF_IDX] = ~^out[7:0];
+ flags_out[SF_IDX] = out[7];
+ flags_out[ZF_IDX] = ~|out[7:0];
+ end
+endtask
diff --git a/common/CPU/x86/alu/enter.sv b/common/CPU/x86/alu/enter.sv
new file mode 100644
index 00000000..84b46ac6
--- /dev/null
+++ b/common/CPU/x86/alu/enter.sv
@@ -0,0 +1,26 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+task do_enter_frame_temp_addr;
+ output [15:0] out;
+ input [15:0] a;
+ input [4:0] b;
+
+ begin
+ out = a - ({10'b0, b, 1'b0});
+ end
+endtask
diff --git a/common/CPU/x86/alu/extend.sv b/common/CPU/x86/alu/extend.sv
new file mode 100644
index 00000000..93d29722
--- /dev/null
+++ b/common/CPU/x86/alu/extend.sv
@@ -0,0 +1,28 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+task do_extend;
+ output [15:0] out;
+ input is_8_bit;
+ // verilator lint_off UNUSED
+ input [15:0] a;
+ // verilator lint_on UNUSED
+
+ begin
+ out = is_8_bit ? {16{a[7]}} : {16{a[15]}};
+ end
+endtask
diff --git a/common/CPU/x86/alu/flags.sv b/common/CPU/x86/alu/flags.sv
new file mode 100644
index 00000000..0ab4fbc4
--- /dev/null
+++ b/common/CPU/x86/alu/flags.sv
@@ -0,0 +1,33 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+task common_flags;
+ inout [15:0] flags;
+ input is_8_bit;
+ // verilator lint_off UNUSED
+ input [15:0] out;
+ input [15:0] a;
+ input [15:0] b;
+ // verilator lint_on UNUSED
+
+ begin
+ flags[PF_IDX] = ~^out[7:0];
+ flags[AF_IDX] = a[4] ^ b[4] ^ out[4];
+ flags[SF_IDX] = out[is_8_bit ? 7 : 15];
+ flags[ZF_IDX] = is_8_bit ? ~|out[7:0] : ~|out;
+ end
+endtask
diff --git a/common/CPU/x86/alu/mul.sv b/common/CPU/x86/alu/mul.sv
new file mode 100644
index 00000000..00e79335
--- /dev/null
+++ b/common/CPU/x86/alu/mul.sv
@@ -0,0 +1,47 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+task do_mul;
+ output [31:0] out;
+ input is_8_bit;
+ input [15:0] a;
+ input [15:0] b;
+ input [15:0] flags_in;
+ output [15:0] flags_out;
+ input is_signed;
+
+ begin
+ flags_out = flags_in;
+ flags_out[ZF_IDX] = 1'b0;
+ out = 32'b0;
+ if (!is_8_bit) begin
+ if (is_signed)
+ out[31:0] = {{16{a[15]}}, a} * {{16{b[15]}}, b};
+ else
+ out[31:0] = {16'b0, a} * {16'b0, b};
+ flags_out[CF_IDX] = |out[31:16];
+ flags_out[OF_IDX] = |out[31:16];
+ end else begin
+ if (is_signed)
+ out = {16'b0, {{8{a[7]}}, a[7:0]} * {{8{b[7]}}, b[7:0]}};
+ else
+ out = {16'b0, {8'b0, a[7:0]} * {8'b0, b[7:0]}};
+ flags_out[CF_IDX] = |out[15:8];
+ flags_out[OF_IDX] = |out[15:8];
+ end
+ end
+endtask
diff --git a/common/CPU/x86/alu/not.sv b/common/CPU/x86/alu/not.sv
new file mode 100644
index 00000000..e3c7a28c
--- /dev/null
+++ b/common/CPU/x86/alu/not.sv
@@ -0,0 +1,28 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+task do_not;
+ output [15:0] out;
+ input [15:0] a;
+ input [15:0] flags_in;
+ output [15:0] flags_out;
+
+ begin
+ flags_out = flags_in;
+ out = ~a;
+ end
+endtask
diff --git a/common/CPU/x86/alu/or.sv b/common/CPU/x86/alu/or.sv
new file mode 100644
index 00000000..b463ff55
--- /dev/null
+++ b/common/CPU/x86/alu/or.sv
@@ -0,0 +1,32 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+task do_or;
+ output [15:0] out;
+ input is_8_bit;
+ input [15:0] a;
+ input [15:0] b;
+ input [15:0] flags_in;
+ output [15:0] flags_out;
+
+ begin
+ flags_out = flags_in;
+ out = a | b;
+ {flags_out[CF_IDX], flags_out[OF_IDX]} = 2'b0;
+ common_flags(flags_out, is_8_bit, out, a, b);
+ end
+endtask
diff --git a/common/CPU/x86/alu/rcl.sv b/common/CPU/x86/alu/rcl.sv
new file mode 100644
index 00000000..d0ef182c
--- /dev/null
+++ b/common/CPU/x86/alu/rcl.sv
@@ -0,0 +1,45 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+task do_rcl;
+ output [31:0] out;
+ input is_8_bit;
+ input [15:0] a;
+ input [4:0] shift_count;
+ input [15:0] flags_in;
+ output [15:0] flags_out;
+ output busy;
+ input multibit_shift;
+
+ begin
+ flags_out = flags_in;
+ out = {11'b0, shift_count, a};
+
+ if (|shift_count || !multibit_shift) begin
+ if (!is_8_bit)
+ {flags_out[CF_IDX], out[15:0]} = {a[15:0], flags_out[CF_IDX]};
+ else
+ {flags_out[CF_IDX], out[7:0]} = {a[7:0], flags_out[CF_IDX]};
+ flags_out[OF_IDX] = is_8_bit ? a[7] ^ a[6] : a[15] ^ a[14];
+ shift_flags(flags_out, is_8_bit, out[15:0], a);
+
+ out[31:16] = {11'b0, shift_count - 1'b1};
+ end
+
+ busy = multibit_shift && |out[20:16];
+ end
+endtask
diff --git a/common/CPU/x86/alu/rcr.sv b/common/CPU/x86/alu/rcr.sv
new file mode 100644
index 00000000..d967349a
--- /dev/null
+++ b/common/CPU/x86/alu/rcr.sv
@@ -0,0 +1,46 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+task do_rcr;
+ output [31:0] out;
+ input is_8_bit;
+ input [15:0] a;
+ input [4:0] shift_count;
+ input [15:0] flags_in;
+ output [15:0] flags_out;
+ output busy;
+ input multibit_shift;
+
+ begin
+ flags_out = flags_in;
+ out = {11'b0, shift_count, a};
+
+ if (|shift_count || !multibit_shift) begin
+ if (!is_8_bit)
+ {out[15:0], flags_out[CF_IDX]} = {flags_out[CF_IDX], a[15:0]};
+ else
+ {out[7:0], flags_out[CF_IDX]} = {flags_out[CF_IDX], a[7:0]};
+ flags_out[OF_IDX] = is_8_bit ? a[7] ^ flags_in[CF_IDX] :
+ a[15] ^ flags_in[CF_IDX];
+ shift_flags(flags_out, is_8_bit, out[15:0], a);
+
+ out[31:16] = {11'b0, shift_count - 1'b1};
+ end
+
+ busy = multibit_shift && |out[20:16];
+ end
+endtask
diff --git a/common/CPU/x86/alu/rol.sv b/common/CPU/x86/alu/rol.sv
new file mode 100644
index 00000000..6bc2d6e8
--- /dev/null
+++ b/common/CPU/x86/alu/rol.sv
@@ -0,0 +1,49 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+task do_rol;
+ output [31:0] out;
+ input is_8_bit;
+ input [15:0] a;
+ input [4:0] shift_count;
+ input [15:0] flags_in;
+ output [15:0] flags_out;
+ output busy;
+ input multibit_shift;
+
+ begin
+ flags_out = flags_in;
+ out = {11'b0, shift_count, a};
+
+ if (|shift_count || !multibit_shift) begin
+ if (!is_8_bit) begin
+ flags_out[CF_IDX] = a[15];
+ out[15:0] = {a[14:0], a[15]};
+ end else begin
+ flags_out[CF_IDX] = a[7];
+ out[7:0] = {a[6:0], a[7]};
+ end
+
+ flags_out[OF_IDX] = is_8_bit ? a[7] ^ a[6] : a[15] ^ a[14];
+ shift_flags(flags_out, is_8_bit, out[15:0], a);
+
+ out[31:16] = {11'b0, shift_count - 1'b1};
+ end
+
+ busy = multibit_shift && |out[20:16];
+ end
+endtask
diff --git a/common/CPU/x86/alu/ror.sv b/common/CPU/x86/alu/ror.sv
new file mode 100644
index 00000000..0acd362f
--- /dev/null
+++ b/common/CPU/x86/alu/ror.sv
@@ -0,0 +1,49 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+task do_ror;
+ output [31:0] out;
+ input is_8_bit;
+ input [15:0] a;
+ input [4:0] shift_count;
+ input [15:0] flags_in;
+ output [15:0] flags_out;
+ output busy;
+ input multibit_shift;
+
+ begin
+ flags_out = flags_in;
+ out = {11'b0, shift_count, a};
+
+ if (|shift_count || !multibit_shift) begin
+ if (!is_8_bit) begin
+ flags_out[CF_IDX] = a[0];
+ out[15:0] = {a[0], out[15:1]};
+ end else begin
+ flags_out[CF_IDX] = a[0];
+ out[7:0] = {a[0], out[7:1]};
+ end
+
+ flags_out[OF_IDX] = is_8_bit ? a[7] ^ a[0] : a[15] ^ a[0];
+ shift_flags(flags_out, is_8_bit, out[15:0], a);
+
+ out[31:16] = {11'b0, shift_count - 1'b1};
+ end
+
+ busy = multibit_shift && |out[20:16];
+ end
+endtask
diff --git a/common/CPU/x86/alu/sar.sv b/common/CPU/x86/alu/sar.sv
new file mode 100644
index 00000000..98f99eb7
--- /dev/null
+++ b/common/CPU/x86/alu/sar.sv
@@ -0,0 +1,45 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+task do_sar;
+ output [31:0] out;
+ input is_8_bit;
+ input [15:0] a;
+ input [4:0] shift_count;
+ input [15:0] flags_in;
+ output [15:0] flags_out;
+ output busy;
+ input multibit_shift;
+
+ begin
+ flags_out = flags_in;
+ out = {11'b0, shift_count, a};
+
+ if (|shift_count || !multibit_shift) begin
+ if (!is_8_bit)
+ {out[15:0], flags_out[CF_IDX]} = $signed({a, 1'b0}) >>> 1'b1;
+ else
+ {out[7:0], flags_out[CF_IDX]} = $signed({a[7:0], 1'b0}) >>> 1'b1;
+ flags_out[OF_IDX] = 0;
+ shift_flags(flags_out, is_8_bit, out[15:0], a);
+
+ out[31:16] = {11'b0, shift_count - 1'b1};
+ end
+
+ busy = multibit_shift && |out[20:16];
+ end
+endtask
diff --git a/common/CPU/x86/alu/shift_flags.sv b/common/CPU/x86/alu/shift_flags.sv
new file mode 100644
index 00000000..0cc7f6de
--- /dev/null
+++ b/common/CPU/x86/alu/shift_flags.sv
@@ -0,0 +1,31 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+task shift_flags;
+ inout [15:0] flags;
+ input is_8_bit;
+ // verilator lint_off UNUSED
+ input [15:0] out;
+ input [15:0] a;
+ // verilator lint_on UNUSED
+
+ begin
+ flags[PF_IDX] = ~^out[7:0];
+ flags[SF_IDX] = out[is_8_bit ? 7 : 15];
+ flags[ZF_IDX] = is_8_bit ? ~|out[7:0] : ~|out;
+ end
+endtask
diff --git a/common/CPU/x86/alu/shl.sv b/common/CPU/x86/alu/shl.sv
new file mode 100644
index 00000000..eebcb06b
--- /dev/null
+++ b/common/CPU/x86/alu/shl.sv
@@ -0,0 +1,46 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+task do_shl;
+ output [31:0] out;
+ input is_8_bit;
+ input [15:0] a;
+ input [4:0] shift_count;
+ input [15:0] flags_in;
+ output [15:0] flags_out;
+ output busy;
+ input multibit_shift;
+
+ begin
+ flags_out = flags_in;
+ out = {11'b0, shift_count, a};
+
+ if (|shift_count || !multibit_shift) begin
+ if (!is_8_bit) begin
+ {flags_out[CF_IDX], out[15:0]} = {1'b0, a} << 1'b1;
+ flags_out[OF_IDX] = a[15] ^ out[15];
+ end else begin
+ {flags_out[CF_IDX], out[7:0]} = {1'b0, a[7:0]} << 1'b1;
+ flags_out[OF_IDX] = a[7] ^ out[7];
+ end
+ shift_flags(flags_out, is_8_bit, out[15:0], a);
+ out[31:16] = {11'b0, shift_count - 1'b1};
+ end
+
+ busy = multibit_shift && |out[20:16];
+ end
+endtask
diff --git a/common/CPU/x86/alu/shr.sv b/common/CPU/x86/alu/shr.sv
new file mode 100644
index 00000000..c44caf59
--- /dev/null
+++ b/common/CPU/x86/alu/shr.sv
@@ -0,0 +1,45 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+task do_shr;
+ output [31:0] out;
+ input is_8_bit;
+ input [15:0] a;
+ input [4:0] shift_count;
+ input [15:0] flags_in;
+ output [15:0] flags_out;
+ output busy;
+ input multibit_shift;
+
+ begin
+ flags_out = flags_in;
+ out = {11'b0, shift_count, a};
+
+ if (|shift_count || !multibit_shift) begin
+ {out[15:0], flags_out[CF_IDX]} = {a, 1'b0} >> 1'b1;
+ shift_flags(flags_out, is_8_bit, out[15:0], a);
+ if (is_8_bit)
+ flags_out[OF_IDX] = a[7] ^ out[7];
+ else
+ flags_out[OF_IDX] = a[15] ^ out[15];
+
+ out[31:16] = {11'b0, shift_count - 1'b1};
+ end
+
+ busy = multibit_shift && |out[20:16];
+ end
+endtask
diff --git a/common/CPU/x86/alu/sub.sv b/common/CPU/x86/alu/sub.sv
new file mode 100644
index 00000000..5dc77cc6
--- /dev/null
+++ b/common/CPU/x86/alu/sub.sv
@@ -0,0 +1,58 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+task do_sub;
+ output [15:0] out;
+ input is_8_bit;
+ input [15:0] a;
+ input [15:0] b;
+ input [15:0] flags_in;
+ output [15:0] flags_out;
+ begin
+ flags_out = flags_in;
+ if (!is_8_bit) begin
+ {flags_out[CF_IDX], out} = a - b;
+ flags_out[OF_IDX] = (a[15] ^ b[15]) & (out[15] ^ a[15]);
+ end else begin
+ out = a - b;
+ flags_out[CF_IDX] = a[8] ^ b[8] ^ out[8];
+ flags_out[OF_IDX] = (a[7] ^ b[7]) & (out[7] ^ a[7]);
+ end
+ common_flags(flags_out, is_8_bit, out, a, b);
+ end
+endtask
+
+task do_sbb;
+ output [15:0] out;
+ input is_8_bit;
+ input [15:0] a;
+ input [15:0] b;
+ input [15:0] flags_in;
+ output [15:0] flags_out;
+ begin
+ flags_out = flags_in;
+ if (!is_8_bit) begin
+ {flags_out[CF_IDX], out} = a - b - {15'b0, flags_in[CF_IDX]};
+ flags_out[OF_IDX] = (a[15] ^ b[15]) & (out[15] ^ a[15]);
+ end else begin
+ out = a - b - {15'b0, flags_in[CF_IDX]};
+ flags_out[CF_IDX] = a[8] ^ b[8] ^ out[8];
+ flags_out[OF_IDX] = (a[7] ^ b[7]) & (out[7] ^ a[7]);
+ end
+ common_flags(flags_out, is_8_bit, out, a, b);
+ end
+endtask
diff --git a/common/CPU/x86/alu/xor.sv b/common/CPU/x86/alu/xor.sv
new file mode 100644
index 00000000..a299fecc
--- /dev/null
+++ b/common/CPU/x86/alu/xor.sv
@@ -0,0 +1,32 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+task do_xor;
+ output [15:0] out;
+ input is_8_bit;
+ input [15:0] a;
+ input [15:0] b;
+ input [15:0] flags_in;
+ output [15:0] flags_out;
+
+ begin
+ flags_out = flags_in;
+ out = a ^ b;
+ {flags_out[CF_IDX], flags_out[OF_IDX]} = 2'b0;
+ common_flags(flags_out, is_8_bit, out, a, b);
+ end
+endtask
diff --git a/common/CPU/x86/cdc/BitSync.sv b/common/CPU/x86/cdc/BitSync.sv
new file mode 100644
index 00000000..05643fd2
--- /dev/null
+++ b/common/CPU/x86/cdc/BitSync.sv
@@ -0,0 +1,52 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+`default_nettype none
+module BitSync(input logic clk,
+ input logic reset,
+ input logic d,
+ output logic q);
+
+`ifdef verilator
+
+reg p1;
+reg p2;
+
+assign q = p2;
+
+always_ff @(posedge clk or posedge reset)
+ if (reset)
+ p1 <= 1'b0;
+ else
+ p1 <= d;
+
+always_ff @(posedge clk or posedge reset)
+ if (reset)
+ p2 <= 1'b0;
+ else
+ p2 <= p1;
+
+`else
+
+altera_std_synchronizer sync(.clk(clk),
+ .reset_n(~reset),
+ .din(d),
+ .dout(q));
+
+`endif
+
+endmodule
diff --git a/common/CPU/x86/cdc/MCP.sv b/common/CPU/x86/cdc/MCP.sv
new file mode 100644
index 00000000..a4c14dc1
--- /dev/null
+++ b/common/CPU/x86/cdc/MCP.sv
@@ -0,0 +1,75 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+// Multi-cycle-path formulation with feedback as described in "Clock Domain
+// Crossing (CDC) Design & Verification Techniques Using SystemVerilog" by
+// Clifford E. Cummings.
+`default_nettype none
+module MCP #(parameter width = 8,
+ parameter reset_val = 8'b0)
+ (input logic reset,
+ input logic clk_a,
+ output logic a_ready,
+ input logic a_send,
+ input logic [width-1:0] a_datain,
+ input logic clk_b,
+ output logic [width-1:0] b_data,
+ output logic b_load);
+
+logic [width-1:0] tx_sample;
+assign a_ready = a_ack | ~tx_busy;
+reg a_en;
+wire a_ack;
+reg tx_busy;
+wire a_load = a_send & a_ready;
+wire b_ack;
+assign b_data = tx_sample;
+
+SyncPulse BLoadPulse(.clk(clk_b),
+ .d(a_en),
+ .p(b_load),
+ .q(b_ack));
+
+SyncPulse AAckPulse(.clk(clk_a),
+ .d(b_ack),
+ .p(a_ack),
+ // verilator lint_off PINCONNECTEMPTY
+ .q()
+ // verilator lint_on PINCONNECTEMPTY
+ );
+
+always_ff @(posedge clk_a)
+ a_en <= a_en ^ a_load;
+
+always_ff @(posedge clk_a or posedge reset) begin
+ if (reset)
+ tx_busy <= 1'b0;
+ else begin
+ if (a_ack)
+ tx_busy <= 1'b0;
+ if (a_send)
+ tx_busy <= 1'b1;
+ end
+end
+
+always_ff @(posedge clk_a or posedge reset)
+ if (reset)
+ tx_sample <= reset_val;
+ else if (a_load)
+ tx_sample <= a_datain;
+
+endmodule
diff --git a/common/CPU/x86/cdc/SyncPulse.sv b/common/CPU/x86/cdc/SyncPulse.sv
new file mode 100644
index 00000000..e40840bb
--- /dev/null
+++ b/common/CPU/x86/cdc/SyncPulse.sv
@@ -0,0 +1,41 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+`default_nettype none
+module SyncPulse(input logic clk,
+ input logic reset,
+ input logic d,
+ output logic p,
+ output logic q);
+
+wire synced;
+reg last_val;
+
+assign p = synced ^ last_val;
+assign q = last_val;
+
+always_ff @(posedge clk or posedge reset)
+ if (reset)
+ last_val <= 1'b0;
+ else
+ last_val <= synced;
+
+BitSync BitSync(.clk(clk),
+ .reset(reset),
+ .d(d),
+ .q(synced));
+endmodule
diff --git a/common/CPU/x86/microcode/CMakeLists.txt b/common/CPU/x86/microcode/CMakeLists.txt
new file mode 100644
index 00000000..d7aabfac
--- /dev/null
+++ b/common/CPU/x86/microcode/CMakeLists.txt
@@ -0,0 +1,116 @@
+# Copyright Jamie Iles, 2017
+#
+# This file is part of s80x86.
+#
+# s80x86 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.
+#
+# s80x86 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 s80x86. If not, see .
+
+set(microprogram_sources
+ ${CMAKE_CURRENT_SOURCE_DIR}/aaa.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/aad.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/aas.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/adc.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/add.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/and.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/bound.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/daa.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/das.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/arithmetic.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/call.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/comparison.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/cmp.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/cmps.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/div.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/enter.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/esc.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/extend.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/flags.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/hlt.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/inc.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/int.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/io.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/jmp.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/lds.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/lea.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/leave.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/les.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/lods.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/loop.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/mov.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/movs.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/mul.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/neg.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/not.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/or.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/pop.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/push.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/rcl.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/rcr.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/ret.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/rol.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/ror.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/sar.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/sbb.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/scas.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/shift.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/shl.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/shr.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/stos.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/sub.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/test.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/xchg.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/xlat.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/xor.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/wait.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/microcode.us
+ ${CMAKE_CURRENT_SOURCE_DIR}/debug.us)
+
+add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/microcode.bin
+ ${CMAKE_CURRENT_BINARY_DIR}/microcode.mif
+ ${CMAKE_CURRENT_BINARY_DIR}/Microcode.sv
+ ${CMAKE_CURRENT_BINARY_DIR}/MicrocodeTypes.sv
+ ${CMAKE_CURRENT_BINARY_DIR}/MicrocodeTypes.h
+ COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/../../scripts/microassembler/uasm -I${CMAKE_CURRENT_BINARY_DIR}/../..
+ ${CMAKE_CURRENT_BINARY_DIR}/microcode.bin
+ ${CMAKE_CURRENT_BINARY_DIR}/microcode.mif
+ ${CMAKE_CURRENT_BINARY_DIR}/Microcode.sv
+ ${CMAKE_CURRENT_BINARY_DIR}/MicrocodeTypes.sv
+ ${CMAKE_CURRENT_BINARY_DIR}/MicrocodeTypes.h
+ ${microprogram_sources}
+ DEPENDS ${microprogram_sources}
+ ${CMAKE_CURRENT_SOURCE_DIR}/Microcode.sv.templ
+ ${CMAKE_CURRENT_SOURCE_DIR}/microcode.mif.templ
+ ${CMAKE_CURRENT_SOURCE_DIR}/MicrocodeTypes.sv.templ
+ ${CMAKE_CURRENT_SOURCE_DIR}/MicrocodeTypes.h.templ
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../scripts/microassembler/uasm
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../scripts/microassembler/microasm/types.py)
+
+set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/Microcode.sv PROPERTIES
+ COMPILE_FLAGS "-DMICROCODE_ROM_PATH=\\\"${CMAKE_CURRENT_BINARY_DIR}\\\"")
+
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+
+add_custom_target(generate_microcode
+ DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/microcode.bin
+ ${CMAKE_CURRENT_BINARY_DIR}/microcode.mif
+ ${CMAKE_CURRENT_BINARY_DIR}/Microcode.sv
+ ${CMAKE_CURRENT_BINARY_DIR}/MicrocodeTypes.sv
+ ${CMAKE_CURRENT_BINARY_DIR}/MicrocodeTypes.h)
+
+verilate(TOPLEVEL Microcode
+ VERILOG_SOURCES
+ ${CMAKE_CURRENT_BINARY_DIR}/MicrocodeTypes.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/../RegisterEnum.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/../Instruction.sv
+ ${CMAKE_CURRENT_SOURCE_DIR}/../InsnDecoder.sv
+ ${CMAKE_CURRENT_BINARY_DIR}/Microcode.sv)
diff --git a/common/CPU/x86/microcode/Microcode.sv.templ b/common/CPU/x86/microcode/Microcode.sv.templ
new file mode 100644
index 00000000..d817e45f
--- /dev/null
+++ b/common/CPU/x86/microcode/Microcode.sv.templ
@@ -0,0 +1,305 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+// vi: ft=systemverilog
+`ifndef MICROCODE_ROM_PATH
+`define MICROCODE_ROM_PATH "."
+`endif
+
+`default_nettype none
+module Microcode(input logic clk,
+ input logic reset,
+ input logic nmi_pulse,
+ input logic intr,
+ output logic inta,
+ output logic irq_to_mdr,
+ output logic start_interrupt,
+ output logic do_escape_fault,
+ output logic starting_instruction,
+ input logic stall,
+ input logic divide_error,
+ input logic rm_is_reg,
+ input logic [2:0] modrm_reg,
+ input logic int_enabled,
+ input logic zf,
+ input logic tf,
+ output logic [15:0] microcode_immediate,
+ output logic [8:0] update_flags,
+ output logic modrm_start,
+ output logic use_microcode_immediate,
+ output logic [7:0] opcode,
+ input logic jump_taken,
+ input logic rb_zero,
+ output logic lock,
+ output logic multibit_shift,
+ output logic is_hlt,
+ output logic next_microinstruction,
+ // Microinstruction fields.
+ <%#exported_fields%>
+ output logic <%type%><%name%>,
+ <%/exported_fields%>
+ output logic width,
+ output logic reg_wr_en,
+ // Fifo Read Port.
+ output logic fifo_rd_en,
+ // verilator lint_off UNUSED
+ input Instruction next_instruction_value,
+ output Instruction cur_instruction,
+ // verilator lint_on UNUSED
+ input logic fifo_empty,
+ input logic fifo_resetting,
+ output logic loop_next,
+ input logic loop_done,
+ // Debug
+ output logic debug_stopped,
+ input logic debug_seize,
+ input logic [7:0] debug_addr,
+ input logic debug_run);
+
+localparam num_instructions = <%num_instructions%>;
+localparam addr_bits = <%addr_bits%>;
+localparam reset_address = <%addr_bits%>'h129;
+localparam nmi_address = <%addr_bits%>'h12a;
+localparam irq_address = <%addr_bits%>'h12b;
+localparam single_step_address = <%addr_bits%>'h12c;
+localparam divide_error_address = <%addr_bits%>'h101;
+localparam next_instruction_address = <%addr_bits%>'h100;
+localparam modrm_wait_address = <%addr_bits%>'h12e;
+localparam bad_opcode_address = <%addr_bits%>'h12f;
+localparam debug_wait_address = <%addr_bits%>'h102;
+localparam do_int_address = <%addr_bits%>'h12d;
+
+typedef struct packed {
+<%#fields%>
+ logic <%type%><%name%>;
+<%/fields%>
+} microcode_instruction;
+
+microcode_instruction mem[num_instructions] /* synthesis ram_init_file = "microcode.mif" */;
+// verilator lint_off UNUSED
+microcode_instruction current;
+// verilator lint_on UNUSED
+reg [addr_bits-1:0] addr;
+reg [addr_bits-1:0] next_addr;
+reg [addr_bits-1:0] jump_target;
+assign use_microcode_immediate = |current.immediate;
+assign opcode = cur_instruction.opcode;
+
+always_comb begin
+ case (current.immediate)
+<%#immediates%>
+ <%idx%>: microcode_immediate = 16'h<%val%>;
+<%/immediates%>
+ default: microcode_immediate = 16'h0;
+ endcase
+end
+
+always_comb begin
+ case (current.update_flags)
+<%#flags%>
+ <%idx%>: update_flags = 9'h<%val%>;
+<%/flags%>
+ default: update_flags = 9'h0;
+ endcase
+end
+
+<%#exported_fields%>
+assign <%name%> = current.<%name%>;
+<%/exported_fields%>
+
+assign fifo_rd_en = starting_instruction;
+assign starting_instruction = !stall && (next_addr == {{addr_bits-8{1'b0}}, next_instruction_value.opcode});
+assign modrm_start = addr == modrm_wait_address ||
+ (addr == next_instruction_address && !fifo_empty && next_instruction_value.has_modrm);
+wire has_rep_prefix = cur_instruction.rep != REP_PREFIX_NONE;
+reg rep_complete;
+assign debug_stopped = addr == debug_wait_address;
+assign multibit_shift = cur_instruction.opcode == 8'hd2 ||
+ cur_instruction.opcode == 8'hd3 ||
+ cur_instruction.opcode == 8'hc0 ||
+ cur_instruction.opcode == 8'hc1;
+assign do_escape_fault = cur_instruction.opcode[7:3] == 5'b11011 && next_addr == do_int_address;
+reg nmi_pending;
+reg ext_int_inhibit;
+wire take_nmi = (nmi_pending | nmi_pulse) & !ext_int_inhibit & !current.ext_int_inhibit;
+wire take_irq = intr & int_enabled & !ext_int_inhibit & !current.ext_int_inhibit;
+wire do_single_step = current.next_instruction & !ext_int_inhibit &
+ trap_flag_set & current.next != debug_wait_address & !current.ext_int_inhibit;
+assign start_interrupt = next_addr == nmi_address ||
+ next_addr == irq_address;
+assign irq_to_mdr = next_addr == irq_address;
+reg trap_flag_set;
+assign is_hlt = cur_instruction.opcode == 8'hf4;
+reg seized;
+wire seizing = debug_seize & ~seized;
+assign loop_next = !stall && current.jump_type == JumpType_LOOP_DONE;
+assign reg_wr_en = current.rd_sel_source != RDSelSource_NONE & ~segment_wr_en;
+assign next_microinstruction = addr != next_addr;
+assign lock = cur_instruction.lock;
+
+always_comb begin
+ case (current.width)
+ WidthType_W8: width = 1'b1;
+ WidthType_W16: width = 1'b0;
+ WidthType_WAUTO: width = ~cur_instruction.opcode[0];
+ default: width = 1'b0;
+ endcase
+end
+
+always_ff @(posedge clk)
+ inta <= next_addr == irq_address && addr != irq_address;
+
+always_ff @(posedge clk or posedge reset)
+ if (reset)
+ trap_flag_set <= 1'b0;
+ else if (next_addr == single_step_address)
+ trap_flag_set <= 1'b0;
+ else if (starting_instruction)
+ trap_flag_set <= tf;
+
+always_ff @(posedge clk or posedge reset)
+ if (reset)
+ ext_int_inhibit <= 1'b0;
+ else if (current.ext_int_inhibit && current.next != debug_wait_address)
+ ext_int_inhibit <= 1'b1;
+ else if (starting_instruction && !stall)
+ ext_int_inhibit <= 1'b0;
+
+`ifdef verilator
+initial $readmemb({{`MICROCODE_ROM_PATH, "/microcode.bin"}}, mem);
+`endif
+
+always_comb begin
+ case (cur_instruction.rep)
+ REP_PREFIX_E: rep_complete = ~zf;
+ REP_PREFIX_NE: rep_complete = zf;
+ default: rep_complete = 1'b0;
+ endcase
+end
+
+always_ff @(posedge clk or posedge reset)
+ if (reset)
+ nmi_pending <= 1'b0;
+ else if (next_addr == nmi_address)
+ nmi_pending <= 1'b0;
+ else if (nmi_pulse)
+ nmi_pending <= 1'b1;
+
+always_ff @(posedge clk or posedge reset)
+ if (reset)
+ seized <= 1'b0;
+ else if (debug_stopped)
+ seized <= 1'b1;
+ else if (!debug_seize)
+ seized <= 1'b0;
+
+always_comb begin
+ unique case (current.jump_type)
+ JumpType_RM_REG_MEM: jump_target = current.next + {{addr_bits-1{1'b0}}, ~rm_is_reg};
+ JumpType_OPCODE: jump_target = !fifo_empty ? {{addr_bits-8{1'b0}}, next_instruction_value.opcode} : addr;
+ JumpType_DISPATCH_REG: jump_target = current.next + {{addr_bits-3{1'b0}}, modrm_reg};
+ JumpType_HAS_NO_REP_PREFIX: jump_target = ~has_rep_prefix ? current.next : addr + 1'b1;
+ JumpType_ZERO: jump_target = zf ? current.next : addr + 1'b1;
+ JumpType_REP_NOT_COMPLETE: jump_target = !rep_complete ? current.next : addr + 1'b1;
+ JumpType_RB_ZERO: jump_target = rb_zero ? current.next : addr + 1'b1;
+ JumpType_LOOP_DONE: jump_target = loop_done ? current.next : addr + 1'b1;
+ JumpType_JUMP_TAKEN: jump_target = jump_taken ? current.next : addr + 1'b1;
+ default: jump_target = current.next;
+ endcase
+end
+
+always_comb begin
+ if (reset)
+ next_addr = reset_address;
+ else if (debug_stopped && debug_run)
+ next_addr = {{addr_bits - 9{1'b0}}, 1'b1, debug_addr};
+ else if (stall)
+ next_addr = addr;
+ else if (current.ext_int_yield && seizing)
+ next_addr = debug_wait_address;
+ else if (current.ext_int_yield && take_nmi)
+ next_addr = nmi_address;
+ else if (current.ext_int_yield && take_irq)
+ next_addr = irq_address;
+ else if (addr == next_instruction_address && !fifo_empty && !fifo_resetting &&
+ next_instruction_value.invalid)
+ next_addr = bad_opcode_address;
+ else if (current.jump_type != JumpType_UNCONDITIONAL)
+ next_addr = jump_target;
+ else if (divide_error)
+ next_addr = divide_error_address;
+ else if (current.next_instruction && take_nmi)
+ next_addr = nmi_address;
+ else if (current.next_instruction && take_irq)
+ next_addr = irq_address;
+ else if ((current.next_instruction && do_single_step) ||
+ (is_hlt && trap_flag_set))
+ next_addr = single_step_address;
+ else if (current.next_instruction && debug_seize)
+ next_addr = debug_wait_address;
+ else if (current.next_instruction || (is_hlt && intr))
+ next_addr = !fifo_empty && !fifo_resetting ?
+ (next_instruction_value.has_modrm ? modrm_wait_address :
+ {{addr_bits-8{1'b0}}, next_instruction_value.opcode}) :
+ next_instruction_address;
+ else
+ next_addr = current.next;
+end
+
+always @(posedge clk)
+ addr <= next_addr;
+
+always @(posedge clk)
+ current <= mem[next_addr];
+
+always_ff @(posedge clk)
+ if (fifo_rd_en)
+ cur_instruction <= next_instruction_value;
+
+`ifdef verilator
+export "DPI-C" function get_microcode_address;
+
+function bit [addr_bits-1:0] get_microcode_address;
+ get_microcode_address = addr;
+endfunction
+
+export "DPI-C" function get_ext_int_yield;
+
+function bit get_ext_int_yield;
+ get_ext_int_yield = current.ext_int_yield;
+endfunction
+
+int microcode_coverage[num_instructions];
+
+always_ff @(posedge clk)
+ microcode_coverage[addr] <= microcode_coverage[addr] + 1;
+
+export "DPI-C" function get_microcode_num_instructions;
+
+function int get_microcode_num_instructions;
+ get_microcode_num_instructions = num_instructions;
+endfunction
+
+export "DPI-C" function get_microcode_coverage_bin;
+
+function int get_microcode_coverage_bin;
+ input int bin;
+ get_microcode_coverage_bin = microcode_coverage[bin];
+endfunction
+`endif
+
+endmodule
diff --git a/common/CPU/x86/microcode/MicrocodeTypes.h.templ b/common/CPU/x86/microcode/MicrocodeTypes.h.templ
new file mode 100644
index 00000000..7f00927c
--- /dev/null
+++ b/common/CPU/x86/microcode/MicrocodeTypes.h.templ
@@ -0,0 +1,27 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+#pragma once
+
+<%#enums%>
+enum <%name%> {
+<%#items%>
+ <%name%> = <%value%>
+<%/items%>
+};
+
+<%/enums%>
diff --git a/common/CPU/x86/microcode/MicrocodeTypes.sv.templ b/common/CPU/x86/microcode/MicrocodeTypes.sv.templ
new file mode 100644
index 00000000..940be2fc
--- /dev/null
+++ b/common/CPU/x86/microcode/MicrocodeTypes.sv.templ
@@ -0,0 +1,30 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+`ifndef MICROCODE_TYPES
+`define MICROCODE_TYPES
+
+<%#enums%>
+typedef enum bit [<%high_bit%>:0] {
+<%#items%>
+ <%name%> = <%num_bits%>'d<%value%>
+<%/items%>
+} <%name%>;
+`define <%name%>_BITS <%num_bits%>
+
+<%/enums%>
+`endif // MICROCODE_TYPES
diff --git a/common/CPU/x86/microcode/aaa.us b/common/CPU/x86/microcode/aaa.us
new file mode 100644
index 00000000..382cb2c9
--- /dev/null
+++ b/common/CPU/x86/microcode/aaa.us
@@ -0,0 +1,24 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+// AAA
+.at 0x37;
+ ra_sel AX, jmp aaa;
+.auto_address;
+aaa:
+ a_sel RA, alu_op AAA, rd_sel_source MICROCODE_RD_SEL, rd_sel AX,
+ update_flags AF CF, next_instruction;
diff --git a/common/CPU/x86/microcode/aad.us b/common/CPU/x86/microcode/aad.us
new file mode 100644
index 00000000..2b3d1aea
--- /dev/null
+++ b/common/CPU/x86/microcode/aad.us
@@ -0,0 +1,29 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+// AAD
+.at 0xd5;
+ width W8, ra_sel AH, jmp aad;
+.auto_address;
+aad:
+ a_sel RA, b_sel IMMEDIATE, alu_op IMUL, tmp_wr_en;
+ width W8, ra_sel AL;
+ a_sel RA, b_sel TEMP, alu_op ADD, update_flags SF ZF PF,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel AX;
+ width W8, b_sel IMMEDIATE, immediate 0x0, alu_op SELB,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel AH,
+ next_instruction;
diff --git a/common/CPU/x86/microcode/aas.us b/common/CPU/x86/microcode/aas.us
new file mode 100644
index 00000000..10952dce
--- /dev/null
+++ b/common/CPU/x86/microcode/aas.us
@@ -0,0 +1,24 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+// AAS
+.at 0x3f;
+ ra_sel AX, jmp aas;
+.auto_address;
+aas:
+ a_sel RA, alu_op AAS, rd_sel_source MICROCODE_RD_SEL, rd_sel AX,
+ update_flags AF CF, next_instruction;
diff --git a/common/CPU/x86/microcode/adc.us b/common/CPU/x86/microcode/adc.us
new file mode 100644
index 00000000..5758847d
--- /dev/null
+++ b/common/CPU/x86/microcode/adc.us
@@ -0,0 +1,24 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+#include "arithmetic.us"
+
+ARITH_REGMEM_REG(0x10, 0x11, ADC, OF SF ZF AF CF PF)
+ARITH_REG_REGMEM(0x12, 0x13, ADC, OF SF ZF AF CF PF)
+ARITH_REGMEM_A(0x14, 0x15, ADC, OF SF ZF AF CF PF)
+ARITH_80_81(ADC, OF SF ZF AF CF PF)
+ARITH_83(ADC, OF SF ZF AF CF PF)
diff --git a/common/CPU/x86/microcode/add.us b/common/CPU/x86/microcode/add.us
new file mode 100644
index 00000000..53086724
--- /dev/null
+++ b/common/CPU/x86/microcode/add.us
@@ -0,0 +1,24 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+#include "arithmetic.us"
+
+ARITH_REGMEM_REG(0x00, 0x01, ADD, OF SF ZF AF CF PF)
+ARITH_REG_REGMEM(0x02, 0x03, ADD, OF SF ZF AF CF PF)
+ARITH_REGMEM_A(0x04, 0x05, ADD, OF SF ZF AF CF PF)
+ARITH_80_81(ADD, OF SF ZF AF CF PF)
+ARITH_83(ADD, OF SF ZF AF CF PF)
diff --git a/common/CPU/x86/microcode/and.us b/common/CPU/x86/microcode/and.us
new file mode 100644
index 00000000..7870ac22
--- /dev/null
+++ b/common/CPU/x86/microcode/and.us
@@ -0,0 +1,24 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+#include "arithmetic.us"
+
+ARITH_REGMEM_REG(0x20, 0x21, AND, OF SF ZF CF PF)
+ARITH_REG_REGMEM(0x22, 0x23, AND, OF SF ZF CF PF)
+ARITH_REGMEM_A(0x24, 0x25, AND, OF SF ZF CF PF)
+ARITH_80_81(AND, OF SF ZF CF PF)
+ARITH_83(AND, OF SF ZF CF PF)
diff --git a/common/CPU/x86/microcode/arithmetic.us b/common/CPU/x86/microcode/arithmetic.us
new file mode 100644
index 00000000..b45bbf23
--- /dev/null
+++ b/common/CPU/x86/microcode/arithmetic.us
@@ -0,0 +1,92 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+#ifndef ARITHMETIC_US
+#define ARITHMETIC_US
+
+#define ARITH_REGMEM_REG(opcode1, opcode2, alufunc, flags) \
+.at opcode1; \
+ mar_write, mar_wr_sel EA, width WAUTO, ra_modrm_rm_reg, \
+ jmp_rm_reg_mem alufunc ## opcode1 ##_reg, segment DS; \
+.at opcode2; \
+ mar_write, mar_wr_sel EA, width WAUTO, ra_modrm_rm_reg, \
+ jmp_rm_reg_mem alufunc ## opcode1 ##_reg, segment DS; \
+.auto_address; \
+alufunc ## opcode1 ## _reg: \
+ a_sel RA, b_sel RB, alu_op alufunc, \
+ rd_sel_source MODRM_RM_REG, update_flags flags, \
+ width WAUTO, next_instruction; \
+alufunc ## opcode1 ## _mem: \
+ segment DS, mem_read, width WAUTO; \
+ a_sel MDR, b_sel RB, alu_op alufunc, mdr_write, \
+ update_flags flags, width WAUTO, segment DS, jmp write_complete;
+
+#define ARITH_REG_REGMEM(opcode1, opcode2, alufunc, flags) \
+.at opcode1; \
+ mar_write, mar_wr_sel EA, width WAUTO, ra_modrm_rm_reg, \
+ jmp_rm_reg_mem alufunc ## opcode1 ## _reg, segment DS; \
+.at opcode2; \
+ mar_write, mar_wr_sel EA, width WAUTO, ra_modrm_rm_reg, \
+ jmp_rm_reg_mem alufunc ## opcode1 ## _reg, segment DS; \
+.auto_address; \
+alufunc ## opcode1 ## _reg: \
+ a_sel RA, b_sel RB, alu_op alufunc, rd_sel_source MODRM_REG, \
+ update_flags flags, width WAUTO, \
+ next_instruction; \
+alufunc ## opcode1 ## _mem: \
+ segment DS, mem_read, width WAUTO; \
+ a_sel MDR, b_sel RB, alu_op alufunc, rd_sel_source MODRM_REG, \
+ update_flags flags, width WAUTO, \
+ next_instruction;
+
+#define ARITH_REGMEM_A(opcode1, opcode2, alufunc, flags) \
+.at opcode1; \
+ width WAUTO, ra_sel AL, jmp alufunc ## opcode1; \
+.at opcode2; \
+ width WAUTO, ra_sel AL, jmp alufunc ## opcode1; \
+.auto_address; \
+alufunc ## opcode1: \
+ a_sel RA, b_sel IMMEDIATE, alu_op alufunc, \
+ rd_sel_source MICROCODE_RD_SEL, rd_sel AL, \
+ update_flags flags, width WAUTO, \
+ next_instruction;
+
+#define ARITH_80_81(alufunc, flags) \
+alufunc ## 80_81_reg: \
+ a_sel RA, b_sel IMMEDIATE, alu_op alufunc, \
+ rd_sel_source MODRM_RM_REG, \
+ width WAUTO, update_flags flags, next_instruction; \
+alufunc ## 80_81_mem: \
+ segment DS, mem_read, width WAUTO; \
+ a_sel MDR, b_sel IMMEDIATE, alu_op alufunc, \
+ mdr_write, update_flags flags, segment DS, width WAUTO, jmp write_complete;
+
+#define ARITH_83(alufunc, flags) \
+alufunc ## 83_reg: \
+ ra_modrm_rm_reg, jmp alufunc ## 83 ## regwrite; \
+alufunc ## 83_mem: \
+ ra_modrm_rm_reg, segment DS, jmp alufunc ## 83 ## memwrite; \
+alufunc ## 83 ## regwrite: \
+ a_sel RA, b_sel IMMEDIATE, alu_op alufunc, \
+ rd_sel_source MODRM_RM_REG, \
+ update_flags flags, next_instruction; \
+alufunc ## 83 ## memwrite: \
+ segment DS, mem_read; \
+ a_sel MDR, b_sel IMMEDIATE, alu_op alufunc, \
+ mdr_write, update_flags flags, segment DS, jmp write_16_complete;
+
+#endif // ARITHMETIC_US
diff --git a/common/CPU/x86/microcode/bound.us b/common/CPU/x86/microcode/bound.us
new file mode 100644
index 00000000..9d5ecf9d
--- /dev/null
+++ b/common/CPU/x86/microcode/bound.us
@@ -0,0 +1,36 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+// BOUND
+.at 0x62;
+ mar_write, mar_wr_sel EA, segment DS, jmp_rm_reg_mem bound_reg;
+.auto_address;
+bound_reg:
+ b_sel IMMEDIATE, immediate 0x18, alu_op SELB, tmp_wr_en, jmp do_int;
+bound_mem:
+ alu_op GETFLAGS, tmp_wr_en, segment DS, mem_read;
+ a_sel MDR, b_sel RB, alu_op BOUNDL, update_flags CF;
+ a_sel MAR, b_sel IMMEDIATE, immediate 0x2, alu_op ADD, mar_write,
+ mar_wr_sel Q, segment DS, jmp_if_taken bound_fail;
+ segment DS, mem_read;
+ a_sel MDR, b_sel RB, alu_op BOUNDH, update_flags CF;
+ jmp_if_taken bound_fail;
+ b_sel TEMP, alu_op SELB, alu_op SETFLAGSB, update_flags CF, next_instruction;
+
+bound_fail:
+ b_sel TEMP, alu_op SELB, alu_op SETFLAGSB, update_flags CF;
+ b_sel IMMEDIATE, immediate 0x14, alu_op SELB, tmp_wr_en, jmp do_int;
diff --git a/common/CPU/x86/microcode/call.us b/common/CPU/x86/microcode/call.us
new file mode 100644
index 00000000..68af61ba
--- /dev/null
+++ b/common/CPU/x86/microcode/call.us
@@ -0,0 +1,81 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+.at 0xe8;
+ jmp calle8, ra_sel SP;
+.auto_address;
+calle8:
+ a_sel RA, b_sel IMMEDIATE, immediate 0x2, alu_op SUB, rd_sel SP,
+ rd_sel_source MICROCODE_RD_SEL, mar_write,
+ mar_wr_sel Q;
+ a_sel IP, alu_op SELA, mdr_write, ra_sel SP, segment SS, segment_force;
+ segment SS, segment_force, mem_write, a_sel IP, b_sel IMMEDIATE,
+ alu_op ADD, load_ip, next_instruction;
+
+callff_indirect_intra_reg:
+ a_sel RA, alu_op SELA, load_ip, jmp callff_indirect_intra_save,
+ ra_sel SP;
+callff_indirect_intra_mem:
+ segment DS, mem_read;
+ a_sel MDR, alu_op SELA, load_ip, jmp callff_indirect_intra_save,
+ ra_sel SP;
+callff_indirect_intra_save:
+ a_sel RA, b_sel IMMEDIATE, immediate 0x2, alu_op SUB, rd_sel SP,
+ rd_sel_source MICROCODE_RD_SEL, mar_write,
+ mar_wr_sel Q;
+ a_sel IP, alu_op SELA, mdr_write, ra_sel SP, segment SS, segment_force;
+ segment SS, segment_force, mem_write, next_instruction;
+
+.at 0x9a;
+ jmp call9a, mdr_write, b_sel IMMEDIATE, alu_op SELB,
+ alu_op SELB, load_ip, segment CS;
+.auto_address;
+call9a:
+ b_sel SR, alu_op SELB, mdr_write, ra_sel SP;
+ a_sel RA, b_sel IMMEDIATE, immediate 0x2, alu_op SUB, rd_sel SP,
+ rd_sel_source MICROCODE_RD_SEL, mar_write,
+ mar_wr_sel Q, segment_force, segment SS;
+ segment_force, segment SS, mem_write, ra_sel SP;
+ a_sel RA, b_sel IMMEDIATE, immediate 0x2, alu_op SUB, rd_sel SP,
+ rd_sel_source MICROCODE_RD_SEL, mar_write,
+ mar_wr_sel Q;
+ a_sel IP, alu_op SELA, mdr_write, segment_force, segment SS;
+ segment_force, segment SS, mem_write;
+ b_sel IMMEDIATE2, alu_op SELB, segment_force, segment CS,
+ segment_wr_en, next_instruction;
+
+callff_indirect_inter_reg:
+ next_instruction;
+callff_indirect_inter_mem:
+ b_sel SR, alu_op SELB, mdr_write, ra_sel SP;
+ a_sel RA, b_sel IMMEDIATE, immediate 0x2, alu_op SUB, rd_sel SP,
+ rd_sel_source MICROCODE_RD_SEL, mar_write,
+ mar_wr_sel Q, segment_force, segment SS;
+ segment_force, segment SS, mem_write, ra_sel SP;
+ a_sel RA, b_sel IMMEDIATE, immediate 0x2, alu_op SUB, rd_sel SP,
+ rd_sel_source MICROCODE_RD_SEL, mar_write,
+ mar_wr_sel Q;
+ a_sel IP, alu_op SELA, mdr_write, segment_force, segment SS;
+ segment_force, segment SS, mem_write;
+ mar_wr_sel EA, mar_write, segment DS;
+ segment DS, mem_read;
+ a_sel MDR, alu_op SELA, load_ip;
+ a_sel MAR, b_sel IMMEDIATE, immediate 0x2, alu_op ADD,
+ mar_wr_sel Q, mar_write, segment DS;
+ segment DS, mem_read;
+ a_sel MDR, alu_op SELA, segment_wr_en,
+ segment_force, segment CS, next_instruction;
diff --git a/common/CPU/x86/microcode/cmp.us b/common/CPU/x86/microcode/cmp.us
new file mode 100644
index 00000000..70e9db77
--- /dev/null
+++ b/common/CPU/x86/microcode/cmp.us
@@ -0,0 +1,24 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+#include "comparison.us"
+
+COMP_REGMEM_REG(0x38, 0x39, SUB, OF SF ZF AF CF PF)
+COMP_REG_REGMEM(0x3a, 0x3b, SUBREV, OF SF ZF AF CF PF)
+COMP_REGMEM_A(0x3c, 0x3d, SUB, OF SF ZF AF CF PF)
+COMP_80_81(SUB, OF SF ZF AF CF PF)
+COMP_83(SUB, OF SF ZF AF CF PF)
diff --git a/common/CPU/x86/microcode/cmps.us b/common/CPU/x86/microcode/cmps.us
new file mode 100644
index 00000000..a1c6b445
--- /dev/null
+++ b/common/CPU/x86/microcode/cmps.us
@@ -0,0 +1,74 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+.at 0xa6;
+ jmp cmpsb;
+
+.auto_address;
+cmpsb:
+ ra_sel DI, rb_cl, jmp_if_not_rep cmpsb_no_rep;
+cmpsb_rep_loop:
+ ra_sel CX, jmp_rb_zero cmpsb_done;
+ ra_sel DI, a_sel RA, b_sel IMMEDIATE, immediate 0x1, alu_op SUB,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel CX;
+cmpsb_no_rep:
+ ra_sel DI, a_sel RA, alu_op SELA, mar_wr_sel Q, mar_write, segment ES,
+ segment_force;
+ width W8, segment ES, segment_force, mem_read,
+ a_sel MDR, alu_op SELA, tmp_wr_en;
+ a_sel MAR, b_sel IMMEDIATE, immediate 0x1, alu_op NEXT,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel DI,
+ ra_sel SI;
+ a_sel RA, alu_op SELA, mar_wr_sel Q, mar_write, segment DS, ra_sel SI;
+ a_sel RA, b_sel IMMEDIATE, immediate 0x1, alu_op NEXT,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel SI,
+ segment DS;
+ width W8, segment DS, mem_read;
+ width W8, a_sel MDR, b_sel TEMP, alu_op SUB,
+ update_flags OF SF ZF CF PF AF, jmp_if_not_rep cmpsb_done;
+ rb_cl, alu_op GETFLAGS, ext_int_yield,
+ jmp_if_rep_not_complete cmpsb_rep_loop;
+cmpsb_done:
+ next_instruction;
+
+.at 0xa7;
+ jmp cmpsw;
+
+.auto_address;
+cmpsw:
+ ra_sel DI, rb_cl, jmp_if_not_rep cmpsw_no_rep;
+cmpsw_rep_loop:
+ ra_sel CX, jmp_rb_zero cmpsw_done;
+ ra_sel DI, a_sel RA, b_sel IMMEDIATE, immediate 0x1, alu_op SUB,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel CX;
+cmpsw_no_rep:
+ ra_sel DI, a_sel RA, alu_op SELA, mar_wr_sel Q, mar_write, segment ES,
+ segment_force;
+ segment ES, segment_force, mem_read, a_sel MDR, alu_op SELA, tmp_wr_en,
+ ra_sel DI;
+ a_sel RA, b_sel IMMEDIATE, immediate 0x2, alu_op NEXT,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel DI,
+ ra_sel SI;
+ a_sel RA, alu_op SELA, mar_wr_sel Q, mar_write, segment DS, ra_sel SI;
+ a_sel RA, b_sel IMMEDIATE, immediate 0x2, alu_op NEXT,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel SI, segment DS;
+ segment DS, mem_read, a_sel MDR, b_sel TEMP, alu_op SUB,
+ update_flags OF SF ZF CF PF AF, jmp_if_not_rep cmpsw_done;
+ rb_cl, alu_op GETFLAGS, ext_int_yield,
+ jmp_if_rep_not_complete cmpsw_rep_loop;
+cmpsw_done:
+ next_instruction;
diff --git a/common/CPU/x86/microcode/comparison.us b/common/CPU/x86/microcode/comparison.us
new file mode 100644
index 00000000..0b66329f
--- /dev/null
+++ b/common/CPU/x86/microcode/comparison.us
@@ -0,0 +1,112 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+#ifndef COMPARISON_US
+#define COMPARISON_US
+
+#define COMP_REGMEM_REG(opcode1, opcode2, alufunc, flags) \
+.at opcode1; \
+ mar_write, mar_wr_sel EA, width WAUTO, segment DS, ra_modrm_rm_reg, \
+ jmp_rm_reg_mem comp ## alufunc ## opcode1 ##_reg; \
+.at opcode2; \
+ mar_write, mar_wr_sel EA, width WAUTO, segment DS, ra_modrm_rm_reg, \
+ jmp_rm_reg_mem comp ## alufunc ## opcode1 ##_reg; \
+.auto_address; \
+comp ## alufunc ## opcode1 ## _reg: \
+ a_sel RA, b_sel RB, alu_op alufunc, \
+ update_flags flags, width WAUTO, next_instruction; \
+comp ## alufunc ## opcode1 ## _mem: \
+ segment DS, mem_read, width WAUTO; \
+ a_sel MDR, b_sel RB, alu_op alufunc, update_flags flags, \
+ width WAUTO, next_instruction;
+
+#define COMP_REG_REGMEM(opcode1, opcode2, alufunc, flags) \
+.at opcode1; \
+ mar_write, mar_wr_sel EA, width WAUTO, segment DS, ra_modrm_rm_reg, \
+ jmp_rm_reg_mem comp ## alufunc ## opcode1 ## _reg; \
+.at opcode2; \
+ mar_write, mar_wr_sel EA, width WAUTO, segment DS, ra_modrm_rm_reg, \
+ jmp_rm_reg_mem comp ## alufunc ## opcode1 ## _reg; \
+.auto_address; \
+comp ## alufunc ## opcode1 ## _reg: \
+ a_sel RA, b_sel RB, alu_op alufunc, update_flags flags, width WAUTO, \
+ next_instruction; \
+comp ## alufunc ## opcode1 ## _mem: \
+ segment DS, mem_read, width WAUTO; \
+ a_sel MDR, b_sel RB, alu_op alufunc, update_flags flags, \
+ width WAUTO, next_instruction;
+
+#define COMP_REGMEM_A(opcode1, opcode2, alufunc, flags) \
+.at opcode1; \
+ width WAUTO, ra_sel AL, jmp comp ## alufunc ## opcode1; \
+.at opcode2; \
+ width WAUTO, ra_sel AL, jmp comp ## alufunc ## opcode1; \
+.auto_address; \
+comp ## alufunc ## opcode1: \
+ a_sel RA, b_sel IMMEDIATE, alu_op alufunc, \
+ update_flags flags, width WAUTO, next_instruction;
+
+#define COMP_80_81(alufunc, flags) \
+comp ## alufunc ## 80_81_reg: \
+ a_sel RA, b_sel IMMEDIATE, alu_op alufunc, \
+ update_flags flags, width WAUTO, next_instruction; \
+comp ## alufunc ## 80_81_mem: \
+ segment DS, mem_read, width WAUTO; \
+ a_sel MDR, b_sel IMMEDIATE, alu_op alufunc, \
+ update_flags flags, width WAUTO, next_instruction;
+
+#define COMP_82(alufunc, flags) \
+comp ## alufunc ## 82_reg: \
+ a_sel RA, b_sel IMMEDIATE, alu_op alufunc, \
+ width W8, update_flags flags, next_instruction; \
+comp ## alufunc ## 82_mem: \
+ width W8, segment DS, mem_read; \
+ a_sel MDR, b_sel IMMEDIATE, alu_op alufunc, \
+ width W8, update_flags flags, next_instruction;
+
+#define COMP_83(alufunc, flags) \
+comp ## alufunc ## 83_reg: \
+ ra_modrm_rm_reg, jmp comp ## alufunc ## 83_regwrite; \
+comp ## alufunc ## 83_mem: \
+ ra_modrm_rm_reg, segment DS, jmp comp ## alufunc ## 83_memwrite; \
+comp ## alufunc ## 83_regwrite: \
+ a_sel RA, b_sel IMMEDIATE, alu_op alufunc, \
+ update_flags flags, next_instruction; \
+comp ## alufunc ## 83_memwrite: \
+ segment DS, mem_read; \
+ a_sel MDR, b_sel IMMEDIATE, alu_op alufunc, \
+ update_flags flags, next_instruction;
+
+#define COMP_F6(alufunc, flags) \
+comp ## alufunc ## f6_reg: \
+ a_sel RA, b_sel IMMEDIATE, alu_op alufunc, \
+ update_flags flags, width W8, next_instruction; \
+comp ## alufunc ## f6_mem: \
+ segment DS, mem_read, width W8; \
+ a_sel MDR, b_sel IMMEDIATE, alu_op alufunc, \
+ update_flags flags, width W8, next_instruction;
+
+#define COMP_F7(alufunc, flags) \
+comp ## alufunc ## f7_reg: \
+ a_sel RA, b_sel IMMEDIATE, alu_op alufunc, \
+ update_flags flags, next_instruction; \
+comp ## alufunc ## f7_mem: \
+ segment DS, mem_read; \
+ a_sel MDR, b_sel IMMEDIATE, alu_op alufunc, \
+ update_flags flags, next_instruction;
+
+#endif // COMPARISON_US
diff --git a/common/CPU/x86/microcode/daa.us b/common/CPU/x86/microcode/daa.us
new file mode 100644
index 00000000..781602f5
--- /dev/null
+++ b/common/CPU/x86/microcode/daa.us
@@ -0,0 +1,24 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+// DAA
+.at 0x27;
+ ra_sel AX, jmp daa;
+.auto_address;
+daa:
+ a_sel RA, alu_op DAA, rd_sel_source MICROCODE_RD_SEL, rd_sel AX,
+ update_flags SF ZF AF CF PF, next_instruction;
diff --git a/common/CPU/x86/microcode/das.us b/common/CPU/x86/microcode/das.us
new file mode 100644
index 00000000..388065d7
--- /dev/null
+++ b/common/CPU/x86/microcode/das.us
@@ -0,0 +1,24 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+// DAS
+.at 0x2f;
+ ra_sel AX, jmp das;
+.auto_address;
+das:
+ a_sel RA, alu_op DAS, rd_sel_source MICROCODE_RD_SEL, rd_sel AX,
+ update_flags SF ZF AF CF PF, next_instruction;
diff --git a/common/CPU/x86/microcode/debug.us b/common/CPU/x86/microcode/debug.us
new file mode 100644
index 00000000..d1447d28
--- /dev/null
+++ b/common/CPU/x86/microcode/debug.us
@@ -0,0 +1,166 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+.at 0x102;
+debug_wait:
+ jmp debug_wait;
+
+#define DEBUG_READ_GPR(reg, addr) \
+.at addr; \
+ ra_sel reg, jmp debug_read_gpr;
+
+#define DEBUG_READ_SR(reg, addr) \
+.at addr; \
+ segment_force, segment reg, jmp debug_read_sr;
+
+DEBUG_READ_GPR(AX, 0x103)
+DEBUG_READ_GPR(CX, 0x104)
+DEBUG_READ_GPR(DX, 0x105)
+DEBUG_READ_GPR(BX, 0x106)
+DEBUG_READ_GPR(SP, 0x107)
+DEBUG_READ_GPR(BP, 0x108)
+DEBUG_READ_GPR(SI, 0x109)
+DEBUG_READ_GPR(DI, 0x10a)
+DEBUG_READ_SR(ES, 0x10b)
+DEBUG_READ_SR(CS, 0x10c)
+DEBUG_READ_SR(SS, 0x10d)
+DEBUG_READ_SR(DS, 0x10e)
+
+#define DEBUG_WRITE_GPR(reg, addr) \
+.at addr; \
+ b_sel TEMP, alu_op SELB, rd_sel_source MICROCODE_RD_SEL, rd_sel reg, \
+ jmp debug_wait;
+
+#define DEBUG_WRITE_SR(reg, addr) \
+.at addr; \
+ b_sel TEMP, alu_op SELB, segment_force, segment_wr_en, \
+ segment_force, segment reg, next_instruction, \
+ ext_int_inhibit, jmp debug_wait;
+
+DEBUG_WRITE_GPR(AX, 0x113)
+DEBUG_WRITE_GPR(CX, 0x114)
+DEBUG_WRITE_GPR(DX, 0x115)
+DEBUG_WRITE_GPR(BX, 0x116)
+DEBUG_WRITE_GPR(SP, 0x117)
+DEBUG_WRITE_GPR(BP, 0x118)
+DEBUG_WRITE_GPR(SI, 0x119)
+DEBUG_WRITE_GPR(DI, 0x11a)
+DEBUG_WRITE_SR(ES, 0x11b)
+DEBUG_WRITE_SR(CS, 0x11c)
+DEBUG_WRITE_SR(SS, 0x11d)
+DEBUG_WRITE_SR(DS, 0x11e)
+
+.auto_address;
+debug_read_gpr:
+ a_sel RA, alu_op SELA, tmp_wr_en, jmp debug_wait;
+
+debug_read_sr:
+ b_sel SR, alu_op SELB, tmp_wr_en, jmp debug_wait;
+
+// Get IP
+.at 0x10f;
+ a_sel IP, alu_op SELA, tmp_wr_en, jmp debug_wait;
+
+// Get flags
+.at 0x110;
+ alu_op GETFLAGS, tmp_wr_en, jmp debug_wait;
+
+// Set IP
+.at 0x111;
+ b_sel TEMP, alu_op SELB, load_ip, next_instruction, ext_int_inhibit,
+ jmp debug_wait;
+
+// Set flags
+.at 0x112;
+ b_sel TEMP, alu_op SETFLAGSB, update_flags CF PF AF ZF SF TF IF DF OF,
+ jmp debug_wait;
+
+// Write MAR
+.at 0x11f;
+ b_sel TEMP, alu_op SELB, mar_wr_sel Q, mar_write, jmp debug_wait;
+
+// Write MDR
+.at 0x120;
+ b_sel TEMP, alu_op SELB, mdr_write, jmp debug_wait;
+
+// Read 8
+.at 0x121;
+ segment_force, segment DS, jmp debug_read8;
+.auto_address;
+debug_read8:
+ segment_force, segment DS, width W8, mem_read;
+ a_sel MDR, alu_op SELA, tmp_wr_en;
+ a_sel MAR, b_sel IMMEDIATE, immediate 0x1, alu_op ADD, mar_wr_sel Q,
+ mar_write, jmp debug_wait;
+
+// Read 16
+.at 0x122;
+ segment_force, segment DS, jmp debug_read16;
+.auto_address;
+debug_read16:
+ segment_force, segment DS, mem_read;
+ a_sel MDR, alu_op SELA, tmp_wr_en;
+ a_sel MAR, b_sel IMMEDIATE, immediate 0x2, alu_op ADD, mar_wr_sel Q,
+ mar_write, jmp debug_wait;
+
+// Write 8
+.at 0x123;
+ segment_force, segment DS, jmp debug_write8;
+.auto_address;
+debug_write8:
+ segment_force, segment DS, width W8, mem_write;
+ a_sel MAR, b_sel IMMEDIATE, immediate 0x1, alu_op ADD, mar_wr_sel Q,
+ mar_write, jmp debug_wait;
+
+// Write 16
+.at 0x124;
+ segment_force, segment DS, jmp debug_write16;
+.auto_address;
+debug_write16:
+ segment_force, segment DS, mem_write;
+ a_sel MAR, b_sel IMMEDIATE, immediate 0x2, alu_op ADD, mar_wr_sel Q,
+ mar_write, jmp debug_wait;
+
+// Read 8 IO
+.at 0x125;
+ segment_force, segment DS, jmp debug_read8io;
+.auto_address;
+debug_read8io:
+ segment_force, segment DS, width W8, mem_read, io;
+ a_sel MDR, alu_op SELA, tmp_wr_en, jmp debug_wait;
+
+// Read 16 IO
+.at 0x126;
+ segment_force, segment DS, jmp debug_read16io;
+.auto_address;
+debug_read16io:
+ segment_force, segment DS, mem_read, io;
+ a_sel MDR, alu_op SELA, tmp_wr_en, jmp debug_wait;
+
+// Write 8 IO
+.at 0x127;
+ segment_force, segment DS, jmp debug_write8io;
+.auto_address;
+debug_write8io:
+ segment_force, segment DS, width W8, mem_write, io, jmp debug_wait;
+
+// Write 16 IO
+.at 0x128;
+ segment_force, segment DS, jmp debug_write16io;
+.auto_address;
+debug_write16io:
+ segment_force, segment DS, mem_write, io, jmp debug_wait;
diff --git a/common/CPU/x86/microcode/div.us b/common/CPU/x86/microcode/div.us
new file mode 100644
index 00000000..f654bc7d
--- /dev/null
+++ b/common/CPU/x86/microcode/div.us
@@ -0,0 +1,77 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+divf6_reg:
+ width W8, a_sel RA, alu_op SELA, mdr_write, jmp do_div8;
+divf6_mem:
+ width W8, segment DS, mem_read, jmp do_div8;
+do_div8:
+ ra_sel AX;
+ // Divisor in MDR, dividend in DX:TMP
+ a_sel RA, alu_op SELA, tmp_wr_en;
+ width W8, alu_op DIV;
+div8_complete:
+ width W8, reg_wr_source QUOTIENT, rd_sel_source MICROCODE_RD_SEL, rd_sel AL;
+ width W8, reg_wr_source REMAINDER, rd_sel_source MICROCODE_RD_SEL,
+ rd_sel AH, next_instruction;
+
+divf7_reg:
+ a_sel RA, alu_op SELA, mdr_write, ra_sel AX, jmp do_div16;
+divf7_mem:
+ segment DS, mem_read, ra_sel AX, jmp do_div16;
+do_div16:
+ // Divisor in MDR, dividend in DX:TMP
+ a_sel RA, alu_op SELA, tmp_wr_en, ra_sel DX;
+ ra_sel DX, alu_op DIV;
+div16_complete:
+ reg_wr_source QUOTIENT, rd_sel_source MICROCODE_RD_SEL, rd_sel AX;
+ reg_wr_source REMAINDER, rd_sel_source MICROCODE_RD_SEL, rd_sel DX,
+ next_instruction;
+
+idivf6_reg:
+ width W8, a_sel RA, alu_op SELA, mdr_write, jmp do_idiv8;
+idivf6_mem:
+ width W8, segment DS, mem_read, jmp do_idiv8;
+do_idiv8:
+ ra_sel AX;
+ // divisor in MDR, dividend in DX:TMP
+ a_sel RA, alu_op SELA, tmp_wr_en;
+ width W8, alu_op IDIV, jmp div8_complete;
+
+idivf7_reg:
+ a_sel RA, alu_op SELA, mdr_write, ra_sel AX, jmp do_idiv16;
+idivf7_mem:
+ segment DS, mem_read, ra_sel AX, jmp do_idiv16;
+do_idiv16:
+ // divisor in MDR, dividend in DX:TMP
+ a_sel RA, alu_op SELA, tmp_wr_en, ra_sel DX;
+ ra_sel DX, alu_op IDIV, jmp div16_complete;
+
+.at 0xd4;
+ width W8, ra_modrm_rm_reg, b_sel IMMEDIATE, alu_op SELB, mdr_write, jmp do_aam;
+.auto_address;
+do_aam:
+ width W8, ra_sel AL;
+ // divisor in MDR, dividend in DX:TMP
+ a_sel RA, alu_op SELA, tmp_wr_en;
+ width W8, alu_op DIV;
+ width W8, reg_wr_source QUOTIENT, rd_sel_source MICROCODE_RD_SEL, rd_sel AH;
+ width W8, reg_wr_source REMAINDER, rd_sel_source MICROCODE_RD_SEL,
+ rd_sel AL;
+ ra_sel AX;
+ a_sel RA, b_sel IMMEDIATE, immediate 0x0, alu_op ADD,
+ update_flags SF ZF PF, next_instruction;
diff --git a/common/CPU/x86/microcode/enter.us b/common/CPU/x86/microcode/enter.us
new file mode 100644
index 00000000..b72da16e
--- /dev/null
+++ b/common/CPU/x86/microcode/enter.us
@@ -0,0 +1,66 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+.at 0xc8;
+ b_sel IMMEDIATE, alu_op SELB, tmp_wr_en, ra_sel SP, jmp enter;
+.auto_address;
+enter:
+ // Push BP
+ a_sel RA, b_sel IMMEDIATE, immediate 0x2, alu_op SUB, mar_write,
+ mar_wr_sel Q, ra_sel BP, rd_sel_source MICROCODE_RD_SEL, rd_sel SP;
+ a_sel RA, alu_op SELA, mdr_write, segment_force, segment SS;
+ segment_force, segment SS, mem_write, ra_sel SP,
+ jmp_loop_done enter_out_nonest;
+
+ // Push frame temp
+ a_sel RA, b_sel IMMEDIATE2, alu_op ENTER_FRAME_TEMP_ADDR, mar_write,
+ mar_wr_sel Q, ra_sel SP;
+ a_sel RA, alu_op SELA, mdr_write, segment_force, segment SS;
+ segment_force, segment SS, mem_write;
+
+enter_loop:
+ jmp_loop_done enter_out, ra_sel BP;
+ // BP := BP - 2
+ a_sel RA, b_sel IMMEDIATE, immediate 0x2, alu_op SUB, rd_sel BP,
+ rd_sel_source MICROCODE_RD_SEL, segment_force, segment SS,
+ mar_write, mar_wr_sel Q;
+ // push [BP]
+ segment_force, segment SS, mem_read, ra_sel SP;
+ a_sel RA, b_sel IMMEDIATE, immediate 0x2, alu_op SUB, rd_sel SP,
+ rd_sel_source MICROCODE_RD_SEL, segment_force, segment SS,
+ mar_write, mar_wr_sel Q;
+ segment_force, segment SS, mem_write;
+ jmp enter_loop;
+
+enter_out:
+ // Reload frame_temp
+ ra_sel SP;
+ a_sel RA, b_sel IMMEDIATE, immediate 0x2, alu_op SUB, rd_sel SP,
+ rd_sel_source MICROCODE_RD_SEL, segment_force, segment SS,
+ mar_write, mar_wr_sel Q;
+ segment_force, segment SS, mem_read, ra_sel SP;
+ a_sel MDR, alu_op SELA, rd_sel BP, rd_sel_source MICROCODE_RD_SEL,
+ ra_sel SP;
+ // SP := SP - size
+ a_sel RA, b_sel TEMP, alu_op SUB, rd_sel SP, rd_sel_source MICROCODE_RD_SEL,
+ next_instruction;
+
+enter_out_nonest:
+ a_sel RA, alu_op SELA, rd_sel BP, rd_sel_source MICROCODE_RD_SEL,
+ ra_sel SP;
+ a_sel RA, b_sel TEMP, alu_op SUB, rd_sel SP, rd_sel_source MICROCODE_RD_SEL,
+ next_instruction;
diff --git a/common/CPU/x86/microcode/esc.us b/common/CPU/x86/microcode/esc.us
new file mode 100644
index 00000000..2bb70884
--- /dev/null
+++ b/common/CPU/x86/microcode/esc.us
@@ -0,0 +1,43 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+#include
+
+.at 0xd8;
+ jmp do_esc;
+.at 0xd9;
+ jmp do_esc;
+.at 0xda;
+ jmp do_esc;
+.at 0xdb;
+ jmp do_esc;
+.at 0xdc;
+ jmp do_esc;
+.at 0xdd;
+ jmp do_esc;
+.at 0xde;
+ jmp do_esc;
+.at 0xdf;
+ jmp do_esc;
+
+.auto_address;
+do_esc:
+#if (S80X86_TRAP_ESCAPE == 1)
+ b_sel IMMEDIATE, immediate 0x1c, alu_op SELB, tmp_wr_en, jmp do_int;
+#else
+ next_instruction;
+#endif
diff --git a/common/CPU/x86/microcode/extend.us b/common/CPU/x86/microcode/extend.us
new file mode 100644
index 00000000..413e9f0e
--- /dev/null
+++ b/common/CPU/x86/microcode/extend.us
@@ -0,0 +1,32 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+.at 0x98;
+ width W8, ra_sel AL, jmp cbw;
+.auto_address;
+cbw:
+ width W8, a_sel RA, b_sel IMMEDIATE, alu_op EXTEND,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel AH,
+ next_instruction;
+
+.at 0x99;
+ ra_sel AX, jmp cwd;
+.auto_address;
+cwd:
+ a_sel RA, b_sel IMMEDIATE, alu_op EXTEND,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel DX,
+ next_instruction;
diff --git a/common/CPU/x86/microcode/flags.us b/common/CPU/x86/microcode/flags.us
new file mode 100644
index 00000000..20041dee
--- /dev/null
+++ b/common/CPU/x86/microcode/flags.us
@@ -0,0 +1,70 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+// CLC
+.at 0xf8;
+ b_sel IMMEDIATE, immediate 0x0, alu_op SETFLAGSB, update_flags CF,
+ next_instruction;
+
+// STC
+.at 0xf9;
+ b_sel IMMEDIATE, immediate 0xffff, alu_op SETFLAGSB, update_flags CF,
+ next_instruction;
+
+// CLI
+.at 0xfa;
+ b_sel IMMEDIATE, immediate 0x0, alu_op SETFLAGSB, update_flags IF,
+ ext_int_inhibit, next_instruction;
+
+// STI
+.at 0xfb;
+ b_sel IMMEDIATE, immediate 0xffff, alu_op SETFLAGSB, update_flags IF,
+ ext_int_inhibit, next_instruction;
+
+// CLD
+.at 0xfc;
+ b_sel IMMEDIATE, immediate 0x0, alu_op SETFLAGSB, update_flags DF,
+ next_instruction;
+
+// STD
+.at 0xfd;
+ b_sel IMMEDIATE, immediate 0xffff, alu_op SETFLAGSB, update_flags DF,
+ next_instruction;
+
+// CMC
+.at 0xf5;
+ alu_op CMC, update_flags CF, next_instruction;
+
+// LAHF
+.at 0x9f;
+ alu_op GETFLAGS, rd_sel_source MICROCODE_RD_SEL, rd_sel AH,
+ width W8, next_instruction;
+
+// SAHF
+.at 0x9e;
+ ra_sel AH, width W8, jmp sahf;
+.auto_address;
+sahf:
+ a_sel RA, alu_op SETFLAGSA, update_flags CF PF AF ZF SF, next_instruction;
+
+// SETALC
+.at 0xd6;
+ ra_sel CX, rb_cl, jmp setalc;
+.auto_address;
+setalc:
+ width W8, a_sel RA, b_sel RB, alu_op SBB,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel AL, next_instruction;
diff --git a/common/CPU/x86/microcode/hlt.us b/common/CPU/x86/microcode/hlt.us
new file mode 100644
index 00000000..64277dae
--- /dev/null
+++ b/common/CPU/x86/microcode/hlt.us
@@ -0,0 +1,22 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+.at 0xf4;
+ jmp hlt;
+.auto_address;
+hlt:
+ jmp hlt, ext_int_yield;
diff --git a/common/CPU/x86/microcode/inc.us b/common/CPU/x86/microcode/inc.us
new file mode 100644
index 00000000..c9e96281
--- /dev/null
+++ b/common/CPU/x86/microcode/inc.us
@@ -0,0 +1,84 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+// Multiplexed inc/dec
+.at 0xfe;
+ width W8, mar_write, mar_wr_sel EA, jmp_dispatch_reg dispatch_fe;
+.auto_address;
+dispatch_fe:
+ width W8, ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem inc_fe_reg; // reg == 0
+ width W8, ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem dec_fe_reg; // reg == 1
+ next_instruction; // reg == 2
+ next_instruction; // reg == 3
+ next_instruction; // reg == 4
+ next_instruction; // reg == 5
+ next_instruction; // reg == 6
+ jmp invalid_opcode; // reg == 7
+
+inc_fe_reg:
+ a_sel RA, b_sel IMMEDIATE, immediate 0x1, alu_op ADD,
+ rd_sel_source MODRM_RM_REG, update_flags OF SF ZF AF PF,
+ width WAUTO, next_instruction;
+inc_fe_mem:
+ width WAUTO, segment DS, mem_read;
+ a_sel MDR, b_sel IMMEDIATE, immediate 0x1, alu_op ADD,
+ mdr_write, update_flags OF SF ZF AF PF, width WAUTO, segment DS,
+ jmp write_complete;
+
+dec_fe_reg:
+ a_sel RA, b_sel IMMEDIATE, immediate 0x1, alu_op SUB,
+ rd_sel_source MODRM_RM_REG, update_flags OF SF ZF AF PF,
+ width WAUTO, next_instruction;
+dec_fe_mem:
+ width WAUTO, segment DS, mem_read;
+ a_sel MDR, b_sel IMMEDIATE, immediate 0x1, alu_op SUB,
+ mdr_write, update_flags OF SF ZF AF PF, width WAUTO, segment DS,
+ jmp write_complete;
+
+#define INC_REG(opcode, reg) \
+.at opcode; \
+ ra_sel reg, jmp inc ## reg; \
+inc ## reg: \
+ a_sel RA, b_sel IMMEDIATE, immediate 0x1, alu_op ADD, \
+ rd_sel_source MICROCODE_RD_SEL, rd_sel reg, \
+ update_flags OF SF ZF AF PF, next_instruction;
+
+#define DEC_REG(opcode, reg) \
+.at opcode; \
+ ra_sel reg, jmp dec ## reg; \
+dec ## reg: \
+ a_sel RA, b_sel IMMEDIATE, immediate 0x1, alu_op SUB, \
+ rd_sel_source MICROCODE_RD_SEL, rd_sel reg, \
+ update_flags OF SF ZF AF PF, next_instruction;
+
+INC_REG(0x40, AX)
+INC_REG(0x41, CX)
+INC_REG(0x42, DX)
+INC_REG(0x43, BX)
+INC_REG(0x44, SP)
+INC_REG(0x45, BP)
+INC_REG(0x46, SI)
+INC_REG(0x47, DI)
+
+DEC_REG(0x48, AX)
+DEC_REG(0x49, CX)
+DEC_REG(0x4a, DX)
+DEC_REG(0x4b, BX)
+DEC_REG(0x4c, SP)
+DEC_REG(0x4d, BP)
+DEC_REG(0x4e, SI)
+DEC_REG(0x4f, DI)
diff --git a/common/CPU/x86/microcode/int.us b/common/CPU/x86/microcode/int.us
new file mode 100644
index 00000000..fc50e848
--- /dev/null
+++ b/common/CPU/x86/microcode/int.us
@@ -0,0 +1,79 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+// INT3
+.at 0xcc;
+ b_sel IMMEDIATE, immediate 0xc, alu_op SELB, tmp_wr_en, jmp do_int;
+
+// The same as above, but this time it's a 8 bit interrupt number.
+.at 0xcd;
+ b_sel IMMEDIATE, alu_op SELB, mar_wr_sel Q, mar_write, jmp intN;
+.auto_address;
+intN:
+ a_sel MAR, b_sel IMMEDIATE, immediate 0xff, alu_op AND, mar_write,
+ mar_wr_sel Q;
+ a_sel MAR, b_sel IMMEDIATE, immediate 0x4, alu_op MUL, tmp_wr_en,
+ jmp do_int;
+
+// INTO: the same as int3, but conditional on OF being set.
+.at 0xce;
+ alu_op GETFLAGS, mdr_write, jmp into;
+.auto_address;
+into:
+ b_sel IMMEDIATE, immediate 0x10, alu_op SELB, tmp_wr_en,
+ jmp_if_taken into_taken, ra_sel SP;
+ next_instruction;
+into_taken:
+ jmp do_int;
+
+// Process an interrupt.
+// TEMP: interrupt vector address
+//
+// This is a reasonably large microprocedure, but a reasonable amount of
+// repetition. Start by storing the flags + CS:IP to the stack, clear TF+IF
+// and then load the new CS:IP. As the vectors are stored in segment 0, this
+// requires temporarily setting CS to 0 to read the final vector address.
+.at 0x12d;
+do_int:
+ alu_op GETFLAGS, mdr_write, ra_sel SP, jmp do_int_main;
+.auto_address;
+do_int_main:
+ a_sel RA, b_sel IMMEDIATE, immediate 0x2, alu_op SUB,
+ mar_write, mar_wr_sel Q, segment SS, segment_force;
+ segment SS, segment_force, mem_write;
+ a_sel MAR, b_sel IMMEDIATE, immediate 0x2, alu_op SUB,
+ mar_write, mar_wr_sel Q, segment_force, segment CS;
+ b_sel SR, alu_op SELB, mdr_write, segment SS, segment_force;
+ segment SS, segment_force, mem_write;
+ a_sel MAR, b_sel IMMEDIATE, immediate 0x2, alu_op SUB,
+ mar_write, mar_wr_sel Q;
+ a_sel IP, alu_op SELA, mdr_write, segment SS, segment_force;
+ segment SS, segment_force, mem_write;
+ a_sel MAR, alu_op SELA, rd_sel_source MICROCODE_RD_SEL,
+ rd_sel SP;
+ b_sel IMMEDIATE, immediate 0x0, alu_op SETFLAGSB, update_flags IF TF;
+ b_sel IMMEDIATE, immediate 0x0, alu_op SELB, segment_force,
+ segment CS, segment_wr_en;
+ b_sel TEMP, alu_op SELB, mar_wr_sel Q, mar_write, segment CS,
+ segment_force;
+ segment_force, segment CS, mem_read;
+ a_sel MDR, alu_op SELA, load_ip;
+ a_sel MAR, b_sel IMMEDIATE, immediate 0x2, alu_op ADD, mar_write,
+ mar_wr_sel Q, segment CS, segment_force;
+ segment_force, segment CS, mem_read;
+ a_sel MDR, alu_op SELA, segment_force, segment CS,
+ segment_wr_en, next_instruction;
diff --git a/common/CPU/x86/microcode/io.us b/common/CPU/x86/microcode/io.us
new file mode 100644
index 00000000..bcf40a6d
--- /dev/null
+++ b/common/CPU/x86/microcode/io.us
@@ -0,0 +1,169 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+// out imm8, al
+.at 0xe6;
+ width W8, b_sel IMMEDIATE, alu_op SELB, mar_wr_sel Q, mar_write,
+ jmp oute6, ra_sel AL;
+// out imm16, al
+.at 0xe7;
+ width W8, b_sel IMMEDIATE, alu_op SELB, mar_wr_sel Q, mar_write, jmp oute6;
+.auto_address;
+oute6:
+ a_sel MAR, b_sel IMMEDIATE, immediate 0xff, alu_op AND, mar_write,
+ mar_wr_sel Q;
+ a_sel RA, alu_op SELA, mdr_write;
+ width WAUTO, io, mem_write, next_instruction;
+
+// out dx, al
+.at 0xee;
+ width W8, ra_sel AL, jmp outee;
+// out dx, ax
+.at 0xef;
+ ra_sel AX, jmp outee;
+.auto_address;
+outee:
+ a_sel RA, alu_op SELA, mdr_write, ra_sel DX;
+ a_sel RA, alu_op SELA, mar_write, mar_wr_sel Q;
+ width WAUTO, io, mem_write, next_instruction;
+
+// in al, immed8
+.at 0xe4;
+ width W8, b_sel IMMEDIATE, alu_op SELB, mar_wr_sel Q, mar_write, jmp ine4;
+// in ax, immed16
+.at 0xe5;
+ width W8, b_sel IMMEDIATE, alu_op SELB, mar_wr_sel Q, mar_write, jmp ine4;
+.auto_address;
+ine4:
+ a_sel MAR, b_sel IMMEDIATE, immediate 0xff, alu_op AND, mar_write,
+ mar_wr_sel Q;
+ width WAUTO, io, mem_read;
+ a_sel MDR, alu_op SELA, rd_sel_source MICROCODE_RD_SEL,
+ rd_sel AL, width WAUTO, next_instruction;
+
+// in dx, al
+.at 0xec;
+ ra_sel DX, jmp inec;
+// in dx, ax
+.at 0xed;
+ ra_sel DX, jmp inec;
+.auto_address;
+inec:
+ a_sel RA, alu_op SELA, mar_write, mar_wr_sel Q;
+ width WAUTO, io, mem_read;
+ a_sel MDR, alu_op SELA, rd_sel_source MICROCODE_RD_SEL,
+ rd_sel AL, width WAUTO, next_instruction;
+
+.at 0x6e;
+ jmp outsb;
+
+.auto_address;
+outsb:
+ ra_sel SI, jmp_if_not_rep outsb_no_rep;
+ rb_cl;
+outsb_rep_loop:
+ ra_sel CX, a_sel RA, b_sel IMMEDIATE, immediate 0x0, alu_op SUB,
+ jmp_rb_zero outsb_done;
+ ra_sel SI, a_sel RA, b_sel IMMEDIATE, immediate 0x1, alu_op SUB,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel CX;
+outsb_no_rep:
+ ra_sel SI, a_sel RA, alu_op SELA, mar_wr_sel Q, mar_write, segment DS;
+ a_sel RA, b_sel IMMEDIATE, immediate 0x1, alu_op NEXT,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel SI, segment DS;
+ width W8, segment DS, mem_read;
+ ra_sel DX;
+ a_sel RA, alu_op SELA, mar_write, mar_wr_sel Q;
+ width W8, io, mem_write, jmp_if_not_rep outsb_done;
+ rb_cl, ext_int_yield, jmp outsb_rep_loop;
+outsb_done:
+ next_instruction;
+
+.at 0x6f;
+ jmp outsw;
+
+.auto_address;
+outsw:
+ ra_sel SI, jmp_if_not_rep outsw_no_rep;
+ rb_cl;
+outsw_rep_loop:
+ ra_sel CX, a_sel RA, b_sel IMMEDIATE, immediate 0x0, alu_op SUB,
+ jmp_rb_zero outsw_done;
+ ra_sel SI, a_sel RA, b_sel IMMEDIATE, immediate 0x1, alu_op SUB,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel CX;
+outsw_no_rep:
+ ra_sel SI, a_sel RA, alu_op SELA, mar_wr_sel Q, mar_write, segment DS;
+ a_sel RA, b_sel IMMEDIATE, immediate 0x2, alu_op NEXT,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel SI, segment DS;
+ segment DS, mem_read;
+ ra_sel DX;
+ a_sel RA, alu_op SELA, mar_write, mar_wr_sel Q;
+ io, mem_write, jmp_if_not_rep outsw_done;
+ rb_cl, ext_int_yield, jmp outsw_rep_loop;
+outsw_done:
+ next_instruction;
+
+.at 0x6c;
+ jmp insb;
+
+.auto_address;
+insb:
+ ra_sel DX, jmp_if_not_rep insb_no_rep;
+ rb_cl;
+insb_rep_loop:
+ ra_sel CX, a_sel RA, b_sel IMMEDIATE, immediate 0x0, alu_op SUB,
+ jmp_rb_zero insb_done;
+ ra_sel DI, a_sel RA, b_sel IMMEDIATE, immediate 0x1, alu_op SUB,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel CX, ra_sel DX;
+insb_no_rep:
+ a_sel RA, alu_op SELA, mar_wr_sel Q, mar_write;
+ width W8, io, mem_read;
+ ra_sel DI;
+ a_sel RA, alu_op SELA, mar_write, mar_wr_sel Q, segment ES, segment_force;
+ segment ES, segment_force, width W8, mem_write;
+ ra_sel DI;
+ a_sel RA, b_sel IMMEDIATE, immediate 0x1, alu_op NEXT,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel DI,
+ jmp_if_not_rep insb_done;
+ rb_cl, ext_int_yield, jmp insb_rep_loop;
+insb_done:
+ next_instruction;
+
+.at 0x6d;
+ jmp insw;
+
+.auto_address;
+insw:
+ ra_sel DX, jmp_if_not_rep insw_no_rep;
+ rb_cl;
+insw_rep_loop:
+ ra_sel CX, a_sel RA, b_sel IMMEDIATE, immediate 0x0, alu_op SUB,
+ jmp_rb_zero insw_done;
+ ra_sel DI, a_sel RA, b_sel IMMEDIATE, immediate 0x1, alu_op SUB,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel CX, ra_sel DX;
+insw_no_rep:
+ a_sel RA, alu_op SELA, mar_wr_sel Q, mar_write;
+ io, mem_read;
+ ra_sel DI;
+ a_sel RA, alu_op SELA, mar_write, mar_wr_sel Q, segment ES, segment_force;
+ segment ES, segment_force, mem_write;
+ ra_sel DI;
+ a_sel RA, b_sel IMMEDIATE, immediate 0x2, alu_op NEXT,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel DI,
+ jmp_if_not_rep insw_done;
+ rb_cl, ext_int_yield, jmp insw_rep_loop;
+insw_done:
+ next_instruction;
diff --git a/common/CPU/x86/microcode/jmp.us b/common/CPU/x86/microcode/jmp.us
new file mode 100644
index 00000000..b34ae86b
--- /dev/null
+++ b/common/CPU/x86/microcode/jmp.us
@@ -0,0 +1,89 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+.at 0xe9;
+ a_sel IP, b_sel IMMEDIATE, alu_op ADD, load_ip,
+ next_instruction;
+
+.at 0xea;
+ b_sel IMMEDIATE, alu_op SELB, load_ip, jmp jmpea;
+.auto_address;
+jmpea:
+ b_sel IMMEDIATE2, alu_op SELB, segment_wr_en,
+ segment_force, segment CS, next_instruction;
+
+.at 0xeb;
+ a_sel IP, b_sel IMMEDIATE, alu_op ADD, load_ip,
+ next_instruction;
+
+jmpff_indirect_intra_reg:
+ a_sel RA, alu_op SELA, load_ip,
+ next_instruction;
+jmpff_indirect_intra_mem:
+ segment DS, mem_read;
+ a_sel MDR, alu_op SELA, load_ip,
+ next_instruction;
+
+jmpff_indirect_inter_reg:
+ next_instruction;
+jmpff_indirect_inter_mem:
+ segment DS, mem_read;
+ a_sel MDR, alu_op SELA, load_ip;
+ immediate 0x2, a_sel MAR, b_sel IMMEDIATE, alu_op ADD,
+ mar_wr_sel Q, mar_write, segment DS;
+ segment DS, mem_read;
+ a_sel MDR, alu_op SELA, segment_wr_en,
+ segment_force, segment CS, next_instruction;
+
+// JCXZ
+.at 0xe3;
+ rb_cl, jmp jcxz;
+
+.auto_address;
+jcxz:
+ jmp_rb_zero jcxz_taken;
+ next_instruction;
+jcxz_taken:
+ a_sel IP, b_sel IMMEDIATE, alu_op ADD, load_ip, next_instruction;
+
+#define JUMP(opcode) \
+.at opcode; \
+ jmp test_jump
+
+JUMP(0x70);
+JUMP(0x71);
+JUMP(0x72);
+JUMP(0x73);
+JUMP(0x74);
+JUMP(0x75);
+JUMP(0x76);
+JUMP(0x77);
+JUMP(0x78);
+JUMP(0x79);
+JUMP(0x7a);
+JUMP(0x7b);
+JUMP(0x7c);
+JUMP(0x7d);
+JUMP(0x7e);
+JUMP(0x7f);
+
+.auto_address;
+test_jump:
+ jmp_if_taken jmp_taken;
+ next_instruction;
+jmp_taken:
+ a_sel IP, b_sel IMMEDIATE, alu_op ADD, load_ip, next_instruction;
diff --git a/common/CPU/x86/microcode/lds.us b/common/CPU/x86/microcode/lds.us
new file mode 100644
index 00000000..8b10859f
--- /dev/null
+++ b/common/CPU/x86/microcode/lds.us
@@ -0,0 +1,32 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+.at 0xc5;
+ mar_write, mar_wr_sel EA, segment DS, jmp_rm_reg_mem lds_reg,
+ segment DS;
+.auto_address;
+lds_reg:
+ next_instruction;
+lds_mem:
+ segment DS, mem_read;
+ rd_sel_source MODRM_REG, a_sel MDR, alu_op SELA,
+ segment DS;
+ a_sel MAR, alu_op ADD, b_sel IMMEDIATE, immediate 0x2,
+ mar_write, mar_wr_sel Q, segment DS;
+ segment DS, mem_read;
+ segment_force, segment DS, segment_wr_en, a_sel MDR, alu_op SELA,
+ next_instruction;
diff --git a/common/CPU/x86/microcode/lea.us b/common/CPU/x86/microcode/lea.us
new file mode 100644
index 00000000..c1bb8ef7
--- /dev/null
+++ b/common/CPU/x86/microcode/lea.us
@@ -0,0 +1,25 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+.at 0x8d;
+ mar_write, mar_wr_sel EA, segment DS, jmp_rm_reg_mem lea_reg;
+.auto_address;
+lea_reg:
+ next_instruction;
+lea_mem:
+ rd_sel AX, rd_sel_source MODRM_REG, a_sel MAR, alu_op SELA,
+ next_instruction;
diff --git a/common/CPU/x86/microcode/leave.us b/common/CPU/x86/microcode/leave.us
new file mode 100644
index 00000000..f421dbff
--- /dev/null
+++ b/common/CPU/x86/microcode/leave.us
@@ -0,0 +1,28 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+.at 0xc9;
+ ra_sel BP, jmp leavec9;
+.auto_address;
+leavec9:
+ a_sel RA, alu_op SELA, rd_sel SP, rd_sel_source MICROCODE_RD_SEL,
+ mar_write, mar_wr_sel Q, segment SS, segment_force;
+ segment SS, segment_force, mem_read;
+ a_sel MDR, alu_op SELA, rd_sel BP, rd_sel_source MICROCODE_RD_SEL;
+ a_sel MAR, b_sel IMMEDIATE, immediate 0x2, alu_op ADD,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel SP,
+ next_instruction;
diff --git a/common/CPU/x86/microcode/les.us b/common/CPU/x86/microcode/les.us
new file mode 100644
index 00000000..f801a04d
--- /dev/null
+++ b/common/CPU/x86/microcode/les.us
@@ -0,0 +1,32 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+.at 0xc4;
+ mar_write, mar_wr_sel EA, segment DS, jmp_rm_reg_mem les_reg,
+ segment DS;
+.auto_address;
+les_reg:
+ next_instruction;
+les_mem:
+ segment DS, mem_read;
+ rd_sel_source MODRM_REG, a_sel MDR, alu_op SELA,
+ segment DS;
+ a_sel MAR, alu_op ADD, b_sel IMMEDIATE, immediate 0x2,
+ mar_write, mar_wr_sel Q, segment DS;
+ segment DS, mem_read;
+ segment_force, segment ES, segment_wr_en, a_sel MDR, alu_op SELA,
+ next_instruction;
diff --git a/common/CPU/x86/microcode/lods.us b/common/CPU/x86/microcode/lods.us
new file mode 100644
index 00000000..7415d94a
--- /dev/null
+++ b/common/CPU/x86/microcode/lods.us
@@ -0,0 +1,56 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+.at 0xac;
+ jmp lodsb;
+
+.auto_address;
+lodsb:
+ ra_sel SI, rb_cl, jmp_if_not_rep lodsb_no_rep;
+lodsb_rep_loop:
+ ra_sel CX, jmp_rb_zero lodsb_done;
+ ra_sel SI, a_sel RA, b_sel IMMEDIATE, immediate 0x1, alu_op SUB,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel CX;
+lodsb_no_rep:
+ ra_sel SI, a_sel RA, alu_op SELA, mar_wr_sel Q, mar_write, segment DS;
+ a_sel RA, b_sel IMMEDIATE, immediate 0x1, alu_op NEXT,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel SI, segment DS;
+ width W8, segment DS, mem_read, a_sel MDR, alu_op SELA,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel AL, jmp_if_not_rep lodsb_done;
+ rb_cl, ext_int_yield, jmp lodsb_rep_loop;
+lodsb_done:
+ next_instruction;
+
+.at 0xad;
+ jmp lodsw;
+
+.auto_address;
+lodsw:
+ ra_sel SI, rb_cl, jmp_if_not_rep lodsw_no_rep;
+lodsw_rep_loop:
+ ra_sel CX, jmp_rb_zero lodsw_done;
+ ra_sel SI, a_sel RA, b_sel IMMEDIATE, immediate 0x1, alu_op SUB,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel CX;
+lodsw_no_rep:
+ ra_sel SI, a_sel RA, alu_op SELA, mar_wr_sel Q, mar_write, segment DS;
+ a_sel RA, b_sel IMMEDIATE, immediate 0x2, alu_op NEXT,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel SI, segment DS;
+ segment DS, mem_read, a_sel MDR, alu_op SELA,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel AX, jmp_if_not_rep lodsw_done;
+ rb_cl, ext_int_yield, jmp lodsw_rep_loop;
+lodsw_done:
+ next_instruction;
diff --git a/common/CPU/x86/microcode/loop.us b/common/CPU/x86/microcode/loop.us
new file mode 100644
index 00000000..a8a6af42
--- /dev/null
+++ b/common/CPU/x86/microcode/loop.us
@@ -0,0 +1,57 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+// LOOP
+.at 0xe2;
+ ra_sel CX, jmp loop;
+
+.auto_address;
+loop:
+ a_sel RA, b_sel IMMEDIATE, immediate 0x1, alu_op SUB,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel CX,
+ rb_cl;
+ jmp_rb_zero loop_not_taken;
+ a_sel IP, b_sel IMMEDIATE, alu_op ADD, load_ip, next_instruction;
+loop_not_taken:
+ next_instruction;
+
+// LOOPE
+.at 0xe1;
+ ra_sel CX, jmp loope;
+
+.auto_address;
+loope:
+ a_sel RA, b_sel IMMEDIATE, immediate 0x1, alu_op SUB,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel CX, rb_cl,
+ jmp_if_zero loope_maybe_taken;
+ jmp loop_not_taken;
+loope_maybe_taken:
+ jmp_rb_zero loop_not_taken;
+ a_sel IP, b_sel IMMEDIATE, alu_op ADD, load_ip, next_instruction;
+
+// LOOPNE
+.at 0xe0;
+ ra_sel CX, jmp loopne;
+
+.auto_address;
+loopne:
+ a_sel RA, b_sel IMMEDIATE, immediate 0x1, alu_op SUB,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel CX, rb_cl,
+ jmp_if_zero loop_not_taken;
+ jmp_rb_zero loop_not_taken;
+loopne_taken:
+ a_sel IP, b_sel IMMEDIATE, alu_op ADD, load_ip, next_instruction;
diff --git a/common/CPU/x86/microcode/microcode.mif.templ b/common/CPU/x86/microcode/microcode.mif.templ
new file mode 100644
index 00000000..3c52e8a6
--- /dev/null
+++ b/common/CPU/x86/microcode/microcode.mif.templ
@@ -0,0 +1,29 @@
+-- Copyright Jamie Iles, 2017
+--
+-- This file is part of s80x86.
+--
+-- s80x86 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.
+--
+-- s80x86 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 s80x86. If not, see .
+
+DEPTH = <%num_instructions%>;
+WIDTH = <%width%>;
+ADDRESS_RADIX = HEX;
+DATA_RADIX = BIN;
+CONTENT
+BEGIN
+
+<%#instructions%>
+<%address%> : <%value%>;
+<%/instructions%>
+
+END;
diff --git a/common/CPU/x86/microcode/microcode.us b/common/CPU/x86/microcode/microcode.us
new file mode 100644
index 00000000..dddd7f4c
--- /dev/null
+++ b/common/CPU/x86/microcode/microcode.us
@@ -0,0 +1,291 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+#include
+
+.at 0x100;
+opcode_fetch:
+ ext_int_yield, jmp_opcode;
+
+// See 0xcc in int.us for more details, this is the same thing but for a
+// divide error.
+.at 0x101;
+divide_error:
+ b_sel IMMEDIATE, immediate 0x0, alu_op SELB, tmp_wr_en, jmp do_int;
+
+// See 0xcc in int.us for more details, this is the same thing but for a
+// IRQ.
+.at 0x12b;
+ // IRQ number to temp
+ a_sel MDR, b_sel IMMEDIATE, immediate 0x4, alu_op MUL, tmp_wr_en,
+ jmp do_int;
+
+// See 0xcc in int.us for more details, this is the same thing but for a
+// NMI.
+.at 0x12a;
+nmi:
+ b_sel IMMEDIATE, immediate 0x8, alu_op SELB, tmp_wr_en, jmp do_int;
+
+// See 0xcc in int.us for more details, this is the same thing but for a
+// single step trap.
+.at 0x12c;
+single_step:
+ b_sel IMMEDIATE, immediate 0x4, alu_op SELB, tmp_wr_en, jmp do_int;
+
+// Wait a single cycle for modrm decoding to complete
+.at 0x12e;
+modrm_decode:
+ jmp_opcode;
+
+.at 0x12f;
+bad_opcode:
+ jmp invalid_opcode;
+
+#define INVALID_OPCODE(opc) \
+.at opc; \
+ jmp invalid_opcode
+
+#define FILL(opc) \
+.at opc; \
+ next_instruction
+
+INVALID_OPCODE(0x0f);
+INVALID_OPCODE(0x63);
+INVALID_OPCODE(0x64);
+INVALID_OPCODE(0x65);
+INVALID_OPCODE(0x66);
+INVALID_OPCODE(0x67);
+INVALID_OPCODE(0xf1);
+
+FILL(0x26);
+FILL(0x2e);
+FILL(0x36);
+FILL(0x3e);
+FILL(0xf0);
+FILL(0xf2);
+FILL(0xf3);
+
+.auto_address;
+invalid_opcode:
+ b_sel IMMEDIATE, immediate 0x18, alu_op SELB, tmp_wr_en, jmp do_int;
+
+// Multiplexed add/adc/sub/sbb/cmp/xor/or/and
+// r/m OP immed8
+.at 0x80;
+ mar_write, mar_wr_sel EA, jmp_dispatch_reg dispatch_80_81;
+.auto_address;
+dispatch_80_81:
+ width WAUTO, ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem ADD80_81_reg; // reg == 0
+ width WAUTO, ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem OR80_81_reg; // reg == 1
+ width WAUTO, ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem ADC80_81_reg; // reg == 2
+ width WAUTO, ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem SBB80_81_reg; // reg == 3
+ width WAUTO, ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem AND80_81_reg; // reg == 4
+ width WAUTO, ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem SUB80_81_reg; // reg == 5
+ width WAUTO, ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem XOR80_81_reg; // reg == 6
+ width WAUTO, ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem compSUB80_81_reg; // reg == 7
+
+// Multiplexed add/adc/sub/sbb/cmp/xor/or/and
+// r/m OP immed16
+.at 0x81;
+ mar_write, mar_wr_sel EA, jmp_dispatch_reg dispatch_80_81;
+
+// Multiplexed add/adc/sub/sbb/cmp
+// r/m OP immed8
+.at 0x82;
+ mar_write, mar_wr_sel EA, jmp_dispatch_reg dispatch_80_81;
+
+// Multiplexed add/adc/sub/sbb/cmp/xor/or/and
+// r/m OP immed16
+.at 0x83;
+ mar_write, mar_wr_sel EA, jmp_dispatch_reg dispatch_83;
+.auto_address;
+dispatch_83:
+ segment DS, jmp_rm_reg_mem ADD83_reg; // reg == 0
+ segment DS, jmp_rm_reg_mem OR83_reg; // reg == 1
+ segment DS, jmp_rm_reg_mem ADC83_reg; // reg == 2
+ segment DS, jmp_rm_reg_mem SBB83_reg; // reg == 3
+ segment DS, jmp_rm_reg_mem AND83_reg; // reg == 4
+ segment DS, jmp_rm_reg_mem SUB83_reg; // reg == 5
+ segment DS, jmp_rm_reg_mem XOR83_reg; // reg == 6
+ segment DS, jmp_rm_reg_mem compSUB83_reg; // reg == 7
+
+// Multiplexed pop/8f
+.at 0x8f;
+ mar_write, mar_wr_sel EA, segment SS, jmp_dispatch_reg dispatch_8f;
+.auto_address;
+dispatch_8f:
+ ra_sel SP, jmp_rm_reg_mem pop8f_reg; // reg == 0
+ next_instruction; // reg == 1
+ next_instruction; // reg == 2
+ next_instruction; // reg == 3
+ next_instruction; // reg == 4
+ next_instruction; // reg == 5
+ next_instruction; // reg == 6
+ next_instruction; // reg == 7
+
+// Multiplexed shift single 8-bit
+.at 0xd0;
+ width WAUTO, mar_write, mar_wr_sel EA, jmp_dispatch_reg dispatch_d0_d1;
+.auto_address;
+dispatch_d0_d1:
+ width WAUTO, ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem ROLd0_d1_reg;
+ width WAUTO, ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem RORd0_d1_reg;
+ width WAUTO, ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem RCLd0_d1_reg;
+ width WAUTO, ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem RCRd0_d1_reg;
+ width WAUTO, ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem SHLd0_d1_reg;
+ width WAUTO, ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem SHRd0_d1_reg;
+ width WAUTO, ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem SHLd0_d1_reg;
+ width WAUTO, ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem SARd0_d1_reg;
+
+// Multiplexed shift single 8-bit by immediate
+.at 0xc0;
+ width W8, mar_write, mar_wr_sel EA,
+ jmp_dispatch_reg dispatch_c0;
+.auto_address;
+dispatch_c0:
+ width W8, tmp_wr_en, alu_op SELB, b_sel IMMEDIATE,
+ ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem ROLc0_reg;
+ width W8, tmp_wr_en, alu_op SELB, b_sel IMMEDIATE,
+ ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem RORc0_reg;
+ width W8, tmp_wr_en, alu_op SELB, b_sel IMMEDIATE,
+ ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem RCLc0_reg;
+ width W8, tmp_wr_en, alu_op SELB, b_sel IMMEDIATE,
+ ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem RCRc0_reg;
+ width W8, tmp_wr_en, alu_op SELB, b_sel IMMEDIATE,
+ ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem SHLc0_reg;
+ width W8, tmp_wr_en, alu_op SELB, b_sel IMMEDIATE,
+ ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem SHRc0_reg;
+ width W8, tmp_wr_en, alu_op SELB, b_sel IMMEDIATE,
+ ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem SHLc0_reg;
+ width W8, tmp_wr_en, alu_op SELB, b_sel IMMEDIATE,
+ ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem SARc0_reg;
+
+// Multiplexed shift single 16-bit by immediate
+.at 0xc1;
+ mar_write, mar_wr_sel EA, jmp_dispatch_reg dispatch_c1;
+.auto_address;
+dispatch_c1:
+ width W8, tmp_wr_en, alu_op SELB, b_sel IMMEDIATE, jmp ROLc1;
+ width W8, tmp_wr_en, alu_op SELB, b_sel IMMEDIATE, jmp RORc1;
+ width W8, tmp_wr_en, alu_op SELB, b_sel IMMEDIATE, jmp RCLc1;
+ width W8, tmp_wr_en, alu_op SELB, b_sel IMMEDIATE, jmp RCRc1;
+ width W8, tmp_wr_en, alu_op SELB, b_sel IMMEDIATE, jmp SHLc1;
+ width W8, tmp_wr_en, alu_op SELB, b_sel IMMEDIATE, jmp SHRc1;
+ width W8, tmp_wr_en, alu_op SELB, b_sel IMMEDIATE, jmp SHLc1;
+ width W8, tmp_wr_en, alu_op SELB, b_sel IMMEDIATE, jmp SARc1;
+
+// Multiplexed shift single 16-bit
+.at 0xd1;
+ mar_write, mar_wr_sel EA, jmp_dispatch_reg dispatch_d0_d1;
+
+// Multiplexed shift multiple 8-bit
+.at 0xd2;
+ width WAUTO, mar_write, mar_wr_sel EA, jmp_dispatch_reg dispatch_d2_d3;
+.auto_address;
+dispatch_d2_d3:
+ width WAUTO, ra_modrm_rm_reg, rb_cl, segment DS, jmp ROLd2_d3;
+ width WAUTO, ra_modrm_rm_reg, rb_cl, segment DS, jmp RORd2_d3;
+ width WAUTO, ra_modrm_rm_reg, rb_cl, segment DS, jmp RCLd2_d3;
+ width WAUTO, ra_modrm_rm_reg, rb_cl, segment DS, jmp RCRd2_d3;
+ width WAUTO, ra_modrm_rm_reg, rb_cl, segment DS, jmp SHLd2_d3;
+ width WAUTO, ra_modrm_rm_reg, rb_cl, segment DS, jmp SHRd2_d3;
+ width WAUTO, ra_modrm_rm_reg, rb_cl, segment DS, jmp SHLd2_d3;
+ width WAUTO, ra_modrm_rm_reg, rb_cl, segment DS, jmp SARd2_d3;
+
+// Multiplexed shift multiple 16-bit
+.at 0xd3;
+ mar_write, mar_wr_sel EA, jmp_dispatch_reg dispatch_d2_d3;
+
+// Multiplexed neg/mul/not/test/div 8 bit
+.at 0xf6;
+ width W8, mar_write, mar_wr_sel EA, jmp_dispatch_reg dispatch_f6;
+.auto_address;
+dispatch_f6:
+ width W8, ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem compANDf6_reg; // reg == 0
+ width W8, ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem compANDf6_reg; // reg == 1
+ width W8, ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem notf6_reg; // reg == 3
+ width W8, ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem negf6_reg; // reg == 3
+ width W8, ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem mulf6_reg; // reg == 4
+ width W8, ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem imulf6_reg; // reg == 5
+ width W8, ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem divf6_reg; // reg == 6
+ width W8, ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem idivf6_reg; // reg == 7
+
+// Multiplexed neg/mul/not/test/div 16 bit
+.at 0xf7;
+ mar_write, mar_wr_sel EA, jmp_dispatch_reg dispatch_f7;
+.auto_address;
+dispatch_f7:
+ ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem compANDf7_reg; // reg == 0
+ ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem compANDf7_reg; // reg == 1
+ ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem notf6_reg; // reg == 2
+ ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem negf6_reg; // reg == 3
+ ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem mulf7_reg; // reg == 4
+ ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem imulf7_reg; // reg == 5
+ ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem divf7_reg; // reg == 6
+ ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem idivf7_reg; // reg == 7
+
+// Multiplexed push/inc/jmp/call/ff
+.at 0xff;
+ mar_write, mar_wr_sel EA, segment DS, jmp_dispatch_reg dispatch_ff;
+.auto_address;
+dispatch_ff:
+ ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem inc_fe_reg; // reg == 0
+ ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem dec_fe_reg; // reg == 1
+ ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem callff_indirect_intra_reg; // reg == 2
+ segment_force, segment CS, jmp_rm_reg_mem callff_indirect_inter_reg; // reg == 3
+ ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem jmpff_indirect_intra_reg; // reg == 4
+ ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem jmpff_indirect_inter_reg; // reg == 5
+ ra_sel SP, segment DS, jmp_rm_reg_mem pushff_reg; // reg == 6
+ jmp invalid_opcode;
+
+.at 0x129;
+ jmp reset;
+
+.auto_address;
+reset:
+ b_sel IMMEDIATE, alu_op SELB, immediate 0x0, rd_sel_source MICROCODE_RD_SEL,
+ rd_sel AX;
+ b_sel IMMEDIATE, alu_op SELB, immediate 0x0, rd_sel_source MICROCODE_RD_SEL,
+ rd_sel CX;
+ b_sel IMMEDIATE, alu_op SELB, immediate 0x0, rd_sel_source MICROCODE_RD_SEL,
+ rd_sel DX;
+ b_sel IMMEDIATE, alu_op SELB, immediate 0x0, rd_sel_source MICROCODE_RD_SEL,
+ rd_sel BX;
+ b_sel IMMEDIATE, alu_op SELB, immediate 0x0, rd_sel_source MICROCODE_RD_SEL,
+ rd_sel SP;
+ b_sel IMMEDIATE, alu_op SELB, immediate 0x0, rd_sel_source MICROCODE_RD_SEL,
+ rd_sel BP;
+ b_sel IMMEDIATE, alu_op SELB, immediate 0x0, rd_sel_source MICROCODE_RD_SEL,
+ rd_sel SI;
+ b_sel IMMEDIATE, alu_op SELB, immediate 0x0, rd_sel_source MICROCODE_RD_SEL,
+ rd_sel DI;
+ b_sel IMMEDIATE, alu_op SELB, immediate 0x0, segment_force, segment ES,
+ segment_wr_en;
+ b_sel IMMEDIATE, alu_op SELB, immediate 0xffff, segment_force, segment CS,
+ segment_wr_en;
+ b_sel IMMEDIATE, alu_op SELB, immediate 0x0, segment_force, segment SS,
+ segment_wr_en;
+ b_sel IMMEDIATE, alu_op SELB, immediate 0x0, segment_force, segment DS,
+ segment_wr_en;
+ next_instruction, jmp opcode_fetch;
+
+.auto_address;
+write_16_complete:
+ segment DS, mem_write, next_instruction;
+
+write_complete:
+ segment DS, mem_write, width WAUTO, next_instruction;
diff --git a/common/CPU/x86/microcode/mov.us b/common/CPU/x86/microcode/mov.us
new file mode 100644
index 00000000..962891b8
--- /dev/null
+++ b/common/CPU/x86/microcode/mov.us
@@ -0,0 +1,151 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+// MOV 0x88 r/m := r (8-bit)
+.at 0x88;
+ mar_write, mar_wr_sel EA, width W8, jmp_rm_reg_mem mov88_reg;
+// MOV 0x89 r/m := r (16-bit)
+.at 0x89;
+ mar_write, mar_wr_sel EA, jmp_rm_reg_mem mov88_reg;
+.auto_address;
+mov88_reg:
+ b_sel RB, alu_op SELB, rd_sel_source MODRM_RM_REG,
+ width WAUTO, next_instruction;
+mov88_mem:
+ b_sel RB, alu_op SELB, mdr_write, segment DS, jmp write_complete;
+
+// MOV 0x8a r := r/m (8-bit)
+.at 0x8a;
+ mar_write, mar_wr_sel EA, ra_modrm_rm_reg, width W8,
+ jmp_rm_reg_mem mov8a_reg, segment DS, a_sel RA;
+// MOV 0x8b r := r/m (16-bit)
+.at 0x8b;
+ mar_write, mar_wr_sel EA, ra_modrm_rm_reg,
+ jmp_rm_reg_mem mov8a_reg, a_sel RA, segment DS;
+.auto_address;
+mov8a_reg:
+ a_sel RA, ra_modrm_rm_reg, alu_op SELA,
+ rd_sel_source MODRM_REG, width WAUTO,
+ next_instruction;
+mov8a_mem:
+ mem_read, width WAUTO, segment DS;
+ rd_sel_source MODRM_REG, a_sel MDR, alu_op SELA, width WAUTO,
+ next_instruction;
+
+// MOV 0xc6 r/m := immed8
+.at 0xc6;
+ mar_write, mar_wr_sel EA, jmp_dispatch_reg c6_dispatch;
+// MOV 0xc7 r/m := immed16
+.at 0xc7;
+ mar_write, mar_wr_sel EA, jmp_dispatch_reg c6_dispatch;
+.auto_address;
+c6_dispatch:
+ jmp_rm_reg_mem movc6_reg; // reg == 0
+ next_instruction; // reg == 1
+ next_instruction; // reg == 2
+ next_instruction; // reg == 3
+ next_instruction; // reg == 4
+ next_instruction; // reg == 5
+ next_instruction; // reg == 6
+ next_instruction; // reg == 7
+movc6_reg:
+ b_sel IMMEDIATE, alu_op SELB,
+ rd_sel_source MODRM_RM_REG, width WAUTO,
+ next_instruction;
+movc6_mem:
+ b_sel IMMEDIATE, alu_op SELB, mdr_write, segment DS, jmp write_complete;
+
+#define MOV_REG_IMMED8(opcode, reg) \
+ .at opcode; \
+ rd_sel_source MICROCODE_RD_SEL, rd_sel reg, \
+ alu_op SELB, b_sel IMMEDIATE, width W8, next_instruction;
+
+MOV_REG_IMMED8(0xb0, AL)
+MOV_REG_IMMED8(0xb1, CL)
+MOV_REG_IMMED8(0xb2, DL)
+MOV_REG_IMMED8(0xb3, BL)
+MOV_REG_IMMED8(0xb4, AH)
+MOV_REG_IMMED8(0xb5, CH)
+MOV_REG_IMMED8(0xb6, DH)
+MOV_REG_IMMED8(0xb7, BH)
+
+#define MOV_REG_IMMED16(opcode, reg) \
+ .at opcode; \
+ rd_sel_source MICROCODE_RD_SEL, rd_sel reg, \
+ alu_op SELB, b_sel IMMEDIATE, next_instruction;
+
+MOV_REG_IMMED16(0xb8, AX)
+MOV_REG_IMMED16(0xb9, CX)
+MOV_REG_IMMED16(0xba, DX)
+MOV_REG_IMMED16(0xbb, BX)
+MOV_REG_IMMED16(0xbc, SP)
+MOV_REG_IMMED16(0xbd, BP)
+MOV_REG_IMMED16(0xbe, SI)
+MOV_REG_IMMED16(0xbf, DI)
+
+// MOV 0xa0 al := m[immed16]
+.at 0xa0;
+ mar_write, mar_wr_sel Q, b_sel IMMEDIATE, alu_op SELB, jmp mova0, segment DS;
+// MOV 0xa1 ax := m[immed16]
+.at 0xa1;
+ mar_write, mar_wr_sel Q, b_sel IMMEDIATE, alu_op SELB, jmp mova0, segment DS;
+.auto_address;
+mova0:
+ segment DS, width WAUTO, mem_read;
+ rd_sel_source MICROCODE_RD_SEL, rd_sel AL, width WAUTO,
+ a_sel MDR, alu_op SELA, next_instruction;
+
+// MOV 0xa2 m[immed16] := al
+.at 0xa2;
+ mar_write, mar_wr_sel Q, b_sel IMMEDIATE, alu_op SELB, jmp mova2, ra_sel AL;
+.at 0xa3;
+ mar_write, mar_wr_sel Q, b_sel IMMEDIATE, alu_op SELB, jmp mova2, ra_sel AL;
+.auto_address;
+mova2:
+ a_sel RA, alu_op SELA, mdr_write, segment DS, jmp write_complete;
+
+// MOV 0x8e sr := reg/mem
+.at 0x8e;
+ mar_write, mar_wr_sel EA, ra_modrm_rm_reg,
+ segment DS, jmp_rm_reg_mem mov8e_reg;
+.auto_address;
+mov8e_reg:
+ segment_wr_en, rd_sel_source MODRM_REG, a_sel RA, alu_op SELA,
+ ext_int_inhibit, next_instruction;
+mov8e_mem:
+ segment DS, mem_read;
+ rd_sel_source MODRM_REG, segment_wr_en, a_sel MDR, alu_op SELA,
+ ext_int_inhibit, next_instruction;
+
+// MOV 0x8c reg/mem := sr
+.at 0x8c;
+ mar_write, mar_wr_sel EA, jmp_dispatch_reg dispatch_8c;
+.auto_address;
+dispatch_8c:
+ segment_force, segment ES, jmp_rm_reg_mem mov8c_reg;
+ segment_force, segment CS, jmp_rm_reg_mem mov8c_reg;
+ segment_force, segment SS, jmp_rm_reg_mem mov8c_reg;
+ segment_force, segment DS, jmp_rm_reg_mem mov8c_reg;
+ segment_force, segment ES, jmp_rm_reg_mem mov8c_reg;
+ segment_force, segment CS, jmp_rm_reg_mem mov8c_reg;
+ segment_force, segment SS, jmp_rm_reg_mem mov8c_reg;
+ segment_force, segment DS, jmp_rm_reg_mem mov8c_reg;
+mov8c_reg:
+ rd_sel_source MODRM_RM_REG, b_sel SR, alu_op SELB,
+ next_instruction;
+mov8c_mem:
+ b_sel SR, alu_op SELB, mdr_write, segment DS, jmp write_16_complete;
diff --git a/common/CPU/x86/microcode/movs.us b/common/CPU/x86/microcode/movs.us
new file mode 100644
index 00000000..fb569171
--- /dev/null
+++ b/common/CPU/x86/microcode/movs.us
@@ -0,0 +1,71 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+.at 0xa4;
+ jmp movsb;
+
+.auto_address;
+movsb:
+ ra_sel SI, rb_cl, jmp_if_not_rep movsb_no_rep;
+movsb_rep_loop:
+ ra_sel CX, jmp_rb_zero movsb_done;
+ ra_sel SI, a_sel RA, b_sel IMMEDIATE, immediate 0x1, alu_op SUB,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel CX;
+movsb_no_rep:
+ a_sel RA, alu_op SELA, mar_wr_sel Q, mar_write, ra_sel SI, segment DS;
+ width W8, segment DS, mem_read;
+
+ ra_sel DI, a_sel MAR, b_sel IMMEDIATE, immediate 0x1, alu_op NEXT,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel SI;
+ ra_sel DI, a_sel RA, alu_op SELA, mar_wr_sel Q, mar_write,
+ segment ES, segment_force;
+ width W8, segment ES, segment_force, mem_write,
+ jmp_if_not_rep movsb_done_no_rep;
+ a_sel MAR, b_sel IMMEDIATE, immediate 0x1, alu_op NEXT,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel DI, rb_cl, ext_int_yield,
+ jmp movsb_rep_loop;
+movsb_done:
+ next_instruction;
+movsb_done_no_rep:
+ a_sel MAR, b_sel IMMEDIATE, immediate 0x1, alu_op NEXT,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel DI, next_instruction;
+
+.at 0xa5;
+ jmp movsw;
+
+.auto_address;
+movsw:
+ ra_sel SI, rb_cl, jmp_if_not_rep movsw_no_rep;
+movsw_rep_loop:
+ ra_sel CX, jmp_rb_zero movsw_done;
+ ra_sel SI, a_sel RA, b_sel IMMEDIATE, immediate 0x1, alu_op SUB,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel CX;
+movsw_no_rep:
+ a_sel RA, alu_op SELA, mar_wr_sel Q, mar_write, ra_sel SI;
+ a_sel RA, b_sel IMMEDIATE, immediate 0x2, alu_op NEXT,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel SI,
+ segment DS;
+ segment DS, mem_read, ra_sel DI, a_sel RA, alu_op SELA, mar_wr_sel Q,
+ mar_write;
+ a_sel RA, b_sel IMMEDIATE, immediate 0x2, alu_op NEXT,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel DI,
+ segment ES, segment_force;
+ segment ES, segment_force, mem_write, jmp_if_not_rep movsw_done;
+
+ rb_cl, ext_int_yield, jmp movsw_rep_loop;
+movsw_done:
+ next_instruction;
diff --git a/common/CPU/x86/microcode/mul.us b/common/CPU/x86/microcode/mul.us
new file mode 100644
index 00000000..3dec34b3
--- /dev/null
+++ b/common/CPU/x86/microcode/mul.us
@@ -0,0 +1,84 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+// Multiplicand in TEMP, multiplier in MDR
+mulf6_reg:
+ width W8, a_sel RA, alu_op SELA, mdr_write, ra_sel AL, jmp do_mul8;
+mulf6_mem:
+ width W8, segment DS, mem_read, ra_sel AL, jmp do_mul8;
+do_mul8:
+ width W8, a_sel RA, alu_op SELA, tmp_wr_en;
+ // 8-bit multiplication yields a 16-bit result so move the result into
+ // TEMP to later transfer to AX as a 16-bit operation.
+ width W8, a_sel MDR, b_sel TEMP, alu_op MUL, update_flags ZF OF CF,
+ tmp_wr_en;
+ b_sel TEMP, alu_op SELB, rd_sel_source MICROCODE_RD_SEL, rd_sel AX,
+ next_instruction;
+
+// Multiplicand in TEMP, multiplier in MDR
+mulf7_reg:
+ a_sel RA, alu_op SELA, mdr_write, ra_sel AX, jmp do_mul16;
+mulf7_mem:
+ segment DS, mem_read, ra_sel AX, jmp do_mul16;
+do_mul16:
+ a_sel RA, alu_op SELA, tmp_wr_en;
+ a_sel MDR, b_sel TEMP, alu_op MUL, update_flags ZF OF CF,
+ tmp_wr_sel Q_HIGH, tmp_wr_en, rd_sel_source MICROCODE_RD_SEL,
+ rd_sel AX;
+ b_sel TEMP, alu_op SELB, rd_sel_source MICROCODE_RD_SEL, rd_sel DX,
+ next_instruction;
+
+// imultiplicand in TEMP, imultiplier in MDR
+imulf6_reg:
+ width W8, a_sel RA, alu_op SELA, mdr_write, ra_sel AL, jmp do_imul8;
+imulf6_mem:
+ width W8, segment DS, mem_read, ra_sel AL, jmp do_imul8;
+do_imul8:
+ width W8, a_sel RA, alu_op SELA, tmp_wr_en;
+ // 8-bit imultiplication yields a 16-bit result so move the result into
+ // TEMP to later transfer to AX as a 16-bit operation.
+ width W8, a_sel MDR, b_sel TEMP, alu_op IMUL, update_flags ZF OF CF,
+ tmp_wr_en;
+ b_sel TEMP, alu_op SELB, rd_sel_source MICROCODE_RD_SEL, rd_sel AX,
+ next_instruction;
+
+// imultiplicand in TEMP, imultiplier in MDR
+imulf7_reg:
+ a_sel RA, alu_op SELA, mdr_write, ra_sel AX, jmp do_imul16;
+imulf7_mem:
+ segment DS, mem_read, ra_sel AX, jmp do_imul16;
+do_imul16:
+ a_sel RA, alu_op SELA, tmp_wr_en;
+ a_sel MDR, b_sel TEMP, alu_op IMUL, update_flags ZF OF CF,
+ tmp_wr_sel Q_HIGH, tmp_wr_en, rd_sel_source MICROCODE_RD_SEL,
+ rd_sel AX;
+ b_sel TEMP, alu_op SELB, rd_sel_source MICROCODE_RD_SEL, rd_sel DX,
+ next_instruction;
+
+.at 0x6b;
+ mar_write, mar_wr_sel EA, ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem imul6b_reg;
+.auto_address;
+imul6b_reg:
+ a_sel RA, b_sel IMMEDIATE, alu_op IMUL, update_flags ZF OF CF,
+ rd_sel_source MODRM_REG, next_instruction;
+imul6b_mem:
+ segment DS, mem_read;
+ a_sel MDR, b_sel IMMEDIATE, alu_op IMUL, update_flags ZF OF CF,
+ rd_sel_source MODRM_REG, next_instruction;
+
+.at 0x69;
+ mar_write, mar_wr_sel EA, ra_modrm_rm_reg, segment DS, jmp_rm_reg_mem imul6b_reg;
diff --git a/common/CPU/x86/microcode/neg.us b/common/CPU/x86/microcode/neg.us
new file mode 100644
index 00000000..b6db9eac
--- /dev/null
+++ b/common/CPU/x86/microcode/neg.us
@@ -0,0 +1,26 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+negf6_reg:
+ a_sel RA, b_sel IMMEDIATE, immediate 0x0, alu_op SUBREV,
+ rd_sel_source MODRM_RM_REG,
+ update_flags OF SF ZF CF PF AF, width WAUTO, next_instruction;
+negf6_mem:
+ width WAUTO, segment DS, mem_read, ra_modrm_rm_reg;
+ a_sel MDR, b_sel IMMEDIATE, immediate 0x0, alu_op SUBREV,
+ mdr_write, update_flags OF SF ZF CF PF AF, width WAUTO,
+ segment DS, jmp write_complete;
diff --git a/common/CPU/x86/microcode/not.us b/common/CPU/x86/microcode/not.us
new file mode 100644
index 00000000..cde9b329
--- /dev/null
+++ b/common/CPU/x86/microcode/not.us
@@ -0,0 +1,26 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+notf6_reg:
+ a_sel RA, b_sel IMMEDIATE, immediate 0x0, alu_op NOT,
+ rd_sel_source MODRM_RM_REG,
+ update_flags OF SF ZF CF PF AF, width WAUTO, next_instruction;
+notf6_mem:
+ width WAUTO, segment DS, mem_read, ra_modrm_rm_reg;
+ a_sel MDR, b_sel IMMEDIATE, immediate 0x0, alu_op NOT,
+ mdr_write, update_flags OF SF ZF CF PF AF, width WAUTO,
+ segment DS, jmp write_complete;
diff --git a/common/CPU/x86/microcode/or.us b/common/CPU/x86/microcode/or.us
new file mode 100644
index 00000000..8c846a59
--- /dev/null
+++ b/common/CPU/x86/microcode/or.us
@@ -0,0 +1,24 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+#include "arithmetic.us"
+
+ARITH_REGMEM_REG(0x08, 0x09, OR, OF SF ZF CF PF)
+ARITH_REG_REGMEM(0x0a, 0x0b, OR, OF SF ZF CF PF)
+ARITH_REGMEM_A(0x0c, 0x0d, OR, OF SF ZF CF PF)
+ARITH_80_81(OR, OF SF ZF CF PF)
+ARITH_83(OR, OF SF ZF CF PF)
diff --git a/common/CPU/x86/microcode/pop.us b/common/CPU/x86/microcode/pop.us
new file mode 100644
index 00000000..a95dee42
--- /dev/null
+++ b/common/CPU/x86/microcode/pop.us
@@ -0,0 +1,85 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+pop8f_reg:
+ a_sel RA, alu_op SELA, mar_wr_sel Q, mar_write,
+ segment_force, segment SS, jmp pop8f_reg_restore;
+pop8f_mem:
+ a_sel RA, alu_op SELA, mar_wr_sel Q, mar_write,
+ segment_force, segment SS, jmp pop8f_mem_restore;
+pop8f_reg_restore:
+ segment_force, segment SS, mem_read, ra_sel SP;
+ a_sel RA, b_sel IMMEDIATE, immediate 0x2, alu_op ADD,
+ rd_sel SP, rd_sel_source MICROCODE_RD_SEL;
+ a_sel MDR, alu_op SELA, rd_sel_source MODRM_RM_REG,
+ next_instruction;
+pop8f_mem_restore:
+ segment_force, segment SS, mem_read, ra_sel SP;
+ a_sel RA, b_sel IMMEDIATE, immediate 0x2, alu_op ADD,
+ rd_sel SP, rd_sel_source MICROCODE_RD_SEL;
+ mar_write, mar_wr_sel EA, segment DS, jmp write_16_complete;
+
+#define POP_GPR(opcode, reg) \
+.at opcode; \
+ ra_sel SP, jmp pop_gpr ## reg; \
+.auto_address; \
+pop_gpr ## reg: \
+ a_sel RA, alu_op SELA, mar_wr_sel Q, mar_write, \
+ segment_force, segment SS; \
+ segment_force, segment SS, mem_read, a_sel MAR, b_sel IMMEDIATE, \
+ immediate 0x2, alu_op ADD, rd_sel SP, \
+ rd_sel_source MICROCODE_RD_SEL; \
+ a_sel MDR, alu_op SELA, rd_sel reg, \
+ rd_sel_source MICROCODE_RD_SEL, next_instruction;
+
+#define POP_SR(opcode, reg) \
+.at opcode; \
+ ra_sel SP, jmp pop_sr ## reg; \
+.auto_address; \
+pop_sr ## reg: \
+ a_sel RA, alu_op SELA, mar_wr_sel Q, mar_write, \
+ segment_force, segment SS; \
+ segment_force, segment SS, mem_read, a_sel MAR, b_sel IMMEDIATE, \
+ immediate 0x2, alu_op ADD, rd_sel SP, \
+ rd_sel_source MICROCODE_RD_SEL; \
+ a_sel MDR, alu_op SELA, segment_force, segment reg, \
+ segment_wr_en, ext_int_inhibit, next_instruction;
+
+POP_SR(0x07, ES)
+POP_SR(0x17, SS)
+POP_SR(0x1f, DS)
+
+POP_GPR(0x58, AX)
+POP_GPR(0x59, CX)
+POP_GPR(0x5a, DX)
+POP_GPR(0x5b, BX)
+POP_GPR(0x5c, SP)
+POP_GPR(0x5d, BP)
+POP_GPR(0x5e, SI)
+POP_GPR(0x5f, DI)
+
+// popf
+.at 0x9d;
+ ra_sel SP, jmp popf;
+.auto_address;
+popf:
+ alu_op SELA, mar_wr_sel Q, mar_write, segment_force, segment SS;
+ segment_force, segment SS, mem_read,
+ a_sel MAR, b_sel IMMEDIATE, immediate 0x2, alu_op ADD,
+ rd_sel SP, rd_sel_source MICROCODE_RD_SEL;
+ a_sel MDR, alu_op SETFLAGSA, update_flags CF PF AF ZF SF TF IF DF OF,
+ ext_int_inhibit, next_instruction;
diff --git a/common/CPU/x86/microcode/push.us b/common/CPU/x86/microcode/push.us
new file mode 100644
index 00000000..4b495369
--- /dev/null
+++ b/common/CPU/x86/microcode/push.us
@@ -0,0 +1,194 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+pushff_reg:
+ a_sel RA, b_sel IMMEDIATE, immediate 0x2, alu_op SUB, rd_sel SP,
+ rd_sel_source MICROCODE_RD_SEL, mar_write, mar_wr_sel Q,
+ jmp pushff_reg_save, ra_modrm_rm_reg, segment DS;
+pushff_mem:
+ segment DS, mem_read, jmp pushff_mem_save, ra_sel SP;
+pushff_reg_save:
+ a_sel RA, alu_op SELA, mdr_write, segment_force, segment SS;
+ segment_force, segment SS, mem_write, a_sel MAR, next_instruction;
+pushff_mem_save:
+ a_sel RA, b_sel IMMEDIATE, immediate 0x2, alu_op SUB, rd_sel SP,
+ rd_sel_source MICROCODE_RD_SEL, mar_write, mar_wr_sel Q,
+ segment_force, segment SS;
+ segment_force, segment SS, mem_write, a_sel MAR, alu_op SELA,
+ next_instruction;
+
+#define PUSH_GPR(opcode, reg) \
+.at opcode; \
+ ra_sel reg, jmp push_gpr;
+
+#define PUSH_SR(opcode, reg) \
+.at opcode; \
+ segment_force, segment reg, jmp push_sr;
+
+PUSH_SR(0x06, ES)
+PUSH_SR(0x0e, CS)
+PUSH_SR(0x16, SS)
+PUSH_SR(0x1e, DS)
+
+PUSH_GPR(0x50, AX)
+PUSH_GPR(0x51, CX)
+PUSH_GPR(0x52, DX)
+PUSH_GPR(0x53, BX)
+PUSH_GPR(0x55, BP)
+PUSH_GPR(0x56, SI)
+PUSH_GPR(0x57, DI)
+
+.auto_address;
+push_gpr:
+ a_sel RA, alu_op SELA, mdr_write, ra_sel SP;
+ a_sel RA, b_sel IMMEDIATE, immediate 0x2, alu_op SUB, rd_sel SP,
+ mar_write, mar_wr_sel Q, segment_force, segment SS;
+ segment_force, segment SS, mem_write, a_sel MAR, rd_sel SP,
+ rd_sel_source MICROCODE_RD_SEL, next_instruction;
+
+// push SP, emulate broken 8086 behaviour: the decremented value gets pushed
+// rather than the original value
+.at 0x54;
+ ra_sel SP, jmp push_sp;
+.auto_address;
+push_sp:
+ a_sel RA, b_sel IMMEDIATE, immediate 0x2, alu_op SUB, rd_sel SP,
+ mar_write, mar_wr_sel Q, mdr_write, segment_force, segment SS;
+ segment_force, segment SS, mem_write, a_sel MAR, rd_sel SP,
+ rd_sel_source MICROCODE_RD_SEL, next_instruction;
+
+push_sr:
+ b_sel SR, alu_op SELB, mdr_write, ra_sel SP;
+ a_sel RA, b_sel IMMEDIATE, immediate 0x2, alu_op SUB, rd_sel SP,
+ mar_write, mar_wr_sel Q, segment_force, segment SS;
+ segment_force, segment SS, mem_write, a_sel MAR, rd_sel SP,
+ rd_sel_source MICROCODE_RD_SEL, next_instruction;
+
+.at 0x68;
+ ra_sel SP, jmp push_immed16;
+.auto_address;
+push_immed16:
+ a_sel RA, b_sel IMMEDIATE, immediate 0x2, alu_op SUB, mar_write,
+ mar_wr_sel Q, rd_sel SP, rd_sel_source MICROCODE_RD_SEL;
+ b_sel IMMEDIATE, alu_op SELB, mdr_write, segment_force, segment SS;
+ segment_force, segment SS, mem_write, next_instruction;
+
+.at 0x6a;
+ ra_sel SP, jmp push_immed8;
+.auto_address;
+push_immed8:
+ a_sel RA, b_sel IMMEDIATE, immediate 0x2, alu_op SUB, mar_write,
+ mar_wr_sel Q, rd_sel SP, rd_sel_source MICROCODE_RD_SEL;
+ b_sel IMMEDIATE, alu_op SELB, mdr_write, segment_force, segment SS;
+ segment_force, segment SS, mem_write, next_instruction;
+
+.at 0x9c;
+ alu_op GETFLAGS, mdr_write, ra_sel SP, jmp pushf;
+.auto_address;
+pushf:
+ a_sel RA, b_sel IMMEDIATE, immediate 0x2, alu_op SUB,
+ mar_wr_sel Q, mar_write, segment_force, segment SS,
+ rd_sel SP, rd_sel_source MICROCODE_RD_SEL;
+ segment_force, segment SS, mem_write, next_instruction;
+
+.at 0x60;
+ ra_sel SP, jmp pusha;
+.auto_address;
+pusha:
+ a_sel RA, ra_sel AX, b_sel IMMEDIATE, immediate 0x2, alu_op SUB,
+ mar_write, mar_wr_sel Q;
+ a_sel RA, alu_op SELA, mdr_write, segment_force, segment SS;
+ segment_force, segment SS, mem_write,
+ ra_sel CX, a_sel MAR, b_sel IMMEDIATE, immediate 0x2, alu_op SUB,
+ mar_wr_sel Q, mar_write;
+
+ a_sel RA, alu_op SELA, mdr_write, segment_force, segment SS;
+ segment_force, segment SS, mem_write,
+ ra_sel DX, a_sel MAR, b_sel IMMEDIATE, immediate 0x2, alu_op SUB,
+ mar_wr_sel Q, mar_write;
+
+ a_sel RA, alu_op SELA, mdr_write, segment_force, segment SS;
+ segment_force, segment SS, mem_write,
+ ra_sel BX, a_sel MAR, b_sel IMMEDIATE, immediate 0x2, alu_op SUB,
+ mar_wr_sel Q, mar_write;
+
+ a_sel RA, alu_op SELA, mdr_write, segment_force, segment SS;
+ segment_force, segment SS, mem_write,
+ ra_sel SP, a_sel MAR, b_sel IMMEDIATE, immediate 0x2, alu_op SUB,
+ mar_wr_sel Q, mar_write;
+
+ a_sel RA, alu_op SELA, mdr_write, segment_force, segment SS;
+ segment_force, segment SS, mem_write,
+ ra_sel BP, a_sel MAR, b_sel IMMEDIATE, immediate 0x2, alu_op SUB,
+ mar_wr_sel Q, mar_write;
+
+ a_sel RA, alu_op SELA, mdr_write, segment_force, segment SS;
+ segment_force, segment SS, mem_write,
+ ra_sel SI, a_sel MAR, b_sel IMMEDIATE, immediate 0x2, alu_op SUB,
+ mar_wr_sel Q, mar_write;
+
+ a_sel RA, alu_op SELA, mdr_write, segment_force, segment SS;
+ segment_force, segment SS, mem_write,
+ ra_sel DI, a_sel MAR, b_sel IMMEDIATE, immediate 0x2, alu_op SUB,
+ mar_wr_sel Q, mar_write;
+ a_sel RA, alu_op SELA, mdr_write, segment_force, segment SS;
+ segment_force, segment SS, mem_write,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel SP, a_sel MAR, alu_op SELA,
+ next_instruction;
+
+.at 0x61;
+ ra_sel SP, jmp popa;
+.auto_address;
+popa:
+ a_sel RA, alu_op SELA, mar_wr_sel Q, mar_write, segment_force,
+ segment SS;
+
+ segment_force, segment SS, mem_read,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel DI, a_sel MDR;
+ a_sel MAR, b_sel IMMEDIATE, immediate 0x2, alu_op ADD, mar_wr_sel Q,
+ mar_write, segment_force, segment SS;
+
+ segment_force, segment SS, mem_read,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel SI, a_sel MDR;
+ a_sel MAR, b_sel IMMEDIATE, immediate 0x2, alu_op ADD, mar_wr_sel Q,
+ mar_write, segment_force, segment SS;
+
+ segment_force, segment SS, mem_read,
+ // Skip over SP
+ rd_sel_source MICROCODE_RD_SEL, rd_sel BP, a_sel MDR;
+ a_sel MAR, b_sel IMMEDIATE, immediate 0x4, alu_op ADD, mar_wr_sel Q,
+ mar_write, segment_force, segment SS;
+
+ segment_force, segment SS, mem_read,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel BX, a_sel MDR;
+ a_sel MAR, b_sel IMMEDIATE, immediate 0x2, alu_op ADD, mar_wr_sel Q,
+ mar_write, segment_force, segment SS;
+
+ segment_force, segment SS, mem_read,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel DX, a_sel MDR;
+ a_sel MAR, b_sel IMMEDIATE, immediate 0x2, alu_op ADD, mar_wr_sel Q,
+ mar_write, segment_force, segment SS;
+
+ segment_force, segment SS, mem_read,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel CX, a_sel MDR;
+ a_sel MAR, b_sel IMMEDIATE, immediate 0x2, alu_op ADD, mar_wr_sel Q,
+ mar_write, segment_force, segment SS;
+
+ segment_force, segment SS, mem_read,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel AX, a_sel MDR;
+ a_sel MAR, b_sel IMMEDIATE, immediate 0x2, alu_op ADD,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel SP, next_instruction;
diff --git a/common/CPU/x86/microcode/rcl.us b/common/CPU/x86/microcode/rcl.us
new file mode 100644
index 00000000..bc27ff97
--- /dev/null
+++ b/common/CPU/x86/microcode/rcl.us
@@ -0,0 +1,23 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+#include "shift.us"
+
+SHIFT1(RCL, OF CF)
+SHIFTN(RCL, CF)
+SHIFTN_IMM8(RCL, CF)
+SHIFTN_IMM16(RCL, CF)
diff --git a/common/CPU/x86/microcode/rcr.us b/common/CPU/x86/microcode/rcr.us
new file mode 100644
index 00000000..0a6139bc
--- /dev/null
+++ b/common/CPU/x86/microcode/rcr.us
@@ -0,0 +1,23 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+#include "shift.us"
+
+SHIFT1(RCR, OF CF)
+SHIFTN(RCR, CF)
+SHIFTN_IMM8(RCR, CF)
+SHIFTN_IMM16(RCR, CF)
diff --git a/common/CPU/x86/microcode/ret.us b/common/CPU/x86/microcode/ret.us
new file mode 100644
index 00000000..04154292
--- /dev/null
+++ b/common/CPU/x86/microcode/ret.us
@@ -0,0 +1,92 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+.at 0xc3;
+ ra_sel SP, jmp retc3;
+.auto_address;
+retc3:
+ a_sel RA, alu_op SELA, mar_write, mar_wr_sel Q, segment SS,
+ segment_force;
+ segment SS, segment_force, mem_read, a_sel MAR, b_sel IMMEDIATE,
+ immediate 0x2, alu_op ADD, rd_sel_source MICROCODE_RD_SEL,
+ rd_sel SP;
+ a_sel MDR, alu_op SELA, load_ip, next_instruction;
+
+.at 0xc2;
+ ra_sel SP, jmp retc2;
+.auto_address;
+retc2:
+ a_sel RA, alu_op SELA, mar_write, mar_wr_sel Q, segment SS,
+ segment_force;
+ segment SS, segment_force, mem_read, a_sel MAR, b_sel IMMEDIATE,
+ immediate 0x2, alu_op ADD, rd_sel_source MICROCODE_RD_SEL,
+ rd_sel SP;
+ a_sel MDR, alu_op SELA, load_ip, ra_sel SP;
+ a_sel RA, b_sel IMMEDIATE, alu_op ADD, rd_sel_source
+ MICROCODE_RD_SEL, rd_sel SP, next_instruction;
+
+.at 0xcb;
+ ra_sel SP, jmp retcb;
+.auto_address;
+retcb:
+ a_sel RA, alu_op SELA, mar_write, mar_wr_sel Q, segment SS,
+ segment_force;
+ segment SS, segment_force, mem_read, a_sel MAR, b_sel IMMEDIATE,
+ immediate 0x2, alu_op ADD, mar_wr_sel Q, mar_write;
+ a_sel MDR, alu_op SELA, load_ip, segment_force, segment SS;
+ segment SS, segment_force, mem_read, a_sel MAR, b_sel IMMEDIATE,
+ immediate 0x2, alu_op ADD, rd_sel_source MICROCODE_RD_SEL,
+ rd_sel SP;
+ a_sel MDR, alu_op SELA, segment_force, segment CS,
+ segment_wr_en, next_instruction;
+
+.at 0xca;
+ ra_sel SP, jmp retca;
+.auto_address;
+retca:
+ a_sel RA, alu_op SELA, mar_write, mar_wr_sel Q, segment SS,
+ segment_force;
+ segment SS, segment_force, mem_read, a_sel MAR, b_sel IMMEDIATE,
+ immediate 0x2, alu_op ADD, mar_wr_sel Q, mar_write;
+ a_sel MDR, alu_op SELA, load_ip, segment_force, segment SS;
+ segment SS, segment_force, mem_read, a_sel MAR, b_sel IMMEDIATE,
+ immediate 0x2, alu_op ADD, mar_wr_sel Q, mar_write;
+ a_sel MAR, b_sel IMMEDIATE, alu_op ADD, rd_sel_source MICROCODE_RD_SEL,
+ rd_sel SP;
+ a_sel MDR, alu_op SELA, segment_force, segment CS,
+ segment_wr_en, next_instruction;
+
+// iret
+.at 0xcf;
+ ra_sel SP, jmp retcf;
+.auto_address;
+retcf:
+ a_sel RA, alu_op SELA, mar_write, mar_wr_sel Q, segment SS,
+ segment_force;
+ segment SS, segment_force, mem_read, a_sel MAR, b_sel IMMEDIATE,
+ immediate 0x2, alu_op ADD, mar_wr_sel Q, mar_write;
+ a_sel MDR, alu_op SELA, load_ip, segment_force, segment SS;
+ segment SS, segment_force, mem_read;
+ a_sel MDR, alu_op SELA, segment_force, segment CS,
+ segment_wr_en;
+ a_sel MAR, b_sel IMMEDIATE, immediate 0x2, alu_op ADD,
+ mar_wr_sel Q, mar_write, segment SS, segment_force;
+ segment SS, segment_force, mem_read, a_sel MDR, alu_op SETFLAGSA,
+ update_flags CF PF AF ZF SF TF IF DF OF;
+ a_sel MAR, b_sel IMMEDIATE, immediate 0x2, alu_op ADD,
+ rd_sel SP, rd_sel_source MICROCODE_RD_SEL,
+ ext_int_inhibit, next_instruction;
diff --git a/common/CPU/x86/microcode/rol.us b/common/CPU/x86/microcode/rol.us
new file mode 100644
index 00000000..8136a8b8
--- /dev/null
+++ b/common/CPU/x86/microcode/rol.us
@@ -0,0 +1,23 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+#include "shift.us"
+
+SHIFT1(ROL, OF CF)
+SHIFTN(ROL, CF)
+SHIFTN_IMM8(ROL, CF)
+SHIFTN_IMM16(ROL, CF)
diff --git a/common/CPU/x86/microcode/ror.us b/common/CPU/x86/microcode/ror.us
new file mode 100644
index 00000000..386cf8ca
--- /dev/null
+++ b/common/CPU/x86/microcode/ror.us
@@ -0,0 +1,23 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+#include "shift.us"
+
+SHIFT1(ROR, OF CF)
+SHIFTN(ROR, CF)
+SHIFTN_IMM8(ROR, CF)
+SHIFTN_IMM16(ROR, CF)
diff --git a/common/CPU/x86/microcode/sar.us b/common/CPU/x86/microcode/sar.us
new file mode 100644
index 00000000..bb711b92
--- /dev/null
+++ b/common/CPU/x86/microcode/sar.us
@@ -0,0 +1,23 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+#include "shift.us"
+
+SHIFT1(SAR, OF CF ZF PF SF)
+SHIFTN(SAR, CF ZF PF SF)
+SHIFTN_IMM8(SAR, CF ZF PF SF)
+SHIFTN_IMM16(SAR, CF ZF PF SF)
diff --git a/common/CPU/x86/microcode/sbb.us b/common/CPU/x86/microcode/sbb.us
new file mode 100644
index 00000000..915b6c7c
--- /dev/null
+++ b/common/CPU/x86/microcode/sbb.us
@@ -0,0 +1,24 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+#include "arithmetic.us"
+
+ARITH_REGMEM_REG(0x18, 0x19, SBB, OF SF ZF AF CF PF)
+ARITH_REG_REGMEM(0x1a, 0x1b, SBBREV, OF SF ZF AF CF PF)
+ARITH_REGMEM_A(0x1c, 0x1d, SBB, OF SF ZF AF CF PF)
+ARITH_80_81(SBB, OF SF ZF AF CF PF)
+ARITH_83(SBB, OF SF ZF AF CF PF)
diff --git a/common/CPU/x86/microcode/scas.us b/common/CPU/x86/microcode/scas.us
new file mode 100644
index 00000000..4efdfd97
--- /dev/null
+++ b/common/CPU/x86/microcode/scas.us
@@ -0,0 +1,68 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+.at 0xae;
+ jmp scasb, ra_sel DI;
+
+.auto_address;
+scasb:
+ ra_sel DI, a_sel RA, alu_op SELA, mar_wr_sel Q, mar_write, rb_cl,
+ jmp_if_not_rep scasb_no_rep;
+scasb_rep_loop:
+ ra_sel CX, jmp_rb_zero scasb_done;
+ ra_sel DI, a_sel RA, b_sel IMMEDIATE, immediate 0x1, alu_op SUB,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel CX, segment ES, segment_force;
+scasb_no_rep:
+ width W8, segment ES, segment_force, mem_read, ra_sel AL,
+ a_sel RA, alu_op SELA, tmp_wr_en;
+ width W8, a_sel MDR, b_sel TEMP, alu_op SUBREV,
+ update_flags OF SF ZF CF PF AF, jmp_if_not_rep scasb_done_no_rep;
+ a_sel MAR, b_sel IMMEDIATE, immediate 0x1, alu_op NEXT,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel DI, mar_write, mar_wr_sel Q,
+ rb_cl, ext_int_yield, jmp_if_rep_not_complete scasb_rep_loop,
+ segment ES, segment_force;
+scasb_done:
+ next_instruction;
+scasb_done_no_rep:
+ a_sel MAR, b_sel IMMEDIATE, immediate 0x1, alu_op NEXT,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel DI, next_instruction;
+
+.at 0xaf;
+ jmp scasw, ra_sel DI;
+
+.auto_address;
+scasw:
+ ra_sel DI, a_sel RA, alu_op SELA, mar_wr_sel Q, mar_write,
+ rb_cl, jmp_if_not_rep scasw_no_rep;
+scasw_rep_loop:
+ ra_sel CX, jmp_rb_zero scasw_done;
+ ra_sel DI, a_sel RA, b_sel IMMEDIATE, immediate 0x1, alu_op SUB,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel CX, segment ES, segment_force;
+scasw_no_rep:
+ segment ES, segment_force, mem_read, ra_sel AX, a_sel RA, alu_op SELA,
+ tmp_wr_en;
+ a_sel MDR, b_sel TEMP, alu_op SUBREV, update_flags OF SF ZF CF PF AF,
+ jmp_if_not_rep scasw_done_no_rep;
+ a_sel MAR, b_sel IMMEDIATE, immediate 0x2, alu_op NEXT,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel DI, mar_write, mar_wr_sel Q,
+ rb_cl, ext_int_yield, jmp_if_rep_not_complete scasw_rep_loop,
+ segment ES, segment_force;
+scasw_done:
+ next_instruction;
+scasw_done_no_rep:
+ a_sel MAR, b_sel IMMEDIATE, immediate 0x2, alu_op NEXT,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel DI, next_instruction;
diff --git a/common/CPU/x86/microcode/shift.us b/common/CPU/x86/microcode/shift.us
new file mode 100644
index 00000000..f6f5d7a3
--- /dev/null
+++ b/common/CPU/x86/microcode/shift.us
@@ -0,0 +1,63 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+#define SHIFT1(alu_func, flags) \
+.auto_address; \
+alu_func ## d0_d1_reg: \
+ a_sel RA, b_sel IMMEDIATE, immediate 0x1, alu_op alu_func, \
+ rd_sel_source MODRM_RM_REG, update_flags flags, \
+ width WAUTO, next_instruction; \
+alu_func ## d0_d1_mem: \
+ segment DS, mem_read, width WAUTO; \
+ width WAUTO, a_sel MDR, b_sel IMMEDIATE, immediate 0x1, alu_op alu_func, \
+ mdr_write, update_flags flags, segment DS, jmp write_complete;
+
+// Variable shifts first write the number of shifts into the temporary
+// register, then when processing, the ALU will perform a subtraction of the
+// count (which is an input to the ALU), and output the decremented value
+// along with a single bit-shifted value, stalling until complete. The
+// temporary register needs to be written each cycle, as does the result.
+
+#define SHIFTN(alu_func, flags) \
+alu_func ## d2_d3: \
+ ra_modrm_rm_reg, b_sel RB, alu_op SELB, tmp_wr_en, width WAUTO, \
+ segment DS, jmp_rm_reg_mem alu_func ## d2_d3_reg; \
+alu_func ## d2_d3_reg: \
+ a_sel RA, b_sel RB, alu_op alu_func, rd_sel_source MODRM_RM_REG, \
+ update_flags flags, width WAUTO, tmp_wr_sel Q_HIGH, \
+ tmp_wr_en, next_instruction, ra_modrm_rm_reg; \
+alu_func ## d2_d3_mem: \
+ segment DS, mem_read, width WAUTO, rb_cl; \
+ width WAUTO, a_sel MDR, b_sel RB, alu_op alu_func, mdr_write, \
+ update_flags flags, segment DS, tmp_wr_sel Q_HIGH, tmp_wr_en, \
+ jmp write_complete;
+
+#define SHIFTN_IMM8(alu_func, flags) \
+alu_func ## c0_reg: \
+ a_sel RA, b_sel IMMEDIATE, alu_op alu_func, rd_sel_source MODRM_RM_REG, \
+ update_flags flags, width WAUTO, tmp_wr_sel Q_HIGH, \
+ tmp_wr_en, next_instruction, ra_modrm_rm_reg; \
+alu_func ## c0_mem: \
+ segment DS, mem_read, width WAUTO; \
+ width WAUTO, a_sel MDR, b_sel IMMEDIATE, alu_op alu_func, mdr_write, \
+ update_flags flags, segment DS, tmp_wr_sel Q_HIGH, tmp_wr_en, \
+ jmp write_complete;
+
+#define SHIFTN_IMM16(alu_func, flags) \
+alu_func ## c1: \
+ tmp_wr_en, alu_op SELB, b_sel IMMEDIATE, ra_modrm_rm_reg, segment DS, \
+ jmp_rm_reg_mem alu_func ## c0_reg;
diff --git a/common/CPU/x86/microcode/shl.us b/common/CPU/x86/microcode/shl.us
new file mode 100644
index 00000000..830cb741
--- /dev/null
+++ b/common/CPU/x86/microcode/shl.us
@@ -0,0 +1,23 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+#include "shift.us"
+
+SHIFT1(SHL, OF CF ZF PF SF)
+SHIFTN(SHL, CF ZF PF SF)
+SHIFTN_IMM8(SHL, CF ZF PF SF)
+SHIFTN_IMM16(SHL, CF ZF PF SF)
diff --git a/common/CPU/x86/microcode/shr.us b/common/CPU/x86/microcode/shr.us
new file mode 100644
index 00000000..86b1ac8b
--- /dev/null
+++ b/common/CPU/x86/microcode/shr.us
@@ -0,0 +1,23 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+#include "shift.us"
+
+SHIFT1(SHR, OF CF ZF PF SF)
+SHIFTN(SHR, CF ZF PF SF)
+SHIFTN_IMM8(SHR, CF ZF PF SF)
+SHIFTN_IMM16(SHR, CF ZF PF SF)
diff --git a/common/CPU/x86/microcode/stos.us b/common/CPU/x86/microcode/stos.us
new file mode 100644
index 00000000..4352305d
--- /dev/null
+++ b/common/CPU/x86/microcode/stos.us
@@ -0,0 +1,58 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+.at 0xaa;
+ width W8, ra_sel AL, jmp stosb;
+
+.auto_address;
+stosb:
+ width W8, a_sel RA, alu_op SELA, mdr_write;
+ ra_sel DI, rb_cl, jmp_if_not_rep stosb_no_rep;
+stosb_rep_loop:
+ ra_sel CX, jmp_rb_zero stosb_done;
+ ra_sel DI, a_sel RA, b_sel IMMEDIATE, immediate 0x1, alu_op SUB,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel CX;
+stosb_no_rep:
+ ra_sel DI, a_sel RA, alu_op SELA, mar_wr_sel Q, mar_write;
+ a_sel RA, b_sel IMMEDIATE, immediate 0x1, alu_op NEXT,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel DI;
+ width W8, ra_sel AL;
+ width W8, alu_op SELA, mdr_write, segment ES, segment_force;
+ width W8, segment ES, segment_force, mem_write, jmp_if_not_rep stosb_done;
+ rb_cl, ext_int_yield, jmp stosb_rep_loop;
+stosb_done:
+ next_instruction;
+
+.at 0xab;
+ ra_sel AX, jmp stosw;
+
+.auto_address;
+stosw:
+ a_sel RA, alu_op SELA, mdr_write,
+ ra_sel DI, rb_cl, jmp_if_not_rep stosw_no_rep;
+stosw_rep_loop:
+ ra_sel CX, jmp_rb_zero stosw_done;
+ ra_sel DI, a_sel RA, b_sel IMMEDIATE, immediate 0x1, alu_op SUB,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel CX;
+stosw_no_rep:
+ ra_sel DI, a_sel RA, alu_op SELA, mar_wr_sel Q, mar_write;
+ a_sel RA, b_sel IMMEDIATE, immediate 0x2, alu_op NEXT,
+ rd_sel_source MICROCODE_RD_SEL, rd_sel DI, segment ES, segment_force;
+ segment ES, segment_force, mem_write, jmp_if_not_rep stosw_done;
+ rb_cl, ext_int_yield, jmp stosw_rep_loop;
+stosw_done:
+ next_instruction;
diff --git a/common/CPU/x86/microcode/sub.us b/common/CPU/x86/microcode/sub.us
new file mode 100644
index 00000000..6599537b
--- /dev/null
+++ b/common/CPU/x86/microcode/sub.us
@@ -0,0 +1,24 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+#include "arithmetic.us"
+
+ARITH_REGMEM_REG(0x28, 0x29, SUB, OF SF ZF AF CF PF)
+ARITH_REG_REGMEM(0x2a, 0x2b, SUBREV, OF SF ZF AF CF PF)
+ARITH_REGMEM_A(0x2c, 0x2d, SUB, OF SF ZF AF CF PF)
+ARITH_80_81(SUB, OF SF ZF AF CF PF)
+ARITH_83(SUB, OF SF ZF AF CF PF)
diff --git a/common/CPU/x86/microcode/test.us b/common/CPU/x86/microcode/test.us
new file mode 100644
index 00000000..bc32d11c
--- /dev/null
+++ b/common/CPU/x86/microcode/test.us
@@ -0,0 +1,23 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+#include "comparison.us"
+
+COMP_REGMEM_REG(0x84, 0x85, AND, OF SF ZF CF PF)
+COMP_REGMEM_A(0xa8, 0xa9, AND, OF SF ZF CF PF)
+COMP_F6(AND, OF SF ZF CF PF)
+COMP_F7(AND, OF SF ZF CF PF)
diff --git a/common/CPU/x86/microcode/wait.us b/common/CPU/x86/microcode/wait.us
new file mode 100644
index 00000000..403cd8be
--- /dev/null
+++ b/common/CPU/x86/microcode/wait.us
@@ -0,0 +1,19 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+.at 0x9b;
+ next_instruction;
diff --git a/common/CPU/x86/microcode/xchg.us b/common/CPU/x86/microcode/xchg.us
new file mode 100644
index 00000000..f381a800
--- /dev/null
+++ b/common/CPU/x86/microcode/xchg.us
@@ -0,0 +1,63 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+.at 0x86;
+ width WAUTO, mar_write, mar_wr_sel EA, ra_modrm_rm_reg,
+ jmp_rm_reg_mem xchg86_reg, segment DS;
+.at 0x87;
+ mar_write, mar_wr_sel EA, ra_modrm_rm_reg,
+ jmp_rm_reg_mem xchg86_reg, segment DS;
+.auto_address;
+xchg86_reg:
+ width WAUTO, a_sel RA, alu_op SELA, mar_write, mar_wr_sel Q,
+ jmp xchg86_reg_store;
+xchg86_mem:
+ segment DS, width WAUTO, mem_read;
+ width WAUTO, b_sel RB, alu_op SELB, mar_write, mar_wr_sel Q;
+ // memory value is in MDR, register value is in MAR
+ width WAUTO, a_sel MDR, alu_op SELA, rd_sel_source MODRM_REG;
+ width WAUTO, a_sel MAR, alu_op SELA, mdr_write, mar_wr_sel EA,
+ mar_write, segment DS, jmp write_complete;
+
+xchg86_reg_store:
+ width WAUTO, b_sel RB, alu_op SELB, rd_sel_source MODRM_RM_REG;
+ width WAUTO, a_sel MAR, alu_op SELA, rd_sel_source MODRM_REG,
+ next_instruction;
+
+#define XCHG_REG(opcode, reg) \
+.at opcode; \
+ ra_sel reg, jmp xchg_ ## reg; \
+.auto_address; \
+xchg_ ## reg: \
+ a_sel RA, alu_op SELA, mar_write, mar_wr_sel Q, \
+ ra_sel AX; \
+ a_sel RA, alu_op SELA, rd_sel_source MICROCODE_RD_SEL, \
+ rd_sel reg; \
+ a_sel MAR, alu_op SELA, rd_sel_source MICROCODE_RD_SEL, \
+ rd_sel AX, next_instruction;
+
+// xchg ax, ax
+.at 0x90;
+ next_instruction;
+
+XCHG_REG(0x91, CX)
+XCHG_REG(0x92, DX)
+XCHG_REG(0x93, BX)
+XCHG_REG(0x94, SP)
+XCHG_REG(0x95, BP)
+XCHG_REG(0x96, SI)
+XCHG_REG(0x97, DI)
diff --git a/common/CPU/x86/microcode/xlat.us b/common/CPU/x86/microcode/xlat.us
new file mode 100644
index 00000000..5784980d
--- /dev/null
+++ b/common/CPU/x86/microcode/xlat.us
@@ -0,0 +1,27 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+.at 0xd7;
+ width W8, ra_sel AL, jmp xlat;
+.auto_address;
+xlat:
+ a_sel RA, alu_op SELA, tmp_wr_en, ra_sel BX;
+ a_sel RA, alu_op SELA, mar_wr_sel Q, mar_write;
+ a_sel MAR, b_sel TEMP, alu_op ADD, mar_wr_sel Q, mar_write, segment DS;
+ segment DS, width W8, mem_read,
+ a_sel MDR, alu_op SELA, width W8, rd_sel_source MICROCODE_RD_SEL,
+ rd_sel AL, next_instruction;
diff --git a/common/CPU/x86/microcode/xor.us b/common/CPU/x86/microcode/xor.us
new file mode 100644
index 00000000..ec1f672c
--- /dev/null
+++ b/common/CPU/x86/microcode/xor.us
@@ -0,0 +1,24 @@
+// Copyright Jamie Iles, 2017
+//
+// This file is part of s80x86.
+//
+// s80x86 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.
+//
+// s80x86 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 s80x86. If not, see .
+
+#include "arithmetic.us"
+
+ARITH_REGMEM_REG(0x30, 0x31, XOR, OF SF ZF CF PF)
+ARITH_REG_REGMEM(0x32, 0x33, XOR, OF SF ZF CF PF)
+ARITH_REGMEM_A(0x34, 0x35, XOR, OF SF ZF CF PF)
+ARITH_80_81(XOR, OF SF ZF CF PF)
+ARITH_83(XOR, OF SF ZF CF PF)
diff --git a/common/CPU/z180/alu_log.v b/common/CPU/z180/alu_log.v
new file mode 100644
index 00000000..066ddaa7
--- /dev/null
+++ b/common/CPU/z180/alu_log.v
@@ -0,0 +1,63 @@
+/*******************************************************************************************/
+/** **/
+/** COPYRIGHT (C) 2011, SYSTEMYDE INTERNATIONAL CORPORATION, ALL RIGHTS RESERVED **/
+/** **/
+/** alu logic module Rev 0.0 07/17/2011 **/
+/** **/
+/*******************************************************************************************/
+module alu_log (logic_c, logic_hc, logic_out, alua_in, alub_in, aluop_reg, carry_bit);
+
+ input carry_bit; /* cpu carry flag */
+ input [15:0] alua_in; /* alu a input */
+ input [15:0] alub_in; /* alu b input */
+ input [`AOP_IDX:0] aluop_reg; /* alu operation control */
+ output logic_c; /* alu logic carry result */
+ output logic_hc; /* alu logic half-carry result */
+ output [15:0] logic_out; /* alu logic result */
+
+ /*****************************************************************************************/
+ /* */
+ /* signal declarations */
+ /* */
+ /*****************************************************************************************/
+ reg logic_c; /* logic carry output */
+ reg logic_hc; /* logic half-carry output */
+ reg [15:0] logic_out; /* logic output */
+
+ /*****************************************************************************************/
+ /* */
+ /* alu logic function */
+ /* */
+ /*****************************************************************************************/
+ always @ (aluop_reg or carry_bit) begin
+ casex (aluop_reg)
+ `AOP_CCF: logic_c = !carry_bit;
+ `AOP_SCF: logic_c = 1'b1;
+ default: logic_c = 1'b0;
+ endcase
+ end
+
+ always @ (aluop_reg or carry_bit) begin
+ casex (aluop_reg)
+ `AOP_BAND: logic_hc = 1'b1;
+ `AOP_CCF: logic_hc = carry_bit;
+ default: logic_hc = 1'b0;
+ endcase
+ end
+
+ always @ (aluop_reg or alua_in or alub_in) begin
+ casex (aluop_reg)
+ `AOP_BAND: logic_out = {8'h00, alua_in[7:0] & alub_in[7:0]};
+ `AOP_BOR: logic_out = {8'h00, alua_in[7:0] | alub_in[7:0]};
+ `AOP_BXOR: logic_out = {8'h00, alua_in[7:0] ^ alub_in[7:0]};
+ `AOP_RLD1: logic_out = {8'h00, alub_in[3:0], alua_in[3:0]};
+ `AOP_RLD2: logic_out = {8'h00, alua_in[7:4], alub_in[7:4]};
+ `AOP_RRD1: logic_out = {8'h00, alua_in[3:0], alub_in[7:4]};
+ `AOP_RRD2: logic_out = {8'h00, alua_in[7:4], alub_in[3:0]};
+ `AOP_APAS: logic_out = alua_in;
+ `AOP_PASS: logic_out = alub_in;
+ default: logic_out = 16'h0000;
+ endcase
+ end
+
+ endmodule
\ No newline at end of file
diff --git a/common/CPU/z180/alu_math.v b/common/CPU/z180/alu_math.v
new file mode 100644
index 00000000..870eb8fe
--- /dev/null
+++ b/common/CPU/z180/alu_math.v
@@ -0,0 +1,135 @@
+/*******************************************************************************************/
+/** **/
+/** COPYRIGHT (C) 2011, SYSTEMYDE INTERNATIONAL CORPORATION, ALL RIGHTS RESERVED **/
+/** **/
+/** alu math module Rev 0.0 07/29/2011 **/
+/** **/
+/*******************************************************************************************/
+module alu_math (adder_c, adder_hc, adder_out, adder_ov, alua_in, alub_in, aluop_reg,
+ carry_bit, carry_daa, daa_op, word_op);
+
+ input carry_bit; /* carry flag */
+ input carry_daa; /* carry for daa */
+ input daa_op; /* daa operation */
+ input word_op; /* word operation */
+ input [15:0] alua_in; /* alu a input */
+ input [15:0] alub_in; /* alu b input */
+ input [`AOP_IDX:0] aluop_reg; /* alu operation control subset */
+ output adder_c; /* alu math carry result */
+ output adder_hc; /* alu math half-carry result */
+ output adder_ov; /* alu math overflow result */
+ output [15:0] adder_out; /* alu math result */
+
+ /*****************************************************************************************/
+ /* */
+ /* signal declarations */
+ /* */
+ /*****************************************************************************************/
+ wire adder_c; /* alu math carry out */
+ wire adder_hc; /* alu math half-carry out */
+ wire [15:8] bsign_ext; /* alu b sign extend */
+ wire [15:0] adder_out; /* alu math out */
+
+ reg alu_cin; /* alu math carry in */
+ reg adder_ov; /* alu math overflow out */
+ reg [4:0] alu0_out; /* alu math nibble 0 */
+ reg [4:0] alu1_out; /* alu math nibble 1 */
+ reg [4:0] alu2_out; /* alu math nibble 2 */
+ reg [4:0] alu3_out; /* alu math nibble 3 */
+
+ /*****************************************************************************************/
+ /* */
+ /* alu math carry input, sign extend */
+ /* */
+ /*****************************************************************************************/
+ always @ (aluop_reg or carry_bit) begin
+ casex (aluop_reg) //synopsys parallel_case
+ `AOP_ADC,
+ `AOP_BADC,
+ `AOP_SBC,
+ `AOP_BSBC: alu_cin = carry_bit;
+ default: alu_cin = 1'b0;
+ endcase
+ end
+
+ assign bsign_ext = {alub_in[7], alub_in[7], alub_in[7], alub_in[7],
+ alub_in[7], alub_in[7], alub_in[7], alub_in[7]};
+
+ /*****************************************************************************************/
+ /* */
+ /* alu math function unit */
+ /* */
+ /*****************************************************************************************/
+ always @ (aluop_reg or alua_in or alub_in or alu_cin) begin
+ casex (aluop_reg) //synopsys parallel_case
+ `AOP_SUB,
+ `AOP_BSUB,
+ `AOP_SBC,
+ `AOP_BSBC: alu0_out = alua_in[3:0] - alub_in[3:0] - alu_cin;
+ default: alu0_out = alua_in[3:0] + alub_in[3:0] + alu_cin;
+ endcase
+ end
+
+ always @ (aluop_reg or alua_in or alub_in or alu0_out) begin
+ casex (aluop_reg) //synopsys parallel_case
+ `AOP_SUB,
+ `AOP_BSUB,
+ `AOP_SBC,
+ `AOP_BSBC: alu1_out = alua_in[7:4] - alub_in[7:4] - alu0_out[4];
+ default: alu1_out = alua_in[7:4] + alub_in[7:4] + alu0_out[4];
+ endcase
+ end
+
+ always @ (aluop_reg or alua_in or alub_in or alu1_out or bsign_ext) begin
+ casex (aluop_reg) //synopsys parallel_case
+ `AOP_ADS: alu2_out = alua_in[11:8] + bsign_ext[11:8] + alu1_out[4];
+ `AOP_SUB,
+ `AOP_BSUB,
+ `AOP_SBC,
+ `AOP_BSBC: alu2_out = alua_in[11:8] - alub_in[11:8] - alu1_out[4];
+ default: alu2_out = alua_in[11:8] + alub_in[11:8] + alu1_out[4];
+ endcase
+ end
+
+ always @ (aluop_reg or alua_in or alub_in or alu2_out or bsign_ext) begin
+ casex (aluop_reg) //synopsys parallel_case
+ `AOP_ADS: alu3_out = alua_in[15:12] + bsign_ext[15:12] + alu2_out[4];
+ `AOP_SUB,
+ `AOP_BSUB,
+ `AOP_SBC,
+ `AOP_BSBC: alu3_out = alua_in[15:12] - alub_in[15:12] - alu2_out[4];
+ default: alu3_out = alua_in[15:12] + alub_in[15:12] + alu2_out[4];
+ endcase
+ end
+
+ assign adder_out = {alu3_out[3:0], alu2_out[3:0], alu1_out[3:0], alu0_out[3:0]};
+
+ /*****************************************************************************************/
+ /* */
+ /* alu math flag generation */
+ /* */
+ /*****************************************************************************************/
+ assign adder_c = (word_op) ? alu3_out[4] :
+ (daa_op) ? carry_daa : alu1_out[4];
+ assign adder_hc = (word_op) ? alu2_out[4] : alu0_out[4];
+
+ always @ (aluop_reg or alua_in or alub_in or alu3_out or alu1_out or bsign_ext) begin
+ casex (aluop_reg) //synopsys parallel_case
+ `AOP_ADC,
+ `AOP_ADD: adder_ov = (!alu3_out[3] && alua_in[15] && alub_in[15]) ||
+ ( alu3_out[3] && !alua_in[15] && !alub_in[15]);
+ `AOP_BADC,
+ `AOP_BADD,
+ `AOP_BDEC: adder_ov = (!alu1_out[3] && alua_in[7] && alub_in[7]) ||
+ ( alu1_out[3] && !alua_in[7] && !alub_in[7]);
+ `AOP_SBC,
+ `AOP_SUB: adder_ov = (!alu3_out[3] && alua_in[15] && !alub_in[15]) ||
+ ( alu3_out[3] && !alua_in[15] && alub_in[15]);
+ `AOP_BSBC,
+ `AOP_BSUB: adder_ov = (!alu1_out[3] && alua_in[7] && !alub_in[7]) ||
+ ( alu1_out[3] && !alua_in[7] && alub_in[7]);
+ default: adder_ov = 1'b0;
+ endcase
+ end
+
+ endmodule
\ No newline at end of file
diff --git a/common/CPU/z180/alu_shft.v b/common/CPU/z180/alu_shft.v
new file mode 100644
index 00000000..426d550b
--- /dev/null
+++ b/common/CPU/z180/alu_shft.v
@@ -0,0 +1,66 @@
+/*******************************************************************************************/
+/** **/
+/** ORIGINAL COPYRIGHT (C) 2011, SYSTEMYDE INTERNATIONAL CORPORATION, ALL RIGHTS RESERVED **/
+/** COPYRIGHT (C) 2012, SERGEY BELYASHOV **/
+/** **/
+/** alu shifter module Rev 0.0 06/13/2012 **/
+/** **/
+/*******************************************************************************************/
+module alu_shft (shft_c, shft_out, alub_in, aluop_reg, carry_bit);
+
+ input carry_bit; /* carry flag input */
+ input [7:0] alub_in; /* alu b input */
+ input [`AOP_IDX:0] aluop_reg; /* alu operation control subset */
+ output shft_c; /* alu shifter carry output */
+ output [7:0] shft_out; /* alu shifter output */
+
+ /*****************************************************************************************/
+ /* */
+ /* signal declarations */
+ /* */
+ /*****************************************************************************************/
+ reg shft_c; /* shifter carry output */
+ reg [7:0] shft_out; /* shifter output */
+
+ /*****************************************************************************************/
+ /* */
+ /* alu shifter function */
+ /* */
+ /*****************************************************************************************/
+ always @ (aluop_reg or alub_in) begin
+ casex (aluop_reg) //synopsys parallel_case
+ `AOP_RL,
+ `AOP_RLA: shft_c = alub_in[7];
+ `AOP_RLC,
+ `AOP_RLCA: shft_c = alub_in[7];
+ `AOP_RR,
+ `AOP_RRA: shft_c = alub_in[0];
+ `AOP_RRC,
+ `AOP_RRCA: shft_c = alub_in[0];
+ `AOP_SLL,
+ `AOP_SLA: shft_c = alub_in[7];
+ `AOP_SRA: shft_c = alub_in[0];
+ `AOP_SRL: shft_c = alub_in[0];
+ default: shft_c = 1'b0;
+ endcase
+ end
+
+ always @ (aluop_reg or alub_in or carry_bit) begin
+ casex (aluop_reg) //synopsys parallel_case
+ `AOP_RL,
+ `AOP_RLA: shft_out = {alub_in[6:0], carry_bit};
+ `AOP_RLC,
+ `AOP_RLCA: shft_out = {alub_in[6:0], alub_in[7]};
+ `AOP_RR,
+ `AOP_RRA: shft_out = {carry_bit, alub_in[7:1]};
+ `AOP_RRC,
+ `AOP_RRCA: shft_out = {alub_in[0], alub_in[7:1]};
+ `AOP_SLA: shft_out = {alub_in[6:0], 1'b0};
+ `AOP_SLL: shft_out = {alub_in[6:0], 1'b1};
+ `AOP_SRA: shft_out = {alub_in[7], alub_in[7:1]};
+ `AOP_SRL: shft_out = {1'b0, alub_in[7:1]};
+ default: shft_out = 8'h00;
+ endcase
+ end
+
+ endmodule
\ No newline at end of file
diff --git a/common/CPU/z180/aluamux.v b/common/CPU/z180/aluamux.v
new file mode 100644
index 00000000..cef83455
--- /dev/null
+++ b/common/CPU/z180/aluamux.v
@@ -0,0 +1,105 @@
+/*******************************************************************************************/
+/** **/
+/** ORIGINAL COPYRIGHT (C) 2011, SYSTEMYDE INTERNATIONAL CORPORATION, ALL RIGHTS RESERVED **/
+/** COPYRIGHT (C) 2012, SERGEY BELYASHOV **/
+/** **/
+/** alu a input multiplexer module Rev 0.0 06/13/2012 **/
+/** **/
+/*******************************************************************************************/
+module aluamux (adda_in, alua_in, alua_reg, aa_reg_out, bit_mask, daa_out, hl_reg_out,
+ ii_reg, int_addr, ix_reg, iy_reg, pc_reg, rr_reg, rst_addr, tmp_reg);
+
+ input [7:0] aa_reg_out; /* a register output */
+ input [7:0] bit_mask; /* bit mask for bit operations */
+ input [7:0] daa_out; /* daa constant */
+ input [7:0] ii_reg; /* i register output */
+ input [7:0] rr_reg; /* r register output */
+ input [7:0] rst_addr; /* restart address */
+ input [15:0] hl_reg_out; /* hl register output */
+ input [15:0] int_addr; /* interrupt address */
+ input [15:0] ix_reg; /* ix register output */
+ input [15:0] iy_reg; /* iy register output */
+ input [15:0] pc_reg; /* pc register output */
+ input [15:0] tmp_reg; /* tmp register output */
+ input [`ALUA_IDX:0] alua_reg; /* pipelined alu input a mux control */
+ output [15:0] adda_in; /* address alu a input bus */
+ output [15:0] alua_in; /* alu a input bus */
+
+ /*****************************************************************************************/
+ /* */
+ /* signal declarations */
+ /* */
+ /*****************************************************************************************/
+ reg [15:0] alua_in;
+ reg [15:0] alua_in_0, alua_in_1, alua_in_2, alua_in_3, alua_in_4, alua_in_5;
+ reg [15:0] alua_in_6, alua_in_7, alua_in_8, alua_in_9, alua_in_10, alua_in_11;
+ reg [15:0] alua_in_12, alua_in_13, alua_in_14;
+
+ wire [15:0] adda_in;
+ wire [15:0] adda_in_0, adda_in_1, adda_in_2, adda_in_4, adda_in_5, adda_in_12;
+ wire [15:0] adda_in_14;
+
+ /*****************************************************************************************/
+ /* */
+ /* alu input a select */
+ /* */
+ /*****************************************************************************************/
+ always @ (alua_reg or aa_reg_out or bit_mask or daa_out or ii_reg or int_addr or
+ hl_reg_out or ix_reg or iy_reg or pc_reg or rr_reg or rst_addr) begin
+ alua_in_0 = 16'h0;
+ alua_in_1 = 16'h0;
+ alua_in_2 = 16'h0;
+ alua_in_3 = 16'h0;
+ alua_in_4 = 16'h0;
+ alua_in_5 = 16'h0;
+ alua_in_6 = 16'h0;
+ alua_in_7 = 16'h0;
+ alua_in_8 = 16'h0;
+ alua_in_9 = 16'h0;
+ alua_in_10 = 16'h0;
+ alua_in_11 = 16'h0;
+ alua_in_12 = 16'h0;
+ alua_in_13 = 16'h0;
+ alua_in_14 = 16'h0;
+ if (alua_reg[`AA_ONE]) alua_in_0 = 16'h0001;
+ if (alua_reg[`AA_M1]) alua_in_1 = 16'hffff;
+ if (alua_reg[`AA_M2]) alua_in_2 = 16'hfffe;
+ if (alua_reg[`AA_HL]) alua_in_3 = hl_reg_out;
+ if (alua_reg[`AA_IX]) alua_in_4 = ix_reg;
+ if (alua_reg[`AA_IY]) alua_in_5 = iy_reg;
+ if (alua_reg[`AA_PC]) alua_in_6 = pc_reg;
+ if (alua_reg[`AA_AA]) alua_in_7 = {8'h00, aa_reg_out};
+ if (alua_reg[`AA_BIT]) alua_in_8 = {8'h00, bit_mask};
+ if (alua_reg[`AA_DAA]) alua_in_9 = {8'h00, daa_out};
+ if (alua_reg[`AA_II]) alua_in_10 = {8'h00, ii_reg};
+ if (alua_reg[`AA_RR]) alua_in_11 = {8'h00, rr_reg};
+ if (alua_reg[`AA_INT]) alua_in_12 = int_addr;
+ if (alua_reg[`AA_TMP]) alua_in_13 = tmp_reg;
+ if (alua_reg[`AA_RST]) alua_in_14 = {8'h00, rst_addr};
+ end
+
+ always @ (alua_in_0 or alua_in_1 or alua_in_2 or alua_in_3 or alua_in_4 or
+ alua_in_5 or alua_in_6 or alua_in_7 or alua_in_8 or alua_in_9 or
+ alua_in_10 or alua_in_11 or alua_in_12 or alua_in_13 or alua_in_14) begin
+ alua_in = alua_in_0 | alua_in_1 | alua_in_2 | alua_in_3 | alua_in_4 |
+ alua_in_5 | alua_in_6 | alua_in_7 | alua_in_8 | alua_in_9 |
+ alua_in_10 | alua_in_11 | alua_in_12 | alua_in_13 | alua_in_14;
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* address alu input a select */
+ /* */
+ /*****************************************************************************************/
+ assign adda_in_0 = (alua_reg[`AA_ONE]) ? 16'h0001 : 16'h0000;
+ assign adda_in_1 = (alua_reg[`AA_M1]) ? 16'hffff : 16'h0000;
+ assign adda_in_2 = (alua_reg[`AA_M2]) ? 16'hfffe : 16'h0000;
+ assign adda_in_4 = (alua_reg[`AA_IX]) ? ix_reg : 16'h0000;
+ assign adda_in_5 = (alua_reg[`AA_IY]) ? iy_reg : 16'h0000;
+ assign adda_in_12 = (alua_reg[`AA_INT]) ? int_addr : 16'h0000;
+ assign adda_in_14 = (alua_reg[`AA_RST]) ? {8'h00, rst_addr} : 16'h0000;
+
+ assign adda_in = adda_in_0 | adda_in_1 | adda_in_2 | adda_in_4 | adda_in_5 |
+ adda_in_12 | adda_in_14;
+
+ endmodule
\ No newline at end of file
diff --git a/common/CPU/z180/alubmux.v b/common/CPU/z180/alubmux.v
new file mode 100644
index 00000000..c2d3dade
--- /dev/null
+++ b/common/CPU/z180/alubmux.v
@@ -0,0 +1,99 @@
+/*******************************************************************************************/
+/** **/
+/** COPYRIGHT (C) 2011, SYSTEMYDE INTERNATIONAL CORPORATION, ALL RIGHTS RESERVED **/
+/** **/
+/** alu b input multiplexer module Rev 0.0 07/24/2011 **/
+/** **/
+/*******************************************************************************************/
+module alubmux (addb_in, alub_in, alub_reg, af_reg_out, bc_reg_out, de_reg_out, din0_reg,
+ din1_reg, hl_reg_out, ix_reg, iy_reg, pc_reg, sp_reg, tmp_reg);
+
+ input [7:0] din0_reg; /* data input 0 register */
+ input [7:0] din1_reg; /* data input 1 register */
+ input [15:0] af_reg_out; /* af register output */
+ input [15:0] bc_reg_out; /* bc register output */
+ input [15:0] de_reg_out; /* de register output */
+ input [15:0] hl_reg_out; /* hl register output */
+ input [15:0] ix_reg; /* ix register output */
+ input [15:0] iy_reg; /* iy register output */
+ input [15:0] pc_reg; /* pc register output */
+ input [15:0] sp_reg; /* sp register output */
+ input [15:0] tmp_reg; /* temporary register output */
+ input [`ALUB_IDX:0] alub_reg; /* pipelined alu input b mux control */
+ output [15:0] addb_in; /* address alu b input bus */
+ output [15:0] alub_in; /* alu b input bus */
+
+ /*****************************************************************************************/
+ /* */
+ /* signal declarations */
+ /* */
+ /*****************************************************************************************/
+ wire [15:0] alub_in;
+ reg [15:0] alub_mux;
+ reg [15:0] alub_mux_1, alub_mux_2, alub_mux_3, alub_mux_4, alub_mux_5;
+ reg [15:0] alub_mux_6, alub_mux_7, alub_mux_8, alub_mux_9, alub_mux_10, alub_mux_11;
+
+ wire [15:0] addb_in;
+ wire [15:0] addb_mux_2, addb_mux_3, addb_mux_4, addb_mux_5, addb_mux_6, addb_mux_7;
+ wire [15:0] addb_mux_8, addb_mux_9, addb_mux_10, addb_mux_12;
+
+ /*****************************************************************************************/
+ /* */
+ /* alu input b select */
+ /* */
+ /*****************************************************************************************/
+ always @ (alub_reg or af_reg_out or bc_reg_out or de_reg_out or hl_reg_out or ix_reg or
+ iy_reg or sp_reg or din1_reg or din0_reg or tmp_reg or pc_reg) begin
+ alub_mux_1 = 32'h0;
+ alub_mux_2 = 32'h0;
+ alub_mux_3 = 32'h0;
+ alub_mux_4 = 32'h0;
+ alub_mux_5 = 32'h0;
+ alub_mux_6 = 32'h0;
+ alub_mux_7 = 32'h0;
+ alub_mux_8 = 32'h0;
+ alub_mux_9 = 32'h0;
+ alub_mux_10 = 32'h0;
+ alub_mux_11 = 32'h0;
+ if (alub_reg[`AB_AF]) alub_mux_1 = af_reg_out;
+ if (alub_reg[`AB_BC]) alub_mux_2 = bc_reg_out;
+ if (alub_reg[`AB_DE]) alub_mux_3 = de_reg_out;
+ if (alub_reg[`AB_HL]) alub_mux_4 = hl_reg_out;
+ if (alub_reg[`AB_IX]) alub_mux_5 = ix_reg;
+ if (alub_reg[`AB_IY]) alub_mux_6 = iy_reg;
+ if (alub_reg[`AB_SP]) alub_mux_7 = sp_reg;
+ if (alub_reg[`AB_DIN]) alub_mux_8 = {din1_reg, din0_reg};
+ if (alub_reg[`AB_IO]) alub_mux_9 = {af_reg_out[15:8], din0_reg};
+ if (alub_reg[`AB_TMP]) alub_mux_10 = tmp_reg;
+ if (alub_reg[`AB_PC]) alub_mux_11 = pc_reg;
+ end
+
+ always @ (alub_mux_1 or alub_mux_2 or alub_mux_3 or alub_mux_4 or alub_mux_5 or
+ alub_mux_6 or alub_mux_7 or alub_mux_8 or alub_mux_9 or alub_mux_10 or
+ alub_mux_11) begin
+ alub_mux = alub_mux_1 | alub_mux_2 | alub_mux_3 | alub_mux_4 | alub_mux_5 |
+ alub_mux_6 | alub_mux_7 | alub_mux_8 | alub_mux_9 | alub_mux_10 | alub_mux_11;
+ end
+
+ assign alub_in = (alub_reg[`AB_SHR]) ? {alub_mux[15:8], alub_mux[15:8]} : alub_mux;
+
+ /*****************************************************************************************/
+ /* */
+ /* address alu input b select */
+ /* */
+ /*****************************************************************************************/
+ assign addb_mux_2 = (alub_reg[`AB_BC]) ? bc_reg_out : 16'h0;
+ assign addb_mux_3 = (alub_reg[`AB_DE]) ? de_reg_out : 16'h0;
+ assign addb_mux_4 = (alub_reg[`AB_HL]) ? hl_reg_out : 16'h0;
+ assign addb_mux_5 = (alub_reg[`AB_IX]) ? ix_reg : 16'h0;
+ assign addb_mux_6 = (alub_reg[`AB_IY]) ? iy_reg : 16'h0;
+ assign addb_mux_7 = (alub_reg[`AB_SP]) ? sp_reg : 16'h0;
+ assign addb_mux_8 = (alub_reg[`AB_DIN]) ? {din1_reg, din0_reg} : 16'h0;
+ assign addb_mux_9 = (alub_reg[`AB_IO]) ? {af_reg_out[15:8], din0_reg} : 16'h0;
+ assign addb_mux_10 = (alub_reg[`AB_TMP]) ? tmp_reg : 16'h0;
+ assign addb_mux_12 = (alub_reg[`AB_ADR]) ? pc_reg : 16'h0;
+
+ assign addb_in = addb_mux_2 | addb_mux_3 | addb_mux_4 | addb_mux_5 | addb_mux_6 |
+ addb_mux_7 | addb_mux_8 |addb_mux_9 | addb_mux_10 | addb_mux_12;
+
+ endmodule
\ No newline at end of file
diff --git a/common/CPU/z180/aluout.v b/common/CPU/z180/aluout.v
new file mode 100644
index 00000000..f73c0702
--- /dev/null
+++ b/common/CPU/z180/aluout.v
@@ -0,0 +1,92 @@
+/*******************************************************************************************/
+/** **/
+/** ORIGINAL COPYRIGHT (C) 2011, SYSTEMYDE INTERNATIONAL CORPORATION, ALL RIGHTS RESERVED **/
+/** COPYRIGHT (C) 2012, SERGEY BELYASHOV **/
+/** **/
+/** alu function unit combiner module Rev 0.0 06/13/2012 **/
+/** **/
+/*******************************************************************************************/
+module aluout (cry_nxt, data_bus, hcar_nxt, one_nxt, par_nxt, sign_nxt, zero_nxt, adder_c,
+ adder_hc, adder_out, hi_byte, logic_c, logic_hc, logic_out, shft_c, shft_out,
+ mult_out,
+ unit_sel, word_op);
+
+ input adder_c; /* math carry result */
+ input adder_hc; /* math half-carry result */
+ input hi_byte; /* shift left byte control */
+ input logic_c; /* logic carry result */
+ input logic_hc; /* logic half-carry result */
+ input shft_c; /* shift carry result */
+ input word_op; /* word operation */
+ input [1:0] unit_sel; /* alu function unit select */
+ input [7:0] shft_out; /* shift unit result */
+ input [15:0] adder_out; /* math unit result */
+ input [15:0] logic_out; /* logic unit result */
+ input [15:0] mult_out; /* multiplier unit result */
+ output cry_nxt; /* carry flag next */
+ output hcar_nxt; /* half-carry flag next */
+ output one_nxt; /* one flag next */
+ output par_nxt; /* parity flag next */
+ output sign_nxt; /* sign flag next */
+ output zero_nxt; /* zero flag next */
+ output [15:0] data_bus; /* datapath data bus */
+
+ /*****************************************************************************************/
+ /* */
+ /* signal declarations */
+ /* */
+ /*****************************************************************************************/
+ wire one_nxt, par_nxt, sign_nxt, zero_nxt;
+ wire [15:0] data_bus;
+
+ reg cry_nxt, hcar_nxt;
+ reg [15:0] alu_result;
+
+ /*****************************************************************************************/
+ /* */
+ /* alu function unit combination */
+ /* */
+ /*****************************************************************************************/
+ always @ (unit_sel or adder_out or logic_out or shft_out or mult_out) begin
+ casex (unit_sel)
+ 2'b01: alu_result = adder_out;
+ 2'b10: alu_result = {8'h00, shft_out};
+ 2'b11: alu_result = mult_out;
+ default: alu_result = logic_out;
+ endcase
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* alu flag outputs */
+ /* */
+ /*****************************************************************************************/
+ always @ (unit_sel or adder_c or logic_c or shft_c) begin
+ casex (unit_sel)
+ 2'b01: cry_nxt = adder_c;
+ 2'b1x: cry_nxt = shft_c;
+ default: cry_nxt = logic_c;
+ endcase
+ end
+
+ always @ (unit_sel or adder_hc or logic_hc) begin
+ casex (unit_sel)
+ 2'b01: hcar_nxt = adder_hc;
+ 2'b1x: hcar_nxt = 1'b0;
+ default: hcar_nxt = logic_hc;
+ endcase
+ end
+
+ assign one_nxt = ~|alu_result[7:1] && alu_result[0];
+ assign par_nxt = ~^alu_result[7:0];
+ assign sign_nxt = (word_op) ? alu_result[15] : alu_result[7];
+ assign zero_nxt = (word_op) ? ~|alu_result[15:0] : ~|alu_result[7:0];
+
+ /*****************************************************************************************/
+ /* */
+ /* alu output left shift */
+ /* */
+ /*****************************************************************************************/
+ assign data_bus = (hi_byte) ? {alu_result[7:0], alu_result[7:0]} : alu_result[15:0];
+
+ endmodule
\ No newline at end of file
diff --git a/common/CPU/z180/control.v b/common/CPU/z180/control.v
new file mode 100644
index 00000000..c42ea494
--- /dev/null
+++ b/common/CPU/z180/control.v
@@ -0,0 +1,5227 @@
+/*******************************************************************************************/
+/** **/
+/** ORIGINAL COPYRIGHT (C) 2011, SYSTEMYDE INTERNATIONAL CORPORATION, ALL RIGHTS RESERVED **/
+/** COPYRIGHT (C) 2012, SERGEY BELYASHOV **/
+/** **/
+/** control module Rev 0.0 06/18/2012 **/
+/** **/
+/*******************************************************************************************/
+module control (add_sel, alua_sel, alub_sel, aluop_sel, cflg_en, di_ctl, do_ctl, ex_af_pls,
+ ex_bank_pls, ex_dehl_inst, halt_nxt, hflg_ctl, ief_ctl, if_frst, inta_frst,
+ imd_ctl, ld_dmaa, ld_inst, ld_inta, ld_page, ld_wait, nflg_ctl, output_inh,
+ page_sel, pc_sel, pflg_ctl, rd_frst, rd_nxt, reti_nxt, rreg_en, sflg_en, state_nxt,
+ tflg_ctl, tran_sel, wr_addr, wr_frst, zflg_en, carry_bit, dmar_reg, inst_reg,
+ intr_reg, page_reg, par_bit, sign_bit, state_reg, tflg_reg, vector_int,
+ xhlt_reg, zero_bit, int_req);
+
+ input carry_bit; /* carry flag */
+ input dmar_reg; /* latched dma request */
+ input intr_reg; /* latched interrupt request */
+ input int_req; /* interrupt request (for SLP) */
+ input par_bit; /* parity flag */
+ input sign_bit; /* sign flag */
+ input tflg_reg; /* temporary flag */
+ input vector_int; /* int vector enable */
+ input xhlt_reg; /* halt exit */
+ input zero_bit; /* zero flag */
+ input [3:0] page_reg; /* instruction decode "page" */
+ input [7:0] inst_reg; /* instruction register */
+ input [`STATE_IDX:0] state_reg; /* current processor state */
+ output cflg_en; /* carry flag control */
+ output ex_af_pls; /* exchange af,af' */
+ output ex_bank_pls; /* exchange register bank */
+ output ex_dehl_inst; /* exchange de,hl */
+ output halt_nxt; /* halt cycle next */
+ output if_frst; /* ifetch first cycle */
+ output inta_frst; /* intack first cycle */
+ output ld_dmaa; /* load dma request */
+ output ld_inst; /* load instruction register */
+ output ld_inta; /* load interrupt request */
+ output ld_page; /* load page register */
+ output ld_wait; /* load wait request */
+ output output_inh; /* disable cpu outputs */
+ output rd_frst; /* read first cycle */
+ output rd_nxt; /* read cycle identifier */
+ output reti_nxt; /* reti identifier */
+ output rreg_en; /* update refresh register */
+ output sflg_en; /* sign flag control */
+ output wr_frst; /* write first cycle */
+ output zflg_en; /* zero flag control */
+ output [3:0] page_sel; /* instruction decode "page" control */
+ output [`ADCTL_IDX:0] add_sel; /* address output mux control */
+ output [`ALUA_IDX:0] alua_sel; /* alu input a mux control */
+ output [`ALUB_IDX:0] alub_sel; /* alu input b mux control */
+ output [`ALUOP_IDX:0] aluop_sel; /* alu operation control */
+ output [`DI_IDX:0] di_ctl; /* data input control */
+ output [`DO_IDX:0] do_ctl; /* data output control */
+ output [`HFLG_IDX:0] hflg_ctl; /* half-carry flag control */
+ output [`IEF_IDX:0] ief_ctl; /* interrupt enable control */
+ output [`IMD_IDX:0] imd_ctl; /* interrupt mode control */
+ output [`NFLG_IDX:0] nflg_ctl; /* negate flag control */
+ output [`PCCTL_IDX:0] pc_sel; /* program counter source control */
+ output [`PFLG_IDX:0] pflg_ctl; /* parity/overflow flag control */
+ output [`STATE_IDX:0] state_nxt; /* next processor state */
+ output [`TFLG_IDX:0] tflg_ctl; /* temp flag control */
+ output [`TTYPE_IDX:0] tran_sel; /* transaction type select */
+ output [`WREG_IDX:0] wr_addr; /* register write address bus */
+
+ /*****************************************************************************************/
+ /* */
+ /* signal declarations */
+ /* */
+ /*****************************************************************************************/
+ reg cflg_en; /* carry flag control */
+ reg ex_af_pls; /* exchange af,af' */
+ reg ex_bank_pls; /* exchange register bank */
+ reg ex_dehl_inst; /* exchange de,hl */
+ reg halt_nxt; /* halt transaction */
+ reg if_frst; /* first clock if ifetch */
+ reg inta_frst; /* first clock of intack */
+ reg ld_inst; /* load instruction register */
+ reg ld_inta; /* sample latched int */
+ reg ld_dmaa; /* sample latched dma */
+ reg ld_page; /* load page register */
+ reg ld_wait; /* sample wait input */
+ reg output_inh; /* disable cpu outputs */
+ reg rd_frst; /* first clock of read */
+ reg rd_nxt; /* read trans next */
+ reg reti_nxt; /* reti trans next */
+`ifdef RREG_EMU
+ reg rreg_en; /* update refresh register */
+`endif
+ reg sflg_en; /* sign flag control */
+ reg wr_frst; /* first clock of write */
+ reg zflg_en; /* zero flag control */
+ reg [3:0] page_sel; /* inst decode page control */
+ reg [`ADCTL_IDX:0] add_sel; /* address output mux control */
+ reg [`ALUA_IDX:0] alua_sel; /* alu input a mux control */
+ reg [`ALUB_IDX:0] alub_sel; /* alu input b mux control */
+ reg [`ALUOP_IDX:0] aluop_sel; /* alu operation control */
+ reg [`DI_IDX:0] di_ctl; /* data input control */
+ reg [`DO_IDX:0] do_ctl; /* data output control */
+ reg [`HFLG_IDX:0] hflg_ctl; /* half-carry flag control */
+ reg [`IEF_IDX:0] ief_ctl; /* interrupt enable control */
+ reg [`IMD_IDX:0] imd_ctl; /* interrupt mode control */
+ reg [`NFLG_IDX:0] nflg_ctl; /* negate flag control */
+ reg [`PCCTL_IDX:0] pc_sel; /* pc source control */
+ reg [`PFLG_IDX:0] pflg_ctl; /* parity/overflow flag control */
+ reg [`STATE_IDX:0] state_nxt; /* machine state */
+ reg [`TFLG_IDX:0] tflg_ctl; /* temp flag control */
+ reg [`TTYPE_IDX:0] tran_sel; /* transaction type */
+ reg [`WREG_IDX:0] wr_addr; /* register write address bus */
+
+ /*****************************************************************************************/
+ /* */
+ /* refresh register control */
+ /* */
+ /*****************************************************************************************/
+`ifdef RREG_EMU
+ always @ (inst_reg or page_reg or state_reg or dmar_reg) begin
+ casex (state_reg) //sysnopsys parallel_case
+ `IF1B,
+ `IF2B,
+ `IF3B: rreg_en = 1'b1;
+ `WR1B,
+ `WR2B: begin
+ casex ({page_reg, inst_reg}) //sysnopsys parallel_case
+ 12'b1xxx10111001,
+ 12'b1xxx10110001,
+ 12'b1xxx10111010,
+ 12'b1xxx10110010,
+ 12'b1xxx10111000,
+ 12'b1xxx10110000,
+ 12'b1xxx10111011,
+ 12'b1xxx10110011,
+ 12'b0001xxxxxxxx: rreg_en = 1'b1;
+ default: rreg_en = 1'b0;
+ endcase
+ end
+ default: rreg_en = 1'b0;
+ endcase
+ end
+`endif
+
+ /*****************************************************************************************/
+ /* */
+ /* exchange instruction control */
+ /* */
+ /*****************************************************************************************/
+ always @ (inst_reg or page_reg or state_reg) begin
+ casex (state_reg)
+ `IF1B: begin
+ case ({page_reg, inst_reg})
+ 12'b000000001000: ex_af_pls = 1'b1;
+ default: ex_af_pls = 1'b0;
+ endcase
+ end
+ default: ex_af_pls = 1'b0;
+ endcase
+ end
+
+ always @ (inst_reg or page_reg or state_reg) begin
+ casex (state_reg)
+ `IF1B: begin
+ case ({page_reg, inst_reg})
+ 12'b000011011001: ex_bank_pls = 1'b1;
+ default: ex_bank_pls = 1'b0;
+ endcase
+ end
+ default: ex_bank_pls = 1'b0;
+ endcase
+ end
+
+ always @ (inst_reg or page_reg or state_reg) begin
+ casex (state_reg)
+ `DEC1: begin
+ case (inst_reg)
+ 8'b11101011: ex_dehl_inst = 1'b1;
+ default: ex_dehl_inst = 1'b0;
+ endcase
+ end
+ default: ex_dehl_inst = 1'b0;
+ endcase
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* interrupt control */
+ /* */
+ /*****************************************************************************************/
+ always @ (inst_reg or page_reg or state_reg) begin
+ casex (state_reg)
+ `IF1B: begin
+ casex ({page_reg, inst_reg})
+ 12'b000011110011: ief_ctl = `IEF_0;
+ 12'b000011111011: ief_ctl = `IEF_1;
+ 12'b0001xxxxxxxx: ief_ctl = `IEF_NMI;
+ 12'b1xxx01000101: ief_ctl = `IEF_RTN;
+ default: ief_ctl = `IEF_NUL;
+ endcase
+ end
+ default: ief_ctl = `IEF_NUL;
+ endcase
+ end
+
+ always @ (inst_reg or page_reg or state_reg) begin
+ casex (state_reg)
+ `IF1B: begin
+ casex ({page_reg, inst_reg})
+ 12'b1xxx01000110: imd_ctl = `IMD_0;
+ 12'b1xxx01010110: imd_ctl = `IMD_1;
+ 12'b1xxx01011110: imd_ctl = `IMD_2;
+ default: imd_ctl = `IMD_NUL;
+ endcase
+ end
+ default: imd_ctl = `IMD_NUL;
+ endcase
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* identifiers to create timing signals */
+ /* */
+ /*****************************************************************************************/
+ always @ (state_reg) begin
+ casex (state_reg) //synopsys parallel_case
+ `DEC1,
+ `DEC2,
+ `OF2A,
+ `IF3A,
+ `IF1A: if_frst = 1'b1;
+ default: if_frst = 1'b0;
+ endcase
+ end
+
+ always @ (state_reg) begin
+ casex (state_reg) //synopsys parallel_case
+ `INTA,
+ `RSTE: inta_frst = 1'b1;
+ default: inta_frst = 1'b0;
+ endcase
+ end
+
+ always @ (inst_reg or page_reg or state_nxt) begin
+ casex (state_nxt) //synopsys parallel_case
+ `RD1A,
+ `RD2A: rd_nxt = 1'b1;
+ default: rd_nxt = 1'b0;
+ endcase
+ end
+
+ always @ (inst_reg or page_reg or state_reg) begin
+ casex (state_reg) //synopsys parallel_case
+ `RD1A,
+ `RD2A: rd_frst = 1'b1;
+ default: rd_frst = 1'b0;
+ endcase
+ end
+
+ always @ (state_reg) begin
+ casex (state_reg) //synopsys parallel_case
+ `WR1A,
+ `WR2A: wr_frst = 1'b1;
+ default: wr_frst = 1'b0;
+ endcase
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* wait sample */
+ /* */
+ /*****************************************************************************************/
+ always @ (inst_reg or page_reg or state_reg or carry_bit or par_bit or
+ sign_bit or zero_bit) begin
+ casex (state_reg) //synopsys parallel_case
+ `DEC1: begin
+ casex (inst_reg) //synopsys parallel_case
+ 8'b00000010,
+ 8'b00001010,
+ 8'b00010010,
+ 8'b00011010,
+ 8'b00110100,
+ 8'b00110101,
+ 8'b011100xx,
+ 8'b0111010x,
+ 8'b01110111,
+ 8'b010xx110,
+ 8'b0110x110,
+ 8'b01111110,
+ 8'b10000110,
+ 8'b10001110,
+ 8'b10010110,
+ 8'b10011110,
+ 8'b10100110,
+ 8'b10101110,
+ 8'b10110110,
+ 8'b10111110,
+ 8'b11001001,
+ 8'b11100011,
+ 8'b11xx0001,
+ 8'b11xx0101,
+ 8'b11xxx111,
+ 8'b01110110,
+ 8'b11101001: ld_wait = 1'b0;
+ 8'b11000000: ld_wait = zero_bit;
+ 8'b11001000: ld_wait = !zero_bit;
+ 8'b11010000: ld_wait = carry_bit;
+ 8'b11011000: ld_wait = !carry_bit;
+ 8'b11100000: ld_wait = par_bit;
+ 8'b11101000: ld_wait = !par_bit;
+ 8'b11110000: ld_wait = sign_bit;
+ 8'b11111000: ld_wait = !sign_bit;
+ default: ld_wait = 1'b1;
+ endcase
+ end
+ `DEC2: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b0010xxxxx110,
+ 12'b010x11100001,
+ 12'b010x11100011,
+ 12'b010x11100101,
+ 12'b1xxx00xxx11x, //ld (hl),rr; ld (hl),ii; ld rr,(hl); ld ii,(hl)
+ 12'b1xxx0100x101,
+ 12'b1xxx0110x111,
+ 12'b1xxx01xxx00x,
+ 12'b1xxx01110110, //slp
+ 12'b1xxx100xx01x, //indm,indmr,inim,inimr, otdm,otdmr,otim,otimr
+ 12'b1xxx101xx0xx,
+ 12'b1xxx10xxx100, //ind2,ind2r,ini2,ini2r, outd2,otd2r,outi2,oti2r
+ 12'b1xxx1100x01x, //indrx,inirx, otdrx,otirx
+ 12'b010x11101001: ld_wait = 1'b0;
+ default: ld_wait = 1'b1;
+ endcase
+ end
+ `OF2A,
+ `IF3A,
+ `RD1A,
+ `RD2A,
+ `WR1A,
+ `WR2A,
+ `IF1A,
+ `INTA: ld_wait = 1'b1;
+ default: ld_wait = 1'b0;
+ endcase
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* instruction register and page register control */
+ /* */
+ /*****************************************************************************************/
+ always @ (inst_reg or page_reg or state_reg) begin
+ casex (state_reg) //synopsys parallel_case
+ `IF2B,
+ `IF3B,
+ `IF1B: ld_inst = 1'b1;
+ default: ld_inst = 1'b0;
+ endcase
+ end
+
+ always @ (inst_reg or page_reg or state_reg) begin
+ casex (state_reg)
+ `DEC1: begin
+ case (inst_reg)
+ 8'b11001011: page_sel = `CB_PAGE;
+ 8'b11011101: page_sel = `DD_PAGE;
+ 8'b11101101: page_sel = `ED_PAGE;
+ 8'b11111101: page_sel = `FD_PAGE;
+ default: page_sel = `MAIN_PG;
+ endcase
+ end
+ `DEC2: begin
+ casex ({page_reg, inst_reg})
+ 12'bx10011001011: page_sel = `DDCB_PG;
+ 12'bx10111001011: page_sel = `FDCB_PG;
+ default: page_sel = `MAIN_PG;
+ endcase
+ end
+ `INTA: page_sel = `INTR_PG;
+ `DMA1: page_sel = `DMA_PG;
+ default: page_sel = `MAIN_PG;
+ endcase
+ end
+
+ always @ (inst_reg or page_reg or state_reg) begin
+ casex (state_reg) //synopsys parallel_case
+ `DEC1: ld_page = 1'b1;
+ `DEC2: begin
+ casex ({page_reg, inst_reg})
+ 12'bx10x11001011: ld_page = 1'b1;
+ default: ld_page = 1'b0;
+ endcase
+ end
+ `INTA,
+ `DMA1: ld_page = 1'b1;
+ default: ld_page = 1'b0;
+ endcase
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* next state control */
+ /* */
+ /*****************************************************************************************/
+ always @ (inst_reg or page_reg or state_reg or carry_bit or dmar_reg or intr_reg or
+ par_bit or sign_bit or tflg_reg or vector_int or xhlt_reg or zero_bit) begin
+ casex (state_reg) //synopsys parallel_case
+ `DEC1: begin
+ casex (inst_reg) //synopsys parallel_case
+ 8'b00000010,
+ 8'b00001010,
+ 8'b00010010,
+ 8'b00011010,
+ 8'b00110100,
+ 8'b00110101,
+ 8'b011100xx,
+ 8'b0111010x,
+ 8'b01110111,
+ 8'b010xx110,
+ 8'b0110x110,
+ 8'b01111110,
+ 8'b10000110,
+ 8'b10001110,
+ 8'b10010110,
+ 8'b10011110,
+ 8'b10100110,
+ 8'b10101110,
+ 8'b10110110,
+ 8'b10111110,
+ 8'b11001001,
+ 8'b11100011,
+ 8'b11xx0001,
+ 8'b11xx0101,
+ 8'b11xxx111: state_nxt = `sADR2;
+ 8'b11000000: state_nxt = ( !zero_bit) ? `sADR2 : `sIF1B;
+ 8'b11001000: state_nxt = ( zero_bit) ? `sADR2 : `sIF1B;
+ 8'b11010000: state_nxt = (!carry_bit) ? `sADR2 : `sIF1B;
+ 8'b11011000: state_nxt = ( carry_bit) ? `sADR2 : `sIF1B;
+ 8'b11100000: state_nxt = ( !par_bit) ? `sADR2 : `sIF1B;
+ 8'b11101000: state_nxt = ( par_bit) ? `sADR2 : `sIF1B;
+ 8'b11110000: state_nxt = ( !sign_bit) ? `sADR2 : `sIF1B;
+ 8'b11111000: state_nxt = ( sign_bit) ? `sADR2 : `sIF1B;
+ 8'b11001011,
+ 8'b11011101,
+ 8'b11101101,
+ 8'b11111101: state_nxt = `sIF2B;
+ 8'b00010000,
+ 8'b00011000,
+ 8'b00100010,
+ 8'b00101010,
+ 8'b00110010,
+ 8'b00111010,
+ 8'b001xx000,
+ 8'b00xx0001,
+ 8'b00xxx110,
+ 8'b11000011,
+ 8'b11000110,
+ 8'b11001101,
+ 8'b11001110,
+ 8'b11010011,
+ 8'b11010110,
+ 8'b11011011,
+ 8'b11011110,
+ 8'b11100110,
+ 8'b11101110,
+ 8'b11110110,
+ 8'b11111110,
+ 8'b11xxx010,
+ 8'b11xxx100: state_nxt = `sOF1B;
+ 8'b01110110,
+ 8'b11101001: state_nxt = `sPCO;
+ default: state_nxt = `sIF1B;
+ endcase
+ end
+ `IF2B: state_nxt = `sDEC2;
+ `DEC2: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b001000000110,
+ 12'b001000001110,
+ 12'b001000010110,
+ 12'b001000011110,
+ 12'b001000100110,
+ 12'b001000101110,
+ 12'b001000110110,
+ 12'b001000111110,
+ 12'b001001xxx110,
+ 12'b001010xxx110,
+ 12'b001011xxx110,
+ 12'b010011100001,
+ 12'b010011100011,
+ 12'b010011100101,
+ 12'b010111100001,
+ 12'b010111100011,
+ 12'b010111100101,
+ 12'b1xxx00110100,
+ 12'b1xxx00110110,
+ 12'b1xxx00110111,
+ 12'b1xxx00111110,
+ 12'b1xxx00111111,
+ 12'b1xxx00xx0111,
+ 12'b1xxx00xx1111,
+ 12'b1xxx01000101,
+ 12'b1xxx01001101,
+ 12'b1xxx01100111,
+ 12'b1xxx01101111,
+ 12'b1xxx01xxx000,
+ 12'b1xxx01xxx001,
+ 12'b1xxx10000010,
+ 12'b1xxx10000011,
+ 12'b1xxx10000100,
+ 12'b1xxx10001010,
+ 12'b1xxx10001011,
+ 12'b1xxx10001100,
+ 12'b1xxx10010010,
+ 12'b1xxx10010011,
+ 12'b1xxx10010100,
+ 12'b1xxx10011010,
+ 12'b1xxx10011011,
+ 12'b1xxx10011100,
+ 12'b1xxx10100000,
+ 12'b1xxx10100001,
+ 12'b1xxx10100010,
+ 12'b1xxx10100011,
+ 12'b1xxx10100100,
+ 12'b1xxx10101000,
+ 12'b1xxx10101001,
+ 12'b1xxx10101010,
+ 12'b1xxx10101011,
+ 12'b1xxx10101100,
+ 12'b1xxx10110000,
+ 12'b1xxx10110001,
+ 12'b1xxx10110010,
+ 12'b1xxx10110011,
+ 12'b1xxx10110100,
+ 12'b1xxx10111000,
+ 12'b1xxx10111001,
+ 12'b1xxx10111010,
+ 12'b1xxx10111011,
+ 12'b1xxx10111100,
+ 12'b1xxx11000010,
+ 12'b1xxx11000011,
+ 12'b1xxx11001010,
+ 12'b1xxx11001011: state_nxt = `sADR2;
+ 12'b001000000xxx,
+ 12'b001000001xxx,
+ 12'b001000010xxx,
+ 12'b001000011xxx,
+ 12'b001000100xxx,
+ 12'b001000101xxx,
+ 12'b001000110xxx,
+ 12'b001000111xxx,
+ 12'b001001xxxxxx,
+ 12'b001010xxxxxx,
+ 12'b001011xxxxxx,
+ 12'b010000100011,
+ 12'b010000100100,
+ 12'b010000100101,
+ 12'b010000101011,
+ 12'b010000101100,
+ 12'b010000101101,
+ 12'b010000xx1001,
+ 12'b01000110x0xx,12'b01000110x10x,12'b01000110x111,
+ 12'b0100010xx10x,12'b01000110x10x,12'b01000111110x,
+ 12'b010010000100,
+ 12'b010010000101,
+ 12'b010010001100,
+ 12'b010010001101,
+ 12'b010010010100,
+ 12'b010010010101,
+ 12'b010010011100,
+ 12'b010010011101,
+ 12'b010010100100,
+ 12'b010010100101,
+ 12'b010010101100,
+ 12'b010010101101,
+ 12'b010010110100,
+ 12'b010010110101,
+ 12'b010010111100,
+ 12'b010010111101,
+ 12'b010011111001,
+ 12'b010100100011,
+ 12'b010100100100,
+ 12'b010100100101,
+ 12'b010100101011,
+ 12'b010100101100,
+ 12'b010100101101,
+ 12'b010100xx1001,
+ 12'b01010110x0xx,12'b01010110x10x,12'b01010110x111,
+ 12'b0101010xx10x,12'b01010110x10x,12'b01010111110x,
+ 12'b010110000100,
+ 12'b010110000101,
+ 12'b010110001100,
+ 12'b010110001101,
+ 12'b010110010100,
+ 12'b010110010101,
+ 12'b010110011100,
+ 12'b010110011101,
+ 12'b010110100100,
+ 12'b010110100101,
+ 12'b010110101100,
+ 12'b010110101101,
+ 12'b010110110100,
+ 12'b010110110101,
+ 12'b010110111100,
+ 12'b010110111101,
+ 12'b010111111001,
+ 12'b1xxx00xxx100,
+ 12'b1xxx01000100,
+ 12'b1xxx01000110,
+ 12'b1xxx01000111,
+ 12'b1xxx01001111,
+ 12'b1xxx01010110,
+ 12'b1xxx01010111,
+ 12'b1xxx01011110,
+ 12'b1xxx01011111,
+ 12'b1xxx01xx1100,
+ 12'b1xxx01xx0010,
+ 12'b1xxx01xx1010: state_nxt = `sIF1B;
+ 12'b010011101001,
+ 12'b010111101001,
+ 12'b1xxx01110110: state_nxt = `sPCO;
+ default: state_nxt = `sOF1B;
+ endcase
+ end
+ `OF1B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b0000000xx110,12'b00000010x110,12'b000000111110,
+ 12'b000011000110,
+ 12'b000011001110,
+ 12'b000011010110,
+ 12'b000011011110,
+ 12'b000011100110,
+ 12'b000011101110,
+ 12'b000011110110,
+ 12'b000011111110,
+ 12'b010000100110,
+ 12'b010000101110,
+ 12'b010100100110,
+ 12'b010100101110,
+ 12'b1xxx00110010,
+ 12'b1xxx00110011,
+ 12'b1xxx00xx0010,
+ 12'b1xxx00xx0011,
+ 12'b1xxx01010100,
+ 12'b1xxx01010101,
+ 12'b1xxx01100100: state_nxt = `sIF1A;
+ 12'b000000100000: state_nxt = ( !zero_bit) ? `sPCA : `sIF1A;
+ 12'b000000101000: state_nxt = ( zero_bit) ? `sPCA : `sIF1A;
+ 12'b000000110000: state_nxt = (!carry_bit) ? `sPCA : `sIF1A;
+ 12'b000000111000: state_nxt = ( carry_bit) ? `sPCA : `sIF1A;
+ 12'b011xxxxxxxxx: state_nxt = `sIF3A; //DD/FD + CB
+ 12'b000000100010,
+ 12'b000000101010,
+ 12'b000000110010,
+ 12'b000000111010,
+ 12'b000000xx0001,
+ 12'b000011000011,
+ 12'b000011001101,
+ 12'b000011xxx010,
+ 12'b000011xxx100,
+ 12'b010000100001,
+ 12'b010000100010,
+ 12'b010000101010,
+ 12'b010000110110,
+ 12'b010100100001,
+ 12'b010100100010,
+ 12'b010100101010,
+ 12'b010100110110,
+ 12'b1xxx01xx0011,
+ 12'b1xxx01xx1011: state_nxt = `sOF2A;
+ 12'b000000010000,
+ 12'b000000011000: state_nxt = `sPCA;
+ 12'b000000110110: state_nxt = `sWR2A;
+ default: state_nxt = `sADR1;
+ endcase
+ end
+ `OF2A: state_nxt = `sOF2B;
+ `OF2B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000000xx0001,
+ 12'b010000100001,
+ 12'b010100100001: state_nxt = `sIF1A;
+ 12'b000011000010: state_nxt = ( !zero_bit) ? `sPCA : `sIF1A;
+ 12'b000011001010: state_nxt = ( zero_bit) ? `sPCA : `sIF1A;
+ 12'b000011010010: state_nxt = (!carry_bit) ? `sPCA : `sIF1A;
+ 12'b000011011010: state_nxt = ( carry_bit) ? `sPCA : `sIF1A;
+ 12'b000011100010: state_nxt = ( !par_bit) ? `sPCA : `sIF1A;
+ 12'b000011101010: state_nxt = ( par_bit) ? `sPCA : `sIF1A;
+ 12'b000011110010: state_nxt = ( !sign_bit) ? `sPCA : `sIF1A;
+ 12'b000011111010: state_nxt = ( sign_bit) ? `sPCA : `sIF1A;
+ 12'b000011000100: state_nxt = ( !zero_bit) ? `sWR1A : `sIF1A;
+ 12'b000011001100: state_nxt = ( zero_bit) ? `sWR1A : `sIF1A;
+ 12'b000011010100: state_nxt = (!carry_bit) ? `sWR1A : `sIF1A;
+ 12'b000011011100: state_nxt = ( carry_bit) ? `sWR1A : `sIF1A;
+ 12'b000011100100: state_nxt = ( !par_bit) ? `sWR1A : `sIF1A;
+ 12'b000011101100: state_nxt = ( par_bit) ? `sWR1A : `sIF1A;
+ 12'b000011110100: state_nxt = ( !sign_bit) ? `sWR1A : `sIF1A;
+ 12'b000011111100: state_nxt = ( sign_bit) ? `sWR1A : `sIF1A;
+ 12'b000011000011: state_nxt = `sPCA;
+ 12'b000011001101: state_nxt = `sWR1A;
+ 12'b010000110110,
+ 12'b010100110110: state_nxt = `sWR2A;
+ default: state_nxt = `sADR1;
+ endcase
+ end
+ `IF3A: state_nxt = `sIF3B;
+ `IF3B: state_nxt = `sRD2A;
+ `ADR1: state_nxt = `sADR2;
+ `ADR2: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000000101010,
+ 12'b000011001001,
+ 12'b000011100011,
+ 12'b000011xxx000,
+ 12'b000011xx0001,
+ 12'b0001xxxxxxxx,
+ 12'b010000101010,
+ 12'b010000110001,
+ 12'b010000110111,
+ 12'b010000xx0111,
+ 12'b010011100001,
+ 12'b010011100011,
+ 12'b010100101010,
+ 12'b010100110001,
+ 12'b010100110111,
+ 12'b010100xx0111,
+ 12'b010111100001,
+ 12'b010111100011,
+ 12'b1xxx00110110,
+ 12'b1xxx00110111,
+ 12'b1xxx00xx0111,
+ 12'b1xxx01000101,
+ 12'b1xxx01001101,
+ 12'b1xxx01xx1011,
+ 12'b1xxx10000010,
+ 12'b1xxx10000011,
+ 12'b1xxx10000100,
+ 12'b1xxx10001010,
+ 12'b1xxx10001011,
+ 12'b1xxx10001100,
+ 12'b1xxx10010010,
+ 12'b1xxx10010011,
+ 12'b1xxx10010100,
+ 12'b1xxx10011010,
+ 12'b1xxx10011011,
+ 12'b1xxx10011100,
+ 12'b1xxx10100000,
+ 12'b1xxx10100001,
+ 12'b1xxx10100010,
+ 12'b1xxx10100011,
+ 12'b1xxx10100100,
+ 12'b1xxx10101000,
+ 12'b1xxx10101001,
+ 12'b1xxx10101010,
+ 12'b1xxx10101011,
+ 12'b1xxx10101100,
+ 12'b1xxx10110000,
+ 12'b1xxx10110001,
+ 12'b1xxx10110010,
+ 12'b1xxx10110011,
+ 12'b1xxx10110100,
+ 12'b1xxx10111000,
+ 12'b1xxx10111001,
+ 12'b1xxx10111010,
+ 12'b1xxx10111011,
+ 12'b1xxx10111100,
+ 12'b1xxx11000010,
+ 12'b1xxx11000011,
+ 12'b1xxx11001010,
+ 12'b1xxx11001011: state_nxt = `sRD1A;
+ 12'b000000100010,
+ 12'b000011xxx111,
+ 12'b000011xx0101,
+ 12'b010000100010,
+ 12'b010000111110,
+ 12'b010000111111,
+ 12'b010000xx1111,
+ 12'b010011100101,
+ 12'b010100100010,
+ 12'b010100111110,
+ 12'b010100111111,
+ 12'b010100xx1111,
+ 12'b010111100101,
+ 12'b1xxx00111110,
+ 12'b1xxx00111111,
+ 12'b1xxx00xx1111,
+ 12'b1xxx01100101,
+ 12'b1xxx01100110,
+ 12'b1xxx01xx0011: state_nxt = `sWR1A;
+ 12'b000000000010,
+ 12'b000000010010,
+ 12'b000000110010,
+ 12'b000001110xxx,
+ 12'b000011010011,
+ 12'b010001110xxx,
+ 12'b010101110xxx,
+ 12'b1xxx00xxx001,
+ 12'b1xxx01xxx001: state_nxt = `sWR2A;
+ default: state_nxt = `sRD2A;
+ endcase
+ end
+ `RD1A: state_nxt = `sRD1B;
+ `RD1B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10100001,
+ 12'b1xxx10101001,
+ 12'b1xxx10110001,
+ 12'b1xxx10111001: state_nxt = `sBLK1;
+ 12'b1xxx10000010,
+ 12'b1xxx10000011,
+ 12'b1xxx10000100,
+ 12'b1xxx10001010,
+ 12'b1xxx10001011,
+ 12'b1xxx10001100,
+ 12'b1xxx10010010,
+ 12'b1xxx10010011,
+ 12'b1xxx10010100,
+ 12'b1xxx10011010,
+ 12'b1xxx10011011,
+ 12'b1xxx10011100,
+ 12'b1xxx10100000,
+ 12'b1xxx10100010,
+ 12'b1xxx10100011,
+ 12'b1xxx10100100,
+ 12'b1xxx10101000,
+ 12'b1xxx10101010,
+ 12'b1xxx10101011,
+ 12'b1xxx10101100,
+ 12'b1xxx10110000,
+ 12'b1xxx10110010,
+ 12'b1xxx10110011,
+ 12'b1xxx10110100,
+ 12'b1xxx10111000,
+ 12'b1xxx10111010,
+ 12'b1xxx10111011,
+ 12'b1xxx10111100,
+ 12'b1xxx11000010,
+ 12'b1xxx11000011,
+ 12'b1xxx11001010,
+ 12'b1xxx11001011: state_nxt = `sWR1A;
+ default: state_nxt = `sRD2A;
+ endcase
+ end
+ `RD2A: state_nxt = `sRD2B;
+ `RD2B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10100001,
+ 12'b1xxx10101001,
+ 12'b1xxx10110001,
+ 12'b1xxx10111001: state_nxt = `sBLK1;
+ 12'b000000001010,
+ 12'b000000011010,
+ 12'b000000101010,
+ 12'b000000111010,
+ 12'b000001xxxxxx,
+ 12'b000001xxx110,
+ 12'b000010000110,
+ 12'b000010000xxx,
+ 12'b000010001110,
+ 12'b000010001xxx,
+ 12'b000010010110,
+ 12'b000010011110,
+ 12'b000010100110,
+ 12'b000010100xxx,
+ 12'b000010101110,
+ 12'b000010110110,
+ 12'b000010110xxx,
+ 12'b000010111110,
+ 12'b000010111xxx,
+ 12'b000011011011,
+ 12'b000011xx0001,
+ 12'b001001xxx110,
+ 12'b001001xxxxxx,
+ 12'b010000101010,
+ 12'b010000110001,
+ 12'b010000110111,
+ 12'b010000xx0111,
+ 12'b010001xxx110,
+ 12'b010010000110,
+ 12'b010010001110,
+ 12'b010010010110,
+ 12'b010010011110,
+ 12'b010010100110,
+ 12'b010010101110,
+ 12'b010010110110,
+ 12'b010010111110,
+ 12'b010011100001,
+ 12'b010100101010,
+ 12'b010100110001,
+ 12'b010100110111,
+ 12'b010100xx0111,
+ 12'b010101xxx110,
+ 12'b010110000110,
+ 12'b010110001110,
+ 12'b010110010110,
+ 12'b010110011110,
+ 12'b010110100110,
+ 12'b010110101110,
+ 12'b010110110110,
+ 12'b010110111110,
+ 12'b010111100001,
+ 12'b011001xxx110,
+ 12'b011101xxx110,
+ 12'b1xxx00110100,
+ 12'b1xxx00110110,
+ 12'b1xxx00110111,
+ 12'b1xxx00xx0111,
+ 12'b1xxx00xxx000,
+ 12'b1xxx00xxx100,
+ 12'b1xxx01110100,
+ 12'b1xxx01xxx000,
+ 12'b1xxx01xx1011: state_nxt = `sIF1A;
+ 12'b000011001001,
+ 12'b000011xxx000,
+ 12'b1xxx01000101,
+ 12'b1xxx01001101: state_nxt = `sPCA;
+ 12'b000011100011,
+ 12'b0001xxxxxxxx,
+ 12'b010011100011,
+ 12'b010111100011: state_nxt = `sWR1A;
+ default: state_nxt = `sWR2A;
+ endcase
+ end
+ `WR1A: state_nxt = `sWR1B;
+ `WR1B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10000010,
+ 12'b1xxx10000011,
+ 12'b1xxx10000100,
+ 12'b1xxx10001010,
+ 12'b1xxx10001011,
+ 12'b1xxx10001100,
+ 12'b1xxx10100000,
+ 12'b1xxx10100010,
+ 12'b1xxx10100011,
+ 12'b1xxx10100100,
+ 12'b1xxx10101000,
+ 12'b1xxx10101010,
+ 12'b1xxx10101011,
+ 12'b1xxx10101100: state_nxt = `sIF1A;
+ 12'b1xxx10010010,
+ 12'b1xxx10010011,
+ 12'b1xxx10010100,
+ 12'b1xxx10011010,
+ 12'b1xxx10011011,
+ 12'b1xxx10011100,
+ 12'b1xxx10110000,
+ 12'b1xxx10110010,
+ 12'b1xxx10110011,
+ 12'b1xxx10110100,
+ 12'b1xxx10111000,
+ 12'b1xxx10111010,
+ 12'b1xxx10111011,
+ 12'b1xxx10111100,
+ 12'b1xxx11000010,
+ 12'b1xxx11000011,
+ 12'b1xxx11001010,
+ 12'b1xxx11001011: state_nxt = (tflg_reg || intr_reg || dmar_reg) ? `sPCA : `sRD2A;
+ default: state_nxt = `sWR2A;
+ endcase
+ end
+ `WR2A: state_nxt = `sWR2B;
+ `WR2B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10010010,
+ 12'b1xxx10010011,
+ 12'b1xxx10010100,
+ 12'b1xxx10011010,
+ 12'b1xxx10011011,
+ 12'b1xxx10011100,
+ 12'b1xxx10100000,
+ 12'b1xxx10100010,
+ 12'b1xxx10100011,
+ 12'b1xxx10101000,
+ 12'b1xxx10101010,
+ 12'b1xxx10101011,
+ 12'b1xxx10110000,
+ 12'b1xxx10110010,
+ 12'b1xxx10110011,
+ 12'b1xxx10110100,
+ 12'b1xxx10111000,
+ 12'b1xxx10111010,
+ 12'b1xxx10111011,
+ 12'b1xxx10111100,
+ 12'b1xxx11000010,
+ 12'b1xxx11000011,
+ 12'b1xxx11001010,
+ 12'b1xxx11001011: state_nxt = (tflg_reg || intr_reg || dmar_reg) ? `sPCA : `sRD2A;
+ default: state_nxt = `sIF1A;
+ endcase
+ end
+ `BLK1: state_nxt = `sBLK2;
+ `BLK2: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10110001,
+ 12'b1xxx10111001: state_nxt = (tflg_reg || intr_reg || dmar_reg) ? `sPCA : `sRD2A;
+ default: state_nxt = `sIF1A;
+ endcase
+ end
+ `PCA: state_nxt = `sPCO;
+ `PCO: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000001110110,
+ 12'b1xxx01110110: state_nxt = `sHLTA;
+ default: state_nxt = `sIF1A;
+ endcase
+ end
+ `HLTA: state_nxt = `sHLTB;
+ `HLTB: state_nxt = (xhlt_reg || (int_req && page_reg[3])) ? `sIF1A : `sHLTA;
+ `IF1A: state_nxt = `sIF1B;
+ `IF1B: state_nxt = `sDEC1;
+ `INTA: state_nxt = `sINTB;
+ `INTB: state_nxt = (vector_int) ? `sADR1 : `sWR1A;
+ `DMA1: state_nxt = `sDMA2;
+ `DMA2: state_nxt = (dmar_reg) ? `sDMA1 : `sIF1A;
+ `RSTE: state_nxt = `sIF1A;
+ default: state_nxt = `sRSTE;
+ endcase
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* transaction type control */
+ /* */
+ /*****************************************************************************************/
+ always @ (inst_reg or page_reg or state_reg or carry_bit or dmar_reg or intr_reg or
+ par_bit or sign_bit or tflg_reg or vector_int or xhlt_reg or zero_bit) begin
+ casex (state_reg) //synopsys parallel_case
+ `IF2B: tran_sel = `TRAN_IF;
+ `OF1B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000000010000,
+ 12'b000000011000,
+ 12'b000011010011,
+ 12'b000011011011,
+ 12'b010000110001,
+ 12'b010000110100,
+ 12'b010000110101,
+ 12'b010000110111,
+ 12'b010000111110,
+ 12'b010000111111,
+ 12'b010000xx0111,
+ 12'b010000xx1111,
+ 12'b010001110xxx,
+ 12'b010001xxx110,
+ 12'b010010000110,
+ 12'b010010001110,
+ 12'b010010010110,
+ 12'b010010011110,
+ 12'b010010100110,
+ 12'b010010101110,
+ 12'b010010110110,
+ 12'b010010111110,
+ 12'b010100110001,
+ 12'b010100110100,
+ 12'b010100110101,
+ 12'b010100110111,
+ 12'b010100111110,
+ 12'b010100111111,
+ 12'b010100xx0111,
+ 12'b010100xx1111,
+ 12'b010101110xxx,
+ 12'b010101xxx110,
+ 12'b010110000110,
+ 12'b010110001110,
+ 12'b010110010110,
+ 12'b010110011110,
+ 12'b010110100110,
+ 12'b010110101110,
+ 12'b010110110110,
+ 12'b010110111110,
+ 12'b1xxx00110010,
+ 12'b1xxx00110011,
+ 12'b1xxx00xx0010,
+ 12'b1xxx00xx0011,
+ 12'b1xxx01010100,
+ 12'b1xxx01010101,
+ 12'b1xxx01100101,
+ 12'b1xxx01100110: tran_sel = `TRAN_IDL;
+ 12'b000000100000: tran_sel = ( zero_bit) ? `TRAN_IF : `TRAN_IDL;
+ 12'b000000101000: tran_sel = ( !zero_bit) ? `TRAN_IF : `TRAN_IDL;
+ 12'b000000110000: tran_sel = ( carry_bit) ? `TRAN_IF : `TRAN_IDL;
+ 12'b000000111000: tran_sel = (!carry_bit) ? `TRAN_IF : `TRAN_IDL;
+ 12'b000000110110: tran_sel = `TRAN_MEM;
+ default: tran_sel = `TRAN_IF;
+ endcase
+ end
+ `OF2B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000000xx0001,
+ 12'b010000100001,
+ 12'b010100100001: tran_sel = `TRAN_IF;
+ 12'b010000110110,
+ 12'b010100110110: tran_sel = `TRAN_MEM;
+ 12'b000011001101: tran_sel = `TRAN_STK;
+ 12'b000011000010: tran_sel = ( !zero_bit) ? `TRAN_IDL : `TRAN_IF;
+ 12'b000011001010: tran_sel = ( zero_bit) ? `TRAN_IDL : `TRAN_IF;
+ 12'b000011010010: tran_sel = (!carry_bit) ? `TRAN_IDL : `TRAN_IF;
+ 12'b000011011010: tran_sel = ( carry_bit) ? `TRAN_IDL : `TRAN_IF;
+ 12'b000011100010: tran_sel = ( !par_bit) ? `TRAN_IDL : `TRAN_IF;
+ 12'b000011101010: tran_sel = ( par_bit) ? `TRAN_IDL : `TRAN_IF;
+ 12'b000011110010: tran_sel = ( !sign_bit) ? `TRAN_IDL : `TRAN_IF;
+ 12'b000011111010: tran_sel = ( sign_bit) ? `TRAN_IDL : `TRAN_IF;
+ 12'b000011000100: tran_sel = ( !zero_bit) ? `TRAN_STK : `TRAN_IF;
+ 12'b000011001100: tran_sel = ( zero_bit) ? `TRAN_STK : `TRAN_IF;
+ 12'b000011010100: tran_sel = (!carry_bit) ? `TRAN_STK : `TRAN_IF;
+ 12'b000011011100: tran_sel = ( carry_bit) ? `TRAN_STK : `TRAN_IF;
+ 12'b000011100100: tran_sel = ( !par_bit) ? `TRAN_STK : `TRAN_IF;
+ 12'b000011101100: tran_sel = ( par_bit) ? `TRAN_STK : `TRAN_IF;
+ 12'b000011110100: tran_sel = ( !sign_bit) ? `TRAN_STK : `TRAN_IF;
+ 12'b000011111100: tran_sel = ( sign_bit) ? `TRAN_STK : `TRAN_IF;
+ default: tran_sel = `TRAN_IDL;
+ endcase
+ end
+ `IF3B: tran_sel = `TRAN_MEM;
+ `ADR2: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000011010011,
+ 12'b000011011011,
+ 12'b1xxx00xxx000,
+ 12'b1xxx00xxx001,
+ 12'b1xxx01110100,
+ 12'b1xxx01xxx000,
+ 12'b1xxx01xxx001,
+ 12'b1xxx10000010,
+ 12'b1xxx10000100,
+ 12'b1xxx10001010,
+ 12'b1xxx10001100,
+ 12'b1xxx10010010,
+ 12'b1xxx10010100,
+ 12'b1xxx10011010,
+ 12'b1xxx10011100,
+ 12'b1xxx10100010,
+ 12'b1xxx10101010,
+ 12'b1xxx10110010,
+ 12'b1xxx10111010,
+ 12'b1xxx11000010,
+ 12'b1xxx11001010: tran_sel = `TRAN_IO;
+ 12'b000011001001,
+ 12'b000011xxx000,
+ 12'b000011xxx111,
+ 12'b000011xx0001,
+ 12'b000011xx0101,
+ 12'b010011100001,
+ 12'b010011100101,
+ 12'b010111100001,
+ 12'b010111100101,
+ 12'b1xxx01000101,
+ 12'b1xxx01001101,
+ 12'b1xxx01100101,
+ 12'b1xxx01100110: tran_sel = `TRAN_STK;
+ default: tran_sel = `TRAN_MEM;
+ endcase
+ end
+ `RD1B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10100001,
+ 12'b1xxx10101001,
+ 12'b1xxx10110001,
+ 12'b1xxx10111001: tran_sel = `TRAN_IDL;
+ 12'b1xxx10000011,
+ 12'b1xxx10001011,
+ 12'b1xxx10010011,
+ 12'b1xxx10011011,
+ 12'b1xxx10100011,
+ 12'b1xxx10100100,
+ 12'b1xxx10101011,
+ 12'b1xxx10101100,
+ 12'b1xxx10110011,
+ 12'b1xxx10110100,
+ 12'b1xxx10111011,
+ 12'b1xxx10111100,
+ 12'b1xxx11000011,
+ 12'b1xxx11001011: tran_sel = `TRAN_IO;
+ 12'b000011001001,
+ 12'b000011xxx000,
+ 12'b000011xx0001,
+ 12'b010011100001,
+ 12'b010111100001,
+ 12'b1xxx01000101,
+ 12'b1xxx01001101: tran_sel = `TRAN_STK;
+ default: tran_sel = `TRAN_MEM;
+ endcase
+ end
+ `RD2B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000011001001,
+ 12'b000011xxx000,
+ 12'b1xxx01000101,
+ 12'b1xxx01001101,
+ 12'b1xxx10100001,
+ 12'b1xxx10101001,
+ 12'b1xxx10110001,
+ 12'b1xxx10111001: tran_sel = `TRAN_IDL;
+ 12'b000000001010,
+ 12'b000000011010,
+ 12'b000000101010,
+ 12'b000000111010,
+ 12'b000001xxx110,
+ 12'b000010000110,
+ 12'b000010001110,
+ 12'b000010010110,
+ 12'b000010011110,
+ 12'b000010100110,
+ 12'b000010101110,
+ 12'b000010110110,
+ 12'b000010111110,
+ 12'b000011011011,
+ 12'b000011xx0001,
+ 12'b001001xxx110,
+ 12'b010000101010,
+ 12'b010000110001,
+ 12'b010000110111,
+ 12'b010000xx0111,
+ 12'b010001xxx110,
+ 12'b010010000110,
+ 12'b010010001110,
+ 12'b010010010110,
+ 12'b010010011110,
+ 12'b010010100110,
+ 12'b010010101110,
+ 12'b010010110110,
+ 12'b010010111110,
+ 12'b010011100001,
+ 12'b010100101010,
+ 12'b010100110001,
+ 12'b010100110111,
+ 12'b010100xx0111,
+ 12'b010101xxx110,
+ 12'b010110000110,
+ 12'b010110001110,
+ 12'b010110010110,
+ 12'b010110011110,
+ 12'b010110100110,
+ 12'b010110101110,
+ 12'b010110110110,
+ 12'b010110111110,
+ 12'b010111100001,
+ 12'b011001xxx110,
+ 12'b011101xxx110,
+ 12'b1xxx00110100,
+ 12'b1xxx00110110,
+ 12'b1xxx00110111,
+ 12'b1xxx00xx0111,
+ 12'b1xxx00xxx000,
+ 12'b1xxx01xxx000,
+ 12'b1xxx01xx1011: tran_sel = `TRAN_IF;
+ 12'b1xxx10000011,
+ 12'b1xxx10001011,
+ 12'b1xxx10010011,
+ 12'b1xxx10011011,
+ 12'b1xxx10100011,
+ 12'b1xxx10100100,
+ 12'b1xxx10101011,
+ 12'b1xxx10101100,
+ 12'b1xxx10110011,
+ 12'b1xxx10110100,
+ 12'b1xxx10111011,
+ 12'b1xxx10111100,
+ 12'b1xxx11000011,
+ 12'b1xxx11001011: tran_sel = `TRAN_IO;
+ 12'b000011100011,
+ 12'b0001xxxxxxxx,
+ 12'b010011100011,
+ 12'b010111100011: tran_sel = `TRAN_STK;
+ default: tran_sel = `TRAN_MEM;
+ endcase
+ end
+ `WR1B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10010010,
+ 12'b1xxx10010100,
+ 12'b1xxx10011010,
+ 12'b1xxx10011100,
+ 12'b1xxx10110010,
+ 12'b1xxx10111010,
+ 12'b1xxx11000010,
+ 12'b1xxx11001010: tran_sel = (tflg_reg || intr_reg || dmar_reg) ? `TRAN_IDL : `TRAN_IO;
+ 12'b1xxx10010011,
+ 12'b1xxx10011011,
+ 12'b1xxx10110000,
+ 12'b1xxx10110011,
+ 12'b1xxx10110100,
+ 12'b1xxx10111000,
+ 12'b1xxx10111011,
+ 12'b1xxx10111100,
+ 12'b1xxx11000011,
+ 12'b1xxx11001011: tran_sel = (tflg_reg || intr_reg || dmar_reg) ? `TRAN_IDL : `TRAN_MEM;
+ 12'b000000100010,
+ 12'b010000100010,
+ 12'b010000111110,
+ 12'b010000111111,
+ 12'b010000xx1111,
+ 12'b010100100010,
+ 12'b010100111110,
+ 12'b010100111111,
+ 12'b010100xx1111,
+ 12'b1xxx00111110,
+ 12'b1xxx00111111,
+ 12'b1xxx00xx1111,
+ 12'b1xxx01xx0011: tran_sel = `TRAN_MEM;
+ 12'b000011001101,
+ 12'b000011100011,
+ 12'b000011xxx100,
+ 12'b000011xxx111,
+ 12'b000011xx0101,
+ 12'b0001xxxxxxxx,
+ 12'b010011100011,
+ 12'b010011100101,
+ 12'b010111100011,
+ 12'b010111100101,
+ 12'b1xxx01100101,
+ 12'b1xxx01100110: tran_sel = `TRAN_STK;
+ default: tran_sel = `TRAN_IF;
+ endcase
+ end
+ `WR2B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10010010,
+ 12'b1xxx10010100,
+ 12'b1xxx10011010,
+ 12'b1xxx10011100,
+ 12'b1xxx10110010,
+ 12'b1xxx11000010,
+ 12'b1xxx11001010,
+ 12'b1xxx10111010: tran_sel = (tflg_reg || intr_reg || dmar_reg) ? `TRAN_IDL : `TRAN_IO;
+ 12'b1xxx10010011,
+ 12'b1xxx10011011,
+ 12'b1xxx10110000,
+ 12'b1xxx10110011,
+ 12'b1xxx10110100,
+ 12'b1xxx10111000,
+ 12'b1xxx10111011,
+ 12'b1xxx10111100,
+ 12'b1xxx11000011,
+ 12'b1xxx11001011: tran_sel = (tflg_reg || intr_reg || dmar_reg) ? `TRAN_IDL : `TRAN_MEM;
+ default: tran_sel = `TRAN_IF;
+ endcase
+ end
+ `BLK2: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10110001,
+ 12'b1xxx10111001: tran_sel = (tflg_reg || intr_reg || dmar_reg) ? `TRAN_IDL : `TRAN_MEM;
+ default: tran_sel = `TRAN_IF;
+ endcase
+ end
+ `PCO: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000001110110,
+ 12'b1xxx01110110: tran_sel = `TRAN_IDL;
+ default: tran_sel = `TRAN_IF;
+ endcase
+ end
+ `IF1B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx01000101,
+ 12'b1xxx01001101,
+ 12'b000011110011,
+ 12'b0001xxxxxxxx: tran_sel = `TRAN_IF;
+ default: tran_sel = (dmar_reg) ? `TRAN_IDL :
+ (intr_reg) ? `TRAN_IAK : `TRAN_IF;
+ endcase
+ end
+ `HLTB: tran_sel = (xhlt_reg || (page_reg[3] && int_req)) ? `TRAN_IF : `TRAN_IDL;
+ `INTB: tran_sel = (vector_int) ? `TRAN_IDL : `TRAN_MEM;
+ `DMA2: tran_sel = (dmar_reg) ? `TRAN_IDL : `TRAN_IF;
+ `RSTE: tran_sel = `TRAN_IF;
+ default: tran_sel = `TRAN_RSTVAL;
+ endcase
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* special transaction identifiers */
+ /* */
+ /*****************************************************************************************/
+ always @ (inst_reg or page_reg or state_reg or xhlt_reg) begin
+ casex (state_reg)
+ `PCO,
+ `HLTB: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000001110110: halt_nxt = !xhlt_reg;
+ 12'b1xxx01110110: halt_nxt = !int_req;
+ default: halt_nxt = 1'b0;
+ endcase
+ end
+ default: halt_nxt = 1'b0;
+ endcase
+ end
+
+ always @ (inst_reg or page_reg or state_reg) begin
+ casex (state_reg)
+ `RD2B: begin
+ casex ({page_reg, inst_reg})
+ 12'b1xxx01001101: reti_nxt = 1'b1;
+ default: reti_nxt = 1'b0;
+ endcase
+ end
+ default: reti_nxt = 1'b0;
+ endcase
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* output inhibit */
+ /* */
+ /*****************************************************************************************/
+ always @ (inst_reg or page_reg or state_reg or dmar_reg or xhlt_reg) begin
+ casex (state_reg)
+ `IF1B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx01000101,
+ 12'b1xxx01001101,
+ 12'b000011110011,
+ 12'b0001xxxxxxxx: output_inh = 1'b0;
+ default: output_inh = dmar_reg;
+ endcase
+ end
+ `DMA2: output_inh = dmar_reg;
+ `PCO,
+ `HLTB: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000001110110: output_inh = !xhlt_reg;
+ 12'b1xxx01110110: output_inh = !int_req;
+ default: output_inh = 1'b0;
+ endcase
+ end
+ default: output_inh = 1'b0;
+ endcase
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* address output control */
+ /* */
+ /*****************************************************************************************/
+ always @ (inst_reg or page_reg or state_reg or carry_bit or par_bit or sign_bit or
+ vector_int or zero_bit) begin
+ casex (state_reg) //synopsys parallel_case
+ `DEC1: begin
+ casex (inst_reg) //synopsys parallel_case
+ 8'b00000010,
+ 8'b00001010,
+ 8'b00010010,
+ 8'b00011010,
+ 8'b11101001,
+ 8'b11xx0101,
+ 8'b11xxx111: add_sel = `ADD_ALU;
+ 8'b00110100,
+ 8'b00110101,
+ 8'b00110110,
+ 8'b011100xx,
+ 8'b0111010x,
+ 8'b01110111,
+ 8'b010xx110,
+ 8'b0110x110,
+ 8'b01111110,
+ 8'b10000110,
+ 8'b10001110,
+ 8'b10010110,
+ 8'b10011110,
+ 8'b10100110,
+ 8'b10101110,
+ 8'b10110110,
+ 8'b10111110: add_sel = `ADD_HL;
+ 8'b11000000: add_sel = ( !zero_bit) ? `ADD_SP : `ADD_PC;
+ 8'b11001000: add_sel = ( zero_bit) ? `ADD_SP : `ADD_PC;
+ 8'b11010000: add_sel = (!carry_bit) ? `ADD_SP : `ADD_PC;
+ 8'b11011000: add_sel = ( carry_bit) ? `ADD_SP : `ADD_PC;
+ 8'b11100000: add_sel = ( !par_bit) ? `ADD_SP : `ADD_PC;
+ 8'b11101000: add_sel = ( par_bit) ? `ADD_SP : `ADD_PC;
+ 8'b11110000: add_sel = ( !sign_bit) ? `ADD_SP : `ADD_PC;
+ 8'b11111000: add_sel = ( sign_bit) ? `ADD_SP : `ADD_PC;
+ 8'b11xx0001,
+ 8'b11100011,
+ 8'b11001001: add_sel = `ADD_SP;
+ default: add_sel = `ADD_PC;
+ endcase
+ end
+ `DEC2: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b010011100101,
+ 12'b010011101001,
+ 12'b010111100101,
+ 12'b010111101001,
+ 12'b1xxx01xxx000,
+ 12'b1xxx01xxx001,
+ 12'b1xxx10000011,
+ 12'b1xxx10000100,
+ 12'b1xxx10001011,
+ 12'b1xxx10001100,
+ 12'b1xxx10010011,
+ 12'b1xxx10010100,
+ 12'b1xxx10011011,
+ 12'b1xxx10011100,
+ 12'b1xxx10100000,
+ 12'b1xxx10100001,
+ 12'b1xxx10100010,
+ 12'b1xxx10100011,
+ 12'b1xxx10101000,
+ 12'b1xxx10101001,
+ 12'b1xxx10101010,
+ 12'b1xxx10101011,
+ 12'b1xxx10110000,
+ 12'b1xxx10110001,
+ 12'b1xxx10110010,
+ 12'b1xxx10110011,
+ 12'b1xxx10110100,
+ 12'b1xxx10111000,
+ 12'b1xxx10111001,
+ 12'b1xxx10111010,
+ 12'b1xxx10111011,
+ 12'b1xxx10111100,
+ 12'b1xxx11000010,
+ 12'b1xxx11000011,
+ 12'b1xxx11001010,
+ 12'b1xxx11001011: add_sel = `ADD_ALU;
+ 12'b1xxx10000010,
+ 12'b1xxx10001010,
+ 12'b1xxx10010010,
+ 12'b1xxx10011010: add_sel = `ADD_ALU8;
+ 12'b001000000110,
+ 12'b001000001110,
+ 12'b001000010110,
+ 12'b001000011110,
+ 12'b001000100110,
+ 12'b001000101110,
+ 12'b001000110110,
+ 12'b001000111110,
+ 12'b001001xxx110,
+ 12'b001010xxx110,
+ 12'b001011xxx110,
+ 12'b1xxx10100100,
+ 12'b1xxx10101100,
+ 12'b1xxx00110100,
+ 12'b1xxx00110110,
+ 12'b1xxx00110111,
+ 12'b1xxx00111110,
+ 12'b1xxx00111111,
+ 12'b1xxx00xx0111,
+ 12'b1xxx00xx1111,
+ 12'b1xxx01100111,
+ 12'b1xxx01101111: add_sel = `ADD_HL;
+ 12'b010011100001,
+ 12'b010011100011,
+ 12'b010111100001,
+ 12'b010111100011,
+ 12'b1xxx01000101,
+ 12'b1xxx01001101: add_sel = `ADD_SP;
+ default: add_sel = `ADD_PC;
+ endcase
+ end
+ `OF2A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000011001101,
+ 12'b010000110110,
+ 12'b010100110110: add_sel = `ADD_ALU;
+ 12'b000011000100: add_sel = ( !zero_bit) ? `ADD_ALU : `ADD_PC;
+ 12'b000011001100: add_sel = ( zero_bit) ? `ADD_ALU : `ADD_PC;
+ 12'b000011010100: add_sel = (!carry_bit) ? `ADD_ALU : `ADD_PC;
+ 12'b000011011100: add_sel = ( carry_bit) ? `ADD_ALU : `ADD_PC;
+ 12'b000011100100: add_sel = ( !par_bit) ? `ADD_ALU : `ADD_PC;
+ 12'b000011101100: add_sel = ( par_bit) ? `ADD_ALU : `ADD_PC;
+ 12'b000011110100: add_sel = ( !sign_bit) ? `ADD_ALU : `ADD_PC;
+ 12'b000011111100: add_sel = ( sign_bit) ? `ADD_ALU : `ADD_PC;
+ default: add_sel = `ADD_PC;
+ endcase
+ end
+ `IF3A: add_sel = `ADD_ALU;
+ `ADR1: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx01110100,
+ 12'b1xxx00xxx000,
+ 12'b1xxx00xxx001: add_sel = `ADD_ALU8;
+ default: add_sel = `ADD_ALU;
+ endcase
+ end
+ `RD1A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx100xx011: add_sel = `ADD_ALU8;
+ default: add_sel = `ADD_ALU;
+ endcase
+ end
+ `RD2A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000011100011,
+ 12'b0001xxxxxxxx,
+ 12'b010000110100,
+ 12'b010000110101,
+ 12'b010011100011,
+ 12'b010100110100,
+ 12'b010100110101,
+ 12'b010111100011,
+ 12'b011000000110,
+ 12'b011000001110,
+ 12'b011000010110,
+ 12'b011000011110,
+ 12'b011000100110,
+ 12'b011000101110,
+ 12'b011000110110,
+ 12'b011000111110,
+ 12'b011010xxx110,
+ 12'b011011xxx110,
+ 12'b011100000110,
+ 12'b011100001110,
+ 12'b011100010110,
+ 12'b011100011110,
+ 12'b011100100110,
+ 12'b011100101110,
+ 12'b011100110110,
+ 12'b011100111110,
+ 12'b011110xxx110,
+ 12'b011111xxx110,
+ 12'b1xxx10000010,
+ 12'b1xxx10001010,
+ 12'b1xxx10010010,
+ 12'b1xxx10010100,
+ 12'b1xxx10011010,
+ 12'b1xxx10011100,
+ 12'b1xxx10100000,
+ 12'b1xxx10100001,
+ 12'b1xxx10100010,
+ 12'b1xxx10100011,
+ 12'b1xxx10101000,
+ 12'b1xxx10101001,
+ 12'b1xxx10101010,
+ 12'b1xxx10101011,
+ 12'b1xxx10110000,
+ 12'b1xxx10110001,
+ 12'b1xxx10110010,
+ 12'b1xxx10110011,
+ 12'b1xxx10110100,
+ 12'b1xxx10111000,
+ 12'b1xxx10111001,
+ 12'b1xxx10111010,
+ 12'b1xxx10111011,
+ 12'b1xxx10111100,
+ 12'b1xxx11000010,
+ 12'b1xxx11000011,
+ 12'b1xxx11001010,
+ 12'b1xxx11001011: add_sel = `ADD_ALU;
+ 12'b1xxx100xx011: add_sel = `ADD_ALU8;
+ 12'b000000110100,
+ 12'b000000110101,
+ 12'b000000xxx100,
+ 12'b000000xxx101,
+ 12'b001000000110,
+ 12'b001000000xxx,
+ 12'b001000001110,
+ 12'b001000001xxx,
+ 12'b001000010110,
+ 12'b001000010xxx,
+ 12'b001000011110,
+ 12'b001000011xxx,
+ 12'b001000100110,
+ 12'b001000100xxx,
+ 12'b001000101110,
+ 12'b001000101xxx,
+ 12'b001000110110,
+ 12'b001000110xxx,
+ 12'b001000111110,
+ 12'b001000111xxx,
+ 12'b001010xxx110,
+ 12'b001010xxxxxx,
+ 12'b001011xxx110,
+ 12'b001011xxxxxx,
+ 12'b1xxx01100111,
+ 12'b1xxx01101111: add_sel = `ADD_HL;
+ default: add_sel = `ADD_PC;
+ endcase
+ end
+ `WR1A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10010010,
+ 12'b1xxx10011010: add_sel = `ADD_ALU8;
+ 12'b1xxx10000010,
+ 12'b1xxx10000011,
+ 12'b1xxx10000100,
+ 12'b1xxx10001010,
+ 12'b1xxx10001011,
+ 12'b1xxx10001100,
+ 12'b1xxx10100000,
+ 12'b1xxx10100010,
+ 12'b1xxx10100011,
+ 12'b1xxx10100100,
+ 12'b1xxx10101000,
+ 12'b1xxx10101010,
+ 12'b1xxx10101011,
+ 12'b1xxx10101100: add_sel = `ADD_PC;
+ default: add_sel = `ADD_ALU;
+ endcase
+ end
+ `WR2A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000011001101,
+ 12'b000011xxx100,
+ 12'b000011xxx111,
+ 12'b0001xxxxxxxx,
+ 12'b1xxx10000011,
+ 12'b1xxx10001011,
+ 12'b1xxx10010011,
+ 12'b1xxx10010100,
+ 12'b1xxx10011011,
+ 12'b1xxx10011100,
+ 12'b1xxx10100000,
+ 12'b1xxx10100010,
+ 12'b1xxx10100011,
+ 12'b1xxx10101000,
+ 12'b1xxx10101010,
+ 12'b1xxx10101011,
+ 12'b1xxx10110000,
+ 12'b1xxx10110010,
+ 12'b1xxx10110011,
+ 12'b1xxx10110100,
+ 12'b1xxx10111000,
+ 12'b1xxx10111010,
+ 12'b1xxx10111011,
+ 12'b1xxx10111100,
+ 12'b1xxx11000010,
+ 12'b1xxx11000011,
+ 12'b1xxx11001010,
+ 12'b1xxx11001011: add_sel = `ADD_ALU;
+ 12'b1xxx10000010,
+ 12'b1xxx10001010,
+ 12'b1xxx10010010,
+ 12'b1xxx10011010: add_sel = `ADD_ALU8;
+ default: add_sel = `ADD_PC;
+ endcase
+ end
+ `BLK1: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10110001,
+ 12'b1xxx10111001: add_sel = `ADD_ALU;
+ default: add_sel = `ADD_PC;
+ endcase
+ end
+ `PCA: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000000010000,
+ 12'b000000011000,
+ 12'b0000001xx000,
+ 12'b000011000011,
+ 12'b000011001001,
+ 12'b000011xxx000,
+ 12'b000011xxx010,
+ 12'b1xxx01000101,
+ 12'b1xxx01001101: add_sel = `ADD_PC;
+ default: add_sel = `ADD_ALU;
+ endcase
+ end
+ `IF1A: add_sel = `ADD_PC;
+ `INTA: add_sel = (vector_int) ? `ADD_PC : `ADD_ALU;
+ `HLTA: add_sel = `ADD_PC;
+ `DMA1: add_sel = `ADD_PC;
+ default: add_sel = `ADD_RSTVAL;
+ endcase
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* program counter control */
+ /* */
+ /*****************************************************************************************/
+ always @ (inst_reg or page_reg or state_reg or carry_bit or par_bit or sign_bit or
+ tflg_reg or zero_bit) begin
+ casex (state_reg) //synopsys parallel_case
+ `DEC1: begin
+ casex (inst_reg) //synopsys parallel_case
+ 8'b00000000,
+ 8'b00000111,
+ 8'b00001000,
+ 8'b00001111,
+ 8'b00010111,
+ 8'b00011111,
+ 8'b00100111,
+ 8'b00101111,
+ 8'b00110111,
+ 8'b00111111,
+ 8'b000xx10x,
+ 8'b0010x10x,
+ 8'b0011110x,
+ 8'b00xx0011,
+ 8'b00xx1001,
+ 8'b00xx1011,
+ 8'b010xx0xx,
+ 8'b0110x0xx,
+ 8'b011110xx,
+ 8'b010xx10x,
+ 8'b0110x10x,
+ 8'b0111110x,
+ 8'b010xx111,
+ 8'b0110x111,
+ 8'b01111111,
+ 8'b10xxx0xx,
+ 8'b10xxx10x,
+ 8'b10xxx111,
+ 8'b11011001,
+ 8'b11101011,
+ 8'b11111001,
+ 8'b11111011: pc_sel = `PC_NILD;
+ 8'b01110110,
+ 8'b11xxx111,
+ 8'b00000010,
+ 8'b00001010,
+ 8'b00010010,
+ 8'b00011010,
+ 8'b00110100,
+ 8'b00110101,
+ 8'b011100xx,
+ 8'b0111010x,
+ 8'b01110111,
+ 8'b010xx110,
+ 8'b0110x110,
+ 8'b01111110,
+ 8'b10000110,
+ 8'b10001110,
+ 8'b10010110,
+ 8'b10011110,
+ 8'b10100110,
+ 8'b10101110,
+ 8'b10110110,
+ 8'b10111110,
+ 8'b11xx0001,
+ 8'b11xx0101,
+ 8'b11100011: pc_sel = `PC_NUL;
+ default: pc_sel = `PC_LD;
+ endcase
+ end
+ `DEC2: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b001000000110,
+ 12'b001000001110,
+ 12'b001000010110,
+ 12'b001000011110,
+ 12'b001000100110,
+ 12'b001000101110,
+ 12'b001000110110,
+ 12'b001000111110,
+ 12'b001001xxx110,
+ 12'b001010xxx110,
+ 12'b001011xxx110,
+ 12'b010011100001,
+ 12'b010011100011,
+ 12'b010011100101,
+ 12'b010111100001,
+ 12'b010111100011,
+ 12'b010111100101,
+ 12'b1xxx00110100,
+ 12'b1xxx00110110,
+ 12'b1xxx00110111,
+ 12'b1xxx00111110,
+ 12'b1xxx00111111,
+ 12'b1xxx00xx0111,
+ 12'b1xxx00xx1111,
+ 12'b1xxx01100111,
+ 12'b1xxx01101111,
+ 12'b1xxx01110110,
+ 12'b1xxx01xxx000,
+ 12'b1xxx01xxx001,
+ 12'b1xxx10000010,
+ 12'b1xxx10000011,
+ 12'b1xxx10000100,
+ 12'b1xxx10001010,
+ 12'b1xxx10001011,
+ 12'b1xxx10001100,
+ 12'b1xxx10010010,
+ 12'b1xxx10010011,
+ 12'b1xxx10010100,
+ 12'b1xxx10011010,
+ 12'b1xxx10011011,
+ 12'b1xxx10011100,
+ 12'b1xxx10100000,
+ 12'b1xxx10100001,
+ 12'b1xxx10100010,
+ 12'b1xxx10100011,
+ 12'b1xxx10100100,
+ 12'b1xxx10101000,
+ 12'b1xxx10101001,
+ 12'b1xxx10101010,
+ 12'b1xxx10101011,
+ 12'b1xxx10101100,
+ 12'b1xxx10110000,
+ 12'b1xxx10110001,
+ 12'b1xxx10110010,
+ 12'b1xxx10110011,
+ 12'b1xxx10110100,
+ 12'b1xxx10111000,
+ 12'b1xxx10111001,
+ 12'b1xxx10111010,
+ 12'b1xxx10111011,
+ 12'b1xxx10111100,
+ 12'b1xxx11000010,
+ 12'b1xxx11000011,
+ 12'b1xxx11001010,
+ 12'b1xxx11001011: pc_sel = `PC_NUL;
+ 12'b010000100001,
+ 12'b010000100010,
+ 12'b010000100110,
+ 12'b010000101010,
+ 12'b010000101110,
+ 12'b010000110001,
+ 12'b010000110100,
+ 12'b010000110101,
+ 12'b010000110110,
+ 12'b010000110111,
+ 12'b010000111110,
+ 12'b010000111111,
+ 12'b010000xx0111,
+ 12'b010000xx1111,
+ 12'b010001110xxx,
+ 12'b010001xxx110,
+ 12'b010010000110,
+ 12'b010010001110,
+ 12'b010010010110,
+ 12'b010010011110,
+ 12'b010010100110,
+ 12'b010010101110,
+ 12'b010010110110,
+ 12'b010010111110,
+ 12'b010011101001,
+ 12'b010100100001,
+ 12'b010100100010,
+ 12'b010100100110,
+ 12'b010100101010,
+ 12'b010100101110,
+ 12'b010100110001,
+ 12'b010100110100,
+ 12'b010100110101,
+ 12'b010100110110,
+ 12'b010100110111,
+ 12'b010100111110,
+ 12'b010100111111,
+ 12'b010100xx0111,
+ 12'b010100xx1111,
+ 12'b010101110xxx,
+ 12'b010101xxx110,
+ 12'b010110000110,
+ 12'b010110001110,
+ 12'b010110010110,
+ 12'b010110011110,
+ 12'b010110100110,
+ 12'b010110101110,
+ 12'b010110110110,
+ 12'b010110111110,
+ 12'b010111101001,
+ 12'b010011001011, //DD+CB prefix
+ 12'b010111001011, //FD+CB prefix
+ 12'b1xxx00110010,
+ 12'b1xxx00110011,
+ 12'b1xxx00xx0010,
+ 12'b1xxx00xx0011,
+ 12'b1xxx00xxx000,
+ 12'b1xxx00xxx001,
+ 12'b1xxx01000101,
+ 12'b1xxx01001101,
+ 12'b1xxx01010100,
+ 12'b1xxx01010101,
+ 12'b1xxx01100100,
+ 12'b1xxx01100101,
+ 12'b1xxx01100110,
+ 12'b1xxx01110100,
+ 12'b1xxx01xx1011,
+ 12'b1xxx01xx0011: pc_sel = `PC_LD;
+ default: pc_sel = `PC_NILD;
+ endcase
+ end
+ `OF2A,
+ `IF3A: pc_sel = `PC_LD;
+ `RD1B,
+ `RD2B: pc_sel = `PC_INT;
+ `WR2B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000011001101,
+ 12'b000011xxx100,
+ 12'b000011xxx111,
+ 12'b0001xxxxxxxx: pc_sel = `PC_LD;
+ default: pc_sel = `PC_NUL;
+ endcase
+ end
+ `PCA: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000000010000: pc_sel = (tflg_reg) ? `PC_NUL : `PC_LD;
+ 12'b000000011000,
+ 12'b0000001xx000,
+ 12'b000011000011,
+ 12'b000011001001,
+ 12'b000011xxx000,
+ 12'b000011xxx010,
+ 12'b1xxx01000101,
+ 12'b1xxx01001101: pc_sel = `PC_LD;
+ default: pc_sel = `PC_NUL;
+ endcase
+ end
+ `PCO: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000011101001,
+ 12'b010011101001,
+ 12'b010111101001,
+ 12'b1xxx10010010,
+ 12'b1xxx10010011,
+ 12'b1xxx10010100,
+ 12'b1xxx10011010,
+ 12'b1xxx10011011,
+ 12'b1xxx10011100,
+ 12'b1xxx10110000,
+ 12'b1xxx10110001,
+ 12'b1xxx10110010,
+ 12'b1xxx10110011,
+ 12'b1xxx10110100,
+ 12'b1xxx10111000,
+ 12'b1xxx10111001,
+ 12'b1xxx10111010,
+ 12'b1xxx10111011,
+ 12'b1xxx10111100,
+ 12'b1xxx11000010,
+ 12'b1xxx11000011,
+ 12'b1xxx11001010,
+ 12'b1xxx11001011: pc_sel = `PC_LD;
+ default: pc_sel = `PC_NUL;
+ endcase
+ end
+ `IF1A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b0001xxxxxxxx,
+ 12'b1xxx01000101,
+ 12'b1xxx01001101: pc_sel = `PC_LD;
+ 12'b1xxx10010010,
+ 12'b1xxx10010011,
+ 12'b1xxx10010100,
+ 12'b1xxx10011010,
+ 12'b1xxx10011011,
+ 12'b1xxx10011100,
+ 12'b1xxx10110000,
+ 12'b1xxx10110001,
+ 12'b1xxx10110010,
+ 12'b1xxx10110011,
+ 12'b1xxx10110100,
+ 12'b1xxx10111000,
+ 12'b1xxx10111001,
+ 12'b1xxx10111010,
+ 12'b1xxx10111011,
+ 12'b1xxx10111100,
+ 12'b1xxx11000010,
+ 12'b1xxx11000011,
+ 12'b1xxx11001010,
+ 12'b1xxx11001011: pc_sel = `PC_NILD2;
+ default: pc_sel = `PC_NILD;
+ endcase
+ end
+ `HLTA: pc_sel = `PC_INT;
+ `DMA1: pc_sel = `PC_DMA;
+ default: pc_sel = `PC_NUL;
+ endcase
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* interrupt ack and dma ack */
+ /* */
+ /*****************************************************************************************/
+ always @ (inst_reg or page_reg or state_reg) begin
+ casex (state_reg) //synopsys parallel_case
+ `IF1B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx01000101,
+ 12'b1xxx01001101,
+ 12'b000011110011,
+ 12'b0001xxxxxxxx: ld_inta = 1'b0;
+ default: ld_inta = 1'b1;
+ endcase
+ end
+ default: ld_inta = 1'b0;
+ endcase
+ end
+
+ always @ (inst_reg or page_reg or state_reg) begin
+ casex (state_reg) //synopsys parallel_case
+ `IF1B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx01000101,
+ 12'b1xxx01001101,
+ 12'b000011110011,
+ 12'b0001xxxxxxxx: ld_dmaa = 1'b0;
+ default: ld_dmaa = 1'b1;
+ endcase
+ end
+ `HLTB,
+ `DMA2: ld_dmaa = 1'b1;
+ default: ld_dmaa = 1'b0;
+ endcase
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* data input register control */
+ /* */
+ /*****************************************************************************************/
+ always @ (inst_reg or page_reg or state_reg) begin
+ casex (state_reg) //synopsys parallel_case
+ `OF1B: di_ctl = `DI_DI10;
+ `OF2B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b010000110110,
+ 12'b010100110110: di_ctl = `DI_DI0;
+ default: di_ctl = `DI_DI1;
+ endcase
+ end
+ `RD1B: di_ctl = `DI_DI0;
+ `RD2B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000000101010,
+ 12'b000011001001,
+ 12'b000011100011,
+ 12'b000011xxx000,
+ 12'b000011xx0001,
+ 12'b0001xxxxxxxx,
+ 12'b010000101010,
+ 12'b010000110001,
+ 12'b010000110111,
+ 12'b010000xx0111,
+ 12'b010011100001,
+ 12'b010011100011,
+ 12'b010100101010,
+ 12'b010100110001,
+ 12'b010100110111,
+ 12'b010100xx0111,
+ 12'b010111100001,
+ 12'b010111100011,
+ 12'b1xxx00110110,
+ 12'b1xxx00110111,
+ 12'b1xxx00xx0111,
+ 12'b1xxx01000101,
+ 12'b1xxx01001101,
+ 12'b1xxx01xx1011: di_ctl = `DI_DI1;
+ default: di_ctl = `DI_DI0;
+ endcase
+ end
+ `INTB: di_ctl = `DI_DI0;
+ default: di_ctl = `DI_NUL;
+ endcase
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* data output register control */
+ /* */
+ /*****************************************************************************************/
+ always @ (inst_reg or page_reg or state_reg) begin
+ casex (state_reg) //synopsys parallel_case
+ `WR1A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000011001101,
+ 12'b000011xxx100,
+ 12'b000011xx0101,
+ 12'b000011xxx111,
+ 12'b0001xxxxxxxx,
+ 12'b010011100101,
+ 12'b010111100101,
+ 12'b1xxx01100101,
+ 12'b1xxx01100110: do_ctl = `DO_MSB;
+ 12'b1xxx10000011,
+ 12'b1xxx10001011,
+ 12'b1xxx10010011,
+ 12'b1xxx10011011,
+ 12'b1xxx10100011,
+ 12'b1xxx10100100,
+ 12'b1xxx10101011,
+ 12'b1xxx10101100,
+ 12'b1xxx10110011,
+ 12'b1xxx10110100,
+ 12'b1xxx10111011,
+ 12'b1xxx10111100,
+ 12'b1xxx11000011,
+ 12'b1xxx11001011: do_ctl = `DO_IO;
+ default: do_ctl = `DO_LSB;
+ endcase
+ end
+ `WR2A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000000100010,
+ 12'b000011100011,
+ 12'b010000100010,
+ 12'b010000111110,
+ 12'b010000111111,
+ 12'b010000xx1111,
+ 12'b010011100011,
+ 12'b010100100010,
+ 12'b010100111110,
+ 12'b010100111111,
+ 12'b010100xx1111,
+ 12'b010111100011,
+ 12'b1xxx00111110,
+ 12'b1xxx00111111,
+ 12'b1xxx00xx1111,
+ 12'b1xxx01xx0011: do_ctl = `DO_MSB;
+ 12'b000011010011,
+ 12'b1xxx00xxx001,
+ 12'b1xxx01xxx001,
+ 12'b1xxx10000011,
+ 12'b1xxx10001011,
+ 12'b1xxx10010011,
+ 12'b1xxx10011011,
+ 12'b1xxx10100011,
+ 12'b1xxx10101011,
+ 12'b1xxx10110011,
+ 12'b1xxx10110100,
+ 12'b1xxx10111100,
+ 12'b1xxx11000011,
+ 12'b1xxx11001011,
+ 12'b1xxx10111011: do_ctl = `DO_IO;
+ default: do_ctl = `DO_LSB;
+ endcase
+ end
+ default: do_ctl = `DO_NUL;
+ endcase
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* alu operation control */
+ /* */
+ /*****************************************************************************************/
+ always @ (inst_reg or page_reg or state_reg or carry_bit or par_bit or sign_bit or
+ zero_bit) begin
+ casex (state_reg) //synopsys parallel_case
+ `DEC1: begin
+ casex (inst_reg) //synopsys parallel_case
+ 8'b00xx0011,
+ 8'b00xx1001,
+ 8'b00xx1011,
+ 8'b11100011,
+ 8'b11xx0101,
+ 8'b11xxx111: aluop_sel = `ALUOP_ADD;
+ 8'b10001xxx: aluop_sel = `ALUOP_BADC;
+ 8'b00010000,
+ 8'b00xxx100,
+ 8'b10000xxx: aluop_sel = `ALUOP_BADD;
+ 8'b10100xxx: aluop_sel = `ALUOP_BAND;
+ 8'b00xxx101: aluop_sel = `ALUOP_BDEC;
+ 8'b10110xxx: aluop_sel = `ALUOP_BOR;
+ 8'b10011xxx: aluop_sel = `ALUOP_BSBC;
+ 8'b10010xxx,
+ 8'b10111xxx: aluop_sel = `ALUOP_BSUB;
+ 8'b00101111,
+ 8'b10101xxx: aluop_sel = `ALUOP_BXOR;
+ 8'b00111111: aluop_sel = `ALUOP_CCF;
+ 8'b00100111: aluop_sel = `ALUOP_DAA;
+ 8'b00010111: aluop_sel = `ALUOP_RLA;
+ 8'b00000111: aluop_sel = `ALUOP_RLCA;
+ 8'b00011111: aluop_sel = `ALUOP_RRA;
+ 8'b00001111: aluop_sel = `ALUOP_RRCA;
+ 8'b00110111: aluop_sel = `ALUOP_SCF;
+ default: aluop_sel = `ALUOP_PASS;
+ endcase
+ end
+ `IF2B: aluop_sel = `ALUOP_ADD;
+ `DEC2: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx01xx1010: aluop_sel = `ALUOP_ADC;
+ 12'b1xxx10100100,
+ 12'b1xxx10101100,
+ 12'b010000100011,
+ 12'b010000101011,
+ 12'b010000xx1001,
+ 12'b010011100101,
+ 12'b010100100011,
+ 12'b010100101011,
+ 12'b010100xx1001,
+ 12'b010111100101: aluop_sel = `ALUOP_ADD;
+ 12'b1xxx01010111,
+ 12'b1xxx01011111: aluop_sel = `ALUOP_APAS;
+ 12'b010010001100,
+ 12'b010010001101,
+ 12'b010110001100,
+ 12'b010110001101: aluop_sel = `ALUOP_BADC;
+ 12'b010010000100,
+ 12'b010010000101,
+ 12'b010110000100,
+ 12'b010110000101,
+ 12'b010000100100,
+ 12'b010000101100,
+ 12'b010100100100,
+ 12'b010100101100: aluop_sel = `ALUOP_BADD;
+ 12'b010010100100,
+ 12'b010010100101,
+ 12'b010110100100,
+ 12'b010110100101,
+ 12'b001001xxxxxx,
+ 12'b001010xxxxxx,
+ 12'b1xxx00xxx100: aluop_sel = `ALUOP_BAND;
+ 12'b010000100101,
+ 12'b010000101101,
+ 12'b010100100101,
+ 12'b010100101101: aluop_sel = `ALUOP_BDEC;
+ 12'b010010110100,
+ 12'b010010110101,
+ 12'b010110110100,
+ 12'b010110110101,
+ 12'b001011xxxxxx: aluop_sel = `ALUOP_BOR;
+ 12'b010010011100,
+ 12'b010010011101,
+ 12'b010110011100,
+ 12'b010110011101: aluop_sel = `ALUOP_BSBC;
+ 12'b010010111100,
+ 12'b010010111101,
+ 12'b010110111100,
+ 12'b010110111101,
+ 12'b010010010100,
+ 12'b010010010101,
+ 12'b010110010100,
+ 12'b010110010101,
+ 12'b1xxx01000100: aluop_sel = `ALUOP_BSUB;
+ 12'b010010101100,
+ 12'b010010101101,
+ 12'b010110101100,
+ 12'b010110101101: aluop_sel = `ALUOP_BXOR;
+ 12'b1xxx01xx1100: aluop_sel = `ALUOP_MLT;
+ 12'b001000010xxx: aluop_sel = `ALUOP_RL;
+ 12'b001000000xxx: aluop_sel = `ALUOP_RLC;
+ 12'b001000011xxx: aluop_sel = `ALUOP_RR;
+ 12'b001000001xxx: aluop_sel = `ALUOP_RRC;
+ 12'b1xxx01xx0010: aluop_sel = `ALUOP_SBC;
+ 12'b001000100xxx: aluop_sel = `ALUOP_SLA;
+ 12'b001000110xxx: aluop_sel = `ALUOP_SLL;
+ 12'b001000101xxx: aluop_sel = `ALUOP_SRA;
+ 12'b001000111xxx: aluop_sel = `ALUOP_SRL;
+ default: aluop_sel = `ALUOP_PASS;
+ endcase
+ end
+ `OF1B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000000100000: aluop_sel = ( !zero_bit) ? `ALUOP_ADS : `ALUOP_ADD;
+ 12'b000000101000: aluop_sel = ( zero_bit) ? `ALUOP_ADS : `ALUOP_ADD;
+ 12'b000000110000: aluop_sel = (!carry_bit) ? `ALUOP_ADS : `ALUOP_ADD;
+ 12'b000000111000: aluop_sel = ( carry_bit) ? `ALUOP_ADS : `ALUOP_ADD;
+ 12'b000000010000,
+ 12'b000000011000: aluop_sel = `ALUOP_ADS;
+ 12'b1xxx01110100,
+ 12'b000000110110: aluop_sel = `ALUOP_PASS;
+ default: aluop_sel = `ALUOP_ADD;
+ endcase
+ end
+ `OF2A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b010000110110,
+ 12'b010100110110: aluop_sel = `ALUOP_ADS;
+ default: aluop_sel = `ALUOP_ADD;
+ endcase
+ end
+ `OF2B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000000xx0001,
+ 12'b010000100001,
+ 12'b010100100001: aluop_sel = `ALUOP_ADD;
+ 12'b000011000010,
+ 12'b000011000100: aluop_sel = ( !zero_bit) ? `ALUOP_PASS : `ALUOP_ADD;
+ 12'b000011001010,
+ 12'b000011001100: aluop_sel = ( zero_bit) ? `ALUOP_PASS : `ALUOP_ADD;
+ 12'b000011010010,
+ 12'b000011010100: aluop_sel = (!carry_bit) ? `ALUOP_PASS : `ALUOP_ADD;
+ 12'b000011011010,
+ 12'b000011011100: aluop_sel = ( carry_bit) ? `ALUOP_PASS : `ALUOP_ADD;
+ 12'b000011100010,
+ 12'b000011100100: aluop_sel = ( !par_bit) ? `ALUOP_PASS : `ALUOP_ADD;
+ 12'b000011101010,
+ 12'b000011101100: aluop_sel = ( par_bit) ? `ALUOP_PASS : `ALUOP_ADD;
+ 12'b000011110010,
+ 12'b000011110100: aluop_sel = ( !sign_bit) ? `ALUOP_PASS : `ALUOP_ADD;
+ 12'b000011111010,
+ 12'b000011111100: aluop_sel = ( sign_bit) ? `ALUOP_PASS : `ALUOP_ADD;
+ default: aluop_sel = `ALUOP_PASS;
+ endcase
+ end
+ `IF3A: aluop_sel = `ALUOP_ADS;
+ `ADR1: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx01100101,
+ 12'b1xxx01100110: aluop_sel = `ALUOP_ADD;
+ 12'b000000100010,
+ 12'b000000101010,
+ 12'b000000110010,
+ 12'b000000111010,
+ 12'b000011010011,
+ 12'b000011011011,
+ 12'b0001xxxxxxxx,
+ 12'b010000100010,
+ 12'b010000101010,
+ 12'b010100100010,
+ 12'b010100101010,
+ 12'b1xxx00xxx000,
+ 12'b1xxx00xxx001,
+ 12'b1xxx01110100,
+ 12'b1xxx01xx1011,
+ 12'b1xxx01xx0011: aluop_sel = `ALUOP_PASS;
+ default: aluop_sel = `ALUOP_ADS;
+ endcase
+ end
+ `ADR2: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10010100,
+ 12'b1xxx10011100,
+ 12'b1xxx10100000,
+ 12'b1xxx10100001,
+ 12'b1xxx10101000,
+ 12'b1xxx10101001,
+ 12'b1xxx10110000,
+ 12'b1xxx10110001,
+ 12'b1xxx10110100,
+ 12'b1xxx10111000,
+ 12'b1xxx10111001,
+ 12'b1xxx10111100,
+ 12'b1xxx11000010,
+ 12'b1xxx11000011,
+ 12'b1xxx11001010,
+ 12'b1xxx11001011: aluop_sel = `ALUOP_ADD;
+ 12'b1xxx01100101,
+ 12'b1xxx01100110: aluop_sel = `ALUOP_ADS;
+ 12'b1xxx10000010,
+ 12'b1xxx10000011,
+ 12'b1xxx10000100,
+ 12'b1xxx10001010,
+ 12'b1xxx10001011,
+ 12'b1xxx10001100,
+ 12'b1xxx10010010,
+ 12'b1xxx10010011,
+ 12'b1xxx10011010,
+ 12'b1xxx10011011,
+ 12'b1xxx10100010,
+ 12'b1xxx10101010,
+ 12'b1xxx10110010,
+ 12'b1xxx10111010: aluop_sel = `ALUOP_BADD;
+ 12'b1xxx10100100,
+ 12'b1xxx10101100,
+ 12'b1xxx10100011,
+ 12'b1xxx10101011,
+ 12'b1xxx10110011,
+ 12'b1xxx10111011: aluop_sel = `ALUOP_BAND;
+ default: aluop_sel = `ALUOP_PASS;
+ endcase
+ end
+ `RD1A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000000101010,
+ 12'b000011001001,
+ 12'b000011100011,
+ 12'b000011xxx000,
+ 12'b000011xx0001,
+ 12'b0001xxxxxxxx,
+ 12'b010000101010,
+ 12'b010000110001,
+ 12'b010000110111,
+ 12'b010000xx0111,
+ 12'b010011100001,
+ 12'b010011100011,
+ 12'b010100101010,
+ 12'b010100110001,
+ 12'b010100110111,
+ 12'b010100xx0111,
+ 12'b010111100001,
+ 12'b010111100011,
+ 12'b1xxx00110110,
+ 12'b1xxx00110111,
+ 12'b1xxx00xx0111,
+ 12'b1xxx01000101,
+ 12'b1xxx01001101,
+ 12'b1xxx01xx1011: aluop_sel = `ALUOP_ADD;
+ default: aluop_sel = `ALUOP_PASS;
+ endcase
+ end
+ `RD1B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10100010,
+ 12'b1xxx10100011,
+ 12'b1xxx10101010,
+ 12'b1xxx10101011,
+ 12'b1xxx10110010,
+ 12'b1xxx10110011,
+ 12'b1xxx10111010,
+ 12'b1xxx10111011: aluop_sel = `ALUOP_BAND;
+ 12'b1xxx10100001,
+ 12'b1xxx10101001,
+ 12'b1xxx10110001,
+ 12'b1xxx10111001: aluop_sel = `ALUOP_BSUB;
+ default: aluop_sel = `ALUOP_PASS;
+ endcase
+ end
+ `RD2A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000011001001,
+ 12'b000011xxx000,
+ 12'b000011xx0001,
+ 12'b0001xxxxxxxx,
+ 12'b010011100001,
+ 12'b010111100001,
+ 12'b1xxx01000101,
+ 12'b1xxx01001101,
+ 12'b1xxx10000010,
+ 12'b1xxx10000100,
+ 12'b1xxx10001010,
+ 12'b1xxx10001100,
+ 12'b1xxx10010010,
+ 12'b1xxx10010100,
+ 12'b1xxx10011010,
+ 12'b1xxx10011100,
+ 12'b1xxx10100000,
+ 12'b1xxx10100010,
+ 12'b1xxx10100100,
+ 12'b1xxx10101000,
+ 12'b1xxx10101010,
+ 12'b1xxx10101100,
+ 12'b1xxx10110000,
+ 12'b1xxx10110010,
+ 12'b1xxx10110100,
+ 12'b1xxx10111000,
+ 12'b1xxx10111010,
+ 12'b1xxx10111100,
+ 12'b1xxx11000010,
+ 12'b1xxx11001010: aluop_sel = `ALUOP_ADD;
+ 12'b1xxx10000011,
+ 12'b1xxx10001011,
+ 12'b1xxx10010011,
+ 12'b1xxx10011011: aluop_sel = `ALUOP_BADD;
+ default: aluop_sel = `ALUOP_PASS;
+ endcase
+ end
+ `RD2B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000000110100,
+ 12'b000000xxx100,
+ 12'b010000110100,
+ 12'b010100110100: aluop_sel = `ALUOP_BADD;
+ 12'b001010xxx110,
+ 12'b001010xxxxxx,
+ 12'b011010xxx110,
+ 12'b011110xxx110,
+ 12'b1xxx10100010,
+ 12'b1xxx10100011,
+ 12'b1xxx10101010,
+ 12'b1xxx10101011,
+ 12'b1xxx10110010,
+ 12'b1xxx10110011,
+ 12'b1xxx10111010,
+ 12'b1xxx10111011: aluop_sel = `ALUOP_BAND;
+ 12'b000000110101,
+ 12'b000000xxx101,
+ 12'b010000110101,
+ 12'b010100110101: aluop_sel = `ALUOP_BDEC;
+ 12'b001011xxx110,
+ 12'b001011xxxxxx,
+ 12'b011011xxx110,
+ 12'b011111xxx110: aluop_sel = `ALUOP_BOR;
+ 12'b1xxx10100001,
+ 12'b1xxx10101001,
+ 12'b1xxx10110001,
+ 12'b1xxx10111001: aluop_sel = `ALUOP_BSUB;
+ 12'b000011001001,
+ 12'b000011100011,
+ 12'b000011xxx000,
+ 12'b0001xxxxxxxx,
+ 12'b010011100011,
+ 12'b010111100011,
+ 12'b1xxx01000101,
+ 12'b1xxx01001101,
+ 12'b1xxx10000010,
+ 12'b1xxx10000011,
+ 12'b1xxx10000100,
+ 12'b1xxx10001010,
+ 12'b1xxx10001011,
+ 12'b1xxx10001100,
+ 12'b1xxx10010010,
+ 12'b1xxx10010011,
+ 12'b1xxx10010100,
+ 12'b1xxx10011010,
+ 12'b1xxx10011011,
+ 12'b1xxx10011100,
+ 12'b1xxx10100000,
+ 12'b1xxx10100100,
+ 12'b1xxx10101000,
+ 12'b1xxx10101100,
+ 12'b1xxx10110000,
+ 12'b1xxx10110100,
+ 12'b1xxx10111000,
+ 12'b1xxx10111100,
+ 12'b1xxx11000010,
+ 12'b1xxx11000011,
+ 12'b1xxx11001010,
+ 12'b1xxx11001011: aluop_sel = `ALUOP_PASS;
+ 12'b0x1x00000xxx: aluop_sel = `ALUOP_RLC;
+ 12'b0x1x00001xxx: aluop_sel = `ALUOP_RRC;
+ 12'b0x1x00010xxx: aluop_sel = `ALUOP_RL;
+ 12'b0x1x00011xxx: aluop_sel = `ALUOP_RR;
+ 12'b0x1x00100xxx: aluop_sel = `ALUOP_SLA;
+ 12'b0x1x00101xxx: aluop_sel = `ALUOP_SRA;
+ 12'b0x1x00110xxx: aluop_sel = `ALUOP_SLL;
+ 12'b0x1x00111xxx: aluop_sel = `ALUOP_SRL;
+ 12'b1xxx01101111: aluop_sel = `ALUOP_RLD1;
+ 12'b1xxx01100111: aluop_sel = `ALUOP_RRD1;
+ default: aluop_sel = `ALUOP_ADD;
+ endcase
+ end
+ `WR1A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10100010,
+ 12'b1xxx10101010,
+ 12'b1xxx10110010,
+ 12'b1xxx10111010,
+ 12'b1xxx11000010,
+ 12'b1xxx11001010: aluop_sel = `ALUOP_PASS;
+ 12'b1xxx10100100,
+ 12'b1xxx10101100: aluop_sel = `ALUOP_BADD;
+ default: aluop_sel = `ALUOP_ADD;
+ endcase
+ end
+ `WR1B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10011011,
+ 12'b1xxx10010011,
+ 12'b1xxx10000010,
+ 12'b1xxx10000100,
+ 12'b1xxx10001010,
+ 12'b1xxx10001100,
+ 12'b1xxx10010100,
+ 12'b1xxx10011100,
+ 12'b1xxx10100100,
+ 12'b1xxx10101100,
+ 12'b1xxx11000010,
+ 12'b1xxx11000011,
+ 12'b1xxx11001010,
+ 12'b1xxx11001011,
+ 12'b1xxx10100000,
+ 12'b1xxx10100010,
+ 12'b1xxx10100011,
+ 12'b1xxx10101000,
+ 12'b1xxx10101010,
+ 12'b1xxx10101011,
+ 12'b1xxx10110000,
+ 12'b1xxx10110100,
+ 12'b1xxx10111100,
+ 12'b1xxx10111000: aluop_sel = `ALUOP_ADD;
+ 12'b1xxx10001011,
+ 12'b1xxx10000011,
+ 12'b1xxx10010010,
+ 12'b1xxx10011010,
+ 12'b1xxx10110010,
+ 12'b1xxx10110011,
+ 12'b1xxx10111010,
+ 12'b1xxx10111011: aluop_sel = `ALUOP_BADD;
+ default: aluop_sel = `ALUOP_PASS;
+ endcase
+ end
+ `WR2A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx100xx011,
+ 12'b1xxx10010100,
+ 12'b1xxx10011100,
+ 12'b1xxx10110100,
+ 12'b1xxx10111100,
+ 12'b1xxx11000011,
+ 12'b1xxx11001011,
+ 12'b1xxx10100000,
+ 12'b1xxx10100011,
+ 12'b1xxx10101000,
+ 12'b1xxx10101011,
+ 12'b1xxx10110000,
+ 12'b1xxx10110011,
+ 12'b1xxx10111000,
+ 12'b1xxx10111011: aluop_sel = `ALUOP_ADD;
+ 12'b000011xxx111,
+ 12'b0001xxxxxxxx: aluop_sel = `ALUOP_APAS;
+ 12'b1xxx10000010,
+ 12'b1xxx10000100,
+ 12'b1xxx10001010,
+ 12'b1xxx10001100,
+ 12'b1xxx10010010,
+ 12'b1xxx10011010,
+ 12'b1xxx10100100,
+ 12'b1xxx10101100: aluop_sel = `ALUOP_BADD;
+ default: aluop_sel = `ALUOP_PASS;
+ endcase
+ end
+ `WR2B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx100xx011,
+ 12'b1xxx10000010,
+ 12'b1xxx10000100,
+ 12'b1xxx10001010,
+ 12'b1xxx10001100,
+ 12'b1xxx10010010,
+ 12'b1xxx10011010,
+ 12'b1xxx10100100,
+ 12'b1xxx10101100,
+ 12'b1xxx10100010,
+ 12'b1xxx10100011,
+ 12'b1xxx10101010,
+ 12'b1xxx10101011,
+ 12'b1xxx10110010,
+ 12'b1xxx10110011,
+ 12'b1xxx10111010,
+ 12'b1xxx10111011: aluop_sel = `ALUOP_BADD;
+ default: aluop_sel = `ALUOP_ADD;
+ endcase
+ end
+ `PCA,
+ `PCO: aluop_sel = `ALUOP_ADD;
+ `IF1A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10000010,
+ 12'b1xxx10000100,
+ 12'b1xxx10001010,
+ 12'b1xxx10001100,
+ 12'b1xxx10010010,
+ 12'b1xxx10010100,
+ 12'b1xxx10011010,
+ 12'b1xxx10011100,
+ 12'b1xxx10100000,
+ 12'b1xxx10100010,
+ 12'b1xxx10101000,
+ 12'b1xxx10101010,
+ 12'b1xxx10110000,
+ 12'b1xxx10110010,
+ 12'b1xxx10110100,
+ 12'b1xxx10111000,
+ 12'b1xxx10111010,
+ 12'b1xxx10111100,
+ 12'b1xxx11000010,
+ 12'b1xxx11000011,
+ 12'b1xxx11001010,
+ 12'b1xxx11001011: aluop_sel = `ALUOP_ADD;
+ 12'b1xxx00011010,
+ 12'b1xxx01010100,
+ 12'b1xxx01010101,
+ 12'b1xxx00110010,
+ 12'b1xxx00110011,
+ 12'b1xxx00xx0010,
+ 12'b1xxx00xx0011: aluop_sel = `ALUOP_ADS;
+ 12'b000010001xxx,
+ 12'b000011001110,
+ 12'b010x10001110: aluop_sel = `ALUOP_BADC;
+ 12'b000010000xxx,
+ 12'b000011000110,
+ 12'b010x10000110,
+ 12'b1xxx100xx011,
+ 12'b1xxx10100100,
+ 12'b1xxx10101100,
+ 12'b1xxx10100011,
+ 12'b1xxx10101011,
+ 12'b1xxx10110011,
+ 12'b1xxx10111011: aluop_sel = `ALUOP_BADD;
+ 12'b000010100xxx,
+ 12'b0x1x01xxxxxx,
+ 12'b010x10100110,
+ 12'b000011100110,
+ 12'b1xxx00110100,
+ 12'b1xxx00xxx000,
+ 12'b1xxx011x0100,
+ 12'b1xxx01xxx000: aluop_sel = `ALUOP_BAND;
+ 12'b000010110xxx,
+ 12'b010x10110110,
+ 12'b000011110110: aluop_sel = `ALUOP_BOR;
+ 12'b000010011xxx,
+ 12'b010x10011110,
+ 12'b000011011110: aluop_sel = `ALUOP_BSBC;
+ 12'b000010010xxx,
+ 12'b000010111xxx,
+ 12'b000011010110,
+ 12'b010x10010110,
+ 12'b010x10111110,
+ 12'b000011111110: aluop_sel = `ALUOP_BSUB;
+ 12'b000010101xxx,
+ 12'b010x10101110,
+ 12'b000011101110: aluop_sel = `ALUOP_BXOR;
+ 12'b1xxx01101111: aluop_sel = `ALUOP_RLD2;
+ 12'b1xxx01100111: aluop_sel = `ALUOP_RRD2;
+ default: aluop_sel = `ALUOP_PASS;
+ endcase
+ end
+ `INTB: aluop_sel = `ALUOP_PASS;
+ default: aluop_sel = `ALUOP_ADD;
+ endcase
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* alu a input control */
+ /* */
+ /*****************************************************************************************/
+ always @ (inst_reg or page_reg or state_reg or carry_bit or par_bit or sign_bit or
+ tflg_reg or zero_bit) begin
+ casex (state_reg) //synopsys parallel_case
+ `DEC1: begin
+ casex (inst_reg) //synopsys parallel_case
+ 8'b10000xxx,
+ 8'b10001xxx,
+ 8'b10010xxx,
+ 8'b10011xxx,
+ 8'b10100xxx,
+ 8'b10101xxx,
+ 8'b10110xxx,
+ 8'b10111xxx: alua_sel = `ALUA_AA;
+ 8'b00100111: alua_sel = `ALUA_DAA;
+ 8'b00xx1001: alua_sel = `ALUA_HL;
+ 8'b00010000,
+ 8'b00101111,
+ 8'b00xxx101,
+ 8'b00xx1011,
+ 8'b11xx0101,
+ 8'b11xxx111: alua_sel = `ALUA_M1;
+ default: alua_sel = `ALUA_ONE;
+ endcase
+ end
+ `DEC2: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b001001xxxxxx,
+ 12'b001010xxxxxx,
+ 12'b001011xxxxxx: alua_sel = `ALUA_BIT;
+ 12'b1xxx01xx0010,
+ 12'b1xxx01xx1010: alua_sel = `ALUA_HL;
+ 12'b1xxx01010111: alua_sel = `ALUA_II;
+ 12'b010000xx1001: alua_sel = `ALUA_IX;
+ 12'b010100xx1001: alua_sel = `ALUA_IY;
+ 12'b010000100101,
+ 12'b010000101011,
+ 12'b010000101101,
+ 12'b010011100101,
+ 12'b010100100101,
+ 12'b010100101011,
+ 12'b010100101101,
+ 12'b1xxx10101100,
+ 12'b010111100101: alua_sel = `ALUA_M1;
+ 12'b1xxx10100100,
+ 12'b010000100100,
+ 12'b010000101100,
+ 12'b010000100011,
+ 12'b010100100100,
+ 12'b010100101100,
+ 12'b010100100011: alua_sel = `ALUA_ONE;
+ 12'b1xxx01011111: alua_sel = `ALUA_RR;
+ 12'b1xxx01000100: alua_sel = `ALUA_ZER;
+ default: alua_sel = `ALUA_AA;
+ endcase
+ end
+ `OF1B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000000100000: alua_sel = ( !zero_bit) ? `ALUA_PC : `ALUA_ONE;
+ 12'b000000101000: alua_sel = ( zero_bit) ? `ALUA_PC : `ALUA_ONE;
+ 12'b000000110000: alua_sel = (!carry_bit) ? `ALUA_PC : `ALUA_ONE;
+ 12'b000000111000: alua_sel = ( carry_bit) ? `ALUA_PC : `ALUA_ONE;
+ 12'b000000010000,
+ 12'b000000011000: alua_sel = `ALUA_PC;
+ default: alua_sel = `ALUA_ONE;
+ endcase
+ end
+ `OF2A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b010000110110: alua_sel = `ALUA_IX;
+ 12'b010100110110: alua_sel = `ALUA_IY;
+ default: alua_sel = `ALUA_M1;
+ endcase
+ end
+ `IF3A: alua_sel = (page_reg[0]) ? `ALUA_IY : `ALUA_IX;
+ `ADR1: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000011010011: alua_sel = `ALUA_M1;
+ 12'b1xxx01100101,
+ 12'b1xxx01100110: alua_sel = `ALUA_M1;
+ default: alua_sel = (page_reg[0]) ? `ALUA_IY : `ALUA_IX;
+ endcase
+ end
+ `ADR2: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx01100101: alua_sel = `ALUA_IX;
+ 12'b1xxx01100110: alua_sel = `ALUA_IY;
+ default: alua_sel = `ALUA_M1;
+ endcase
+ end
+ `RD1B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10100001,
+ 12'b1xxx10101001,
+ 12'b1xxx10110001,
+ 12'b1xxx10111001: alua_sel = `ALUA_AA;
+ default: alua_sel = `ALUA_M1;
+ endcase
+ end
+ `RD2A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b0001xxxxxxxx,
+ 12'b1xxx10001010,
+ 12'b1xxx10001011,
+ 12'b1xxx10001100,
+ 12'b1xxx10011010,
+ 12'b1xxx10011011,
+ 12'b1xxx10011100,
+ 12'b1xxx10101000,
+ 12'b1xxx10101010,
+ 12'b1xxx10101100,
+ 12'b1xxx10111000,
+ 12'b1xxx10111010,
+ 12'b1xxx10111100,
+ 12'b1xxx11001010,
+ 12'b1xxx11001011: alua_sel = `ALUA_M1;
+ default: alua_sel = `ALUA_ONE;
+ endcase
+ end
+ `RD2B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx01100111,
+ 12'b1xxx01101111,
+ 12'b1xxx10100001,
+ 12'b1xxx10101001,
+ 12'b1xxx10110001,
+ 12'b1xxx10111001: alua_sel = `ALUA_AA;
+ 12'b0x1x1xxxxxxx: alua_sel = `ALUA_BIT;
+ 12'b000000xxx101,
+ 12'b010000110101,
+ 12'b010100110101,
+ 12'b1xxx10100010,
+ 12'b1xxx10100011,
+ 12'b1xxx10101010,
+ 12'b1xxx10101011,
+ 12'b1xxx10110010,
+ 12'b1xxx10110011,
+ 12'b1xxx10111010,
+ 12'b1xxx10111011: alua_sel = `ALUA_M1;
+ default: alua_sel = `ALUA_ONE;
+ endcase
+ end
+ `WR1A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000011001101,
+ 12'b000011xxx100,
+ 12'b000011xx0101,
+ 12'b000011xxx111,
+ 12'b0001xxxxxxxx,
+ 12'b010011100101,
+ 12'b010111100101,
+ 12'b1xxx01100101,
+ 12'b1xxx01100110,
+ 12'b1xxx10001010,
+ 12'b1xxx10001011,
+ 12'b1xxx10001100,
+ 12'b1xxx10011010,
+ 12'b1xxx10011011,
+ 12'b1xxx10011100,
+ 12'b1xxx10101000,
+ 12'b1xxx10101011,
+ 12'b1xxx10100100,
+ 12'b1xxx10101100,
+ 12'b1xxx10111000,
+ 12'b1xxx10111011,
+ 12'b1xxx10111100,
+ 12'b1xxx11001010,
+ 12'b1xxx11001011: alua_sel = `ALUA_M1;
+ default: alua_sel = `ALUA_ONE;
+ endcase
+ end
+ `WR1B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10000010,
+ 12'b1xxx10000011,
+ 12'b1xxx10000100,
+ 12'b1xxx10001010,
+ 12'b1xxx10001011,
+ 12'b1xxx10001100,
+ 12'b1xxx10100000,
+ 12'b1xxx10100010,
+ 12'b1xxx10100011,
+ 12'b1xxx10100100,
+ 12'b1xxx10101000,
+ 12'b1xxx10101010,
+ 12'b1xxx10101011,
+ 12'b1xxx10101100: alua_sel = `ALUA_ONE;
+ default: alua_sel = `ALUA_M1;
+ endcase
+ end
+ `WR2A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b0001xxxxxxxx: alua_sel = `ALUA_INT;
+ 12'b1xxx10001010,
+ 12'b1xxx10001011,
+ 12'b1xxx10001100,
+ 12'b1xxx10011010,
+ 12'b1xxx10011011,
+ 12'b1xxx10011100,
+ 12'b1xxx10101000,
+ 12'b1xxx10101011,
+ 12'b1xxx10101100,
+ 12'b1xxx10111000,
+ 12'b1xxx10111011,
+ 12'b1xxx10111100,
+ 12'b1xxx11001010,
+ 12'b1xxx11001011: alua_sel = `ALUA_M1;
+ 12'b000011xxx111: alua_sel = `ALUA_RST;
+ default: alua_sel = `ALUA_ONE;
+ endcase
+ end
+ `WR2B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10000010,
+ 12'b1xxx10000011,
+ 12'b1xxx10000100,
+ 12'b1xxx10001010,
+ 12'b1xxx10001011,
+ 12'b1xxx10001100,
+ 12'b1xxx10010010,
+ 12'b1xxx10010011,
+ 12'b1xxx10010100,
+ 12'b1xxx10011010,
+ 12'b1xxx10011011,
+ 12'b1xxx10011100,
+ 12'b1xxx10100000,
+ 12'b1xxx10100010,
+ 12'b1xxx10100011,
+ 12'b1xxx10100100,
+ 12'b1xxx10101000,
+ 12'b1xxx10101010,
+ 12'b1xxx10101011,
+ 12'b1xxx10101100,
+ 12'b1xxx10110000,
+ 12'b1xxx10110010,
+ 12'b1xxx10110011,
+ 12'b1xxx10110100,
+ 12'b1xxx10111000,
+ 12'b1xxx10111010,
+ 12'b1xxx10111011,
+ 12'b1xxx10111100,
+ 12'b1xxx11000010,
+ 12'b1xxx11000011,
+ 12'b1xxx11001010,
+ 12'b1xxx11001011: alua_sel = `ALUA_M1;
+ default: alua_sel = `ALUA_ONE;
+ endcase
+ end
+ `BLK1: begin
+ alua_sel = (inst_reg[3]) ? `ALUA_M1 : `ALUA_ONE;
+ end
+ `BLK2: begin
+ alua_sel = (inst_reg[4]) ? `ALUA_M1 : `ALUA_ONE;
+ end
+ `PCA: alua_sel = (tflg_reg) ? `ALUA_ZER : `ALUA_M2;
+ `IF1A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b0x1x01xxxxxx: alua_sel = `ALUA_BIT;
+ 12'b1xxx00110010,
+ 12'b1xxx00xx0010,
+ 12'b1xxx01010101: alua_sel = `ALUA_IX;
+ 12'b1xxx00110011,
+ 12'b1xxx00xx0011,
+ 12'b1xxx01010100: alua_sel = `ALUA_IY;
+ 12'b1xxx00xxx000,
+ 12'b1xxx01xxx000,
+ 12'b1xxx10001010,
+ 12'b1xxx10001011,
+ 12'b1xxx10001100,
+ 12'b1xxx10011010,
+ 12'b1xxx10011011,
+ 12'b1xxx10011100,
+ 12'b1xxx10100011,
+ 12'b1xxx10101000,
+ 12'b1xxx10101010,
+ 12'b1xxx10101011,
+ 12'b1xxx10101100,
+ 12'b1xxx10110011,
+ 12'b1xxx10111000,
+ 12'b1xxx10111010,
+ 12'b1xxx10111011,
+ 12'b1xxx10111100,
+ 12'b1xxx11001010,
+ 12'b1xxx11001011: alua_sel = `ALUA_M1;
+ 12'b1xxx10000010,
+ 12'b1xxx10000011,
+ 12'b1xxx10000100,
+ 12'b1xxx10010010,
+ 12'b1xxx10010011,
+ 12'b1xxx10010100,
+ 12'b1xxx10100000,
+ 12'b1xxx10100010,
+ 12'b1xxx10100100,
+ 12'b1xxx10110000,
+ 12'b1xxx10110010,
+ 12'b1xxx10110100,
+ 12'b1xxx11000010,
+ 12'b1xxx11000011: alua_sel = `ALUA_ONE;
+ 12'b1xxx01110100: alua_sel = `ALUA_TMP;
+ default: alua_sel = `ALUA_AA;
+ endcase
+ end
+ `INTA: alua_sel = `ALUA_M1;
+ default: alua_sel = `ALUA_ONE;
+ endcase
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* alu b input control */
+ /* */
+ /*****************************************************************************************/
+ always @ (inst_reg or page_reg or state_reg or carry_bit or par_bit or sign_bit or
+ zero_bit) begin
+ casex (state_reg) //synopsys parallel_case
+ `DEC1: begin
+ casex (inst_reg) //synopsys parallel_case
+ 8'b00000111,
+ 8'b00001111,
+ 8'b00010111,
+ 8'b00011111,
+ 8'b00100111,
+ 8'b00101111: alub_sel = `ALUB_AA;
+ 8'b00010000: alub_sel = `ALUB_BB;
+ 8'b00000010,
+ 8'b00001010: alub_sel = `ALUB_BC;
+ 8'b00010010,
+ 8'b00011010,
+ 8'b11101011: alub_sel = `ALUB_DE;
+ 8'b11101001,
+ 8'b11111001: alub_sel = `ALUB_HL;
+ 8'b01xxx000,
+ 8'b10xxx000: alub_sel = `ALUB_BB;
+ 8'b01xxx001,
+ 8'b10xxx001: alub_sel = `ALUB_CC;
+ 8'b01xxx010,
+ 8'b10xxx010: alub_sel = `ALUB_DD;
+ 8'b01xxx011,
+ 8'b10xxx011: alub_sel = `ALUB_EE;
+ 8'b01xxx100,
+ 8'b10xxx100: alub_sel = `ALUB_HH;
+ 8'b01xxx101,
+ 8'b10xxx101: alub_sel = `ALUB_LL;
+ 8'b01xxx111,
+ 8'b10xxx111: alub_sel = `ALUB_AA;
+ 8'b0000010x: alub_sel = `ALUB_BB;
+ 8'b0000110x: alub_sel = `ALUB_CC;
+ 8'b0001010x: alub_sel = `ALUB_DD;
+ 8'b0001110x: alub_sel = `ALUB_EE;
+ 8'b0010010x: alub_sel = `ALUB_HH;
+ 8'b0010110x: alub_sel = `ALUB_LL;
+ 8'b0011110x: alub_sel = `ALUB_AA;
+ 8'b00000011,
+ 8'b00001001,
+ 8'b00001011: alub_sel = `ALUB_BC;
+ 8'b00010011,
+ 8'b00011001,
+ 8'b00011011: alub_sel = `ALUB_DE;
+ 8'b00100011,
+ 8'b00101001,
+ 8'b00101011: alub_sel = `ALUB_HL;
+ 8'b00110011,
+ 8'b00111001,
+ 8'b00111011: alub_sel = `ALUB_SP;
+ 8'b11xx0101,
+ 8'b11xxx111: alub_sel = `ALUB_SP;
+ default: alub_sel = `ALUB_PC;
+ endcase
+ end
+ `IF2B: alub_sel = `ALUB_PC;
+ `DEC2: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx01000100,
+ 12'b1xxx01000111,
+ 12'b1xxx01001111: alub_sel = `ALUB_AA;
+ 12'b1xxx01xxx000,
+ 12'b1xxx01xxx001,
+ 12'b1xxx10000100,
+ 12'b1xxx10001100,
+ 12'b1xxx10100010,
+ 12'b1xxx10101010,
+ 12'b1xxx10110010,
+ 12'b1xxx10111010: alub_sel = `ALUB_BC;
+ 12'b010000100011,
+ 12'b010000101011,
+ 12'b010011101001,
+ 12'b010011111001: alub_sel = `ALUB_IX;
+ 12'b010000100100,
+ 12'b010000100101,
+ 12'b0100010xx100,12'b01000110x100,12'b010001111100,
+ 12'b010010000100,
+ 12'b010010001100,
+ 12'b010010010100,
+ 12'b010010011100,
+ 12'b010010100100,
+ 12'b010010101100,
+ 12'b010010110100,
+ 12'b010010111100: alub_sel = `ALUB_IXH;
+ 12'b010100100100,
+ 12'b010100100101,
+ 12'b0101010xx100,12'b01010110x100,12'b010101111100,
+ 12'b010110000100,
+ 12'b010110001100,
+ 12'b010110010100,
+ 12'b010110011100,
+ 12'b010110100100,
+ 12'b010110101100,
+ 12'b010110110100,
+ 12'b010110111100: alub_sel = `ALUB_IYH;
+ 12'b010000101100,
+ 12'b010000101101,
+ 12'b0100010xx101,12'b01000110x101,12'b010001111101,
+ 12'b010010000101,
+ 12'b010010001101,
+ 12'b010010010101,
+ 12'b010010011101,
+ 12'b010010100101,
+ 12'b010010101101,
+ 12'b010010110101,
+ 12'b010010111101: alub_sel = `ALUB_IXL;
+ 12'b010100101100,
+ 12'b010100101101,
+ 12'b0101010xx101,12'b01010110x101,12'b010101111101,
+ 12'b010110000101,
+ 12'b010110001101,
+ 12'b010110010101,
+ 12'b010110011101,
+ 12'b010110100101,
+ 12'b010110101101,
+ 12'b010110110101,
+ 12'b010110111101: alub_sel = `ALUB_IYL;
+ 12'b010100100011,
+ 12'b010100101011,
+ 12'b010111101001,
+ 12'b010111111001: alub_sel = `ALUB_IY;
+ 12'b1xxx01000101,
+ 12'b1xxx01001101: alub_sel = `ALUB_PC;
+ 12'b010x0110x000,
+ 12'b1xxx00000100,
+ 12'b0010xxxxx000: alub_sel = `ALUB_BB;
+ 12'b010x0110x001,
+ 12'b1xxx00001100,
+ 12'b1xxx10000010,
+ 12'b1xxx10001010,
+ 12'b1xxx10010010,
+ 12'b1xxx10011010,
+ 12'b0010xxxxx001: alub_sel = `ALUB_CC;
+ 12'b010x0110x010,
+ 12'b1xxx00010100,
+ 12'b0010xxxxx010: alub_sel = `ALUB_DD;
+ 12'b010x0110x011,
+ 12'b1xxx00011100,
+ 12'b0010xxxxx011: alub_sel = `ALUB_EE;
+ 12'b1xxx00100100,
+ 12'b0010xxxxx100: alub_sel = `ALUB_HH;
+ 12'b1xxx00101100,
+ 12'b0010xxxxx101: alub_sel = `ALUB_LL;
+ 12'b010x0110x111,
+ 12'b1xxx00111100,
+ 12'b0010xxxxx111: alub_sel = `ALUB_AA;
+ 12'b1xxx01001100,
+ 12'b1xxx0100x010: alub_sel = `ALUB_BC;
+ 12'b1xxx01011100,
+ 12'b1xxx0101x010: alub_sel = `ALUB_DE;
+ 12'b1xxx01111100,
+ 12'b1xxx0111x010: alub_sel = `ALUB_SP;
+ 12'b010011100101,
+ 12'b010111100101: alub_sel = `ALUB_SP;
+ 12'b010x00001001: alub_sel = `ALUB_BC;
+ 12'b1xxx10010100,
+ 12'b1xxx10011100,
+ 12'b1xxx11000010,
+ 12'b1xxx11001010,
+ 12'b010x00011001: alub_sel = `ALUB_DE;
+ 12'b010000101001: alub_sel = `ALUB_IX;
+ 12'b010100101001: alub_sel = `ALUB_IY;
+ 12'b010x00111001: alub_sel = `ALUB_SP;
+ default: alub_sel = `ALUB_HL;
+ endcase
+ end
+ `OF1B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx01110100,
+ 12'b000000010000,
+ 12'b000000011000,
+ 12'b000000110110: alub_sel = `ALUB_DIN;
+ 12'b000000100000: alub_sel = ( !zero_bit) ? `ALUB_DIN : `ALUB_PC;
+ 12'b000000101000: alub_sel = ( zero_bit) ? `ALUB_DIN : `ALUB_PC;
+ 12'b000000110000: alub_sel = (!carry_bit) ? `ALUB_DIN : `ALUB_PC;
+ 12'b000000111000: alub_sel = ( carry_bit) ? `ALUB_DIN : `ALUB_PC;
+ default: alub_sel = `ALUB_PC;
+ endcase
+ end
+ `OF2A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b010000110110,
+ 12'b010100110110: alub_sel = `ALUB_DIN;
+ default: alub_sel = `ALUB_SP;
+ endcase
+ end
+ `OF2B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000011000011,
+ 12'b010000110110,
+ 12'b010100110110: alub_sel = `ALUB_DIN;
+ 12'b000011000010: alub_sel = ( !zero_bit) ? `ALUB_DIN : `ALUB_PC;
+ 12'b000011001010: alub_sel = ( zero_bit) ? `ALUB_DIN : `ALUB_PC;
+ 12'b000011010010: alub_sel = (!carry_bit) ? `ALUB_DIN : `ALUB_PC;
+ 12'b000011011010: alub_sel = ( carry_bit) ? `ALUB_DIN : `ALUB_PC;
+ 12'b000011100010: alub_sel = ( !par_bit) ? `ALUB_DIN : `ALUB_PC;
+ 12'b000011101010: alub_sel = ( par_bit) ? `ALUB_DIN : `ALUB_PC;
+ 12'b000011110010: alub_sel = ( !sign_bit) ? `ALUB_DIN : `ALUB_PC;
+ 12'b000011111010: alub_sel = ( sign_bit) ? `ALUB_DIN : `ALUB_PC;
+ 12'b000011001101: alub_sel = `ALUB_PCH;
+ 12'b000011000100: alub_sel = ( !zero_bit) ? `ALUB_PCH : `ALUB_PC;
+ 12'b000011001100: alub_sel = ( zero_bit) ? `ALUB_PCH : `ALUB_PC;
+ 12'b000011010100: alub_sel = (!carry_bit) ? `ALUB_PCH : `ALUB_PC;
+ 12'b000011011100: alub_sel = ( carry_bit) ? `ALUB_PCH : `ALUB_PC;
+ 12'b000011100100: alub_sel = ( !par_bit) ? `ALUB_PCH : `ALUB_PC;
+ 12'b000011101100: alub_sel = ( par_bit) ? `ALUB_PCH : `ALUB_PC;
+ 12'b000011110100: alub_sel = ( !sign_bit) ? `ALUB_PCH : `ALUB_PC;
+ 12'b000011111100: alub_sel = ( sign_bit) ? `ALUB_PCH : `ALUB_PC;
+ default: alub_sel = `ALUB_PC;
+ endcase
+ end
+ `IF3A: alub_sel = `ALUB_DIN;
+ `ADR1: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx01110100: alub_sel = `ALUB_CC;
+ 12'b000011010011,
+ 12'b000011011011: alub_sel = `ALUB_IO;
+ 12'b1xxx01100101,
+ 12'b1xxx01100110: alub_sel = `ALUB_SP;
+ 12'b0001xxxxxxxx: alub_sel = `ALUB_TMP;
+ default: alub_sel = `ALUB_DIN;
+ endcase
+ end
+ `ADR2: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000000000010,
+ 12'b000000010010,
+ 12'b000000110010,
+ 12'b000011010011: alub_sel = `ALUB_AA;
+ 12'b1xxx10000010,
+ 12'b1xxx10000100,
+ 12'b1xxx10001010,
+ 12'b1xxx10001100,
+ 12'b1xxx10010010,
+ 12'b1xxx10011010,
+ 12'b1xxx10100100,
+ 12'b1xxx10101100,
+ 12'b1xxx100xx011,
+ 12'b1xxx10100010,
+ 12'b1xxx10100011,
+ 12'b1xxx10101010,
+ 12'b1xxx10101011,
+ 12'b1xxx10110010,
+ 12'b1xxx10110011,
+ 12'b1xxx10111010,
+ 12'b1xxx10111011: alub_sel = `ALUB_BB;
+ 12'b1xxx10010100,
+ 12'b1xxx10011100,
+ 12'b1xxx11000010,
+ 12'b1xxx11000011,
+ 12'b1xxx11001010,
+ 12'b1xxx11001011,
+ 12'b1xxx10100000,
+ 12'b1xxx10100001,
+ 12'b1xxx10101000,
+ 12'b1xxx10101001,
+ 12'b1xxx10110000,
+ 12'b1xxx10110001,
+ 12'b1xxx10110100,
+ 12'b1xxx10111100,
+ 12'b1xxx10111000,
+ 12'b1xxx10111001: alub_sel = `ALUB_BC;
+ 12'b1xxx01100101,
+ 12'b1xxx01100110: alub_sel = `ALUB_DIN;
+ 12'b010000100010: alub_sel = `ALUB_IX;
+ 12'b010011100101: alub_sel = `ALUB_IXH;
+ 12'b010000111111,
+ 12'b010100111110,
+ 12'b1xxx00111111: alub_sel = `ALUB_IXL;
+ 12'b010100100010: alub_sel = `ALUB_IY;
+ 12'b010111100101: alub_sel = `ALUB_IYH;
+ 12'b010000111110,
+ 12'b010100111111,
+ 12'b1xxx00111110: alub_sel = `ALUB_IYL;
+ 12'b000011xxx111: alub_sel = `ALUB_PCH;
+ 12'b000001xxx000,
+ 12'b010x01110000,
+ 12'b1xxx00000001,
+ 12'b1xxx01000001: alub_sel = `ALUB_BB;
+ 12'b010000001111,
+ 12'b010100001111,
+ 12'b1xxx00001111,
+ 12'b000001xxx001,
+ 12'b010x01110001,
+ 12'b1xxx01110100,
+ 12'b1xxx00001001,
+ 12'b1xxx01001001: alub_sel = `ALUB_CC;
+ 12'b000001xxx010,
+ 12'b010x01110010,
+ 12'b1xxx00010001,
+ 12'b1xxx01010001: alub_sel = `ALUB_DD;
+ 12'b010000011111,
+ 12'b010100011111,
+ 12'b1xxx00011111,
+ 12'b000001xxx011,
+ 12'b010x01110011,
+ 12'b1xxx00011001,
+ 12'b1xxx01011001: alub_sel = `ALUB_EE;
+ 12'b000001xxx100,
+ 12'b010x01110100,
+ 12'b1xxx00100001,
+ 12'b1xxx01100001: alub_sel = `ALUB_HH;
+ 12'b010000101111,
+ 12'b010100101111,
+ 12'b1xxx00101111,
+ 12'b000001xxx101,
+ 12'b010x01110101,
+ 12'b1xxx00101001,
+ 12'b1xxx01101001: alub_sel = `ALUB_LL;
+ 12'b000001xxx111,
+ 12'b010x01110111,
+ 12'b1xxx00111001,
+ 12'b1xxx01111001: alub_sel = `ALUB_AA;
+ 12'b1xxx01000011: alub_sel = `ALUB_BC;
+ 12'b1xxx01010011: alub_sel = `ALUB_DE;
+ 12'b1xxx01110011: alub_sel = `ALUB_SP;
+ 12'b000011000101: alub_sel = `ALUB_BB;
+ 12'b000011010101: alub_sel = `ALUB_DD;
+ 12'b000011100101: alub_sel = `ALUB_HH;
+ 12'b000011110101: alub_sel = `ALUB_AA;
+ 12'b1xxx01100101,
+ 12'b1xxx01100110: alub_sel = `ALUB_TMP;
+ default: alub_sel = `ALUB_HL;
+ endcase
+ end
+ `RD1A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10100100,
+ 12'b1xxx10101100,
+ 12'b1xxx10100011,
+ 12'b1xxx10101011,
+ 12'b1xxx10110011,
+ 12'b1xxx10111011: alub_sel = `ALUB_BC;
+ 12'b1xxx100xx011: alub_sel = `ALUB_CC;
+ 12'b1xxx11000011,
+ 12'b1xxx11001011,
+ 12'b1xxx10100000,
+ 12'b1xxx10101000,
+ 12'b1xxx10110000,
+ 12'b1xxx10110100,
+ 12'b1xxx10111100,
+ 12'b1xxx10111000: alub_sel = `ALUB_DE;
+ 12'b1xxx00110110,
+ 12'b1xxx00110111,
+ 12'b1xxx00xx0111,
+ 12'b1xxx10000010,
+ 12'b1xxx10000100,
+ 12'b1xxx10001010,
+ 12'b1xxx10001100,
+ 12'b1xxx10010010,
+ 12'b1xxx10010100,
+ 12'b1xxx10011010,
+ 12'b1xxx10011100,
+ 12'b1xxx11000010,
+ 12'b1xxx11001010,
+ 12'b1xxx10100001,
+ 12'b1xxx10100010,
+ 12'b1xxx10101001,
+ 12'b1xxx10101010,
+ 12'b1xxx10110001,
+ 12'b1xxx10110010,
+ 12'b1xxx10111001,
+ 12'b1xxx10111010: alub_sel = `ALUB_HL;
+ 12'b010000110001,
+ 12'b010000110111,
+ 12'b010000xx0111,
+ 12'b010100110001,
+ 12'b010100110111,
+ 12'b010100xx0111,
+ 12'b000000101010,
+ 12'b0001xxxxxxxx,
+ 12'b010000101010,
+ 12'b010100101010,
+ 12'b1xxx01xx1011: alub_sel = `ALUB_TMP;
+ default: alub_sel = `ALUB_SP;
+ endcase
+ end
+ `RD1B: alub_sel = `ALUB_DIN;
+ `RD2A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10100100,
+ 12'b1xxx10101100,
+ 12'b1xxx10100011,
+ 12'b1xxx10101011,
+ 12'b1xxx10110011,
+ 12'b1xxx10111011: alub_sel = `ALUB_BC;
+ 12'b1xxx01110100,
+ 12'b1xxx100xx011: alub_sel = `ALUB_CC;
+ 12'b1xxx11000011,
+ 12'b1xxx11001011,
+ 12'b1xxx10100000,
+ 12'b1xxx10101000,
+ 12'b1xxx10110000,
+ 12'b1xxx10110100,
+ 12'b1xxx10111100,
+ 12'b1xxx10111000: alub_sel = `ALUB_DE;
+ 12'b1xxx10000010,
+ 12'b1xxx10000100,
+ 12'b1xxx10001010,
+ 12'b1xxx10001100,
+ 12'b1xxx10010010,
+ 12'b1xxx10010100,
+ 12'b1xxx10011010,
+ 12'b1xxx10011100,
+ 12'b1xxx11000010,
+ 12'b1xxx11001010,
+ 12'b001010xxxxxx,
+ 12'b1xxx10100001,
+ 12'b1xxx10100010,
+ 12'b1xxx10101001,
+ 12'b1xxx10101010,
+ 12'b1xxx10110001,
+ 12'b1xxx10110010,
+ 12'b1xxx10111001,
+ 12'b1xxx10111010: alub_sel = `ALUB_HL;
+ 12'b000011001001,
+ 12'b000011100011,
+ 12'b000011xxx000,
+ 12'b000011xx0001,
+ 12'b0001xxxxxxxx,
+ 12'b010011100001,
+ 12'b010011100011,
+ 12'b010111100001,
+ 12'b010111100011,
+ 12'b1xxx01000101,
+ 12'b1xxx01001101: alub_sel = `ALUB_SP;
+ default: alub_sel = `ALUB_TMP;
+ endcase
+ end
+ `RD2B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000011100011: alub_sel = `ALUB_HL;
+ 12'b010011100011: alub_sel = `ALUB_IX;
+ 12'b010111100011: alub_sel = `ALUB_IY;
+ 12'b010000110001,
+ 12'b010000110111,
+ 12'b010000xx0111,
+ 12'b010100110001,
+ 12'b010100110111,
+ 12'b010100xx0111,
+ 12'b1xxx00110110,
+ 12'b1xxx00110111,
+ 12'b1xxx00xx0111,
+ 12'b000000001010,
+ 12'b000000011010,
+ 12'b000000101010,
+ 12'b000000111010,
+ 12'b000001xxxxxx,
+ 12'b000010000xxx,
+ 12'b000010001xxx,
+ 12'b000010010xxx,
+ 12'b000010011xxx,
+ 12'b000010100xxx,
+ 12'b000010101xxx,
+ 12'b000010110xxx,
+ 12'b000010111xxx,
+ 12'b000011011011,
+ 12'b000011xx0001,
+ 12'b001001xxx110,
+ 12'b001001xxxxxx,
+ 12'b010000101010,
+ 12'b010001xxx110,
+ 12'b010010000110,
+ 12'b010010001110,
+ 12'b010010010110,
+ 12'b010010011110,
+ 12'b010010100110,
+ 12'b010010101110,
+ 12'b010010110110,
+ 12'b010010111110,
+ 12'b010011100001,
+ 12'b010100101010,
+ 12'b010101xxx110,
+ 12'b010110000110,
+ 12'b010110001110,
+ 12'b010110010110,
+ 12'b010110011110,
+ 12'b010110100110,
+ 12'b010110101110,
+ 12'b010110110110,
+ 12'b010110111110,
+ 12'b010111100001,
+ 12'b011001xxx110,
+ 12'b011101xxx110,
+ 12'b1xxx00xxx000,
+ 12'b1xxx00xxx100,
+ 12'b1xxx01xxx000,
+ 12'b1xxx01xxx100,
+ 12'b1xxx01xx1011: alub_sel = `ALUB_PC;
+ 12'b0001xxxxxxxx: alub_sel = `ALUB_PCH;
+ default: alub_sel = `ALUB_DIN;
+ endcase
+ end
+ `WR1A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10100100,
+ 12'b1xxx10101100: alub_sel = `ALUB_BB;
+ 12'b1xxx10000100,
+ 12'b1xxx10001100,
+ 12'b1xxx10100010,
+ 12'b1xxx10101010,
+ 12'b1xxx10110010,
+ 12'b1xxx10111010: alub_sel = `ALUB_BC;
+ 12'b1xxx10000010,
+ 12'b1xxx10001010,
+ 12'b1xxx10010010,
+ 12'b1xxx10011010: alub_sel = `ALUB_CC;
+ 12'b1xxx10010100,
+ 12'b1xxx10011100,
+ 12'b1xxx11000010,
+ 12'b1xxx11001010: alub_sel = `ALUB_DE;
+ 12'b1xxx00111110,
+ 12'b1xxx00111111,
+ 12'b1xxx00xx1111,
+ 12'b1xxx10100100,
+ 12'b1xxx10101100,
+ 12'b1xxx10110100,
+ 12'b1xxx10111100,
+ 12'b1xxx11000011,
+ 12'b1xxx11001011,
+ 12'b1xxx100xx011,
+ 12'b1xxx10100000,
+ 12'b1xxx10100011,
+ 12'b1xxx10101000,
+ 12'b1xxx10101011,
+ 12'b1xxx10110000,
+ 12'b1xxx10110011,
+ 12'b1xxx10111000,
+ 12'b1xxx10111011: alub_sel = `ALUB_HL;
+ 12'b010000111110,
+ 12'b010000111111,
+ 12'b010000xx1111,
+ 12'b010100111110,
+ 12'b010100111111,
+ 12'b010100xx1111,
+ 12'b000000100010,
+ 12'b010000100010,
+ 12'b010100100010,
+ 12'b1xxx01xx0011: alub_sel = `ALUB_TMP;
+ default: alub_sel = `ALUB_SP;
+ endcase
+ end
+ `WR1B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10010010,
+ 12'b1xxx10011010,
+ 12'b010000001111,
+ 12'b010100001111,
+ 12'b1xxx00001111,
+ 12'b1xxx1001x011,
+ 12'b1xxx10110010,
+ 12'b1xxx10110011,
+ 12'b1xxx10111010,
+ 12'b1xxx10111011: alub_sel = `ALUB_BB;
+ 12'b1xxx10010100,
+ 12'b1xxx10011100,
+ 12'b1xxx11000010,
+ 12'b1xxx11000011,
+ 12'b1xxx11001010,
+ 12'b1xxx11001011,
+ 12'b1xxx10110100,
+ 12'b1xxx10111100,
+ 12'b1xxx10110000,
+ 12'b1xxx10111000: alub_sel = `ALUB_BC;
+ 12'b010000011111,
+ 12'b010100011111,
+ 12'b1xxx00011111: alub_sel = `ALUB_DD;
+ 12'b010000101111,
+ 12'b010100101111,
+ 12'b1xxx00101111,
+ 12'b000000100010,
+ 12'b000011100011: alub_sel = `ALUB_HH;
+ 12'b010011100101: alub_sel = `ALUB_IX;
+ 12'b010000111111,
+ 12'b010100111110,
+ 12'b1xxx00111111,
+ 12'b010000100010,
+ 12'b010011100011: alub_sel = `ALUB_IXH;
+ 12'b010111100101: alub_sel = `ALUB_IY;
+ 12'b010000111110,
+ 12'b010100111111,
+ 12'b1xxx00111110,
+ 12'b010100100010,
+ 12'b010111100011: alub_sel = `ALUB_IYH;
+ 12'b1xxx01000011: alub_sel = `ALUB_BC;
+ 12'b1xxx01010011: alub_sel = `ALUB_DE;
+ 12'b1xxx01100011: alub_sel = `ALUB_HL;
+ 12'b1xxx01110011: alub_sel = `ALUB_SP;
+ 12'b000011000101: alub_sel = `ALUB_BC;
+ 12'b000011010101: alub_sel = `ALUB_DE;
+ 12'b000011100101: alub_sel = `ALUB_HL;
+ 12'b000011110101: alub_sel = `ALUB_AF;
+ 12'b1xxx01100101,
+ 12'b1xxx01100110: alub_sel = `ALUB_TMP;
+ default: alub_sel = `ALUB_PC;
+ endcase
+ end
+ `WR2A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10000010,
+ 12'b1xxx10001010,
+ 12'b1xxx10010010,
+ 12'b1xxx10011010: alub_sel = `ALUB_CC;
+ 12'b1xxx10100010,
+ 12'b1xxx10101010,
+ 12'b1xxx10110010,
+ 12'b1xxx10111010: alub_sel = `ALUB_BC;
+ 12'b1xxx10010100,
+ 12'b1xxx10011100,
+ 12'b1xxx11000010,
+ 12'b1xxx11001010: alub_sel = `ALUB_DE;
+ 12'b000011001101,
+ 12'b000011xxx100: alub_sel = `ALUB_DIN;
+ default: alub_sel = `ALUB_HL;
+ endcase
+ end
+ `WR2B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10000010,
+ 12'b1xxx10000100,
+ 12'b1xxx10001010,
+ 12'b1xxx10001100,
+ 12'b1xxx10010010,
+ 12'b1xxx10011010,
+ 12'b1xxx10100100,
+ 12'b1xxx10101100,
+ 12'b1xxx100xx011,
+ 12'b1xxx10100010,
+ 12'b1xxx10100011,
+ 12'b1xxx10101010,
+ 12'b1xxx10101011,
+ 12'b1xxx10110010,
+ 12'b1xxx10110011,
+ 12'b1xxx10111010,
+ 12'b1xxx10111011: alub_sel = `ALUB_BB;
+ 12'b1xxx10010100,
+ 12'b1xxx10011100,
+ 12'b1xxx11000010,
+ 12'b1xxx11000011,
+ 12'b1xxx11001010,
+ 12'b1xxx11001011,
+ 12'b1xxx10110100,
+ 12'b1xxx10111100,
+ 12'b1xxx10100000,
+ 12'b1xxx10101000,
+ 12'b1xxx10110000,
+ 12'b1xxx10111000: alub_sel = `ALUB_BC;
+ default: alub_sel = `ALUB_PC;
+ endcase
+ end
+ `BLK1: alub_sel = `ALUB_HL;
+ `BLK2: alub_sel = (inst_reg[4]) ? `ALUB_BC : `ALUB_PC;
+ `PCA,
+ `PCO: alub_sel = `ALUB_PC;
+ `IF1A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10100011,
+ 12'b1xxx10101011,
+ 12'b1xxx10110011,
+ 12'b1xxx10111011: alub_sel = `ALUB_BB;
+ 12'b1xxx10100100,
+ 12'b1xxx10101100,
+ 12'b1xxx100xx011: alub_sel = `ALUB_CC;
+ 12'b1xxx11000011,
+ 12'b1xxx11001011,
+ 12'b1xxx10100000,
+ 12'b1xxx10101000,
+ 12'b1xxx10110100,
+ 12'b1xxx10111100,
+ 12'b1xxx10110000,
+ 12'b1xxx10111000: alub_sel = `ALUB_DE;
+ 12'b1xxx10000010,
+ 12'b1xxx10000100,
+ 12'b1xxx10001010,
+ 12'b1xxx10001100,
+ 12'b1xxx10010010,
+ 12'b1xxx10010100,
+ 12'b1xxx10011010,
+ 12'b1xxx10011100,
+ 12'b1xxx10101010,
+ 12'b1xxx10111010,
+ 12'b1xxx10100010,
+ 12'b1xxx10110010,
+ 12'b1xxx11000010,
+ 12'b1xxx11001010: alub_sel = `ALUB_HL;
+ default: alub_sel = `ALUB_DIN;
+ endcase
+ end
+ `INTA: alub_sel = `ALUB_SP;
+ `INTB: alub_sel = `ALUB_PCH;
+ default: alub_sel = `ALUB_PC;
+ endcase
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* register write control */
+ /* */
+ /*****************************************************************************************/
+ always @ (inst_reg or page_reg or state_reg or carry_bit or par_bit or sign_bit or
+ vector_int or zero_bit) begin
+ casex (state_reg) //synopsys parallel_case
+ `OF1B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000000010000: wr_addr = `WREG_BB;
+ default: wr_addr = `WREG_NUL;
+ endcase
+ end
+ `OF2B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000011001101: wr_addr = `WREG_SP;
+ 12'b000011000100: wr_addr = ( !zero_bit) ? `WREG_SP : `WREG_NUL;
+ 12'b000011001100: wr_addr = ( zero_bit) ? `WREG_SP : `WREG_NUL;
+ 12'b000011010100: wr_addr = (!carry_bit) ? `WREG_SP : `WREG_NUL;
+ 12'b000011011100: wr_addr = ( carry_bit) ? `WREG_SP : `WREG_NUL;
+ 12'b000011100100: wr_addr = ( !par_bit) ? `WREG_SP : `WREG_NUL;
+ 12'b000011101100: wr_addr = ( par_bit) ? `WREG_SP : `WREG_NUL;
+ 12'b000011110100: wr_addr = ( !sign_bit) ? `WREG_SP : `WREG_NUL;
+ 12'b000011111100: wr_addr = ( sign_bit) ? `WREG_SP : `WREG_NUL;
+ default: wr_addr = `WREG_NUL;
+ endcase
+ end
+ `IF3B: wr_addr = `WREG_TMP;
+ `ADR1: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx01110100: wr_addr = `WREG_TMP;
+ default: wr_addr = `WREG_NUL;
+ endcase
+ end
+ `ADR2: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10100100,
+ 12'b1xxx10101100: wr_addr = `WREG_HL;
+ 12'b1xxx01100101,
+ 12'b1xxx01100110,
+ 12'b000011xxx111,
+ 12'b000011xx0101,
+ 12'b010011100101,
+ 12'b010111100101: wr_addr = `WREG_SP;
+ 12'b010000110001,
+ 12'b010000110111,
+ 12'b010000111110,
+ 12'b010000111111,
+ 12'b010000xx0111,
+ 12'b010000xx1111,
+ 12'b010100110001,
+ 12'b010100110111,
+ 12'b010100111110,
+ 12'b010100111111,
+ 12'b010100xx0111,
+ 12'b010100xx1111,
+ 12'b000000100010,
+ 12'b000000101010,
+ 12'b010000100010,
+ 12'b010000101010,
+ 12'b010000110100,
+ 12'b010000110101,
+ 12'b010100100010,
+ 12'b010100101010,
+ 12'b010100110100,
+ 12'b010100110101,
+ 12'b1xxx01xx0011,
+ 12'b1xxx01xx1011: wr_addr = `WREG_TMP;
+ default: wr_addr = `WREG_NUL;
+ endcase
+ end
+ `RD1A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10000010,
+ 12'b1xxx10000100,
+ 12'b1xxx10001010,
+ 12'b1xxx10001100,
+ 12'b1xxx10010010,
+ 12'b1xxx10011010,
+ 12'b1xxx100xx011,
+ 12'b1xxx10100010,
+ 12'b1xxx10100011,
+ 12'b1xxx10101010,
+ 12'b1xxx10101011,
+ 12'b1xxx10110010,
+ 12'b1xxx10110011,
+ 12'b1xxx10111010,
+ 12'b1xxx10111011: wr_addr = `WREG_BB;
+ 12'b1xxx10010100,
+ 12'b1xxx10011100,
+ 12'b1xxx10110100,
+ 12'b1xxx10111100,
+ 12'b1xxx11000010,
+ 12'b1xxx11000011,
+ 12'b1xxx11001010,
+ 12'b1xxx11001011,
+ 12'b1xxx10100000,
+ 12'b1xxx10100001,
+ 12'b1xxx10101000,
+ 12'b1xxx10101001,
+ 12'b1xxx10110000,
+ 12'b1xxx10110001,
+ 12'b1xxx10111000,
+ 12'b1xxx10111001: wr_addr = `WREG_BC;
+ default: wr_addr = `WREG_NUL;
+ endcase
+ end
+ `RD1B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000011001001,
+ 12'b000011xxx000,
+ 12'b000011xx0001,
+ 12'b010011100001,
+ 12'b010111100001,
+ 12'b1xxx01000101,
+ 12'b1xxx01001101: wr_addr = `WREG_SP;
+ default: wr_addr = `WREG_NUL;
+ endcase
+ end
+ `RD2A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10000010,
+ 12'b1xxx10000100,
+ 12'b1xxx10001010,
+ 12'b1xxx10001100,
+ 12'b1xxx10010010,
+ 12'b1xxx10011010,
+ 12'b1xxx10100100,
+ 12'b1xxx10101100,
+ 12'b1xxx100xx011,
+ 12'b1xxx10100010,
+ 12'b1xxx10100011,
+ 12'b1xxx10101010,
+ 12'b1xxx10101011,
+ 12'b1xxx10110010,
+ 12'b1xxx10110011,
+ 12'b1xxx10111010,
+ 12'b1xxx10111011: wr_addr = `WREG_BB;
+ 12'b1xxx10010100,
+ 12'b1xxx10011100,
+ 12'b1xxx10110100,
+ 12'b1xxx10111100,
+ 12'b1xxx11000010,
+ 12'b1xxx11000011,
+ 12'b1xxx11001010,
+ 12'b1xxx11001011,
+ 12'b1xxx10100000,
+ 12'b1xxx10100001,
+ 12'b1xxx10101000,
+ 12'b1xxx10101001,
+ 12'b1xxx10110000,
+ 12'b1xxx10110001,
+ 12'b1xxx10111000,
+ 12'b1xxx10111001: wr_addr = `WREG_BC;
+ default: wr_addr = `WREG_NUL;
+ endcase
+ end
+ `RD2B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx100xx011: wr_addr = `WREG_CC;
+ 12'b1xxx10110100,
+ 12'b1xxx10111100,
+ 12'b1xxx10100000,
+ 12'b1xxx10101000,
+ 12'b1xxx10110000,
+ 12'b1xxx10111000: wr_addr = `WREG_DE;
+ 12'b1xxx10000010,
+ 12'b1xxx10000100,
+ 12'b1xxx10001010,
+ 12'b1xxx10001100,
+ 12'b1xxx10010010,
+ 12'b1xxx10010100,
+ 12'b1xxx10011010,
+ 12'b1xxx10011100,
+ 12'b1xxx10100010,
+ 12'b1xxx10101010,
+ 12'b1xxx10110010,
+ 12'b1xxx10111010,
+ 12'b1xxx11000010,
+ 12'b1xxx11001010: wr_addr = `WREG_HL;
+ 12'b000011001001,
+ 12'b000011xxx000,
+ 12'b000011xx0001,
+ 12'b0001xxxxxxxx,
+ 12'b010011100001,
+ 12'b010111100001,
+ 12'b1xxx01000101,
+ 12'b1xxx01001101: wr_addr = `WREG_SP;
+ default: wr_addr = `WREG_NUL;
+ endcase
+ end
+ `WR1A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx01100101,
+ 12'b1xxx01100110: wr_addr = `WREG_TMP;
+ default: wr_addr = `WREG_NUL;
+ endcase
+ end
+ `WR1B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10100100,
+ 12'b1xxx10101100: wr_addr = `WREG_BB;
+ 12'b1xxx10000010,
+ 12'b1xxx10000100,
+ 12'b1xxx10001010,
+ 12'b1xxx10001100,
+ 12'b1xxx10010010,
+ 12'b1xxx10011010: wr_addr = `WREG_CC;
+ 12'b1xxx10010100,
+ 12'b1xxx10011100: wr_addr = `WREG_DE;
+ 12'b1xxx10110100,
+ 12'b1xxx10111100,
+ 12'b1xxx11000011,
+ 12'b1xxx11001011,
+ 12'b1xxx100xx011,
+ 12'b1xxx10100000,
+ 12'b1xxx10100011,
+ 12'b1xxx10101000,
+ 12'b1xxx10101011,
+ 12'b1xxx10110000,
+ 12'b1xxx10110011,
+ 12'b1xxx10111000,
+ 12'b1xxx10111011: wr_addr = `WREG_HL;
+ 12'b1xxx01100101,
+ 12'b1xxx01100110,
+ 12'b000011001101,
+ 12'b000011xxx100,
+ 12'b000011xxx111,
+ 12'b000011xx0101,
+ 12'b0001xxxxxxxx,
+ 12'b010011100101,
+ 12'b010111100101: wr_addr = `WREG_SP;
+ default: wr_addr = `WREG_NUL;
+ endcase
+ end
+ `WR2B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10000010,
+ 12'b1xxx10000100,
+ 12'b1xxx10001010,
+ 12'b1xxx10001100,
+ 12'b1xxx10010010,
+ 12'b1xxx10011010: wr_addr = `WREG_CC;
+ 12'b1xxx10010100,
+ 12'b1xxx10011100: wr_addr = `WREG_DE;
+ 12'b1xxx10100100,
+ 12'b1xxx10101100,
+ 12'b1xxx10110100,
+ 12'b1xxx10111100,
+ 12'b1xxx11000011,
+ 12'b1xxx11001011,
+ 12'b1xxx100xx011,
+ 12'b1xxx10100000,
+ 12'b1xxx10100011,
+ 12'b1xxx10101000,
+ 12'b1xxx10101011,
+ 12'b1xxx10110000,
+ 12'b1xxx10110011,
+ 12'b1xxx10111000,
+ 12'b1xxx10111011: wr_addr = `WREG_HL;
+ default: wr_addr = `WREG_NUL;
+ endcase
+ end
+ `BLK2: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10100001,
+ 12'b1xxx10101001,
+ 12'b1xxx10110001,
+ 12'b1xxx10111001: wr_addr = `WREG_HL;
+ default: wr_addr = `WREG_NUL;
+ endcase
+ end
+ `IF1B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000000000111,
+ 12'b000000001010,
+ 12'b000000001111,
+ 12'b000000010111,
+ 12'b000000011010,
+ 12'b000000011111,
+ 12'b000000100111,
+ 12'b000000101111,
+ 12'b000000111010,
+ 12'b00000011110x,
+ 12'b000000111110,
+ 12'b000001111xxx,
+ 12'b000010000xxx,
+ 12'b000010001xxx,
+ 12'b000010010xxx,
+ 12'b000010011xxx,
+ 12'b000010100xxx,
+ 12'b000010101xxx,
+ 12'b000010110xxx,
+ 12'b000011000110,
+ 12'b000011001110,
+ 12'b000011010110,
+ 12'b000011011011,
+ 12'b000011011110,
+ 12'b000011100110,
+ 12'b000011101110,
+ 12'b000011110110,
+ 12'b001000xxx111,
+ 12'b00101xxxx111,
+ 12'b010010000100,
+ 12'b010010000101,
+ 12'b010010000110,
+ 12'b010010001100,
+ 12'b010010001101,
+ 12'b010010001110,
+ 12'b010010010100,
+ 12'b010010010101,
+ 12'b010010010110,
+ 12'b010010011100,
+ 12'b010010011101,
+ 12'b010010011110,
+ 12'b010010100100,
+ 12'b010010100101,
+ 12'b010010100110,
+ 12'b010010101100,
+ 12'b010010101101,
+ 12'b010010101110,
+ 12'b010010110100,
+ 12'b010010110101,
+ 12'b010010110110,
+ 12'b010110000100,
+ 12'b010110000101,
+ 12'b010110000110,
+ 12'b010110001100,
+ 12'b010110001101,
+ 12'b010110001110,
+ 12'b010110010100,
+ 12'b010110010101,
+ 12'b010110010110,
+ 12'b010110011100,
+ 12'b010110011101,
+ 12'b010110011110,
+ 12'b010110100100,
+ 12'b010110100101,
+ 12'b010110100110,
+ 12'b010110101100,
+ 12'b010110101101,
+ 12'b010110101110,
+ 12'b010110110100,
+ 12'b010110110101,
+ 12'b010110110110,
+ 12'b010x0111110x,
+ 12'b010x01111110,
+ 12'b1xxx01000100,
+ 12'b1xxx01010111,
+ 12'b1xxx01011111,
+ 12'b1xxx01100111,
+ 12'b1xxx01101111,
+ 12'b1xxx0x111000: wr_addr = `WREG_AA;
+ 12'b000011110001: wr_addr = `WREG_AF;
+ 12'b00000000010x,
+ 12'b000000000110,
+ 12'b000001000xxx,
+ 12'b001000xxx000,
+ 12'b00101xxxx000,
+ 12'b010x0100010x,
+ 12'b010x01000110,
+ 12'b1xxx0x000000,
+ 12'b1xxx10100011,
+ 12'b1xxx10101011,
+ 12'b1xxx10110011,
+ 12'b1xxx10111011: wr_addr = `WREG_BB;
+ 12'b010000000111,
+ 12'b010100000111,
+ 12'b1xxx00000111,
+ 12'b1xxx00000010,
+ 12'b1xxx00000011,
+ 12'b000000000001,
+ 12'b00000000x011,
+ 12'b000011000001,
+ 12'b1xxx01001100,
+ 12'b1xxx01001011: wr_addr = `WREG_BC;
+ 12'b1xxx10100100,
+ 12'b1xxx10101100,
+ 12'b00000000110x,
+ 12'b000000001110,
+ 12'b000001001xxx,
+ 12'b001000xxx001,
+ 12'b00101xxxx001,
+ 12'b010x0100110x,
+ 12'b010x01001110,
+ 12'b1xxx100xx011,
+ 12'b1xxx0x001000: wr_addr = `WREG_CC;
+ 12'b00000001010x,
+ 12'b000000010110,
+ 12'b000001010xxx,
+ 12'b001000xxx010,
+ 12'b00101xxxx010,
+ 12'b010x0101010x,
+ 12'b010x01010110,
+ 12'b1xxx0x010000: wr_addr = `WREG_DD;
+ 12'b010000010111,
+ 12'b010100010111,
+ 12'b1xxx00010111,
+ 12'b1xxx10110100,
+ 12'b1xxx10111100,
+ 12'b1xxx00010010,
+ 12'b1xxx00010011,
+ 12'b000011010001,
+ 12'b00000001x011,
+ 12'b000000010001,
+ 12'b1xxx01011100,
+ 12'b1xxx01011011,
+ 12'b1xxx10100000,
+ 12'b1xxx10101000,
+ 12'b1xxx10110000,
+ 12'b1xxx10111000: wr_addr = `WREG_DE;
+ 12'b000011101011: wr_addr = `WREG_DEHL;
+ 12'b00000001110x,
+ 12'b000000011110,
+ 12'b000001011xxx,
+ 12'b001000xxx011,
+ 12'b00101xxxx011,
+ 12'b010x0101110x,
+ 12'b010x01011110,
+ 12'b1xxx0x011000: wr_addr = `WREG_EE;
+ 12'b00000010010x,
+ 12'b000000100110,
+ 12'b000001100xxx,
+ 12'b001000xxx100,
+ 12'b00101xxxx100,
+ 12'b010x01100110,
+ 12'b1xxx0x100000: wr_addr = `WREG_HH;
+ 12'b010000100111,
+ 12'b010100100111,
+ 12'b1xxx00100010,
+ 12'b1xxx00100011,
+ 12'b1xxx00100111,
+ 12'b1xxx10000010,
+ 12'b1xxx10000100,
+ 12'b1xxx10001010,
+ 12'b1xxx10001100,
+ 12'b1xxx10010010,
+ 12'b1xxx10010100,
+ 12'b1xxx10011010,
+ 12'b1xxx10011100,
+ 12'b000000100001,
+ 12'b000000101010,
+ 12'b00000010x011,
+ 12'b000000xx1001,
+ 12'b000011100001,
+ 12'b000011100011,
+ 12'b1xxx01101100,
+ 12'b1xxx01101011,
+ 12'b1xxx01xx0010,
+ 12'b1xxx01xx1010,
+ 12'b1xxx10100010,
+ 12'b1xxx10101010,
+ 12'b1xxx10110010,
+ 12'b1xxx10111010,
+ 12'b1xxx11000010,
+ 12'b1xxx11001010: wr_addr = `WREG_HL;
+ 12'b1xxx01000111: wr_addr = `WREG_II;
+ 12'b010000110111,
+ 12'b010100110001,
+ 12'b1xxx00110111,
+ 12'b1xxx00110010,
+ 12'b1xxx01010100,
+ 12'b010000100001,
+ 12'b010000100011,
+ 12'b010000101010,
+ 12'b010000101011,
+ 12'b010000xx1001,
+ 12'b010011100001,
+ 12'b010011100011: wr_addr = `WREG_IX;
+ 12'b010000100100,
+ 12'b010000100101,
+ 12'b010000100110,
+ 12'b0100011000xx,
+ 12'b01000110010x,
+ 12'b010001100111: wr_addr = `WREG_IXH;
+ 12'b010000101100,
+ 12'b010000101101,
+ 12'b010000101110,
+ 12'b0100011010xx,
+ 12'b01000110110x,
+ 12'b010001101111: wr_addr = `WREG_IXL;
+ 12'b010000110001,
+ 12'b010100110111,
+ 12'b1xxx00110110,
+ 12'b1xxx00110011,
+ 12'b1xxx01010101,
+ 12'b010100100001,
+ 12'b010100100011,
+ 12'b010100101010,
+ 12'b010100101011,
+ 12'b010100xx1001,
+ 12'b010111100001,
+ 12'b010111100011: wr_addr = `WREG_IY;
+ 12'b010100100100,
+ 12'b010100100101,
+ 12'b010100100110,
+ 12'b0101011000xx,
+ 12'b01010110010x,
+ 12'b010101100111: wr_addr = `WREG_IYH;
+ 12'b010100101100,
+ 12'b010100101101,
+ 12'b010100101110,
+ 12'b0101011010xx,
+ 12'b01010110110x,
+ 12'b010101101111: wr_addr = `WREG_IYL;
+ 12'b00000010110x,
+ 12'b000000101110,
+ 12'b000001101xxx,
+ 12'b001000xxx101,
+ 12'b00101xxxx101,
+ 12'b010x01101110,
+ 12'b1xxx0x101000: wr_addr = `WREG_LL;
+ 12'b1xxx01001111: wr_addr = `WREG_RR;
+ 12'b000000110001,
+ 12'b00000011x011,
+ 12'b000011111001,
+ 12'b010x11111001,
+ 12'b1xxx01111100,
+ 12'b1xxx01111011: wr_addr = `WREG_SP;
+ default: wr_addr = `WREG_NUL;
+ endcase
+ end
+ `INTB: wr_addr = (vector_int) ? `WREG_TMP : `WREG_SP;
+ default: wr_addr = `WREG_NUL;
+ endcase
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* s flag control */
+ /* */
+ /*****************************************************************************************/
+ always @ (inst_reg or page_reg or state_reg) begin
+ casex (state_reg) //synopsys parallel_case
+ `WR2A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000000110100,
+ 12'b000000110101,
+ 12'b001000xxxxxx,
+ 12'b010000110100,
+ 12'b010000110101,
+ 12'b010100110100,
+ 12'b010100110101,
+ 12'b011x00xxxxxx: sflg_en = 1'b1;
+ default: sflg_en = 1'b0;
+ endcase
+ end
+ `BLK1: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10100001,
+ 12'b1xxx10101001,
+ 12'b1xxx10110001,
+ 12'b1xxx10111001: sflg_en = 1'b1;
+ default: sflg_en = 1'b0;
+ endcase
+ end
+ `IF1B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000000100111,
+ 12'b0000000xx100,12'b00000010x100,12'b000000111100,
+ 12'b0000000xx101,12'b00000010x101,12'b000000111101,
+ 12'b000010000110,
+ 12'b000010000xxx,
+ 12'b000010001110,
+ 12'b000010001xxx,
+ 12'b000010010110,
+ 12'b000010010xxx,
+ 12'b000010011110,
+ 12'b000010011xxx,
+ 12'b000010100110,
+ 12'b000010100xxx,
+ 12'b000010101110,
+ 12'b000010101xxx,
+ 12'b000010110110,
+ 12'b000010110xxx,
+ 12'b000010111110,
+ 12'b000010111xxx,
+ 12'b000011000110,
+ 12'b000011001110,
+ 12'b000011010110,
+ 12'b000011011110,
+ 12'b000011100110,
+ 12'b000011101110,
+ 12'b000011110110,
+ 12'b000011111110,
+ 12'b001000xxx0xx,
+ 12'b001000xxx10x,
+ 12'b001000xxx111,
+ 12'b010000100100,
+ 12'b010000100101,
+ 12'b010000101100,
+ 12'b010000101101,
+ 12'b010010000100,
+ 12'b010010000101,
+ 12'b010010000110,
+ 12'b010010001100,
+ 12'b010010001101,
+ 12'b010010001110,
+ 12'b010010010100,
+ 12'b010010010101,
+ 12'b010010010110,
+ 12'b010010011100,
+ 12'b010010011101,
+ 12'b010010011110,
+ 12'b010010100100,
+ 12'b010010100101,
+ 12'b010010100110,
+ 12'b010010101100,
+ 12'b010010101101,
+ 12'b010010101110,
+ 12'b010010110100,
+ 12'b010010110101,
+ 12'b010010110110,
+ 12'b010010111100,
+ 12'b010010111101,
+ 12'b010010111110,
+ 12'b010100100100,
+ 12'b010100100101,
+ 12'b010100101100,
+ 12'b010100101101,
+ 12'b010110000100,
+ 12'b010110000101,
+ 12'b010110000110,
+ 12'b010110001100,
+ 12'b010110001101,
+ 12'b010110001110,
+ 12'b010110010100,
+ 12'b010110010101,
+ 12'b010110010110,
+ 12'b010110011100,
+ 12'b010110011101,
+ 12'b010110011110,
+ 12'b010110100100,
+ 12'b010110100101,
+ 12'b010110100110,
+ 12'b010110101100,
+ 12'b010110101101,
+ 12'b010110101110,
+ 12'b010110110100,
+ 12'b010110110101,
+ 12'b010110110110,
+ 12'b010110111100,
+ 12'b010110111101,
+ 12'b010110111110,
+ 12'b1xxx00110100,
+ 12'b1xxx00xxxx00,
+ 12'b1xxx011x0100,
+ 12'b1xxx01000100,
+ 12'b1xxx01010111,
+ 12'b1xxx01011111,
+ 12'b1xxx01100111,
+ 12'b1xxx01101111,
+ 12'b1xxx01xxx000,
+ 12'b1xxx01xx0010,
+ 12'b1xxx01xx1010: sflg_en = 1'b1;
+ default: sflg_en = 1'b0;
+ endcase
+ end
+ default: sflg_en = 1'b0;
+ endcase
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* z flag control */
+ /* */
+ /*****************************************************************************************/
+ always @ (inst_reg or page_reg or state_reg) begin
+ casex (state_reg) //synopsys parallel_case
+ `RD1A,
+ `RD2A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10000010,
+ 12'b1xxx10000100,
+ 12'b1xxx10001010,
+ 12'b1xxx10001100,
+ 12'b1xxx10010010,
+ 12'b1xxx10010100,
+ 12'b1xxx10011010,
+ 12'b1xxx10011100,
+ 12'b1xxx10110100,
+ 12'b1xxx10111100,
+ 12'b1xxx11000010,
+ 12'b1xxx11000011,
+ 12'b1xxx11001010,
+ 12'b1xxx11001011,
+ 12'b1xxx100xx011,
+ 12'b1xxx10100010,
+ 12'b1xxx10100011,
+ 12'b1xxx10101010,
+ 12'b1xxx10101011,
+ 12'b1xxx10110010,
+ 12'b1xxx10110011,
+ 12'b1xxx10111010,
+ 12'b1xxx10111011: zflg_en = 1'b1;
+ default: zflg_en = 1'b0;
+ endcase
+ end
+ `WR1B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10100100,
+ 12'b1xxx10101100: zflg_en = 1'b1;
+ default: zflg_en = 1'b0;
+ endcase
+ end
+ `WR2A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000000110100,
+ 12'b000000110101,
+ 12'b001000xxxxxx,
+ 12'b010000110100,
+ 12'b010000110101,
+ 12'b010100110100,
+ 12'b010100110101,
+ 12'b011x00xxxxxx: zflg_en = 1'b1;
+ default: zflg_en = 1'b0;
+ endcase
+ end
+ `BLK1: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10100001,
+ 12'b1xxx10101001,
+ 12'b1xxx10110001,
+ 12'b1xxx10111001: zflg_en = 1'b1;
+ default: zflg_en = 1'b0;
+ endcase
+ end
+ `IF1B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000000100111,
+ 12'b0000000xx100,12'b00000010x100,12'b000000111100,
+ 12'b0000000xx101,12'b00000010x101,12'b000000111101,
+ 12'b000010000110,
+ 12'b000010000xxx,
+ 12'b000010001110,
+ 12'b000010001xxx,
+ 12'b000010010110,
+ 12'b000010010xxx,
+ 12'b000010011110,
+ 12'b000010011xxx,
+ 12'b000010100110,
+ 12'b000010100xxx,
+ 12'b000010101110,
+ 12'b000010101xxx,
+ 12'b000010110110,
+ 12'b000010110xxx,
+ 12'b000010111110,
+ 12'b000010111xxx,
+ 12'b000011000110,
+ 12'b000011001110,
+ 12'b000011010110,
+ 12'b000011011110,
+ 12'b000011100110,
+ 12'b000011101110,
+ 12'b000011110110,
+ 12'b000011111110,
+ 12'b001000xxx0xx,12'b001000xxx10x,12'b001000xxx111,
+ 12'b001001xxx110,
+ 12'b001001xxxxxx,
+ 12'b010000100100,
+ 12'b010000100101,
+ 12'b010000101100,
+ 12'b010000101101,
+ 12'b010010000100,
+ 12'b010010000101,
+ 12'b010010000110,
+ 12'b010010001100,
+ 12'b010010001101,
+ 12'b010010001110,
+ 12'b010010010100,
+ 12'b010010010101,
+ 12'b010010010110,
+ 12'b010010011100,
+ 12'b010010011101,
+ 12'b010010011110,
+ 12'b010010100100,
+ 12'b010010100101,
+ 12'b010010100110,
+ 12'b010010101100,
+ 12'b010010101101,
+ 12'b010010101110,
+ 12'b010010110100,
+ 12'b010010110101,
+ 12'b010010110110,
+ 12'b010010111100,
+ 12'b010010111101,
+ 12'b010010111110,
+ 12'b010100100100,
+ 12'b010100100101,
+ 12'b010100101100,
+ 12'b010100101101,
+ 12'b010110000100,
+ 12'b010110000101,
+ 12'b010110000110,
+ 12'b010110001100,
+ 12'b010110001101,
+ 12'b010110001110,
+ 12'b010110010100,
+ 12'b010110010101,
+ 12'b010110010110,
+ 12'b010110011100,
+ 12'b010110011101,
+ 12'b010110011110,
+ 12'b010110100100,
+ 12'b010110100101,
+ 12'b010110100110,
+ 12'b010110101100,
+ 12'b010110101101,
+ 12'b010110101110,
+ 12'b010110110100,
+ 12'b010110110101,
+ 12'b010110110110,
+ 12'b010110111100,
+ 12'b010110111101,
+ 12'b010110111110,
+ 12'b011001xxx110,
+ 12'b011101xxx110,
+ 12'b1xxx00xxxx00,
+ 12'b1xxx01000100,
+ 12'b1xxx01010111,
+ 12'b1xxx01011111,
+ 12'b1xxx01100111,
+ 12'b1xxx01101111,
+ 12'b1xxx011x0100,
+ 12'b1xxx01xxx000,
+ 12'b1xxx01xx0010,
+ 12'b1xxx01xx1010,
+ 12'b1xxx10100011,
+ 12'b1xxx10101011,
+ 12'b1xxx10110011,
+ 12'b1xxx10111011: zflg_en = 1'b1;
+ default: zflg_en = 1'b0;
+ endcase
+ end
+ default: zflg_en = 1'b0;
+ endcase
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* h flag control */
+ /* */
+ /*****************************************************************************************/
+ always @ (inst_reg or page_reg or state_reg) begin
+ casex (state_reg) //synopsys parallel_case
+ `WR2A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b001000xxxxxx,
+ 12'b011x00xxxxxx,
+ 12'b1xxx01100111,
+ 12'b1xxx01101111: hflg_ctl = `HFLG_0;
+ 12'b000000110100,
+ 12'b000000110101,
+ 12'b010x00110100,
+ 12'b010x00110101: hflg_ctl = `HFLG_H;
+ default: hflg_ctl = `HFLG_NUL;
+ endcase
+ end
+ `BLK1: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10100001,
+ 12'b1xxx10101001,
+ 12'b1xxx10110001,
+ 12'b1xxx10111001: hflg_ctl = `HFLG_H;
+ default: hflg_ctl = `HFLG_NUL;
+ endcase
+ end
+ `IF1B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000000000111,
+ 12'b000000001111,
+ 12'b000000010111,
+ 12'b000000011111,
+ 12'b000000110111,
+ 12'b000010101110,
+ 12'b000010101xxx,
+ 12'b000010110110,
+ 12'b000010110xxx,
+ 12'b000011101110,
+ 12'b000011110110,
+ 12'b001000000xxx,
+ 12'b001000001xxx,
+ 12'b001000010xxx,
+ 12'b001000011xxx,
+ 12'b001000100xxx,
+ 12'b001000101xxx,
+ 12'b001000110xxx,
+ 12'b001000111xxx,
+ 12'b010010101100,
+ 12'b010010101101,
+ 12'b010010101110,
+ 12'b010010110100,
+ 12'b010010110101,
+ 12'b010010110110,
+ 12'b010110101100,
+ 12'b010110101101,
+ 12'b010110101110,
+ 12'b010110110100,
+ 12'b010110110101,
+ 12'b010110110110,
+ 12'b1xxx00xxx000,
+ 12'b1xxx01010111,
+ 12'b1xxx01011111,
+ 12'b1xxx01xxx000,
+ 12'b1xxx10100000,
+ 12'b1xxx10101000,
+ 12'b1xxx10110000,
+ 12'b1xxx10111000: hflg_ctl = `HFLG_0;
+ 12'b000000101111,
+ 12'b000010100110,
+ 12'b000010100xxx,
+ 12'b000011100110,
+ 12'b001001xxx110,
+ 12'b001001xxxxxx,
+ 12'b010010100100,
+ 12'b010010100101,
+ 12'b010010100110,
+ 12'b010110100100,
+ 12'b010110100101,
+ 12'b010110100110,
+ 12'b011001xxx110,
+ 12'b011101xxx110,
+ 12'b1xxx00xxx100,
+ 12'b1xxx011x0100: hflg_ctl = `HFLG_1;
+ 12'b000000111111,
+ 12'b000000100111,
+ 12'b0000000xx100,12'b00000010x100,12'b000000111100,
+ 12'b0000000xx101,12'b00000010x101,12'b000000111101,
+ 12'b000000xx1001,
+ 12'b000010000110,
+ 12'b000010000xxx,
+ 12'b000010001110,
+ 12'b000010001xxx,
+ 12'b000010010110,
+ 12'b000010010xxx,
+ 12'b000010011110,
+ 12'b000010011xxx,
+ 12'b000010111110,
+ 12'b000010111xxx,
+ 12'b000011000110,
+ 12'b000011001110,
+ 12'b000011010110,
+ 12'b000011011110,
+ 12'b000011111110,
+ 12'b010000100100,
+ 12'b010000100101,
+ 12'b010000101100,
+ 12'b010000101101,
+ 12'b010000xx1001,
+ 12'b010010000100,
+ 12'b010010000101,
+ 12'b010010000110,
+ 12'b010010001100,
+ 12'b010010001101,
+ 12'b010010001110,
+ 12'b010010010100,
+ 12'b010010010101,
+ 12'b010010010110,
+ 12'b010010011100,
+ 12'b010010011101,
+ 12'b010010011110,
+ 12'b010010111100,
+ 12'b010010111101,
+ 12'b010010111110,
+ 12'b010100100100,
+ 12'b010100100101,
+ 12'b010100101100,
+ 12'b010100101101,
+ 12'b010100xx1001,
+ 12'b010110000100,
+ 12'b010110000101,
+ 12'b010110000110,
+ 12'b010110001100,
+ 12'b010110001101,
+ 12'b010110001110,
+ 12'b010110010100,
+ 12'b010110010101,
+ 12'b010110010110,
+ 12'b010110011100,
+ 12'b010110011101,
+ 12'b010110011110,
+ 12'b010110111100,
+ 12'b010110111101,
+ 12'b010110111110,
+ 12'b1xxx01000100,
+ 12'b1xxx01xx0010,
+ 12'b1xxx01xx1010: hflg_ctl = `HFLG_H;
+ default: hflg_ctl = `HFLG_NUL;
+ endcase
+ end
+ default: hflg_ctl = `HFLG_NUL;
+ endcase
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* pv flag control */
+ /* */
+ /*****************************************************************************************/
+ always @ (inst_reg or page_reg or state_reg) begin
+ casex (state_reg) //synopsys parallel_case
+ `RD1A,
+ `RD2A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10100000,
+ 12'b1xxx10100001,
+ 12'b1xxx10101000,
+ 12'b1xxx10101001,
+ 12'b1xxx10110000,
+ 12'b1xxx10110001,
+ 12'b1xxx10111000,
+ 12'b1xxx10111001: pflg_ctl = `PFLG_B;
+ default: pflg_ctl = `PFLG_NUL;
+ endcase
+ end
+ `WR2A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b001000xxxxxx,
+ 12'b011x00xxxxxx: pflg_ctl = `PFLG_P;
+ 12'b000000110100,
+ 12'b000000110101,
+ 12'b010000110100,
+ 12'b010000110101,
+ 12'b010100110100,
+ 12'b010100110101: pflg_ctl = `PFLG_V;
+ default: pflg_ctl = `PFLG_NUL;
+ endcase
+ end
+ `IF1B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx01010111,
+ 12'b1xxx01011111: pflg_ctl = `PFLG_F;
+ 12'b000000100111,
+ 12'b000010100110,
+ 12'b000010100xxx,
+ 12'b000010101110,
+ 12'b000010101xxx,
+ 12'b000010110110,
+ 12'b000010110xxx,
+ 12'b000011100110,
+ 12'b000011101110,
+ 12'b000011110110,
+ 12'b001000xxx0xx,12'b001000xxx10x,12'b001000xxx111,
+ 12'b010010100100,
+ 12'b010010100101,
+ 12'b010010100110,
+ 12'b010010101100,
+ 12'b010010101101,
+ 12'b010010101110,
+ 12'b010010110100,
+ 12'b010010110101,
+ 12'b010010110110,
+ 12'b010110100100,
+ 12'b010110100101,
+ 12'b010110100110,
+ 12'b010110101100,
+ 12'b010110101101,
+ 12'b010110101110,
+ 12'b010110110100,
+ 12'b010110110101,
+ 12'b010110110110,
+ 12'b1xxx00xxxx00,
+ 12'b1xxx00110100,
+ 12'b1xxx011x0100,
+ 12'b1xxx01100111,
+ 12'b1xxx01101111,
+ 12'b1xxx01xxx000: pflg_ctl = `PFLG_P;
+ 12'b0000000xx100,12'b00000010x100,12'b000000111100,
+ 12'b0000000xx101,12'b00000010x101,12'b000000111101,
+ 12'b000010000110,
+ 12'b000010000xxx,
+ 12'b000010001110,
+ 12'b000010001xxx,
+ 12'b000010010110,
+ 12'b000010010xxx,
+ 12'b000010011110,
+ 12'b000010011xxx,
+ 12'b000010111110,
+ 12'b000010111xxx,
+ 12'b000011000110,
+ 12'b000011001110,
+ 12'b000011010110,
+ 12'b000011011110,
+ 12'b000011111110,
+ 12'b010000100100,
+ 12'b010000100101,
+ 12'b010000101100,
+ 12'b010000101101,
+ 12'b010010000100,
+ 12'b010010000101,
+ 12'b010010000110,
+ 12'b010010001100,
+ 12'b010010001101,
+ 12'b010010001110,
+ 12'b010010010100,
+ 12'b010010010101,
+ 12'b010010010110,
+ 12'b010010011100,
+ 12'b010010011101,
+ 12'b010010011110,
+ 12'b010010111100,
+ 12'b010010111101,
+ 12'b010010111110,
+ 12'b010100100100,
+ 12'b010100100101,
+ 12'b010100101100,
+ 12'b010100101101,
+ 12'b010110000100,
+ 12'b010110000101,
+ 12'b010110000110,
+ 12'b010110001100,
+ 12'b010110001101,
+ 12'b010110001110,
+ 12'b010110010100,
+ 12'b010110010101,
+ 12'b010110010110,
+ 12'b010110011100,
+ 12'b010110011101,
+ 12'b010110011110,
+ 12'b010110111100,
+ 12'b010110111101,
+ 12'b010110111110,
+ 12'b1xxx01000100,
+ 12'b1xxx01xx0010,
+ 12'b1xxx01xx1010: pflg_ctl = `PFLG_V;
+ default: pflg_ctl = `PFLG_NUL;
+ endcase
+ end
+ default: pflg_ctl = `PFLG_NUL;
+ endcase
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* n flag control */
+ /* */
+ /*****************************************************************************************/
+ always @ (inst_reg or page_reg or state_reg) begin
+ casex (state_reg) //synopsys parallel_case
+ `WR1A,
+ `WR2A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b1xxx10100010,
+ 12'b1xxx10100011,
+ 12'b1xxx10101010,
+ 12'b1xxx10101011,
+ 12'b1xxx10110010,
+ 12'b1xxx10110011,
+ 12'b1xxx10111010,
+ 12'b1xxx10111011: nflg_ctl = `NFLG_S;
+ default: nflg_ctl = `NFLG_NUL;
+ endcase
+ end
+ `IF1B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000000000111,
+ 12'b000000001111,
+ 12'b000000010111,
+ 12'b000000011111,
+ 12'b000000110100,
+ 12'b000000110111,
+ 12'b000000111111,
+ 12'b000000xxx100,
+ 12'b000000xx1001,
+ 12'b000010000110,
+ 12'b000010000xxx,
+ 12'b000010001110,
+ 12'b000010001xxx,
+ 12'b000010100110,
+ 12'b000010100xxx,
+ 12'b000010101110,
+ 12'b000010101xxx,
+ 12'b000010110110,
+ 12'b000010110xxx,
+ 12'b000011000110,
+ 12'b000011001110,
+ 12'b000011100110,
+ 12'b000011101110,
+ 12'b000011110110,
+ 12'b010000100100,
+ 12'b010000101100,
+ 12'b010000110100,
+ 12'b010000xx1001,
+ 12'b010010000100,
+ 12'b010010000101,
+ 12'b010010000110,
+ 12'b010010001100,
+ 12'b010010001101,
+ 12'b010010001110,
+ 12'b010010100100,
+ 12'b010010100101,
+ 12'b010010100110,
+ 12'b010010101100,
+ 12'b010010101101,
+ 12'b010010101110,
+ 12'b010010110100,
+ 12'b010010110101,
+ 12'b010010110110,
+ 12'b010100100100,
+ 12'b010100101100,
+ 12'b010100110100,
+ 12'b010100xx1001,
+ 12'b010110000100,
+ 12'b010110000101,
+ 12'b010110000110,
+ 12'b010110001100,
+ 12'b010110001101,
+ 12'b010110001110,
+ 12'b010110100100,
+ 12'b010110100101,
+ 12'b010110100110,
+ 12'b010110101100,
+ 12'b010110101101,
+ 12'b010110101110,
+ 12'b010110110100,
+ 12'b010110110101,
+ 12'b010110110110,
+ 12'b00100xxxxxxx,
+ 12'b011x0xxxxxxx,
+ 12'b1xxx00xxxx00,
+ 12'b1xxx00110100,
+ 12'b1xxx011x0100,
+ 12'b1xxx01010111,
+ 12'b1xxx01011111,
+ 12'b1xxx01100111,
+ 12'b1xxx01101111,
+ 12'b1xxx01xxx000,
+ 12'b1xxx01xx1010,
+ 12'b1xxx10100000,
+ 12'b1xxx10101000,
+ 12'b1xxx10110000,
+ 12'b1xxx10111000: nflg_ctl = `NFLG_0;
+ 12'b1xxx10000010,
+ 12'b1xxx10000100,
+ 12'b1xxx10001010,
+ 12'b1xxx10001100,
+ 12'b1xxx10010010,
+ 12'b1xxx10010100,
+ 12'b1xxx10011010,
+ 12'b1xxx10011100,
+ 12'b1xxx10100100,
+ 12'b1xxx10101100,
+ 12'b1xxx10110100,
+ 12'b1xxx10111100,
+ 12'b1xxx11000010,
+ 12'b1xxx11000011,
+ 12'b1xxx11001010,
+ 12'b1xxx11001011,
+ 12'b000000101111,
+ 12'b000000110101,
+ 12'b000000xxx101,
+ 12'b000010010110,
+ 12'b000010010xxx,
+ 12'b000010011110,
+ 12'b000010011xxx,
+ 12'b000010111110,
+ 12'b000010111xxx,
+ 12'b000011010110,
+ 12'b000011011110,
+ 12'b000011111110,
+ 12'b010000100101,
+ 12'b010000101101,
+ 12'b010000110101,
+ 12'b010010010100,
+ 12'b010010010101,
+ 12'b010010010110,
+ 12'b010010011100,
+ 12'b010010011101,
+ 12'b010010011110,
+ 12'b010010111100,
+ 12'b010010111101,
+ 12'b010010111110,
+ 12'b010100100101,
+ 12'b010100101101,
+ 12'b010100110101,
+ 12'b010110010100,
+ 12'b010110010101,
+ 12'b010110010110,
+ 12'b010110011100,
+ 12'b010110011101,
+ 12'b010110011110,
+ 12'b010110111100,
+ 12'b010110111101,
+ 12'b010110111110,
+ 12'b1xxx01000100,
+ 12'b1xxx01xx0010,
+ 12'b1xxx100xx011,
+ 12'b1xxx10100001,
+ 12'b1xxx10101001,
+ 12'b1xxx10110001,
+ 12'b1xxx10111001: nflg_ctl = `NFLG_1;
+ default: nflg_ctl = `NFLG_NUL;
+ endcase
+ end
+ default: nflg_ctl = `NFLG_NUL;
+ endcase
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* c flag control */
+ /* */
+ /*****************************************************************************************/
+ always @ (inst_reg or page_reg or state_reg) begin
+ casex (state_reg) //synopsys parallel_case
+ `WR2A: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b001000xxxxxx,
+ 12'b011x00xxxxxx: cflg_en = 1'b1;
+ default: cflg_en = 1'b0;
+ endcase
+ end
+ `IF1B: begin
+ casex ({page_reg, inst_reg}) //synopsys parallel_case
+ 12'b000010100110,
+ 12'b000010100xxx,
+ 12'b000010101110,
+ 12'b000010101xxx,
+ 12'b000010110110,
+ 12'b000010110xxx,
+ 12'b000011100110,
+ 12'b000011101110,
+ 12'b000011110110,
+ 12'b010010100100,
+ 12'b010010100101,
+ 12'b010010100110,
+ 12'b010010101100,
+ 12'b010010101101,
+ 12'b010010101110,
+ 12'b010010110100,
+ 12'b010010110101,
+ 12'b010010110110,
+ 12'b010110100100,
+ 12'b010110100101,
+ 12'b010110100110,
+ 12'b010110101100,
+ 12'b010110101101,
+ 12'b010110101110,
+ 12'b010110110100,
+ 12'b010110110101,
+ 12'b010110110110,
+ 12'b000000110111,
+ 12'b000000000111,
+ 12'b000000001111,
+ 12'b000000010111,
+ 12'b000000011111,
+ 12'b000000100111,
+ 12'b000000111111,
+ 12'b000000xx1001,
+ 12'b000010000110,
+ 12'b000010000xxx,
+ 12'b000010001110,
+ 12'b000010001xxx,
+ 12'b000010010110,
+ 12'b000010010xxx,
+ 12'b000010011110,
+ 12'b000010011xxx,
+ 12'b000010111110,
+ 12'b000010111xxx,
+ 12'b000011000110,
+ 12'b000011001110,
+ 12'b000011010110,
+ 12'b000011011110,
+ 12'b000011111110,
+ 12'b001000xxx0xx,12'b001000xxx10x,12'b001000xxx111,
+ 12'b010000xx1001,
+ 12'b010010000100,
+ 12'b010010000101,
+ 12'b010010000110,
+ 12'b010010001100,
+ 12'b010010001101,
+ 12'b010010001110,
+ 12'b010010010100,
+ 12'b010010010101,
+ 12'b010010010110,
+ 12'b010010011100,
+ 12'b010010011101,
+ 12'b010010011110,
+ 12'b010010111100,
+ 12'b010010111101,
+ 12'b010010111110,
+ 12'b010100xx1001,
+ 12'b010110000100,
+ 12'b010110000101,
+ 12'b010110000110,
+ 12'b010110001100,
+ 12'b010110001101,
+ 12'b010110001110,
+ 12'b010110010100,
+ 12'b010110010101,
+ 12'b010110010110,
+ 12'b010110011100,
+ 12'b010110011101,
+ 12'b010110011110,
+ 12'b010110111100,
+ 12'b010110111101,
+ 12'b010110111110,
+ 12'b1xxx00xxxx00,
+ 12'b1xxx00110100,
+ 12'b1xxx011x0100,
+ 12'b1xxx01000100,
+ 12'b1xxx01xx0010,
+ 12'b1xxx01xx1010: cflg_en = 1'b1;
+ default: cflg_en = 1'b0;
+ endcase
+ end
+ default: cflg_en = 1'b0;
+ endcase
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* temporary flag control */
+ /* */
+ /*****************************************************************************************/
+ always @ (inst_reg or page_reg or state_reg) begin
+ casex (state_reg) //synopsys parallel_case
+ `OF1B: tflg_ctl = `TFLG_Z;
+ `RD1A,
+ `RD2A: begin
+ casex ({page_reg, inst_reg})
+ 12'b1xxx10100011,
+ 12'b1xxx10101011,
+ 12'b1xxx10110011,
+ 12'b1xxx10111011: tflg_ctl = `TFLG_1;
+ default: tflg_ctl = `TFLG_Z;
+ endcase
+ end
+ `BLK1: tflg_ctl = `TFLG_B;
+ default: tflg_ctl = `TFLG_NUL;
+ endcase
+ end
+
+ endmodule
\ No newline at end of file
diff --git a/common/CPU/z180/datapath.v b/common/CPU/z180/datapath.v
new file mode 100644
index 00000000..6437a018
--- /dev/null
+++ b/common/CPU/z180/datapath.v
@@ -0,0 +1,691 @@
+/*******************************************************************************************/
+/** **/
+/** ORIGINAL COPYRIGHT (C) 2011, SYSTEMYDE INTERNATIONAL CORPORATION, ALL RIGHTS RESERVED **/
+/** COPYRIGHT (C) 2012, SERGEY BELYASHOV **/
+/** **/
+/** data path module Rev 0.0 05/13/2012 **/
+/** **/
+/*******************************************************************************************/
+module datapath (addr_reg_in, carry_bit, dmar_reg, dout_io_reg, dout_mem_reg, inst_reg,
+ intr_reg, page_reg, par_bit, sign_bit, tflg_reg, vector_int, xhlt_reg,
+ zero_bit, add_sel, alua_sel, alub_sel, aluop_sel, clearb, clkc, cflg_en,
+ data_in, di_ctl, dma_req, do_ctl, ex_af_pls, ex_bank_pls, ex_dehl_inst,
+ hflg_ctl, ief_ctl, imd_ctl, int_req, ivec_rd, ld_ctrl, ld_inst, ld_page,
+ nflg_ctl, nmi_req, page_sel, pc_sel, pflg_ctl, resetb, sflg_en, tflg_ctl,
+ wait_st, wr_addr, zflg_en, rreg_en);
+
+ input cflg_en; /* carry flag control */
+ input clearb; /* master (testing) reset */
+ input clkc; /* main cpu clock */
+ input dma_req; /* dma request */
+ input ex_af_pls; /* exchange af,af' */
+ input ex_bank_pls; /* exchange register bank */
+ input ex_dehl_inst; /* exchange de,hl */
+ input int_req; /* interrupt request */
+ input ivec_rd; /* interrupt vector enable */
+ input ld_ctrl; /* load control register */
+ input ld_inst; /* load instruction register */
+ input ld_page; /* load page register */
+ input nmi_req; /* nmi request */
+ input resetb; /* internal (user) reset */
+ input rreg_en; /* update R register */
+ input sflg_en; /* sign flag control */
+ input wait_st; /* wait state identifier */
+ input zflg_en; /* zero flag control */
+ input [3:0] page_sel; /* instruction decode "page" control */
+ input [7:0] data_in; /* read data bus */
+ input [`ADCTL_IDX:0] add_sel; /* address output mux control */
+ input [`ALUA_IDX:0] alua_sel; /* alu input a mux control */
+ input [`ALUB_IDX:0] alub_sel; /* alu input b mux control */
+ input [`ALUOP_IDX:0] aluop_sel; /* alu operation control */
+ input [`DI_IDX:0] di_ctl; /* data input control */
+ input [`DO_IDX:0] do_ctl; /* data output control */
+ input [`HFLG_IDX:0] hflg_ctl; /* half-carry flag control */
+ input [`IEF_IDX:0] ief_ctl; /* interrupt enable control */
+ input [`IMD_IDX:0] imd_ctl; /* interrupt mode control */
+ input [`NFLG_IDX:0] nflg_ctl; /* negate flag control */
+ input [`PCCTL_IDX:0] pc_sel; /* program counter source control */
+ input [`PFLG_IDX:0] pflg_ctl; /* parity/overflow flag control */
+ input [`TFLG_IDX:0] tflg_ctl; /* temp flag control */
+ input [`WREG_IDX:0] wr_addr; /* register write address bus */
+ output carry_bit; /* carry flag */
+ output dmar_reg; /* latched dma request */
+ output intr_reg; /* latched interrupt request */
+ output par_bit; /* parity flag */
+ output sign_bit; /* sign flag */
+ output tflg_reg; /* temporary flag */
+ output vector_int; /* int vector enable */
+ output xhlt_reg; /* halt exit */
+ output zero_bit; /* zero flag */
+ output [3:0] page_reg; /* instruction decode "page" */
+ output [7:0] inst_reg; /* instruction register */
+ output [7:0] dout_io_reg; /* i/o write data bus */
+ output [7:0] dout_mem_reg; /* memory write data bus */
+ output [15:0] addr_reg_in; /* processor address bus */
+
+ /*****************************************************************************************/
+ /* */
+ /* signal declarations */
+ /* */
+ /*****************************************************************************************/
+ wire adder_c; /* math carry */
+ wire adder_hc; /* math half-carry */
+ wire adder_ov; /* math overflow result */
+ wire alu_carry; /* final carry */
+ wire alu_hcar; /* final half-carry */
+ wire alu_neg; /* final negate */
+ wire alu_one; /* final one */
+ wire alu_sign; /* final sign */
+ wire alu_zero; /* final zero */
+ wire bit7, bit6, bit5, bit4; /* bit decode */
+ wire bit3, bit2, bit1, bit0;
+ wire carry_bit; /* carry flag */
+ wire carry_daa; /* daa carry */
+ wire cry_nxt; /* combined carry */
+ wire daa_l1, daa_l2, daa_l3, daa_l4; /* decimal adjust */
+ wire daa_l5, daa_h1, daa_h2, daa_h3;
+ wire daa_h4, daa_h5, daa_h6, daa_h7;
+ wire daa1, daa2, daa3, daa4, daa5;
+ wire daa6, daa7;
+ wire hcar_nxt; /* combined half-carry */
+ wire hi_byte; /* replicate data byte */
+ wire ld_m_aa, ld_m_ff, ld_m_bb, ld_m_cc; /* register loads */
+ wire ld_m_dd, ld_m_ee, ld_m_hh, ld_m_ll;
+ wire ld_a_aa, ld_a_ff, ld_a_bb, ld_a_cc;
+ wire ld_a_dd, ld_a_ee, ld_a_hh, ld_a_ll;
+ wire ld_sp;
+ wire ld_ixh, ld_ixl, ld_iyh, ld_iyl;
+ wire ld_ii, ld_rr, ld_tmp;
+ wire ld_dout_io, ld_dout_mem; /* load data out */
+ wire ld_flag; /* load flags */
+ wire ld_regf; /* load register file */
+ wire ld_tflg; /* load temp flag */
+ wire logic_c; /* logic carry */
+ wire logic_hc; /* logic half-carry */
+ wire one_nxt; /* combined one */
+ wire par_bit; /* parity flag */
+ wire par_nxt; /* combined parity */
+ wire shft_c; /* shift carry */
+ wire sign_bit; /* sign flag */
+ wire sign_nxt; /* combined sign */
+ wire vector_int; /* int vector enable */
+ wire zero_bit; /* zero flag */
+ wire zero_nxt; /* combined zero */
+ wire [7:0] bit_mask; /* mask for bit inst */
+ wire [7:0] daa_out; /* daa result */
+ wire [7:0] ff_reg_in; /* register input */
+ wire [7:0] aa_reg_out, ff_reg_out; /* register outputs */
+ wire [7:0] new_flags; /* new flag byte */
+ wire [7:0] rst_addr; /* restart address */
+ wire [7:0] shft_out; /* shift result */
+ wire [15:8] bsign_ext; /* address alu b sign extend */
+ wire [15:0] adda_in, addb_in; /* address alu inputs */
+ wire [15:0] adder_out; /* math result */
+ wire [15:0] addr_alu8, addr_alu, addr_hl, addr_pc, addr_sp; /* address mux terms */
+ wire [15:0] addr_reg_in; /* address register input */
+ wire [15:0] alua_in, alub_in; /* alu inputs */
+ wire [15:0] data_bus; /* alu output */
+ wire [15:0] de_reg_in; /* register inputs */
+ wire [15:0] af_reg_out, bc_reg_out; /* register outputs */
+ wire [15:0] de_reg_out, hl_reg_out;
+ wire [15:0] logic_out; /* logic result */
+
+ reg alt_af_reg, alt_bnk_reg; /* main/alt select */
+ reg alu_ovflo; /* final ov */
+ reg daa_sel, daa_op; /* daa operation */
+ reg decr_sel, decr_op; /* decrement operation */
+ reg dmar_reg; /* latched dma request */
+ reg ex_dehl_reg; /* special exchange */
+ reg ief1_reg; /* int enable flag 1 */
+ reg ief2_reg; /* int enable flag 2 */
+ reg imd1_reg; /* int mode 1 */
+ reg imd2_reg; /* int mode 2 */
+ reg intr_reg; /* latched int req */
+ reg ld_dmar, ld_intr; /* sample int/dma */
+ reg ld_pc; /* load pc */
+ reg nmi_hld; /* nmi edge tracker */
+ reg nmi_reg; /* latched nmi req */
+ reg tflg_nxt, tflg_reg; /* temp flag */
+ reg valid_dma; /* valid dma request */
+ reg valid_int, valid_nmi, valid_xhlt; /* valid int request */
+ reg word_sel, word_op; /* 16-bit operation */
+ reg xhlt_reg; /* halt exit */
+ reg [3:0] page_reg /* synthesis syn_preserve=1 */;
+ reg [7:0] inst_reg; /* instruction register */
+ reg [7:0] m_aa_reg, m_ff_reg, m_bb_reg, m_cc_reg; /* individual registers */
+ reg [7:0] m_dd_reg, m_ee_reg, m_hh_reg, m_ll_reg;
+ reg [7:0] a_aa_reg, a_ff_reg, a_bb_reg, a_cc_reg;
+ reg [7:0] a_dd_reg, a_ee_reg, a_hh_reg, a_ll_reg;
+ reg [7:0] ii_reg, rr_reg;
+ reg [7:0] din0_reg, din1_reg; /* data input registers */
+ reg [7:0] dout_io_reg, dout_mem_reg; /* data output registers */
+ reg [15:0] adda_out; /* address alu out */
+ reg [15:0] int_addr; /* interrupt address */
+ reg [15:0] ix_reg, iy_reg; /* index registers */
+ reg [15:0] pc_reg; /* program counter */
+ reg [15:0] sp_reg; /* stack pointer */
+ reg [15:0] tmp_reg; /* temporary register */
+ reg [`ADCTL_IDX:0] addsel_reg /* synthesis syn_preserve=1 */;
+ reg [`ALUA_IDX:0] alua_reg /* synthesis syn_preserve=1 */;
+ reg [`ALUB_IDX:0] alub_reg /* synthesis syn_preserve=1 */;
+ reg [`ALUOP_IDX:0] aluop_reg /* synthesis syn_preserve=1 */;
+
+ /*****************************************************************************************/
+ /* */
+ /* input synchronization */
+ /* */
+ /*****************************************************************************************/
+ always @ (posedge clkc or negedge resetb) begin
+ if (!resetb) begin
+ nmi_hld <= 1'b0;
+ valid_dma <= 1'b0;
+ valid_int <= 1'b0;
+ valid_nmi <= 1'b0;
+ valid_xhlt <= 1'b0;
+ end
+ else begin
+ nmi_hld <= (nmi_req && !valid_nmi) || (!(ivec_rd && nmi_reg) && nmi_hld);
+ valid_dma <= dma_req;
+ valid_int <= nmi_req || nmi_hld || ((&ief_ctl[1:0] || ief1_reg) && int_req);
+ valid_nmi <= nmi_req || nmi_hld;
+ valid_xhlt <= !dma_req && (nmi_req || nmi_hld || (ief1_reg && int_req));
+ end
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* interrupt mode and enables */
+ /* */
+ /*****************************************************************************************/
+ always @ (posedge clkc or negedge resetb) begin
+ if (!resetb) begin
+ ief1_reg <= 1'b0;
+ ief2_reg <= 1'b0;
+ imd1_reg <= 1'b0;
+ imd2_reg <= 1'b0;
+ end
+ else begin
+ if (|ief_ctl[2:1]) ief1_reg <= (ief_ctl[1]) ? ief_ctl[0] : (ief_ctl[0] && ief2_reg);
+ if (|ief_ctl[2:1]) ief2_reg <= (ief_ctl[1]) ? ief_ctl[0] :
+ (ief_ctl[0]) ? ief2_reg : (nmi_reg && ief1_reg);
+ if (|imd_ctl) imd1_reg <= imd_ctl[1] && !imd_ctl[0];
+ if (|imd_ctl) imd2_reg <= &imd_ctl;
+ end
+ end
+
+ assign vector_int = imd2_reg && !nmi_reg;
+
+ /*****************************************************************************************/
+ /* */
+ /* interrupt pending */
+ /* */
+ /*****************************************************************************************/
+ always @ (pc_sel or wait_st) begin
+ case (pc_sel)
+ `PC_DMA, /* dma xfer dma sample */
+ `PC_INT: ld_dmar = 1'b1; /* block inst dma sample */
+ `PC_NILD: ld_dmar = !wait_st; /* inst end dma sample */
+ default: ld_dmar = 1'b0;
+ endcase
+ end
+
+ always @ (pc_sel or wait_st) begin
+ case (pc_sel)
+ `PC_INT: ld_intr = 1'b1; /* block inst int sample */
+ `PC_NILD: ld_intr = !wait_st; /* inst end int sample */
+ default: ld_intr = 1'b0;
+ endcase
+ end
+
+ always @ (posedge clkc or negedge resetb) begin
+ if (!resetb) begin
+ dmar_reg <= 1'b0;
+ intr_reg <= 1'b0;
+ nmi_reg <= 1'b0;
+ xhlt_reg <= 1'b0;
+ end
+ else begin
+ if (ld_dmar) dmar_reg <= valid_dma;
+ if (ld_intr) intr_reg <= !valid_dma && (valid_nmi || (ief1_reg && valid_int));
+ if (ld_intr) nmi_reg <= !valid_dma && valid_nmi;
+ if (ld_intr) xhlt_reg <= !valid_dma && valid_xhlt;
+ end
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* register control */
+ /* */
+ /*****************************************************************************************/
+ always @ (pc_sel or dmar_reg or intr_reg or valid_dma or valid_int or wait_st) begin
+ case (pc_sel)
+ `PC_LD: ld_pc = !wait_st; /* load PC unconditionally */
+ `PC_NILD: ld_pc = !((ief1_reg && valid_int) || valid_nmi || valid_dma) && !wait_st;
+ `PC_NILD2: ld_pc = !(intr_reg || dmar_reg) && !wait_st; /* if no latched int */
+ default: ld_pc = 1'b0;
+ endcase
+ end
+
+ always @ (posedge clkc or negedge resetb) begin
+ if (!resetb) begin
+ alt_af_reg <= 1'b0;
+ alt_bnk_reg <= 1'b0;
+ ex_dehl_reg <= 1'b0;
+ end
+ else begin
+ alt_af_reg <= ex_af_pls ^ alt_af_reg;
+ alt_bnk_reg <= ex_bank_pls ^ alt_bnk_reg;
+ ex_dehl_reg <= ex_dehl_inst && ld_ctrl;
+ end
+ end
+
+ assign ld_flag = (sflg_en || zflg_en || |hflg_ctl || |pflg_ctl || |nflg_ctl ||
+ cflg_en) && !wait_st;
+ assign ld_regf = wr_addr[`WR_REG] && !wait_st;
+
+ /*****************************************************************************************/
+ /* */
+ /* cpu register interface */
+ /* */
+ /*****************************************************************************************/
+ assign ff_reg_in = (ld_flag) ? new_flags : data_bus[7:0];
+ assign de_reg_in = (ex_dehl_reg) ? hl_reg_out : data_bus;
+
+ assign ld_m_aa = ld_regf && wr_addr[`WR_AA] && !alt_af_reg;
+ assign ld_m_ff = ((ld_regf && wr_addr[`WR_FF]) || ld_flag) && !alt_af_reg;
+ assign ld_m_bb = ld_regf && wr_addr[`WR_BB] && !alt_bnk_reg;
+ assign ld_m_cc = ld_regf && wr_addr[`WR_CC] && !alt_bnk_reg;
+ assign ld_m_dd = ld_regf && wr_addr[`WR_DD] && !alt_bnk_reg;
+ assign ld_m_ee = ld_regf && wr_addr[`WR_EE] && !alt_bnk_reg;
+ assign ld_m_hh = ld_regf && wr_addr[`WR_HH] && !alt_bnk_reg;
+ assign ld_m_ll = ld_regf && wr_addr[`WR_LL] && !alt_bnk_reg;
+ assign ld_a_aa = ld_regf && wr_addr[`WR_AA] && alt_af_reg;
+ assign ld_a_ff = ((ld_regf && wr_addr[`WR_FF]) || ld_flag) && alt_af_reg;
+ assign ld_a_bb = ld_regf && wr_addr[`WR_BB] && alt_bnk_reg;
+ assign ld_a_cc = ld_regf && wr_addr[`WR_CC] && alt_bnk_reg;
+ assign ld_a_dd = ld_regf && wr_addr[`WR_DD] && alt_bnk_reg;
+ assign ld_a_ee = ld_regf && wr_addr[`WR_EE] && alt_bnk_reg;
+ assign ld_a_hh = ld_regf && wr_addr[`WR_HH] && alt_bnk_reg;
+ assign ld_a_ll = ld_regf && wr_addr[`WR_LL] && alt_bnk_reg;
+ assign ld_sp = ld_regf && wr_addr[`WR_SP];
+ assign ld_ixh = ld_regf && wr_addr[`WR_IXH];
+ assign ld_ixl = ld_regf && wr_addr[`WR_IXL];
+ assign ld_iyh = ld_regf && wr_addr[`WR_IYH];
+ assign ld_iyl = ld_regf && wr_addr[`WR_IYL];
+ assign ld_ii = ld_regf && wr_addr[`WR_II];
+ assign ld_rr = ld_regf && wr_addr[`WR_RR];
+ assign ld_tmp = ld_regf && wr_addr[`WR_TMP];
+
+ assign af_reg_out = (alt_af_reg) ? {a_aa_reg, a_ff_reg} : {m_aa_reg, m_ff_reg};
+ assign bc_reg_out = (alt_bnk_reg) ? {a_bb_reg, a_cc_reg} : {m_bb_reg, m_cc_reg};
+ assign de_reg_out = (alt_bnk_reg) ? {a_dd_reg, a_ee_reg} : {m_dd_reg, m_ee_reg};
+ assign hl_reg_out = (alt_bnk_reg) ? {a_hh_reg, a_ll_reg} : {m_hh_reg, m_ll_reg};
+ assign aa_reg_out = af_reg_out[15:8];
+ assign ff_reg_out = af_reg_out[7:0];
+ assign carry_bit = af_reg_out[0];
+ assign par_bit = af_reg_out[2];
+ assign sign_bit = af_reg_out[7];
+ assign zero_bit = af_reg_out[6];
+ assign hi_byte = (wr_addr[`WR_AA] && !wr_addr[`WR_FF]) ||
+ (wr_addr[`WR_BB] && !wr_addr[`WR_CC]) ||
+ (wr_addr[`WR_DD] && !wr_addr[`WR_EE]) ||
+ (wr_addr[`WR_HH] && !wr_addr[`WR_LL]) ||
+ (wr_addr[`WR_IXH]&& !wr_addr[`WR_IXL]) ||
+ (wr_addr[`WR_IYH]&& !wr_addr[`WR_IYL]) ||
+ wr_addr[`WR_II] || wr_addr[`WR_RR];
+
+ /*****************************************************************************************/
+ /* */
+ /* cpu registers */
+ /* */
+ /*****************************************************************************************/
+ always @ (posedge clkc or negedge clearb) begin
+ if (!clearb) begin
+ m_aa_reg <= 8'h00;
+ m_ff_reg <= 8'h00;
+ m_bb_reg <= 8'h00;
+ m_cc_reg <= 8'h00;
+ m_dd_reg <= 8'h00;
+ m_ee_reg <= 8'h00;
+ m_hh_reg <= 8'h00;
+ m_ll_reg <= 8'h00;
+ a_aa_reg <= 8'h00;
+ a_ff_reg <= 8'h00;
+ a_bb_reg <= 8'h00;
+ a_cc_reg <= 8'h00;
+ a_dd_reg <= 8'h00;
+ a_ee_reg <= 8'h00;
+ a_hh_reg <= 8'h00;
+ a_ll_reg <= 8'h00;
+ ix_reg <= 16'h0000;
+ iy_reg <= 16'h0000;
+ end
+ else begin
+ if (ld_m_aa) m_aa_reg <= data_bus[15:8];
+ if (ld_m_ff) m_ff_reg <= ff_reg_in;
+ if (ld_m_bb) m_bb_reg <= data_bus[15:8];
+ if (ld_m_cc) m_cc_reg <= data_bus[7:0];
+ if (ld_m_dd) m_dd_reg <= de_reg_in[15:8];
+ if (ld_m_ee) m_ee_reg <= de_reg_in[7:0];
+ if (ld_m_hh) m_hh_reg <= data_bus[15:8];
+ if (ld_m_ll) m_ll_reg <= data_bus[7:0];
+ if (ld_a_aa) a_aa_reg <= data_bus[15:8];
+ if (ld_a_ff) a_ff_reg <= ff_reg_in;
+ if (ld_a_bb) a_bb_reg <= data_bus[15:8];
+ if (ld_a_cc) a_cc_reg <= data_bus[7:0];
+ if (ld_a_dd) a_dd_reg <= de_reg_in[15:8];
+ if (ld_a_ee) a_ee_reg <= de_reg_in[7:0];
+ if (ld_a_hh) a_hh_reg <= data_bus[15:8];
+ if (ld_a_ll) a_ll_reg <= data_bus[7:0];
+ if (ld_ixh) ix_reg[15:8] <= data_bus[15:8];
+ if (ld_ixl) ix_reg[7:0] <= data_bus[7:0];
+ if (ld_iyh) iy_reg[15:8] <= data_bus[15:8];
+ if (ld_iyl) iy_reg[7:0] <= data_bus[7:0];
+ end
+ end
+
+ always @ (posedge clkc or negedge resetb) begin
+ if (!resetb) begin
+ ii_reg <= 8'h00;
+ pc_reg <= 16'h0000;
+ rr_reg <= 8'h00;
+ sp_reg <= 16'h0000;
+ tmp_reg <= 16'h0000;
+ end
+ else begin
+ if (ld_ii) ii_reg <= data_bus[15:8];
+ if (ld_pc) pc_reg <= data_bus;
+ if (ld_rr)
+ rr_reg <= data_bus[15:8];
+`ifdef RREG_EMU
+ else
+ rr_reg[6:0] <= rr_reg[6:0] + {6'h0, rreg_en && !dmar_reg && !wait_st};
+`endif
+ if (ld_sp) sp_reg <= data_bus;
+ if (ld_tmp) tmp_reg <= (ivec_rd) ? {ii_reg, data_in} : data_bus;
+ end
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* temporary flag */
+ /* */
+ /*****************************************************************************************/
+ assign ld_tflg = |tflg_ctl && !wait_st;
+
+ always @ (tflg_ctl or alu_one or alu_zero or ff_reg_out) begin
+ casex (tflg_ctl)
+ `TFLG_1: tflg_nxt = alu_one; /* blk set if done (next xfr) */
+ `TFLG_Z: tflg_nxt = alu_zero; /* blk set if done (this xfr) */
+ `TFLG_B: tflg_nxt = alu_zero || !ff_reg_out[2]; /* blk cp set if done or match */
+ default: tflg_nxt = 1'b0;
+ endcase
+ end
+
+ always @ (posedge clkc or negedge resetb) begin
+ if (!resetb) tflg_reg <= 1'b0;
+ else if (ld_tflg) tflg_reg <= tflg_nxt;
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* data input and data output registers */
+ /* */
+ /*****************************************************************************************/
+ assign ld_dout_io = do_ctl[1] && !wait_st;
+ assign ld_dout_mem = do_ctl[2] && !wait_st;
+
+ always @ (posedge clkc or negedge resetb) begin
+ if (!resetb) begin
+ din0_reg <= 8'h00;
+ din1_reg <= 8'h00;
+ dout_io_reg <= 8'h00;
+ dout_mem_reg <= 8'h00;
+ end
+ else begin
+ if (di_ctl[0]) din0_reg <= data_in;
+ if (di_ctl[1]) din1_reg <= data_in;
+ if (ld_dout_io) dout_io_reg <= data_bus[7:0];
+ if (ld_dout_mem) dout_mem_reg <= (do_ctl[0]) ? data_bus[15:8] : data_bus[7:0];
+ end
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* instruction and page registers */
+ /* */
+ /*****************************************************************************************/
+ always @ (posedge clkc or negedge resetb) begin
+ if (!resetb) inst_reg <= 8'h00;
+ else if (ld_inst) inst_reg <= data_in;
+ end
+
+ always @ (posedge clkc or negedge resetb) begin
+ if (!resetb) page_reg <= 4'b0000;
+ else if (ld_page && ld_ctrl) page_reg <= page_sel;
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* alu control pipeline registers */
+ /* */
+ /*****************************************************************************************/
+ always @ (aluop_sel) begin
+ case (aluop_sel) //synopsys parallel_case
+ `ALUOP_DAA: daa_sel = 1'b1;
+ default: daa_sel = 1'b0;
+ endcase
+ end
+
+ always @ (aluop_sel) begin
+ case (aluop_sel) //synopsys parallel_case
+ `ALUOP_BDEC: decr_sel = 1'b1;
+ default: decr_sel = 1'b0;
+ endcase
+ end
+
+ always @ (aluop_sel) begin
+ case (aluop_sel) //synopsys parallel_case
+ `ALUOP_ADC,
+ `ALUOP_ADD,
+ `ALUOP_PASS,
+ `ALUOP_SBC,
+ `ALUOP_SUB: word_sel = 1'b1;
+ default: word_sel = 1'b0;
+ endcase
+ end
+
+ always @ (posedge clkc or negedge resetb) begin
+ if (!resetb) begin
+ addsel_reg <= `ADD_RSTVAL;
+ alua_reg <= `ALUA_RSTVAL;
+ alub_reg <= `ALUB_RSTVAL;
+ aluop_reg <= `ALUOP_RSTVAL;
+ daa_op <= 1'b0;
+ decr_op <= 1'b0;
+ word_op <= 1'b0;
+ end
+ else if (ld_ctrl) begin
+ addsel_reg <= add_sel;
+ alua_reg <= alua_sel;
+ alub_reg <= alub_sel;
+ aluop_reg <= aluop_sel;
+ daa_op <= daa_sel;
+ decr_op <= decr_sel;
+ word_op <= word_sel;
+ end
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* bit manipulation constant generator */
+ /* */
+ /*****************************************************************************************/
+ assign bit7 = (inst_reg[7] && !inst_reg[6]) ^ (inst_reg[5:3] == 3'b111);
+ assign bit6 = (inst_reg[7] && !inst_reg[6]) ^ (inst_reg[5:3] == 3'b110);
+ assign bit5 = (inst_reg[7] && !inst_reg[6]) ^ (inst_reg[5:3] == 3'b101);
+ assign bit4 = (inst_reg[7] && !inst_reg[6]) ^ (inst_reg[5:3] == 3'b100);
+ assign bit3 = (inst_reg[7] && !inst_reg[6]) ^ (inst_reg[5:3] == 3'b011);
+ assign bit2 = (inst_reg[7] && !inst_reg[6]) ^ (inst_reg[5:3] == 3'b010);
+ assign bit1 = (inst_reg[7] && !inst_reg[6]) ^ (inst_reg[5:3] == 3'b001);
+ assign bit0 = (inst_reg[7] && !inst_reg[6]) ^ (inst_reg[5:3] == 3'b000);
+ assign bit_mask = {bit7, bit6, bit5, bit4, bit3, bit2, bit1, bit0};
+
+ /*****************************************************************************************/
+ /* */
+ /* decimal adjust accumulator constant generator */
+ /* */
+ /*****************************************************************************************/
+ assign daa_l1 = !ff_reg_out[1] && !ff_reg_out[4] &&
+ (!aa_reg_out[3] || (aa_reg_out[3] && !aa_reg_out[2] && !aa_reg_out[1]));
+ assign daa_l2 = !ff_reg_out[1] && !ff_reg_out[4] &&
+ (aa_reg_out[3] && (aa_reg_out[2] || aa_reg_out[1]));
+ assign daa_l3 = !ff_reg_out[1] && ff_reg_out[4] && (!aa_reg_out[3] && !aa_reg_out[2]);
+ assign daa_l4 = ff_reg_out[1] && !ff_reg_out[4] &&
+ (!aa_reg_out[3] || (aa_reg_out[3] && !aa_reg_out[2] && !aa_reg_out[1]));
+ assign daa_l5 = ff_reg_out[1] && ff_reg_out[4] &&
+ ((!aa_reg_out[3] && aa_reg_out[2] && aa_reg_out[1]) || aa_reg_out[3]);
+ assign daa_h1 = !ff_reg_out[0] && (aa_reg_out[7] && (aa_reg_out[6] || aa_reg_out[5]));
+ assign daa_h2 = ff_reg_out[0] &&
+ (!aa_reg_out[7] && !aa_reg_out[6] && (!aa_reg_out[5] || !aa_reg_out[4]));
+ assign daa_h3 = !ff_reg_out[0] &&
+ (aa_reg_out[7] && (aa_reg_out[6] || aa_reg_out[5] || aa_reg_out[4]));
+ assign daa_h4 = ff_reg_out[0] && (!aa_reg_out[7] && !aa_reg_out[6]);
+ assign daa_h5 = ff_reg_out[0] &&
+ ((aa_reg_out[6] && aa_reg_out[5] && aa_reg_out[4]) || aa_reg_out[7]);
+ assign daa_h6 = !ff_reg_out[0] &&
+ ((!aa_reg_out[6] && !aa_reg_out[5] && !aa_reg_out[4]) || !aa_reg_out[7]);
+ assign daa_h7 = ff_reg_out[0] && ((aa_reg_out[6] && aa_reg_out[5]) || aa_reg_out[7]);
+
+ assign daa1 = daa_l2 || daa_l3 || daa_l5;
+ assign daa2 = daa_l2 || daa_l3;
+ assign daa3 = daa_l5;
+ assign daa4 = daa_l5 && (daa_h6 || daa_h7);
+ assign daa5 = (daa_l1 && (daa_h1 || daa_h2)) || (daa_l2 && (daa_h2 || daa_h3)) ||
+ (daa_l3 && (daa_h1 || daa_h4)) || (daa_l4 && daa_h5) ||
+ (daa_l5 && daa_h6);
+ assign daa6 = (daa_l1 && (daa_h1 || daa_h2)) || (daa_l2 && (daa_h2 || daa_h3)) ||
+ (daa_l3 && (daa_h1 || daa_h4)) || (daa_l5 && daa_h6);
+ assign daa7 = (daa_l4 && daa_h5) || (daa_l5 && (daa_h6 || daa_h7));
+
+ assign daa_out = {daa7, daa6, daa5, daa4, daa3, daa2, daa1, 1'b0};
+ assign carry_daa = (daa_l1 && (daa_h1 || daa_h2)) || (daa_l2 && (daa_h2 || daa_h3)) ||
+ (daa_l3 && (daa_h1 || daa_h4)) || (daa_l4 && daa_h5) ||
+ (daa_l5 && daa_h7);
+
+ /*****************************************************************************************/
+ /* */
+ /* interrupt/restart address generator */
+ /* */
+ /*****************************************************************************************/
+ assign rst_addr = {2'b00, inst_reg[5:3], 3'b000};
+
+ always @ (nmi_reg or imd2_reg or imd1_reg or din0_reg or din1_reg) begin
+ casex ({nmi_reg, imd2_reg, imd1_reg})
+ 3'b001: int_addr = 16'h0038;
+ 3'b010: int_addr = {din1_reg, din0_reg};
+ 3'b1xx: int_addr = 16'h0066;
+ default: int_addr = 16'h0000;
+ endcase
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* alu input selects */
+ /* */
+ /*****************************************************************************************/
+ aluamux AMUX ( .adda_in(adda_in), .alua_in(alua_in), .alua_reg(alua_reg),
+ .aa_reg_out(aa_reg_out), .bit_mask(bit_mask), .daa_out(daa_out),
+ .hl_reg_out(hl_reg_out), .ii_reg(ii_reg), .int_addr(int_addr),
+ .ix_reg(ix_reg), .iy_reg(iy_reg), .pc_reg(pc_reg), .rr_reg(rr_reg),
+ .rst_addr(rst_addr), .tmp_reg(tmp_reg) );
+
+ alubmux BMUX ( .addb_in(addb_in), .alub_in(alub_in), .alub_reg(alub_reg),
+ .af_reg_out(af_reg_out), .bc_reg_out(bc_reg_out), .de_reg_out(de_reg_out),
+ .din0_reg(din0_reg), .din1_reg(din1_reg), .hl_reg_out(hl_reg_out),
+ .ix_reg(ix_reg), .iy_reg(iy_reg), .pc_reg(pc_reg), .sp_reg(sp_reg),
+ .tmp_reg(tmp_reg) );
+
+ /*****************************************************************************************/
+ /* */
+ /* function units */
+ /* */
+ /*****************************************************************************************/
+ alu_log ALULOG ( .logic_c(logic_c), .logic_hc(logic_hc), .logic_out(logic_out),
+ .alua_in(alua_in), .alub_in(alub_in), .aluop_reg(aluop_reg[`AOP_IDX:0]),
+ .carry_bit(carry_bit) );
+
+ alu_math ALUMATH ( .adder_c(adder_c), .adder_hc(adder_hc), .adder_out(adder_out),
+ .adder_ov(adder_ov), .alua_in(alua_in), .alub_in(alub_in),
+ .aluop_reg(aluop_reg[`AOP_IDX:0]), .carry_bit(carry_bit),
+ .carry_daa(carry_daa), .daa_op(daa_op), .word_op(word_op) );
+
+ alu_shft ALUSHFT ( .shft_c(shft_c), .shft_out(shft_out), .alub_in(alub_in[7:0]),
+ .aluop_reg(aluop_reg[`AOP_IDX:0]), .carry_bit(carry_bit) );
+ wire [15:0] mult_out = alub_in[15:8] * alub_in[7:0];
+ aluout ALUOUT ( .cry_nxt(cry_nxt), .data_bus(data_bus), .hcar_nxt(hcar_nxt),
+ .one_nxt(one_nxt), .par_nxt(par_nxt), .sign_nxt(sign_nxt),
+ .zero_nxt(zero_nxt), .adder_c(adder_c), .adder_hc(adder_hc),
+ .adder_out(adder_out), .hi_byte(hi_byte), .logic_c(logic_c),
+ .logic_hc(logic_hc), .logic_out(logic_out), .shft_c(shft_c),
+ .shft_out(shft_out), .mult_out(mult_out), .unit_sel(aluop_reg[7:6]), .word_op(word_op) );
+
+ /*****************************************************************************************/
+ /* */
+ /* flag generation */
+ /* */
+ /*****************************************************************************************/
+ assign alu_carry = decr_op ^ cry_nxt;
+ assign alu_hcar = (hflg_ctl[1]) ? hflg_ctl[0] : (decr_op ^ hcar_nxt);
+ assign alu_neg = (nflg_ctl[1]) ? nflg_ctl[0] : sign_nxt;
+ assign alu_one = one_nxt;
+ assign alu_sign = sign_nxt;
+ assign alu_zero = zero_nxt;
+
+ always @ (pflg_ctl or adder_ov or ief2_reg or par_nxt or zero_nxt) begin
+ case (pflg_ctl)
+ `PFLG_V: alu_ovflo = adder_ov;
+ `PFLG_1: alu_ovflo = 1'b1;
+ `PFLG_P: alu_ovflo = par_nxt;
+ `PFLG_B: alu_ovflo = !zero_nxt;
+ `PFLG_F: alu_ovflo = ief2_reg;
+ default: alu_ovflo = 1'b0;
+ endcase
+ end
+
+ assign new_flags[7] = (sflg_en) ? alu_sign : ff_reg_out[7];
+ assign new_flags[6] = (zflg_en) ? alu_zero : ff_reg_out[6];
+ assign new_flags[5] = ff_reg_out[5];
+ assign new_flags[4] = (|hflg_ctl) ? alu_hcar : ff_reg_out[4];
+ assign new_flags[3] = ff_reg_out[3];
+ assign new_flags[2] = (|pflg_ctl) ? alu_ovflo : ff_reg_out[2];
+ assign new_flags[1] = (|nflg_ctl) ? alu_neg : ff_reg_out[1];
+ assign new_flags[0] = (cflg_en) ? alu_carry : ff_reg_out[0];
+
+ /*****************************************************************************************/
+ /* */
+ /* address alu */
+ /* */
+ /*****************************************************************************************/
+ assign bsign_ext = {addb_in[7], addb_in[7], addb_in[7], addb_in[7],
+ addb_in[7], addb_in[7], addb_in[7], addb_in[7]};
+
+ always @ (aluop_reg or adda_in or addb_in or bsign_ext) begin
+ case (aluop_reg)
+ `ALUOP_ADS: adda_out = adda_in + {bsign_ext[15:8], addb_in[7:0]};
+ `ALUOP_BADD,
+ `ALUOP_ADD: adda_out = adda_in + addb_in;
+ `ALUOP_APAS: adda_out = adda_in;
+ default: adda_out = addb_in;
+ endcase
+ end
+
+ assign addr_alu8 = (addsel_reg[`AD_ALU8]) ? {8'h00, adda_out[7:0]} : 16'h0000;
+ assign addr_alu = (addsel_reg[`AD_ALU]) ? adda_out : 16'h0000;
+ assign addr_hl = (addsel_reg[`AD_HL]) ? hl_reg_out : 16'h0000;
+ assign addr_pc = (addsel_reg[`AD_PC]) ? pc_reg : 16'h0000;
+ assign addr_sp = (addsel_reg[`AD_SP]) ? sp_reg : 16'h0000;
+
+ assign addr_reg_in = addr_alu8 | addr_alu | addr_hl | addr_pc | addr_sp;
+
+ endmodule
\ No newline at end of file
diff --git a/common/CPU/z180/defines.v b/common/CPU/z180/defines.v
new file mode 100644
index 00000000..37c9d92c
--- /dev/null
+++ b/common/CPU/z180/defines.v
@@ -0,0 +1,468 @@
+/*******************************************************************************************/
+/** **/
+/** ORIGINAL COPYRIGHT (C) 2011, SYSTEMYDE INTERNATIONAL CORPORATION, ALL RIGHTS RESERVED **/
+/** COPYRIGHT (C) 2012, SERGEY BELYASHOV **/
+/** **/
+/** define file to make the code more readable Rev 0.0 06/18/2012 **/
+/** **/
+/*******************************************************************************************/
+
+ /*****************************************************************************************/
+ /* */
+ /* page register control - DO NOT MODIFY */
+ /* */
+ /*****************************************************************************************/
+ `define MAIN_PG 4'b0000 //no instruction prefix byte(s)
+ `define INTR_PG 4'b0001 //interrupt acknowledge
+ `define CB_PAGE 4'b0010 //CB instruction prefix
+ `define DMA_PG 4'b0011 //dma acknowledge
+ `define DD_PAGE 4'b0100 //DD instruction prefix
+ `define FD_PAGE 4'b0101 //FD instruction prefix
+ `define DDCB_PG 4'b0110 //DD-CB instruction prefix
+ `define FDCB_PG 4'b0111 //FD-CB instruction prefix
+ `define ED_PAGE 4'b1000 //ED instruction prefix
+ `define DEC_MAIN 4'b0x0x //main page or DD page or FD page
+ `define DEC_ED 4'b1xxx //ED page
+
+ /*****************************************************************************************/
+ /* */
+ /* program counter register control: pc_sel */
+ /* */
+ /*****************************************************************************************/
+ `define PCCTL_IDX 2
+ `define PC_NUL 3'b000 //No operation on PC
+ `define PC_LD 3'b001 //PC loaded unconditionally
+ `define PC_NILD 3'b011 //PC loaded if no interrupt, sample interrupt
+ `define PC_INT 3'b100 //Sample interrupt/dma only
+ `define PC_DMA 3'b110 //Sample dma only
+ `define PC_NILD2 3'b111 //PC loaded if no latched interrupt
+
+ /*****************************************************************************************/
+ /* */
+ /* address bus select: add_sel */
+ /* */
+ /*****************************************************************************************/
+ `define ADCTL_IDX 4
+ `define ADD_RSTVAL 5'b00000 //Pipeline register reset value
+ `define ADD_PC 5'b00001 //Select address register from PC
+ `define ADD_HL 5'b00010 //Select address register from HL
+ `define ADD_SP 5'b00100 //Select address register from SP
+ `define ADD_ALU 5'b01000 //Select address register from ALU
+ `define ADD_ALU8 5'b10000 //Select address register from {8'h0, ALU[7:0]}
+
+ `define AD_PC 0 //Address from PC
+ `define AD_HL 1 //Address from HL
+ `define AD_SP 2 //Address from SP
+ `define AD_ALU 3 //Address from ALU
+ `define AD_ALU8 4 //Address from {8'h0, ALU[7:0]}
+
+ /*****************************************************************************************/
+ /* */
+ /* transaction type select: tran_sel */
+ /* */
+ /*****************************************************************************************/
+ `define TTYPE_IDX 5
+ `define TRAN_RSTVAL 6'b000000 //Transaction type reset value
+ `define TRAN_IAK 6'b000001 //Intack transaction
+ `define TRAN_IDL 6'b000010 //Idle transaction
+ `define TRAN_IF 6'b000100 //Instruction fetch transaction
+ `define TRAN_IO 6'b001000 //I/O transaction
+ `define TRAN_MEM 6'b010000 //Memory (data) transaction
+ `define TRAN_STK 6'b100000 //Memory (stack) transaction
+
+ `define TT_IAK 0 //Interrupt acknowledge transaction
+ `define TT_IDL 1 //Idle transaction
+ `define TT_IF 2 //Instruction fetch transaction
+ `define TT_IO 3 //I/O transaction
+ `define TT_MEM 4 //Memory (data) transaction
+ `define TT_STK 5 //Memory (stack) transaction
+
+ /*****************************************************************************************/
+ /* */
+ /* data output control: do_ctl - DO NOT MODIFY */
+ /* */
+ /*****************************************************************************************/
+ `define DO_IDX 2
+ `define DO_NUL 3'b000 //No load
+ `define DO_IO 3'b010 //Load i/o data from lsb
+ `define DO_LSB 3'b100 //Load mem data from lsb
+ `define DO_MSB 3'b101 //Load mem data from msb
+
+ /*****************************************************************************************/
+ /* */
+ /* data input control: di_ctl - DO NOT MODIFY */
+ /* */
+ /*****************************************************************************************/
+ `define DI_IDX 1
+ `define DI_NUL 2'b00 //No load
+ `define DI_DI0 2'b01 //Load din0
+ `define DI_DI1 2'b10 //Load din1
+ `define DI_DI10 2'b11 //Load both din0 and din1
+
+ /*****************************************************************************************/
+ /* */
+ /* interrupt enable control: ief_ctl - DO NOT MODIFY */
+ /* */
+ /*****************************************************************************************/
+ `define IEF_IDX 2
+ `define IEF_NUL 3'b000 //No load
+ `define IEF_0 3'b010 //Load zero
+ `define IEF_1 3'b011 //Load one
+ `define IEF_NMI 3'b100 //ief2 <= ief1, ief1 <= 0
+ `define IEF_RTN 3'b101 //ief1 <= ief2
+
+ /*****************************************************************************************/
+ /* */
+ /* int mode control: imd_ctl - DO NOT MODIFY */
+ /* */
+ /*****************************************************************************************/
+ `define IMD_IDX 1
+ `define IMD_NUL 2'b00 //No load
+ `define IMD_0 2'b01 //Set interrupt mode 0
+ `define IMD_1 2'b10 //Set interrupt mode 1
+ `define IMD_2 2'b11 //Set interrupt mode 2
+
+ /*****************************************************************************************/
+ /* */
+ /* half-carry flag control: hflg_ctl - DO NOT MODIFY */
+ /* */
+ /*****************************************************************************************/
+ `define HFLG_IDX 1
+ `define HFLG_NUL 2'b00 //No load
+ `define HFLG_H 2'b01 //Load half-carry result
+ `define HFLG_0 2'b10 //Load zero
+ `define HFLG_1 2'b11 //Load one
+
+ /*****************************************************************************************/
+ /* */
+ /* parity/overflow flag control: pflg_ctl */
+ /* */
+ /*****************************************************************************************/
+ `define PFLG_IDX 2
+ `define PFLG_NUL 3'b000 //No load
+ `define PFLG_V 3'b001 //Load overflow result
+ `define PFLG_0 3'b010 //Load zero
+ `define PFLG_1 3'b011 //Load one
+ `define PFLG_P 3'b100 //Load parity result
+ `define PFLG_B 3'b101 //Load block count zero result
+ `define PFLG_F 3'b111 //Load ief
+
+ /*****************************************************************************************/
+ /* */
+ /* negate flag control: nflg_ctl - DO NOT MODIFY */
+ /* */
+ /*****************************************************************************************/
+ `define NFLG_IDX 1
+ `define NFLG_NUL 2'b00 //No load
+ `define NFLG_S 2'b01 //Load sign result
+ `define NFLG_0 2'b10 //Load zero
+ `define NFLG_1 2'b11 //Load one
+
+ /*****************************************************************************************/
+ /* */
+ /* temporary flag control: tflg_ctl */
+ /* */
+ /*****************************************************************************************/
+ `define TFLG_IDX 1
+ `define TFLG_NUL 2'b00 //No load
+ `define TFLG_Z 2'b01 //Load zero result
+ `define TFLG_1 2'b10 //Load one result (blk out)
+ `define TFLG_B 2'b11 //Load blk cp result
+
+ /*****************************************************************************************/
+ /* */
+ /* write register control: wr_sel - unencoded */
+ /* */
+ /*****************************************************************************************/
+ `define WREG_IDX 16
+ `define WREG_BB 17'b11000000000000000 //Select B to write
+ `define WREG_BC 17'b11100000000000000 //Select BC to write
+ `define WREG_CC 17'b10100000000000000 //Select C to write
+ `define WREG_DD 17'b10010000000000000 //Select D to write
+ `define WREG_DE 17'b10011000000000000 //Select DE to write
+ `define WREG_EE 17'b10001000000000000 //Select E to write
+ `define WREG_HH 17'b10000100000000000 //Select H to write
+ `define WREG_HL 17'b10000110000000000 //Select HL to write
+ `define WREG_LL 17'b10000010000000000 //Select L to write
+ `define WREG_DEHL 17'b10011110000000000 //Select DEHL to write (ex case)
+ `define WREG_AA 17'b10000001000000000 //Select A to write
+ `define WREG_AF 17'b10000001100000000 //Select A and F to write
+ `define WREG_FF 17'b10000000100000000 //Select F to write
+ `define WREG_SP 17'b10000000010000000 //Select SP to write
+ `define WREG_TMP 17'b10000000001000000 //Select TMP register to write
+ `define WREG_IXH 17'b10000000000100000 //Select IXH to write
+ `define WREG_IX 17'b10000000000110000 //Select IX to write
+ `define WREG_IXL 17'b10000000000010000 //Select IXL to write
+ `define WREG_IYH 17'b10000000000001000 //Select IYH to write
+ `define WREG_IY 17'b10000000000001100 //Select IY to write
+ `define WREG_IYL 17'b10000000000000100 //Select IYL to write
+ `define WREG_II 17'b10000000000000010 //Select I register to write
+ `define WREG_RR 17'b10000000000000001 //Select R register to write
+ `define WREG_NUL 17'b00000000000000000 //No register write
+
+ `define WR_REG 16 //register write
+ `define WR_BB 15 //BB register index
+ `define WR_CC 14 //CC register index
+ `define WR_DD 13 //DD register index
+ `define WR_EE 12 //EE register index
+ `define WR_HH 11 //HH register index
+ `define WR_LL 10 //LL register index
+ `define WR_AA 9 //AA register index
+ `define WR_FF 8 //FF register index
+ `define WR_SP 7 //SP register index
+ `define WR_TMP 6 //TMP register index
+ `define WR_IXH 5 //IXH register index
+ `define WR_IXL 4 //IXL register index
+ `define WR_IYH 3 //IYH register index
+ `define WR_IYL 2 //IYL register index
+ `define WR_II 1 //II register index
+ `define WR_RR 0 //RR register index
+
+ /*****************************************************************************************/
+ /* */
+ /* ALU input A control: alua_sel */
+ /* */
+ /*****************************************************************************************/
+ `define ALUA_IDX 14
+ `define ALUA_RSTVAL 15'h0000 //Reset value for pipeline controls
+ `define ALUA_ZER 15'h0000 //Select 16'h0000 (default)
+ `define ALUA_ONE 15'h0001 //Select 16'h0001
+ `define ALUA_M1 15'h0002 //Select 16'hFFFF
+ `define ALUA_M2 15'h0004 //Select 16'hFFFE
+ `define ALUA_HL 15'h0008 //Select HL register
+ `define ALUA_IX 15'h0010 //Select IX register
+ `define ALUA_IY 15'h0020 //Select IY register
+ `define ALUA_PC 15'h0040 //Select PC register
+ `define ALUA_AA 15'h0080 //Select A register
+ `define ALUA_BIT 15'h0100 //Select bit select constant
+ `define ALUA_DAA 15'h0200 //Select decimal adjust constant
+ `define ALUA_II 15'h0400 //Select I register
+ `define ALUA_RR 15'h0800 //Select R register
+ `define ALUA_INT 15'h1000 //Select interrupt address
+ `define ALUA_TMP 15'h2000 //Select TMP register
+ `define ALUA_RST 15'h4000 //Select restart address
+
+ `define AA_ONE 0 //alua one
+ `define AA_M1 1 //alua -1
+ `define AA_M2 2 //alua -2
+ `define AA_HL 3 //alua hl
+ `define AA_IX 4 //alua ix
+ `define AA_IY 5 //alua iy
+ `define AA_PC 6 //alua pc
+ `define AA_AA 7 //alua aa
+ `define AA_BIT 8 //alua bit
+ `define AA_DAA 9 //alua daa
+ `define AA_II 10 //alua ii
+ `define AA_RR 11 //alua rr
+ `define AA_INT 12 //alua interrupt
+ `define AA_TMP 13 //alua tmp
+ `define AA_RST 14 //alua restart
+
+ /*****************************************************************************************/
+ /* */
+ /* ALU input B control: alub_sel */
+ /* */
+ /*****************************************************************************************/
+ `define ALUB_IDX 12
+ `define ALUB_RSTVAL 13'h1000 //Reset value for pipeline controls
+ `define ALUB_AF 13'h1002 //Select A and F registers
+ `define ALUB_AA 13'h1003 //Select A register
+ `define ALUB_BC 13'h0004 //Select BC register
+ `define ALUB_BB 13'h0005 //Select B register
+ `define ALUB_CC 13'h0004 //Select C register
+ `define ALUB_DE 13'h0008 //Select DE register
+ `define ALUB_DD 13'h0009 //Select D register
+ `define ALUB_EE 13'h0008 //Select E register
+ `define ALUB_HL 13'h0010 //Select HL register
+ `define ALUB_HH 13'h0011 //Select H register
+ `define ALUB_LL 13'h0010 //Select L register
+ `define ALUB_IX 13'h0020 //Select IX register
+ `define ALUB_IXH 13'h0021 //Select IX register high byte
+ `define ALUB_IXL 13'h0020 //Select IX register low byte
+ `define ALUB_IY 13'h0040 //Select IY register
+ `define ALUB_IYH 13'h0041 //Select IY register high byte
+ `define ALUB_IYL 13'h0040 //Select IY register low byte
+ `define ALUB_SP 13'h0080 //Select SP register
+ `define ALUB_SPH 13'h0081 //Select SP register high byte
+ `define ALUB_DIN 13'h0100 //Select data input register
+ `define ALUB_DINH 13'h0101 //Select data input register high byte
+ `define ALUB_IO 13'h0200 //Select i/o address
+ `define ALUB_TMP 13'h0400 //Select TMP register
+ `define ALUB_TMPH 13'h0401 //Select TMP register high byte
+ `define ALUB_PC 13'h1800 //Select PC register
+ `define ALUB_PCH 13'h1801 //Select PC register high byte
+
+ `define AB_SHR 0 //alub shift right
+ `define AB_AF 1 //alub af
+ `define AB_BC 2 //alub bc
+ `define AB_DE 3 //alub de
+ `define AB_HL 4 //alub hl
+ `define AB_IX 5 //alub ix
+ `define AB_IY 6 //alub iy
+ `define AB_SP 7 //alub sp
+ `define AB_DIN 8 //alub din
+ `define AB_IO 9 //alub io
+ `define AB_TMP 10 //alub tmp
+ `define AB_PC 11 //alub pc
+ `define AB_ADR 12 //alub address pc
+
+ /*****************************************************************************************/
+ /* */
+ /* ALU operation control: aluop_sel - 2 MSBs fixed for unit sel */
+ /* */
+ /*****************************************************************************************/
+ `define ALUOP_IDX 7
+ `define ALUOP_RSTVAL 8'b00000000 //Reset Value for pipeline controls
+ `define ALUOP_ADD 8'b01000000 //ALU math: add
+ `define ALUOP_BADD 8'b01000001 //ALU math: byte add
+ `define ALUOP_BDEC 8'b01000011 //ALU math: byte add (decrement)
+ `define ALUOP_ADS 8'b01000100 //ALU math: add signed byte
+ `define ALUOP_DAA 8'b01000101 //ALU math: byte add (daa)
+ `define ALUOP_ADC 8'b01001000 //ALU math: add with carry
+ `define ALUOP_BADC 8'b01001001 //ALU math: byte add with carry
+ `define ALUOP_SUB 8'b01010000 //ALU math: subtract
+ `define ALUOP_BSUB 8'b01010001 //ALU math: subtract
+ `define ALUOP_SBC 8'b01100000 //ALU math: subtract with carry
+ `define ALUOP_BSBC 8'b01100001 //ALU math: byte subtract with carry
+
+ `define ALUOP_PASS 8'b00000000 //ALU logic: pass b bus
+ `define ALUOP_BAND 8'b00000011 //ALU logic: byte and
+ `define ALUOP_BOR 8'b00000101 //ALU logic: byte or
+ `define ALUOP_BXOR 8'b00001001 //ALU logic: byte or
+ `define ALUOP_CCF 8'b00010000 //ALU logic: complement carry
+ `define ALUOP_SCF 8'b00010010 //ALU logic: set carry
+ `define ALUOP_RLD1 8'b00011000 //ALU logic: rld first step
+ `define ALUOP_RLD2 8'b00011010 //ALU logic: rld second step
+ `define ALUOP_RRD1 8'b00011100 //ALU logic: rrd first step
+ `define ALUOP_RRD2 8'b00011110 //ALU logic: rrd second step
+ `define ALUOP_APAS 8'b00100000 //ALU logic: pass a bus
+
+ `define ALUOP_RL 8'b10000000 //ALU shft: rotate left
+ `define ALUOP_RLA 8'b10000001 //ALU shft: rotate left acc
+ `define ALUOP_RLC 8'b10000010 //ALU shft: rotate left circular
+ `define ALUOP_RLCA 8'b10000011 //ALU shft: rotate left circular acc
+ `define ALUOP_RR 8'b10000100 //ALU shft: rotate right
+ `define ALUOP_RRA 8'b10000101 //ALU shft: rotate right acc
+ `define ALUOP_RRC 8'b10001000 //ALU shft: rotate right circular
+ `define ALUOP_RRCA 8'b10001001 //ALU shft: rotate right circular acc
+ `define ALUOP_SLA 8'b10010000 //ALU shft: shift left arithmetic
+ `define ALUOP_SLL 8'b10011000 //ALU shft: shift left logical (x = (x << 1) | 1)
+ `define ALUOP_SRL 8'b10100000 //ALU shft: shift right logical
+ `define ALUOP_SRA 8'b10101000 //ALU shft: shift right arithmetic
+
+ `define ALUOP_MLT 8'b11000000 //ALU mult: 8 bit multiplication
+ /*****************************************************************************************/
+ /* */
+ /* ALU operation control: 6 encoded */
+ /* */
+ /*****************************************************************************************/
+ `define AOP_IDX 5
+ `define AOP_ADD 6'b000000 //ALU math: add
+ `define AOP_BADD 6'b000001 //ALU math: byte add
+ `define AOP_BDEC 6'b000011 //ALU math: byte add (decrement)
+ `define AOP_ADS 6'b000100 //ALU math: add signed byte
+ `define AOP_DAA 6'b000101 //ALU math: byte add (daa)
+ `define AOP_ADC 6'b001000 //ALU math: add with carry
+ `define AOP_BADC 6'b001001 //ALU math: byte add with carry
+ `define AOP_SUB 6'b010000 //ALU math: subtract
+ `define AOP_BSUB 6'b010001 //ALU math: subtract
+ `define AOP_SBC 6'b100000 //ALU math: subtract with carry
+ `define AOP_BSBC 6'b100001 //ALU math: byte subtract with carry
+
+ `define AOP_PASS 6'b000000 //ALU logic: pass b bus
+ `define AOP_BAND 6'b000011 //ALU logic: byte and
+ `define AOP_BOR 6'b000101 //ALU logic: byte or
+ `define AOP_BXOR 6'b001001 //ALU logic: byte or
+ `define AOP_CCF 6'b010000 //ALU logic: complement carry
+ `define AOP_SCF 6'b010010 //ALU logic: set carry
+ `define AOP_RLD1 6'b011000 //ALU logic: rld first step
+ `define AOP_RLD2 6'b011010 //ALU logic: rld second step
+ `define AOP_RRD1 6'b011100 //ALU logic: rrd first step
+ `define AOP_RRD2 6'b011110 //ALU logic: rrd second step
+ `define AOP_APAS 6'b100000 //ALU logic: pass a bus
+
+ `define AOP_RL 6'b000000 //ALU shft: rotate left
+ `define AOP_RLA 6'b000001 //ALU shft: rotate left acc
+ `define AOP_RLC 6'b000010 //ALU shft: rotate left circular
+ `define AOP_RLCA 6'b000011 //ALU shft: rotate left circular acc
+ `define AOP_RR 6'b000100 //ALU shft: rotate right
+ `define AOP_RRA 6'b000101 //ALU shft: rotate right acc
+ `define AOP_RRC 6'b001000 //ALU shft: rotate right circular
+ `define AOP_RRCA 6'b001001 //ALU shft: rotate right circular acc
+ `define AOP_SLA 6'b010000 //ALU shft: shift left arithmetic
+ `define AOP_SLL 6'b011000 //ALU shft: shift left logical
+ `define AOP_SRL 6'b100000 //ALU shft: shift right logical
+ `define AOP_SRA 6'b101000 //ALU shft: shift right arithmetic
+
+ `define AOP_MLT 6'b000000 //ALU mult: 8 bit multiplication
+ /*****************************************************************************************/
+ /* */
+ /* machine state - pseudo-one-hot */
+ /* */
+ /*****************************************************************************************/
+ `define STATE_IDX 31
+ `define sRST 32'b00000000000000000000000000000000 //reset
+ `define sDEC1 32'b00000000000000000000000000000011 //decode 1st opcode
+ `define sIF2B 32'b00000000000000000000000000000101 //fetch 2nd opcode (2)
+ `define sDEC2 32'b00000000000000000000000000001001 //decode 2nd opcode
+ `define sOF1B 32'b00000000000000000000000000010001 //fetch 1st operand (2)
+ `define sOF2A 32'b00000000000000000000000000100001 //fetch 2nd operand (1)
+ `define sOF2B 32'b00000000000000000000000001000001 //fetch 2nd operand (2)
+ `define sIF3A 32'b00000000000000000000000010000001 //fetch 3rd opcode (1)
+ `define sIF3B 32'b00000000000000000000000100000001 //fetch 3rd opcode (2)
+ `define sADR1 32'b00000000000000000000001000000001 //address calculate (1)
+ `define sADR2 32'b00000000000000000000010000000001 //address calculate (2)
+ `define sRD1A 32'b00000000000000000000100000000001 //read 1st operand (1)
+ `define sRD1B 32'b00000000000000000001000000000001 //read 1st operand (2)
+ `define sRD2A 32'b00000000000000000010000000000001 //read 2nd operand (1)
+ `define sRD2B 32'b00000000000000000100000000000001 //read 2nd operand (2)
+ `define sWR1A 32'b00000000000000001000000000000001 //write 1st operand (1)
+ `define sWR1B 32'b00000000000000010000000000000001 //write 1st operand (2)
+ `define sWR2A 32'b00000000000000100000000000000001 //write 2nd operand (1)
+ `define sWR2B 32'b00000000000001000000000000000001 //write 2nd operand (2)
+ `define sBLK1 32'b00000000000010000000000000000001 //block instruction (1)
+ `define sBLK2 32'b00000000000100000000000000000001 //block instruction (2)
+ `define sPCA 32'b00000000001000000000000000000001 //PC adjust
+ `define sPCO 32'b00000000010000000000000000000001 //PC output
+ `define sIF1A 32'b00000000100000000000000000000001 //fetch 1st opcode (1)
+ `define sIF1B 32'b00000001000000000000000000000001 //fetch 1st opcode (2)
+ `define sINTA 32'b00000010000000000000000000000001 //interrupt acknowledge (1)
+ `define sINTB 32'b00000100000000000000000000000001 //interrupt acknowledge (2)
+ `define sHLTA 32'b00001000000000000000000000000001 //halt & sleep (1)
+ `define sHLTB 32'b00010000000000000000000000000001 //halt & sleep (2)
+ `define sDMA1 32'b00100000000000000000000000000001 //dma transfer (1)
+ `define sDMA2 32'b01000000000000000000000000000001 //dma transfer (2)
+ `define sRSTE 32'b10000000000000000000000000000001 //reset exit
+
+ `define RST 32'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0 //reset
+ `define DEC1 32'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx11 //decode 1st opcode
+ `define IF2B 32'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1x1 //fetch 2nd opcode (2)
+ `define DEC2 32'bxxxxxxxxxxxxxxxxxxxxxxxxxxxx1xx1 //decode 2nd opcode
+ `define OF1B 32'bxxxxxxxxxxxxxxxxxxxxxxxxxxx1xxx1 //fetch 1st operand (2)
+ `define OF2A 32'bxxxxxxxxxxxxxxxxxxxxxxxxxx1xxxx1 //fetch 2nd operand (1)
+ `define OF2B 32'bxxxxxxxxxxxxxxxxxxxxxxxxx1xxxxx1 //fetch 2nd operand (2)
+ `define IF3A 32'bxxxxxxxxxxxxxxxxxxxxxxxx1xxxxxx1 //fetch 3rd opcode (1)
+ `define IF3B 32'bxxxxxxxxxxxxxxxxxxxxxxx1xxxxxxx1 //fetch 3rd opcode (2)
+ `define ADR1 32'bxxxxxxxxxxxxxxxxxxxxxx1xxxxxxxx1 //address calculate (1)
+ `define ADR2 32'bxxxxxxxxxxxxxxxxxxxxx1xxxxxxxxx1 //address calculate (2)
+ `define RD1A 32'bxxxxxxxxxxxxxxxxxxxx1xxxxxxxxxx1 //read 1st operand (1)
+ `define RD1B 32'bxxxxxxxxxxxxxxxxxxx1xxxxxxxxxxx1 //read 1st operand (2)
+ `define RD2A 32'bxxxxxxxxxxxxxxxxxx1xxxxxxxxxxxx1 //read 2nd operand (1)
+ `define RD2B 32'bxxxxxxxxxxxxxxxxx1xxxxxxxxxxxxx1 //read 2nd operand (2)
+ `define WR1A 32'bxxxxxxxxxxxxxxxx1xxxxxxxxxxxxxx1 //write 1st operand (1)
+ `define WR1B 32'bxxxxxxxxxxxxxxx1xxxxxxxxxxxxxxx1 //write 1st operand (2)
+ `define WR2A 32'bxxxxxxxxxxxxxx1xxxxxxxxxxxxxxxx1 //write 2nd operand (1)
+ `define WR2B 32'bxxxxxxxxxxxxx1xxxxxxxxxxxxxxxxx1 //write 2nd operand (2)
+ `define BLK1 32'bxxxxxxxxxxxx1xxxxxxxxxxxxxxxxxx1 //block instruction (1)
+ `define BLK2 32'bxxxxxxxxxxx1xxxxxxxxxxxxxxxxxxx1 //block instruction (2)
+ `define PCA 32'bxxxxxxxxxx1xxxxxxxxxxxxxxxxxxxx1 //PC adjust
+ `define PCO 32'bxxxxxxxxx1xxxxxxxxxxxxxxxxxxxxx1 //PC output
+ `define IF1A 32'bxxxxxxxx1xxxxxxxxxxxxxxxxxxxxxx1 //fetch 1st opcode (1)
+ `define IF1B 32'bxxxxxxx1xxxxxxxxxxxxxxxxxxxxxxx1 //fetch 1st opcode (2)
+ `define INTA 32'bxxxxxx1xxxxxxxxxxxxxxxxxxxxxxxx1 //interrupt acknowledge (1)
+ `define INTB 32'bxxxxx1xxxxxxxxxxxxxxxxxxxxxxxxx1 //interrupt acknowledge (2)
+ `define HLTA 32'bxxxx1xxxxxxxxxxxxxxxxxxxxxxxxxx1 //halt & sleep (1)
+ `define HLTB 32'bxxx1xxxxxxxxxxxxxxxxxxxxxxxxxxx1 //halt & sleep (2)
+ `define DMA1 32'bxx1xxxxxxxxxxxxxxxxxxxxxxxxxxxx1 //dma transfer (1)
+ `define DMA2 32'bx1xxxxxxxxxxxxxxxxxxxxxxxxxxxxx1 //dma transfer (2)
+ `define RSTE 32'b1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx1 //reset exit
\ No newline at end of file
diff --git a/common/CPU/z180/extint.v b/common/CPU/z180/extint.v
new file mode 100644
index 00000000..8a218d3a
--- /dev/null
+++ b/common/CPU/z180/extint.v
@@ -0,0 +1,153 @@
+/*******************************************************************************************/
+/** **/
+/** COPYRIGHT (C) 2011, SYSTEMYDE INTERNATIONAL CORPORATION, ALL RIGHTS RESERVED **/
+/** **/
+/** external interface module Rev 0.0 07/21/2011 **/
+/** **/
+/*******************************************************************************************/
+module extint (data_in, dma_ack, ftch_tran, halt_tran, iack_tran, io_addr_out, io_data_out,
+ io_read, io_strobe, io_tran, ivec_rd, mem_addr_out, mem_data_out, mem_rd,
+ mem_tran, mem_wr, reti_tran, t1, addr_reg_in, clkc, dmar_reg,
+ dout_io_reg, dout_mem_reg, halt_nxt, if_frst, inta_frst, io_data_in,
+ ivec_data_in, ld_dmaa, ld_wait, mem_data_in, output_inh, rd_frst, rd_nxt,
+ resetb, reti_nxt, tran_sel, wr_frst);
+
+ input clkc; /* main cpu clock */
+ input dmar_reg; /* latched dma request */
+ input halt_nxt; /* halt cycle identifier */
+ input if_frst; /* first part of fetch cycle identifier */
+ input inta_frst; /* first part of intack cycle identifier */
+ input ld_dmaa; /* load dma request */
+ input ld_wait; /* load wait request */
+ input output_inh; /* disable cpu outputs */
+ input rd_frst; /* first part of read cycle identifier */
+ input rd_nxt; /* read cycle identifier */
+ input resetb; /* internal reset */
+ input reti_nxt; /* reti cycle identifier */
+ input wr_frst; /* first part of write cycle identifier */
+ input [7:0] dout_io_reg; /* io data output */
+ input [7:0] dout_mem_reg; /* mem data output */
+ input [7:0] io_data_in; /* i/o input data bus */
+ input [7:0] ivec_data_in; /* interrupt vector bus */
+ input [7:0] mem_data_in; /* memory input bus */
+ input [15:0] addr_reg_in; /* processor logical address bus */
+ input [`TTYPE_IDX:0] tran_sel; /* transaction type select */
+ output dma_ack; /* dma acknowledge */
+ output ftch_tran; /* instruction fetch transaction */
+ output halt_tran; /* halt transaction */
+ output iack_tran; /* interrupt acknowledge transaction */
+ output io_read; /* i/o read enable */
+ output io_strobe; /* i/o data strobe */
+ output io_tran; /* i/o transaction */
+ output ivec_rd; /* interrupt vector enable */
+ output mem_rd; /* memory read enable */
+ output mem_tran; /* memory transaction */
+ output mem_wr; /* memory write enable */
+ output reti_tran; /* return from interrupt transaction */
+ output t1; /* first clock of transaction */
+ output [7:0] data_in; /* data input bus */
+ output [7:0] io_data_out; /* i/o output data bus */
+ output [7:0] mem_data_out; /* memory output data bus */
+ output [15:0] io_addr_out; /* i/o address bus */
+ output [15:0] mem_addr_out; /* memory address bus */
+
+ /*****************************************************************************************/
+ /* */
+ /* signal declarations */
+ /* */
+ /*****************************************************************************************/
+ wire ld_io_addr; /* update io address */
+ wire ld_mem_addr; /* update memory address */
+ wire [7:0] io_data_out; /* i/o output data bus */
+ wire [7:0] mem_data_out; /* memory output data bus */
+
+ reg dma_ack; /* dma acknowledge */
+ reg ftch_tran; /* inst fetch transaction */
+ reg halt_tran; /* halt transaction */
+ reg iack_tran; /* int ack transaction */
+ reg io_read; /* i/o read enable */
+ reg io_tran; /* i/o transaction */
+ reg io_strobe; /* i/o data strobe */
+ reg ivec_rd; /* interrupt vector enable */
+ reg mem_rd; /* memory read enable */
+ reg mem_tran; /* memory transaction */
+ reg mem_wr; /* memory write enable */
+ reg out_inh_reg; /* latched output inhibit */
+ reg reti_tran; /* reti transaction */
+ reg t1; /* first clock of transaction */
+ reg [7:0] data_in; /* data input bus */
+ reg [15:0] io_addr_out; /* i/o address bus */
+ reg [15:0] mem_addr_out; /* memory address bus */
+
+ /*****************************************************************************************/
+ /* */
+ /* misc signals & buses */
+ /* */
+ /*****************************************************************************************/
+ assign io_data_out = (out_inh_reg) ? 8'h00 : dout_io_reg;
+ assign mem_data_out = (out_inh_reg) ? 8'h00 : dout_mem_reg;
+ assign ld_io_addr = tran_sel[`TT_IO] || output_inh;
+ assign ld_mem_addr = tran_sel[`TT_IAK] || tran_sel[`TT_IDL] || tran_sel[`TT_IF] ||
+ tran_sel[`TT_MEM] || tran_sel[`TT_STK];
+
+ always @ (iack_tran or io_tran or io_data_in or ivec_data_in or mem_data_in) begin
+ case ({iack_tran, io_tran})
+ 2'b01: data_in = io_data_in;
+ 2'b10: data_in = ivec_data_in;
+ default: data_in = mem_data_in;
+ endcase
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* timing generation */
+ /* */
+ /*****************************************************************************************/
+ always @ (posedge clkc or negedge resetb) begin
+ if (!resetb) begin
+ dma_ack <= 1'b0;
+ ftch_tran <= 1'b0;
+ halt_tran <= 1'b0;
+ iack_tran <= 1'b0;
+ io_addr_out <= 16'h0000;
+ io_read <= 1'b0;
+ io_tran <= 1'b0;
+ mem_addr_out <= 16'h0000;
+ mem_tran <= 1'b0;
+ out_inh_reg <= 1'b0;
+ reti_tran <= 1'b0;
+ end
+ else if (|tran_sel) begin
+ dma_ack <= ld_dmaa && dmar_reg;
+ ftch_tran <= tran_sel[`TT_IF];
+ halt_tran <= halt_nxt;
+ iack_tran <= tran_sel[`TT_IAK];
+ if (ld_io_addr) io_addr_out <= (output_inh) ? 16'h0000 : addr_reg_in;
+ io_read <= tran_sel[`TT_IO] && rd_nxt;
+ io_tran <= tran_sel[`TT_IO];
+ if (ld_mem_addr) mem_addr_out <= (output_inh) ? 16'h0000 : addr_reg_in;
+ mem_tran <= (tran_sel[`TT_IDL] || tran_sel[`TT_IF] || tran_sel[`TT_MEM] ||
+ tran_sel[`TT_STK]) && !output_inh;
+ out_inh_reg <= output_inh;
+ reti_tran <= reti_nxt;
+ end
+ end
+
+ always @ (posedge clkc or negedge resetb) begin
+ if (!resetb) begin
+ io_strobe <= 1'b0;
+ ivec_rd <= 1'b0;
+ mem_rd <= 1'b0;
+ mem_wr <= 1'b0;
+ t1 <= 1'b0;
+ end
+ else begin
+ io_strobe <= io_tran && (rd_frst || wr_frst);
+ ivec_rd <= iack_tran && inta_frst;
+ mem_rd <= (if_frst || (mem_tran && rd_frst)) && ld_wait;
+ mem_wr <= mem_tran && wr_frst;
+ t1 <= |tran_sel && !(halt_nxt || dmar_reg);
+ end
+ end
+
+ endmodule
\ No newline at end of file
diff --git a/common/CPU/z180/hierarchy.v b/common/CPU/z180/hierarchy.v
new file mode 100644
index 00000000..ab17b855
--- /dev/null
+++ b/common/CPU/z180/hierarchy.v
@@ -0,0 +1,19 @@
+/*******************************************************************************************/
+/** **/
+/** COPYRIGHT (C) 2011, SYSTEMYDE INTERNATIONAL CORPORATION, ALL RIGHTS RESERVED **/
+/** **/
+/** chip design file include list Rev 0.0 07/17/2011 **/
+/** **/
+/*******************************************************************************************/
+ `include "defines.v" /* control signal mnemonics */
+ `include "control.v" /* processor control */
+ `include "datapath.v" /* processor data path */
+ `include "alu_log.v" /* alu logic unit */
+ `include "alu_math.v" /* alu math unit */
+ `include "alu_shft.v" /* alu shifter unit */
+ `include "aluamux.v" /* alu a input multiplexer */
+ `include "alubmux.v" /* alu b input multiplexer */
+ `include "aluout.v" /* alu output multiplexer */
+ `include "extint.v" /* processor external interface */
+ `include "machine.v" /* processor state machine */
+ `include "y80_top.v" /* cpu top level */
\ No newline at end of file
diff --git a/common/CPU/z180/machine.v b/common/CPU/z180/machine.v
new file mode 100644
index 00000000..ab628ae0
--- /dev/null
+++ b/common/CPU/z180/machine.v
@@ -0,0 +1,51 @@
+/*******************************************************************************************/
+/** **/
+/** COPYRIGHT (C) 2011, SYSTEMYDE INTERNATIONAL CORPORATION, ALL RIGHTS RESERVED **/
+/** **/
+/** state machine module Rev 0.0 07/01/2011 **/
+/** **/
+/*******************************************************************************************/
+module machine (ld_ctrl, state_reg, wait_st, clkc, dmar_reg, intr_reg, ld_inta, ld_wait,
+ resetb, state_nxt, wait_req);
+
+ input clkc; /* main cpu clock */
+ input dmar_reg; /* latched dma request */
+ input intr_reg; /* latched interrupt request */
+ input ld_inta; /* load interrupt request */
+ input ld_wait; /* load wait request */
+ input resetb; /* internal reset */
+ input wait_req; /* wait request */
+ input [`STATE_IDX:0] state_nxt; /* next processor state */
+ output ld_ctrl; /* load control register */
+ output wait_st; /* wait state identifier */
+ output [`STATE_IDX:0] state_reg; /* current processor state */
+
+ /*****************************************************************************************/
+ /* */
+ /* signal declarations */
+ /* */
+ /*****************************************************************************************/
+ wire ld_ctrl; /* advance state */
+
+ reg wait_st; /* wait state - inhibit op */
+ reg [`STATE_IDX:0] state_reg; /* current processor state */
+
+ /*****************************************************************************************/
+ /* */
+ /* processor state machine */
+ /* */
+ /*****************************************************************************************/
+ assign ld_ctrl = !ld_wait || !wait_req;
+
+ always @ (posedge clkc or negedge resetb) begin
+ if (!resetb) wait_st <= 1'b0;
+ else wait_st <= !ld_ctrl;
+ end
+
+ always @ (posedge clkc or negedge resetb) begin
+ if (!resetb) state_reg <= `sRST;
+ else if (ld_ctrl) state_reg <= (ld_inta && dmar_reg) ? `sDMA1 :
+ (ld_inta && intr_reg) ? `sINTA : state_nxt;
+ end
+
+ endmodule
\ No newline at end of file
diff --git a/common/CPU/z180/top_levl.v b/common/CPU/z180/top_levl.v
new file mode 100644
index 00000000..39812146
--- /dev/null
+++ b/common/CPU/z180/top_levl.v
@@ -0,0 +1,573 @@
+/*******************************************************************************************/
+/** **/
+/** ORIGINAL COPYRIGHT (C) 2011, SYSTEMYDE INTERNATIONAL CORPORATION, ALL RIGHTS RESERVED **/
+/** COPYRIGHT (C) 2012, SERGEY BELYASHOV **/
+/** **/
+/** Y80e processor test bench Rev 0.0 06/18/2012 **/
+/** **/
+/*******************************************************************************************/
+`timescale 1ns / 10ps /* set time scale */
+`include "version.v" /* select version */
+`include "hierarchy.v" /* include sources */
+
+module top_levl;
+
+ wire DMA_ACK; /* dma acknowledge */
+ wire HALT_TRAN; /* halt transaction */
+ wire IACK_TRAN; /* int ack transaction */
+ wire IO_READ; /* i/o read/write status */
+ wire IO_STROBE; /* i/o strobe */
+ wire IO_TRAN; /* i/o transaction */
+ wire IVEC_RD; /* int vector read strobe */
+ wire MEM_RD; /* mem read strobe */
+ wire MEM_TRAN; /* mem transaction */
+ wire MEM_WR; /* mem write strobe */
+ wire RETI_TRAN; /* reti transaction */
+ wire T1; /* first clock of transaction */
+ wire [7:0] IO_DATA_OUT; /* i/o data output bus */
+ wire [7:0] MEM_DATA_OUT; /* mem data output bus */
+ wire [15:0] IO_ADDR; /* i/o address bus */
+ wire [15:0] MEM_ADDR; /* mem address bus */
+
+ reg CLEARB; /* master (test) reset */
+ reg CLKC; /* clock */
+ reg DMA_REQ; /* dma request */
+ reg INT_REQ; /* interrupt request */
+ reg NMI_REQ; /* non-maskable interrupt req */
+ reg RESETB; /* internal (user) reset */
+ reg WAIT_REQ; /* wait request */
+ reg [7:0] IO_DATA_IN; /* i/o data input bus */
+ reg [7:0] IVEC_DATA_IN; /* vector input bus */
+ reg [7:0] MEM_DATA_IN; /* mem data input bus */
+
+ /*****************************************************************************************/
+ /* */
+ /* testbench internal variables */
+ /* */
+ /*****************************************************************************************/
+ reg CLR_INT; /* deassert interrupt */
+ reg CLR_NMI; /* deassert nmi */
+ reg DISABLE_BREQ; /* bus req generator control */
+ reg DISABLE_INT; /* interrupt generator control */
+ reg DISABLE_WAIT; /* wait generator control */
+ reg INT_TYPE; /* int type during bus req */
+ reg PAT_DONE; /* pattern done flag */
+ reg TRIG_INT; /* assert interrupt */
+ reg TRIG_NMI; /* assert nmi */
+ reg [3:0] PAT_CNT; /* counter to track patterns */
+ reg [15:0] CMP_ERR_L; /* error counter */
+
+ reg wait_dly; /* wait request state machine */
+ reg [5:0] breq_mach; /* bus request state machine */
+
+ reg TREF0, TREF1, TREF2, TREF3, TREF4; /* timing generator */
+ reg TREF5, TREF6, TREF7, TREF8, TREF9;
+
+ /*****************************************************************************************/
+ /* */
+ /* read memory and write data compare memory */
+ /* */
+ /*****************************************************************************************/
+ reg [7:0] rdmem [0:65535];
+ reg [7:0] wrmem [0:65535];
+
+ wire [7:0] wr_data = (MEM_TRAN) ? wrmem[MEM_ADDR] :
+ (IO_TRAN) ? wrmem[IO_ADDR] : 8'hxx;
+
+ wire [7:0] rd_data = rdmem[MEM_ADDR];
+ wire [7:0] iord_data = rdmem[IO_ADDR];
+
+ always @ (posedge TREF6) begin
+ IO_DATA_IN = (IO_TRAN && IO_READ && IO_STROBE && !WAIT_REQ) ? iord_data : 8'hxx;
+ MEM_DATA_IN = (MEM_TRAN && MEM_RD && !WAIT_REQ) ? rd_data : 8'hxx;
+ end
+
+ always @ (posedge TREF6) begin
+ IVEC_DATA_IN = (IACK_TRAN && IVEC_RD && !WAIT_REQ) ? rd_data : 8'hxx;
+ end
+
+ always @ (posedge TREF0) begin
+ IO_DATA_IN = 8'hxx;
+ MEM_DATA_IN = 8'hxx;
+ IVEC_DATA_IN = 8'hxx;
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* instantiate the design */
+ /* */
+ /*****************************************************************************************/
+ y80_top Y80 ( .dma_ack(DMA_ACK), .halt_tran(HALT_TRAN), .iack_tran(IACK_TRAN),
+ .io_addr_out(IO_ADDR), .io_data_out(IO_DATA_OUT), .io_read(IO_READ),
+ .io_strobe(IO_STROBE), .io_tran(IO_TRAN), .ivec_rd(IVEC_RD),
+ .mem_addr_out(MEM_ADDR), .mem_data_out(MEM_DATA_OUT), .mem_rd(MEM_RD),
+ .mem_tran(MEM_TRAN), .mem_wr(MEM_WR), .reti_tran(RETI_TRAN), .t1(T1),
+ .clearb(CLEARB), .clkc(CLKC), .dma_req(DMA_REQ), .int_req(INT_REQ),
+ .io_data_in(IO_DATA_IN), .ivec_data_in(IVEC_DATA_IN),
+ .mem_data_in(MEM_DATA_IN), .nmi_req(NMI_REQ), .resetb(RESETB),
+ .wait_req(WAIT_REQ) );
+
+ /*****************************************************************************************/
+ /* */
+ /* timing generator */
+ /* */
+ /*****************************************************************************************/
+ initial begin
+ TREF0 = 1;
+ CLKC = 1;
+ end
+
+ always begin
+ #10 TREF0 <= 1'b0;
+ TREF1 <= 1'b1;
+ #10 TREF1 <= 1'b0;
+ TREF2 <= 1'b1;
+ #10 TREF2 <= 1'b0;
+ TREF3 <= 1'b1;
+ #10 TREF3 <= 1'b0;
+ TREF4 <= 1'b1;
+ #10 TREF4 <= 1'b0;
+ TREF5 <= 1'b1;
+ #10 TREF5 <= 1'b0;
+ TREF6 <= 1'b1;
+ #10 TREF6 <= 1'b0;
+ TREF7 <= 1'b1;
+ #10 TREF7 <= 1'b0;
+ TREF8 <= 1'b1;
+ #10 TREF8 <= 1'b0;
+ TREF9 <= 1'b1;
+ #10 TREF9 <= 1'b0;
+ TREF0 <= 1'b1;
+ end
+
+ always @ (posedge TREF3) CLKC = 0;
+ always @ (posedge TREF8) CLKC = 1;
+
+ /*****************************************************************************************/
+ /* */
+ /* initialize input signals */
+ /* */
+ /*****************************************************************************************/
+ initial begin
+ CLEARB = 1;
+ DMA_REQ = 0;
+ INT_REQ = 0;
+ NMI_REQ = 0;
+ RESETB = 1;
+ WAIT_REQ = 0;
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* initialize testbench variables */
+ /* */
+ /*****************************************************************************************/
+ initial begin
+ breq_mach = 6'b000000;
+ CMP_ERR_L = 16'h0000;
+ CLR_INT = 0;
+ CLR_NMI = 0;
+ DISABLE_BREQ = 1;
+ DISABLE_INT = 1;
+ DISABLE_WAIT = 1;
+ INT_TYPE = 0;
+ PAT_DONE = 0;
+ TRIG_INT = 0;
+ TRIG_NMI = 0;
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* reset and clear task */
+ /* */
+ /*****************************************************************************************/
+ task resettask;
+ begin
+ wait(TREF6);
+ RESETB = 0;
+ wait(TREF0);
+ wait(TREF6);
+ wait(TREF0);
+ wait(TREF6);
+ RESETB = 1;
+ CLR_INT = 1;
+ CLR_NMI = 1;
+ wait(TREF0);
+ PAT_DONE = 0;
+ end
+ endtask
+
+ task cleartask;
+ begin
+ wait(TREF6);
+ CLEARB = 0;
+ RESETB = 0;
+ wait(TREF0);
+ wait(TREF6);
+ wait(TREF0);
+ wait(TREF6);
+ CLEARB = 1;
+ RESETB = 1;
+ CLR_INT = 1;
+ CLR_NMI = 1;
+ wait(TREF0);
+ PAT_DONE = 0;
+ end
+ endtask
+
+ /*****************************************************************************************/
+ /* */
+ /* error log */
+ /* */
+ /*****************************************************************************************/
+ always @ (posedge TREF4) begin
+ if (MEM_WR) CMP_ERR_L = CMP_ERR_L + (MEM_DATA_OUT != wr_data);
+ if (!IO_READ && IO_STROBE) CMP_ERR_L = CMP_ERR_L + (IO_DATA_OUT != wr_data);
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* end-of-pattern detect */
+ /* */
+ /*****************************************************************************************/
+ always @ (posedge TREF4) begin
+ PAT_DONE = (MEM_ADDR[15:0] == 16'h00c3);
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* interrupt/nmi request generator */
+ /* */
+ /*****************************************************************************************/
+ always @ (posedge TREF4) begin
+ TRIG_INT = !((MEM_ADDR[15:13] == 3'b110) && (MEM_ADDR[8:0] == 9'h0ff)) ||
+ DISABLE_INT || |breq_mach;
+ TRIG_NMI = !((MEM_ADDR[15:13] == 3'b110) && (MEM_ADDR[8:0] == 9'h1ff)) ||
+ DISABLE_INT || |breq_mach;
+ CLR_INT = (MEM_ADDR[15:13] == 3'b111);
+ CLR_NMI = (MEM_ADDR[15:13] == 3'b111);
+ if (T1) INT_TYPE = MEM_ADDR[8];
+ end
+
+ always @ (negedge TRIG_NMI) begin
+ NMI_REQ = 1;
+ end
+
+ always @ (posedge CLR_NMI) begin
+ NMI_REQ = 0;
+ end
+
+ always @ (negedge TRIG_INT) begin
+ INT_REQ = 1;
+ end
+
+ always @ (posedge CLR_INT) begin
+ wait(TREF0);
+ wait(TREF4);
+ wait(TREF0);
+ wait(TREF4);
+ INT_REQ = 0;
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* interrupt request generator (during Halt) */
+ /* */
+ /*****************************************************************************************/
+ integer j;
+
+ always @ (posedge HALT_TRAN) begin
+ for (j=0; j < 10; j=j+1) begin
+ wait (TREF6);
+ wait (TREF0);
+ end
+ wait (TREF6);
+ INT_REQ = HALT_TRAN && !INT_TYPE;
+ NMI_REQ = HALT_TRAN && INT_TYPE;
+ wait (TREF0);
+ for (j=0; j < 12; j=j+1) begin
+ wait (TREF6);
+ wait (TREF0);
+ end
+ INT_REQ = 0;
+ NMI_REQ = 0;
+ wait (TREF6);
+ wait (TREF0);
+ wait (TREF6);
+ NMI_REQ = HALT_TRAN && INT_TYPE;
+ wait (TREF0);
+ wait (TREF6);
+ wait (TREF0);
+ NMI_REQ = 0;
+ end
+
+ /*****************************************************************************************/
+ /* */
+ /* wait request generator */
+ /* */
+ /*****************************************************************************************/
+ always @ (posedge CLKC) begin
+ wait_dly <= T1;
+ end
+
+ always @ (posedge TREF6) WAIT_REQ = !DISABLE_WAIT && (T1 || wait_dly);
+ always @ (posedge TREF9) WAIT_REQ = 1'b0;
+
+ /*****************************************************************************************/
+ /* */
+ /* bus request generator */
+ /* */
+ /*****************************************************************************************/
+ always @ (posedge CLKC) begin
+ breq_mach <= (DISABLE_BREQ) ? 6'b000000 :
+ (T1) ? 6'b000001 : {breq_mach[4:0], wait_dly};
+ end
+
+ always @ (posedge TREF6) DMA_REQ = !DISABLE_BREQ &&
+ (T1 || |breq_mach[2:0] || (HALT_TRAN && |breq_mach));
+
+ /*****************************************************************************************/
+ /* */
+ /* run the test patterns */
+ /* */
+ /*****************************************************************************************/
+ initial begin
+ $readmemh("setup_hl.vm", rdmem);
+ cleartask;
+ wait (PAT_DONE);
+
+ DISABLE_INT = 0; /* interrupt generator on */
+
+ resettask;
+ CMP_ERR_L = 16'h0000;
+ PAT_CNT = 5'h1;
+ $readmemh("blank_xx.vm", rdmem);
+ $readmemh("blank_xx.vm", wrmem);
+ $readmemh("int_ops.vm", rdmem);
+ $readmemh("int_opsd.vm", wrmem);
+ wait (PAT_DONE);
+
+ DISABLE_INT = 1; /* interrupt generator off */
+
+ resettask;
+ CMP_ERR_L = 16'h0000;
+ PAT_CNT = 5'h2;
+ $readmemh("blank_xx.vm", rdmem);
+ $readmemh("blank_xx.vm", wrmem);
+ $readmemh("alu_ops.vm", rdmem);
+ $readmemh("alu_opsd.vm", wrmem);
+ wait (PAT_DONE);
+
+ resettask;
+ CMP_ERR_L = 16'h0000;
+ PAT_CNT = 5'h3;
+ $readmemh("blank_xx.vm", rdmem);
+ $readmemh("blank_xx.vm", wrmem);
+ $readmemh("dat_mov.vm", rdmem);
+ $readmemh("dat_movd.vm", wrmem);
+ wait (PAT_DONE);
+
+ resettask;
+ CMP_ERR_L = 16'h0000;
+ PAT_CNT = 5'h4;
+ $readmemh("blank_xx.vm", rdmem);
+ $readmemh("blank_xx.vm", wrmem);
+ $readmemh("bit_ops.vm", rdmem);
+ $readmemh("bit_opsd.vm", wrmem);
+ wait (PAT_DONE);
+
+ resettask;
+ CMP_ERR_L = 16'h0000;
+ PAT_CNT = 5'h5;
+ $readmemh("blank_xx.vm", rdmem);
+ $readmemh("blank_xx.vm", wrmem);
+ $readmemh("jmp_ops.vm", rdmem);
+ $readmemh("jmp_opsd.vm", wrmem);
+ wait (PAT_DONE);
+
+ resettask;
+ CMP_ERR_L = 16'h0000;
+ PAT_CNT = 5'h6;
+ $readmemh("blank_xx.vm", rdmem);
+ $readmemh("blank_xx.vm", wrmem);
+ $readmemh("io_ops.vm", rdmem);
+ $readmemh("io_opsd.vm", wrmem);
+ wait (PAT_DONE);
+
+ resettask;
+ CMP_ERR_L = 16'h0000;
+ PAT_CNT = 5'h7;
+ $readmemh("blank_xx.vm", rdmem);
+ $readmemh("blank_xx.vm", wrmem);
+ $readmemh("180_ops.vm", rdmem);
+ $readmemh("180_opsd.vm", wrmem);
+ wait (PAT_DONE);
+
+ resettask;
+ CMP_ERR_L = 16'h0000;
+ PAT_CNT = 5'h8;
+ $readmemh("blank_xx.vm", rdmem);
+ $readmemh("blank_xx.vm", wrmem);
+ $readmemh("ez8_ops.vm", rdmem);
+ $readmemh("ez8_opsd.vm", wrmem);
+ wait (PAT_DONE);
+
+ DISABLE_INT = 0; /* interrupt generator on */
+ DISABLE_WAIT = 0; /* wait generator on */
+
+ resettask;
+ CMP_ERR_L = 16'h0000;
+ PAT_CNT = 5'h1;
+ $readmemh("blank_xx.vm", rdmem);
+ $readmemh("blank_xx.vm", wrmem);
+ $readmemh("int_ops.vm", rdmem);
+ $readmemh("int_opsd.vm", wrmem);
+ wait (PAT_DONE);
+
+ DISABLE_INT = 1; /* interrupt generator off */
+
+ resettask;
+ CMP_ERR_L = 16'h0000;
+ PAT_CNT = 5'h2;
+ $readmemh("blank_xx.vm", rdmem);
+ $readmemh("blank_xx.vm", wrmem);
+ $readmemh("alu_ops.vm", rdmem);
+ $readmemh("alu_opsd.vm", wrmem);
+ wait (PAT_DONE);
+
+ resettask;
+ CMP_ERR_L = 16'h0000;
+ PAT_CNT = 5'h3;
+ $readmemh("blank_xx.vm", rdmem);
+ $readmemh("blank_xx.vm", wrmem);
+ $readmemh("dat_mov.vm", rdmem);
+ $readmemh("dat_movd.vm", wrmem);
+ wait (PAT_DONE);
+
+ resettask;
+ CMP_ERR_L = 16'h0000;
+ PAT_CNT = 5'h4;
+ $readmemh("blank_xx.vm", rdmem);
+ $readmemh("blank_xx.vm", wrmem);
+ $readmemh("bit_ops.vm", rdmem);
+ $readmemh("bit_opsd.vm", wrmem);
+ wait (PAT_DONE);
+
+ resettask;
+ CMP_ERR_L = 16'h0000;
+ PAT_CNT = 5'h5;
+ $readmemh("blank_xx.vm", rdmem);
+ $readmemh("blank_xx.vm", wrmem);
+ $readmemh("jmp_ops.vm", rdmem);
+ $readmemh("jmp_opsd.vm", wrmem);
+ wait (PAT_DONE);
+
+ resettask;
+ CMP_ERR_L = 16'h0000;
+ PAT_CNT = 5'h6;
+ $readmemh("blank_xx.vm", rdmem);
+ $readmemh("blank_xx.vm", wrmem);
+ $readmemh("io_ops.vm", rdmem);
+ $readmemh("io_opsd.vm", wrmem);
+ wait (PAT_DONE);
+
+ resettask;
+ CMP_ERR_L = 16'h0000;
+ PAT_CNT = 5'h7;
+ $readmemh("blank_xx.vm", rdmem);
+ $readmemh("blank_xx.vm", wrmem);
+ $readmemh("180_ops.vm", rdmem);
+ $readmemh("180_opsd.vm", wrmem);
+ wait (PAT_DONE);
+
+ resettask;
+ CMP_ERR_L = 16'h0000;
+ PAT_CNT = 5'h8;
+ $readmemh("blank_xx.vm", rdmem);
+ $readmemh("blank_xx.vm", wrmem);
+ $readmemh("ez8_ops.vm", rdmem);
+ $readmemh("ez8_opsd.vm", wrmem);
+ wait (PAT_DONE);
+
+ DISABLE_INT = 0; /* interrupt generator on */
+ DISABLE_BREQ = 0; /* bus req generator on */
+ DISABLE_WAIT = 1; /* wait generator off */
+
+ resettask;
+ CMP_ERR_L = 16'h0000;
+ PAT_CNT = 5'h1;
+ $readmemh("blank_xx.vm", rdmem);
+ $readmemh("blank_xx.vm", wrmem);
+ $readmemh("int_ops.vm", rdmem);
+ $readmemh("int_opss.vm", wrmem);
+ wait (PAT_DONE);
+
+ DISABLE_INT = 1; /* interrupt generator off */
+
+ resettask;
+ CMP_ERR_L = 16'h0000;
+ PAT_CNT = 5'h2;
+ $readmemh("blank_xx.vm", rdmem);
+ $readmemh("blank_xx.vm", wrmem);
+ $readmemh("alu_ops.vm", rdmem);
+ $readmemh("alu_opsd.vm", wrmem);
+ wait (PAT_DONE);
+
+ resettask;
+ CMP_ERR_L = 16'h0000;
+ PAT_CNT = 5'h3;
+ $readmemh("blank_xx.vm", rdmem);
+ $readmemh("blank_xx.vm", wrmem);
+ $readmemh("dat_mov.vm", rdmem);
+ $readmemh("dat_movd.vm", wrmem);
+ wait (PAT_DONE);
+
+ resettask;
+ CMP_ERR_L = 16'h0000;
+ PAT_CNT = 5'h4;
+ $readmemh("blank_xx.vm", rdmem);
+ $readmemh("blank_xx.vm", wrmem);
+ $readmemh("bit_ops.vm", rdmem);
+ $readmemh("bit_opsd.vm", wrmem);
+ wait (PAT_DONE);
+
+ resettask;
+ CMP_ERR_L = 16'h0000;
+ PAT_CNT = 5'h5;
+ $readmemh("blank_xx.vm", rdmem);
+ $readmemh("blank_xx.vm", wrmem);
+ $readmemh("jmp_ops.vm", rdmem);
+ $readmemh("jmp_opsd.vm", wrmem);
+ wait (PAT_DONE);
+
+ resettask;
+ CMP_ERR_L = 16'h0000;
+ PAT_CNT = 5'h6;
+ $readmemh("blank_xx.vm", rdmem);
+ $readmemh("blank_xx.vm", wrmem);
+ $readmemh("io_ops.vm", rdmem);
+ $readmemh("io_opsd.vm", wrmem);
+ wait (PAT_DONE);
+
+ resettask;
+ CMP_ERR_L = 16'h0000;
+ PAT_CNT = 5'h7;
+ $readmemh("blank_xx.vm", rdmem);
+ $readmemh("blank_xx.vm", wrmem);
+ $readmemh("180_ops.vm", rdmem);
+ $readmemh("180_opsd.vm", wrmem);
+ wait (PAT_DONE);
+
+ resettask;
+ CMP_ERR_L = 16'h0000;
+ PAT_CNT = 5'h8;
+ $readmemh("blank_xx.vm", rdmem);
+ $readmemh("blank_xx.vm", wrmem);
+ $readmemh("ez8_ops.vm", rdmem);
+ $readmemh("ez8_opsd.vm", wrmem);
+ wait (PAT_DONE);
+
+ $stop;
+ end
+
+ endmodule
\ No newline at end of file
diff --git a/common/CPU/z180/version.v b/common/CPU/z180/version.v
new file mode 100644
index 00000000..0c73b245
--- /dev/null
+++ b/common/CPU/z180/version.v
@@ -0,0 +1,62 @@
+/*******************************************************************************************/
+/** **/
+/** ORIGINAL COPYRIGHT (C) 2010, SYSTEMYDE INTERNATIONAL CORPORATION, ALL RIGHTS RESERVED **/
+/** COPYRIGHT (C) 2012, SERGEY BELYASHOV **/
+/** **/
+/** version definition file Rev 0.0 06/13/2012 **/
+/** **/
+/*******************************************************************************************/
+
+/*******************************************************************************************/
+/* */
+/* SELECT ONLY ONE OPTION PER GROUP! default is first option */
+/* */
+/*******************************************************************************************/
+
+/*******************************************************************************************/
+/* */
+/* enable/disable refresh register emulation (if enabled then breaks testbench) */
+/* */
+/*******************************************************************************************/
+// `define RREG_EMU /* enable emulation */
+
+/*******************************************************************************************/
+/* */
+/* select CPU or MPU */
+/* */
+/*******************************************************************************************/
+// `define Y90_CPU /* stand-alone cpu only */
+// `define Y90_MPU /* integrated version */
+`define Y90_180 /* clone version */
+
+/*******************************************************************************************/
+/* */
+/* select the operation of the H flag for the CCF instruction */
+/* */
+/*******************************************************************************************/
+`define Z80_CCF /* z80 CCF operation */
+// `define Z180_CCF /* z180 CCF operation */
+
+/*******************************************************************************************/
+/* */
+/* select the implementation of the MLT instruction */
+/* */
+/*******************************************************************************************/
+`define MUL_NORM /* parallel multiplier */
+// `define MUL_FAST /* serial multiplier */
+
+/*******************************************************************************************/
+/* */
+/* select the value reported in the System Status Block for dreq_bus (Y90 MPU Only) */
+/* */
+/*******************************************************************************************/
+`define DREQ_LOG /* log dreq timeouts */
+// `define DREQ_ACC /* count dreq timeouts */
+
+/*******************************************************************************************/
+/* */
+/* select the value reported in the System Status Block for wait_req (Y90 MPU Only) */
+/* */
+/*******************************************************************************************/
+`define WAIT_LOG /* log wait timeouts */
+// `define WAIT_ACC /* count wait timeouts */
\ No newline at end of file
diff --git a/common/CPU/z180/y80_top.v b/common/CPU/z180/y80_top.v
new file mode 100644
index 00000000..7de44e75
--- /dev/null
+++ b/common/CPU/z180/y80_top.v
@@ -0,0 +1,194 @@
+/*******************************************************************************************/
+/** **/
+/** ORIGINAL COPYRIGHT (C) 2011, SYSTEMYDE INTERNATIONAL CORPORATION, ALL RIGHTS RESERVED **/
+/** COPYRIGHT (C) 2012, SERGEY BELYASHOV **/
+/** **/
+/** processor top level Rev 0.0 06/13/2012 **/
+/** **/
+/*******************************************************************************************/
+module y80_top (dma_ack, halt_tran, iack_tran, io_addr_out, io_data_out, io_read, io_strobe,
+ io_tran, ivec_rd, mem_addr_out, mem_data_out, mem_rd, mem_tran, mem_wr,
+ reti_tran, t1, clearb, clkc, dma_req, int_req, io_data_in, ivec_data_in,
+ mem_data_in, nmi_req, resetb, wait_req);
+
+ input clearb; /* master (test) reset */
+ input clkc; /* main cpu clock */
+ input dma_req; /* dma request */
+ input int_req; /* interrupt request */
+ input nmi_req; /* nmi request */
+ input resetb; /* internal (user) reset */
+ input wait_req; /* wait request */
+ input [7:0] io_data_in; /* i/o input data bus */
+ input [7:0] ivec_data_in; /* interrupt vector bus */
+ input [7:0] mem_data_in; /* memory input bus */
+ output dma_ack; /* dma acknowledge */
+ output halt_tran; /* halt transaction */
+ output iack_tran; /* interrupt acknowledge transaction */
+ output io_read; /* i/o read enable */
+ output io_tran; /* i/o transaction */
+ output io_strobe; /* i/o data strobe */
+ output ivec_rd; /* interrupt vector enable */
+ output mem_rd; /* memory read enable */
+ output mem_tran; /* memory transaction */
+ output mem_wr; /* memory write enable */
+ output reti_tran; /* return from interrupt transaction */
+ output t1; /* first clock of transaction */
+ output [7:0] io_data_out; /* i/o output data bus */
+ output [7:0] mem_data_out; /* memory output data bus */
+ output [15:0] io_addr_out; /* i/o address bus */
+ output [15:0] mem_addr_out; /* memory address bus */
+
+ /*****************************************************************************************/
+ /* */
+ /* signal declarations */
+ /* */
+ /*****************************************************************************************/
+ wire burst_done; /* burst/mlt done */
+ wire cflg_en; /* carry flag control */
+ wire carry_bit; /* carry flag */
+ wire dma_ack; /* dma acknowledge */
+ wire dmar_reg; /* latched dma request */
+ wire ex_af_pls; /* exchange af,af' */
+ wire ex_bank_pls; /* exchange register bank */
+ wire ex_dehl_inst; /* exchange de,hl */
+ wire ftch_tran; /* inst fetch transaction */
+ wire halt_nxt, halt_tran; /* halt transaction */
+ wire iack_tran; /* int ack transaction */
+ wire if_frst; /* first clock if ifetch */
+ wire inta_frst; /* first clock of intack */
+ wire intr_reg; /* latched interrupt request */
+ wire io_read; /* i/o read enable */
+ wire io_tran; /* i/o transaction */
+ wire io_strobe; /* i/o data strobe */
+ wire ivec_rd; /* interrupt vector enable */
+ wire ld_ctrl; /* load control register */
+ wire ld_dmaa; /* load dma request */
+ wire ld_inst; /* load instruction register */
+ wire ld_inta; /* sample latched int */
+ wire ld_page; /* load page register */
+ wire ld_wait; /* sample wait input */
+ wire mem_rd; /* memory read enable */
+ wire mem_tran; /* memory transaction */
+ wire mem_wr; /* memory write enable */
+ wire output_inh; /* disable cpu outputs */
+ wire par_bit; /* parity flag */
+ wire rd_brst; /* burst read */
+ wire rd_frst; /* first clock of read */
+ wire rd_nxt; /* read trans next */
+ wire reti_nxt, reti_tran; /* reti transaction */
+ wire rreg_en; /* update refresh register */
+ wire sflg_en; /* sign flag control */
+ wire sign_bit; /* sign flag */
+ wire tflg_reg; /* temporary flag */
+ wire t1; /* first clock of transaction */
+ wire vector_int; /* int vector enable */
+ wire wait_st; /* wait state identifier */
+ wire wr_brst; /* burst write */
+ wire wr_frst; /* first clock of write */
+ wire xhlt_reg; /* halt exit */
+ wire zero_bit; /* zero flag */
+ wire zflg_en; /* zero flag control */
+ wire [3:0] page_sel; /* inst decode page control */
+ wire [3:0] page_reg; /* instruction decode "page" */
+ wire [7:0] inst_reg; /* instruction register */
+ wire [7:0] data_in; /* read data bus */
+ wire [7:0] dout_io_reg, dout_mem_reg; /* write data bus */
+ wire [15:0] addr_reg_in; /* processor logical address */
+ wire [7:0] io_data_out; /* i/o output data bus */
+ wire [7:0] mem_data_out; /* memory output data bus */
+ wire [15:0] io_addr_out; /* i/o address bus */
+ wire [15:0] mem_addr_out; /* memory address bus */
+ wire [`ADCTL_IDX:0] add_sel; /* address output mux control */
+ wire [`ALUA_IDX:0] alua_sel; /* alu input a mux control */
+ wire [`ALUB_IDX:0] alub_sel; /* alu input b mux control */
+ wire [`ALUOP_IDX:0] aluop_sel; /* alu operation control */
+ wire [`DI_IDX:0] di_ctl; /* data input control */
+ wire [`DO_IDX:0] do_ctl; /* data output control */
+ wire [`HFLG_IDX:0] hflg_ctl; /* half-carry flag control */
+ wire [`IEF_IDX:0] ief_ctl; /* interrupt enable control */
+ wire [`IMD_IDX:0] imd_ctl; /* interrupt mode control */
+ wire [`NFLG_IDX:0] nflg_ctl; /* negate flag control */
+ wire [`PCCTL_IDX:0] pc_sel; /* pc source control */
+ wire [`PFLG_IDX:0] pflg_ctl; /* parity/overflow flag control */
+ wire [`STATE_IDX:0] state_nxt, state_reg; /* machine state */
+ wire [`TFLG_IDX:0] tflg_ctl; /* temp flag control */
+ wire [`TTYPE_IDX:0] tran_sel; /* transaction type */
+ wire [`WREG_IDX:0] wr_addr; /* register write address bus */
+
+ /*****************************************************************************************/
+ /* */
+ /* interface module */
+ /* */
+ /*****************************************************************************************/
+ extint EXTINT ( .data_in(data_in), .dma_ack(dma_ack), .ftch_tran(ftch_tran),
+ .halt_tran(halt_tran), .iack_tran(iack_tran),
+ .io_addr_out(io_addr_out), .io_data_out(io_data_out),
+ .io_read(io_read), .io_strobe(io_strobe), .io_tran(io_tran),
+ .ivec_rd(ivec_rd), .mem_addr_out(mem_addr_out),
+ .mem_data_out(mem_data_out), .mem_rd(mem_rd), .mem_tran(mem_tran),
+ .mem_wr(mem_wr), .reti_tran(reti_tran), .t1(t1),
+ .addr_reg_in(addr_reg_in), .clkc(clkc), .dmar_reg(dmar_reg),
+ .dout_io_reg(dout_io_reg), .dout_mem_reg(dout_mem_reg),
+ .halt_nxt(halt_nxt), .if_frst(if_frst), .inta_frst(inta_frst),
+ .io_data_in(io_data_in), .ivec_data_in(ivec_data_in),
+ .ld_dmaa(ld_dmaa), .ld_wait(ld_wait), .mem_data_in(mem_data_in),
+ .output_inh(output_inh), .rd_frst(rd_frst), .rd_nxt(rd_nxt),
+ .resetb(resetb), .reti_nxt(reti_nxt), .tran_sel(tran_sel),
+ .wr_frst(wr_frst) );
+
+ /*****************************************************************************************/
+ /* */
+ /* state machine module */
+ /* */
+ /*****************************************************************************************/
+ machine MACHINE ( .ld_ctrl(ld_ctrl), .state_reg(state_reg), .wait_st(wait_st),
+ .clkc(clkc), .dmar_reg(dmar_reg), .intr_reg(intr_reg),
+ .ld_inta(ld_inta), .ld_wait(ld_wait), .resetb(resetb),
+ .state_nxt(state_nxt), .wait_req(wait_req) );
+
+ /*****************************************************************************************/
+ /* */
+ /* control module */
+ /* */
+ /*****************************************************************************************/
+ control CONTROL ( .add_sel(add_sel), .alua_sel(alua_sel), .alub_sel(alub_sel),
+ .aluop_sel(aluop_sel), .cflg_en(cflg_en), .di_ctl(di_ctl),
+ .do_ctl(do_ctl), .ex_af_pls(ex_af_pls), .ex_bank_pls(ex_bank_pls),
+ .ex_dehl_inst(ex_dehl_inst), .halt_nxt(halt_nxt), .hflg_ctl(hflg_ctl),
+ .ief_ctl(ief_ctl), .if_frst(if_frst), .inta_frst(inta_frst),
+ .imd_ctl(imd_ctl), .ld_dmaa(ld_dmaa), .ld_inst(ld_inst),
+ .ld_inta(ld_inta), .ld_page(ld_page), .ld_wait(ld_wait),
+ .nflg_ctl(nflg_ctl), .output_inh(output_inh), .page_sel(page_sel),
+ .pc_sel(pc_sel), .pflg_ctl(pflg_ctl), .rd_frst(rd_frst),
+ .rd_nxt(rd_nxt), .reti_nxt(reti_nxt), .rreg_en(rreg_en), .sflg_en(sflg_en),
+ .state_nxt(state_nxt), .tflg_ctl(tflg_ctl), .tran_sel(tran_sel),
+ .wr_addr(wr_addr), .wr_frst(wr_frst), .zflg_en(zflg_en),
+ .carry_bit(carry_bit), .dmar_reg(dmar_reg), .inst_reg(inst_reg),
+ .intr_reg(intr_reg), .page_reg(page_reg), .par_bit(par_bit),
+ .sign_bit(sign_bit), .state_reg(state_reg), .tflg_reg(tflg_reg),
+ .vector_int(vector_int), .xhlt_reg(xhlt_reg), .zero_bit(zero_bit),
+ .int_req(int_req) );
+
+ /*****************************************************************************************/
+ /* */
+ /* data path module */
+ /* */
+ /*****************************************************************************************/
+ datapath DATAPATH ( .addr_reg_in(addr_reg_in), .carry_bit(carry_bit), .dmar_reg(dmar_reg),
+ .dout_io_reg(dout_io_reg), .dout_mem_reg(dout_mem_reg),
+ .inst_reg(inst_reg), .intr_reg(intr_reg), .page_reg(page_reg),
+ .par_bit(par_bit), .sign_bit(sign_bit), .tflg_reg(tflg_reg),
+ .vector_int(vector_int), .xhlt_reg(xhlt_reg), .zero_bit(zero_bit),
+ .add_sel(add_sel), .alua_sel(alua_sel), .alub_sel(alub_sel),
+ .aluop_sel(aluop_sel), .clearb(clearb), .clkc(clkc), .cflg_en(cflg_en),
+ .data_in(data_in), .di_ctl(di_ctl), .dma_req(dma_req), .do_ctl(do_ctl),
+ .ex_af_pls(ex_af_pls), .ex_bank_pls(ex_bank_pls),
+ .ex_dehl_inst(ex_dehl_inst), .hflg_ctl(hflg_ctl), .ief_ctl(ief_ctl),
+ .imd_ctl(imd_ctl), .int_req(int_req), .ivec_rd(ivec_rd),
+ .ld_ctrl(ld_ctrl), .ld_inst(ld_inst), .ld_page(ld_page),
+ .nflg_ctl(nflg_ctl), .nmi_req(nmi_req), .page_sel(page_sel),
+ .pc_sel(pc_sel), .pflg_ctl(pflg_ctl), .resetb(resetb), .rreg_en(rreg_en),
+ .sflg_en(sflg_en), .tflg_ctl(tflg_ctl), .wait_st(wait_st),
+ .wr_addr(wr_addr), .zflg_en(zflg_en) );
+
+ endmodule
\ No newline at end of file
diff --git a/common/Cores-master.zip b/common/Cores-master.zip
new file mode 100644
index 00000000..80b11316
Binary files /dev/null and b/common/Cores-master.zip differ
diff --git a/common/IO/R6532.vhd b/common/IO/R6532.vhd
new file mode 100644
index 00000000..b08a96d0
--- /dev/null
+++ b/common/IO/R6532.vhd
@@ -0,0 +1,362 @@
+-------------------------------------------------------------------------------
+-- File : R6532.vhd
+-- Author : Thierry DAVROUX
+-- Company : Flipprojets
+-- Created : 12-01-2017
+-------------------------------------------------------------------------------
+-- Description: Version simplifiee d'un 6532.
+-- Avec uniquement les ports A et B et le timer.
+-- La RAM et la ROM ne sont pas integrees dans ce module.
+-- La selection est simplifiee avec un seul "Chip Select".
+-- Detection de front sur PA7.
+-- Bus d'adresses sur 5 bits (A4..A0).
+-------------------------------------------------------------------------------
+-- Copyright (c) Flipprojets François et Thierry DAVROUX - 2018
+-- (contact@flipprojets.fr)
+--
+-- Concédée sous licence EUPL, version 1.2 ou – dès leur approbation par la
+-- Commission européenne - versions ultérieures de l’EUPL (la «Licence»).
+-- Vous ne pouvez utiliser la présente œuvre que conformément à la Licence.
+-- Vous pouvez obtenir une copie de la Licence à l’adresse suivante:
+--
+-- https://joinup.ec.europa.eu/software/page/eupl
+--
+-- Sauf obligation légale ou contractuelle écrite, le logiciel distribué sous
+-- la Licence est distribué «en l’état», SANS GARANTIES OU CONDITIONS QUELLES
+-- QU’ELLES SOIENT, expresses ou implicites. Consultez la Licence pour les
+-- autorisations et les restrictions linguistiques spécifiques relevant de la
+-- Licence.
+-------------------------------------------------------------------------------
+-- Revisions :
+-- Date Version Author Description
+-- 12-01-2017 1.0 TDX Creation
+-- 27-03-2017 1.1 TDX Correction bug detection front PA7
+-------------------------------------------------------------------------------
+
+library IEEE ;
+use IEEE.std_logic_1164.all ;
+use IEEE.numeric_std.all ;
+
+entity R6532 is
+ port (
+ phi2 : in std_logic ; -- PHI2 horloge
+ rst_n : in std_logic ; -- RST reset negatif
+ cs : in std_logic ; -- CS chip select
+ rw_n : in std_logic ; -- RW read/write
+ irq_n : out std_logic ; -- IRQ interruption
+
+ add : in std_logic_vector (4 downto 0) ; -- A4..A0 Bus d'adresses
+ din : in std_logic_vector (7 downto 0) ; -- DI7..DI0 Bus de donnees (entrees)
+ dout : out std_logic_vector (7 downto 0) ; -- DO7..DO0 Bus de donnees (sorties)
+
+ pa_in : in std_logic_vector (7 downto 0) ; -- PORT A entrees
+ pa_out : out std_logic_vector (7 downto 0) ; -- PORT A sorties
+ pb_in : in std_logic_vector (7 downto 0) ; -- PORT B entrees
+ pb_out : out std_logic_vector (7 downto 0) -- PORT B sorties
+ );
+end entity;
+
+architecture RTL of R6532 is
+
+ signal s_ddra : std_logic_vector (7 downto 0) ; -- Registre DDRA
+ signal s_ddrb : std_logic_vector (7 downto 0) ; -- Registre DDRB
+ signal s_ora : std_logic_vector (7 downto 0) ; -- Registre ORA
+ signal s_orb : std_logic_vector (7 downto 0) ; -- Registre ORB
+
+ signal s_dout : std_logic_vector (7 downto 0) ; -- Sortie du bus de donnees
+
+ signal s_irq_timer : std_logic ; -- Etat de l'interruption par le timer
+ signal s_irq_timer_en : std_logic ; -- Autorisation interruption par le timer
+ signal s_divider : unsigned (9 downto 0) ; -- Prediviseur (valeur maxi)
+ signal s_count : unsigned (9 downto 0) ; -- Compteur du prediviseur (compteur)
+ signal s_timer : unsigned (7 downto 0) ; -- Decompteur du timer (valeur en cours)
+
+ signal s_irq_pa7 : std_logic ; -- Etat de l'interruption par PA7
+ signal s_irq_pa7_en : std_logic ; -- Autorisation interruption par PA7
+ signal s_edge : std_logic ; -- Detection front sur PA7 (0 negatif, 1 positif)
+ signal s_PA7 : std_logic ; -- Etat du PA7 memorise, pour detection front
+
+begin
+
+ ------------------------------------------------------------------------
+ -- Fonctionnement principal dependant de PHI2
+ ------------------------------------------------------------------------
+
+ process(phi2)
+ begin
+
+ if (rising_edge(phi2)) then
+
+ ------------------------------------------------------------------------
+ -- Tout le circuit fonctionne sur front montant du PHI2
+ -- y compris la prise en compte du RESET
+ ------------------------------------------------------------------------
+
+ if (rst_n = '0') then
+
+ ------------------------------------------------------------------------
+ -- RESET, init de la sortie de donnees et des ports A/B
+ ------------------------------------------------------------------------
+ s_dout <= (others => '1') ; -- Sortie FF
+ s_ddra <= (others => '0') ; -- DDRA a zero
+ s_ddrb <= (others => '0') ; -- DDRB a zero
+ s_ora <= (others => '0') ; -- ORA a zero
+ s_orb <= (others => '0') ; -- ORB a zero
+
+ ------------------------------------------------------------------------
+ -- RESET, init du timer/diviseur et du flag d'interruption
+ ------------------------------------------------------------------------
+ s_timer <= (others => '0') ; -- Remise a zero du decompteur du timer
+ s_divider <= "0000000000" ; -- Remise a zero du prediviseur (mode 1T)
+ s_count <= (others => '0') ; -- Remise a zero du compteur du prediviseur
+ s_irq_timer <= '0' ; -- Remise a zero de l'interruption
+ s_irq_timer_en <= '0' ; -- Interruption non autorisee
+
+ ------------------------------------------------------------------------
+ -- RESET, init du pa7 et du flag d'interruption
+ ------------------------------------------------------------------------
+ s_irq_pa7 <= '0' ; -- Remise a zero de l'interruption
+ s_irq_pa7_en <= '0' ; -- Interruption non autorisee
+ s_edge <= '0' ; -- Detection sur front negatif par defaut
+
+ else
+
+ ------------------------------------------------------------------------
+ -- Traitement du timer, sur front montant du PHI2
+ ------------------------------------------------------------------------
+
+ if (s_count = s_divider) then
+ s_timer <= s_timer - 1 ; -- On decremente le timer
+ s_count <= (others => '0') ; -- et on reinitialise le compteur du prediviseur
+ if (s_timer = "00000000") then -- Si le timer est arrive a zero
+ s_divider <= "0000000000" ; -- on remet le diviseur a 1T
+ s_irq_timer <= '1' ; -- et on leve le flag d'interruption
+ end if ;
+ else
+ s_count <= s_count + 1 ; -- On incremente le compteur du prediviseur
+ end if ;
+
+ ------------------------------------------------------------------------
+ -- Traitement du PA7, sur front montant du PHI2
+ ------------------------------------------------------------------------
+
+ if (not(pa_in(7) = s_PA7)) then -- Changement d'etat par rapport au dernier etat memorise
+ if (pa_in(7) = s_edge) then -- Detection du front positif ou negatif selon programmation
+ s_irq_pa7 <= '1' ; -- Si oui, on leve le flag d'interruption pour PA7
+ end if ;
+ end if ;
+ s_PA7 <= pa_in(7) ; -- Memorisation de l'etat actuel du PA7
+
+ ------------------------------------------------------------------------
+ -- Acces aux registres, sur front montant du PHI2
+ ------------------------------------------------------------------------
+
+ if (cs = '1') then
+ -------------------------------------------------------------------------------
+ -- A condition que le CHIP SELECT soit actif, l'adressage est le suivant : --
+ -- RW xx000 - Read/Write ORA --
+ -- RW xx001 - Read/Write DDRA --
+ -- RW xx010 - Read/Write ORB --
+ -- RW xx011 - Read/Write DDRB --
+ -- W 1.100 - Write Timer 1T --
+ -- W 1.101 - Write Timer 8T --
+ -- W 1.110 - Write Timer 64T --
+ -- W 1.111 - Write Timer 1024T --
+ -- W 0x1.. - Write Edge Detect Control --
+ -- R xx1x0 - Read Timer --
+ -- R xx1x1 - Read Status (interrupt flag) --
+ -------------------------------------------------------------------------------
+
+ if (rw_n = '0') then
+ --------------
+ -- Ecriture --
+ --------------
+
+ if (add(2) = '0') then
+ ---------------------------------------------
+ -- Acces aux registres I/O quand A2 = 0 --
+ ---------------------------------------------
+
+ case add(1 downto 0) is
+ when "00" =>
+ ------------------------------
+ -- 000 : Ecriture dans ORA --
+ ------------------------------
+ s_ora <= din ;
+ when "01" =>
+ ------------------------------
+ -- 001 : Ecriture dans DDRA --
+ ------------------------------
+ s_ddra <= din ;
+ when "10" =>
+ ------------------------------
+ -- 010 : Ecriture dans ORB --
+ ------------------------------
+ s_orb <= din ;
+ when "11" =>
+ ------------------------------
+ -- 011 : Ecriture dans DDRB --
+ ------------------------------
+ s_ddrb <= din ;
+ when others =>
+ null ;
+ end case ;
+
+ else
+ -------------------------------------------------
+ -- Acces aux registres Timer/Edge quand A2 = 1 --
+ -------------------------------------------------
+
+ if (add(4) = '1') then
+ ---------------------------------------------
+ -- Acces au timer/prediviseur quand A4 = 1 --
+ ---------------------------------------------
+
+ ---------------------------------------------
+ -- A3 active ou non les interruptions --
+ ---------------------------------------------
+
+ s_irq_timer_en <= add(3) ; -- Autorisation des interruptions selon le bit A3
+ s_irq_timer <= '0' ; -- Efface le flag d'interruption
+ s_timer <= unsigned(din) - 1 ; -- Valeur initiale du timer
+ s_count <= (others => '0') ; -- Mise a zero du compteur du prediviseur
+
+ case add(1 downto 0) is
+ when "00" =>
+ --------------------------
+ -- 100 : diviseur 1T --
+ --------------------------
+ s_divider <= "0000000000" ; -- Valeur maxi du compteur = 0
+ when "01" =>
+ --------------------------
+ -- 101 : diviseur 8T --
+ --------------------------
+ s_divider <= "0000000111" ; -- Valeur maxi du compteur = 7
+ when "10" =>
+ --------------------------
+ -- 110 : diviseur 64T --
+ --------------------------
+ s_divider <= "0000111111" ; -- Valeur maxi du compteur = 63
+ when "11" =>
+ --------------------------
+ -- 111 : diviseur 1024T --
+ --------------------------
+ s_divider <= "1111111111" ; -- Valeur maxi du compteur = 1023
+ when others =>
+ null ;
+ end case ;
+
+ else
+ ---------------------------------------------
+ -- Acces au Edge quand A4 = 0 --
+ ---------------------------------------------
+
+ ---------------------------------------------------------
+ -- A1 active ou non les interruptions --
+ -- A0 indique le sens de la transition --
+ ---------------------------------------------------------
+
+ s_irq_pa7_en <= add(1) ; -- Autorisation des interruptions selon le bit A1
+ s_edge <= add(0) ; -- Transition front positif ou negatif
+ s_irq_pa7 <= '0' ; -- Efface le flag d'interruption
+
+ end if ;
+
+ end if ; -- Fin des ecritures --
+
+ else
+ -------------
+ -- Lecture --
+ -------------
+
+ if (add(2) = '0') then
+ ---------------------------------------------
+ -- Acces aux registres I/O quand A2 = 0 --
+ ---------------------------------------------
+
+ case add(1 downto 0) is
+ when "00" =>
+ ---------------------------
+ -- 000 : Lecture de ORA --
+ ---------------------------
+ s_dout <= ((s_ddra and s_ora) or (pa_in and not(s_ddra))) ; -- Lecture du port en entree ou des latches de sortie
+ when "01" =>
+ ---------------------------
+ -- 001 : Lecture de DDRA --
+ ---------------------------
+ s_dout <= s_ddra ;
+ when "10" =>
+ ---------------------------
+ -- 010 : Lecture de ORB --
+ ---------------------------
+ s_dout <= ((s_ddrb and s_orb) or (pb_in and not(s_ddrb))) ; -- Lecture du port en entree ou des latches de sortie
+ when "11" =>
+ ---------------------------
+ -- 011 : Lecture de DDRB --
+ ---------------------------
+ s_dout <= s_ddrb ;
+ when others =>
+ null ;
+
+ end case ;
+
+ else
+ ---------------------------------------------
+ -- Acces au timer et status quand A2 = 1 --
+ ---------------------------------------------
+
+ if (add(0) = '0') then
+ ----------------------------------------
+ -- 1x0 : Lecture du TIMER --
+ -- A3 active ou non les interruptions --
+ ----------------------------------------
+ s_irq_timer_en <= add(3) ; -- Autorisation des interruptions selon le bit A3
+
+ s_dout <= std_logic_vector(s_timer) ; -- Valeur courante du timer
+ if not (s_timer = "00000000") then
+ s_irq_timer <= '0' ; -- Efface le flag d'interruption du timer, sauf si interruption en cours
+ end if ;
+ else
+ -----------------------------
+ -- 1x1 : Lecture du STATUS --
+ -----------------------------
+ s_dout <= s_irq_timer & s_irq_pa7 & "000000" ; -- Registre de status (flag d'interruption)
+ s_irq_pa7 <= '0' ; -- Efface le flag d'interruption PA7
+ end if ;
+
+ end if ;
+
+ end if ; -- Fin des lectures --
+
+ end if ; -- Fin des acces dependant du chip select --
+
+ end if ; -- Fin des traitements hors RESET
+
+ ------------------------------------------------------------------------
+ -- Signal d'interruption en sortie, si interruption generee et autorisee
+ ------------------------------------------------------------------------
+
+ irq_n <= not ((s_irq_timer and s_irq_timer_en) or (s_irq_pa7 and s_irq_pa7_en)) ;
+
+ end if ; -- Fin du traitement sur front montant de PHI2
+
+ ------------------------------------------------------------------------
+ -- Sorties sur les ports A et B, sur front descendant du PHI2
+ ------------------------------------------------------------------------
+
+ if (falling_edge(phi2)) then
+ pa_out <= ((s_ora and s_ddra) or (pa_in and not(s_ddra))) ; -- Sortie sur PORT A, uniquement pour les bits en sorties (a "1" dans DDRA) + copie des entrees
+ pb_out <= ((s_orb and s_ddrb) or (pb_in and not(s_ddrb))) ; -- Sortie sur PORT B, uniquement pour les bits en sorties (a "1" dans DDRB) + copie des entrees
+ end if ;
+
+ end process ;
+
+ ------------------------------------------------------------------------
+ -- Sortie sur le bus de donnees
+ ------------------------------------------------------------------------
+
+ dout <= s_dout when ((cs = '1') and (rw_n = '1')) else (others => '1') ; -- Si lecture et chip select, sinon FF
+
+end architecture;
+
+
\ No newline at end of file
diff --git a/common/IO/cia6526.vhd b/common/IO/cia6526.vhd
new file mode 100644
index 00000000..25eb4255
--- /dev/null
+++ b/common/IO/cia6526.vhd
@@ -0,0 +1,782 @@
+-- -----------------------------------------------------------------------
+--
+-- FPGA 64
+--
+-- A fully functional commodore 64 implementation in a single FPGA
+--
+-- -----------------------------------------------------------------------
+-- Peter Wendrich (pwsoft@syntiac.com)
+-- http://www.syntiac.com/fpga64.html
+-- -----------------------------------------------------------------------
+--
+-- 6526 Complex Interface Adapter
+--
+-- rev 1 - june17 / TOD alarms
+-- -----------------------------------------------------------------------
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.numeric_std.ALL;
+
+-- -----------------------------------------------------------------------
+
+entity cia6526 is
+ generic (
+ todEnabled : std_logic := '1'
+ );
+ port (
+ clk: in std_logic;
+ todClk: in std_logic;
+ reset: in std_logic;
+ enable: in std_logic;
+ cs: in std_logic;
+ we: in std_logic; -- Write strobe
+ rd: in std_logic; -- Read strobe
+
+ addr: in unsigned(3 downto 0);
+ di: in unsigned(7 downto 0);
+ do: out unsigned(7 downto 0);
+
+ ppai: in unsigned(7 downto 0);
+ ppao: out unsigned(7 downto 0);
+ ppad: out unsigned(7 downto 0);
+
+ ppbi: in unsigned(7 downto 0);
+ ppbo: out unsigned(7 downto 0);
+ ppbd: out unsigned(7 downto 0);
+
+ flag_n: in std_logic;
+
+ irq_n: out std_logic
+ );
+end cia6526;
+
+-- -----------------------------------------------------------------------
+
+architecture Behavioral of cia6526 is
+ -- IO ports
+ signal pra: unsigned(7 downto 0);
+ signal prb: unsigned(7 downto 0);
+ signal ddra: unsigned(7 downto 0);
+ signal ddrb: unsigned(7 downto 0);
+
+ -- Timer to IO ports
+ signal timerAPulse : std_logic;
+ signal timerAToggle : std_logic;
+ signal timerBPulse : std_logic;
+ signal timerBToggle : std_logic;
+
+ -- Timer A reload registers
+ signal talo: unsigned(7 downto 0) := (others => '1');
+ signal tahi: unsigned(7 downto 0) := (others => '1');
+
+ -- Timer B reload registers
+ signal tblo: unsigned(7 downto 0) := (others => '1');
+ signal tbhi: unsigned(7 downto 0) := (others => '1');
+
+ -- Timer A and B internal registers
+ signal timerA : unsigned(15 downto 0);
+ signal forceTimerA : std_logic;
+ signal loadTimerA : std_logic;
+ signal clkTimerA : std_logic; -- internal timer clock
+
+ signal timerB: unsigned(15 downto 0);
+ signal forceTimerB : std_logic;
+ signal loadTimerB : std_logic;
+ signal clkTimerB : std_logic; -- internal timer clock
+
+ signal WR_Delay_offset : std_logic; -- adjustable WR signal delay - LCA jun17
+
+ -- Config register A
+ signal cra_start : std_logic;
+ signal cra_pbon : std_logic;
+ signal cra_outmode : std_logic;
+ signal cra_runmode : std_logic;
+ signal cra_runmode_reg : std_logic;
+ signal cra_inmode : std_logic;
+ signal cra_spmode : std_logic;
+ signal cra_todin : std_logic;
+
+ -- Config register B
+ signal crb_start : std_logic;
+ signal crb_pbon : std_logic;
+ signal crb_outmode : std_logic;
+ signal crb_runmode : std_logic;
+ signal crb_runmode_reg : std_logic;
+ signal crb_inmode5 : std_logic;
+ signal crb_inmode6 : std_logic;
+ signal crb_alarm : std_logic;
+
+ -- TOD 50/60 hz clock
+ signal todTick : std_logic;
+ signal oldTodClk : std_logic;
+ signal tod_clkcnt: unsigned(2 downto 0);
+
+ -- TOD counters
+ signal tod_running: std_logic;
+ signal tod_10ths: unsigned(3 downto 0);
+ signal tod_secs: unsigned(6 downto 0);
+ signal tod_mins: unsigned(6 downto 0);
+ signal tod_hrs: unsigned(7 downto 0);
+ signal tod_pm: std_logic;
+
+ -- TOD latches
+ signal tod_latched: std_logic;
+ signal tod_latch_10ths: unsigned(3 downto 0);
+ signal tod_latch_secs: unsigned(6 downto 0);
+ signal tod_latch_mins: unsigned(6 downto 0);
+ signal tod_latch_hrs: unsigned(7 downto 0);
+ constant tod_latch_pm: std_logic := '0';
+
+ -- TOD alarms - LCA
+ signal tod_10ths_alarm: unsigned(3 downto 0);
+ signal tod_secs_alarm: unsigned(6 downto 0);
+ signal tod_mins_alarm: unsigned(6 downto 0);
+ signal tod_hrs_alarm: unsigned(7 downto 0);
+ signal tod_pm_alarm: std_logic;
+
+ -- Interrupt processing
+ signal resetIrq : boolean;
+ signal intr_flagn : std_logic;
+ signal intr_serial : std_logic;
+ signal intr_alarm : std_logic; -- LCA
+ signal intr_timerA : std_logic;
+ signal intr_timerB : std_logic;
+ signal mask_timerA : std_logic;
+ signal mask_timerB : std_logic;
+ signal mask_alarm : std_logic; -- LCA
+ signal mask_serial : std_logic;
+ signal mask_flagn : std_logic;
+ signal ir: std_logic;
+
+ signal prevFlag_n: std_logic;
+
+ signal myWr : std_logic;
+ signal myRd : std_logic;
+begin
+-- -----------------------------------------------------------------------
+-- chip-select signals
+-- -----------------------------------------------------------------------
+ myWr <= cs and we;
+ myRd <= cs and rd;
+
+-- -----------------------------------------------------------------------
+-- I/O ports
+-- -----------------------------------------------------------------------
+ -- Port A
+ process(pra, ddra)
+ begin
+ ppad <= ddra;
+ ppao <= pra or (not ddra);
+ end process;
+
+ -- Port B
+ process(prb, ddrb, cra_pbon, cra_outmode, crb_pbon, crb_outmode, timerAPulse, timerAToggle, timerBPulse, timerBToggle)
+ begin
+ ppbd <= ddrb;
+ ppbo <= prb or (not ddrb);
+ if cra_pbon = '1' then
+ ppbo(6) <= timerAPulse or (not ddrb(6));
+ if cra_outmode = '1' then
+ ppbo(6) <= timerAToggle or (not ddrb(6));
+ end if;
+ end if;
+ if crb_pbon = '1' then
+ ppbo(7) <= timerBPulse or (not ddrb(7));
+ if crb_outmode = '1' then
+ ppbo(7) <= timerBToggle or (not ddrb(7));
+ end if;
+ end if;
+ end process;
+
+ -- I/O port registers
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if myWr = '1' then
+ case addr is
+ when X"0" => pra <= di;
+ when X"1" => prb <= di;
+ when X"2" => ddra <= di;
+ when X"3" => ddrb <= di;
+ when others => null;
+ end case;
+ end if;
+ if reset = '1' then
+ pra <= (others => '0');
+ prb <= (others => '0');
+ ddra <= (others => '0');
+ ddrb <= (others => '0');
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+-- TOD - time of day
+-- -----------------------------------------------------------------------
+ process(clk)
+ begin
+ -- Process rising edge on the todClk.
+ -- There is a prescaler of 5 or 6 to get 10ths of seconds from
+ -- 50 Hz or 60 Hz line frequency.
+ --
+ -- Output is a 'todTick' signal synchronished with enable signal (@ 1Mhz).
+ if rising_edge(clk) then
+ if todEnabled = '1' then
+ if enable = '1' then
+ todTick <= '0';
+ end if;
+
+ if todClk = '1' and oldTodClk = '0' then
+ -- Divide by 5 or 6 dependng on 50/60 Hz flag.
+ if tod_clkcnt /= "000" then
+ tod_clkcnt <= tod_clkcnt - 1;
+ else
+ todTick <= tod_running;
+ tod_clkcnt <= "101"; -- 60 Hz
+ if cra_todin = '1' then
+ tod_clkcnt <= "100"; -- 50 Hz
+ end if;
+ end if;
+ end if;
+ oldTodClk <= todClk;
+ else
+ todTick <= '0';
+ end if;
+ end if;
+ end process;
+
+ process(clk)
+ variable new_10ths : unsigned(3 downto 0);
+ variable new_secsL : unsigned(3 downto 0);
+ variable new_secsH : unsigned(2 downto 0);
+ variable new_minsL : unsigned(3 downto 0);
+ variable new_minsH : unsigned(2 downto 0);
+ variable new_hrsL : unsigned(3 downto 0);
+ variable new_hrsH : std_logic;
+ variable new_hrs_byte : unsigned(7 downto 0); -- LCA am/pm and hours
+ begin
+ if rising_edge(clk) then
+ new_10ths := tod_10ths;
+ new_secsL := tod_secs(3 downto 0);
+ new_secsH := tod_secs(6 downto 4);
+ new_minsL := tod_mins(3 downto 0);
+ new_minsH := tod_mins(6 downto 4);
+-- new_hrsL := tod_hrs(3 downto 0);
+-- new_hrsH := tod_hrs(4);
+ new_hrs_byte := tod_hrs (7 downto 0); -- LCA am/pm and hours
+-- new_hrs_byte := new_hrsH & new_hrsL;
+
+ if enable = '1'
+ and todTick = '1' then
+ if new_10ths /= "1001" then
+ new_10ths := new_10ths + 1;
+ else
+ new_10ths := "0000";
+ if new_secsL /= "1001" then
+ new_secsL := new_secsL + 1;
+ else
+ new_secsL := "0000";
+ if new_secsH /= "101" then
+ new_secsH := new_secsH + 1;
+ else
+ new_secsH := "000";
+ if new_minsL /= "1001" then
+ new_minsL := new_minsL + 1;
+ else
+ new_minsL := "0000";
+ if new_minsH /= "101" then
+ new_minsH := new_minsH + 1;
+ else
+ new_minsH := "000";
+ -- hrs were missing jun17 LCA
+ -- I mean completely absent from code :) !!!!!!
+ -- case to lookup then handles oddities in others
+ -- retarded am/pm flag flip madness handled at register load below (REG B)
+
+ case tod_hrs is -- case state to set hours and am/pm
+ when "00010010" =>
+ new_hrs_byte := "00000001"; -- 1 am set
+ when "00000001" =>
+ new_hrs_byte := "00000010";
+ when "00000010" =>
+ new_hrs_byte := "00000011";
+ when "00000011" =>
+ new_hrs_byte := "00000100";
+ when "00000100" =>
+ new_hrs_byte := "00000101";
+ when "00000101" =>
+ new_hrs_byte := "00000110";
+ when "00000110" =>
+ new_hrs_byte := "00000111";
+ when "00000111" =>
+ new_hrs_byte := "00001000";
+ when "00001000" =>
+ new_hrs_byte := "00001001";
+ when "00001001" =>
+ new_hrs_byte := "00010000";
+ when "00010000" =>
+ new_hrs_byte := "00010001"; -- 11am set
+ when "00010001" =>
+ new_hrs_byte := "10010010"; -- 12pm set
+ when "10010010" =>
+ new_hrs_byte := "10000001"; -- 1 pm set
+
+ when "10000001" =>
+ new_hrs_byte := "10000010";
+ when "10000010" =>
+ new_hrs_byte := "10000011";
+ when "10000011" =>
+ new_hrs_byte := "10000100";
+ when "10000100" =>
+ new_hrs_byte := "10000101";
+ when "10000101" =>
+ new_hrs_byte := "10000110";
+ when "10000110" =>
+ new_hrs_byte := "10000111";
+ when "10000111" =>
+ new_hrs_byte := "10001000";
+ when "10001000" =>
+ new_hrs_byte := "10001001";
+ when "10001001" =>
+ new_hrs_byte := "10010000"; -- 10pm set
+ when "10010000" =>
+ new_hrs_byte := "10010001"; -- 11pm set
+ when "10010001" =>
+ new_hrs_byte := "00010010"; -- 12am set (midnight)
+ when others =>
+ new_hrs_byte (3 downto 0) := new_hrs_byte (3 downto 0) + 1;
+ --null;
+ end case;
+
+ end if;
+ end if;
+ end if;
+ end if;
+ end if;
+ end if;
+
+ if myWr = '1' then
+ if crb_alarm = '0' then
+ case addr is
+ when X"8" =>
+ new_10ths := di(3 downto 0);
+ tod_running <= '1';
+ when X"9" =>
+ new_secsL := di(3 downto 0);
+ new_secsH := di(6 downto 4);
+ when X"A" =>
+ new_minsL := di(3 downto 0);
+ new_minsH := di(6 downto 4);
+ when X"B" =>
+ new_hrs_byte := di(7) & "00" & di(4 downto 0); -- LCA
+ tod_running <= '0';
+ if di(7 downto 0) = "10010010" or di(7 downto 0) = "00010010" then -- super bodge because cbm flips am/pm flag at 12 am or pm (its retarded!!!!!)
+ new_hrs_byte(7) := not new_hrs_byte(7); -- This P.O.S. now mimics real commodore 64 !!!!! LCA
+ end if;
+ when others =>
+ null;
+ end case;
+ else -- TOD ALARM UPDATE
+ case addr is
+ when X"8" =>
+ tod_10ths_alarm <= di(3 downto 0);
+ when X"9" =>
+ tod_secs_alarm <= di(6 downto 0);
+ when X"A" =>
+ tod_mins_alarm <= di(6 downto 0);
+ when X"B" =>
+-- tod_hrs_alarm <= di(4 downto 0);
+-- tod_pm_alarm <= di(7);
+ tod_hrs_alarm <= di(7) & "00" & di(4 downto 0); -- LCA
+ if di(7 downto 0) = "10010010" or di(7 downto 0) = "00010010" then -- super bodge because cbm flips am/pm flag at 12 am or pm (its retarded!!!!!)
+ tod_hrs_alarm(7) <= not tod_hrs_alarm(7); -- This P.O.S. now mimics real commodore 64 !!!!! LCA
+ end if;
+ when others =>
+ null;
+ end case;
+ end if;
+ end if;
+
+ -- Update state
+ tod_10ths <= new_10ths;
+ tod_secs <= new_secsH & new_secsL;
+ tod_mins <= new_minsH & new_minsL;
+ tod_hrs <= new_hrs_byte; -- LCA
+
+ if tod_latched = '0' then
+ tod_latch_10ths <= new_10ths;
+ tod_latch_secs <= new_secsH & new_secsL;
+ tod_latch_mins <= new_minsH & new_minsL;
+ tod_latch_hrs <= new_hrs_byte; -- LCA
+ end if;
+
+ -- TOD ALARM test for match - LCA
+ if (tod_10ths = tod_10ths_alarm) and
+ (tod_secs = tod_secs_alarm) and
+ (tod_mins = tod_mins_alarm) and
+ (tod_hrs = tod_hrs_alarm) and
+ (crb_alarm = '1') then
+ intr_alarm <= '1' ;
+ end if;
+
+ if reset = '1' then
+ tod_running <= '0';
+ tod_10ths_alarm <= "0000" ;
+ tod_secs_alarm <= "0000000" ;
+ tod_mins_alarm <= "0000000" ;
+ tod_hrs_alarm <= "00000000" ;
+ tod_pm_alarm <= '0' ;
+ end if;
+
+ if resetIrq then
+ intr_alarm <= '0' ;
+ end if;
+ end if;
+ end process;
+
+ -- Control TOD output latch
+ -- Reading the hours latches the output until
+ -- the 10ths of seconds are read. While latched the
+ -- clock continues to run in the bankground.
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if myRd = '1' then
+ case addr is
+ when X"8" => tod_latched <= '0';
+ when X"B" => tod_latched <= '1';
+ when others => null;
+ end case;
+ end if;
+ end if;
+ end process;
+
+
+-- -----------------------------------------------------------------------
+-- Timer A and B
+-- -----------------------------------------------------------------------
+
+
+-- adjustable time delay jun17 - LCA
+
+-- -----------------------------------------------------------------------
+-- -----------------------------------------------------------------------
+
+ process(clk)
+ variable WR_delay : unsigned(15 downto 0);
+ begin
+ if rising_edge(clk) then
+ if (myWr = '0' or reset = '1') then
+ WR_delay := "0000000000000000";
+ WR_Delay_offset <= '0';
+-- end if;
+ elsif (myWr = '1' and (WR_delay < 31)) then
+ WR_delay := WR_delay + 1;
+-- end if;
+ elsif (WR_delay > 8) then -- adds a (1/32mhz * value) qualifier to WR signal in timers - LCA jun17
+ WR_Delay_offset <= '1';
+ else
+ WR_Delay_offset <= '0';
+ end if;
+ end if;
+ end process;
+
+-- -----------------------------------------------------------------------
+
+ process(clk)
+ variable newTimerA : unsigned(15 downto 0);
+ variable nextClkTimerA : std_logic;
+ variable timerBInput : std_logic;
+ variable newTimerB : unsigned(15 downto 0);
+ variable nextClkTimerB : std_logic;
+ variable new_cra_runmode : std_logic;
+ variable new_crb_runmode : std_logic;
+ begin
+ if rising_edge(clk) then
+ loadTimerA <= '0';
+ loadTimerB <= '0';
+ new_cra_runmode := cra_runmode;
+ new_crb_runmode := crb_runmode;
+
+ if resetIrq then
+ intr_timerA <= '0';
+ intr_timerB <= '0';
+ end if;
+
+ if myWr = '1' then
+-- if (myWr = '1' and WR_Delay_offset = '1') then -- x/32mhz offset to qualify WR signal LCA jun17
+ case addr is
+ when X"4" =>
+ talo <= di;
+ when X"5" =>
+ tahi <= di;
+ if cra_start = '0' then
+ loadTimerA <= '1';
+ end if;
+ when X"6" =>
+ tblo <= di;
+ when X"7" =>
+ tbhi <= di;
+ if crb_start = '0' then
+ loadTimerB <= '1';
+ end if;
+ when X"E" =>
+ if cra_start = '0' then
+ -- Only set on rising edge
+ timerAToggle <= timerAToggle or di(0);
+ end if;
+ cra_start <= di(0);
+ new_cra_runmode := di(3);
+ when X"F" =>
+ if crb_start = '0' then
+ -- Only set on rising edge
+ timerBToggle <= timerBToggle or di(0);
+ end if;
+ crb_start <= di(0);
+ new_crb_runmode := di(3);
+ when others => null;
+ end case;
+ end if;
+
+ if reset = '1' then
+ new_cra_runmode := '0';
+ new_crb_runmode := '0';
+ end if;
+
+ cra_runmode <= new_cra_runmode;
+ crb_runmode <= new_crb_runmode;
+
+ if enable = '1' then
+ --
+ -- process timer A
+ --
+ timerAPulse <= '0';
+ newTimerA := timerA;
+
+ -- CNT is not emulated so don't count when inmode = 1
+ nextClkTimerA := cra_start and (not cra_inmode);
+ if clkTimerA = '1' then
+ newTimerA := newTimerA - 1;
+ end if;
+ if nextClkTimerA = '1'
+ and newTimerA = 0 then
+ intr_timerA <= '1';
+ loadTimerA <= '1';
+ timerAPulse <= '1';
+ timerAToggle <= not timerAToggle;
+ if (new_cra_runmode or cra_runmode) = '1' then
+ cra_start <= '0';
+ end if;
+ end if;
+ if forceTimerA = '1' then
+ loadTimerA <= '1';
+ end if;
+ clkTimerA <= nextClkTimerA;
+ timerA <= newTimerA;
+
+ --
+ -- process timer B
+ --
+ timerBPulse <= '0';
+ newTimerB := timerB;
+
+ if crb_inmode6 = '1' then
+ -- count timerA underflows
+ timerBInput := timerAPulse;
+ elsif crb_inmode5 = '0' then
+ -- count clock pulses
+ timerBInput := '1';
+ else
+ -- CNT is not emulated so don't count
+ timerBInput := '0';
+ end if;
+ nextClkTimerB := timerBInput and crb_start;
+ if clkTimerB = '1' then
+ newTimerB := newTimerB - 1;
+ end if;
+ if nextClkTimerB = '1'
+ and newTimerB = 0 then
+ intr_timerB <= '1';
+ loadTimerB <= '1';
+ timerBPulse <= '1';
+ timerBToggle <= not timerBToggle;
+ if (new_crb_runmode or crb_runmode) = '1' then
+ crb_start <= '0';
+ end if;
+ end if;
+ if forceTimerB = '1' then
+ loadTimerB <= '1';
+ end if;
+ clkTimerB <= nextClkTimerB;
+ timerB <= newTimerB;
+ end if;
+
+ if loadTimerA = '1' then
+ timerA <= tahi & talo;
+ clkTimerA <= '0';
+ end if;
+
+ if loadTimerB = '1' then
+ timerB <= tbhi & tblo;
+ clkTimerB <= '0';
+ end if;
+ end if;
+ end process;
+
+
+-- -----------------------------------------------------------------------
+-- Interrupts
+-- -----------------------------------------------------------------------
+ resetIrq <= ((myRd = '1') and (addr = X"D")) or (reset = '1');
+ irq_n <= not(ir);
+ intr_serial <= '0';
+
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ if enable = '1' then
+ ir <= ir
+ or (intr_timerA and mask_timerA)
+ or (intr_timerB and mask_timerB)
+ or (intr_alarm and mask_alarm)
+ or (intr_serial and mask_serial)
+ or (intr_flagn and mask_flagn);
+ end if;
+
+ if myWr = '1' then
+ case addr is
+ when X"D" =>
+ if di(7) ='0' then
+ mask_timerA <= mask_timerA and (not di(0));
+ mask_timerB <= mask_timerB and (not di(1));
+ mask_alarm <= mask_alarm and (not di(2)); -- LCA
+ mask_serial <= mask_serial and (not di(3));
+ mask_flagn <= mask_flagn and (not di(4));
+ else
+ mask_timerA <= mask_timerA or di(0);
+ mask_timerB <= mask_timerB or di(1);
+ mask_alarm <= mask_alarm or di(2); -- LCA
+ mask_serial <= mask_serial or di(3);
+ mask_flagn <= mask_flagn or di(4);
+ end if;
+ when others =>
+ null;
+ end case;
+ end if;
+
+ if resetIrq then
+ ir <= '0';
+ end if;
+
+ if reset = '1' then
+ mask_timerA <= '0';
+ mask_timerB <= '0';
+ mask_alarm <= '0' ;
+ mask_serial <= '0';
+ mask_flagn <= '0';
+ end if;
+ end if;
+ end process;
+
+
+
+
+-- -----------------------------------------------------------------------
+-- FLAG_N input
+-- -----------------------------------------------------------------------
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ prevFlag_n <= flag_n;
+ if (flag_n = '0') and (prevFlag_n = '1') then
+ intr_flagn <= '1';
+ end if;
+ if resetIrq then
+ intr_flagn <= '0';
+ end if;
+ end if;
+ end process;
+
+
+-- -----------------------------------------------------------------------
+-- Write registers
+-- -----------------------------------------------------------------------
+ process(clk)
+ begin
+ if rising_edge(clk) then
+-- resetIrq <= '0';
+ if enable = '1' then
+ forceTimerA <= '0';
+ forceTimerB <= '0';
+-- cra_runmode_reg <= cra_runmode;
+-- crb_runmode_reg <= crb_runmode;
+ end if;
+ if myWr = '1' then
+ case addr is
+ when X"E" =>
+ cra_pbon <= di(1);
+ cra_outmode <= di(2);
+-- cra_runmode <= di(3);
+ forceTimerA <= di(4);
+ cra_inmode <= di(5);
+ cra_spmode <= di(6);
+ cra_todin <= di(7);
+ when X"F" =>
+ crb_pbon <= di(1);
+ crb_outmode <= di(2);
+-- crb_runmode <= di(3);
+ forceTimerB <= di(4);
+ crb_inmode5 <= di(5);
+ crb_inmode6 <= di(6);
+ crb_alarm <= di(7);
+ when others => null;
+ end case;
+ end if;
+ if reset = '1' then
+ cra_pbon <= '0';
+ cra_outmode <= '0';
+-- cra_runmode <= '0';
+ cra_inmode <= '0';
+ cra_spmode <= '0';
+ cra_todin <= '0';
+ crb_pbon <= '0';
+ crb_outmode <= '0';
+-- crb_runmode <= '0';
+ crb_inmode5 <= '0';
+ crb_inmode6 <= '0';
+ crb_alarm <= '0';
+ end if;
+ end if;
+ end process;
+
+
+-- -----------------------------------------------------------------------
+-- Read registers
+-- -----------------------------------------------------------------------
+ process(clk)
+ begin
+ if rising_edge(clk) then
+ case addr is
+ when X"0" => do <= ppai;
+ when X"1" => do <= ppbi;
+ when X"2" => do <= DDRA;
+ when X"3" => do <= DDRB;
+ when X"4" => do <= timera(7 downto 0);
+ when X"5" => do <= timera(15 downto 8);
+ when X"6" => do <= timerb(7 downto 0);
+ when X"7" => do <= timerb(15 downto 8);
+ when X"8" => do <= "0000" & tod_latch_10ths;
+ when X"9" => do <= "0" & tod_latch_secs;
+ when X"A" => do <= "0" & tod_latch_mins;
+-- when X"B" => do <= tod_latch_pm & "00" & tod_latch_hrs;
+ when X"B" => do <= tod_latch_hrs; -- LCA
+ when X"C" => do <= (others => '0');
+ when X"D" => do <= ir & "00" & intr_flagn & intr_serial & intr_alarm & intr_timerB & intr_timerA;
+ when X"E" => do <= cra_todin & cra_spmode & cra_inmode & '0' & cra_runmode & cra_outmode & cra_pbon & cra_start;
+ when X"F" => do <= crb_alarm & crb_inmode6 & crb_inmode5 & '0' & crb_runmode & crb_outmode & crb_pbon & crb_start;
+ when others => do <= (others => '-');
+ end case;
+ end if;
+ end process;
+end Behavioral;
diff --git a/common/IO/i8035ip.v b/common/IO/i8035ip.v
new file mode 100644
index 00000000..e2c23a6e
--- /dev/null
+++ b/common/IO/i8035ip.v
@@ -0,0 +1,132 @@
+//===============================================================================
+// FPGA DONKEY KONG T8035 I/F
+//
+// Version : 1.01
+//
+// Copyright(c) 2004 Katsumi Degawa , All rights reserved
+//
+// Important !
+//
+// This program is freeware for non-commercial use.
+// An author does no guarantee about this program.
+// You can use this under your own risk.
+//
+// 2004- 9- 2 T48-IP(beta3) was include. K.Degawa
+// 2004- 9- 2 T48 Bug Fix K.Degawa
+// 2004- 9-14 T48-IP was changed to beta4. K.Degawa
+// 2005- 2- 9 It cleaned.
+//================================================================================
+
+
+module I8035IP(
+
+I_CLK,
+I_RSTn,
+I_INTn,
+I_EA,
+O_PSENn,
+O_RDn,
+O_WRn,
+O_ALE,
+O_PROGn,
+I_T0,
+O_T0,
+I_T1,
+I_DB,
+O_DB,
+I_P1,
+O_P1,
+I_P2,
+O_P2
+
+);
+
+input I_CLK;
+input I_RSTn;
+input I_INTn;
+input I_EA;
+output O_PSENn;
+output O_RDn;
+output O_WRn;
+output O_ALE;
+output O_PROGn;
+input I_T0;
+output O_T0;
+input I_T1;
+input [7:0]I_DB;
+output [7:0]O_DB;
+input [7:0]I_P1;
+output [7:0]O_P1;
+input [7:0]I_P2;
+output [7:0]O_P2;
+
+wire W_PSENn;
+assign O_PSENn = W_PSENn ;
+
+// 64 Byte RAM ------------------------------------------
+wire [7:0]t48_ram_a;
+wire t48_ram_we;
+wire [7:0]t48_ram_do;
+wire [7:0]t48_ram_di;
+
+ram_64_8 t48_ram(
+
+.I_CLK(I_CLK),
+.I_ADDR(t48_ram_a[5:0]),
+.I_D(t48_ram_di),
+.I_CE(1'b1),
+.I_WE(t48_ram_we),
+.O_D(t48_ram_do)
+
+);
+
+//----------------------------------------------------------
+
+wire xtal3_s;
+
+t48_core t48_core(
+
+.xtal_i(I_CLK),
+.reset_i(I_RSTn),
+.t0_i(I_T0),
+.t0_o(O_T0),
+.t0_dir_o(),
+.int_n_i(I_INTn),
+.ea_i(I_EA),
+.rd_n_o(O_RDn),
+.psen_n_o(W_PSENn),
+.wr_n_o(O_WRn),
+.ale_o(O_ALE),
+.db_i(I_DB),
+.db_o(O_DB),
+.db_dir_o(),
+.t1_i(I_T1),
+.p2_i(I_P2),
+.p2_o(O_P2),
+.p2_low_imp_o(),
+.p1_i(I_P1),
+.p1_o(O_P1),
+.p1_low_imp_o(),
+.prog_n_o(O_PROGn),
+.clk_i(I_CLK),
+.en_clk_i(xtal3_s),
+.xtal3_o(xtal3_s),
+.dmem_addr_o(t48_ram_a),
+.dmem_we_o(t48_ram_we),
+.dmem_data_i(t48_ram_do),
+.dmem_data_o(t48_ram_di),
+.pmem_addr_o(),
+.pmem_data_i(8'h00)
+
+);
+
+
+endmodule
+
+
+
+
+
+
+
+
diff --git a/common/IO/i8253.v b/common/IO/i8253.v
new file mode 100644
index 00000000..72e2b77d
--- /dev/null
+++ b/common/IO/i8253.v
@@ -0,0 +1,158 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer:
+//
+// Create Date: 09:58:45 02/25/2008
+// Design Name:
+// Module Name: i8253
+// Project Name:
+// Target Devices:
+// Tool versions:
+// Description:
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+//
+//////////////////////////////////////////////////////////////////////////////////
+module i8253(reset, clk, addr, data_out, data_in, cs, rd, wr, clk0, clk1, clk2, out0, out1, out2);
+ input reset;
+ input clk;
+ input [1:0] addr;
+ output[7:0] data_out;
+ input [7:0] data_in;
+ input cs, rd, wr;
+ input clk0, clk1, clk2;
+ output out0, out1, out2;
+ wire [1:0] addr;
+ wire [7:0] data_out, data_in;
+ wire cs, rd, wr;
+ wire clk0, clk1, clk2;
+ wire out0, out1, out2;
+
+ reg [7:0] mode0, mode1, mode2;
+ reg [15:0] max0, max1, max2;
+ reg [15:0] count0 = 0, count1 = 0, count2 = 0;
+ reg signal0 = 0, signal1 = 0, signal2 = 0;
+ reg read_hl0, read_hl1, read_hl2;
+ reg write_hl0, write_hl1, write_hl2;
+ reg [7:0] data;
+
+ always @(posedge clk or posedge reset) begin
+ if ( reset ) begin
+ mode0 <= 8'h00;
+ mode1 <= 8'h00;
+ mode2 <= 8'h00;
+ max0 <= 16'd1;
+ max1 <= 16'd1;
+ max2 <= 16'd1;
+ write_hl0 <= 1'b0;
+ write_hl1 <= 1'b0;
+ write_hl2 <= 1'b0;
+ read_hl0 <= 1'b0;
+ read_hl1 <= 1'b0;
+ read_hl2 <= 1'b0;
+ end else if ( cs ) begin
+ if ( addr == 2'd0 & wr ) begin
+ write_hl0 <= ( mode0[5:4] == 2'b00 | mode0[5:4] == 2'b11 ) ? ~write_hl0: write_hl0;
+ if ( ((mode0[5:4] == 2'b00 | mode0[5:4] == 2'b11) & write_hl0) | mode0[5:4] == 2'b10 )
+ max0[15:8] <= data_in;
+ else
+ max0[7:0] <= data_in;
+ end else if ( addr == 2'd1 & wr ) begin
+ write_hl1 <= ( mode1[5:4] == 2'b00 | mode1[5:4] == 2'b11 ) ? ~write_hl1: write_hl1;
+ if ( ((mode1[5:4] == 2'b00 | mode1[5:4] == 2'b11) & write_hl1) | mode1[5:4] == 2'b10 )
+ max1[15:8] <= data_in;
+ else
+ max1[7:0] <= data_in;
+ end else if ( addr == 2'd2 & wr ) begin
+ write_hl2 <= ( mode2[5:4] == 2'b00 | mode2[5:4] == 2'b11 ) ? ~write_hl2: write_hl2;
+ if ( ((mode2[5:4] == 2'b00 | mode2[5:4] == 2'b11) & write_hl2) | mode2[5:4] == 2'b10 )
+ max2[15:8] <= data_in;
+ else
+ max2[7:0] <= data_in;
+ end else if ( addr == 2'd3 & wr ) begin
+ if ( data_in[7:6] == 2'd0 ) begin
+ mode0 <= data_in;
+ read_hl0 <= data_in[5:4] == 2'b10 ? 1 : 0;
+ write_hl0 <= data_in[5:4] == 2'b10 ? 1 : 0;
+ end else if ( data_in[7:6] == 2'd1 ) begin
+ mode1 <= data_in;
+ read_hl1 <= data_in[5:4] == 2'b10 ? 1 : 0;
+ write_hl1 <= data_in[5:4] == 2'b10 ? 1 : 0;
+ end else if ( data_in[7:6] == 2'd2 ) begin
+ mode2 <= data_in;
+ read_hl2 <= data_in[5:4] == 2'b10 ? 1 : 0;
+ write_hl2 <= data_in[5:4] == 2'b10 ? 1 : 0;
+ end
+ end else if ( addr == 2'd0 & rd ) begin
+ read_hl0 <= ( mode0[5:4] == 2'b00 | mode0[5:4] == 2'b11 ) ? ~read_hl0: read_hl0;
+ data <= ~( ((mode0[5:4] == 2'b00 | mode0[5:4] == 2'b11 ) & read_hl0) | mode0[5:4] == 2'b10 ) ? count0[15:8] : count0[7:0];
+ end else if ( addr == 2'd1 & rd ) begin
+ read_hl1 <= ( mode1[5:4] == 2'b00 | mode1[5:4] == 2'b11 ) ? ~read_hl1: read_hl1;
+ data <= ~( ((mode1[5:4] == 2'b00 | mode1[5:4] == 2'b11 ) & read_hl1) | mode1[5:4] == 2'b10 ) ? count1[15:8] : count1[7:0];
+ end else if ( addr == 2'd2 & rd ) begin
+ read_hl2 <= ( mode2[5:4] == 2'b00 | mode2[5:4] == 2'b11 ) ? ~read_hl2: read_hl2;
+ data <= ~( ((mode2[5:4] == 2'b00 | mode2[5:4] == 2'b11 ) & read_hl2) | mode2[5:4] == 2'b10 ) ? count2[15:8] : count2[7:0];
+ end
+ end
+ end
+
+ always @(posedge clk0) begin
+ if ( count0 != 0 ) begin
+ count0 <= ( count0 <= max0 ) ? count0 - 1: max0;
+ if ( mode0[3:1] == 3'b000 | mode0[3:1] == 3'b001 ) // MODE0
+ signal0 <= 0;
+ end else begin
+ if ( mode0[3:1] == 3'b000 | mode0[3:1] == 3'b001 ) begin // MODE0
+ count0 <= max0;
+ signal0 <= 1;
+ end else begin
+ count0 <= max0;
+ signal0 <= ~signal0;
+ end
+ end
+ end
+
+ always @(posedge clk1) begin
+ if ( count1 != 0 ) begin
+ count1 <= ( count1 <= max1 ) ? count1 - 1: max1;
+ if ( mode1[3:1] == 3'b000 | mode1[3:1] == 3'b001 ) // MODE0/1
+ signal1 <= 0;
+ end else begin
+ if ( mode1[3:1] == 3'b000 | mode1[3:1] == 3'b001 ) begin // MODE0/1
+ count1 <= max1;
+ signal1 <= 1;
+ end else begin
+ count1 <= max1;
+ signal1 <= ~signal1;
+ end
+ end
+ end
+
+ always @(posedge clk2) begin
+ if ( count2 != 0 ) begin
+ count2 <= ( count2 <= max2 ) ? count2 - 1: max2;
+ if ( mode2[3:1] == 3'b000 | mode2[3:1] == 3'b001 ) // MODE0/1
+ signal2 <= 0;
+ end else begin
+ if ( mode2[3:1] == 3'b000 | mode2[3:1] == 3'b001 ) begin // MODE0/1
+ count2 <= max2;
+ signal2 <= 1;
+ end else begin
+ count2 <= max2;
+ signal2 <= ~signal2;
+ end
+ end
+ end
+
+ assign out0 = signal0;
+ assign out1 = signal1;
+ assign out2 = signal2;
+
+ assign data_out = data;
+
+endmodule
diff --git a/common/IO/i8255.vhd b/common/IO/i8255.vhd
new file mode 100644
index 00000000..7af5db5b
--- /dev/null
+++ b/common/IO/i8255.vhd
@@ -0,0 +1,700 @@
+---------------------------------------------------------------------------------------------------------
+--
+-- Name: i8255.vhd
+-- Created: Feb 2007
+-- Author(s): MikeJ, Refactored and ported for this emulation by Philip Smart
+-- Description: Sharp MZ series i8255 PPI
+-- This module emulates the Intel i8255 Programmable Peripheral Interface chip.
+--
+-- Credits:
+-- Copyright: (c) MikeJ - Feb 2007
+--
+-- History: July 2018 - Initial module refactored and updated for this emulation.
+--
+---------------------------------------------------------------------------------------------------------
+--
+-- Original copyright notice below:-
+--
+-- A simulation model of i8255 PIA
+-- Copyright (c) MikeJ - Feb 2007
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS CODE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- You are responsible for any legal issues arising from your use of this code.
+--
+-- The latest version of this file can be found at: www.fpgaarcade.com
+--
+-- Email support@fpgaarcade.com
+--
+-- Revision list
+--
+-- version 001 initial release
+--
+---------------------------------------------------------------------------------------------------------
+
+library ieee ;
+ use ieee.std_logic_1164.all ;
+ use ieee.std_logic_unsigned.all;
+ use ieee.numeric_std.all;
+
+entity i8255 is
+ port (
+ RESET : in std_logic;
+ CLK : in std_logic;
+ ENA : in std_logic; -- (CPU) clk enable
+ ADDR : in std_logic_vector(1 downto 0); -- A1-A0
+ DI : in std_logic_vector(7 downto 0); -- D7-D0
+ DO : out std_logic_vector(7 downto 0);
+-- DO_OE_n : out std_logic;
+ CS_n : in std_logic;
+ RD_n : in std_logic;
+ WR_n : in std_logic;
+
+ PA_I : in std_logic_vector(7 downto 0);
+ PA_O : out std_logic_vector(7 downto 0);
+ PA_O_OE_n : out std_logic_vector(7 downto 0);
+
+ PB_I : in std_logic_vector(7 downto 0);
+ PB_O : out std_logic_vector(7 downto 0);
+ PB_O_OE_n : out std_logic_vector(7 downto 0);
+
+ PC_I : in std_logic_vector(7 downto 0);
+ PC_O : out std_logic_vector(7 downto 0);
+ PC_O_OE_n : out std_logic_vector(7 downto 0)
+ );
+end;
+
+architecture RTL of i8255 is
+
+ -- registers
+ signal bit_mask : std_logic_vector(7 downto 0);
+ signal r_porta : std_logic_vector(7 downto 0);
+ signal r_portb : std_logic_vector(7 downto 0);
+ signal r_portc : std_logic_vector(7 downto 0);
+ signal r_control : std_logic_vector(7 downto 0);
+ --
+ signal porta_we : std_logic;
+ signal portb_we : std_logic;
+ signal porta_re : std_logic;
+ signal portb_re : std_logic;
+ --
+ signal porta_we_t1 : std_logic;
+ signal portb_we_t1 : std_logic;
+ signal porta_re_t1 : std_logic;
+ signal portb_re_t1 : std_logic;
+ --
+ signal porta_we_rising : boolean;
+ signal portb_we_rising : boolean;
+ signal porta_re_rising : boolean;
+ signal portb_re_rising : boolean;
+ --
+ signal groupa_mode : std_logic_vector(1 downto 0); -- port a/c upper
+ signal groupb_mode : std_logic; -- port b/c lower
+ --
+ signal porta_read : std_logic_vector(7 downto 0);
+ signal portb_read : std_logic_vector(7 downto 0);
+ signal portc_read : std_logic_vector(7 downto 0);
+ signal control_read : std_logic_vector(7 downto 0);
+ signal mode_clear : std_logic;
+ --
+ signal a_inte1 : std_logic;
+ signal a_inte2 : std_logic;
+ signal b_inte : std_logic;
+ --
+ signal a_intr : std_logic;
+ signal a_obf_l : std_logic;
+ signal a_ibf : std_logic;
+ signal a_ack_l : std_logic;
+ signal a_stb_l : std_logic;
+ signal a_ack_l_t1 : std_logic;
+ signal a_stb_l_t1 : std_logic;
+ --
+ signal b_intr : std_logic;
+ signal b_obf_l : std_logic;
+ signal b_ibf : std_logic;
+ signal b_ack_l : std_logic;
+ signal b_stb_l : std_logic;
+ signal b_ack_l_t1 : std_logic;
+ signal b_stb_l_t1 : std_logic;
+ --
+ signal a_ack_l_rising : boolean;
+ signal a_stb_l_rising : boolean;
+ signal b_ack_l_rising : boolean;
+ signal b_stb_l_rising : boolean;
+ --
+ signal porta_ipreg : std_logic_vector(7 downto 0);
+ signal portb_ipreg : std_logic_vector(7 downto 0);
+begin
+ --
+ -- mode 0 - basic input/output
+ -- mode 1 - strobed input/output
+ -- mode 2/3 - bi-directional bus
+ --
+ -- control word (write)
+ --
+ -- D7 mode set flag 1 = active
+ -- D6..5 GROUPA mode selection (mode 0,1,2)
+ -- D4 GROUPA porta 1 = input, 0 = output
+ -- D3 GROUPA portc upper 1 = input, 0 = output
+ -- D2 GROUPB mode selection (mode 0 ,1)
+ -- D1 GROUPB portb 1 = input, 0 = output
+ -- D0 GROUPB portc lower 1 = input, 0 = output
+ --
+ -- D7 bit set/reset 0 = active
+ -- D6..4 x
+ -- D3..1 bit select
+ -- d0 1 = set, 0 - reset
+ --
+ -- all output registers including status are reset when mode is changed
+ --1. Port A:
+ --All Modes: Output data is cleared, input data is not cleared.
+
+ --2. Port B:
+ --Mode 0: Output data is cleared, input data is not cleared.
+ --Mode 1 and 2: Both output and input data are cleared.
+
+ --3. Port C:
+ --Mode 0:Output data is cleared, input data is not cleared.
+ --Mode 1 and 2: IBF and INTR are cleared and OBF# is set.
+ --Outputs in Port C which are not used for handshaking or interrupt signals are cleared.
+ --Inputs such as STB#, ACK#, or "spare" inputs are not affected. The interrupts for Ports A and B are disabled.
+
+ p_bit_mask : process(DI)
+ begin
+ bit_mask <= x"01";
+ case DI(3 downto 1) is
+ when "000" => bit_mask <= x"01";
+ when "001" => bit_mask <= x"02";
+ when "010" => bit_mask <= x"04";
+ when "011" => bit_mask <= x"08";
+ when "100" => bit_mask <= x"10";
+ when "101" => bit_mask <= x"20";
+ when "110" => bit_mask <= x"40";
+ when "111" => bit_mask <= x"80";
+ when others => null;
+ end case;
+ end process;
+
+ p_write_reg_reset : process(RESET, CLK)
+ variable r_portc_masked : std_logic_vector(7 downto 0);
+ variable r_portc_setclr : std_logic_vector(7 downto 0);
+ begin
+ if (RESET = '1') then
+ r_porta <= x"00";
+ r_portb <= x"00";
+ r_portc <= x"00";
+ r_control <= x"9B"; -- 10011011
+ mode_clear <= '1';
+ elsif rising_edge(CLK) then
+
+ r_portc_masked := (not bit_mask) and r_portc;
+ for i in 0 to 7 loop
+ r_portc_setclr(i) := bit_mask(i) and DI(0);
+ end loop;
+
+ if (ENA = '1') then
+ mode_clear <= '0';
+ if (CS_n = '0') and (WR_n = '0') then
+ case ADDR is
+ when "00" => r_porta <= DI;
+ when "01" => r_portb <= DI;
+ when "10" => r_portc <= DI;
+
+ when "11" => if (DI(7) = '0') then -- set/clr
+ r_portc <= r_portc_masked or r_portc_setclr;
+ else
+ --mode_clear <= '1';
+ --r_porta <= x"00";
+ --r_portb <= x"00"; -- clear port b input reg
+ --r_portc <= x"00"; -- clear control sigs
+ r_control <= DI; -- load new mode
+ end if;
+ when others => null;
+ end case;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ p_decode_control : process(r_control)
+ begin
+ groupa_mode <= r_control(6 downto 5);
+ groupb_mode <= r_control(2);
+ end process;
+
+ --p_oe : process(CS_n, RD_n)
+ --begin
+ -- DO_OE_n <= '1';
+ -- if (CS_n = '0') and (RD_n = '0') then
+ -- DO_OE_n <= '0';
+ -- end if;
+ --end process;
+
+ p_read : process(ADDR , porta_read, portb_read, portc_read, control_read)
+ begin
+ DO <= x"00"; -- default
+ --if (CS_n = '0') and (RD_n = '0') then -- not required
+ case ADDR is
+ when "00" => DO <= porta_read;
+ when "01" => DO <= portb_read;
+ when "10" => DO <= portc_read;
+ when "11" => DO <= control_read;
+ when others => null;
+ end case;
+ --end if;
+ end process;
+ control_read(7) <= '1'; -- always 1
+ control_read(6 downto 0) <= r_control(6 downto 0);
+
+ p_rw_control : process(CS_n, RD_n, WR_n, ADDR )
+ begin
+ porta_we <= '0';
+ portb_we <= '0';
+ porta_re <= '0';
+ portb_re <= '0';
+
+ if (CS_n = '0') and (ADDR = "00") then
+ porta_we <= not WR_n;
+ porta_re <= not RD_n;
+ end if;
+
+ if (CS_n = '0') and (ADDR = "01") then
+ portb_we <= not WR_n;
+ portb_re <= not RD_n;
+ end if;
+ end process;
+
+ p_rw_control_reg : process
+ begin
+ wait until rising_edge(CLK);
+ if (ENA = '1') then
+ porta_we_t1 <= porta_we;
+ portb_we_t1 <= portb_we;
+ porta_re_t1 <= porta_re;
+ portb_re_t1 <= portb_re;
+
+ a_stb_l_t1 <= a_stb_l;
+ a_ack_l_t1 <= a_ack_l;
+ b_stb_l_t1 <= b_stb_l;
+ b_ack_l_t1 <= b_ack_l;
+ end if;
+ end process;
+
+ porta_we_rising <= (porta_we = '0') and (porta_we_t1 = '1'); -- falling as inverted
+ portb_we_rising <= (portb_we = '0') and (portb_we_t1 = '1'); -- "
+ porta_re_rising <= (porta_re = '0') and (porta_re_t1 = '1'); -- falling as inverted
+ portb_re_rising <= (portb_re = '0') and (portb_re_t1 = '1'); -- "
+ --
+ a_stb_l_rising <= (a_stb_l = '1') and (a_stb_l_t1 = '0');
+ a_ack_l_rising <= (a_ack_l = '1') and (a_ack_l_t1 = '0');
+ b_stb_l_rising <= (b_stb_l = '1') and (b_stb_l_t1 = '0');
+ b_ack_l_rising <= (b_ack_l = '1') and (b_ack_l_t1 = '0');
+ --
+ -- GROUP A
+ -- in mode 1
+ --
+ -- d4=1 (porta = input)
+ -- pc7,6 io (d3=1 input, d3=0 output)
+ -- pc5 output a_ibf
+ -- pc4 input a_stb_l
+ -- pc3 output a_intr
+ --
+ -- d4=0 (porta = output)
+ -- pc7 output a_obf_l
+ -- pc6 input a_ack_l
+ -- pc5,4 io (d3=1 input, d3=0 output)
+ -- pc3 output a_intr
+ --
+ -- GROUP B
+ -- in mode 1
+ -- d1=1 (portb = input)
+ -- pc2 input b_stb_l
+ -- pc1 output b_ibf
+ -- pc0 output b_intr
+ --
+ -- d1=0 (portb = output)
+ -- pc2 input b_ack_l
+ -- pc1 output b_obf_l
+ -- pc0 output b_intr
+
+
+ -- WHEN AN INPUT
+ --
+ -- stb_l a low on this input latches input data
+ -- ibf a high on this output indicates data latched. set by stb_l and reset by rising edge of RD_L
+ -- intr a high on this output indicates interrupt. set by stb_l high, ibf high and inte high. reset by falling edge of RD_L
+ -- inte A controlled by bit/set PC4
+ -- inte B controlled by bit/set PC2
+
+ -- WHEN AN OUTPUT
+ --
+ -- obf_l output will go low when cpu has written data
+ -- ack_l input - a low on this clears obf_l
+ -- intr output set when ack_l is high, obf_l is high and inte is one. reset by falling edge of WR_L
+ -- inte A controlled by bit/set PC6
+ -- inte B controlled by bit/set PC2
+
+ -- GROUP A
+ -- in mode 2
+ --
+ -- porta = IO
+ --
+ -- control bits 2..0 still control groupb/c lower 2..0
+ --
+ --
+ -- PC7 output a_obf
+ -- PC6 input a_ack_l
+ -- PC5 output a_ibf
+ -- PC4 input a_stb_l
+ -- PC3 is still interrupt out
+ p_control_flags : process(RESET, CLK)
+ variable we : boolean;
+ variable set1 : boolean;
+ variable set2 : boolean;
+ begin
+ if (RESET = '1') then
+ a_obf_l <= '1';
+ a_inte1 <= '0';
+ a_ibf <= '0';
+ a_inte2 <= '0';
+ a_intr <= '0';
+ --
+ b_inte <= '0';
+ b_obf_l <= '1';
+ b_ibf <= '0';
+ b_intr <= '0';
+ elsif rising_edge(CLK) then
+ we := (CS_n = '0') and (WR_n = '0') and (ADDR = "11") and (DI(7) = '0');
+
+ if (ENA = '1') then
+ if (mode_clear = '1') then
+ a_obf_l <= '1';
+ a_inte1 <= '0';
+ a_ibf <= '0';
+ a_inte2 <= '0';
+ a_intr <= '0';
+ --
+ b_inte <= '0';
+ b_obf_l <= '1';
+ b_ibf <= '0';
+ b_intr <= '0';
+ else
+ if (bit_mask(7) = '1') and we then
+ a_obf_l <= DI(0);
+ else
+ if porta_we_rising then
+ a_obf_l <= '0';
+ elsif (a_ack_l = '0') then
+ a_obf_l <= '1';
+ end if;
+ end if;
+ --
+ if (bit_mask(6) = '1') and we then a_inte1 <= DI(0); end if; -- bus set when mode1 & input?
+ --
+ if (bit_mask(5) = '1') and we then
+ a_ibf <= DI(0);
+ else
+ if porta_re_rising then
+ a_ibf <= '0';
+ elsif (a_stb_l = '0') then
+ a_ibf <= '1';
+ end if;
+ end if;
+ --
+ if (bit_mask(4) = '1') and we then a_inte2 <= DI(0); end if; -- bus set when mode1 & output?
+ --
+ set1 := a_ack_l_rising and (a_obf_l = '1') and (a_inte1 = '1');
+ set2 := a_stb_l_rising and (a_ibf = '1') and (a_inte2 = '1');
+ --
+ if (bit_mask(3) = '1') and we then
+ a_intr <= DI(0);
+ else
+ if (groupa_mode(1) = '1') then
+ if (porta_we = '1') or (porta_re = '1') then
+ a_intr <= '0';
+ elsif set1 or set2 then
+ a_intr <= '1';
+ end if;
+ else
+ if (r_control(4) = '0') then -- output
+ if (porta_we = '1') then -- falling ?
+ a_intr <= '0';
+ elsif set1 then
+ a_intr <= '1';
+ end if;
+ elsif (r_control(4) = '1') then -- input
+ if (porta_re = '1') then -- falling ?
+ a_intr <= '0';
+ elsif set2 then
+ a_intr <= '1';
+ end if;
+ end if;
+ end if;
+ end if;
+ --
+ if (bit_mask(2) = '1') and we then b_inte <= DI(0); end if; -- bus set?
+
+ if (bit_mask(1) = '1') and we then
+ b_obf_l <= DI(0);
+ else
+ if (r_control(1) = '0') then -- output
+ if portb_we_rising then
+ b_obf_l <= '0';
+ elsif (b_ack_l = '0') then
+ b_obf_l <= '1';
+ end if;
+ else
+ if portb_re_rising then
+ b_ibf <= '0';
+ elsif (b_stb_l = '0') then
+ b_ibf <= '1';
+ end if;
+ end if;
+ end if;
+
+ if (bit_mask(0) = '1') and we then
+ b_intr <= DI(0);
+ else
+ if (r_control(1) = '0') then -- output
+ if (portb_we = '1') then -- falling ?
+ b_intr <= '0';
+ elsif b_ack_l_rising and (b_obf_l = '1') and (b_inte = '1') then
+ b_intr <= '1';
+ end if;
+ else
+ if (portb_re = '1') then -- falling ?
+ b_intr <= '0';
+ elsif b_stb_l_rising and (b_ibf = '1') and (b_inte = '1') then
+ b_intr <= '1';
+ end if;
+ end if;
+ end if;
+
+ end if;
+ end if;
+ end if;
+ end process;
+
+ p_porta : process(r_porta, r_control, groupa_mode, PA_I, porta_ipreg, a_ack_l)
+ begin
+ -- D4 GROUPA porta 1 = input, 0 = output
+ PA_O <= x"FF"; -- if not driven, float high
+ PA_O_OE_n <= x"FF";
+ porta_read <= x"00";
+
+ if (groupa_mode = "00") then -- simple io
+ if (r_control(4) = '0') then -- output
+ PA_O <= r_porta;
+ PA_O_OE_n <= x"00";
+ end if;
+ porta_read <= PA_I;
+ elsif (groupa_mode = "01") then -- strobed
+ if (r_control(4) = '0') then -- output
+ PA_O <= r_porta;
+ PA_O_OE_n <= x"00";
+ end if;
+ porta_read <= porta_ipreg;
+ else -- if (groupa_mode(1) = '1') then -- bi dir
+ if (a_ack_l = '0') then -- output enable
+ PA_O <= r_porta;
+ PA_O_OE_n <= x"00";
+ end if;
+ porta_read <= porta_ipreg; -- latched data
+ end if;
+
+ end process;
+
+ p_portb : process(r_portb, r_control, groupb_mode, PB_I, portb_ipreg)
+ begin
+ PB_O <= x"FF"; -- if not driven, float high
+ PB_O_OE_n <= x"FF";
+ portb_read <= x"00";
+
+ if (groupb_mode = '0') then -- simple io
+ if (r_control(1) = '0') then -- output
+ PB_O <= r_portb;
+ PB_O_OE_n <= x"00";
+ end if;
+ portb_read <= PB_I;
+ else -- strobed mode
+ if (r_control(1) = '0') then -- output
+ PB_O <= r_portb;
+ PB_O_OE_n <= x"00";
+ end if;
+ portb_read <= portb_ipreg;
+ end if;
+ end process;
+
+ p_portc_out : process(r_portc, r_control, groupa_mode, groupb_mode,
+ a_obf_l, a_ibf, a_intr,b_obf_l, b_ibf, b_intr)
+ begin
+ PC_O <= x"FF"; -- if not driven, float high
+ PC_O_OE_n <= x"FF";
+
+ -- bits 7..4
+ if (groupa_mode = "00") then -- simple io
+ if (r_control(3) = '0') then -- output
+ PC_O (7 downto 4) <= r_portc(7 downto 4);
+ PC_O_OE_n(7 downto 4) <= x"0";
+ end if;
+ elsif (groupa_mode = "01") then -- mode1
+
+ if (r_control(4) = '0') then -- port a output
+ PC_O (7) <= a_obf_l;
+ PC_O_OE_n(7) <= '0';
+ -- 6 is ack_l input
+ if (r_control(3) = '0') then -- port c output
+ PC_O (5 downto 4) <= r_portc(5 downto 4);
+ PC_O_OE_n(5 downto 4) <= "00";
+ end if;
+ else -- port a input
+ if (r_control(3) = '0') then -- port c output
+ PC_O (7 downto 6) <= r_portc(7 downto 6);
+ PC_O_OE_n(7 downto 6) <= "00";
+ end if;
+ PC_O (5) <= a_ibf;
+ PC_O_OE_n(5) <= '0';
+ -- 4 is stb_l input
+ end if;
+
+ else -- if (groupa_mode(1) = '1') then -- mode2
+ PC_O (7) <= a_obf_l;
+ PC_O_OE_n(7) <= '0';
+ -- 6 is ack_l input
+ PC_O (5) <= a_ibf;
+ PC_O_OE_n(5) <= '0';
+ -- 4 is stb_l input
+ end if;
+
+ -- bit 3 (controlled by group a)
+ if (groupa_mode = "00") then -- group a steals this bit
+ --if (groupb_mode = '0') then -- we will let bit 3 be driven, data sheet is a bit confused about this
+ if (r_control(0) = '0') then -- ouput (note, groupb control bit)
+ PC_O (3) <= r_portc(3);
+ PC_O_OE_n(3) <= '0';
+ end if;
+ --
+ else -- stolen
+ PC_O (3) <= a_intr;
+ PC_O_OE_n(3) <= '0';
+ end if;
+
+ -- bits 2..0
+ if (groupb_mode = '0') then -- simple io
+ if (r_control(0) = '0') then -- output
+ PC_O (2 downto 0) <= r_portc(2 downto 0);
+ PC_O_OE_n(2 downto 0) <= "000";
+ end if;
+ else
+ -- mode 1
+ -- 2 is input
+ if (r_control(1) = '0') then -- output
+ PC_O (1) <= b_obf_l;
+ PC_O_OE_n(1) <= '0';
+ else -- input
+ PC_O (1) <= b_ibf;
+ PC_O_OE_n(1) <= '0';
+ end if;
+ PC_O (0) <= b_intr;
+ PC_O_OE_n(0) <= '0';
+ end if;
+ end process;
+
+ p_portc_in : process(r_portc, PC_I, r_control, groupa_mode, groupb_mode, a_ibf, b_obf_l,
+ a_obf_l, a_inte1, a_inte2, a_intr, b_inte, b_ibf, b_intr)
+ begin
+ portc_read <= x"00";
+
+ a_stb_l <= '1';
+ a_ack_l <= '1';
+ b_stb_l <= '1';
+ b_ack_l <= '1';
+
+ if (groupa_mode = "01") then -- mode1 or 2
+ if (r_control(4) = '0') then -- port a output
+ a_ack_l <= PC_I(6);
+ else -- port a input
+ a_stb_l <= PC_I(4);
+ end if;
+ elsif (groupa_mode(1) = '1') then -- mode 2
+ a_ack_l <= PC_I(6);
+ a_stb_l <= PC_I(4);
+ end if;
+
+ if (groupb_mode = '1') then
+ if (r_control(1) = '0') then -- output
+ b_ack_l <= PC_I(2);
+ else -- input
+ b_stb_l <= PC_I(2);
+ end if;
+ end if;
+
+ if (groupa_mode = "00") then -- simple io
+ portc_read(7 downto 3) <= PC_I(7 downto 3);
+ elsif (groupa_mode = "01") then
+ if (r_control(4) = '0') then -- port a output
+ portc_read(7 downto 3) <= a_obf_l & a_inte1 & PC_I(5 downto 4) & a_intr;
+ else -- input
+ portc_read(7 downto 3) <= PC_I(7 downto 6) & a_ibf & a_inte2 & a_intr;
+ end if;
+ else -- mode 2
+ portc_read(7 downto 3) <= a_obf_l & a_inte1 & a_ibf & a_inte2 & a_intr;
+ end if;
+
+ if (groupb_mode = '0') then -- simple io
+ portc_read(2 downto 0) <= PC_I(2 downto 0);
+ else
+ if (r_control(1) = '0') then -- output
+ portc_read(2 downto 0) <= b_inte & b_obf_l & b_intr;
+ else -- input
+ portc_read(2 downto 0) <= b_inte & b_ibf & b_intr;
+ end if;
+ end if;
+ end process;
+
+ p_ipreg : process
+ begin
+ wait until rising_edge(CLK);
+ -- pc4 input a_stb_l
+ -- pc2 input b_stb_l
+
+ if (ENA = '1') then
+ if (a_stb_l = '0') then
+ porta_ipreg <= PA_I;
+ end if;
+
+ if (mode_clear = '1') then
+ portb_ipreg <= (others => '0');
+ elsif (b_stb_l = '0') then
+ portb_ipreg <= PB_I;
+ end if;
+ end if;
+ end process;
+
+end architecture RTL;
diff --git a/common/IO/i82c55.vhd b/common/IO/i82c55.vhd
new file mode 100644
index 00000000..d415d932
--- /dev/null
+++ b/common/IO/i82c55.vhd
@@ -0,0 +1,686 @@
+--
+-- A simulation model of Scramble hardware
+-- Copyright (c) MikeJ - Feb 2007
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS CODE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- You are responsible for any legal issues arising from your use of this code.
+--
+-- The latest version of this file can be found at: www.fpgaarcade.com
+--
+-- Email support@fpgaarcade.com
+--
+-- Revision list
+--
+-- version 001 initial release
+--
+
+library ieee ;
+ use ieee.std_logic_1164.all ;
+ use ieee.std_logic_unsigned.all;
+ use ieee.numeric_std.all;
+
+entity I82C55 is
+ port (
+
+ I_ADDR : in std_logic_vector(1 downto 0); -- A1-A0
+ I_DATA : in std_logic_vector(7 downto 0); -- D7-D0
+ O_DATA : out std_logic_vector(7 downto 0);
+ O_DATA_OE_L : out std_logic;
+
+ I_CS_L : in std_logic;
+ I_RD_L : in std_logic;
+ I_WR_L : in std_logic;
+
+ I_PA : in std_logic_vector(7 downto 0);
+ O_PA : out std_logic_vector(7 downto 0);
+ O_PA_OE_L : out std_logic_vector(7 downto 0);
+
+ I_PB : in std_logic_vector(7 downto 0);
+ O_PB : out std_logic_vector(7 downto 0);
+ O_PB_OE_L : out std_logic_vector(7 downto 0);
+
+ I_PC : in std_logic_vector(7 downto 0);
+ O_PC : out std_logic_vector(7 downto 0);
+ O_PC_OE_L : out std_logic_vector(7 downto 0);
+
+ RESET : in std_logic;
+ ENA : in std_logic; -- (CPU) clk enable
+ CLK : in std_logic
+ );
+end;
+
+architecture RTL of I82C55 is
+
+ -- registers
+ signal bit_mask : std_logic_vector(7 downto 0);
+ signal r_porta : std_logic_vector(7 downto 0);
+ signal r_portb : std_logic_vector(7 downto 0);
+ signal r_portc : std_logic_vector(7 downto 0);
+ signal r_control : std_logic_vector(7 downto 0);
+ --
+ signal porta_we : std_logic;
+ signal portb_we : std_logic;
+ signal porta_re : std_logic;
+ signal portb_re : std_logic;
+ --
+ signal porta_we_t1 : std_logic;
+ signal portb_we_t1 : std_logic;
+ signal porta_re_t1 : std_logic;
+ signal portb_re_t1 : std_logic;
+ --
+ signal porta_we_rising : boolean;
+ signal portb_we_rising : boolean;
+ signal porta_re_rising : boolean;
+ signal portb_re_rising : boolean;
+ --
+ signal groupa_mode : std_logic_vector(1 downto 0); -- port a/c upper
+ signal groupb_mode : std_logic; -- port b/c lower
+ --
+ signal porta_read : std_logic_vector(7 downto 0);
+ signal portb_read : std_logic_vector(7 downto 0);
+ signal portc_read : std_logic_vector(7 downto 0);
+ signal control_read : std_logic_vector(7 downto 0);
+ signal mode_clear : std_logic;
+ --
+ signal a_inte1 : std_logic;
+ signal a_inte2 : std_logic;
+ signal b_inte : std_logic;
+ --
+ signal a_intr : std_logic;
+ signal a_obf_l : std_logic;
+ signal a_ibf : std_logic;
+ signal a_ack_l : std_logic;
+ signal a_stb_l : std_logic;
+ signal a_ack_l_t1 : std_logic;
+ signal a_stb_l_t1 : std_logic;
+ --
+ signal b_intr : std_logic;
+ signal b_obf_l : std_logic;
+ signal b_ibf : std_logic;
+ signal b_ack_l : std_logic;
+ signal b_stb_l : std_logic;
+ signal b_ack_l_t1 : std_logic;
+ signal b_stb_l_t1 : std_logic;
+ --
+ signal a_ack_l_rising : boolean;
+ signal a_stb_l_rising : boolean;
+ signal b_ack_l_rising : boolean;
+ signal b_stb_l_rising : boolean;
+ --
+ signal porta_ipreg : std_logic_vector(7 downto 0);
+ signal portb_ipreg : std_logic_vector(7 downto 0);
+begin
+ --
+ -- mode 0 - basic input/output
+ -- mode 1 - strobed input/output
+ -- mode 2/3 - bi-directional bus
+ --
+ -- control word (write)
+ --
+ -- D7 mode set flag 1 = active
+ -- D6..5 GROUPA mode selection (mode 0,1,2)
+ -- D4 GROUPA porta 1 = input, 0 = output
+ -- D3 GROUPA portc upper 1 = input, 0 = output
+ -- D2 GROUPB mode selection (mode 0 ,1)
+ -- D1 GROUPB portb 1 = input, 0 = output
+ -- D0 GROUPB portc lower 1 = input, 0 = output
+ --
+ -- D7 bit set/reset 0 = active
+ -- D6..4 x
+ -- D3..1 bit select
+ -- d0 1 = set, 0 - reset
+ --
+ -- all output registers including status are reset when mode is changed
+ --1. Port A:
+ --All Modes: Output data is cleared, input data is not cleared.
+
+ --2. Port B:
+ --Mode 0: Output data is cleared, input data is not cleared.
+ --Mode 1 and 2: Both output and input data are cleared.
+
+ --3. Port C:
+ --Mode 0:Output data is cleared, input data is not cleared.
+ --Mode 1 and 2: IBF and INTR are cleared and OBF# is set.
+ --Outputs in Port C which are not used for handshaking or interrupt signals are cleared.
+ --Inputs such as STB#, ACK#, or "spare" inputs are not affected. The interrupts for Ports A and B are disabled.
+
+ p_bit_mask : process(I_DATA)
+ begin
+ bit_mask <= x"01";
+ case I_DATA(3 downto 1) is
+ when "000" => bit_mask <= x"01";
+ when "001" => bit_mask <= x"02";
+ when "010" => bit_mask <= x"04";
+ when "011" => bit_mask <= x"08";
+ when "100" => bit_mask <= x"10";
+ when "101" => bit_mask <= x"20";
+ when "110" => bit_mask <= x"40";
+ when "111" => bit_mask <= x"80";
+ when others => null;
+ end case;
+ end process;
+
+ p_write_reg_reset : process(RESET, CLK)
+ variable r_portc_masked : std_logic_vector(7 downto 0);
+ variable r_portc_setclr : std_logic_vector(7 downto 0);
+ begin
+ if (RESET = '1') then
+ r_porta <= x"00";
+ r_portb <= x"00";
+ r_portc <= x"00";
+ r_control <= x"9B"; -- 10011011
+ mode_clear <= '1';
+ elsif rising_edge(CLK) then
+
+ r_portc_masked := (not bit_mask) and r_portc;
+ for i in 0 to 7 loop
+ r_portc_setclr(i) := bit_mask(i) and I_DATA(0);
+ end loop;
+
+ if (ENA = '1') then
+ mode_clear <= '0';
+ if (I_CS_L = '0') and (I_WR_L = '0') then
+ case I_ADDR is
+ when "00" => r_porta <= I_DATA;
+ when "01" => r_portb <= I_DATA;
+ when "10" => r_portc <= I_DATA;
+
+ when "11" => if (I_DATA(7) = '0') then -- set/clr
+ r_portc <= r_portc_masked or r_portc_setclr;
+ else
+ --mode_clear <= '1';
+ --r_porta <= x"00";
+ --r_portb <= x"00"; -- clear port b input reg
+ --r_portc <= x"00"; -- clear control sigs
+ r_control <= I_DATA; -- load new mode
+ end if;
+ when others => null;
+ end case;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ p_decode_control : process(r_control)
+ begin
+ groupa_mode <= r_control(6 downto 5);
+ groupb_mode <= r_control(2);
+ end process;
+
+ p_oe : process(I_CS_L, I_RD_L)
+ begin
+ O_DATA_OE_L <= '1';
+ if (I_CS_L = '0') and (I_RD_L = '0') then
+ O_DATA_OE_L <= '0';
+ end if;
+ end process;
+
+ p_read : process(I_ADDR, porta_read, portb_read, portc_read, control_read)
+ begin
+ O_DATA <= x"00"; -- default
+ --if (I_CS_L = '0') and (I_RD_L = '0') then -- not required
+ case I_ADDR is
+ when "00" => O_DATA <= porta_read;
+ when "01" => O_DATA <= portb_read;
+ when "10" => O_DATA <= portc_read;
+ when "11" => O_DATA <= control_read;
+ when others => null;
+ end case;
+ --end if;
+ end process;
+ control_read(7) <= '1'; -- always 1
+ control_read(6 downto 0) <= r_control(6 downto 0);
+
+ p_rw_control : process(I_CS_L, I_RD_L, I_WR_L, I_ADDR)
+ begin
+ porta_we <= '0';
+ portb_we <= '0';
+ porta_re <= '0';
+ portb_re <= '0';
+
+ if (I_CS_L = '0') and (I_ADDR = "00") then
+ porta_we <= not I_WR_L;
+ porta_re <= not I_RD_L;
+ end if;
+
+ if (I_CS_L = '0') and (I_ADDR = "01") then
+ portb_we <= not I_WR_L;
+ portb_re <= not I_RD_L;
+ end if;
+ end process;
+
+ p_rw_control_reg : process
+ begin
+ wait until rising_edge(CLK);
+ if (ENA = '1') then
+ porta_we_t1 <= porta_we;
+ portb_we_t1 <= portb_we;
+ porta_re_t1 <= porta_re;
+ portb_re_t1 <= portb_re;
+
+ a_stb_l_t1 <= a_stb_l;
+ a_ack_l_t1 <= a_ack_l;
+ b_stb_l_t1 <= b_stb_l;
+ b_ack_l_t1 <= b_ack_l;
+ end if;
+ end process;
+
+ porta_we_rising <= (porta_we = '0') and (porta_we_t1 = '1'); -- falling as inverted
+ portb_we_rising <= (portb_we = '0') and (portb_we_t1 = '1'); -- "
+ porta_re_rising <= (porta_re = '0') and (porta_re_t1 = '1'); -- falling as inverted
+ portb_re_rising <= (portb_re = '0') and (portb_re_t1 = '1'); -- "
+ --
+ a_stb_l_rising <= (a_stb_l = '1') and (a_stb_l_t1 = '0');
+ a_ack_l_rising <= (a_ack_l = '1') and (a_ack_l_t1 = '0');
+ b_stb_l_rising <= (b_stb_l = '1') and (b_stb_l_t1 = '0');
+ b_ack_l_rising <= (b_ack_l = '1') and (b_ack_l_t1 = '0');
+ --
+ -- GROUP A
+ -- in mode 1
+ --
+ -- d4=1 (porta = input)
+ -- pc7,6 io (d3=1 input, d3=0 output)
+ -- pc5 output a_ibf
+ -- pc4 input a_stb_l
+ -- pc3 output a_intr
+ --
+ -- d4=0 (porta = output)
+ -- pc7 output a_obf_l
+ -- pc6 input a_ack_l
+ -- pc5,4 io (d3=1 input, d3=0 output)
+ -- pc3 output a_intr
+ --
+ -- GROUP B
+ -- in mode 1
+ -- d1=1 (portb = input)
+ -- pc2 input b_stb_l
+ -- pc1 output b_ibf
+ -- pc0 output b_intr
+ --
+ -- d1=0 (portb = output)
+ -- pc2 input b_ack_l
+ -- pc1 output b_obf_l
+ -- pc0 output b_intr
+
+
+ -- WHEN AN INPUT
+ --
+ -- stb_l a low on this input latches input data
+ -- ibf a high on this output indicates data latched. set by stb_l and reset by rising edge of RD_L
+ -- intr a high on this output indicates interrupt. set by stb_l high, ibf high and inte high. reset by falling edge of RD_L
+ -- inte A controlled by bit/set PC4
+ -- inte B controlled by bit/set PC2
+
+ -- WHEN AN OUTPUT
+ --
+ -- obf_l output will go low when cpu has written data
+ -- ack_l input - a low on this clears obf_l
+ -- intr output set when ack_l is high, obf_l is high and inte is one. reset by falling edge of WR_L
+ -- inte A controlled by bit/set PC6
+ -- inte B controlled by bit/set PC2
+
+ -- GROUP A
+ -- in mode 2
+ --
+ -- porta = IO
+ --
+ -- control bits 2..0 still control groupb/c lower 2..0
+ --
+ --
+ -- PC7 output a_obf
+ -- PC6 input a_ack_l
+ -- PC5 output a_ibf
+ -- PC4 input a_stb_l
+ -- PC3 is still interrupt out
+ p_control_flags : process(RESET, CLK)
+ variable we : boolean;
+ variable set1 : boolean;
+ variable set2 : boolean;
+ begin
+ if (RESET = '1') then
+ a_obf_l <= '1';
+ a_inte1 <= '0';
+ a_ibf <= '0';
+ a_inte2 <= '0';
+ a_intr <= '0';
+ --
+ b_inte <= '0';
+ b_obf_l <= '1';
+ b_ibf <= '0';
+ b_intr <= '0';
+ elsif rising_edge(CLK) then
+ we := (I_CS_L = '0') and (I_WR_L = '0') and (I_ADDR = "11") and (I_DATA(7) = '0');
+
+ if (ENA = '1') then
+ if (mode_clear = '1') then
+ a_obf_l <= '1';
+ a_inte1 <= '0';
+ a_ibf <= '0';
+ a_inte2 <= '0';
+ a_intr <= '0';
+ --
+ b_inte <= '0';
+ b_obf_l <= '1';
+ b_ibf <= '0';
+ b_intr <= '0';
+ else
+ if (bit_mask(7) = '1') and we then
+ a_obf_l <= I_DATA(0);
+ else
+ if porta_we_rising then
+ a_obf_l <= '0';
+ elsif (a_ack_l = '0') then
+ a_obf_l <= '1';
+ end if;
+ end if;
+ --
+ if (bit_mask(6) = '1') and we then a_inte1 <= I_DATA(0); end if; -- bus set when mode1 & input?
+ --
+ if (bit_mask(5) = '1') and we then
+ a_ibf <= I_DATA(0);
+ else
+ if porta_re_rising then
+ a_ibf <= '0';
+ elsif (a_stb_l = '0') then
+ a_ibf <= '1';
+ end if;
+ end if;
+ --
+ if (bit_mask(4) = '1') and we then a_inte2 <= I_DATA(0); end if; -- bus set when mode1 & output?
+ --
+ set1 := a_ack_l_rising and (a_obf_l = '1') and (a_inte1 = '1');
+ set2 := a_stb_l_rising and (a_ibf = '1') and (a_inte2 = '1');
+ --
+ if (bit_mask(3) = '1') and we then
+ a_intr <= I_DATA(0);
+ else
+ if (groupa_mode(1) = '1') then
+ if (porta_we = '1') or (porta_re = '1') then
+ a_intr <= '0';
+ elsif set1 or set2 then
+ a_intr <= '1';
+ end if;
+ else
+ if (r_control(4) = '0') then -- output
+ if (porta_we = '1') then -- falling ?
+ a_intr <= '0';
+ elsif set1 then
+ a_intr <= '1';
+ end if;
+ elsif (r_control(4) = '1') then -- input
+ if (porta_re = '1') then -- falling ?
+ a_intr <= '0';
+ elsif set2 then
+ a_intr <= '1';
+ end if;
+ end if;
+ end if;
+ end if;
+ --
+ if (bit_mask(2) = '1') and we then b_inte <= I_DATA(0); end if; -- bus set?
+
+ if (bit_mask(1) = '1') and we then
+ b_obf_l <= I_DATA(0);
+ else
+ if (r_control(1) = '0') then -- output
+ if portb_we_rising then
+ b_obf_l <= '0';
+ elsif (b_ack_l = '0') then
+ b_obf_l <= '1';
+ end if;
+ else
+ if portb_re_rising then
+ b_ibf <= '0';
+ elsif (b_stb_l = '0') then
+ b_ibf <= '1';
+ end if;
+ end if;
+ end if;
+
+ if (bit_mask(0) = '1') and we then
+ b_intr <= I_DATA(0);
+ else
+ if (r_control(1) = '0') then -- output
+ if (portb_we = '1') then -- falling ?
+ b_intr <= '0';
+ elsif b_ack_l_rising and (b_obf_l = '1') and (b_inte = '1') then
+ b_intr <= '1';
+ end if;
+ else
+ if (portb_re = '1') then -- falling ?
+ b_intr <= '0';
+ elsif b_stb_l_rising and (b_ibf = '1') and (b_inte = '1') then
+ b_intr <= '1';
+ end if;
+ end if;
+ end if;
+
+ end if;
+ end if;
+ end if;
+ end process;
+
+ p_porta : process(r_control, groupa_mode, r_porta, I_PA, porta_ipreg, a_ack_l)
+ begin
+ -- D4 GROUPA porta 1 = input, 0 = output
+ O_PA <= x"FF"; -- if not driven, float high
+ O_PA_OE_L <= x"FF";
+ porta_read <= x"00";
+
+ if (groupa_mode = "00") then -- simple io
+ if (r_control(4) = '0') then -- output
+ O_PA <= r_porta;
+ O_PA_OE_L <= x"00";
+ end if;
+ porta_read <= I_PA;
+ elsif (groupa_mode = "01") then -- strobed
+ if (r_control(4) = '0') then -- output
+ O_PA <= r_porta;
+ O_PA_OE_L <= x"00";
+ end if;
+ porta_read <= porta_ipreg;
+ else -- if (groupa_mode(1) = '1') then -- bi dir
+ if (a_ack_l = '0') then -- output enable
+ O_PA <= r_porta;
+ O_PA_OE_L <= x"00";
+ end if;
+ porta_read <= porta_ipreg; -- latched data
+ end if;
+
+ end process;
+
+ p_portb : process(r_control, groupb_mode, r_portb, I_PB, portb_ipreg)
+ begin
+ O_PB <= x"FF"; -- if not driven, float high
+ O_PB_OE_L <= x"FF";
+ portb_read <= x"00";
+
+ if (groupb_mode = '0') then -- simple io
+ if (r_control(1) = '0') then -- output
+ O_PB <= r_portb;
+ O_PB_OE_L <= x"00";
+ end if;
+ portb_read <= I_PB;
+ else -- strobed mode
+ if (r_control(1) = '0') then -- output
+ O_PB <= r_portb;
+ O_PB_OE_L <= x"00";
+ end if;
+ portb_read <= portb_ipreg;
+ end if;
+ end process;
+
+ p_portc_out : process(r_portc, r_control, groupa_mode, groupb_mode,
+ a_obf_l, a_ibf, a_intr,b_obf_l, b_ibf, b_intr)
+ begin
+ O_PC <= x"FF"; -- if not driven, float high
+ O_PC_OE_L <= x"FF";
+
+ -- bits 7..4
+ if (groupa_mode = "00") then -- simple io
+ if (r_control(3) = '0') then -- output
+ O_PC (7 downto 4) <= r_portc(7 downto 4);
+ O_PC_OE_L(7 downto 4) <= x"0";
+ end if;
+ elsif (groupa_mode = "01") then -- mode1
+
+ if (r_control(4) = '0') then -- port a output
+ O_PC (7) <= a_obf_l;
+ O_PC_OE_L(7) <= '0';
+ -- 6 is ack_l input
+ if (r_control(3) = '0') then -- port c output
+ O_PC (5 downto 4) <= r_portc(5 downto 4);
+ O_PC_OE_L(5 downto 4) <= "00";
+ end if;
+ else -- port a input
+ if (r_control(3) = '0') then -- port c output
+ O_PC (7 downto 6) <= r_portc(7 downto 6);
+ O_PC_OE_L(7 downto 6) <= "00";
+ end if;
+ O_PC (5) <= a_ibf;
+ O_PC_OE_L(5) <= '0';
+ -- 4 is stb_l input
+ end if;
+
+ else -- if (groupa_mode(1) = '1') then -- mode2
+ O_PC (7) <= a_obf_l;
+ O_PC_OE_L(7) <= '0';
+ -- 6 is ack_l input
+ O_PC (5) <= a_ibf;
+ O_PC_OE_L(5) <= '0';
+ -- 4 is stb_l input
+ end if;
+
+ -- bit 3 (controlled by group a)
+ if (groupa_mode = "00") then -- group a steals this bit
+ --if (groupb_mode = '0') then -- we will let bit 3 be driven, data sheet is a bit confused about this
+ if (r_control(0) = '0') then -- ouput (note, groupb control bit)
+ O_PC (3) <= r_portc(3);
+ O_PC_OE_L(3) <= '0';
+ end if;
+ --
+ else -- stolen
+ O_PC (3) <= a_intr;
+ O_PC_OE_L(3) <= '0';
+ end if;
+
+ -- bits 2..0
+ if (groupb_mode = '0') then -- simple io
+ if (r_control(0) = '0') then -- output
+ O_PC (2 downto 0) <= r_portc(2 downto 0);
+ O_PC_OE_L(2 downto 0) <= "000";
+ end if;
+ else
+ -- mode 1
+ -- 2 is input
+ if (r_control(1) = '0') then -- output
+ O_PC (1) <= b_obf_l;
+ O_PC_OE_L(1) <= '0';
+ else -- input
+ O_PC (1) <= b_ibf;
+ O_PC_OE_L(1) <= '0';
+ end if;
+ O_PC (0) <= b_intr;
+ O_PC_OE_L(0) <= '0';
+ end if;
+ end process;
+
+ p_portc_in : process(r_portc, I_PC, r_control, groupa_mode, groupb_mode, a_ibf, b_obf_l,
+ a_obf_l, a_inte1, a_inte2, a_intr, b_inte, b_ibf, b_intr)
+ begin
+ portc_read <= x"00";
+
+ a_stb_l <= '1';
+ a_ack_l <= '1';
+ b_stb_l <= '1';
+ b_ack_l <= '1';
+
+ if (groupa_mode = "01") then -- mode1 or 2
+ if (r_control(4) = '0') then -- port a output
+ a_ack_l <= I_PC(6);
+ else -- port a input
+ a_stb_l <= I_PC(4);
+ end if;
+ elsif (groupa_mode(1) = '1') then -- mode 2
+ a_ack_l <= I_PC(6);
+ a_stb_l <= I_PC(4);
+ end if;
+
+ if (groupb_mode = '1') then
+ if (r_control(1) = '0') then -- output
+ b_ack_l <= I_PC(2);
+ else -- input
+ b_stb_l <= I_PC(2);
+ end if;
+ end if;
+
+ if (groupa_mode = "00") then -- simple io
+ portc_read(7 downto 3) <= I_PC(7 downto 3);
+ elsif (groupa_mode = "01") then
+ if (r_control(4) = '0') then -- port a output
+ portc_read(7 downto 3) <= a_obf_l & a_inte1 & I_PC(5 downto 4) & a_intr;
+ else -- input
+ portc_read(7 downto 3) <= I_PC(7 downto 6) & a_ibf & a_inte2 & a_intr;
+ end if;
+ else -- mode 2
+ portc_read(7 downto 3) <= a_obf_l & a_inte1 & a_ibf & a_inte2 & a_intr;
+ end if;
+
+ if (groupb_mode = '0') then -- simple io
+ portc_read(2 downto 0) <= I_PC(2 downto 0);
+ else
+ if (r_control(1) = '0') then -- output
+ portc_read(2 downto 0) <= b_inte & b_obf_l & b_intr;
+ else -- input
+ portc_read(2 downto 0) <= b_inte & b_ibf & b_intr;
+ end if;
+ end if;
+ end process;
+
+ p_ipreg : process
+ begin
+ wait until rising_edge(CLK);
+ -- pc4 input a_stb_l
+ -- pc2 input b_stb_l
+
+ if (ENA = '1') then
+ if (a_stb_l = '0') then
+ porta_ipreg <= I_PA;
+ end if;
+
+ if (mode_clear = '1') then
+ portb_ipreg <= (others => '0');
+ elsif (b_stb_l = '0') then
+ portb_ipreg <= I_PB;
+ end if;
+ end if;
+ end process;
+
+end architecture RTL;
diff --git a/common/IO/m6522.vhd b/common/IO/m6522.vhd
new file mode 100644
index 00000000..20d9b941
--- /dev/null
+++ b/common/IO/m6522.vhd
@@ -0,0 +1,920 @@
+--
+-- A simulation model of VIC20 hardware
+-- Copyright (c) MikeJ - March 2003
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS CODE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- You are responsible for any legal issues arising from your use of this code.
+--
+-- The latest version of this file can be found at: www.fpgaarcade.com
+--
+-- Email vic20@fpgaarcade.com
+--
+--
+-- Revision list
+--
+-- version 004 fixes to PB7 T1 control and Mode 0 Shift Register operation
+-- version 003 fix reset of T1/T2 IFR flags if T1/T2 is reload via reg5/reg9 from wolfgang (WoS)
+-- Ported to numeric_std and simulation fix for signal initializations from arnim laeuger
+-- version 002 fix from Mark McDougall, untested
+-- version 001 initial release
+-- not very sure about the shift register, documentation is a bit light.
+
+library ieee ;
+ use ieee.std_logic_1164.all ;
+ use ieee.std_logic_unsigned.all;
+ use ieee.numeric_std.all;
+
+entity M6522 is
+ port (
+
+ I_RS : in std_logic_vector(3 downto 0);
+ I_DATA : in std_logic_vector(7 downto 0);
+ O_DATA : out std_logic_vector(7 downto 0);
+ O_DATA_OE_L : out std_logic;
+
+ I_RW_L : in std_logic;
+ I_CS1 : in std_logic;
+ I_CS2_L : in std_logic;
+
+ O_IRQ_L : out std_logic; -- note, not open drain
+ -- port a
+ I_CA1 : in std_logic;
+ I_CA2 : in std_logic;
+ O_CA2 : out std_logic;
+ O_CA2_OE_L : out std_logic;
+
+ I_PA : in std_logic_vector(7 downto 0);
+ O_PA : out std_logic_vector(7 downto 0);
+ O_PA_OE_L : out std_logic_vector(7 downto 0);
+
+ -- port b
+ I_CB1 : in std_logic;
+ O_CB1 : out std_logic;
+ O_CB1_OE_L : out std_logic;
+
+ I_CB2 : in std_logic;
+ O_CB2 : out std_logic;
+ O_CB2_OE_L : out std_logic;
+
+ I_PB : in std_logic_vector(7 downto 0);
+ O_PB : out std_logic_vector(7 downto 0);
+ O_PB_OE_L : out std_logic_vector(7 downto 0);
+
+ I_P2_H : in std_logic; -- high for phase 2 clock ____----__
+ RESET_L : in std_logic;
+ ENA_4 : in std_logic; -- clk enable
+ CLK : in std_logic
+ );
+end;
+
+architecture RTL of M6522 is
+
+ signal phase : std_logic_vector(1 downto 0):="00";
+ signal p2_h_t1 : std_logic;
+ signal cs : std_logic;
+
+ -- registers
+ signal r_ddra : std_logic_vector(7 downto 0);
+ signal r_ora : std_logic_vector(7 downto 0);
+ signal r_ira : std_logic_vector(7 downto 0);
+
+ signal r_ddrb : std_logic_vector(7 downto 0);
+ signal r_orb : std_logic_vector(7 downto 0);
+ signal r_irb : std_logic_vector(7 downto 0);
+
+ signal r_t1l_l : std_logic_vector(7 downto 0);
+ signal r_t1l_h : std_logic_vector(7 downto 0);
+ signal r_t2l_l : std_logic_vector(7 downto 0);
+ signal r_t2l_h : std_logic_vector(7 downto 0); -- not in real chip
+ signal r_sr : std_logic_vector(7 downto 0);
+ signal r_acr : std_logic_vector(7 downto 0);
+ signal r_pcr : std_logic_vector(7 downto 0);
+ signal r_ifr : std_logic_vector(7 downto 0);
+ signal r_ier : std_logic_vector(6 downto 0);
+
+ signal sr_write_ena : boolean;
+ signal sr_read_ena : boolean;
+ signal ifr_write_ena : boolean;
+ signal ier_write_ena : boolean;
+ signal clear_irq : std_logic_vector(7 downto 0);
+ signal load_data : std_logic_vector(7 downto 0);
+
+ -- timer 1
+ signal t1c : std_logic_vector(15 downto 0) := (others => '1'); -- simulators may not catch up w/o init here...
+ signal t1c_active : boolean;
+ signal t1c_done : boolean;
+ signal t1_w_reset_int : boolean;
+ signal t1_r_reset_int : boolean;
+ signal t1_load_counter : boolean;
+ signal t1_reload_counter : boolean;
+ signal t1_toggle : std_logic;
+ signal t1_irq : std_logic := '0';
+
+ -- timer 2
+ signal t2c : std_logic_vector(15 downto 0) := (others => '1'); -- simulators may not catch up w/o init here...
+ signal t2c_active : boolean;
+ signal t2c_done : boolean;
+ signal t2_pb6 : std_logic;
+ signal t2_pb6_t1 : std_logic;
+ signal t2_w_reset_int : boolean;
+ signal t2_r_reset_int : boolean;
+ signal t2_load_counter : boolean;
+ signal t2_reload_counter : boolean;
+ signal t2_irq : std_logic := '0';
+ signal t2_sr_ena : boolean;
+
+ -- shift reg
+ signal sr_cnt : std_logic_vector(3 downto 0);
+ signal sr_cb1_oe_l : std_logic;
+ signal sr_cb1_out : std_logic;
+ signal sr_drive_cb2 : std_logic;
+ signal sr_strobe : std_logic;
+ signal sr_strobe_t1 : std_logic;
+ signal sr_strobe_falling : boolean;
+ signal sr_strobe_rising : boolean;
+ signal sr_irq : std_logic;
+ signal sr_out : std_logic;
+ signal sr_off_delay : std_logic;
+
+ -- io
+ signal w_orb_hs : std_logic;
+ signal w_ora_hs : std_logic;
+ signal r_irb_hs : std_logic;
+ signal r_ira_hs : std_logic;
+
+ signal ca_hs_sr : std_logic;
+ signal ca_hs_pulse : std_logic;
+ signal cb_hs_sr : std_logic;
+ signal cb_hs_pulse : std_logic;
+
+ signal cb1_in_mux : std_logic;
+ signal ca1_ip_reg : std_logic;
+ signal cb1_ip_reg : std_logic;
+ signal ca1_int : boolean;
+ signal cb1_int : boolean;
+ signal ca1_irq : std_logic;
+ signal cb1_irq : std_logic;
+
+ signal ca2_ip_reg : std_logic;
+ signal cb2_ip_reg : std_logic;
+ signal ca2_int : boolean;
+ signal cb2_int : boolean;
+ signal ca2_irq : std_logic;
+ signal cb2_irq : std_logic;
+
+ signal final_irq : std_logic;
+begin
+
+ p_phase : process
+ begin
+ -- internal clock phase
+ wait until rising_edge(CLK);
+ if (ENA_4 = '1') then
+ p2_h_t1 <= I_P2_H;
+ if (p2_h_t1 = '0') and (I_P2_H = '1') then
+ phase <= "11";
+ else
+ phase <= phase + "1";
+ end if;
+ end if;
+ end process;
+
+ p_cs : process(I_CS1, I_CS2_L, I_P2_H)
+ begin
+ cs <= '0';
+ if (I_CS1 = '1') and (I_CS2_L = '0') and (I_P2_H = '1') then
+ cs <= '1';
+ end if;
+ end process;
+
+ -- peripheral control reg (pcr)
+ -- 0 ca1 interrupt control (0 +ve edge, 1 -ve edge)
+ -- 3..1 ca2 operation
+ -- 000 input -ve edge
+ -- 001 independend interrupt input -ve edge
+ -- 010 input +ve edge
+ -- 011 independend interrupt input +ve edge
+ -- 100 handshake output
+ -- 101 pulse output
+ -- 110 low output
+ -- 111 high output
+ -- 7..4 as 3..0 for cb1,cb2
+
+ -- auxiliary control reg (acr)
+ -- 0 input latch PA (0 disable, 1 enable)
+ -- 1 input latch PB (0 disable, 1 enable)
+ -- 4..2 shift reg control
+ -- 000 disable
+ -- 001 shift in using t2
+ -- 010 shift in using o2
+ -- 011 shift in using ext clk
+ -- 100 shift out free running t2 rate
+ -- 101 shift out using t2
+ -- 101 shift out using o2
+ -- 101 shift out using ext clk
+ -- 5 t2 timer control (0 timed interrupt, 1 count down with pulses on pb6)
+ -- 7..6 t1 timer control
+ -- 00 timed interrupt each time t1 is loaded pb7 disable
+ -- 01 continuous interrupts pb7 disable
+ -- 00 timed interrupt each time t1 is loaded pb7 one shot output
+ -- 01 continuous interrupts pb7 square wave output
+ --
+
+ p_write_reg_reset : process(RESET_L, CLK)
+ begin
+ if (RESET_L = '0') then
+ r_ora <= x"00"; r_orb <= x"00";
+ r_ddra <= x"00"; r_ddrb <= x"00";
+ r_acr <= x"00"; r_pcr <= x"00";
+
+ w_orb_hs <= '0';
+ w_ora_hs <= '0';
+ elsif rising_edge(CLK) then
+ if (ENA_4 = '1') then
+ w_orb_hs <= '0';
+ w_ora_hs <= '0';
+ if (cs = '1') and (I_RW_L = '0') then
+ case I_RS is
+ when x"0" => r_orb <= I_DATA; w_orb_hs <= '1';
+ when x"1" => r_ora <= I_DATA; w_ora_hs <= '1';
+ when x"2" => r_ddrb <= I_DATA;
+ when x"3" => r_ddra <= I_DATA;
+
+ when x"B" => r_acr <= I_DATA;
+ when x"C" => r_pcr <= I_DATA;
+ when x"F" => r_ora <= I_DATA;
+
+ when others => null;
+ end case;
+ end if;
+
+ if r_acr(7) = '1' then
+ -- DMB: Forgetting to clear B7 broke Acornsoft Planetoid
+ if t1_load_counter then
+ r_orb(7) <= '0'; -- writing T1C-H resets bit 7
+ elsif t1_toggle = '1' then
+ r_orb(7) <= not r_orb(7); -- toggle
+ end if;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ p_write_reg : process (RESET_L, CLK) is
+ begin
+ if (RESET_L = '0') then
+ -- The spec says, this is not reset.
+ -- Fact is that the 1541 VIA1 timer won't work,
+ -- as the firmware ONLY sets the r_t1l_h latch!!!!
+ r_t1l_l <= (others => '0');
+ r_t1l_h <= (others => '0');
+ r_t2l_l <= (others => '0');
+ r_t2l_h <= (others => '0');
+ elsif rising_edge(CLK) then
+ if (ENA_4 = '1') then
+ t1_w_reset_int <= false;
+ t1_load_counter <= false;
+
+ t2_w_reset_int <= false;
+ t2_load_counter <= false;
+
+ load_data <= x"00";
+ sr_write_ena <= false;
+ ifr_write_ena <= false;
+ ier_write_ena <= false;
+
+ if (cs = '1') and (I_RW_L = '0') then
+ load_data <= I_DATA;
+ case I_RS is
+ when x"4" => r_t1l_l <= I_DATA;
+ when x"5" => r_t1l_h <= I_DATA; t1_w_reset_int <= true;
+ t1_load_counter <= true;
+
+ when x"6" => r_t1l_l <= I_DATA;
+ when x"7" => r_t1l_h <= I_DATA; t1_w_reset_int <= true;
+
+ when x"8" => r_t2l_l <= I_DATA;
+ when x"9" => r_t2l_h <= I_DATA; t2_w_reset_int <= true;
+ t2_load_counter <= true;
+
+ when x"A" => sr_write_ena <= true;
+ when x"D" => ifr_write_ena <= true;
+ when x"E" => ier_write_ena <= true;
+
+ when others => null;
+ end case;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ p_oe : process(cs, I_RW_L)
+ begin
+ O_DATA_OE_L <= '1';
+ if (cs = '1') and (I_RW_L = '1') then
+ O_DATA_OE_L <= '0';
+ end if;
+ end process;
+
+ p_read : process(cs, I_RW_L, I_RS, r_irb, r_ira, r_ddrb, r_ddra, t1c, r_t1l_l,
+ r_t1l_h, t2c, r_sr, r_acr, r_pcr, r_ifr, r_ier, r_orb)
+ begin
+ t1_r_reset_int <= false;
+ t2_r_reset_int <= false;
+ sr_read_ena <= false;
+ r_irb_hs <= '0';
+ r_ira_hs <= '0';
+ O_DATA <= x"00"; -- default
+ if (cs = '1') and (I_RW_L = '1') then
+ case I_RS is
+ --when x"0" => O_DATA <= r_irb; r_irb_hs <= '1';
+ -- fix from Mark McDougall, untested
+ when x"0" => O_DATA <= (r_irb and not r_ddrb) or (r_orb and r_ddrb); r_irb_hs <= '1';
+ when x"1" => O_DATA <= r_ira; r_ira_hs <= '1';
+ when x"2" => O_DATA <= r_ddrb;
+ when x"3" => O_DATA <= r_ddra;
+ when x"4" => O_DATA <= t1c( 7 downto 0); t1_r_reset_int <= true;
+ when x"5" => O_DATA <= t1c(15 downto 8);
+ when x"6" => O_DATA <= r_t1l_l;
+ when x"7" => O_DATA <= r_t1l_h;
+ when x"8" => O_DATA <= t2c( 7 downto 0); t2_r_reset_int <= true;
+ when x"9" => O_DATA <= t2c(15 downto 8);
+ when x"A" => O_DATA <= r_sr; sr_read_ena <= true;
+ when x"B" => O_DATA <= r_acr;
+ when x"C" => O_DATA <= r_pcr;
+ when x"D" => O_DATA <= r_ifr;
+ when x"E" => O_DATA <= ('0' & r_ier);
+ when x"F" => O_DATA <= r_ira;
+ when others => null;
+ end case;
+ end if;
+
+ end process;
+ --
+ -- IO
+ --
+ p_ca1_cb1_sel : process(sr_cb1_oe_l, sr_cb1_out, I_CB1)
+ begin
+ -- if the shift register is enabled, cb1 may be an output
+ -- in this case, we should listen to the CB1_OUT for the interrupt
+ if (sr_cb1_oe_l = '1') then
+ cb1_in_mux <= I_CB1;
+ else
+ cb1_in_mux <= sr_cb1_out;
+ end if;
+ end process;
+
+ p_ca1_cb1_int : process(r_pcr, ca1_ip_reg, I_CA1, cb1_ip_reg, cb1_in_mux)
+ begin
+ if (r_pcr(0) = '0') then -- ca1 control
+ -- negative edge
+ ca1_int <= (ca1_ip_reg = '1') and (I_CA1 = '0');
+ else
+ -- positive edge
+ ca1_int <= (ca1_ip_reg = '0') and (I_CA1 = '1');
+ end if;
+
+ if (r_pcr(4) = '0') then -- cb1 control
+ -- negative edge
+ cb1_int <= (cb1_ip_reg = '1') and (cb1_in_mux = '0');
+ else
+ -- positive edge
+ cb1_int <= (cb1_ip_reg = '0') and (cb1_in_mux = '1');
+ end if;
+ end process;
+
+ p_ca2_cb2_int : process(r_pcr, ca2_ip_reg, I_CA2, cb2_ip_reg, I_CB2)
+ begin
+ ca2_int <= false;
+ if (r_pcr(3) = '0') then -- ca2 input
+ if (r_pcr(2) = '0') then -- ca2 edge
+ -- negative edge
+ ca2_int <= (ca2_ip_reg = '1') and (I_CA2 = '0');
+ else
+ -- positive edge
+ ca2_int <= (ca2_ip_reg = '0') and (I_CA2 = '1');
+ end if;
+ end if;
+
+ cb2_int <= false;
+ if (r_pcr(7) = '0') then -- cb2 input
+ if (r_pcr(6) = '0') then -- cb2 edge
+ -- negative edge
+ cb2_int <= (cb2_ip_reg = '1') and (I_CB2 = '0');
+ else
+ -- positive edge
+ cb2_int <= (cb2_ip_reg = '0') and (I_CB2 = '1');
+ end if;
+ end if;
+ end process;
+
+ p_ca2_cb2 : process(RESET_L, CLK)
+ begin
+ if (RESET_L = '0') then
+ O_CA2 <= '0';
+ O_CA2_OE_L <= '1';
+ O_CB2 <= '0';
+ O_CB2_OE_L <= '1';
+
+ ca_hs_sr <= '0';
+ ca_hs_pulse <= '0';
+ cb_hs_sr <= '0';
+ cb_hs_pulse <= '0';
+ elsif rising_edge(CLK) then
+ if (ENA_4 = '1') then
+ -- ca
+ if (phase = "00") and ((w_ora_hs = '1') or (r_ira_hs = '1')) then
+ ca_hs_sr <= '1';
+ elsif ca1_int then
+ ca_hs_sr <= '0';
+ end if;
+
+ if (phase = "00") then
+ ca_hs_pulse <= w_ora_hs or r_ira_hs;
+ end if;
+
+ O_CA2_OE_L <= not r_pcr(3); -- ca2 output
+ case r_pcr(3 downto 1) is
+ when "000" => O_CA2 <= '0'; -- input
+ when "001" => O_CA2 <= '0'; -- input
+ when "010" => O_CA2 <= '0'; -- input
+ when "011" => O_CA2 <= '0'; -- input
+ when "100" => O_CA2 <= not (ca_hs_sr); -- handshake
+ when "101" => O_CA2 <= not (ca_hs_pulse); -- pulse
+ when "110" => O_CA2 <= '0'; -- low
+ when "111" => O_CA2 <= '1'; -- high
+ when others => null;
+ end case;
+
+ -- cb
+ if (phase = "00") and (w_orb_hs = '1') then
+ cb_hs_sr <= '1';
+ elsif cb1_int then
+ cb_hs_sr <= '0';
+ end if;
+
+ if (phase = "00") then
+ cb_hs_pulse <= w_orb_hs;
+ end if;
+
+ O_CB2_OE_L <= not (r_pcr(7) or sr_drive_cb2); -- cb2 output or serial
+ if (sr_drive_cb2 = '1') then -- serial output
+ O_CB2 <= sr_out;
+ else
+ case r_pcr(7 downto 5) is
+ when "000" => O_CB2 <= '0'; -- input
+ when "001" => O_CB2 <= '0'; -- input
+ when "010" => O_CB2 <= '0'; -- input
+ when "011" => O_CB2 <= '0'; -- input
+ when "100" => O_CB2 <= not (cb_hs_sr); -- handshake
+ when "101" => O_CB2 <= not (cb_hs_pulse); -- pulse
+ when "110" => O_CB2 <= '0'; -- low
+ when "111" => O_CB2 <= '1'; -- high
+ when others => null;
+ end case;
+ end if;
+ end if;
+ end if;
+ end process;
+ O_CB1 <= sr_cb1_out;
+ O_CB1_OE_L <= sr_cb1_oe_l;
+
+ p_ca_cb_irq : process(RESET_L, CLK)
+ begin
+ if (RESET_L = '0') then
+ ca1_irq <= '0';
+ ca2_irq <= '0';
+ cb1_irq <= '0';
+ cb2_irq <= '0';
+ elsif rising_edge(CLK) then
+ if (ENA_4 = '1') then
+ -- not pretty
+ if ca1_int then
+ ca1_irq <= '1';
+ elsif (r_ira_hs = '1') or (w_ora_hs = '1') or (clear_irq(1) = '1') then
+ ca1_irq <= '0';
+ end if;
+
+ if ca2_int then
+ ca2_irq <= '1';
+ else
+ if (((r_ira_hs = '1') or (w_ora_hs = '1')) and (r_pcr(1) = '0')) or
+ (clear_irq(0) = '1') then
+ ca2_irq <= '0';
+ end if;
+ end if;
+
+ if cb1_int then
+ cb1_irq <= '1';
+ elsif (r_irb_hs = '1') or (w_orb_hs = '1') or (clear_irq(4) = '1') then
+ cb1_irq <= '0';
+ end if;
+
+ if cb2_int then
+ cb2_irq <= '1';
+ else
+ if (((r_irb_hs = '1') or (w_orb_hs = '1')) and (r_pcr(5) = '0')) or
+ (clear_irq(3) = '1') then
+ cb2_irq <= '0';
+ end if;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ p_input_reg : process(RESET_L, CLK)
+ begin
+ if (RESET_L = '0') then
+ ca1_ip_reg <= '0';
+ cb1_ip_reg <= '0';
+
+ ca2_ip_reg <= '0';
+ cb2_ip_reg <= '0';
+
+ r_ira <= x"00";
+ r_irb <= x"00";
+
+ elsif rising_edge(CLK) then
+ if (ENA_4 = '1') then
+ -- we have a fast clock, so we can have input registers
+ ca1_ip_reg <= I_CA1;
+ cb1_ip_reg <= cb1_in_mux;
+
+ ca2_ip_reg <= I_CA2;
+ cb2_ip_reg <= I_CB2;
+
+ if (r_acr(0) = '0') then
+ r_ira <= I_PA;
+ else -- enable latching
+ if ca1_int then
+ r_ira <= I_PA;
+ end if;
+ end if;
+
+ if (r_acr(1) = '0') then
+ r_irb <= I_PB;
+ else -- enable latching
+ if cb1_int then
+ r_irb <= I_PB;
+ end if;
+ end if;
+ end if;
+ end if;
+ end process;
+
+
+ p_buffers : process(r_ddra, r_ora, r_ddrb, r_acr, r_orb)
+ begin
+ -- data direction reg (ddr) 0 = input, 1 = output
+ O_PA <= r_ora;
+ O_PA_OE_L <= not r_ddra;
+
+ if (r_acr(7) = '1') then -- not clear if r_ddrb(7) must be 1 as well
+ O_PB_OE_L(7) <= '0'; -- an output if under t1 control
+ else
+ O_PB_OE_L(7) <= not (r_ddrb(7));
+ end if;
+
+ O_PB_OE_L(6 downto 0) <= not r_ddrb(6 downto 0);
+ O_PB(7 downto 0) <= r_orb(7 downto 0);
+
+ end process;
+ --
+ -- Timer 1
+ --
+ p_timer1_done : process
+ variable done : boolean;
+ begin
+ wait until rising_edge(CLK);
+ if (ENA_4 = '1') then
+ done := (t1c = x"0000");
+ t1c_done <= done and (phase = "11");
+ if (phase = "11") then
+ t1_reload_counter <= done and (r_acr(6) = '1');
+ end if;
+ if t1_load_counter then -- done reset on load!
+ t1c_done <= false;
+ end if;
+ end if;
+ end process;
+
+ p_timer1 : process
+ begin
+ wait until rising_edge(CLK);
+ if (ENA_4 = '1') then
+ if t1_load_counter or (t1_reload_counter and phase = "11") then
+ t1c( 7 downto 0) <= r_t1l_l;
+ t1c(15 downto 8) <= r_t1l_h;
+ elsif (phase="11") then
+ t1c <= t1c - "1";
+ end if;
+
+ if t1_load_counter or t1_reload_counter then
+ t1c_active <= true;
+ elsif t1c_done then
+ t1c_active <= false;
+ end if;
+
+ t1_toggle <= '0';
+ if t1c_active and t1c_done then
+ t1_toggle <= '1';
+ t1_irq <= '1';
+ elsif t1_w_reset_int or t1_r_reset_int or (clear_irq(6) = '1') then
+ t1_irq <= '0';
+ end if;
+ if t1_load_counter then -- irq reset on load!
+ t1_irq <= '0';
+ end if;
+ end if;
+ end process;
+ --
+ -- Timer2
+ --
+ p_timer2_pb6_input : process
+ begin
+ wait until rising_edge(CLK);
+ if (ENA_4 = '1') then
+ if (phase = "01") then -- leading edge p2_h
+ t2_pb6 <= I_PB(6);
+ t2_pb6_t1 <= t2_pb6;
+ end if;
+ end if;
+ end process;
+
+ p_timer2_done : process
+ variable done : boolean;
+ begin
+ wait until rising_edge(CLK);
+ if (ENA_4 = '1') then
+ done := (t2c = x"0000");
+ t2c_done <= done and (phase = "11");
+ if (phase = "11") then
+ t2_reload_counter <= done;
+ end if;
+ if t2_load_counter then -- done reset on load!
+ t2c_done <= false;
+ end if;
+ end if;
+ end process;
+
+ p_timer2 : process
+ variable ena : boolean;
+ begin
+ wait until rising_edge(CLK);
+ if (ENA_4 = '1') then
+ if (r_acr(5) = '0') then
+ ena := true;
+ else
+ ena := (t2_pb6_t1 = '1') and (t2_pb6 = '0'); -- falling edge
+ end if;
+
+ if t2_load_counter or (t2_reload_counter and phase = "11") then
+ -- not sure if t2c_reload should be here. Does timer2 just continue to
+ -- count down, or is it reloaded ? Reloaded makes more sense if using
+ -- it to generate a clock for the shift register.
+ t2c( 7 downto 0) <= r_t2l_l;
+ t2c(15 downto 8) <= r_t2l_h;
+ else
+ if (phase="11") and ena then -- or count mode
+ t2c <= t2c - "1";
+ end if;
+ end if;
+
+ t2_sr_ena <= (t2c(7 downto 0) = x"00") and (phase = "11");
+
+ if t2_load_counter then
+ t2c_active <= true;
+ elsif t2c_done then
+ t2c_active <= false;
+ end if;
+
+ if t2c_active and t2c_done then
+ t2_irq <= '1';
+ elsif t2_w_reset_int or t2_r_reset_int or (clear_irq(5) = '1') then
+ t2_irq <= '0';
+ end if;
+ if t2_load_counter then -- irq reset on load!
+ t2_irq <= '0';
+ end if;
+ end if;
+ end process;
+ --
+ -- Shift Register
+ --
+ p_sr : process(RESET_L, CLK)
+ variable dir_out : std_logic;
+ variable ena : std_logic;
+ variable cb1_op : std_logic;
+ variable cb1_ip : std_logic;
+ variable use_t2 : std_logic;
+ variable free_run : std_logic;
+ variable sr_count_ena : boolean;
+ begin
+ if (RESET_L = '0') then
+ r_sr <= x"00";
+ sr_drive_cb2 <= '0';
+ sr_cb1_oe_l <= '1';
+ sr_cb1_out <= '0';
+ sr_strobe <= '1';
+ sr_cnt <= "0000";
+ sr_irq <= '0';
+ sr_out <= '1';
+ sr_off_delay <= '0';
+ elsif rising_edge(CLK) then
+ if (ENA_4 = '1') then
+ -- decode mode
+ dir_out := r_acr(4); -- output on cb2
+ cb1_op := '0';
+ cb1_ip := '0';
+ use_t2 := '0';
+ free_run := '0';
+
+ -- DMB: SR still runs even in disabled mode (on rising edge of CB1).
+ -- It just doesn't generate any interrupts.
+ -- Ref BBC micro advanced user guide p409
+
+ case r_acr(4 downto 2) is
+ -- DMB: in disabled mode, configure cb1 as an input
+ when "000" => ena := '0'; cb1_ip := '1';
+ when "001" => ena := '1'; cb1_op := '1'; use_t2 := '1';
+ when "010" => ena := '1'; cb1_op := '1';
+ when "011" => ena := '1'; cb1_ip := '1';
+ when "100" => ena := '1'; use_t2 := '1'; free_run := '1';
+ when "101" => ena := '1'; cb1_op := '1'; use_t2 := '1';
+ when "110" => ena := '1';
+ when "111" => ena := '1'; cb1_ip := '1';
+ when others => null;
+ end case;
+
+ -- clock select
+ -- DMB: in disabled mode, strobe from cb1
+ if (cb1_ip = '1') then
+ sr_strobe <= I_CB1;
+ else
+ if (sr_cnt(3) = '0') and (free_run = '0') then
+ sr_strobe <= '1';
+ else
+ if ((use_t2 = '1') and t2_sr_ena) or
+ ((use_t2 = '0') and (phase = "00")) then
+ sr_strobe <= not sr_strobe;
+ end if;
+ end if;
+ end if;
+
+ -- latch on rising edge, shift on falling edge
+ if sr_write_ena then
+ r_sr <= load_data;
+
+ else
+ -- DMB: allow shifting in all modes
+ if (dir_out = '0') then
+ -- input
+ if (sr_cnt(3) = '1') or (cb1_ip = '1') then
+ if sr_strobe_rising then
+ r_sr(0) <= I_CB2;
+ elsif sr_strobe_falling then
+ r_sr(7 downto 1) <= r_sr(6 downto 0);
+ end if;
+ end if;
+ sr_out <= '1';
+ else
+ -- output
+ if (sr_cnt(3) = '1') or (sr_off_delay = '1') or (cb1_ip = '1') or (free_run = '1') then
+ if sr_strobe_falling then
+ r_sr(7 downto 1) <= r_sr(6 downto 0);
+ r_sr(0) <= r_sr(7);
+ sr_out <= r_sr(7);
+ end if;
+ else
+ sr_out <= '1';
+ end if;
+ end if;
+ end if;
+
+ sr_count_ena := sr_strobe_rising;
+
+ -- DMB: reseting sr_count when not enabled cause the sr to
+ -- start running immediately it was enabled, which is incorrect
+ -- and broke the latest SmartSPI ROM on the BBC Micro
+ if ena = '1' and (sr_write_ena or sr_read_ena) then
+ -- some documentation says sr bit in IFR must be set as well ?
+ sr_cnt <= "1000";
+ elsif sr_count_ena and (sr_cnt(3) = '1') then
+ sr_cnt <= sr_cnt + "1";
+ end if;
+
+ if (phase = "00") then
+ sr_off_delay <= sr_cnt(3); -- give some hold time when shifting out
+ end if;
+
+ if sr_count_ena and (sr_cnt = "1111") and (ena = '1') and (free_run = '0') then
+ sr_irq <= '1';
+ elsif sr_write_ena or sr_read_ena or (clear_irq(2) = '1') then
+ sr_irq <= '0';
+ end if;
+
+ -- assign ops
+ sr_drive_cb2 <= dir_out;
+ sr_cb1_oe_l <= not cb1_op;
+ sr_cb1_out <= sr_strobe;
+ end if;
+ end if;
+ end process;
+
+ p_sr_strobe_rise_fall : process
+ begin
+ wait until rising_edge(CLK);
+ if (ENA_4 = '1') then
+ sr_strobe_t1 <= sr_strobe;
+ sr_strobe_rising <= (sr_strobe_t1 = '0') and (sr_strobe = '1');
+ sr_strobe_falling <= (sr_strobe_t1 = '1') and (sr_strobe = '0');
+ end if;
+ end process;
+ --
+ -- Interrupts
+ --
+ p_ier : process(RESET_L, CLK)
+ begin
+ if (RESET_L = '0') then
+ r_ier <= "0000000";
+ elsif rising_edge(CLK) then
+ if (ENA_4 = '1') then
+ if ier_write_ena then
+ if (load_data(7) = '1') then
+ -- set
+ r_ier <= r_ier or load_data(6 downto 0);
+ else
+ -- clear
+ r_ier <= r_ier and not load_data(6 downto 0);
+ end if;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ p_ifr : process(t1_irq, t2_irq, final_irq, ca1_irq, ca2_irq, sr_irq,
+ cb1_irq, cb2_irq)
+ begin
+ r_ifr(7) <= final_irq;
+ r_ifr(6) <= t1_irq;
+ r_ifr(5) <= t2_irq;
+ r_ifr(4) <= cb1_irq;
+ r_ifr(3) <= cb2_irq;
+ r_ifr(2) <= sr_irq;
+ r_ifr(1) <= ca1_irq;
+ r_ifr(0) <= ca2_irq;
+
+ O_IRQ_L <= not final_irq;
+ end process;
+
+ p_irq : process(RESET_L, CLK)
+ begin
+ if (RESET_L = '0') then
+ final_irq <= '0';
+ elsif rising_edge(CLK) then
+ if (ENA_4 = '1') then
+ if ((r_ifr(6 downto 0) and r_ier(6 downto 0)) = "0000000") then
+ final_irq <= '0'; -- no interrupts
+ else
+ final_irq <= '1';
+ end if;
+ end if;
+ end if;
+ end process;
+
+ p_clear_irq : process(ifr_write_ena, load_data)
+ begin
+ clear_irq <= x"00";
+ if ifr_write_ena then
+ clear_irq <= load_data;
+ end if;
+ end process;
+
+end architecture RTL;
diff --git a/common/IO/m6522a.vhd b/common/IO/m6522a.vhd
new file mode 100644
index 00000000..b650d971
--- /dev/null
+++ b/common/IO/m6522a.vhd
@@ -0,0 +1,903 @@
+--
+-- A simulation model of VIC20 hardware
+-- Copyright (c) MikeJ - March 2003
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS CODE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- You are responsible for any legal issues arising from your use of this code.
+--
+-- The latest version of this file can be found at: www.fpgaarcade.com
+--
+-- Email vic20@fpgaarcade.com
+--
+--
+-- Revision list
+--
+-- Arnim Laeuger, 12-Jan-2009:
+-- Ported to numeric_std and simulation fix for signal initializations
+-- version 002 fix from Mark McDougall, untested
+-- version 001 initial release
+-- not very sure about the shift register, documentation is a bit light.
+--
+-- DarFPGA, 08-fev-2018 - m6522a.vhd
+-- fixe Port_B(7) control with respect to T1 and ACR(7) for vectrex.
+--
+
+library ieee ;
+ use ieee.std_logic_1164.all ;
+ use ieee.numeric_std.all;
+
+entity M6522 is
+ port (
+
+ I_RS : in std_logic_vector(3 downto 0);
+ I_DATA : in std_logic_vector(7 downto 0);
+ O_DATA : out std_logic_vector(7 downto 0);
+ O_DATA_OE_L : out std_logic;
+
+ I_RW_L : in std_logic;
+ I_CS1 : in std_logic;
+ I_CS2_L : in std_logic;
+
+ O_IRQ_L : out std_logic; -- note, not open drain
+ -- port a
+ I_CA1 : in std_logic;
+ I_CA2 : in std_logic;
+ O_CA2 : out std_logic;
+ O_CA2_OE_L : out std_logic;
+
+ I_PA : in std_logic_vector(7 downto 0);
+ O_PA : out std_logic_vector(7 downto 0);
+ O_PA_OE_L : out std_logic_vector(7 downto 0);
+
+ -- port b
+ I_CB1 : in std_logic;
+ O_CB1 : out std_logic;
+ O_CB1_OE_L : out std_logic;
+
+ I_CB2 : in std_logic;
+ O_CB2 : out std_logic;
+ O_CB2_OE_L : out std_logic;
+
+ I_PB : in std_logic_vector(7 downto 0);
+ O_PB : out std_logic_vector(7 downto 0);
+ O_PB_OE_L : out std_logic_vector(7 downto 0);
+
+ I_P2_H : in std_logic; -- high for phase 2 clock ____----__
+ RESET_L : in std_logic;
+ ENA_4 : in std_logic; -- clk enable
+ CLK : in std_logic
+ );
+end;
+
+architecture RTL of M6522 is
+
+ signal phase : std_logic_vector(1 downto 0);
+ signal p2_h_t1 : std_logic;
+ signal cs : std_logic;
+
+ -- registers
+ signal r_ddra : std_logic_vector(7 downto 0);
+ signal r_ora : std_logic_vector(7 downto 0);
+ signal r_ira : std_logic_vector(7 downto 0);
+
+ signal r_ddrb : std_logic_vector(7 downto 0);
+ signal r_orb : std_logic_vector(7 downto 0);
+ signal r_orb_in : std_logic_vector(7 downto 0); -- DAR 2018-01-18
+ signal r_irb : std_logic_vector(7 downto 0);
+
+ signal r_t1l_l : std_logic_vector(7 downto 0) := (others => '0');
+ signal r_t1l_h : std_logic_vector(7 downto 0) := (others => '0');
+ signal r_t2l_l : std_logic_vector(7 downto 0) := (others => '0');
+ signal r_t2l_h : std_logic_vector(7 downto 0) := (others => '0'); -- not in real chip
+ signal r_sr : std_logic_vector(7 downto 0);
+ signal r_acr : std_logic_vector(7 downto 0);
+ signal r_pcr : std_logic_vector(7 downto 0);
+ signal r_ifr : std_logic_vector(7 downto 0);
+ signal r_ier : std_logic_vector(6 downto 0);
+
+ signal sr_write_ena : boolean;
+ signal sr_read_ena : boolean;
+ signal ifr_write_ena : boolean;
+ signal ier_write_ena : boolean;
+ signal clear_irq : std_logic_vector(7 downto 0);
+ signal load_data : std_logic_vector(7 downto 0);
+
+ -- timer 1
+ signal t1c : std_logic_vector(15 downto 0) := (others => '0');
+ signal t1c_active : boolean;
+ signal t1c_done : boolean;
+ signal t1_w_reset_int : boolean;
+ signal t1_r_reset_int : boolean;
+ signal t1_load_counter : boolean;
+ signal t1_reload_counter : boolean;
+ signal t1_toggle : std_logic;
+ signal t1_irq : std_logic := '0';
+
+ -- timer 2
+ signal t2c : std_logic_vector(15 downto 0) := (others => '0');
+ signal t2c_active : boolean;
+ signal t2c_done : boolean;
+ signal t2_pb6 : std_logic;
+ signal t2_pb6_t1 : std_logic;
+ signal t2_w_reset_int : boolean;
+ signal t2_r_reset_int : boolean;
+ signal t2_load_counter : boolean;
+ signal t2_reload_counter : boolean;
+ signal t2_irq : std_logic := '0';
+ signal t2_sr_ena : boolean;
+
+ -- shift reg
+ signal sr_cnt : std_logic_vector(3 downto 0);
+ signal sr_cb1_oe_l : std_logic;
+ signal sr_cb1_out : std_logic;
+ signal sr_drive_cb2 : std_logic;
+ signal sr_strobe : std_logic;
+ signal sr_strobe_t1 : std_logic;
+ signal sr_strobe_falling : boolean;
+ signal sr_strobe_rising : boolean;
+ signal sr_irq : std_logic;
+ signal sr_out : std_logic;
+ signal sr_off_delay : std_logic;
+
+ -- io
+ signal w_orb_hs : std_logic;
+ signal w_ora_hs : std_logic;
+ signal r_irb_hs : std_logic;
+ signal r_ira_hs : std_logic;
+
+ signal ca_hs_sr : std_logic;
+ signal ca_hs_pulse : std_logic;
+ signal cb_hs_sr : std_logic;
+ signal cb_hs_pulse : std_logic;
+
+ signal cb1_in_mux : std_logic;
+ signal ca1_ip_reg : std_logic;
+ signal cb1_ip_reg : std_logic;
+ signal ca1_int : boolean;
+ signal cb1_int : boolean;
+ signal ca1_irq : std_logic;
+ signal cb1_irq : std_logic;
+
+ signal ca2_ip_reg : std_logic;
+ signal cb2_ip_reg : std_logic;
+ signal ca2_int : boolean;
+ signal cb2_int : boolean;
+ signal ca2_irq : std_logic;
+ signal cb2_irq : std_logic;
+
+ signal final_irq : std_logic;
+begin
+
+ p_phase : process
+ begin
+ -- internal clock phase
+ wait until rising_edge(CLK);
+ if (ENA_4 = '1') then
+ p2_h_t1 <= I_P2_H;
+ if (p2_h_t1 = '0') and (I_P2_H = '1') then
+ phase <= "11";
+ else
+ phase <= std_logic_vector(unsigned(phase) + 1);
+ end if;
+ end if;
+ end process;
+
+ p_cs : process(I_CS1, I_CS2_L, I_P2_H)
+ begin
+ cs <= '0';
+ if (I_CS1 = '1') and (I_CS2_L = '0') and (I_P2_H = '1') then
+ cs <= '1';
+ end if;
+ end process;
+
+ -- peripheral control reg (pcr)
+ -- 0 ca1 interrupt control (0 +ve edge, 1 -ve edge)
+ -- 3..1 ca2 operation
+ -- 000 input -ve edge
+ -- 001 independend interrupt input -ve edge
+ -- 010 input +ve edge
+ -- 011 independend interrupt input +ve edge
+ -- 100 handshake output
+ -- 101 pulse output
+ -- 110 low output
+ -- 111 high output
+ -- 7..4 as 3..0 for cb1,cb2
+
+ -- auxiliary control reg (acr)
+ -- 0 input latch PA (0 disable, 1 enable)
+ -- 1 input latch PB (0 disable, 1 enable)
+ -- 4..2 shift reg control
+ -- 000 disable
+ -- 001 shift in using t2
+ -- 010 shift in using o2
+ -- 011 shift in using ext clk
+ -- 100 shift out free running t2 rate
+ -- 101 shift out using t2
+ -- 101 shift out using o2
+ -- 101 shift out using ext clk
+ -- 5 t2 timer control (0 timed interrupt, 1 count down with pulses on pb6)
+ -- 7..6 t1 timer control
+ -- 00 timed interrupt each time t1 is loaded pb7 disable
+ -- 01 continuous interrupts pb7 disable
+ -- 00 timed interrupt each time t1 is loaded pb7 one shot output
+ -- 01 continuous interrupts pb7 square wave output
+ --
+
+ p_write_reg_reset : process(RESET_L, CLK)
+ begin
+ if (RESET_L = '0') then
+ r_ora <= x"00"; r_orb <= x"00";
+ r_ddra <= x"00"; r_ddrb <= x"00";
+ r_acr <= x"00"; r_pcr <= x"00";
+
+ w_orb_hs <= '0';
+ w_ora_hs <= '0';
+ elsif rising_edge(CLK) then
+ if (ENA_4 = '1') then
+ w_orb_hs <= '0';
+ w_ora_hs <= '0';
+ if (cs = '1') and (I_RW_L = '0') then
+ case I_RS is
+ when x"0" => r_orb <= I_DATA; w_orb_hs <= '1';
+ r_orb_in <= I_DATA; -- DAR 2018-01-18
+ when x"1" => r_ora <= I_DATA; w_ora_hs <= '1';
+ when x"2" => r_ddrb <= I_DATA;
+ when x"3" => r_ddra <= I_DATA;
+ when x"B" => r_acr <= I_DATA;
+ when x"C" => r_pcr <= I_DATA;
+ when x"F" => r_ora <= I_DATA;
+
+ when others => null;
+ end case;
+ end if;
+
+ if r_acr(7) = '1' then -- DAR 2018-01-18
+ if t1c_active = true then
+ r_orb(7) <= '0'; -- DAR 2018-01-18
+ else
+ r_orb(7) <= '1'; -- DAR 2018-01-18
+ end if;
+ else
+ r_orb(7) <= r_orb_in(7); -- DAR 2018-01-18
+ end if;
+
+ end if;
+ end if;
+ end process;
+
+ p_write_reg : process
+ begin
+ wait until rising_edge(CLK);
+ if (ENA_4 = '1') then
+ t1_w_reset_int <= false;
+ t1_load_counter <= false;
+
+ t2_w_reset_int <= false;
+ t2_load_counter <= false;
+
+ load_data <= x"00";
+ sr_write_ena <= false;
+ ifr_write_ena <= false;
+ ier_write_ena <= false;
+
+ if (cs = '1') and (I_RW_L = '0') then
+ load_data <= I_DATA;
+ case I_RS is
+ when x"4" => r_t1l_l <= I_DATA;
+ when x"5" => r_t1l_h <= I_DATA; t1_w_reset_int <= true;
+ t1_load_counter <= true;
+
+ when x"6" => r_t1l_l <= I_DATA;
+ when x"7" => r_t1l_h <= I_DATA; t1_w_reset_int <= true;
+
+ when x"8" => r_t2l_l <= I_DATA;
+ when x"9" => r_t2l_h <= I_DATA; t2_w_reset_int <= true;
+ t2_load_counter <= true;
+
+ when x"A" => sr_write_ena <= true;
+ when x"D" => ifr_write_ena <= true;
+ when x"E" => ier_write_ena <= true;
+
+ when others => null;
+ end case;
+ end if;
+ end if;
+ end process;
+
+ p_oe : process(cs, I_RW_L)
+ begin
+ O_DATA_OE_L <= '1';
+ if (cs = '1') and (I_RW_L = '1') then
+ O_DATA_OE_L <= '0';
+ end if;
+ end process;
+
+ p_read : process(cs, I_RW_L, I_RS, r_irb, r_ira, r_ddrb, r_ddra, t1c, r_t1l_l,
+ r_t1l_h, t2c, r_sr, r_acr, r_pcr, r_ifr, r_ier, r_orb)
+ begin
+ t1_r_reset_int <= false;
+ t2_r_reset_int <= false;
+ sr_read_ena <= false;
+ r_irb_hs <= '0';
+ r_ira_hs <= '0';
+ O_DATA <= x"00"; -- default
+ if (cs = '1') and (I_RW_L = '1') then
+ case I_RS is
+ --when x"0" => O_DATA <= r_irb; r_irb_hs <= '1';
+ -- fix from Mark McDougall, untested
+ when x"0" => O_DATA <= (r_irb and not r_ddrb) or (r_orb and r_ddrb); r_irb_hs <= '1';
+ --when x"1" => O_DATA <= r_ira; r_ira_hs <= '1';
+ when x"1" => O_DATA <= (r_ira and not r_ddra) or (r_ora and r_ddra); r_ira_hs <= '1';
+ when x"2" => O_DATA <= r_ddrb;
+ when x"3" => O_DATA <= r_ddra;
+ when x"4" => O_DATA <= t1c( 7 downto 0); t1_r_reset_int <= true;
+ when x"5" => O_DATA <= t1c(15 downto 8);
+ when x"6" => O_DATA <= r_t1l_l;
+ when x"7" => O_DATA <= r_t1l_h;
+ when x"8" => O_DATA <= t2c( 7 downto 0); t2_r_reset_int <= true;
+ when x"9" => O_DATA <= t2c(15 downto 8);
+ when x"A" => O_DATA <= r_sr; sr_read_ena <= true;
+ when x"B" => O_DATA <= r_acr;
+ when x"C" => O_DATA <= r_pcr;
+ when x"D" => O_DATA <= r_ifr;
+ when x"E" => O_DATA <= ('0' & r_ier);
+ when x"F" => O_DATA <= r_ira;
+ when others => null;
+ end case;
+ end if;
+
+ end process;
+ --
+ -- IO
+ --
+ p_ca1_cb1_sel : process(sr_cb1_oe_l, sr_cb1_out, I_CB1)
+ begin
+ -- if the shift register is enabled, cb1 may be an output
+ -- in this case, we should listen to the CB1_OUT for the interrupt
+ if (sr_cb1_oe_l = '1') then
+ cb1_in_mux <= I_CB1;
+ else
+ cb1_in_mux <= sr_cb1_out;
+ end if;
+ end process;
+
+ p_ca1_cb1_int : process(r_pcr, ca1_ip_reg, I_CA1, cb1_ip_reg, cb1_in_mux)
+ begin
+ if (r_pcr(0) = '0') then -- ca1 control
+ -- negative edge
+ ca1_int <= (ca1_ip_reg = '1') and (I_CA1 = '0');
+ else
+ -- positive edge
+ ca1_int <= (ca1_ip_reg = '0') and (I_CA1 = '1');
+ end if;
+
+ if (r_pcr(4) = '0') then -- cb1 control
+ -- negative edge
+ cb1_int <= (cb1_ip_reg = '1') and (cb1_in_mux = '0');
+ else
+ -- positive edge
+ cb1_int <= (cb1_ip_reg = '0') and (cb1_in_mux = '1');
+ end if;
+ end process;
+
+ p_ca2_cb2_int : process(r_pcr, ca2_ip_reg, I_CA2, cb2_ip_reg, I_CB2)
+ begin
+ ca2_int <= false;
+ if (r_pcr(3) = '0') then -- ca2 input
+ if (r_pcr(2) = '0') then -- ca2 edge
+ -- negative edge
+ ca2_int <= (ca2_ip_reg = '1') and (I_CA2 = '0');
+ else
+ -- positive edge
+ ca2_int <= (ca2_ip_reg = '0') and (I_CA2 = '1');
+ end if;
+ end if;
+
+ cb2_int <= false;
+ if (r_pcr(7) = '0') then -- cb2 input
+ if (r_pcr(6) = '0') then -- cb2 edge
+ -- negative edge
+ cb2_int <= (cb2_ip_reg = '1') and (I_CB2 = '0');
+ else
+ -- positive edge
+ cb2_int <= (cb2_ip_reg = '0') and (I_CB2 = '1');
+ end if;
+ end if;
+ end process;
+
+ p_ca2_cb2 : process(RESET_L, CLK)
+ begin
+ if (RESET_L = '0') then
+ O_CA2 <= '0';
+ O_CA2_OE_L <= '1';
+ O_CB2 <= '0';
+ O_CB2_OE_L <= '1';
+
+ ca_hs_sr <= '0';
+ ca_hs_pulse <= '0';
+ cb_hs_sr <= '0';
+ cb_hs_pulse <= '0';
+ elsif rising_edge(CLK) then
+ if (ENA_4 = '1') then
+ -- ca
+ if (phase = "00") and ((w_ora_hs = '1') or (r_ira_hs = '1')) then
+ ca_hs_sr <= '1';
+ elsif ca1_int then
+ ca_hs_sr <= '0';
+ end if;
+
+ if (phase = "00") then
+ ca_hs_pulse <= w_ora_hs or r_ira_hs;
+ end if;
+
+ O_CA2_OE_L <= not r_pcr(3); -- ca2 output
+ case r_pcr(3 downto 1) is
+ when "000" => O_CA2 <= '0'; -- input
+ when "001" => O_CA2 <= '0'; -- input
+ when "010" => O_CA2 <= '0'; -- input
+ when "011" => O_CA2 <= '0'; -- input
+ when "100" => O_CA2 <= not (ca_hs_sr); -- handshake
+ when "101" => O_CA2 <= not (ca_hs_pulse); -- pulse
+ when "110" => O_CA2 <= '0'; -- low
+ when "111" => O_CA2 <= '1'; -- high
+ when others => null;
+ end case;
+
+ -- cb
+ if (phase = "00") and (w_orb_hs = '1') then
+ cb_hs_sr <= '1';
+ elsif cb1_int then
+ cb_hs_sr <= '0';
+ end if;
+
+ if (phase = "00") then
+ cb_hs_pulse <= w_orb_hs;
+ end if;
+
+ O_CB2_OE_L <= not (r_pcr(7) or sr_drive_cb2); -- cb2 output or serial
+ if (sr_drive_cb2 = '1') then -- serial output
+ O_CB2 <= sr_out;
+ else
+ case r_pcr(7 downto 5) is
+ when "000" => O_CB2 <= '0'; -- input
+ when "001" => O_CB2 <= '0'; -- input
+ when "010" => O_CB2 <= '0'; -- input
+ when "011" => O_CB2 <= '0'; -- input
+ when "100" => O_CB2 <= not (cb_hs_sr); -- handshake
+ when "101" => O_CB2 <= not (cb_hs_pulse); -- pulse
+ when "110" => O_CB2 <= '0'; -- low
+ when "111" => O_CB2 <= '1'; -- high
+ when others => null;
+ end case;
+ end if;
+ end if;
+ end if;
+ end process;
+ O_CB1 <= sr_cb1_out;
+ O_CB1_OE_L <= sr_cb1_oe_l;
+
+ p_ca_cb_irq : process(RESET_L, CLK)
+ begin
+ if (RESET_L = '0') then
+ ca1_irq <= '0';
+ ca2_irq <= '0';
+ cb1_irq <= '0';
+ cb2_irq <= '0';
+ elsif rising_edge(CLK) then
+ if (ENA_4 = '1') then
+ -- not pretty
+ if ca1_int then
+ ca1_irq <= '1';
+ elsif (r_ira_hs = '1') or (w_ora_hs = '1') or (clear_irq(1) = '1') then
+ ca1_irq <= '0';
+ end if;
+
+ if ca2_int then
+ ca2_irq <= '1';
+ else
+ if (((r_ira_hs = '1') or (w_ora_hs = '1')) and (r_pcr(1) = '0')) or
+ (clear_irq(0) = '1') then
+ ca2_irq <= '0';
+ end if;
+ end if;
+
+ if cb1_int then
+ cb1_irq <= '1';
+ elsif (r_irb_hs = '1') or (w_orb_hs = '1') or (clear_irq(4) = '1') then
+ cb1_irq <= '0';
+ end if;
+
+ if cb2_int then
+ cb2_irq <= '1';
+ else
+ if (((r_irb_hs = '1') or (w_orb_hs = '1')) and (r_pcr(5) = '0')) or
+ (clear_irq(3) = '1') then
+ cb2_irq <= '0';
+ end if;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ p_input_reg : process(RESET_L, CLK)
+ begin
+ if (RESET_L = '0') then
+ ca1_ip_reg <= '0';
+ cb1_ip_reg <= '0';
+
+ ca2_ip_reg <= '0';
+ cb2_ip_reg <= '0';
+
+ r_ira <= x"00";
+ r_irb <= x"00";
+
+ elsif rising_edge(CLK) then
+ if (ENA_4 = '1') then
+ -- we have a fast clock, so we can have input registers
+ ca1_ip_reg <= I_CA1;
+ cb1_ip_reg <= cb1_in_mux;
+
+ ca2_ip_reg <= I_CA2;
+ cb2_ip_reg <= I_CB2;
+
+ if (r_acr(0) = '0') then
+ r_ira <= I_PA;
+ else -- enable latching
+ if ca1_int then
+ r_ira <= I_PA;
+ end if;
+ end if;
+
+ if (r_acr(1) = '0') then
+ r_irb <= I_PB;
+ else -- enable latching
+ if cb1_int then
+ r_irb <= I_PB;
+ end if;
+ end if;
+ end if;
+ end if;
+ end process;
+
+
+ p_buffers : process(r_ddra, r_ora, r_ddrb, r_acr, r_orb)
+ begin
+ -- data direction reg (ddr) 0 = input, 1 = output
+ O_PA <= r_ora;
+ O_PA_OE_L <= not r_ddra;
+
+ if (r_acr(7) = '1') then -- not clear if r_ddrb(7) must be 1 as well
+ O_PB_OE_L(7) <= '0'; -- an output if under t1 control
+ else
+ O_PB_OE_L(7) <= not (r_ddrb(7));
+ end if;
+
+ O_PB_OE_L(6 downto 0) <= not r_ddrb(6 downto 0);
+ O_PB(7 downto 0) <= r_orb(7 downto 0);
+
+ end process;
+ --
+ -- Timer 1
+ --
+ p_timer1_done : process
+ variable done : boolean;
+ begin
+ wait until rising_edge(CLK);
+ if (ENA_4 = '1') then
+ done := (t1c = x"0000");
+ t1c_done <= done and (phase = "11");
+ if (phase = "11") then
+ t1_reload_counter <= done and (r_acr(6) = '1');
+ end if;
+ end if;
+ end process;
+
+ p_timer1 : process
+ begin
+ wait until rising_edge(CLK);
+ if (ENA_4 = '1') then
+ if t1_load_counter or (t1_reload_counter and phase = "11") then
+ t1c( 7 downto 0) <= r_t1l_l;
+ t1c(15 downto 8) <= r_t1l_h;
+ elsif (phase="11") then
+ t1c <= std_logic_vector(unsigned(t1c) - 1);
+ end if;
+
+ if t1_load_counter or t1_reload_counter then
+ t1c_active <= true;
+ elsif t1c_done then
+ t1c_active <= false;
+ end if;
+
+ t1_toggle <= '0';
+ if t1c_active and t1c_done then
+ t1_toggle <= '1';
+ t1_irq <= '1';
+ elsif t1_w_reset_int or t1_r_reset_int or (clear_irq(6) = '1') then
+ t1_irq <= '0';
+ end if;
+ end if;
+ end process;
+ --
+ -- Timer2
+ --
+ p_timer2_pb6_input : process
+ begin
+ wait until rising_edge(CLK);
+ if (ENA_4 = '1') then
+ if (phase = "01") then -- leading edge p2_h
+ t2_pb6 <= I_PB(6);
+ t2_pb6_t1 <= t2_pb6;
+ end if;
+ end if;
+ end process;
+
+ p_timer2_done : process
+ variable done : boolean;
+ begin
+ wait until rising_edge(CLK);
+ if (ENA_4 = '1') then
+ done := (t2c = x"0000");
+ t2c_done <= done and (phase = "11");
+ if (phase = "11") then
+ t2_reload_counter <= done;
+ end if;
+ end if;
+ end process;
+
+ p_timer2 : process
+ variable ena : boolean;
+ begin
+ wait until rising_edge(CLK);
+ if (ENA_4 = '1') then
+ if (r_acr(5) = '0') then
+ ena := true;
+ else
+ ena := (t2_pb6_t1 = '1') and (t2_pb6 = '0'); -- falling edge
+ end if;
+
+ if t2_load_counter or (t2_reload_counter and phase = "11") then
+ -- not sure if t2c_reload should be here. Does timer2 just continue to
+ -- count down, or is it reloaded ? Reloaded makes more sense if using
+ -- it to generate a clock for the shift register.
+ t2c( 7 downto 0) <= r_t2l_l;
+ t2c(15 downto 8) <= r_t2l_h;
+ else
+ if (phase="11") and ena then -- or count mode
+ t2c <= std_logic_vector(unsigned(t2c) - 1);
+ end if;
+ end if;
+
+ t2_sr_ena <= (t2c(7 downto 0) = x"00") and (phase = "11");
+
+ if t2_load_counter then
+ t2c_active <= true;
+ elsif t2c_done then
+ t2c_active <= false;
+ end if;
+
+
+ if t2c_active and t2c_done then
+ t2_irq <= '1';
+ elsif t2_w_reset_int or t2_r_reset_int or (clear_irq(5) = '1') then
+ t2_irq <= '0';
+ end if;
+ end if;
+ end process;
+ --
+ -- Shift Register
+ --
+ p_sr : process(RESET_L, CLK)
+ variable dir_out : std_logic;
+ variable ena : std_logic;
+ variable cb1_op : std_logic;
+ variable cb1_ip : std_logic;
+ variable use_t2 : std_logic;
+ variable free_run : std_logic;
+ variable sr_count_ena : boolean;
+ begin
+ if (RESET_L = '0') then
+ r_sr <= x"00";
+ sr_drive_cb2 <= '0';
+ sr_cb1_oe_l <= '1';
+ sr_cb1_out <= '0';
+ sr_strobe <= '1';
+ sr_cnt <= "0000";
+ sr_irq <= '0';
+ sr_out <= '1';
+ sr_off_delay <= '0';
+ elsif rising_edge(CLK) then
+ if (ENA_4 = '1') then
+ -- decode mode
+ dir_out := r_acr(4); -- output on cb2
+ cb1_op := '0';
+ cb1_ip := '0';
+ use_t2 := '0';
+ free_run := '0';
+
+ case r_acr(4 downto 2) is
+ when "000" => ena := '0';
+ when "001" => ena := '1'; cb1_op := '1'; use_t2 := '1';
+ when "010" => ena := '1'; cb1_op := '1';
+ when "011" => ena := '1'; cb1_ip := '1';
+ when "100" => ena := '1'; use_t2 := '1'; free_run := '1';
+ when "101" => ena := '1'; cb1_op := '1'; use_t2 := '1';
+-- when "110" => ena := '1'; free_run := '1'; -- hack
+ when "110" => ena := '1'; -- DAR 2018_01_24
+ when "111" => ena := '1'; cb1_ip := '1';
+ when others => null;
+ end case;
+
+ -- clock select
+ if (ena = '0') then
+ sr_strobe <= '1';
+ else
+ if (cb1_ip = '1') then
+ sr_strobe <= I_CB1;
+ else
+ if (sr_cnt(3) = '0') and (free_run = '0') then
+ sr_strobe <= '1';
+ else
+ if ((use_t2 = '1') and t2_sr_ena) or
+ ((use_t2 = '0') and (phase = "00")) then
+ sr_strobe <= not sr_strobe;
+ end if;
+ end if;
+ end if;
+ end if;
+
+ -- latch on rising edge, shift on falling edge
+ if sr_write_ena then
+ r_sr <= load_data;
+ elsif (ena = '1') then -- use shift reg
+
+ if (dir_out = '0') then
+ -- input
+ if (sr_cnt(3) = '1') or (cb1_ip = '1') then
+ if sr_strobe_rising then
+ r_sr(0) <= I_CB2;
+ elsif sr_strobe_falling then
+ r_sr(7 downto 1) <= r_sr(6 downto 0);
+ end if;
+ end if;
+ sr_out <= '1';
+ else
+ -- output
+ if (sr_cnt(3) = '1') or (sr_off_delay = '1') or (cb1_ip = '1') or (free_run = '1') then
+ if sr_strobe_falling then
+ r_sr(7 downto 1) <= r_sr(6 downto 0);
+ r_sr(0) <= r_sr(7);
+ sr_out <= r_sr(7);
+ end if;
+ else
+-- sr_out <= '1';
+ sr_out <= r_sr(7); -- DAR 2018-01-25
+ end if;
+ end if;
+ end if;
+
+ sr_count_ena := sr_strobe_rising;
+
+ if sr_write_ena or sr_read_ena then
+ -- some documentation says sr bit in IFR must be set as well ?
+-- sr_cnt <= "1000";
+ sr_cnt <= "1001"; -- DAR 2018-01-25
+ elsif sr_count_ena and (sr_cnt(3) = '1') then
+ sr_cnt <= std_logic_vector(unsigned(sr_cnt) + 1);
+ end if;
+
+ if (phase = "00") then
+ sr_off_delay <= sr_cnt(3); -- give some hold time when shifting out
+ end if;
+
+ if sr_count_ena and (sr_cnt = "1111") and (ena = '1') and (free_run = '0') then
+ sr_irq <= '1';
+ elsif sr_write_ena or sr_read_ena or (clear_irq(2) = '1') then
+ sr_irq <= '0';
+ end if;
+
+ -- assign ops
+ sr_drive_cb2 <= dir_out;
+ sr_cb1_oe_l <= not cb1_op;
+ sr_cb1_out <= sr_strobe;
+ end if;
+ end if;
+ end process;
+
+ p_sr_strobe_rise_fall : process
+ begin
+ wait until rising_edge(CLK);
+ if (ENA_4 = '1') then
+ sr_strobe_t1 <= sr_strobe;
+ sr_strobe_rising <= (sr_strobe_t1 = '0') and (sr_strobe = '1');
+ sr_strobe_falling <= (sr_strobe_t1 = '1') and (sr_strobe = '0');
+ end if;
+ end process;
+ --
+ -- Interrupts
+ --
+ p_ier : process(RESET_L, CLK)
+ begin
+ if (RESET_L = '0') then
+ r_ier <= "0000000";
+ elsif rising_edge(CLK) then
+ if (ENA_4 = '1') then
+ if ier_write_ena then
+ if (load_data(7) = '1') then
+ -- set
+ r_ier <= r_ier or load_data(6 downto 0);
+ else
+ -- clear
+ r_ier <= r_ier and not load_data(6 downto 0);
+ end if;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ p_ifr : process(t1_irq, t2_irq, final_irq, ca1_irq, ca2_irq, sr_irq,
+ cb1_irq, cb2_irq)
+ begin
+ r_ifr(7) <= final_irq;
+ r_ifr(6) <= t1_irq;
+ r_ifr(5) <= t2_irq;
+ r_ifr(4) <= cb1_irq;
+ r_ifr(3) <= cb2_irq;
+ r_ifr(2) <= sr_irq;
+ r_ifr(1) <= ca1_irq;
+ r_ifr(0) <= ca2_irq;
+
+ O_IRQ_L <= not final_irq;
+ end process;
+
+ p_irq : process(RESET_L, CLK)
+ begin
+ if (RESET_L = '0') then
+ final_irq <= '0';
+ elsif rising_edge(CLK) then
+ if (ENA_4 = '1') then
+ if ((r_ifr(6 downto 0) and r_ier(6 downto 0)) = "0000000") then
+ final_irq <= '0'; -- no interrupts
+ else
+ final_irq <= '1';
+ end if;
+ end if;
+ end if;
+ end process;
+
+ p_clear_irq : process(ifr_write_ena, load_data)
+ begin
+ clear_irq <= x"00";
+ if ifr_write_ena then
+ clear_irq <= load_data;
+ end if;
+ end process;
+
+end architecture RTL;
diff --git a/common/IO/mos6529.v b/common/IO/mos6529.v
new file mode 100644
index 00000000..8b7a7889
--- /dev/null
+++ b/common/IO/mos6529.v
@@ -0,0 +1,54 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Copyright 2013-2016 Istvan Hegedus
+//
+// FPGATED 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.
+//
+// FPGATED 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 .
+//
+// Create Date: 09:08:17 12/17/2015
+// Design Name: FPGATED
+// Module Name: mos6529.v
+// Description: MOS 6529 IC emulation.
+//
+// Revision:
+// 0.1 first release
+// 1.0 chip read bug fixed 5/04/2016
+//
+// Additional Comments:
+// CS signal is high active while in real IC it is low active.
+//////////////////////////////////////////////////////////////////////////////////
+
+module mos6529(
+ input clk,
+ input [7:0] data_in,
+ output wire [7:0] data_out,
+ input [7:0] port_in,
+ output wire [7:0] port_out,
+ input rw,
+ input cs
+ );
+
+reg [7:0] iodata=0;
+
+assign port_out=iodata;
+assign data_out=(cs & rw)?iodata:8'hff;
+
+always @(posedge clk)
+ begin
+ if(cs)
+ if(rw)
+ iodata<=port_in;
+ else
+ iodata<=data_in;
+ end
+endmodule
diff --git a/common/IO/pia6520.v b/common/IO/pia6520.v
new file mode 100644
index 00000000..ae4770e6
--- /dev/null
+++ b/common/IO/pia6520.v
@@ -0,0 +1,230 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////
+//
+// Engineer: Thomas Skibo
+//
+// Create Date: Sep 24, 2011
+//
+// Module Name: pia6520
+//
+// Description:
+//
+// A simple implementation of the 6520 Peripheral Interface Adapter (PIA).
+// Tri-state lines aren't used. Instead, All PIA I/O signals have
+// seperate "in" and "out" signals. Wire or ignore appropriately.
+//
+/////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2011, Thomas Skibo. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * The names of contributors may not be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL Thomas Skibo OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+module pia6520
+(
+ output reg [7:0] data_out, // cpu interface
+ input [7:0] data_in,
+ input [1:0] addr,
+ input strobe,
+ input we,
+
+ output irq,
+
+ output reg [7:0] porta_out,
+ input [7:0] porta_in,
+ output reg [7:0] portb_out,
+ input [7:0] portb_in,
+
+ input ca1_in,
+ output reg ca2_out,
+ input ca2_in,
+ input cb1_in,
+ output reg cb2_out,
+ input cb2_in,
+
+ input clk,
+ input reset
+);
+
+reg [7:0] ddra;
+reg [5:0] cra;
+reg irqa1;
+reg irqa2;
+
+reg [7:0] ddrb;
+reg [5:0] crb;
+reg irqb1;
+reg irqb2;
+
+// Register address offsets
+parameter [1:0]
+ ADDR_PORTA = 2'b00,
+ ADDR_CRA = 2'b01,
+ ADDR_PORTB = 2'b10,
+ ADDR_CRB = 2'b11;
+
+wire wr_strobe = strobe && we;
+wire rd_strobe = strobe && !we;
+wire porta_rd_strobe = rd_strobe && addr == ADDR_PORTA;
+wire portb_rd_strobe = rd_strobe && addr == ADDR_PORTB;
+wire portb_wr_strobe = wr_strobe && addr == ADDR_PORTB;
+
+// Implement CRA[5:0]
+always @(posedge clk) begin
+ if (reset) cra <= 6'b00_0000;
+ else if (wr_strobe && addr == ADDR_CRA) cra <= data_in[5:0];
+end
+
+// Implement CRB[5:0]
+always @(posedge clk) begin
+ if (reset) crb <= 6'b00_0000;
+ else if (wr_strobe && addr == ADDR_CRB) crb <= data_in[5:0];
+end
+
+// Implement PORTA (out)
+always @(posedge clk) begin
+ if (reset) porta_out <= 8'h00;
+ else if (wr_strobe && addr == ADDR_PORTA && cra[2]) porta_out <= data_in;
+end
+
+// Implement DDRA
+always @(posedge clk) begin
+ if (reset) ddra <= 8'h00;
+ else if (wr_strobe && addr == ADDR_PORTA && !cra[2]) ddra <= data_in;
+end
+
+// Implement PORTB (out)
+always @(posedge clk) begin
+ if (reset) portb_out <= 8'h00;
+ else if (wr_strobe && addr == ADDR_PORTB && crb[2]) portb_out <= data_in;
+end
+
+// Implement DDRB
+always @(posedge clk) begin
+ if (reset) ddrb <= 8'h00;
+ else if (wr_strobe && addr == ADDR_PORTB && !crb[2]) ddrb <= data_in;
+end
+
+////////////////////////////////////////////////////////
+// IRQA logic
+
+// register ca1_in and ca2_in to detect transitions.
+reg ca1_in_1;
+reg ca2_in_1;
+always @(posedge clk) begin
+ ca1_in_1 <= ca1_in;
+ ca2_in_1 <= ca2_in;
+end
+
+// detect "active" transitions
+wire ca1_act_trans = ((ca1_in && !ca1_in_1 && cra[1]) || (!ca1_in && ca1_in_1 && !cra[1]));
+wire ca2_act_trans = ((ca2_in && !ca2_in_1 && cra[4]) || (!ca2_in && ca2_in_1 && !cra[4]));
+
+// IRQA1
+always @(posedge clk) begin
+ if (reset || (porta_rd_strobe && !ca1_act_trans)) irqa1 <= 1'b0;
+ else if (ca1_act_trans) irqa1 <= 1'b1;
+end
+
+// IRQA2
+always @(posedge clk) begin
+ if (reset || (porta_rd_strobe && !ca2_act_trans)) irqa2 <= 1'b0;
+ else if (ca2_act_trans && !cra[5]) irqa2 <= 1'b1;
+end
+
+
+////////////////////////////////////////////////////////
+// IRQB logic
+
+// register cb1_in and cb2_in to detect transitions.
+reg cb1_in_1;
+reg cb2_in_1;
+always @(posedge clk) begin
+ cb1_in_1 <= cb1_in;
+ cb2_in_1 <= cb2_in;
+end
+
+// detect "active" transitions
+wire cb1_act_trans = ((cb1_in && !cb1_in_1 && crb[1]) || (!cb1_in && cb1_in_1 && !crb[1]));
+wire cb2_act_trans = ((cb2_in && !cb2_in_1 && crb[4]) || (!cb2_in && cb2_in_1 && !crb[4]));
+
+// IRQB1
+always @(posedge clk) begin
+ if (reset || (portb_rd_strobe && !cb1_act_trans)) irqb1 <= 1'b0;
+ else if (cb1_act_trans) irqb1 <= 1'b1;
+end
+
+// IRQB2
+always @(posedge clk) begin
+ if (reset || (portb_rd_strobe && !cb2_act_trans)) irqb2 <= 1'b0;
+ else if (cb2_act_trans && !crb[5]) irqb2 <= 1'b1;
+end
+
+
+// IRQ and enable logic.
+assign irq = (irqa1 && cra[0]) || (irqa2 && cra[3]) ||
+ (irqb1 && crb[0]) || (irqb2 && crb[3]);
+
+///////////////////////////////////////////////////
+// CA2 and CB2 output modes
+always @(posedge clk) begin
+ case (cra[5:3])
+ 3'b100: ca2_out <= irqa1;
+ 3'b101: ca2_out <= !ca1_act_trans;
+ 3'b111: ca2_out <= 1'b1;
+ default: ca2_out <= 1'b0;
+ endcase
+end
+
+reg cb2_out_r;
+always @(posedge clk) begin
+ if (reset || (portb_wr_strobe && !cb1_act_trans)) cb2_out_r <= 1'b0;
+ else if (cb1_act_trans) cb2_out_r <= 1'b1;
+end
+
+always @(posedge clk) begin
+ case (crb[5:3])
+ 3'b100: cb2_out <= cb2_out_r;
+ 3'b101: cb2_out <= !portb_wr_strobe;
+ 3'b111: cb2_out <= 1'b1;
+ default: cb2_out <= 1'b0;
+ endcase
+end
+
+///////////////////////////////////////////////////
+// Read data mux
+wire [7:0] porta = (porta_out & ddra) | (porta_in & ~ddra);
+wire [7:0] portb = (portb_out & ddrb) | (portb_in & ~ddrb);
+
+always @(*) begin
+ case (addr)
+ ADDR_PORTA: data_out = cra[2] ? porta : ddra;
+ ADDR_CRA: data_out = { irqa1, irqa2, cra };
+ ADDR_PORTB: data_out = crb[2] ? portb : ddrb;
+ ADDR_CRB: data_out = { irqb1, irqb2, crb };
+ endcase
+end
+
+endmodule // pia6520
diff --git a/common/IO/pia6821.vhd b/common/IO/pia6821.vhd
new file mode 100644
index 00000000..d565ae36
--- /dev/null
+++ b/common/IO/pia6821.vhd
@@ -0,0 +1,553 @@
+--===========================================================================--
+--
+-- S Y N T H E Z I A B L E I/O Port C O R E
+--
+-- www.OpenCores.Org - May 2004
+-- This core adheres to the GNU public license
+--
+-- File name : pia6821.vhd
+--
+-- Purpose : Implements 2 x 8 bit parallel I/O ports
+-- with programmable data direction registers
+--
+-- Dependencies : ieee.Std_Logic_1164
+-- ieee.std_logic_unsigned
+--
+-- Author : John E. Kent
+--
+--===========================================================================----
+--
+-- Revision History:
+--
+-- Date: Revision Author
+-- 1 May 2004 0.0 John Kent
+-- Initial version developed from ioport.vhd
+--
+--
+-- Unkown date 0.0.1 found at Pacedev repository
+-- remove High Z output and and oe signal
+--
+-- 18 October 2017 0.0.2 DarFpga
+-- Set output to low level when in data is in input mode
+-- (to avoid infered latch warning)
+--
+--===========================================================================----
+--
+-- Memory Map
+--
+-- IO + $00 - Port A Data & Direction register
+-- IO + $01 - Port A Control register
+-- IO + $02 - Port B Data & Direction Direction Register
+-- IO + $03 - Port B Control Register
+--
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+
+entity pia6821 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);
+ irqa : out std_logic;
+ irqb : out std_logic;
+ pa_i : in std_logic_vector(7 downto 0);
+ pa_o : out std_logic_vector(7 downto 0);
+ pa_oe : out std_logic_vector(7 downto 0);
+ ca1 : in std_logic;
+ ca2_i : in std_logic;
+ ca2_o : out std_logic;
+ ca2_oe : out std_logic;
+ pb_i : in std_logic_vector(7 downto 0);
+ pb_o : out std_logic_vector(7 downto 0);
+ pb_oe : out std_logic_vector(7 downto 0);
+ cb1 : in std_logic;
+ cb2_i : in std_logic;
+ cb2_o : out std_logic;
+ cb2_oe : out std_logic
+ );
+end;
+
+architecture pia_arch of pia6821 is
+
+signal porta_ddr : std_logic_vector(7 downto 0);
+signal porta_data : std_logic_vector(7 downto 0);
+signal porta_ctrl : std_logic_vector(5 downto 0);
+signal porta_read : std_logic;
+
+signal portb_ddr : std_logic_vector(7 downto 0);
+signal portb_data : std_logic_vector(7 downto 0);
+signal portb_ctrl : std_logic_vector(5 downto 0);
+signal portb_read : std_logic;
+signal portb_write : std_logic;
+
+signal ca1_del : std_logic;
+signal ca1_rise : std_logic;
+signal ca1_fall : std_logic;
+signal ca1_edge : std_logic;
+signal irqa1 : std_logic;
+
+signal ca2_del : std_logic;
+signal ca2_rise : std_logic;
+signal ca2_fall : std_logic;
+signal ca2_edge : std_logic;
+signal irqa2 : std_logic;
+signal ca2_out : std_logic;
+
+signal cb1_del : std_logic;
+signal cb1_rise : std_logic;
+signal cb1_fall : std_logic;
+signal cb1_edge : std_logic;
+signal irqb1 : std_logic;
+
+signal cb2_del : std_logic;
+signal cb2_rise : std_logic;
+signal cb2_fall : std_logic;
+signal cb2_edge : std_logic;
+signal irqb2 : std_logic;
+signal cb2_out : std_logic;
+
+begin
+
+--------------------------------
+--
+-- read I/O port
+--
+--------------------------------
+
+pia_read : process( addr, cs,
+ irqa1, irqa2, irqb1, irqb2,
+ porta_ddr, portb_ddr,
+ porta_data, portb_data,
+ porta_ctrl, portb_ctrl,
+ pa_i, pb_i )
+variable count : integer;
+begin
+ case addr is
+ when "00" =>
+ for count in 0 to 7 loop
+ if porta_ctrl(2) = '0' then
+ data_out(count) <= porta_ddr(count);
+ porta_read <= '0';
+ else
+ if porta_ddr(count) = '1' then
+ data_out(count) <= porta_data(count);
+ else
+ data_out(count) <= pa_i(count);
+ end if;
+ porta_read <= cs;
+ end if;
+ end loop;
+ portb_read <= '0';
+
+ when "01" =>
+ data_out <= irqa1 & irqa2 & porta_ctrl;
+ porta_read <= '0';
+ portb_read <= '0';
+
+ when "10" =>
+ for count in 0 to 7 loop
+ if portb_ctrl(2) = '0' then
+ data_out(count) <= portb_ddr(count);
+ portb_read <= '0';
+ else
+ if portb_ddr(count) = '1' then
+ data_out(count) <= portb_data(count);
+ else
+ data_out(count) <= pb_i(count);
+ end if;
+ portb_read <= cs;
+ end if;
+ end loop;
+ porta_read <= '0';
+
+ when "11" =>
+ data_out <= irqb1 & irqb2 & portb_ctrl;
+ porta_read <= '0';
+ portb_read <= '0';
+
+ when others =>
+ data_out <= "00000000";
+ porta_read <= '0';
+ portb_read <= '0';
+
+ end case;
+end process;
+
+---------------------------------
+--
+-- Write I/O ports
+--
+---------------------------------
+
+pia_write : process( clk, rst, addr, cs, rw, data_in,
+ porta_ctrl, portb_ctrl,
+ porta_data, portb_data,
+ porta_ddr, portb_ddr )
+begin
+ if rst = '1' then
+ porta_ddr <= "00000000";
+ porta_data <= "00000000";
+ porta_ctrl <= "000000";
+ portb_ddr <= "00000000";
+ portb_data <= "00000000";
+ portb_ctrl <= "000000";
+ portb_write <= '0';
+ elsif clk'event and clk = '1' then
+ if cs = '1' and rw = '0' then
+ case addr is
+ when "00" =>
+ if porta_ctrl(2) = '0' then
+ porta_ddr <= data_in;
+ porta_data <= porta_data;
+ else
+ porta_ddr <= porta_ddr;
+ porta_data <= data_in;
+ end if;
+ porta_ctrl <= porta_ctrl;
+ portb_ddr <= portb_ddr;
+ portb_data <= portb_data;
+ portb_ctrl <= portb_ctrl;
+ portb_write <= '0';
+ when "01" =>
+ porta_ddr <= porta_ddr;
+ porta_data <= porta_data;
+ porta_ctrl <= data_in(5 downto 0);
+ portb_ddr <= portb_ddr;
+ portb_data <= portb_data;
+ portb_ctrl <= portb_ctrl;
+ portb_write <= '0';
+ when "10" =>
+ porta_ddr <= porta_ddr;
+ porta_data <= porta_data;
+ porta_ctrl <= porta_ctrl;
+ if portb_ctrl(2) = '0' then
+ portb_ddr <= data_in;
+ portb_data <= portb_data;
+ portb_write <= '0';
+ else
+ portb_ddr <= portb_ddr;
+ portb_data <= data_in;
+ portb_write <= '1';
+ end if;
+ portb_ctrl <= portb_ctrl;
+ when "11" =>
+ porta_ddr <= porta_ddr;
+ porta_data <= porta_data;
+ porta_ctrl <= porta_ctrl;
+ portb_ddr <= portb_ddr;
+ portb_data <= portb_data;
+ portb_ctrl <= data_in(5 downto 0);
+ portb_write <= '0';
+ when others =>
+ porta_ddr <= porta_ddr;
+ porta_data <= porta_data;
+ porta_ctrl <= porta_ctrl;
+ portb_ddr <= portb_ddr;
+ portb_data <= portb_data;
+ portb_ctrl <= portb_ctrl;
+ portb_write <= '0';
+ end case;
+ else
+ porta_ddr <= porta_ddr;
+ porta_data <= porta_data;
+ porta_ctrl <= porta_ctrl;
+ portb_data <= portb_data;
+ portb_ddr <= portb_ddr;
+ portb_ctrl <= portb_ctrl;
+ portb_write <= '0';
+ 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
+ pa_o(count) <= porta_data(count);
+ pa_oe(count) <= '1';
+ else
+ pa_o(count) <= '0';
+ pa_oe(count) <= '0';
+ end if;
+ end loop;
+end process;
+
+---------------------------------
+--
+-- CA1 Edge detect
+--
+---------------------------------
+ca1_input : process( clk, rst, ca1, ca1_del,
+ ca1_rise, ca1_fall, ca1_edge,
+ irqa1, porta_ctrl, porta_read )
+begin
+ if rst = '1' then
+ ca1_del <= '0';
+ ca1_rise <= '0';
+ ca1_fall <= '0';
+ ca1_edge <= '0';
+ irqa1 <= '0';
+ elsif clk'event and clk = '0' then
+ ca1_del <= ca1;
+ ca1_rise <= (not ca1_del) and ca1;
+ ca1_fall <= ca1_del and (not ca1);
+ if ca1_edge = '1' then
+ irqa1 <= '1';
+ elsif porta_read = '1' then
+ irqa1 <= '0';
+ else
+ irqa1 <= irqa1;
+ end if;
+ end if;
+
+ if porta_ctrl(1) = '0' then
+ ca1_edge <= ca1_fall;
+ else
+ ca1_edge <= ca1_rise;
+ end if;
+end process;
+
+---------------------------------
+--
+-- CA2 Edge detect
+--
+---------------------------------
+ca2_input : process( clk, rst, ca2_i, ca2_del,
+ ca2_rise, ca2_fall, ca2_edge,
+ irqa2, porta_ctrl, porta_read )
+begin
+ if rst = '1' then
+ ca2_del <= '0';
+ ca2_rise <= '0';
+ ca2_fall <= '0';
+ ca2_edge <= '0';
+ irqa2 <= '0';
+ elsif clk'event and clk = '0' then
+ ca2_del <= ca2_i;
+ ca2_rise <= (not ca2_del) and ca2_i;
+ ca2_fall <= ca2_del and (not ca2_i);
+ if porta_ctrl(5) = '0' and ca2_edge = '1' then
+ irqa2 <= '1';
+ elsif porta_read = '1' then
+ irqa2 <= '0';
+ else
+ irqa2 <= irqa2;
+ end if;
+ end if;
+
+ if porta_ctrl(4) = '0' then
+ ca2_edge <= ca2_fall;
+ else
+ ca2_edge <= ca2_rise;
+ end if;
+end process;
+
+---------------------------------
+--
+-- CA2 output control
+--
+---------------------------------
+ca2_output : process( clk, rst, porta_ctrl, porta_read, ca1_edge, ca2_out )
+begin
+ if rst='1' then
+ ca2_out <= '0';
+ elsif clk'event and clk='0' then
+ case porta_ctrl(5 downto 3) is
+ when "100" => -- read PA clears, CA1 edge sets
+ if porta_read = '1' then
+ ca2_out <= '0';
+ elsif ca1_edge = '1' then
+ ca2_out <= '1';
+ else
+ ca2_out <= ca2_out;
+ end if;
+ when "101" => -- read PA clears, E sets
+ ca2_out <= not porta_read;
+ when "110" => -- set low
+ ca2_out <= '0';
+ when "111" => -- set high
+ ca2_out <= '1';
+ when others => -- no change
+ ca2_out <= ca2_out;
+ end case;
+ end if;
+end process;
+
+---------------------------------
+--
+-- CA2 direction control
+--
+---------------------------------
+ca2_direction : process( porta_ctrl, ca2_out )
+begin
+ if porta_ctrl(5) = '0' then
+ ca2_oe <= '0';
+ ca2_o <= '0';
+ else
+ ca2_o <= ca2_out;
+ ca2_oe <= '1';
+ end if;
+end process;
+
+---------------------------------
+--
+-- direction control port b
+--
+---------------------------------
+portb_direction : process ( portb_data, portb_ddr )
+variable count : integer;
+begin
+ for count in 0 to 7 loop
+ if portb_ddr(count) = '1' then
+ pb_o(count) <= portb_data(count);
+ pb_oe(count) <= '1';
+ else
+ pb_o(count) <= '0';
+ pb_oe(count) <= '0';
+ end if;
+ end loop;
+end process;
+
+---------------------------------
+--
+-- CB1 Edge detect
+--
+---------------------------------
+cb1_input : process( clk, rst, cb1, cb1_del,
+ cb1_rise, cb1_fall, cb1_edge,
+ irqb1, portb_ctrl, portb_read )
+begin
+ if rst = '1' then
+ cb1_del <= '0';
+ cb1_rise <= '0';
+ cb1_fall <= '0';
+ cb1_edge <= '0';
+ irqb1 <= '0';
+ elsif clk'event and clk = '0' then
+ cb1_del <= cb1;
+ cb1_rise <= (not cb1_del) and cb1;
+ cb1_fall <= cb1_del and (not cb1);
+ if cb1_edge = '1' then
+ irqb1 <= '1';
+ elsif portb_read = '1' then
+ irqb1 <= '0';
+ else
+ irqb1 <= irqb1;
+ end if;
+ end if;
+
+ if portb_ctrl(1) = '0' then
+ cb1_edge <= cb1_fall;
+ else
+ cb1_edge <= cb1_rise;
+ end if;
+end process;
+
+---------------------------------
+--
+-- CB2 Edge detect
+--
+---------------------------------
+cb2_input : process( clk, rst, cb2_i, cb2_del,
+ cb2_rise, cb2_fall, cb2_edge,
+ irqb2, portb_ctrl, portb_read )
+begin
+ if rst = '1' then
+ cb2_del <= '0';
+ cb2_rise <= '0';
+ cb2_fall <= '0';
+ cb2_edge <= '0';
+ irqb2 <= '0';
+ elsif clk'event and clk = '0' then
+ cb2_del <= cb2_i;
+ cb2_rise <= (not cb2_del) and cb2_i;
+ cb2_fall <= cb2_del and (not cb2_i);
+ if portb_ctrl(5) = '0' and cb2_edge = '1' then
+ irqb2 <= '1';
+ elsif portb_read = '1' then
+ irqb2 <= '0';
+ else
+ irqb2 <= irqb2;
+ end if;
+ end if;
+
+ if portb_ctrl(4) = '0' then
+ cb2_edge <= cb2_fall;
+ else
+ cb2_edge <= cb2_rise;
+ end if;
+
+end process;
+
+---------------------------------
+--
+-- CB2 output control
+--
+---------------------------------
+cb2_output : process( clk, rst, portb_ctrl, portb_write, cb1_edge, cb2_out )
+begin
+ if rst='1' then
+ cb2_out <= '0';
+ elsif clk'event and clk='0' then
+ case portb_ctrl(5 downto 3) is
+ when "100" => -- write PB clears, CA1 edge sets
+ if portb_write = '1' then
+ cb2_out <= '0';
+ elsif cb1_edge = '1' then
+ cb2_out <= '1';
+ else
+ cb2_out <= cb2_out;
+ end if;
+ when "101" => -- write PB clears, E sets
+ cb2_out <= not portb_write;
+ when "110" => -- set low
+ cb2_out <= '0';
+ when "111" => -- set high
+ cb2_out <= '1';
+ when others => -- no change
+ cb2_out <= cb2_out;
+ end case;
+ end if;
+end process;
+
+---------------------------------
+--
+-- CB2 direction control
+--
+---------------------------------
+cb2_direction : process( portb_ctrl, cb2_out )
+begin
+ if portb_ctrl(5) = '0' then
+ cb2_oe <= '0';
+ cb2_o <= '0';
+ else
+ cb2_o <= cb2_out;
+ cb2_oe <= '1';
+ end if;
+end process;
+
+---------------------------------
+--
+-- IRQ control
+--
+---------------------------------
+pia_irq : process( irqa1, irqa2, irqb1, irqb2, porta_ctrl, portb_ctrl )
+begin
+ irqa <= (irqa1 and porta_ctrl(0)) or (irqa2 and porta_ctrl(3));
+ irqb <= (irqb1 and portb_ctrl(0)) or (irqb2 and portb_ctrl(3));
+end process;
+
+end pia_arch;
+
diff --git a/common/IO/pia8255.vhd b/common/IO/pia8255.vhd
new file mode 100644
index 00000000..ad3d77cd
--- /dev/null
+++ b/common/IO/pia8255.vhd
@@ -0,0 +1,185 @@
+library IEEE;
+use IEEE.std_logic_1164.all;
+Use IEEE.std_logic_unsigned.all;
+use ieee.numeric_std.all;
+
+entity pia8255 is
+ port
+ (
+ -- uC interface
+ clk : in std_logic;
+ clken : in std_logic;
+ reset : in std_logic;
+ a : in std_logic_vector(1 downto 0);
+ d_i : in std_logic_vector(7 downto 0);
+ d_o : out std_logic_vector(7 downto 0);
+ cs : in std_logic;
+ rd : in std_logic;
+ wr : in std_logic;
+
+ -- I/O interface
+ pa_i : in std_logic_vector(7 downto 0);
+ pb_i : in std_logic_vector(7 downto 0);
+ pc_i : in std_logic_vector(7 downto 0);
+ pa_o : out std_logic_vector(7 downto 0);
+ pb_o : out std_logic_vector(7 downto 0);
+ pc_o : out std_logic_vector(7 downto 0)
+ );
+end pia8255;
+
+architecture SYN of pia8255 is
+
+ type byte_vector is array (natural range <>) of std_logic_vector(7 downto 0);
+
+ signal ctrl : std_logic_vector(7 downto 0);
+ signal pa_oen : std_logic;
+ signal pb_oen : std_logic;
+ signal pcl_oen : std_logic;
+ signal pch_oen : std_logic;
+
+ signal pa_d : std_logic_vector(7 downto 0);
+ signal pb_d : std_logic_vector(7 downto 0);
+ signal pc_d : std_logic_vector(7 downto 0);
+
+begin
+
+ pa_o <= pa_d when (reset = '0' and pa_oen = '1') else X"FF";
+ pb_o <= pb_d when (reset = '0' and pb_oen = '1') else X"FF";
+ pc_o(7 downto 4) <= pc_d(7 downto 4) when (reset = '0' and pch_oen = '1') else X"F";
+ pc_o(3 downto 0) <= pc_d(3 downto 0) when (reset = '0' and pcl_oen = '1') else X"F";
+
+ -- Synchronous logic
+ process(clk, reset)
+ variable ctrl_r : std_logic_vector(7 downto 0);
+ variable csel : integer;
+ begin
+ pa_oen <= not ctrl_r(4);
+ pb_oen <= not ctrl_r(1);
+ pcl_oen <= not ctrl_r(0);
+ pch_oen <= not ctrl_r(3);
+
+ ctrl <= ctrl_r;
+
+ -- Reset values
+ if reset = '1' then
+ ctrl_r := X"9B";
+ pa_d <= X"00";
+ pb_d <= X"00";
+ pc_d <= X"00";
+
+ -- Handle register writes
+ elsif rising_edge(clk) and clken = '1' and cs = '1' and wr = '1' then
+ if a = "00" then
+ pa_d <= d_i;
+ end if;
+
+ if a = "01" then
+ pb_d <= d_i;
+ end if;
+
+ if a = "10" then
+ pc_d <= d_i;
+ end if;
+
+ if a = "11" then
+ -- D7=1, write control
+ if d_i(7) = '1' then
+ ctrl_r := d_i;
+ pa_d <= X"00";
+ pb_d <= X"00";
+ pc_d <= X"00";
+
+ -- D7=0, write C bit
+ else
+ csel := conv_integer(d_i(3 downto 1));
+ pc_d(csel) <= d_i(0);
+ end if;
+ end if;
+ end if;
+ end process;
+
+ -- Data out mux
+ process(a, cs, rd)
+ variable data_out : std_logic_vector(7 downto 0);
+ begin
+ if cs = '1' and rd = '1' then
+ case a is
+ when "00" => data_out := pa_i;
+ when "01" => data_out := pb_i;
+ when "10" => data_out := pc_i;
+ when "11" => data_out := ctrl;
+ when others => data_out := (others => 'X');
+ end case;
+ else
+ data_out := (others => 'X');
+ end if;
+
+ d_o <= data_out;
+ end process;
+end SYN;
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+Use IEEE.std_logic_unsigned.all;
+use ieee.numeric_std.all;
+
+entity pia8255_n is
+ port
+ (
+ -- uC interface
+ clk : in std_logic;
+ clken : in std_logic;
+ reset : in std_logic;
+ a : in std_logic_vector(1 downto 0);
+ d_i : in std_logic_vector(7 downto 0);
+ d_o : out std_logic_vector(7 downto 0);
+ cs_n : in std_logic;
+ rd_n : in std_logic;
+ wr_n : in std_logic;
+
+ -- I/O interface
+ pa_i : in std_logic_vector(7 downto 0);
+ pb_i : in std_logic_vector(7 downto 0);
+ pc_i : in std_logic_vector(7 downto 0);
+ pa_o : out std_logic_vector(7 downto 0);
+ pb_o : out std_logic_vector(7 downto 0);
+ pc_o : out std_logic_vector(7 downto 0)
+ );
+end pia8255_n;
+
+architecture SYN of pia8255_n is
+
+ signal cs : std_logic;
+ signal rd : std_logic;
+ signal wr : std_logic;
+
+begin
+
+ cs <= not cs_n;
+ rd <= not rd_n;
+ wr <= not wr_n;
+
+ pia_inst : entity work.pia8255
+ port map
+ (
+ -- uC interface
+ clk => clk,
+ clken => clken,
+ reset => reset,
+ a => a,
+ d_i => d_i,
+ d_o => d_o,
+ cs => cs,
+ rd => rd,
+ wr => wr,
+
+ -- I/O interface
+ pa_i => pa_i,
+ pb_i => pb_i,
+ pc_i => pc_i,
+ pa_o => pa_o,
+ pb_o => pb_o,
+ pc_o => pc_o
+ );
+
+end SYN;
diff --git a/common/IO/t48_ip/alu.vhd b/common/IO/t48_ip/alu.vhd
new file mode 100644
index 00000000..22845122
--- /dev/null
+++ b/common/IO/t48_ip/alu.vhd
@@ -0,0 +1,446 @@
+-------------------------------------------------------------------------------
+--
+-- The Arithmetic Logic Unit (ALU).
+-- It contains the ALU core plus the Accumulator and the Temp Reg.
+--
+-- $Id: alu.vhd,v 1.8 2004/04/24 23:43:56 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.word_t;
+use work.alu_pack.alu_op_t;
+
+entity alu is
+
+ port (
+ -- Global Interface -------------------------------------------------------
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ -- T48 Bus Interface ------------------------------------------------------
+ data_i : in word_t;
+ data_o : out word_t;
+ write_accu_i : in boolean;
+ write_shadow_i : in boolean;
+ write_temp_reg_i : in boolean;
+ read_alu_i : in boolean;
+ -- Decoder Interface ------------------------------------------------------
+ carry_i : in std_logic;
+ carry_o : out std_logic;
+ aux_carry_o : out std_logic;
+ alu_op_i : in alu_op_t;
+ use_carry_i : in boolean;
+ da_high_i : in boolean;
+ da_overflow_o : out boolean;
+ accu_low_i : in boolean;
+ p06_temp_reg_i : in boolean;
+ p60_temp_reg_i : in boolean
+ );
+
+end alu;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+use work.t48_pack.clk_active_c;
+use work.t48_pack.res_active_c;
+use work.t48_pack.bus_idle_level_c;
+use work.t48_pack.nibble_t;
+use work.alu_pack.all;
+
+-- pragma translate_off
+use work.t48_tb_pack.tb_accu_s;
+-- pragma translate_on
+
+architecture rtl of alu is
+
+ -- the Accumulator and Temp Reg
+ signal accumulator_q,
+ accu_shadow_q,
+ temp_req_q : word_t;
+ -- inputs to the ALU core
+ signal in_a_s,
+ in_b_s : word_t;
+ -- output of the ALU core
+ signal data_s : word_t;
+
+ signal add_result_s : alu_operand_t;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process working_regs
+ --
+ -- Purpose:
+ -- Implements the working registers:
+ -- + Accumulator
+ -- + Temp Reg
+ --
+ working_regs: process (res_i, clk_i)
+ begin
+ if res_i = res_active_c then
+ accumulator_q <= (others => '0');
+ accu_shadow_q <= (others => '0');
+ temp_req_q <= (others => '0');
+
+ elsif clk_i'event and clk_i = clk_active_c then
+ if en_clk_i then
+
+ if write_accu_i then
+ if accu_low_i then
+ accumulator_q(nibble_t'range) <= data_i(nibble_t'range);
+ else
+ accumulator_q <= data_i;
+ end if;
+ end if;
+
+ if write_shadow_i then
+ -- write shadow directly from t48 data bus
+ accu_shadow_q <= data_i;
+ else
+ -- default: update shadow Accumulator from real Accumulator
+ accu_shadow_q <= accumulator_q;
+ end if;
+
+ if p06_temp_reg_i then
+ -- low nibble of DA sequence
+ temp_req_q <= "00000110";
+ elsif p60_temp_reg_i then
+ -- high nibble of DA sequence
+ temp_req_q <= "01100000";
+ elsif write_temp_reg_i then
+ -- normal load from T48 bus
+ temp_req_q <= data_i;
+ end if;
+
+ end if;
+
+ end if;
+
+ end process working_regs;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Build the inputs to the ALU core.
+ -- Input A:
+ -- Unary operators use only Input A.
+ -- Is always fed from the shadow Accumulator.
+ -- Assumption: It never happens that the Accumulator is written and then
+ -- read for an ALU operation in the next cycle.
+ -- Its contents can thus be staged through the shadow Accu.
+ -- Input B:
+ -- Is always fed from the Temp Reg.
+ -----------------------------------------------------------------------------
+ in_a_s <= accu_shadow_q;
+ in_b_s <= temp_req_q;
+
+
+ -----------------------------------------------------------------------------
+ -- Process alu_core
+ --
+ -- Purpose:
+ -- Implements the ALU core.
+ -- All operations defined in alu_op_t are handled here.
+ --
+ alu_core: process (in_a_s,
+ in_b_s,
+ alu_op_i,
+ carry_i,
+ use_carry_i,
+ add_result_s)
+
+ begin
+ -- default assigments
+ data_s <= (others => '0');
+ carry_o <= '0';
+
+ case alu_op_i is
+ -- Operation: AND -------------------------------------------------------
+ when ALU_AND =>
+ data_s <= in_a_s and in_b_s;
+
+ -- Operation: OR --------------------------------------------------------
+ when ALU_OR =>
+ data_s <= in_a_s or in_b_s;
+
+ -- Operation: XOR -------------------------------------------------------
+ when ALU_XOR =>
+ data_s <= in_a_s xor in_b_s;
+
+ -- Operation: Add -------------------------------------------------------
+ when ALU_ADD =>
+ data_s <= add_result_s(data_s'range);
+ carry_o <= add_result_s(add_result_s'high);
+
+ -- Operation: CPL -------------------------------------------------------
+ when ALU_CPL =>
+ data_s <= not in_a_s;
+
+ -- Operation: CLR -------------------------------------------------------
+ when ALU_CLR =>
+ data_s <= (others => '0');
+
+ -- Operation: RL --------------------------------------------------------
+ when ALU_RL =>
+ data_s(7 downto 1) <= in_a_s(6 downto 0);
+ carry_o <= in_a_s(7);
+
+ if use_carry_i then
+ data_s(0) <= carry_i;
+ else
+ data_s(0) <= in_a_s(7);
+ end if;
+
+ -- Operation: RR --------------------------------------------------------
+ when ALU_RR =>
+ data_s(6 downto 0) <= in_a_s(7 downto 1);
+ carry_o <= in_a_s(0);
+
+ if use_carry_i then
+ data_s(7) <= carry_i;
+ else
+ data_s(7) <= in_a_s(0);
+ end if;
+
+ -- Operation: Swap ------------------------------------------------------
+ when ALU_SWAP =>
+ data_s(3 downto 0) <= in_a_s(7 downto 4);
+ data_s(7 downto 4) <= in_a_s(3 downto 0);
+
+ -- Operation: DEC -------------------------------------------------------
+ when ALU_DEC =>
+ data_s <= add_result_s(data_s'range);
+
+ -- Operation: INC -------------------------------------------------------
+ when ALU_INC =>
+ data_s <= add_result_s(data_s'range);
+
+ -- Operation CONCAT -----------------------------------------------------
+ when ALU_CONCAT =>
+ data_s <= in_b_s(7 downto 4) & in_a_s(3 downto 0);
+
+ -- Operation: NOP -------------------------------------------------------
+ when ALU_NOP =>
+ data_s <= in_a_s;
+
+ when others =>
+ -- pragma translate_off
+ assert false
+ report "Unknown ALU operation selected!"
+ severity error;
+ -- pragma translate_on
+
+ end case;
+
+ end process alu_core;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process adder
+ --
+ -- Purpose:
+ -- Implements the adder used by several instructions.
+ -- This way of modelling the adder forces resource sharing of:
+ -- * ADD
+ -- * INC
+ -- * DEC
+ --
+ adder: process (in_a_s,
+ in_b_s,
+ alu_op_i,
+ carry_i,
+ use_carry_i)
+
+ variable add_a_v, add_b_v : alu_operand_t;
+ variable c_v : alu_operand_t;
+ variable result_v : UNSIGNED(alu_operand_t'range);
+ variable aux_c_v : std_logic_vector(1 downto 0);
+
+ begin
+ -- Carry Selection --------------------------------------------------------
+ c_v := (others => '0');
+ if use_carry_i and carry_i = '1' then
+ c_v(0) := '1';
+ end if;
+
+ -- Operand Selection ------------------------------------------------------
+ -- defaults for ADD
+ add_a_v := '0' & in_a_s;
+ add_b_v := '0' & in_b_s;
+
+ case alu_op_i is
+ when ALU_INC =>
+ add_b_v := (others => '0');
+ add_b_v(0) := '1';
+ when ALU_DEC =>
+ add_b_v := (others => '1');
+ when others =>
+ null;
+ end case;
+
+ -- The Adder --------------------------------------------------------------
+ result_v := UNSIGNED(add_a_v) +
+ UNSIGNED(add_b_v) +
+ UNSIGNED(c_v);
+
+ add_result_s <= std_logic_vector(result_v);
+
+ -- Auxiliary Carry --------------------------------------------------------
+ aux_c_v := in_a_s(4) & in_b_s(4);
+
+ aux_carry_o <= '0';
+ case aux_c_v is
+ when "00" | "11" =>
+ if result_v(4) = '1' then
+ aux_carry_o <= '1';
+ end if;
+
+ when "01" | "10" =>
+ if result_v(4) = '0' then
+ aux_carry_o <= '1';
+ end if;
+
+ when others =>
+ null;
+
+ end case;
+
+ end process adder;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process da_overflow
+ --
+ -- Purpose:
+ -- Detect overflow situation during DA sequence.
+ --
+ da_overflow: process (accu_shadow_q,
+ da_high_i)
+
+ variable da_nibble_v : nibble_t;
+
+ function da_overflow_f(data : in nibble_t) return boolean is
+ variable overflow_v : boolean;
+ begin
+ case data is
+ when "1010" |
+ "1011" |
+ "1100" |
+ "1101" |
+ "1110" |
+ "1111" =>
+ overflow_v := true;
+ when others =>
+ overflow_v := false;
+ end case;
+
+ return(overflow_v);
+ end;
+
+ begin
+ if da_high_i then
+ da_nibble_v := accu_shadow_q(7 downto 4);
+ else
+ da_nibble_v := accu_shadow_q(3 downto 0);
+ end if;
+
+ da_overflow_o <= da_overflow_f(da_nibble_v);
+
+ end process da_overflow;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -- pragma translate_off
+ -----------------------------------------------------------------------------
+ -- Testbench support.
+ -----------------------------------------------------------------------------
+ tb_accu_s <= accumulator_q;
+ -- pragma translate_on
+
+ -----------------------------------------------------------------------------
+ -- Output Multiplexer.
+ -----------------------------------------------------------------------------
+ data_o <= data_s
+ when read_alu_i else
+ (others => bus_idle_level_c);
+
+end rtl;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: alu.vhd,v $
+-- Revision 1.8 2004/04/24 23:43:56 arniml
+-- move from std_logic_arith to numeric_std
+--
+-- Revision 1.7 2004/04/07 22:09:03 arniml
+-- remove unused signals
+--
+-- Revision 1.6 2004/04/07 20:56:23 arniml
+-- default assignment for aux_carry_o
+--
+-- Revision 1.5 2004/04/06 20:21:53 arniml
+-- fix sensitivity list
+--
+-- Revision 1.4 2004/04/06 18:10:41 arniml
+-- rework adder and force resource sharing between ADD, INC and DEC
+--
+-- Revision 1.3 2004/04/04 14:18:52 arniml
+-- add measures to implement XCHD
+--
+-- Revision 1.2 2004/03/28 21:08:51 arniml
+-- support for DA instruction
+--
+-- Revision 1.1 2004/03/23 21:31:52 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/IO/t48_ip/alu_pack-p.vhd b/common/IO/t48_ip/alu_pack-p.vhd
new file mode 100644
index 00000000..9fbbb9f2
--- /dev/null
+++ b/common/IO/t48_ip/alu_pack-p.vhd
@@ -0,0 +1,49 @@
+-------------------------------------------------------------------------------
+--
+-- $Id: alu_pack-p.vhd,v 1.2 2004/04/04 14:18:53 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.word_width_c;
+
+package alu_pack is
+
+ -----------------------------------------------------------------------------
+ -- The ALU operations
+ -----------------------------------------------------------------------------
+ type alu_op_t is (ALU_AND, ALU_OR, ALU_XOR,
+ ALU_CPL, ALU_CLR,
+ ALU_RL, ALU_RR,
+ ALU_SWAP,
+ ALU_DEC, ALU_INC,
+ ALU_ADD,
+ ALU_CONCAT,
+ ALU_NOP);
+
+ -----------------------------------------------------------------------------
+ -- The dedicated ALU arithmetic types.
+ -----------------------------------------------------------------------------
+ subtype alu_operand_t is std_logic_vector(word_width_c downto 0);
+
+end alu_pack;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: alu_pack-p.vhd,v $
+-- Revision 1.2 2004/04/04 14:18:53 arniml
+-- add measures to implement XCHD
+--
+-- Revision 1.1 2004/03/23 21:31:52 arniml
+-- initial check-in
+--
+--
+-------------------------------------------------------------------------------
diff --git a/common/IO/t48_ip/bus_mux.vhd b/common/IO/t48_ip/bus_mux.vhd
new file mode 100644
index 00000000..d79d3387
--- /dev/null
+++ b/common/IO/t48_ip/bus_mux.vhd
@@ -0,0 +1,111 @@
+-------------------------------------------------------------------------------
+--
+-- The T48 Bus Connector.
+-- Multiplexes all drivers of the T48 bus.
+--
+-- $Id: bus_mux.vhd,v 1.1 2004/03/23 21:31:52 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.word_t;
+
+entity bus_mux is
+
+ port (
+ alu_data_i : in word_t;
+ bus_data_i : in word_t;
+ dec_data_i : in word_t;
+ dm_data_i : in word_t;
+ pm_data_i : in word_t;
+ p1_data_i : in word_t;
+ p2_data_i : in word_t;
+ psw_data_i : in word_t;
+ tim_data_i : in word_t;
+ data_o : out word_t
+ );
+
+end bus_mux;
+
+
+use work.t48_pack.bus_idle_level_c;
+
+architecture rtl of bus_mux is
+
+begin
+
+ or_tree: if bus_idle_level_c = '0' generate
+ data_o <= alu_data_i or
+ bus_data_i or
+ dec_data_i or
+ dm_data_i or
+ pm_data_i or
+ p1_data_i or
+ p2_data_i or
+ psw_data_i or
+ tim_data_i;
+ end generate;
+
+ and_tree: if bus_idle_level_c = '1' generate
+ data_o <= alu_data_i and
+ bus_data_i and
+ dec_data_i and
+ dm_data_i and
+ pm_data_i and
+ p1_data_i and
+ p2_data_i and
+ psw_data_i and
+ tim_data_i;
+ end generate;
+
+end rtl;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: bus_mux.vhd,v $
+-- Revision 1.1 2004/03/23 21:31:52 arniml
+-- initial check-in
+--
+--
+-------------------------------------------------------------------------------
diff --git a/common/IO/t48_ip/clock_ctrl.vhd b/common/IO/t48_ip/clock_ctrl.vhd
new file mode 100644
index 00000000..d56c32fd
--- /dev/null
+++ b/common/IO/t48_ip/clock_ctrl.vhd
@@ -0,0 +1,397 @@
+-------------------------------------------------------------------------------
+--
+-- The Clock Control unit.
+-- Clock States and Machine Cycles are generated here.
+--
+-- $Id: clock_ctrl.vhd,v 1.4 2004/04/24 23:44:25 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.all;
+
+entity clock_ctrl is
+
+ generic (
+ -- divide XTAL1 by 3 to derive Clock States
+ xtal_div_3_g : integer := 1
+ );
+
+ port (
+ clk_i : in std_logic;
+ xtal_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ xtal3_o : out boolean;
+ multi_cycle_i : in boolean;
+ assert_psen_i : in boolean;
+ assert_prog_i : in boolean;
+ assert_rd_i : in boolean;
+ assert_wr_i : in boolean;
+ mstate_o : out mstate_t;
+ second_cycle_o : out boolean;
+ ale_o : out boolean;
+ psen_o : out boolean;
+ prog_o : out boolean;
+ rd_o : out boolean;
+ wr_o : out boolean
+ );
+
+end clock_ctrl;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+architecture rtl of clock_ctrl is
+
+ -- The three XTAL1 cycles.
+ signal xtal_q : unsigned(1 downto 0);
+ signal xtal1_s,
+ xtal2_s,
+ xtal3_s : boolean;
+ signal x1_s,
+ x2_s,
+ x3_s : std_logic;
+
+
+ -- The five clock states.
+ signal mstate_q : mstate_t;
+
+ signal ale_q : boolean;
+ signal psen_q : boolean;
+ signal prog_q : boolean;
+ signal rd_q : boolean;
+ signal wr_q : boolean;
+
+
+ -- The Machine Cycle marker.
+ signal second_cycle_q : boolean;
+ signal multi_cycle_q : boolean;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Verify the generics
+ -----------------------------------------------------------------------------
+
+ -- pragma translate_off
+
+ -- XTAL1 divide by 3 --------------------------------------------------------
+ assert (xtal_div_3_g = 1) or (xtal_div_3_g = 0)
+ report "xtal_div_3_g must be either 1 or 0!"
+ severity failure;
+
+ -- pragma translate_on
+
+
+ -----------------------------------------------------------------------------
+ -- Divide XTAL1 by 3 to derive Clock States.
+ -----------------------------------------------------------------------------
+ use_xtal_div: if xtal_div_3_g = 1 generate
+ xtal: process (res_i, xtal_i)
+ begin
+ if res_i = res_active_c then
+ xtal_q <= TO_UNSIGNED(0, 2);
+
+ elsif xtal_i'event and xtal_i = clk_active_c then
+ if xtal_q < 2 then
+ xtal_q <= xtal_q + 1;
+ else
+ xtal_q <= TO_UNSIGNED(0, 2);
+ end if;
+
+ end if;
+
+ end process xtal;
+
+ x1_s <= '1'
+ when xtal_q = 0 else
+ '0';
+ x2_s <= '1'
+ when xtal_q = 1 else
+ '0';
+ x3_s <= '1'
+ when xtal_q = 2 else
+ '0';
+
+ end generate;
+
+ -----------------------------------------------------------------------------
+ -- XTAL1 is used directly for Clock States.
+ -----------------------------------------------------------------------------
+ no_xtal_div: if xtal_div_3_g = 0 generate
+ xtal_q <= TO_UNSIGNED(0, 2);
+
+ x1_s <= '1';
+ x2_s <= '1';
+ x3_s <= '1';
+
+ end generate;
+
+ -- And finally the boolean flags --------------------------------------------
+ xtal1_s <= to_boolean(x1_s);
+ xtal2_s <= to_boolean(x2_s);
+ xtal3_s <= to_boolean(x3_s);
+
+
+ -----------------------------------------------------------------------------
+ -- Process external_signal
+ --
+ -- Purpose:
+ -- Control signals ALE, PSEN, PROG and RD/WR are generated here.
+ --
+ external_signals: process (res_i, xtal_i)
+ begin
+ if res_i = res_active_c then
+ ale_q <= false;
+ psen_q <= false;
+ prog_q <= false;
+ rd_q <= false;
+ wr_q <= false;
+
+ elsif xtal_i'event and xtal_i = clk_active_c then
+
+ case mstate_q is
+ when MSTATE5 =>
+ -- RD, WR are set at the end of XTAL2 of first machine cycle
+ if xtal2_s and not second_cycle_q then
+ if assert_rd_i then
+ rd_q <= true;
+ end if;
+ if assert_wr_i then
+ wr_q <= true;
+ end if;
+ end if;
+
+ when MSTATE1 =>
+ if xtal3_s then
+ psen_q <= false;
+ end if;
+
+ when MSTATE2 =>
+ if xtal2_s then
+ -- RD, WR are removed at the end of XTAL3 of second machine cycle
+ rd_q <= false;
+ wr_q <= false;
+ -- PROG is removed at the and of XTAL3 of second machine cycle
+ prog_q <= false;
+ end if;
+
+ when MSTATE3 =>
+ -- ALE is set at the end of XTAL2 of every machine cycle
+ if xtal2_s then
+ ale_q <= true;
+ end if;
+
+ when MSTATE4 =>
+ if xtal3_s then
+ -- PSEN is set at the end of XTAL3
+ if assert_psen_i then
+ psen_q <= true;
+ end if;
+
+ end if;
+
+ -- PROG is set at the and of XTAL2
+ if xtal2_s and multi_cycle_q and not second_cycle_q and
+ assert_prog_i then
+ prog_q <= true;
+ end if;
+
+ -- ALE is removed at the end of XTAL2 of every machine cycle
+ if xtal2_s then
+ ale_q <= false;
+ end if;
+
+ when others =>
+ -- recover when states are out of sync
+ ale_q <= false;
+ psen_q <= false;
+ prog_q <= false;
+ rd_q <= false;
+ wr_q <= false;
+
+ end case;
+
+ end if;
+
+ end process external_signals;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process states
+ --
+ -- Purpose:
+ -- The Clock State controller.
+ --
+ states: process (res_i, clk_i)
+ begin
+ if res_i = res_active_c then
+ -- Reset machine state to MSTATE3
+ -- This allows a proper instruction fetch for the first real instruction
+ -- after reset.
+ -- The MSTATE3 is part of a virtual NOP that has no MSTATE1 and MSTATE2.
+ mstate_q <= MSTATE3;
+
+ elsif clk_i'event and clk_i = clk_active_c then
+ if en_clk_i then
+
+ case mstate_q is
+ when MSTATE5 =>
+ mstate_q <= MSTATE1;
+
+ when MSTATE1 =>
+ mstate_q <= MSTATE2;
+
+ when MSTATE2 =>
+ mstate_q <= MSTATE3;
+
+ when MSTATE3 =>
+ mstate_q <= MSTATE4;
+
+ when MSTATE4 =>
+ mstate_q <= MSTATE5;
+
+ when others =>
+ -- recover when states are out of sync
+ mstate_q <= MSTATE1;
+
+ -- pragma translate_off
+ assert false
+ report "Encoding of Clock States failed!"
+ severity error;
+ -- pragma translate_on
+
+ end case;
+
+ end if;
+
+ end if;
+
+ end process states;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process machine_cycle
+ --
+ -- Purpose:
+ -- Keep track of machine cycles.
+ -- Basically, this means to differ between first and second cycle.
+ --
+ machine_cycle: process (res_i, clk_i)
+ variable state2_v, state5_v : boolean;
+ begin
+ if res_i = res_active_c then
+ multi_cycle_q <= false;
+ second_cycle_q <= false;
+
+ elsif clk_i'event and clk_i = clk_active_c then
+ if en_clk_i then
+
+ state2_v := mstate_q = MSTATE2;
+ state5_v := mstate_q = MSTATE5;
+
+ -- multi cycle information is delivered in State 2 from the decoder
+ if state2_v and multi_cycle_i then
+ multi_cycle_q <= true;
+ end if;
+
+ -- mark second machine cycle
+ if multi_cycle_q and state5_v then
+ second_cycle_q <= true;
+ end if;
+
+ -- reset at end of second machine cycle
+ if state5_v and
+ (multi_cycle_q and second_cycle_q) then
+ multi_cycle_q <= false;
+ second_cycle_q <= false;
+ end if;
+
+ end if;
+
+ end if;
+
+ end process machine_cycle;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Output assignments
+ -----------------------------------------------------------------------------
+ xtal3_o <= xtal3_s;
+ mstate_o <= mstate_q;
+ second_cycle_o <= second_cycle_q;
+ ale_o <= ale_q;
+ psen_o <= psen_q;
+ prog_o <= prog_q;
+ rd_o <= rd_q;
+ wr_o <= wr_q;
+
+end rtl;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: clock_ctrl.vhd,v $
+-- Revision 1.4 2004/04/24 23:44:25 arniml
+-- move from std_logic_arith to numeric_std
+--
+-- Revision 1.3 2004/04/18 18:56:23 arniml
+-- reset machine state to MSTATE3 to allow proper instruction fetch
+-- after reset
+--
+-- Revision 1.2 2004/03/28 12:55:06 arniml
+-- move code for PROG out of if-branch for xtal3_s
+--
+-- Revision 1.1 2004/03/23 21:31:52 arniml
+-- initial check-in
+--
+--
+-------------------------------------------------------------------------------
diff --git a/common/IO/t48_ip/cond_branch.vhd b/common/IO/t48_ip/cond_branch.vhd
new file mode 100644
index 00000000..692a737e
--- /dev/null
+++ b/common/IO/t48_ip/cond_branch.vhd
@@ -0,0 +1,215 @@
+-------------------------------------------------------------------------------
+--
+-- The Conditional Branch Logic unit.
+-- Decisions whether to take a jump or not are made here.
+--
+-- $Id: cond_branch.vhd,v 1.2 2004/04/24 23:44:25 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.word_t;
+
+use work.cond_branch_pack.all;
+
+entity cond_branch is
+
+ port (
+ -- Global Interface -------------------------------------------------------
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ -- Decoder Interface ------------------------------------------------------
+ compute_take_i : in boolean;
+ branch_cond_i : in branch_conditions_t;
+ take_branch_o : out boolean;
+ accu_i : in word_t;
+ t0_i : in std_logic;
+ t1_i : in std_logic;
+ int_n_i : in std_logic;
+ f0_i : in std_logic;
+ f1_i : in std_logic;
+ tf_i : in std_logic;
+ carry_i : in std_logic;
+ comp_value_i : in comp_value_t
+ );
+
+end cond_branch;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+use work.t48_pack.res_active_c;
+use work.t48_pack.clk_active_c;
+
+architecture rtl of cond_branch is
+
+ -- marker for branch taken
+ signal take_branch_s,
+ take_branch_q : boolean;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process decide_take
+ --
+ -- Purpose:
+ -- Decides whether a branch has to be taken or not.
+ --
+ decide_take: process (accu_i,
+ branch_cond_i,
+ t0_i, t1_i,
+ int_n_i,
+ f0_i, f1_i,
+ tf_i,
+ carry_i,
+ comp_value_i)
+ variable or_v : std_logic;
+ begin
+ -- default assignment
+ take_branch_s <= false;
+ or_v := '0';
+
+ case branch_cond_i is
+ -- Branch On: Accumulator Bit -------------------------------------------
+ when COND_ON_BIT =>
+ if accu_i(TO_INTEGER(UNSIGNED(comp_value_i))) = '1' then
+ take_branch_s <= true;
+ end if;
+
+ -- Branch On: Accumulator Zero ------------------------------------------
+ when COND_Z =>
+ for i in accu_i'range loop
+ or_v := or_v or accu_i(i);
+ end loop;
+ take_branch_s <= or_v = not comp_value_i(0);
+
+ -- Branch On: Carry -----------------------------------------------------
+ when COND_C =>
+ take_branch_s <= carry_i = comp_value_i(0);
+
+ -- Branch On: Flag 0 ----------------------------------------------------
+ when COND_F0 =>
+ take_branch_s <= f0_i = '1';
+
+ -- Branch On: Flag 1 ----------------------------------------------------
+ when COND_F1 =>
+ take_branch_s <= f1_i = '1';
+
+ -- Branch On: Interrupt -------------------------------------------------
+ when COND_INT =>
+ take_branch_s <= int_n_i = '0';
+
+ -- Branch On: Test 0 ----------------------------------------------------
+ when COND_T0 =>
+ take_branch_s <= t0_i = comp_value_i(0);
+
+ -- Branch On: Test 1 ----------------------------------------------------
+ when COND_T1 =>
+ take_branch_s <= t1_i = comp_value_i(0);
+
+ -- Branch On: Timer Flag ------------------------------------------------
+ when COND_TF =>
+ take_branch_s <= tf_i = '1';
+
+ when others =>
+ -- pragma translate_off
+ assert false
+ report "Unknown branch condition specified!"
+ severity error;
+ -- pragma translate_on
+
+ end case;
+
+ end process decide_take;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process reg
+ --
+ -- Purpose:
+ -- Implement the marker register.
+ --
+ reg: process (res_i, clk_i)
+ begin
+ if res_i = res_active_c then
+ take_branch_q <= false;
+
+ elsif clk_i'event and clk_i = clk_active_c then
+ if en_clk_i then
+
+ if compute_take_i then
+ take_branch_q <= take_branch_s;
+ end if;
+
+ end if;
+
+ end if;
+
+ end process reg;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Output Mapping.
+ -----------------------------------------------------------------------------
+ take_branch_o <= take_branch_q;
+
+end rtl;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: cond_branch.vhd,v $
+-- Revision 1.2 2004/04/24 23:44:25 arniml
+-- move from std_logic_arith to numeric_std
+--
+-- Revision 1.1 2004/03/23 21:31:52 arniml
+-- initial check-in
+--
+--
+-------------------------------------------------------------------------------
diff --git a/common/IO/t48_ip/cond_branch_pack-p.vhd b/common/IO/t48_ip/cond_branch_pack-p.vhd
new file mode 100644
index 00000000..4d14ce0d
--- /dev/null
+++ b/common/IO/t48_ip/cond_branch_pack-p.vhd
@@ -0,0 +1,39 @@
+-------------------------------------------------------------------------------
+--
+-- $Id: cond_branch_pack-p.vhd,v 1.1 2004/03/23 21:31:52 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+package cond_branch_pack is
+
+ -----------------------------------------------------------------------------
+ -- The branch conditions.
+ -----------------------------------------------------------------------------
+ type branch_conditions_t is (COND_ON_BIT, COND_Z,
+ COND_C,
+ COND_F0, COND_F1,
+ COND_INT,
+ COND_T0, COND_T1,
+ COND_TF);
+
+ subtype comp_value_t is std_logic_vector(2 downto 0);
+
+end cond_branch_pack;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: cond_branch_pack-p.vhd,v $
+-- Revision 1.1 2004/03/23 21:31:52 arniml
+-- initial check-in
+--
+--
+-------------------------------------------------------------------------------
diff --git a/common/IO/t48_ip/db_bus.vhd b/common/IO/t48_ip/db_bus.vhd
new file mode 100644
index 00000000..f14fee6a
--- /dev/null
+++ b/common/IO/t48_ip/db_bus.vhd
@@ -0,0 +1,151 @@
+-------------------------------------------------------------------------------
+--
+-- The BUS unit.
+-- Implements the BUS port logic.
+--
+-- $Id: db_bus.vhd,v 1.2 2004/04/04 14:15:45 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.word_t;
+
+entity db_bus is
+
+ port (
+ -- Global Interface -------------------------------------------------------
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ ea_i : in std_logic;
+ -- T48 Bus Interface ------------------------------------------------------
+ data_i : in word_t;
+ data_o : out word_t;
+ write_bus_i : in boolean;
+ read_bus_i : in boolean;
+ -- BUS Interface ----------------------------------------------------------
+ output_pcl_i : in boolean;
+ bidir_bus_i : in boolean;
+ pcl_i : in word_t;
+ db_i : in word_t;
+ db_o : out word_t;
+ db_dir_o : out std_logic
+ );
+
+end db_bus;
+
+
+use work.t48_pack.clk_active_c;
+use work.t48_pack.res_active_c;
+use work.t48_pack.bus_idle_level_c;
+use work.t48_pack.to_stdLogic;
+
+architecture rtl of db_bus is
+
+ -- the BUS output register
+ signal bus_q : word_t;
+
+ -- BUS direction marker
+ signal db_dir_q : std_logic;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process bus_regs
+ --
+ -- Purpose:
+ -- Implements the BUS output register.
+ --
+ bus_regs: process (res_i, clk_i)
+ begin
+ if res_i = res_active_c then
+ bus_q <= (others => '0');
+ db_dir_q <= '0';
+
+ elsif clk_i'event and clk_i = clk_active_c then
+ if en_clk_i then
+
+ if write_bus_i then
+ bus_q <= data_i;
+
+ db_dir_q <= '1';
+
+ elsif ea_i = '1' or bidir_bus_i then
+ db_dir_q <= '0';
+
+ end if;
+
+ end if;
+
+ end if;
+
+ end process bus_regs;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Output Mapping.
+ -----------------------------------------------------------------------------
+ db_o <= pcl_i
+ when output_pcl_i else
+ bus_q;
+ db_dir_o <= db_dir_q or to_stdLogic(output_pcl_i);
+ data_o <= (others => bus_idle_level_c)
+ when not read_bus_i else
+ db_i;
+
+end rtl;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: db_bus.vhd,v $
+-- Revision 1.2 2004/04/04 14:15:45 arniml
+-- add dump_compare support
+--
+-- Revision 1.1 2004/03/23 21:31:52 arniml
+-- initial check-in
+--
+--
+-------------------------------------------------------------------------------
diff --git a/common/IO/t48_ip/decoder.vhd b/common/IO/t48_ip/decoder.vhd
new file mode 100644
index 00000000..f53ee56b
--- /dev/null
+++ b/common/IO/t48_ip/decoder.vhd
@@ -0,0 +1,2006 @@
+-------------------------------------------------------------------------------
+--
+-- The Decoder unit.
+-- It decodes the instruction opcodes and executes them.
+--
+-- $Id: decoder.vhd,v 1.15 2004/09/12 00:35:44 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.word_t;
+use work.t48_pack.mstate_t;
+use work.alu_pack.alu_op_t;
+use work.cond_branch_pack.all;
+use work.dmem_ctrl_pack.all;
+use work.pmem_ctrl_pack.all;
+
+entity decoder is
+
+ generic (
+ -- store mnemonic in flip-flops (registered-out)
+ register_mnemonic_g : integer := 1
+ );
+
+ port (
+ -- Global Interface -------------------------------------------------------
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ ea_i : in std_logic;
+ ale_i : in boolean;
+ int_n_i : in std_logic;
+ t0_dir_o : out std_logic;
+ -- T48 Bus Interface ------------------------------------------------------
+ data_i : in word_t;
+ data_o : out word_t;
+ stack_high_o : out boolean;
+ alu_write_accu_o : out boolean;
+ alu_write_shadow_o : out boolean;
+ alu_write_temp_reg_o : out boolean;
+ alu_read_alu_o : out boolean;
+ bus_write_bus_o : out boolean;
+ bus_read_bus_o : out boolean;
+ dm_write_dmem_addr_o : out boolean;
+ dm_write_dmem_o : out boolean;
+ dm_read_dmem_o : out boolean;
+ p1_write_p1_o : out boolean;
+ p1_read_p1_o : out boolean;
+ p2_write_p2_o : out boolean;
+ p2_write_exp_o : out boolean;
+ p2_read_p2_o : out boolean;
+ p2_read_exp_o : out boolean;
+ pm_write_pcl_o : out boolean;
+ pm_read_pcl_o : out boolean;
+ pm_write_pch_o : out boolean;
+ pm_read_pch_o : out boolean;
+ pm_read_pmem_o : out boolean;
+ psw_read_psw_o : out boolean;
+ psw_read_sp_o : out boolean;
+ psw_write_psw_o : out boolean;
+ psw_write_sp_o : out boolean;
+ -- ALU Interface ----------------------------------------------------------
+ alu_carry_i : in std_logic;
+ alu_op_o : out alu_op_t;
+ alu_use_carry_o : out boolean;
+ alu_da_high_o : out boolean;
+ alu_accu_low_o : out boolean;
+ alu_p06_temp_reg_o : out boolean;
+ alu_p60_temp_reg_o : out boolean;
+ alu_da_overflow_i : in boolean;
+ -- BUS Interface ----------------------------------------------------------
+ bus_output_pcl_o : out boolean;
+ bus_bidir_bus_o : out boolean;
+ -- Clock Controller Interface ---------------------------------------------
+ clk_multi_cycle_o : out boolean;
+ clk_assert_psen_o : out boolean;
+ clk_assert_prog_o : out boolean;
+ clk_assert_rd_o : out boolean;
+ clk_assert_wr_o : out boolean;
+ clk_mstate_i : in mstate_t;
+ clk_second_cycle_i : in boolean;
+ -- Conditional Branch Logic Interface -------------------------------------
+ cnd_compute_take_o : out boolean;
+ cnd_branch_cond_o : out branch_conditions_t;
+ cnd_take_branch_i : in boolean;
+ cnd_comp_value_o : out comp_value_t;
+ cnd_f1_o : out std_logic;
+ cnd_tf_o : out std_logic;
+ -- Data Memory Controller Interface ---------------------------------------
+ dm_addr_type_o : out dmem_addr_ident_t;
+ -- Port 1 Interface -------------------------------------------------------
+ p1_read_reg_o : out boolean;
+ -- Port 2 Interface -------------------------------------------------------
+ p2_read_reg_o : out boolean;
+ p2_output_pch_o : out boolean;
+ p2_output_exp_o : out boolean;
+ -- Program Memory Controller Interface ------------------------------------
+ pm_inc_pc_o : out boolean;
+ pm_write_pmem_addr_o : out boolean;
+ pm_addr_type_o : out pmem_addr_ident_t;
+ -- Program Status Word Interface ------------------------------------------
+ psw_special_data_o : out std_logic;
+ psw_carry_i : in std_logic;
+ psw_aux_carry_i : in std_logic;
+ psw_f0_i : in std_logic;
+ psw_inc_stackp_o : out boolean;
+ psw_dec_stackp_o : out boolean;
+ psw_write_carry_o : out boolean;
+ psw_write_aux_carry_o : out boolean;
+ psw_write_f0_o : out boolean;
+ psw_write_bs_o : out boolean;
+ -- Timer Interface --------------------------------------------------------
+ tim_read_timer_o : out boolean;
+ tim_write_timer_o : out boolean;
+ tim_start_t_o : out boolean;
+ tim_start_cnt_o : out boolean;
+ tim_stop_tcnt_o : out boolean;
+ tim_overflow_i : in boolean
+ );
+
+end decoder;
+
+
+use work.t48_pack.all;
+use work.alu_pack.all;
+use work.decoder_pack.all;
+
+use work.t48_comp_pack.opc_decoder;
+use work.t48_comp_pack.int;
+
+-- pragma translate_off
+use work.t48_tb_pack.tb_istrobe_s;
+-- pragma translate_on
+
+architecture rtl of decoder is
+
+ -- Enable fixing a bug of Quartus II 4.0
+ constant enable_quartus_bugfix_c : boolean := true;
+
+ -- Opcode Decoder
+ signal opc_multi_cycle_s : boolean;
+ signal opc_read_bus_s : boolean;
+ signal opc_inj_int_s : boolean;
+ signal opc_opcode_s : word_t;
+ signal opc_mnemonic_s : mnemonic_t;
+ signal last_cycle_s : boolean;
+
+ -- state translators
+ signal assert_psen_s : boolean;
+
+ -- branch taken handshake
+ signal branch_taken_s,
+ branch_taken_q : boolean;
+ signal pm_inc_pc_s : boolean;
+ signal pm_write_pmem_addr_s : boolean;
+ -- additional signal to increment PC during CALL
+ signal add_inc_pc_s : boolean;
+ -- addtional signal to set PC during RET(R)
+ signal add_write_pmem_addr_s : boolean;
+
+ -- Flag 1
+ signal clear_f1_s,
+ cpl_f1_s : boolean;
+ signal f1_q : std_logic;
+ -- memory bank select
+ signal clear_mb_s,
+ set_mb_s : boolean;
+ signal mb_q : std_logic;
+
+ -- T0 direction selection
+ signal ent0_clk_s : boolean;
+ signal t0_dir_q : std_logic;
+
+ signal data_s : word_t;
+ signal read_dec_s : boolean;
+
+ signal tf_s : std_logic;
+
+ signal bus_read_bus_s : boolean;
+ signal add_read_bus_s : boolean;
+
+ signal dm_write_dmem_s : boolean;
+
+ -- interrupt handling
+ signal jtf_executed_s : boolean;
+ signal en_tcnti_s : boolean;
+ signal dis_tcnti_s : boolean;
+ signal en_i_s : boolean;
+ signal dis_i_s : boolean;
+ signal tim_int_s : boolean;
+ signal retr_executed_s : boolean;
+ signal int_executed_s : boolean;
+ signal int_pending_s : boolean;
+ signal int_in_progress_s : boolean;
+
+ -- pragma translate_off
+ signal istrobe_res_q : std_logic;
+ signal istrobe_q : std_logic;
+ signal injected_int_q : std_logic;
+ -- pragma translate_on
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Opcode Decoder
+ -----------------------------------------------------------------------------
+ opc_decoder_b : opc_decoder
+ generic map (
+ register_mnemonic_g => register_mnemonic_g
+ )
+ port map (
+ clk_i => clk_i,
+ res_i => res_i,
+ en_clk_i => en_clk_i,
+ data_i => data_i,
+ read_bus_i => opc_read_bus_s,
+ inj_int_i => opc_inj_int_s,
+ opcode_o => opc_opcode_s,
+ mnemonic_o => opc_mnemonic_s,
+ multi_cycle_o => opc_multi_cycle_s
+ );
+
+
+ -----------------------------------------------------------------------------
+ -- Interrupt Controller.
+ -----------------------------------------------------------------------------
+ int_b : int
+ port map (
+ clk_i => clk_i,
+ res_i => res_i,
+ en_clk_i => en_clk_i,
+ clk_mstate_i => clk_mstate_i,
+ jtf_executed_i => jtf_executed_s,
+ tim_overflow_i => tim_overflow_i,
+ tf_o => tf_s,
+ en_tcnti_i => en_tcnti_s,
+ dis_tcnti_i => dis_tcnti_s,
+ int_n_i => int_n_i,
+ ale_i => ale_i,
+ last_cycle_i => last_cycle_s,
+ en_i_i => en_i_s,
+ dis_i_i => dis_i_s,
+ ext_int_o => open,
+ tim_int_o => tim_int_s,
+ retr_executed_i => retr_executed_s,
+ int_executed_i => int_executed_s,
+ int_pending_o => int_pending_s,
+ int_in_progress_o => int_in_progress_s
+ );
+
+ last_cycle_s <= not opc_multi_cycle_s or
+ (opc_multi_cycle_s and clk_second_cycle_i);
+
+ -----------------------------------------------------------------------------
+ -- Process machine_cycle
+ --
+ -- Purpose:
+ -- Generates the control signals that are basically needed for the
+ -- handling of a machine cycle.
+ --
+ machine_cycle: process (clk_mstate_i,
+ clk_second_cycle_i,
+ last_cycle_s,
+ ea_i,
+ assert_psen_s,
+ branch_taken_q,
+ int_pending_s)
+
+ variable need_address_v : boolean;
+
+ begin
+ -- default assignments
+ clk_assert_psen_o <= false;
+ pm_inc_pc_s <= false;
+ pm_write_pmem_addr_s <= false;
+ pm_read_pmem_o <= false;
+ bus_output_pcl_o <= false;
+ p2_output_pch_o <= false;
+ opc_read_bus_s <= false;
+ opc_inj_int_s <= false;
+ bus_read_bus_s <= false;
+
+ need_address_v := not clk_second_cycle_i or
+ (clk_second_cycle_i and assert_psen_s);
+
+ case clk_mstate_i is
+ when MSTATE1 =>
+ if need_address_v and not int_pending_s then
+ if ea_i = '0' then
+ pm_read_pmem_o <= true;
+ else
+ bus_read_bus_s <= true;
+ p2_output_pch_o <= true;
+ end if;
+ end if;
+
+ if not clk_second_cycle_i then
+ if not int_pending_s then
+ opc_read_bus_s <= true;
+ else
+ opc_inj_int_s <= true; -- inject interrupt call
+ end if;
+ end if;
+
+ when MSTATE2 =>
+ if need_address_v and not branch_taken_q and
+ not int_pending_s then
+ pm_inc_pc_s <= true;
+ end if;
+
+ when MSTATE3 =>
+ if need_address_v then
+ -- Theory of operation:
+ -- Program Memory address is updated at end of State 3 (or end of
+ -- State 2 in case of a RET). Address information is thus available
+ -- latest with State 4.
+ -- This is the time where we need information about access target
+ -- (internal or external = EA). EA information needs to be stable
+ -- until end of State 1.
+ pm_write_pmem_addr_s <= true;
+ end if;
+
+ when MSTATE4 =>
+ if ea_i = '1' and
+ ((not clk_second_cycle_i and assert_psen_s)
+ or last_cycle_s) then
+ clk_assert_psen_o <= true;
+ p2_output_pch_o <= true;
+ bus_output_pcl_o <= true;
+ end if;
+
+ when MSTATE5 =>
+ if ea_i = '1' and
+ (need_address_v or last_cycle_s) then
+ p2_output_pch_o <= true;
+ end if;
+
+ when others =>
+ -- pragma translate_off
+ assert false
+ report "Unkown machine state!"
+ severity error;
+ -- pragma translate_on
+
+ end case;
+
+ end process machine_cycle;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process decode
+ --
+ -- Purpose:
+ -- Indentifies each single instruction and steps through the related
+ -- execution sequence.
+ --
+ decode: process (alu_carry_i,
+ psw_aux_carry_i,
+ alu_da_overflow_i,
+ clk_mstate_i,
+ clk_second_cycle_i,
+ cnd_take_branch_i,
+ opc_opcode_s,
+ opc_mnemonic_s,
+ psw_carry_i,
+ psw_f0_i,
+ f1_q,
+ mb_q,
+ tim_int_s,
+ int_pending_s,
+ int_in_progress_s)
+
+ procedure address_indirect_3_f is
+ begin
+ -- apply dmem address from selected register for indirect mode
+ if opc_opcode_s(3) = '0' or enable_quartus_bugfix_c then
+ dm_read_dmem_o <= true;
+ dm_write_dmem_addr_o <= true;
+ dm_addr_type_o <= DM_PLAIN;
+ end if;
+ end;
+
+ procedure and_or_xor_add_4_f is
+ begin
+ -- write dmem contents to Temp Reg
+ dm_read_dmem_o <= true;
+ alu_write_temp_reg_o <= true;
+ end;
+
+ procedure and_or_xor_add_5_f (alu_op : alu_op_t) is
+ begin
+ -- perform ALU operation and store in Accumulator
+ alu_op_o <= alu_op;
+ alu_read_alu_o <= true;
+ alu_write_accu_o <= true;
+ end;
+
+ procedure cond_jump_c2_m1_f is
+ begin
+ -- store address in Program Counter low byte if branch has to
+ -- be taken
+-- if clk_mstate_i = MSTATE1 and cnd_take_branch_i then
+ pm_write_pcl_o <= true;
+ branch_taken_s <= true;
+-- end if;
+ end;
+
+ -- intermediate value of the Program Memory Bank Flag
+ variable mb_v : std_logic;
+
+ begin
+ -- default assignments
+ data_s <= (others => '-');
+ read_dec_s <= false;
+ branch_taken_s <= false;
+ clear_f1_s <= false;
+ cpl_f1_s <= false;
+ clear_mb_s <= false;
+ set_mb_s <= false;
+ add_inc_pc_s <= false;
+ assert_psen_s <= false;
+ stack_high_o <= false;
+ alu_write_accu_o <= false;
+ alu_write_shadow_o <= false;
+ alu_write_temp_reg_o <= false;
+ alu_p06_temp_reg_o <= false;
+ alu_p60_temp_reg_o <= false;
+ alu_read_alu_o <= false;
+ bus_write_bus_o <= false;
+ bus_bidir_bus_o <= false;
+ dm_write_dmem_addr_o <= false;
+ dm_write_dmem_s <= false;
+ dm_read_dmem_o <= false;
+ pm_write_pcl_o <= false;
+ pm_read_pcl_o <= false;
+ pm_write_pch_o <= false;
+ pm_read_pch_o <= false;
+ pm_addr_type_o <= PM_PC;
+ psw_read_psw_o <= false;
+ psw_read_sp_o <= false;
+ psw_write_psw_o <= false;
+ psw_write_sp_o <= false;
+ alu_op_o <= ALU_NOP;
+ alu_use_carry_o <= false;
+ alu_da_high_o <= false;
+ alu_accu_low_o <= false;
+ clk_assert_prog_o <= false;
+ clk_assert_rd_o <= false;
+ clk_assert_wr_o <= false;
+ cnd_branch_cond_o <= COND_ON_BIT;
+ cnd_compute_take_o <= false;
+ cnd_comp_value_o <= opc_opcode_s(7 downto 5);
+ dm_addr_type_o <= DM_REG;
+ tim_read_timer_o <= false;
+ tim_write_timer_o <= false;
+ tim_start_t_o <= false;
+ tim_start_cnt_o <= false;
+ tim_stop_tcnt_o <= false;
+ p1_write_p1_o <= false;
+ p1_read_p1_o <= false;
+ p1_read_reg_o <= false;
+ p2_write_p2_o <= false;
+ p2_write_exp_o <= false;
+ p2_read_p2_o <= false;
+ p2_read_reg_o <= false;
+ p2_read_exp_o <= false;
+ p2_output_exp_o <= false;
+ psw_special_data_o <= '0';
+ psw_inc_stackp_o <= false;
+ psw_dec_stackp_o <= false;
+ psw_write_carry_o <= false;
+ psw_write_aux_carry_o <= false;
+ psw_write_f0_o <= false;
+ psw_write_bs_o <= false;
+ jtf_executed_s <= false;
+ en_tcnti_s <= false;
+ dis_tcnti_s <= false;
+ en_i_s <= false;
+ dis_i_s <= false;
+ retr_executed_s <= false;
+ int_executed_s <= false;
+ add_write_pmem_addr_s <= false;
+ ent0_clk_s <= false;
+ add_read_bus_s <= false;
+
+ -- the Program Memory Bank Flag is held low when interrupts are in progress
+ -- according to the MCS-48 User's Manual
+ if int_in_progress_s then
+ mb_v := '0';
+ else
+ mb_v := mb_q;
+ end if;
+
+ -- prepare potential register indirect address mode
+ if not clk_second_cycle_i and clk_mstate_i = MSTATE2 then
+ data_s <= (others => '0');
+ if opc_opcode_s(3) = '1' then
+ data_s(2 downto 0) <= opc_opcode_s(2 downto 0);
+ else
+ data_s(2 downto 0) <= "00" & opc_opcode_s(0);
+ end if;
+
+ read_dec_s <= true;
+ dm_write_dmem_addr_o <= true;
+ dm_addr_type_o <= DM_REG;
+ end if;
+
+ case opc_mnemonic_s is
+
+ -- Mnemonic ADD ---------------------------------------------------------
+ when MN_ADD =>
+ case clk_mstate_i is
+ -- read RAM once for indirect address mode
+ when MSTATE3 =>
+ if not enable_quartus_bugfix_c or
+ opc_opcode_s(3) = '0' then
+ address_indirect_3_f;
+ end if;
+
+ -- store data from RAM to Temp Reg
+ when MSTATE4 =>
+ and_or_xor_add_4_f;
+
+ -- perform ADD and store in Accumulator
+ when MSTATE5 =>
+ and_or_xor_add_5_f(alu_op => ALU_ADD);
+
+ if opc_opcode_s(4) = '1' then
+ alu_use_carry_o <= true;
+ end if;
+
+ psw_special_data_o <= alu_carry_i;
+ psw_write_carry_o <= true;
+ psw_write_aux_carry_o <= true;
+
+ when others =>
+ null;
+
+ end case;
+
+ -- Mnemonic ADD_A_DATA --------------------------------------------------
+ when MN_ADD_A_DATA =>
+ assert_psen_s <= true;
+
+ if clk_second_cycle_i then
+ case clk_mstate_i is
+ -- write Temp Reg when contents of Program Memory is on bus
+ when MSTATE1 =>
+ alu_write_temp_reg_o <= true;
+
+ -- perform ADD and store in Accumulator
+ when MSTATE3 =>
+ and_or_xor_add_5_f(alu_op => ALU_ADD);
+
+ if opc_opcode_s(4) = '1' then
+ alu_use_carry_o <= true;
+ end if;
+
+ psw_special_data_o <= alu_carry_i;
+ psw_write_carry_o <= true;
+ psw_write_aux_carry_o <= true;
+
+ when others =>
+ null;
+
+ end case;
+
+ end if;
+
+ -- Mnemonic ANL ---------------------------------------------------------
+ when MN_ANL =>
+ case clk_mstate_i is
+ -- read RAM once for indirect address mode
+ when MSTATE3 =>
+ if not enable_quartus_bugfix_c or
+ opc_opcode_s(3) = '0' then
+ address_indirect_3_f;
+ end if;
+
+ -- store data from RAM to Temp Reg
+ when MSTATE4 =>
+ and_or_xor_add_4_f;
+
+ -- perform AND and store in Accumulator
+ when MSTATE5 =>
+ and_or_xor_add_5_f(alu_op => ALU_AND);
+
+ when others =>
+ null;
+
+ end case;
+
+ -- Mnemonic ANL_A_DATA --------------------------------------------------
+ when MN_ANL_A_DATA =>
+ assert_psen_s <= true;
+
+ if clk_second_cycle_i then
+ case clk_mstate_i is
+ -- write Temp Reg when contents of Program Memory is on bus
+ when MSTATE1 =>
+ alu_write_temp_reg_o <= true;
+
+ -- perform AND and store in Accumulator
+ when MSTATE3 =>
+ and_or_xor_add_5_f(alu_op => ALU_AND);
+
+ when others =>
+ null;
+
+ end case;
+
+ end if;
+
+ -- Mnemonic ANL_EXT -----------------------------------------------------
+ when MN_ANL_EXT =>
+ assert_psen_s <= true;
+
+ if not clk_second_cycle_i then
+ -- read port to Temp Reg
+ if clk_mstate_i = MSTATE5 then
+ if opc_opcode_s(1 downto 0) = "00" then
+ add_read_bus_s <= true;
+ elsif opc_opcode_s(1) = '0' then
+ p1_read_p1_o <= true;
+ p1_read_reg_o <= true;
+ else
+ p2_read_p2_o <= true;
+ p2_read_reg_o <= true;
+ end if;
+
+ alu_write_temp_reg_o <= true;
+ end if;
+
+ else
+ case clk_mstate_i is
+ -- write shadow Accumulator when contents of Program Memory is
+ -- on bus
+ when MSTATE1 =>
+ alu_write_shadow_o <= true;
+
+ -- loop shadow Accumulator through ALU to prevent update from
+ -- real Accumulator
+ when MSTATE2 =>
+ alu_read_alu_o <= true;
+ alu_write_shadow_o <= true;
+
+ -- write result of AND operation back to port
+ when MSTATE3 =>
+ alu_op_o <= ALU_AND;
+ alu_read_alu_o <= true;
+
+ if opc_opcode_s(1 downto 0) = "00" then
+ bus_write_bus_o <= true;
+ elsif opc_opcode_s(1) = '0' then
+ p1_write_p1_o <= true;
+ else
+ p2_write_p2_o <= true;
+ end if;
+
+ when others =>
+ null;
+
+ end case;
+
+ end if;
+
+ -- Mnemonic CALL --------------------------------------------------------
+ when MN_CALL =>
+ assert_psen_s <= true;
+
+ if not clk_second_cycle_i then
+ case clk_mstate_i is
+ -- read Stack Pointer and address Data Memory for low byte
+ -- also increment Program Counter to point to next instruction
+ when MSTATE3 =>
+ psw_read_sp_o <= true;
+ dm_write_dmem_addr_o <= true;
+ dm_addr_type_o <= DM_STACK;
+
+ -- only increment PC if this is not an injected CALL
+ -- injected CALLS are not located in Program Memory,
+ -- the PC points already to the instruction to be executed
+ -- after the interrupt
+ if not int_pending_s then
+ add_inc_pc_s <= true;
+ end if;
+
+ -- store Program Counter low byte on stack
+ when MSTATE4 =>
+ pm_read_pcl_o <= true;
+ dm_write_dmem_s <= true;
+
+ -- store Program Counter high byte and PSW on stack
+ -- increment Stack pointer
+ when MSTATE5 =>
+ psw_read_psw_o <= true;
+ pm_read_pch_o <= true;
+ dm_write_dmem_addr_o <= true;
+ dm_addr_type_o <= DM_STACK_HIGH;
+ dm_write_dmem_s <= true;
+ psw_inc_stackp_o <= true;
+
+ when others =>
+ null;
+
+ end case;
+
+ else
+ case clk_mstate_i is
+ -- store address in Program Counter low byte
+ when MSTATE1 =>
+ pm_write_pcl_o <= true;
+ branch_taken_s <= true;
+ if int_pending_s then
+ -- apply low part of vector address manually
+ data_s <= (others => '0');
+ data_s(1 downto 0) <= "11";
+ if tim_int_s then
+ data_s(2) <= '1';
+ end if;
+ read_dec_s <= true;
+ end if;
+
+ when MSTATE2 =>
+ pm_write_pch_o <= true;
+ read_dec_s <= true;
+ if not int_pending_s then
+ -- store high part of target address in Program Counter
+ data_s <= "0000" & mb_v & opc_opcode_s(7 downto 5);
+ else
+ -- apply high part of vector address manually
+ data_s <= (others => '0');
+ int_executed_s <= true;
+ end if;
+
+ when others =>
+ null;
+
+ end case;
+
+ end if;
+
+ -- Mnemonic CLR_A -------------------------------------------------------
+ when MN_CLR_A =>
+ -- write CLR output of ALU to Accumulator
+ if clk_mstate_i = MSTATE3 then
+ alu_op_o <= ALU_CLR;
+ alu_read_alu_o <= true;
+ alu_write_accu_o <= true;
+ end if;
+
+ -- Mnemonic CLR_C -------------------------------------------------------
+ when MN_CLR_C =>
+ -- store 0 to Carry
+ if clk_mstate_i = MSTATE3 then
+ psw_special_data_o <= '0';
+ psw_write_carry_o <= true;
+ end if;
+
+ -- Mnemonic CLR_F -------------------------------------------------------
+ when MN_CLR_F =>
+ -- store 0 to selected flag
+ if clk_mstate_i = MSTATE3 then
+ if opc_opcode_s(5) = '0' then
+ psw_special_data_o <= '0';
+ psw_write_f0_o <= true;
+ else
+ clear_f1_s <= true;
+ end if;
+
+ end if;
+
+ -- Mnemonic CPL_A -------------------------------------------------------
+ when MN_CPL_A =>
+ -- write CPL output of ALU to Accumulator
+ if clk_mstate_i = MSTATE3 then
+ alu_op_o <= ALU_CPL;
+ alu_read_alu_o <= true;
+ alu_write_accu_o <= true;
+ end if;
+
+ -- Mnemnonic CPL_C ------------------------------------------------------
+ when MN_CPL_C =>
+ -- write inverse of Carry to PSW
+ if clk_mstate_i = MSTATE3 then
+ psw_special_data_o <= not psw_carry_i;
+ psw_write_carry_o <= true;
+ end if;
+
+ -- Mnemonic CPL_F -------------------------------------------------------
+ when MN_CPL_f =>
+ -- write inverse of selected flag back to flag
+ if clk_mstate_i = MSTATE3 then
+ if opc_opcode_s(5) = '0' then
+ psw_special_data_o <= not psw_f0_i;
+ psw_write_f0_o <= true;
+ else
+ cpl_f1_s <= true;
+ end if;
+
+ end if;
+
+ -- Mnemonic DA ----------------------------------------------------------
+ when MN_DA =>
+ alu_op_o <= ALU_ADD;
+
+ case clk_mstate_i is
+ -- Step 1: Preload Temp Reg with 0x06
+ when MSTATE3 =>
+ alu_p06_temp_reg_o <= true;
+
+ -- Step 2: Check Auxiliary Carry and overflow on low nibble
+ -- Add 0x06 to shadow Accumulator if one is true
+ when MSTATE4 =>
+ if psw_aux_carry_i = '1' or alu_da_overflow_i then
+ alu_read_alu_o <= true;
+ alu_write_shadow_o <= true;
+ end if;
+
+ -- preload Temp Reg with 0x60
+ alu_p60_temp_reg_o <= true;
+
+ -- Step 3: Check overflow on high nibble
+ -- Add 0x60 to shadow Accumulator if true and store result
+ -- in Accumulator and PSW (only Carry)
+ when MSTATE5 =>
+ alu_da_high_o <= true;
+
+ if alu_da_overflow_i then
+ psw_special_data_o <= alu_carry_i;
+ else
+ alu_op_o <= ALU_NOP;
+ psw_special_data_o <= '0';
+ end if;
+ alu_read_alu_o <= true;
+ alu_write_accu_o <= true;
+ psw_write_carry_o <= true;
+
+ when others =>
+ null;
+
+ end case;
+
+ -- Mnemonic DEC ---------------------------------------------------------
+ when MN_DEC =>
+ case clk_mstate_i is
+ when MSTATE4 =>
+ -- DEC Rr: store data from RAM to shadow Accumulator
+ if opc_opcode_s(6) = '1' then
+ dm_read_dmem_o <= true;
+ alu_write_shadow_o <= true;
+ end if;
+
+ when MSTATE5 =>
+ alu_op_o <= ALU_DEC;
+ alu_read_alu_o <= true;
+
+ if opc_opcode_s(6) = '0' then
+ -- write DEC of Accumulator to Accumulator
+ alu_write_accu_o <= true;
+ else
+ -- store DEC of shadow Accumulator back to dmem
+ dm_write_dmem_s <= true;
+ end if;
+
+ when others =>
+ null;
+
+ end case;
+
+ -- Mnemonic DIS_EN_I ----------------------------------------------------
+ when MN_DIS_EN_I =>
+ if clk_mstate_i = MSTATE3 then
+ if opc_opcode_s(4) = '1' then
+ dis_i_s <= true;
+ else
+ en_i_s <= true;
+ end if;
+ end if;
+
+ -- Mnemonic DIS_EN_TCNTI ------------------------------------------------
+ when MN_DIS_EN_TCNTI =>
+ if clk_mstate_i = MSTATE3 then
+ if opc_opcode_s(4) = '1' then
+ dis_tcnti_s <= true;
+ else
+ en_tcnti_s <= true;
+ end if;
+ end if;
+
+ -- Mnemonic DJNZ --------------------------------------------------------
+ when MN_DJNZ =>
+ assert_psen_s <= true;
+
+ if not clk_second_cycle_i then
+ case clk_mstate_i is
+ -- store data from RAM to shadow Accumulator
+ when MSTATE4 =>
+ dm_read_dmem_o <= true;
+ alu_write_shadow_o <= true;
+
+ -- write DEC result of shadow Accumulator back to dmem and
+ -- conditional branch logic
+ when MSTATE5 =>
+ alu_op_o <= ALU_DEC;
+ alu_read_alu_o <= true;
+ dm_write_dmem_s <= true;
+
+ cnd_compute_take_o <= true;
+ cnd_branch_cond_o <= COND_Z;
+ cnd_comp_value_o(0) <= '0';
+
+ when others =>
+ null;
+
+ end case;
+
+ else
+ -- store address in Program Counter low byte if branch has to
+ -- be taken
+ if clk_mstate_i = MSTATE1 and cnd_take_branch_i then
+ cond_jump_c2_m1_f;
+ end if;
+
+ end if;
+
+ -- Mnemonic ENT0_CLK ----------------------------------------------------
+ when MN_ENT0_CLK =>
+ if clk_mstate_i = MSTATE3 then
+ ent0_clk_s <= true;
+ end if;
+
+ -- Mnemonic IN ----------------------------------------------------------
+ when MN_IN =>
+ -- read Port and store in Accumulator
+ if clk_second_cycle_i and clk_mstate_i = MSTATE2 then
+ alu_write_accu_o <= true;
+
+ if opc_opcode_s(1) = '0' then
+ p1_read_p1_o <= true;
+ else
+ p2_read_p2_o <= true;
+ end if;
+ end if;
+
+ -- Mnemonic INS ---------------------------------------------------------
+ when MN_INS =>
+ -- read BUS and store in Accumulator
+ if clk_second_cycle_i and clk_mstate_i = MSTATE2 then
+ alu_write_accu_o <= true;
+
+ add_read_bus_s <= true;
+ end if;
+
+ -- Mnemonic INC ---------------------------------------------------------
+ when MN_INC =>
+ case clk_mstate_i is
+ -- read RAM once for indirect address mode
+ when MSTATE3 =>
+ if not enable_quartus_bugfix_c or
+ opc_opcode_s(3) = '0' then
+ address_indirect_3_f;
+ end if;
+
+ when MSTATE4 =>
+ -- INC Rr; INC @ Rr: store data from RAM to shadow Accumulator
+ if opc_opcode_s(3 downto 2) /= "01" then
+ dm_read_dmem_o <= true;
+ alu_write_shadow_o <= true;
+ end if;
+
+ when MSTATE5 =>
+ alu_op_o <= ALU_INC;
+ alu_read_alu_o <= true;
+
+ if opc_opcode_s(3 downto 2) = "01" then
+ -- write INC output of ALU to Accumulator
+ alu_write_accu_o <= true;
+ else
+ -- store INC of shadow Accumulator back to dmem
+ dm_write_dmem_s <= true;
+ end if;
+
+ when others =>
+ null;
+
+ end case;
+
+ -- Mnemonic JBB ---------------------------------------------------------
+ when MN_JBB =>
+ assert_psen_s <= true;
+ cnd_branch_cond_o <= COND_ON_BIT;
+
+ if not clk_second_cycle_i then
+ -- read Accumulator and start branch calculation
+ if clk_mstate_i = MSTATE3 then
+ alu_read_alu_o <= true;
+ cnd_compute_take_o <= true;
+ -- cnd_comp_value_o is ok by default assignment
+ end if;
+
+ else
+ -- store address in Program Counter low byte if branch has to
+ -- be taken
+ if clk_mstate_i = MSTATE1 and cnd_take_branch_i then
+ cond_jump_c2_m1_f;
+ end if;
+
+ end if;
+
+ -- Mnemonic JC ----------------------------------------------------------
+ when MN_JC =>
+ assert_psen_s <= true;
+ cnd_branch_cond_o <= COND_C;
+
+ if not clk_second_cycle_i then
+ -- start branch calculation
+ if clk_mstate_i = MSTATE3 then
+ cnd_compute_take_o <= true;
+ cnd_comp_value_o(0) <= opc_opcode_s(4);
+ end if;
+
+ else
+ -- store address in Program Counter low byte if branch has to
+ -- be taken
+ if clk_mstate_i = MSTATE1 and cnd_take_branch_i then
+ cond_jump_c2_m1_f;
+ end if;
+
+ end if;
+
+ -- Mnemonic JF ----------------------------------------------------------
+ when MN_JF =>
+ assert_psen_s <= true;
+
+ if not clk_second_cycle_i then
+ -- start branch calculation
+ if clk_mstate_i = MSTATE3 then
+ cnd_compute_take_o <= true;
+ if opc_opcode_s(7) = '1' then
+ -- JF0
+ cnd_branch_cond_o <= COND_F0;
+ else
+ -- JF1
+ cnd_branch_cond_o <= COND_F1;
+ end if;
+
+ end if;
+
+ else
+ -- store address in Program Counter low byte if branch has to
+ -- be taken
+ if clk_mstate_i = MSTATE1 and cnd_take_branch_i then
+ cond_jump_c2_m1_f;
+ end if;
+
+ end if;
+
+
+ -- Mnemonic JMP ---------------------------------------------------------
+ when MN_JMP =>
+ assert_psen_s <= true;
+
+ if clk_second_cycle_i then
+ case clk_mstate_i is
+ -- store address in Program Counter low byte
+ when MSTATE1 =>
+ pm_write_pcl_o <= true;
+ branch_taken_s <= true;
+
+ -- store high part of target address in Program Counter
+ when MSTATE2 =>
+ data_s <= "0000" & mb_v & opc_opcode_s(7 downto 5);
+ read_dec_s <= true;
+ pm_write_pch_o <= true;
+
+ when others =>
+ null;
+
+ end case;
+
+ end if;
+
+ -- Mnemonic JMPP --------------------------------------------------------
+ when MN_JMPP =>
+ assert_psen_s <= true;
+
+ if not clk_second_cycle_i then
+ -- write Accumulator to Program Memory address
+ -- (skip page offset update from Program Counter)
+ if clk_mstate_i = MSTATE3 then
+ alu_read_alu_o <= true;
+ pm_addr_type_o <= PM_PAGE;
+ end if;
+
+ else
+ if clk_mstate_i = MSTATE1 then
+ -- store address in Program Counter low byte
+ pm_write_pcl_o <= true;
+ branch_taken_s <= true;
+ end if;
+
+ end if;
+
+ -- Mnemonic JNI ---------------------------------------------------------
+ when MN_JNI =>
+ assert_psen_s <= true;
+ cnd_branch_cond_o <= COND_INT;
+
+ if not clk_second_cycle_i then
+ -- start branch calculation
+ if clk_mstate_i = MSTATE3 then
+ cnd_compute_take_o <= true;
+ end if;
+
+ else
+ -- store address in Program Counter low byte if branch has to
+ -- be taken
+ if clk_mstate_i = MSTATE1 and cnd_take_branch_i then
+ cond_jump_c2_m1_f;
+ end if;
+
+ end if;
+
+ -- Mnemonic JT ----------------------------------------------------------
+ when MN_JT =>
+ assert_psen_s <= true;
+ if opc_opcode_s(6) = '0' then
+ cnd_branch_cond_o <= COND_T0;
+ else
+ cnd_branch_cond_o <= COND_T1;
+ end if;
+
+ if not clk_second_cycle_i then
+ -- start branch calculation
+ if clk_mstate_i = MSTATE3 then
+ cnd_compute_take_o <= true;
+ cnd_comp_value_o(0) <= opc_opcode_s(4);
+ end if;
+
+ else
+ -- store address in Program Counter low byte if branch has to
+ -- be taken
+ if clk_mstate_i = MSTATE1 and cnd_take_branch_i then
+ cond_jump_c2_m1_f;
+ end if;
+
+ end if;
+
+ -- Mnemonic JTF ---------------------------------------------------------
+ when MN_JTF =>
+ assert_psen_s <= true;
+ cnd_branch_cond_o <= COND_TF;
+
+ if not clk_second_cycle_i then
+ -- start branch calculation
+ if clk_mstate_i = MSTATE3 then
+ cnd_compute_take_o <= true;
+ jtf_executed_s <= true;
+ end if;
+
+ else
+ -- store address in Program Counter low byte if branch has to
+ -- be taken
+ if clk_mstate_i = MSTATE1 and cnd_take_branch_i then
+ cond_jump_c2_m1_f;
+ end if;
+
+ end if;
+
+ -- Mnemonic JZ ----------------------------------------------------------
+ when MN_JZ =>
+ assert_psen_s <= true;
+ cnd_branch_cond_o <= COND_Z;
+
+ if not clk_second_cycle_i then
+ -- read Accumulator and start branch calculation
+ if clk_mstate_i = MSTATE3 then
+ alu_read_alu_o <= true;
+ cnd_compute_take_o <= true;
+ cnd_comp_value_o(0) <= opc_opcode_s(6);
+ end if;
+
+ else
+ -- store address in Program Counter low byte if branch has to
+ -- be taken
+ if clk_mstate_i = MSTATE1 and cnd_take_branch_i then
+ cond_jump_c2_m1_f;
+ end if;
+
+ end if;
+
+ -- Mnemonic MOV_A_DATA --------------------------------------------------
+ when MN_MOV_A_DATA =>
+ assert_psen_s <= true;
+
+ -- Write Accumulator when contents of Program Memory is on bus
+ -- during machine state 1 of second cycle.
+ if clk_second_cycle_i and clk_mstate_i = MSTATE1 then
+ alu_write_accu_o <= true;
+ end if;
+
+ -- Mnemonic MOV_A_RR ----------------------------------------------------
+ when MN_MOV_A_RR =>
+ case clk_mstate_i is
+ -- read RAM once for indirect address mode
+ when MSTATE3 =>
+ if not enable_quartus_bugfix_c or
+ opc_opcode_s(3) = '0' then
+ address_indirect_3_f;
+ end if;
+
+ -- read data from RAM and store in Accumulator
+ when MSTATE4 =>
+ and_or_xor_add_4_f;
+ alu_write_accu_o <= true;
+
+ when others =>
+ null;
+
+ end case;
+
+ -- Mnemonic MOV_A_PSW ---------------------------------------------------
+ when MN_MOV_A_PSW =>
+ if clk_mstate_i = MSTATE3 then
+ psw_read_psw_o <= true;
+ psw_read_sp_o <= true;
+ alu_write_accu_o <= true;
+ end if;
+
+ -- Mnemoniv MOV_PSW_A ---------------------------------------------------
+ when MN_MOV_PSW_A =>
+ if clk_mstate_i = MSTATE3 then
+ alu_read_alu_o <= true;
+ psw_write_psw_o <= true;
+ psw_write_sp_o <= true;
+ end if;
+
+ -- Mnemonic MOV_RR ------------------------------------------------------
+ when MN_MOV_RR =>
+ case clk_mstate_i is
+ -- read RAM once for indirect address mode
+ when MSTATE3 =>
+ if not enable_quartus_bugfix_c or
+ opc_opcode_s(3) = '0' then
+ address_indirect_3_f;
+ end if;
+
+ -- write Accumulator to dmem
+ when MSTATE5 =>
+ alu_read_alu_o <= true;
+ dm_write_dmem_s <= true;
+
+ when others =>
+ null;
+
+ end case;
+
+ -- Mnemonic MOV_RR_DATA -------------------------------------------------
+ when MN_MOV_RR_DATA =>
+ assert_psen_s <= true;
+
+ -- read RAM once for indirect address mode
+ if not clk_second_cycle_i and clk_mstate_i = MSTATE3 then
+ if not enable_quartus_bugfix_c or
+ opc_opcode_s(3) = '0' then
+ address_indirect_3_f;
+ end if;
+ end if;
+
+ -- Write Data Memory when contents of Program Memory is on bus
+ -- during machine state 1 of second cycle.
+ if clk_second_cycle_i and clk_mstate_i = MSTATE1 then
+ dm_write_dmem_s <= true;
+ end if;
+
+ -- Mnemonic MOV_T -------------------------------------------------------
+ when MN_MOV_T =>
+ if clk_mstate_i = MSTATE3 then
+ if opc_opcode_s(5) = '1' then
+ alu_read_alu_o <= true; -- MOV T, A
+ tim_write_timer_o <= true;
+ else
+ tim_read_timer_o <= true; -- MOV A, T
+ alu_write_accu_o <= true;
+ end if;
+ end if;
+
+ -- Mnemonic OUTD_PP_A ---------------------------------------------------
+ when MN_OUTD_PP_A =>
+ clk_assert_prog_o <= true;
+
+ if not clk_second_cycle_i then
+ case clk_mstate_i is
+ -- propagate expander port number to Port 2
+ when MSTATE3 =>
+
+ data_s(7 downto 4) <= (others => '0');
+ data_s(1 downto 0) <= opc_opcode_s(1 downto 0);
+ -- decide which 8243 command to use
+ case opc_opcode_s(7 downto 4) is
+ when "1001" =>
+ data_s(3 downto 2) <= "11"; -- ANLD command
+ when "1000" =>
+ data_s(3 downto 2) <= "10"; -- ORLD command
+ when "0011" =>
+ data_s(3 downto 2) <= "01"; -- MOVD command
+ when others =>
+ null;
+ end case;
+
+ read_dec_s <= true;
+ p2_write_exp_o <= true;
+
+ -- output expander port number on Port 2 while active edge of PROG
+ -- write Accumulator to expander port
+ when MSTATE4 =>
+ p2_output_exp_o <= true;
+
+ alu_read_alu_o <= true;
+ p2_write_exp_o <= true;
+
+ when MSTATE5 =>
+ p2_output_exp_o <= true;
+
+ when others =>
+ null;
+
+ end case;
+
+ else
+ -- hold expander port until inactive edge of PROG
+ if clk_mstate_i = MSTATE1 or clk_mstate_i = MSTATE2 then
+ p2_output_exp_o <= true;
+ end if;
+
+ end if;
+
+ -- Mnemonic MOVD_A_PP ---------------------------------------------------
+ when MN_MOVD_A_PP =>
+ clk_assert_prog_o <= true;
+
+ if not clk_second_cycle_i then
+ case clk_mstate_i is
+ -- propagate expander port number to Port 2
+ when MSTATE3 =>
+ data_s <= "0000" &
+ "00" & -- 8243 command: read
+ opc_opcode_s(1 downto 0);
+ read_dec_s <= true;
+ p2_write_exp_o <= true;
+
+ -- output expander port number on Port 2 while active edge of PROG
+ -- write 1's to expander port to set lower nibble of Port 2 to input
+ when MSTATE4 =>
+ p2_output_exp_o <= true;
+
+ data_s(nibble_t'range) <= (others => '1');
+ read_dec_s <= true;
+ p2_write_exp_o <= true;
+
+ when MSTATE5 =>
+ p2_output_exp_o <= true;
+
+ when others =>
+ null;
+
+ end case;
+
+ else
+ case clk_mstate_i is
+ -- hold expander port until inactive edge of PROG
+ when MSTATE1 =>
+ p2_output_exp_o <= true;
+
+ -- hold expander port until inactive edge of PROG
+ -- write Accumulator with nibble of expander port
+ when MSTATE2 =>
+ p2_read_p2_o <= true;
+ p2_output_exp_o <= true;
+ p2_read_exp_o <= true;
+ alu_write_accu_o <= true;
+
+ when others =>
+ null;
+
+ end case;
+
+ end if;
+
+ -- Mnemonic MOVP --------------------------------------------------------
+ when MN_MOVP =>
+ assert_psen_s <= true;
+
+ if not clk_second_cycle_i then
+ -- write Accumulator to Program Memory address
+ -- (skip page offset update from Program Counter)
+ if clk_mstate_i = MSTATE3 then
+ alu_read_alu_o <= true;
+ if opc_opcode_s(6) = '0' then
+ pm_addr_type_o <= PM_PAGE;
+ else
+ pm_addr_type_o <= PM_PAGE3;
+ end if;
+ end if;
+
+ else
+ if clk_mstate_i = MSTATE1 then
+ -- store data from Program Memory in Accumulator
+ alu_write_accu_o <= true;
+ -- trick & treat to prevent additional PC increment
+ -- our branch target is the previously incremented PC!
+ branch_taken_s <= true;
+ end if;
+
+ end if;
+
+ -- Mnemonic MOVX --------------------------------------------------------
+ when MN_MOVX =>
+ bus_bidir_bus_o <= true;
+
+ if opc_opcode_s(4) = '0' then
+ clk_assert_rd_o <= true;
+ else
+ clk_assert_wr_o <= true;
+ end if;
+
+ if not clk_second_cycle_i then
+ case clk_mstate_i is
+ -- read dmem and put contents on BUS as external address
+ when MSTATE3 =>
+ dm_read_dmem_o <= true;
+ bus_write_bus_o <= true;
+
+ -- store contents of Accumulator to BUS
+ when MSTATE5 =>
+ if opc_opcode_s(4) = '1' then
+ alu_read_alu_o <= true;
+ bus_write_bus_o <= true;
+ end if;
+
+ when others =>
+ null;
+ end case;
+
+ else
+ if clk_mstate_i = MSTATE1 then
+ if opc_opcode_s(4) = '0' then
+ -- store contents of BUS in Accumulator
+ add_read_bus_s <= true;
+ alu_write_accu_o <= true;
+ else
+ -- store contents of Accumulator to BUS
+ alu_read_alu_o <= true;
+ bus_write_bus_o <= true;
+ end if;
+ end if;
+
+ end if;
+
+ -- Mnemonic NOP ---------------------------------------------------------
+ when MN_NOP =>
+ -- nothing to do
+
+ -- Mnemonic ORL ---------------------------------------------------------
+ when MN_ORL =>
+ case clk_mstate_i is
+ -- read RAM once for indirect address mode
+ when MSTATE3 =>
+ if not enable_quartus_bugfix_c or
+ opc_opcode_s(3) = '0' then
+ address_indirect_3_f;
+ end if;
+
+ -- store data from RAM to Temp Reg
+ when MSTATE4 =>
+ and_or_xor_add_4_f;
+
+ -- perform OR and store in Accumulator
+ when MSTATE5 =>
+ and_or_xor_add_5_f(alu_op => ALU_OR);
+
+ when others =>
+ null;
+
+ end case;
+
+ -- Mnemonic ORL_A_DATA --------------------------------------------------
+ when MN_ORL_A_DATA =>
+ assert_psen_s <= true;
+
+ if clk_second_cycle_i then
+ case clk_mstate_i is
+ -- write Temp Reg when contents of Program Memory is on bus
+ when MSTATE1 =>
+ alu_write_temp_reg_o <= true;
+
+ -- perform OR and store in Accumulator
+ when MSTATE3 =>
+ and_or_xor_add_5_f(alu_op => ALU_OR);
+
+ when others =>
+ null;
+
+ end case;
+
+ end if;
+
+ -- Mnemonic ORL_EXT -----------------------------------------------------
+ when MN_ORL_EXT =>
+ assert_psen_s <= true;
+
+ if not clk_second_cycle_i then
+ -- read port to Temp Reg
+ if clk_mstate_i = MSTATE5 then
+ if opc_opcode_s(1 downto 0) = "00" then
+ add_read_bus_s <= true;
+ elsif opc_opcode_s(1) = '0' then
+ p1_read_p1_o <= true;
+ p1_read_reg_o <= true;
+ else
+ p2_read_p2_o <= true;
+ p2_read_reg_o <= true;
+ end if;
+
+ alu_write_temp_reg_o <= true;
+ end if;
+
+ else
+ case clk_mstate_i is
+ -- write shadow Accumulator when contents of Program Memory is
+ -- on bus
+ when MSTATE1 =>
+ alu_write_shadow_o <= true;
+
+ -- loop shadow Accumulator through ALU to prevent update from
+ -- real Accumulator
+ when MSTATE2 =>
+ alu_read_alu_o <= true;
+ alu_write_shadow_o <= true;
+
+ -- write result of OR operation back to port
+ when MSTATE3 =>
+ alu_op_o <= ALU_OR;
+ alu_read_alu_o <= true;
+
+ if opc_opcode_s(1 downto 0) = "00" then
+ bus_write_bus_o <= true;
+ elsif opc_opcode_s(1) = '0' then
+ p1_write_p1_o <= true;
+ else
+ p2_write_p2_o <= true;
+ end if;
+
+ when others =>
+ null;
+
+ end case;
+
+ end if;
+
+ -- Mnemonic OUTL_EXT ----------------------------------------------------
+ when MN_OUTL_EXT =>
+ -- read Accumulator and store in Port/BUS output register
+ if clk_second_cycle_i and clk_mstate_i = MSTATE4 then
+ alu_read_alu_o <= true;
+
+ if opc_opcode_s(4) = '1' then
+ if opc_opcode_s(1) = '0' then
+ p1_write_p1_o <= true;
+ else
+ p2_write_p2_o <= true;
+ end if;
+
+ else
+ bus_write_bus_o <= true;
+
+ end if;
+
+ end if;
+
+ -- Mnemonic RET ---------------------------------------------------------
+ when MN_RET =>
+ if not clk_second_cycle_i then
+ case clk_mstate_i is
+ -- decrement Stack Pointer
+ when MSTATE3 =>
+ psw_dec_stackp_o <= true;
+
+ -- read Stack Pointer and address Data Memory for low byte
+ when MSTATE4 =>
+ psw_read_sp_o <= true;
+ dm_write_dmem_addr_o <= true;
+ dm_addr_type_o <= DM_STACK;
+
+ -- read Data Memory and store to Program Counter low
+ -- prepare address to Data memory for high byte
+ when MSTATE5 =>
+ dm_read_dmem_o <= true;
+ pm_write_pcl_o <= true;
+ dm_write_dmem_addr_o <= true;
+ dm_addr_type_o <= DM_STACK_HIGH;
+
+ when others =>
+ null;
+
+ end case;
+
+ else
+ case clk_mstate_i is
+ -- read Data Memory and store to Program Counter high and PSW
+ when MSTATE1 =>
+ dm_read_dmem_o <= true;
+ pm_write_pch_o <= true;
+ if opc_opcode_s(4) = '1' then
+ psw_write_psw_o <= true;
+ retr_executed_s <= true;
+ end if;
+
+ when MSTATE2 =>
+ add_write_pmem_addr_s <= true;
+
+ when others =>
+ null;
+
+ end case;
+
+ end if;
+
+ -- Mnemonic RL ----------------------------------------------------------
+ when MN_RL =>
+ if clk_mstate_i = MSTATE3 then
+ alu_op_o <= ALU_RL;
+ alu_read_alu_o <= true;
+ alu_write_accu_o <= true;
+
+ if opc_opcode_s(4) = '1' then
+ psw_special_data_o <= alu_carry_i;
+ psw_write_carry_o <= true;
+ alu_use_carry_o <= true;
+ end if;
+ end if;
+
+ -- Mnemonic RR ----------------------------------------------------------
+ when MN_RR =>
+ if clk_mstate_i = MSTATE3 then
+ alu_op_o <= ALU_RR;
+ alu_read_alu_o <= true;
+ alu_write_accu_o <= true;
+
+ if opc_opcode_s(4) = '0' then
+ psw_special_data_o <= alu_carry_i;
+ psw_write_carry_o <= true;
+ alu_use_carry_o <= true;
+ end if;
+ end if;
+
+ -- Mnemonic SEL_MB ------------------------------------------------------
+ when MN_SEL_MB =>
+ if clk_mstate_i = MSTATE3 then
+ if opc_opcode_s(4) = '1' then
+ set_mb_s <= true;
+ else
+ clear_mb_s <= true;
+ end if;
+ end if;
+
+ -- Mnemonic SEL_RB ------------------------------------------------------
+ when MN_SEL_RB =>
+ if clk_mstate_i = MSTATE3 then
+ psw_special_data_o <= opc_opcode_s(4);
+ psw_write_bs_o <= true;
+ end if;
+
+ -- Mnemonic STOP_TCNT ---------------------------------------------------
+ when MN_STOP_TCNT =>
+ if clk_mstate_i = MSTATE3 then
+ tim_stop_tcnt_o <= true;
+ end if;
+
+ -- Mnemonic STRT --------------------------------------------------------
+ when MN_STRT =>
+ if clk_mstate_i = MSTATE3 then
+ if opc_opcode_s(4) = '1' then
+ tim_start_t_o <= true;
+ else
+ tim_start_cnt_o <= true;
+ end if;
+ end if;
+
+ -- Mnemonic SWAP --------------------------------------------------------
+ when MN_SWAP =>
+ alu_op_o <= ALU_SWAP;
+
+ if clk_mstate_i = MSTATE3 then
+ alu_read_alu_o <= true;
+ alu_write_accu_o <= true;
+ end if;
+
+ -- Mnemonic XCH ---------------------------------------------------------
+ when MN_XCH =>
+ case clk_mstate_i is
+ -- read RAM once for indirect address mode
+ when MSTATE3 =>
+ if not enable_quartus_bugfix_c or
+ opc_opcode_s(3) = '0' then
+ address_indirect_3_f;
+ end if;
+
+ -- store data from RAM in Accumulator and Temp Reg
+ -- Accumulator is already shadowed!
+ when MSTATE4 =>
+ dm_read_dmem_o <= true;
+ alu_write_accu_o <= true;
+ alu_write_temp_reg_o <= true;
+ if opc_opcode_s(4) = '1' then
+ -- XCHD
+ -- only write lower nibble of Accumulator
+ alu_accu_low_o <= true;
+ end if;
+
+ -- store data from shadow (previous) Accumulator to dmem
+ when MSTATE5 =>
+ dm_write_dmem_s <= true;
+ alu_read_alu_o <= true;
+ if opc_opcode_s(4) = '1' then
+ -- XCHD
+ -- concatenate shadow Accumulator and Temp Reg
+ alu_op_o <= ALU_CONCAT;
+ end if;
+
+ when others =>
+ null;
+
+ end case;
+
+ -- Mnemonic XRL ---------------------------------------------------------
+ when MN_XRL =>
+ case clk_mstate_i is
+ -- read RAM once for indirect address mode
+ when MSTATE3 =>
+ if not enable_quartus_bugfix_c or
+ opc_opcode_s(3) = '0' then
+ address_indirect_3_f;
+ end if;
+
+ -- store data from RAM to Temp Reg
+ when MSTATE4 =>
+ and_or_xor_add_4_f;
+
+ -- perform XOR and store in Accumulator
+ when MSTATE5 =>
+ and_or_xor_add_5_f(alu_op => ALU_XOR);
+
+ when others =>
+ null;
+
+ end case;
+
+ -- Mnemonic XRL_A_DATA --------------------------------------------------
+ when MN_XRL_A_DATA =>
+ assert_psen_s <= true;
+
+ if clk_second_cycle_i then
+ case clk_mstate_i is
+ -- write Temp Reg when contents of Program Memory is on bus
+ when MSTATE1 =>
+ alu_write_temp_reg_o <= true;
+
+ -- perform XOR and store in Accumulator
+ when MSTATE3 =>
+ and_or_xor_add_5_f(alu_op => ALU_XOR);
+
+ when others =>
+ null;
+
+ end case;
+
+ end if;
+
+ -- Unimplemented mnemonic -----------------------------------------------
+ when others =>
+ -- this will behave like a NOP
+
+ -- pragma translate_off
+ assert false
+ report "Mnemonic not yet implemented."
+ severity warning;
+ -- pragma translate_on
+
+ end case;
+
+ end process decode;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process regs
+ --
+ -- Purpose:
+ -- Implements the various registes.
+ --
+ regs: process (res_i, clk_i)
+ begin
+ if res_i = res_active_c then
+ branch_taken_q <= false;
+ f1_q <= '0';
+ mb_q <= '0';
+ t0_dir_q <= '0';
+ -- pragma translate_off
+ istrobe_res_q <= '1';
+ istrobe_q <= '0';
+ injected_int_q <= '0';
+ -- pragma translate_on
+
+ elsif clk_i'event and clk_i = clk_active_c then
+ if en_clk_i then
+
+ -- branch taken flag
+ if branch_taken_s then
+ branch_taken_q <= true;
+ elsif clk_mstate_i = MSTATE5 then
+ -- release flag when new instruction starts
+ branch_taken_q <= false;
+ end if;
+
+ -- Flag 1
+ if clear_f1_s then
+ f1_q <= '0';
+ elsif cpl_f1_s then
+ f1_q <= not f1_q;
+ end if;
+
+ -- Memory Bank select
+ if clear_mb_s then
+ mb_q <= '0';
+ elsif set_mb_s then
+ mb_q <= '1';
+ end if;
+
+ -- T0 direction selection
+ if ent0_clk_s then
+ t0_dir_q <= '1';
+ end if;
+
+ -- pragma translate_off
+ -- Marker for injected instruction ------------------------------------
+ if opc_inj_int_s then
+ injected_int_q <= '1';
+ elsif clk_mstate_i = MSTATE5 and last_cycle_s then
+ injected_int_q <= '0';
+ end if;
+
+ -- Remove istrobe after reset suppression -----------------------------
+ if clk_mstate_i = MSTATE5 and last_cycle_s then
+ istrobe_res_q <= '0';
+ end if;
+ -- pragma translate_on
+
+ end if;
+
+ -- pragma translate_off
+ -- Instruction Strobe ---------------------------------------------------
+ if clk_mstate_i = MSTATE5 and last_cycle_s and
+ injected_int_q = '0' then
+ if istrobe_res_q = '0' then
+ istrobe_q <= '1';
+ end if;
+ else
+ istrobe_q <= '0';
+ end if;
+ -- pragma translate_on
+
+ end if;
+
+ end process regs;
+ --
+ -----------------------------------------------------------------------------
+
+ -- pragma translate_off
+ -- assign to global signal for testbench
+ tb_istrobe_s <= istrobe_q;
+ -- pragma translate_on
+
+
+ -----------------------------------------------------------------------------
+ -- Output Mapping.
+ -----------------------------------------------------------------------------
+ clk_multi_cycle_o <= opc_multi_cycle_s;
+ cnd_f1_o <= f1_q;
+ cnd_tf_o <= tf_s;
+ data_o <= data_s
+ when read_dec_s else
+ (others => bus_idle_level_c);
+ dm_write_dmem_o <= dm_write_dmem_s and en_clk_i;
+ pm_inc_pc_o <= pm_inc_pc_s or add_inc_pc_s;
+ pm_write_pmem_addr_o <= pm_write_pmem_addr_s or add_write_pmem_addr_s;
+ t0_dir_o <= t0_dir_q;
+ bus_read_bus_o <= bus_read_bus_s or add_read_bus_s;
+
+end rtl;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: decoder.vhd,v $
+-- Revision 1.15 2004/09/12 00:35:44 arniml
+-- Fix bug report:
+-- "PSENn Timing"
+-- PSEN is now only asserted for the second cycle if explicitely
+-- requested by assert_psen_s.
+-- The previous implementation asserted PSEN together with RD or WR.
+--
+-- Revision 1.14 2004/06/30 21:18:28 arniml
+-- Fix bug report:
+-- "Program Memory bank can be switched during interrupt"
+-- int module emits int_in_progress signal that is used inside the decoder
+-- to hold mb low for JMP and CALL during interrupts
+--
+-- Revision 1.13 2004/05/20 21:51:40 arniml
+-- clean-up use of ea_i
+--
+-- Revision 1.12 2004/05/17 14:40:09 arniml
+-- assert p2_read_p2_o when expander port is read
+--
+-- Revision 1.11 2004/05/16 15:33:39 arniml
+-- work around bug in Quartus II 4.0
+--
+-- Revision 1.10 2004/04/25 16:22:03 arniml
+-- adjust external timing of BUS
+--
+-- Revision 1.9 2004/04/24 11:22:55 arniml
+-- removed superfluous signal from sensitivity list
+--
+-- Revision 1.8 2004/04/18 18:57:43 arniml
+-- + enhance instruction strobe generation
+-- + rework address output under EA=1 conditions
+--
+-- Revision 1.7 2004/04/15 22:06:05 arniml
+-- + add marker for injected calls
+-- + suppress intstruction strobes for injected calls
+--
+-- Revision 1.6 2004/04/14 20:53:33 arniml
+-- make istrobe visible through testbench package
+--
+-- Revision 1.5 2004/04/07 22:09:03 arniml
+-- remove unused signals
+--
+-- Revision 1.4 2004/04/04 14:18:53 arniml
+-- add measures to implement XCHD
+--
+-- Revision 1.3 2004/03/28 21:15:48 arniml
+-- implemented mnemonic DA
+--
+-- Revision 1.2 2004/03/28 13:06:32 arniml
+-- implement mnemonics:
+-- + MOVD_A_PP
+-- + OUTD_PP_A -> ANLD PP, A; MOVD PP, A; ORLD PP, A
+--
+-- Revision 1.1 2004/03/23 21:31:52 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/IO/t48_ip/decoder_pack-p.vhd b/common/IO/t48_ip/decoder_pack-p.vhd
new file mode 100644
index 00000000..d157a913
--- /dev/null
+++ b/common/IO/t48_ip/decoder_pack-p.vhd
@@ -0,0 +1,87 @@
+-------------------------------------------------------------------------------
+--
+-- $Id: decoder_pack-p.vhd,v 1.2 2004/03/28 13:09:53 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+package decoder_pack is
+
+ -----------------------------------------------------------------------------
+ -- The Mnemonics.
+ -----------------------------------------------------------------------------
+ type mnemonic_t is (MN_ADD,
+ MN_ADD_A_DATA,
+ MN_ANL,
+ MN_ANL_A_DATA,
+ MN_ANL_EXT,
+ MN_CALL,
+ MN_CLR_A,
+ MN_CLR_C,
+ MN_CLR_F,
+ MN_CPL_A,
+ MN_CPL_C,
+ MN_CPL_F,
+ MN_DA,
+ MN_DEC,
+ MN_DIS_EN_I,
+ MN_DIS_EN_TCNTI,
+ MN_DJNZ,
+ MN_ENT0_CLK,
+ MN_IN,
+ MN_INC,
+ MN_INS,
+ MN_JBB,
+ MN_JC,
+ MN_JF,
+ MN_JMP,
+ MN_JMPP,
+ MN_JNI,
+ MN_JT,
+ MN_JTF,
+ MN_JZ,
+ MN_MOV_A_DATA,
+ MN_MOV_A_PSW,
+ MN_MOV_A_RR,
+ MN_MOV_PSW_A,
+ MN_MOV_RR,
+ MN_MOV_RR_DATA,
+ MN_MOV_T,
+ MN_MOVD_A_PP,
+ MN_MOVP,
+ MN_MOVX,
+ MN_NOP,
+ MN_ORL,
+ MN_ORL_A_DATA,
+ MN_ORL_EXT,
+ MN_OUTD_PP_A,
+ MN_OUTL_EXT,
+ MN_RET,
+ MN_RL,
+ MN_RR,
+ MN_SEL_MB,
+ MN_SEL_RB,
+ MN_STOP_TCNT,
+ MN_STRT,
+ MN_SWAP,
+ MN_XCH,
+ MN_XRL,
+ MN_XRL_A_DATA);
+
+end decoder_pack;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: decoder_pack-p.vhd,v $
+-- Revision 1.2 2004/03/28 13:09:53 arniml
+-- merge MN_ANLD, MN_MOVD_PP_A and MN_ORLD_PP_A to OUTLD_PP_A
+--
+-- Revision 1.1 2004/03/23 21:31:52 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/IO/t48_ip/dmem_ctrl.vhd b/common/IO/t48_ip/dmem_ctrl.vhd
new file mode 100644
index 00000000..19acd114
--- /dev/null
+++ b/common/IO/t48_ip/dmem_ctrl.vhd
@@ -0,0 +1,217 @@
+-------------------------------------------------------------------------------
+--
+-- The Data Memory control unit.
+-- All accesses to the Data Memory are managed here.
+--
+-- $Id: dmem_ctrl.vhd,v 1.3 2004/04/24 23:44:25 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.dmem_addr_t;
+use work.t48_pack.word_t;
+use work.dmem_ctrl_pack.dmem_addr_ident_t;
+
+entity dmem_ctrl is
+
+ port (
+ -- Global Interface -------------------------------------------------------
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ -- Control Interface ------------------------------------------------------
+ data_i : in word_t;
+ write_dmem_addr_i : in boolean;
+ write_dmem_i : in boolean;
+ read_dmem_i : in boolean;
+ addr_type_i : in dmem_addr_ident_t;
+ bank_select_i : in std_logic;
+ data_o : out word_t;
+ -- Data Memory Interface --------------------------------------------------
+ dmem_data_i : in word_t;
+ dmem_addr_o : out dmem_addr_t;
+ dmem_we_o : out std_logic;
+ dmem_data_o : out word_t
+ );
+
+end dmem_ctrl;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+use work.t48_pack.clk_active_c;
+use work.t48_pack.res_active_c;
+use work.t48_pack.bus_idle_level_c;
+use work.t48_pack.to_stdLogic;
+
+use work.dmem_ctrl_pack.all;
+
+architecture rtl of dmem_ctrl is
+
+ signal dmem_addr_s,
+ dmem_addr_q : dmem_addr_t;
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process addr_decode
+ --
+ -- Purpose:
+ -- Decode/multiplex the address information for the Data Memory.
+ --
+ addr_decode: process (data_i,
+ addr_type_i,
+ bank_select_i,
+ dmem_addr_q)
+ variable stack_addr_v : unsigned(5 downto 0);
+ begin
+ -- default assignment
+ dmem_addr_s <= dmem_addr_q;
+ stack_addr_v := (others => '0');
+
+ case addr_type_i is
+ when DM_PLAIN =>
+ dmem_addr_s <= data_i;
+
+ when DM_REG =>
+ dmem_addr_s <= (others => '0');
+ dmem_addr_s(2 downto 0) <= data_i(2 downto 0);
+ -- implement bank switching
+ if bank_select_i = '1' then
+ -- dmem address 24 - 31: access proper set
+ dmem_addr_s(4 downto 3) <= "11";
+ end if;
+
+ when DM_STACK =>
+ -- build address from stack pointer
+ stack_addr_v(3 downto 1) := unsigned(data_i(2 downto 0));
+ -- dmem address 8 - 23
+ stack_addr_v := stack_addr_v + 8;
+
+ dmem_addr_s <= (others => '0');
+ dmem_addr_s(5 downto 0) <= std_logic_vector(stack_addr_v);
+
+ when DM_STACK_HIGH =>
+ dmem_addr_s(0) <= '1';
+
+ when others =>
+ -- do nothing
+
+ -- pragma translate_off
+ assert false
+ report "Unknown address type identification for Data Memory controller!"
+ severity error;
+ -- pragma translate_on
+
+ end case;
+
+ end process addr_decode;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process dmem_addr_reg
+ --
+ -- Purpose:
+ -- Implements the Data Memory Address Register.
+ -- This register is necessary to hold the address during a write operation
+ -- as we cannot hold the address in the input register of the
+ -- synchronous RAM (no clock suppression/gating).
+ --
+ dmem_addr_reg: process (res_i, clk_i)
+ begin
+ if res_i = res_active_c then
+ dmem_addr_q <= (others => '0');
+
+ elsif clk_i'event and clk_i = clk_active_c then
+ if en_clk_i then
+
+ if write_dmem_addr_i then
+ dmem_addr_q <= dmem_addr_s;
+ end if;
+
+ end if;
+
+ end if;
+
+ end process dmem_addr_reg;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Output mapping.
+ -----------------------------------------------------------------------------
+ dmem_addr_o <= dmem_addr_s
+ when write_dmem_addr_i and en_clk_i else
+ dmem_addr_q;
+
+ -- data from bus is fed through
+ dmem_data_o <= data_i;
+
+ -- data to bus is enabled upon read request
+ data_o <= dmem_data_i
+ when read_dmem_i else
+ (others => bus_idle_level_c);
+
+ -- write enable to Data Memory is fed through
+ dmem_we_o <= to_stdLogic(write_dmem_i);
+
+end rtl;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: dmem_ctrl.vhd,v $
+-- Revision 1.3 2004/04/24 23:44:25 arniml
+-- move from std_logic_arith to numeric_std
+--
+-- Revision 1.2 2004/04/18 18:58:29 arniml
+-- clean up sensitivity list
+--
+-- Revision 1.1 2004/03/23 21:31:52 arniml
+-- initial check-in
+--
+--
+-------------------------------------------------------------------------------
diff --git a/common/IO/t48_ip/dmem_ctrl_pack-p.vhd b/common/IO/t48_ip/dmem_ctrl_pack-p.vhd
new file mode 100644
index 00000000..cc49f2aa
--- /dev/null
+++ b/common/IO/t48_ip/dmem_ctrl_pack-p.vhd
@@ -0,0 +1,32 @@
+-------------------------------------------------------------------------------
+--
+-- $Id: dmem_ctrl_pack-p.vhd,v 1.1 2004/03/23 21:31:52 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+package dmem_ctrl_pack is
+
+ -----------------------------------------------------------------------------
+ -- Address Type Identifier
+ -----------------------------------------------------------------------------
+ type dmem_addr_ident_t is (DM_PLAIN,
+ DM_REG,
+ DM_STACK,
+ DM_STACK_HIGH);
+
+end dmem_ctrl_pack;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: dmem_ctrl_pack-p.vhd,v $
+-- Revision 1.1 2004/03/23 21:31:52 arniml
+-- initial check-in
+--
+--
+-------------------------------------------------------------------------------
diff --git a/common/IO/t48_ip/int.vhd b/common/IO/t48_ip/int.vhd
new file mode 100644
index 00000000..2320337e
--- /dev/null
+++ b/common/IO/t48_ip/int.vhd
@@ -0,0 +1,252 @@
+-------------------------------------------------------------------------------
+--
+-- The Interrupt Controller.
+-- It collects the interrupt sources and notifies the decoder.
+--
+-- $Id: int.vhd,v 1.3 2004/07/11 16:51:33 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.mstate_t;
+
+entity int is
+
+ port (
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ clk_mstate_i : in mstate_t;
+ jtf_executed_i : in boolean;
+ tim_overflow_i : in boolean;
+ tf_o : out std_logic;
+ en_tcnti_i : in boolean;
+ dis_tcnti_i : in boolean;
+ int_n_i : in std_logic;
+ ale_i : in boolean;
+ last_cycle_i : in boolean;
+ en_i_i : in boolean;
+ dis_i_i : in boolean;
+ ext_int_o : out boolean;
+ tim_int_o : out boolean;
+ retr_executed_i : in boolean;
+ int_executed_i : in boolean;
+ int_pending_o : out boolean;
+ int_in_progress_o : out boolean
+ );
+
+end int;
+
+
+use work.t48_pack.all;
+
+architecture rtl of int is
+
+ constant tim_int_c : std_logic := '0';
+ constant ext_int_c : std_logic := '1';
+
+ type int_state_t is (IDLE, PENDING, INT);
+
+ signal int_state_s,
+ int_state_q : int_state_t;
+
+ signal timer_flag_q : boolean;
+ signal timer_overflow_q : boolean;
+ signal timer_int_enable_q : boolean;
+ signal int_q : boolean;
+ signal int_enable_q : boolean;
+ signal ale_q : boolean;
+ signal int_type_q : std_logic;
+ signal int_in_progress_q : boolean;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process nstate
+ --
+ -- Purpose:
+ -- Determines the next state of the Interrupt controller FSM.
+ --
+ nstate: process (int_state_q,
+ int_type_q,
+ int_in_progress_q,
+ int_executed_i,
+ retr_executed_i,
+ clk_mstate_i,
+ last_cycle_i)
+ begin
+ int_state_s <= int_state_q;
+
+ case int_state_q is
+ when IDLE =>
+ if int_in_progress_q and
+ last_cycle_i and clk_mstate_i = MSTATE5 then
+ int_state_s <= PENDING;
+ end if;
+
+ when PENDING =>
+ if int_executed_i then
+ int_state_s <= INT;
+ end if;
+
+ when INT =>
+ if retr_executed_i then
+ int_state_s <= IDLE;
+ end if;
+
+ when others =>
+ int_state_s <= IDLE;
+
+ end case;
+
+ end process nstate;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process regs
+ --
+ -- Purpose:
+ -- Implement the various registers.
+ -- They are designed according Figure "Interrupt Logic" of
+ -- "The Single Component MCS-48 System".
+ --
+ regs: process (res_i, clk_i)
+ begin
+ if res_i = res_active_c then
+ timer_flag_q <= false;
+ timer_overflow_q <= false;
+ timer_int_enable_q <= false;
+ int_q <= false;
+ int_enable_q <= false;
+ ale_q <= false;
+ int_type_q <= '0';
+ int_state_q <= IDLE;
+ int_in_progress_q <= false;
+
+ elsif clk_i'event and clk_i = clk_active_c then
+ if en_clk_i then
+
+ ale_q <= ale_i;
+
+ int_state_q <= int_state_s;
+
+ if jtf_executed_i then
+ timer_flag_q <= false;
+ elsif tim_overflow_i then
+ timer_flag_q <= true;
+ end if;
+
+ if (int_type_q = tim_int_c and int_executed_i) or
+ not timer_int_enable_q then
+ timer_overflow_q <= false;
+ elsif tim_overflow_i then
+ timer_overflow_q <= true;
+ end if;
+
+ if dis_tcnti_i then
+ timer_int_enable_q <= false;
+ elsif en_tcnti_i then
+ timer_int_enable_q <= true;
+ end if;
+
+ if last_cycle_i and
+ ale_q and not ale_i then
+ int_q <= not to_boolean(int_n_i);
+ end if;
+
+ if dis_i_i then
+ int_enable_q <= false;
+ elsif en_i_i then
+ int_enable_q <= true;
+ end if;
+
+ if retr_executed_i then
+ int_in_progress_q <= false;
+ elsif (int_q and int_enable_q) or
+ timer_overflow_q then
+ int_in_progress_q <= true;
+ if not int_in_progress_q then
+ int_type_q <= to_stdLogic(int_q and int_enable_q);
+ end if;
+ end if;
+
+ end if;
+
+ end if;
+
+ end process regs;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Output Mapping.
+ -----------------------------------------------------------------------------
+ tf_o <= to_stdLogic(timer_flag_q);
+ ext_int_o <= int_type_q = ext_int_c;
+ tim_int_o <= int_type_q = tim_int_c;
+ int_pending_o <= int_state_q = PENDING;
+ int_in_progress_o <= int_in_progress_q;
+
+end rtl;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: int.vhd,v $
+-- Revision 1.3 2004/07/11 16:51:33 arniml
+-- cleanup copyright notice
+--
+-- Revision 1.2 2004/06/30 21:18:28 arniml
+-- Fix bug report:
+-- "Program Memory bank can be switched during interrupt"
+-- int module emits int_in_progress signal that is used inside the decoder
+-- to hold mb low for JMP and CALL during interrupts
+--
+-- Revision 1.1 2004/03/23 21:31:52 arniml
+-- initial check-in
+--
+--
+-------------------------------------------------------------------------------
diff --git a/common/IO/t48_ip/opc_decoder.vhd b/common/IO/t48_ip/opc_decoder.vhd
new file mode 100644
index 00000000..34682ac4
--- /dev/null
+++ b/common/IO/t48_ip/opc_decoder.vhd
@@ -0,0 +1,180 @@
+-------------------------------------------------------------------------------
+--
+-- The Opcode Decoder.
+-- Derives instruction mnemonics and multicycle information
+-- using the OPC table unit.
+--
+-- $Id: opc_decoder.vhd,v 1.2 2004/07/11 16:51:33 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.word_t;
+use work.decoder_pack.mnemonic_t;
+
+entity opc_decoder is
+
+ generic (
+ -- store mnemonic in flip-flops (registered-out)
+ register_mnemonic_g : integer := 1
+ );
+
+ port (
+ -- Global Interface -------------------------------------------------------
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ -- T48 Bus Interface ------------------------------------------------------
+ data_i : in word_t;
+ read_bus_i : in boolean;
+ -- Decoder Interface ------------------------------------------------------
+ inj_int_i : in boolean;
+ opcode_o : out word_t;
+ mnemonic_o : out mnemonic_t;
+ multi_cycle_o : out boolean
+ );
+
+end opc_decoder;
+
+
+use work.t48_pack.clk_active_c;
+use work.t48_pack.res_active_c;
+use work.t48_pack.to_boolean;
+--use work.decoder_pack.MN_NOP;
+use work.decoder_pack.all;
+
+use work.t48_comp_pack.opc_table;
+
+architecture rtl of opc_decoder is
+
+ -- the opcode register
+ signal opcode_q : word_t;
+
+ -- the mnemonic
+ signal mnemonic_s,
+ mnemonic_q : mnemonic_t;
+
+ signal multi_cycle_s : std_logic;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Verify the generics
+ -----------------------------------------------------------------------------
+
+ -- pragma translate_off
+
+ -- Register Mnemonic --------------------------------------------------------
+ assert (register_mnemonic_g = 1) or (register_mnemonic_g = 0)
+ report "register_mnemonic_g must be either 1 or 0!"
+ severity failure;
+
+ -- pragma translate_on
+
+
+ -----------------------------------------------------------------------------
+ -- Opcode Decoder Table
+ -----------------------------------------------------------------------------
+ opc_table_b : opc_table
+ port map (
+ opcode_i => opcode_q,
+ multi_cycle_o => multi_cycle_s,
+ mnemonic_o => mnemonic_s
+ );
+
+
+ -----------------------------------------------------------------------------
+ -- Process regs
+ --
+ -- Purpose:
+ -- Implements the opcode and mnemonic registers.
+ --
+ regs: process (res_i, clk_i)
+ begin
+ if res_i = res_active_c then
+ opcode_q <= (others => '0'); -- NOP
+ mnemonic_q <= MN_NOP;
+
+ elsif clk_i'event and clk_i = clk_active_c then
+ if en_clk_i then
+
+ if read_bus_i then
+ opcode_q <= data_i;
+ elsif inj_int_i then
+ opcode_q <= "00010100";
+ else
+ mnemonic_q <= mnemonic_s;
+ end if;
+
+ end if;
+
+ end if;
+
+ end process regs;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Output Mapping.
+ -----------------------------------------------------------------------------
+ opcode_o <= opcode_q;
+ multi_cycle_o <= to_boolean(multi_cycle_s);
+ mnemonic_o <= mnemonic_q
+ when register_mnemonic_g = 1 else
+ mnemonic_s;
+
+end rtl;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: opc_decoder.vhd,v $
+-- Revision 1.2 2004/07/11 16:51:33 arniml
+-- cleanup copyright notice
+--
+-- Revision 1.1 2004/03/23 21:31:52 arniml
+-- initial check-in
+--
+--
+-------------------------------------------------------------------------------
diff --git a/common/IO/t48_ip/opc_table.vhd b/common/IO/t48_ip/opc_table.vhd
new file mode 100644
index 00000000..7185ba8f
--- /dev/null
+++ b/common/IO/t48_ip/opc_table.vhd
@@ -0,0 +1,422 @@
+-------------------------------------------------------------------------------
+--
+-- The Opcode Decoder Table.
+-- Decodes the given opcode to instruction mnemonics.
+-- Also derives the multicycle information.
+--
+-- $Id: opc_table.vhd,v 1.3 2004/07/11 16:51:33 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.word_t;
+use work.decoder_pack.mnemonic_t;
+
+entity opc_table is
+
+ port (
+ opcode_i : in word_t;
+ multi_cycle_o : out std_logic;
+ mnemonic_o : out mnemonic_t
+ );
+
+end opc_table;
+
+
+use work.decoder_pack.all;
+
+architecture rtl of opc_table is
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process opc_decode
+ --
+ -- Purpose:
+ -- Decode the opcode to the set of mnemonics.
+ --
+ opc_decode: process (opcode_i)
+ begin
+ -- default assignment
+ mnemonic_o <= MN_NOP;
+ multi_cycle_o <= '0';
+
+ case opcode_i is
+ -- Mnemonic ADD ---------------------------------------------------------
+ when "01101000" | "01101001" | "01101010" | "01101011" | -- ADD A, Rr
+ "01101100" | "01101101" | "01101110" | "01101111" | --
+ "01100000" | "01100001" | -- ADD A, @ Rr
+ "01111000" | "01111001" | "01111010" | "01111011" | -- ADDC A, Rr
+ "01111100" | "01111101" | "01111110" | "01111111" | --
+ "01110000" | "01110001" => -- ADDC A, @ Rr
+ mnemonic_o <= MN_ADD;
+
+ -- Mnemonic ADD_A_DATA --------------------------------------------------
+ when "00000011" | -- ADD A, data
+ "00010011" => -- ADDC A, data
+ mnemonic_o <= MN_ADD_A_DATA;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic ANL ---------------------------------------------------------
+ when "01011000" | "01011001" | "01011010" | "01011011" | -- ANL A, Rr
+ "01011100" | "01011101" | "01011110" | "01011111" | --
+ "01010000" | "01010001" => -- ANL A, @ Rr
+ mnemonic_o <= MN_ANL;
+
+ -- Mnemonic ANL_A_DATA --------------------------------------------------
+ when "01010011" => -- ANL A, data
+ mnemonic_o <= MN_ANL_A_DATA;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic ANL_EXT -----------------------------------------------------
+ when "10011000" | -- ANL BUS, data
+ "10011001" | "10011010" => -- ANL PP, data
+ mnemonic_o <= MN_ANL_EXT;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic CALL --------------------------------------------------------
+ when "00010100" | "00110100" | "01010100" | "01110100" | -- CALL addr
+ "10010100" | "10110100" | "11010100" | "11110100" => --
+ mnemonic_o <= MN_CALL;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic CLR_A -------------------------------------------------------
+ when "00100111" => -- CLR A
+ mnemonic_o <= MN_CLR_A;
+
+ -- Mnemonic CLR_C -------------------------------------------------------
+ when "10010111" => -- CLR C
+ mnemonic_o <= MN_CLR_C;
+
+ -- Mnemonic CLR_F -------------------------------------------------------
+ when "10000101" | -- CLR F0
+ "10100101" =>
+ mnemonic_o <= MN_CLR_F;
+
+ -- Mnemonic CPL_A -------------------------------------------------------
+ when "00110111" => -- CPL A
+ mnemonic_o <= MN_CPL_A;
+
+ -- Mnemonic CPL_C -------------------------------------------------------
+ when "10100111" => -- CPL C
+ mnemonic_o <= MN_CPL_C;
+
+ -- Mnemonic CPL_F -------------------------------------------------------
+ when "10010101" | -- CPL F0
+ "10110101" => -- CPL F1
+ mnemonic_o <= MN_CPL_F;
+
+ -- Mnemonic DA ----------------------------------------------------------
+ when "01010111" => -- DA D
+ mnemonic_o <= MN_DA;
+
+ -- Mnemonic DEC ---------------------------------------------------------
+ when "11001000" | "11001001" | "11001010" | "11001011" | -- DEC Rr
+ "11001100" | "11001101" | "11001110" | "11001111" | --
+ "00000111" => -- DEC A
+ mnemonic_o <= MN_DEC;
+
+ -- Mnemonic DIS_EN_I ----------------------------------------------------
+ when "00010101" | -- DIS I
+ "00000101" => -- EN I
+ mnemonic_o <= MN_DIS_EN_I;
+
+ -- Mnemonic DIS_EN_TCNTI ------------------------------------------------
+ when "00110101" | -- DIS TCNTI
+ "00100101" => -- EN TCNTI
+ mnemonic_o <= MN_DIS_EN_TCNTI;
+
+ -- Mnemonic DJNZ --------------------------------------------------------
+ when "11101000" | "11101001" | "11101010" | "11101011" | -- DJNZ Rr, addr
+ "11101100" | "11101101" | "11101110" | "11101111" => --
+ mnemonic_o <= MN_DJNZ;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic ENT0_CLK ----------------------------------------------------
+ when "01110101" => -- ENT0 CLK
+ mnemonic_o <= MN_ENT0_CLK;
+
+ -- Mnemonic IN ----------------------------------------------------------
+ when "00001001" | "00001010" => -- IN A, Pp
+ mnemonic_o <= MN_IN;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic INC ---------------------------------------------------------
+ when "00010111" | -- INC A
+ "00011000" | "00011001" | "00011010" | "00011011" | -- INC Rr
+ "00011100" | "00011101" | "00011110" | "00011111" | --
+ "00010000" | "00010001" => -- INC @ Rr
+ mnemonic_o <= MN_INC;
+
+ -- Mnemonic INS ---------------------------------------------------------
+ when "00001000" => -- INS A, BUS
+ mnemonic_o <= MN_INS;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic JBB ---------------------------------------------------------
+ when "00010010" | "00110010" | "01010010" | "01110010" | -- JBb addr
+ "10010010" | "10110010" | "11010010" | "11110010" => --
+ mnemonic_o <= MN_JBB;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic JC ----------------------------------------------------------
+ when "11110110" | -- JC addr
+ "11100110" => -- JNC addr
+ mnemonic_o <= MN_JC;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic JF ----------------------------------------------------------
+ when "10110110" | -- JF0 addr
+ "01110110" => -- JF1 addr
+ mnemonic_o <= MN_JF;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic JMP ---------------------------------------------------------
+ when "00000100" | "00100100" | "01000100" | "01100100" | -- JMP addr
+ "10000100" | "10100100" | "11000100" | "11100100" => --
+ mnemonic_o <= MN_JMP;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic JMPP --------------------------------------------------------
+ when "10110011" => -- JMPP @ A
+ mnemonic_o <= MN_JMPP;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic JNI ---------------------------------------------------------
+ when "10000110" => -- JNI addr
+ mnemonic_o <= MN_JNI;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic JT ----------------------------------------------------------
+ when "00100110" | -- JNT0 addr
+ "01000110" | -- JNT1 addr
+ "00110110" | -- JT0 addr
+ "01010110" => -- JT1 addr
+ mnemonic_o <= MN_JT;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic JTF ---------------------------------------------------------
+ when "00010110" => -- JTF addr
+ mnemonic_o <= MN_JTF;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic JZ ----------------------------------------------------------
+ when "10010110" | -- JNZ addr
+ "11000110" => -- JZ addr
+ mnemonic_o <= MN_JZ;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic MOV_A_DATA --------------------------------------------------
+ when "00100011" => -- MOV A, data
+ mnemonic_o <= MN_MOV_A_DATA;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic MOV_A_PSW ---------------------------------------------------
+ when "11000111" => -- MOV A, PSW
+ mnemonic_o <= MN_MOV_A_PSW;
+
+ -- Mnemonic MOV_A_RR ----------------------------------------------------
+ when "11111000" | "11111001" | "11111010" | "11111011" | -- MOV A, Rr
+ "11111100" | "11111101" | "11111110" | "11111111" | --
+ "11110000" | "11110001" => -- MOV A, @ Rr
+ mnemonic_o <= MN_MOV_A_RR;
+
+ -- Mnemonic MOV_PSW_A ---------------------------------------------------
+ when "11010111" => -- MOV PSW, A
+ mnemonic_o <= MN_MOV_PSW_A;
+
+ -- Mnemonic MOV_RR ------------------------------------------------------
+ when "10101000" | "10101001" | "10101010" | "10101011" | -- MOV Rr, A
+ "10101100" | "10101101" | "10101110" | "10101111" | --
+ "10100000" | "10100001" => -- MOV @ Rr, A
+ mnemonic_o <= MN_MOV_RR;
+
+ -- Mnemonic MOV_RR_DATA -------------------------------------------------
+ when "10111000" | "10111001" | "10111010" | "10111011" | -- MOV Rr, data
+ "10111100" | "10111101" | "10111110" | "10111111" | --
+ "10110000" | "10110001" => -- MOV @ Rr, data
+ mnemonic_o <= MN_MOV_RR_DATA;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic MOV_T -------------------------------------------------------
+ when "01100010" | -- MOV T, A
+ "01000010" => -- MOV A, T
+ mnemonic_o <= MN_MOV_T;
+
+ -- Mnemonic MOVD_A_PP ---------------------------------------------------
+ when "00001100" | "00001101" | "00001110" | "00001111" => -- MOVD A, Pp
+ mnemonic_o <= MN_MOVD_A_PP;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic MOVP --------------------------------------------------------
+ when "10100011" | -- MOVP A, @ A
+ "11100011" => -- MOVP3 A, @ A
+ mnemonic_o <= MN_MOVP;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic MOVX --------------------------------------------------------
+ when "10000000" | "10000001" | -- MOVX A, @ Rr
+ "10010000" | "10010001" => -- MOVX @ Rr, A
+ mnemonic_o <= MN_MOVX;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic NOP ---------------------------------------------------------
+ when "00000000" => -- NOP
+ mnemonic_o <= MN_NOP;
+
+ -- Mnemonic ORL ---------------------------------------------------------
+ when "01001000" | "01001001" | "01001010" | "01001011" | -- ORL A, Rr
+ "01001100" | "01001101" | "01001110" | "01001111" | --
+ "01000000" | "01000001" => -- ORL A, @ Rr
+ mnemonic_o <= MN_ORL;
+
+ -- Mnemonic ORL_A_DATA --------------------------------------------------
+ when "01000011" => -- ORL A, data
+ mnemonic_o <= MN_ORL_A_DATA;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic ORL_EXT -----------------------------------------------------
+ when "10001000" | -- ORL BUS, data
+ "10001001" | "10001010" => -- ORL Pp, data
+ mnemonic_o <= MN_ORL_EXT;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic OUTD_PP_A ---------------------------------------------------
+ when "00111100" | "00111101" | "00111110" | "00111111" | -- MOVD Pp, A
+ "10011100" | "10011101" | "10011110" | "10011111" | -- ANLD PP, A
+ "10001100" | "10001101" | "10001110" | "10001111" => -- ORLD Pp, A
+ mnemonic_o <= MN_OUTD_PP_A;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic OUTL_EXT ----------------------------------------------------
+ when "00111001" | "00111010" | -- OUTL Pp, A
+ "00000010" => -- OUTL BUS, A
+ mnemonic_o <= MN_OUTL_EXT;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic RET ---------------------------------------------------------
+ when "10000011" | -- RET
+ "10010011" => -- RETR
+ mnemonic_o <= MN_RET;
+ multi_cycle_o <= '1';
+
+ -- Mnemonic RL ----------------------------------------------------------
+ when "11100111" | -- RL A
+ "11110111" => -- RLC A
+ mnemonic_o <= MN_RL;
+
+ -- Mnemonic RR ----------------------------------------------------------
+ when "01110111" | -- RR A
+ "01100111" => -- RRC A
+ mnemonic_o <= MN_RR;
+
+ -- Mnemonic SEL_MB ------------------------------------------------------
+ when "11100101" | -- SEL MB0
+ "11110101" => -- SEL MB1
+ mnemonic_o <= MN_SEL_MB;
+
+ -- Mnemonic SEL_RB ------------------------------------------------------
+ when "11000101" | -- SEL RB0
+ "11010101" => -- SEL RB1
+ mnemonic_o <= MN_SEL_RB;
+
+ -- Mnemonic STOP_TCNT ---------------------------------------------------
+ when "01100101" => -- STOP TCNT
+ mnemonic_o <= MN_STOP_TCNT;
+
+ -- Mnemonic START -------------------------------------------------------
+ when "01000101" | -- STRT CNT
+ "01010101" => -- STRT T
+ mnemonic_o <= MN_STRT;
+
+ -- Mnemonic SWAP --------------------------------------------------------
+ when "01000111" => -- SWAP A
+ mnemonic_o <= MN_SWAP;
+
+ -- Mnemonic XCH ---------------------------------------------------------
+ when "00101000" | "00101001" | "00101010" | "00101011" | -- XCH A, Rr
+ "00101100" | "00101101" | "00101110" | "00101111" | --
+ "00100000" | "00100001" | -- XCH A, @ Rr
+ "00110000" | "00110001" => -- XCHD A, @ Rr
+ mnemonic_o <= MN_XCH;
+
+ -- Mnemonic XRL ---------------------------------------------------------
+ when "11011000" | "11011001" | "11011010" | "11011011" | -- XRL A, Rr
+ "11011100" | "11011101" | "11011110" | "11011111" | --
+ "11010000" | "11010001" => -- XRL A, @ Rr
+ mnemonic_o <= MN_XRL;
+
+ -- Mnemonic XRL_A_DATA --------------------------------------------------
+ when "11010011" => -- XRL A, data
+ mnemonic_o <= MN_XRL_A_DATA;
+ multi_cycle_o <= '1';
+
+ when others =>
+ -- pragma translate_off
+ assert now = 0 ns
+ report "Unknown opcode."
+ severity warning;
+ -- pragma translate_on
+
+ end case;
+
+ end process opc_decode;
+ --
+ -----------------------------------------------------------------------------
+
+end rtl;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: opc_table.vhd,v $
+-- Revision 1.3 2004/07/11 16:51:33 arniml
+-- cleanup copyright notice
+--
+-- Revision 1.2 2004/03/28 13:10:48 arniml
+-- merge MN_ANLD, MN_MOVD_PP_A and MN_ORLD_PP_A to OUTLD_PP_A
+--
+-- Revision 1.1 2004/03/23 21:31:52 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/IO/t48_ip/p1.vhd b/common/IO/t48_ip/p1.vhd
new file mode 100644
index 00000000..7c6058cc
--- /dev/null
+++ b/common/IO/t48_ip/p1.vhd
@@ -0,0 +1,170 @@
+-------------------------------------------------------------------------------
+--
+-- The Port 1 unit.
+-- Implements the Port 1 logic.
+--
+-- $Id: p1.vhd,v 1.4 2004/07/11 16:51:33 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.word_t;
+
+entity p1 is
+
+ port (
+ -- Global Interface -------------------------------------------------------
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ -- T48 Bus Interface ------------------------------------------------------
+ data_i : in word_t;
+ data_o : out word_t;
+ write_p1_i : in boolean;
+ read_p1_i : in boolean;
+ read_reg_i : in boolean;
+ -- Port 1 Interface -------------------------------------------------------
+ p1_i : in word_t;
+ p1_o : out word_t;
+ p1_low_imp_o : out std_logic
+ );
+
+end p1;
+
+
+use work.t48_pack.clk_active_c;
+use work.t48_pack.res_active_c;
+use work.t48_pack.bus_idle_level_c;
+
+architecture rtl of p1 is
+
+ -- the port output register
+ signal p1_q : word_t;
+
+ -- the low impedance marker
+ signal low_imp_q : std_logic;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process p1_reg
+ --
+ -- Purpose:
+ -- Implements the port output register.
+ --
+ p1_reg: process (res_i, clk_i)
+ begin
+ if res_i = res_active_c then
+ p1_q <= (others => '1');
+ low_imp_q <= '0';
+
+ elsif clk_i'event and clk_i = clk_active_c then
+ if en_clk_i then
+
+ if write_p1_i then
+ p1_q <= data_i;
+ low_imp_q <= '1';
+ else
+ low_imp_q <= '0';
+ end if;
+
+ end if;
+
+ end if;
+
+ end process p1_reg;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process p1_data
+ --
+ -- Purpose:
+ -- Generates the T48 bus data.
+ --
+ p1_data: process (read_p1_i,
+ p1_i,
+ read_reg_i,
+ p1_q)
+ begin
+ data_o <= (others => bus_idle_level_c);
+
+ if read_p1_i then
+ if read_reg_i then
+ data_o <= p1_q;
+ else
+ data_o <= p1_i;
+ end if;
+ end if;
+
+ end process p1_data;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Output Mapping.
+ -----------------------------------------------------------------------------
+ p1_o <= p1_q;
+ p1_low_imp_o <= low_imp_q;
+
+end rtl;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: p1.vhd,v $
+-- Revision 1.4 2004/07/11 16:51:33 arniml
+-- cleanup copyright notice
+--
+-- Revision 1.3 2004/05/17 14:37:53 arniml
+-- reorder data_o generation
+--
+-- Revision 1.2 2004/03/29 19:39:58 arniml
+-- rename pX_limp to pX_low_imp
+--
+-- Revision 1.1 2004/03/23 21:31:52 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/IO/t48_ip/p2.vhd b/common/IO/t48_ip/p2.vhd
new file mode 100644
index 00000000..b1c3192e
--- /dev/null
+++ b/common/IO/t48_ip/p2.vhd
@@ -0,0 +1,219 @@
+-------------------------------------------------------------------------------
+--
+-- The Port 2 unit.
+-- Implements the Port 2 logic.
+--
+-- $Id: p2.vhd,v 1.6 2004/07/11 16:51:33 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.word_t;
+use work.t48_pack.nibble_t;
+
+entity p2 is
+
+ port (
+ -- Global Interface -------------------------------------------------------
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ -- T48 Bus Interface ------------------------------------------------------
+ data_i : in word_t;
+ data_o : out word_t;
+ write_p2_i : in boolean;
+ write_exp_i : in boolean;
+ read_p2_i : in boolean;
+ read_reg_i : in boolean;
+ read_exp_i : in boolean;
+ -- Port 2 Interface -------------------------------------------------------
+ output_pch_i : in boolean;
+ output_exp_i : in boolean;
+ pch_i : in nibble_t;
+ p2_i : in word_t;
+ p2_o : out word_t;
+ p2_low_imp_o : out std_logic
+ );
+
+end p2;
+
+
+use work.t48_pack.clk_active_c;
+use work.t48_pack.res_active_c;
+use work.t48_pack.bus_idle_level_c;
+
+architecture rtl of p2 is
+
+ -- the port output register
+ signal p2_q : word_t;
+
+ -- the low impedance marker
+ signal low_imp_q : std_logic;
+
+ -- the expander register
+ signal exp_q : nibble_t;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process p2_regs
+ --
+ -- Purpose:
+ -- Implements the port output and expander registers.
+ --
+ p2_regs: process (res_i, clk_i)
+ begin
+ if res_i = res_active_c then
+ p2_q <= (others => '1');
+ low_imp_q <= '0';
+ exp_q <= (others => '0');
+
+ elsif clk_i'event and clk_i = clk_active_c then
+ if en_clk_i then
+
+ if write_p2_i then
+ p2_q <= data_i;
+ low_imp_q <= '1';
+ else
+ low_imp_q <= '0';
+ end if;
+
+ if write_exp_i then
+ exp_q <= data_i(exp_q'range);
+ end if;
+
+ end if;
+
+ end if;
+
+ end process p2_regs;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process p2_port
+ --
+ -- Purpose:
+ -- Generates the output byte vector for Port 2.
+ --
+ p2_port: process (p2_q,
+ exp_q,
+ output_exp_i,
+ pch_i,
+ output_pch_i)
+ begin
+ p2_o <= p2_q;
+
+ if output_exp_i then
+ p2_o(nibble_t'range) <= exp_q;
+ end if;
+
+ if output_pch_i then
+ p2_o(nibble_t'range) <= pch_i;
+ end if;
+
+ end process p2_port;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process p2_data
+ --
+ -- Purpose:
+ -- Generates the T48 bus data.
+ --
+ p2_data: process (read_p2_i,
+ p2_i,
+ read_reg_i,
+ p2_q,
+ read_exp_i)
+ begin
+ data_o <= (others => bus_idle_level_c);
+
+ if read_p2_i then
+ if read_reg_i then
+ data_o <= p2_q;
+ elsif read_exp_i then
+ data_o <= "0000" & p2_i(nibble_t'range);
+ else
+ data_o <= p2_i;
+ end if;
+ end if;
+
+ end process p2_data;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Output Mapping.
+ -----------------------------------------------------------------------------
+ p2_low_imp_o <= low_imp_q;
+
+end rtl;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: p2.vhd,v $
+-- Revision 1.6 2004/07/11 16:51:33 arniml
+-- cleanup copyright notice
+--
+-- Revision 1.5 2004/05/17 13:52:46 arniml
+-- Fix bug "ANL and ORL to P1/P2 read port status instead of port output register"
+--
+-- Revision 1.4 2004/04/24 23:44:25 arniml
+-- move from std_logic_arith to numeric_std
+--
+-- Revision 1.3 2004/03/29 19:39:58 arniml
+-- rename pX_limp to pX_low_imp
+--
+-- Revision 1.2 2004/03/28 13:11:43 arniml
+-- rework Port 2 expander handling
+--
+-- Revision 1.1 2004/03/23 21:31:53 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/IO/t48_ip/pmem_ctrl.vhd b/common/IO/t48_ip/pmem_ctrl.vhd
new file mode 100644
index 00000000..f7e1e971
--- /dev/null
+++ b/common/IO/t48_ip/pmem_ctrl.vhd
@@ -0,0 +1,231 @@
+-------------------------------------------------------------------------------
+--
+-- The Program Memory control unit.
+-- All operations related to the Program Memory are managed here.
+--
+-- $Id: pmem_ctrl.vhd,v 1.3 2004/07/11 16:51:33 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.pmem_addr_t;
+use work.t48_pack.word_t;
+use work.pmem_ctrl_pack.pmem_addr_ident_t;
+
+entity pmem_ctrl is
+
+ port (
+ -- Global Interface -------------------------------------------------------
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ -- T48 Bus Interface ------------------------------------------------------
+ data_i : in word_t;
+ data_o : out word_t;
+ write_pcl_i : in boolean;
+ read_pcl_i : in boolean;
+ write_pch_i : in boolean;
+ read_pch_i : in boolean;
+ inc_pc_i : in boolean;
+ write_pmem_addr_i : in boolean;
+ addr_type_i : in pmem_addr_ident_t;
+ read_pmem_i : in boolean;
+ -- Porgram Memroy Interface -----------------------------------------------
+ pmem_addr_o : out pmem_addr_t;
+ pmem_data_i : in word_t
+ );
+
+end pmem_ctrl;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+use work.pmem_ctrl_pack.all;
+use work.t48_pack.res_active_c;
+use work.t48_pack.clk_active_c;
+use work.t48_pack.bus_idle_level_c;
+use work.t48_pack.pmem_addr_width_c;
+use work.t48_pack.dmem_addr_width_c;
+use work.t48_pack.page_t;
+
+architecture rtl of pmem_ctrl is
+
+ -- the Program Counter
+ signal program_counter_q : unsigned(pmem_addr_t'range);
+
+ -- the Program Memory address
+ signal pmem_addr_s,
+ pmem_addr_q : std_logic_vector(pmem_addr_t'range);
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process program_counter
+ --
+ -- Purpose:
+ -- Implements the Program Counter.
+ --
+ program_counter: process (res_i, clk_i)
+ begin
+ if res_i = res_active_c then
+ program_counter_q <= (others => '0');
+ pmem_addr_q <= (others => '0');
+
+ elsif clk_i'event and clk_i = clk_active_c then
+ if en_clk_i then
+
+ -- parallel load mode
+ if write_pcl_i then
+ program_counter_q(data_i'range) <= UNSIGNED(data_i);
+ elsif write_pch_i then
+ program_counter_q(pmem_addr_width_c-1 downto data_i'high+1) <=
+ UNSIGNED(data_i(pmem_addr_width_c - dmem_addr_width_c - 1 downto 0));
+ elsif inc_pc_i then
+ -- increment mode
+ program_counter_q <= program_counter_q + 1;
+ end if;
+
+ -- set pmem address
+ if write_pmem_addr_i then
+ pmem_addr_q <= pmem_addr_s;
+ end if;
+
+ end if;
+
+ end if;
+
+ end process program_counter;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process pmem_addr
+ --
+ -- Purpose:
+ -- Multiplex the Program Memory address.
+ --
+ pmem_addr: process (program_counter_q,
+ addr_type_i,
+ pmem_addr_q,
+ data_i)
+ begin
+ -- default assignment
+ pmem_addr_s <= STD_LOGIC_VECTOR(program_counter_q);
+
+ case addr_type_i is
+ when PM_PC =>
+ -- default is ok
+ null;
+
+ when PM_PAGE =>
+ pmem_addr_s(word_t'range) <= data_i;
+ -- take page address from program counter
+ -- => important for JMPP, MOVP!
+ -- they must wrap to next page when at FF!
+
+ when PM_PAGE3 =>
+ pmem_addr_s(word_t'range) <= data_i;
+ -- page address is explicitely specified
+ pmem_addr_s(page_t'range) <= "0011";
+
+ when others =>
+ null;
+
+ end case;
+
+ end process pmem_addr;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process data_output
+ --
+ -- Purpose:
+ -- Multiplex the data bus output.
+ --
+ data_output: process (read_pmem_i,
+ read_pcl_i,
+ read_pch_i,
+ pmem_data_i,
+ program_counter_q)
+ begin
+ data_o <= (others => bus_idle_level_c);
+
+ if read_pmem_i then
+ data_o <= pmem_data_i;
+ elsif read_pcl_i then
+ data_o <= STD_LOGIC_VECTOR(program_counter_q(data_o'range));
+ elsif read_pch_i then
+ data_o(3 downto 0) <= STD_LOGIC_VECTOR(program_counter_q(pmem_addr_width_c-1 downto data_o'high+1));
+ end if;
+
+ end process data_output;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Output Mapping.
+ -----------------------------------------------------------------------------
+ pmem_addr_o <= pmem_addr_q;
+
+end rtl;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: pmem_ctrl.vhd,v $
+-- Revision 1.3 2004/07/11 16:51:33 arniml
+-- cleanup copyright notice
+--
+-- Revision 1.2 2004/04/24 23:44:25 arniml
+-- move from std_logic_arith to numeric_std
+--
+-- Revision 1.1 2004/03/23 21:31:53 arniml
+-- initial check-in
+--
+--
+-------------------------------------------------------------------------------
diff --git a/common/IO/t48_ip/pmem_ctrl_pack-p.vhd b/common/IO/t48_ip/pmem_ctrl_pack-p.vhd
new file mode 100644
index 00000000..1e7564a1
--- /dev/null
+++ b/common/IO/t48_ip/pmem_ctrl_pack-p.vhd
@@ -0,0 +1,31 @@
+-------------------------------------------------------------------------------
+--
+-- $Id: pmem_ctrl_pack-p.vhd,v 1.1 2004/03/23 21:31:53 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+package pmem_ctrl_pack is
+
+ -----------------------------------------------------------------------------
+ -- Address Type Identifier
+ -----------------------------------------------------------------------------
+ type pmem_addr_ident_t is (PM_PC,
+ PM_PAGE,
+ PM_PAGE3);
+
+end pmem_ctrl_pack;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: pmem_ctrl_pack-p.vhd,v $
+-- Revision 1.1 2004/03/23 21:31:53 arniml
+-- initial check-in
+--
+--
+-------------------------------------------------------------------------------
diff --git a/common/IO/t48_ip/psw.vhd b/common/IO/t48_ip/psw.vhd
new file mode 100644
index 00000000..bd3a1f9f
--- /dev/null
+++ b/common/IO/t48_ip/psw.vhd
@@ -0,0 +1,240 @@
+-------------------------------------------------------------------------------
+--
+-- The Program Status Word (PSW).
+-- Implements the PSW with its special bits.
+--
+-- $Id: psw.vhd,v 1.7 2004/07/11 16:51:33 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.word_t;
+
+entity psw is
+
+ port (
+ -- Global Interface -------------------------------------------------------
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ -- T48 Bus Interface ------------------------------------------------------
+ data_i : in word_t;
+ data_o : out word_t;
+ read_psw_i : in boolean;
+ read_sp_i : in boolean;
+ write_psw_i : in boolean;
+ write_sp_i : in boolean;
+ -- Decoder Interface ------------------------------------------------------
+ special_data_i : in std_logic;
+ inc_stackp_i : in boolean;
+ dec_stackp_i : in boolean;
+ write_carry_i : in boolean;
+ write_aux_carry_i : in boolean;
+ write_f0_i : in boolean;
+ write_bs_i : in boolean;
+ carry_o : out std_logic;
+ aux_carry_i : in std_logic;
+ aux_carry_o : out std_logic;
+ f0_o : out std_logic;
+ bs_o : out std_logic
+ );
+
+end psw;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+use work.t48_pack.clk_active_c;
+use work.t48_pack.res_active_c;
+use work.t48_pack.bus_idle_level_c;
+use work.t48_pack.nibble_t;
+
+architecture rtl of psw is
+
+ -- special bit positions in PSW
+ constant carry_c : natural := 3;
+ constant aux_carry_c : natural := 2;
+ constant f0_c : natural := 1;
+ constant bs_c : natural := 0;
+
+ -- the PSW register
+ signal psw_q : nibble_t;
+ -- the Stack Pointer
+ signal sp_q : unsigned(2 downto 0);
+
+ -- pragma translate_off
+ signal psw_s : word_t;
+ -- pragma translate_on
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process psw_reg
+ --
+ -- Purpose:
+ -- Implements the PSW register.
+ --
+ psw_reg: process (res_i, clk_i)
+ begin
+ if res_i = res_active_c then
+ psw_q <= (others => '0');
+ sp_q <= (others => '0');
+
+ elsif clk_i'event and clk_i = clk_active_c then
+ if en_clk_i then
+
+ -- T48 bus access
+ if write_psw_i then
+ psw_q <= data_i(7 downto 4);
+ end if;
+ if write_sp_i then
+ sp_q <= unsigned(data_i(2 downto 0));
+ end if;
+
+ -- increment Stack Pointer
+ if inc_stackp_i then
+ sp_q <= sp_q + 1;
+ end if;
+ -- decrement Stack Pointer
+ if dec_stackp_i then
+ sp_q <= sp_q - 1;
+ end if;
+
+ -- access to special bits
+ if write_carry_i then
+ psw_q(carry_c) <= special_data_i;
+ end if;
+ --
+ if write_aux_carry_i then
+ psw_q(aux_carry_c) <= aux_carry_i;
+ end if;
+ --
+ if write_f0_i then
+ psw_q(f0_c) <= special_data_i;
+ end if;
+ --
+ if write_bs_i then
+ psw_q(bs_c) <= special_data_i;
+ end if;
+
+ end if;
+
+ end if;
+
+ end process psw_reg;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process data_out
+ --
+ -- Purpose:
+ -- Output multiplexer for T48 Data Bus.
+ --
+ data_out: process (read_psw_i,
+ read_sp_i,
+ psw_q,
+ sp_q)
+ begin
+ data_o <= (others => bus_idle_level_c);
+
+ if read_psw_i then
+ data_o(7 downto 4) <= psw_q;
+ end if;
+
+ if read_sp_i then
+ data_o(3 downto 0) <= '1' & std_logic_vector(sp_q);
+ end if;
+
+ end process data_out;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -- pragma translate_off
+ tb: process (psw_q, sp_q)
+ begin
+ psw_s(7 downto 4) <= psw_q;
+ psw_s(3) <= '1';
+ psw_s(2 downto 0) <= std_logic_vector(sp_q);
+ end process tb;
+ -- pragma translate_on
+
+ -----------------------------------------------------------------------------
+ -- Output mapping.
+ -----------------------------------------------------------------------------
+ carry_o <= psw_q(carry_c);
+ aux_carry_o <= psw_q(aux_carry_c);
+ f0_o <= psw_q(f0_c);
+ bs_o <= psw_q(bs_c);
+
+end rtl;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: psw.vhd,v $
+-- Revision 1.7 2004/07/11 16:51:33 arniml
+-- cleanup copyright notice
+--
+-- Revision 1.6 2004/04/24 23:44:25 arniml
+-- move from std_logic_arith to numeric_std
+--
+-- Revision 1.5 2004/04/24 11:25:39 arniml
+-- removed dummy_s - workaround not longer needed for GHDL 0.11.1
+--
+-- Revision 1.4 2004/04/18 18:59:01 arniml
+-- add temporary workaround for GHDL 0.11
+--
+-- Revision 1.3 2004/04/04 14:15:45 arniml
+-- add dump_compare support
+--
+-- Revision 1.2 2004/03/28 21:28:13 arniml
+-- take auxiliary carry from direct ALU connection
+--
+-- Revision 1.1 2004/03/23 21:31:53 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/IO/t48_ip/syn_ram-e.vhd b/common/IO/t48_ip/syn_ram-e.vhd
new file mode 100644
index 00000000..45059493
--- /dev/null
+++ b/common/IO/t48_ip/syn_ram-e.vhd
@@ -0,0 +1,73 @@
+-------------------------------------------------------------------------------
+--
+-- A synchronous parametrizable RAM.
+--
+-- $Id: syn_ram-e.vhd,v 1.1 2004/03/24 21:32:27 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity syn_ram is
+
+ generic (
+ address_width_g : positive := 8
+ );
+ port (
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ ram_addr_i : in std_logic_vector(address_width_g-1 downto 0);
+ ram_data_i : in std_logic_vector(7 downto 0);
+ ram_we_i : in std_logic;
+ ram_data_o : out std_logic_vector(7 downto 0)
+ );
+
+end syn_ram;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: syn_ram-e.vhd,v $
+-- Revision 1.1 2004/03/24 21:32:27 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/IO/t48_ip/t48_comp_pack-p.vhd b/common/IO/t48_ip/t48_comp_pack-p.vhd
new file mode 100644
index 00000000..3c452f45
--- /dev/null
+++ b/common/IO/t48_ip/t48_comp_pack-p.vhd
@@ -0,0 +1,392 @@
+-------------------------------------------------------------------------------
+--
+-- $Id: t48_comp_pack-p.vhd,v 1.7 2004/06/30 21:16:21 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.alu_pack.alu_op_t;
+use work.cond_branch_pack.branch_conditions_t;
+use work.cond_branch_pack.comp_value_t;
+use work.decoder_pack.mnemonic_t;
+use work.dmem_ctrl_pack.dmem_addr_ident_t;
+use work.pmem_ctrl_pack.pmem_addr_ident_t;
+use work.t48_pack.dmem_addr_t;
+use work.t48_pack.pmem_addr_t;
+use work.t48_pack.mstate_t;
+use work.t48_pack.word_t;
+use work.t48_pack.nibble_t;
+
+package t48_comp_pack is
+
+ component alu
+ port (
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ data_i : in word_t;
+ data_o : out word_t;
+ write_accu_i : in boolean;
+ write_shadow_i : in boolean;
+ write_temp_reg_i : in boolean;
+ read_alu_i : in boolean;
+ carry_i : in std_logic;
+ carry_o : out std_logic;
+ aux_carry_o : out std_logic;
+ alu_op_i : in alu_op_t;
+ use_carry_i : in boolean;
+ da_high_i : in boolean;
+ da_overflow_o : out boolean;
+ accu_low_i : in boolean;
+ p06_temp_reg_i : in boolean;
+ p60_temp_reg_i : in boolean
+ );
+ end component;
+
+ component bus_mux
+ port (
+ alu_data_i : in word_t;
+ bus_data_i : in word_t;
+ dec_data_i : in word_t;
+ dm_data_i : in word_t;
+ pm_data_i : in word_t;
+ p1_data_i : in word_t;
+ p2_data_i : in word_t;
+ psw_data_i : in word_t;
+ tim_data_i : in word_t;
+ data_o : out word_t
+ );
+ end component;
+
+ component clock_ctrl
+ generic (
+ xtal_div_3_g : integer := 1
+ );
+ port (
+ clk_i : in std_logic;
+ xtal_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ xtal3_o : out boolean;
+ multi_cycle_i : in boolean;
+ assert_psen_i : in boolean;
+ assert_prog_i : in boolean;
+ assert_rd_i : in boolean;
+ assert_wr_i : in boolean;
+ mstate_o : out mstate_t;
+ second_cycle_o : out boolean;
+ ale_o : out boolean;
+ psen_o : out boolean;
+ prog_o : out boolean;
+ rd_o : out boolean;
+ wr_o : out boolean
+ );
+ end component;
+
+ component cond_branch
+ port (
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ compute_take_i : in boolean;
+ branch_cond_i : in branch_conditions_t;
+ take_branch_o : out boolean;
+ accu_i : in word_t;
+ t0_i : in std_logic;
+ t1_i : in std_logic;
+ int_n_i : in std_logic;
+ f0_i : in std_logic;
+ f1_i : in std_logic;
+ tf_i : in std_logic;
+ carry_i : in std_logic;
+ comp_value_i : in comp_value_t
+ );
+ end component;
+
+ component db_bus
+ port (
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ ea_i : in std_logic;
+ data_i : in word_t;
+ data_o : out word_t;
+ write_bus_i : in boolean;
+ read_bus_i : in boolean;
+ output_pcl_i : in boolean;
+ bidir_bus_i : in boolean;
+ pcl_i : in word_t;
+ db_i : in word_t;
+ db_o : out word_t;
+ db_dir_o : out std_logic
+ );
+ end component;
+
+ component decoder
+ generic (
+ register_mnemonic_g : integer := 1
+ );
+ port (
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ ea_i : in std_logic;
+ ale_i : in boolean;
+ int_n_i : in std_logic;
+ t0_dir_o : out std_logic;
+ data_i : in word_t;
+ data_o : out word_t;
+ alu_write_accu_o : out boolean;
+ alu_write_shadow_o : out boolean;
+ alu_write_temp_reg_o : out boolean;
+ alu_read_alu_o : out boolean;
+ bus_write_bus_o : out boolean;
+ bus_read_bus_o : out boolean;
+ dm_write_dmem_addr_o : out boolean;
+ dm_write_dmem_o : out boolean;
+ dm_read_dmem_o : out boolean;
+ p1_write_p1_o : out boolean;
+ p1_read_p1_o : out boolean;
+ p2_write_p2_o : out boolean;
+ p2_write_exp_o : out boolean;
+ p2_read_p2_o : out boolean;
+ pm_write_pcl_o : out boolean;
+ pm_read_pcl_o : out boolean;
+ pm_write_pch_o : out boolean;
+ pm_read_pch_o : out boolean;
+ pm_read_pmem_o : out boolean;
+ psw_read_psw_o : out boolean;
+ psw_read_sp_o : out boolean;
+ psw_write_psw_o : out boolean;
+ psw_write_sp_o : out boolean;
+ alu_carry_i : in std_logic;
+ alu_op_o : out alu_op_t;
+ alu_da_high_o : out boolean;
+ alu_accu_low_o : out boolean;
+ alu_da_overflow_i : in boolean;
+ alu_p06_temp_reg_o : out boolean;
+ alu_p60_temp_reg_o : out boolean;
+ alu_use_carry_o : out boolean;
+ bus_output_pcl_o : out boolean;
+ bus_bidir_bus_o : out boolean;
+ clk_multi_cycle_o : out boolean;
+ clk_assert_psen_o : out boolean;
+ clk_assert_prog_o : out boolean;
+ clk_assert_rd_o : out boolean;
+ clk_assert_wr_o : out boolean;
+ clk_mstate_i : in mstate_t;
+ clk_second_cycle_i : in boolean;
+ cnd_compute_take_o : out boolean;
+ cnd_branch_cond_o : out branch_conditions_t;
+ cnd_take_branch_i : in boolean;
+ cnd_comp_value_o : out comp_value_t;
+ cnd_f1_o : out std_logic;
+ cnd_tf_o : out std_logic;
+ dm_addr_type_o : out dmem_addr_ident_t;
+ tim_read_timer_o : out boolean;
+ tim_write_timer_o : out boolean;
+ tim_start_t_o : out boolean;
+ tim_start_cnt_o : out boolean;
+ tim_stop_tcnt_o : out boolean;
+ p1_read_reg_o : out boolean;
+ p2_read_reg_o : out boolean;
+ p2_read_exp_o : out boolean;
+ p2_output_pch_o : out boolean;
+ p2_output_exp_o : out boolean;
+ pm_inc_pc_o : out boolean;
+ pm_write_pmem_addr_o : out boolean;
+ pm_addr_type_o : out pmem_addr_ident_t;
+ psw_special_data_o : out std_logic;
+ psw_carry_i : in std_logic;
+ psw_aux_carry_i : in std_logic;
+ psw_f0_i : in std_logic;
+ psw_inc_stackp_o : out boolean;
+ psw_dec_stackp_o : out boolean;
+ psw_write_carry_o : out boolean;
+ psw_write_aux_carry_o : out boolean;
+ psw_write_f0_o : out boolean;
+ psw_write_bs_o : out boolean;
+ tim_overflow_i : in boolean
+ );
+ end component;
+
+ component dmem_ctrl
+ port (
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ data_i : in word_t;
+ write_dmem_addr_i : in boolean;
+ write_dmem_i : in boolean;
+ read_dmem_i : in boolean;
+ addr_type_i : in dmem_addr_ident_t;
+ bank_select_i : in std_logic;
+ data_o : out word_t;
+ dmem_data_i : in word_t;
+ dmem_addr_o : out dmem_addr_t;
+ dmem_we_o : out std_logic;
+ dmem_data_o : out word_t
+ );
+ end component;
+
+ component int
+ port (
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ clk_mstate_i : in mstate_t;
+ jtf_executed_i : in boolean;
+ tim_overflow_i : in boolean;
+ tf_o : out std_logic;
+ en_tcnti_i : in boolean;
+ dis_tcnti_i : in boolean;
+ int_n_i : in std_logic;
+ ale_i : in boolean;
+ last_cycle_i : in boolean;
+ en_i_i : in boolean;
+ dis_i_i : in boolean;
+ ext_int_o : out boolean;
+ tim_int_o : out boolean;
+ retr_executed_i : in boolean;
+ int_executed_i : in boolean;
+ int_pending_o : out boolean;
+ int_in_progress_o : out boolean
+ );
+ end component;
+
+ component opc_table
+ port (
+ opcode_i : in word_t;
+ multi_cycle_o : out std_logic;
+ mnemonic_o : out mnemonic_t
+ );
+ end component;
+
+ component opc_decoder
+ generic (
+ register_mnemonic_g : integer := 1
+ );
+ port (
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ data_i : in word_t;
+ read_bus_i : in boolean;
+ inj_int_i : in boolean;
+ opcode_o : out word_t;
+ mnemonic_o : out mnemonic_t;
+ multi_cycle_o : out boolean
+ );
+ end component;
+
+ component timer
+ generic (
+ sample_t1_state_g : integer := 4
+ );
+ port (
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ t1_i : in std_logic;
+ clk_mstate_i : in mstate_t;
+ data_i : in word_t;
+ data_o : out word_t;
+ read_timer_i : in boolean;
+ write_timer_i : in boolean;
+ start_t_i : in boolean;
+ start_cnt_i : in boolean;
+ stop_tcnt_i : in boolean;
+ overflow_o : out std_logic
+ );
+ end component;
+
+ component p1
+ port (
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ data_i : in word_t;
+ data_o : out word_t;
+ write_p1_i : in boolean;
+ read_p1_i : in boolean;
+ read_reg_i : in boolean;
+ p1_i : in word_t;
+ p1_o : out word_t;
+ p1_low_imp_o : out std_logic
+ );
+ end component;
+
+ component p2
+ port (
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ data_i : in word_t;
+ data_o : out word_t;
+ write_p2_i : in boolean;
+ write_exp_i : in boolean;
+ read_p2_i : in boolean;
+ read_reg_i : in boolean;
+ read_exp_i : in boolean;
+ output_pch_i : in boolean;
+ output_exp_i : in boolean;
+ pch_i : in nibble_t;
+ p2_i : in word_t;
+ p2_o : out word_t;
+ p2_low_imp_o : out std_logic
+ );
+ end component;
+
+ component pmem_ctrl
+ port (
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ data_i : in word_t;
+ data_o : out word_t;
+ write_pcl_i : in boolean;
+ read_pcl_i : in boolean;
+ write_pch_i : in boolean;
+ read_pch_i : in boolean;
+ inc_pc_i : in boolean;
+ write_pmem_addr_i : in boolean;
+ addr_type_i : in pmem_addr_ident_t;
+ read_pmem_i : in boolean;
+ pmem_addr_o : out pmem_addr_t;
+ pmem_data_i : in word_t
+ );
+ end component;
+
+ component psw
+ port (
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ data_i : in word_t;
+ data_o : out word_t;
+ read_psw_i : in boolean;
+ read_sp_i : in boolean;
+ write_psw_i : in boolean;
+ write_sp_i : in boolean;
+ special_data_i : in std_logic;
+ inc_stackp_i : in boolean;
+ dec_stackp_i : in boolean;
+ write_carry_i : in boolean;
+ write_aux_carry_i : in boolean;
+ write_f0_i : in boolean;
+ write_bs_i : in boolean;
+ carry_o : out std_logic;
+ aux_carry_i : in std_logic;
+ aux_carry_o : out std_logic;
+ f0_o : out std_logic;
+ bs_o : out std_logic
+ );
+ end component;
+
+end t48_comp_pack;
diff --git a/common/IO/t48_ip/t48_core.vhd b/common/IO/t48_ip/t48_core.vhd
new file mode 100644
index 00000000..a8e5a56f
--- /dev/null
+++ b/common/IO/t48_ip/t48_core.vhd
@@ -0,0 +1,655 @@
+-------------------------------------------------------------------------------
+--
+-- T48 Microcontroller Core
+--
+-- $Id: t48_core.vhd,v 1.7 2004/05/01 11:58:04 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-- Limitations :
+-- =============
+--
+-- Compared to the original MCS-48 architecture, the following limitations
+-- apply:
+--
+-- * Nibble-wide instructions addressing expander port implemented but
+-- not verified in detail.
+--
+-- * Single-step mode not implemented.
+-- Not selected for future implementation.
+--
+-- * Reading of internal Program Memory not implemented.
+-- Not selected for future implementation.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity t48_core is
+
+ generic (
+ -- divide XTAL1 by 3 to derive Clock States
+ xtal_div_3_g : integer := 1;
+ -- store mnemonic in flip-flops (registered-out)
+ register_mnemonic_g : integer := 1;
+ -- include the port 1 module
+ include_port1_g : integer := 1;
+ -- include the port 2 module
+ include_port2_g : integer := 1;
+ -- include the BUS module
+ include_bus_g : integer := 1;
+ -- include the timer module
+ include_timer_g : integer := 1;
+ -- state in which T1 is sampled (3 or 4)
+ sample_t1_state_g : integer := 4
+ );
+
+ port (
+ -- T48 Interface ----------------------------------------------------------
+ xtal_i : in std_logic;
+ reset_i : in std_logic;
+ t0_i : in std_logic;
+ t0_o : out std_logic;
+ t0_dir_o : out std_logic;
+ int_n_i : in std_logic;
+ ea_i : in std_logic;
+ rd_n_o : out std_logic;
+ psen_n_o : out std_logic;
+ wr_n_o : out std_logic;
+ ale_o : out std_logic;
+ db_i : in std_logic_vector( 7 downto 0);
+ db_o : out std_logic_vector( 7 downto 0);
+ db_dir_o : out std_logic;
+ t1_i : in std_logic;
+ p2_i : in std_logic_vector( 7 downto 0);
+ p2_o : out std_logic_vector( 7 downto 0);
+ p2_low_imp_o : out std_logic;
+ p1_i : in std_logic_vector( 7 downto 0);
+ p1_o : out std_logic_vector( 7 downto 0);
+ p1_low_imp_o : out std_logic;
+ prog_n_o : out std_logic;
+ -- Core Interface ---------------------------------------------------------
+ clk_i : in std_logic;
+ en_clk_i : in std_logic;
+ xtal3_o : out std_logic;
+ dmem_addr_o : out std_logic_vector( 7 downto 0);
+ dmem_we_o : out std_logic;
+ dmem_data_i : in std_logic_vector( 7 downto 0);
+ dmem_data_o : out std_logic_vector( 7 downto 0);
+ pmem_addr_o : out std_logic_vector(11 downto 0);
+ pmem_data_i : in std_logic_vector( 7 downto 0)
+ );
+
+end t48_core;
+
+
+use work.alu_pack.alu_op_t;
+use work.cond_branch_pack.branch_conditions_t;
+use work.cond_branch_pack.comp_value_t;
+use work.dmem_ctrl_pack.dmem_addr_ident_t;
+use work.pmem_ctrl_pack.pmem_addr_ident_t;
+use work.t48_comp_pack.all;
+use work.t48_pack.bus_idle_level_c;
+use work.t48_pack.word_t;
+use work.t48_pack.pmem_addr_t;
+use work.t48_pack.mstate_t;
+use work.t48_pack.to_stdLogic;
+use work.t48_pack.to_boolean;
+
+architecture struct of t48_core is
+
+ signal t48_data_s : word_t;
+
+ signal en_clk_s : boolean;
+
+ -- ALU signals
+ signal alu_data_s : word_t;
+ signal alu_write_accu_s : boolean;
+ signal alu_write_shadow_s : boolean;
+ signal alu_write_temp_reg_s : boolean;
+ signal alu_read_alu_s : boolean;
+ signal alu_carry_s : std_logic;
+ signal alu_aux_carry_s : std_logic;
+ signal alu_op_s : alu_op_t;
+ signal alu_use_carry_s : boolean;
+ signal alu_da_high_s : boolean;
+ signal alu_da_overflow_s : boolean;
+ signal alu_accu_low_s : boolean;
+ signal alu_p06_temp_reg_s : boolean;
+ signal alu_p60_temp_reg_s : boolean;
+
+ -- BUS signals
+ signal bus_write_bus_s : boolean;
+ signal bus_read_bus_s : boolean;
+ signal bus_output_pcl_s : boolean;
+ signal bus_bidir_bus_s : boolean;
+ signal bus_data_s : word_t;
+
+ -- Clock Controller signals
+ signal clk_multi_cycle_s : boolean;
+ signal clk_assert_psen_s : boolean;
+ signal clk_assert_prog_s : boolean;
+ signal clk_assert_rd_s : boolean;
+ signal clk_assert_wr_s : boolean;
+ signal clk_mstate_s : mstate_t;
+ signal clk_second_cycle_s : boolean;
+ signal psen_s : boolean;
+ signal prog_s : boolean;
+ signal rd_s : boolean;
+ signal wr_s : boolean;
+ signal ale_s : boolean;
+ signal xtal3_s : boolean;
+
+ -- Conditional Branch Logic signals
+ signal cnd_compute_take_s : boolean;
+ signal cnd_branch_cond_s : branch_conditions_t;
+ signal cnd_take_branch_s : boolean;
+ signal cnd_comp_value_s : comp_value_t;
+ signal cnd_f1_s : std_logic;
+ signal cnd_tf_s : std_logic;
+
+ -- Data Memory Controller signals
+ signal dm_write_dmem_addr_s : boolean;
+ signal dm_write_dmem_s : boolean;
+ signal dm_read_dmem_s : boolean;
+ signal dm_addr_type_s : dmem_addr_ident_t;
+ signal dm_data_s : word_t;
+
+ -- Decoder signals
+ signal dec_data_s : word_t;
+
+ -- Port 1 signals
+ signal p1_write_p1_s : boolean;
+ signal p1_read_p1_s : boolean;
+ signal p1_read_reg_s : boolean;
+ signal p1_data_s : word_t;
+
+ -- Port 2 signals
+ signal p2_write_p2_s : boolean;
+ signal p2_write_exp_s : boolean;
+ signal p2_read_p2_s : boolean;
+ signal p2_read_reg_s : boolean;
+ signal p2_read_exp_s : boolean;
+ signal p2_output_pch_s : boolean;
+ signal p2_output_exp_s : boolean;
+ signal p2_data_s : word_t;
+
+ -- Program Memory Controller signals
+ signal pm_write_pcl_s : boolean;
+ signal pm_read_pcl_s : boolean;
+ signal pm_write_pch_s : boolean;
+ signal pm_read_pch_s : boolean;
+ signal pm_read_pmem_s : boolean;
+ signal pm_inc_pc_s : boolean;
+ signal pm_write_pmem_addr_s : boolean;
+ signal pm_data_s : word_t;
+ signal pm_addr_type_s : pmem_addr_ident_t;
+ signal pmem_addr_s : pmem_addr_t;
+
+ -- PSW signals
+ signal psw_read_psw_s : boolean;
+ signal psw_read_sp_s : boolean;
+ signal psw_write_psw_s : boolean;
+ signal psw_write_sp_s : boolean;
+ signal psw_carry_s : std_logic;
+ signal psw_aux_carry_s : std_logic;
+ signal psw_f0_s : std_logic;
+ signal psw_bs_s : std_logic;
+ signal psw_special_data_s : std_logic;
+ signal psw_inc_stackp_s : boolean;
+ signal psw_dec_stackp_s : boolean;
+ signal psw_write_carry_s : boolean;
+ signal psw_write_aux_carry_s : boolean;
+ signal psw_write_f0_s : boolean;
+ signal psw_write_bs_s : boolean;
+ signal psw_data_s : word_t;
+
+ -- Timer signals
+ signal tim_overflow_s : boolean;
+ signal tim_of_s : std_logic;
+ signal tim_read_timer_s : boolean;
+ signal tim_write_timer_s : boolean;
+ signal tim_start_t_s : boolean;
+ signal tim_start_cnt_s : boolean;
+ signal tim_stop_tcnt_s : boolean;
+ signal tim_data_s : word_t;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Check generics for valid values.
+ -----------------------------------------------------------------------------
+ -- pragma translate_off
+ assert include_timer_g = 0 or include_timer_g = 1
+ report "include_timer_g must be either 1 or 0!"
+ severity failure;
+
+ assert include_port1_g = 0 or include_port1_g = 1
+ report "include_port1_g must be either 1 or 0!"
+ severity failure;
+
+ assert include_port2_g = 0 or include_port2_g = 1
+ report "include_port2_g must be either 1 or 0!"
+ severity failure;
+
+ assert include_bus_g = 0 or include_bus_g = 1
+ report "include_bus_g must be either 1 or 0!"
+ severity failure;
+ -- pragma translate_on
+
+
+ en_clk_s <= to_boolean(en_clk_i);
+
+ alu_b : alu
+ port map (
+ clk_i => clk_i,
+ res_i => reset_i,
+ en_clk_i => en_clk_s,
+ data_i => t48_data_s,
+ data_o => alu_data_s,
+ write_accu_i => alu_write_accu_s,
+ write_shadow_i => alu_write_shadow_s,
+ write_temp_reg_i => alu_write_temp_reg_s,
+ read_alu_i => alu_read_alu_s,
+ carry_i => psw_carry_s,
+ carry_o => alu_carry_s,
+ aux_carry_o => alu_aux_carry_s,
+ alu_op_i => alu_op_s,
+ use_carry_i => alu_use_carry_s,
+ da_high_i => alu_da_high_s,
+ da_overflow_o => alu_da_overflow_s,
+ accu_low_i => alu_accu_low_s,
+ p06_temp_reg_i => alu_p06_temp_reg_s,
+ p60_temp_reg_i => alu_p60_temp_reg_s
+ );
+
+ bus_mux_b : bus_mux
+ port map (
+ alu_data_i => alu_data_s,
+ bus_data_i => bus_data_s,
+ dec_data_i => dec_data_s,
+ dm_data_i => dm_data_s,
+ pm_data_i => pm_data_s,
+ p1_data_i => p1_data_s,
+ p2_data_i => p2_data_s,
+ psw_data_i => psw_data_s,
+ tim_data_i => tim_data_s,
+ data_o => t48_data_s
+ );
+
+ clock_ctrl_b : clock_ctrl
+ generic map (
+ xtal_div_3_g => xtal_div_3_g
+ )
+ port map (
+ clk_i => clk_i,
+ xtal_i => xtal_i,
+ res_i => reset_i,
+ en_clk_i => en_clk_s,
+ xtal3_o => xtal3_s,
+ multi_cycle_i => clk_multi_cycle_s,
+ assert_psen_i => clk_assert_psen_s,
+ assert_prog_i => clk_assert_prog_s,
+ assert_rd_i => clk_assert_rd_s,
+ assert_wr_i => clk_assert_wr_s,
+ mstate_o => clk_mstate_s,
+ second_cycle_o => clk_second_cycle_s,
+ ale_o => ale_s,
+ psen_o => psen_s,
+ prog_o => prog_s,
+ rd_o => rd_s,
+ wr_o => wr_s
+ );
+
+ cond_branch_b : cond_branch
+ port map (
+ clk_i => clk_i,
+ res_i => reset_i,
+ en_clk_i => en_clk_s,
+ compute_take_i => cnd_compute_take_s,
+ branch_cond_i => cnd_branch_cond_s,
+ take_branch_o => cnd_take_branch_s,
+ accu_i => alu_data_s,
+ t0_i => To_X01Z(t0_i),
+ t1_i => To_X01Z(t1_i),
+ int_n_i => int_n_i,
+ f0_i => psw_f0_s,
+ f1_i => cnd_f1_s,
+ tf_i => cnd_tf_s,
+ carry_i => psw_carry_s,
+ comp_value_i => cnd_comp_value_s
+ );
+
+ use_db_bus: if include_bus_g = 1 generate
+ db_bus_b : db_bus
+ port map (
+ clk_i => clk_i,
+ res_i => reset_i,
+ en_clk_i => en_clk_s,
+ ea_i => ea_i,
+ data_i => t48_data_s,
+ data_o => bus_data_s,
+ write_bus_i => bus_write_bus_s,
+ read_bus_i => bus_read_bus_s,
+ output_pcl_i => bus_output_pcl_s,
+ bidir_bus_i => bus_bidir_bus_s,
+ pcl_i => pmem_addr_s(word_t'range),
+ db_i => db_i,
+ db_o => db_o,
+ db_dir_o => db_dir_o
+ );
+ end generate;
+
+ skip_db_bus: if include_bus_g = 0 generate
+ bus_data_s <= (others => bus_idle_level_c);
+ db_o <= (others => '0');
+ db_dir_o <= '0';
+ end generate;
+
+ decoder_b : decoder
+ generic map (
+ register_mnemonic_g => register_mnemonic_g
+ )
+ port map (
+ clk_i => clk_i,
+ res_i => reset_i,
+ en_clk_i => en_clk_s,
+ ea_i => ea_i,
+ ale_i => ale_s,
+ int_n_i => int_n_i,
+ t0_dir_o => t0_dir_o,
+ data_i => t48_data_s,
+ data_o => dec_data_s,
+ alu_write_accu_o => alu_write_accu_s,
+ alu_write_shadow_o => alu_write_shadow_s,
+ alu_write_temp_reg_o => alu_write_temp_reg_s,
+ alu_read_alu_o => alu_read_alu_s,
+ bus_write_bus_o => bus_write_bus_s,
+ bus_read_bus_o => bus_read_bus_s,
+ dm_write_dmem_addr_o => dm_write_dmem_addr_s,
+ dm_write_dmem_o => dm_write_dmem_s,
+ dm_read_dmem_o => dm_read_dmem_s,
+ p1_write_p1_o => p1_write_p1_s,
+ p1_read_p1_o => p1_read_p1_s,
+ pm_write_pcl_o => pm_write_pcl_s,
+ p2_write_p2_o => p2_write_p2_s,
+ p2_write_exp_o => p2_write_exp_s,
+ p2_read_p2_o => p2_read_p2_s,
+ pm_read_pcl_o => pm_read_pcl_s,
+ pm_write_pch_o => pm_write_pch_s,
+ pm_read_pch_o => pm_read_pch_s,
+ pm_read_pmem_o => pm_read_pmem_s,
+ psw_read_psw_o => psw_read_psw_s,
+ psw_read_sp_o => psw_read_sp_s,
+ psw_write_psw_o => psw_write_psw_s,
+ psw_write_sp_o => psw_write_sp_s,
+ alu_carry_i => alu_carry_s,
+ alu_op_o => alu_op_s,
+ alu_use_carry_o => alu_use_carry_s,
+ alu_da_high_o => alu_da_high_s,
+ alu_da_overflow_i => alu_da_overflow_s,
+ alu_accu_low_o => alu_accu_low_s,
+ alu_p06_temp_reg_o => alu_p06_temp_reg_s,
+ alu_p60_temp_reg_o => alu_p60_temp_reg_s,
+ bus_output_pcl_o => bus_output_pcl_s,
+ bus_bidir_bus_o => bus_bidir_bus_s,
+ clk_multi_cycle_o => clk_multi_cycle_s,
+ clk_assert_psen_o => clk_assert_psen_s,
+ clk_assert_prog_o => clk_assert_prog_s,
+ clk_assert_rd_o => clk_assert_rd_s,
+ clk_assert_wr_o => clk_assert_wr_s,
+ clk_mstate_i => clk_mstate_s,
+ clk_second_cycle_i => clk_second_cycle_s,
+ cnd_compute_take_o => cnd_compute_take_s,
+ cnd_branch_cond_o => cnd_branch_cond_s,
+ cnd_take_branch_i => cnd_take_branch_s,
+ cnd_comp_value_o => cnd_comp_value_s,
+ cnd_f1_o => cnd_f1_s,
+ cnd_tf_o => cnd_tf_s,
+ dm_addr_type_o => dm_addr_type_s,
+ tim_read_timer_o => tim_read_timer_s,
+ tim_write_timer_o => tim_write_timer_s,
+ tim_start_t_o => tim_start_t_s,
+ tim_start_cnt_o => tim_start_cnt_s,
+ tim_stop_tcnt_o => tim_stop_tcnt_s,
+ p1_read_reg_o => p1_read_reg_s,
+ p2_read_reg_o => p2_read_reg_s,
+ p2_read_exp_o => p2_read_exp_s,
+ p2_output_pch_o => p2_output_pch_s,
+ p2_output_exp_o => p2_output_exp_s,
+ pm_inc_pc_o => pm_inc_pc_s,
+ pm_write_pmem_addr_o => pm_write_pmem_addr_s,
+ pm_addr_type_o => pm_addr_type_s,
+ psw_special_data_o => psw_special_data_s,
+ psw_carry_i => psw_carry_s,
+ psw_aux_carry_i => psw_aux_carry_s,
+ psw_f0_i => psw_f0_s,
+ psw_inc_stackp_o => psw_inc_stackp_s,
+ psw_dec_stackp_o => psw_dec_stackp_s,
+ psw_write_carry_o => psw_write_carry_s,
+ psw_write_aux_carry_o => psw_write_aux_carry_s,
+ psw_write_f0_o => psw_write_f0_s,
+ psw_write_bs_o => psw_write_bs_s,
+ tim_overflow_i => tim_overflow_s
+ );
+
+ dmem_ctrl_b : dmem_ctrl
+ port map (
+ clk_i => clk_i,
+ res_i => reset_i,
+ en_clk_i => en_clk_s,
+ data_i => t48_data_s,
+ write_dmem_addr_i => dm_write_dmem_addr_s,
+ write_dmem_i => dm_write_dmem_s,
+ read_dmem_i => dm_read_dmem_s,
+ addr_type_i => dm_addr_type_s,
+ bank_select_i => psw_bs_s,
+ data_o => dm_data_s,
+ dmem_data_i => dmem_data_i,
+ dmem_addr_o => dmem_addr_o,
+ dmem_we_o => dmem_we_o,
+ dmem_data_o => dmem_data_o
+ );
+
+ use_timer: if include_timer_g = 1 generate
+ timer_b : timer
+ generic map (
+ sample_t1_state_g => sample_t1_state_g
+ )
+ port map (
+ clk_i => clk_i,
+ res_i => reset_i,
+ en_clk_i => en_clk_s,
+ t1_i => To_X01Z(t1_i),
+ clk_mstate_i => clk_mstate_s,
+ data_i => t48_data_s,
+ data_o => tim_data_s,
+ read_timer_i => tim_read_timer_s,
+ write_timer_i => tim_write_timer_s,
+ start_t_i => tim_start_t_s,
+ start_cnt_i => tim_start_cnt_s,
+ stop_tcnt_i => tim_stop_tcnt_s,
+ overflow_o => tim_of_s
+ );
+ end generate;
+
+ skip_timer: if include_timer_g = 0 generate
+ tim_data_s <= (others => bus_idle_level_c);
+ tim_of_s <= '0';
+ end generate;
+
+ tim_overflow_s <= to_boolean(tim_of_s);
+
+ use_p1: if include_port1_g = 1 generate
+ p1_b : p1
+ port map (
+ clk_i => clk_i,
+ res_i => reset_i,
+ en_clk_i => en_clk_s,
+ data_i => t48_data_s,
+ data_o => p1_data_s,
+ write_p1_i => p1_write_p1_s,
+ read_p1_i => p1_read_p1_s,
+ read_reg_i => p1_read_reg_s,
+ p1_i => p1_i,
+ p1_o => p1_o,
+ p1_low_imp_o => p1_low_imp_o
+ );
+ end generate;
+
+ skip_p1: if include_port1_g = 0 generate
+ p1_data_s <= (others => bus_idle_level_c);
+ p1_o <= (others => '0');
+ p1_low_imp_o <= '0';
+ end generate;
+
+ use_p2: if include_port2_g = 1 generate
+ p2_b : p2
+ port map (
+ clk_i => clk_i,
+ res_i => reset_i,
+ en_clk_i => en_clk_s,
+ data_i => t48_data_s,
+ data_o => p2_data_s,
+ write_p2_i => p2_write_p2_s,
+ write_exp_i => p2_write_exp_s,
+ read_p2_i => p2_read_p2_s,
+ read_reg_i => p2_read_reg_s,
+ read_exp_i => p2_read_exp_s,
+ output_pch_i => p2_output_pch_s,
+ output_exp_i => p2_output_exp_s,
+ pch_i => pmem_addr_s(11 downto 8),
+ p2_i => p2_i,
+ p2_o => p2_o,
+ p2_low_imp_o => p2_low_imp_o
+ );
+ end generate;
+
+ skip_p2: if include_port2_g = 0 generate
+ p2_data_s <= (others => bus_idle_level_c);
+ p2_o <= (others => '0');
+ p2_low_imp_o <= '0';
+ end generate;
+
+ pmem_ctrl_b : pmem_ctrl
+ port map (
+ clk_i => clk_i,
+ res_i => reset_i,
+ en_clk_i => en_clk_s,
+ data_i => t48_data_s,
+ data_o => pm_data_s,
+ write_pcl_i => pm_write_pcl_s,
+ read_pcl_i => pm_read_pcl_s,
+ write_pch_i => pm_write_pch_s,
+ read_pch_i => pm_read_pch_s,
+ inc_pc_i => pm_inc_pc_s,
+ write_pmem_addr_i => pm_write_pmem_addr_s,
+ addr_type_i => pm_addr_type_s,
+ read_pmem_i => pm_read_pmem_s,
+ pmem_addr_o => pmem_addr_s,
+ pmem_data_i => pmem_data_i
+ );
+
+ psw_b : psw
+ port map (
+ clk_i => clk_i,
+ res_i => reset_i,
+ en_clk_i => en_clk_s,
+ data_i => t48_data_s,
+ data_o => psw_data_s,
+ read_psw_i => psw_read_psw_s,
+ read_sp_i => psw_read_sp_s,
+ write_psw_i => psw_write_psw_s,
+ write_sp_i => psw_write_sp_s,
+ special_data_i => psw_special_data_s,
+ inc_stackp_i => psw_inc_stackp_s,
+ dec_stackp_i => psw_dec_stackp_s,
+ write_carry_i => psw_write_carry_s,
+ write_aux_carry_i => psw_write_aux_carry_s,
+ write_f0_i => psw_write_f0_s,
+ write_bs_i => psw_write_bs_s,
+ carry_o => psw_carry_s,
+ aux_carry_i => alu_aux_carry_s,
+ aux_carry_o => psw_aux_carry_s,
+ f0_o => psw_f0_s,
+ bs_o => psw_bs_s
+ );
+
+
+ -----------------------------------------------------------------------------
+ -- Output Mapping.
+ -----------------------------------------------------------------------------
+ ale_o <= to_stdLogic(ale_s);
+ t0_o <= clk_i;
+ psen_n_o <= to_stdLogic(not psen_s);
+ prog_n_o <= to_stdLogic(not prog_s);
+ rd_n_o <= to_stdLogic(not rd_s);
+ wr_n_o <= to_stdLogic(not wr_s);
+ xtal3_o <= to_stdLogic(xtal3_s);
+ pmem_addr_o <= pmem_addr_s;
+
+end struct;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: t48_core.vhd,v $
+-- Revision 1.7 2004/05/01 11:58:04 arniml
+-- update notice about expander port instructions
+--
+-- Revision 1.6 2004/04/07 22:09:03 arniml
+-- remove unused signals
+--
+-- Revision 1.5 2004/04/04 14:18:53 arniml
+-- add measures to implement XCHD
+--
+-- Revision 1.4 2004/03/29 19:39:58 arniml
+-- rename pX_limp to pX_low_imp
+--
+-- Revision 1.3 2004/03/28 21:27:50 arniml
+-- update wiring for DA support
+--
+-- Revision 1.2 2004/03/28 13:13:20 arniml
+-- connect control signal for Port 2 expander
+--
+-- Revision 1.1 2004/03/23 21:31:53 arniml
+-- initial check-in
+--
+-------------------------------------------------------------------------------
diff --git a/common/IO/t48_ip/t48_core_comp_pack-p.vhd b/common/IO/t48_ip/t48_core_comp_pack-p.vhd
new file mode 100644
index 00000000..7fca7c98
--- /dev/null
+++ b/common/IO/t48_ip/t48_core_comp_pack-p.vhd
@@ -0,0 +1,87 @@
+-------------------------------------------------------------------------------
+--
+-- $Id: t48_core_comp_pack-p.vhd,v 1.2 2004/03/29 19:39:58 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+package t48_core_comp_pack is
+
+ component t48_core
+ generic (
+ xtal_div_3_g : integer := 1;
+ register_mnemonic_g : integer := 1;
+ include_port1_g : integer := 1;
+ include_port2_g : integer := 1;
+ include_bus_g : integer := 1;
+ include_timer_g : integer := 1;
+ sample_t1_state_g : integer := 4
+ );
+
+ port (
+ xtal_i : in std_logic;
+ reset_i : in std_logic;
+ t0_i : in std_logic;
+ t0_o : out std_logic;
+ t0_dir_o : out std_logic;
+ int_n_i : in std_logic;
+ ea_i : in std_logic;
+ rd_n_o : out std_logic;
+ psen_n_o : out std_logic;
+ wr_n_o : out std_logic;
+ ale_o : out std_logic;
+ db_i : in std_logic_vector( 7 downto 0);
+ db_o : out std_logic_vector( 7 downto 0);
+ db_dir_o : out std_logic;
+ t1_i : in std_logic;
+ p2_i : in std_logic_vector( 7 downto 0);
+ p2_o : out std_logic_vector( 7 downto 0);
+ p2_low_imp_o : out std_logic;
+ p1_i : in std_logic_vector( 7 downto 0);
+ p1_o : out std_logic_vector( 7 downto 0);
+ p1_low_imp_o : out std_logic;
+ prog_n_o : out std_logic;
+ clk_i : in std_logic;
+ en_clk_i : in std_logic;
+ xtal3_o : out std_logic;
+ dmem_addr_o : out std_logic_vector( 7 downto 0);
+ dmem_we_o : out std_logic;
+ dmem_data_i : in std_logic_vector( 7 downto 0);
+ dmem_data_o : out std_logic_vector( 7 downto 0);
+ pmem_addr_o : out std_logic_vector(11 downto 0);
+ pmem_data_i : in std_logic_vector( 7 downto 0)
+ );
+ end component;
+
+ component syn_rom
+ generic (
+ address_width_g : positive := 10
+ );
+ port (
+ clk_i : in std_logic;
+ rom_addr_i : in std_logic_vector(address_width_g-1 downto 0);
+ rom_data_o : out std_logic_vector(7 downto 0)
+ );
+ end component;
+
+ component syn_ram
+ generic (
+ address_width_g : positive := 8
+ );
+ port (
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ ram_addr_i : in std_logic_vector(address_width_g-1 downto 0);
+ ram_data_i : in std_logic_vector(7 downto 0);
+ ram_we_i : in std_logic;
+ ram_data_o : out std_logic_vector(7 downto 0)
+ );
+ end component;
+
+end t48_core_comp_pack;
diff --git a/common/IO/t48_ip/t48_pack-p.vhd b/common/IO/t48_ip/t48_pack-p.vhd
new file mode 100644
index 00000000..f95fa752
--- /dev/null
+++ b/common/IO/t48_ip/t48_pack-p.vhd
@@ -0,0 +1,82 @@
+-------------------------------------------------------------------------------
+--
+-- $Id: t48_pack-p.vhd,v 1.1 2004/03/23 21:31:53 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+package t48_pack is
+
+ -----------------------------------------------------------------------------
+ -- Global constants
+ -----------------------------------------------------------------------------
+
+ -- clock active level
+ constant clk_active_c : std_logic := '1';
+ -- reset active level
+ constant res_active_c : std_logic := '0';
+ -- idle level on internal data bus
+ constant bus_idle_level_c : std_logic := '1';
+
+ -- global data word width
+ constant word_width_c : natural := 8;
+
+ -- data memory address width
+ constant dmem_addr_width_c : natural := 8;
+ -- program memory address width
+ constant pmem_addr_width_c : natural := 12;
+
+
+ -----------------------------------------------------------------------------
+ -- Global data types
+ -----------------------------------------------------------------------------
+
+ -- the global data word width type
+ subtype word_t is std_logic_vector(word_width_c-1 downto 0);
+ subtype nibble_t is std_logic_vector(word_width_c/2-1 downto 0);
+ -- the global data memory address type
+ subtype dmem_addr_t is std_logic_vector(dmem_addr_width_c-1 downto 0);
+ -- the global program memory address type
+ subtype pmem_addr_t is std_logic_vector(pmem_addr_width_c-1 downto 0);
+ subtype page_t is std_logic_vector(pmem_addr_width_c-1 downto word_width_c);
+
+ -- the machine states
+ type mstate_t is (MSTATE1, MSTATE2, MSTATE3, MSTATE4, MSTATE5);
+
+
+ -----------------------------------------------------------------------------
+ -- Global functions
+ -----------------------------------------------------------------------------
+
+ function to_stdLogic(input: boolean) return std_logic;
+ function to_boolean(input: std_logic) return boolean;
+
+end t48_pack;
+
+package body t48_pack is
+
+ function to_stdLogic(input: boolean) return std_logic is
+ begin
+ if input then
+ return '1';
+ else
+ return '0';
+ end if;
+ end to_stdLogic;
+
+ function to_boolean(input: std_logic) return boolean is
+ begin
+ if input = '1' then
+ return true;
+ else
+ return false;
+ end if;
+ end to_boolean;
+
+end t48_pack;
diff --git a/common/IO/t48_ip/timer.vhd b/common/IO/t48_ip/timer.vhd
new file mode 100644
index 00000000..88147b7b
--- /dev/null
+++ b/common/IO/t48_ip/timer.vhd
@@ -0,0 +1,278 @@
+-------------------------------------------------------------------------------
+--
+-- The Timer/Counter unit.
+--
+-- $Id: timer.vhd,v 1.5 2004/07/11 16:51:33 arniml Exp $
+--
+-- Copyright (c) 2004, Arnim Laeuger (arniml@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t48/
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.t48_pack.word_t;
+use work.t48_pack.mstate_t;
+
+entity timer is
+
+ generic (
+ -- state in which T1 is sampled (3 or 4)
+ sample_t1_state_g : integer := 4
+ );
+
+ port (
+ -- Global Interface -------------------------------------------------------
+ clk_i : in std_logic;
+ res_i : in std_logic;
+ en_clk_i : in boolean;
+ t1_i : in std_logic;
+ clk_mstate_i : in mstate_t;
+ -- T48 Bus Interface ------------------------------------------------------
+ data_i : in word_t;
+ data_o : out word_t;
+ read_timer_i : in boolean;
+ write_timer_i : in boolean;
+ -- Decoder Interface ------------------------------------------------------
+ start_t_i : in boolean;
+ start_cnt_i : in boolean;
+ stop_tcnt_i : in boolean;
+ overflow_o : out std_logic
+ );
+
+end timer;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+use work.t48_pack.all;
+
+architecture rtl of timer is
+
+ -- the 8 bit counter core
+ signal counter_q : unsigned(word_t'range);
+ signal overflow_q : boolean;
+
+ -- increment signal for the counter core
+ type inc_type_t is (NONE, TIMER, COUNTER);
+ signal increment_s : boolean;
+ signal inc_sel_q : inc_type_t;
+
+ -- T1 edge detector
+ signal t1_q : std_logic;
+ signal t1_inc_s : boolean;
+
+ -- timer prescaler
+ signal prescaler_q : unsigned(4 downto 0);
+ signal pre_inc_s : boolean;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Verify the generics
+ -----------------------------------------------------------------------------
+
+ -- pragma translate_off
+ assert (sample_t1_state_g = 3) or (sample_t1_state_g = 4)
+ report "sample_t1_state_g must be either 3 or 4!"
+ severity failure;
+ -- pragma translate_on
+
+
+ -----------------------------------------------------------------------------
+ -- Process t1_edge
+ --
+ -- Purpose:
+ -- Implements the edge detector for T1.
+ --
+ t1_edge: process (t1_i,
+ t1_q,
+ clk_mstate_i)
+ begin
+ t1_inc_s <= false;
+
+ -- sample in state according to generic
+ -- Old devices: sample at the beginning of state 3
+ -- New devices: sample in state 4
+ if (sample_t1_state_g = 3 and clk_mstate_i = MSTATE3) or
+ (sample_t1_state_g = 4 and clk_mstate_i = MSTATE4) then
+ -- detect falling edge
+ if t1_q = '1' and t1_i = '0' then
+ t1_inc_s <= true;
+ end if;
+ end if;
+
+ end process t1_edge;
+ --
+ -----------------------------------------------------------------------------
+
+
+ pre_inc_s <= clk_mstate_i = MSTATE4 and prescaler_q = 31;
+
+
+ -----------------------------------------------------------------------------
+ -- Process inc_sel
+ --
+ -- Purpose:
+ -- Select increment source (timer, counter or none).
+ --
+ inc_sel: process (inc_sel_q,
+ pre_inc_s,
+ t1_inc_s)
+ begin
+ -- default assignment
+ increment_s <= false;
+
+ case inc_sel_q is
+ when NONE =>
+ increment_s <= false;
+ when TIMER =>
+ increment_s <= pre_inc_s;
+ when COUNTER =>
+ increment_s <= t1_inc_s;
+ when others =>
+ null;
+ end case;
+
+ end process inc_sel;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process regs
+ --
+ -- Purpose:
+ -- Implements the counter, the prescaler and other registers.
+ --
+ regs: process (res_i, clk_i)
+ begin
+ if res_i = res_active_c then
+ overflow_q <= false;
+ t1_q <= '0';
+ prescaler_q <= (others => '0');
+ inc_sel_q <= NONE;
+
+ elsif clk_i'event and clk_i = clk_active_c then
+ if en_clk_i then
+
+ -- Counter Core and overflow ------------------------------------------
+ overflow_q <= false;
+
+ if write_timer_i then
+ counter_q <= unsigned(data_i);
+
+ elsif increment_s then
+ counter_q <= counter_q + 1;
+
+ if counter_q = 255 then
+ overflow_q <= true;
+ end if;
+
+ end if;
+
+ -- T1 edge detector ---------------------------------------------------
+ if (sample_t1_state_g = 3 and clk_mstate_i = MSTATE3) or
+ (sample_t1_state_g = 4 and clk_mstate_i = MSTATE4) then
+ t1_q <= t1_i;
+ end if;
+
+ -- Prescaler ----------------------------------------------------------
+ if start_t_i then
+ prescaler_q <= (others => '0');
+
+ elsif clk_mstate_i = MSTATE3 then
+ prescaler_q <= prescaler_q + 1;
+
+ end if;
+
+ -- Increment Selector -------------------------------------------------
+ if start_t_i then
+ inc_sel_q <= TIMER;
+ elsif start_cnt_i then
+ inc_sel_q <= COUNTER;
+ elsif stop_tcnt_i then
+ inc_sel_q <= NONE;
+ end if;
+
+ end if;
+
+ end if;
+
+ end process regs;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Output Mapping.
+ -----------------------------------------------------------------------------
+ data_o <= std_logic_vector(counter_q)
+ when read_timer_i else
+ (others => bus_idle_level_c);
+ overflow_o <= to_stdLogic(overflow_q);
+
+end rtl;
+
+
+-------------------------------------------------------------------------------
+-- File History:
+--
+-- $Log: timer.vhd,v $
+-- Revision 1.5 2004/07/11 16:51:33 arniml
+-- cleanup copyright notice
+--
+-- Revision 1.4 2004/07/04 13:06:45 arniml
+-- counter_q is not cleared during reset
+-- this would match all different descriptions of the Counter as
+-- a) if the software assumes that the Counter is modified during reset, it
+-- will initialize the Counter anyhow
+-- b) the special case 'Counter not modified during reset' is covered
+--
+-- Revision 1.3 2004/05/16 15:32:57 arniml
+-- fix edge detector bug for counter
+--
+-- Revision 1.2 2004/04/15 22:05:13 arniml
+-- increment prescaler with MSTATE4
+--
+-- Revision 1.1 2004/03/23 21:31:53 arniml
+-- initial check-in
+--
+--
+-------------------------------------------------------------------------------
diff --git a/common/IO/via6522.v b/common/IO/via6522.v
new file mode 100644
index 00000000..b4c9ecaf
--- /dev/null
+++ b/common/IO/via6522.v
@@ -0,0 +1,483 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////
+//
+// Engineer: Thomas Skibo
+//
+// Create Date: Sep 24, 2011
+//
+// Module Name: via6522
+//
+// Description:
+//
+// A simple implementation of the 6522 Versatile Interface Adapter (VIA).
+// Tri-state lines aren't used. Instead, All PIA I/O signals have
+// seperate "in" and "out" signals. Wire or ignore appropriately.
+//
+// A seperate "slow clock" (a synchronous pulse) runs the timers.
+// Typically, it's 1Mhz.
+//
+/////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2011, Thomas Skibo. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * The names of contributors may not be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL Thomas Skibo OR CONTRIBUTORS BE LIABLE FOR
+// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+module via6522
+(
+ output reg [7:0] data_out, // cpu interface
+ input [7:0] data_in,
+ input [3:0] addr,
+ input strobe,
+ input we,
+
+ output reg irq,
+
+ output reg [7:0] porta_out,
+ input [7:0] porta_in,
+ output reg [7:0] portb_out,
+ input [7:0] portb_in,
+
+ input ca1_in,
+ output reg ca2_out,
+ input ca2_in,
+ output reg cb1_out,
+ input cb1_in,
+ output reg cb2_out,
+ input cb2_in,
+
+ input ce,
+ input clk,
+ input reset
+);
+
+// Register address offsets
+parameter [3:0]
+ ADDR_PORTB = 4'h0,
+ ADDR_PORTA = 4'h1,
+ ADDR_DDRB = 4'h2,
+ ADDR_DDRA = 4'h3,
+ ADDR_TIMER1_LO = 4'h4,
+ ADDR_TIMER1_HI = 4'h5,
+ ADDR_TIMER1_LATCH_LO = 4'h6,
+ ADDR_TIMER1_LATCH_HI = 4'h7,
+ ADDR_TIMER2_LO = 4'h8,
+ ADDR_TIMER2_HI = 4'h9,
+ ADDR_SR = 4'ha,
+ ADDR_ACR = 4'hb,
+ ADDR_PCR = 4'hc,
+ ADDR_IFR = 4'hd,
+ ADDR_IER = 4'he,
+ ADDR_PORTA_NH = 4'hf;
+
+wire wr_strobe = strobe && we;
+wire rd_strobe = strobe && !we;
+
+///////////////////////////////////////////////////
+// IER - Interrupt Enable Register
+reg [6:0] ier;
+
+always @(posedge clk) begin
+ if (reset) ier <= 7'd0;
+ else if (wr_strobe && addr == ADDR_IER) ier <= data_in[7] ? (ier | data_in[6:0]) : (ier & ~data_in[6:0]);
+end
+
+////////////////////////////////////////////////////
+// PCR - Peripheral Control Register
+reg [7:0] pcr;
+
+always @(posedge clk) begin
+ if (reset) pcr <= 8'h00;
+ else if (wr_strobe && addr == ADDR_PCR) pcr <= data_in;
+end
+
+//////////////////////////////////////////////////////
+// ACR - Auxiliary Control Register
+reg [7:0] acr;
+
+always @(posedge clk) begin
+ if (reset) acr <= 8'h00;
+ else if (wr_strobe && addr == ADDR_ACR) acr <= data_in;
+end
+
+/////////////////////////////////////////////////////
+// PORTs and DDRs
+reg [7:0] ddra;
+reg [7:0] ddrb;
+reg pb7_nxt; // generated by timer1 logic, used when acr7 is set
+
+// Implement PORTA (out)
+always @(posedge clk) begin
+ if (reset) porta_out <= 8'h00;
+ else if (wr_strobe && (addr == ADDR_PORTA || addr == ADDR_PORTA_NH)) porta_out <= data_in;
+end
+
+// Implement DDRA
+always @(posedge clk) begin
+ if (reset) ddra <= 8'h00;
+ else if (wr_strobe && addr == ADDR_DDRA) ddra <= data_in;
+end
+
+// Implement PORTB (out).
+always @(posedge clk) begin
+ if (reset) portb_out[6:0] <= 7'h00;
+ else if (wr_strobe && addr == ADDR_PORTB) portb_out[6:0] <= data_in[6:0];
+end
+
+always @(posedge clk) begin
+ if (reset) portb_out[7] <= 1'b0;
+ else if (acr[7]) portb_out[7] <= pb7_nxt;
+ else if (wr_strobe && addr == ADDR_PORTB) portb_out[7] <= data_in[7];
+end
+
+// Implement DDRB
+always @(posedge clk) begin
+ if (reset) ddrb <= 8'h00;
+ else if (wr_strobe && addr == ADDR_DDRB) ddrb <= data_in;
+end
+
+////////////////////////////////////////////////////////
+// CA interrupt logic
+reg irq_ca1;
+reg irq_ca2;
+
+// CA1 and CA2 transition logic.
+reg ca1_in_1;
+reg ca2_in_1;
+always @(posedge clk) begin
+ ca1_in_1 <= ca1_in;
+ ca2_in_1 <= ca2_in;
+end
+
+// detect "active" transitions.
+wire ca1_act_trans = ((ca1_in && !ca1_in_1 && pcr[0]) ||
+ (!ca1_in && ca1_in_1 && !pcr[0]));
+wire ca2_act_trans = ((ca2_in && !ca2_in_1 && pcr[2]) ||
+ (!ca2_in && ca2_in_1 && !pcr[2]));
+
+ // logic for clearing CA1 and CA2 interrupt bits.
+wire irq_ca1_clr = ((strobe && addr == ADDR_PORTA) ||
+ (wr_strobe && addr == ADDR_IFR && data_in[1]));
+wire irq_ca2_clr = ((strobe && addr == ADDR_PORTA) ||
+ (wr_strobe && addr == ADDR_IFR && data_in[0]));
+
+always @(posedge clk) begin
+ if (reset || (irq_ca1_clr && !ca1_act_trans)) irq_ca1 <= 1'b0;
+ else if (ca1_act_trans) irq_ca1 <= 1'b1;
+end
+
+always @(posedge clk) begin
+ if (reset || (irq_ca2_clr && !ca2_act_trans)) irq_ca2 <= 1'b0;
+ else if (ca2_act_trans) irq_ca2 <= 1'b1;
+end
+
+
+////////////////////////////////////////////////////////
+// CB logic
+reg irq_cb1;
+reg irq_cb2;
+
+// transition logic
+reg cb1_in_1;
+reg cb2_in_1;
+always @(posedge clk) begin
+ cb1_in_1 <= cb1_in;
+ cb2_in_1 <= cb2_in;
+end
+
+// detect "active" transitions.
+wire cb1_act_trans = ((cb1_in && !cb1_in_1 && pcr[4]) ||
+ (!cb1_in && cb1_in_1 && !pcr[4]));
+wire cb2_act_trans = ((cb2_in && !cb2_in_1 && pcr[6]) ||
+ (!cb2_in && cb2_in_1 && !pcr[6]));
+
+// logic for clearing CB1 and CB2 interrupt bits.
+wire irq_cb1_clr = ((strobe && addr == ADDR_PORTB) ||
+ (wr_strobe && addr == ADDR_IFR && data_in[4]));
+wire irq_cb2_clr = ((strobe && addr == ADDR_PORTB) ||
+ (wr_strobe && addr == ADDR_IFR && data_in[3]));
+
+always @(posedge clk) begin
+ if (reset || (irq_cb1_clr && !cb1_act_trans)) irq_cb1 <= 1'b0;
+ else if (cb1_act_trans) irq_cb1 <= 1'b1;
+end
+
+always @(posedge clk) begin
+ if (reset || (irq_cb2_clr && !cb2_act_trans)) irq_cb2 <= 1'b0;
+ else if (cb2_act_trans) irq_cb2 <= 1'b1;
+end
+
+///////////////////////////////////////////////////
+// CA2/CB2 output modes
+always @(posedge clk) begin
+ case (pcr[3:1])
+ 3'b100: ca2_out <= irq_ca1;
+ 3'b101: ca2_out <= !ca1_act_trans;
+ 3'b111: ca2_out <= 1'b1;
+ default: ca2_out <= 1'b0;
+ endcase
+end
+
+reg cb2_out_r;
+wire portb_wr_strobe = wr_strobe && addr == ADDR_PORTB;
+wire cb2_sr_out;
+
+always @(posedge clk) begin
+ if (reset || (portb_wr_strobe && !cb1_act_trans)) cb2_out_r <= 1'b0;
+ else if (cb1_act_trans) cb2_out_r <= 1'b1;
+end
+
+always @(posedge clk) begin
+ if (acr[4]) cb2_out <= cb2_sr_out;
+ else begin
+ case (pcr[7:5])
+ 3'b100: cb2_out <= cb2_out_r;
+ 3'b101: cb2_out <= !portb_wr_strobe;
+ 3'b111: cb2_out <= 1'b1;
+ default: cb2_out <= 1'b0;
+ endcase
+ end
+end
+
+//////////////////////////////////////////////////////////
+// Implement PORTA (in) latch
+reg [7:0] porta_in_r;
+always @(posedge clk) begin
+ if (!acr[0] || !irq_ca1) porta_in_r <= porta_in;
+end
+
+// Implement PORTB (in) latch
+reg [7:0] portb_in_r;
+always @(posedge clk) begin
+ if (!acr[1] || !irq_cb1) portb_in_r <= portb_in;
+end
+
+///////////////////////////////////////////////////
+// Timers
+reg [15:0] timer1;
+reg [7:0] timer1_latch_lo;
+reg [7:0] timer1_latch_hi;
+
+reg [15:0] timer2;
+reg [7:0] timer2_latch_lo;
+
+reg irq_t1_one_shot;
+reg irq_t1;
+reg irq_t2_one_shot;
+reg irq_t2;
+
+// TIMER1
+always @(posedge clk) begin
+ if (reset) timer1 <= 16'hffff;
+ else if (wr_strobe && addr == ADDR_TIMER1_HI) timer1 <= {data_in, timer1_latch_lo};
+ else if (timer1 == 16'h0000 && ce && acr[6]) timer1 <= {timer1_latch_hi, timer1_latch_lo};
+ else if (ce) timer1 <= timer1 - 1'b1;
+end
+
+// T1 latch lo
+always @(posedge clk) begin
+ if (reset) timer1_latch_lo <= 8'hff;
+ else if (wr_strobe && (addr == ADDR_TIMER1_LO || addr == ADDR_TIMER1_LATCH_LO)) timer1_latch_lo <= data_in;
+end
+
+// T1 latch hi
+always @(posedge clk) begin
+ if (reset) timer1_latch_hi <= 8'hff;
+ else if (wr_strobe && (addr == ADDR_TIMER1_HI || addr == ADDR_TIMER1_LATCH_HI)) timer1_latch_hi <= data_in;
+end
+
+// "one-shot" logic so we only get an interrupt on first counter roll-over
+always @(posedge clk) begin
+ if (reset) irq_t1_one_shot <= 1'b0;
+ else if (wr_strobe && addr == ADDR_TIMER1_HI) irq_t1_one_shot <= 1'b1;
+ else if (timer1 == 16'h0000 && ce) irq_t1_one_shot <= 1'b0;
+end
+
+// T1 interrupt set and clear logic
+wire irq_t1_set = (timer1 == 16'h0000 && ce && (irq_t1_one_shot || acr[6]));
+wire irq_t1_clr = ((wr_strobe && addr == ADDR_TIMER1_HI) ||
+ (wr_strobe && addr == ADDR_TIMER1_LATCH_HI) ||
+ (rd_strobe && addr == ADDR_TIMER1_LO) ||
+ (wr_strobe && addr == ADDR_IFR && data_in[6]));
+
+// T1 IRQ
+always @(posedge clk) begin
+ if (reset || irq_t1_clr) irq_t1 <= 1'b0;
+ else if (irq_t1_set) irq_t1 <= 1'b1;
+end
+
+// I forget what this is for
+always @(posedge clk) begin
+ if (reset) pb7_nxt <= 1'b1;
+ else if (wr_strobe && addr == ADDR_TIMER1_HI) pb7_nxt <= 1'b0;
+ else if (timer1 == 16'h0001 && ce) pb7_nxt <= !pb7_nxt;
+end
+
+// TIMER2
+always @(posedge clk) begin
+ if (reset) timer2 <= 16'hffff;
+ else if (wr_strobe && addr == ADDR_TIMER2_HI) timer2 <= {data_in, timer2_latch_lo};
+ else if ((!acr[5] || !portb_in[6]) && ce) timer2 <= timer2 - 1'b1;
+end
+
+// T2 latch lo (i.e. writes to T2L)
+always @(posedge clk) begin
+ if (reset) timer2_latch_lo <= 8'hff;
+ else if (wr_strobe && addr == ADDR_TIMER2_LO) timer2_latch_lo <= data_in;
+end
+
+// T2 IRQ "one-shot" logic
+always @(posedge clk) begin
+ if (reset) irq_t2_one_shot <= 1'b0;
+ else if (wr_strobe && addr == ADDR_TIMER2_HI) irq_t2_one_shot <= 1'b1;
+ else if (timer2 == 16'h0000 && ce) irq_t2_one_shot <= 1'b0;
+end
+
+// T2 IRQ set and clear logic
+wire irq_t2_set = (timer2 == 16'h0000 && ce && irq_t2_one_shot);
+wire irq_t2_clr = ((wr_strobe && addr == ADDR_TIMER2_HI) ||
+ (rd_strobe && addr == ADDR_TIMER2_LO) ||
+ (wr_strobe && addr == ADDR_IFR && data_in[5]));
+
+// T2 IRQ
+always @(posedge clk) begin
+ if (reset || irq_t2_clr) irq_t2 <= 1'b0;
+ else if (irq_t2_set) irq_t2 <= 1'b1;
+end
+
+
+////////////////////////////////////////////////////////
+// SR - shift register
+reg [7:0] sr;
+reg [2:0] sr_cntr;
+reg [7:0] sr_clk_div_ctr;
+reg sr_clk_div;
+reg irq_sr;
+reg sr_go;
+reg do_shift;
+
+always @(posedge clk) begin
+ if (reset) sr <= 8'h00;
+ else if (wr_strobe && addr == ADDR_SR) sr <= data_in;
+ else if (do_shift) sr <= { sr[6:0], (acr[4] ? sr[7] : cb2_in) };
+end
+
+assign cb2_sr_out = sr[7];
+
+always @(posedge clk) begin
+ if (reset) sr_clk_div_ctr <= 8'd0;
+ else if (ce && sr_clk_div_ctr == 8'd0) sr_clk_div_ctr <= timer2_latch_lo;
+ else if (ce) sr_clk_div_ctr <= sr_clk_div_ctr - 1'b1;
+end
+
+always @(posedge clk) begin
+ if (reset) sr_clk_div <= 1'b0;
+ else sr_clk_div <= (ce && sr_clk_div_ctr == 8'd0);
+end
+
+always @(posedge clk) begin
+ if (reset || (strobe && addr == ADDR_SR)) sr_cntr <= 3'd7;
+ else if (do_shift) sr_cntr <= sr_cntr - 1'b1;
+end
+
+// SR IRQ set and clr logic
+wire irq_sr_set = do_shift && sr_cntr == 3'b000;
+wire irq_sr_clr = ((strobe && addr == ADDR_SR) || (wr_strobe && addr == ADDR_IFR && data_in[2]));
+
+// SR IRQ
+always @(posedge clk) begin
+ if (reset || (irq_sr_clr && !irq_sr_set)) irq_sr <= 1'b0;
+ else if (irq_sr_set) irq_sr <= 1'b1;
+end
+
+always @(posedge clk) begin
+ if (reset) sr_go <= 1'b0;
+ else if (strobe && addr == ADDR_SR) sr_go <= 1'b1;
+ else if (irq_sr_set) sr_go <= 1'b0;
+end
+
+// cominatorial logic for do_shift signal.
+always @(sr_clk_div or ce or cb1_act_trans or sr_go or acr) begin
+ case (acr[4:2])
+ 3'b000: do_shift = 1'b0;
+ 3'b100: do_shift = sr_clk_div;
+ 3'b001,
+ 3'b101: do_shift = (sr_go && sr_clk_div);
+ 3'b010,
+ 3'b110: do_shift = (sr_go && ce);
+ 3'b011,
+ 3'b111: do_shift = cb1_act_trans;
+ endcase
+end
+
+always @(posedge clk) begin
+ if (reset) cb1_out <= 1'b1;
+ else if (do_shift) cb1_out <= !cb1_out;
+end
+
+////////////////////////////////////////////////////////
+// IRQ and enable logic.
+//
+
+// IFR register (not including bit 7)
+wire [6:0] ifr = { irq_t1, irq_t2, irq_cb1, irq_cb2, irq_sr, irq_ca1, irq_ca2 };
+
+// IRQ combinatorial logic
+wire irq_p = |{ (ifr & ier) };
+
+// IRQ output
+always @(posedge clk) begin
+ if (reset) irq <= 1'b0;
+ else irq <= irq_p;
+end
+
+///////////////////////////////////////////////////
+// Read data mux
+wire [7:0] porta = (porta_out & ddra) | (porta_in_r & ~ddra);
+wire [7:0] portb = (portb_out & ddrb) | (portb_in_r & ~ddrb);
+
+always @(*) begin
+ case (addr)
+ ADDR_PORTB: data_out = portb;
+ ADDR_PORTA: data_out = porta;
+ ADDR_DDRB: data_out = ddrb;
+ ADDR_DDRA: data_out = ddra;
+ ADDR_TIMER1_LO: data_out = timer1[7:0];
+ ADDR_TIMER1_HI: data_out = timer1[15:8];
+ ADDR_TIMER1_LATCH_LO: data_out = timer1_latch_lo;
+ ADDR_TIMER1_LATCH_HI: data_out = timer1_latch_hi;
+ ADDR_TIMER2_LO: data_out = timer2[7:0];
+ ADDR_TIMER2_HI: data_out = timer2[15:8];
+ ADDR_IER: data_out = {1'b1, ier};
+ ADDR_PCR: data_out = pcr;
+ ADDR_ACR: data_out = acr;
+ ADDR_IFR: data_out = {irq_p, ifr};
+ ADDR_SR: data_out = sr;
+ ADDR_PORTA_NH: data_out = porta;
+ default: data_out = 8'hXX;
+ endcase
+end
+
+endmodule // via6522
diff --git a/common/Memory/dpSDRAM16Mb.vhd b/common/Memory/dpSDRAM16Mb.vhd
new file mode 100644
index 00000000..87bcad97
--- /dev/null
+++ b/common/Memory/dpSDRAM16Mb.vhd
@@ -0,0 +1,371 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2016, Fabio Belavenuto (belavenuto@gmail.com)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+--
+-- Emulacao memoria dual-port para SDRAMs
+--
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.numeric_std.all;
+
+entity dpSDRAM16Mb is
+ generic (
+ freq_g : integer := 100
+ );
+ port (
+ clock_i : in std_logic;
+ reset_i : in std_logic;
+ refresh_i : in std_logic := '1';
+ -- Porta 0
+ port0_cs_i : in std_logic;
+ port0_oe_i : in std_logic;
+ port0_we_i : in std_logic;
+ port0_addr_i : in std_logic_vector(20 downto 0);
+ port0_data_i : in std_logic_vector( 7 downto 0);
+ port0_data_o : out std_logic_vector( 7 downto 0);
+ -- Porta 1
+ port1_cs_i : in std_logic;
+ port1_oe_i : in std_logic;
+ port1_we_i : in std_logic;
+ port1_addr_i : in std_logic_vector(20 downto 0);
+ port1_data_i : in std_logic_vector( 7 downto 0);
+ port1_data_o : out std_logic_vector( 7 downto 0);
+ -- SD-RAM ports
+ mem_cke_o : out std_logic;
+ mem_cs_n_o : out std_logic;
+ mem_ras_n_o : out std_logic;
+ mem_cas_n_o : out std_logic;
+ mem_we_n_o : out std_logic;
+ mem_udq_o : out std_logic;
+ mem_ldq_o : out std_logic;
+ mem_ba_o : out std_logic;
+ mem_addr_o : out std_logic_vector(10 downto 0);
+ mem_data_io : inout std_logic_vector(15 downto 0)
+ );
+end entity;
+
+architecture Behavior of dpSDRAM16Mb is
+
+ constant SdrCmd_de_c : std_logic_vector(3 downto 0) := "1111"; -- deselect
+ constant SdrCmd_xx_c : std_logic_vector(3 downto 0) := "0111"; -- no operation
+ constant SdrCmd_rd_c : std_logic_vector(3 downto 0) := "0101"; -- read
+ constant SdrCmd_wr_c : std_logic_vector(3 downto 0) := "0100"; -- write
+ constant SdrCmd_ac_c : std_logic_vector(3 downto 0) := "0011"; -- activate
+ constant SdrCmd_pr_c : std_logic_vector(3 downto 0) := "0010"; -- precharge all
+ constant SdrCmd_re_c : std_logic_vector(3 downto 0) := "0001"; -- refresh
+ constant SdrCmd_ms_c : std_logic_vector(3 downto 0) := "0000"; -- mode regiser set
+ -- SD-RAM control signals
+ signal SdrCmd_s : std_logic_vector(3 downto 0);
+ signal SdrBa_s : std_logic;
+ signal SdrUdq_s : std_logic;
+ signal SdrLdq_s : std_logic;
+ signal SdrAdr_s : std_logic_vector(10 downto 0);
+ signal SdrDat_s : std_logic_vector(15 downto 0);
+
+ signal ram0_req_s : std_logic;
+ signal ram0_ack_s : std_logic;
+ signal ram0_addr_s : std_logic_vector(20 downto 0);
+ signal ram0_din_s : std_logic_vector( 7 downto 0);
+ signal ram0_dout_s : std_logic_vector( 7 downto 0);
+ signal ram0_we_s : std_logic;
+
+ signal ram1_req_s : std_logic;
+ signal ram1_ack_s : std_logic;
+ signal ram1_addr_s : std_logic_vector(20 downto 0);
+ signal ram1_din_s : std_logic_vector( 7 downto 0);
+ signal ram1_dout_s : std_logic_vector( 7 downto 0);
+ signal ram1_we_s : std_logic;
+
+begin
+
+ -- Detectar pedido na porta 0
+ process (reset_i, clock_i)
+ variable pcs_v : std_logic_vector(1 downto 0);
+ variable acesso_v : std_logic;
+ begin
+ if reset_i = '1' then
+ port0_data_o <= (others => '1');
+ ram0_we_s <= '0';
+ ram0_req_s <= '0';
+ pcs_v := "00";
+ elsif rising_edge(clock_i) then
+ if ram0_req_s = '1' and ram0_ack_s = '1' then
+ if ram0_we_s = '0' then
+ port0_data_o <= ram0_dout_s;
+ end if;
+ ram0_req_s <= '0';
+ end if;
+
+ if pcs_v = "01" then
+ ram0_addr_s <= port0_addr_i;
+ ram0_req_s <= '1';
+ if port0_we_i = '1' then
+ ram0_din_s <= port0_data_i;
+ ram0_we_s <= '1';
+ else
+ ram0_we_s <= '0';
+ end if;
+ end if;
+
+ acesso_v := port0_cs_i and (port0_oe_i or port0_we_i);
+ pcs_v := pcs_v(0) & acesso_v;
+
+ end if;
+ end process;
+
+ -- Detectar pedido na porta 1
+ process (reset_i, clock_i)
+ variable pcs_v : std_logic_vector(1 downto 0);
+ variable acesso_v : std_logic;
+ begin
+ if reset_i = '1' then
+ port1_data_o <= (others => '1');
+ ram1_we_s <= '0';
+ ram1_req_s <= '0';
+ pcs_v := "00";
+ elsif rising_edge(clock_i) then
+ if ram1_req_s = '1' and ram1_ack_s = '1' then
+ if ram1_we_s = '0' then
+ port1_data_o <= ram1_dout_s;
+ end if;
+ ram1_req_s <= '0';
+ end if;
+
+ if pcs_v = "01" then
+ ram1_addr_s <= port1_addr_i;
+ ram1_req_s <= '1';
+ if port1_we_i = '1' then
+ ram1_din_s <= port1_data_i;
+ ram1_we_s <= '1';
+ else
+ ram1_we_s <= '0';
+ end if;
+ end if;
+
+ acesso_v := port1_cs_i and (port1_oe_i or port1_we_i);
+ pcs_v := pcs_v(0) & acesso_v;
+
+ end if;
+ end process;
+
+ ----------------------------
+ process (clock_i)
+
+ type typSdrRoutine_t is ( SdrRoutine_Null, SdrRoutine_Init, SdrRoutine_Idle, SdrRoutine_RefreshAll, SdrRoutine_ReadOne, SdrRoutine_WriteOne );
+ variable SdrRoutine_v : typSdrRoutine_t := SdrRoutine_Null;
+ variable SdrRoutineSeq_v : unsigned( 7 downto 0) := X"00";
+ variable refreshDelayCounter_v : unsigned(23 downto 0) := x"000000";
+ variable SdrRefreshCounter_v : unsigned(15 downto 0) := X"0000";
+ variable SdrPort_v : std_logic := '0';
+ variable SdrAddress_v : std_logic_vector(20 downto 0);
+
+ begin
+
+ if rising_edge(clock_i) then
+
+ ram0_ack_s <= '0';
+ ram1_ack_s <= '0';
+
+ case SdrRoutine_v is
+
+ when SdrRoutine_Null =>
+ SdrCmd_s <= SdrCmd_xx_c;
+ SdrDat_s <= (others => 'Z');
+
+ if refreshDelayCounter_v = 0 then
+ SdrRoutine_v := SdrRoutine_Init;
+ end if;
+
+ when SdrRoutine_Init =>
+ if SdrRoutineSeq_v = X"00" then
+ SdrCmd_s <= SdrCmd_pr_c;
+ SdrAdr_s <= (others => '1');
+ SdrBa_s <= '0';
+ SdrUdq_s <= '1';
+ SdrLdq_s <= '1';
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ elsif SdrRoutineSeq_v = X"04" or SdrRoutineSeq_v = X"0C" then
+ SdrCmd_s <= SdrCmd_re_c;
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ elsif SdrRoutineSeq_v = X"14" then
+ SdrCmd_s <= SdrCmd_ms_c;
+ SdrAdr_s <= "0000" & "010" & "0" & "000"; -- CAS Latency=2, WT=0(seq), BL=1
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ elsif SdrRoutineSeq_v = X"17" then
+ SdrCmd_s <= SdrCmd_xx_c;
+ SdrRoutineSeq_v := X"00";
+ SdrRoutine_v := SdrRoutine_Idle;
+ else
+ SdrCmd_s <= SdrCmd_xx_c;
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ end if;
+
+ when SdrRoutine_Idle =>
+ SdrCmd_s <= SdrCmd_xx_c;
+ SdrDat_s <= (others => 'Z');
+
+ if ram0_req_s = '1' and ram0_ack_s = '0' then
+ SdrPort_v := '0';
+ SdrAddress_v := ram0_addr_s;
+ if ram0_we_s = '1' then
+ SdrRoutine_v := SdrRoutine_WriteOne;
+ else
+ SdrRoutine_v := SdrRoutine_ReadOne;
+ end if;
+ elsif ram1_req_s = '1' and ram1_ack_s = '0' then
+ SdrPort_v := '1';
+ SdrAddress_v := ram1_addr_s;
+ if ram1_we_s = '1' then
+ SdrRoutine_v := SdrRoutine_WriteOne;
+ else
+ SdrRoutine_v := SdrRoutine_ReadOne;
+ end if;
+ elsif SdrRefreshCounter_v < 2048 and refresh_i = '1' then
+ SdrRoutine_v := SdrRoutine_RefreshAll;
+ SdrRefreshCounter_v := SdrRefreshCounter_v + 1;
+ end if;
+ when SdrRoutine_RefreshAll =>
+ if SdrRoutineSeq_v = X"00" then
+ SdrCmd_s <= SdrCmd_re_c;
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ elsif SdrRoutineSeq_v = X"06" then
+ SdrCmd_s <= SdrCmd_xx_c;
+ SdrRoutineSeq_v := X"00";
+ SdrRoutine_v := SdrRoutine_Idle;
+ else
+ SdrCmd_s <= SdrCmd_xx_c;
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ end if;
+
+ when SdrRoutine_ReadOne =>
+ if SdrRoutineSeq_v = X"00" then
+ SdrCmd_s <= SdrCmd_ac_c;
+ SdrBa_s <= SdrAddress_v(20);
+ SdrAdr_s <= SdrAddress_v(19 downto 9); -- Row (11 bits)
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ elsif SdrRoutineSeq_v = X"02" then
+ SdrCmd_s <= SdrCmd_rd_c;
+ SdrAdr_s(10 downto 8) <= "100"; -- A10 = '1' => Auto Pre-charge
+ SdrAdr_s(7 downto 0) <= SdrAddress_v(8 downto 1); -- Col (8 bits)
+ SdrUdq_s <= '0';
+ SdrLdq_s <= '0';
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ elsif SdrRoutineSeq_v = X"05" then
+ if SdrPort_v = '0' then
+ if SdrAddress_v(0) = '0' then
+ ram0_dout_s <= mem_data_io(7 downto 0);
+ else
+ ram0_dout_s <= mem_data_io(15 downto 8);
+ end if;
+ ram0_ack_s <= '1';
+ else
+ if SdrAddress_v(0) = '0' then
+ ram1_dout_s <= mem_data_io(7 downto 0);
+ else
+ ram1_dout_s <= mem_data_io(15 downto 8);
+ end if;
+ ram1_ack_s <= '1';
+ end if;
+ SdrCmd_s <= SdrCmd_xx_c;
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ elsif SdrRoutineSeq_v = X"06" then
+ SdrRoutineSeq_v := X"00";
+ SdrRoutine_v := SdrRoutine_Idle;
+ else
+ SdrCmd_s <= SdrCmd_xx_c;
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ end if;
+
+ when SdrRoutine_WriteOne =>
+ if SdrRoutineSeq_v = X"00" then
+ SdrCmd_s <= SdrCmd_ac_c;
+ SdrBa_s <= SdrAddress_v(20);
+ SdrAdr_s <= SdrAddress_v(19 downto 9);
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ elsif SdrRoutineSeq_v = X"02" then
+ SdrCmd_s <= SdrCmd_wr_c;
+ SdrAdr_s(10 downto 8) <= "100"; -- A10 = '1' => Auto Pre-charge
+ SdrAdr_s(7 downto 0) <= SdrAddress_v(8 downto 1);
+ SdrUdq_s <= not SdrAddress_v(0);
+ SdrLdq_s <= SdrAddress_v(0);
+ if SdrPort_v = '0' then
+ SdrDat_s <= ram0_din_s & ram0_din_s;
+ else
+ SdrDat_s <= ram1_din_s & ram1_din_s;
+ end if;
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ elsif SdrRoutineSeq_v = X"03" then
+ if SdrPort_v = '0' then
+ ram0_ack_s <= '1';
+ else
+ ram1_ack_s <= '1';
+ end if;
+ SdrCmd_s <= SdrCmd_xx_c;
+ SdrDat_s <= (others => 'Z');
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ elsif SdrRoutineSeq_v = X"05" then
+ SdrRoutineSeq_v := X"00";
+ SdrRoutine_v := SdrRoutine_Idle;
+ else
+ SdrCmd_s <= SdrCmd_xx_c;
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ end if;
+ end case;
+
+ refreshDelayCounter_v := refreshDelayCounter_v + 1;
+
+ if refreshDelayCounter_v >= ( freq_g * 1000 * 32 ) then
+ refreshDelayCounter_v := x"000000";
+ SdrRefreshCounter_v := x"0000";
+ end if;
+ end if;
+ end process;
+
+ mem_cke_o <= '1';
+ mem_cs_n_o <= SdrCmd_s(3);
+ mem_ras_n_o <= SdrCmd_s(2);
+ mem_cas_n_o <= SdrCmd_s(1);
+ mem_we_n_o <= SdrCmd_s(0);
+ mem_udq_o <= SdrUdq_s;
+ mem_ldq_o <= SdrLdq_s;
+ mem_ba_o <= SdrBa_s;
+ mem_addr_o <= SdrAdr_s;
+ mem_data_io <= SdrDat_s;
+
+end architecture;
\ No newline at end of file
diff --git a/common/Memory/dpSDRAM256Mb.vhd b/common/Memory/dpSDRAM256Mb.vhd
new file mode 100644
index 00000000..3009a2ed
--- /dev/null
+++ b/common/Memory/dpSDRAM256Mb.vhd
@@ -0,0 +1,373 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2016, Fabio Belavenuto (belavenuto@gmail.com)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+--
+-- Emulacao memoria dual-port para SDRAMs
+--
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.numeric_std.all;
+
+entity dpSDRAM256Mb is
+ generic (
+ freq_g : integer := 100
+ );
+ port (
+ clock_i : in std_logic;
+ reset_i : in std_logic;
+ refresh_i : in std_logic := '1';
+ -- Port 0
+ port0_cs_i : in std_logic;
+ port0_oe_i : in std_logic;
+ port0_we_i : in std_logic;
+ port0_addr_i : in std_logic_vector(24 downto 0);
+ port0_data_i : in std_logic_vector( 7 downto 0);
+ port0_data_o : out std_logic_vector( 7 downto 0);
+ -- Port 1
+ port1_cs_i : in std_logic;
+ port1_oe_i : in std_logic;
+ port1_we_i : in std_logic;
+ port1_addr_i : in std_logic_vector(24 downto 0);
+ port1_data_i : in std_logic_vector( 7 downto 0);
+ port1_data_o : out std_logic_vector( 7 downto 0);
+ -- SDRAM in board
+ mem_cke_o : out std_logic;
+ mem_cs_n_o : out std_logic;
+ mem_ras_n_o : out std_logic;
+ mem_cas_n_o : out std_logic;
+ mem_we_n_o : out std_logic;
+ mem_udq_o : out std_logic;
+ mem_ldq_o : out std_logic;
+ mem_ba_o : out std_logic_vector( 1 downto 0);
+ mem_addr_o : out std_logic_vector(12 downto 0);
+ mem_data_io : inout std_logic_vector(15 downto 0)
+ );
+end entity;
+
+architecture Behavior of dpSDRAM256Mb is
+
+ constant SdrCmd_de_c : std_logic_vector(3 downto 0) := "1111"; -- deselect
+ constant SdrCmd_xx_c : std_logic_vector(3 downto 0) := "0111"; -- no operation
+ constant SdrCmd_rd_c : std_logic_vector(3 downto 0) := "0101"; -- read
+ constant SdrCmd_wr_c : std_logic_vector(3 downto 0) := "0100"; -- write
+ constant SdrCmd_ac_c : std_logic_vector(3 downto 0) := "0011"; -- activate
+ constant SdrCmd_pr_c : std_logic_vector(3 downto 0) := "0010"; -- precharge all
+ constant SdrCmd_re_c : std_logic_vector(3 downto 0) := "0001"; -- refresh
+ constant SdrCmd_ms_c : std_logic_vector(3 downto 0) := "0000"; -- mode regiser set
+ -- SD-RAM control signals
+ signal SdrCmd_s : std_logic_vector(3 downto 0);
+ signal SdrBa_s : std_logic_vector(1 downto 0);
+ signal SdrUdq_s : std_logic;
+ signal SdrLdq_s : std_logic;
+ signal SdrAdr_s : std_logic_vector(12 downto 0);
+ signal SdrDat_s : std_logic_vector(15 downto 0);
+
+ signal ram0_req_s : std_logic;
+ signal ram0_ack_s : std_logic;
+ signal ram0_addr_s : std_logic_vector(24 downto 0);
+ signal ram0_din_s : std_logic_vector( 7 downto 0);
+ signal ram0_dout_s : std_logic_vector( 7 downto 0);
+ signal ram0_we_s : std_logic;
+
+ signal ram1_req_s : std_logic;
+ signal ram1_ack_s : std_logic;
+ signal ram1_addr_s : std_logic_vector(24 downto 0);
+ signal ram1_din_s : std_logic_vector( 7 downto 0);
+ signal ram1_dout_s : std_logic_vector( 7 downto 0);
+ signal ram1_we_s : std_logic;
+
+begin
+
+ -- Detectar pedido na porta 0
+ process (reset_i, clock_i)
+ variable pcs_v : std_logic_vector(1 downto 0);
+ variable acesso_v : std_logic;
+ begin
+ if reset_i = '1' then
+ port0_data_o <= (others => '1');
+ ram0_we_s <= '0';
+ ram0_req_s <= '0';
+ pcs_v := "00";
+ elsif rising_edge(clock_i) then
+ if ram0_req_s = '1' and ram0_ack_s = '1' then
+ if ram0_we_s = '0' then
+ port0_data_o <= ram0_dout_s;
+ end if;
+ ram0_req_s <= '0';
+ end if;
+
+ if pcs_v = "01" then
+ ram0_addr_s <= port0_addr_i;
+ ram0_req_s <= '1';
+ if port0_we_i = '1' then
+ ram0_din_s <= port0_data_i;
+ ram0_we_s <= '1';
+ else
+ ram0_we_s <= '0';
+ end if;
+ end if;
+
+ acesso_v := port0_cs_i and (port0_oe_i or port0_we_i);
+ pcs_v := pcs_v(0) & acesso_v;
+
+ end if;
+ end process;
+
+ -- Detectar pedido na porta 1
+ process (reset_i, clock_i)
+ variable pcs_v : std_logic_vector(1 downto 0);
+ variable acesso_v : std_logic;
+ begin
+ if reset_i = '1' then
+ port1_data_o <= (others => '1');
+ ram1_we_s <= '0';
+ ram1_req_s <= '0';
+ pcs_v := "00";
+ elsif rising_edge(clock_i) then
+ if ram1_req_s = '1' and ram1_ack_s = '1' then
+ if ram1_we_s = '0' then
+ port1_data_o <= ram1_dout_s;
+ end if;
+ ram1_req_s <= '0';
+ end if;
+
+ if pcs_v = "01" then
+ ram1_addr_s <= port1_addr_i;
+ ram1_req_s <= '1';
+ if port1_we_i = '1' then
+ ram1_din_s <= port1_data_i;
+ ram1_we_s <= '1';
+ else
+ ram1_we_s <= '0';
+ end if;
+ end if;
+
+ acesso_v := port1_cs_i and (port1_oe_i or port1_we_i);
+ pcs_v := pcs_v(0) & acesso_v;
+
+ end if;
+ end process;
+
+ ----------------------------
+ process (clock_i)
+
+ type typSdrRoutine_t is ( SdrRoutine_Null, SdrRoutine_Init, SdrRoutine_Idle, SdrRoutine_RefreshAll, SdrRoutine_ReadOne, SdrRoutine_WriteOne );
+ variable SdrRoutine_v : typSdrRoutine_t := SdrRoutine_Null;
+ variable SdrRoutineSeq_v : unsigned(7 downto 0) := X"00";
+
+ variable refreshDelayCounter_v : unsigned(23 downto 0) := x"000000";
+ variable SdrRefreshCounter_v : unsigned(15 downto 0) := X"0000";
+
+ variable SdrPort_v : std_logic := '0';
+ variable SdrAddress_v : std_logic_vector(24 downto 0);
+
+ begin
+
+ if rising_edge(clock_i) then
+
+ ram0_ack_s <= '0';
+ ram1_ack_s <= '0';
+
+ case SdrRoutine_v is
+
+ when SdrRoutine_Null =>
+ SdrCmd_s <= SdrCmd_xx_c;
+ SdrDat_s <= (others => 'Z');
+
+ if refreshDelayCounter_v = 0 then
+ SdrRoutine_v := SdrRoutine_Init;
+ end if;
+
+ when SdrRoutine_Init =>
+ if SdrRoutineSeq_v = X"0" then
+ SdrCmd_s <= SdrCmd_pr_c;
+ SdrAdr_s <= (others => '1');
+ SdrBa_s <= "00";
+ SdrUdq_s <= '1';
+ SdrLdq_s <= '1';
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ elsif SdrRoutineSeq_v = X"04" or SdrRoutineSeq_v = X"0C" then
+ SdrCmd_s <= SdrCmd_re_c;
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ elsif SdrRoutineSeq_v = X"14" then
+ SdrCmd_s <= SdrCmd_ms_c;
+ SdrAdr_s <= "000" & "1" & "00" & "010" & "0" & "000"; -- Single, Standard, CAS Latency=2, WT=0(seq), BL=1
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ elsif SdrRoutineSeq_v = X"17" then
+ SdrCmd_s <= SdrCmd_xx_c;
+ SdrRoutineSeq_v := X"00";
+ SdrRoutine_v := SdrRoutine_Idle;
+ else
+ SdrCmd_s <= SdrCmd_xx_c;
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ end if;
+
+ when SdrRoutine_Idle =>
+ SdrCmd_s <= SdrCmd_xx_c;
+ SdrDat_s <= (others => 'Z');
+
+ if ram0_req_s = '1' and ram0_ack_s = '0' then
+ SdrPort_v := '0';
+ SdrAddress_v := ram0_addr_s;
+ if ram0_we_s = '1' then
+ SdrRoutine_v := SdrRoutine_WriteOne;
+ else
+ SdrRoutine_v := SdrRoutine_ReadOne;
+ end if;
+ elsif ram1_req_s = '1' and ram1_ack_s = '0' then
+ SdrPort_v := '1';
+ SdrAddress_v := ram1_addr_s;
+ if ram1_we_s = '1' then
+ SdrRoutine_v := SdrRoutine_WriteOne;
+ else
+ SdrRoutine_v := SdrRoutine_ReadOne;
+ end if;
+ elsif SdrRefreshCounter_v < 8192 and refresh_i = '1' then
+ SdrRoutine_v := SdrRoutine_RefreshAll;
+ SdrRefreshCounter_v := SdrRefreshCounter_v + 1;
+ end if;
+ when SdrRoutine_RefreshAll =>
+ if SdrRoutineSeq_v = X"00" then
+ SdrCmd_s <= SdrCmd_re_c;
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ elsif SdrRoutineSeq_v = X"06" then
+ SdrCmd_s <= SdrCmd_xx_c;
+ SdrRoutineSeq_v := X"00";
+ SdrRoutine_v := SdrRoutine_Idle;
+ else
+ SdrCmd_s <= SdrCmd_xx_c;
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ end if;
+
+ when SdrRoutine_ReadOne =>
+ if SdrRoutineSeq_v = X"00" then
+ SdrCmd_s <= SdrCmd_ac_c;
+ SdrBa_s <= SdrAddress_v(24 downto 23);
+ SdrAdr_s <= SdrAddress_v(22 downto 10); -- Row (13 bits)
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ elsif SdrRoutineSeq_v = X"02" then
+ SdrCmd_s <= SdrCmd_rd_c;
+ SdrAdr_s(12 downto 9) <= "0010"; -- A10 = '1' => Auto Pre-charge
+ SdrAdr_s(8 downto 0) <= SdrAddress_v(9 downto 1);
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ SdrUdq_s <= '0';
+ SdrLdq_s <= '0';
+ elsif SdrRoutineSeq_v = X"05" then
+ if SdrPort_v = '0' then
+ if SdrAddress_v(0) = '0' then
+ ram0_dout_s <= mem_data_io(7 downto 0);
+ else
+ ram0_dout_s <= mem_data_io(15 downto 8);
+ end if;
+ ram0_ack_s <= '1';
+ else
+ if SdrAddress_v(0) = '0' then
+ ram1_dout_s <= mem_data_io(7 downto 0);
+ else
+ ram1_dout_s <= mem_data_io(15 downto 8);
+ end if;
+ ram1_ack_s <= '1';
+ end if;
+ SdrCmd_s <= SdrCmd_xx_c;
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ elsif SdrRoutineSeq_v = X"06" then
+ SdrRoutineSeq_v := X"00";
+ SdrRoutine_v := SdrRoutine_Idle;
+ else
+ SdrCmd_s <= SdrCmd_xx_c;
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ end if;
+
+ when SdrRoutine_WriteOne =>
+ if SdrRoutineSeq_v = X"00" then
+ SdrCmd_s <= SdrCmd_ac_c;
+ SdrBa_s <= SdrAddress_v(24 downto 23);
+ SdrAdr_s <= SdrAddress_v(22 downto 10);
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ elsif SdrRoutineSeq_v = X"02" then
+ SdrCmd_s <= SdrCmd_wr_c;
+ SdrAdr_s(12 downto 9) <= "0010"; -- A10 = '1' => Auto Pre-charge
+ SdrAdr_s(8 downto 0) <= SdrAddress_v(9 downto 1);
+ SdrUdq_s <= not SdrAddress_v(0);
+ SdrLdq_s <= SdrAddress_v(0);
+ if SdrPort_v = '0' then
+ SdrDat_s <= ram0_din_s & ram0_din_s;
+ else
+ SdrDat_s <= ram1_din_s & ram1_din_s;
+ end if;
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ elsif SdrRoutineSeq_v = X"03" then
+ if SdrPort_v = '0' then
+ ram0_ack_s <= '1';
+ else
+ ram1_ack_s <= '1';
+ end if;
+ SdrCmd_s <= SdrCmd_xx_c;
+ SdrDat_s <= (others => 'Z');
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ elsif SdrRoutineSeq_v = X"05" then
+ SdrRoutineSeq_v := X"00";
+ SdrRoutine_v := SdrRoutine_Idle;
+ else
+ SdrCmd_s <= SdrCmd_xx_c;
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ end if;
+ end case;
+
+ refreshDelayCounter_v := refreshDelayCounter_v + 1;
+
+ if refreshDelayCounter_v >= ( freq_g * 1000 * 64 ) then
+ refreshDelayCounter_v := x"000000";
+ SdrRefreshCounter_v := x"0000";
+ end if;
+ end if;
+ end process;
+
+ mem_cke_o <= '1';
+ mem_cs_n_o <= SdrCmd_s(3);
+ mem_ras_n_o <= SdrCmd_s(2);
+ mem_cas_n_o <= SdrCmd_s(1);
+ mem_we_n_o <= SdrCmd_s(0);
+ mem_udq_o <= SdrUdq_s;
+ mem_ldq_o <= SdrLdq_s;
+ mem_ba_o <= SdrBa_s;
+ mem_addr_o <= SdrAdr_s;
+ mem_data_io <= SdrDat_s;
+
+end architecture;
\ No newline at end of file
diff --git a/common/Memory/dpSDRAM64Mb.vhd b/common/Memory/dpSDRAM64Mb.vhd
new file mode 100644
index 00000000..9d5ccfb7
--- /dev/null
+++ b/common/Memory/dpSDRAM64Mb.vhd
@@ -0,0 +1,371 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2016, Fabio Belavenuto (belavenuto@gmail.com)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+--
+-- SDRAM dual-port emulation
+--
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.numeric_std.all;
+
+entity dpSDRAM64Mb is
+ generic (
+ freq_g : integer := 100
+ );
+ port (
+ clock_i : in std_logic;
+ reset_i : in std_logic;
+ refresh_i : in std_logic := '1';
+ -- Port 0
+ port0_cs_i : in std_logic;
+ port0_oe_i : in std_logic;
+ port0_we_i : in std_logic;
+ port0_addr_i : in std_logic_vector(22 downto 0);
+ port0_data_i : in std_logic_vector( 7 downto 0);
+ port0_data_o : out std_logic_vector( 7 downto 0);
+ -- Port 1
+ port1_cs_i : in std_logic;
+ port1_oe_i : in std_logic;
+ port1_we_i : in std_logic;
+ port1_addr_i : in std_logic_vector(22 downto 0);
+ port1_data_i : in std_logic_vector( 7 downto 0);
+ port1_data_o : out std_logic_vector( 7 downto 0);
+ -- SDRAM in board
+ mem_cke_o : out std_logic;
+ mem_cs_n_o : out std_logic;
+ mem_ras_n_o : out std_logic;
+ mem_cas_n_o : out std_logic;
+ mem_we_n_o : out std_logic;
+ mem_udq_o : out std_logic;
+ mem_ldq_o : out std_logic;
+ mem_ba_o : out std_logic_vector( 1 downto 0);
+ mem_addr_o : out std_logic_vector(11 downto 0);
+ mem_data_io : inout std_logic_vector(15 downto 0)
+ );
+end entity;
+
+architecture Behavior of dpSDRAM64Mb is
+
+ constant SdrCmd_de_c : std_logic_vector(3 downto 0) := "1111"; -- deselect
+ constant SdrCmd_xx_c : std_logic_vector(3 downto 0) := "0111"; -- no operation
+ constant SdrCmd_rd_c : std_logic_vector(3 downto 0) := "0101"; -- read
+ constant SdrCmd_wr_c : std_logic_vector(3 downto 0) := "0100"; -- write
+ constant SdrCmd_ac_c : std_logic_vector(3 downto 0) := "0011"; -- activate
+ constant SdrCmd_pr_c : std_logic_vector(3 downto 0) := "0010"; -- precharge all
+ constant SdrCmd_re_c : std_logic_vector(3 downto 0) := "0001"; -- refresh
+ constant SdrCmd_ms_c : std_logic_vector(3 downto 0) := "0000"; -- mode regiser set
+ -- SD-RAM control signals
+ signal SdrCmd_s : std_logic_vector(3 downto 0);
+ signal SdrBa_s : std_logic_vector(1 downto 0);
+ signal SdrUdq_s : std_logic;
+ signal SdrLdq_s : std_logic;
+ signal SdrAdr_s : std_logic_vector(11 downto 0);
+ signal SdrDat_s : std_logic_vector(15 downto 0);
+
+ signal ram0_req_s : std_logic;
+ signal ram0_ack_s : std_logic;
+ signal ram0_addr_s : std_logic_vector(22 downto 0);
+ signal ram0_din_s : std_logic_vector( 7 downto 0);
+ signal ram0_dout_s : std_logic_vector( 7 downto 0);
+ signal ram0_we_s : std_logic;
+
+ signal ram1_req_s : std_logic;
+ signal ram1_ack_s : std_logic;
+ signal ram1_addr_s : std_logic_vector(22 downto 0);
+ signal ram1_din_s : std_logic_vector( 7 downto 0);
+ signal ram1_dout_s : std_logic_vector( 7 downto 0);
+ signal ram1_we_s : std_logic;
+
+begin
+
+ -- Detectar pedido na porta 0
+ process (reset_i, clock_i)
+ variable pcs_v : std_logic_vector(1 downto 0);
+ variable acesso_v : std_logic;
+ begin
+ if reset_i = '1' then
+ port0_data_o <= (others => '1');
+ ram0_we_s <= '0';
+ ram0_req_s <= '0';
+ pcs_v := "00";
+ elsif rising_edge(clock_i) then
+ if ram0_req_s = '1' and ram0_ack_s = '1' then
+ if ram0_we_s = '0' then
+ port0_data_o <= ram0_dout_s;
+ end if;
+ ram0_req_s <= '0';
+ end if;
+
+ if pcs_v = "01" then
+ ram0_addr_s <= port0_addr_i;
+ ram0_req_s <= '1';
+ if port0_we_i = '1' then
+ ram0_din_s <= port0_data_i;
+ ram0_we_s <= '1';
+ else
+ ram0_we_s <= '0';
+ end if;
+ end if;
+
+ acesso_v := port0_cs_i and (port0_oe_i or port0_we_i);
+ pcs_v := pcs_v(0) & acesso_v;
+
+ end if;
+ end process;
+
+ -- Detectar pedido na porta 1
+ process (reset_i, clock_i)
+ variable pcs_v : std_logic_vector(1 downto 0);
+ variable acesso_v : std_logic;
+ begin
+ if reset_i = '1' then
+ port1_data_o <= (others => '1');
+ ram1_we_s <= '0';
+ ram1_req_s <= '0';
+ pcs_v := "00";
+ elsif rising_edge(clock_i) then
+ if ram1_req_s = '1' and ram1_ack_s = '1' then
+ if ram1_we_s = '0' then
+ port1_data_o <= ram1_dout_s;
+ end if;
+ ram1_req_s <= '0';
+ end if;
+
+ if pcs_v = "01" then
+ ram1_addr_s <= port1_addr_i;
+ ram1_req_s <= '1';
+ if port1_we_i = '1' then
+ ram1_din_s <= port1_data_i;
+ ram1_we_s <= '1';
+ else
+ ram1_we_s <= '0';
+ end if;
+ end if;
+
+ acesso_v := port1_cs_i and (port1_oe_i or port1_we_i);
+ pcs_v := pcs_v(0) & acesso_v;
+
+ end if;
+ end process;
+
+ ----------------------------
+ process (clock_i)
+
+ type typSdrRoutine_t is ( SdrRoutine_Null, SdrRoutine_Init, SdrRoutine_Idle, SdrRoutine_RefreshAll, SdrRoutine_ReadOne, SdrRoutine_WriteOne );
+ variable SdrRoutine_v : typSdrRoutine_t := SdrRoutine_Null;
+ variable SdrRoutineSeq_v : unsigned( 7 downto 0) := X"00";
+ variable refreshDelayCounter_v : unsigned(23 downto 0) := x"000000";
+ variable SdrRefreshCounter_v : unsigned(15 downto 0) := X"0000";
+ variable SdrPort_v : std_logic := '0';
+ variable SdrAddress_v : std_logic_vector(22 downto 0);
+
+ begin
+
+ if rising_edge(clock_i) then
+
+ ram0_ack_s <= '0';
+ ram1_ack_s <= '0';
+
+ case SdrRoutine_v is
+
+ when SdrRoutine_Null =>
+ SdrCmd_s <= SdrCmd_xx_c;
+ SdrDat_s <= (others => 'Z');
+
+ if refreshDelayCounter_v = 0 then
+ SdrRoutine_v := SdrRoutine_Init;
+ end if;
+
+ when SdrRoutine_Init =>
+ if SdrRoutineSeq_v = X"00" then
+ SdrCmd_s <= SdrCmd_pr_c;
+ SdrAdr_s <= (others => '1');
+ SdrBa_s <= "00";
+ SdrUdq_s <= '1';
+ SdrLdq_s <= '1';
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ elsif SdrRoutineSeq_v = X"04" or SdrRoutineSeq_v = X"0C" then
+ SdrCmd_s <= SdrCmd_re_c;
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ elsif SdrRoutineSeq_v = X"14" then
+ SdrCmd_s <= SdrCmd_ms_c;
+ SdrAdr_s <= "00" & "1" & "00" & "010" & "0" & "000"; -- Single, Standard, CAS Latency=2, WT=0(seq), BL=1
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ elsif SdrRoutineSeq_v = X"17" then
+ SdrCmd_s <= SdrCmd_xx_c;
+ SdrRoutineSeq_v := X"00";
+ SdrRoutine_v := SdrRoutine_Idle;
+ else
+ SdrCmd_s <= SdrCmd_xx_c;
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ end if;
+
+ when SdrRoutine_Idle =>
+ SdrCmd_s <= SdrCmd_xx_c;
+ SdrDat_s <= (others => 'Z');
+
+ if ram0_req_s = '1' and ram0_ack_s = '0' then
+ SdrPort_v := '0';
+ SdrAddress_v := ram0_addr_s;
+ if ram0_we_s = '1' then
+ SdrRoutine_v := SdrRoutine_WriteOne;
+ else
+ SdrRoutine_v := SdrRoutine_ReadOne;
+ end if;
+ elsif ram1_req_s = '1' and ram1_ack_s = '0' then
+ SdrPort_v := '1';
+ SdrAddress_v := ram1_addr_s;
+ if ram1_we_s = '1' then
+ SdrRoutine_v := SdrRoutine_WriteOne;
+ else
+ SdrRoutine_v := SdrRoutine_ReadOne;
+ end if;
+ elsif SdrRefreshCounter_v < 4096 and refresh_i = '1' then
+ SdrRoutine_v := SdrRoutine_RefreshAll;
+ SdrRefreshCounter_v := SdrRefreshCounter_v + 1;
+ end if;
+ when SdrRoutine_RefreshAll =>
+ if SdrRoutineSeq_v = X"00" then
+ SdrCmd_s <= SdrCmd_re_c;
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ elsif SdrRoutineSeq_v = X"06" then
+ SdrCmd_s <= SdrCmd_xx_c;
+ SdrRoutineSeq_v := X"00";
+ SdrRoutine_v := SdrRoutine_Idle;
+ else
+ SdrCmd_s <= SdrCmd_xx_c;
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ end if;
+
+ when SdrRoutine_ReadOne =>
+ if SdrRoutineSeq_v = X"00" then
+ SdrCmd_s <= SdrCmd_ac_c;
+ SdrBa_s <= SdrAddress_v(22 downto 21);
+ SdrAdr_s <= SdrAddress_v(20 downto 9); -- Row (12 bits)
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ elsif SdrRoutineSeq_v = X"02" then
+ SdrCmd_s <= SdrCmd_rd_c;
+ SdrAdr_s(11 downto 8) <= "0100"; -- A10 = '1' => Auto Pre-charge
+ SdrAdr_s(7 downto 0) <= SdrAddress_v(8 downto 1); -- Col (8 bits)
+ SdrUdq_s <= '0';
+ SdrLdq_s <= '0';
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ elsif SdrRoutineSeq_v = X"05" then
+ if SdrPort_v = '0' then
+ if SdrAddress_v(0) = '0' then
+ ram0_dout_s <= mem_data_io(7 downto 0);
+ else
+ ram0_dout_s <= mem_data_io(15 downto 8);
+ end if;
+ ram0_ack_s <= '1';
+ else
+ if SdrAddress_v(0) = '0' then
+ ram1_dout_s <= mem_data_io(7 downto 0);
+ else
+ ram1_dout_s <= mem_data_io(15 downto 8);
+ end if;
+ ram1_ack_s <= '1';
+ end if;
+ SdrCmd_s <= SdrCmd_xx_c;
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ elsif SdrRoutineSeq_v = X"06" then
+ SdrRoutineSeq_v := X"00";
+ SdrRoutine_v := SdrRoutine_Idle;
+ else
+ SdrCmd_s <= SdrCmd_xx_c;
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ end if;
+
+ when SdrRoutine_WriteOne =>
+ if SdrRoutineSeq_v = X"00" then
+ SdrCmd_s <= SdrCmd_ac_c;
+ SdrBa_s <= SdrAddress_v(22 downto 21);
+ SdrAdr_s <= SdrAddress_v(20 downto 9);
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ elsif SdrRoutineSeq_v = X"02" then
+ SdrCmd_s <= SdrCmd_wr_c;
+ SdrAdr_s(11 downto 8) <= "0100"; -- A10 = '1' => Auto Pre-charge
+ SdrAdr_s(7 downto 0) <= SdrAddress_v(8 downto 1);
+ SdrUdq_s <= not SdrAddress_v(0);
+ SdrLdq_s <= SdrAddress_v(0);
+ if SdrPort_v = '0' then
+ SdrDat_s <= ram0_din_s & ram0_din_s;
+ else
+ SdrDat_s <= ram1_din_s & ram1_din_s;
+ end if;
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ elsif SdrRoutineSeq_v = X"03" then
+ if SdrPort_v = '0' then
+ ram0_ack_s <= '1';
+ else
+ ram1_ack_s <= '1';
+ end if;
+ SdrCmd_s <= SdrCmd_xx_c;
+ SdrDat_s <= (others => 'Z');
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ elsif SdrRoutineSeq_v = X"05" then
+ SdrRoutineSeq_v := X"00";
+ SdrRoutine_v := SdrRoutine_Idle;
+ else
+ SdrCmd_s <= SdrCmd_xx_c;
+ SdrRoutineSeq_v := SdrRoutineSeq_v + 1;
+ end if;
+ end case;
+
+ refreshDelayCounter_v := refreshDelayCounter_v + 1;
+
+ if refreshDelayCounter_v >= ( freq_g * 1000 * 64 ) then
+ refreshDelayCounter_v := x"000000";
+ SdrRefreshCounter_v := x"0000";
+ end if;
+ end if;
+ end process;
+
+ mem_cke_o <= '1';
+ mem_cs_n_o <= SdrCmd_s(3);
+ mem_ras_n_o <= SdrCmd_s(2);
+ mem_cas_n_o <= SdrCmd_s(1);
+ mem_we_n_o <= SdrCmd_s(0);
+ mem_udq_o <= SdrUdq_s;
+ mem_ldq_o <= SdrLdq_s;
+ mem_ba_o <= SdrBa_s;
+ mem_addr_o <= SdrAdr_s;
+ mem_data_io <= SdrDat_s;
+
+end architecture;
\ No newline at end of file
diff --git a/common/Memory/dpSRAM_1288.vhd b/common/Memory/dpSRAM_1288.vhd
new file mode 100644
index 00000000..997a696b
--- /dev/null
+++ b/common/Memory/dpSRAM_1288.vhd
@@ -0,0 +1,136 @@
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity dpSRAM_1288 is
+ port (
+ clk_i : in std_logic;
+ -- Porta 0
+ porta0_addr_i : in std_logic_vector(16 downto 0);
+ porta0_ce_i : in std_logic;
+ porta0_oe_i : in std_logic;
+ porta0_we_i : in std_logic;
+ porta0_data_i : in std_logic_vector(7 downto 0);
+ porta0_data_o : out std_logic_vector(7 downto 0);
+ -- Porta 1
+ porta1_addr_i : in std_logic_vector(16 downto 0);
+ porta1_ce_i : in std_logic;
+ porta1_oe_i : in std_logic;
+ porta1_we_i : in std_logic;
+ porta1_data_i : in std_logic_vector(7 downto 0);
+ porta1_data_o : out std_logic_vector(7 downto 0);
+ -- Output to SRAM in board
+ sram_addr_o : out std_logic_vector(16 downto 0);
+ sram_data_io : inout std_logic_vector(7 downto 0);
+ sram_ce_n_o : out std_logic := '1';
+ sram_oe_n_o : out std_logic := '1';
+ sram_we_n_o : out std_logic := '1'
+ );
+end entity;
+
+architecture Behavior of dpSRAM_1288 is
+
+ signal sram_we_n_s : std_logic;
+ signal sram_oe_n_s : std_logic;
+
+begin
+
+ sram_ce_n_o <= '0'; -- sempre ativa
+ sram_we_n_o <= sram_we_n_s;
+ sram_oe_n_o <= sram_oe_n_s;
+
+ process (clk_i)
+
+ variable state_v : std_logic := '0';
+ variable p0_ce_v : std_logic_vector(1 downto 0);
+ variable p1_ce_v : std_logic_vector(1 downto 0);
+ variable acesso0_v : std_logic;
+ variable acesso1_v : std_logic;
+ variable p0_req_v : std_logic := '0';
+ variable p1_req_v : std_logic := '0';
+ variable p0_we_v : std_logic := '0';
+ variable p1_we_v : std_logic := '0';
+ variable p0_addr_v : std_logic_vector(16 downto 0);
+ variable p1_addr_v : std_logic_vector(16 downto 0);
+ variable p0_data_v : std_logic_vector(7 downto 0);
+ variable p1_data_v : std_logic_vector(7 downto 0);
+
+ begin
+ if rising_edge(clk_i) then
+ acesso0_v := porta0_ce_i and (porta0_oe_i or porta0_we_i);
+ acesso1_v := porta1_ce_i and (porta1_oe_i or porta1_we_i);
+ p0_ce_v := p0_ce_v(0) & acesso0_v;
+ p1_ce_v := p1_ce_v(0) & acesso1_v;
+
+ if p0_ce_v = "01" then -- detecta rising edge do pedido da porta0
+ p0_req_v := '1'; -- marca que porta0 pediu acesso
+ p0_we_v := '0'; -- por enquanto eh leitura
+ p0_addr_v := porta0_addr_i; -- pegamos endereco
+ if porta0_we_i = '1' then -- se foi gravacao que a porta0 pediu
+ p0_we_v := '1'; -- marcamos que eh gravacao
+ p0_data_v := porta0_data_i; -- pegamos dado
+ end if;
+ end if;
+
+ if p1_ce_v = "01" then -- detecta rising edge do pedido da porta1
+ p1_req_v := '1'; -- marca que porta1 pediu acesso
+ p1_we_v := '0'; -- por enquanto eh leitura
+ p1_addr_v := porta1_addr_i; -- pegamos endereco
+ if porta1_we_i = '1' then -- se foi gravacao que a porta1 pediu
+ p1_we_v := '1'; -- marcamos que eh gravacao
+ p1_data_v := porta1_data_i; -- pegamos dado
+ end if;
+ end if;
+
+ if state_v = '0' then -- Estado 0
+ sram_data_io <= (others => 'Z'); -- desconectar bus da SRAM
+ if p0_req_v = '1' then -- pedido da porta0 pendente
+ sram_addr_o <= p0_addr_v; -- colocamos o endereco pedido na SRAM
+ sram_we_n_s <= '1';
+-- sram_ce_n <= '0';
+ sram_oe_n_s <= '0';
+ if p0_we_v = '1' then -- se for gravacao
+ sram_data_io <= p0_data_v; -- damos o dado para a SRAM
+ sram_we_n_s <= '0'; -- e dizemos para ela gravar
+ sram_oe_n_s <= '1';
+ end if;
+ state_v := '1';
+ elsif p1_req_v = '1' then -- pedido da porta1 pendente
+ sram_addr_o <= p1_addr_v; -- colocamos o endereco pedido na SRAM
+ sram_we_n_s <= '1';
+-- sram_ce_n <= '0';
+ sram_oe_n_s <= '0';
+ if p1_we_v = '1' then -- se for gravacao
+ sram_data_io <= p1_data_v; -- damos o dado para a SRAM
+ sram_we_n_s <= '0'; -- e dizemos para ela gravar
+ sram_oe_n_s <= '1';
+ end if;
+ state_v := '1'; -- proximo rising do clock vamos para segundo estado
+ end if;
+ elsif state_v = '1' then -- Estado 1
+ if p0_req_v = '1' then -- pedido da porta0 pendente
+ sram_we_n_s <= '1';
+ sram_data_io <= (others => 'Z'); -- desconectar bus da SRAM
+ if p0_we_v = '0' then -- se for leitura
+ porta0_data_o <= sram_data_io; -- pegamos o dado que a SRAM devolveu
+ end if;
+ p0_req_v := '0'; -- limpamos a flag de requisicao da porta0
+ state_v := '0'; -- voltar para estado 0
+ sram_oe_n_s <= '1';
+-- sram_ce_n <= '1';
+ elsif p1_req_v = '1' then -- pedido da porta1 pendente
+ sram_we_n_s <= '1';
+ sram_data_io <= (others => 'Z'); -- desconectar bus da SRAM
+ if p1_we_v = '0' then -- se for leitura
+ porta1_data_o <= sram_data_io; -- pegamos o dado que a SRAM devolveu
+ end if;
+ p1_req_v := '0'; -- limpamos a flag de requisicao da porta1
+ state_v := '0'; -- voltar para estado 0
+ sram_oe_n_s <= '1';
+-- sram_ce_n <= '1';
+ end if;
+ end if;
+ end if;
+ end process;
+
+end;
\ No newline at end of file
diff --git a/common/Memory/dpSRAM_25616.vhd b/common/Memory/dpSRAM_25616.vhd
new file mode 100644
index 00000000..f3f1924f
--- /dev/null
+++ b/common/Memory/dpSRAM_25616.vhd
@@ -0,0 +1,186 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2016, Fabio Belavenuto (belavenuto@gmail.com)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity dpSRAM_25616 is
+ port (
+ clk_i : in std_logic;
+ -- Port 0
+ porta0_addr_i : in std_logic_vector(18 downto 0);
+ porta0_ce_i : in std_logic;
+ porta0_oe_i : in std_logic;
+ porta0_we_i : in std_logic;
+ porta0_d_i : in std_logic_vector(7 downto 0);
+ porta0_d_o : out std_logic_vector(7 downto 0);
+ -- Port 1
+ porta1_addr_i : in std_logic_vector(18 downto 0);
+ porta1_ce_i : in std_logic;
+ porta1_oe_i : in std_logic;
+ porta1_we_i : in std_logic;
+ porta1_d_i : in std_logic_vector(7 downto 0);
+ porta1_d_o : out std_logic_vector(7 downto 0);
+ -- SRAM in board
+ sram_addr_o : out std_logic_vector(17 downto 0);
+ sram_data_io : inout std_logic_vector(15 downto 0);
+ sram_ub_o : out std_logic;
+ sram_lb_o : out std_logic;
+ sram_ce_n_o : out std_logic := '1';
+ sram_oe_n_o : out std_logic := '1';
+ sram_we_n_o : out std_logic := '1'
+ );
+end entity;
+
+architecture Behavior of dpSRAM_25616 is
+
+ signal sram_a_s : std_logic_vector(18 downto 0);
+ signal sram_d_s : std_logic_vector(7 downto 0);
+ signal sram_we_s : std_logic;
+ signal sram_oe_s : std_logic;
+
+begin
+
+ sram_ce_n_o <= '0'; -- sempre ativa
+ sram_oe_n_o <= sram_oe_s;
+ sram_we_n_o <= sram_we_s;
+ sram_ub_o <= not sram_a_s(0); -- UB = 0 ativa bits 15..8
+ sram_lb_o <= sram_a_s(0); -- LB = 0 ativa bits 7..0
+ sram_addr_o <= sram_a_s(18 downto 1);
+ sram_data_io <= "ZZZZZZZZ" & sram_d_s when sram_a_s(0) = '0' else
+ sram_d_s & "ZZZZZZZZ";
+
+ process (clk_i)
+
+ variable state_v : std_logic := '0';
+ variable p0_ce_v : std_logic_vector(1 downto 0);
+ variable p1_ce_v : std_logic_vector(1 downto 0);
+ variable acesso0_v : std_logic;
+ variable acesso1_v : std_logic;
+ variable p0_req_v : std_logic := '0';
+ variable p1_req_v : std_logic := '0';
+ variable p0_we_v : std_logic := '0';
+ variable p1_we_v : std_logic := '0';
+ variable p0_addr_v : std_logic_vector(18 downto 0);
+ variable p1_addr_v : std_logic_vector(18 downto 0);
+ variable p0_data_v : std_logic_vector(7 downto 0);
+ variable p1_data_v : std_logic_vector(7 downto 0);
+
+ begin
+ if rising_edge(clk_i) then
+ acesso0_v := porta0_ce_i and (porta0_oe_i or porta0_we_i);
+ acesso1_v := porta1_ce_i and (porta1_oe_i or porta1_we_i);
+ p0_ce_v := p0_ce_v(0) & acesso0_v;
+ p1_ce_v := p1_ce_v(0) & acesso1_v;
+
+ if p0_ce_v = "01" then -- detecta rising edge do pedido da porta0
+ p0_req_v := '1'; -- marca que porta0 pediu acesso
+ p0_we_v := '0'; -- por enquanto eh leitura
+ p0_addr_v := porta0_addr_i; -- pegamos endereco
+ if porta0_we_i = '1' then -- se foi gravacao que a porta0 pediu
+ p0_we_v := '1'; -- marcamos que eh gravacao
+ p0_data_v := porta0_d_i; -- pegamos dado
+ end if;
+ end if;
+
+ if p1_ce_v = "01" then -- detecta rising edge do pedido da porta1
+ p1_req_v := '1'; -- marca que porta1 pediu acesso
+ p1_we_v := '0'; -- por enquanto eh leitura
+ p1_addr_v := porta1_addr_i; -- pegamos endereco
+ if porta1_we_i = '1' then -- se foi gravacao que a porta1 pediu
+ p1_we_v := '1'; -- marcamos que eh gravacao
+ p1_data_v := porta1_d_i; -- pegamos dado
+ end if;
+ end if;
+
+ if state_v = '0' then -- Estado 0
+ sram_d_s <= (others => 'Z'); -- desconectar bus da SRAM
+ if p0_req_v = '1' then -- pedido da porta0 pendente
+ sram_a_s <= p0_addr_v; -- colocamos o endereco pedido na SRAM
+ sram_we_s <= '1';
+ sram_oe_s <= '0';
+ if p0_we_v = '1' then -- se for gravacao
+ sram_d_s <= p0_data_v; -- damos o dado para a SRAM
+ sram_we_s <= '0'; -- e dizemos para ela gravar
+ sram_oe_s <= '1';
+ end if;
+ state_v := '1';
+ elsif p1_req_v = '1' then -- pedido da porta1 pendente
+ sram_a_s <= p1_addr_v; -- colocamos o endereco pedido na SRAM
+ sram_we_s <= '1';
+ sram_oe_s <= '0';
+ if p1_we_v = '1' then -- se for gravacao
+ sram_d_s <= p1_data_v; -- damos o dado para a SRAM
+ sram_we_s <= '0'; -- e dizemos para ela gravar
+ sram_oe_s <= '1';
+ end if;
+ state_v := '1'; -- proximo rising do clock vamos para segundo estado
+ end if;
+ elsif state_v = '1' then -- Estado 1
+ if p0_req_v = '1' then -- pedido da porta0 pendente
+ sram_we_s <= '1';
+ sram_d_s <= (others => 'Z'); -- desconectar bus da SRAM
+ if p0_we_v = '0' then -- se for leitura
+ if sram_a_s(0) = '0' then -- pegamos o dado que a SRAM devolveu
+ porta0_d_o <= sram_data_io(7 downto 0);
+ else
+ porta0_d_o <= sram_data_io(15 downto 8);
+ end if;
+ end if;
+ p0_req_v := '0'; -- limpamos a flag de requisicao da porta0
+ state_v := '0'; -- voltar para estado 0
+ sram_oe_s <= '1';
+ elsif p1_req_v = '1' then -- pedido da porta1 pendente
+ sram_we_s <= '1';
+ sram_d_s <= (others => 'Z'); -- desconectar bus da SRAM
+ if p1_we_v = '0' then -- se for leitura
+ if sram_a_s(0) = '0' then -- pegamos o dado que a SRAM devolveu
+ porta1_d_o <= sram_data_io(7 downto 0);
+ else
+ porta1_d_o <= sram_data_io(15 downto 8);
+ end if;
+ end if;
+ p1_req_v := '0'; -- limpamos a flag de requisicao da porta1
+ state_v := '0'; -- voltar para estado 0
+ sram_oe_s <= '1';
+ end if;
+ end if;
+ end if;
+ end process;
+
+end;
\ No newline at end of file
diff --git a/common/Memory/dpSRAM_5128.vhd b/common/Memory/dpSRAM_5128.vhd
new file mode 100644
index 00000000..10551947
--- /dev/null
+++ b/common/Memory/dpSRAM_5128.vhd
@@ -0,0 +1,173 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2016, Fabio Belavenuto (belavenuto@gmail.com)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity dpSRAM_5128 is
+ port (
+ clk_i : in std_logic;
+ -- Port 0
+ porta0_addr_i : in std_logic_vector(18 downto 0);
+ porta0_ce_i : in std_logic;
+ porta0_oe_i : in std_logic;
+ porta0_we_i : in std_logic;
+ porta0_data_i : in std_logic_vector(7 downto 0);
+ porta0_data_o : out std_logic_vector(7 downto 0);
+ -- Port 1
+ porta1_addr_i : in std_logic_vector(18 downto 0);
+ porta1_ce_i : in std_logic;
+ porta1_oe_i : in std_logic;
+ porta1_we_i : in std_logic;
+ porta1_data_i : in std_logic_vector(7 downto 0);
+ porta1_data_o : out std_logic_vector(7 downto 0);
+ -- SRAM in board
+ sram_addr_o : out std_logic_vector(18 downto 0);
+ sram_data_io : inout std_logic_vector(7 downto 0);
+ sram_ce_n_o : out std_logic := '1';
+ sram_oe_n_o : out std_logic := '1';
+ sram_we_n_o : out std_logic := '1'
+ );
+end entity;
+
+architecture Behavior of dpSRAM_5128 is
+
+ signal sram_we_s : std_logic;
+ signal sram_oe_s : std_logic;
+
+begin
+
+ sram_ce_n_o <= '0'; -- sempre ativa
+ sram_we_n_o <= sram_we_s;
+ sram_oe_n_o <= sram_oe_s;
+
+ process (clk_i)
+
+ variable state_v : std_logic := '0';
+ variable p0_ce_v : std_logic_vector(1 downto 0);
+ variable p1_ce_v : std_logic_vector(1 downto 0);
+ variable acesso0_v : std_logic;
+ variable acesso1_v : std_logic;
+ variable p0_req_v : std_logic := '0';
+ variable p1_req_v : std_logic := '0';
+ variable p0_we_v : std_logic := '0';
+ variable p1_we_v : std_logic := '0';
+ variable p0_addr_v : std_logic_vector(18 downto 0);
+ variable p1_addr_v : std_logic_vector(18 downto 0);
+ variable p0_data_v : std_logic_vector(7 downto 0);
+ variable p1_data_v : std_logic_vector(7 downto 0);
+
+ begin
+ if rising_edge(clk_i) then
+ acesso0_v := porta0_ce_i and (porta0_oe_i or porta0_we_i);
+ acesso1_v := porta1_ce_i and (porta1_oe_i or porta1_we_i);
+ p0_ce_v := p0_ce_v(0) & acesso0_v;
+ p1_ce_v := p1_ce_v(0) & acesso1_v;
+
+ if p0_ce_v = "01" then -- detecta rising edge do pedido da porta0
+ p0_req_v := '1'; -- marca que porta0 pediu acesso
+ p0_we_v := '0'; -- por enquanto eh leitura
+ p0_addr_v := porta0_addr_i; -- pegamos endereco
+ if porta0_we_i = '1' then -- se foi gravacao que a porta0 pediu
+ p0_we_v := '1'; -- marcamos que eh gravacao
+ p0_data_v := porta0_data_i; -- pegamos dado
+ end if;
+ end if;
+
+ if p1_ce_v = "01" then -- detecta rising edge do pedido da porta1
+ p1_req_v := '1'; -- marca que porta1 pediu acesso
+ p1_we_v := '0'; -- por enquanto eh leitura
+ p1_addr_v := porta1_addr_i; -- pegamos endereco
+ if porta1_we_i = '1' then -- se foi gravacao que a porta1 pediu
+ p1_we_v := '1'; -- marcamos que eh gravacao
+ p1_data_v := porta1_data_i; -- pegamos dado
+ end if;
+ end if;
+
+ if state_v = '0' then -- Estado 0
+ sram_data_io <= (others => 'Z'); -- desconectar bus da SRAM
+ if p0_req_v = '1' then -- pedido da porta0 pendente
+ sram_addr_o <= p0_addr_v; -- colocamos o endereco pedido na SRAM
+ sram_we_s <= '1';
+-- sram_ce_n <= '0';
+ sram_oe_s <= '0';
+ if p0_we_v = '1' then -- se for gravacao
+ sram_data_io <= p0_data_v; -- damos o dado para a SRAM
+ sram_we_s <= '0'; -- e dizemos para ela gravar
+ sram_oe_s <= '1';
+ end if;
+ state_v := '1';
+ elsif p1_req_v = '1' then -- pedido da porta1 pendente
+ sram_addr_o <= p1_addr_v; -- colocamos o endereco pedido na SRAM
+ sram_we_s <= '1';
+-- sram_ce_n <= '0';
+ sram_oe_s <= '0';
+ if p1_we_v = '1' then -- se for gravacao
+ sram_data_io <= p1_data_v; -- damos o dado para a SRAM
+ sram_we_s <= '0'; -- e dizemos para ela gravar
+ sram_oe_s <= '1';
+ end if;
+ state_v := '1'; -- proximo rising do clock vamos para segundo estado
+ end if;
+ elsif state_v = '1' then -- Estado 1
+ if p0_req_v = '1' then -- pedido da porta0 pendente
+ sram_we_s <= '1';
+ sram_data_io <= (others => 'Z'); -- desconectar bus da SRAM
+ if p0_we_v = '0' then -- se for leitura
+ porta0_data_o <= sram_data_io; -- pegamos o dado que a SRAM devolveu
+ end if;
+ p0_req_v := '0'; -- limpamos a flag de requisicao da porta0
+ state_v := '0'; -- voltar para estado 0
+ sram_oe_s <= '1';
+-- sram_ce_n <= '1';
+ elsif p1_req_v = '1' then -- pedido da porta1 pendente
+ sram_we_s <= '1';
+ sram_data_io <= (others => 'Z'); -- desconectar bus da SRAM
+ if p1_we_v = '0' then -- se for leitura
+ porta1_data_o <= sram_data_io; -- pegamos o dado que a SRAM devolveu
+ end if;
+ p1_req_v := '0'; -- limpamos a flag de requisicao da porta1
+ state_v := '0'; -- voltar para estado 0
+ sram_oe_s <= '1';
+-- sram_ce_n <= '1';
+ end if;
+ end if;
+ end if;
+ end process;
+
+end;
\ No newline at end of file
diff --git a/common/Memory/dpram.vhd b/common/Memory/dpram.vhd
new file mode 100644
index 00000000..d867b5d2
--- /dev/null
+++ b/common/Memory/dpram.vhd
@@ -0,0 +1,59 @@
+-------------------------------------------------------------------------------
+-- $Id: dpram.vhd,v 1.1 2006/02/23 21:46:45 arnim Exp $
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+
+entity dpram is
+ generic (
+ addr_width_g : integer := 8;
+ data_width_g : integer := 8
+ );
+ port (
+ clk_a_i : in std_logic;
+ we_i : in std_logic;
+ addr_a_i : in std_logic_vector(addr_width_g-1 downto 0);
+ data_a_i : in std_logic_vector(data_width_g-1 downto 0);
+ data_a_o : out std_logic_vector(data_width_g-1 downto 0);
+ clk_b_i : in std_logic;
+ addr_b_i : in std_logic_vector(addr_width_g-1 downto 0);
+ data_b_o : out std_logic_vector(data_width_g-1 downto 0)
+ );
+end entity;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+architecture rtl of dpram is
+
+ type ram_t is array (natural range 2**addr_width_g-1 downto 0) of
+ std_logic_vector(data_width_g-1 downto 0);
+ signal ram_q : ram_t;
+
+begin
+
+ mem_a: process (clk_a_i)
+ variable read_addr_v : unsigned(addr_width_g-1 downto 0);
+ begin
+ if rising_edge(clk_a_i) then
+ read_addr_v := unsigned(addr_a_i);
+ if we_i = '1' then
+ ram_q(to_integer(read_addr_v)) <= data_a_i;
+ end if;
+ data_a_o <= ram_q(to_integer(read_addr_v));
+ end if;
+ end process mem_a;
+
+ mem_b: process (clk_b_i)
+ variable read_addr_v : unsigned(addr_width_g-1 downto 0);
+ begin
+ if rising_edge(clk_b_i) then
+ read_addr_v := unsigned(addr_b_i);
+ data_b_o <= ram_q(to_integer(read_addr_v));
+ end if;
+ end process mem_b;
+
+end rtl;
diff --git a/common/Memory/spram.vhd b/common/Memory/spram.vhd
new file mode 100644
index 00000000..6d006211
--- /dev/null
+++ b/common/Memory/spram.vhd
@@ -0,0 +1,89 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2016, Fabio Belavenuto (belavenuto@gmail.com)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+--
+-- Generic single port RAM.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity spram is
+ generic (
+ addr_width_g : integer := 8;
+ data_width_g : integer := 8
+ );
+ port (
+ clk_i : in std_logic;
+ we_i : in std_logic;
+ addr_i : in std_logic_vector(addr_width_g-1 downto 0);
+ data_i : in std_logic_vector(data_width_g-1 downto 0);
+ data_o : out std_logic_vector(data_width_g-1 downto 0)
+ );
+
+end spram;
+
+library ieee;
+use ieee.numeric_std.all;
+
+architecture rtl of spram is
+
+ type ram_t is array (natural range 2**addr_width_g-1 downto 0) of std_logic_vector(data_width_g-1 downto 0);
+ signal ram_q : ram_t
+ -- pragma translate_off
+ := (others => (others => '0'))
+ -- pragma translate_on
+ ;
+ signal read_addr_q : unsigned(addr_width_g-1 downto 0);
+
+begin
+
+ process (clk_i)
+ begin
+ if rising_edge(clk_i) then
+ if we_i = '1' then
+ ram_q(to_integer(unsigned(addr_i))) <= data_i;
+ end if;
+
+ read_addr_q <= unsigned(addr_i);
+ end if;
+ end process;
+
+ data_o <= ram_q(to_integer(read_addr_q));
+
+end rtl;
diff --git a/common/Memory/sprom.vhd b/common/Memory/sprom.vhd
new file mode 100644
index 00000000..3ec3beb7
--- /dev/null
+++ b/common/Memory/sprom.vhd
@@ -0,0 +1,77 @@
+LIBRARY ieee;
+USE ieee.std_logic_1164.all;
+
+LIBRARY altera_mf;
+USE altera_mf.all;
+
+ENTITY sprom IS
+ GENERIC
+ (
+ init_file : string := "";
+ numwords_a : natural := 0; -- not used any more
+ widthad_a : natural;
+ width_a : natural := 8;
+ outdata_reg_a : string := "UNREGISTERED"
+ );
+ PORT
+ (
+ address : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0);
+ clock : IN STD_LOGIC ;
+ q : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0)
+ );
+END sprom;
+
+
+ARCHITECTURE SYN OF sprom IS
+
+ SIGNAL sub_wire0 : STD_LOGIC_VECTOR (width_a-1 DOWNTO 0);
+
+ COMPONENT altsyncram
+ GENERIC (
+ clock_enable_input_a : STRING;
+ clock_enable_output_a : STRING;
+ init_file : STRING;
+ intended_device_family : STRING;
+ lpm_hint : STRING;
+ lpm_type : STRING;
+ numwords_a : NATURAL;
+ operation_mode : STRING;
+ outdata_aclr_a : STRING;
+ outdata_reg_a : STRING;
+ widthad_a : NATURAL;
+ width_a : NATURAL;
+ width_byteena_a : NATURAL
+ );
+ PORT (
+ clock0 : IN STD_LOGIC ;
+ address_a : IN STD_LOGIC_VECTOR (widthad_a-1 DOWNTO 0);
+ q_a : OUT STD_LOGIC_VECTOR (width_a-1 DOWNTO 0)
+ );
+ END COMPONENT;
+
+BEGIN
+ q <= sub_wire0(width_a-1 DOWNTO 0);
+
+ altsyncram_component : altsyncram
+ GENERIC MAP (
+ clock_enable_input_a => "BYPASS",
+ clock_enable_output_a => "BYPASS",
+ init_file => init_file,
+ intended_device_family => "Cyclone II",
+ lpm_hint => "ENABLE_RUNTIME_MOD=NO",
+ lpm_type => "altsyncram",
+ numwords_a => 2**widthad_a,
+ operation_mode => "ROM",
+ outdata_aclr_a => "NONE",
+ outdata_reg_a => outdata_reg_a,
+ widthad_a => widthad_a,
+ width_a => width_a,
+ width_byteena_a => 1
+ )
+ PORT MAP (
+ clock0 => clock,
+ address_a => address,
+ q_a => sub_wire0
+ );
+
+END SYN;
diff --git a/common/PIO.vhd b/common/PIO.vhd
new file mode 100644
index 00000000..be9196fe
--- /dev/null
+++ b/common/PIO.vhd
@@ -0,0 +1,219 @@
+------------------------------------------------------------------------------
+-- Project : Red Zombie
+------------------------------------------------------------------------------
+-- File : redzombie.vhd
+-- Author : fpgakuechle
+-- Company : hobbyist
+-- Created : 2012-12
+-- Last update: 2013-04-02
+-- Lizenz : GNU General Public License (http://www.gnu.de/documents/gpl.de.html)
+------------------------------------------------------------------------------
+-- Description:
+--parallel io unit
+--Zilog Z80 PIO - U855
+------------------------------------------------------------------------------
+--Status: UNDER CONSTRUCTION: 2013-03-03
+--missing: IRQ-control
+--control register/data path under test now
+--last change: fixed: mixed up mask and mode register; add single bit mode
+-- fixed: outputs *_rdy at single bit mode
+------------------------------------------------------------------------------
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity pio is
+ port(
+ clk : in std_logic;
+ ce_ni : in std_logic;
+ IOREQn_i : in std_logic;
+ data_o : out std_logic_vector(7 downto 0);
+ data_i : in std_logic_vector(7 downto 0);
+ RD_n : in std_logic;
+ M1_n : in std_logic;
+
+ sel_b_nA : in std_logic;
+ sel_c_nD : in std_logic;
+ --
+ IRQEna_i : in std_logic;
+ IRQEna_o : out std_logic;
+
+ INTn_o : out std_logic;
+
+ astb_n : in std_logic; --Data strobe in, is able to generate IREQ
+ ardy_n : out std_logic; --
+ porta_o : out std_logic_vector(7 downto 0);
+ porta_i : in std_logic_vector(7 downto 0);
+
+ bstb_n : in std_logic;
+ brdy_n : out std_logic;
+ portb_o : out std_logic_vector(7 downto 0);
+ portb_i : in std_logic_vector(7 downto 0));
+end entity pio;
+
+architecture behave of pio is
+ signal ctrl_selected : boolean;
+ signal data_selected : boolean;
+
+ type T_ALL_REGS_INDEX is (
+ IRQ_VEC, MODE, PORTDIR, IRQ_CTRL, MASK, ERR);
+ type T_PORT_INDEX is (PORT_A, PORT_B);
+
+ subtype T_REG is std_logic_vector(7 downto 0);
+ type T_ALL_REGS is array (T_ALL_REGS_INDEX) of T_REG;
+
+ signal reg_index : T_ALL_REGS_INDEX;
+
+ type T_2P_SL is array (T_PORT_INDEX'left to T_PORT_INDEX'right) of std_logic;
+ type T_2P_REG_7b is array (T_PORT_INDEX) of std_logic_vector(7 downto 1);
+ type T_2P_REG_8b is array (T_PORT_INDEX) of std_logic_vector(7 downto 0);
+ type T_2P_REG_2b is array (T_PORT_INDEX) of std_logic_vector(7 downto 6);
+
+ --default mode: Byte - Out
+ signal mode_reg : T_2P_REG_2b := (others => "01");
+ signal portdir_reg : T_2P_REG_8b := (others => x"00");
+ signal mask_reg : T_2P_REG_8b := (others => x"00");
+ signal irq_vec_reg : T_2P_REG_7b := (others => "0000000");
+
+ signal irq_ctrl_reg : std_logic_vector(7 downto 4) := (others => '0');
+ signal err_reg : std_logic_vector(7 downto 0) := (others => '0');
+
+ signal wr_dir_reg_q : boolean := false;
+ signal wr_mask_reg_q : boolean := false;
+
+ signal data_oq : std_logic_vector(7 downto 0);
+ signal port_sel : T_PORT_INDEX;
+ --ports as vectors
+ signal port_indata : T_2P_REG_8b;
+ signal port_outdata : T_2P_REG_8b;
+ --ports regs
+ signal port_indata_reg : T_2P_REG_8b;
+ signal port_outdata_reg : T_2P_REG_8b;
+
+ signal strb_in : T_2P_SL;
+ signal rdy_out : T_2P_SL;
+
+begin
+ port_sel <= PORT_B when sel_b_nA = '1' else
+ PORT_A;
+
+ strb_in(PORT_A) <= astb_n;
+ strb_in(PORT_B) <= bstb_n;
+
+ ardy_n <= rdy_out(PORT_A);
+ brdy_n <= rdy_out(PORT_B);
+
+ port_indata(PORT_A) <= porta_i;
+ port_indata(PORT_B) <= portb_i;
+
+ porta_o <= port_outdata(PORT_A);
+ portb_o <= port_outdata(PORT_B);
+
+ --built enables for control register
+ process(data_i(3 downto 0), wr_dir_reg_q, wr_mask_reg_q) is
+ begin
+ if wr_dir_reg_q then
+ reg_index <= PORTDIR;
+ elsif wr_mask_reg_q then
+ reg_index <= MASK;
+ elsif data_i(0) = '0' then
+ reg_index <= IRQ_VEC;
+ elsif data_i(3 downto 0) = x"F" then
+ reg_index <= MODE;
+ elsif data_i(3 downto 0) = x"7" then
+ reg_index <= IRQ_CTRL;
+ else
+ reg_index <= ERR;
+ end if;
+ end process;
+
+ ctrl_selected <= ce_ni = '0' and IOREQn_i = '0' and sel_c_nD = '1'; --access controlregs
+ data_selected <= ce_ni = '0' and IOREQn_i = '0' and sel_c_nD = '0'; --access ports
+
+ --read/write control register
+ process(clk)
+ begin
+ if falling_edge(clk) then
+ if ctrl_selected then
+ if rd_n = '1' then
+ wr_dir_reg_q <= false;
+ wr_mask_reg_q <= false;
+ --write control reg
+ case reg_index is
+ when IRQ_VEC => irq_vec_reg(port_sel) <= data_i(7 downto 1);
+ when MODE => mode_reg(port_sel) <= data_i(7 downto 6);
+ if data_i(7 downto 6) = "11" then
+ wr_dir_reg_q <= true;
+ end if;
+
+ when PORTDIR => portdir_reg(port_sel) <= data_i(7 downto 0);
+ when IRQ_CTRL => irq_ctrl_reg <= data_i(7 downto 4);
+ if data_i(4) = '1' then
+ wr_mask_reg_q <= true;
+ end if;
+ when MASK => mask_reg(port_sel) <= data_i(7 downto 0);
+ when ERR => err_reg <= data_i(7 downto 0);
+ when others => err_reg <= data_i(7 downto 0);
+ end case;
+ else
+ --read control reg ?How to select control register while reading?
+ case reg_index is
+ when IRQ_VEC => data_oq <= irq_vec_reg(port_sel) & '0';
+ when MODE => data_oq <= mode_reg(port_sel) & "000000";
+ when PORTDIR => data_oq <= portdir_reg(port_sel);
+ when IRQ_CTRL => data_oq <= irq_ctrl_reg & x"0";
+
+ when MASK => data_oq <= mask_reg(port_sel);
+ when ERR => data_oq <= err_reg;
+ when others => data_oq <= x"00";
+ end case;
+ end if;
+ --port_regs <> CPU
+ elsif data_selected then
+ if rd_n = '0' then
+ data_oq <= port_indata_reg(port_sel);
+ else
+ port_outdata_reg(port_sel) <= data_i;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ g_portCPU : for pchan in T_PORT_INDEX generate
+ --real port access
+ process(clk)
+ begin
+ if falling_edge(clk) then
+ if mode_reg(pchan) = "00" then --output mode
+ port_outdata(pchan) <= port_outdata_reg(pchan);
+ elsif mode_reg(pchan) = "01" then --input mode
+ port_indata_reg(pchan) <= port_indata(pchan);
+ elsif mode_reg(pchan) = "10" then --bidir
+ for i in 0 to 7 loop --strb contrl mot implemented yet
+ if portdir_reg(pchan)(i) = '0' then --output
+ port_outdata(pchan)(i) <= port_outdata_reg(pchan)(i);
+ else
+ port_indata_reg(pchan)(i) <= port_indata(pchan)(i);
+ end if;
+ end loop;
+ elsif mode_reg(pchan) = "11" then --bit mode
+ for i in 0 to 7 loop
+ if portdir_reg(pchan)(i) = '0' then --output port
+ port_outdata(pchan)(i) <= port_outdata_reg(pchan)(i);
+ else --input port
+ port_indata_reg(pchan)(i) <= port_indata(pchan)(i);
+ end if;
+ end loop;
+ end if;
+ end if;
+ end process;
+ end generate g_portCPU;
+ data_o <= data_oq;
+ --unused output yet
+
+ IRQEna_o <= '1';
+ INTn_o <= '1';
+
+ rdy_out(PORT_A) <= '0' when mode_reg(PORT_A) = "11" else '1'; --other modes
+ --not implemented
+ rdy_out(PORT_B) <= '0' when mode_reg(PORT_B) = "11" and mode_reg(PORT_A) /= "10" else '1';
+end architecture;
diff --git a/common/Sound/AY8912.sv b/common/Sound/AY8912.sv
new file mode 100644
index 00000000..5d4fe22c
--- /dev/null
+++ b/common/Sound/AY8912.sv
@@ -0,0 +1,278 @@
+
+
+module AY8912
+(
+ input CLK, // Global clock
+ input CE, // PSG Clock enable
+ input RESET, // Chip RESET (set all Registers to '0', active hi)
+ input BDIR, // Bus Direction (0 - read , 1 - write)
+ input BC, // Bus control
+ input [7:0] DI, // Data In
+ output [7:0] DO, // Data Out
+ output [7:0] CHANNEL_A, // PSG Output channel A
+ output [7:0] CHANNEL_B, // PSG Output channel B
+ output [7:0] CHANNEL_C, // PSG Output channel C
+ input SEL,
+ input [7:0] IO_in,
+ output [7:0] IO_out
+);
+
+assign IO_out = ymreg[14];
+
+reg ena_div;
+reg ena_div_noise;
+reg [3:0] addr;
+reg [7:0] ymreg[16];
+reg env_ena;
+reg [4:0] env_vol;
+
+wire [7:0] volTableAy[16] =
+ '{8'h00, 8'h03, 8'h04, 8'h06,
+ 8'h0a, 8'h0f, 8'h15, 8'h22,
+ 8'h28, 8'h41, 8'h5b, 8'h72,
+ 8'h90, 8'hb5, 8'hd7, 8'hff
+ };
+
+
+// Read from AY
+assign DO = dout;
+reg [7:0] dout;
+always_comb begin
+ case(addr)
+ 0: dout = ymreg[0];
+ 1: dout = {4'b0000, ymreg[1][3:0]};
+ 2: dout = ymreg[2];
+ 3: dout = {4'b0000, ymreg[3][3:0]};
+ 4: dout = ymreg[4];
+ 5: dout = {4'b0000, ymreg[5][3:0]};
+ 6: dout = {3'b000, ymreg[6][4:0]};
+ 7: dout = ymreg[7];
+ 8: dout = {3'b000, ymreg[8][4:0]};
+ 9: dout = {3'b000, ymreg[9][4:0]};
+ 10: dout = {3'b000, ymreg[10][4:0]};
+ 11: dout = ymreg[11];
+ 12: dout = ymreg[12];
+ 13: dout = {4'b0000, ymreg[13][3:0]};
+ 14: dout = (ymreg[7][6] ? ymreg[14] : IO_in);
+ 15: dout = (ymreg[7][7] ? ymreg[15] : IO_in);
+ endcase
+end
+
+// p_divider
+always @(posedge CLK) begin
+ reg [3:0] cnt_div;
+ reg noise_div;
+
+ if(CE) begin
+ ena_div <= 0;
+ ena_div_noise <= 0;
+ if(!cnt_div) begin
+ cnt_div <= {SEL, 3'b111};
+ ena_div <= 1;
+
+ noise_div <= (~noise_div);
+ if (noise_div) ena_div_noise <= 1;
+ end else begin
+ cnt_div <= cnt_div - 1'b1;
+ end
+ end
+end
+
+
+reg [16:0] poly17;
+wire [4:0] noise_gen_comp = ymreg[6][4:0] ? ymreg[6][4:0] - 1'd1 : 5'd0;
+
+// p_noise_gen
+always @(posedge CLK) begin
+ reg [4:0] noise_gen_cnt;
+
+ if(CE) begin
+ if (ena_div_noise) begin
+ if (noise_gen_cnt >= noise_gen_comp) begin
+ noise_gen_cnt <= 0;
+ poly17 <= {(poly17[0] ^ poly17[2] ^ !poly17), poly17[16:1]};
+ end else begin
+ noise_gen_cnt <= noise_gen_cnt + 1'd1;
+ end
+ end
+ end
+end
+
+wire [11:0] tone_gen_freq[1:3];
+assign tone_gen_freq[1] = {ymreg[1][3:0], ymreg[0]};
+assign tone_gen_freq[2] = {ymreg[3][3:0], ymreg[2]};
+assign tone_gen_freq[3] = {ymreg[5][3:0], ymreg[4]};
+
+wire [11:0] tone_gen_comp[1:3];
+assign tone_gen_comp[1] = tone_gen_freq[1] ? tone_gen_freq[1] - 1'd1 : 12'd0;
+assign tone_gen_comp[2] = tone_gen_freq[2] ? tone_gen_freq[2] - 1'd1 : 12'd0;
+assign tone_gen_comp[3] = tone_gen_freq[3] ? tone_gen_freq[3] - 1'd1 : 12'd0;
+
+reg [3:1] tone_gen_op;
+
+//p_tone_gens
+always @(posedge CLK) begin
+ integer i;
+ reg [11:0] tone_gen_cnt[1:3];
+
+ if(CE) begin
+ // looks like real chips count up - we need to get the Exact behaviour ..
+
+ for (i = 1; i <= 3; i = i + 1) begin
+ if(ena_div) begin
+ if (tone_gen_cnt[i] >= tone_gen_comp[i]) begin
+ tone_gen_cnt[i] <= 0;
+ tone_gen_op[i] <= (~tone_gen_op[i]);
+ end else begin
+ tone_gen_cnt[i] <= tone_gen_cnt[i] + 1'd1;
+ end
+ end
+ end
+ end
+end
+
+wire [15:0] env_gen_comp = {ymreg[12], ymreg[11]} ? {ymreg[12], ymreg[11]} - 1'd1 : 16'd0;
+
+//p_envelope_freq
+always @(posedge CLK) begin
+ reg [15:0] env_gen_cnt;
+
+ if(CE) begin
+ env_ena <= 0;
+ if(ena_div) begin
+ if (env_gen_cnt >= env_gen_comp) begin
+ env_gen_cnt <= 0;
+ env_ena <= 1;
+ end else begin
+ env_gen_cnt <= (env_gen_cnt + 1'd1);
+ end
+ end
+ end
+end
+
+wire is_bot = (env_vol == 5'b00000);
+wire is_bot_p1 = (env_vol == 5'b00001);
+wire is_top_m1 = (env_vol == 5'b11110);
+wire is_top = (env_vol == 5'b11111);
+
+always @(posedge CLK) begin
+ reg old_BDIR;
+ reg env_reset;
+ reg env_hold;
+ reg env_inc;
+
+ // envelope shapes
+ // C AtAlH
+ // 0 0 x x \___
+ //
+ // 0 1 x x /___
+ //
+ // 1 0 0 0 \\\\
+ //
+ // 1 0 0 1 \___
+ //
+ // 1 0 1 0 \/\/
+ // ___
+ // 1 0 1 1 \
+ //
+ // 1 1 0 0 ////
+ // ___
+ // 1 1 0 1 /
+ //
+ // 1 1 1 0 /\/\
+ //
+ // 1 1 1 1 /___
+
+ if(RESET) begin
+ ymreg[0] <= 0;
+ ymreg[1] <= 0;
+ ymreg[2] <= 0;
+ ymreg[3] <= 0;
+ ymreg[4] <= 0;
+ ymreg[5] <= 0;
+ ymreg[6] <= 0;
+ ymreg[7] <= 255;
+ ymreg[8] <= 0;
+ ymreg[9] <= 0;
+ ymreg[10] <= 0;
+ ymreg[11] <= 0;
+ ymreg[12] <= 0;
+ ymreg[13] <= 0;
+ ymreg[14] <= 0;
+ ymreg[15] <= 0;
+ addr <= 0;
+ env_vol <= 0;
+ end else begin
+ old_BDIR <= BDIR;
+ if(~old_BDIR & BDIR) begin
+ if(BC) addr <= DI[3:0];
+ else begin
+ ymreg[addr] <= DI;
+ env_reset <= (addr == 13);
+ end
+ end
+ end
+
+ if(CE) begin
+ if(env_reset) begin
+ env_reset <= 0;
+ // load initial state
+ if(!ymreg[13][2]) begin // attack
+ env_vol <= 5'b11111;
+ env_inc <= 0; // -1
+ end else begin
+ env_vol <= 5'b00000;
+ env_inc <= 1; // +1
+ end
+ env_hold <= 0;
+ end else begin
+
+ if (env_ena) begin
+ if (!env_hold) begin
+ if (env_inc) env_vol <= (env_vol + 5'b00001);
+ else env_vol <= (env_vol + 5'b11111);
+ end
+
+ // envelope shape control.
+ if(!ymreg[13][3]) begin
+ if(!env_inc) begin // down
+ if(is_bot_p1) env_hold <= 1;
+ end else if (is_top) env_hold <= 1;
+ end else if(ymreg[13][0]) begin // hold = 1
+ if(!env_inc) begin // down
+ if(ymreg[13][1]) begin // alt
+ if(is_bot) env_hold <= 1;
+ end else if(is_bot_p1) env_hold <= 1;
+ end else if(ymreg[13][1]) begin // alt
+ if(is_top) env_hold <= 1;
+ end else if(is_top_m1) env_hold <= 1;
+ end else if(ymreg[13][1]) begin // alternate
+ if(env_inc == 1'b0) begin // down
+ if(is_bot_p1) env_hold <= 1;
+ if(is_bot) begin
+ env_hold <= 0;
+ env_inc <= 1;
+ end
+ end else begin
+ if(is_top_m1) env_hold <= 1;
+ if(is_top) begin
+ env_hold <= 0;
+ env_inc <= 0;
+ end
+ end
+ end
+ end
+ end
+ end
+end
+
+wire [4:0] A = ~((ymreg[7][0] | tone_gen_op[1]) & (ymreg[7][3] | poly17[0])) ? 5'd0 : ymreg[8][4] ? env_vol[4:0] : { ymreg[8][3:0], ymreg[8][3]};
+wire [4:0] B = ~((ymreg[7][1] | tone_gen_op[2]) & (ymreg[7][4] | poly17[0])) ? 5'd0 : ymreg[9][4] ? env_vol[4:0] : { ymreg[9][3:0], ymreg[9][3]};
+wire [4:0] C = ~((ymreg[7][2] | tone_gen_op[3]) & (ymreg[7][5] | poly17[0])) ? 5'd0 : ymreg[10][4] ? env_vol[4:0] : {ymreg[10][3:0], ymreg[10][3]};
+
+assign CHANNEL_A = volTableAy[A[4:1]];
+assign CHANNEL_B = volTableAy[B[4:1]];
+assign CHANNEL_C = volTableAy[C[4:1]];
+
+
+endmodule
diff --git a/common/Sound/Pokey/POKEY.sv b/common/Sound/Pokey/POKEY.sv
new file mode 100644
index 00000000..6cbbac04
--- /dev/null
+++ b/common/Sound/Pokey/POKEY.sv
@@ -0,0 +1,505 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Company: M-x Butterfly
+// Engineer: Peter Pearson
+//
+// Create Date: 10/29/2015 03:59:30 PM
+// Design Name:
+// Module Name: POKEY
+// Project Name:
+// Target Devices:
+// Tool Versions:
+// Description:
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+//
+//////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+module POKEY
+ (
+ input logic [7:0] Din,
+ output logic [7:0] Dout,
+ input logic [3:0] A,
+ input logic [7:0] P,
+ input logic phi2,
+ input logic readHighWriteLow,
+ input logic cs0Bar,
+ output logic aud,
+ output logic [3:0] audio,
+ //This clk is the 100 MHz clock, and is not a pin on the POKEY DIP
+ input logic clk
+ );
+
+
+ logic [7:0] audf1, audf2, audf3, audf4, audc1, audc2, audc3, audc4, audCtl, allPot, skCtl;
+ logic [7:0] dataIn, dataOut;
+ logic clr;
+ logic baseClkWave;
+ logic wave15k, pulse15k, wave64k, pulse64k, wave179m, pulse179m;
+ logic rand4, rand5, rand17, reduce9;
+ logic [7:0] rngRead;
+ logic phi2Rising;
+ logic [3:0] bypassMask1, bypassMask2, bypassMask3, bypassMask4;
+
+ //Outputs of the divide-by-N blocks for each channel
+ logic [3:0] divOut;
+
+ //Base clock fed to each channel
+ logic [3:0] baseClks;
+
+ //High pass filter clocks fed to each channel
+ logic [3:0] hpfClks;
+
+ //Output waveform of each channel
+ logic [3:0] rawWave;
+
+ assign clr = (skCtl[1:0] == 2'b00);
+
+
+// tristateDriver #(8) triDrv(.i(dataOut), .o(D), .en(readHighWriteLow));
+ assign dataIn = Din;
+ assign Dout = dataOut;
+
+
+ wave15kGen w15k(.clk(clk), .clr(clr), .wave(wave15k), .pulse(pulse15k));
+ wave64kGen w64k(.clk(clk), .clr(clr), .wave(wave64k), .pulse(pulse64k));
+ wave179mGen w179m(.clk(clk), .clr(clr), .wave(wave179m), .pulse(pulse179m));
+
+ polyCounter4 pc4(.clk(clk), .pulse179m(pulse179m), .rand4(rand4), .clr(clr));
+ polyCounter5 pc5(.clk(clk), .pulse179m(pulse179m), .rand5(rand5), .clr(clr));
+ polyCounter17 pc17(.clk(clk), .pulse179m(pulse179m), .reduce9(reduce9), .rand17(rand17), .rngVal(rngRead), .clr(clr));
+
+
+ risingDetector risingPhi(.clk(clk), .clr(clr), .signalIn(phi2), .risingEdge(phi2Rising));
+
+
+ audioChannelDigital channel1(.clk(clk), .clr(clr), .baseClkWave(baseClks[0]), .audf(audf1), .audc(audc1), .rand4(rand4), .rand5(rand5), .rand17(rand17), .hpfClk(hpfClks[0]), .bypassMask(bypassMask1), .rawWave(rawWave[0]), .divOut(divOut[0]));
+ audioChannelDigital channel2(.clk(clk), .clr(clr), .baseClkWave(baseClks[1]), .audf(audf2), .audc(audc2), .rand4(rand4), .rand5(rand5), .rand17(rand17), .hpfClk(hpfClks[1]), .bypassMask(bypassMask2), .rawWave(rawWave[1]), .divOut(divOut[1]));
+ audioChannelDigital channel3(.clk(clk), .clr(clr), .baseClkWave(baseClks[2]), .audf(audf3), .audc(audc3), .rand4(rand4), .rand5(rand5), .rand17(rand17), .hpfClk(hpfClks[2]), .bypassMask(bypassMask3), .rawWave(rawWave[2]), .divOut(divOut[2]));
+ audioChannelDigital channel4(.clk(clk), .clr(clr), .baseClkWave(baseClks[3]), .audf(audf4), .audc(audc4), .rand4(rand4), .rand5(rand5), .rand17(rand17), .hpfClk(hpfClks[3]), .bypassMask(bypassMask4), .rawWave(rawWave[3]), .divOut(divOut[3]));
+
+ assign audio = {4{aud}};
+ volumeMixer finalMix(.clk(clk), .clr(clr), .audc1(audc1), .audc2(audc2), .audc3(audc3), .audc4(audc4), .digitalWave(rawWave), .pwmWave(aud));
+
+
+ assign hpfClks = {{divOut[2]},{divOut[3]},{2'b00}};
+
+
+ //AUDCTL and bypass mask logic
+ always_comb
+ begin
+ reduce9 = audCtl[7];
+
+ baseClks[0] = (audCtl[6] ? wave179m : baseClkWave);
+ baseClks[2] = (audCtl[5] ? wave179m : baseClkWave);
+ baseClks[1] = (audCtl[4] ? divOut[0] : baseClkWave);
+ baseClks[3] = (audCtl[3] ? divOut[2] : baseClkWave);
+
+ bypassMask1 = {{audCtl[2]},{3'b000}};
+ bypassMask2 = {{audCtl[1]},{3'b000}};
+ bypassMask3 = 4'h8;
+ bypassMask4 = 4'h8;
+
+ baseClkWave = (audCtl[0] ? wave15k : wave64k);
+ end
+
+
+ always_ff@(posedge clk)
+ begin
+ if(phi2Rising & !cs0Bar)
+ begin
+ if(clr)
+ begin
+ audf1 <= 8'd0;
+ audf2 <= 8'd0;
+ audf3 <= 8'd0;
+ audf4 <= 8'd0;
+ audc1 <= 8'd0;
+ audc2 <= 8'd0;
+ audc3 <= 8'd0;
+ audc4 <= 8'd0;
+ audCtl <= 8'd0;
+ allPot <= 8'd0;
+ dataOut <= 8'd0;
+ if(!readHighWriteLow & (A == 4'hF))
+ begin
+ skCtl <= dataIn;
+ end
+ end
+ else
+ begin
+ if(readHighWriteLow)
+ begin
+ case(A)
+ 4'h8: dataOut <= allPot;
+ 4'hA: dataOut <= rngRead;
+ endcase
+ end
+ else
+ begin
+ case(A)
+ 4'h0: audf1 <= dataIn;
+ 4'h1: audc1 <= dataIn;
+ 4'h2: audf2 <= dataIn;
+ 4'h3: audc2 <= dataIn;
+ 4'h4: audf3 <= dataIn;
+ 4'h5: audc3 <= dataIn;
+ 4'h6: audf4 <= dataIn;
+ 4'h7: audc4 <= dataIn;
+ 4'h8: audCtl <= dataIn;
+ 4'hB: allPot <= P;
+ 4'hF: skCtl <= dataIn;
+ endcase // case (A)
+ end // else: !if(readHighWriteLow)
+ end
+ end
+ end
+
+
+endmodule: POKEY
+
+module tristateDriver
+ #(parameter WIDTH = 8)
+ (
+ input logic [WIDTH-1:0] i,
+ output logic [WIDTH-1:0] o,
+ input logic en
+ );
+
+ assign o = (en) ? i : ({WIDTH{1'bz}});
+
+endmodule: tristateDriver
+
+module volumeMixer
+ (
+ input logic clk, clr,
+ input logic [7:0] audc1, audc2, audc3, audc4,
+ input logic [3:0] digitalWave,
+ output logic pwmWave
+ );
+
+ logic [5:0] volume;
+ logic [5:0] pwmCnt;
+
+ assign volume =
+ ((digitalWave[3] | audc4[4]) ? audc4[3:0] : 0) +
+ ((digitalWave[2] | audc3[4]) ? audc3[3:0] : 0) +
+ ((digitalWave[1] | audc2[4]) ? audc2[3:0] : 0) +
+ ((digitalWave[0] | audc1[4]) ? audc1[3:0] : 0);
+
+ m_counter #(6) pwmClk(.Q(pwmCnt), .D(6'd0), .clk(clk), .clr(clr), .load(1'b0), .en(1'b1), .up(1'b1));
+
+ assign pwmWave = (pwmCnt < volume);
+
+endmodule: volumeMixer
+
+module audioChannelDigital
+ (
+ input logic clk, clr,
+ input logic baseClkWave,
+ input logic [7:0] audf, audc,
+ input logic rand4, rand5, rand17,
+ input logic hpfClk,
+ input logic [3:0] bypassMask,
+ output logic rawWave, divOut, noiseOut, arbDiv2Out
+ );
+
+
+ logic noise;
+
+ logic [3:0] sigIn, sigOut;
+
+ divideByN stage1(.signalIn(sigIn[0]), .clk(clk), .clr(clr), .N(audf), .signalOut(sigOut[0]));
+ noiseGen rng(.rand4(rand4), .rand5(rand5), .rand17(rand17), .noise(noise), .randSel(audc[7:5]));
+ randomMixer randMix(.clk(clk), .clr(clr), .randomIn(noise), .signalIn(sigIn[1]), .signalOut(sigOut[1]));
+ arbDivBy2 adb2(.clk(clk), .clr(clr), .signalIn(sigIn[2]), .signalOut(sigOut[2]));
+ highPassFilter hpf(.hpfClk(hpfClk), .clk(clk), .clr(clr), .inputSignal(sigIn[3]), .outputSignal(sigOut[3]));
+
+
+ assign sigIn[0] = baseClkWave;
+ assign sigIn[1] = bypassMask[0] ? sigIn[0] : sigOut[0];
+ assign sigIn[2] = bypassMask[1] ? sigIn[1] : sigOut[1];
+ assign sigIn[3] = bypassMask[2] ? sigIn[2] : sigOut[2];
+ assign rawWave = bypassMask[3] ? sigIn[3] : sigOut[3];
+ assign divOut = sigOut[0];
+ assign noiseOut = sigOut[1];
+ assign arbDiv2Out = sigOut[2];
+
+endmodule: audioChannelDigital
+
+module highPassFilter
+ (
+ input logic clk, clr,
+ input logic hpfClk,
+ input logic inputSignal,
+ output logic outputSignal
+ );
+
+ logic ffOut;
+
+ m_register #(1) filterReg(.Q(ffOut), .D(inputSignal), .clr(clr), .clk(clk), .en(hpfClk));
+ assign outputSignal = (inputSignal ^ ffOut);
+
+endmodule: highPassFilter
+
+
+module noiseGen
+ (
+ input logic rand4, rand5, rand17,
+ input logic [2:0] randSel,
+ output logic noise
+ );
+
+ always_comb
+ begin
+ casex(randSel)
+ 3'b000:
+ begin
+ noise = rand5 & rand17;
+ end
+ 3'b0?1:
+ begin
+ noise = rand5;
+ end
+ 3'b010:
+ begin
+ noise = rand4 & rand5;
+ end
+ 3'b100:
+ begin
+ noise = rand17;
+ end
+ 3'b1?1:
+ begin
+ noise = 1'b1;
+ end
+ 3'b110:
+ begin
+ noise = rand4;
+ end
+ default:
+ begin
+ noise = 1'b1;
+ end
+ endcase // casex (randSel)
+
+ end
+
+
+endmodule: noiseGen
+
+module edgeDetector
+ (
+ input logic clk, clr,
+ input logic signal,
+ output logic edgeFound
+ );
+
+ logic prevSignal;
+
+ m_register #(1) edgeRegister(.Q(prevSignal), .D(signal), .clk(clk), .clr(clr), .en(1'b1));
+
+ assign edgeFound = signal ^ prevSignal;
+
+endmodule: edgeDetector
+
+
+module divideByN
+ (
+ input logic signalIn, clk, clr,
+ input logic [7:0] N,
+ output logic signalOut
+ );
+
+ logic [7:0] countOut;
+ logic rollover, edgeFound;
+
+ edgeDetector edgeChecker(.clk(clk), .clr(clr), .signal(signalIn), .edgeFound(edgeFound));
+ m_counter #(8) divCounter(.D(8'd0), .Q(countOut), .clk(clk), .en(edgeFound), .up(1'b1), .clr(clr), .load(rollover));
+ m_register #(1) waveTracker(.Q(signalOut), .D(!signalOut), .clk(clk), .en(rollover), .clr(clr));
+
+ assign rollover = (countOut >= N) & edgeFound;
+
+endmodule: divideByN
+
+
+module wave15kGen
+ (
+ input logic clk, clr,
+ output logic wave, pulse
+ );
+
+ logic [11:0] parallel15k;
+
+ m_counter #(12) counter15k(.D(12'd0), .Q(parallel15k), .clk(clk), .en(1'b1), .up(1'b1), .clr(clr), .load(pulse));
+ m_register #(1) waveTracker(.D(!wave), .Q(wave), .clk(clk), .en(pulse), .clr(clr));
+
+ assign pulse = (parallel15k == 12'd3333);
+
+endmodule: wave15kGen
+
+module wave64kGen
+ (
+ input logic clk, clr,
+ output logic wave, pulse
+ );
+
+ logic [9:0] parallel64k;
+
+ m_counter #(10) counter64k(.D(10'd0), .Q(parallel64k), .clk(clk), .en(1'b1), .up(1'b1), .clr(clr), .load(pulse));
+ m_register #(1) waveTracker(.D(!wave), .Q(wave), .clk(clk), .en(pulse), .clr(clr));
+
+ assign pulse = (parallel64k == 10'd781);
+
+endmodule: wave64kGen
+
+module wave179mGen
+ (
+ input logic clk, clr,
+ output logic wave, pulse
+ );
+
+ logic [4:0] parallel179m;
+
+ m_counter #(5) counter64k(.D(5'd0), .Q(parallel179m), .clk(clk), .en(1'b1), .up(1'b1), .clr(clr), .load(pulse));
+ m_register #(1) waveTracker(.D(!wave), .Q(wave), .clk(clk), .en(pulse), .clr(clr));
+
+ assign pulse = (parallel179m == 5'd28);
+
+endmodule: wave179mGen
+
+
+module polyCounter4
+ (
+ input logic clk, pulse179m, clr,
+ output logic rand4
+ );
+
+ logic [3:0] regValue;
+ logic feedbackVal;
+
+ m_shift_register #(4) polyShifter(.Q(regValue), .clk(clk), .en(pulse179m), .left(1'b0), .s_in(feedbackVal), .clr(clr));
+
+ assign feedbackVal = !(regValue[3] ^ regValue[2]);
+ assign rand4 = regValue[3];
+
+endmodule: polyCounter4
+
+
+module polyCounter5
+ (
+ input logic clk, pulse179m, clr,
+ output logic rand5
+ );
+
+ logic [4:0] regValue;
+ logic feedbackVal;
+
+ m_shift_register #(5) polyShifter(.Q(regValue), .clk(clk), .en(pulse179m), .left(1'b1), .s_in(feedbackVal), .clr(clr));
+
+ assign feedbackVal = !(regValue[4] ^ regValue[2]);
+ assign rand5 = regValue[4];
+
+endmodule: polyCounter5
+
+
+module polyCounter17
+ (
+ input logic clk, pulse179m, clr,
+ input logic reduce9,
+ output logic rand17,
+ output logic [7:0] rngVal
+ );
+
+ logic [16:0] regValue;
+ logic feedbackVal;
+
+ m_shift_register #(9) polyShifterUpper(.Q(regValue[16:8]), .clk(clk), .en(pulse179m), .left(1'b1), .s_in(reduce9 ? feedbackVal : regValue[7]), .clr(clr));
+ m_shift_register #(8) polyShifterLower(.Q(regValue[7:0]), .clk(clk), .en(pulse179m), .left(1'b1), .s_in(feedbackVal), .clr(clr));
+
+ assign feedbackVal = !(regValue[16] ^ regValue[11]);
+ assign rand17 = regValue[16];
+ assign rngVal = regValue[16:9];
+
+endmodule: polyCounter17
+
+module volumeControl
+ (
+ input logic clk, clr,
+ input logic signalIn,
+ input logic [3:0] volume,
+ input logic dcVolume,
+ output logic signalOut
+ );
+
+ logic [3:0] pwmCount;
+ logic pwmOn;
+
+ m_counter #(4) pwmTimer(.Q(pwmCount), .D(4'h0), .clk(clk), .clr(clr), .load(1'b0), .en(1'b1), .up(1'b1));
+
+ assign pwmOn = (pwmCount <= volume);
+
+ assign signalOut = dcVolume ? pwmOn : (pwmOn & signalIn);
+
+
+endmodule: volumeControl
+
+module risingDetector
+ (
+ input logic clk, clr,
+ input logic signalIn,
+ output logic risingEdge
+ );
+
+ logic prevSignal;
+
+ m_register #(1) risingRegister(.Q(prevSignal), .D(signalIn), .en(1'b1), .clk(clk), .clr(clr));
+ assign risingEdge = signalIn & ~prevSignal;
+
+endmodule: risingDetector
+
+module randomMixer
+ (
+ input logic clk, clr,
+ input logic signalIn,
+ input logic randomIn,
+ output logic signalOut
+ );
+
+ logic risingEdge;
+
+ logic waveWideRandom;
+
+ //This instance name made sense at 4AM when I typed it
+ risingDetector rayfall(.clk(clk), .clr(clr), .signalIn(signalIn), .risingEdge(risingEdge));
+
+ m_register #(1) randomCapture(.Q(waveWideRandom), .D(randomIn), .en(risingEdge), .clk(clk), .clr(clr));
+
+ assign signalOut = signalIn & waveWideRandom;
+
+endmodule: randomMixer
+
+module arbDivBy2
+ (
+ input logic clk, clr,
+ input logic signalIn,
+ output logic signalOut
+ );
+
+ logic risingEdge;
+
+ risingDetector risingCheck(.clk(clk), .clr(clr), .signalIn(signalIn), .risingEdge(risingEdge));
+
+ m_register #(1) waveTracker(.Q(signalOut), .D(~signalOut), .en(risingEdge), .clk(clk), .clr(clr));
+
+endmodule: arbDivBy2
+
+
+
diff --git a/common/Sound/Pokey/matoro.sv b/common/Sound/Pokey/matoro.sv
new file mode 100644
index 00000000..c647dc1f
--- /dev/null
+++ b/common/Sound/Pokey/matoro.sv
@@ -0,0 +1,129 @@
+`timescale 1ns / 1ps
+module m_range_check
+ #(parameter WIDTH = 6)
+ (input logic [WIDTH-1:0] val, low, high,
+ output logic is_between);
+
+ logic smallEnough, largeEnough;
+
+ m_comparator #(WIDTH) lc(,,largeEnough, low, val);
+ m_comparator #(WIDTH) hc(,,smallEnough, val, high);
+
+ assign is_between = ~smallEnough & ~largeEnough;
+
+endmodule: m_range_check
+
+module m_offset_check
+ #(parameter WIDTH = 6)
+ (input logic [WIDTH-1:0] val, low, delta,
+ output logic is_between);
+
+ logic [WIDTH-1:0] high;
+
+ m_adder #(WIDTH) add(high,, low, delta, 1'b0);
+ m_range_check #(WIDTH) rc(.*);
+
+endmodule: m_offset_check
+
+module m_comparator
+ #(parameter WIDTH = 6)
+ (output logic AltB, AeqB, AgtB,
+ input logic [WIDTH-1:0] A, B);
+
+ assign AltB = (A < B);
+ assign AeqB = (A == B);
+ assign AgtB = (A > B);
+
+endmodule: m_comparator
+
+module m_adder
+ #(parameter WIDTH = 6)
+ (output logic [WIDTH-1:0] Sum,
+ output logic Cout,
+ input logic [WIDTH-1:0] A, B,
+ input logic Cin);
+
+ assign {Cout, Sum} = A + B + Cin;
+
+endmodule: m_adder
+
+module m_mux
+ #(parameter WIDTH = 6)
+ (output logic Y,
+ input logic [WIDTH-1:0] I,
+ input logic [$clog2(WIDTH)-1:0] Sel);
+
+ assign Y = I[Sel];
+
+endmodule: m_mux
+
+module m_mux2to1
+ #(parameter WIDTH = 6)
+ (output logic [WIDTH-1:0] Y,
+ input logic [WIDTH-1:0] I0, I1,
+ input logic Sel);
+
+ assign Y = (Sel ? I1 : I0);
+
+endmodule: m_mux2to1
+
+module m_decoder
+ #(parameter WIDTH = 6)
+ (output logic [(1 << WIDTH)-1:0] D,
+ input logic [WIDTH-1:0] I,
+ input logic en);
+
+ assign D = en << I;
+
+endmodule: m_decoder
+
+module m_register
+ #(parameter WIDTH = 6)
+ (output logic [WIDTH-1:0] Q,
+ input logic [WIDTH-1:0] D,
+ input logic clr, en, clk);
+
+ always_ff @(posedge clk)
+ if(clr)
+ Q <= 0;
+ else if(en)
+ Q <= D;
+
+endmodule: m_register
+
+module m_counter
+ #(parameter WIDTH = 6)
+ (output logic [WIDTH-1:0] Q,
+ input logic [WIDTH-1:0] D,
+ input logic clk, clr, load, en, up);
+
+ always_ff @(posedge clk) begin
+ if(clr)
+ Q <= 0;
+ else if(load)
+ Q <= D;
+ else if(en)
+ Q <= (up ? Q + 1 : Q - 1);
+ end
+endmodule: m_counter
+
+module m_shift_register
+ #(parameter WIDTH = 6)
+ (output logic [WIDTH-1:0] Q,
+ input logic clk, en, left, s_in, clr);
+
+ always_ff @(posedge clk)
+ if (clr) begin
+ Q <= 'd0;
+ end
+ else if(en) begin
+ if(left) begin
+ Q <= (Q << 1);
+ Q[0] <= s_in;
+ end
+ else begin
+ Q <= (Q >> 1);
+ Q[WIDTH-1] <= s_in;
+ end
+ end
+endmodule: m_shift_register
diff --git a/common/Sound/Speech256-master.zip b/common/Sound/Speech256-master.zip
new file mode 100644
index 00000000..7a8b2696
Binary files /dev/null and b/common/Sound/Speech256-master.zip differ
diff --git a/common/Sound/YM2149.sv b/common/Sound/YM2149.sv
new file mode 100644
index 00000000..e4cf9525
--- /dev/null
+++ b/common/Sound/YM2149.sv
@@ -0,0 +1,326 @@
+//
+// Copyright (c) MikeJ - Jan 2005
+// Copyright (c) 2016-2018 Sorgelig
+//
+// All rights reserved
+//
+// Redistribution and use in source and synthezised forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// Redistributions in synthesized form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// Neither the name of the author nor the names of other contributors may
+// be used to endorse or promote products derived from this software without
+// specific prior written permission.
+//
+// THIS CODE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+
+
+// BDIR BC MODE
+// 0 0 inactive
+// 0 1 read value
+// 1 0 write value
+// 1 1 set address
+//
+
+module YM2149
+(
+ input CLK, // Global clock
+ input CE, // PSG Clock enable
+ input RESET, // Chip RESET (set all Registers to '0', active hi)
+ input BDIR, // Bus Direction (0 - read , 1 - write)
+ input BC, // Bus control
+ input [7:0] DI, // Data In
+ output [7:0] DO, // Data Out
+ output [7:0] CHANNEL_A, // PSG Output channel A
+ output [7:0] CHANNEL_B, // PSG Output channel B
+ output [7:0] CHANNEL_C, // PSG Output channel C
+
+ input SEL,
+ input MODE,
+
+ output [5:0] ACTIVE,
+
+ input [7:0] IOA_in,
+ output [7:0] IOA_out,
+
+ input [7:0] IOB_in,
+ output [7:0] IOB_out
+);
+
+assign ACTIVE = ~ymreg[7][5:0];
+assign IOA_out = ymreg[7][6] ? ymreg[14] : 8'hff;
+assign IOB_out = ymreg[7][7] ? ymreg[15] : 8'hff;
+
+reg [7:0] addr;
+reg [7:0] ymreg[16];
+
+// Write to PSG
+reg env_reset;
+always @(posedge CLK) begin
+ if(RESET) begin
+ ymreg <= '{default:0};
+ ymreg[7] <= '1;
+ addr <= '0;
+ env_reset <= 0;
+ end else begin
+ env_reset <= 0;
+ if(BDIR) begin
+ if(BC) addr <= DI;
+ else if(!addr[7:4]) begin
+ ymreg[addr[3:0]] <= DI;
+ env_reset <= (addr == 13);
+ end
+ end
+ end
+end
+
+// Read from PSG
+assign DO = dout;
+reg [7:0] dout;
+always_comb begin
+ dout = 8'hFF;
+ if(~BDIR & BC & !addr[7:4]) begin
+ case(addr[3:0])
+ 0: dout = ymreg[0];
+ 1: dout = ymreg[1][3:0];
+ 2: dout = ymreg[2];
+ 3: dout = ymreg[3][3:0];
+ 4: dout = ymreg[4];
+ 5: dout = ymreg[5][3:0];
+ 6: dout = ymreg[6][4:0];
+ 7: dout = ymreg[7];
+ 8: dout = ymreg[8][4:0];
+ 9: dout = ymreg[9][4:0];
+ 10: dout = ymreg[10][4:0];
+ 11: dout = ymreg[11];
+ 12: dout = ymreg[12];
+ 13: dout = ymreg[13][3:0];
+ 14: dout = ymreg[7][6] ? ymreg[14] : IOA_in;
+ 15: dout = ymreg[7][7] ? ymreg[15] : IOB_in;
+ endcase
+ end
+end
+
+reg ena_div;
+reg ena_div_noise;
+
+// p_divider
+always @(posedge CLK) begin
+ reg [3:0] cnt_div;
+ reg noise_div;
+
+ if(CE) begin
+ ena_div <= 0;
+ ena_div_noise <= 0;
+ if(!cnt_div) begin
+ cnt_div <= {SEL, 3'b111};
+ ena_div <= 1;
+
+ noise_div <= (~noise_div);
+ if (noise_div) ena_div_noise <= 1;
+ end else begin
+ cnt_div <= cnt_div - 1'b1;
+ end
+ end
+end
+
+
+reg [2:0] noise_gen_op;
+
+// p_noise_gen
+always @(posedge CLK) begin
+ reg [16:0] poly17;
+ reg [4:0] noise_gen_cnt;
+
+ if(CE) begin
+ if (ena_div_noise) begin
+ if (!ymreg[6][4:0] || noise_gen_cnt >= ymreg[6][4:0] - 1'd1) begin
+ noise_gen_cnt <= 0;
+ poly17 <= {(poly17[0] ^ poly17[2] ^ !poly17), poly17[16:1]};
+ end else begin
+ noise_gen_cnt <= noise_gen_cnt + 1'd1;
+ end
+ noise_gen_op <= {3{poly17[0]}};
+ end
+ end
+end
+
+wire [11:0] tone_gen_freq[1:3];
+assign tone_gen_freq[1] = {ymreg[1][3:0], ymreg[0]};
+assign tone_gen_freq[2] = {ymreg[3][3:0], ymreg[2]};
+assign tone_gen_freq[3] = {ymreg[5][3:0], ymreg[4]};
+
+reg [3:1] tone_gen_op;
+
+//p_tone_gens
+always @(posedge CLK) begin
+ integer i;
+ reg [11:0] tone_gen_cnt[1:3];
+
+ if(CE) begin
+ // looks like real chips count up - we need to get the Exact behaviour ..
+
+ for (i = 1; i <= 3; i = i + 1) begin
+ if(ena_div) begin
+ if (tone_gen_freq[i]) begin
+ if (tone_gen_cnt[i] >= (tone_gen_freq[i] - 1'd1)) begin
+ tone_gen_cnt[i] <= 0;
+ tone_gen_op[i] <= ~tone_gen_op[i];
+ end else begin
+ tone_gen_cnt[i] <= tone_gen_cnt[i] + 1'd1;
+ end
+ end else begin
+ tone_gen_op[i] <= ymreg[7][i];
+ tone_gen_cnt[i] <= 0;
+ end
+ end
+ end
+ end
+end
+
+reg env_ena;
+wire [15:0] env_gen_comp = {ymreg[12], ymreg[11]} ? {ymreg[12], ymreg[11]} - 1'd1 : 16'd0;
+
+//p_envelope_freq
+always @(posedge CLK) begin
+ reg [15:0] env_gen_cnt;
+
+ if(CE) begin
+ env_ena <= 0;
+ if(ena_div) begin
+ if (env_gen_cnt >= env_gen_comp) begin
+ env_gen_cnt <= 0;
+ env_ena <= 1;
+ end else begin
+ env_gen_cnt <= (env_gen_cnt + 1'd1);
+ end
+ end
+ end
+end
+
+reg [4:0] env_vol;
+
+wire is_bot = (env_vol == 5'b00000);
+wire is_bot_p1 = (env_vol == 5'b00001);
+wire is_top_m1 = (env_vol == 5'b11110);
+wire is_top = (env_vol == 5'b11111);
+
+always @(posedge CLK) begin
+ reg env_hold;
+ reg env_inc;
+
+ // envelope shapes
+ // C AtAlH
+ // 0 0 x x \___
+ //
+ // 0 1 x x /___
+ //
+ // 1 0 0 0 \\\\
+ //
+ // 1 0 0 1 \___
+ //
+ // 1 0 1 0 \/\/
+ // ___
+ // 1 0 1 1 \
+ //
+ // 1 1 0 0 ////
+ // ___
+ // 1 1 0 1 /
+ //
+ // 1 1 1 0 /\/\
+ //
+ // 1 1 1 1 /___
+
+ if(env_reset | RESET) begin
+ // load initial state
+ if(!ymreg[13][2]) begin // attack
+ env_vol <= 5'b11111;
+ env_inc <= 0; // -1
+ end else begin
+ env_vol <= 5'b00000;
+ env_inc <= 1; // +1
+ end
+ env_hold <= 0;
+ end
+ else if(CE) begin
+ if (env_ena) begin
+ if (!env_hold) begin
+ if (env_inc) env_vol <= (env_vol + 5'b00001);
+ else env_vol <= (env_vol + 5'b11111);
+ end
+
+ // envelope shape control.
+ if(!ymreg[13][3]) begin
+ if(!env_inc) begin // down
+ if(is_bot_p1) env_hold <= 1;
+ end else if (is_top) env_hold <= 1;
+ end else if(ymreg[13][0]) begin // hold = 1
+ if(!env_inc) begin // down
+ if(ymreg[13][1]) begin // alt
+ if(is_bot) env_hold <= 1;
+ end else if(is_bot_p1) env_hold <= 1;
+ end else if(ymreg[13][1]) begin // alt
+ if(is_top) env_hold <= 1;
+ end else if(is_top_m1) env_hold <= 1;
+ end else if(ymreg[13][1]) begin // alternate
+ if(env_inc == 1'b0) begin // down
+ if(is_bot_p1) env_hold <= 1;
+ if(is_bot) begin
+ env_hold <= 0;
+ env_inc <= 1;
+ end
+ end else begin
+ if(is_top_m1) env_hold <= 1;
+ if(is_top) begin
+ env_hold <= 0;
+ env_inc <= 0;
+ end
+ end
+ end
+ end
+ end
+end
+
+reg [5:0] A,B,C;
+always @(posedge CLK) begin
+ A <= {MODE, ~((ymreg[7][0] | tone_gen_op[1]) & (ymreg[7][3] | noise_gen_op[0])) ? 5'd0 : ymreg[8][4] ? env_vol[4:0] : { ymreg[8][3:0], ymreg[8][3]}};
+ B <= {MODE, ~((ymreg[7][1] | tone_gen_op[2]) & (ymreg[7][4] | noise_gen_op[1])) ? 5'd0 : ymreg[9][4] ? env_vol[4:0] : { ymreg[9][3:0], ymreg[9][3]}};
+ C <= {MODE, ~((ymreg[7][2] | tone_gen_op[3]) & (ymreg[7][5] | noise_gen_op[2])) ? 5'd0 : ymreg[10][4] ? env_vol[4:0] : {ymreg[10][3:0], ymreg[10][3]}};
+end
+
+wire [7:0] volTable[64] = '{
+ //YM2149
+ 8'h00, 8'h01, 8'h01, 8'h02, 8'h02, 8'h03, 8'h03, 8'h04,
+ 8'h06, 8'h07, 8'h09, 8'h0a, 8'h0c, 8'h0e, 8'h11, 8'h13,
+ 8'h17, 8'h1b, 8'h20, 8'h25, 8'h2c, 8'h35, 8'h3e, 8'h47,
+ 8'h54, 8'h66, 8'h77, 8'h88, 8'ha1, 8'hc0, 8'he0, 8'hff,
+
+ //AY8910
+ 8'h00, 8'h00, 8'h03, 8'h03, 8'h04, 8'h04, 8'h06, 8'h06,
+ 8'h0a, 8'h0a, 8'h0f, 8'h0f, 8'h15, 8'h15, 8'h22, 8'h22,
+ 8'h28, 8'h28, 8'h41, 8'h41, 8'h5b, 8'h5b, 8'h72, 8'h72,
+ 8'h90, 8'h90, 8'hb5, 8'hb5, 8'hd7, 8'hd7, 8'hff, 8'hff
+};
+
+assign CHANNEL_A = volTable[A];
+assign CHANNEL_B = volTable[B];
+assign CHANNEL_C = volTable[C];
+
+endmodule
diff --git a/common/Sound/YM2149_linmix_sep.vhd b/common/Sound/YM2149_linmix_sep.vhd
new file mode 100644
index 00000000..27f26749
--- /dev/null
+++ b/common/Sound/YM2149_linmix_sep.vhd
@@ -0,0 +1,553 @@
+-- changes for seperate audio outputs and enable now enables cpu access as well
+--
+-- A simulation model of YM2149 (AY-3-8910 with bells on)
+
+-- Copyright (c) MikeJ - Jan 2005
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS CODE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- You are responsible for any legal issues arising from your use of this code.
+--
+-- The latest version of this file can be found at: www.fpgaarcade.com
+--
+-- Email support@fpgaarcade.com
+--
+-- Revision list
+--
+-- version 001 initial release
+--
+-- Clues from MAME sound driver and Kazuhiro TSUJIKAWA
+--
+-- These are the measured outputs from a real chip for a single Isolated channel into a 1K load (V)
+-- vol 15 .. 0
+-- 3.27 2.995 2.741 2.588 2.452 2.372 2.301 2.258 2.220 2.198 2.178 2.166 2.155 2.148 2.141 2.132
+-- As the envelope volume is 5 bit, I have fitted a curve to the not quite log shape in order
+-- to produced all the required values.
+-- (The first part of the curve is a bit steeper and the last bit is more linear than expected)
+--
+-- NOTE, this component uses LINEAR mixing of the three analogue channels, and is only
+-- accurate for designs where the outputs are buffered and not simply wired together.
+-- The ouput level is more complex in that case and requires a larger table.
+
+library ieee;
+ use ieee.std_logic_1164.all;
+ use ieee.std_logic_arith.all;
+ use ieee.std_logic_unsigned.all;
+
+entity YM2149 is
+ port (
+ -- data bus
+ I_DA : in std_logic_vector(7 downto 0);
+ O_DA : out std_logic_vector(7 downto 0);
+ O_DA_OE_L : out std_logic;
+ -- control
+ I_A9_L : in std_logic;
+ I_A8 : in std_logic;
+ I_BDIR : in std_logic;
+ I_BC2 : in std_logic;
+ I_BC1 : in std_logic;
+ I_SEL_L : in std_logic;
+
+ O_AUDIO : out std_logic_vector(7 downto 0);
+ O_CHAN : out std_logic_vector(1 downto 0);
+ -- port a
+ I_IOA : in std_logic_vector(7 downto 0);
+ O_IOA : out std_logic_vector(7 downto 0);
+ O_IOA_OE_L : out std_logic;
+ -- port b
+ I_IOB : in std_logic_vector(7 downto 0);
+ O_IOB : out std_logic_vector(7 downto 0);
+ O_IOB_OE_L : out std_logic;
+
+ ENA : in std_logic; -- clock enable for higher speed operation
+ RESET_L : in std_logic;
+ CLK : in std_logic -- note 6 Mhz
+ );
+end;
+
+architecture RTL of YM2149 is
+ type array_16x8 is array (0 to 15) of std_logic_vector( 7 downto 0);
+ type array_3x12 is array (1 to 3) of std_logic_vector(11 downto 0);
+
+ signal cnt_div : std_logic_vector(3 downto 0) := (others => '0');
+ signal cnt_div_t1 : std_logic_vector(3 downto 0);
+ signal noise_div : std_logic := '0';
+ signal ena_div : std_logic;
+ signal ena_div_noise : std_logic;
+ signal poly17 : std_logic_vector(16 downto 0) := (others => '0');
+
+ -- registers
+ signal addr : std_logic_vector(7 downto 0);
+ signal busctrl_addr : std_logic;
+ signal busctrl_we : std_logic;
+ signal busctrl_re : std_logic;
+
+ signal reg : array_16x8;
+ signal env_reset : std_logic;
+ signal ioa_inreg : std_logic_vector(7 downto 0);
+ signal iob_inreg : std_logic_vector(7 downto 0);
+
+ signal noise_gen_cnt : std_logic_vector(4 downto 0);
+ signal noise_gen_op : std_logic;
+ signal tone_gen_cnt : array_3x12 := (others => (others => '0'));
+ signal tone_gen_op : std_logic_vector(3 downto 1) := "000";
+
+ signal env_gen_cnt : std_logic_vector(15 downto 0);
+ signal env_ena : std_logic;
+ signal env_hold : std_logic;
+ signal env_inc : std_logic;
+ signal env_vol : std_logic_vector(4 downto 0);
+
+ signal tone_ena_l : std_logic;
+ signal tone_src : std_logic;
+ signal noise_ena_l : std_logic;
+ signal chan_vol : std_logic_vector(4 downto 0);
+
+ signal dac_amp : std_logic_vector(7 downto 0);
+begin
+ -- cpu i/f
+ p_busdecode : process(I_BDIR, I_BC2, I_BC1, addr, I_A9_L, I_A8)
+ variable cs : std_logic;
+ variable sel : std_logic_vector(2 downto 0);
+ begin
+ -- BDIR BC2 BC1 MODE
+ -- 0 0 0 inactive
+ -- 0 0 1 address
+ -- 0 1 0 inactive
+ -- 0 1 1 read
+ -- 1 0 0 address
+ -- 1 0 1 inactive
+ -- 1 1 0 write
+ -- 1 1 1 read
+ busctrl_addr <= '0';
+ busctrl_we <= '0';
+ busctrl_re <= '0';
+
+ cs := '0';
+ if (I_A9_L = '0') and (I_A8 = '1') and (addr(7 downto 4) = "0000") then
+ cs := '1';
+ end if;
+
+ sel := (I_BDIR & I_BC2 & I_BC1);
+ case sel is
+ when "000" => null;
+ when "001" => busctrl_addr <= '1';
+ when "010" => null;
+ when "011" => busctrl_re <= cs;
+ when "100" => busctrl_addr <= '1';
+ when "101" => null;
+ when "110" => busctrl_we <= cs;
+ when "111" => busctrl_addr <= '1';
+ when others => null;
+ end case;
+ end process;
+
+ p_oe : process(busctrl_re)
+ begin
+ -- if we are emulating a real chip, maybe clock this to fake up the tristate typ delay of 100ns
+ O_DA_OE_L <= not (busctrl_re);
+ end process;
+
+ --
+ -- CLOCKED
+ --
+ p_waddr : process(RESET_L, CLK)
+ begin
+ -- looks like registers are latches in real chip, but the address is caught at the end of the address state.
+ if (RESET_L = '0') then
+ addr <= (others => '0');
+ elsif rising_edge(CLK) then
+ if (ENA = '1') then
+ if (busctrl_addr = '1') then
+ addr <= I_DA;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ p_wdata : process(RESET_L, CLK)
+ begin
+ if (RESET_L = '0') then
+ reg <= (others => (others => '0'));
+ env_reset <= '1';
+ elsif rising_edge(CLK) then
+ if (ENA = '1') then
+ env_reset <= '0';
+ if (busctrl_we = '1') then
+ case addr(3 downto 0) is
+ when x"0" => reg(0) <= I_DA;
+ when x"1" => reg(1) <= I_DA;
+ when x"2" => reg(2) <= I_DA;
+ when x"3" => reg(3) <= I_DA;
+ when x"4" => reg(4) <= I_DA;
+ when x"5" => reg(5) <= I_DA;
+ when x"6" => reg(6) <= I_DA;
+ when x"7" => reg(7) <= I_DA;
+ when x"8" => reg(8) <= I_DA;
+ when x"9" => reg(9) <= I_DA;
+ when x"A" => reg(10) <= I_DA;
+ when x"B" => reg(11) <= I_DA;
+ when x"C" => reg(12) <= I_DA;
+ when x"D" => reg(13) <= I_DA; env_reset <= '1';
+ when x"E" => reg(14) <= I_DA;
+ when x"F" => reg(15) <= I_DA;
+ when others => null;
+ end case;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ p_rdata : process(busctrl_re, addr, reg, ioa_inreg, iob_inreg)
+ begin
+ O_DA <= (others => '0'); -- 'X'
+ if (busctrl_re = '1') then -- not necessary, but useful for putting 'X's in the simulator
+ case addr(3 downto 0) is
+ when x"0" => O_DA <= reg(0) ;
+ when x"1" => O_DA <= "0000" & reg(1)(3 downto 0) ;
+ when x"2" => O_DA <= reg(2) ;
+ when x"3" => O_DA <= "0000" & reg(3)(3 downto 0) ;
+ when x"4" => O_DA <= reg(4) ;
+ when x"5" => O_DA <= "0000" & reg(5)(3 downto 0) ;
+ when x"6" => O_DA <= "000" & reg(6)(4 downto 0) ;
+ when x"7" => O_DA <= reg(7) ;
+ when x"8" => O_DA <= "000" & reg(8)(4 downto 0) ;
+ when x"9" => O_DA <= "000" & reg(9)(4 downto 0) ;
+ when x"A" => O_DA <= "000" & reg(10)(4 downto 0) ;
+ when x"B" => O_DA <= reg(11);
+ when x"C" => O_DA <= reg(12);
+ when x"D" => O_DA <= "0000" & reg(13)(3 downto 0);
+ when x"E" => if (reg(7)(6) = '0') then -- input
+ O_DA <= ioa_inreg;
+ else
+ O_DA <= reg(14); -- read output reg
+ end if;
+ when x"F" => if (Reg(7)(7) = '0') then
+ O_DA <= iob_inreg;
+ else
+ O_DA <= reg(15);
+ end if;
+ when others => null;
+ end case;
+ end if;
+ end process;
+ --
+ p_divider : process
+ begin
+ wait until rising_edge(CLK);
+ -- / 8 when SEL is high and /16 when SEL is low
+ if (ENA = '1') then
+ ena_div <= '0';
+ ena_div_noise <= '0';
+ if (cnt_div = "0000") then
+ cnt_div <= (not I_SEL_L) & "111";
+ ena_div <= '1';
+
+ noise_div <= not noise_div;
+ if (noise_div = '1') then
+ ena_div_noise <= '1';
+ end if;
+ else
+ cnt_div <= cnt_div - "1";
+ end if;
+ end if;
+ end process;
+
+ p_noise_gen : process
+ variable noise_gen_comp : std_logic_vector(4 downto 0);
+ variable poly17_zero : std_logic;
+ begin
+ wait until rising_edge(CLK);
+ if (reg(6)(4 downto 0) = "00000") then
+ noise_gen_comp := "00000";
+ else
+ noise_gen_comp := (reg(6)(4 downto 0) - "1");
+ end if;
+
+ poly17_zero := '0';
+ if (poly17 = "00000000000000000") then poly17_zero := '1'; end if;
+
+ if (ENA = '1') then
+ if (ena_div_noise = '1') then -- divider ena
+
+ if (noise_gen_cnt >= noise_gen_comp) then
+ noise_gen_cnt <= "00000";
+ poly17 <= (poly17(0) xor poly17(2) xor poly17_zero) & poly17(16 downto 1);
+ else
+ noise_gen_cnt <= (noise_gen_cnt + "1");
+ end if;
+ end if;
+ end if;
+ end process;
+ noise_gen_op <= poly17(0);
+
+ p_tone_gens : process
+ variable tone_gen_freq : array_3x12;
+ variable tone_gen_comp : array_3x12;
+ begin
+ wait until rising_edge(CLK);
+ -- looks like real chips count up - we need to get the Exact behaviour ..
+ tone_gen_freq(1) := reg(1)(3 downto 0) & reg(0);
+ tone_gen_freq(2) := reg(3)(3 downto 0) & reg(2);
+ tone_gen_freq(3) := reg(5)(3 downto 0) & reg(4);
+ -- period 0 = period 1
+ for i in 1 to 3 loop
+ if (tone_gen_freq(i) = x"000") then
+ tone_gen_comp(i) := x"000";
+ else
+ tone_gen_comp(i) := (tone_gen_freq(i) - "1");
+ end if;
+ end loop;
+
+ if (ENA = '1') then
+ for i in 1 to 3 loop
+ if (ena_div = '1') then -- divider ena
+
+ if (tone_gen_cnt(i) >= tone_gen_comp(i)) then
+ tone_gen_cnt(i) <= x"000";
+ tone_gen_op(i) <= not tone_gen_op(i);
+ else
+ tone_gen_cnt(i) <= (tone_gen_cnt(i) + "1");
+ end if;
+ end if;
+ end loop;
+ end if;
+ end process;
+
+ p_envelope_freq : process
+ variable env_gen_freq : std_logic_vector(15 downto 0);
+ variable env_gen_comp : std_logic_vector(15 downto 0);
+ begin
+ wait until rising_edge(CLK);
+ env_gen_freq := reg(12) & reg(11);
+ -- envelope freqs 1 and 0 are the same.
+ if (env_gen_freq = x"0000") then
+ env_gen_comp := x"0000";
+ else
+ env_gen_comp := (env_gen_freq - "1");
+ end if;
+
+ if (ENA = '1') then
+ env_ena <= '0';
+ if (ena_div = '1') then -- divider ena
+ if (env_gen_cnt >= env_gen_comp) then
+ env_gen_cnt <= x"0000";
+ env_ena <= '1';
+ else
+ env_gen_cnt <= (env_gen_cnt + "1");
+ end if;
+ end if;
+ end if;
+ end process;
+
+ p_envelope_shape : process(env_reset, reg, CLK)
+ variable is_bot : boolean;
+ variable is_bot_p1 : boolean;
+ variable is_top_m1 : boolean;
+ variable is_top : boolean;
+ begin
+ if (env_reset = '1') then
+ -- load initial state
+ if (reg(13)(2) = '0') then -- attack
+ env_vol <= "11111";
+ env_inc <= '0'; -- -1
+ else
+ env_vol <= "00000";
+ env_inc <= '1'; -- +1
+ end if;
+ env_hold <= '0';
+
+ elsif rising_edge(CLK) then
+ is_bot := (env_vol = "00000");
+ is_bot_p1 := (env_vol = "00001");
+ is_top_m1 := (env_vol = "11110");
+ is_top := (env_vol = "11111");
+
+ if (ENA = '1') then
+ if (env_ena = '1') then
+ if (env_hold = '0') then
+ if (env_inc = '1') then
+ env_vol <= (env_vol + "00001");
+ else
+ env_vol <= (env_vol + "11111");
+ end if;
+ end if;
+
+ -- envelope shape control.
+ if (reg(13)(3) = '0') then
+ if (env_inc = '0') then -- down
+ if is_bot_p1 then env_hold <= '1'; end if;
+ else
+ if is_top then env_hold <= '1'; end if;
+ end if;
+ else
+ if (reg(13)(0) = '1') then -- hold = 1
+ if (env_inc = '0') then -- down
+ if (reg(13)(1) = '1') then -- alt
+ if is_bot then env_hold <= '1'; end if;
+ else
+ if is_bot_p1 then env_hold <= '1'; end if;
+ end if;
+ else
+ if (reg(13)(1) = '1') then -- alt
+ if is_top then env_hold <= '1'; end if;
+ else
+ if is_top_m1 then env_hold <= '1'; end if;
+ end if;
+ end if;
+
+ elsif (reg(13)(1) = '1') then -- alternate
+ if (env_inc = '0') then -- down
+ if is_bot_p1 then env_hold <= '1'; end if;
+ if is_bot then env_hold <= '0'; env_inc <= '1'; end if;
+ else
+ if is_top_m1 then env_hold <= '1'; end if;
+ if is_top then env_hold <= '0'; env_inc <= '0'; end if;
+ end if;
+ end if;
+
+ end if;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ p_chan_mixer : process(cnt_div, reg, tone_gen_op)
+ begin
+ tone_ena_l <= '1'; tone_src <= '1';
+ noise_ena_l <= '1'; chan_vol <= "00000";
+ case cnt_div(1 downto 0) is
+ when "00" =>
+ tone_ena_l <= reg(7)(0); tone_src <= tone_gen_op(1); chan_vol <= reg(8)(4 downto 0);
+ noise_ena_l <= reg(7)(3);
+ when "01" =>
+ tone_ena_l <= reg(7)(1); tone_src <= tone_gen_op(2); chan_vol <= reg(9)(4 downto 0);
+ noise_ena_l <= reg(7)(4);
+ when "10" =>
+ tone_ena_l <= reg(7)(2); tone_src <= tone_gen_op(3); chan_vol <= reg(10)(4 downto 0);
+ noise_ena_l <= reg(7)(5);
+ when "11" => null; -- tone gen outputs become valid on this clock
+ when others => null;
+ end case;
+ end process;
+
+ p_op_mixer : process
+ variable chan_mixed : std_logic;
+ variable chan_amp : std_logic_vector(4 downto 0);
+ begin
+ wait until rising_edge(CLK);
+ if (ENA = '1') then
+
+ chan_mixed := (tone_ena_l or tone_src) and (noise_ena_l or noise_gen_op);
+
+ chan_amp := (others => '0');
+ if (chan_mixed = '1') then
+ if (chan_vol(4) = '0') then
+ if (chan_vol(3 downto 0) = "0000") then -- nothing is easy ! make sure quiet is quiet
+ chan_amp := "00000";
+ else
+ chan_amp := chan_vol(3 downto 0) & '1'; -- make sure level 31 (env) = level 15 (tone)
+ end if;
+ else
+ chan_amp := env_vol(4 downto 0);
+ end if;
+ end if;
+
+ dac_amp <= x"00";
+ case chan_amp is
+ when "11111" => dac_amp <= x"FF";
+ when "11110" => dac_amp <= x"D9";
+ when "11101" => dac_amp <= x"BA";
+ when "11100" => dac_amp <= x"9F";
+ when "11011" => dac_amp <= x"88";
+ when "11010" => dac_amp <= x"74";
+ when "11001" => dac_amp <= x"63";
+ when "11000" => dac_amp <= x"54";
+ when "10111" => dac_amp <= x"48";
+ when "10110" => dac_amp <= x"3D";
+ when "10101" => dac_amp <= x"34";
+ when "10100" => dac_amp <= x"2C";
+ when "10011" => dac_amp <= x"25";
+ when "10010" => dac_amp <= x"1F";
+ when "10001" => dac_amp <= x"1A";
+ when "10000" => dac_amp <= x"16";
+ when "01111" => dac_amp <= x"13";
+ when "01110" => dac_amp <= x"10";
+ when "01101" => dac_amp <= x"0D";
+ when "01100" => dac_amp <= x"0B";
+ when "01011" => dac_amp <= x"09";
+ when "01010" => dac_amp <= x"08";
+ when "01001" => dac_amp <= x"07";
+ when "01000" => dac_amp <= x"06";
+ when "00111" => dac_amp <= x"05";
+ when "00110" => dac_amp <= x"04";
+ when "00101" => dac_amp <= x"03";
+ when "00100" => dac_amp <= x"03";
+ when "00011" => dac_amp <= x"02";
+ when "00010" => dac_amp <= x"02";
+ when "00001" => dac_amp <= x"01";
+ when "00000" => dac_amp <= x"00";
+ when others => null;
+ end case;
+
+ cnt_div_t1 <= cnt_div;
+ end if;
+ end process;
+
+ p_audio_output : process(RESET_L, CLK)
+ begin
+ if (RESET_L = '0') then
+ O_AUDIO <= (others => '0');
+ O_CHAN <= (others => '0');
+ elsif rising_edge(CLK) then
+
+ if (ENA = '1') then
+ O_AUDIO <= dac_amp(7 downto 0);
+ O_CHAN <= cnt_div_t1(1 downto 0);
+ end if;
+ end if;
+ end process;
+
+ p_io_ports : process(reg)
+ begin
+ O_IOA <= reg(14);
+ O_IOA_OE_L <= not reg(7)(6);
+ O_IOB <= reg(15);
+ O_IOB_OE_L <= not reg(7)(7);
+ end process;
+
+ p_io_ports_inreg : process
+ begin
+ wait until rising_edge(CLK);
+ if (ENA = '1') then -- resync
+ ioa_inreg <= I_IOA;
+ iob_inreg <= I_IOB;
+ end if;
+ end process;
+end architecture RTL;
diff --git a/common/Sound/ay8910.sv b/common/Sound/ay8910.sv
new file mode 100644
index 00000000..31d79c50
--- /dev/null
+++ b/common/Sound/ay8910.sv
@@ -0,0 +1,308 @@
+// ports are not identical to the actual AY chip - no need for that.
+// Also the parallel ports are not very useful, so they are not connected
+
+
+
+
+module ay8910(rst_n,clk,clk_en,asel,wr_n,cs_n,din,dout,A,B,C,audio);
+ input rst_n;
+ input clk; // 28 MHz clock from the system
+ input clk_en; // 1.7 (?) clock to run the sound timing
+ input asel;
+ input wr_n;
+ input cs_n;
+ input [7:0] din;
+ output [7:0] dout;
+ output [7:0] A;
+ output [7:0] B;
+ output [7:0] C;
+ output [7:0] audio;
+
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Write Register
+/////////////////////////////////////////////////////////////////////////////
+
+
+reg [3:0] addr;
+
+
+// registers
+reg [11:0] period_a,period_b,period_c;
+reg [4:0] period_n;
+reg [7:0] reg_en;
+reg [4:0] vol_a,vol_b,vol_c;
+reg [15:0] period_e;
+reg [3:0] shape_e;
+reg [7:0] pa_r,pb_r;
+
+
+wire pb_od = reg_en[7];
+wire pa_od = reg_en[6];
+wire na = reg_en[5];
+wire nb = reg_en[4];
+wire nc = reg_en[3];
+wire ena = reg_en[2];
+wire enb = reg_en[1];
+wire enc = reg_en[0];
+
+
+always @(posedge clk)
+if(~rst_n) begin
+ vol_a <= 0;
+ vol_b <= 0;
+ vol_c <= 0;
+end else
+
+
+if(~wr_n && ~cs_n) begin
+ if(asel)
+ begin
+ // address write
+ addr <= din[3:0];
+ end else begin
+ // register write
+ case(addr)
+ 0:period_a[ 7:0] <= din;
+ 1:period_a[11:8] <= din[3:0];
+ 2:period_b[ 7:0] <= din;
+ 3:period_b[11:8] <= din[3:0];
+ 4:period_c[ 7:0] <= din;
+ 5:period_c[11:8] <= din[3:0];
+ 6:period_n[ 4:0] <= din[4:0];
+ 7:reg_en <= din;
+ 8:vol_a <= din[4:0];
+ 9:vol_b <= din[4:0];
+ 10:vol_c <= din[4:0];
+ 11:period_e[7:0] <= din;
+ 12:period_e[15:8] <= din;
+ 13:shape_e <= din[3:0];
+ 14:pa_r <= din;
+ 15:pb_r <= din;
+ endcase
+ end
+end
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Read Register
+/////////////////////////////////////////////////////////////////////////////
+assign dout = addr==4'h0 ? period_a[7:0] :
+ addr==4'h1 ? {4'h0,period_a[11:0]} :
+ addr==4'h2 ? period_b[7:0] :
+ addr==4'h3 ? {4'h0,period_b[11:0]} :
+ addr==4'h4 ? period_c[7:0] :
+ addr==4'h5 ? {4'h0,period_c[11:0]} :
+ addr==4'h6 ? {3'h0,period_n} :
+ addr==4'h7 ? reg_en :
+ addr==4'h8 ? {3'h0,vol_a} :
+ addr==4'h9 ? {3'h0,vol_b} :
+ addr==4'ha ? {3'h0,vol_c} :
+ addr==4'hb ? period_e[7:0] :
+ addr==4'hc ? period_e[15:8] :
+ addr==4'hd ? {4'h0,shape_e} : 8'hff;
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+// PSG
+/////////////////////////////////////////////////////////////////////////////
+
+
+//
+// toneA 12bit | 12bit
+// toneB 12bit | 12bit
+// toneC 12bit | 12bit
+// env 15bit | 15bit
+//
+reg [2:0] pris;
+reg [11:0] cnt_a,cnt_b,cnt_c;
+
+
+reg out_a,out_b,out_c;
+
+
+always @(posedge clk)
+if(clk_en) begin
+ pris <= pris + 1;
+ if(pris==0)
+ begin
+ // tone generator
+ cnt_a <= cnt_a + 1;
+ if(cnt_a==period_a)
+ begin
+ out_a <= ~out_a;
+ cnt_a <= 0;
+ end
+ cnt_b <= cnt_b + 1;
+ if(cnt_b==period_b)
+ begin
+ out_b <= ~out_b;
+ cnt_b <= 0;
+ end
+ cnt_c <= cnt_c + 1;
+ if(cnt_c==period_c)
+ begin
+ out_c <= ~out_c;
+ cnt_c <= 0;
+ end
+ end
+end
+
+
+/////////////////////////////////////////////////////////////////////////////
+// envelope generator
+/////////////////////////////////////////////////////////////////////////////
+reg [15:0] env_cnt;
+reg [3:0] env_phase;
+reg env_start;
+reg env_en;
+reg env_inv;
+
+
+// write eshape
+wire env_clr = (addr==13) & ~cs_n & ~wr_n;
+
+
+// bit3 = turn reset , 0=on , 1=off
+// bit2 = start , 0=up , 1=down(inv)
+// bit1 = turn invert, 0=tggle , 1=fix
+// bit0 = turn repeat, 0=off, 1=on
+
+
+wire next_no_reset = shape_e[3];
+wire start_no_inv = shape_e[2];
+wire next_toggle = shape_e[1];
+wire next_repeat = shape_e[0];
+
+
+// envelope volume output
+wire [3:0] vol_e = env_phase ^ {4{env_inv}};
+
+
+//
+always @(posedge clk or posedge env_clr)
+begin
+ if(env_clr) env_start <= 1'b1;
+ else if(clk_en) env_start <= 1'b0;
+end
+
+
+always @(posedge clk or negedge rst_n)
+begin
+ if(~rst_n)
+ begin
+ env_en <= 1'b0;
+ end else
+ if(clk_en)begin
+
+
+ // start trigger
+ if(env_start)
+ begin
+ env_cnt <= 0;
+ env_phase <= 0;
+ env_inv <= ~start_no_inv;
+ env_en <= 1'b1;
+ end
+
+
+ // count
+ if(pris==0 && env_en)
+ begin
+ // phase up
+ env_cnt <= env_cnt + 1;
+ if(env_cnt==period_e)
+ begin
+ env_cnt <= 0;
+ env_phase <= env_phase+1;
+ // turn over
+ if(env_phase==15)
+ begin
+ if(~next_no_reset)
+ begin
+ env_inv <= (env_inv ^ next_toggle) & next_no_reset;
+ env_en <= next_repeat & next_no_reset;
+ end
+ end
+ end
+ end
+ end
+end
+
+
+/////////////////////////////////////////////////////////////////////////////
+// noise generator
+/////////////////////////////////////////////////////////////////////////////
+reg [16:0] shift_n;
+reg [4:0] cnt_n;
+
+
+always @(posedge clk or negedge rst_n)
+begin
+ if(~rst_n)
+ begin
+ shift_n <= 17'b00000000000000001;
+ end else if((pris==0) &&(clk_en))
+ begin
+ cnt_n <= cnt_n +1;
+ if(cnt_n == period_n)
+ begin
+ cnt_n <= 0;
+ shift_n <= {shift_n[0]^shift_n[3],shift_n[16:1]};
+ end
+ end
+end
+
+
+wire out_n = shift_n[0];
+
+
+/////////////////////////////////////////////////////////////////////////////
+// volume table 3db / step
+/////////////////////////////////////////////////////////////////////////////
+function [7:0] vol_tbl;
+input [4:0] vol;
+input [3:0] vole;
+input out;
+begin
+ if(~out)
+ vol_tbl = 0;
+ else case(vol[4]?vole:vol[3:0])
+ 15:vol_tbl = 255;
+ 14:vol_tbl = 180;
+ 13:vol_tbl = 127;
+ 12:vol_tbl = 90;
+ 11:vol_tbl = 64;
+ 10:vol_tbl = 45;
+ 9:vol_tbl = 32;
+ 8:vol_tbl = 22;
+ 7:vol_tbl = 16;
+ 6:vol_tbl = 11;
+ 5:vol_tbl = 8;
+ 4:vol_tbl = 5;
+ 3:vol_tbl = 4;
+ 2:vol_tbl = 3;
+ 1:vol_tbl = 2;
+ 0:vol_tbl = 0; //1;
+ endcase
+end
+endfunction
+
+
+/////////////////////////////////////////////////////////////////////////////
+// output
+/////////////////////////////////////////////////////////////////////////////
+assign A = vol_tbl(vol_a,vol_e,(out_a | ena) & (out_n | na) );
+assign B = vol_tbl(vol_b,vol_e,(out_b | enb) & (out_n | nb) );
+assign C = vol_tbl(vol_c,vol_e,(out_c | enc) & (out_n | nc) );
+assign audio = {"00",A} + {"00",B} + {"00",C};//todo gehstock
+
+
+
+
+
+
+endmodule
\ No newline at end of file
diff --git a/common/Sound/ay8912.vhd b/common/Sound/ay8912.vhd
new file mode 100644
index 00000000..9cd0a82e
--- /dev/null
+++ b/common/Sound/ay8912.vhd
@@ -0,0 +1,380 @@
+------------------------------------------------------------------------------
+------------------------------------------------------------------------------
+-- --
+-- Copyright (c) 2005-2009 Tobias Gubener --
+-- Subdesign CPC T-REX by TobiFlex --
+-- --
+-- This source file 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 source file 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 . --
+-- --
+------------------------------------------------------------------------------
+------------------------------------------------------------------------------
+
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+
+entity ay8912 is
+ port (
+ cpuclk : in STD_LOGIC; --48MHz
+ reset : in STD_LOGIC;
+ cs : in STD_LOGIC; --H-aktiv
+ bc0 : in STD_LOGIC; --
+ bdir : in STD_LOGIC;
+ Data_in : in STD_LOGIC_VECTOR (7 downto 0);
+ Data_out : out STD_LOGIC_VECTOR (7 downto 0);
+ IO_A : in STD_LOGIC_VECTOR (7 downto 0);
+ chanA : buffer STD_LOGIC_VECTOR (10 downto 0);
+ chanB : buffer STD_LOGIC_VECTOR (10 downto 0);
+ chanC : buffer STD_LOGIC_VECTOR (10 downto 0);
+ Arechts : out STD_LOGIC_VECTOR (15 downto 0);
+ Alinks : out STD_LOGIC_VECTOR (15 downto 0);
+ Amono : out STD_LOGIC_VECTOR (15 downto 0)
+ );
+end ay8912;
+
+architecture logic of ay8912 is
+signal t_Data : STD_LOGIC_VECTOR (7 downto 0);
+signal PSGReg : STD_LOGIC_VECTOR (3 downto 0);
+signal APeriode : STD_LOGIC_VECTOR (11 downto 0); --Reg 0,1
+signal BPeriode : STD_LOGIC_VECTOR (11 downto 0); --Reg 2,3
+signal CPeriode : STD_LOGIC_VECTOR (11 downto 0); --Reg 4,5
+signal Noise : STD_LOGIC_VECTOR (4 downto 0); --Reg 6
+signal enable : STD_LOGIC_VECTOR (7 downto 0); --Reg 7
+signal AVol : STD_LOGIC_VECTOR (4 downto 0); --Reg 8
+signal BVol : STD_LOGIC_VECTOR (4 downto 0); --Reg 9
+signal CVol : STD_LOGIC_VECTOR (4 downto 0); --Reg 10
+signal HPeriode : STD_LOGIC_VECTOR (15 downto 0); --Reg 11,12
+signal HKurve : STD_LOGIC_VECTOR (3 downto 0); --Reg 13
+signal PortA : STD_LOGIC_VECTOR (7 downto 0); --Reg 14
+signal PortB : STD_LOGIC_VECTOR (7 downto 0); --Reg 15
+signal AVollog : STD_LOGIC_VECTOR (9 downto 0); --Reg 8log
+signal BVollog : STD_LOGIC_VECTOR (9 downto 0); --Reg 9log
+signal CVollog : STD_LOGIC_VECTOR (9 downto 0); --Reg 10log
+signal Alog : STD_LOGIC_VECTOR (9 downto 0);
+signal Blog : STD_LOGIC_VECTOR (9 downto 0);
+signal Clog : STD_LOGIC_VECTOR (9 downto 0);
+signal HVollog : STD_LOGIC_VECTOR (11 downto 0);
+signal ACount : STD_LOGIC_VECTOR (11 downto 0);
+signal BCount : STD_LOGIC_VECTOR (11 downto 0);
+signal CCount : STD_LOGIC_VECTOR (11 downto 0);
+signal NCount : STD_LOGIC_VECTOR (4 downto 0);
+signal HCount : STD_LOGIC_VECTOR (15 downto 0);
+signal HVol : STD_LOGIC_VECTOR (4 downto 0);
+signal nHVol : STD_LOGIC_VECTOR (3 downto 0);
+signal HStart : STD_LOGIC;
+signal Noisebit : STD_LOGIC;
+signal RNG : STD_LOGIC_VECTOR (16 downto 0);
+signal Anot, Bnot, Cnot : STD_LOGIC;
+signal n_setreg : STD_LOGIC;
+signal n_Pegel : STD_LOGIC_VECTOR (11 downto 0);
+
+signal clockgen : STD_LOGIC_VECTOR (9 downto 0);
+signal S_Tick : STD_LOGIC;
+signal H_Tick : STD_LOGIC;
+
+
+
+begin
+
+-------------------------------------------------------------------------
+--Clock gen
+-------------------------------------------------------------------------
+process (cpuclk, clockgen)
+begin
+ S_Tick <= '0'; --sound
+ H_Tick <= '0'; --Hüllkurve
+ IF clockgen(9 downto 1)=0 THEN
+ S_Tick <= '1';
+ IF clockgen(0)='0' THEN
+ H_Tick <= '1';
+ END IF;
+ END IF;
+ IF rising_edge(cpuclk) THEN
+ Arechts <= (chanA&"00000")+('0'&chanB&"0000");
+ Alinks <= (chanC&"00000")+('0'&chanB&"0000");
+ Amono <= (chanC&"00000")+('0'&chanB&"0000")+(chanA&"00000");
+ IF H_Tick='1' THEN
+-- clockgen <= ((48*16)-1); --48MHz
+ clockgen <= "1011111111"; --48MHz
+ ELSE
+ clockgen <= clockgen-1;
+ END IF;
+ END IF;
+END process;
+-------------------------------------------------------------------------
+--IO Regs
+-------------------------------------------------------------------------
+process (cpuclk, reset, IO_A, PortA, PortB, Aperiode, Bperiode, Cperiode, Hperiode, AVol, BVol, CVol, Noise, HKurve, enable, Data_in, t_Data, PSGReg, bdir, bc0)
+begin
+ IF reset='0' THEN
+ enable <= (others => '0');
+ PortA <= "11111111";
+ PortB <= "11111111";
+ ELSIF rising_edge(cpuclk) THEN
+ HStart <= '0';
+ IF bdir='1' AND bc0='1' THEN
+ IF Data_in(7 downto 4)="0000" THEN
+ PSGReg <= Data_in(3 downto 0);
+ END IF;
+ ELSE
+ IF bdir='1' AND bc0='0' THEN
+ CASE PSGReg IS
+ WHEN "0000" =>
+ APeriode(7 downto 0) <= Data_in;
+ WHEN "0001" =>
+ APeriode(11 downto 8) <= Data_in(3 downto 0);
+ WHEN "0010" =>
+ BPeriode(7 downto 0) <= Data_in;
+ WHEN "0011" =>
+ BPeriode(11 downto 8) <= Data_in(3 downto 0);
+ WHEN "0100" =>
+ CPeriode(7 downto 0) <= Data_in;
+ WHEN "0101" =>
+ CPeriode(11 downto 8) <= Data_in(3 downto 0);
+ WHEN "0110" =>
+ Noise(4 downto 0) <= Data_in(4 downto 0);
+ WHEN "0111" =>
+ enable <= Data_in XOR B"00111111";
+ WHEN "1000" =>
+ AVollog <= n_Pegel(9 downto 0);
+ AVol(4 downto 0) <= Data_in(4 downto 0);
+ WHEN "1001" =>
+ BVollog <= n_Pegel(9 downto 0);
+ BVol(4 downto 0) <= Data_in(4 downto 0);
+ WHEN "1010" =>
+ CVollog <= n_Pegel(9 downto 0);
+ CVol(4 downto 0) <= Data_in(4 downto 0);
+ WHEN "1011" =>
+ HPeriode(7 downto 0) <= Data_in;
+ WHEN "1100" =>
+ HPeriode(15 downto 8) <= Data_in;
+ WHEN "1101" =>
+ HStart <= '1';
+ HKurve(3 downto 0) <= Data_in(3 downto 0);
+ WHEN "1110" =>
+ PortA <= Data_in;
+ WHEN "1111" =>
+ PortB <= Data_in;
+ WHEN OTHERS => null;
+ END CASE;
+ END IF;
+ END IF;
+ END IF;
+ CASE Data_in(3 downto 0) IS
+ WHEN "1111" => n_Pegel <= X"2AA"; -- Umsetzung in logarithmische Werte in ca. 3dB Schritten
+ WHEN "1110" => n_Pegel <= X"1E2"; -- für Kanäle
+ WHEN "1101" => n_Pegel <= X"155";
+ WHEN "1100" => n_Pegel <= X"0F1";
+ WHEN "1011" => n_Pegel <= X"0AA";
+ WHEN "1010" => n_Pegel <= X"078";
+ WHEN "1001" => n_Pegel <= X"055";
+ WHEN "1000" => n_Pegel <= X"03C";
+ WHEN "0111" => n_Pegel <= X"02A";
+ WHEN "0110" => n_Pegel <= X"01E";
+ WHEN "0101" => n_Pegel <= X"015";
+ WHEN "0100" => n_Pegel <= X"00F";
+ WHEN "0011" => n_Pegel <= X"00A";
+ WHEN "0010" => n_Pegel <= X"007";
+ WHEN "0001" => n_Pegel <= X"005";
+ WHEN "0000" => n_Pegel <= X"000";
+ WHEN OTHERS => null;
+ END CASE;
+-- read reg
+
+ IF bc0='1' AND bdir='0' THEN
+ Data_out <= t_Data;
+ ELSE
+ Data_out <= "11111111";
+ END IF;
+
+ t_Data <= "00000000";
+ CASE PSGReg IS
+ WHEN "0000" =>
+ t_Data <= Aperiode(7 downto 0);
+ WHEN "0001" =>
+ t_Data(3 downto 0) <= Aperiode(11 downto 8);
+ WHEN "0010" =>
+ t_Data <= Bperiode(7 downto 0);
+ WHEN "0011" =>
+ t_Data(3 downto 0) <= Bperiode(11 downto 8);
+ WHEN "0100" =>
+ t_Data <= Cperiode(7 downto 0);
+ WHEN "0101" =>
+ t_Data(3 downto 0) <= Cperiode(11 downto 8);
+ WHEN "0110" =>
+ t_Data(4 downto 0) <= Noise;
+ WHEN "0111" =>
+ t_Data <= enable XOR "00111111";
+ WHEN "1000" =>
+ t_Data(4 downto 0) <= AVol;
+ WHEN "1001" =>
+ t_Data(4 downto 0) <= BVol;
+ WHEN "1010" =>
+ t_Data(4 downto 0) <= CVol;
+ WHEN "1011" =>
+ t_Data <= Hperiode(7 downto 0);
+ WHEN "1100" =>
+ t_Data <= Hperiode(15 downto 8);
+ WHEN "1101" =>
+ t_Data(3 downto 0) <= HKurve;
+ WHEN "1110" =>
+ IF enable(6)='0' THEN
+ t_Data <= PortA AND IO_A;
+ ELSE
+ t_Data <= PortA;
+ END IF;
+ WHEN "1111" =>
+ t_Data <= PortB;
+ END CASE;
+END process;
+-------------------------------------------------------------------------
+--Soundgen
+-------------------------------------------------------------------------
+process (cpuclk, reset, AVol, BVol, CVol, HVol, nHVol, AVollog, BVollog, CVollog, HVollog, HKurve)
+begin
+-- channel A
+ IF AVol(4)='1' THEN
+ Alog <= HVollog(9 downto 0);
+ ELSE
+ Alog <= AVollog;
+ END IF;
+ IF rising_edge(cpuclk) THEN
+ IF ((enable(3) AND Noisebit) XOR Anot)='1' THEN
+ chanA <= ('0'&Alog);
+ ELSE
+ chanA <= (others => '0');
+ END IF;
+ IF enable(0)='0' OR APeriode="000000000000" THEN
+ Anot <= '1';
+ ACount <= "000000000000";
+ ELSIF S_Tick='1' THEN
+ IF ACount(11 downto 0)>=APeriode THEN
+ ACount <= "000000000001";
+ Anot <= NOT Anot;
+ ELSE
+ ACount <= ACount+1;
+ END IF;
+ END IF;
+ END IF;
+
+-- channel B
+ IF BVol(4)='1' THEN
+ Blog <= HVollog(9 downto 0);
+ ELSE
+ Blog <= BVollog;
+ END IF;
+ IF rising_edge(cpuclk) THEN
+ IF ((enable(4) AND Noisebit) XOR Bnot)='1' THEN
+ chanB <= ('0'&Blog);
+ ELSE
+ chanB <= (others => '0');
+ END IF;
+ IF enable(1)='0' OR BPeriode="000000000000" THEN
+ Bnot <= '1';
+ BCount <= "000000000000";
+ ELSIF S_Tick='1' THEN
+ IF BCount(11 downto 0)>=BPeriode THEN
+ BCount <= "000000000001";
+ Bnot <= NOT Bnot;
+ ELSE
+ BCount <= BCount+1;
+ END IF;
+ END IF;
+ END IF;
+
+-- channel C
+ IF CVol(4)='1' THEN
+ Clog <= HVollog(9 downto 0);
+ ELSE
+ Clog <= CVollog;
+ END IF;
+ IF rising_edge(cpuclk) THEN
+ IF ((enable(5) AND Noisebit) XOR Cnot)='1' THEN
+ chanC <= ('0'&Clog);
+ ELSE
+ chanC <= (others => '0');
+ END IF;
+ IF enable(2)='0' OR CPeriode="000000000000" THEN
+ Cnot <= '1';
+ CCount <= "000000000000";
+ ELSIF S_Tick='1' THEN
+ IF CCount(11 downto 0)>=CPeriode THEN
+ CCount <= "000000000001";
+ Cnot <= NOT Cnot;
+ ELSE
+ CCount <= CCount+1;
+ END IF;
+ END IF;
+ END IF;
+
+--noise
+--Noise="00000" and Noise="00001" is the same
+ IF rising_edge(cpuclk) THEN
+ IF S_Tick='1' THEN
+ IF NCount(4 downto 1)="0000" THEN
+ NCount <= Noise ;
+ RNG <= (NOT (RNG(0) XOR RNG(2))& RNG(16 downto 1));
+ Noisebit <= RNG(0);
+ ELSE
+ NCount <= NCount-1;
+ END IF;
+ END IF;
+ END IF;
+
+-- Huellkurve
+ nHVol <= HVol(3 downto 0);
+ IF ((HKurve(3) OR NOT HVol(4)) AND ( NOT HKurve(2) XOR ((HKurve(1) XOR HKurve(0)) AND HVol(4))))='1' THEN
+ nHVol <= HVol(3 downto 0) XOR "1111";
+ END IF;
+
+ IF rising_edge(cpuclk) THEN
+ IF HStart='1' THEN
+ HCount <= "0000000000000001";
+ HVol <= "00000";
+ ELSIF H_Tick='1' THEN
+ IF HCount>=HPeriode THEN
+ HCount <= "0000000000000001";
+ IF (NOT HVol(4) OR (NOT HKurve(0) AND HKurve(3)))='1' AND (HPeriode /= 0) THEN --HOLD
+-- IF (NOT HVol(4) OR (NOT HKurve(0) AND HKurve(3)))='1' THEN --HOLD
+ HVol <= HVol+1;
+ END IF;
+ ELSE
+ HCount <= HCount+1;
+ END IF;
+ END IF;
+ END IF;
+
+ CASE nHVol(3 downto 0) IS
+ WHEN "1111" => HVollog <= X"2AA"; -- Umsetzung in logarithmische Werte in ca. 3dB Schritten
+ WHEN "1110" => HVollog <= X"1E2"; -- für Hüllkurve
+ WHEN "1101" => HVollog <= X"155";
+ WHEN "1100" => HVollog <= X"0F1";
+ WHEN "1011" => HVollog <= X"0AA";
+ WHEN "1010" => HVollog <= X"078";
+ WHEN "1001" => HVollog <= X"055";
+ WHEN "1000" => HVollog <= X"03C";
+ WHEN "0111" => HVollog <= X"02A";
+ WHEN "0110" => HVollog <= X"01E";
+ WHEN "0101" => HVollog <= X"015";
+ WHEN "0100" => HVollog <= X"00F";
+ WHEN "0011" => HVollog <= X"00A";
+ WHEN "0010" => HVollog <= X"007";
+ WHEN "0001" => HVollog <= X"005";
+ WHEN "0000" => HVollog <= X"000";
+ WHEN OTHERS => null;
+ END CASE;
+END process;
+
+end logic;
diff --git a/common/Sound/ay8913.vhd b/common/Sound/ay8913.vhd
new file mode 100644
index 00000000..256f9d51
--- /dev/null
+++ b/common/Sound/ay8913.vhd
@@ -0,0 +1,375 @@
+------------------------------------------------------------------------------
+------------------------------------------------------------------------------
+-- --
+-- Copyright (c) 2005-2009 Tobias Gubener --
+-- Subdesign CPC T-REX by TobiFlex --
+-- --
+-- This source file 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 source file 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 . --
+-- --
+------------------------------------------------------------------------------
+------------------------------------------------------------------------------
+
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+
+entity ay8913 is
+ port (
+ cpuclk : in STD_LOGIC; --48MHz
+ reset : in STD_LOGIC;
+ cs : in STD_LOGIC; --H-aktiv
+ bc0 : in STD_LOGIC; --
+ bdir : in STD_LOGIC;
+ Data_in : in STD_LOGIC_VECTOR (7 downto 0);
+ Data_out : out STD_LOGIC_VECTOR (7 downto 0);
+ chanA : buffer STD_LOGIC_VECTOR (10 downto 0);
+ chanB : buffer STD_LOGIC_VECTOR (10 downto 0);
+ chanC : buffer STD_LOGIC_VECTOR (10 downto 0);
+ Arechts : out STD_LOGIC_VECTOR (15 downto 0);
+ Alinks : out STD_LOGIC_VECTOR (15 downto 0);
+ Amono : out STD_LOGIC_VECTOR (15 downto 0)
+ );
+end ay8913;
+
+architecture logic of ay8913 is
+signal t_Data : STD_LOGIC_VECTOR (7 downto 0);
+signal PSGReg : STD_LOGIC_VECTOR (3 downto 0);
+signal APeriode : STD_LOGIC_VECTOR (11 downto 0); --Reg 0,1
+signal BPeriode : STD_LOGIC_VECTOR (11 downto 0); --Reg 2,3
+signal CPeriode : STD_LOGIC_VECTOR (11 downto 0); --Reg 4,5
+signal Noise : STD_LOGIC_VECTOR (4 downto 0); --Reg 6
+signal enable : STD_LOGIC_VECTOR (7 downto 0); --Reg 7
+signal AVol : STD_LOGIC_VECTOR (4 downto 0); --Reg 8
+signal BVol : STD_LOGIC_VECTOR (4 downto 0); --Reg 9
+signal CVol : STD_LOGIC_VECTOR (4 downto 0); --Reg 10
+signal HPeriode : STD_LOGIC_VECTOR (15 downto 0); --Reg 11,12
+signal HKurve : STD_LOGIC_VECTOR (3 downto 0); --Reg 13
+signal PortA : STD_LOGIC_VECTOR (7 downto 0); --Reg 14
+signal PortB : STD_LOGIC_VECTOR (7 downto 0); --Reg 15
+signal AVollog : STD_LOGIC_VECTOR (9 downto 0); --Reg 8log
+signal BVollog : STD_LOGIC_VECTOR (9 downto 0); --Reg 9log
+signal CVollog : STD_LOGIC_VECTOR (9 downto 0); --Reg 10log
+signal Alog : STD_LOGIC_VECTOR (9 downto 0);
+signal Blog : STD_LOGIC_VECTOR (9 downto 0);
+signal Clog : STD_LOGIC_VECTOR (9 downto 0);
+signal HVollog : STD_LOGIC_VECTOR (11 downto 0);
+signal ACount : STD_LOGIC_VECTOR (11 downto 0);
+signal BCount : STD_LOGIC_VECTOR (11 downto 0);
+signal CCount : STD_LOGIC_VECTOR (11 downto 0);
+signal NCount : STD_LOGIC_VECTOR (4 downto 0);
+signal HCount : STD_LOGIC_VECTOR (15 downto 0);
+signal HVol : STD_LOGIC_VECTOR (4 downto 0);
+signal nHVol : STD_LOGIC_VECTOR (3 downto 0);
+signal HStart : STD_LOGIC;
+signal Noisebit : STD_LOGIC;
+signal RNG : STD_LOGIC_VECTOR (16 downto 0);
+signal Anot, Bnot, Cnot : STD_LOGIC;
+signal n_setreg : STD_LOGIC;
+signal n_Pegel : STD_LOGIC_VECTOR (11 downto 0);
+
+signal clockgen : STD_LOGIC_VECTOR (9 downto 0);
+signal S_Tick : STD_LOGIC;
+signal H_Tick : STD_LOGIC;
+
+
+
+begin
+
+-------------------------------------------------------------------------
+--Clock gen
+-------------------------------------------------------------------------
+process (cpuclk, clockgen)
+begin
+ S_Tick <= '0'; --sound
+ H_Tick <= '0'; --Hüllkurve
+ IF clockgen(9 downto 1)=0 THEN
+ S_Tick <= '1';
+ IF clockgen(0)='0' THEN
+ H_Tick <= '1';
+ END IF;
+ END IF;
+ IF rising_edge(cpuclk) THEN
+ Arechts <= (chanA&"00000")+('0'&chanB&"0000");
+ Alinks <= (chanC&"00000")+('0'&chanB&"0000");
+ Amono <= (chanC&"00000")+('0'&chanB&"0000")+(chanA&"00000");
+ IF H_Tick='1' THEN
+-- clockgen <= ((48*16)-1); --48MHz
+ clockgen <= "1011111111"; --48MHz
+ ELSE
+ clockgen <= clockgen-1;
+ END IF;
+ END IF;
+END process;
+-------------------------------------------------------------------------
+--IO Regs
+-------------------------------------------------------------------------
+process (cpuclk, reset, IO_A, PortA, PortB, Aperiode, Bperiode, Cperiode, Hperiode, AVol, BVol, CVol, Noise, HKurve, enable, Data_in, t_Data, PSGReg, bdir, bc0)
+begin
+ IF reset='0' THEN
+ enable <= (others => '0');
+ PortA <= "11111111";
+ PortB <= "11111111";
+ ELSIF rising_edge(cpuclk) THEN
+ HStart <= '0';
+ IF bdir='1' AND bc0='1' THEN
+ IF Data_in(7 downto 4)="0000" THEN
+ PSGReg <= Data_in(3 downto 0);
+ END IF;
+ ELSE
+ IF bdir='1' AND bc0='0' THEN
+ CASE PSGReg IS
+ WHEN "0000" =>
+ APeriode(7 downto 0) <= Data_in;
+ WHEN "0001" =>
+ APeriode(11 downto 8) <= Data_in(3 downto 0);
+ WHEN "0010" =>
+ BPeriode(7 downto 0) <= Data_in;
+ WHEN "0011" =>
+ BPeriode(11 downto 8) <= Data_in(3 downto 0);
+ WHEN "0100" =>
+ CPeriode(7 downto 0) <= Data_in;
+ WHEN "0101" =>
+ CPeriode(11 downto 8) <= Data_in(3 downto 0);
+ WHEN "0110" =>
+ Noise(4 downto 0) <= Data_in(4 downto 0);
+ WHEN "0111" =>
+ enable <= Data_in XOR B"00111111";
+ WHEN "1000" =>
+ AVollog <= n_Pegel(9 downto 0);
+ AVol(4 downto 0) <= Data_in(4 downto 0);
+ WHEN "1001" =>
+ BVollog <= n_Pegel(9 downto 0);
+ BVol(4 downto 0) <= Data_in(4 downto 0);
+ WHEN "1010" =>
+ CVollog <= n_Pegel(9 downto 0);
+ CVol(4 downto 0) <= Data_in(4 downto 0);
+ WHEN "1011" =>
+ HPeriode(7 downto 0) <= Data_in;
+ WHEN "1100" =>
+ HPeriode(15 downto 8) <= Data_in;
+ WHEN "1101" =>
+ HStart <= '1';
+ HKurve(3 downto 0) <= Data_in(3 downto 0);
+ WHEN "1110" =>
+ PortA <= Data_in;
+ WHEN "1111" =>
+ PortB <= Data_in;
+ WHEN OTHERS => null;
+ END CASE;
+ END IF;
+ END IF;
+ END IF;
+ CASE Data_in(3 downto 0) IS
+ WHEN "1111" => n_Pegel <= X"2AA"; -- Umsetzung in logarithmische Werte in ca. 3dB Schritten
+ WHEN "1110" => n_Pegel <= X"1E2"; -- für Kanäle
+ WHEN "1101" => n_Pegel <= X"155";
+ WHEN "1100" => n_Pegel <= X"0F1";
+ WHEN "1011" => n_Pegel <= X"0AA";
+ WHEN "1010" => n_Pegel <= X"078";
+ WHEN "1001" => n_Pegel <= X"055";
+ WHEN "1000" => n_Pegel <= X"03C";
+ WHEN "0111" => n_Pegel <= X"02A";
+ WHEN "0110" => n_Pegel <= X"01E";
+ WHEN "0101" => n_Pegel <= X"015";
+ WHEN "0100" => n_Pegel <= X"00F";
+ WHEN "0011" => n_Pegel <= X"00A";
+ WHEN "0010" => n_Pegel <= X"007";
+ WHEN "0001" => n_Pegel <= X"005";
+ WHEN "0000" => n_Pegel <= X"000";
+ WHEN OTHERS => null;
+ END CASE;
+-- read reg
+
+ IF bc0='1' AND bdir='0' THEN
+ Data_out <= t_Data;
+ ELSE
+ Data_out <= "11111111";
+ END IF;
+
+ t_Data <= "00000000";
+ CASE PSGReg IS
+ WHEN "0000" =>
+ t_Data <= Aperiode(7 downto 0);
+ WHEN "0001" =>
+ t_Data(3 downto 0) <= Aperiode(11 downto 8);
+ WHEN "0010" =>
+ t_Data <= Bperiode(7 downto 0);
+ WHEN "0011" =>
+ t_Data(3 downto 0) <= Bperiode(11 downto 8);
+ WHEN "0100" =>
+ t_Data <= Cperiode(7 downto 0);
+ WHEN "0101" =>
+ t_Data(3 downto 0) <= Cperiode(11 downto 8);
+ WHEN "0110" =>
+ t_Data(4 downto 0) <= Noise;
+ WHEN "0111" =>
+ t_Data <= enable XOR "00111111";
+ WHEN "1000" =>
+ t_Data(4 downto 0) <= AVol;
+ WHEN "1001" =>
+ t_Data(4 downto 0) <= BVol;
+ WHEN "1010" =>
+ t_Data(4 downto 0) <= CVol;
+ WHEN "1011" =>
+ t_Data <= Hperiode(7 downto 0);
+ WHEN "1100" =>
+ t_Data <= Hperiode(15 downto 8);
+ WHEN "1101" =>
+ t_Data(3 downto 0) <= HKurve;
+ WHEN "1110" =>
+ t_Data <= PortA;
+ WHEN "1111" =>
+ t_Data <= PortB;
+ END CASE;
+END process;
+-------------------------------------------------------------------------
+--Soundgen
+-------------------------------------------------------------------------
+process (cpuclk, reset, AVol, BVol, CVol, HVol, nHVol, AVollog, BVollog, CVollog, HVollog, HKurve)
+begin
+-- channel A
+ IF AVol(4)='1' THEN
+ Alog <= HVollog(9 downto 0);
+ ELSE
+ Alog <= AVollog;
+ END IF;
+ IF rising_edge(cpuclk) THEN
+ IF ((enable(3) AND Noisebit) XOR Anot)='1' THEN
+ chanA <= ('0'&Alog);
+ ELSE
+ chanA <= (others => '0');
+ END IF;
+ IF enable(0)='0' OR APeriode="000000000000" THEN
+ Anot <= '1';
+ ACount <= "000000000000";
+ ELSIF S_Tick='1' THEN
+ IF ACount(11 downto 0)>=APeriode THEN
+ ACount <= "000000000001";
+ Anot <= NOT Anot;
+ ELSE
+ ACount <= ACount+1;
+ END IF;
+ END IF;
+ END IF;
+
+-- channel B
+ IF BVol(4)='1' THEN
+ Blog <= HVollog(9 downto 0);
+ ELSE
+ Blog <= BVollog;
+ END IF;
+ IF rising_edge(cpuclk) THEN
+ IF ((enable(4) AND Noisebit) XOR Bnot)='1' THEN
+ chanB <= ('0'&Blog);
+ ELSE
+ chanB <= (others => '0');
+ END IF;
+ IF enable(1)='0' OR BPeriode="000000000000" THEN
+ Bnot <= '1';
+ BCount <= "000000000000";
+ ELSIF S_Tick='1' THEN
+ IF BCount(11 downto 0)>=BPeriode THEN
+ BCount <= "000000000001";
+ Bnot <= NOT Bnot;
+ ELSE
+ BCount <= BCount+1;
+ END IF;
+ END IF;
+ END IF;
+
+-- channel C
+ IF CVol(4)='1' THEN
+ Clog <= HVollog(9 downto 0);
+ ELSE
+ Clog <= CVollog;
+ END IF;
+ IF rising_edge(cpuclk) THEN
+ IF ((enable(5) AND Noisebit) XOR Cnot)='1' THEN
+ chanC <= ('0'&Clog);
+ ELSE
+ chanC <= (others => '0');
+ END IF;
+ IF enable(2)='0' OR CPeriode="000000000000" THEN
+ Cnot <= '1';
+ CCount <= "000000000000";
+ ELSIF S_Tick='1' THEN
+ IF CCount(11 downto 0)>=CPeriode THEN
+ CCount <= "000000000001";
+ Cnot <= NOT Cnot;
+ ELSE
+ CCount <= CCount+1;
+ END IF;
+ END IF;
+ END IF;
+
+--noise
+--Noise="00000" and Noise="00001" is the same
+ IF rising_edge(cpuclk) THEN
+ IF S_Tick='1' THEN
+ IF NCount(4 downto 1)="0000" THEN
+ NCount <= Noise ;
+ RNG <= (NOT (RNG(0) XOR RNG(2))& RNG(16 downto 1));
+ Noisebit <= RNG(0);
+ ELSE
+ NCount <= NCount-1;
+ END IF;
+ END IF;
+ END IF;
+
+-- Huellkurve
+ nHVol <= HVol(3 downto 0);
+ IF ((HKurve(3) OR NOT HVol(4)) AND ( NOT HKurve(2) XOR ((HKurve(1) XOR HKurve(0)) AND HVol(4))))='1' THEN
+ nHVol <= HVol(3 downto 0) XOR "1111";
+ END IF;
+
+ IF rising_edge(cpuclk) THEN
+ IF HStart='1' THEN
+ HCount <= "0000000000000001";
+ HVol <= "00000";
+ ELSIF H_Tick='1' THEN
+ IF HCount>=HPeriode THEN
+ HCount <= "0000000000000001";
+ IF (NOT HVol(4) OR (NOT HKurve(0) AND HKurve(3)))='1' AND (HPeriode /= 0) THEN --HOLD
+-- IF (NOT HVol(4) OR (NOT HKurve(0) AND HKurve(3)))='1' THEN --HOLD
+ HVol <= HVol+1;
+ END IF;
+ ELSE
+ HCount <= HCount+1;
+ END IF;
+ END IF;
+ END IF;
+
+ CASE nHVol(3 downto 0) IS
+ WHEN "1111" => HVollog <= X"2AA"; -- Umsetzung in logarithmische Werte in ca. 3dB Schritten
+ WHEN "1110" => HVollog <= X"1E2"; -- für Hüllkurve
+ WHEN "1101" => HVollog <= X"155";
+ WHEN "1100" => HVollog <= X"0F1";
+ WHEN "1011" => HVollog <= X"0AA";
+ WHEN "1010" => HVollog <= X"078";
+ WHEN "1001" => HVollog <= X"055";
+ WHEN "1000" => HVollog <= X"03C";
+ WHEN "0111" => HVollog <= X"02A";
+ WHEN "0110" => HVollog <= X"01E";
+ WHEN "0101" => HVollog <= X"015";
+ WHEN "0100" => HVollog <= X"00F";
+ WHEN "0011" => HVollog <= X"00A";
+ WHEN "0010" => HVollog <= X"007";
+ WHEN "0001" => HVollog <= X"005";
+ WHEN "0000" => HVollog <= X"000";
+ WHEN OTHERS => null;
+ END CASE;
+END process;
+
+end logic;
diff --git a/common/Sound/sn76489/COPYING b/common/Sound/sn76489/COPYING
new file mode 100644
index 00000000..60549be5
--- /dev/null
+++ b/common/Sound/sn76489/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C) 19yy
+
+ 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 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ , 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/common/Sound/sn76489/README b/common/Sound/sn76489/README
new file mode 100644
index 00000000..33630144
--- /dev/null
+++ b/common/Sound/sn76489/README
@@ -0,0 +1,143 @@
+
+An SN76489AN Compatible Implementation in VHDL
+==============================================
+Version: $Date: 2006/06/18 19:28:40 $
+
+Copyright (c) 2005, 2006, Arnim Laeuger (arnim.laeuger@gmx.net)
+See the file COPYING.
+
+
+Integration
+-----------
+
+The sn76489 design exhibits all interface signals as the original chip. It
+only differs in the audio data output which is provided as an 8 bit signed
+vector instead of an analog output pin.
+
+ generic (
+ clock_div_16_g : integer := 1
+ -- Set to '1' when operating the design in SN76489 mode. The primary clock
+ -- input is divided by 16 in this variant. The data sheet mentions the
+ -- SN76494 which contains a divide-by-2 clock input stage. Set the generic
+ -- to '0' to enable this mode.
+ );
+ port (
+ clock_i : in std_logic;
+ -- Primary clock input
+ -- Drive with the target frequency or any integer multiple of it.
+
+ clock_en_i : in std_logic;
+ -- Clock enable
+ -- A '1' on this input qualifies a valid rising edge on clock_i. A '0'
+ -- disables the next rising clock edge, effectivley halting the design
+ -- until the next enabled rising clock edge.
+ -- Can be used to run the core at lower frequencies than applied on
+ -- clock_i.
+
+ res_n_i : in std_logic;
+ -- Asynchronous low active reset input.
+ -- Sets all sequential elements to a known state.
+
+ ce_n_i : in std_logic;
+ -- Chip enable, low active.
+
+ we_n_i : in std_logic;
+ -- Write enable, low active.
+
+ ready_o : out std_logic;
+ -- Ready indication to microprocessor.
+
+ d_i : in std_logic_vector(0 to 7);
+ -- Data input
+ -- MSB 0 ... 7 LSB
+
+ aout_o : out signed(0 to 7)
+ -- Audio output, signed vector
+ -- MSB/SIGN 0 ... 7 LSB
+ );
+
+
+Both 8 bit vector ports are defined (0 to 7) which declares bit 0 to be the
+MSB and bit 7 to be the LSB. This has been implemented according to TI's data
+sheet, thus all register/data format figures apply 1:1 for this design.
+Many systems will flip the system data bus bit wise before it is connected to
+this PSG. This is simply achieved with the following VHDL construct:
+
+ signal data_s : std_logic_vector(7 downto 0);
+
+ ...
+ d_i => data_s,
+ ...
+
+d_i and data_s will be assigned from left to right, resulting in the expected
+bit assignment:
+
+ d_i data_s
+ 0 7
+ 1 6
+ ...
+ 6 1
+ 7 0
+
+
+As this design is fully synchronous, care has to be taken when the design
+replaces an SN76489 in asynchronous mode. No problems are expected when
+interfacing the code to other synchronous components.
+
+
+Design Hierarchy
+----------------
+
+ sn76489_top
+ |
+ +-- sn76489_latch_ctrl
+ |
+ +-- sn76489_clock_div
+ |
+ +-- sn76489_tone
+ | |
+ | \-- sn76489_attentuator
+ |
+ +-- sn76489_tone
+ | |
+ | \-- sn76489_attentuator
+ |
+ +-- sn76489_tone
+ | |
+ | \-- sn76489_attentuator
+ |
+ \-- sn76489_noise
+ |
+ \-- sn76489_attentuator
+
+Resulting compilation sequence:
+
+ sn76489_comp_pack-p.vhd
+ sn76489_top.vhd
+ sn76489_latch_ctrl.vhd
+ sn76489_latch_ctrl-c.vhd
+ sn76489_clock_div.vhd
+ sn76489_clock_div-c.vhd
+ sn76489_attenuator.vhd
+ sn76489_attenuator-c.vhd
+ sn76489_tone.vhd
+ sn76489_tone-c.vhd
+ sn76489_noise.vhd
+ sn76489_noise-c.vhd
+ sn76489_top-c.vhd
+
+Skip the files containing VHDL configurations when analyzing the code for
+synthesis.
+
+
+References
+----------
+
+* TI Data sheet SN76489.pdf
+ ftp://ftp.whtech.com/datasheets%20&%20manuals/SN76489.pdf
+
+* John Kortink's article on the SN76489:
+ http://web.inter.nl.net/users/J.Kortink/home/articles/sn76489/
+
+* Maxim's "SN76489 notes" in
+ http://www.smspower.org/maxim/docs/SN76489.txt
diff --git a/common/Sound/sn76489/sn76489_attenuator.vhd b/common/Sound/sn76489/sn76489_attenuator.vhd
new file mode 100644
index 00000000..444064e5
--- /dev/null
+++ b/common/Sound/sn76489/sn76489_attenuator.vhd
@@ -0,0 +1,114 @@
+-------------------------------------------------------------------------------
+--
+-- Synthesizable model of TI's SN76489AN.
+--
+-- $Id: sn76489_attenuator.vhd,v 1.7 2006/02/27 20:30:10 arnim Exp $
+--
+-- Attenuator Module
+--
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2005, 2006, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity sn76489_attenuator is
+
+ port (
+ attenuation_i : in std_logic_vector(0 to 3);
+ factor_i : in signed(0 to 1);
+ product_o : out signed(0 to 7)
+ );
+
+end sn76489_attenuator;
+
+
+architecture rtl of sn76489_attenuator is
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process attenuate
+ --
+ -- Purpose:
+ -- Determine the attenuation and generate the resulting product.
+ --
+ -- The maximum attenuation value is 31 which corresponds to volume off.
+ -- As described in the data sheet, the maximum "playing" attenuation is
+ -- 28 = 16 + 8 + 4
+ --
+ -- The table for the volume constants is derived from the following
+ -- formula (each step is 2dB voltage):
+ -- v(0) = 31
+ -- v(n+1) = v(n) * 0.79432823
+ --
+ attenuate: process (attenuation_i,
+ factor_i)
+
+ type volume_t is array (natural range 0 to 15) of natural;
+ constant volume_c : volume_t :=
+ (31, 25, 20, 16, 12, 10, 8, 6, 5, 4, 3, 2, 2, 2, 1, 0);
+
+ variable attenuation_v : unsigned(attenuation_i'range);
+ variable volume_v : signed(product_o'range);
+
+ begin
+
+ attenuation_v := unsigned(attenuation_i);
+
+ -- volume look-up table
+ volume_v := to_signed(volume_c(to_integer(attenuation_v)),
+ product_o'length);
+
+ -- this replaces a multiplier and consumes a bit fewer
+ -- resources
+ case to_integer(factor_i) is
+ when +1 =>
+ product_o <= volume_v;
+ when -1 =>
+ product_o <= -volume_v;
+ when others =>
+ product_o <= (others => '0');
+ end case;
+
+ end process attenuate;
+ --
+ -----------------------------------------------------------------------------
+
+end rtl;
diff --git a/common/Sound/sn76489/sn76489_clock_div.vhd b/common/Sound/sn76489/sn76489_clock_div.vhd
new file mode 100644
index 00000000..eab86beb
--- /dev/null
+++ b/common/Sound/sn76489/sn76489_clock_div.vhd
@@ -0,0 +1,134 @@
+-------------------------------------------------------------------------------
+--
+-- Synthesizable model of TI's SN76489AN.
+--
+-- $Id: sn76489_clock_div.vhd,v 1.4 2005/10/10 21:51:27 arnim Exp $
+--
+-- Clock Divider Circuit
+--
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2005, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity sn76489_clock_div is
+
+ generic (
+ clock_div_16_g : integer := 1
+ );
+ port (
+ clock_i : in std_logic;
+ clock_en_i : in std_logic;
+ res_n_i : in std_logic;
+ clk_en_o : out boolean
+ );
+
+end sn76489_clock_div;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+architecture rtl of sn76489_clock_div is
+
+ signal cnt_s,
+ cnt_q : unsigned(3 downto 0);
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process seq
+ --
+ -- Purpose:
+ -- Implements the sequential counter element.
+ --
+ seq: process (clock_i, res_n_i)
+ begin
+ if res_n_i = '0' then
+ cnt_q <= (others => '0');
+ elsif clock_i'event and clock_i = '1' then
+ cnt_q <= cnt_s;
+ end if;
+ end process seq;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process comb
+ --
+ -- Purpose:
+ -- Implements the combinational counter logic.
+ --
+ comb: process (clock_en_i,
+ cnt_q)
+ begin
+ -- default assignments
+ cnt_s <= cnt_q;
+ clk_en_o <= false;
+
+ if clock_en_i = '1' then
+
+ if cnt_q = 0 then
+ clk_en_o <= true;
+
+ if clock_div_16_g = 1 then
+ cnt_s <= to_unsigned(15, cnt_q'length);
+ elsif clock_div_16_g = 0 then
+ cnt_s <= to_unsigned( 1, cnt_q'length);
+ else
+ -- pragma translate_off
+ assert false
+ report "Generic clock_div_16_g must be either 0 or 1."
+ severity failure;
+ -- pragma translate_on
+ end if;
+
+ else
+ cnt_s <= cnt_q - 1;
+
+ end if;
+
+ end if;
+
+ end process comb;
+ --
+ -----------------------------------------------------------------------------
+
+end rtl;
diff --git a/common/Sound/sn76489/sn76489_latch_ctrl.vhd b/common/Sound/sn76489/sn76489_latch_ctrl.vhd
new file mode 100644
index 00000000..789720c2
--- /dev/null
+++ b/common/Sound/sn76489/sn76489_latch_ctrl.vhd
@@ -0,0 +1,138 @@
+-------------------------------------------------------------------------------
+--
+-- Synthesizable model of TI's SN76489AN.
+--
+-- $Id: sn76489_latch_ctrl.vhd,v 1.6 2006/02/27 20:30:10 arnim Exp $
+--
+-- Latch Control Unit
+--
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2005, 2006, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity sn76489_latch_ctrl is
+
+ port (
+ clock_i : in std_logic;
+ clk_en_i : in boolean;
+ res_n_i : in std_logic;
+ ce_n_i : in std_logic;
+ we_n_i : in std_logic;
+ d_i : in std_logic_vector(0 to 7);
+ ready_o : out std_logic;
+ tone1_we_o : out boolean;
+ tone2_we_o : out boolean;
+ tone3_we_o : out boolean;
+ noise_we_o : out boolean;
+ r2_o : out std_logic
+ );
+
+end sn76489_latch_ctrl;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+architecture rtl of sn76489_latch_ctrl is
+
+ signal reg_q : std_logic_vector(0 to 2);
+ signal we_q : boolean;
+ signal ready_q : std_logic;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process seq
+ --
+ -- Purpose:
+ -- Implements the sequential elements.
+ --
+ seq: process (clock_i, res_n_i)
+ begin
+ if res_n_i = '0' then
+ reg_q <= (others => '0');
+ we_q <= false;
+ ready_q <= '0';
+
+ elsif clock_i'event and clock_i = '1' then
+ -- READY Flag Output ----------------------------------------------------
+ if ready_q = '0' and we_q then
+ if clk_en_i then
+ -- assert READY when write access happened
+ ready_q <= '1';
+ end if;
+ elsif ce_n_i = '1' then
+ -- deassert READY when access has finished
+ ready_q <= '0';
+ end if;
+
+ -- Register Selection ---------------------------------------------------
+ if ce_n_i = '0' and we_n_i = '0' then
+ if clk_en_i then
+ if d_i(0) = '1' then
+ reg_q <= d_i(1 to 3);
+ end if;
+ we_q <= true;
+ end if;
+ else
+ we_q <= false;
+ end if;
+
+ end if;
+ end process seq;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Output mapping
+ -----------------------------------------------------------------------------
+ tone1_we_o <= reg_q(0 to 1) = "00" and we_q;
+ tone2_we_o <= reg_q(0 to 1) = "01" and we_q;
+ tone3_we_o <= reg_q(0 to 1) = "10" and we_q;
+ noise_we_o <= reg_q(0 to 1) = "11" and we_q;
+
+ r2_o <= reg_q(2);
+
+ ready_o <= ready_q
+ when ce_n_i = '0' else
+ '1';
+
+end rtl;
diff --git a/common/Sound/sn76489/sn76489_noise.vhd b/common/Sound/sn76489/sn76489_noise.vhd
new file mode 100644
index 00000000..688bdd56
--- /dev/null
+++ b/common/Sound/sn76489/sn76489_noise.vhd
@@ -0,0 +1,278 @@
+-------------------------------------------------------------------------------
+--
+-- Synthesizable model of TI's SN76489AN.
+--
+-- $Id: sn76489_noise.vhd,v 1.6 2006/02/27 20:30:10 arnim Exp $
+--
+-- Noise Generator
+--
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2005, 2006, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity sn76489_noise is
+
+ port (
+ clock_i : in std_logic;
+ clk_en_i : in boolean;
+ res_n_i : in std_logic;
+ we_i : in boolean;
+ d_i : in std_logic_vector(0 to 7);
+ r2_i : in std_logic;
+ tone3_ff_i : in std_logic;
+ noise_o : out signed(0 to 7)
+ );
+
+end sn76489_noise;
+
+architecture rtl of sn76489_noise is
+
+ signal nf_q : std_logic_vector(0 to 1);
+ signal fb_q : std_logic;
+ signal a_q : std_logic_vector(0 to 3);
+ signal freq_cnt_q : unsigned(0 to 6);
+ signal freq_ff_q : std_logic;
+
+ signal shift_source_s,
+ shift_source_q : std_logic;
+ signal shift_rise_edge_s : boolean;
+
+ signal lfsr_q : std_logic_vector(0 to 15);
+
+ signal freq_s : signed(0 to 1);
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process cpu_regs
+ --
+ -- Purpose:
+ -- Implements the registers writable by the CPU.
+ --
+ cpu_regs: process (clock_i, res_n_i)
+ begin
+ if res_n_i = '0' then
+ nf_q <= (others => '0');
+ fb_q <= '0';
+ a_q <= (others => '1');
+
+ elsif clock_i'event and clock_i = '1' then
+ if clk_en_i and we_i then
+ if r2_i = '0' then
+ -- access to control register
+ -- both access types can write to the control register!
+ nf_q <= d_i(6 to 7);
+ fb_q <= d_i(5);
+
+ else
+ -- access to attenuator register
+ -- both access types can write to the attenuator register!
+ a_q <= d_i(4 to 7);
+
+ end if;
+ end if;
+ end if;
+ end process cpu_regs;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process freq_gen
+ --
+ -- Purpose:
+ -- Implements the frequency generation components.
+ --
+ freq_gen: process (clock_i, res_n_i)
+ begin
+ if res_n_i = '0' then
+ freq_cnt_q <= (others => '0');
+ freq_ff_q <= '0';
+
+ elsif clock_i'event and clock_i = '1' then
+ if clk_en_i then
+ if freq_cnt_q = 0 then
+ -- reload frequency counter according to NF setting
+ case nf_q is
+ when "00" =>
+ freq_cnt_q <= to_unsigned(16 * 2 - 1, freq_cnt_q'length);
+ when "01" =>
+ freq_cnt_q <= to_unsigned(16 * 4 - 1, freq_cnt_q'length);
+ when "10" =>
+ freq_cnt_q <= to_unsigned(16 * 8 - 1, freq_cnt_q'length);
+ when others =>
+ null;
+ end case;
+
+ freq_ff_q <= not freq_ff_q;
+
+ else
+ -- decrement frequency counter
+ freq_cnt_q <= freq_cnt_q - 1;
+
+ end if;
+
+ end if;
+ end if;
+ end process freq_gen;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Multiplex the source of the LFSR's shift enable
+ -----------------------------------------------------------------------------
+ shift_source_s <= tone3_ff_i
+ when nf_q = "11" else
+ freq_ff_q;
+
+ -----------------------------------------------------------------------------
+ -- Process rise_edge
+ --
+ -- Purpose:
+ -- Detect the rising edge of the selected LFSR shift source.
+ --
+ rise_edge: process (clock_i, res_n_i)
+ begin
+ if res_n_i = '0' then
+ shift_source_q <= '0';
+
+ elsif clock_i'event and clock_i = '1' then
+ if clk_en_i then
+ shift_source_q <= shift_source_s;
+ end if;
+ end if;
+ end process rise_edge;
+ --
+ -----------------------------------------------------------------------------
+
+ -- detect rising edge on shift source
+ shift_rise_edge_s <= shift_source_q = '0' and shift_source_s = '1';
+
+
+ -----------------------------------------------------------------------------
+ -- Process lfsr
+ --
+ -- Purpose:
+ -- Implements the LFSR that generates noise.
+ -- Note: This implementation shifts the register right, i.e. from index
+ -- 15 towards 0 => bit 15 is the input, bit 0 is the output
+ --
+ -- Tapped bits according to MAME's sn76496.c, implemented in function
+ -- lfsr_tapped_f.
+ --
+ lfsr: process (clock_i, res_n_i)
+
+ function lfsr_tapped_f(lfsr : in std_logic_vector) return std_logic is
+ constant tapped_bits_c : std_logic_vector(0 to 15)
+ -- tapped bits are 0, 2, 15
+ := "1010000000000001";
+ variable parity_v : std_logic;
+ begin
+ parity_v := '0';
+
+ for idx in lfsr'low to lfsr'high loop
+ parity_v := parity_v xor (lfsr(idx) and tapped_bits_c(idx));
+ end loop;
+
+ return parity_v;
+ end;
+
+ begin
+ if res_n_i = '0' then
+ -- reset LFSR to "0000000000000001"
+ lfsr_q <= (others => '0');
+ lfsr_q(lfsr_q'right) <= '1';
+
+ elsif clock_i'event and clock_i = '1' then
+ if clk_en_i then
+ if we_i and r2_i = '0' then
+ -- write to noise register
+ -- -> reset LFSR
+ lfsr_q <= (others => '0');
+ lfsr_q(lfsr_q'right) <= '1';
+
+ elsif shift_rise_edge_s then
+
+ -- shift LFSR left towards MSB
+ for idx in lfsr_q'right-1 downto lfsr_q'left loop
+ lfsr_q(idx) <= lfsr_q(idx+1);
+ end loop;
+
+ -- determine input bit
+ if fb_q = '0' then
+ -- "Periodic" Noise
+ -- -> input to LFSR is output
+ lfsr_q(lfsr_q'right) <= lfsr_q(lfsr_q'left);
+ else
+ -- "White" Noise
+ -- -> input to LFSR is parity of tapped bits
+ lfsr_q(lfsr_q'right) <= lfsr_tapped_f(lfsr_q);
+ end if;
+
+ end if;
+
+ end if;
+ end if;
+ end process lfsr;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Map output of LFSR to signed value for attenuator.
+ -----------------------------------------------------------------------------
+ freq_s <= to_signed(+1, 2)
+ when lfsr_q(0) = '1' else
+ to_signed( 0, 2);
+
+
+ -----------------------------------------------------------------------------
+ -- The attenuator itself
+ -----------------------------------------------------------------------------
+ attenuator_b : entity work.sn76489_attenuator
+ port map (
+ attenuation_i => a_q,
+ factor_i => freq_s,
+ product_o => noise_o
+ );
+
+end rtl;
diff --git a/common/Sound/sn76489/sn76489_tone.vhd b/common/Sound/sn76489/sn76489_tone.vhd
new file mode 100644
index 00000000..3658efcc
--- /dev/null
+++ b/common/Sound/sn76489/sn76489_tone.vhd
@@ -0,0 +1,188 @@
+-------------------------------------------------------------------------------
+--
+-- Synthesizable model of TI's SN76489AN.
+--
+-- $Id: sn76489_tone.vhd,v 1.5 2006/02/27 20:30:10 arnim Exp $
+--
+-- Tone Generator
+--
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2005, 2006, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity sn76489_tone is
+
+ port (
+ clock_i : in std_logic;
+ clk_en_i : in boolean;
+ res_n_i : in std_logic;
+ we_i : in boolean;
+ d_i : in std_logic_vector(0 to 7);
+ r2_i : in std_logic;
+ ff_o : out std_logic;
+ tone_o : out signed(0 to 7)
+ );
+
+end sn76489_tone;
+
+architecture rtl of sn76489_tone is
+
+ signal f_q : std_logic_vector(0 to 9);
+ signal a_q : std_logic_vector(0 to 3);
+ signal freq_cnt_q : unsigned(0 to 9);
+ signal freq_ff_q : std_logic;
+
+ signal freq_s : signed(0 to 1);
+
+ function all_zero(a : in std_logic_vector) return boolean is
+ variable result_v : boolean;
+ begin
+ result_v := true;
+
+ for idx in a'low to a'high loop
+ if a(idx) /= '0' then
+ result_v := false;
+ end if;
+ end loop;
+
+ return result_v;
+ end;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process cpu_regs
+ --
+ -- Purpose:
+ -- Implements the registers writable by the CPU.
+ --
+ cpu_regs: process (clock_i, res_n_i)
+ begin
+ if res_n_i = '0' then
+ f_q <= (others => '0');
+ a_q <= (others => '1');
+
+ elsif clock_i'event and clock_i = '1' then
+ if clk_en_i and we_i then
+ if r2_i = '0' then
+ -- access to frequency register
+ if d_i(0) = '0' then
+ f_q(0 to 5) <= d_i(2 to 7);
+ else
+ f_q(6 to 9) <= d_i(4 to 7);
+ end if;
+
+ else
+ -- access to attenuator register
+ -- both access types can write to the attenuator register!
+ a_q <= d_i(4 to 7);
+
+ end if;
+ end if;
+ end if;
+ end process cpu_regs;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process freq_gen
+ --
+ -- Purpose:
+ -- Implements the frequency generation components.
+ --
+ freq_gen: process (clock_i, res_n_i)
+ begin
+ if res_n_i = '0' then
+ freq_cnt_q <= (others => '0');
+ freq_ff_q <= '0';
+
+ elsif clock_i'event and clock_i = '1' then
+ if clk_en_i then
+ if freq_cnt_q = 0 then
+ -- update counter from frequency register
+ freq_cnt_q <= unsigned(f_q);
+
+ -- and toggle the frequency flip-flop if enabled
+ if not all_zero(f_q) then
+ freq_ff_q <= not freq_ff_q;
+ else
+ -- if frequency setting is 0, then keep flip-flop at +1
+ freq_ff_q <= '1';
+ end if;
+
+ else
+ -- decrement frequency counter
+ freq_cnt_q <= freq_cnt_q - 1;
+
+ end if;
+ end if;
+ end if;
+ end process freq_gen;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Map frequency flip-flop to signed value for attenuator.
+ -----------------------------------------------------------------------------
+ freq_s <= to_signed(+1, 2)
+ when freq_ff_q = '1' else
+ to_signed(-1, 2);
+
+
+ -----------------------------------------------------------------------------
+ -- The attenuator itself
+ -----------------------------------------------------------------------------
+ attenuator_b : entity work.sn76489_attenuator
+ port map (
+ attenuation_i => a_q,
+ factor_i => freq_s,
+ product_o => tone_o
+ );
+
+
+ -----------------------------------------------------------------------------
+ -- Output mapping
+ -----------------------------------------------------------------------------
+ ff_o <= freq_ff_q;
+
+end rtl;
diff --git a/common/Sound/sn76489/sn76489_top.vhd b/common/Sound/sn76489/sn76489_top.vhd
new file mode 100644
index 00000000..c26d0e1a
--- /dev/null
+++ b/common/Sound/sn76489/sn76489_top.vhd
@@ -0,0 +1,200 @@
+-------------------------------------------------------------------------------
+--
+-- Synthesizable model of TI's SN76489AN.
+--
+-- $Id: sn76489_top.vhd,v 1.9 2006/02/27 20:30:10 arnim Exp $
+--
+-- Chip Toplevel
+--
+-- References:
+--
+-- * TI Data sheet SN76489.pdf
+-- ftp://ftp.whtech.com/datasheets%20&%20manuals/SN76489.pdf
+--
+-- * John Kortink's article on the SN76489:
+-- http://web.inter.nl.net/users/J.Kortink/home/articles/sn76489/
+--
+-- * Maxim's "SN76489 notes" in
+-- http://www.smspower.org/maxim/docs/SN76489.txt
+--
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2005, 2006, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library ieee;
+use ieee.numeric_std.all;
+
+entity sn76489_top is
+
+ generic (
+ clock_div_16_g : integer := 1
+ );
+ port (
+ clock_i : in std_logic;
+ clock_en_i : in std_logic;
+ res_n_i : in std_logic;
+ ce_n_i : in std_logic;
+ we_n_i : in std_logic;
+ ready_o : out std_logic;
+ d_i : in std_logic_vector(0 to 7);
+ aout_o : out signed(0 to 7)
+ );
+
+end sn76489_top;
+
+architecture struct of sn76489_top is
+
+ signal clk_en_s : boolean;
+
+ signal tone1_we_s,
+ tone2_we_s,
+ tone3_we_s,
+ noise_we_s : boolean;
+ signal r2_s : std_logic;
+
+ signal tone1_s,
+ tone2_s,
+ tone3_s,
+ noise_s : signed(0 to 7);
+
+ signal tone3_ff_s : std_logic;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Clock Divider
+ -----------------------------------------------------------------------------
+ clock_div_b : entity work.sn76489_clock_div
+ generic map (
+ clock_div_16_g => clock_div_16_g
+ )
+ port map (
+ clock_i => clock_i,
+ clock_en_i => clock_en_i,
+ res_n_i => res_n_i,
+ clk_en_o => clk_en_s
+ );
+
+
+ -----------------------------------------------------------------------------
+ -- Latch Control = CPU Interface
+ -----------------------------------------------------------------------------
+ latch_ctrl_b : entity work.sn76489_latch_ctrl
+ port map (
+ clock_i => clock_i,
+ clk_en_i => clk_en_s,
+ res_n_i => res_n_i,
+ ce_n_i => ce_n_i,
+ we_n_i => we_n_i,
+ d_i => d_i,
+ ready_o => ready_o,
+ tone1_we_o => tone1_we_s,
+ tone2_we_o => tone2_we_s,
+ tone3_we_o => tone3_we_s,
+ noise_we_o => noise_we_s,
+ r2_o => r2_s
+ );
+
+
+ -----------------------------------------------------------------------------
+ -- Tone Channel 1
+ -----------------------------------------------------------------------------
+ tone1_b : entity work.sn76489_tone
+ port map (
+ clock_i => clock_i,
+ clk_en_i => clk_en_s,
+ res_n_i => res_n_i,
+ we_i => tone1_we_s,
+ d_i => d_i,
+ r2_i => r2_s,
+ ff_o => open,
+ tone_o => tone1_s
+ );
+
+ -----------------------------------------------------------------------------
+ -- Tone Channel 2
+ -----------------------------------------------------------------------------
+ tone2_b : entity work.sn76489_tone
+ port map (
+ clock_i => clock_i,
+ clk_en_i => clk_en_s,
+ res_n_i => res_n_i,
+ we_i => tone2_we_s,
+ d_i => d_i,
+ r2_i => r2_s,
+ ff_o => open,
+ tone_o => tone2_s
+ );
+
+ -----------------------------------------------------------------------------
+ -- Tone Channel 3
+ -----------------------------------------------------------------------------
+ tone3_b : entity work.sn76489_tone
+ port map (
+ clock_i => clock_i,
+ clk_en_i => clk_en_s,
+ res_n_i => res_n_i,
+ we_i => tone3_we_s,
+ d_i => d_i,
+ r2_i => r2_s,
+ ff_o => tone3_ff_s,
+ tone_o => tone3_s
+ );
+
+ -----------------------------------------------------------------------------
+ -- Noise Channel
+ -----------------------------------------------------------------------------
+ noise_b : entity work.sn76489_noise
+ port map (
+ clock_i => clock_i,
+ clk_en_i => clk_en_s,
+ res_n_i => res_n_i,
+ we_i => noise_we_s,
+ d_i => d_i,
+ r2_i => r2_s,
+ tone3_ff_i => tone3_ff_s,
+ noise_o => noise_s
+ );
+
+
+ aout_o <= tone1_s + tone2_s + tone3_s + noise_s;
+
+end struct;
diff --git a/common/TTL/CPLD_74LS245.vhd b/common/TTL/CPLD_74LS245.vhd
new file mode 100644
index 00000000..01dd9083
--- /dev/null
+++ b/common/TTL/CPLD_74LS245.vhd
@@ -0,0 +1,26 @@
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.STD_LOGIC_ARITH.ALL;
+use IEEE.STD_LOGIC_UNSIGNED.ALL;
+
+entity CPLD_74LS245 is
+ Port ( nE : in STD_LOGIC;
+ dir : in STD_LOGIC;
+ Bin : in STD_LOGIC_VECTOR (7 downto 0);
+ Ain : in STD_LOGIC_VECTOR (7 downto 0);
+ Bout :out STD_LOGIC_VECTOR (7 downto 0);
+ Aout : out STD_LOGIC_VECTOR (7 downto 0));
+end CPLD_74LS245;
+
+architecture Behavioral of CPLD_74LS245 is
+begin
+
+ -- if nE = 1 or dir = '1' then HighZ
+ -- else B
+ Aout <= (7 downto 0 => 'Z') when nE = '1' OR dir = '1' else Bin;
+
+ -- if nE = 1 or dir = '1' then HighZ
+ -- wlse A
+ Bout <= (7 downto 0 => 'Z') when nE = '1' OR dir = '0' else Ain;
+
+end Behavioral;
\ No newline at end of file
diff --git a/common/TTL/TTL74LS138.vhd b/common/TTL/TTL74LS138.vhd
new file mode 100644
index 00000000..b74b90f1
Binary files /dev/null and b/common/TTL/TTL74LS138.vhd differ
diff --git a/common/TTL/TTL74LS139.vhd b/common/TTL/TTL74LS139.vhd
new file mode 100644
index 00000000..1a0ff8a9
--- /dev/null
+++ b/common/TTL/TTL74LS139.vhd
@@ -0,0 +1,33 @@
+library ieee;
+ use ieee.std_logic_1164.all;
+ use ieee.numeric_std.all;
+
+-------------------------------------------------------------------------------
+-- 74xx139
+-- 2-to-4 line decoder
+-------------------------------------------------------------------------------
+entity LOGIC_74XX139 is
+ port (
+ I_G : in std_logic;
+ I_Sel : in std_logic_vector(1 downto 0);
+ O_Q : out std_logic_vector(3 downto 0)
+ );
+end;
+
+architecture RTL of LOGIC_74XX139 is
+begin
+ xx139 : process (I_G, I_Sel)
+ begin
+ if I_G = '0' then
+ case I_Sel is
+ when "00" => O_Q <= "1110";
+ when "01" => O_Q <= "1101";
+ when "10" => O_Q <= "1011";
+ when "11" => O_Q <= "0111";
+ when others => null;
+ end case;
+ else
+ O_Q <= "1111";
+ end if;
+ end process;
+end RTL;
\ No newline at end of file
diff --git a/common/TTL/TTL74LS245.sv b/common/TTL/TTL74LS245.sv
new file mode 100644
index 00000000..8a026487
--- /dev/null
+++ b/common/TTL/TTL74LS245.sv
@@ -0,0 +1,16 @@
+module TTL74LS245 (
+ input OE,
+ input DIR,
+ input [7:0] Ain,
+ output [7:0]Aout,
+ input [7:0] Bin,
+ output [7:0]Bout
+ );
+
+always @ (OE, DIR, Ain,Bin) begin
+ if (OE== 1'b0 & DIR == 1'b1)
+ Bout = Ain;
+ else if (OE== 1'b0 & DIR == 1'b0)
+ Aout = Bin;
+end
+endmodule
\ No newline at end of file
diff --git a/common/TTL/TTL74LS373.sv b/common/TTL/TTL74LS373.sv
new file mode 100644
index 00000000..fef4e1a8
--- /dev/null
+++ b/common/TTL/TTL74LS373.sv
@@ -0,0 +1,84 @@
+module TTL74LS373 (
+input LE,
+input [8:1] D,
+input OE_n,
+output [8:1] Q
+);
+
+reg SYNTHESIZED_WIRE_0;
+reg SYNTHESIZED_WIRE_2;
+reg SYNTHESIZED_WIRE_4;
+reg SYNTHESIZED_WIRE_6;
+reg SYNTHESIZED_WIRE_8;
+reg SYNTHESIZED_WIRE_10;
+reg SYNTHESIZED_WIRE_12;
+reg SYNTHESIZED_WIRE_14;
+
+
+
+always@(LE or D[1])
+begin
+if (LE)
+ SYNTHESIZED_WIRE_0 <= D[1];
+end
+
+
+always@(LE or D[2])
+begin
+if (LE)
+ SYNTHESIZED_WIRE_2 <= D[2];
+end
+
+
+always@(LE or D[3])
+begin
+if (LE)
+ SYNTHESIZED_WIRE_4 <= D[3];
+end
+
+
+always@(LE or D[4])
+begin
+if (LE)
+ SYNTHESIZED_WIRE_6 <= D[4];
+end
+
+
+always@(LE or D[5])
+begin
+if (LE)
+ SYNTHESIZED_WIRE_8 <= D[5];
+end
+
+
+always@(LE or D[6])
+begin
+if (LE)
+ SYNTHESIZED_WIRE_10 <= D[6];
+end
+
+
+always@(LE or D[7])
+begin
+if (LE)
+ SYNTHESIZED_WIRE_12 <= D[7];
+end
+
+
+always@(LE or D[8])
+begin
+if (LE)
+ SYNTHESIZED_WIRE_14 <= D[8];
+end
+
+assign Q[1] = OE_n ? SYNTHESIZED_WIRE_0 : 1'bz;
+assign Q[2] = OE_n ? SYNTHESIZED_WIRE_2 : 1'bz;
+assign Q[3] = OE_n ? SYNTHESIZED_WIRE_4 : 1'bz;
+assign Q[4] = OE_n ? SYNTHESIZED_WIRE_6 : 1'bz;
+assign Q[5] = OE_n ? SYNTHESIZED_WIRE_8 : 1'bz;
+assign Q[6] = OE_n ? SYNTHESIZED_WIRE_10 : 1'bz;
+assign Q[7] = OE_n ? SYNTHESIZED_WIRE_12 : 1'bz;
+assign Q[8] = OE_n ? SYNTHESIZED_WIRE_14 : 1'bz;
+
+
+endmodule
diff --git a/common/TTL/ls00.v b/common/TTL/ls00.v
new file mode 100644
index 00000000..69f08363
--- /dev/null
+++ b/common/TTL/ls00.v
@@ -0,0 +1,39 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer: Paul Wightmore
+//
+// Create Date: 20:13:54 04/24/2018
+// Design Name: LS00
+// Module Name: system86/ttl/ls00.v
+// Project Name: Namco System86 simulation
+// Target Devices:
+// Tool versions:
+// Description: LS00 - Quadruple 2-Input Positive-NAND Gates
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+// License: https://www.apache.org/licenses/LICENSE-2.0
+//
+//////////////////////////////////////////////////////////////////////////////////
+module LS00(
+ input wire A1,
+ input wire B1,
+ input wire A2,
+ input wire B2,
+ input wire A3,
+ input wire B3,
+ input wire A4,
+ input wire B4,
+ output wire Y1,
+ output wire Y2,
+ output wire Y3,
+ output wire Y4
+ );
+
+ nand ls00[0:3] ( {Y4, Y3, Y2, Y1}, {A4, A3, A2, A1}, {B4, B3, B2, B1} );
+
+endmodule
diff --git a/common/TTL/ls00.vhd b/common/TTL/ls00.vhd
new file mode 100644
index 00000000..60d8ff0b
--- /dev/null
+++ b/common/TTL/ls00.vhd
@@ -0,0 +1,63 @@
+--============================================================================
+--
+-- VHDL implementation of the 74LS00 quad NAND gate
+-- Copyright (C) 2018, 2019 Ace
+--
+-- Permission is hereby granted, free of charge, to any person obtaining a
+-- copy of this software and associated documentation files (the "Software"),
+-- to deal in the Software without restriction, including without limitation
+-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
+-- and/or sell copies of the Software, and to permit persons to whom the
+-- Software is furnished to do so, subject to the following conditions:
+--
+-- The above copyright notice and this permission notice shall be included in
+-- all copies or substantial portions of the Software.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+-- DEALINGS IN THE SOFTWARE.
+--
+--============================================================================
+
+--Chip pinout:
+/* _____________
+ _| |_
+a1 |_|1 14|_| VCC
+ _| |_
+b1 |_|2 13|_| a4
+ _| |_
+y1 |_|3 12|_| b4
+ _| |_
+a2 |_|4 11|_| y4
+ _| |_
+b2 |_|5 10|_| a3
+ _| |_
+y2 |_|6 9|_| b3
+ _| |_
+GND |_|7 8|_| y3
+ |_____________|
+*/
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+
+entity ls00 is
+port
+(
+ a1, a2, a3, a4 : in std_logic;
+ b1, b2, b3, b4 : in std_logic;
+ y1, y2, y3, y4 : out std_logic
+);
+end ls00;
+
+architecture arch of ls00 is
+begin
+ y1 <= a1 nand b1;
+ y2 <= a2 nand b2;
+ y3 <= a3 nand b3;
+ y4 <= a4 nand b4;
+end arch;
\ No newline at end of file
diff --git a/common/TTL/ls02.v b/common/TTL/ls02.v
new file mode 100644
index 00000000..0c734506
--- /dev/null
+++ b/common/TTL/ls02.v
@@ -0,0 +1,39 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer: Paul Wightmore
+//
+// Create Date: 19:39:10 05/10/2018
+// Design Name: LS02
+// Module Name: system86/ttl/ls02
+// Project Name: Namco System86 simulation
+// Target Devices:
+// Tool versions:
+// Description: LS02 - Quadruple 2-Input Positive-NOR Gates
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+// License: https://www.apache.org/licenses/LICENSE-2.0
+//
+//////////////////////////////////////////////////////////////////////////////////
+module LS02(
+ input wire A1,
+ input wire B1,
+ input wire A2,
+ input wire B2,
+ input wire A3,
+ input wire B3,
+ input wire A4,
+ input wire B4,
+ output wire Y1,
+ output wire Y2,
+ output wire Y3,
+ output wire Y4
+ );
+
+ nor ls02[0:3] ( {Y4, Y3, Y2, Y1}, {A4, A3, A2, A1}, {B4, B3, B2, B1} );
+
+endmodule
diff --git a/common/TTL/ls04.vhd b/common/TTL/ls04.vhd
new file mode 100644
index 00000000..9ee0d155
--- /dev/null
+++ b/common/TTL/ls04.vhd
@@ -0,0 +1,64 @@
+--============================================================================
+--
+-- VHDL implementation of the 74LS04 hex inverter
+-- Copyright (C) 2018, 2019 Ace
+--
+-- Permission is hereby granted, free of charge, to any person obtaining a
+-- copy of this software and associated documentation files (the "Software"),
+-- to deal in the Software without restriction, including without limitation
+-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
+-- and/or sell copies of the Software, and to permit persons to whom the
+-- Software is furnished to do so, subject to the following conditions:
+--
+-- The above copyright notice and this permission notice shall be included in
+-- all copies or substantial portions of the Software.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+-- DEALINGS IN THE SOFTWARE.
+--
+--============================================================================
+
+--Chip pinout:
+/* _____________
+ _| |_
+a1 |_|1 14|_| VCC
+ _| |_
+y1 |_|2 13|_| a6
+ _| |_
+a2 |_|3 12|_| y6
+ _| |_
+y2 |_|4 11|_| a5
+ _| |_
+a3 |_|5 10|_| y5
+ _| |_
+y3 |_|6 9|_| a4
+ _| |_
+GND |_|7 8|_| y4
+ |_____________|
+*/
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+
+entity ls04 is
+port
+(
+ a1, a2, a3, a4, a5, a6 : in std_logic;
+ y1, y2, y3, y4, y5, y6 : out std_logic
+);
+end ls04;
+
+architecture arch of ls04 is
+begin
+ y1 <= not a1;
+ y2 <= not a2;
+ y3 <= not a3;
+ y4 <= not a4;
+ y5 <= not a5;
+ y6 <= not a6;
+end arch;
\ No newline at end of file
diff --git a/common/TTL/ls08.v b/common/TTL/ls08.v
new file mode 100644
index 00000000..09720737
--- /dev/null
+++ b/common/TTL/ls08.v
@@ -0,0 +1,39 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer: Paul Wightmore
+//
+// Create Date: 19:40:01 05/10/2018
+// Design Name: LS08
+// Module Name: system86/ttl/ls08.v
+// Project Name: Namco System86 simulation
+// Target Devices:
+// Tool versions:
+// Description: LS08 - Quadruple 2-Input Positive-AND Gates
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+// License: https://www.apache.org/licenses/LICENSE-2.0
+//
+//////////////////////////////////////////////////////////////////////////////////
+module LS08(
+ input wire A1,
+ input wire B1,
+ input wire A2,
+ input wire B2,
+ input wire A3,
+ input wire B3,
+ input wire A4,
+ input wire B4,
+ output wire Y1,
+ output wire Y2,
+ output wire Y3,
+ output wire Y4
+ );
+
+ and ls08[0:3] ( {Y4, Y3, Y2, Y1}, {A4, A3, A2, A1}, {B4, B3, B2, B1} );
+
+endmodule
diff --git a/common/TTL/ls08.vhd b/common/TTL/ls08.vhd
new file mode 100644
index 00000000..c8763575
--- /dev/null
+++ b/common/TTL/ls08.vhd
@@ -0,0 +1,63 @@
+--============================================================================
+--
+-- VHDL implementation of the 74LS08 quad AND gate
+-- Copyright (C) 2018, 2019 Ace
+--
+-- Permission is hereby granted, free of charge, to any person obtaining a
+-- copy of this software and associated documentation files (the "Software"),
+-- to deal in the Software without restriction, including without limitation
+-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
+-- and/or sell copies of the Software, and to permit persons to whom the
+-- Software is furnished to do so, subject to the following conditions:
+--
+-- The above copyright notice and this permission notice shall be included in
+-- all copies or substantial portions of the Software.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+-- DEALINGS IN THE SOFTWARE.
+--
+--============================================================================
+
+--Chip pinout:
+/* _____________
+ _| |_
+a1 |_|1 14|_| VCC
+ _| |_
+b1 |_|2 13|_| a4
+ _| |_
+y1 |_|3 12|_| b4
+ _| |_
+a2 |_|4 11|_| y4
+ _| |_
+b2 |_|5 10|_| a3
+ _| |_
+y2 |_|6 9|_| b3
+ _| |_
+GND |_|7 8|_| y3
+ |_____________|
+*/
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+
+entity ls08 is
+port
+(
+ a1, a2, a3, a4 : in std_logic;
+ b1, b2, b3, b4 : in std_logic;
+ y1, y2, y3, y4 : out std_logic
+);
+end ls08;
+
+architecture arch of ls08 is
+begin
+ y1 <= a1 and b1;
+ y2 <= a2 and b2;
+ y3 <= a3 and b3;
+ y4 <= a4 and b4;
+end arch;
\ No newline at end of file
diff --git a/common/TTL/ls10.v b/common/TTL/ls10.v
new file mode 100644
index 00000000..043b7634
--- /dev/null
+++ b/common/TTL/ls10.v
@@ -0,0 +1,38 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer: Paul Wightmore
+//
+// Create Date: 19:27:14 05/10/2018
+// Design Name: LS10
+// Module Name: system86/ttl/ls10
+// Project Name: Namco System86 simulation
+// Target Devices:
+// Tool versions:
+// Description: LS10 - Triple 3-Input Positive-NAND Gates
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+// License: https://www.apache.org/licenses/LICENSE-2.0
+//
+//////////////////////////////////////////////////////////////////////////////////
+module LS10(
+ input wire A1,
+ input wire B1,
+ input wire C1,
+ input wire A2,
+ input wire B2,
+ input wire C2,
+ input wire A3,
+ input wire B3,
+ input wire C3,
+ output wire Y1,
+ output wire Y2,
+ output wire Y3
+ );
+
+ nand ls10[0:2] ( {Y3, Y2, Y1}, {A3, A2, A1}, {B3, B2, B1}, {C3, C2, C1} );
+endmodule
diff --git a/common/TTL/ls139.v b/common/TTL/ls139.v
new file mode 100644
index 00000000..be16c8cd
--- /dev/null
+++ b/common/TTL/ls139.v
@@ -0,0 +1,49 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer: Paul Wightmore
+//
+// Create Date: 21:02:26 04/24/2018
+// Design Name: LS139
+// Module Name: system86\src\ttl\ls139.v
+// Project Name: Namco System86 simulation
+// Target Devices:
+// Tool versions:
+// Description: LS139 - Dual 2-Line To 4-Line Decoder/Demultiplexer
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+// License: https://www.apache.org/licenses/LICENSE-2.0
+//
+//////////////////////////////////////////////////////////////////////////////////
+module LS139(
+ input wire Ea,
+ input wire A0a,
+ input wire A1a,
+ input wire Eb,
+ input wire A0b,
+ input wire A1b,
+ output wire O0a,
+ output wire O1a,
+ output wire O2a,
+ output wire O3a,
+ output wire O0b,
+ output wire O1b,
+ output wire O2b,
+ output wire O3b
+ );
+
+ assign O0a = Ea & (~A0a & ~A1a);
+ assign O1a = Ea & (A0a & ~A1a);
+ assign O2a = Ea & (~A0a & A1a);
+ assign O3a = Ea & (A0a & A1a);
+
+ assign O0b = Eb & (~A0b & ~A1b);
+ assign O1b = Eb & (A0b & ~A1b);
+ assign O2b = Eb & (~A0b & A1b);
+ assign O3b = Eb & (A0b & A1b);
+
+endmodule
diff --git a/common/TTL/ls139.vhd b/common/TTL/ls139.vhd
new file mode 100644
index 00000000..54b64b53
--- /dev/null
+++ b/common/TTL/ls139.vhd
@@ -0,0 +1,73 @@
+--============================================================================
+--
+-- VHDL implementation of the 74LS139 dual 2-to-4 address decoder
+-- Copyright (C) 2018, 2019 Ace
+--
+-- Permission is hereby granted, free of charge, to any person obtaining a
+-- copy of this software and associated documentation files (the "Software"),
+-- to deal in the Software without restriction, including without limitation
+-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
+-- and/or sell copies of the Software, and to permit persons to whom the
+-- Software is furnished to do so, subject to the following conditions:
+--
+-- The above copyright notice and this permission notice shall be included in
+-- all copies or substantial portions of the Software.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+-- DEALINGS IN THE SOFTWARE.
+--
+--============================================================================
+
+--Chip pinout:
+/* _____________
+ _| |_
+n_e(0) |_|1 16|_| VCC
+ _| |_
+a0(0) |_|2 15|_| n_e(1)
+ _| |_
+a1(0) |_|3 14|_| a0(1)
+ _| |_
+o0(0) |_|4 13|_| a1(1)
+ _| |_
+o0(1) |_|5 12|_| o1(0)
+ _| |_
+o0(2) |_|6 11|_| o1(1)
+ _| |_
+o0(3) |_|7 10|_| o1(2)
+ _| |_
+GND |_|8 9|_| o1(3)
+ |_____________|
+*/
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+
+entity ls139 is
+port
+(
+ a0 : in std_logic_vector(1 downto 0);
+ a1 : in std_logic_vector(1 downto 0);
+ n_e : in std_logic_vector(1 downto 0);
+ o0 : out std_logic_vector(3 downto 0);
+ o1 : out std_logic_vector(3 downto 0)
+);
+end ls139;
+
+architecture arch of ls139 is
+begin
+ o0 <= "1110" when (not n_e(0) and not a0(0) and not a1(0))
+ else "1101" when (not n_e(0) and a0(0) and not a1(0))
+ else "1011" when (not n_e(0) and not a0(0) and a1(0))
+ else "0111" when (not n_e(0) and a0(0) and a1(0))
+ else "1111";
+ o1 <= "1110" when (not n_e(1) and not a0(1) and not a1(1))
+ else "1101" when (not n_e(1) and a0(1) and not a1(1))
+ else "1011" when (not n_e(1) and not a0(1) and a1(1))
+ else "0111" when (not n_e(1) and a0(1) and a1(1))
+ else "1111";
+end arch;
\ No newline at end of file
diff --git a/common/TTL/ls139_tb.v b/common/TTL/ls139_tb.v
new file mode 100644
index 00000000..560c8cef
--- /dev/null
+++ b/common/TTL/ls139_tb.v
@@ -0,0 +1,111 @@
+`timescale 1ns / 1ps
+
+////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer: Paul Wightmore
+//
+// Create Date: 21:05:44 04/24/2018
+// Design Name: LS139
+// Module Name: system86/src/ttl/ls139_tb.v
+// Project Name: Namco System86 simulation
+//// Target Device:
+// Tool versions:
+// Description: LS139 - Dual 2-Line To 4-Line Decoder/Demultiplexer - test bench
+//
+// Verilog Test Fixture created by ISE for module: LS139
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+// License: https://www.apache.org/licenses/LICENSE-2.0
+//
+////////////////////////////////////////////////////////////////////////////////
+
+module LS139_tb;
+
+ // Inputs
+ reg Ea;
+ reg A0a;
+ reg A1a;
+ reg Eb;
+ reg A0b;
+ reg A1b;
+
+ // Outputs
+ wire O0a;
+ wire O1a;
+ wire O2a;
+ wire O3a;
+ wire O0b;
+ wire O1b;
+ wire O2b;
+ wire O3b;
+
+ // Instantiate the Unit Under Test (UUT)
+ LS139 uut (
+ .Ea(Ea),
+ .A0a(A0a),
+ .A1a(A1a),
+ .Eb(Eb),
+ .A0b(A0b),
+ .A1b(A1b),
+ .O0a(O0a),
+ .O1a(O1a),
+ .O2a(O2a),
+ .O3a(O3a),
+ .O0b(O0b),
+ .O1b(O1b),
+ .O2b(O2b),
+ .O3b(O3b)
+ );
+
+ integer e;
+ integer i;
+
+ initial begin
+ // Initialize Inputs
+ Ea = 0;
+ A0a = 0;
+ A1a = 0;
+ Eb = 0;
+ A0b = 0;
+ A1b = 0;
+
+ // Wait 100 ns for global reset to finish
+ #100;
+
+ // Add stimulus here
+ $display("A0\tA1\tEa\tEb\tO0a\tO1a\tO2a\tO3a\tO0b\tO1b\tO2b\tO3b");
+
+ for (e = 0; e < 4; e=e+1) begin
+ Ea = e[0];
+ Eb = e[1];
+ for (i = 0; i < 16; i=i+1) begin
+ A0a = i[0];
+ A1a = i[1];
+ A0b = i[0];
+ A1b = i[1];
+ #4
+ $display("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s",
+ i[0] ? "H" : "L",
+ i[1] ? "H" : "L",
+ Ea ? "H" : "L",
+ Eb ? "H" : "L",
+ O0a ? "H" : "L",
+ O1a ? "H" : "L",
+ O2a ? "H" : "L",
+ O3a ? "H" : "L",
+ O0b ? "H" : "L",
+ O1b ? "H" : "L",
+ O2b ? "H" : "L",
+ O3b ? "H" : "L",);
+ end
+ end
+
+ $finish;
+ end
+
+endmodule
+
diff --git a/common/TTL/ls153.v b/common/TTL/ls153.v
new file mode 100644
index 00000000..aee59d0a
--- /dev/null
+++ b/common/TTL/ls153.v
@@ -0,0 +1,41 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer: Paul Wightmore
+//
+// Create Date: 20:13:54 04/24/2018
+// Design Name: LS153
+// Module Name: system86/ttl/ls153.v
+// Project Name: Namco System86 simulation
+// Target Devices:
+// Tool versions:
+// Description: LS153 - Dual 4-Line To 1-Line Data Selectors/Multiplexers
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+// License: https://www.apache.org/licenses/LICENSE-2.0
+//
+//////////////////////////////////////////////////////////////////////////////////
+module LS153(
+ input wire S0,
+ input wire S1,
+ input wire Ea,
+ input wire I0a,
+ input wire I1a,
+ input wire I2a,
+ input wire I3a,
+ input wire Eb,
+ input wire I0b,
+ input wire I1b,
+ input wire I2b,
+ input wire I3b,
+ output wire Za,
+ output wire Zb
+ );
+
+ assign Za = Ea & ((I0a & ~S1 & ~S0) | (I1a & ~S1 & S0) | (I2a & S1 & ~S0) | (I3a & S1 & S0));
+ assign Zb = Eb & ((I0b & ~S1 & ~S0) | (I1b & ~S1 & S0) | (I2b & S1 & ~S0) | (I3b & S1 & S0));
+endmodule
diff --git a/common/TTL/ls153_tb.v b/common/TTL/ls153_tb.v
new file mode 100644
index 00000000..523bd3ca
--- /dev/null
+++ b/common/TTL/ls153_tb.v
@@ -0,0 +1,124 @@
+`timescale 1ns / 1ps
+
+////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer: Paul Wightmore
+//
+// Create Date: 20:24:08 04/24/2018
+// Design Name: LS153
+// Module Name: system86/src/ttl/ls153_tb.v
+// Project Name: Namco System86 simulation
+//// Target Device:
+// Tool versions:
+// Description: LS153 - Dual 4-Input Multiplexer - test bench
+//
+// Verilog Test Fixture created by ISE for module: LS153
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+// License: https://www.apache.org/licenses/LICENSE-2.0
+//
+////////////////////////////////////////////////////////////////////////////////
+
+module LS153_tb;
+
+ // Inputs
+ reg S0;
+ reg S1;
+ reg Ea;
+ reg I0a;
+ reg I1a;
+ reg I2a;
+ reg I3a;
+ reg Eb;
+ reg I0b;
+ reg I1b;
+ reg I2b;
+ reg I3b;
+
+ // Outputs
+ wire Za;
+ wire Zb;
+
+ // Instantiate the Unit Under Test (UUT)
+ LS153 uut (
+ .S0(S0),
+ .S1(S1),
+ .Ea(Ea),
+ .I0a(I0a),
+ .I1a(I1a),
+ .I2a(I2a),
+ .I3a(I3a),
+ .Eb(Eb),
+ .I0b(I0b),
+ .I1b(I1b),
+ .I2b(I2b),
+ .I3b(I3b),
+ .Za(Za),
+ .Zb(Zb)
+ );
+
+ integer e;
+ integer s;
+ integer i;
+
+ initial begin
+ // Initialize Inputs
+ S0 = 0;
+ S1 = 0;
+ Ea = 0;
+ I0a = 0;
+ I1a = 0;
+ I2a = 0;
+ I3a = 0;
+ Eb = 0;
+ I0b = 0;
+ I1b = 0;
+ I2b = 0;
+ I3b = 0;
+
+ // Wait 100 ns for global reset to finish
+ #100;
+
+ // Add stimulus here
+ $display("S0\tS1\tI0\tI1\tI2\tI3\tEa\tEb\tZa\tZb");
+
+ for (e = 0; e < 4; e=e+1) begin
+ Ea = e[0];
+ Eb = e[1];
+ for (s = 0; s < 4; s=s+1) begin
+ S0 = s[0];
+ S1 = s[1];
+ for (i = 0; i < 16; i=i+1) begin
+ I0a = i[0];
+ I1a = i[1];
+ I2a = i[2];
+ I3a = i[3];
+ I0b = i[0];
+ I1b = i[1];
+ I2b = i[2];
+ I3b = i[3];
+ #4
+ $display("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s",
+ S0 ? "H" : "L",
+ S1 ? "H" : "L",
+ i[0] ? "H" : "L",
+ i[1] ? "H" : "L",
+ i[2] ? "H" : "L",
+ i[3] ? "H" : "L",
+ Ea ? "H" : "L",
+ Eb ? "H" : "L",
+ Za ? "H" : "L",
+ Zb ? "H" : "L");
+ end
+ end
+ end
+
+ $finish;
+ end
+
+endmodule
+
diff --git a/common/TTL/ls155.vhd b/common/TTL/ls155.vhd
new file mode 100644
index 00000000..ce820c96
--- /dev/null
+++ b/common/TTL/ls155.vhd
@@ -0,0 +1,73 @@
+--============================================================================
+--
+-- VHDL implementation of the 74LS155 dual 2-to-4 address decoder
+-- Copyright (C) 2018, 2019 Ace
+--
+-- Permission is hereby granted, free of charge, to any person obtaining a
+-- copy of this software and associated documentation files (the "Software"),
+-- to deal in the Software without restriction, including without limitation
+-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
+-- and/or sell copies of the Software, and to permit persons to whom the
+-- Software is furnished to do so, subject to the following conditions:
+--
+-- The above copyright notice and this permission notice shall be included in
+-- all copies or substantial portions of the Software.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+-- DEALINGS IN THE SOFTWARE.
+--
+--============================================================================
+
+--Chip pinout:
+/* _____________
+ _| |_
+n_ea(0) |_|1 16|_| VCC
+ _| |_
+n_ea(1) |_|2 15|_| n_eb(0)
+ _| |_
+a1 |_|3 14|_| n_eb(1)
+ _| |_
+o0(3) |_|4 13|_| a0
+ _| |_
+o0(2) |_|5 12|_| o1(3)
+ _| |_
+o0(1) |_|6 11|_| o1(2)
+ _| |_
+o0(0) |_|7 10|_| o1(1)
+ _| |_
+GND |_|8 9|_| o1(0)
+ |_____________|
+*/
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+
+entity ls155 is
+port
+(
+ a0, a1 : in std_logic;
+ n_ea : in std_logic_vector(1 downto 0); --n_ea(0) active high, n_ea(1) active low
+ n_eb : in std_logic_vector(1 downto 0);
+ o0 : out std_logic_vector(3 downto 0);
+ o1 : out std_logic_vector(3 downto 0)
+);
+end ls155;
+
+architecture arch of ls155 is
+begin
+ o0 <= "1110" when (n_ea(0) and not n_ea(1) and not a0 and not a1)
+ else "1101" when (n_ea(0) and not n_ea(1) and a0 and not a1)
+ else "1011" when (n_ea(0) and not n_ea(1) and not a0 and a1)
+ else "0111" when (n_ea(0) and not n_ea(1) and a0 and a1)
+ else "1111";
+ o1 <= "1110" when (not n_eb(0) and not n_eb(1) and not a0 and not a1)
+ else "1101" when (not n_eb(0) and not n_eb(1) and a0 and not a1)
+ else "1011" when (not n_eb(0) and not n_eb(1) and not a0 and a1)
+ else "0111" when (not n_eb(0) and not n_eb(1) and a0 and a1)
+ else "1111";
+end arch;
\ No newline at end of file
diff --git a/common/TTL/ls157.v b/common/TTL/ls157.v
new file mode 100644
index 00000000..f5afc6c1
--- /dev/null
+++ b/common/TTL/ls157.v
@@ -0,0 +1,32 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer: Paul Wightmore
+//
+// Create Date: 21:46:13 05/04/2018
+// Design Name: LS157
+// Module Name: system86\src\custom\ls157.v
+// Project Name: Namco System86 simulation
+// Target Devices:
+// Tool versions:
+// Description: LS157 - Quad 2-Input Multiplexer
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+// License: https://www.apache.org/licenses/LICENSE-2.0
+//
+//////////////////////////////////////////////////////////////////////////////////
+module LS157(
+ input wire G,
+ input wire SELA,
+ input wire [3:0] A,
+ input wire [3:0] B,
+ output wire [3:0] Y
+ );
+
+ assign Y = G ? (SELA ? A : B) : 4'b0;
+
+endmodule
diff --git a/common/TTL/ls157.vhd b/common/TTL/ls157.vhd
new file mode 100644
index 00000000..ad8f151d
--- /dev/null
+++ b/common/TTL/ls157.vhd
@@ -0,0 +1,66 @@
+--============================================================================
+--
+-- VHDL implementation of the 74LS157 dual 2-to-1 multiplexor
+-- Copyright (C) 2018, 2019 Ace
+--
+-- Permission is hereby granted, free of charge, to any person obtaining a
+-- copy of this software and associated documentation files (the "Software"),
+-- to deal in the Software without restriction, including without limitation
+-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
+-- and/or sell copies of the Software, and to permit persons to whom the
+-- Software is furnished to do so, subject to the following conditions:
+--
+-- The above copyright notice and this permission notice shall be included in
+-- all copies or substantial portions of the Software.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+-- DEALINGS IN THE SOFTWARE.
+--
+--============================================================================
+
+--Chip pinout:
+/* _____________
+ _| |_
+s |_|1 16|_| VCC
+ _| |_
+i0(0) |_|2 15|_| n_e
+ _| |_
+i1(0) |_|3 14|_| i0(2)
+ _| |_
+z(0) |_|4 13|_| i1(2)
+ _| |_
+i0(1) |_|5 12|_| z(2)
+ _| |_
+i1(1) |_|6 11|_| i0(3)
+ _| |_
+z(1) |_|7 10|_| i1(3)
+ _| |_
+GND |_|8 9|_| z(3)
+ |_____________|
+*/
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+
+entity ls157 is
+port
+(
+ i0 : in std_logic_vector(3 downto 0);
+ i1 : in std_logic_vector(3 downto 0);
+ n_e : in std_logic;
+ s : in std_logic;
+ z : out std_logic_vector(3 downto 0)
+);
+end ls157;
+
+architecture arch of ls157 is
+begin
+ z <= i0 when not n_e and not s
+ else i1 when not n_e and s
+ else "0000";
+end arch;
\ No newline at end of file
diff --git a/common/TTL/ls158.v b/common/TTL/ls158.v
new file mode 100644
index 00000000..60f12f19
--- /dev/null
+++ b/common/TTL/ls158.v
@@ -0,0 +1,32 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer: Paul Wightmore
+//
+// Create Date: 21:46:13 05/04/2018
+// Design Name: LS158
+// Module Name: system86/ttl/ls158.v
+// Project Name: Namco System86 simulation
+// Target Devices:
+// Tool versions:
+// Description: LS158 - As LS157 only with inverted outputs
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+// License: https://www.apache.org/licenses/LICENSE-2.0
+//
+//////////////////////////////////////////////////////////////////////////////////
+module LS158(
+ input wire G,
+ input wire SELA,
+ input wire [3:0] A,
+ input wire [3:0] B,
+ output wire [3:0] Y
+ );
+
+ assign Y = G ? ~(SELA ? A : B) : 4'b1;
+
+endmodule
diff --git a/common/TTL/ls161.vhd b/common/TTL/ls161.vhd
new file mode 100644
index 00000000..8cb01dbc
--- /dev/null
+++ b/common/TTL/ls161.vhd
@@ -0,0 +1,80 @@
+--============================================================================
+--
+-- VHDL implementation of the 74LS161 synchonous presettable 4-bit counter
+-- Copyright (C) 2018, 2019 Ace
+--
+-- Permission is hereby granted, free of charge, to any person obtaining a
+-- copy of this software and associated documentation files (the "Software"),
+-- to deal in the Software without restriction, including without limitation
+-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
+-- and/or sell copies of the Software, and to permit persons to whom the
+-- Software is furnished to do so, subject to the following conditions:
+--
+-- The above copyright notice and this permission notice shall be included in
+-- all copies or substantial portions of the Software.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+-- DEALINGS IN THE SOFTWARE.
+--
+--============================================================================
+
+--Chip pinout:
+/* _____________
+ _| |_
+n_clr |_|1 16|_| VCC
+ _| |_
+clk |_|2 15|_| rco
+ _| |_
+din(0) |_|3 14|_| q(0)
+ _| |_
+din(1) |_|4 13|_| q(1)
+ _| |_
+din(2) |_|5 12|_| q(2)
+ _| |_
+din(3) |_|6 11|_| q(3)
+ _| |_
+enp |_|7 10|_| ent
+ _| |_
+GND |_|8 9|_| n_load
+ |_____________|
+*/
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+
+entity ls161 is
+port
+(
+ n_clr : in std_logic;
+ clk : in std_logic;
+ din : in std_logic_vector(3 downto 0);
+ enp, ent : in std_logic;
+ n_load : in std_logic;
+ q : out std_logic_vector(3 downto 0);
+ rco : out std_logic
+);
+end ls161;
+
+architecture arch of ls161 is
+signal data : std_logic_vector(3 downto 0) := "0000";
+begin
+ process(clk, n_clr, enp, ent, data) begin
+ if(n_clr = '0') then
+ data <= "0000";
+ elsif(clk'event and clk = '1') then
+ if(n_load = '0') then
+ data <= din;
+ elsif(enp = '1' and ent = '1') then
+ data <= data + '1';
+ end if;
+ end if;
+ end process;
+ q <= data;
+ rco <= data(0) and data(1) and data(2) and data(3) and ent;
+end arch;
\ No newline at end of file
diff --git a/common/TTL/ls17.vhd b/common/TTL/ls17.vhd
new file mode 100644
index 00000000..d7f5604e
--- /dev/null
+++ b/common/TTL/ls17.vhd
@@ -0,0 +1,20 @@
+library IEEE;
+use IEEE.std_logic_1164.all;
+
+entity ls17 is
+port
+(
+ a1, a2, a3, a4, a5, a6 : in std_logic;
+ y1, y2, y3, y4, y5, y6 : out std_logic
+);
+end ls17;
+
+architecture arch of ls17 is
+begin
+ y1 <= a1;
+ y2 <= a2;
+ y3 <= a3;
+ y4 <= a4;
+ y5 <= a5;
+ y6 <= a6;
+end arch;
\ No newline at end of file
diff --git a/common/TTL/ls174.v b/common/TTL/ls174.v
new file mode 100644
index 00000000..2ccab8d1
--- /dev/null
+++ b/common/TTL/ls174.v
@@ -0,0 +1,36 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer: Paul Wightmore
+//
+// Create Date: 23:33:42 05/14/2018
+// Design Name: LS174
+// Module Name: system86/ttl/ls174.v
+// Project Name: Namco System86 simulation
+// Target Devices:
+// Tool versions:
+// Description: LS174 - Hex D-Type Positive-Edge-Triggered Flip-Flops With Clear
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+// License: https://www.apache.org/licenses/LICENSE-2.0
+//
+//////////////////////////////////////////////////////////////////////////////////
+module LS174(
+ input wire CLK,
+ input wire CLR,
+ input wire [5:0] D,
+ output reg [5:0] Q
+ );
+
+ always @(posedge CLK) begin
+ if (CLR)
+ Q = 6'b0;
+ else
+ Q = D;
+ end
+
+endmodule
diff --git a/common/TTL/ls174.vhd b/common/TTL/ls174.vhd
new file mode 100644
index 00000000..51ab709f
--- /dev/null
+++ b/common/TTL/ls174.vhd
@@ -0,0 +1,69 @@
+--============================================================================
+--
+-- VHDL implementation of the 74LS174 hex D-flip flop
+-- Copyright (C) 2018, 2019 Ace
+--
+-- Permission is hereby granted, free of charge, to any person obtaining a
+-- copy of this software and associated documentation files (the "Software"),
+-- to deal in the Software without restriction, including without limitation
+-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
+-- and/or sell copies of the Software, and to permit persons to whom the
+-- Software is furnished to do so, subject to the following conditions:
+--
+-- The above copyright notice and this permission notice shall be included in
+-- all copies or substantial portions of the Software.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+-- DEALINGS IN THE SOFTWARE.
+--
+--============================================================================
+
+--Chip pinout:
+/* _____________
+ _| |_
+mr |_|1 16|_| VCC
+ _| |_
+q(0) |_|2 15|_| q(5)
+ _| |_
+d(0) |_|3 14|_| d(5)
+ _| |_
+d(1) |_|4 13|_| d(4)
+ _| |_
+q(1) |_|5 12|_| q(4)
+ _| |_
+d(2) |_|6 11|_| d(3)
+ _| |_
+q(2) |_|7 10|_| q(3)
+ _| |_
+GND |_|8 9|_| clk
+ |_____________|
+*/
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+
+entity ls174 is
+port
+(
+ d : in std_logic_vector(5 downto 0);
+ clk : in std_logic;
+ mr : in std_logic;
+ q : out std_logic_vector(5 downto 0)
+);
+end ls174;
+
+architecture arch of ls174 is
+begin
+ process(clk, mr) begin
+ if(mr = '0') then
+ q <= "000000";
+ elsif(clk'event and clk = '1') then
+ q <= d;
+ end if;
+ end process;
+end arch;
\ No newline at end of file
diff --git a/common/TTL/ls175.v b/common/TTL/ls175.v
new file mode 100644
index 00000000..5c541da5
--- /dev/null
+++ b/common/TTL/ls175.v
@@ -0,0 +1,58 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer: Paul Wightmore
+//
+// Create Date: 20:44:36 04/25/2018
+// Design Name: LS175
+// Module Name: system86\src\ttl\ls175.v
+// Project Name: Namco System86 simulation
+// Target Devices:
+// Tool versions:
+// Description: LS175 - Quad D-Type Flip-Flop
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+// License: https://www.apache.org/licenses/LICENSE-2.0
+//
+//////////////////////////////////////////////////////////////////////////////////
+module LS175(
+ input wire CLK,
+ input wire CLR,
+ input wire D1,
+ input wire D2,
+ input wire D3,
+ input wire D4,
+ output reg Q1,
+ output wire Q1_L,
+ output reg Q2,
+ output wire Q2_L,
+ output reg Q3,
+ output wire Q3_L,
+ output reg Q4,
+ output wire Q4_L
+ );
+
+ always @(posedge CLK) begin
+ if (CLR) begin
+ Q1 <= 0;
+ Q2 <= 0;
+ Q3 <= 0;
+ Q4 <= 0;
+ end else begin
+ Q1 <= D1;
+ Q2 <= D2;
+ Q3 <= D3;
+ Q4 <= D4;
+ end
+ end
+
+ assign Q1_L = ~Q1;
+ assign Q2_L = ~Q2;
+ assign Q3_L = ~Q3;
+ assign Q4_L = ~Q4;
+
+endmodule
diff --git a/common/TTL/ls20.vhd b/common/TTL/ls20.vhd
new file mode 100644
index 00000000..df9fca8d
--- /dev/null
+++ b/common/TTL/ls20.vhd
@@ -0,0 +1,61 @@
+--============================================================================
+--
+-- VHDL implementation of the 74LS20 dual 4-input NAND gate
+-- Copyright (C) 2018, 2019 Ace
+--
+-- Permission is hereby granted, free of charge, to any person obtaining a
+-- copy of this software and associated documentation files (the "Software"),
+-- to deal in the Software without restriction, including without limitation
+-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
+-- and/or sell copies of the Software, and to permit persons to whom the
+-- Software is furnished to do so, subject to the following conditions:
+--
+-- The above copyright notice and this permission notice shall be included in
+-- all copies or substantial portions of the Software.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+-- DEALINGS IN THE SOFTWARE.
+--
+--============================================================================
+
+--Chip pinout:
+/* _____________
+ _| |_
+a1 |_|1 14|_| VCC
+ _| |_
+b1 |_|2 13|_| d2
+ _| |_
+NC |_|3 12|_| c2
+ _| |_
+c1 |_|4 11|_| NC
+ _| |_
+d1 |_|5 10|_| b2
+ _| |_
+y1 |_|6 9|_| a2
+ _| |_
+GND |_|7 8|_| y2
+ |_____________|
+*/
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+
+entity ls20 is
+port
+(
+ a1, b1, c1, d1 : in std_logic;
+ a2, b2, c2, d2 : in std_logic;
+ y1, y2 : out std_logic
+);
+end ls20;
+
+architecture arch of ls20 is
+begin
+ y1 <= not(a1 and b1 and c1 and d1);
+ y2 <= not(a2 and b2 and c2 and d2);
+end arch;
\ No newline at end of file
diff --git a/common/TTL/ls244.vhd b/common/TTL/ls244.vhd
new file mode 100644
index 00000000..8932d4b8
--- /dev/null
+++ b/common/TTL/ls244.vhd
@@ -0,0 +1,71 @@
+--============================================================================
+--
+-- VHDL implementation of the 74LS244 octal line driver with tristate outputs
+-- Copyright (C) 2018, 2019 Ace
+--
+-- Permission is hereby granted, free of charge, to any person obtaining a
+-- copy of this software and associated documentation files (the "Software"),
+-- to deal in the Software without restriction, including without limitation
+-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
+-- and/or sell copies of the Software, and to permit persons to whom the
+-- Software is furnished to do so, subject to the following conditions:
+--
+-- The above copyright notice and this permission notice shall be included in
+-- all copies or substantial portions of the Software.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+-- DEALINGS IN THE SOFTWARE.
+--
+--============================================================================
+
+--Chip pinout:
+/* _____________
+ _| |_
+n_g1 |_|1 20|_| VCC
+ _| |_
+a1(0) |_|2 19|_| n_g2
+ _| |_
+y2(3) |_|3 18|_| y1(0)
+ _| |_
+a1(1) |_|4 17|_| a2(3)
+ _| |_
+y2(2) |_|5 16|_| y1(1)
+ _| |_
+a1(2) |_|6 15|_| a2(2)
+ _| |_
+y2(1) |_|7 14|_| y1(2)
+ _| |_
+a1(3) |_|8 13|_| a2(1)
+ _| |_
+y2(0) |_|9 12|_| y1(3)
+ _| |_
+GND |_|10 11|_| a2(0)
+ |_____________|
+*/
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity ls244 is
+port
+(
+ n_g1, n_g2 : in std_logic;
+ a1 : in std_logic_vector(3 downto 0);
+ a2 : in std_logic_vector(3 downto 0);
+ y1 : out std_logic_vector(3 downto 0);
+ y2 : out std_logic_vector(3 downto 0)
+);
+end ls244;
+
+architecture arch of ls244 is
+begin
+ y1 <= a1 when not n_g1
+ else (others => 'Z');
+ y2 <= a2 when not n_g2
+ else (others => 'Z');
+end arch;
\ No newline at end of file
diff --git a/common/TTL/ls245.v b/common/TTL/ls245.v
new file mode 100644
index 00000000..d76580a9
--- /dev/null
+++ b/common/TTL/ls245.v
@@ -0,0 +1,35 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer: Paul Wightmore
+//
+// Create Date: 19:33:12 05/01/2018
+// Design Name: LS245
+// Module Name: system86\src\ttl\ls245.v
+// Project Name: Namco System86 simulation
+// Target Devices:
+// Tool versions:
+// Description: LS245 - Octal Bus Transceiver
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+// License: https://www.apache.org/licenses/LICENSE-2.0
+//
+//////////////////////////////////////////////////////////////////////////////////
+module LS245(
+ input wire DIR,
+ input wire OE,
+ inout wire [7:0] A,
+ inout wire [7:0] B
+ );
+
+ wire BToA = OE & ~DIR;
+ wire AToB = OE & DIR;
+
+ assign A = BToA ? B : 8'bZ;
+ assign B = AToB ? A : 8'bZ;
+
+endmodule
diff --git a/common/TTL/ls245.vhd b/common/TTL/ls245.vhd
new file mode 100644
index 00000000..e82439cd
--- /dev/null
+++ b/common/TTL/ls245.vhd
@@ -0,0 +1,25 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity ls245 is
+port
+(
+ dir, n_oe : in std_logic;
+ a, b : inout std_logic_vector(7 downto 0)
+);
+end ls245;
+
+architecture arch of ls245 is
+begin
+ a <= (others => 'Z');
+ b <= (others => 'Z');
+ process(dir, n_oe, a, b) begin
+ if(n_oe = '0' and dir = '1') then
+ a <= (others => 'Z');
+ b <= a;
+ elsif(n_oe = '0' and dir = '0') then
+ b <= (others => 'Z');
+ a <= b;
+ end if;
+ end process;
+end arch;
\ No newline at end of file
diff --git a/common/TTL/ls245_tb.v b/common/TTL/ls245_tb.v
new file mode 100644
index 00000000..692e7d0b
--- /dev/null
+++ b/common/TTL/ls245_tb.v
@@ -0,0 +1,86 @@
+`timescale 1ns / 1ps
+
+////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer: Paul Wightmore
+//
+// Create Date: 19:38:32 05/01/2018
+// Design Name: LS245
+// Module Name: System86/LS245_tb.v
+// Project Name: Namco System86 simulation
+// Target Device:
+// Tool versions:
+// Description: LS245 - Octal Bus Transceiver - test bench
+//
+// Verilog Test Fixture created by ISE for module: LS245
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+// License: https://www.apache.org/licenses/LICENSE-2.0
+//
+////////////////////////////////////////////////////////////////////////////////
+
+module LS245_tb;
+
+ // Inputs
+ reg DIR;
+ reg OE;
+
+ // Bidirs
+ wire [7:0] A;
+ wire [7:0] B;
+
+ reg [7:0] AIn = 'h99;
+ reg [7:0] BIn = 'h66;
+
+ assign A = DIR ? AIn : 8'bZ;
+ assign B = ~DIR ? BIn : 8'bZ;
+
+ // Instantiate the Unit Under Test (UUT)
+ LS245 uut (
+ .DIR(DIR),
+ .OE(OE),
+ .A(A),
+ .B(B)
+ );
+
+ integer e;
+ integer d;
+
+ initial begin
+ // Initialize Inputs
+ DIR = 0;
+ OE = 0;
+
+ // Wait 100 ns for global reset to finish
+ #100;
+
+ // Add stimulus here
+ $display("OE\tDIR\tAIn\tBIn\tAOut\tBOut");
+
+ for (e = 0; e <= 1; e=e+1) begin
+ OE <= e[0];
+
+ for (d = 0; d <= 1; d=d+1) begin
+
+ DIR <= d[0];
+
+ #4
+ $display("%s\t%s\t0x%x\t0x%x\t0x%x\t0x%x",
+ OE ? "H" : "L",
+ DIR ? "H" : "L",
+ AIn,
+ BIn,
+ A,
+ B);
+ end
+ end
+
+ $finish;
+ end
+
+endmodule
+
diff --git a/common/TTL/ls257.v b/common/TTL/ls257.v
new file mode 100644
index 00000000..615002e3
--- /dev/null
+++ b/common/TTL/ls257.v
@@ -0,0 +1,32 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer: Paul Wightmore
+//
+// Create Date: 21:34:16 05/04/2018
+// Design Name: LS257
+// Module Name: system86\src\ttl\ls257.v
+// Project Name: Namco System86 simulation
+// Target Devices:
+// Tool versions:
+// Description: LS257 - Quad 2-Line To 1-Line Data Selectors/Multiplexers
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+// License: https://www.apache.org/licenses/LICENSE-2.0
+//
+//////////////////////////////////////////////////////////////////////////////////
+module LS257(
+ input wire G,
+ input wire SELA,
+ input wire [3:0] A,
+ input wire [3:0] B,
+ output wire [3:0] Y
+ );
+
+ assign Y = G ? (SELA ? A : B) : 4'bZ;
+
+endmodule
diff --git a/common/TTL/ls257.vhd b/common/TTL/ls257.vhd
new file mode 100644
index 00000000..426ae82d
--- /dev/null
+++ b/common/TTL/ls257.vhd
@@ -0,0 +1,67 @@
+--============================================================================
+--
+-- VHDL implementation of the 74LS257 quad 2-to-1 multiplexer with tristate
+-- outputs
+-- Copyright (C) 2018, 2019 Ace
+--
+-- Permission is hereby granted, free of charge, to any person obtaining a
+-- copy of this software and associated documentation files (the "Software"),
+-- to deal in the Software without restriction, including without limitation
+-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
+-- and/or sell copies of the Software, and to permit persons to whom the
+-- Software is furnished to do so, subject to the following conditions:
+--
+-- The above copyright notice and this permission notice shall be included in
+-- all copies or substantial portions of the Software.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+-- DEALINGS IN THE SOFTWARE.
+--
+--============================================================================
+
+--Chip pinout:
+/* _____________
+ _| |_
+sel |_|1 16|_| VCC
+ _| |_
+a(0) |_|2 15|_| out_ctl
+ _| |_
+b(0) |_|3 14|_| a(2)
+ _| |_
+y(0) |_|4 13|_| b(2)
+ _| |_
+a(1) |_|5 12|_| y(2)
+ _| |_
+b(1) |_|6 11|_| a(3)
+ _| |_
+y(1) |_|7 10|_| b(3)
+ _| |_
+GND |_|8 9|_| y(3)
+ |_____________|
+*/
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+
+entity ls257 is
+port
+(
+ a : in std_logic_vector(3 downto 0);
+ b : in std_logic_vector(3 downto 0);
+ out_ctl : in std_logic;
+ sel : in std_logic;
+ y : out std_logic_vector(3 downto 0)
+);
+end ls257;
+
+architecture arch of ls257 is
+begin
+ y <= a when not out_ctl and not sel
+ else b when not out_ctl and sel
+ else (others => 'Z');
+end arch;
\ No newline at end of file
diff --git a/common/TTL/ls27.vhd b/common/TTL/ls27.vhd
new file mode 100644
index 00000000..996b60f2
--- /dev/null
+++ b/common/TTL/ls27.vhd
@@ -0,0 +1,63 @@
+--============================================================================
+--
+-- VHDL implementation of the 74LS27 triple 3-input NOR gate
+-- Copyright (C) 2018, 2019 Ace
+--
+-- Permission is hereby granted, free of charge, to any person obtaining a
+-- copy of this software and associated documentation files (the "Software"),
+-- to deal in the Software without restriction, including without limitation
+-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
+-- and/or sell copies of the Software, and to permit persons to whom the
+-- Software is furnished to do so, subject to the following conditions:
+--
+-- The above copyright notice and this permission notice shall be included in
+-- all copies or substantial portions of the Software.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+-- DEALINGS IN THE SOFTWARE.
+--
+--============================================================================
+
+--Chip pinout:
+/* _____________
+ _| |_
+a1 |_|1 14|_| VCC
+ _| |_
+b1 |_|2 13|_| c1
+ _| |_
+a2 |_|3 12|_| y1
+ _| |_
+b2 |_|4 11|_| c3
+ _| |_
+c2 |_|5 10|_| b3
+ _| |_
+y2 |_|6 9|_| a3
+ _| |_
+GND |_|7 8|_| y3
+ |_____________|
+*/
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+
+entity ls27 is
+port
+(
+ a1, a2, a3 : in std_logic;
+ b1, b2, b3 : in std_logic;
+ c1, c2, c3 : in std_logic;
+ y1, y2, y3 : out std_logic
+);
+end ls27;
+
+architecture arch of ls27 is
+begin
+ y1 <= not(a1 or b1 or c1);
+ y2 <= not(a2 or b2 or c2);
+ y3 <= not(a3 or b3 or c3);
+end arch;
\ No newline at end of file
diff --git a/common/TTL/ls273.v b/common/TTL/ls273.v
new file mode 100644
index 00000000..538be959
--- /dev/null
+++ b/common/TTL/ls273.v
@@ -0,0 +1,36 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer: Paul Wightmore
+//
+// Create Date: 21:51:32 05/14/2018
+// Design Name: LS273
+// Module Name: system86/ttl/ls273.v
+// Project Name: Namco System86 simulation
+// Target Devices:
+// Tool versions:
+// Description:
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+// License: https://www.apache.org/licenses/LICENSE-2.0
+//
+//////////////////////////////////////////////////////////////////////////////////
+module LS273(
+ input wire CLK,
+ input wire CLR,
+ input wire [7:0] D,
+ output reg [7:0] Q
+ );
+
+ always @(posedge CLK) begin
+ if (CLR)
+ Q = 8'b0;
+ else
+ Q = D;
+ end
+
+endmodule
diff --git a/common/TTL/ls273.vhd b/common/TTL/ls273.vhd
new file mode 100644
index 00000000..5d8dece1
--- /dev/null
+++ b/common/TTL/ls273.vhd
@@ -0,0 +1,73 @@
+--============================================================================
+--
+-- VHDL implementation of the 74LS273 8-bit register
+-- Copyright (C) 2018, 2019 Ace
+--
+-- Permission is hereby granted, free of charge, to any person obtaining a
+-- copy of this software and associated documentation files (the "Software"),
+-- to deal in the Software without restriction, including without limitation
+-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
+-- and/or sell copies of the Software, and to permit persons to whom the
+-- Software is furnished to do so, subject to the following conditions:
+--
+-- The above copyright notice and this permission notice shall be included in
+-- all copies or substantial portions of the Software.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+-- DEALINGS IN THE SOFTWARE.
+--
+--============================================================================
+
+--Chip pinout:
+/* _____________
+ _| |_
+res |_|1 20|_| VCC
+ _| |_
+q(0) |_|2 19|_| q(7)
+ _| |_
+d(0) |_|3 18|_| d(7)
+ _| |_
+d(1) |_|4 17|_| d(6)
+ _| |_
+q(1) |_|5 16|_| q(6)
+ _| |_
+q(2) |_|6 15|_| q(5)
+ _| |_
+d(2) |_|7 14|_| d(5)
+ _| |_
+d(3) |_|8 13|_| d(4)
+ _| |_
+q(3) |_|9 12|_| q(4)
+ _| |_
+GND |_|10 11|_| clk
+ |_____________|
+*/
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+
+entity ls273 is
+port
+(
+ d : in std_logic_vector(7 downto 0);
+ clk : in std_logic;
+ res : in std_logic;
+ q : out std_logic_vector(7 downto 0)
+);
+end ls273;
+
+architecture arch of ls273 is
+begin
+ process(clk, res) begin
+ if(res = '0') then
+ q <= "00000000";
+ elsif(clk'event and clk = '1') then
+ q <= d;
+ end if;
+ end process;
+end arch;
\ No newline at end of file
diff --git a/common/TTL/ls283.vhd b/common/TTL/ls283.vhd
new file mode 100644
index 00000000..44220ec5
--- /dev/null
+++ b/common/TTL/ls283.vhd
@@ -0,0 +1,68 @@
+--============================================================================
+--
+-- VHDL implementation of the 74LS283 4-bit full adder with fast carry
+-- Copyright (C) 2018, 2019 Ace
+--
+-- Permission is hereby granted, free of charge, to any person obtaining a
+-- copy of this software and associated documentation files (the "Software"),
+-- to deal in the Software without restriction, including without limitation
+-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
+-- and/or sell copies of the Software, and to permit persons to whom the
+-- Software is furnished to do so, subject to the following conditions:
+--
+-- The above copyright notice and this permission notice shall be included in
+-- all copies or substantial portions of the Software.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+-- DEALINGS IN THE SOFTWARE.
+--
+--============================================================================
+
+--Chip pinout:
+/* _____________
+ _| |_
+sum(1) |_|1 16|_| VCC
+ _| |_
+b(1) |_|2 15|_| b(2)
+ _| |_
+a(1) |_|3 14|_| a(2)
+ _| |_
+sum(0) |_|4 13|_| sum(2)
+ _| |_
+a(0) |_|5 12|_| a(3)
+ _| |_
+b(0) |_|6 11|_| b(3)
+ _| |_
+c_in |_|7 10|_| sum(3)
+ _| |_
+GND |_|8 9|_| c_out
+ |_____________|
+*/
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.std_logic_unsigned.all;
+
+entity ls283 is
+port
+(
+ a : in std_logic_vector(3 downto 0);
+ b : in std_logic_vector(3 downto 0);
+ c_in : in std_logic;
+ sum : out std_logic_vector(3 downto 0);
+ c_out : out std_logic
+);
+end ls283;
+
+architecture arch of ls283 is
+signal sum_int : std_logic_vector(4 downto 0);
+begin
+ sum_int <= ('0' & a) + ('0' & b) + ("0000" & c_in);
+ sum <= sum_int(3 downto 0);
+ c_out <= sum_int(4);
+end arch;
\ No newline at end of file
diff --git a/common/TTL/ls32.v b/common/TTL/ls32.v
new file mode 100644
index 00000000..4eadcc6a
--- /dev/null
+++ b/common/TTL/ls32.v
@@ -0,0 +1,39 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer: Paul Wightmore
+//
+// Create Date: 19:42:41 05/10/2018
+// Design Name: LS32
+// Module Name: system86/ttl/ls32.v
+// Project Name: Namco System86 simulation
+// Target Devices:
+// Tool versions:
+// Description: LS32 - Quadruple 2-Input Positive-OR Gates
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+// License: https://www.apache.org/licenses/LICENSE-2.0
+//
+//////////////////////////////////////////////////////////////////////////////////
+module LS32(
+ input wire A1,
+ input wire B1,
+ input wire A2,
+ input wire B2,
+ input wire A3,
+ input wire B3,
+ input wire A4,
+ input wire B4,
+ output wire Y1,
+ output wire Y2,
+ output wire Y3,
+ output wire Y4
+ );
+
+ or ls32[0:3]( {Y4, Y3, Y2, Y1}, {A4, A3, A2, A1}, {B4, B3, B2, B1} );
+
+endmodule
diff --git a/common/TTL/ls32.vhd b/common/TTL/ls32.vhd
new file mode 100644
index 00000000..9da58abf
--- /dev/null
+++ b/common/TTL/ls32.vhd
@@ -0,0 +1,63 @@
+--============================================================================
+--
+-- VHDL implementation of the 74LS32 quad OR gate
+-- Copyright (C) 2018, 2019 Ace
+--
+-- Permission is hereby granted, free of charge, to any person obtaining a
+-- copy of this software and associated documentation files (the "Software"),
+-- to deal in the Software without restriction, including without limitation
+-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
+-- and/or sell copies of the Software, and to permit persons to whom the
+-- Software is furnished to do so, subject to the following conditions:
+--
+-- The above copyright notice and this permission notice shall be included in
+-- all copies or substantial portions of the Software.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+-- DEALINGS IN THE SOFTWARE.
+--
+--============================================================================
+
+--Chip pinout:
+/* _____________
+ _| |_
+a1 |_|1 14|_| VCC
+ _| |_
+b1 |_|2 13|_| a4
+ _| |_
+y1 |_|3 12|_| b4
+ _| |_
+a2 |_|4 11|_| y4
+ _| |_
+b2 |_|5 10|_| a3
+ _| |_
+y2 |_|6 9|_| b3
+ _| |_
+GND |_|7 8|_| y3
+ |_____________|
+*/
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+
+entity ls32 is
+port
+(
+ a1, a2, a3, a4 : in std_logic;
+ b1, b2, b3, b4 : in std_logic;
+ y1, y2, y3, y4 : out std_logic
+);
+end ls32;
+
+architecture arch of ls32 is
+begin
+ y1 <= a1 or b1;
+ y2 <= a2 or b2;
+ y3 <= a3 or b3;
+ y4 <= a4 or b4;
+end arch;
\ No newline at end of file
diff --git a/common/TTL/ls373.vhd b/common/TTL/ls373.vhd
new file mode 100644
index 00000000..52290d66
--- /dev/null
+++ b/common/TTL/ls373.vhd
@@ -0,0 +1,74 @@
+--============================================================================
+--
+-- VHDL implementation of the 74LS373 octal transparent latch
+-- Copyright (C) 2018, 2019 Ace
+--
+-- Permission is hereby granted, free of charge, to any person obtaining a
+-- copy of this software and associated documentation files (the "Software"),
+-- to deal in the Software without restriction, including without limitation
+-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
+-- and/or sell copies of the Software, and to permit persons to whom the
+-- Software is furnished to do so, subject to the following conditions:
+--
+-- The above copyright notice and this permission notice shall be included in
+-- all copies or substantial portions of the Software.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+-- DEALINGS IN THE SOFTWARE.
+--
+--============================================================================
+
+--Chip pinout:
+/* _____________
+ _| |_
+out_ctl |_|1 20|_| VCC
+ _| |_
+q(0) |_|2 19|_| q(7)
+ _| |_
+d(0) |_|3 18|_| d(7)
+ _| |_
+d(1) |_|4 17|_| d(6)
+ _| |_
+q(1) |_|5 16|_| q(6)
+ _| |_
+q(2) |_|6 15|_| q(5)
+ _| |_
+d(2) |_|7 14|_| d(5)
+ _| |_
+d(3) |_|8 13|_| d(4)
+ _| |_
+q(3) |_|9 12|_| q(4)
+ _| |_
+GND |_|10 11|_| g
+ |_____________|
+*/
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+
+entity ls373 is
+port
+(
+ d : in std_logic_vector(7 downto 0);
+ g : in std_logic;
+ out_ctl : in std_logic;
+ q : out std_logic_vector(7 downto 0)
+);
+end ls373;
+
+architecture arch of ls373 is
+signal q_int : std_logic_vector(7 downto 0);
+begin
+ process(d, g) begin
+ if(g = '1') then
+ q_int <= d;
+ end if;
+ end process;
+ q <= q_int when not out_ctl
+ else (others => 'Z');
+end arch;
\ No newline at end of file
diff --git a/common/TTL/ls374.v b/common/TTL/ls374.v
new file mode 100644
index 00000000..d6d68c49
--- /dev/null
+++ b/common/TTL/ls374.v
@@ -0,0 +1,36 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer: Paul Wightmore
+//
+// Create Date: 20:28:15 05/15/2018
+// Design Name: LS374
+// Module Name: system86/ttl/ls374.v
+// Project Name: Namco System86 simulation
+// Target Devices:
+// Tool versions:
+// Description: LS374 - Octal D-Type Transparent Latches And Edge-Triggered Flip-Flops
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+// License: https://www.apache.org/licenses/LICENSE-2.0
+//
+//////////////////////////////////////////////////////////////////////////////////
+module LS374(
+ input wire OC,
+ input wire CLK,
+ input wire [1:8] D,
+ output reg [1:8] Q
+ );
+
+ always @(posedge CLK) begin
+ if (OC)
+ Q = D;
+ else
+ Q = 8'bZ;
+ end
+
+endmodule
diff --git a/common/TTL/ls374.vhd b/common/TTL/ls374.vhd
new file mode 100644
index 00000000..050f4b0a
--- /dev/null
+++ b/common/TTL/ls374.vhd
@@ -0,0 +1,74 @@
+--============================================================================
+--
+-- VHDL implementation of the 74LS374 octal D-flip flop
+-- Copyright (C) 2018, 2019 Ace
+--
+-- Permission is hereby granted, free of charge, to any person obtaining a
+-- copy of this software and associated documentation files (the "Software"),
+-- to deal in the Software without restriction, including without limitation
+-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
+-- and/or sell copies of the Software, and to permit persons to whom the
+-- Software is furnished to do so, subject to the following conditions:
+--
+-- The above copyright notice and this permission notice shall be included in
+-- all copies or substantial portions of the Software.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+-- DEALINGS IN THE SOFTWARE.
+--
+--============================================================================
+
+--Chip pinout:
+/* _____________
+ _| |_
+out_ctl |_|1 20|_| VCC
+ _| |_
+q(0) |_|2 19|_| q(7)
+ _| |_
+d(0) |_|3 18|_| d(7)
+ _| |_
+d(1) |_|4 17|_| d(6)
+ _| |_
+q(1) |_|5 16|_| q(6)
+ _| |_
+q(2) |_|6 15|_| q(5)
+ _| |_
+d(2) |_|7 14|_| d(5)
+ _| |_
+d(3) |_|8 13|_| d(4)
+ _| |_
+q(3) |_|9 12|_| q(4)
+ _| |_
+GND |_|10 11|_| clk
+ |_____________|
+*/
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+
+entity ls374 is
+port
+(
+ d : in std_logic_vector(7 downto 0);
+ clk : in std_logic;
+ out_ctl : in std_logic;
+ q : out std_logic_vector(7 downto 0)
+);
+end ls374;
+
+architecture arch of ls374 is
+signal q_internal : std_logic_vector(7 downto 0);
+begin
+ process(clk) begin
+ if(clk'event and clk = '1') then
+ q_internal <= d;
+ end if;
+ end process;
+ q <= q_internal when not out_ctl
+ else (others => 'Z');
+end arch;
\ No newline at end of file
diff --git a/common/TTL/ls393.vhd b/common/TTL/ls393.vhd
new file mode 100644
index 00000000..ba2f16fa
--- /dev/null
+++ b/common/TTL/ls393.vhd
@@ -0,0 +1,79 @@
+--============================================================================
+--
+-- VHDL implementation of the 74LS393 dual 4-bit binary counter
+-- Copyright (C) 2018, 2019 Ace
+--
+-- Permission is hereby granted, free of charge, to any person obtaining a
+-- copy of this software and associated documentation files (the "Software"),
+-- to deal in the Software without restriction, including without limitation
+-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
+-- and/or sell copies of the Software, and to permit persons to whom the
+-- Software is furnished to do so, subject to the following conditions:
+--
+-- The above copyright notice and this permission notice shall be included in
+-- all copies or substantial portions of the Software.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+-- DEALINGS IN THE SOFTWARE.
+--
+--============================================================================
+
+--Chip pinout:
+/* _____________
+ _| |_
+clk1 |_|1 14|_| VCC
+ _| |_
+clr1 |_|2 13|_| clk2
+ _| |_
+q1(0) |_|3 12|_| clr2
+ _| |_
+q1(1) |_|4 11|_| q2(0)
+ _| |_
+q1(2) |_|5 10|_| q2(1)
+ _| |_
+q1(3) |_|6 9|_| q2(2)
+ _| |_
+GND |_|7 8|_| q2(3)
+ |_____________|
+*/
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.std_logic_arith.all;
+
+entity ls393 is
+port
+(
+ clk1, clk2 : in std_logic;
+ clr1, clr2 : in std_logic;
+ q1, q2 : out std_logic_vector(3 downto 0)
+);
+end ls393;
+
+architecture arch of ls393 is
+signal count1 : std_logic_vector(3 downto 0);
+signal count2 : std_logic_vector(3 downto 0);
+begin
+ process(clk1, clr1) begin
+ if(clr1 = '1') then
+ count1 <= "0000";
+ elsif(clk1'event and clk1 = '0') then
+ count1 <= count1 + 1;
+ end if;
+ end process;
+ process(clk2, clr2) begin
+ if(clr2 = '1') then
+ count2 <= "0000";
+ elsif(clk2'event and clk2 = '0') then
+ count2 <= count2 + 1;
+ end if;
+ end process;
+ q1 <= count1;
+ q2 <= count2;
+end arch;
\ No newline at end of file
diff --git a/common/TTL/ls669.vhd b/common/TTL/ls669.vhd
new file mode 100644
index 00000000..d15e66fe
--- /dev/null
+++ b/common/TTL/ls669.vhd
@@ -0,0 +1,85 @@
+--============================================================================
+--
+-- VHDL implementation of the 74LS669 synchronous 4-bit up/down counter
+-- Copyright (C) 2018, 2019 Ace
+--
+-- Permission is hereby granted, free of charge, to any person obtaining a
+-- copy of this software and associated documentation files (the "Software"),
+-- to deal in the Software without restriction, including without limitation
+-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
+-- and/or sell copies of the Software, and to permit persons to whom the
+-- Software is furnished to do so, subject to the following conditions:
+--
+-- The above copyright notice and this permission notice shall be included in
+-- all copies or substantial portions of the Software.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+-- DEALINGS IN THE SOFTWARE.
+--
+--============================================================================
+
+--Chip pinout:
+/* _____________
+ _| |_
+u_d |_|1 16|_| VCC
+ _| |_
+clk |_|2 15|_| n_rco
+ _| |_
+d_in(0) |_|3 14|_| d_out(0)
+ _| |_
+d_in(1) |_|4 13|_| d_out(1)
+ _| |_
+d_in(2) |_|5 12|_| d_out(2)
+ _| |_
+d_in(3) |_|6 11|_| d_out(3)
+ _| |_
+n_en_p |_|7 10|_| n_en_t
+ _| |_
+GND |_|8 9|_| load
+ |_____________|
+*/
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.std_logic_arith.all;
+
+entity ls669 is
+port
+(
+ d_in : in std_logic_vector(3 downto 0);
+ clk : in std_logic;
+ load : in std_logic;
+ n_en_p : in std_logic;
+ n_en_t : in std_logic;
+ u_d : in std_logic;
+ d_out : out std_logic_vector(3 downto 0);
+ n_rco : out std_logic
+);
+end ls669;
+
+architecture arch of ls669 is
+signal count: std_logic_vector(3 downto 0);
+begin
+ process(clk) begin
+ if(clk'event and clk = '1') then
+ if(load = '0') then
+ count <= d_in;
+ elsif(n_en_p = '0' and n_en_t = '0') then
+ if(u_d = '1') then
+ count <= count + 1;
+ else
+ count <= count - 1;
+ end if;
+ end if;
+ end if;
+ end process;
+ d_out <= count;
+ n_rco <= (not n_en_t and u_d and count(0) and count(1) and count(2) and count(3))
+ nor (not n_en_t and not u_d and not count(0) and not count(1) and not count(2) and not count(3));
+end arch;
\ No newline at end of file
diff --git a/common/TTL/ls74.v b/common/TTL/ls74.v
new file mode 100644
index 00000000..afbc59f5
--- /dev/null
+++ b/common/TTL/ls74.v
@@ -0,0 +1,66 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer: Paul Wightmore
+//
+// Create Date: 19:24:54 05/16/2018
+// Design Name: LS47
+// Module Name: system86/ttl/ls74.v
+// Project Name: Namco System86 simulation
+// Target Devices:
+// Tool versions:
+// Description: LS74 - Dual D-Type Positive-Edge -Triggered Flip-Flops With Preset and Clear
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+// License: https://www.apache.org/licenses/LICENSE-2.0
+//
+//////////////////////////////////////////////////////////////////////////////////
+module LS74(
+ input wire CLR1,
+ input wire CLR2,
+ input wire CLK1,
+ input wire CLK2,
+ input wire PRE1,
+ input wire PRE2,
+ input wire D1,
+ input wire D2,
+ output reg Q1,
+ output reg Q2,
+ output reg nQ1,
+ output reg nQ2
+ );
+
+ reg Q1Next = 0;
+ reg Q2Next = 0;
+
+ always @(posedge CLK1) begin
+ Q1Next <= D1;
+ end
+
+ always @(posedge CLK2) begin
+ Q2Next <= D2;
+ end
+
+ always @(PRE1 or CLR1 or Q1Next) begin
+ if (!PRE1 && !CLR1) begin
+ Q1 <= Q1Next;
+ end else begin
+ Q1 <= PRE1;
+ nQ1 <= PRE1 || !CLR1;
+ end
+ end
+
+ always @(PRE2 or CLR2 or Q2Next) begin
+ if (!PRE2 && !CLR2) begin
+ Q2 <= Q2Next;
+ end else begin
+ Q2 <= PRE2;
+ nQ2 <= PRE2 || !CLR2;
+ end
+ end
+
+endmodule
diff --git a/common/TTL/ls74.vhd b/common/TTL/ls74.vhd
new file mode 100644
index 00000000..bd5cd851
--- /dev/null
+++ b/common/TTL/ls74.vhd
@@ -0,0 +1,81 @@
+--============================================================================
+--
+-- VHDL implementation of the 74LS74 dual D-flip flop
+-- Copyright (C) 2018, 2019 Ace
+--
+-- Permission is hereby granted, free of charge, to any person obtaining a
+-- copy of this software and associated documentation files (the "Software"),
+-- to deal in the Software without restriction, including without limitation
+-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
+-- and/or sell copies of the Software, and to permit persons to whom the
+-- Software is furnished to do so, subject to the following conditions:
+--
+-- The above copyright notice and this permission notice shall be included in
+-- all copies or substantial portions of the Software.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+-- DEALINGS IN THE SOFTWARE.
+--
+--============================================================================
+
+--Chip pinout:
+/* _____________
+ _| |_
+n_clr1 |_|1 14|_| VCC
+ _| |_
+d1 |_|2 13|_| n_clr2
+ _| |_
+clk1 |_|3 12|_| d2
+ _| |_
+n_pre1 |_|4 11|_| clk2
+ _| |_
+q1 |_|5 10|_| n_pre2
+ _| |_
+n_q1 |_|6 9|_| q2
+ _| |_
+GND |_|7 8|_| n_q2
+ |_____________|
+*/
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+
+entity ls74 is
+port
+(
+ n_pre1, n_pre2 : in std_logic;
+ n_clr1, n_clr2 : in std_logic;
+ clk1, clk2 : in std_logic;
+ d1, d2 : in std_logic;
+ q1, n_q1, q2, n_q2 : buffer std_logic
+);
+end ls74;
+
+architecture arch of ls74 is
+begin
+ process(clk1, n_pre1, n_clr1) begin
+ if(n_pre1 = '0') then
+ q1 <= '1';
+ elsif(n_clr1 = '0') then
+ q1 <= '0';
+ elsif(clk1'event and clk1 = '1') then
+ q1 <= d1;
+ end if;
+ end process;
+ process(clk2, n_pre2, n_clr2) begin
+ if(n_pre2 = '0') then
+ q2 <= '1';
+ elsif(n_clr2 = '0') then
+ q2 <= '0';
+ elsif(clk2'event and clk2 = '1') then
+ q2 <= d2;
+ end if;
+ end process;
+ n_q1 <= not q1;
+ n_q2 <= not q2;
+end arch;
\ No newline at end of file
diff --git a/common/TTL/ls85.v b/common/TTL/ls85.v
new file mode 100644
index 00000000..6dee847c
--- /dev/null
+++ b/common/TTL/ls85.v
@@ -0,0 +1,37 @@
+`timescale 1ns / 1ps
+//////////////////////////////////////////////////////////////////////////////////
+// Company:
+// Engineer: Paul Wightmore
+//
+// Create Date: 22:06:05 05/14/2018
+// Design Name: LS85
+// Module Name: system86/ttl/ls85.v
+// Project Name: Namco System86 simulation
+// Target Devices:
+// Tool versions:
+// Description: LS85 - 4-Bit Magnitude Comparators
+//
+// Dependencies:
+//
+// Revision:
+// Revision 0.01 - File Created
+// Additional Comments:
+// License: https://www.apache.org/licenses/LICENSE-2.0
+//
+//////////////////////////////////////////////////////////////////////////////////
+module LS85(
+ input wire [3:0] A,
+ input wire [3:0] B,
+ output wire AgtBin,
+ output wire AeqBin,
+ output wire AltBin,
+ output wire AgtBout,
+ output wire AeqBout,
+ output wire AltBout
+ );
+
+ assign AgtBout = (A > B) || (!AeqBin && AgtBin && (A == B));
+ assign AeqBout = (A == B) && AeqBin;
+ assign AltBout = (A < B) || (!AeqBin && AltBin && (A == B));
+
+endmodule
diff --git a/common/TTL/ls86.vhd b/common/TTL/ls86.vhd
new file mode 100644
index 00000000..b21a7921
--- /dev/null
+++ b/common/TTL/ls86.vhd
@@ -0,0 +1,63 @@
+--============================================================================
+--
+-- VHDL implementation of the 74LS86 quad XOR gate
+-- Copyright (C) 2018, 2019 Ace
+--
+-- Permission is hereby granted, free of charge, to any person obtaining a
+-- copy of this software and associated documentation files (the "Software"),
+-- to deal in the Software without restriction, including without limitation
+-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
+-- and/or sell copies of the Software, and to permit persons to whom the
+-- Software is furnished to do so, subject to the following conditions:
+--
+-- The above copyright notice and this permission notice shall be included in
+-- all copies or substantial portions of the Software.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+-- DEALINGS IN THE SOFTWARE.
+--
+--============================================================================
+
+--Chip pinout:
+/* _____________
+ _| |_
+a1 |_|1 14|_| VCC
+ _| |_
+b1 |_|2 13|_| a4
+ _| |_
+y1 |_|3 12|_| b4
+ _| |_
+a2 |_|4 11|_| y4
+ _| |_
+b2 |_|5 10|_| a3
+ _| |_
+y2 |_|6 9|_| b3
+ _| |_
+GND |_|7 8|_| y3
+ |_____________|
+*/
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+
+entity ls86 is
+port
+(
+ a1, a2, a3, a4 : in std_logic;
+ b1, b2, b3, b4 : in std_logic;
+ y1, y2, y3, y4 : out std_logic
+);
+end ls86;
+
+architecture arch of ls86 is
+begin
+ y1 <= a1 xor b1;
+ y2 <= a2 xor b2;
+ y3 <= a3 xor b3;
+ y4 <= a4 xor b4;
+end arch;
\ No newline at end of file
diff --git a/common/TTL/multi74123.vhd b/common/TTL/multi74123.vhd
new file mode 100644
index 00000000..5b25f241
--- /dev/null
+++ b/common/TTL/multi74123.vhd
@@ -0,0 +1,36 @@
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+
+entity multi74123 is
+ Port ( inh_pos : in STD_LOGIC;
+ q_neg : out STD_LOGIC;
+ clk : in STD_LOGIC);
+end multi74123;
+
+architecture Behavioral of multi74123 is
+constant pulse_len : integer range 0 to 32767 := 20160;
+signal cnt : integer range 0 to 32767 := 0;
+signal inh_R : std_logic := '0';
+signal inh_R_prev : std_logic := '0';
+
+begin
+
+ process (clk) is
+ begin
+ if rising_edge(clk) then
+ if cnt>0 then
+ cnt <= cnt - 1;
+ end if;
+ inh_R_prev <= inh_R;
+ inh_R <= inh_pos;
+ if inh_R_prev = '0' and inh_R='1' then
+ cnt <= pulse_len;
+ end if;
+ end if;
+ end process;
+
+ q_neg <= '0' when (cnt>0) else '1';
+
+end Behavioral;
+
diff --git a/common/TTL/ttl_175.vhd b/common/TTL/ttl_175.vhd
new file mode 100644
index 00000000..b6459332
--- /dev/null
+++ b/common/TTL/ttl_175.vhd
@@ -0,0 +1,129 @@
+-------------------------------------------------------------------------------
+--
+-- TTL 74175 - Quad D-Type Flip-Flops with Clear
+--
+-- $Id: ttl_175.vhd,v 1.5 2005/10/10 21:59:13 arnim Exp $
+--
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2005, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity ttl_175 is
+
+ port (
+ ck_i : in std_logic;
+ ck_en_i : in std_logic;
+ por_n_i : in std_logic;
+ cl_n_i : in std_logic;
+ d_i : in std_logic_vector(4 downto 1);
+ q_o : out std_logic_vector(4 downto 1);
+ q_n_o : out std_logic_vector(4 downto 1);
+ d_o : out std_logic_vector(4 downto 1);
+ d_n_o : out std_logic_vector(4 downto 1)
+ );
+
+end ttl_175;
+
+
+architecture rtl of ttl_175 is
+
+ signal flops_q,
+ flops_s : std_logic_vector(4 downto 1);
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process flops
+ --
+ -- Purpose:
+ -- Implement the sequential elements.
+ --
+ -- Note: We assume that the sequential elements power-up to the same state
+ -- as forced into by cl_n_i.
+ --
+ flops: process (ck_i, por_n_i)
+ begin
+ if por_n_i = '0' then
+ flops_q <= (others => '0');
+ elsif ck_i'event and ck_i = '1' then
+ flops_q <= flops_s;
+ end if;
+ end process flops;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process comb
+ --
+ -- Purpose:
+ -- Implements the combinational logic.
+ --
+ comb: process (flops_q,
+ cl_n_i,
+ d_i,
+ ck_en_i)
+ begin
+ -- default assignments
+ flops_s <= flops_q;
+
+ if cl_n_i = '1' then
+ if ck_en_i = '1' then
+ flops_s <= d_i;
+ end if;
+
+ else
+ -- pseudo-asynchronous clear
+ flops_s <= (others => '0');
+ end if;
+ end process comb;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Output Mapping
+ -----------------------------------------------------------------------------
+ q_o <= flops_q;
+ q_n_o <= not flops_q;
+ d_o <= flops_s;
+ d_n_o <= not flops_s;
+
+end rtl;
diff --git a/common/TTL/ttl_393.vhd b/common/TTL/ttl_393.vhd
new file mode 100644
index 00000000..3ef25d4b
--- /dev/null
+++ b/common/TTL/ttl_393.vhd
@@ -0,0 +1,152 @@
+-------------------------------------------------------------------------------
+--
+-- TTL 74LS393 - Dual 4-Bit Binary Counter
+--
+-- $Id: ttl_393.vhd,v 1.3 2005/10/10 21:59:13 arnim Exp $
+--
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2005, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity ttl_393 is
+
+ port (
+ ck_i : in std_logic;
+ ck_en_i : in std_logic_vector(2 downto 1);
+ por_n_i : in std_logic;
+ cl_i : in std_logic_vector(2 downto 1);
+ qa_o : out std_logic_vector(2 downto 1);
+ qb_o : out std_logic_vector(2 downto 1);
+ qc_o : out std_logic_vector(2 downto 1);
+ qd_o : out std_logic_vector(2 downto 1);
+ da_o : out std_logic_vector(2 downto 1);
+ db_o : out std_logic_vector(2 downto 1);
+ dc_o : out std_logic_vector(2 downto 1);
+ dd_o : out std_logic_vector(2 downto 1)
+ );
+
+end ttl_393;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+architecture rtl of ttl_393 is
+
+ type cnt_q_t is array (natural range 2 downto 1) of unsigned(3 downto 0);
+ type cnt_d_t is array (natural range 2 downto 1) of unsigned(4 downto 0);
+ signal cnt_q : cnt_q_t;
+ signal cnt_s : cnt_d_t;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process seq
+ --
+ -- Purpose:
+ -- Implements the flip-flops.
+ --
+ -- Note: We assume that the sequential elements power-up to the same state
+ -- as forced into by cl_i.
+ --
+ seq: process (ck_i, por_n_i)
+ begin
+ if por_n_i = '0' then
+ cnt_q(1) <= (others => '0');
+ cnt_q(2) <= (others => '0');
+ elsif ck_i'event and ck_i = '1' then
+ cnt_q(1) <= cnt_s(1)(3 downto 0);
+ cnt_q(2) <= cnt_s(2)(3 downto 0);
+ end if;
+ end process seq;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process adder
+ --
+ -- Purpose:
+ -- Implements the adder.
+ --
+ adder: process (ck_en_i,
+ cl_i,
+ cnt_q)
+ begin
+ for idx in 2 downto 1 loop
+ cnt_s(idx) <= '0' & cnt_q(idx);
+
+ if cl_i(idx) = '0' then
+ if ck_en_i(idx) = '1' then
+ -- increment upon enable
+ cnt_s(idx) <= ('0' & cnt_q(idx)) + 1;
+ end if;
+
+ else
+ -- pseudo-asynchronous clear
+ cnt_s(idx) <= (others => '0');
+ end if;
+ end loop;
+ end process adder;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Output Mapping
+ -----------------------------------------------------------------------------
+ qa_o(1) <= cnt_q(1)(0);
+ qb_o(1) <= cnt_q(1)(1);
+ qc_o(1) <= cnt_q(1)(2);
+ qd_o(1) <= cnt_q(1)(3);
+ qa_o(2) <= cnt_q(2)(0);
+ qb_o(2) <= cnt_q(2)(1);
+ qc_o(2) <= cnt_q(2)(2);
+ qd_o(2) <= cnt_q(2)(3);
+ da_o(1) <= cnt_s(1)(0);
+ db_o(1) <= cnt_s(1)(1);
+ dc_o(1) <= cnt_s(1)(2);
+ dd_o(1) <= cnt_s(1)(3);
+ da_o(2) <= cnt_s(2)(0);
+ db_o(2) <= cnt_s(2)(1);
+ dc_o(2) <= cnt_s(2)(2);
+ dd_o(2) <= cnt_s(2)(3);
+
+end rtl;
diff --git a/common/TTL/ttl_74LS138.vhd b/common/TTL/ttl_74LS138.vhd
new file mode 100644
index 00000000..e2fe478a
--- /dev/null
+++ b/common/TTL/ttl_74LS138.vhd
@@ -0,0 +1,97 @@
+library IEEE;
+use IEEE.std_logic_1164.all;
+Use IEEE.std_logic_unsigned.all;
+use ieee.numeric_std.all;
+
+entity ttl_74ls138 is
+ port
+ (
+ -- input
+ a : in std_logic;
+ b : in std_logic;
+ c : in std_logic;
+
+ g1 : in std_logic;
+ g2a_n : in std_logic;
+ g2b_n : in std_logic;
+
+ -- output
+ y_n : out std_logic_vector(7 downto 0)
+ );
+end ttl_74ls138;
+
+architecture SYN of ttl_74ls138 is
+
+ signal enabled : std_logic;
+
+begin
+
+ enabled <= g1 and not g2a_n and not g2b_n;
+
+ y_n(0) <= '1' when enabled = '0' else
+ not (not a and not b and not c);
+ y_n(1) <= '1' when enabled = '0' else
+ not (a and not b and not c);
+ y_n(2) <= '1' when enabled = '0' else
+ not (not a and b and not c);
+ y_n(3) <= '1' when enabled = '0' else
+ not (a and b and not c);
+ y_n(4) <= '1' when enabled = '0' else
+ not (not a and not b and c);
+ y_n(5) <= '1' when enabled = '0' else
+ not (a and not b and c);
+ y_n(6) <= '1' when enabled = '0' else
+ not (not a and b and c);
+ y_n(7) <= '1' when enabled = '0' else
+ not (a and b and c);
+
+end SYN;
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+Use IEEE.std_logic_unsigned.all;
+use ieee.numeric_std.all;
+
+entity ttl_74ls138_p is
+ port
+ (
+ -- input
+ a : in std_logic;
+ b : in std_logic;
+ c : in std_logic;
+
+ g1 : in std_logic;
+ g2a : in std_logic;
+ g2b : in std_logic;
+
+ -- output
+ y : out std_logic_vector(7 downto 0)
+ );
+end ttl_74ls138_p;
+
+architecture SYN of ttl_74ls138_p is
+
+ signal g2a_n : std_logic;
+ signal g2b_n : std_logic;
+ signal y_n : std_logic_vector(7 downto 0);
+
+begin
+
+ g2a_n <= not g2a;
+ g2b_n <= not g2b;
+ y <= not y_n;
+
+ ttl_74ls138_inst : entity work.ttl_74ls138
+ port map
+ (
+ a => a,
+ b => b,
+ c => c,
+ g1 => g1,
+ g2a_n => g2a_n,
+ g2b_n => g2b_n,
+ y_n => y_n
+ );
+
+end SYN;
+
diff --git a/common/TTL/v74161.vhd b/common/TTL/v74161.vhd
new file mode 100644
index 00000000..6a03d402
--- /dev/null
+++ b/common/TTL/v74161.vhd
@@ -0,0 +1,43 @@
+-- 74161 counter - extended to 8 bits
+-- code found on the internet
+-- adjustments made for 8 bit counter structure
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity v74161 is
+port ( CLK, CLRN, LDN, ENP, ENT: in STD_LOGIC :='0';
+D: in UNSIGNED (7 downto 0) := "00000000";
+Q: out UNSIGNED (7 downto 0):= "00000000";
+RCO: out STD_LOGIC :='0');
+end v74161;
+
+architecture V74x161_arch of v74161 is
+ signal IQ: UNSIGNED (7 downto 0) := "00000000";
+ signal IRCO: STD_LOGIC := '0';
+ begin
+
+process (CLK, CLRN, IQ, ENT)
+begin
+
+if CLRN='0' then IQ <= "00000000";
+elsif rising_edge(CLK) then
+if LDN='0' then IQ <= D;
+elsif (ENT and ENP)='1' then IQ <= IQ + 1;
+end if;
+end if;
+
+--if (IQ=15) and (ENT='1') then IRCO <= '1';
+if (IQ=255) and (ENT='1') then IRCO <= '1';
+else IRCO <= '0';
+end if;
+
+end process;
+
+
+
+Q <= IQ;
+RCO <= IRCO;
+
+end V74x161_arch;
diff --git a/common/TTL/v74161_16bit.vhd b/common/TTL/v74161_16bit.vhd
new file mode 100644
index 00000000..efd71187
--- /dev/null
+++ b/common/TTL/v74161_16bit.vhd
@@ -0,0 +1,44 @@
+-- 74161 counter: 16 bit extended version
+-- code found on the internet
+-- adjusted to fit 16 bit counter structure
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity v74161_16bit is
+port ( CLK, CLRN, LDN, ENP, ENT: in STD_LOGIC :='0';
+D: in UNSIGNED (15 downto 0) := "0000000000000000";
+Q: out UNSIGNED (15 downto 0):= "0000000000000000";
+RCO: out STD_LOGIC :='0');
+end v74161_16bit;
+
+architecture V74x161_arch of v74161_16bit is
+ signal IQ: UNSIGNED (15 downto 0) := "0000000000000000";
+ signal IRCO: STD_LOGIC := '0';
+ begin
+
+process (CLK, CLRN, IQ, ENT)
+begin
+
+if CLRN='0' then IQ <= "0000000000000000";
+elsif rising_edge(CLK) then
+if LDN='0' then
+ IQ <= D;
+elsif (ENT and ENP)='1' then IQ <= IQ + 1;
+end if;
+end if;
+
+--if (IQ=15) and (ENT='1') then IRCO <= '1';
+
+if (IQ=65535) and (ENT='1') then IRCO <= '1';
+else IRCO <= '0';
+end if;
+
+end process;
+
+
+Q <= IQ;
+RCO <= IRCO;
+
+end V74x161_arch;
diff --git a/common/Video/CHAR_GEN.v b/common/Video/CHAR_GEN.v
new file mode 100644
index 00000000..a9d45ce9
--- /dev/null
+++ b/common/Video/CHAR_GEN.v
@@ -0,0 +1,68 @@
+module CHAR_GEN(
+ // control
+ reset,
+
+ char_code,
+ subchar_line,
+ subchar_pixel,
+
+ pixel_clock,
+ pixel_on
+);
+
+input pixel_clock;
+input reset;
+
+input [7:0] char_code;
+input [4:0] subchar_line; // line number within 12 line block
+input [3:0] subchar_pixel; // pixel position within 8 pixel block
+
+output pixel_on;
+
+reg [7:0] latched_data;
+reg pixel_on;
+
+wire [11:0] rom_addr = {char_code[7:0], subchar_line[4:1]};
+wire [7:0] rom_data;
+
+
+// instantiate the character generator ROM
+//CHAR_GEN_ROM CHAR_GEN_ROM
+//(
+// pixel_clock,
+// rom_addr,
+// rom_data
+//);
+
+sprom #(
+ .init_file("./roms/charrom_4k.mif"),
+ .widthad_a(12),
+ .width_a(8))
+CHAR_GEN_ROM(
+ .address(rom_addr),
+ .clock(pixel_clock),
+ .q(rom_data)
+ );
+
+
+// serialize the CHARACTER MODE data
+always @ (posedge pixel_clock or posedge reset) begin
+ if (reset)
+ begin
+ pixel_on = 1'b0;
+ latched_data = 8'h00;
+ end
+
+ else begin
+ case(subchar_pixel)
+ 4'b0101:
+ latched_data [7:0] = {rom_data[0],rom_data[1],rom_data[2],rom_data[3],rom_data[4],rom_data[5],rom_data[6],rom_data[7]};
+ default:
+ if(subchar_pixel[0]==1'b0)
+ {pixel_on,latched_data [7:1]} <= latched_data [7:0];
+ endcase
+ end
+
+ end
+
+endmodule //CHAR_GEN
diff --git a/common/Video/CHAR_GEN_ROM.v b/common/Video/CHAR_GEN_ROM.v
new file mode 100644
index 00000000..691de90e
--- /dev/null
+++ b/common/Video/CHAR_GEN_ROM.v
@@ -0,0 +1,19 @@
+module CHAR_GEN_ROM
+(
+ pixel_clock,
+ address,
+ data
+);
+
+input pixel_clock;
+input [11:0] address;
+output wire [7:0] data;
+
+// Character generator
+char_rom_4k_altera char_rom(
+ .address(address),
+ .clock(pixel_clock),
+ .q(data)
+);
+
+endmodule //CHAR_GEN_ROM
diff --git a/common/Video/Crtc6845_VHDL.zip b/common/Video/Crtc6845_VHDL.zip
new file mode 100644
index 00000000..38628aba
Binary files /dev/null and b/common/Video/Crtc6845_VHDL.zip differ
diff --git a/common/Video/PIXEL_DISPLAY.v b/common/Video/PIXEL_DISPLAY.v
new file mode 100644
index 00000000..585fea04
--- /dev/null
+++ b/common/Video/PIXEL_DISPLAY.v
@@ -0,0 +1,296 @@
+module PIXEL_DISPLAY (
+ pixel_clock,
+ reset,
+
+ show_border,
+
+ // mode
+ ag,
+ gm,
+ css,
+
+ // text
+ char_column,
+ char_line,
+ subchar_line,
+ subchar_pixel,
+
+ // graph
+ graph_pixel,
+ graph_line_2x,
+ graph_line_3x,
+
+ // vram
+ vram_rd_enable,
+ vram_addr,
+ vram_data,
+
+ // vga
+ vga_red,
+ vga_green,
+ vga_blue
+);
+
+input pixel_clock;
+input reset;
+
+input show_border;
+
+// mode
+input ag;
+input [2:0] gm;
+input css;
+
+// text
+input [6:0] char_column; // character number on the current line
+input [6:0] char_line; // line number on the screen
+input [4:0] subchar_line; // the line number within a character block 0-8
+input [3:0] subchar_pixel; // the pixel number within a character block 0-8
+
+// graph
+input [8:0] graph_pixel; // pixel number on the current line
+input [9:0] graph_line_2x; // line number on the screen
+input [9:0] graph_line_3x; // line number on the screen
+
+output vram_rd_enable;
+output reg [12:0] vram_addr;
+input [7:0] vram_data;
+
+output [7:0] vga_red;
+output [7:0] vga_green;
+output [7:0] vga_blue;
+
+
+//// Label Definitions ////
+
+// Note: all labels must match their defined length--shorter labels will be padded with solid blocks,
+// and longer labels will be truncated
+
+// 48 character label for the example text
+
+wire pixel_on; // high => output foreground color, low => output background color
+
+
+// 8p 代表每个点占用VGA水平 8 pixel
+// 2bit 代表每个点取2位值
+
+wire [1:0] pixel_8p_2bit; // high => output foreground color, low => output background color
+wire [1:0] pixel_4p_2bit; // high => output foreground color, low => output background color
+wire pixel_4p_1bit; // high => output foreground color, low => output background color
+wire pixel_2p_1bit; // high => output foreground color, low => output background color
+
+reg [7:0] latched_vram_data; // the data that will be written to character memory at the clock rise
+
+// 锁存数据用于选择调色板
+reg [7:0] latched_palette_data;
+
+assign vram_rd_enable = pixel_clock;
+
+reg [23:0] latched_vga_rgb;
+wire [23:0] vga_rgb;
+
+// write the appropriate character data to memory
+
+always @ (posedge pixel_clock) begin
+ if(ag==1'b0)
+ begin
+ if(subchar_pixel==4'b0001)
+ vram_addr <= {4'b0,char_line[3:0], char_column[4:0]};
+ // 对于同步sram需要等待 1 个时钟周期
+ if(subchar_pixel==4'b0011)
+ latched_vram_data <= vram_data;
+ if(graph_pixel[3:0]==4'b0110)
+ latched_palette_data <= latched_vram_data;
+ end
+ else
+ begin
+ case(gm)
+ 3'b000:
+ begin
+ // 64 x 64 x 4 gm: 000
+ if(graph_pixel[4:0]==5'b00001)
+ vram_addr <= {3'b0, graph_line_3x[9:4], graph_pixel[8:5]};
+ // 对于同步sram需要等待 1 个时钟周期
+ if(graph_pixel[4:0]==5'b00011)
+ latched_vram_data <= vram_data;
+ end
+ 3'b001:
+ begin
+ // 128 x 64 x 2 gm: 001
+ if(graph_pixel[4:0]==5'b00001)
+ vram_addr <= {3'b0, graph_line_3x[9:4], graph_pixel[8:5]};
+ // 对于同步sram需要等待 1 个时钟周期
+ if(graph_pixel[4:0]==5'b00011)
+ latched_vram_data <= vram_data;
+ end
+ 3'b011:
+ begin
+ // 128 x 96 x 2 gm: 011
+ if(graph_pixel[4:0]==5'b00001)
+ vram_addr <= {2'b0, graph_line_2x[9:3], graph_pixel[8:5]};
+ // 对于同步sram需要等待 1 个时钟周期
+ if(graph_pixel[4:0]==5'b00011)
+ latched_vram_data <= vram_data;
+ end
+ 3'b100:
+ begin
+ // 128 x 96 x 4 gm: 100
+ if(graph_pixel[3:0]==4'b0001)
+ vram_addr <= {1'b0, graph_line_2x[8:1], graph_pixel[8:4]};
+ // 对于同步sram需要等待 1 个时钟周期
+ if(graph_pixel[3:0]==4'b0011)
+ latched_vram_data <= vram_data;
+ end
+ 3'b101:
+ begin
+ // 128 x 192 x 2 gm: 101
+ if(graph_pixel[4:0]==5'b00001)
+ vram_addr <= {1'b0, graph_line_2x[9:1], graph_pixel[8:5]};
+ // 对于同步sram需要等待 1 个时钟周期
+ if(graph_pixel[4:0]==5'b00011)
+ latched_vram_data <= vram_data;
+ end
+ 3'b110:
+ begin
+ // 128 x 192 x 4 gm: 110
+ if(graph_pixel[3:0]==4'b0001)
+ vram_addr <= {graph_line_2x[9:1], graph_pixel[8:4]};
+ // 对于同步sram需要等待 1 个时钟周期
+ if(graph_pixel[3:0]==4'b0011)
+ latched_vram_data <= vram_data;
+ end
+ 3'b111:
+ begin
+ // 256 x 192 x 2 gm: 111
+ if(graph_pixel[3:0]==4'b0001)
+ vram_addr <= {graph_line_2x[9:1], graph_pixel[8:4]};
+ // 对于同步sram需要等待 1 个时钟周期
+ if(graph_pixel[3:0]==4'b0011)
+ latched_vram_data <= vram_data;
+ end
+ default:
+ begin
+ // 128 x 64 x 4 gm: 010
+ if(graph_pixel[3:0]==4'b0001)
+ vram_addr <= {2'b0,graph_line_3x[9:3], graph_pixel[8:4]};
+ //vram_addr <= {2'b0,graph_line_3x[8:3], graph_pixel[6:2]};
+ // 对于同步sram需要等待 1 个时钟周期
+ if(graph_pixel[3:0]==4'b0011)
+ latched_vram_data <= vram_data;
+ end
+ endcase
+ end
+ latched_vga_rgb <= vga_rgb;
+end
+
+// palette
+/*
+位\色 绿 黄 蓝 红 浅黄 浅蓝 紫 橙
+D6 0 0 0 0 1 1 1 1
+D5 0 0 1 1 0 0 1 1
+D4 0 1 0 1 0 1 0 1
+
+0x07 0xff 0x00 // GREEN
+0xff 0xff 0x00 // YELLOW
+0x3b 0x08 0xff // BLUE
+0xcc 0x00 0x3b // RED
+0xff 0xff 0xff // BUFF
+0x07 0xe3 0x99 // CYAN
+0xff 0x1c 0xff // MAGENTA
+0xff 0x81 0x00 // ORANGE
+
+0x00 0x00 0x00 // BLACK
+0x07 0xff 0x00 // GREEN
+0x3b 0x08 0xff // BLUE
+0xff 0xff 0xff // BUFF
+
+*/
+
+wire [2:0] palette_bit_graph;
+
+wire [23:0] palette_rgb_border = (~ag)?24'h000000: // 字符模式背景
+ (css)?24'hffffff:24'h07ff00; // 图形模式背景
+
+wire [23:0] palette_rgb_pixel = 24'h000000;
+wire [23:0] palette_rgb_background = 24'h07ff00;
+
+// 64 x 64 x 4 gm: 000
+// 128 x 64 x 2 gm: 001
+// 128 x 64 x 4 gm: 010
+// 128 x 96 x 2 gm: 011
+// 128 x 96 x 4 gm: 100
+// 128 x 192 x 2 gm: 101
+// 128 x 192 x 4 gm: 110
+// 256 x 192 x 2 gm: 111
+
+//assign palette_bit_graph = (ag)? {css, pixel_4p_2bit} : latched_palette_data[6:4];
+
+assign palette_bit_graph = (~ag) ? latched_palette_data[6:4] :
+ (gm==3'b000) ? {css, pixel_8p_2bit } :
+ (gm==3'b001) ? {css, pixel_4p_1bit, pixel_4p_1bit } :
+ (gm==3'b010) ? {css, pixel_4p_2bit } :
+ (gm==3'b011) ? {css, pixel_4p_1bit, pixel_4p_1bit } :
+ (gm==3'b100) ? {css, pixel_4p_2bit } :
+ (gm==3'b101) ? {css, pixel_4p_1bit, pixel_4p_1bit } :
+ (gm==3'b110) ? {css, pixel_4p_2bit } :
+ {css, pixel_2p_1bit, pixel_2p_1bit } ;
+
+wire [23:0] palette_rgb_graph = (palette_bit_graph==3'b000) ? 24'h07ff00 : // GREEN
+ (palette_bit_graph==3'b001) ? 24'hffff00 : // YELLOW
+ (palette_bit_graph==3'b010) ? 24'h3b08ff : // BLUE
+ (palette_bit_graph==3'b011) ? 24'hcc003b : // RED
+ (palette_bit_graph==3'b100) ? 24'hffffff : // BUFF
+ (palette_bit_graph==3'b101) ? 24'h07e399 : // CYAN
+ (palette_bit_graph==3'b110) ? 24'hff1cff : // MAGENTA
+ 24'hff8100 ; // ORANGE
+
+/*
+ 24'h000000 // BLACK
+ 24'h07ff00 // GREEN
+ 24'h3b08ff // BLUE
+ 24'hffffff // BUFF
+*/
+
+
+// use the result of the character generator module to choose between the foreground and background color
+
+assign vga_rgb = (show_border) ? palette_rgb_border :
+ (ag) ? palette_rgb_graph :
+ (~pixel_on) ? palette_rgb_pixel :
+ (latched_palette_data[7]) ? palette_rgb_graph : palette_rgb_background;
+
+assign vga_red = latched_vga_rgb[23:16];
+assign vga_green = latched_vga_rgb[15:8];
+assign vga_blue = latched_vga_rgb[7:0];
+
+
+// the character generator block includes the character RAM
+// and the character generator ROM
+CHAR_GEN CHAR_GEN
+(
+ .reset(reset), // reset signal
+
+ .char_code(latched_vram_data),
+ .subchar_line(subchar_line), // current line of pixels within current character
+ .subchar_pixel(subchar_pixel), // current column of pixels withing current character
+
+ .pixel_clock(pixel_clock), // read clock
+ .pixel_on(pixel_on) // read data
+);
+
+PIXEL_GEN PIXEL_GEN
+(
+ .reset(reset), // reset signal
+
+ .pixel_code(latched_vram_data),
+ .graph_pixel(graph_pixel), // current column of pixels withing current character
+
+ .pixel_clock(pixel_clock), // read clock
+
+ .pixel_8p_2bit(pixel_8p_2bit), // 64x64x4
+ .pixel_4p_2bit(pixel_4p_2bit), // 128x64x4 128x96x4 128x192x4
+ .pixel_4p_1bit(pixel_4p_1bit), // 128x64x2 128x96x2 128x192x2
+ .pixel_2p_1bit(pixel_2p_1bit) // 256x192x2
+);
+
+endmodule //CHAR_DISPLAY
diff --git a/common/Video/PIXEL_GEN.v b/common/Video/PIXEL_GEN.v
new file mode 100644
index 00000000..cc2f61f3
--- /dev/null
+++ b/common/Video/PIXEL_GEN.v
@@ -0,0 +1,129 @@
+module PIXEL_GEN(
+ // control
+ reset,
+
+ pixel_code,
+ graph_pixel,
+
+ pixel_clock,
+
+ pixel_8p_2bit, // 64x64x4
+ pixel_4p_2bit, // 128x64x4 128x96x4 128x192x4
+ pixel_4p_1bit, // 128x64x2 128x96x2 128x192x2
+ pixel_2p_1bit // 256x192x2
+);
+
+
+input reset;
+
+input [7:0] pixel_code;
+input [8:0] graph_pixel; // pixel number on the current line
+
+input pixel_clock;
+
+output reg [1:0] pixel_8p_2bit;
+output reg [1:0] pixel_4p_2bit;
+output reg pixel_4p_1bit;
+output reg pixel_2p_1bit;
+
+reg [7:0] latched_8p_2bit_data;
+reg [7:0] latched_4p_2bit_data;
+reg [7:0] latched_4p_1bit_data;
+reg [7:0] latched_2p_1bit_data;
+
+
+// 移位寄存器有四种模式
+// 每2个点 移 1 位
+// 每4个点 移 2 位
+// 每4个点 移 1 位
+// 每8个点 移 2 位
+
+
+// serialize the GRAPH MODE data
+always @ (posedge pixel_clock or posedge reset) begin
+ if (reset)
+ begin
+ pixel_8p_2bit <= 2'b00;
+ latched_8p_2bit_data <= 8'h00;
+ end
+ else begin
+ case(graph_pixel[4:0])
+ 5'b00101:
+ latched_8p_2bit_data[7:0] <= pixel_code;
+ default:
+ if(graph_pixel[3:0]==3'b110)
+ {pixel_8p_2bit,latched_8p_2bit_data[7:2]} <= latched_8p_2bit_data[7:0];
+ endcase
+ end
+
+ end
+
+
+// 延时:图形模式 128x64 4色
+// 1、(001)锁存 vram 地址,2、(010)读取 vram 3、(011)锁存 vram 数据 4、(100)空 5、(101)数据锁存至移位寄存器
+// 6、(110)移位得到点阵 7、(111)建立调色板,锁存色彩
+
+// serialize the GRAPH MODE data
+always @ (posedge pixel_clock or posedge reset) begin
+ if (reset)
+ begin
+ pixel_4p_2bit <= 2'b00;
+ latched_4p_2bit_data <= 8'h00;
+ end
+ else begin
+ case(graph_pixel[3:0])
+ 4'b0101:
+ latched_4p_2bit_data[7:0] <= pixel_code;
+ default:
+ if(graph_pixel[1:0]==2'b10)
+ {pixel_4p_2bit,latched_4p_2bit_data[7:2]} <= latched_4p_2bit_data[7:0];
+ endcase
+ end
+
+ end
+
+
+// serialize the GRAPH MODE data
+always @ (posedge pixel_clock or posedge reset) begin
+ if (reset)
+ begin
+ pixel_4p_1bit <= 2'b00;
+ latched_4p_1bit_data <= 8'h00;
+ end
+ else begin
+ case(graph_pixel[4:0])
+ 5'b00101:
+ latched_4p_1bit_data[7:0] <= pixel_code;
+ default:
+ if(graph_pixel[1:0]==2'b10)
+ {pixel_4p_1bit,latched_4p_1bit_data[7:1]} <= latched_4p_1bit_data[7:0];
+ endcase
+ end
+
+ end
+
+
+// 延时:图形模式 256x192 2色
+// 1、(001)锁存 vram 地址,2、(010)读取 vram 3、(011)锁存 vram 数据 4、(100)空 5、(101)数据锁存至移位寄存器
+// 6、(110)移位得到点阵 7、(111)建立调色板,锁存色彩
+
+// serialize the GRAPH MODE data
+always @ (posedge pixel_clock or posedge reset) begin
+ if (reset)
+ begin
+ pixel_2p_1bit <= 1'b0;
+ latched_2p_1bit_data <= 8'h00;
+ end
+ else begin
+ case(graph_pixel[3:0])
+ 4'b0101:
+ latched_2p_1bit_data[7:0] <= pixel_code;
+ default:
+ if(graph_pixel[0]==1'b0)
+ {pixel_2p_1bit,latched_2p_1bit_data[7:1]} <= latched_2p_1bit_data[7:0];
+ endcase
+ end
+
+ end
+
+endmodule //PIXEL_GEN
diff --git a/common/Video/SVGA_DEFINES.v b/common/Video/SVGA_DEFINES.v
new file mode 100644
index 00000000..599e568a
--- /dev/null
+++ b/common/Video/SVGA_DEFINES.v
@@ -0,0 +1,246 @@
+/*
+---------------------------------------------------------------------------------
+To select a resolution and refresh rate, remove the comments around the desired
+block in this file. The pixel clock output by the DCM module should approximately
+equal the rate specified above the timing block that is uncommented.
+---------------------------------------------------------------------------------
+*/
+
+// DEFINE THE VARIOUS PIPELINE DELAYS
+
+`define CHARACTER_DECODE_DELAY 4
+
+
+// 640 X 480 @ 60Hz with a 25.175MHz pixel clock
+`define H_ACTIVE 640 // pixels
+`define H_FRONT_PORCH 16 // pixels
+`define H_SYNCH 96 // pixels
+`define H_BACK_PORCH 48 // pixels
+`define H_TOTAL 800 // pixels
+
+`define V_ACTIVE 480 // lines
+`define V_FRONT_PORCH 11 // lines
+`define V_SYNCH 2 // lines
+`define V_BACK_PORCH 31 // lines
+`define V_TOTAL 524 // lines
+
+`define CLK_MULTIPLY 2 // 50 * 2/4 = 25.000 MHz
+`define CLK_DIVIDE 4
+
+
+/*
+// 640 X 480 @ 72Hz with a 31.500MHz pixel clock
+`define H_ACTIVE 640 // pixels
+`define H_FRONT_PORCH 24 // pixels
+`define H_SYNCH 40 // pixels
+`define H_BACK_PORCH 128 // pixels
+`define H_TOTAL 832 // pixels
+
+`define V_ACTIVE 480 // lines
+`define V_FRONT_PORCH 9 // lines
+`define V_SYNCH 3 // lines
+`define V_BACK_PORCH 28 // lines
+`define V_TOTAL 520 // lines
+
+`define CLK_MULTIPLY 5 // 50 * 5/8 = 31.250 MHz
+`define CLK_DIVIDE 8
+*/
+
+/*
+// 640 X 480 @ 75Hz with a 31.500MHz pixel clock
+`define H_ACTIVE 640 // pixels
+`define H_FRONT_PORCH 16 // pixels
+`define H_SYNCH 96 // pixels
+`define H_BACK_PORCH 48 // pixels
+`define H_TOTAL 800 // pixels
+
+`define V_ACTIVE 480 // lines
+`define V_FRONT_PORCH 11 // lines
+`define V_SYNCH 2 // lines
+`define V_BACK_PORCH 32 // lines
+`define V_TOTAL 525 // lines
+
+`define CLK_MULTIPLY 5 // 50 * 5/8 = 31.250 MHz
+`define CLK_DIVIDE 8
+*/
+
+/*
+// 640 X 480 @ 85Hz with a 36.000MHz pixel clock
+`define H_ACTIVE 640 // pixels
+`define H_FRONT_PORCH 32 // pixels
+`define H_SYNCH 48 // pixels
+`define H_BACK_PORCH 112 // pixels
+`define H_TOTAL 832 // pixels
+
+`define V_ACTIVE 480 // lines
+`define V_FRONT_PORCH 1 // lines
+`define V_SYNCH 3 // lines
+`define V_BACK_PORCH 25 // lines
+`define V_TOTAL 509 // lines
+
+`define CLK_MULTIPLY 18 // 50 * 18/25 = 36.000 MHz
+`define CLK_DIVIDE 25
+*/
+
+/*
+// 800 X 600 @ 56Hz with a 38.100MHz pixel clock
+`define H_ACTIVE 800 // pixels
+`define H_FRONT_PORCH 32 // pixels
+`define H_SYNCH 128 // pixels
+`define H_BACK_PORCH 128 // pixels
+`define H_TOTAL 1088 // pixels
+
+`define V_ACTIVE 600 // lines
+`define V_FRONT_PORCH 1 // lines
+`define V_SYNCH 4 // lines
+`define V_BACK_PORCH 14 // lines
+`define V_TOTAL 619 // lines
+
+`define CLK_MULTIPLY 16 // 50 * 16/21 = 38.095 MHz
+`define CLK_DIVIDE 21
+*/
+
+/*
+// 800 X 600 @ 60Hz with a 40.000MHz pixel clock
+`define H_ACTIVE 800 // pixels
+`define H_FRONT_PORCH 40 // pixels
+`define H_SYNCH 128 // pixels
+`define H_BACK_PORCH 88 // pixels
+`define H_TOTAL 1056 // pixels
+
+`define V_ACTIVE 600 // lines
+`define V_FRONT_PORCH 1 // lines
+`define V_SYNCH 4 // lines
+`define V_BACK_PORCH 23 // lines
+`define V_TOTAL 628 // lines
+
+`define CLK_MULTIPLY 4 // 50 * 4/5 = 40.000 MHz
+`define CLK_DIVIDE 5
+*/
+
+/*
+// 800 X 600 @ 72Hz with a 50.000MHz pixel clock
+`define H_ACTIVE 800 // pixels
+`define H_FRONT_PORCH 56 // pixels
+`define H_SYNCH 120 // pixels
+`define H_BACK_PORCH 64 // pixels
+`define H_TOTAL 1040 // pixels
+
+`define V_ACTIVE 600 // lines
+`define V_FRONT_PORCH 37 // lines
+`define V_SYNCH 6 // lines
+`define V_BACK_PORCH 23 // lines
+`define V_TOTAL 666 // lines
+
+`define CLK_MULTIPLY 2 // 50 * 2/2 = 50.000 MHz
+`define CLK_DIVIDE 2
+*/
+
+/*
+// 800 X 600 @ 75Hz with a 49.500MHz pixel clock
+`define H_ACTIVE 800 // pixels
+`define H_FRONT_PORCH 16 // pixels
+`define H_SYNCH 80 // pixels
+`define H_BACK_PORCH 160 // pixels
+`define H_TOTAL 1056 // pixels
+
+`define V_ACTIVE 600 // lines
+`define V_FRONT_PORCH 1 // lines
+`define V_SYNCH 2 // lines
+`define V_BACK_PORCH 21 // lines
+`define V_TOTAL 624 // lines
+
+`define CLK_MULTIPLY 2 // 50 * 2/2 = 50.000 MHz
+`define CLK_DIVIDE 2
+*/
+
+/*
+// 800 X 600 @ 85Hz with a 56.250MHz pixel clock
+`define H_ACTIVE 800 // pixels
+`define H_FRONT_PORCH 32 // pixels
+`define H_SYNCH 64 // pixels
+`define H_BACK_PORCH 152 // pixels
+`define H_TOTAL 1048 // pixels
+
+`define V_ACTIVE 600 // lines
+`define V_FRONT_PORCH 1 // lines
+`define V_SYNCH 3 // lines
+`define V_BACK_PORCH 27 // lines
+`define V_TOTAL 631 // lines
+
+`define CLK_MULTIPLY 9 // 50 * 9/8 = 56.250 MHz
+`define CLK_DIVIDE 8
+*/
+
+/*
+// 1024 X 768 @ 60Hz with a 65.000MHz pixel clock
+`define H_ACTIVE 1024 // pixels
+`define H_FRONT_PORCH 24 // pixels
+`define H_SYNCH 136 // pixels
+`define H_BACK_PORCH 160 // pixels
+`define H_TOTAL 1344 // pixels
+
+`define V_ACTIVE 768 // lines
+`define V_FRONT_PORCH 3 // lines
+`define V_SYNCH 6 // lines
+`define V_BACK_PORCH 29 // lines
+`define V_TOTAL 806 // lines
+
+`define CLK_MULTIPLY 13 // 50 * 13/10 = 65.000 MHz
+`define CLK_DIVIDE 10
+/*
+
+/*
+// 1024 X 768 @ 70Hz with a 75.000MHz pixel clock
+`define H_ACTIVE 1024 // pixels
+`define H_FRONT_PORCH 24 // pixels
+`define H_SYNCH 136 // pixels
+`define H_BACK_PORCH 144 // pixels
+`define H_TOTAL 1328 // pixels
+
+`define V_ACTIVE 768 // lines
+`define V_FRONT_PORCH 3 // lines
+`define V_SYNCH 6 // lines
+`define V_BACK_PORCH 29 // lines
+`define V_TOTAL 806 // lines
+
+`define CLK_MULTIPLY 3 // 50 * 3/2 = 75.000 MHz
+`define CLK_DIVIDE 2
+*/
+
+/*
+// 1024 X 768 @ 75Hz with a 78.750MHz pixel clock
+`define H_ACTIVE 1024 // pixels
+`define H_FRONT_PORCH 16 // pixels
+`define H_SYNCH 96 // pixels
+`define H_BACK_PORCH 176 // pixels
+`define H_TOTAL 1312 // pixels
+
+`define V_ACTIVE 768 // lines
+`define V_FRONT_PORCH 1 // lines
+`define V_SYNCH 3 // lines
+`define V_BACK_PORCH 28 // lines
+`define V_TOTAL 800 // lines
+
+`define CLK_MULTIPLY 11 // 50 * 11/7 = 78.571 MHz
+`define CLK_DIVIDE 7
+*/
+
+/*
+// 1024 X 768 @ 85Hz with a 94.500MHz pixel clock
+`define H_ACTIVE 1024 // pixels
+`define H_FRONT_PORCH 48 // pixels
+`define H_SYNCH 96 // pixels
+`define H_BACK_PORCH 208 // pixels
+`define H_TOTAL 1376 // pixels
+
+`define V_ACTIVE 768 // lines
+`define V_FRONT_PORCH 1 // lines
+`define V_SYNCH 3 // lines
+`define V_BACK_PORCH 36 // lines
+`define V_TOTAL 808 // lines
+
+`define CLK_MULTIPLY 17 // 50 * 17/9 = 94.444 MHz
+`define CLK_DIVIDE 9
+*/
+
diff --git a/common/Video/SVGA_TIMING_GENERATION.v b/common/Video/SVGA_TIMING_GENERATION.v
new file mode 100644
index 00000000..42a99da6
--- /dev/null
+++ b/common/Video/SVGA_TIMING_GENERATION.v
@@ -0,0 +1,353 @@
+`include "SVGA_DEFINES.v"
+
+
+`define SVGA_DECODE_DELAY 7
+// 延时:字符模式
+// 1、(001)锁存 vram 地址,2、(010)读取 vram 3、(011)锁存 vram 数据 4、(100)字库地址 5、(101)锁存字库
+// 6、(110)移位得到点阵,同时锁存vram数据用于调色板 7、(111)建立调色板,锁存色彩
+
+// Delay: Character mode
+// 1 (001) latch vram address, 2, (010) read vram 3, (011) latch vram data 4, (100) font address 5, (101) latch font
+// 6, (110) shift to get a lattice, while latching vram data for the palette 7, (111) to create a palette, latch color
+
+// 延时:图形模式 128x64 4色
+// 1、(001)锁存 vram 地址,2、(010)读取 vram 3、(011)锁存 vram 数据 4、(100)空 5、(101)数据锁存至移位寄存器
+// 6、(110)移位得到点阵 7、(111)建立调色板,锁存色彩
+
+// Delay: graphics mode 128x64 4 colors
+// 1, (001) latch vram address, 2, (010) read vram 3, (011) latch vram data 4, (100) empty 5, (101) data latched to the shift register
+// 6, (110) shift to get the dot matrix 7, (111) to create a palette, latch color
+
+module SVGA_TIMING_GENERATION
+(
+ pixel_clock,
+ reset,
+ h_synch,
+ v_synch,
+ blank,
+ pixel_count,
+ line_count,
+
+ show_border,
+
+ // text
+ subchar_pixel,
+ subchar_line,
+ char_column,
+ char_line,
+
+ // graph
+ graph_pixel,
+ graph_line_2x,
+ graph_line_3x
+);
+
+input pixel_clock; // pixel clock
+input reset; // reset
+(*keep*)output reg h_synch; // horizontal synch for VGA connector
+(*keep*)output reg v_synch; // vertical synch for VGA connector
+output reg blank; // composite blanking
+output reg [10:0] pixel_count; // counts the pixels in a line
+output reg [9:0] line_count; // counts the display lines
+
+(*keep*)output reg show_border;
+
+// 字符控制
+(*keep*)output reg [3:0] subchar_pixel; // pixel position within the character
+(*keep*)output reg [4:0] subchar_line; // identifies the line number within a character block
+(*keep*)output reg [6:0] char_column; // character number on the current line
+(*keep*)output reg [6:0] char_line; // line number on the screen
+
+// 图形控制 128*64
+(*keep*)output reg [8:0] graph_pixel;
+(*keep*)output reg [9:0] graph_line_3x;
+
+// 图形控制 256*192
+(*keep*)output reg [9:0] graph_line_2x;
+
+(*keep*)reg h_blank;
+reg v_blank;
+
+reg show_pixel;
+reg show_line;
+
+// CREATE THE HORIZONTAL LINE PIXEL COUNTER
+always @ (posedge pixel_clock or posedge reset) begin
+ if (reset)
+ // on reset set pixel counter to 0
+ pixel_count <= 11'd0;
+
+ else if (pixel_count == (`H_TOTAL - 1))
+ // last pixel in the line, so reset pixel counter
+ pixel_count <= 11'd0;
+
+ else
+ pixel_count <= pixel_count + 1;
+end
+
+// CREATE THE HORIZONTAL SYNCH PULSE
+always @ (posedge pixel_clock or posedge reset) begin
+ if (reset)
+ // on reset remove h_synch
+ h_synch <= 1'b0;
+
+ else if (pixel_count == (`H_ACTIVE + `H_FRONT_PORCH - 1))
+ // start of h_synch
+ h_synch <= 1'b1;
+
+ else if (pixel_count == (`H_TOTAL - `H_BACK_PORCH - 1))
+ // end of h_synch
+ h_synch <= 1'b0;
+end
+
+// CREATE THE VERTICAL FRAME LINE COUNTER
+always @ (posedge pixel_clock or posedge reset) begin
+ if (reset)
+ // on reset set line counter to 0
+ line_count <= 10'd0;
+
+ else if ((line_count == (`V_TOTAL - 1)) & (pixel_count == (`H_TOTAL - 1)))
+ // last pixel in last line of frame, so reset line counter
+ line_count <= 10'd0;
+
+ else if ((pixel_count == (`H_TOTAL - 1)))
+ // last pixel but not last line, so increment line counter
+ line_count <= line_count + 1;
+end
+
+// CREATE THE VERTICAL SYNCH PULSE
+always @ (posedge pixel_clock or posedge reset) begin
+ if (reset)
+ // on reset remove v_synch
+ v_synch <= 1'b0;
+
+ else if ((line_count == (`V_ACTIVE + `V_FRONT_PORCH - 1) &
+ (pixel_count == `H_TOTAL - 1)))
+ // start of v_synch
+ v_synch <= 1'b1;
+
+ else if ((line_count == (`V_TOTAL - `V_BACK_PORCH - 1)) &
+ (pixel_count == (`H_TOTAL - 1)))
+ // end of v_synch
+ v_synch <= 1'b0;
+end
+
+
+// CREATE THE HORIZONTAL BLANKING SIGNAL
+// the "-2" is used instead of "-1" because of the extra register delay
+// for the composite blanking signal
+always @ (posedge pixel_clock or posedge reset) begin
+ if (reset)
+ // on reset remove the h_blank
+ h_blank <= 1'b0;
+
+ else if (pixel_count == (`H_ACTIVE -2))
+ // start of HBI
+ h_blank <= 1'b1;
+
+ else if (pixel_count == (`H_TOTAL -2))
+ // end of HBI
+ h_blank <= 1'b0;
+end
+
+
+// CREATE THE VERTICAL BLANKING SIGNAL
+// the "-2" is used instead of "-1" in the horizontal factor because of the extra
+// register delay for the composite blanking signal
+always @ (posedge pixel_clock or posedge reset) begin
+ if (reset)
+ // on reset remove v_blank
+ v_blank <= 1'b0;
+
+ else if ((line_count == (`V_ACTIVE - 1) &
+ (pixel_count == `H_TOTAL - 2)))
+ // start of VBI
+ v_blank <= 1'b1;
+
+ else if ((line_count == (`V_TOTAL - 1)) &
+ (pixel_count == (`H_TOTAL - 2)))
+ // end of VBI
+ v_blank <= 1'b0;
+end
+
+
+// CREATE THE COMPOSITE BANKING SIGNAL
+always @ (posedge pixel_clock or posedge reset) begin
+ if (reset)
+ // on reset remove blank
+ blank <= 1'b0;
+
+ // blank during HBI or VBI
+ else if (h_blank || v_blank)
+ blank <= 1'b1;
+
+ else
+ // active video do not blank
+ blank <= 1'b0;
+end
+
+
+////////////////////////////////////////////////////
+// 以上部分内容相对固定,是VGA的控制信号和计数器 //
+////////////////////////////////////////////////////
+
+
+/*
+ CREATE THE CHARACTER COUNTER.
+ CHARACTERS ARE DEFINED WITHIN AN 8 x 8 PIXEL BLOCK.
+
+ A 640 x 480 video mode will display 80 characters on 60 lines.
+ A 800 x 600 video mode will display 100 characters on 75 lines.
+ A 1024 x 768 video mode will display 128 characters on 96 lines.
+
+ "subchar_line" identifies the row in the 8 x 8 block.
+ "subchar_pixel" identifies the column in the 8 x 8 block.
+*/
+
+// 8x12点阵 32x16个字符 256x192
+// 640x480 倍线 512x384 左右各空64个点,上下空 48 个点。
+// 需要生成四个数据:
+// 字符点阵 subchar_line subchar_pixel
+// 字符寻址 char_column char_line
+
+always @ (posedge pixel_clock or posedge reset) begin
+ if (reset)
+ show_pixel <= 1'b0;
+ else if (pixel_count == (-1) + 64 - `SVGA_DECODE_DELAY)
+ show_pixel <= 1'b1;
+ else if (pixel_count == (`H_ACTIVE - 1) - 64 - `SVGA_DECODE_DELAY)
+ show_pixel <= 1'b0;
+end
+
+always @ (posedge h_synch or posedge reset) begin
+ if (reset)
+ show_line <= 1'b0;
+ else if (line_count == (-1) + 48)
+ show_line <= 1'b1;
+ else if (line_count == (`V_ACTIVE - 1) - 48)
+ show_line <= 1'b0;
+end
+
+always @ (posedge pixel_clock or posedge reset) begin
+ if (reset)
+ show_border <= 1'b1;
+ else if (pixel_count == (-1) + 64)
+ show_border <= ~show_line;
+ else if (pixel_count == (`H_ACTIVE - 1) - 64)
+ show_border <= 1'b1;
+end
+
+
+// text 32x16
+
+always @ (posedge pixel_clock or posedge reset) begin
+ if (reset)
+ begin
+ // reset to 5 so that the first character data can be latched
+ subchar_pixel <= 4'b0000;
+ char_column <= 7'd0;
+ end
+ else if (h_synch)
+ begin
+ // reset to 5 so that the first character data can be latched
+ subchar_pixel <= 4'b0000;
+ char_column <= 7'd0;
+ end
+ else if(show_pixel)
+ begin
+ subchar_pixel <= subchar_pixel + 1;
+ if(subchar_pixel == 4'b1111) // 8*2-1
+ char_column <= char_column + 1;
+ end
+end
+
+
+always @ (posedge h_synch or posedge reset) begin
+ if (reset)
+ begin
+ // on reset set line counter to 0
+ subchar_line <= 5'b00000;
+ char_line <= 7'd0;
+ end
+ else if(v_synch)
+ begin
+ // reset line counter
+ subchar_line <= 5'b00000;
+ char_line <= 7'd0;
+ end
+ else if(show_line)
+ if(subchar_line == 5'd23) // 12*2-1
+ begin
+ subchar_line <= 5'b00000;
+ char_line <= char_line + 1;
+ end
+ else
+ // increment line counter
+ subchar_line <= subchar_line + 1;
+end
+
+
+// 为所有图形模式提供水平计数
+always @ (posedge pixel_clock or posedge reset) begin
+ if (reset)
+ begin
+ // reset to 5 so that the first character data can be latched
+ graph_pixel <= 9'd0;
+ end
+ else if (h_synch)
+ begin
+ // reset to 5 so that the first character data can be latched
+ graph_pixel <= 9'd0;
+ end
+ else if(show_pixel)
+ begin
+ graph_pixel <= graph_pixel + 1;
+ end
+end
+
+// 为图形模式提供垂直计数
+// 64x64 4色
+// 128x64 2色
+// 128x64 4色
+always @ (posedge h_synch or posedge reset) begin
+ if (reset)
+ begin
+ // on reset set line counter to 0
+ graph_line_3x <= 10'd0;
+ end
+ else if(v_synch)
+ begin
+ // reset line counter
+ graph_line_3x <= 10'd0;
+ end
+ else if(show_line)
+ if(graph_line_3x[1:0] == 2'b10) // 3行为单位计数
+ graph_line_3x <= graph_line_3x + 2;
+ else
+ // increment line counter
+ graph_line_3x <= graph_line_3x + 1;
+end
+
+// 为图形模式提供垂直计数
+// 128x96 2色
+// 128x96 4色
+// 128x192 2色
+// 128x192 4色
+// 256x192 2色
+always @ (posedge h_synch or posedge reset) begin
+ if (reset)
+ begin
+ // on reset set line counter to 0
+ graph_line_2x <= 10'd0;
+ end
+ else if(v_synch)
+ begin
+ // reset line counter
+ graph_line_2x <= 10'd0;
+ end
+ else if(show_line)
+ // increment line counter
+ graph_line_2x <= graph_line_2x + 1;
+end
+
+endmodule //SVGA_TIMING_GENERATION
diff --git a/common/Video/VIDEO_OUT.v b/common/Video/VIDEO_OUT.v
new file mode 100644
index 00000000..2c8f8a25
--- /dev/null
+++ b/common/Video/VIDEO_OUT.v
@@ -0,0 +1,70 @@
+module VIDEO_OUT
+(
+ pixel_clock,
+ reset,
+ vga_red_data,
+ vga_green_data,
+ vga_blue_data,
+ h_synch,
+ v_synch,
+ blank,
+
+ VGA_OUT_HSYNC,
+ VGA_OUT_VSYNC,
+ VGA_OUT_RED,
+ VGA_OUT_GREEN,
+ VGA_OUT_BLUE
+);
+
+input pixel_clock;
+input reset;
+input [7:0] vga_red_data;
+input [7:0] vga_green_data;
+input [7:0] vga_blue_data;
+input h_synch;
+input v_synch;
+input blank;
+
+output VGA_OUT_HSYNC;
+output VGA_OUT_VSYNC;
+output [7:0] VGA_OUT_RED;
+output [7:0] VGA_OUT_GREEN;
+output [7:0] VGA_OUT_BLUE;
+
+reg VGA_OUT_HSYNC;
+reg VGA_OUT_VSYNC;
+reg [7:0] VGA_OUT_RED;
+reg [7:0] VGA_OUT_GREEN;
+reg [7:0] VGA_OUT_BLUE;
+
+// make the external video connections
+always @ (posedge pixel_clock or posedge reset) begin
+ if (reset) begin
+ // shut down the video output during reset
+ VGA_OUT_HSYNC <= 1'b1;
+ VGA_OUT_VSYNC <= 1'b1;
+ VGA_OUT_RED <= 8'b0;
+ VGA_OUT_GREEN <= 8'b0;
+ VGA_OUT_BLUE <= 8'b0;
+ end
+
+ else if (blank) begin
+ // output black during the blank signal
+ VGA_OUT_HSYNC <= h_synch;
+ VGA_OUT_VSYNC <= v_synch;
+ VGA_OUT_RED <= 8'b0;
+ VGA_OUT_GREEN <= 8'b0;
+ VGA_OUT_BLUE <= 8'b0;
+ end
+
+ else begin
+ // output color data otherwise
+ VGA_OUT_HSYNC <= h_synch;
+ VGA_OUT_VSYNC <= v_synch;
+ VGA_OUT_RED <= vga_red_data;
+ VGA_OUT_GREEN <= vga_green_data;
+ VGA_OUT_BLUE <= vga_blue_data;
+ end
+end
+
+endmodule // VIDEO_OUT
diff --git a/common/Video/crtc6845s.v b/common/Video/crtc6845s.v
new file mode 100644
index 00000000..a3c85003
--- /dev/null
+++ b/common/Video/crtc6845s.v
@@ -0,0 +1,510 @@
+//--------------------------------------------------------------------------------------
+// CRTC6845(HD46505) CORE
+//
+// Version : beta 4
+//
+// Copyright(c) 2004 Katsumi Degawa , All rights reserved.
+// Copyright(c) 2004 Tatsuyuki Satoh , All rights reserved.
+//
+// Important !
+//
+// This program is freeware for non-commercial use.
+// An author does no guarantee about this program.
+// You can use this under your own risk.
+//
+// VerilogHDL model of MC6845(HD46505) compatible CRTC.
+// This was made for FPGA-GAME(ROCK-OLA).
+// Therefore. There is a limitation in the function.
+// 1. This doesn't implement interlace mode.
+// 2. This doesn't implement light pen detection founction.
+// 3. This doesn't implement cursor control founction.
+//
+// 4. This doesn't implement display sque (HD46505SP)
+// 5. This doesn't support case Nht==0
+//
+// File History
+// 2005. 4. 5 by T.satoh
+// bugfix port size mismatch
+// 2005. 1.13 by T.satoh
+// bugfix VSYNC pulse width (line to raster)
+// bugfix NEXT_R_RA bit size mismatch.
+// 2004.12. 9 by T.satoh
+// rewrite source with minimize code. (178 -> 119 slice to Spartan3 with Area optimize)
+// bugfix , bypass wite register 10H-1FH ( R_ADR width change 5bit from 4bit).
+// fix register mismatch width W_Nr,O_Nr,Nvt,Nvd and Nvsp.
+// change R_V_CNT width 9bit to 7bit.
+//
+// 2004.10.23 First release
+//--------------------------------------------------------------------------------------
+
+
+module crtc6845s #(
+ // type 0 : 6845 - Based on MC6845 datasheet
+ // - Super-80
+ // type 1 : 6845-1 - supports vsync pulse width
+ // - Rockola, BBC Micro
+ // type 2 : 6545-1 - supports vsync pulse width
+ // - Microbee
+ parameter device_type = 1
+) (
+// INPUT
+I_E,
+I_DI,
+I_RS,
+I_RWn,
+I_CSn,
+I_CLK,
+I_RSTn,
+I_LPSTB,
+
+// OUTPUT
+O_DO,
+O_RA,
+O_MA,
+O_H_SYNC,
+O_V_SYNC,
+O_DISPTMG,
+O_CURSOR
+
+);
+
+input I_E;
+input [7:0]I_DI;
+input I_RS;
+input I_RWn;
+input I_CSn;
+
+input I_CLK;
+input I_RSTn;
+
+input I_LPSTB;
+
+output [7:0]O_DO;
+output [4:0]O_RA;
+output [13:0]O_MA;
+output O_H_SYNC;
+output O_V_SYNC;
+output O_DISPTMG;
+
+output O_CURSOR;
+
+wire [7:0]W_Nht;
+wire [7:0]W_Nhd;
+wire [7:0]W_Nhsp;
+wire [3:0]W_Nhsw;
+wire [6:0]W_Nvt;
+wire [4:0]W_Nadj;
+wire [6:0]W_Nvd;
+wire [6:0]W_Nvsp;
+wire [3:0]W_Nvsw;
+wire [4:0]W_Nr;
+wire [13:0]W_Msa;
+
+wire W_Vmode;
+wire W_IntSync;
+wire [1:0] W_DScue;
+wire [1:0] W_CScue;
+
+wire [7:6] W_STS;
+
+mpu_if # (
+.device_type(device_type)
+) mpu_if (
+
+.I_RSTn(I_RSTn),
+.I_E(I_E),
+.I_DI(I_DI),
+.I_RS(I_RS),
+.I_RWn(I_RWn),
+.I_CSn(I_CSn),
+.I_STS(W_STS),
+
+.O_DO(O_DO),
+.O_Nht(W_Nht),
+.O_Nhd(W_Nhd),
+.O_Nhsp(W_Nhsp),
+.O_Nhsw(W_Nhsw),
+.O_Nvt(W_Nvt),
+.O_Nadj(W_Nadj),
+.O_Nvd(W_Nvd),
+.O_Nvsp(W_Nvsp),
+.O_Nvsw(W_Nvsw),
+.O_Nr(W_Nr),
+.O_Msa(W_Msa),
+
+.O_VMode(W_Vmode),
+.O_IntSync(W_IntSync),
+// HD46505-SP only
+.O_DScue(W_DScue),
+.O_CScue(W_CScue),
+.O_LPRd(W_LPRd)
+);
+
+crtc_gen crtc_gen(
+
+.I_CLK(I_CLK),
+.I_RSTn(I_RSTn),
+.I_Nht(W_Nht),
+.I_Nhd(W_Nhd),
+.I_Nhsp(W_Nhsp),
+.I_Nhsw(W_Nhsw),
+.I_Nvt(W_Nvt),
+.I_Nadj(W_Nadj),
+.I_Nvd(W_Nvd),
+.I_Nvsp(W_Nvsp),
+.I_Nvsw(W_Nvsw),
+.I_Nr(W_Nr),
+.I_Msa(W_Msa),
+.I_LPSTB(I_LPSTB),
+.I_LPRd(W_LPRd),
+
+.O_STS(W_STS),
+.O_RA(O_RA),
+.O_MA(O_MA),
+.O_H_SYNC(O_H_SYNC),
+.O_V_SYNC(O_V_SYNC),
+.O_DISPTMG(O_DISPTMG)
+
+);
+
+endmodule
+
+
+module mpu_if #(
+ parameter device_type
+)(
+
+I_RSTn,
+I_E,
+I_DI,
+I_RS,
+I_RWn,
+I_CSn,
+I_STS,
+
+O_DO,
+O_Nht,
+O_Nhd,
+O_Nhsp,
+O_Nhsw,
+O_Nvt,
+O_Nadj,
+O_Nvd,
+O_Nvsp,
+O_Nvsw,
+O_Nr,
+O_Msa,
+
+O_DScue,
+O_CScue,
+O_VMode,
+O_IntSync,
+O_LPRd
+);
+
+input I_RSTn;
+input I_E;
+input [7:0]I_DI;
+input I_RS;
+input I_RWn;
+input I_CSn;
+input [6:5]I_STS;
+
+output [7:0]O_DO;
+output [7:0]O_Nht;
+output [7:0]O_Nhd;
+output [7:0]O_Nhsp;
+output [3:0]O_Nhsw;
+output [6:0]O_Nvt;
+output [4:0]O_Nadj;
+output [6:0]O_Nvd;
+output [6:0]O_Nvsp;
+output [3:0]O_Nvsw;
+output [4:0]O_Nr;
+output [13:0]O_Msa;
+output [1:0] O_DScue;
+output [1:0] O_CScue;
+output O_VMode;
+output O_IntSync;
+output O_LPRd;
+
+reg [7:0]R_DO;
+reg [4:0]R_ADR;
+reg [7:0]R_Nht;
+reg [7:0]R_Nhd;
+reg [7:0]R_Nhsp;
+reg [7:0]R_Nsw;
+reg [6:0]R_Nvt;
+reg [4:0]R_Nadj;
+reg [6:0]R_Nvd;
+reg [6:0]R_Nvsp;
+reg [7:0]R_Intr;
+reg [4:0]R_Nr;
+reg [5:0]R_Msah;
+reg [7:0]R_Msal;
+reg [7:0]R_Curh;
+reg [7:0]R_Curl;
+reg [7:0]R_Lph;
+reg [7:0]R_Lpl;
+reg R_LPRd;
+
+assign O_DO = R_DO;
+assign O_Nht = R_Nht;
+assign O_Nhd = R_Nhd;
+assign O_Nhsp = R_Nhsp;
+assign O_Nhsw = R_Nsw[3:0];
+assign O_Nvt = R_Nvt;
+assign O_Nadj = R_Nadj;
+assign O_Nvd = R_Nvd;
+assign O_Nvsp = R_Nvsp;
+assign O_Nvsw = R_Nsw[7:4];
+assign O_Nr = R_Nr;
+assign O_Msa = {R_Msah,R_Msal};
+assign O_VMode = R_Intr[1];
+assign O_IntSync = R_Intr[0];
+// HD46505-SP only
+assign O_DScue = R_Intr[5:4]; // disp scue 0,1,2 or OFF
+assign O_CScue = R_Intr[7:6]; // cursor scue 0,1,2 or OFF
+assign O_LPRd = R_LPRd;
+
+always@(negedge I_RSTn or negedge I_E)
+begin
+ if(~I_RSTn) begin
+ R_DO <= 8'h00;
+ // this is currently set for "non-interlace MODE 7"
+ // - it's a fudge because this controller doesn't support interlace
+ R_Nht <= 8'h3F; // 0
+ R_Nhd <= 8'h28; // 1
+ R_Nhsp <= 8'h33; // 2
+ // device_type=0 should default R_Nsw[7:4] to 16!
+ //R_Nsw <= 8'h24; // 3
+ R_Nsw <= 8'h44; // 3
+ R_Nvt <= 7'h1E; // 4
+ R_Nadj <= 5'h02; // 5
+ R_Nvd <= 7'h19; // 6
+ R_Nvsp <= 7'h1B; //1C; // 7
+ R_Intr <= 8'h91; //93; // 8
+ R_Nr <= 5'h09; //12; // 9
+ R_Msah <= 6'h28; // 12
+ R_Msal <= 8'h00; // 13
+ end else
+ begin
+ // Read-reset bit
+ // - reads on R16,R17
+ if (~I_CSn & I_RWn & I_RS & (R_ADR[4:1] == 4'b1000))
+ R_LPRd <= 1'b1;
+ else
+ R_LPRd <= 1'b0;
+
+ if(~I_CSn)begin
+ if(I_RWn)begin
+ // reads
+ if(~I_RS)
+ R_DO <= { 1'b0, I_STS, 5'b0 };
+ end else begin
+ // writes
+ if(~I_RS)begin
+ R_ADR <= I_DI[4:0];
+ end else begin
+ case(R_ADR)
+ 5'h0 : R_Nht <= I_DI ;
+ 5'h1 : R_Nhd <= I_DI ;
+ 5'h2 : R_Nhsp <= I_DI ;
+ 5'h3 : R_Nsw <= (device_type == 0
+ ? { R_Nsw[7:4], I_DI[3:0] }
+ : I_DI) ;
+ 5'h4 : R_Nvt <= I_DI[6:0] ;
+ 4'h5 : R_Nadj <= I_DI[4:0] ;
+ 5'h6 : R_Nvd <= I_DI[6:0] ;
+ 5'h7 : R_Nvsp <= I_DI[6:0] ;
+ 5'h8 : R_Intr <= I_DI[7:0] ;
+ 5'h9 : R_Nr <= I_DI[4:0] ;
+ 5'hC : R_Msah <= I_DI[5:0] ;
+ 5'hD : R_Msal <= I_DI ;
+ default:;
+ endcase
+ end
+ end
+ end
+ end
+end
+
+endmodule
+
+module crtc_gen(
+
+I_CLK,
+I_RSTn,
+I_Nht,
+I_Nhd,
+I_Nhsp,
+I_Nhsw,
+I_Nvt,
+I_Nadj,
+I_Nvd,
+I_Nvsp,
+I_Nvsw,
+I_Nr,
+I_Msa,
+I_LPSTB,
+I_LPRd,
+
+O_STS,
+O_RA,
+O_MA,
+O_H_SYNC,
+O_V_SYNC,
+O_DISPTMG
+
+);
+
+input I_CLK;
+input I_RSTn;
+input [7:0]I_Nht;
+input [7:0]I_Nhd;
+input [7:0]I_Nhsp;
+input [3:0]I_Nhsw;
+input [6:0]I_Nvt;
+input [4:0]I_Nr;
+input [4:0]I_Nadj; // (I_Nadj-1 <= I_Nr) is Support. (I_Nadj-1 > I_Nr) is Not Support.
+input [6:0]I_Nvd;
+input [6:0]I_Nvsp;
+input [3:0]I_Nvsw;
+input [13:0]I_Msa;
+input I_LPSTB;
+input I_LPRd;
+
+output [6:5]O_STS;
+output [4:0]O_RA;
+output [13:0]O_MA;
+output O_H_SYNC;
+output O_V_SYNC;
+output O_DISPTMG;
+
+reg [7:0]R_H_CNT;
+reg [6:0]R_V_CNT;
+reg [4:0]R_RA;
+reg [13:0]R_MA;
+reg R_H_SYNC,R_V_SYNC;
+reg R_DISPTMG ,R_V_DISPTMG;
+reg R_LAST_LINE;
+
+// next count value (cnt+1)
+wire [7:0] NEXT_R_H_CNT = (R_H_CNT+8'h01);
+wire [6:0] NEXT_R_V_CNT = (R_V_CNT+7'h01);
+wire [4:0] NEXT_R_RA = R_RA + 1;
+
+// h return trigger
+wire W_HD = (R_H_CNT==I_Nht);
+
+// v return trigger
+wire W_VD = (R_V_CNT==I_Nvt);
+wire W_ADJ_C = R_LAST_LINE & (NEXT_R_RA==I_Nadj);
+wire W_VCNT_RET = ((R_RA==I_Nr) & (I_Nadj==0) & W_VD) | W_ADJ_C;
+
+// RA return trigger
+wire W_RA_C = (R_RA==I_Nr) | W_ADJ_C;
+
+// sync trigger
+wire W_HSYNC_P = (NEXT_R_H_CNT == I_Nhsp);
+wire W_HSYNC_W = (NEXT_R_H_CNT[3:0] == (I_Nhsp[3:0]+I_Nhsw) );
+wire W_VSYNC_P = (NEXT_R_V_CNT == I_Nvsp ) & W_RA_C;
+wire W_VSYNC_W = (NEXT_R_RA[3:0]==I_Nvsw);
+
+// disp trigger
+wire W_HDISP_N = (NEXT_R_H_CNT==I_Nhd);
+wire W_VDISP_N = (NEXT_R_V_CNT==I_Nvd) & W_RA_C;
+
+//output assign
+assign O_H_SYNC = R_H_SYNC;
+assign O_V_SYNC = R_V_SYNC;
+assign O_RA = R_RA;
+assign O_MA = R_MA;
+assign O_DISPTMG = R_DISPTMG;
+
+// MA MAX = 14'h3FFF ---------------------
+reg [13:0] R_MA_C;
+always@(negedge I_CLK or negedge I_RSTn)
+begin
+ if(! I_RSTn)begin
+ R_MA <= 14'h0000;
+ R_MA_C <= 14'h0000;
+ R_H_CNT <= 8'h00;
+ R_H_SYNC <= 0;
+ R_RA <= 5'h00;
+
+ R_V_CNT <= 7'h00;
+ R_LAST_LINE <= 1'b0;
+ R_V_SYNC <= 0;
+
+ R_V_DISPTMG <= 1'b0;
+ R_DISPTMG <= 1'b0;
+ end
+ else begin
+ // H CNT
+ R_H_CNT <= W_HD ? 8'h00 : NEXT_R_H_CNT;
+
+ // MA
+ R_MA <= W_HD ? R_MA_C : R_MA + 1;
+
+ // MA return address
+ if(W_RA_C & (R_H_CNT==I_Nhd) )
+ R_MA_C <= W_VCNT_RET ? I_Msa : R_MA;
+
+ // HSYNC
+ if(W_HSYNC_P) R_H_SYNC <= 1'b1;
+ else if(W_HSYNC_W) R_H_SYNC <= 1'b0;
+
+ // H RETURN
+ if(W_HD)
+ begin
+ // RA
+ R_RA <= W_RA_C ? 5'h00 : NEXT_R_RA;
+
+ // VSYNC
+ if(W_VSYNC_P) R_V_SYNC <= 1'b1;
+ else if(W_VSYNC_W) R_V_SYNC <= 1'b0;
+
+ if(W_RA_C)
+ begin
+ // for adjust line
+ R_LAST_LINE <= W_VD;
+
+ // V CNT
+ R_V_CNT <= W_VCNT_RET ? 7'h00 : NEXT_R_V_CNT;
+ end
+ end
+
+ // V DISPTMG (next line)
+ if(W_VCNT_RET) R_V_DISPTMG <= 1'b1;
+ else if(W_VDISP_N) R_V_DISPTMG <= 1'b0;
+
+ // H & V DISPTMG
+ if(W_HD) R_DISPTMG <= R_V_DISPTMG;
+ else if(W_HDISP_N) R_DISPTMG <= 1'b0;
+ end
+end
+
+reg R_LPSTB;
+reg [6:5] R_STS;
+
+always @(negedge I_RSTn or negedge I_CLK)
+begin
+ if (~I_RSTn)
+ begin
+ R_STS <= 2'b00;
+ end else begin
+ // negedge I_CLK
+ if (I_LPSTB & ~R_LPSTB)
+ R_STS[6] <= 1'b1;
+ else if (I_LPRd)
+ R_STS[6] <= 1'b0;
+ R_STS[5] <= ~R_V_DISPTMG;
+ end
+ // edge-detect
+ R_LPSTB <= I_LPSTB;
+end
+
+assign O_STS = R_STS;
+
+endmodule
diff --git a/common/Video/ctc.vhd b/common/Video/ctc.vhd
new file mode 100644
index 00000000..29ab8a4e
--- /dev/null
+++ b/common/Video/ctc.vhd
@@ -0,0 +1,137 @@
+-- Copyright (c) 2015, $ME
+-- All rights reserved.
+--
+-- Redistribution and use in source and synthezised forms, with or without modification, are permitted
+-- provided that the following conditions are met:
+--
+-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions
+-- and the following disclaimer.
+--
+-- 2. Redistributions in synthezised form must reproduce the above copyright notice, this list of conditions
+-- and the following disclaimer in the documentation and/or other materials provided with the distribution.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+-- WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+-- ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+-- TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+-- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+--
+-- implementation of a z80 ctc
+--
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+
+entity ctc is
+ generic (
+ sysclk : integer := 500000; -- 50MHz
+ ctcclk : integer := 24576 -- 2.4576MHz
+ );
+ port (
+ clk : in std_logic;
+ res_n : in std_logic; -- negative
+ en : in std_logic; -- negative
+
+ dIn : in std_logic_vector(7 downto 0);
+ dOut : out std_logic_vector(7 downto 0);
+
+ cs : in std_logic_vector(1 downto 0);
+ m1_n : in std_logic; -- negative
+ iorq_n : in std_logic; -- negative
+ rd_n : in std_logic; -- negative
+
+ int : out std_logic_vector(3 downto 0);
+ intAck : in std_logic_vector(3 downto 0);
+
+ clk_trg : in std_logic_vector(3 downto 0);
+ zc_to : out std_logic_vector(3 downto 0);
+ kcSysClk : out std_logic
+ );
+end ctc;
+
+architecture rtl of ctc is
+ type byteArray is array (natural range <>) of std_logic_vector(7 downto 0);
+
+ signal clkCounter : integer range 0 to sysclk+ctcclk-1 := 0;
+ signal ctcClkEn : std_logic := '0';
+
+ signal cEn : std_logic_vector(3 downto 0);
+ signal cDOut : byteArray(3 downto 0);
+ signal cSetTC : std_logic_vector(3 downto 0);
+ signal setTC : std_logic;
+
+ signal irqVect : std_logic_vector(7 downto 3) := (others => '0');
+
+ signal intAckChannel : std_logic_vector(1 downto 0);
+
+begin
+ kcSysClk <= ctcClkEn;
+
+ intAckChannel <=
+ "00" when intAck(0)='1' else
+ "01" when intAck(1)='1' else
+ "10" when intAck(2)='1' else
+ "11";
+
+ dOut <=
+ irqVect & intAckChannel & "0" when intAck/="0000" else -- int acknowledge
+ cDOut(0) when cEn(0)='1' else
+ cDOut(1) when cEn(1)='1' else
+ cDOut(2) when cEn(2)='1' else
+ cDOut(3);
+
+ setTC <=
+ cSetTC(0) when cs="00" else
+ cSetTC(1) when cs="01" else
+ cSetTC(2) when cs="10" else
+ cSetTC(3);
+
+ -- generate clock for ctc timer
+ clkGen : process
+ begin
+ wait until rising_edge(clk);
+
+ if (clkCounter>=sysclk-ctcclk) then
+ clkCounter <= clkCounter - sysclk + ctcclk;
+ ctcClkEn <= '1';
+ else
+ clkCounter <= clkCounter + ctcclk;
+ ctcClkEn <= '0';
+ end if;
+ end process;
+
+ cpuInt : process
+ begin
+ wait until rising_edge(clk);
+
+ if (en='0' and rd_n='1' and iorq_n='0' and m1_n='1' and dIn(0)='0' and setTC='0') then -- set irq vector
+ irqVect <= dIn(7 downto 3);
+ end if;
+ end process;
+
+ channels: for i in 0 to 3 generate
+ channel : entity work.ctc_channel
+ port map (
+ clk => clk,
+ res_n => res_n,
+ en => cEn(i),
+
+ dIn => dIn,
+ dOut => cDOut(i),
+
+ rd_n => rd_n,
+
+ int => int(i),
+ setTC => cSetTC(i),
+ ctcClkEn => ctcClkEn,
+ clk_trg => clk_trg(i),
+ zc_to => zc_to(i)
+ );
+
+ cEn(i) <= '1' when (en='0' and iorq_n='0' and m1_n='1' and to_integer(unsigned(cs))=i) else '0';
+ end generate;
+end;
\ No newline at end of file
diff --git a/common/Video/ctc_channel.vhd b/common/Video/ctc_channel.vhd
new file mode 100644
index 00000000..74be74e0
--- /dev/null
+++ b/common/Video/ctc_channel.vhd
@@ -0,0 +1,172 @@
+-- Copyright (c) 2015, $ME
+-- All rights reserved.
+--
+-- Redistribution and use in source and synthezised forms, with or without modification, are permitted
+-- provided that the following conditions are met:
+--
+-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions
+-- and the following disclaimer.
+--
+-- 2. Redistributions in synthezised form must reproduce the above copyright notice, this list of conditions
+-- and the following disclaimer in the documentation and/or other materials provided with the distribution.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+-- WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+-- ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+-- TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+-- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+--
+-- single ctc channel
+--
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+
+entity ctc_channel is
+ port (
+ clk : in std_logic;
+ res_n : in std_logic;
+ en : in std_logic;
+
+ dIn : in std_logic_vector(7 downto 0);
+ dOut : out std_logic_vector(7 downto 0);
+
+ rd_n : in std_logic;
+
+ int : out std_logic;
+ setTC : out std_logic;
+
+ ctcClkEn : in std_logic;
+ clk_trg : in std_logic;
+ zc_to : out std_logic
+ );
+end ctc_channel;
+
+architecture rtl of ctc_channel is
+ type states is (default, setTimeConstant);
+ signal state : states := default;
+ signal nextState : states := default;
+
+ signal control : std_logic_vector(7 downto 3) := (others => '0');
+
+ signal preDivider : integer range 0 to 255 := 0;
+ signal preDivVect : std_logic_vector(7 downto 0);
+ signal edgeDet : std_logic_vector(1 downto 0);
+
+ signal dCounter : integer range 0 to 256 := 0;
+ signal timeConstant : integer range 1 to 256 := 256;
+
+ signal triggerIrq : boolean := false;
+ signal running : boolean := false;
+ signal startUp : boolean := true;
+
+begin
+ setTC <= '1' when state=setTimeConstant else '0';
+ dOut <= std_logic_vector(to_unsigned(dCounter, dOut'length)); -- CTC Read
+
+ int <= '1' when triggerIrq and control(7)='1' else '0';
+
+-- zc_to <= '1' when control(7)='1' else '0';
+-- zc_to <= edgeDet(1);
+
+ preDivVect <= std_logic_vector(to_unsigned(preDivider, preDivVect'length));
+
+ -- ctc counter
+ counter : process
+ variable cntrEvent : boolean;
+ begin
+ wait until rising_edge(clk);
+
+ if (ctcClkEn='1') then
+ if (preDivider=255) then
+ preDivider <= 0;
+ else
+ preDivider <= preDivider + 1;
+ end if;
+ end if;
+
+ -- edgeDetector
+ if (control(6 downto 5)="00") then -- Timer mode + Prescaler 16
+ edgeDet(0) <= preDivVect(3);
+ elsif (control(6 downto 5)="01") then -- Timer mode + Prescaler 256
+ edgeDet(0) <= preDivVect(7);
+ else -- Counter mode
+ edgeDet(0) <= clk_trg;
+ end if;
+ edgeDet(1) <= edgeDet(0);
+
+ triggerIrq <= false;
+ cntrEvent := false;
+
+ if (running) then
+ if (edgeDet="01") then
+ cntrEvent := true;
+ end if;
+
+ if (startUp) then
+ startUp <= false;
+ dCounter <= timeConstant;
+ elsif (cntrEvent) then
+ if (dCounter = 1) then -- next count 0 => reload
+ dCounter <= timeConstant;
+ triggerIrq <= true;
+ zc_to <= '1';
+ else
+ dCounter <= dCounter - 1;
+ zc_to <= '0';
+ end if;
+ end if;
+ else
+ edgeDet <= (others => '0');
+ startUp <= true;
+ dCounter <= 0;
+ preDivider <= 0;
+ triggerIrq <= false;
+ zc_to <= '0';
+ end if;
+ end process;
+
+ -- cpu-interface
+ cpu : process
+ variable tcData : integer range 0 to 255;
+ begin
+ wait until rising_edge(clk);
+
+ if (res_n='0') then
+ nextState <= default;
+ running <= false;
+ timeConstant <= 256;
+ elsif (en='1') then
+ if (rd_n='1') then -- CTC Write
+ if (state=setTimeConstant) then -- set Time Constant
+ nextState <= default;
+ running <= true;
+
+ tcData := to_integer(unsigned(dIn));
+ if (tcData=0) then
+ timeConstant <= 256;
+ else
+ timeConstant <= to_integer(unsigned(dIn));
+ end if;
+
+ elsif (dIn(0)='1') then
+ control <= dIn(7 downto 3);
+
+ if (dIn(2)='1') then -- Time Constant Follows
+ nextState <= setTimeConstant;
+ end if;
+
+ if (dIn(1)='1') then -- reset
+ running <= false;
+ end if;
+ end if;
+ end if;
+ else
+ state <= nextState;
+ end if;
+ end process;
+end;
\ No newline at end of file
diff --git a/common/Video/cursor.vhd b/common/Video/cursor.vhd
new file mode 100644
index 00000000..b096e658
--- /dev/null
+++ b/common/Video/cursor.vhd
@@ -0,0 +1,93 @@
+--===========================================================================--
+-- --
+-- S Y N T H E S I Z A B L E CRTC6845 C O R E --
+-- --
+-- www.opencores.org - January 2000 --
+-- This IP core adheres to the GNU public license. --
+-- --
+-- VHDL model of MC6845 compatible CRTC --
+-- --
+-- This model doesn't implement interlace mode. Everything else is --
+-- (probably) according to original MC6845 data sheet (except VTOTADJ). --
+-- --
+-- Implementation in Xilinx Virtex XCV50-6 runs at 50 MHz (character clock).--
+-- With external pixel generator this CRTC could handle 450MHz pixel rate --
+-- (see MC6845 datasheet for typical application). --
+-- --
+-- Author: Damjan Lampret, lampret@opencores.org --
+-- --
+-- TO DO: --
+-- --
+-- - fix REG_INIT and remove non standard signals at topl level entity. --
+-- Allow fixed registers values (now set with REG_INIT). Anyway cleanup --
+-- required. --
+-- --
+-- - split design in four units (horizontal sync, vertical sync, bus --
+-- interface and the rest) --
+-- --
+-- - synthesis with Synplify pending (there are some problems with --
+-- UNSIGNED and BIT_LOGIC_VECTOR types in some units !) --
+-- --
+-- - testbench --
+-- --
+-- - interlace mode support, extend VSYNC for V.Total Adjust value (R5) --
+-- --
+-- - verification in a real application --
+-- --
+--===========================================================================--
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.std_logic_arith.all;
+
+entity cursor_ctrl is
+ generic (
+ RA_WIDTH : natural := 5
+ );
+ port (
+ RESETn : in STD_LOGIC;
+ CLK : in STD_LOGIC;
+ RA : in STD_LOGIC_VECTOR (RA_WIDTH-1 downto 0);
+ CURSOR : out STD_LOGIC;
+ ACTIVE : in STD_LOGIC;
+ CURST : in STD_LOGIC_VECTOR (6 downto 0);
+ CUREND : in STD_LOGIC_VECTOR (4 downto 0)
+ );
+end cursor_ctrl;
+
+architecture cursor_ctrl_behav of cursor_ctrl is
+
+signal CTR_BLINK : UNSIGNED (4 downto 0);
+begin
+
+blink_ctr_p:
+process (CLK, RESETn)
+begin
+ if RESETn = '0' then
+ CTR_BLINK <= (others => '0');
+ elsif rising_edge(CLK) then
+ CTR_BLINK <= CTR_BLINK + 1;
+ end if;
+end process;
+
+cursor_p:
+process (ACTIVE, CURST, CUREND, RA, CTR_BLINK)
+begin
+ if RA >= CURST(4 downto 0) and RA <= CUREND and ACTIVE = '1' then
+ case CURST(6 downto 5) is
+ when "00" =>
+ CURSOR <= '1';
+ when "10" =>
+ CURSOR <= CTR_BLINK(3);
+ when "11" =>
+ CURSOR <= CTR_BLINK(4);
+ when others =>
+ CURSOR <= '0';
+ end case;
+ else
+ CURSOR <= '0';
+ end if;
+end process;
+
+end cursor_ctrl_behav;
+
diff --git a/common/Video/i8244/i8244_charset_rom-c.vhd b/common/Video/i8244/i8244_charset_rom-c.vhd
new file mode 100644
index 00000000..6dfa8b7e
--- /dev/null
+++ b/common/Video/i8244/i8244_charset_rom-c.vhd
@@ -0,0 +1,14 @@
+-------------------------------------------------------------------------------
+--
+-- i8244 Video Display Controller
+--
+-- $Id: i8244_charset_rom-c.vhd,v 1.2 2007/02/05 21:57:37 arnim Exp $
+--
+-------------------------------------------------------------------------------
+
+configuration i8244_charset_rom_rtl_c0 of i8244_charset_rom is
+
+ for rtl
+ end for;
+
+end i8244_charset_rom_rtl_c0;
diff --git a/common/Video/i8244/i8244_charset_rom.vhd b/common/Video/i8244/i8244_charset_rom.vhd
new file mode 100644
index 00000000..03257819
--- /dev/null
+++ b/common/Video/i8244/i8244_charset_rom.vhd
@@ -0,0 +1,174 @@
+-------------------------------------------------------------------------------
+--
+-- i8244 Video Display Controller
+--
+-- $Id: i8244_charset_rom.vhd,v 1.5 2007/02/05 22:08:59 arnim Exp $
+--
+-- Built-in charater set ROM
+--
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2007, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity i8244_charset_rom is
+
+ port (
+ clk_i : in std_logic;
+ rom_addr_i : in std_logic_vector(8 downto 0);
+ rom_en_i : in std_logic;
+ rom_data_o : out std_logic_vector(7 downto 0)
+ );
+
+end i8244_charset_rom;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+architecture rtl of i8244_charset_rom is
+
+ subtype payload_t is natural range 0 to 255;
+ type rom_cont_t is array (natural range 0 to 511) of
+ payload_t;
+ constant rom_cont_c : rom_cont_t := (
+ 16#7C#,16#C6#,16#C6#,16#C6#,16#C6#,16#C6#,16#7C#,16#00#,
+ 16#18#,16#38#,16#18#,16#18#,16#18#,16#18#,16#3C#,16#00#,
+ 16#3C#,16#66#,16#0C#,16#18#,16#30#,16#60#,16#7E#,16#00#,
+ 16#7C#,16#C6#,16#06#,16#3C#,16#06#,16#C6#,16#7C#,16#00#,
+ 16#CC#,16#CC#,16#CC#,16#FE#,16#0C#,16#0C#,16#0C#,16#00#,
+ 16#FE#,16#C0#,16#C0#,16#7C#,16#06#,16#C6#,16#7C#,16#00#,
+ 16#7C#,16#C6#,16#C0#,16#FC#,16#C6#,16#C6#,16#7C#,16#00#,
+ 16#FE#,16#06#,16#0C#,16#18#,16#30#,16#60#,16#C0#,16#00#,
+ 16#7C#,16#C6#,16#C6#,16#7C#,16#C6#,16#C6#,16#7C#,16#00#,
+ 16#7C#,16#C6#,16#C6#,16#7E#,16#06#,16#C6#,16#7C#,16#00#,
+ 16#00#,16#18#,16#18#,16#00#,16#18#,16#18#,16#00#,16#00#,
+ 16#18#,16#7E#,16#58#,16#7E#,16#1A#,16#7E#,16#18#,16#00#,
+ 16#00#,16#00#,16#00#,16#00#,16#00#,16#00#,16#00#,16#00#,
+ 16#3C#,16#66#,16#0C#,16#18#,16#18#,16#00#,16#18#,16#00#,
+ 16#C0#,16#C0#,16#C0#,16#C0#,16#C0#,16#C0#,16#FE#,16#00#,
+ 16#FC#,16#C6#,16#C6#,16#FC#,16#C0#,16#C0#,16#C0#,16#00#,
+ 16#00#,16#18#,16#18#,16#7E#,16#18#,16#18#,16#00#,16#00#,
+ 16#C6#,16#C6#,16#C6#,16#D6#,16#FE#,16#EE#,16#C6#,16#00#,
+ 16#FE#,16#C0#,16#C0#,16#F8#,16#C0#,16#C0#,16#FE#,16#00#,
+ 16#FC#,16#C6#,16#C6#,16#FC#,16#D8#,16#CC#,16#C6#,16#00#,
+ 16#7E#,16#18#,16#18#,16#18#,16#18#,16#18#,16#18#,16#00#,
+ 16#C6#,16#C6#,16#C6#,16#C6#,16#C6#,16#C6#,16#7C#,16#00#,
+ 16#3C#,16#18#,16#18#,16#18#,16#18#,16#18#,16#3C#,16#00#,
+ 16#7C#,16#C6#,16#C6#,16#C6#,16#C6#,16#C6#,16#7C#,16#00#,
+ 16#7C#,16#C6#,16#C6#,16#C6#,16#DE#,16#CC#,16#76#,16#00#,
+ 16#7C#,16#C6#,16#C0#,16#7C#,16#06#,16#C6#,16#7C#,16#00#,
+ 16#FC#,16#C6#,16#C6#,16#C6#,16#C6#,16#C6#,16#FC#,16#00#,
+ 16#FE#,16#C0#,16#C0#,16#F8#,16#C0#,16#C0#,16#C0#,16#00#,
+ 16#7C#,16#C6#,16#C0#,16#C0#,16#CE#,16#C6#,16#7E#,16#00#,
+ 16#C6#,16#C6#,16#C6#,16#FE#,16#C6#,16#C6#,16#C6#,16#00#,
+ 16#06#,16#06#,16#06#,16#06#,16#06#,16#C6#,16#7C#,16#00#,
+ 16#C6#,16#CC#,16#D8#,16#F0#,16#D8#,16#CC#,16#C6#,16#00#,
+ 16#38#,16#6C#,16#C6#,16#C6#,16#FE#,16#C6#,16#C6#,16#00#,
+ 16#7E#,16#06#,16#0C#,16#18#,16#30#,16#60#,16#7E#,16#00#,
+ 16#C6#,16#C6#,16#6C#,16#38#,16#6C#,16#C6#,16#C6#,16#00#,
+ 16#7C#,16#C6#,16#C0#,16#C0#,16#C0#,16#C6#,16#7C#,16#00#,
+ 16#C6#,16#C6#,16#C6#,16#C6#,16#C6#,16#6C#,16#38#,16#00#,
+ 16#FC#,16#C6#,16#C6#,16#FC#,16#C6#,16#C6#,16#FC#,16#00#,
+ 16#C6#,16#EE#,16#FE#,16#D6#,16#C6#,16#C6#,16#C6#,16#00#,
+ 16#00#,16#00#,16#00#,16#00#,16#00#,16#38#,16#38#,16#00#,
+ 16#00#,16#00#,16#00#,16#7E#,16#00#,16#00#,16#00#,16#00#,
+ 16#00#,16#66#,16#3C#,16#18#,16#3C#,16#66#,16#00#,16#00#,
+ 16#00#,16#18#,16#00#,16#7E#,16#00#,16#18#,16#00#,16#00#,
+ 16#00#,16#00#,16#7C#,16#00#,16#7C#,16#00#,16#00#,16#00#,
+ 16#66#,16#66#,16#66#,16#3C#,16#18#,16#18#,16#18#,16#00#,
+ 16#C6#,16#E6#,16#F6#,16#FE#,16#DE#,16#CE#,16#C6#,16#00#,
+ 16#03#,16#06#,16#0C#,16#18#,16#30#,16#60#,16#C0#,16#00#,
+ 16#FF#,16#FF#,16#FF#,16#FF#,16#FF#,16#FF#,16#FF#,16#00#,
+ 16#CE#,16#DB#,16#DB#,16#DB#,16#DB#,16#DB#,16#CE#,16#00#,
+ 16#00#,16#00#,16#3C#,16#7E#,16#7E#,16#7E#,16#3C#,16#00#,
+ 16#1C#,16#1C#,16#18#,16#1E#,16#18#,16#18#,16#1C#,16#00#,
+ 16#1C#,16#1C#,16#18#,16#1E#,16#18#,16#34#,16#26#,16#00#,
+ 16#38#,16#38#,16#18#,16#78#,16#18#,16#2C#,16#64#,16#00#,
+ 16#38#,16#38#,16#18#,16#78#,16#18#,16#18#,16#38#,16#00#,
+ 16#00#,16#18#,16#0C#,16#FE#,16#0C#,16#18#,16#00#,16#00#,
+ 16#18#,16#3C#,16#7E#,16#FF#,16#FF#,16#18#,16#18#,16#00#,
+ 16#03#,16#07#,16#0F#,16#1F#,16#3F#,16#7F#,16#FF#,16#00#,
+ 16#C0#,16#E0#,16#F0#,16#F8#,16#FC#,16#FE#,16#FF#,16#00#,
+ 16#38#,16#38#,16#12#,16#FE#,16#B8#,16#28#,16#6C#,16#00#,
+ 16#C0#,16#60#,16#30#,16#18#,16#0C#,16#06#,16#03#,16#00#,
+ 16#00#,16#00#,16#0C#,16#08#,16#08#,16#FF#,16#7E#,16#00#,
+ 16#00#,16#03#,16#63#,16#FF#,16#FF#,16#18#,16#08#,16#00#,
+ 16#00#,16#00#,16#00#,16#10#,16#38#,16#FF#,16#7E#,16#00#,
+ 16#00#,16#00#,16#00#,16#06#,16#6E#,16#FF#,16#7E#,16#00#);
+
+ signal addr_q : std_logic_vector(rom_addr_i'range);
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process seq
+ --
+ -- Purpose:
+ -- Implements the address register.
+ --
+ seq: process (clk_i)
+ begin
+ if rising_edge(clk_i) then
+ if rom_en_i = '1' then
+ addr_q <= rom_addr_i;
+ end if;
+ end if;
+ end process seq;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process rom_data
+ --
+ -- Purpose:
+ -- Does the ROM array look-up
+ --
+ rom_data: process (addr_q)
+ variable idx_v : natural range 0 to 511;
+ variable dat_v : std_logic_vector(7 downto 0);
+ begin
+ idx_v := to_integer(unsigned(addr_q));
+ rom_data_o <= std_logic_vector(to_unsigned(rom_cont_c(idx_v), 8));
+ end process rom_data;
+ --
+ -----------------------------------------------------------------------------
+
+end rtl;
diff --git a/common/Video/i8244/i8244_col_mux-c.vhd b/common/Video/i8244/i8244_col_mux-c.vhd
new file mode 100644
index 00000000..bcf57a05
--- /dev/null
+++ b/common/Video/i8244/i8244_col_mux-c.vhd
@@ -0,0 +1,14 @@
+-------------------------------------------------------------------------------
+--
+-- i8244 Video Display Controller
+--
+-- $Id: i8244_col_mux-c.vhd,v 1.2 2007/02/05 21:57:37 arnim Exp $
+--
+-------------------------------------------------------------------------------
+
+configuration i8244_col_mux_rtl_c0 of i8244_col_mux is
+
+ for rtl
+ end for;
+
+end i8244_col_mux_rtl_c0;
diff --git a/common/Video/i8244/i8244_col_mux.vhd b/common/Video/i8244/i8244_col_mux.vhd
new file mode 100644
index 00000000..0534fc5f
--- /dev/null
+++ b/common/Video/i8244/i8244_col_mux.vhd
@@ -0,0 +1,148 @@
+-------------------------------------------------------------------------------
+--
+-- i8244 Video Display Controller
+--
+-- $Id: i8244_col_mux.vhd,v 1.8 2007/02/05 22:08:59 arnim Exp $
+--
+-- Color multiplexer
+--
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2007, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.i8244_pack.col_attr_t;
+use work.i8244_pack.col_attrs_t;
+use work.i8244_minor_pack.minor_obj_range_t;
+
+entity i8244_col_mux is
+
+ port (
+ clk_i : in std_logic;
+ clk_en_i : in boolean;
+ res_i : in boolean;
+ hbl_i : in std_logic;
+ vbl_i : in std_logic;
+ grid_bg_col_i : in std_logic_vector(6 downto 0);
+ grid_hpix_i : in std_logic;
+ grid_vpix_i : in std_logic;
+ grid_dpix_i : in std_logic;
+ major_pix_i : in std_logic;
+ major_attr_i : in col_attr_t;
+ minor_pix_i : in std_logic_vector(minor_obj_range_t);
+ minor_attrs_i : in col_attrs_t(minor_obj_range_t);
+ r_o : out std_logic;
+ g_o : out std_logic;
+ b_o : out std_logic;
+ l_o : out std_logic
+ );
+
+end i8244_col_mux;
+
+
+architecture rtl of i8244_col_mux is
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process col_mux
+ --
+ -- Purpose:
+ -- Implements the priority color multiplexor.
+ --
+ col_mux: process (clk_i, res_i)
+ variable col_v : col_attr_t;
+ variable lum_v : std_logic;
+ begin
+ if res_i then
+ r_o <= '0';
+ g_o <= '0';
+ b_o <= '0';
+ l_o <= '0';
+
+ elsif rising_edge(clk_i) then
+ -- background color
+ col_v := grid_bg_col_i(5 downto 3);
+ lum_v := '0';
+
+ -- next pane: grid
+ if (grid_hpix_i or grid_vpix_i or grid_dpix_i) = '1' then
+ col_v := grid_bg_col_i(2 downto 0);
+ lum_v := grid_bg_col_i(6);
+ end if;
+
+ -- next pane: major objects
+ if major_pix_i = '1' then
+ for pos in 2 downto 0 loop
+ col_v(pos) := major_attr_i(2 - pos);
+ end loop;
+ lum_v := '1';
+ end if;
+
+ -- next pane: minor objects
+ -- minor 0 has highest priority
+ for obj in minor_obj_range_t'high downto 0 loop
+ if minor_pix_i(obj) = '1' then
+ for pos in 2 downto 0 loop
+ col_v(pos) := minor_attrs_i(obj)(2 - pos);
+ end loop;
+ lum_v := '1';
+ end if;
+ end loop;
+
+ if clk_en_i then
+ if (hbl_i or vbl_i) = '0' then
+ -- assign RGB and luminance outputs
+ r_o <= col_v(2);
+ g_o <= col_v(1);
+ b_o <= col_v(0);
+ l_o <= lum_v;
+ else
+ r_o <= '0';
+ g_o <= '0';
+ b_o <= '0';
+ l_o <= '0';
+ end if;
+ end if;
+ end if;
+ end process col_mux;
+ --
+ -----------------------------------------------------------------------------
+
+end rtl;
diff --git a/common/Video/i8244/i8244_col_pack-p.vhd b/common/Video/i8244/i8244_col_pack-p.vhd
new file mode 100644
index 00000000..0a5df00d
--- /dev/null
+++ b/common/Video/i8244/i8244_col_pack-p.vhd
@@ -0,0 +1,55 @@
+-------------------------------------------------------------------------------
+--
+-- i8244 Video Display Controller
+--
+-- $Id: i8244_col_pack-p.vhd,v 1.4 2007/03/11 11:40:58 arnim Exp $
+--
+-- Copyright (c) 2007, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+package i8244_col_pack is
+
+ constant r_c : natural := 0;
+ constant g_c : natural := 1;
+ constant b_c : natural := 2;
+
+ subtype rgb_val_t is natural range 0 to 255;
+ type rgb_triple_t is array (natural range 0 to 2) of
+ rgb_val_t;
+ type rgb_table_t is array (natural range 0 to 15) of
+ rgb_triple_t;
+
+ -----------------------------------------------------------------------------
+ -- Full RGB Value Array
+ --
+ -- Refer to vdc.c of o2em source distribution.
+ --
+ constant full_rgb_table_c : rgb_table_t := (
+ -- R G B LRGB
+ (r_c => 16#00#, g_c => 16#00#, b_c => 16#00#), -- 0000
+ (r_c => 16#0e#, g_c => 16#3d#, b_c => 16#d4#), -- 0001
+ (r_c => 16#00#, g_c => 16#98#, b_c => 16#1b#), -- 0010
+ (r_c => 16#00#, g_c => 16#bb#, b_c => 16#d9#), -- 0011
+ (r_c => 16#c7#, g_c => 16#00#, b_c => 16#08#), -- 0100
+ (r_c => 16#cc#, g_c => 16#16#, b_c => 16#b3#), -- 0101
+ (r_c => 16#9d#, g_c => 16#87#, b_c => 16#10#), -- 0110
+ (r_c => 16#e1#, g_c => 16#de#, b_c => 16#e1#), -- 0111
+ (r_c => 16#5f#, g_c => 16#6e#, b_c => 16#6b#), -- 1000
+ (r_c => 16#6a#, g_c => 16#a1#, b_c => 16#ff#), -- 1001
+ (r_c => 16#3d#, g_c => 16#f0#, b_c => 16#7a#), -- 1010
+ (r_c => 16#31#, g_c => 16#ff#, b_c => 16#ff#), -- 1011
+ (r_c => 16#ff#, g_c => 16#42#, b_c => 16#55#), -- 1100
+ (r_c => 16#ff#, g_c => 16#98#, b_c => 16#ff#), -- 1101
+ (r_c => 16#d9#, g_c => 16#ad#, b_c => 16#5d#), -- 1110
+ (r_c => 16#ff#, g_c => 16#ff#, b_c => 16#ff#) -- 1111
+ );
+ --
+ -----------------------------------------------------------------------------
+
+end;
diff --git a/common/Video/i8244/i8244_comp_pack-p.vhd b/common/Video/i8244/i8244_comp_pack-p.vhd
new file mode 100644
index 00000000..f895a38a
--- /dev/null
+++ b/common/Video/i8244/i8244_comp_pack-p.vhd
@@ -0,0 +1,218 @@
+-------------------------------------------------------------------------------
+--
+-- i8244 Video Display Controller
+--
+-- $Id: i8244_comp_pack-p.vhd,v 1.21 2007/02/05 22:08:59 arnim Exp $
+--
+-- Copyright (c) 2007, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.i8244_pack.pos_t;
+use work.i8244_pack.byte_t;
+use work.i8244_pack.col_attr_t;
+use work.i8244_pack.col_attrs_t;
+
+use work.i8244_grid_pack.grid_cfg_t;
+
+use work.i8244_minor_pack.minor_objs_t;
+use work.i8244_minor_pack.minor_patterns_t;
+use work.i8244_minor_pack.minor_obj_range_t;
+
+use work.i8244_major_pack.all;
+
+use work.i8244_sound_pack.cpu2snd_t;
+
+package i8244_comp_pack is
+
+ component i8244_sync_gen
+ generic (
+ is_pal_g : integer := 1
+ );
+ port (
+ clk_i : in std_logic;
+ clk_en_i : in boolean;
+ clk_rise_en_o : out boolean;
+ clk_fall_en_o : out boolean;
+ res_i : in boolean;
+ ms_i : in std_logic;
+ vbl_i : in std_logic;
+ hbl_o : out std_logic;
+ hsync_o : out std_logic;
+ vsync_o : out std_logic;
+ bg_o : out std_logic;
+ vbl_o : out std_logic;
+ hpos_o : out pos_t;
+ vpos_o : out pos_t;
+ hor_int_o : out std_logic
+ );
+ end component;
+
+ component i8244_grid
+ port (
+ clk_i : in std_logic;
+ clk_en_i : in boolean;
+ res_i : in boolean;
+ hpos_i : in pos_t;
+ vpos_i : in pos_t;
+ hbl_i : in std_logic;
+ vbl_i : in std_logic;
+ grid_cfg_i : in grid_cfg_t;
+ grid_hpix_o : out std_logic;
+ grid_vpix_o : out std_logic;
+ grid_dpix_o : out std_logic
+ );
+ end component;
+
+ component i8244_minor
+ port (
+ clk_i : in std_logic;
+ clk_rise_en_i : in boolean;
+ clk_fall_en_i : in boolean;
+ res_i : in boolean;
+ hpos_i : in pos_t;
+ vpos_i : in pos_t;
+ hbl_i : in std_logic;
+ vbl_i : in std_logic;
+ minor_objs_i : in minor_objs_t;
+ minor_patterns_i : in minor_patterns_t;
+ minor_pix_o : out std_logic_vector(minor_obj_range_t)
+ );
+ end component;
+
+ component i8244_major_obj
+ port (
+ clk_i : in std_logic;
+ clk_en_i : in boolean;
+ res_i : in boolean;
+ hpos_i : in pos_t;
+ vpos_i : in pos_t;
+ vstop_i : in boolean;
+ hstop_i : in boolean;
+ obj_i : in major_obj_t;
+ vhmatch_o : out boolean;
+ lss_o : out lss_t;
+ col_attr_o : out col_attr_t
+ );
+ end component;
+
+ component i8244_major_quad_obj
+ port (
+ clk_i : in std_logic;
+ clk_en_i : in boolean;
+ res_i : in boolean;
+ hpos_i : in pos_t;
+ vpos_i : in pos_t;
+ vstop_i : in boolean;
+ hstop_i : in boolean;
+ quad_obj_i : in major_quad_obj_t;
+ vhmatch_o : out boolean;
+ lss_o : out lss_t;
+ col_attr_o : out col_attr_t
+ );
+ end component;
+
+ component i8244_major
+ port (
+ clk_i : in std_logic;
+ clk_fall_en_i : in boolean;
+ res_i : in boolean;
+ hpos_i : in pos_t;
+ vpos_i : in pos_t;
+ major_objs_i : in major_objs_t;
+ major_quad_objs_i : in major_quad_objs_t;
+ rom_addr_o : out rom_addr_t;
+ rom_en_o : out std_logic;
+ rom_data_i : in rom_data_t;
+ major_pix_o : out std_logic;
+ major_attr_o : out col_attr_t;
+ major_coll_o : out boolean
+ );
+ end component;
+
+ component i8244_cpuio
+ port (
+ -- Global Interface -----------------------------------------------------
+ clk_i : in std_logic;
+ clk_rise_en_i : in boolean;
+ clk_fall_en_i : in boolean;
+ res_i : in boolean;
+ hpos_i : in pos_t;
+ vpos_i : in pos_t;
+ vbl_i : in std_logic;
+ hor_int_i : in std_logic;
+ stb_i : in std_logic;
+ -- Bus Interface --------------------------------------------------------
+ ale_i : in std_logic;
+ din_i : in byte_t;
+ dout_o : out byte_t;
+ dout_en_o : out std_logic;
+ cs_n_i : in std_logic;
+ rd_n_i : in std_logic;
+ wr_n_i : in std_logic;
+ intr_n_o : out std_logic;
+ -- Display interface ----------------------------------------------------
+ en_disp_o : out std_logic;
+ grid_bg_col_o : out std_logic_vector(6 downto 0);
+ cx_i : in std_logic;
+ grid_hpix_i : in std_logic;
+ grid_vpix_i : in std_logic;
+ grid_dpix_i : in std_logic;
+ major_pix_i : in std_logic;
+ minor_pix_i : in std_logic_vector(minor_obj_range_t);
+ major_coll_i : in boolean;
+ -- Grid Configuration ---------------------------------------------------
+ grid_cfg_o : out grid_cfg_t;
+ -- Major Objects --------------------------------------------------------
+ major_objs_o : out major_objs_t;
+ major_quad_objs_o : out major_quad_objs_t;
+ -- Minor Objects --------------------------------------------------------
+ minor_objs_o : out minor_objs_t;
+ minor_patterns_o : out minor_patterns_t;
+ -- Sound Interface ------------------------------------------------------
+ cpu2snd_o : out cpu2snd_t;
+ snd_int_i : in boolean
+ );
+ end component;
+
+ component i8244_col_mux
+ port (
+ clk_i : in std_logic;
+ clk_en_i : in boolean;
+ res_i : in boolean;
+ hbl_i : in std_logic;
+ vbl_i : in std_logic;
+ grid_bg_col_i : in std_logic_vector(6 downto 0);
+ grid_hpix_i : in std_logic;
+ grid_vpix_i : in std_logic;
+ grid_dpix_i : in std_logic;
+ major_pix_i : in std_logic;
+ major_attr_i : in col_attr_t;
+ minor_pix_i : in std_logic_vector(minor_obj_range_t);
+ minor_attrs_i : in col_attrs_t(minor_obj_range_t);
+ r_o : out std_logic;
+ g_o : out std_logic;
+ b_o : out std_logic;
+ l_o : out std_logic
+ );
+ end component;
+
+ component i8244_sound
+ port (
+ clk_i : in std_logic;
+ clk_en_i : in boolean;
+ res_i : in boolean;
+ hbl_i : in std_logic;
+ cpu2snd_i : in cpu2snd_t;
+ snd_int_o : out boolean;
+ snd_o : out std_logic;
+ snd_vec_o : out std_logic_vector(3 downto 0)
+ );
+ end component;
+
+end;
diff --git a/common/Video/i8244/i8244_core-c.vhd b/common/Video/i8244/i8244_core-c.vhd
new file mode 100644
index 00000000..37662838
--- /dev/null
+++ b/common/Video/i8244/i8244_core-c.vhd
@@ -0,0 +1,43 @@
+-------------------------------------------------------------------------------
+--
+-- i8244 Video Display Controller
+--
+-- $Id: i8244_core-c.vhd,v 1.4 2007/02/05 21:57:37 arnim Exp $
+--
+-------------------------------------------------------------------------------
+
+configuration i8244_core_struct_c0 of i8244_core is
+
+ for struct
+
+ for sync_gen_b: i8244_sync_gen
+ use configuration work.i8244_sync_gen_rtl_c0;
+ end for;
+
+ for grid_b: i8244_grid
+ use configuration work.i8244_grid_rtl_c0;
+ end for;
+
+ for major_b: i8244_major
+ use configuration work.i8244_major_rtl_c0;
+ end for;
+
+ for minor_b: i8244_minor
+ use configuration work.i8244_minor_rtl_c0;
+ end for;
+
+ for cpuio_b: i8244_cpuio
+ use configuration work.i8244_cpuio_rtl_c0;
+ end for;
+
+ for col_mux_b: i8244_col_mux
+ use configuration work.i8244_col_mux_rtl_c0;
+ end for;
+
+ for sound_b: i8244_sound
+ use configuration work.i8244_sound_rtl_c0;
+ end for;
+
+ end for;
+
+end i8244_core_struct_c0;
diff --git a/common/Video/i8244/i8244_core.vhd b/common/Video/i8244/i8244_core.vhd
new file mode 100644
index 00000000..c39085e6
--- /dev/null
+++ b/common/Video/i8244/i8244_core.vhd
@@ -0,0 +1,390 @@
+-------------------------------------------------------------------------------
+--
+-- i8244 Video Display Controller
+--
+-- $Id: i8244_core.vhd,v 1.17 2007/02/05 22:08:59 arnim Exp $
+--
+-- i8244 Core
+--
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2007, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity i8244_core is
+
+ generic (
+ is_pal_g : integer := 1
+ );
+ port (
+ -- System Interface -------------------------------------------------------
+ clk_i : in std_logic;
+ clk_en_i : in std_logic;
+ res_n_i : in std_logic;
+ -- ROM Interface ----------------------------------------------------------
+ rom_addr_o : out std_logic_vector(8 downto 0);
+ rom_en_o : out std_logic;
+ rom_data_i : in std_logic_vector(7 downto 0);
+ -- I8244 Pads Interface ---------------------------------------------------
+ intr_n_o : out std_logic;
+ stb_i : in std_logic;
+ bg_o : out std_logic;
+ hsync_o : out std_logic;
+ vsync_o : out std_logic;
+ ms_i : in std_logic;
+ hbl_o : out std_logic;
+ vbl_i : in std_logic;
+ vbl_o : out std_logic;
+ cx_i : in std_logic;
+ l_o : out std_logic;
+ cs_n_i : in std_logic;
+ wr_n_i : in std_logic;
+ rd_n_i : in std_logic;
+ din_i : in std_logic_vector(7 downto 0);
+ dout_o : out std_logic_vector(7 downto 0);
+ dout_en_o : out std_logic;
+ r_o : out std_logic;
+ g_o : out std_logic;
+ b_o : out std_logic;
+ ale_i : in std_logic;
+ snd_o : out std_logic;
+ snd_vec_o : out std_logic_vector(3 downto 0)
+ );
+
+end i8244_core;
+
+
+use work.i8244_pack.all;
+--
+use work.i8244_grid_pack.grid_cfg_t;
+--
+use work.i8244_major_pack.major_objs_t;
+use work.i8244_major_pack.major_quad_objs_t;
+use work.i8244_major_pack.rom_addr_t;
+use work.i8244_major_pack.rom_data_t;
+--
+use work.i8244_minor_pack.minor_objs_t;
+use work.i8244_minor_pack.minor_patterns_t;
+use work.i8244_minor_pack.minor_obj_range_t;
+--
+use work.i8244_sound_pack.cpu2snd_t;
+
+use work.i8244_comp_pack.i8244_sync_gen;
+use work.i8244_comp_pack.i8244_grid;
+use work.i8244_comp_pack.i8244_major;
+use work.i8244_comp_pack.i8244_minor;
+use work.i8244_comp_pack.i8244_cpuio;
+use work.i8244_comp_pack.i8244_col_mux;
+use work.i8244_comp_pack.i8244_sound;
+
+architecture struct of i8244_core is
+
+ -- active reset level
+ constant res_level_c : std_logic := '0';
+
+ -- global signals
+ signal clk_en_s : boolean;
+ signal res_s : boolean;
+
+ -- sync generator signals
+ signal clk_rise_en_s,
+ clk_fall_en_s : boolean;
+ signal hpos_s,
+ vpos_s : pos_t;
+ signal hbl_s,
+ vbl_s : std_logic;
+ signal hor_int_s : std_logic;
+
+ -- grid display system signals
+ signal grid_cfg_s : grid_cfg_t;
+ signal grid_hpix_s,
+ grid_vpix_s,
+ grid_dpix_s : std_logic;
+
+ -- major display system signals
+ signal major_objs_s : major_objs_t;
+ signal major_quad_objs_s : major_quad_objs_t;
+ signal major_pix_s : std_logic;
+ signal major_attr_s : col_attr_t;
+ signal major_coll_s : boolean;
+
+ -- minor display system signals
+ signal minor_objs_s : minor_objs_t;
+ signal minor_patterns_s : minor_patterns_t;
+ signal minor_pix_s : std_logic_vector(minor_obj_range_t);
+
+ -- CPU I/O module signals
+ signal en_disp_s : std_logic;
+ signal grid_bg_col_s : std_logic_vector(6 downto 0);
+
+ -- color mux module signals
+ signal minor_cols_s : col_attrs_t(minor_obj_range_t);
+
+ -- enabled pixel signals
+ signal grid_hpix_en_s,
+ grid_vpix_en_s,
+ grid_dpix_en_s,
+ major_pix_en_s : std_logic;
+ signal minor_pix_en_s : std_logic_vector(minor_obj_range_t);
+
+ -- sound module signals
+ signal snd_int_s : boolean;
+ signal cpu2snd_s : cpu2snd_t;
+
+begin
+
+ res_s <= res_n_i = res_level_c;
+ clk_en_s <= clk_en_i = '1';
+
+
+ -----------------------------------------------------------------------------
+ -- Sync generator
+ -----------------------------------------------------------------------------
+ sync_gen_b : i8244_sync_gen
+ generic map (
+ is_pal_g => is_pal_g
+ )
+ port map (
+ clk_i => clk_i,
+ clk_en_i => clk_en_s,
+ clk_rise_en_o => clk_rise_en_s,
+ clk_fall_en_o => clk_fall_en_s,
+ res_i => res_s,
+ ms_i => ms_i,
+ vbl_i => vbl_i,
+ hbl_o => hbl_s,
+ hsync_o => hsync_o,
+ vsync_o => vsync_o,
+ bg_o => bg_o,
+ vbl_o => vbl_s,
+ hpos_o => hpos_s,
+ vpos_o => vpos_s,
+ hor_int_o => hor_int_s
+ );
+ --
+ vbl_o <= vbl_s;
+ hbl_o <= hbl_s;
+
+
+ -----------------------------------------------------------------------------
+ -- Grid display system
+ -----------------------------------------------------------------------------
+ grid_b : i8244_grid
+ port map (
+ clk_i => clk_i,
+ clk_en_i => clk_fall_en_s,
+ res_i => res_s,
+ hpos_i => hpos_s,
+ vpos_i => vpos_s,
+ hbl_i => hbl_s,
+ vbl_i => vbl_s,
+ grid_cfg_i => grid_cfg_s,
+ grid_hpix_o => grid_hpix_s,
+ grid_vpix_o => grid_vpix_s,
+ grid_dpix_o => grid_dpix_s
+ );
+
+
+ -----------------------------------------------------------------------------
+ -- Major display system
+ -----------------------------------------------------------------------------
+ major_b : i8244_major
+ port map (
+ clk_i => clk_i,
+ clk_fall_en_i => clk_fall_en_s,
+ res_i => res_s,
+ hpos_i => hpos_s,
+ vpos_i => vpos_s,
+ major_objs_i => major_objs_s,
+ major_quad_objs_i => major_quad_objs_s,
+ rom_addr_o => rom_addr_o,
+ rom_en_o => rom_en_o,
+ rom_data_i => rom_data_i,
+ major_pix_o => major_pix_s,
+ major_attr_o => major_attr_s,
+ major_coll_o => major_coll_s
+ );
+
+
+ -----------------------------------------------------------------------------
+ -- Minor display system
+ -----------------------------------------------------------------------------
+ minor_b : i8244_minor
+ port map (
+ clk_i => clk_i,
+ clk_rise_en_i => clk_rise_en_s,
+ clk_fall_en_i => clk_fall_en_s,
+ res_i => res_s,
+ hpos_i => hpos_s,
+ vpos_i => vpos_s,
+ hbl_i => hbl_s,
+ vbl_i => vbl_s,
+ minor_objs_i => minor_objs_s,
+ minor_patterns_i => minor_patterns_s,
+ minor_pix_o => minor_pix_s
+ );
+
+
+ -----------------------------------------------------------------------------
+ -- Process disp_en
+ --
+ -- Purpose:
+ -- Masks the pixel signals when display is disabled
+ --
+ disp_en: process (en_disp_s,
+ grid_cfg_s,
+ grid_hpix_s, grid_vpix_s, grid_dpix_s,
+ major_pix_s,
+ minor_pix_s)
+ begin
+ -- enable major an minor pix channels
+ if en_disp_s = '1' then
+ major_pix_en_s <= major_pix_s;
+ minor_pix_en_s <= minor_pix_s;
+ else
+ major_pix_en_s <= '0';
+ minor_pix_en_s <= (others => '0');
+ end if;
+
+ -- enable horizontal and vertical grid channels
+ if grid_cfg_s.enable = '1' then
+ grid_hpix_en_s <= grid_hpix_s;
+ grid_vpix_en_s <= grid_vpix_s;
+ else
+ grid_hpix_en_s <= '0';
+ grid_vpix_en_s <= '0';
+ end if;
+
+ -- enable dot grid channel
+ if grid_cfg_s.dot_en = '1' then
+ grid_dpix_en_s <= grid_dpix_s;
+ else
+ grid_dpix_en_s <= '0';
+ end if;
+ end process disp_en;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- CPU I/O module
+ -----------------------------------------------------------------------------
+ cpuio_b : i8244_cpuio
+ port map (
+ clk_i => clk_i,
+ clk_rise_en_i => clk_rise_en_s,
+ clk_fall_en_i => clk_fall_en_s,
+ res_i => res_s,
+ hpos_i => hpos_s,
+ vpos_i => vpos_s,
+ vbl_i => vbl_s,
+ hor_int_i => hor_int_s,
+ stb_i => stb_i,
+ ale_i => ale_i,
+ din_i => din_i,
+ dout_o => dout_o,
+ dout_en_o => dout_en_o,
+ cs_n_i => cs_n_i,
+ rd_n_i => rd_n_i,
+ wr_n_i => wr_n_i,
+ intr_n_o => intr_n_o,
+ en_disp_o => en_disp_s,
+ grid_bg_col_o => grid_bg_col_s,
+ cx_i => cx_i,
+ grid_hpix_i => grid_hpix_en_s,
+ grid_vpix_i => grid_vpix_en_s,
+ grid_dpix_i => grid_dpix_en_s,
+ major_pix_i => major_pix_en_s,
+ minor_pix_i => minor_pix_en_s,
+ major_coll_i => major_coll_s,
+ grid_cfg_o => grid_cfg_s,
+ major_objs_o => major_objs_s,
+ major_quad_objs_o => major_quad_objs_s,
+ minor_objs_o => minor_objs_s,
+ minor_patterns_o => minor_patterns_s,
+ cpu2snd_o => cpu2snd_s,
+ snd_int_i => snd_int_s
+ );
+
+
+ -----------------------------------------------------------------------------
+ -- Color mux module
+ -----------------------------------------------------------------------------
+ minor_cols: for obj in minor_obj_range_t generate
+ minor_cols_s(obj) <= minor_objs_s(obj).col;
+ end generate;
+ --
+ col_mux_b : i8244_col_mux
+ port map (
+ clk_i => clk_i,
+ clk_en_i => clk_en_s,
+ res_i => res_s,
+ hbl_i => hbl_s,
+ vbl_i => vbl_s,
+ grid_bg_col_i => grid_bg_col_s,
+ grid_hpix_i => grid_hpix_en_s,
+ grid_vpix_i => grid_vpix_en_s,
+ grid_dpix_i => grid_dpix_en_s,
+ major_pix_i => major_pix_en_s,
+ major_attr_i => major_attr_s,
+ minor_pix_i => minor_pix_en_s,
+ minor_attrs_i => minor_cols_s,
+ r_o => r_o,
+ g_o => g_o,
+ b_o => b_o,
+ l_o => l_o
+ );
+
+
+ -----------------------------------------------------------------------------
+ -- Sound module
+ -----------------------------------------------------------------------------
+ sound_b : i8244_sound
+ port map (
+ clk_i => clk_i,
+ clk_en_i => clk_fall_en_s,
+ res_i => res_s,
+ hbl_i => hbl_s,
+ cpu2snd_i => cpu2snd_s,
+ snd_int_o => snd_int_s,
+ snd_o => snd_o,
+ snd_vec_o => snd_vec_o
+ );
+
+end struct;
diff --git a/common/Video/i8244/i8244_core_comp_pack-p.vhd b/common/Video/i8244/i8244_core_comp_pack-p.vhd
new file mode 100644
index 00000000..e0399141
--- /dev/null
+++ b/common/Video/i8244/i8244_core_comp_pack-p.vhd
@@ -0,0 +1,103 @@
+-------------------------------------------------------------------------------
+--
+-- i8244 Video Display Controller
+--
+-- $Id: i8244_core_comp_pack-p.vhd,v 1.6 2007/02/05 22:08:59 arnim Exp $
+--
+-- Copyright (c) 2007, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+package i8244_core_comp_pack is
+
+ component i8244_charset_rom
+ port (
+ clk_i : in std_logic;
+ rom_addr_i : in std_logic_vector(8 downto 0);
+ rom_en_i : in std_logic;
+ rom_data_o : out std_logic_vector(7 downto 0)
+ );
+ end component;
+
+ component i8244_core
+ generic (
+ is_pal_g : integer := 1
+ );
+ port (
+ -- System Interface -----------------------------------------------------
+ clk_i : in std_logic;
+ clk_en_i : in std_logic;
+ res_n_i : in std_logic;
+ -- ROM Interface --------------------------------------------------------
+ rom_addr_o : out std_logic_vector(8 downto 0);
+ rom_en_o : out std_logic;
+ rom_data_i : in std_logic_vector(7 downto 0);
+ -- I8244 Pads Interface -------------------------------------------------
+ intr_n_o : out std_logic;
+ stb_i : in std_logic;
+ bg_o : out std_logic;
+ hsync_o : out std_logic;
+ vsync_o : out std_logic;
+ ms_i : in std_logic;
+ hbl_o : out std_logic;
+ vbl_i : in std_logic;
+ vbl_o : out std_logic;
+ cx_i : in std_logic;
+ l_o : out std_logic;
+ cs_n_i : in std_logic;
+ wr_n_i : in std_logic;
+ rd_n_i : in std_logic;
+ din_i : in std_logic_vector(7 downto 0);
+ dout_o : out std_logic_vector(7 downto 0);
+ dout_en_o : out std_logic;
+ r_o : out std_logic;
+ g_o : out std_logic;
+ b_o : out std_logic;
+ ale_i : in std_logic;
+ snd_o : out std_logic;
+ snd_vec_o : out std_logic_vector(3 downto 0)
+ );
+ end component;
+
+ component i8244_top_sync
+ generic (
+ is_pal_g : integer := 1
+ );
+ port (
+ -- System Interface -----------------------------------------------------
+ clk_i : in std_logic;
+ clk_en_i : in std_logic;
+ res_n_i : in std_logic;
+ -- I8244 Pads Interface -------------------------------------------------
+ intr_n_o : out std_logic;
+ stb_i : in std_logic;
+ bg_o : out std_logic;
+ hsync_o : out std_logic;
+ vsync_o : out std_logic;
+ ms_i : in std_logic;
+ hbl_o : out std_logic;
+ vbl_i : in std_logic;
+ vbl_o : out std_logic;
+ cx_i : in std_logic;
+ l_o : out std_logic;
+ cs_n_i : in std_logic;
+ wr_n_i : in std_logic;
+ rd_n_i : in std_logic;
+ din_i : in std_logic_vector(7 downto 0);
+ dout_o : out std_logic_vector(7 downto 0);
+ dout_en_o : out std_logic;
+ r_o : out std_logic;
+ g_o : out std_logic;
+ b_o : out std_logic;
+ ale_i : in std_logic;
+ snd_o : out std_logic;
+ snd_vec_o : out std_logic_vector(3 downto 0)
+ );
+ end component;
+
+end;
diff --git a/common/Video/i8244/i8244_cpuio-c.vhd b/common/Video/i8244/i8244_cpuio-c.vhd
new file mode 100644
index 00000000..8f545510
--- /dev/null
+++ b/common/Video/i8244/i8244_cpuio-c.vhd
@@ -0,0 +1,14 @@
+-------------------------------------------------------------------------------
+--
+-- i8244 Video Display Controller
+--
+-- $Id: i8244_cpuio-c.vhd,v 1.2 2007/02/05 21:57:37 arnim Exp $
+--
+-------------------------------------------------------------------------------
+
+configuration i8244_cpuio_rtl_c0 of i8244_cpuio is
+
+ for rtl
+ end for;
+
+end i8244_cpuio_rtl_c0;
diff --git a/common/Video/i8244/i8244_cpuio.vhd b/common/Video/i8244/i8244_cpuio.vhd
new file mode 100644
index 00000000..5297efcf
--- /dev/null
+++ b/common/Video/i8244/i8244_cpuio.vhd
@@ -0,0 +1,837 @@
+-------------------------------------------------------------------------------
+--
+-- i8244 Video Display Controller
+--
+-- $Id: i8244_cpuio.vhd,v 1.26 2007/02/05 22:08:59 arnim Exp $
+--
+-- CPU I/O Interface
+--
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2007, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.i8244_pack.pos_t;
+use work.i8244_pack.byte_t;
+
+use work.i8244_grid_pack.grid_cfg_t;
+use work.i8244_major_pack.major_objs_t;
+use work.i8244_major_pack.major_quad_objs_t;
+use work.i8244_minor_pack.all;
+use work.i8244_sound_pack.cpu2snd_t;
+
+entity i8244_cpuio is
+
+ port (
+ -- Global Interface -------------------------------------------------------
+ clk_i : in std_logic;
+ clk_rise_en_i : in boolean;
+ clk_fall_en_i : in boolean;
+ res_i : in boolean;
+ hpos_i : in pos_t;
+ vpos_i : in pos_t;
+ vbl_i : in std_logic;
+ hor_int_i : in std_logic;
+ stb_i : in std_logic;
+ -- Bus Interface ----------------------------------------------------------
+ ale_i : in std_logic;
+ din_i : in byte_t;
+ dout_o : out byte_t;
+ dout_en_o : out std_logic;
+ cs_n_i : in std_logic;
+ rd_n_i : in std_logic;
+ wr_n_i : in std_logic;
+ intr_n_o : out std_logic;
+ -- Display interface ------------------------------------------------------
+ en_disp_o : out std_logic;
+ grid_bg_col_o : out std_logic_vector(6 downto 0);
+ cx_i : in std_logic;
+ grid_hpix_i : in std_logic;
+ grid_vpix_i : in std_logic;
+ grid_dpix_i : in std_logic;
+ major_pix_i : in std_logic;
+ minor_pix_i : in std_logic_vector(minor_obj_range_t);
+ major_coll_i : in boolean;
+ -- Grid Configuration -----------------------------------------------------
+ grid_cfg_o : out grid_cfg_t;
+ -- Major Objects ----------------------------------------------------------
+ major_objs_o : out major_objs_t;
+ major_quad_objs_o : out major_quad_objs_t;
+ -- Minor Objects ----------------------------------------------------------
+ minor_objs_o : out minor_objs_t;
+ minor_patterns_o : out minor_patterns_t;
+ -- Sound Interface --------------------------------------------------------
+ cpu2snd_o : out cpu2snd_t;
+ snd_int_i : in boolean
+ );
+
+end i8244_cpuio;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+use work.i8244_pack.all;
+use work.i8244_grid_pack.hbars_t;
+use work.i8244_grid_pack.grid_bars_t;
+use work.i8244_major_pack.major_obj_range_t;
+use work.i8244_major_pack.lss_t;
+use work.i8244_major_pack.major_quad_obj_range_t;
+use work.i8244_major_pack.major_quad_attr_range_t;
+use work.i8244_sound_pack.all;
+
+architecture rtl of i8244_cpuio is
+
+ -- ranges and constant values for address decoding
+ constant addr_minor_ctrl_s_c : natural := 16#00#;
+ constant addr_minor_ctrl_e_c : natural := 16#0f#;
+ constant addr_major_obj_s_c : natural := 16#10#;
+ constant addr_major_obj_e_c : natural := 16#3f#;
+ constant addr_major_quad_s_c : natural := 16#40#;
+ constant addr_major_quad_e_c : natural := 16#7f#;
+ constant addr_minor_pattern_s_c : natural := 16#80#;
+ constant addr_minor_pattern_e_c : natural := 16#9f#;
+ constant addr_ctrl_c : natural := 16#a0#;
+ constant addr_ctrl_stat_c : natural := 16#a1#;
+ constant addr_overlap_c : natural := 16#a2#;
+ constant addr_color_c : natural := 16#a3#;
+ constant addr_ypos_c : natural := 16#a4#;
+ constant addr_xpos_c : natural := 16#a5#;
+ constant addr_snd0_c : natural := 16#a7#;
+ constant addr_snd1_c : natural := 16#a8#;
+ constant addr_snd2_c : natural := 16#a9#;
+ constant addr_snd_stat_c : natural := 16#aa#;
+ constant addr_grid_cx_s_c : natural := 16#c0#;
+ constant addr_grid_cx_e_c : natural := 16#c8#;
+ constant addr_grid_dx_s_c : natural := 16#d0#;
+ constant addr_grid_dx_e_c : natural := 16#d8#;
+ constant addr_grid_ex_s_c : natural := 16#e0#;
+ constant addr_grid_ex_e_c : natural := 16#e9#;
+
+ -- register bits of CONTROL
+ constant bit_ctrl_wide_c : natural := 7;
+ constant bit_ctrl_dot_en_c : natural := 6;
+ constant bit_ctrl_en_display_c : natural := 5;
+ constant bit_ctrl_en_ext_overlap_c : natural := 4;
+ constant bit_ctrl_en_grid_c : natural := 3;
+ constant bit_ctrl_en_sound_int_c : natural := 2;
+ constant bit_ctrl_fps_c : natural := 1;
+ constant bit_ctrl_en_hor_int_c : natural := 0;
+
+ -- register bits of ENABLE OVERLAP / OVERLAP STATUS
+ constant bit_over_major_c : natural := 7;
+ constant bit_over_ext_c : natural := 6;
+ constant bit_over_hdgrid_c : natural := 5;
+ constant bit_over_vgrid_c : natural := 4;
+ constant bit_over_minor3_c : natural := 3;
+ constant bit_over_minor2_c : natural := 2;
+ constant bit_over_minor1_c : natural := 1;
+ constant bit_over_minor0_c : natural := 0;
+
+ -- register bits of SOUND CONTROL
+ constant bit_snd_en_c : natural := 7;
+ constant bit_snd_freq_c : natural := 5;
+ constant bit_snd_noise_c : natural := 4;
+ constant bit_snd_vol_h_c : natural := 3;
+ constant bit_snd_vol_l_c : natural := 0;
+
+ signal din_q : byte_t;
+
+ signal addr_q : unsigned(byte_t'range);
+
+ signal ale_q,
+ rd_n_q,
+ wr_n_q,
+ cs_n_q : std_logic;
+
+ signal sel_minor_ctrl_s,
+ sel_major_obj_s,
+ sel_major_quad_s,
+ sel_minor_pattern_s,
+ sel_ctrl_s,
+ sel_overlap_s,
+ sel_color_s,
+ sel_sound_s,
+ sel_grid_cx_s,
+ sel_grid_dx_s,
+ sel_grid_ex_s : boolean;
+ signal sel_objsub0_s,
+ sel_objsub1_s,
+ sel_objsub2_s,
+ sel_objsub3_s : boolean;
+
+ signal reg_minor_objs_q : minor_objs_t;
+ signal reg_major_objs_q : major_objs_t;
+ signal reg_major_quad_objs_q : major_quad_objs_t;
+ signal reg_minor_patterns_q : minor_patterns_t;
+ signal reg_ctrl_q,
+ reg_enoverlap_q,
+ reg_overlap_q,
+ reg_y_q,
+ reg_x_q,
+ reg_sound_q : byte_t;
+ signal reg_color_q : std_logic_vector(6 downto 0);
+ signal reg_grid_bars_q : grid_bars_t;
+
+ signal pos_strobe_s : std_logic;
+
+ signal vbl_q : std_logic;
+ signal sound_int_q,
+ ext_int_q : boolean;
+ signal intr_q : boolean;
+ signal major_coll_q : boolean;
+
+ signal sound_reg_sel_s : sound_reg_sel_t;
+
+ signal min_num_s : natural range 0 to 3;
+ signal maj_num_s : natural range 0 to 11;
+ signal quad_num_s : natural range 0 to 3;
+ signal hbar_num_s : natural range 0 to 8;
+ signal vbar_num_s : natural range 0 to 9;
+
+ signal ale_pulse_s,
+ rd_pulse_s,
+ wr_pulse_s : boolean;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process cpu_acc
+ --
+ -- Purpose:
+ -- Generates the central control signals for detecting and executing
+ -- accesses from the CPU.
+ --
+ cpu_acc: process (ale_i, ale_q,
+ rd_n_i, rd_n_q,
+ wr_n_i, wr_n_q,
+ cs_n_i, cs_n_q)
+ variable ale_inact_v,
+ rd_inact_v,
+ wr_inact_v,
+ cs_inact_v : boolean;
+ begin
+ -- edge detection flags
+ ale_inact_v := ale_i = '0' and ale_q = '1';
+ rd_inact_v := rd_n_i = '1' and rd_n_q = '0';
+ wr_inact_v := wr_n_i = '1' and wr_n_q = '0';
+ cs_inact_v := cs_n_i = '1' and cs_n_q = '0';
+
+ -- ALE pulse
+ ale_pulse_s <= ale_inact_v and cs_n_q = '0';
+ -- read pulse
+ rd_pulse_s <= (rd_inact_v and cs_n_q = '0') or
+ (cs_inact_v and rd_n_q = '0');
+ -- write pulse
+ wr_pulse_s <= (wr_inact_v and cs_n_q = '0') or
+ (cs_inact_v and wr_n_q = '0');
+ end process cpu_acc;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process seq
+ --
+ -- Purpose:
+ -- Implements the sequential elements:
+ -- * input data latch
+ -- * address latch
+ -- * delay flags for ALE, RD#, WR# and CS#
+ -- * dedicated storage elements for grid, major and minor object data
+ -- * control registers
+ -- * overlap collision flags
+ -- * interrupt flags
+ -- * major <-> major collision flag
+ --
+ seq: process (clk_i, res_i)
+ variable pix_vec_v : byte_t;
+
+ function tag_overlap_f(pix : in std_logic_vector;
+ mask : in std_logic_vector;
+ idx : in natural) return boolean is
+ variable pix_or_v, mask_or_v : std_logic;
+ variable pix_res_v, mask_res_v : boolean;
+ begin
+ pix_or_v := '0';
+ mask_or_v := '0';
+
+ for pos in pix'range loop
+ -- OR all pix / masked pix except for the given index
+ if pos /= idx then
+ pix_or_v := pix_or_v or pix(pos);
+ mask_or_v := mask_or_v or (pix(pos) and mask(pos));
+ end if;
+ end loop;
+
+ -- 1) overlap bit for idx has to be set when
+ -- this channel overlaps with other enabled pix channels
+ pix_res_v := pix(idx) = '1' and mask_or_v = '1';
+ -- 2) overlap bit for idx has to be set when
+ -- mask enables this bit and other pix channels collide
+ mask_res_v := (pix(idx) and mask(idx)) = '1' and
+ pix_or_v = '1';
+
+ return pix_res_v or mask_res_v;
+ end;
+
+ begin
+ if res_i then
+ din_q <= (others => '0');
+ addr_q <= (others => '0');
+ ale_q <= '0';
+ rd_n_q <= '1';
+ wr_n_q <= '1';
+ cs_n_q <= '1';
+ vbl_q <= '0';
+ sound_int_q <= false;
+ ext_int_q <= false;
+ intr_q <= false;
+ major_coll_q <= false;
+
+ for hbar in hbars_t'range loop
+ reg_grid_bars_q.hbars(hbar) <= (others => '0');
+ end loop;
+ reg_grid_bars_q.vbars <= (others => (others => '0'));
+
+-- reg_minor_objs_q <= (others => (cam_y => (others => '1'),
+-- cam_x => (others => '1'),
+-- col => (others => '0'),
+-- x9 => '0',
+-- s => '0',
+-- d => '0'));
+ for obj in minor_obj_range_t loop
+ reg_minor_objs_q(obj).cam_y <= (others => '1');
+ reg_minor_objs_q(obj).cam_x <= (others => '1');
+ reg_minor_objs_q(obj).col <= (others => '0');
+ reg_minor_objs_q(obj).x9 <= '0';
+ reg_minor_objs_q(obj).s <= '0';
+ reg_minor_objs_q(obj).d <= '0';
+ end loop;
+-- reg_major_objs_q <= (others => (cam_y => (others => '1'),
+-- cam_x => (others => '1'),
+-- attr => (lss => (others => '0'),
+-- col => (others => '0'))));
+ for obj in major_obj_range_t loop
+ reg_major_objs_q(obj).cam_y <= (others => '1');
+ reg_major_objs_q(obj).cam_x <= (others => '1');
+ reg_major_objs_q(obj).attr.lss <= (others => '0');
+ reg_major_objs_q(obj).attr.col <= (others => '0');
+ end loop;
+-- reg_major_quad_objs_q <= (others => (cam_y => (others => '1'),
+-- cam_x => (others => '1'),
+-- attrs => (others => (lss => (others => '0'),
+-- col => (others => '0')))));
+ for obj in major_quad_obj_range_t loop
+ reg_major_quad_objs_q(obj).cam_y <= (others => '1');
+ reg_major_quad_objs_q(obj).cam_x <= (others => '1');
+ for attr in major_quad_attr_range_t loop
+ reg_major_quad_objs_q(obj).attrs(attr).lss <= (others => '0');
+ reg_major_quad_objs_q(obj).attrs(attr).col <= (others => '0');
+ end loop;
+ end loop;
+ -- dedicated registers
+ reg_ctrl_q <= (others => '0');
+ reg_enoverlap_q <= (others => '0');
+ reg_overlap_q <= (others => '0');
+ reg_color_q <= (others => '0');
+ reg_sound_q <= (others => '0');
+
+ elsif rising_edge(clk_i) then
+ -- save din_i value for later processing
+ din_q <= din_i;
+ -- save control inputs for edge detection
+ ale_q <= ale_i;
+ rd_n_q <= rd_n_i;
+ wr_n_q <= wr_n_i;
+ cs_n_q <= cs_n_i;
+
+ -- latch address upon falling ALE ---------------------------------------
+ if ale_pulse_s then
+ addr_q <= unsigned(din_q);
+ end if;
+
+ -- write to registers ---------------------------------------------------
+ if wr_pulse_s then
+ -- write to minor control
+ if sel_minor_ctrl_s then
+ if sel_objsub0_s then
+ reg_minor_objs_q(min_num_s).cam_y <= din_q;
+ end if;
+ if sel_objsub1_s then
+ reg_minor_objs_q(min_num_s).cam_x <= din_q;
+ end if;
+ if sel_objsub2_s then
+ reg_minor_objs_q(min_num_s).x9 <= din_q(minor_attr_x9_c);
+ reg_minor_objs_q(min_num_s).s <= din_q(minor_attr_s_c);
+ reg_minor_objs_q(min_num_s).d <= din_q(minor_attr_d_c);
+ reg_minor_objs_q(min_num_s).col <= din_q(5 downto 3);
+ end if;
+ end if;
+
+ -- write to major single objects
+ if sel_major_obj_s then
+ if sel_objsub0_s then
+ reg_major_objs_q(maj_num_s).cam_y <= din_q;
+ end if;
+ if sel_objsub1_s then
+ reg_major_objs_q(maj_num_s).cam_x <= din_q;
+ end if;
+ if sel_objsub2_s then
+ reg_major_objs_q(maj_num_s).attr.lss(byte_t'range) <= din_q;
+ end if;
+ if sel_objsub3_s then
+ reg_major_objs_q(maj_num_s).attr.lss(lss_t'high) <= din_q(0);
+ reg_major_objs_q(maj_num_s).attr.col(0) <= din_q(1);
+ reg_major_objs_q(maj_num_s).attr.col(1) <= din_q(2);
+ reg_major_objs_q(maj_num_s).attr.col(2) <= din_q(3);
+ end if;
+ end if;
+
+ -- write to major quad objects
+ if sel_major_quad_s then
+ if sel_objsub0_s then
+ reg_major_quad_objs_q(quad_num_s).cam_y <= din_q;
+ end if;
+ if sel_objsub1_s then
+ reg_major_quad_objs_q(quad_num_s).cam_x <= din_q;
+ end if;
+ if sel_objsub2_s then
+ reg_major_quad_objs_q(quad_num_s).attrs(min_num_s).lss(byte_t'range) <= din_q;
+ end if;
+ if sel_objsub3_s then
+ reg_major_quad_objs_q(quad_num_s).attrs(min_num_s).lss(lss_t'high) <= din_q(0);
+ reg_major_quad_objs_q(quad_num_s).attrs(min_num_s).col(0) <= din_q(1);
+ reg_major_quad_objs_q(quad_num_s).attrs(min_num_s).col(1) <= din_q(2);
+ reg_major_quad_objs_q(quad_num_s).attrs(min_num_s).col(2) <= din_q(3);
+ end if;
+ end if;
+
+ -- write to minor patterns
+ if sel_minor_pattern_s then
+ reg_minor_patterns_q(to_integer(addr_q(4 downto 3)))
+ (to_integer(addr_q(2 downto 0))) <= din_q;
+ end if;
+
+ -- write to CONTROL register
+ if sel_ctrl_s then
+ reg_ctrl_q <= din_q;
+ end if;
+
+ -- write to ENABLE OVERLAP register
+ if sel_overlap_s then
+ reg_enoverlap_q <= din_q;
+ end if;
+
+ -- write to COLOR register
+ if sel_color_s then
+ reg_color_q <= din_q(6 downto 0);
+ end if;
+
+ -- write to SOUND CONTROL register
+ if sel_sound_s then
+ reg_sound_q <= din_q;
+ end if;
+
+ -- write to grid bar configuration
+ if sel_grid_cx_s then
+ for hbar in byte_t'range loop
+ reg_grid_bars_q.hbars(hbar)(hbar_num_s) <= din_q(hbar);
+ end loop;
+ end if;
+ if sel_grid_dx_s then
+ reg_grid_bars_q.hbars(8)(hbar_num_s) <= din_q(0);
+ end if;
+ if sel_grid_ex_s then
+ reg_grid_bars_q.vbars(vbar_num_s) <= din_q;
+ end if;
+ end if;
+
+ -- position strobe ------------------------------------------------------
+ if clk_fall_en_i then
+ if pos_strobe_s = '1' then
+ reg_y_q <= std_logic_vector(vpos_i(pos_t'high-1 downto 0));
+ reg_x_q <= std_logic_vector(hpos_i(pos_t'high downto 1));
+ end if;
+ end if;
+
+ -- detect overlap -------------------------------------------------------
+ pix_vec_v := (bit_over_major_c => major_pix_i,
+ bit_over_ext_c => cx_i,
+ bit_over_hdgrid_c => grid_hpix_i or grid_dpix_i,
+ bit_over_vgrid_c => grid_vpix_i,
+ bit_over_minor3_c => minor_pix_i(3),
+ bit_over_minor2_c => minor_pix_i(2),
+ bit_over_minor1_c => minor_pix_i(1),
+ bit_over_minor0_c => minor_pix_i(0));
+ if clk_rise_en_i or clk_fall_en_i then
+ for idx in byte_t'range loop
+ if tag_overlap_f(pix => pix_vec_v,
+ mask => reg_enoverlap_q,
+ idx => idx) then
+ reg_overlap_q(idx) <= '1';
+ end if;
+ end loop;
+ end if;
+ -- clear OVERLAP register upon read
+ if rd_pulse_s and addr_q = addr_overlap_c then
+ reg_overlap_q <= (others => '0');
+ end if;
+
+ -- interrupts -----------------------------------------------------------
+ if clk_rise_en_i or clk_fall_en_i then
+ -- rising edge detection on vbl_i
+ vbl_q <= vbl_i;
+
+ if (cx_i and (major_pix_i or
+ grid_hpix_i or grid_dpix_i or grid_vpix_i or
+ minor_pix_i(3) or minor_pix_i(2) or minor_pix_i(1) or
+ minor_pix_i(0))) = '1' then
+ ext_int_q <= true;
+ end if;
+ if snd_int_i then
+ sound_int_q <= true;
+ end if;
+
+ if (ext_int_q and reg_ctrl_q(bit_ctrl_en_ext_overlap_c) = '1') or
+ (sound_int_q and reg_ctrl_q(bit_ctrl_en_sound_int_c) = '1') or
+ (hor_int_i and reg_ctrl_q(bit_ctrl_en_hor_int_c)) = '1' or
+ (vbl_i = '1' and vbl_q = '0') then
+ intr_q <= true;
+ end if;
+ end if;
+ -- clear interrupts upon CONTROL STATUS read
+ if rd_pulse_s and addr_q = addr_ctrl_stat_c then
+ ext_int_q <= false;
+ sound_int_q <= false;
+ intr_q <= false;
+ end if;
+
+ -- major <-> major collision flag ---------------------------------------
+ if clk_fall_en_i then
+ if major_coll_i then
+ major_coll_q <= true;
+ end if;
+ end if;
+ -- clear flag upon CONTROL STATUS read
+ if rd_pulse_s and addr_q = addr_ctrl_stat_c then
+ major_coll_q <= false;
+ end if;
+ end if;
+ end process seq;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process obj_num
+ --
+ -- Purpose:
+ -- Precalculates index numbers for various objects.
+ -- They are referenced at several places.
+ --
+ obj_num: process (addr_q)
+ begin
+ -- minor object and quad attribute number indicator
+ min_num_s <= to_integer(addr_q(3 downto 2));
+ -- major object number
+ case addr_q(5 downto 2) is
+ when "0100" => maj_num_s <= 0;
+ when "0101" => maj_num_s <= 1;
+ when "0110" => maj_num_s <= 2;
+ when "0111" => maj_num_s <= 3;
+ when "1000" => maj_num_s <= 4;
+ when "1001" => maj_num_s <= 5;
+ when "1010" => maj_num_s <= 6;
+ when "1011" => maj_num_s <= 7;
+ when "1100" => maj_num_s <= 8;
+ when "1101" => maj_num_s <= 9;
+ when "1110" => maj_num_s <= 10;
+ when "1111" => maj_num_s <= 11;
+ when others => maj_num_s <= 0;
+ end case;
+ -- quad object number indicator
+ quad_num_s <= to_integer(addr_q(5 downto 4));
+ -- horizontal/vertical grid bar number
+ hbar_num_s <= 0;
+ vbar_num_s <= 0;
+ case addr_q(3 downto 0) is
+ when "0001" =>
+ hbar_num_s <= 1;
+ vbar_num_s <= 1;
+ when "0010" =>
+ hbar_num_s <= 2;
+ vbar_num_s <= 2;
+ when "0011" =>
+ hbar_num_s <= 3;
+ vbar_num_s <= 3;
+ when "0100" =>
+ hbar_num_s <= 4;
+ vbar_num_s <= 4;
+ when "0101" =>
+ hbar_num_s <= 5;
+ vbar_num_s <= 5;
+ when "0110" =>
+ hbar_num_s <= 6;
+ vbar_num_s <= 6;
+ when "0111" =>
+ hbar_num_s <= 7;
+ vbar_num_s <= 7;
+ when "1000" =>
+ hbar_num_s <= 8;
+ vbar_num_s <= 8;
+ when "1001" =>
+ vbar_num_s <= 9;
+ when others =>
+ null;
+ end case;
+ end process obj_num;
+ --
+ -----------------------------------------------------------------------------
+
+ -- position strobe enable
+ pos_strobe_s <= stb_i or reg_ctrl_q(bit_ctrl_fps_c);
+
+
+ -----------------------------------------------------------------------------
+ -- Process read_mux
+ --
+ -- Purpose:
+ -- Implements the data read multiplexor that provides the readable
+ -- elements of the CPU I/O interface.
+ --
+ read_mux: process (addr_q,
+ wr_pulse_s,
+ reg_minor_objs_q,
+ reg_major_objs_q,
+ reg_major_quad_objs_q,
+ reg_minor_patterns_q,
+ reg_ctrl_q,
+ reg_overlap_q,
+ reg_y_q, reg_x_q,
+ reg_sound_q,
+ reg_grid_bars_q,
+ vbl_i,
+ pos_strobe_s,
+ ext_int_q, sound_int_q, hor_int_i,
+ major_coll_q,
+ min_num_s, maj_num_s, quad_num_s,
+ hbar_num_s, vbar_num_s)
+ begin
+ -- default assignements
+ dout_o <= (others => '-');
+ sel_minor_ctrl_s <= false;
+ sel_major_obj_s <= false;
+ sel_major_quad_s <= false;
+ sel_minor_pattern_s <= false;
+ sel_ctrl_s <= false;
+ sel_overlap_s <= false;
+ sel_color_s <= false;
+ sel_sound_s <= false;
+ sel_grid_cx_s <= false;
+ sel_grid_dx_s <= false;
+ sel_grid_ex_s <= false;
+ sel_objsub0_s <= addr_q(1 downto 0) = 0;
+ sel_objsub1_s <= addr_q(1 downto 0) = 1;
+ sel_objsub2_s <= addr_q(1 downto 0) = 2;
+ sel_objsub3_s <= addr_q(1 downto 0) = 3;
+ sound_reg_sel_s <= SND_REG_NONE;
+
+ case to_integer(addr_q) is
+ -- minor CAM
+ when addr_minor_ctrl_s_c to addr_minor_ctrl_e_c =>
+ sel_minor_ctrl_s <= true;
+ case addr_q(1 downto 0) is
+ when "00" =>
+ dout_o <= reg_minor_objs_q(min_num_s).cam_y;
+ when "01" =>
+ dout_o <= reg_minor_objs_q(min_num_s).cam_x;
+ when others =>
+ null;
+ end case;
+
+ -- major single objects
+ when addr_major_obj_s_c to addr_major_obj_e_c =>
+ sel_major_obj_s <= true;
+ case addr_q(1 downto 0) is
+ when "00" =>
+ dout_o <= reg_major_objs_q(maj_num_s).cam_y;
+ when "01" =>
+ dout_o <= reg_major_objs_q(maj_num_s).cam_x;
+ when "10" =>
+ dout_o <= reg_major_objs_q(maj_num_s).attr.lss(byte_t'range);
+ when "11" =>
+ dout_o(0) <= reg_major_objs_q(maj_num_s).attr.lss(lss_t'high);
+ dout_o(1) <= reg_major_objs_q(maj_num_s).attr.col(0);
+ dout_o(2) <= reg_major_objs_q(maj_num_s).attr.col(1);
+ dout_o(3) <= reg_major_objs_q(maj_num_s).attr.col(2);
+ when others =>
+ null;
+ end case;
+
+ -- major quad objects
+ when addr_major_quad_s_c to addr_major_quad_e_c =>
+ sel_major_quad_s <= true;
+ case addr_q(1 downto 0) is
+ when "00" =>
+ dout_o <= reg_major_quad_objs_q(quad_num_s).cam_y;
+ when "01" =>
+ dout_o <= reg_major_quad_objs_q(quad_num_s).cam_x;
+ when "10" =>
+ dout_o <= reg_major_quad_objs_q(quad_num_s).attrs(min_num_s).lss(byte_t'range);
+ when "11" =>
+ dout_o(0) <= reg_major_quad_objs_q(quad_num_s).attrs(min_num_s).lss(lss_t'high);
+ dout_o(1) <= reg_major_quad_objs_q(quad_num_s).attrs(min_num_s).col(0);
+ dout_o(2) <= reg_major_quad_objs_q(quad_num_s).attrs(min_num_s).col(1);
+ dout_o(3) <= reg_major_quad_objs_q(quad_num_s).attrs(min_num_s).col(2);
+ when others =>
+ null;
+ end case;
+
+ -- minor pattern RAM
+ when addr_minor_pattern_s_c to addr_minor_pattern_e_c =>
+ sel_minor_pattern_s <= true;
+ dout_o <= reg_minor_patterns_q(to_integer(addr_q(4 downto 3)))
+ (to_integer(addr_q(2 downto 0)));
+
+ -- CONTROL register
+ when addr_ctrl_c =>
+ sel_ctrl_s <= true;
+ dout_o <= reg_ctrl_q;
+
+ -- CONTROL STATUS register
+ when addr_ctrl_stat_c =>
+ dout_o <= (0 => not hor_int_i,
+ 1 => pos_strobe_s,
+ 2 => to_stdlogic(sound_int_q),
+ 3 => vbl_i,
+ 6 => to_stdlogic(ext_int_q),
+ 7 => to_stdlogic(major_coll_q),
+ others => '0');
+
+ -- OVERLAP STATUS register
+ when addr_overlap_c =>
+ sel_overlap_s <= true;
+ dout_o <= reg_overlap_q;
+
+ -- COLOR register
+ when addr_color_c =>
+ sel_color_s <= true;
+
+ -- Y register
+ when addr_ypos_c =>
+ dout_o <= reg_y_q;
+
+ -- X register
+ when addr_xpos_c =>
+ dout_o <= reg_x_q;
+
+ -- SOUND registers
+ when addr_snd0_c =>
+ if wr_pulse_s then
+ sound_reg_sel_s <= SND_REG_0;
+ end if;
+ when addr_snd1_c =>
+ if wr_pulse_s then
+ sound_reg_sel_s <= SND_REG_1;
+ end if;
+ when addr_snd2_c =>
+ if wr_pulse_s then
+ sound_reg_sel_s <= SND_REG_2;
+ end if;
+
+ -- SOUND STATUS register
+ when addr_snd_stat_c =>
+ sel_sound_s <= true;
+ dout_o <= reg_sound_q;
+
+ -- GRID configuration
+ when addr_grid_cx_s_c to addr_grid_cx_e_c =>
+ sel_grid_cx_s <= true;
+ for hbar in byte_t'range loop
+ dout_o(hbar) <= reg_grid_bars_q.hbars(hbar)(hbar_num_s);
+ end loop;
+ when addr_grid_dx_s_c to addr_grid_dx_e_c =>
+ sel_grid_dx_s <= true;
+ dout_o(0) <= reg_grid_bars_q.hbars(8)(hbar_num_s);
+ when addr_grid_ex_s_c to addr_grid_ex_e_c =>
+ sel_grid_ex_s <= true;
+ dout_o <= reg_grid_bars_q.vbars(vbar_num_s);
+
+ when others =>
+ null;
+ end case;
+ end process read_mux;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Output mapping
+ -----------------------------------------------------------------------------
+ dout_en_o <= not cs_n_i and not rd_n_i;
+ en_disp_o <= reg_ctrl_q(bit_ctrl_en_display_c);
+ grid_bg_col_o <= reg_color_q;
+ intr_n_o <= '0' when intr_q else '1';
+ --
+ minor_objs_o <= reg_minor_objs_q;
+ major_objs_o <= reg_major_objs_q;
+ major_quad_objs_o <= reg_major_quad_objs_q;
+ minor_patterns_o <= reg_minor_patterns_q;
+
+-- the following is not working due to a problem in GHDL 0.25
+-- grid_cfg_o <= (enable => reg_ctrl_q(bit_ctrl_en_grid_c),
+-- wide => reg_ctrl_q(bit_ctrl_wide_c),
+-- dot_en => reg_ctrl_q(bit_ctrl_dot_en_c),
+-- bars => reg_grid_bars_q);
+ grid_cfg_o.enable <= reg_ctrl_q(bit_ctrl_en_grid_c);
+ grid_cfg_o.wide <= reg_ctrl_q(bit_ctrl_wide_c);
+ grid_cfg_o.dot_en <= reg_ctrl_q(bit_ctrl_dot_en_c);
+ grid_cfg_o.bars <= reg_grid_bars_q;
+
+ cpu2snd_o.enable <= reg_sound_q(bit_snd_en_c) = '1';
+ cpu2snd_o.freq <= SND_FREQ_HIGH
+ when reg_sound_q(bit_snd_freq_c) = '1' else
+ SND_FREQ_LOW;
+ cpu2snd_o.noise <= reg_sound_q(bit_snd_noise_c) = '1';
+ cpu2snd_o.volume <= reg_sound_q(bit_snd_vol_h_c downto bit_snd_vol_l_c);
+ cpu2snd_o.reg_sel <= sound_reg_sel_s;
+ cpu2snd_o.din <= din_q;
+
+end rtl;
diff --git a/common/Video/i8244/i8244_grid-c.vhd b/common/Video/i8244/i8244_grid-c.vhd
new file mode 100644
index 00000000..3d38d0ea
--- /dev/null
+++ b/common/Video/i8244/i8244_grid-c.vhd
@@ -0,0 +1,14 @@
+-------------------------------------------------------------------------------
+--
+-- i8244 Video Display Controller
+--
+-- $Id: i8244_grid-c.vhd,v 1.2 2007/02/05 21:57:37 arnim Exp $
+--
+-------------------------------------------------------------------------------
+
+configuration i8244_grid_rtl_c0 of i8244_grid is
+
+ for rtl
+ end for;
+
+end i8244_grid_rtl_c0;
diff --git a/common/Video/i8244/i8244_grid.vhd b/common/Video/i8244/i8244_grid.vhd
new file mode 100644
index 00000000..f7138b0b
--- /dev/null
+++ b/common/Video/i8244/i8244_grid.vhd
@@ -0,0 +1,211 @@
+-------------------------------------------------------------------------------
+--
+-- i8244 Video Display Controller
+--
+-- $Id: i8244_grid.vhd,v 1.14 2007/02/05 22:08:59 arnim Exp $
+--
+-- Grid Generator
+--
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2007, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.i8244_pack.pos_t;
+use work.i8244_grid_pack.grid_cfg_t;
+
+entity i8244_grid is
+
+ port (
+ clk_i : in std_logic;
+ clk_en_i : in boolean;
+ res_i : in boolean;
+ hpos_i : in pos_t;
+ vpos_i : in pos_t;
+ hbl_i : in std_logic;
+ vbl_i : in std_logic;
+ grid_cfg_i : in grid_cfg_t;
+ grid_hpix_o : out std_logic;
+ grid_vpix_o : out std_logic;
+ grid_dpix_o : out std_logic
+ );
+
+end i8244_grid;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+use work.i8244_pack.all;
+use work.i8244_grid_pack.all;
+
+architecture rtl of i8244_grid is
+
+ -----------------------------------------------------------------------------
+ -- Grid geometry:
+ --
+ -- number of horizontal grid segments
+ constant grid_hnum_c : natural := 10;
+ -- left horizontal offset (3.54 MHz clocks)
+ constant grid_hoffset_c : natural := 16#08#;
+ -- horizontal width of vertical segments and dots (3.54 MHz clock)
+ constant grid_hwidth_c : natural := 16#02#;
+ -- length/spacing of horizontal grid segments (3.54 MHz clock)
+ constant grid_hspace_c : natural := 16#10#;
+ --
+ -- number of vertical grid segments
+ constant grid_vnum_c : natural := 9;
+ -- upper vertical offset (scanlines)
+ constant grid_voffset_c : natural := 16#18#;
+ -- vertical height of horizontal segments and dots (scanlines)
+ constant grid_vwidth_c : natural := 16#03#;
+ -- height/spacing of vertical grid segments (scanlines)
+ constant grid_vspace_c : natural := 16#18#;
+ --
+ -----------------------------------------------------------------------------
+
+ signal hgrid_q,
+ vgrid_q,
+ dgrid_q : std_logic;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process grid_gen
+ --
+ -- Purpose:
+ -- Generates the grid activity signals for horizontal and vertical
+ -- grid elements.
+ --
+ grid_gen: process (clk_i, res_i)
+ variable hpos_v,
+ vpos_v : natural;
+ variable upper_v,
+ lower_v,
+ left_v,
+ right_v,
+ dot_v : natural;
+ begin
+ if res_i then
+ hgrid_q <= '0';
+ vgrid_q <= '0';
+ dgrid_q <= '0';
+
+ elsif rising_edge(clk_i) then
+ -- horizontal positioning bases on 3.54 MHz pixels/clocks
+ hpos_v := to_integer(hpos_i(pos_t'high downto 1));
+ -- vertical positioning bases on scanlines (no scaling etc.)
+ vpos_v := to_integer(vpos_i);
+
+ if clk_en_i then
+ hgrid_q <= '0';
+ dgrid_q <= '0';
+ vgrid_q <= '0';
+
+ -- horizontal bars ----------------------------------------------------
+ for hbar in 0 to grid_vnum_c-1 loop
+ upper_v := grid_voffset_c + hbar * grid_vspace_c;
+ lower_v := upper_v + grid_vwidth_c;
+
+ -- check upper and lower bar/dot limits
+ if vpos_v >= upper_v and vpos_v < lower_v then
+ for idx in 0 to grid_hnum_c-2 loop
+ left_v := grid_hoffset_c + idx * grid_hspace_c;
+ right_v := left_v + grid_hspace_c + grid_hwidth_c;
+ dot_v := left_v + grid_hwidth_c;
+
+ -- check left limit
+ if hpos_v >= left_v then
+ -- bar: check right limit
+ if hpos_v < right_v then
+ if grid_cfg_i.bars.hbars(hbar)(idx) = '1' then
+ hgrid_q <= '1';
+ end if;
+ end if;
+ -- dot: check right limit
+ if hpos_v < dot_v then
+ dgrid_q <= '1';
+ end if;
+ end if;
+ end loop;
+ end if;
+ end loop;
+
+ -- vertical bars ------------------------------------------------------
+ for vbar in 0 to grid_hnum_c-1 loop
+ left_v := grid_hoffset_c + vbar * grid_hspace_c;
+ if grid_cfg_i.wide = '1' then
+ -- wide grid extends over horizontal space
+ right_v := left_v + grid_hspace_c;
+ else
+ -- normal grid
+ right_v := left_v + grid_hwidth_c;
+ end if;
+
+ -- check left and right bar limits
+ if hpos_v >= left_v and hpos_v < right_v then
+ for idx in 0 to grid_vnum_c-2 loop
+ upper_v := grid_voffset_c + idx * grid_vspace_c;
+ lower_v := upper_v + grid_vspace_c;
+
+ -- check upper and lower bar limits
+ if vpos_v >= upper_v and vpos_v < lower_v then
+ if grid_cfg_i.bars.vbars(vbar)(idx) = '1' then
+ vgrid_q <= '1';
+ end if;
+ end if;
+ end loop;
+ end if;
+ end loop;
+
+ end if;
+ end if;
+ end process grid_gen;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Output mapping
+ -----------------------------------------------------------------------------
+ grid_hpix_o <= hgrid_q;
+ grid_vpix_o <= vgrid_q;
+ grid_dpix_o <= dgrid_q;
+
+end rtl;
diff --git a/common/Video/i8244/i8244_grid_pack-p.vhd b/common/Video/i8244/i8244_grid_pack-p.vhd
new file mode 100644
index 00000000..bc95d8de
--- /dev/null
+++ b/common/Video/i8244/i8244_grid_pack-p.vhd
@@ -0,0 +1,38 @@
+-------------------------------------------------------------------------------
+--
+-- i8244 Video Display Controller
+--
+-- $Id: i8244_grid_pack-p.vhd,v 1.5 2007/02/05 22:08:59 arnim Exp $
+--
+-- Copyright (c) 2007, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.i8244_pack.byte_array_t;
+
+package i8244_grid_pack is
+
+ subtype hbar_t is std_logic_vector(8 downto 0);
+ type hbars_t is array (natural range 0 to 8) of hbar_t;
+
+ -- grid configuration
+ type grid_bars_t is
+ record
+ hbars : hbars_t;
+ vbars : byte_array_t(0 to 9);
+ end record;
+ --
+ type grid_cfg_t is
+ record
+ enable : std_logic;
+ wide : std_logic;
+ dot_en : std_logic;
+ bars : grid_bars_t;
+ end record;
+
+end;
diff --git a/common/Video/i8244/i8244_major-c.vhd b/common/Video/i8244/i8244_major-c.vhd
new file mode 100644
index 00000000..0c716f22
--- /dev/null
+++ b/common/Video/i8244/i8244_major-c.vhd
@@ -0,0 +1,27 @@
+-------------------------------------------------------------------------------
+--
+-- i8244 Video Display Controller
+--
+-- $Id: i8244_major-c.vhd,v 1.3 2007/02/05 21:57:37 arnim Exp $
+--
+-------------------------------------------------------------------------------
+
+configuration i8244_major_rtl_c0 of i8244_major is
+
+ for rtl
+
+ for single_object
+ for all : i8244_major_obj
+ use configuration work.i8244_major_obj_rtl_c0;
+ end for;
+ end for;
+
+ for quad_object
+ for all : i8244_major_quad_obj
+ use configuration work.i8244_major_quad_obj_rtl_c0;
+ end for;
+ end for;
+
+ end for;
+
+end i8244_major_rtl_c0;
diff --git a/common/Video/i8244/i8244_major.vhd b/common/Video/i8244/i8244_major.vhd
new file mode 100644
index 00000000..b2b73398
--- /dev/null
+++ b/common/Video/i8244/i8244_major.vhd
@@ -0,0 +1,263 @@
+-------------------------------------------------------------------------------
+--
+-- i8244 Video Display Controller
+--
+-- $Id: i8244_major.vhd,v 1.10 2007/02/05 22:08:59 arnim Exp $
+--
+-- Major Display System
+--
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2007, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.i8244_pack.pos_t;
+use work.i8244_pack.col_attr_t;
+use work.i8244_major_pack.all;
+
+entity i8244_major is
+
+ port (
+ clk_i : in std_logic;
+ clk_fall_en_i : in boolean;
+ res_i : in boolean;
+ hpos_i : in pos_t;
+ vpos_i : in pos_t;
+ major_objs_i : in major_objs_t;
+ major_quad_objs_i : in major_quad_objs_t;
+ rom_addr_o : out rom_addr_t;
+ rom_en_o : out std_logic;
+ rom_data_i : in rom_data_t;
+ major_pix_o : out std_logic;
+ major_attr_o : out col_attr_t;
+ major_coll_o : out boolean
+ );
+
+end i8244_major;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+use work.i8244_pack.byte_t;
+use work.i8244_comp_pack.i8244_major_obj;
+use work.i8244_comp_pack.i8244_major_quad_obj;
+
+architecture rtl of i8244_major is
+
+ -- vertical/horizontal match lines from all major objects
+ type vhmatch_all_t is array (all_major_obj_range_t) of boolean;
+ signal vhmatch_all_s : vhmatch_all_t;
+ signal vhmatch_s : boolean;
+
+ -- LSS information from all major objects
+ type lss_all_t is array (all_major_obj_range_t) of lss_t;
+ signal lss_all_s : lss_all_t;
+ signal lss_s : lss_t;
+
+ -- color attribute information from all major objects
+ type col_attr_all_t is array (all_major_obj_range_t) of col_attr_t;
+ signal col_attr_all_s : col_attr_all_t;
+ signal col_attr_s : col_attr_t;
+
+ signal vstop_s,
+ hstop_s : boolean;
+
+ signal rom_addr_s : rom_addr_t;
+ signal rom_addr_low_q : std_logic_vector(2 downto 0);
+
+ subtype pix_idx_t is unsigned(3 downto 0);
+ -- idle value of counter: MSB cleared
+ constant pix_idx_idle_c : pix_idx_t := "0111";
+ -- start value upon activation:
+ -- set MSB
+ constant pix_idx_start_c : pix_idx_t := "1111";
+ signal pix_idx_q : pix_idx_t;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Single major objetcs
+ -----------------------------------------------------------------------------
+ single_object: for idx in 0 to num_major_objects_c-1 generate
+ obj_b : i8244_major_obj
+ port map (
+ clk_i => clk_i,
+ clk_en_i => clk_fall_en_i,
+ res_i => res_i,
+ hpos_i => hpos_i,
+ vpos_i => vpos_i,
+ vstop_i => vstop_s,
+ hstop_i => hstop_s,
+ obj_i => major_objs_i(idx),
+ vhmatch_o => vhmatch_all_s(idx),
+ lss_o => lss_all_s(idx),
+ col_attr_o => col_attr_all_s(idx)
+ );
+ end generate;
+
+
+ -----------------------------------------------------------------------------
+ -- Quad major objects
+ -----------------------------------------------------------------------------
+ quad_object: for idx in 0 to num_major_quad_objects_c-1 generate
+ obj_b : i8244_major_quad_obj
+ port map (
+ clk_i => clk_i,
+ clk_en_i => clk_fall_en_i,
+ res_i => res_i,
+ hpos_i => hpos_i,
+ vpos_i => vpos_i,
+ vstop_i => vstop_s,
+ hstop_i => hstop_s,
+ quad_obj_i => major_quad_objs_i(idx),
+ vhmatch_o => vhmatch_all_s(num_major_objects_c + idx),
+ lss_o => lss_all_s(num_major_objects_c + idx),
+ col_attr_o => col_attr_all_s(num_major_objects_c + idx)
+ );
+ end generate;
+
+
+ -----------------------------------------------------------------------------
+ -- Process or_trees
+ --
+ -- Purpose:
+ -- Generates the OR trees on the outputs of all major objects
+ --
+ or_trees: process (vhmatch_all_s,
+ lss_all_s,
+ col_attr_all_s)
+ variable vhmatch_v : boolean;
+ variable lss_v : lss_t;
+ variable col_attr_v : col_attr_t;
+ begin
+ vhmatch_v := false;
+ lss_v := (others => '0');
+ col_attr_v := (others => '0');
+
+ for idx in 0 to num_all_major_objects_c-1 loop
+ vhmatch_v := vhmatch_v or vhmatch_all_s(idx);
+ lss_v := lss_v or lss_all_s(idx);
+ col_attr_v := col_attr_v or col_attr_all_s(idx);
+ end loop;
+
+ vhmatch_s <= vhmatch_v;
+ lss_s <= lss_v;
+ col_attr_s <= col_attr_v;
+ end process or_trees;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process seq
+ --
+ -- Purpose:
+ -- Implements the various sequential elements.
+ --
+ seq: process (clk_i, res_i)
+ begin
+ if res_i then
+ pix_idx_q <= pix_idx_idle_c;
+ rom_addr_low_q <= (others => '0');
+
+ elsif rising_edge(clk_i) then
+ if clk_fall_en_i then
+ if vhmatch_s then
+ -- start counter
+ pix_idx_q <= pix_idx_start_c;
+ elsif pix_idx_q(3) = '1' then
+ -- count while active
+ pix_idx_q <= pix_idx_q - 1;
+ end if;
+
+ rom_addr_low_q <= rom_addr_s(2 downto 0);
+ end if;
+ end if;
+ end process seq;
+ --
+ -----------------------------------------------------------------------------
+
+ -- stop horizontal presentation of character line
+ -- a) when all pixels have been drawn (counter pix_idx is at 0)
+ -- b) when a new V/H match for another character occurs
+ hstop_s <= clk_fall_en_i and (pix_idx_q(2 downto 0) = 0 or vhmatch_s);
+ -- stop vertical presentation of character:
+ -- * horizontal presentation finished
+ -- * last line of character is shown
+ -- * last vertical scanline is shown
+ vstop_s <= hstop_s and rom_addr_low_q = "110" and vpos_i(0) = '1';
+
+ -----------------------------------------------------------------------------
+ -- Process rom_addr
+ --
+ -- Purpose:
+ -- Implements the 9 bit adder for ROM address calculation.
+ --
+ rom_addr: process (vpos_i,
+ lss_s)
+ variable a_v,
+ b_v,
+ sum_v : unsigned(8 downto 0);
+ begin
+ a_v := '0' & unsigned(vpos_i(8 downto 1));
+ b_v := unsigned(lss_s);
+ sum_v := a_v + b_v;
+
+ rom_addr_s <= std_logic_vector(sum_v);
+ end process rom_addr;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Output mapping
+ -----------------------------------------------------------------------------
+ rom_addr_o <= rom_addr_s;
+ rom_en_o <= '1' when vhmatch_s and clk_fall_en_i else '0';
+ major_pix_o <= rom_data_i(to_integer(pix_idx_q(2 downto 0)))
+ when pix_idx_q(3) = '1' else
+ '0';
+ major_attr_o <= col_attr_s;
+ -- major <-> major collision when vhmatches and pix index is in the middle
+ -- of a character
+ major_coll_o <= clk_fall_en_i and vhmatch_s and
+ pix_idx_q > 8;
+
+end rtl;
diff --git a/common/Video/i8244/i8244_major_obj-c.vhd b/common/Video/i8244/i8244_major_obj-c.vhd
new file mode 100644
index 00000000..072d78b3
--- /dev/null
+++ b/common/Video/i8244/i8244_major_obj-c.vhd
@@ -0,0 +1,14 @@
+-------------------------------------------------------------------------------
+--
+-- i8244 Video Display Controller
+--
+-- $Id: i8244_major_obj-c.vhd,v 1.2 2007/02/05 21:57:37 arnim Exp $
+--
+-------------------------------------------------------------------------------
+
+configuration i8244_major_obj_rtl_c0 of i8244_major_obj is
+
+ for rtl
+ end for;
+
+end i8244_major_obj_rtl_c0;
diff --git a/common/Video/i8244/i8244_major_obj.vhd b/common/Video/i8244/i8244_major_obj.vhd
new file mode 100644
index 00000000..989808d9
--- /dev/null
+++ b/common/Video/i8244/i8244_major_obj.vhd
@@ -0,0 +1,203 @@
+-------------------------------------------------------------------------------
+--
+-- i8244 Video Display Controller
+--
+-- $Id: i8244_major_obj.vhd,v 1.8 2007/02/05 22:08:59 arnim Exp $
+--
+-- Major Display Object
+--
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2007, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.i8244_pack.pos_t;
+use work.i8244_pack.col_attr_t;
+use work.i8244_major_pack.all;
+
+entity i8244_major_obj is
+
+ port (
+ clk_i : in std_logic;
+ clk_en_i : in boolean;
+ res_i : in boolean;
+ hpos_i : in pos_t;
+ vpos_i : in pos_t;
+ vstop_i : in boolean;
+ hstop_i : in boolean;
+ obj_i : in major_obj_t;
+ vhmatch_o : out boolean;
+ lss_o : out lss_t;
+ col_attr_o : out col_attr_t
+ );
+
+end i8244_major_obj;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+use work.i8244_pack.byte_t;
+
+architecture rtl of i8244_major_obj is
+
+ signal vactive_s,
+ vactive_q : boolean;
+ signal hactive_s,
+ hactive_q : boolean;
+
+ signal vhmatch_s : boolean;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process seq
+ --
+ -- Purpose:
+ -- Implements the sequential elements of a major object.
+ --
+ seq: process (clk_i, res_i)
+ begin
+ if res_i then
+ vactive_q <= false;
+ hactive_q <= false;
+ elsif rising_edge(clk_i) then
+ if clk_en_i then
+ -- default update
+ vactive_q <= vactive_s;
+ hactive_q <= hactive_s;
+
+ if vactive_q and hactive_q then
+ if vstop_i then
+ -- char is finished
+ vactive_q <= false;
+ end if;
+
+ if hstop_i and not vhmatch_s then
+ -- current line is finished
+ hactive_q <= false;
+ end if;
+ end if;
+
+ end if;
+ end if;
+ end process seq;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process comb
+ --
+ -- Purpose:
+ -- Implements the combinational logic of a major object:
+ -- * vertical CAM comparison
+ -- * horizontal CAM comparison
+ --
+ comb: process (hpos_i, vpos_i,
+ obj_i,
+ vactive_q, hactive_q)
+ variable vactive_v,
+ hactive_v : boolean;
+ begin
+ -- default assignments
+ vhmatch_s <= false;
+ vactive_v := vactive_q;
+ hactive_v := hactive_q;
+
+ -- vertical CAM comparison ------------------------------------------------
+ if vpos_i(pos_t'high downto 1) =
+ unsigned(obj_i.cam_y(byte_t'high downto 1)) and
+ hpos_i = 0 then
+ vactive_v := true;
+ end if;
+
+ -- horizontal CAM comparison ----------------------------------------------
+ if vactive_v and
+ hpos_i(pos_t'high downto 1) =
+ unsigned(obj_i.cam_x) then
+ hactive_v := true;
+ vhmatch_s <= true;
+ end if;
+
+ vactive_s <= vactive_v;
+ hactive_s <= hactive_v;
+ end process comb;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process output
+ --
+ -- Purpose:
+ -- Generates the output signals.
+ -- Per default, they are inactive and only when a line of this object
+ -- is displayed, they carry information.
+ --
+ output: process (vactive_q, hactive_q,
+ vhmatch_s,
+ hstop_i,
+ obj_i)
+ begin
+ -- default (inactive state) assignemnts
+ lss_o <= (others => '0');
+ col_attr_o <= (others => '0');
+
+ -- drive active data when
+ -- * V/H match occurs
+ -- * this object is actively displaying a line and
+ -- no horizontal stop has been signalled
+ if vhmatch_s or
+ (vactive_q and hactive_q and not hstop_i) then
+ -- stop LSS immediately to prevent overlap with next character
+ -- when (pre)fetching ROM data
+ lss_o <= obj_i.attr.lss;
+ end if;
+ if vhmatch_s or
+ (vactive_q and hactive_q) then
+ col_attr_o <= obj_i.attr.col;
+ end if;
+ end process output;
+ --
+ -----------------------------------------------------------------------------
+
+ vhmatch_o <= vhmatch_s;
+
+end rtl;
diff --git a/common/Video/i8244/i8244_major_pack-p.vhd b/common/Video/i8244/i8244_major_pack-p.vhd
new file mode 100644
index 00000000..cafee3ee
--- /dev/null
+++ b/common/Video/i8244/i8244_major_pack-p.vhd
@@ -0,0 +1,61 @@
+-------------------------------------------------------------------------------
+--
+-- i8244 Video Display Controller
+--
+-- $Id: i8244_major_pack-p.vhd,v 1.7 2007/02/05 22:08:59 arnim Exp $
+--
+-- Copyright (c) 2007, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.i8244_pack.byte_t;
+use work.i8244_pack.col_attr_t;
+
+package i8244_major_pack is
+
+ subtype lss_t is std_logic_vector(8 downto 0);
+ subtype rom_addr_t is std_logic_vector(8 downto 0);
+ subtype rom_data_t is std_logic_vector(7 downto 0);
+
+ type major_attr_t is
+ record
+ lss : lss_t;
+ col : col_attr_t;
+ end record;
+
+ constant num_major_quad_attr_c : natural := 4;
+ subtype major_quad_attr_range_t is natural range 0 to num_major_quad_attr_c-1;
+ type major_quad_attrs_t is array (major_quad_attr_range_t) of major_attr_t;
+
+ type major_obj_t is
+ record
+ cam_y : byte_t;
+ cam_x : byte_t;
+ attr : major_attr_t;
+ end record;
+
+ constant num_major_objects_c : natural := 12;
+ subtype major_obj_range_t is natural range 0 to num_major_objects_c-1;
+ type major_objs_t is array (major_obj_range_t) of major_obj_t;
+
+ type major_quad_obj_t is
+ record
+ cam_y : byte_t;
+ cam_x : byte_t;
+ attrs : major_quad_attrs_t;
+ end record;
+
+ constant num_major_quad_objects_c : natural := 4;
+ subtype major_quad_obj_range_t is natural range 0 to num_major_quad_objects_c-1;
+ type major_quad_objs_t is array (major_quad_obj_range_t) of major_quad_obj_t;
+
+ constant num_all_major_objects_c : natural := num_major_quad_objects_c +
+ num_major_objects_c;
+ subtype all_major_obj_range_t is natural range 0 to num_all_major_objects_c-1;
+
+end;
diff --git a/common/Video/i8244/i8244_major_quad_obj-c.vhd b/common/Video/i8244/i8244_major_quad_obj-c.vhd
new file mode 100644
index 00000000..f849ba9a
--- /dev/null
+++ b/common/Video/i8244/i8244_major_quad_obj-c.vhd
@@ -0,0 +1,19 @@
+-------------------------------------------------------------------------------
+--
+-- i8244 Video Display Controller
+--
+-- $Id: i8244_major_quad_obj-c.vhd,v 1.2 2007/02/05 21:57:37 arnim Exp $
+--
+-------------------------------------------------------------------------------
+
+configuration i8244_major_quad_obj_rtl_c0 of i8244_major_quad_obj is
+
+ for rtl
+
+ for obj_b : i8244_major_obj
+ use configuration work.i8244_major_obj_rtl_c0;
+ end for;
+
+ end for;
+
+end i8244_major_quad_obj_rtl_c0;
diff --git a/common/Video/i8244/i8244_major_quad_obj.vhd b/common/Video/i8244/i8244_major_quad_obj.vhd
new file mode 100644
index 00000000..e009f5c9
--- /dev/null
+++ b/common/Video/i8244/i8244_major_quad_obj.vhd
@@ -0,0 +1,188 @@
+-------------------------------------------------------------------------------
+--
+-- i8244 Video Display Controller
+--
+-- $Id: i8244_major_quad_obj.vhd,v 1.7 2007/02/05 22:08:59 arnim Exp $
+--
+-- Major Display Quad Object
+---
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2007, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.i8244_pack.pos_t;
+use work.i8244_pack.col_attr_t;
+use work.i8244_major_pack.all;
+
+entity i8244_major_quad_obj is
+
+ port (
+ clk_i : in std_logic;
+ clk_en_i : in boolean;
+ res_i : in boolean;
+ hpos_i : in pos_t;
+ vpos_i : in pos_t;
+ vstop_i : in boolean;
+ hstop_i : in boolean;
+ quad_obj_i : in major_quad_obj_t;
+ vhmatch_o : out boolean;
+ lss_o : out lss_t;
+ col_attr_o : out col_attr_t
+ );
+
+end i8244_major_quad_obj;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+use work.i8244_comp_pack.i8244_major_obj;
+
+architecture rtl of i8244_major_quad_obj is
+
+ signal vhmatch_s : boolean;
+ signal vstop_s : boolean;
+ signal obj_s : major_obj_t;
+
+ signal match_cnt_q : unsigned(1 downto 0);
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- One core major object
+ -----------------------------------------------------------------------------
+ obj_b : i8244_major_obj
+ port map (
+ clk_i => clk_i,
+ clk_en_i => clk_en_i,
+ res_i => res_i,
+ hpos_i => hpos_i,
+ vpos_i => vpos_i,
+ vstop_i => vstop_s,
+ hstop_i => hstop_i,
+ obj_i => obj_s,
+ vhmatch_o => vhmatch_s,
+ lss_o => lss_o,
+ col_attr_o => col_attr_o
+ );
+
+
+ -----------------------------------------------------------------------------
+ -- Process cnt
+ --
+ -- Purpose:
+ -- Implements the counter for tracking horizontal matches.
+ -- It is used to determine when the fourth character inside this quad
+ -- element has been displayed.
+ -- It also adds an offset to the horizontal CAM value as it increments.
+ --
+ cnt: process (clk_i, res_i)
+ begin
+ if res_i then
+ match_cnt_q <= (others => '0');
+ elsif rising_edge(clk_i) then
+ if clk_en_i then
+ if vhmatch_s then
+ match_cnt_q <= match_cnt_q + 1;
+ end if;
+ end if;
+ end if;
+ end process cnt;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process ctrl
+ --
+ -- Purpose:
+ -- Controls the embedded major object.
+ -- According to the current state of the match counter, it
+ -- * calculates the next horizontal CAM value
+ -- * provides the lss and attr parts of the four quad elements
+ -- * suppresses the vstop input until the fourth element is
+ -- displayed
+ --
+ ctrl: process (match_cnt_q,
+ quad_obj_i,
+ vstop_i)
+ variable next_cam_x_v : unsigned(7 downto 0);
+ begin
+ -- default assignments
+ vstop_s <= false;
+ obj_s.cam_y <= quad_obj_i.cam_y;
+
+ -- add content of match counter times 16 to the horizontal CAM value
+ next_cam_x_v := unsigned(quad_obj_i.cam_x);
+ next_cam_x_v(7 downto 4) := next_cam_x_v(7 downto 4) + match_cnt_q;
+ obj_s.cam_x <= std_logic_vector(next_cam_x_v);
+
+ -- note: match_cnt_q points to the NEXT displayed object
+ -- thus lss is taken from the next (pointed to) object while
+ -- the color attributes are taken from the current (previous pointed
+ -- to) object
+ case match_cnt_q is
+ when "00" =>
+ obj_s.attr.lss <= quad_obj_i.attrs(0).lss;
+ obj_s.attr.col <= quad_obj_i.attrs(3).col;
+ -- enable vstop trigger
+ vstop_s <= vstop_i;
+ when "01" =>
+ obj_s.attr.lss <= quad_obj_i.attrs(1).lss;
+ obj_s.attr.col <= quad_obj_i.attrs(0).col;
+ when "10" =>
+ obj_s.attr.lss <= quad_obj_i.attrs(2).lss;
+ obj_s.attr.col <= quad_obj_i.attrs(1).col;
+ when others =>
+ obj_s.attr.lss <= quad_obj_i.attrs(3).lss;
+ obj_s.attr.col <= quad_obj_i.attrs(2).col;
+ end case;
+
+ end process ctrl;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Output mapping
+ -----------------------------------------------------------------------------
+ vhmatch_o <= vhmatch_s;
+
+end rtl;
diff --git a/common/Video/i8244/i8244_minor-c.vhd b/common/Video/i8244/i8244_minor-c.vhd
new file mode 100644
index 00000000..89d6b428
--- /dev/null
+++ b/common/Video/i8244/i8244_minor-c.vhd
@@ -0,0 +1,14 @@
+-------------------------------------------------------------------------------
+--
+-- i8244 Video Display Controller
+--
+-- $Id: i8244_minor-c.vhd,v 1.2 2007/02/05 21:57:37 arnim Exp $
+--
+-------------------------------------------------------------------------------
+
+configuration i8244_minor_rtl_c0 of i8244_minor is
+
+ for rtl
+ end for;
+
+end i8244_minor_rtl_c0;
diff --git a/common/Video/i8244/i8244_minor.vhd b/common/Video/i8244/i8244_minor.vhd
new file mode 100644
index 00000000..9ee3f0ea
--- /dev/null
+++ b/common/Video/i8244/i8244_minor.vhd
@@ -0,0 +1,282 @@
+-------------------------------------------------------------------------------
+--
+-- i8244 Video Display Controller
+--
+-- $Id: i8244_minor.vhd,v 1.9 2007/02/05 22:08:59 arnim Exp $
+--
+-- Minor Display System
+--
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2007, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.i8244_pack.pos_t;
+use work.i8244_minor_pack.all;
+
+entity i8244_minor is
+
+ port (
+ clk_i : in std_logic;
+ clk_rise_en_i : in boolean;
+ clk_fall_en_i : in boolean;
+ res_i : in boolean;
+ hpos_i : in pos_t;
+ vpos_i : in pos_t;
+ hbl_i : in std_logic;
+ vbl_i : in std_logic;
+ minor_objs_i : in minor_objs_t;
+ minor_patterns_i : in minor_patterns_t;
+ minor_pix_o : out std_logic_vector(minor_obj_range_t)
+ );
+
+end i8244_minor;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+use work.i8244_pack.byte_t;
+
+architecture rtl of i8244_minor is
+
+ -- a line counter for each object
+ subtype line_cnt_t is unsigned(2 downto 0);
+ type line_cnts_t is array (minor_obj_range_t) of line_cnt_t;
+ signal line_cnts_q : line_cnts_t;
+ -- and a flag that tells whether the object is active or idle
+ type objs_active_t is array (minor_obj_range_t) of boolean;
+ signal objs_active_q : objs_active_t;
+
+ -- a shift register for each object
+ type shift_regs_t is array (minor_obj_range_t) of byte_t;
+ signal shift_regs_q : shift_regs_t;
+
+ -- counter delay registers
+ subtype del_cnt_t is unsigned(0 downto 0);
+ type del_cnts_t is array (minor_obj_range_t) of del_cnt_t;
+ signal del_cnts_q : del_cnts_t;
+
+ -- pixel delay registers
+ type del_pix_t is array (minor_obj_range_t) of std_logic;
+ signal del_pix_q : del_pix_t;
+
+ signal hbl_q : std_logic;
+ signal hbl_rising_q : boolean;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process minor_objects
+ --
+ -- Purpose:
+ -- Implements all minor objects.
+ --
+ minor_objects: process (clk_i, res_i)
+ variable objs_active_v : objs_active_t;
+ variable update_shift_v : objs_active_t;
+ variable del_cnt_rel_v : del_cnt_t;
+ begin
+ if res_i then
+ line_cnts_q <= (others => (others => '0'));
+ objs_active_q <= (others => false);
+ del_cnts_q <= (others => (others => '0'));
+ shift_regs_q <= (others => (others => '0'));
+ hbl_q <= '0';
+ hbl_rising_q <= false;
+
+ elsif rising_edge(clk_i) then
+ objs_active_v := objs_active_q;
+
+ -- check vertical CAM match
+ if vbl_i = '0' then
+ for object in minor_obj_range_t loop
+ -- is there a vertical CAM match?
+ if unsigned(minor_objs_i(object).cam_y) = vpos_i(7 downto 0) then
+ objs_active_v(object) := true;
+ end if;
+ end loop;
+ end if;
+
+ if clk_fall_en_i then
+ -- edge detection flag
+ hbl_q <= hbl_i;
+ hbl_rising_q <= hbl_i = '1' and hbl_q = '0';
+
+ -- commit "object active" flags
+ objs_active_q <= objs_active_v;
+
+ -- check horizontal CAM match
+ update_shift_v := (others => false);
+ for object in minor_obj_range_t loop
+ if objs_active_v(object) then
+ if unsigned(minor_objs_i(object).cam_x) = hpos_i(pos_t'high downto 1) then
+ -- parallel load of shift register when horizontal position matched
+ update_shift_v(object) := true;
+ end if;
+ end if;
+ end loop;
+
+ -- increment line counters upon rising hbl edge
+ if hbl_rising_q then
+ for object in minor_obj_range_t loop
+ if objs_active_q(object) then
+ -- increment on this line if
+ -- a) object is single size (D attribute = 0) and
+ -- current vertical line is the "second line"
+ -- b) object is double size (D attribute = 1) and
+ -- current vertical line is the "fourth line"
+ if (minor_objs_i(object).d = '0' and
+ vpos_i(0) = not minor_objs_i(object).cam_y(0)) or
+ (minor_objs_i(object).d = '1' and
+ vpos_i(1 downto 0) = unsigned(minor_objs_i(object).cam_y(1 downto 0)) - 1) then
+ line_cnts_q(object) <= line_cnts_q(object) + 1;
+ if line_cnts_q(object) = "111" then
+ -- stop counter on overflow
+ objs_active_q(object) <= false;
+ end if;
+ end if;
+ end if;
+ end loop;
+ end if;
+
+ -- delay counter
+ for object in minor_obj_range_t loop
+ del_cnt_rel_v := (0 => minor_objs_i(object).d);
+ if update_shift_v(object) then
+ -- preset upon CAM match
+ del_cnts_q(object) <= del_cnt_rel_v;
+ else
+ if del_cnts_q(object) = 0 then
+ del_cnts_q(object) <= del_cnt_rel_v;
+ else
+ del_cnts_q(object) <= del_cnts_q(object) - 1;
+ end if;
+ end if;
+ end loop;
+
+ -- shift register implementation
+ for object in minor_obj_range_t loop
+ if update_shift_v(object) then
+ -- parallel load upon CAM match
+ shift_regs_q(object) <= minor_patterns_i(object)(to_integer(line_cnts_q(object)));
+ elsif del_cnts_q(object) = 0 then
+ -- shift one bit position to the right
+ shift_regs_q(object)(byte_t'high-1 downto 0) <=
+ shift_regs_q(object)(byte_t'high downto 1);
+ shift_regs_q(object)(byte_t'high) <= '0';
+ end if;
+ end loop;
+
+ end if;
+ end if;
+ end process minor_objects;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process del_pix
+ --
+ -- Purpose:
+ -- Implements the delay for even and odd lines.
+ -- Depending on attribute bit D, the delay is either
+ -- D = 0 : 1 clk_i cycle = 140 ns
+ -- D = 1 : 2 clk_i cycles = 280 ns
+ --
+ del_pix: process (clk_i, res_i)
+ begin
+ if res_i then
+ del_pix_q <= (others => '0');
+
+ elsif rising_edge(clk_i) then
+ for object in minor_obj_range_t loop
+ if clk_fall_en_i or
+ (clk_rise_en_i and minor_objs_i(object).d = '0') then
+ del_pix_q(object) <= shift_regs_q(object)(0);
+ end if;
+ end loop;
+
+ end if;
+ end process del_pix;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process out_mux
+ --
+ -- Purpose:
+ -- Multiplexes the direct or delayed pixel information onto the
+ -- module outputs.
+ --
+ out_mux: process (shift_regs_q,
+ del_pix_q,
+ minor_objs_i,
+ line_cnts_q)
+ variable attributes_v : std_logic_vector(1 downto 0);
+ begin
+ for object in minor_obj_range_t loop
+ attributes_v := minor_objs_i(object).s &
+ minor_objs_i(object).x9;
+
+ case attributes_v is
+ when "01" =>
+ minor_pix_o(object) <= del_pix_q(object);
+ when "10" =>
+ if line_cnts_q(object)(0) = '0' then
+ minor_pix_o(object) <= del_pix_q(object);
+ else
+ minor_pix_o(object) <= shift_regs_q(object)(0);
+ end if;
+ when "11" =>
+ if line_cnts_q(object)(0) = '1' then
+ minor_pix_o(object) <= del_pix_q(object);
+ else
+ minor_pix_o(object) <= shift_regs_q(object)(0);
+ end if;
+ when others =>
+ minor_pix_o(object) <= shift_regs_q(object)(0);
+ end case;
+ end loop;
+ end process out_mux;
+ --
+ -----------------------------------------------------------------------------
+
+end rtl;
diff --git a/common/Video/i8244/i8244_minor_pack-p.vhd b/common/Video/i8244/i8244_minor_pack-p.vhd
new file mode 100644
index 00000000..ca8f9099
--- /dev/null
+++ b/common/Video/i8244/i8244_minor_pack-p.vhd
@@ -0,0 +1,46 @@
+-------------------------------------------------------------------------------
+--
+-- i8244 Video Display Controller
+--
+-- $Id: i8244_minor_pack-p.vhd,v 1.3 2007/02/05 22:08:59 arnim Exp $
+--
+-- Copyright (c) 2007, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.i8244_pack.byte_t;
+use work.i8244_pack.col_attr_t;
+
+package i8244_minor_pack is
+
+ -- constants for minor object attributes
+ constant minor_attr_x9_c : natural := 0;
+ constant minor_attr_s_c : natural := 1;
+ constant minor_attr_d_c : natural := 2;
+
+ -- number of minor objects
+ constant num_minor_objects_c : natural := 4;
+ subtype minor_obj_range_t is natural range 0 to num_minor_objects_c-1;
+
+ -- minor object and patterns
+ type minor_obj_t is
+ record
+ cam_y : byte_t;
+ cam_x : byte_t;
+ x9 : std_logic;
+ s : std_logic;
+ d : std_logic;
+ col : col_attr_t;
+ end record;
+
+ type minor_objs_t is array (minor_obj_range_t) of minor_obj_t;
+
+ type minor_pattern_t is array (0 to 7) of byte_t;
+ type minor_patterns_t is array (minor_obj_range_t) of minor_pattern_t;
+
+end;
diff --git a/common/Video/i8244/i8244_pack-p.vhd b/common/Video/i8244/i8244_pack-p.vhd
new file mode 100644
index 00000000..4c01793f
--- /dev/null
+++ b/common/Video/i8244/i8244_pack-p.vhd
@@ -0,0 +1,54 @@
+-------------------------------------------------------------------------------
+--
+-- i8244 Video Display Controller
+--
+-- $Id: i8244_pack-p.vhd,v 1.9 2007/02/05 22:08:59 arnim Exp $
+--
+-- Copyright (c) 2007, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+package i8244_pack is
+
+ subtype byte_t is std_logic_vector(7 downto 0);
+ type byte_array_t is array (natural range <>) of byte_t;
+
+ subtype pos_t is unsigned(8 downto 0);
+
+ function to_pos_f(int : in natural) return pos_t;
+ function to_stdlogic(a : in boolean) return std_logic;
+
+ constant is_ntsc_c : integer := 0;
+ constant is_pal_c : integer := 1;
+
+ subtype col_attr_t is std_logic_vector(2 downto 0);
+ type col_attrs_t is array (natural range <>) of col_attr_t;
+
+end i8244_pack;
+
+
+package body i8244_pack is
+
+ function to_pos_f(int : in natural) return pos_t is
+ variable result_v : pos_t;
+ begin
+ result_v := to_unsigned(int, pos_t'length);
+ return result_v;
+ end;
+
+ function to_stdlogic(a : in boolean) return std_logic is
+ begin
+ if a then
+ return '1';
+ else
+ return '0';
+ end if;
+ end;
+
+end i8244_pack;
diff --git a/common/Video/i8244/i8244_sound-c.vhd b/common/Video/i8244/i8244_sound-c.vhd
new file mode 100644
index 00000000..f2e6ef9e
--- /dev/null
+++ b/common/Video/i8244/i8244_sound-c.vhd
@@ -0,0 +1,14 @@
+-------------------------------------------------------------------------------
+--
+-- i8244 Video Display Controller
+--
+-- $Id: i8244_sound-c.vhd,v 1.2 2007/02/05 21:57:37 arnim Exp $
+--
+-------------------------------------------------------------------------------
+
+configuration i8244_sound_rtl_c0 of i8244_sound is
+
+ for rtl
+ end for;
+
+end i8244_sound_rtl_c0;
diff --git a/common/Video/i8244/i8244_sound.vhd b/common/Video/i8244/i8244_sound.vhd
new file mode 100644
index 00000000..92ab5e0e
--- /dev/null
+++ b/common/Video/i8244/i8244_sound.vhd
@@ -0,0 +1,210 @@
+-------------------------------------------------------------------------------
+--
+-- i8244 Video Display Controller
+--
+-- $Id: i8244_sound.vhd,v 1.6 2007/02/05 22:08:59 arnim Exp $
+--
+-- Sound Generator
+--
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2007, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.i8244_sound_pack.all;
+
+entity i8244_sound is
+
+ port (
+ clk_i : in std_logic;
+ clk_en_i : in boolean;
+ res_i : in boolean;
+ hbl_i : in std_logic;
+ cpu2snd_i : in cpu2snd_t;
+ snd_int_o : out boolean;
+ snd_o : out std_logic;
+ snd_vec_o : out std_logic_vector(3 downto 0)
+ );
+
+end i8244_sound;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+architecture rtl of i8244_sound is
+
+ signal snd_q : std_logic_vector(23 downto 0);
+ signal snd_s : std_logic;
+ signal hbl_q : std_logic;
+
+ constant pre_3k9_max_c : unsigned(3 downto 0) := to_unsigned( 3, 4);
+ constant pre_0k9_max_c : unsigned(3 downto 0) := to_unsigned(15, 4);
+ signal prescaler_q : unsigned(3 downto 0);
+
+ constant shift_cnt_max_c : unsigned(4 downto 0) := to_unsigned(23, 5);
+ signal shift_cnt_q : unsigned(4 downto 0);
+
+ signal noise_lfsr_q : std_logic_vector(15 downto 0);
+
+ signal int_q : boolean;
+
+ signal chop_cnt_q : unsigned(3 downto 0);
+ signal chop_q : std_logic;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process seq
+ --
+ -- Purpose:
+ -- Implements the sequential elements.
+ --
+ seq: process (clk_i, res_i)
+ variable shift_en_v : boolean;
+ begin
+ if res_i then
+ snd_q <= (others => '0');
+ hbl_q <= '0';
+ shift_cnt_q <= shift_cnt_max_c;
+ int_q <= false;
+ prescaler_q <= pre_3k9_max_c;
+ chop_cnt_q <= (others => '0');
+ chop_q <= '0';
+ -- set LSB of noise LFSR
+ noise_lfsr_q <= (others => '0');
+ noise_lfsr_q(0) <= '1';
+
+ elsif rising_edge(clk_i) then
+ if clk_en_i then
+ -- default: interrupt off
+ int_q <= false;
+
+ -- flag for edge detection
+ hbl_q <= hbl_i;
+
+ shift_en_v := false;
+ -- prescaler
+ if hbl_i = '1' and hbl_q = '0' then -- detect rising edge on hbl
+ if prescaler_q = 0 then
+ case cpu2snd_i.freq is
+ when SND_FREQ_HIGH =>
+ prescaler_q <= pre_3k9_max_c;
+ when SND_FREQ_LOW =>
+ prescaler_q <= pre_0k9_max_c;
+ end case;
+
+ -- and shift one bit
+ if cpu2snd_i.enable then
+ shift_en_v := true;
+ end if;
+ else
+ prescaler_q <= prescaler_q - 1;
+ end if;
+ end if;
+
+
+ -- operate shift register
+ if shift_en_v then
+ if shift_cnt_q = 0 then
+ -- start all over
+ shift_cnt_q <= shift_cnt_max_c;
+
+ -- generate interrupt
+ int_q <= true;
+ else
+ shift_cnt_q <= shift_cnt_q - 1;
+ snd_q(22 downto 0) <= snd_q(23 downto 1);
+ snd_q(23) <= snd_q(0);
+ end if;
+
+ -- and update noise LFSR register by shifting it up
+ noise_lfsr_q(noise_lfsr_q'length-1 downto 1) <=
+ noise_lfsr_q(noise_lfsr_q'length-2 downto 0);
+ -- insert tapped bits at vacant position 0
+ noise_lfsr_q(0) <= noise_lfsr_q(15) xor noise_lfsr_q(13) xor
+ noise_lfsr_q(0);
+ end if;
+
+ -- chopper
+ if chop_cnt_q = unsigned(cpu2snd_i.volume) then
+ chop_q <= '1';
+ end if;
+ if chop_cnt_q = 0 then
+ chop_cnt_q <= (others => '1');
+ chop_q <= '0';
+ else
+ chop_cnt_q <= chop_cnt_q - 1;
+ end if;
+
+ end if;
+
+ -- parallel load from CPU interface
+ case cpu2snd_i.reg_sel is
+ when SND_REG_0 =>
+ snd_q(23 downto 16) <= cpu2snd_i.din;
+ when SND_REG_1 =>
+ snd_q(15 downto 8) <= cpu2snd_i.din;
+ when SND_REG_2 =>
+ snd_q( 7 downto 0) <= cpu2snd_i.din;
+ when others =>
+ null;
+ end case;
+ end if;
+ end process seq;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -- overlay noise bit on shift register output
+ snd_s <= snd_q(0) xor noise_lfsr_q(15)
+ when cpu2snd_i.noise else
+ snd_q(0);
+
+
+ -----------------------------------------------------------------------------
+ -- Output mapping
+ -----------------------------------------------------------------------------
+ snd_int_o <= int_q;
+ snd_o <= snd_s and chop_q;
+ snd_vec_o <= cpu2snd_i.volume
+ when snd_s = '1' and cpu2snd_i.enable else
+ (others => '0');
+
+end rtl;
diff --git a/common/Video/i8244/i8244_sound_pack-p.vhd b/common/Video/i8244/i8244_sound_pack-p.vhd
new file mode 100644
index 00000000..8050a770
--- /dev/null
+++ b/common/Video/i8244/i8244_sound_pack-p.vhd
@@ -0,0 +1,33 @@
+-------------------------------------------------------------------------------
+--
+-- i8244 Video Display Controller
+--
+-- $Id: i8244_sound_pack-p.vhd,v 1.3 2007/02/05 22:08:59 arnim Exp $
+--
+-- Copyright (c) 2007, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.i8244_pack.byte_t;
+
+package i8244_sound_pack is
+
+ type sound_freq_t is (SND_FREQ_LOW, SND_FREQ_HIGH);
+ type sound_reg_sel_t is (SND_REG_NONE, SND_REG_0, SND_REG_1, SND_REG_2);
+
+ type cpu2snd_t is
+ record
+ enable : boolean;
+ freq : sound_freq_t;
+ noise : boolean;
+ volume : std_logic_vector(3 downto 0);
+ reg_sel : sound_reg_sel_t;
+ din : byte_t;
+ end record;
+
+end;
diff --git a/common/Video/i8244/i8244_sync_gen-c.vhd b/common/Video/i8244/i8244_sync_gen-c.vhd
new file mode 100644
index 00000000..58b87684
--- /dev/null
+++ b/common/Video/i8244/i8244_sync_gen-c.vhd
@@ -0,0 +1,14 @@
+-------------------------------------------------------------------------------
+--
+-- i8244 Video Display Controller
+--
+-- $Id: i8244_sync_gen-c.vhd,v 1.2 2007/02/05 21:57:37 arnim Exp $
+--
+-------------------------------------------------------------------------------
+
+configuration i8244_sync_gen_rtl_c0 of i8244_sync_gen is
+
+ for rtl
+ end for;
+
+end i8244_sync_gen_rtl_c0;
diff --git a/common/Video/i8244/i8244_sync_gen.vhd b/common/Video/i8244/i8244_sync_gen.vhd
new file mode 100644
index 00000000..598f8cf7
--- /dev/null
+++ b/common/Video/i8244/i8244_sync_gen.vhd
@@ -0,0 +1,270 @@
+-------------------------------------------------------------------------------
+--
+-- i8244 Video Display Controller
+--
+-- $Id: i8244_sync_gen.vhd,v 1.15 2007/02/05 22:08:59 arnim Exp $
+--
+-- Sync Generator
+--
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2007, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.i8244_pack.pos_t;
+
+entity i8244_sync_gen is
+
+ generic (
+ is_pal_g : integer := 1
+ );
+ port (
+ clk_i : in std_logic;
+ clk_en_i : in boolean;
+ clk_rise_en_o : out boolean;
+ clk_fall_en_o : out boolean;
+ res_i : in boolean;
+ ms_i : in std_logic;
+ vbl_i : in std_logic;
+ hbl_o : out std_logic;
+ hsync_o : out std_logic;
+ vsync_o : out std_logic;
+ bg_o : out std_logic;
+ vbl_o : out std_logic;
+ hpos_o : out pos_t;
+ vpos_o : out pos_t;
+ hor_int_o : out std_logic
+ );
+
+end i8244_sync_gen;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+use work.i8244_pack.all;
+
+architecture rtl of i8244_sync_gen is
+
+ type limits_t is array (natural range 0 to 1) of pos_t;
+
+ -- last horizontal blank defines horizontal interval:
+ -- (228 * 2) - 1 = 455
+ constant last_hpos_c : pos_t := to_pos_f(454);
+ constant last_hblank_c : pos_t := last_hpos_c - to_pos_f(0);
+ constant first_hblank_c : pos_t := last_hblank_c - to_pos_f(87);
+ constant first_hsync_c : pos_t := first_hblank_c + to_pos_f(10);
+ constant last_hsync_c : pos_t := first_hsync_c + to_pos_f(34-1);
+ constant first_bg_c : pos_t := first_hblank_c + to_pos_f(48);
+ constant last_bg_c : pos_t := first_bg_c + to_pos_f(18-1);
+ -- horizontal interrupt starts 20 us before hblank
+ constant first_hor_int_c : pos_t := first_hblank_c - to_pos_f(142);
+ -- and ends 5 us before end of hblank
+ constant last_hor_int_c : pos_t := last_hblank_c - to_pos_f(37);
+
+ constant last_vis_line_c : pos_t := to_pos_f(239);
+ constant last_frame_line_c : limits_t := (
+ is_ntsc_c => to_pos_f(261),
+ is_pal_c => to_pos_f(311));
+ constant first_vblank_c : pos_t := last_vis_line_c + to_pos_f(0);
+ constant last_vblank_c : limits_t := (
+ is_ntsc_c => to_pos_f(0),
+ is_pal_c => to_pos_f(0));
+ constant first_vsync_c : pos_t := first_vblank_c + to_pos_f(16);
+ constant last_vsync_c : pos_t := first_vsync_c + to_pos_f(5);
+
+ signal hpos_q : pos_t;
+ signal vpos_q : pos_t;
+
+ signal vbl_slave_q : std_logic;
+
+ signal hbl_q : std_logic;
+ signal hsync_q : std_logic;
+ signal vsync_q : std_logic;
+ signal bg_q : std_logic;
+ signal vbl_q : std_logic;
+ signal hor_int_q : std_logic;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process pos_count
+ --
+ -- Purpose:
+ -- Implements the hpos and vpos counters.
+ -- The vpos counter depends on the NTSC/PAL setting and can be
+ -- synchronized from an external vbl signal in slave mode.
+ --
+ -- Furthermore, the flags for generating hbl, hsync, bg and vbl
+ -- are managed here.
+ --
+ pos_count: process (clk_i, res_i)
+ variable last_frame_line_v : pos_t;
+ variable last_vblank_v : pos_t;
+ variable vbl_sync_v : boolean;
+ variable vinc_v : boolean;
+ begin
+ if res_i then
+ hpos_q <= to_pos_f(0);
+ vpos_q <= to_pos_f(0);
+ vbl_slave_q <= '0';
+ --
+ hbl_q <= '0';
+ hsync_q <= '0';
+ vsync_q <= '0';
+ bg_q <= '0';
+ vbl_q <= '0';
+ hor_int_q <= '0';
+
+ elsif rising_edge(clk_i) then
+ last_frame_line_v := last_frame_line_c(is_pal_g);
+ last_vblank_v := last_vblank_c(is_pal_g);
+
+ if clk_en_i then
+ -- sync to rising edge of external vbl in slave mode ------------------
+ vbl_slave_q <= vbl_i;
+ if ms_i = '0' and
+ vbl_slave_q = '0' and vbl_i = '1' then
+ vbl_sync_v := true;
+ else
+ vbl_sync_v := false;
+ end if;
+
+ -- horizontal position counter ----------------------------------------
+ vinc_v := false;
+ if vbl_sync_v then
+ -- sync to pixel 1 in new line
+ hpos_q <= to_pos_f(1);
+ else
+ if hpos_q = last_hpos_c then
+ hpos_q <= to_pos_f(0);
+ vinc_v := true;
+ else
+ hpos_q <= hpos_q + 1;
+ end if;
+ end if;
+
+ -- vertical position counter ------------------------------------------
+ if vbl_sync_v then
+ -- sync to first line of VBLANK
+ vpos_q <= first_vblank_c + to_pos_f(1);
+ elsif vinc_v then
+ if vpos_q = last_frame_line_v then
+ vpos_q <= to_pos_f(0);
+ else
+ vpos_q <= vpos_q + 1;
+ end if;
+ end if;
+
+ -- timing flags -------------------------------------------------------
+ if vbl_sync_v then
+ hbl_q <= '0';
+ hsync_q <= '0';
+ vsync_q <= '0';
+ bg_q <= '0';
+ vbl_q <= '1';
+ else
+ -- hbl
+ if hpos_q = first_hblank_c - 1 then
+ hbl_q <= '1';
+ elsif hpos_q = last_hblank_c then
+ hbl_q <= '0';
+ end if;
+
+ -- hsync
+ if hpos_q = first_hsync_c - 1 then
+ hsync_q <= '1';
+ elsif hpos_q = last_hsync_c then
+ hsync_q <= '0';
+ end if;
+
+ -- vsync
+ if vpos_q = first_vsync_c - 1 then
+ vsync_q <= '1';
+ elsif vpos_q = last_vsync_c then
+ vsync_q <= '0';
+ end if;
+
+ -- bg
+ if hpos_q = first_bg_c - 1 then
+ bg_q <= '1';
+ elsif hpos_q = last_bg_c then
+ bg_q <= '0';
+ end if;
+
+ -- vbl
+ if vinc_v then
+ if vpos_q = first_vblank_c then
+ vbl_q <= '1';
+ elsif vpos_q = last_vblank_v then
+ vbl_q <= '0';
+ end if;
+ end if;
+
+ -- horizontal interrupt
+ if hpos_q = first_hor_int_c - 1 then
+ hor_int_q <= '1';
+ elsif hpos_q = last_hsync_c then
+ hor_int_q <= '0';
+ end if;
+
+ end if;
+
+ end if;
+ end if;
+ end process pos_count;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Output mapping
+ -----------------------------------------------------------------------------
+ clk_rise_en_o <= clk_en_i and hpos_q(0) = '1';
+ clk_fall_en_o <= clk_en_i and hpos_q(0) = '0';
+ hbl_o <= hbl_q;
+ hsync_o <= hsync_q;
+ vsync_o <= vsync_q;
+ bg_o <= bg_q;
+ vbl_o <= vbl_q;
+ hpos_o <= hpos_q;
+ vpos_o <= vpos_q;
+ hor_int_o <= hor_int_q;
+
+end rtl;
diff --git a/common/Video/i8244/i8244_top_sync-c.vhd b/common/Video/i8244/i8244_top_sync-c.vhd
new file mode 100644
index 00000000..adb7a880
--- /dev/null
+++ b/common/Video/i8244/i8244_top_sync-c.vhd
@@ -0,0 +1,23 @@
+-------------------------------------------------------------------------------
+--
+-- i8244 Video Display Controller
+--
+-- $Id: i8244_top_sync-c.vhd,v 1.2 2007/02/05 21:57:37 arnim Exp $
+--
+-------------------------------------------------------------------------------
+
+configuration i8244_top_sync_struct_c0 of i8244_top_sync is
+
+ for struct
+
+ for core_b: i8244_core
+ use configuration work.i8244_core_struct_c0;
+ end for;
+
+ for charset_rom_b: i8244_charset_rom
+ use configuration work.i8244_charset_rom_rtl_c0;
+ end for;
+
+ end for;
+
+end i8244_top_sync_struct_c0;
diff --git a/common/Video/i8244/i8244_top_sync.vhd b/common/Video/i8244/i8244_top_sync.vhd
new file mode 100644
index 00000000..d9e119e2
--- /dev/null
+++ b/common/Video/i8244/i8244_top_sync.vhd
@@ -0,0 +1,151 @@
+-------------------------------------------------------------------------------
+--
+-- i8244 Video Display Controller
+--
+-- $Id: i8244_top_sync.vhd,v 1.5 2007/02/05 22:08:59 arnim Exp $
+--
+-- i8244 Synchronous Toplevel
+--
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2007, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity i8244_top_sync is
+
+ generic (
+ is_pal_g : integer := 1
+ );
+ port (
+ -- System Interface -------------------------------------------------------
+ clk_i : in std_logic;
+ clk_en_i : in std_logic;
+ res_n_i : in std_logic;
+ -- I8244 Pads Interface ---------------------------------------------------
+ intr_n_o : out std_logic;
+ stb_i : in std_logic;
+ bg_o : out std_logic;
+ hsync_o : out std_logic;
+ vsync_o : out std_logic;
+ ms_i : in std_logic;
+ hbl_o : out std_logic;
+ vbl_i : in std_logic;
+ vbl_o : out std_logic;
+ cx_i : in std_logic;
+ l_o : out std_logic;
+ cs_n_i : in std_logic;
+ wr_n_i : in std_logic;
+ rd_n_i : in std_logic;
+ din_i : in std_logic_vector(7 downto 0);
+ dout_o : out std_logic_vector(7 downto 0);
+ dout_en_o : out std_logic;
+ r_o : out std_logic;
+ g_o : out std_logic;
+ b_o : out std_logic;
+ ale_i : in std_logic;
+ snd_o : out std_logic;
+ snd_vec_o : out std_logic_vector(3 downto 0)
+ );
+
+end i8244_top_sync;
+
+
+use work.i8244_core_comp_pack.i8244_core;
+use work.i8244_core_comp_pack.i8244_charset_rom;
+
+architecture struct of i8244_top_sync is
+
+ signal rom_addr_s : std_logic_vector(8 downto 0);
+ signal rom_en_s : std_logic;
+ signal rom_data_s : std_logic_vector(7 downto 0);
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- I8244 Core
+ -----------------------------------------------------------------------------
+ core_b : i8244_core
+ generic map (
+ is_pal_g => is_pal_g
+ )
+ port map (
+ clk_i => clk_i,
+ clk_en_i => clk_en_i,
+ res_n_i => res_n_i,
+ rom_addr_o => rom_addr_s,
+ rom_en_o => rom_en_s,
+ rom_data_i => rom_data_s,
+ intr_n_o => intr_n_o,
+ stb_i => stb_i,
+ bg_o => bg_o,
+ hsync_o => hsync_o,
+ vsync_o => vsync_o,
+ ms_i => ms_i,
+ hbl_o => hbl_o,
+ vbl_i => vbl_i,
+ vbl_o => vbl_o,
+ cx_i => cx_i,
+ l_o => l_o,
+ cs_n_i => cs_n_i,
+ wr_n_i => wr_n_i,
+ rd_n_i => rd_n_i,
+ din_i => din_i,
+ dout_o => dout_o,
+ dout_en_o => dout_en_o,
+ r_o => r_o,
+ g_o => g_o,
+ b_o => b_o,
+ ale_i => ale_i,
+ snd_o => snd_o,
+ snd_vec_o => snd_vec_o
+ );
+
+
+ -----------------------------------------------------------------------------
+ -- Character set ROM
+ -----------------------------------------------------------------------------
+ charset_rom_b : i8244_charset_rom
+ port map (
+ clk_i => clk_i,
+ rom_addr_i => rom_addr_s,
+ rom_en_i => rom_en_s,
+ rom_data_o => rom_data_s
+ );
+
+end struct;
diff --git a/common/Video/mc6847.vhd b/common/Video/mc6847.vhd
new file mode 100644
index 00000000..55ca7e31
--- /dev/null
+++ b/common/Video/mc6847.vhd
@@ -0,0 +1,673 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.numeric_std.all;
+
+entity mc6847 is
+ generic
+ (
+ T1_VARIANT : boolean := false;
+ CHAR_ROM_FILE : string := "";
+
+ CVBS_NOT_VGA : boolean := true
+ );
+ port
+ (
+ clk : in std_logic;
+ clk_ena : in std_logic;
+ reset : in std_logic;
+
+ -- address output lines
+ da0 : out std_logic;
+
+ -- data inputs
+ dd : in std_logic_vector(7 downto 0);
+
+ -- synchronising outputs
+ hs_n : out std_logic;
+ fs_n : out std_logic;
+
+ -- mode control lines
+ an_g : in std_logic;
+ an_s : in std_logic;
+ intn_ext : in std_logic;
+ gm : in std_logic_vector(2 downto 0);
+ css : in std_logic;
+ inv : in std_logic;
+
+ -- VGA output
+ red : out std_logic_vector(7 downto 0);
+ green : out std_logic_vector(7 downto 0);
+ blue : out std_logic_vector(7 downto 0);
+ hsync : out std_logic;
+ vsync : out std_logic;
+ hblank : out std_logic;
+ vblank : out std_logic;
+
+ -- special inputs
+ artifact_en : in std_logic;
+ artifact_set : in std_logic;
+ artifact_phase : in std_logic;
+
+ -- CVBS output
+ cvbs : out std_logic_vector(7 downto 0)
+ );
+end mc6847;
+
+architecture SYN of mc6847 is
+
+ constant BUILD_DEBUG : boolean := false;
+ constant DEBUG_AN_G : std_logic := '1';
+ constant DEBUG_AN_S : std_logic := '1';
+ constant DEBUG_INTN_EXT : std_logic := '1';
+ constant DEBUG_GM : std_logic_vector(2 downto 0) := "111";
+ constant DEBUG_CSS : std_logic := '1';
+ constant DEBUG_INV : std_logic := '0';
+
+ -- H_TOTAL_PER_LINE must be divisible by 16
+ -- so that sys_count is the same on each line when
+ -- the video comes out of hblank
+ -- so the phase relationship between data from the 6847 and character timing is maintained
+
+ -- 14.31818 MHz : 256 X 384
+ constant H_FRONT_PORCH : integer := 11-1+1;
+ constant H_HORIZ_SYNC : integer := H_FRONT_PORCH + 35+2;
+ constant H_BACK_PORCH : integer := H_HORIZ_SYNC + 34+1;
+ constant H_LEFT_BORDER : integer := H_BACK_PORCH + 61+1+3; -- adjust for hblank de-assert @sys_count=6
+ constant H_VIDEO : integer := H_LEFT_BORDER + 256;
+ constant H_RIGHT_BORDER : integer := H_VIDEO + 61+1-3; -- "
+ constant H_TOTAL_PER_LINE : integer := H_RIGHT_BORDER;
+
+ -- (not used)
+ --constant V_FRONT_PORCH : integer := 2-1;
+ --constant V_VERTICAL_SYNC : integer := V_FRONT_PORCH + 2;
+ --constant V_BACK_PORCH : integer := V_VERTICAL_SYNC + 25;
+ --constant V_TOP_BORDER : integer := V_BACK_PORCH + 8 + 48;
+ --constant V_VIDEO : integer := V_TOP_BORDER + 384;
+ --constant V_BOTTOM_BORDER : integer := V_VIDEO + 8 + 48;
+ --constant V_TOTAL_PER_FIELD : integer := V_BOTTOM_BORDER;
+
+ constant V2_FRONT_PORCH : integer := 2;
+ constant V2_VERTICAL_SYNC : integer := V2_FRONT_PORCH + 2;
+ constant V2_BACK_PORCH : integer := V2_VERTICAL_SYNC + 12;
+ constant V2_TOP_BORDER : integer := V2_BACK_PORCH + 27; -- + 25; -- +25 for PAL
+ constant V2_VIDEO : integer := V2_TOP_BORDER + 192;
+ constant V2_BOTTOM_BORDER : integer := V2_VIDEO + 27; -- + 25; -- +25 for PAL
+ constant V2_TOTAL_PER_FIELD : integer := V2_BOTTOM_BORDER;
+
+ -- internal version of control ports
+
+ signal an_g_s : std_logic;
+ signal an_s_s : std_logic;
+ signal intn_ext_s : std_logic;
+ signal gm_s : std_logic_vector(2 downto 0);
+ signal css_s : std_logic;
+ signal inv_s : std_logic;
+
+ -- VGA signals
+
+ signal vga_clk_ena : std_logic;
+ signal vga_hsync : std_logic;
+ signal vga_vsync : std_logic;
+ signal vga_hblank : std_logic;
+ signal vga_vblank : std_logic;
+ signal vga_linebuf_addr : std_logic_vector(8 downto 0);
+ signal vga_data : std_logic_vector(7 downto 0);
+ signal vga_hborder : std_logic;
+ signal vga_vborder : std_logic;
+
+ -- CVBS signals
+
+ signal cvbs_clk_ena : std_logic; -- PAL/NTSC*2
+ signal cvbs_hsync : std_logic;
+ signal cvbs_vsync : std_logic;
+ signal cvbs_hblank : std_logic;
+ signal cvbs_vblank : std_logic;
+ signal cvbs_hborder : std_logic;
+ signal cvbs_vborder : std_logic;
+ signal cvbs_linebuf_we : std_logic;
+ signal cvbs_linebuf_addr : std_logic_vector(8 downto 0);
+
+ signal active_h_start : std_logic := '0';
+ signal an_s_r : std_logic;
+ signal inv_r : std_logic;
+ signal dd_r : std_logic_vector(7 downto 0);
+ signal pixel_data : std_logic_vector(7 downto 0);
+ signal cvbs_data : std_logic_vector(7 downto 0); -- CVBS data out
+
+ alias hs_int : std_logic is cvbs_hblank;
+ alias fs_int : std_logic is cvbs_vblank;
+ signal da0_int : std_logic_vector(4 downto 0);
+
+ -- character rom signals
+ signal char_a : std_logic_vector(10 downto 0);
+ signal char_d_o : std_logic_vector(7 downto 0);
+ signal cvbs_linebuf_we_r : std_logic;
+ signal cvbs_linebuf_addr_r : std_logic_vector(8 downto 0);
+ signal cvbs_linebuf_we_rr : std_logic;
+ signal cvbs_linebuf_addr_rr : std_logic_vector(8 downto 0);
+
+ -- used by both CVBS and VGA
+ shared variable v_count : std_logic_vector(8 downto 0);
+
+ shared variable row_v : std_logic_vector(3 downto 0);
+
+ procedure map_palette ( vga_data : in std_logic_vector(7 downto 0);
+ r : out std_logic_vector(7 downto 0);
+ g : out std_logic_vector(7 downto 0);
+ b : out std_logic_vector(7 downto 0)) is
+
+ type pal_entry_t is array (0 to 2) of std_logic_vector(1 downto 0);
+ type pal_a is array (0 to 7) of pal_entry_t;
+ constant pal : pal_a :=
+ (
+ 0 => (0=>"00", 1=>"11", 2=>"00"), -- green
+ 1 => (0=>"11", 1=>"11", 2=>"00"), -- yellow
+ 2 => (0=>"00", 1=>"00", 2=>"11"), -- blue
+ 3 => (0=>"11", 1=>"00", 2=>"00"), -- red
+ 4 => (0=>"11", 1=>"11", 2=>"11"), -- white
+ 5 => (0=>"00", 1=>"11", 2=>"11"), -- cyan
+ 6 => (0=>"11", 1=>"00", 2=>"11"), -- magenta
+ 7 => (0=>"11", 1=>"10", 2=>"00") -- orange
+ --others => (others => (others => '0'))
+ );
+ alias css_v : std_logic is vga_data(6);
+ alias an_g_v : std_logic is vga_data(5);
+ alias an_s_v : std_logic is vga_data(4);
+ alias luma : std_logic is vga_data(3);
+ alias chroma : std_logic_vector(2 downto 0) is vga_data(2 downto 0);
+ begin
+ if luma = '1' then
+ r := pal(to_integer(unsigned(chroma)))(0) & "000000";
+ g := pal(to_integer(unsigned(chroma)))(1) & "000000";
+ b := pal(to_integer(unsigned(chroma)))(2) & "000000";
+ else
+ -- not quite black in alpha mode
+ if an_g_v = '0' and an_s_v = '0' then
+ -- dark green/orange
+ r := '0' & css_v & "000000";
+ g := "01000000";
+ else
+ r := (others => '0');
+ g := (others => '0');
+ end if;
+ b := (others => '0');
+ end if;
+ end procedure;
+
+begin
+
+ -- assign control inputs for debug/release build
+ an_g_s <= DEBUG_AN_G when BUILD_DEBUG else an_g;
+ an_s_s <= DEBUG_AN_S when BUILD_DEBUG else an_s;
+ intn_ext_s <= DEBUG_INTN_EXT when BUILD_DEBUG else intn_ext;
+ gm_s <= DEBUG_GM when BUILD_DEBUG else gm;
+ css_s <= DEBUG_CSS when BUILD_DEBUG else css;
+ inv_s <= DEBUG_INV when BUILD_DEBUG else inv;
+
+ -- generate the clocks
+ PROC_CLOCKS : process (clk, reset)
+ variable toggle : std_logic := '0';
+ begin
+ if reset = '1' then
+ toggle := '0';
+ cvbs_clk_ena <= '0';
+ elsif rising_edge(clk) then
+ cvbs_clk_ena <= '0'; -- default
+ if clk_ena = '1' then
+ cvbs_clk_ena <= toggle;
+ toggle := not toggle;
+ end if;
+ vga_clk_ena <= clk_ena;
+ end if;
+ end process PROC_CLOCKS;
+
+ -- generate horizontal timing for VGA
+ -- generate line buffer address for reading VGA data
+ PROC_VGA : process (clk, reset)
+ variable h_count : integer range 0 to H_TOTAL_PER_LINE;
+ variable active_h_count : std_logic_vector(7 downto 0);
+ variable vga_vblank_r : std_logic;
+ begin
+ if reset = '1' then
+ h_count := 0;
+ vga_hsync <= '1';
+ vga_vsync <= '1';
+ vga_hblank <= '0';
+
+ elsif rising_edge (clk) and vga_clk_ena = '1' then
+
+ -- start hsync when cvbs comes out of vblank
+ if vga_vblank_r = '1' and vga_vblank = '0' then
+ h_count := 0;
+ else
+ if h_count = H_TOTAL_PER_LINE then
+ h_count := 0;
+ vga_hborder <= '0';
+ else
+ h_count := h_count + 1;
+ end if;
+
+ if h_count = H_FRONT_PORCH then
+ vga_hsync <= '0';
+ elsif h_count = H_HORIZ_SYNC then
+ vga_hsync <= '1';
+ elsif h_count = H_BACK_PORCH then
+ vga_hborder <= '1';
+ elsif h_count = H_LEFT_BORDER then
+ vga_hblank <= '0';
+ active_h_count := (others => '0');
+ elsif h_count = H_VIDEO then
+ vga_hblank <= '1';
+ elsif h_count = H_RIGHT_BORDER then
+ vga_hborder <= '0';
+ else
+ active_h_count := std_logic_vector(unsigned(active_h_count) + 1);
+ end if;
+
+ end if;
+
+ -- vertical syncs, blanks are the same
+ vga_vsync <= cvbs_vsync;
+
+ -- generate linebuffer address
+ -- - alternate every 2nd line
+ vga_linebuf_addr <= (not v_count(0)) & active_h_count;
+
+ vga_vblank_r := vga_vblank;
+
+ end if;
+ end process;
+
+ -- generate horizontal timing for CVBS
+ -- generate line buffer address for writing CVBS data
+ PROC_CVBS : process (clk, reset)
+ variable h_count : integer range 0 to H_TOTAL_PER_LINE;
+ variable active_h_count : std_logic_vector(7 downto 0);
+ variable cvbs_hblank_r : std_logic := '0';
+ --variable row_v : std_logic_vector(3 downto 0);
+ -- for debug only
+ variable active_v_count : std_logic_vector(v_count'range);
+ begin
+ if reset = '1' then
+
+ h_count := H_TOTAL_PER_LINE;
+ v_count := std_logic_vector(to_unsigned(V2_TOTAL_PER_FIELD, v_count'length));
+ active_h_count := (others => '0');
+ active_h_start <= '0';
+ cvbs_hsync <= '1';
+ cvbs_vsync <= '1';
+ cvbs_hblank <= '0';
+ cvbs_vblank <= '1';
+ vga_vblank <= '1';
+ da0_int <= (others => '0');
+ cvbs_hblank_r := '0';
+ row_v := (others => '0');
+
+ elsif rising_edge (clk) and cvbs_clk_ena = '1' then
+
+ active_h_start <= '0'; -- default
+
+ if h_count = H_TOTAL_PER_LINE then
+ h_count := 0;
+ if v_count = V2_TOTAL_PER_FIELD then
+ v_count := (others => '0');
+ else
+ v_count := v_count + 1;
+ end if;
+
+ -- VGA vblank is 1 line behind CVBS
+ -- - because we need to fill the line buffer
+ vga_vblank <= cvbs_vblank;
+
+ if v_count = V2_FRONT_PORCH then
+ cvbs_vsync <= '0';
+ elsif v_count = V2_VERTICAL_SYNC then
+ cvbs_vsync <= '1';
+ elsif v_count = V2_BACK_PORCH then
+ cvbs_vborder <= '1';
+ elsif v_count = V2_TOP_BORDER then
+ cvbs_vblank <= '0';
+ row_v := (others => '0');
+ active_v_count := (others => '0'); -- debug only
+ elsif v_count = V2_VIDEO then
+ cvbs_vblank <= '1';
+ elsif v_count = V2_BOTTOM_BORDER then
+ cvbs_vborder <= '0';
+ else
+ if row_v = 11 then
+ row_v := (others => '0');
+ active_v_count := active_v_count + 5; -- debug only
+ else
+ row_v := row_v + 1;
+ active_v_count := active_v_count + 1; -- debug only
+ end if;
+ end if;
+
+ else
+ h_count := h_count + 1;
+
+ if h_count = H_FRONT_PORCH then
+ cvbs_hsync <= '0';
+ elsif h_count = H_HORIZ_SYNC then
+ cvbs_hsync <= '1';
+ elsif h_count = H_BACK_PORCH then
+ elsif h_count = H_LEFT_BORDER then
+ cvbs_hblank <= '0';
+ active_h_count := (others => '0');
+ active_h_start <= '1';
+ elsif h_count = H_VIDEO then
+ cvbs_hblank <= '1';
+ -- only needed for debug???
+ active_h_count := active_h_count + 1;
+ elsif h_count = H_RIGHT_BORDER then
+ null;
+ else
+ active_h_count := active_h_count + 1;
+ end if;
+ end if;
+
+ -- generate character rom address
+ char_a <= '0' & dd(5 downto 0) & row_v(3 downto 0);
+
+ -- DA0 high during FS
+ if cvbs_vblank = '1' then
+ da0_int <= (others => '1');
+ elsif cvbs_hblank = '1' then
+ da0_int <= (others => '0');
+ elsif cvbs_hblank_r = '1' and cvbs_hblank = '0' then
+ da0_int <= "01000";
+ else
+ da0_int <= da0_int + 1;
+ end if;
+
+ -- generate linebuffer address
+ -- - alternate every line
+ cvbs_linebuf_addr <= v_count(0) & active_h_count;
+
+ -- pipeline writes to linebuf because data is delayed 1 clock as well!
+ cvbs_linebuf_we_r <= cvbs_linebuf_we;
+ cvbs_linebuf_addr_r <= cvbs_linebuf_addr;
+ cvbs_linebuf_we_rr <= cvbs_linebuf_we_r;
+ cvbs_linebuf_addr_rr <= cvbs_linebuf_addr_r;
+
+ cvbs_hblank_r := cvbs_hblank;
+
+ end if; -- cvbs_clk_ena
+ end process;
+
+ -- handle latching & shifting of character, graphics data
+ process (clk, reset)
+ variable count : std_logic_vector(3 downto 0) := (others => '0');
+ begin
+ if reset = '1' then
+ count := (others => '0');
+ elsif rising_edge(clk) and cvbs_clk_ena = '1' then
+ if active_h_start = '1' then
+ count := (others => '0');
+ end if;
+ if an_g_s = '0' then
+ -- alpha-semi modes
+ if count(2 downto 0) = 0 then
+ -- handle alpha-semi latching
+ an_s_r <= an_s_s;
+ inv_r <= inv_s;
+ if an_s_s = '0' then
+ dd_r <= char_d_o; -- alpha mode
+ else
+ -- store luma,chroma(2..0),luma,chroma(2..0)
+ if intn_ext_s = '0' then -- semi-4
+ if row_v < 6 then
+ dd_r <= dd(3) & dd(6) & dd(5) & dd(4) &
+ dd(2) & dd(6) & dd(5) & dd(4);
+ else
+ dd_r <= dd(1) & dd(6) & dd(5) & dd(4) &
+ dd(0) & dd(6) & dd(5) & dd(4);
+ end if;
+ else -- semi-6
+ if row_v < 4 then
+ dd_r <= dd(5) & css_s & dd(7) & dd(6) &
+ dd(4) & css_s & dd(7) & dd(6);
+ elsif row_v < 8 then
+ dd_r <= dd(3) & css_s & dd(7) & dd(6) &
+ dd(2) & css_s & dd(7) & dd(6);
+ else
+ dd_r <= dd(1) & css_s & dd(7) & dd(6) &
+ dd(0) & css_s & dd(7) & dd(6);
+ end if;
+ end if;
+ end if;
+ else
+ -- handle alpha-semi shifting
+ if an_s_r = '0' then
+ dd_r <= dd_r(dd_r'left-1 downto 0) & '0'; -- alpha mode
+ else
+ if count(1 downto 0) = 0 then
+ dd_r <= dd_r(dd_r'left-4 downto 0) & "0000"; -- semi mode
+ end if;
+ end if;
+ end if;
+ else
+ -- graphics modes
+ --if IN_SIMULATION then
+ an_s_r <= '0';
+ --end if;
+ case gm_s is
+ when "000" | "001" | "011" | "101" => -- CG1/RG1/RG2/RG3
+ if count(3 downto 0) = 0 then
+ -- handle graphics latching
+ dd_r <= dd;
+ else
+ -- handle graphics shifting
+ if gm_s = "000" then
+ if count(1 downto 0) = 0 then
+ dd_r <= dd_r(dd_r'left-2 downto 0) & "00"; -- CG1
+ end if;
+ else
+ if count(0) = '0' then
+ dd_r <= dd_r(dd_r'left-1 downto 0) & '0'; -- RG1/RG2/RG3
+ end if;
+ end if;
+ end if;
+ when others => -- CG2/CG3/CG6/RG6
+ if count(2 downto 0) = 0 then
+ -- handle graphics latching
+ dd_r <= dd;
+ else
+ -- handle graphics shifting
+ if gm_s = "111" then
+ dd_r <= dd_r(dd_r'left-1 downto 0) & '0'; -- RG6
+ else
+ if count(0) = '0' then
+ dd_r <= dd_r(dd_r'left-2 downto 0) & "00"; -- CG2/CG3/CG6
+ end if;
+ end if;
+ end if;
+ end case;
+ end if;
+ count := count + 1;
+ end if;
+ end process;
+
+ -- generate pixel data
+ process (clk, reset)
+ variable luma : std_logic;
+ variable chroma : std_logic_vector(2 downto 0);
+ begin
+ if reset = '1' then
+ elsif rising_edge(clk) and cvbs_clk_ena = '1' then
+ -- alpha/graphics mode
+ if an_g_s = '0' then
+ -- alphanumeric & semi-graphics mode
+ luma := dd_r(dd_r'left);
+ if an_s_r = '0' then
+ -- alphanumeric
+ if intn_ext_s = '0' then
+ -- internal rom
+ chroma := (others => css_s);
+ if inv_r = '1' then
+ luma := not luma;
+ end if; -- normal/inverse
+ else
+ -- external ROM?!?
+ end if; -- internal/external
+ else
+ chroma := dd_r(dd_r'left-1 downto dd_r'left-3);
+ end if; -- alphanumeric/semi-graphics
+ else
+ -- graphics mode
+ case gm_s is
+ when "000" => -- CG1 64x64x4
+ luma := '1';
+ chroma := css_s & dd_r(dd_r'left downto dd_r'left-1);
+ when "001" | "011" | "101" => -- RG1/2/3 128x64/96/192x2
+ luma := dd_r(dd_r'left);
+ chroma := css_s & "00"; -- green/buff
+ when "010" | "100" | "110" => -- CG2/3/6 128x64/96/192x4
+ luma := '1';
+ chroma := css_s & dd_r(dd_r'left downto dd_r'left-1);
+ when others => -- RG6 256x192x2
+ luma := dd_r(dd_r'left);
+ chroma := css_s & "00"; -- green/buff
+ end case;
+ end if; -- alpha/graphics mode
+
+ -- pack source data into line buffer
+ -- - palette lookup on output
+ pixel_data <= '0' & css_s & an_g_s & an_s_r & luma & chroma;
+
+ end if;
+ end process;
+
+ -- only write to the linebuffer during active display
+ cvbs_linebuf_we <= not (cvbs_vblank or cvbs_hblank);
+
+ cvbs <= '0' & cvbs_vsync & "000000" when cvbs_vblank = '1' else
+ '0' & cvbs_hsync & "000000" when cvbs_hblank = '1' else
+ cvbs_data;
+
+ -- assign outputs
+
+ hs_n <= not hs_int;
+ fs_n <= not fs_int;
+ da0 <= da0_int(4) when (gm_s = "001" or gm_s = "011" or gm_s = "101") else
+ da0_int(3);
+
+ -- map the palette to the pixel data
+ -- - we do that at the output so we can use a
+ -- higher colour-resolution palette
+ -- without using memory in the line buffer
+ PROC_OUTPUT : process (clk)
+ variable r : std_logic_vector(red'range);
+ variable g : std_logic_vector(green'range);
+ variable b : std_logic_vector(blue'range);
+ -- for artifacting testing only
+ variable p_in : std_logic_vector(vga_data'range);
+ variable p_out: std_logic_vector(vga_data'range);
+ variable count : std_logic := '0';
+ begin
+ if reset = '1' then
+ count := '0';
+ elsif rising_edge(clk) then
+ if CVBS_NOT_VGA then
+ if cvbs_clk_ena = '1' then
+ if cvbs_hblank = '0' and cvbs_vblank = '0' then
+ map_palette (vga_data, r, g, b);
+ else
+ r := (others => '0');
+ g := (others => '0');
+ b := (others => '0');
+ end if;
+ end if;
+ else
+ if vga_clk_ena = '1' then
+ if vga_hblank = '1' then
+ count := '0';
+ p_in := (others => '0');
+ end if;
+ if vga_hblank = '0' and vga_vblank = '0' then
+ -- artifacting test only --
+ if artifact_en = '1' and an_g_s = '1' and gm_s = "111" then
+ if count /= '0' then
+ p_out(p_out'left downto 4) := vga_data(p_out'left downto 4);
+ if p_in(3) = '0' and vga_data(3) = '0' then
+ p_out(3 downto 0) := "0000";
+ elsif p_in(3) = '1' and vga_data(3) = '1' then
+ p_out(3 downto 0) := "1100";
+ elsif p_in(3) = '0' and vga_data(3) = '1' then
+ p_out(3 downto 0) := "1011"; -- red
+ --p_out(3 downto 0) := "1101"; -- cyan
+ else
+ p_out(3 downto 0) := "1010"; -- blue
+ --p_out(3 downto 0) := "1111"; -- orange
+ end if;
+ end if;
+ map_palette (p_out, r, g, b);
+ p_in := vga_data;
+ else
+ map_palette (vga_data, r, g, b);
+ end if;
+ count := not count;
+ elsif an_g_s = '1' and vga_hborder = '1' and cvbs_vborder = '1' then
+ -- graphics mode, either green or buff (white)
+ map_palette ("00001" & css_s & "00", r, g, b);
+ else
+ r := (others => '0');
+ g := (others => '0');
+ b := (others => '0');
+ end if;
+ end if;
+ end if; -- CVBS_NOT_VGA
+ red <= r; green <= g; blue <= b;
+ end if; -- rising_edge(clk)
+
+ if CVBS_NOT_VGA then
+ hsync <= cvbs_hsync;
+ vsync <= cvbs_vsync;
+ hblank <= cvbs_hblank;
+ vblank <= cvbs_vblank;
+ else
+ hsync <= vga_hsync;
+ vsync <= vga_vsync;
+ hblank <= not vga_hborder; --vga_hblank;
+ vblank <= not cvbs_vborder; --vga_vblank;
+ end if;
+ end process PROC_OUTPUT;
+
+ -- fixme (clocking)!!!
+
+ linebuf : entity work.dpram_1r1w
+ generic map
+ (
+ numwords_a => 512,
+ widthad_a => 9
+ )
+ port map
+ (
+ wrclock => cvbs_clk_ena,
+ wren => cvbs_linebuf_we_rr,
+ wraddress => cvbs_linebuf_addr_rr,
+ data => pixel_data,
+
+ rdclock => clk,
+ rdaddress => vga_linebuf_addr,
+ q => vga_data
+ );
+
+ -- Character ROM
+ -- - technically the rom size is 1KB or 1.5KB (T1)
+ charrom_inst : entity work.sprom
+ generic map
+ (
+ init_file => CHAR_ROM_FILE,
+ --numwords_a => 2048,
+ widthad_a => 11
+ )
+ port map
+ (
+ clock => clk,
+ address => char_a,
+ q => char_d_o
+ );
+
+end SYN;
diff --git a/common/Video/mc6847_vga.v b/common/Video/mc6847_vga.v
new file mode 100644
index 00000000..9b638ead
--- /dev/null
+++ b/common/Video/mc6847_vga.v
@@ -0,0 +1,199 @@
+// LASER310 VZ200
+// mc6847
+
+module MC6847_VGA(
+PIX_CLK,
+RESET_N,
+
+RD,
+DD,
+DA,
+
+AG,
+AS,
+EXT,
+INV,
+GM,
+CSS,
+
+// vga
+blank,
+VGA_OUT_HSYNC,
+VGA_OUT_VSYNC,
+VGA_OUT_RED,
+VGA_OUT_GREEN,
+VGA_OUT_BLUE
+);
+
+input PIX_CLK;
+input RESET_N;
+
+output wire RD;
+output wire [12:0] DA; // 8KB
+input [7:0] DD;
+input AG;
+input AS;
+input EXT;
+input INV;
+input CSS;
+input [2:0] GM;
+output wire blank;
+output wire VGA_OUT_HSYNC;
+output wire VGA_OUT_VSYNC;
+output wire [7:0] VGA_OUT_RED;
+output wire [7:0] VGA_OUT_GREEN;
+output wire [7:0] VGA_OUT_BLUE;
+
+
+reg LATCHED_AG;
+reg LATCHED_AS;
+reg LATCHED_EXT;
+reg LATCHED_INV;
+reg [2:0] LATCHED_GM;
+reg LATCHED_CSS;
+
+wire pixel_clock; // generated from SYSTEM CLOCK
+wire reset; // reset asserted when DCMs are NOT LOCKED
+
+wire [7:0] vga_red; // red video data
+wire [7:0] vga_green; // green video data
+wire [7:0] vga_blue; // blue video data
+
+// internal video timing signals
+wire h_synch; // horizontal synch for VGA connector
+wire v_synch; // vertical synch for VGA connector
+//wire blank; // composite blanking
+wire [10:0] pixel_count; // bit mapped pixel position within the line
+wire [9:0] line_count; // bit mapped line number in a frame lines within the frame
+
+wire show_border;
+
+// text
+wire [3:0] subchar_pixel; // pixel position within the character
+wire [4:0] subchar_line; // identifies the line number within a character block
+wire [6:0] char_column; // character number on the current line
+wire [6:0] char_line; // line number on the screen
+
+// graph
+wire [8:0] graph_pixel; // pixel number on the current line
+wire [9:0] graph_line_2x; // line number on the screen
+wire [9:0] graph_line_3x; // line number on the screen
+
+/*
+wire [11:0] ROM_ADDRESS;
+wire [7:0] ROM_DATA;
+*/
+
+assign reset = ~RESET_N;
+assign pixel_clock = PIX_CLK;
+
+//assign vga_red = 8'hff;
+//assign vga_green = 8'h7f;
+//assign vga_blue = 8'h7f;
+
+// Character generator
+/*
+char_rom_4k_altera char_rom(
+ .address(ROM_ADDRESS),
+ .clock(pixel_clock),
+ .q(ROM_DATA)
+);
+*/
+
+// 为了防止闪屏,再垂直回扫信号产生时,锁存模式信号。
+
+always @ (posedge v_synch or negedge RESET_N)
+begin
+ if(!RESET_N)
+ begin
+ LATCHED_AG <= 1'b0;
+ LATCHED_AS <= 1'b0;
+ LATCHED_EXT <= 1'b0;
+ LATCHED_INV <= 1'b0;
+ LATCHED_GM <= 3'b0;
+ LATCHED_CSS <= 1'b0;
+ end
+ else
+ begin
+ LATCHED_AG <= AG;
+ LATCHED_AS <= AS;
+ LATCHED_EXT <= EXT;
+ LATCHED_INV <= INV;
+ LATCHED_GM <= GM;
+ LATCHED_CSS <= CSS;
+ end
+end
+
+// instantiate the character generator
+PIXEL_DISPLAY PIXEL_DISPLAY(
+ .pixel_clock(pixel_clock),
+ .reset(reset),
+ .show_border(show_border),
+ // mode
+ .ag(LATCHED_AG),
+ .gm(LATCHED_GM),
+ .css(LATCHED_CSS),
+ // text
+ .char_column(char_column),
+ .char_line(char_line),
+ .subchar_line(subchar_line),
+ .subchar_pixel(subchar_pixel),
+ // graph
+ .graph_pixel(graph_pixel),
+ .graph_line_2x(graph_line_2x),
+ .graph_line_3x(graph_line_3x),
+ // vram
+ .vram_rd_enable(RD),
+ .vram_addr(DA),
+ .vram_data(DD),
+ // vga
+ .vga_red(vga_red),
+ .vga_green(vga_green),
+ .vga_blue(vga_blue)
+);
+
+// instantiate the video timing generator
+SVGA_TIMING_GENERATION SVGA_TIMING_GENERATION
+(
+ pixel_clock,
+ reset,
+ h_synch,
+ v_synch,
+ blank,
+ pixel_count,
+ line_count,
+
+ show_border,
+
+ // text
+ subchar_pixel,
+ subchar_line,
+ char_column,
+ char_line,
+
+ // graph
+ graph_pixel,
+ graph_line_2x,
+ graph_line_3x
+);
+
+// instantiate the video output mux
+VIDEO_OUT VIDEO_OUT
+(
+ pixel_clock,
+ reset,
+ vga_red,
+ vga_green,
+ vga_blue,
+ h_synch,
+ v_synch,
+ blank,
+
+ VGA_OUT_HSYNC,
+ VGA_OUT_VSYNC,
+ VGA_OUT_RED,
+ VGA_OUT_GREEN,
+ VGA_OUT_BLUE
+);
+
+endmodule
diff --git a/common/Video/mc6883.vhd b/common/Video/mc6883.vhd
new file mode 100644
index 00000000..a6ac33aa
--- /dev/null
+++ b/common/Video/mc6883.vhd
@@ -0,0 +1,375 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.numeric_std.all;
+
+entity mc6883 is
+ port
+ (
+ clk : in std_logic;
+ clk_ena : in std_logic;
+ reset : in std_logic;
+
+ -- input
+ a : in std_logic_vector(15 downto 0);
+ rw_n : in std_logic;
+
+ -- vdg signals
+ da0 : in std_logic;
+ hs_n : in std_logic;
+ vclk : out std_logic;
+
+ -- peripheral address selects
+ s : out std_logic_vector(2 downto 0);
+
+ -- clock generation
+ e : out std_logic;
+ q : out std_logic;
+
+ -- dynamic addresses
+ z : out std_logic_vector(7 downto 0);
+
+ -- ram
+ ras0_n : out std_logic;
+ cas_n : out std_logic;
+ we_n : out std_logic;
+
+ -- debug
+ dbg : out std_logic_vector(15 downto 0)
+ );
+end mc6883;
+
+architecture SYN of mc6883 is
+
+ subtype DivisorType is integer range 0 to 11;
+ type DivisorArrayType is array (natural range <>) of DivisorType;
+ -- Division variables for V0=0, V2..V1=sel
+ --constant y_divisor : DivisorArrayType(0 to 3) := (12, 3, 2, 1);
+ -- Division variable for V0=1, v2..V1=sel
+ --constant x_divisor : DivisorArrayType(0 to 3) := (3, 2, 1, 1);
+ constant mode_rows : DivisorArrayType(0 to 7) := (12-1, 3-1, 3-1, 2-1, 2-1, 1-1, 1-1, 1-1);
+
+ -- clocks
+ signal clk_7M15909 : std_logic;
+ signal clk_3M579545 : std_logic;
+ signal clk_1M769772 : std_logic;
+ signal clk_0M894866 : std_logic;
+
+ -- some rising_edge pulses
+ signal rising_edge_hs : std_logic;
+ signal rising_edge_q : std_logic;
+ signal rising_edge_e : std_logic;
+
+ -- internal versions of pin signals
+ signal we_n_s : std_logic;
+
+ -- video counter
+ signal b_int : std_logic_vector(15 downto 0);
+
+ -- control register (CR)
+ signal cr : std_logic_vector(15 downto 0);
+ signal sel_cr : std_logic;
+
+ alias ty : std_logic is cr(15);
+ alias m : std_logic_vector(1 downto 0) is cr(14 downto 13);
+ alias r : std_logic_vector(1 downto 0) is cr(12 downto 11);
+ alias p : std_logic is cr(10);
+ alias f : std_logic_vector(6 downto 0) is cr(9 downto 3);
+ alias v : std_logic_vector(2 downto 0) is cr(2 downto 0);
+
+ alias flag : std_logic is a(0);
+
+ -- internal chipselect vectors
+ signal s_ty0 : std_logic_vector(2 downto 0);
+ signal s_ty1 : std_logic_vector(2 downto 0);
+
+ signal debug : std_logic_vector(1 downto 0);
+
+ shared variable yscale : integer;
+
+begin
+
+ --
+ -- CPU Address is valid tAD after falling edge of E
+ -- CPU Read Data latched at falling edge of E
+ -- CPU Write Data valid tDDW after rising edge of Q,
+ -- - until tDHW (short) after falling edge E
+ --
+
+ -- clock generation, ras/cas generation
+ PROC_MAIN : process (clk, reset, rw_n)
+ variable count : std_logic_vector(3 downto 0);
+ begin
+ if reset = '1' then
+ --count := (others => '0');
+ count := "0000";
+ z <= (others => '0');
+ q <= '0';
+ e <= '0';
+ ras0_n <= '1';
+ cas_n <= '1';
+ we_n_s <= '1';
+ elsif rising_edge (clk) then
+ if clk_ena = '1' then
+ we_n_s <= '1'; -- default
+ clk_7M15909 <= count(0);
+ clk_3M579545 <= count(1);
+ clk_1M769772 <= count(2);
+ clk_0M894866 <= count(3);
+ vclk <= not clk_3M579545;
+ case count is
+ when "0000" =>
+ -- valid VDG address (row)
+ -- z(7) is RAS1# or B(7)
+ z <= b_int(7 downto 0);
+ ras0_n <= '0';
+ when "0001" =>
+ when "0010" =>
+ -- valid VDG address (col)
+ --case m is
+ -- when "00" =>
+ -- z <= "00" & b_int(11 downto 6);
+ -- when "01" =>
+ -- z <= '0' & b_int(13 downto 7);
+ -- when others =>
+ z <= b_int(15 downto 8);
+ --end case;
+ cas_n <= '0';
+ when "0011" =>
+ q <= '1';
+ when "0100" =>
+ when "0101" =>
+ ras0_n <= '1';
+ when "0110" =>
+ when "0111" =>
+ cas_n <= '1';
+ e <= '1';
+ when "1000" =>
+ -- valid MPU address (row)
+ -- z(7) is RAS1# or A(7)
+ z <= a(7 downto 0);
+ ras0_n <= '0';
+ when "1001" =>
+ when "1010" =>
+ -- valid MPU address (col)
+ -- no need to munge any signal with RAS/CAS
+ --case m is
+ -- when "00" =>
+ -- z <= "00" & a(11 downto 6);
+ -- when "01" =>
+ -- z(7) is P or don't care
+ -- z <= p & a(13 downto 7);
+ -- when others =>
+ -- if ty = '0' then
+ -- z <= p & a(14 downto 8);
+ -- else
+ z <= a(15 downto 8);
+ -- end if;
+ --end case;
+ cas_n <= '0';
+ when "1011" =>
+ q <= '0';
+ when "1100" =>
+ when "1101" =>
+ ras0_n <= '1';
+ -- drive WEn some time after mpu address is latched
+ -- on the falling edge of cas_n above
+ -- but in plenty of time before falling edge of E
+ we_n_s <= rw_n;
+ when "1110" =>
+ when "1111" =>
+ cas_n <= '1';
+ e <= '0';
+ when others =>
+ null;
+ end case;
+ count := count + 1;
+ end if; -- clk_ena
+ end if;
+ end process PROC_MAIN;
+
+ -- assign outputs
+ we_n <= we_n_s;
+
+ -- rising edge pulses
+ process (clk, reset)
+ variable old_hs : std_logic;
+ variable old_q : std_logic;
+ variable old_e : std_logic;
+ begin
+ if reset = '1' then
+ old_hs := '0';
+ rising_edge_hs <= '0';
+ old_q := '0';
+ rising_edge_q <= '0';
+ old_e := '0';
+ rising_edge_e <= '0';
+ elsif rising_edge (clk) then
+ if clk_ena = '1' then
+ rising_edge_hs <= '0';
+ if old_hs = '0' and hs_n = '1' then
+ rising_edge_hs <= '1';
+ end if;
+ old_hs := hs_n;
+ end if; -- clk_ena
+ end if;
+ end process;
+
+ -- video address generation
+ -- normally, da0 clocks the internal counter
+ -- but we want a synchronous design
+ -- so sample da0 each internal clock
+ process (clk, reset, da0, hs_n)
+ variable old_hs : std_logic;
+ variable old_da0 : std_logic;
+ --variable yscale : integer;
+ variable saved_b : std_logic_vector(15 downto 0);
+ begin
+ if reset = '1' then
+ b_int <= (others => '0');
+ old_hs := '1';
+ old_da0 := '1';
+ yscale := 0;
+ saved_b := (others => '0');
+ elsif rising_edge (clk) then
+ if clk_ena = '1' then
+ -- vertical blanking - HS rises when DA0 is high
+ -- resets bits B9-15, clear B1-B8
+ if rising_edge_hs = '1' and da0 = '1' then
+ b_int(15 downto 9) <= f(6 downto 0);
+ b_int(8 downto 0) <= (others => '0');
+ yscale := mode_rows(conv_integer(v(2 downto 0)));
+ saved_b := f(6 downto 0) & "000000000";
+ -- horizontal blanking - HS low
+ -- resets bits B1-B3/4
+ elsif hs_n = '0' then
+ if v(0) = '0' then
+ b_int(4) <= '0';
+ end if;
+ b_int(3 downto 1) <= (others => '0');
+ -- coming out of HS?
+ if old_hs = '1' then
+ if yscale = mode_rows(conv_integer(v(2 downto 0))) then
+ yscale := 0;
+ saved_b := b_int;
+ else
+ yscale := yscale + 1;
+ b_int <= saved_b;
+ end if;
+ end if;
+ -- transition on da is the video clock
+ elsif da0 /= old_da0 then
+ b_int <= b_int + 1;
+ end if;
+ old_hs := hs_n;
+ old_da0 := da0;
+ debug <= old_hs & old_da0;
+ end if; -- clk_ena
+ end if;
+ end process;
+
+ -- select control register (CR)
+ sel_cr <= '1' when a(15 downto 5) = "11111111110" else '0';
+
+ --
+ -- Memory decode logic
+ -- - combinatorial - needs to be gated
+ --
+ s_ty0 <= "010" when -- $FFF2-$FFFF (6809 vectors)
+ -- $FFE0-$FFF1 (reserved)
+ a(15 downto 5) = "11111111111"
+ else
+ "111" when -- $FFC0-$FFDF (SAM control register)
+ -- $FF60-$FFBF (reserved)
+ sel_cr = '1' or
+ (a(15 downto 8) = "11111111" and (a(7) = '1' or a(6 downto 5) = "11"))
+ else
+ "110" when -- $FF40-$FF5F (IO2)
+ a(15 downto 5) = "11111111010"
+ else
+ "101" when -- $FF20-$FF3F (IO1)
+ a(15 downto 5) = "11111111001"
+ else
+ "100" when -- $FF00-$FF1F (IO0)
+ a(15 downto 5) = "11111111000"
+ else
+ "011" when -- $C000-$FEFF (rom2)
+ a(15 downto 14) = "11"
+ else
+ "010" when -- $A000-$BFFF (rom1)
+ a(15 downto 13) = "101"
+ else
+ "001" when -- $8000-$9FFF (rom0)
+ a(15 downto 13) = "100"
+ else
+ "000" when -- $0000-$7FFF (32K) RW_N=1
+ a(15) = '0' and rw_n = '1'
+ else
+ "111" when -- $0000-$7FFF (32K) RW_N=0
+ a(15) = '0' and rw_n = '0';
+
+ s_ty1 <= s_ty0 when -- $FF00-$FFFF
+ a(15 downto 8) = X"FF"
+ else
+ "000" when -- $0000-$FEFF (32K) RW_N=1
+ rw_n = '1'
+ else
+ "111" when -- $0000-$FEFF (32K) RW_N=0
+ rw_n = '0';
+
+ s <= s_ty0 when ty = '0' else
+ s_ty1;
+
+ --
+ -- Handle update of the control register (CR)
+ --
+ WRITE_CR : process (clk, reset, a, rw_n)
+ begin
+ if reset = '1' then
+ cr <= (others => '0');
+ elsif falling_edge (clk) then
+ if clk_ena = '1' then
+ if sel_cr = '1' and we_n_s = '0' then
+ case a(4 downto 1) is
+ when "0000" =>
+ v(0) <= flag;
+ when "0001" =>
+ v(1) <= flag;
+ when "0010" =>
+ v(2) <= flag;
+ when "0011" =>
+ f(0) <= flag;
+ when "0100" =>
+ f(1) <= flag;
+ when "0101" =>
+ f(2) <= flag;
+ when "0110" =>
+ f(3) <= flag;
+ when "0111" =>
+ f(4) <= flag;
+ when "1000" =>
+ f(5) <= flag;
+ when "1001" =>
+ f(6) <= flag;
+ when "1010" =>
+ p <= flag;
+ when "1011" =>
+ r(0) <= flag;
+ when "1100" =>
+ r(1) <= flag;
+ when "1101" =>
+ m(0) <= flag;
+ when "1110" =>
+ m(1) <= flag;
+ when others => -- "1111"
+ ty <= flag;
+ end case;
+ end if;
+ end if; -- clk_ena
+ end if;
+ end process WRITE_CR;
+
+ -- for hexy display, for example
+ dbg <= cr;
+
+end SYN;
diff --git a/common/Video/oc_crtc6845.vhd b/common/Video/oc_crtc6845.vhd
new file mode 100644
index 00000000..d48874ff
--- /dev/null
+++ b/common/Video/oc_crtc6845.vhd
@@ -0,0 +1,493 @@
+--===========================================================================--
+-- --
+-- S Y N T H E S I Z A B L E CRTC6845 C O R E --
+-- --
+-- www.opencores.org - January 2000 --
+-- This IP core adheres to the GNU public license. --
+-- --
+-- VHDL model of MC6845 compatible CRTC --
+-- --
+-- This model doesn't implement interlace mode. Everything else is --
+-- (probably) according to original MC6845 data sheet (except VTOTADJ). --
+-- --
+-- Implementation in Xilinx Virtex XCV50-6 runs at 50 MHz (character clock).--
+-- With external pixel generator this CRTC could handle 450MHz pixel rate --
+-- (see MC6845 datasheet for typical application). --
+-- --
+-- Author: Damjan Lampret, lampret@opencores.org --
+-- --
+-- TO DO: --
+-- --
+-- - fix REG_INIT and remove non standard signals at topl level entity. --
+-- Allow fixed registers values (now set with REG_INIT). Anyway cleanup --
+-- required. --
+-- --
+-- - split design in four units (horizontal sync, vertical sync, bus --
+-- interface and the rest) --
+-- --
+-- - synthesis with Synplify pending (there are some problems with --
+-- UNSIGNED and BIT_LOGIC_VECTOR types in some units !) --
+-- --
+-- - testbench --
+-- --
+-- - interlace mode support, extend VSYNC for V.Total Adjust value (R5) --
+-- --
+-- - verification in a real application --
+-- --
+--===========================================================================--
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.std_logic_arith.all;
+
+entity crtc6845 is
+ generic (
+ MA_WIDTH : natural := 14;
+ RA_WIDTH : natural := 5;
+ DB_WIDTH : natural := 8;
+ AR_WIDTH : natural := 5
+ );
+ port (
+ MA : out STD_LOGIC_VECTOR (MA_WIDTH-1 downto 0);
+ RA : out STD_LOGIC_VECTOR (RA_WIDTH-1 downto 0);
+ HSYNC : out STD_LOGIC;
+ VSYNC : out STD_LOGIC;
+ DE : out STD_LOGIC;
+ CURSOR : out STD_LOGIC;
+ LPSTBn : in STD_LOGIC;
+ E : in STD_LOGIC;
+ RS : in STD_LOGIC;
+ CSn : in STD_LOGIC;
+ RW : in STD_LOGIC;
+ DI : in STD_LOGIC_VECTOR (DB_WIDTH-1 downto 0);
+ DO : out STD_LOGIC_VECTOR (DB_WIDTH-1 downto 0);
+ RESETn : in STD_LOGIC;
+ CLK : in STD_LOGIC;
+ -- not standard
+ REG_INIT: in STD_LOGIC;
+ --
+ Hend: inout STD_LOGIC;
+ HS: inout STD_LOGIC;
+ CHROW_CLK: inout STD_LOGIC;
+ Vend: inout STD_LOGIC;
+ SLadj: inout STD_LOGIC;
+ H: inout STD_LOGIC;
+ V: inout STD_LOGIC;
+ CURSOR_ACTIVE: inout STD_LOGIC;
+ VERT_RST: inout STD_LOGIC
+ );
+end crtc6845;
+
+architecture crtc6845_behav of crtc6845 is
+
+constant INDEX_HT : STD_LOGIC_VECTOR (4 downto 0) := '0' & x"0";
+constant INDEX_HD : STD_LOGIC_VECTOR (4 downto 0) := '0' & x"1";
+constant INDEX_HSP : STD_LOGIC_VECTOR (4 downto 0) := '0' & x"2";
+constant INDEX_HSW : STD_LOGIC_VECTOR (4 downto 0) := '0' & x"3";
+constant INDEX_VT : STD_LOGIC_VECTOR (4 downto 0) := '0' & x"4";
+constant INDEX_ADJ : STD_LOGIC_VECTOR (4 downto 0) := '0' & x"5";
+constant INDEX_VD : STD_LOGIC_VECTOR (4 downto 0) := '0' & x"6";
+constant INDEX_VSP : STD_LOGIC_VECTOR (4 downto 0) := '0' & x"7";
+constant INDEX_IM : STD_LOGIC_VECTOR (4 downto 0) := '0' & x"8";
+constant INDEX_SL : STD_LOGIC_VECTOR (4 downto 0) := '0' & x"9";
+constant INDEX_CURST : STD_LOGIC_VECTOR (4 downto 0) := '0' & x"a";
+constant INDEX_CUREND : STD_LOGIC_VECTOR (4 downto 0) := '0' & x"b";
+constant INDEX_SA_H : STD_LOGIC_VECTOR (4 downto 0) := '0' & x"c";
+constant INDEX_SA_L : STD_LOGIC_VECTOR (4 downto 0) := '0' & x"d";
+constant INDEX_CUR_H : STD_LOGIC_VECTOR (4 downto 0) := '0' & x"e";
+constant INDEX_CUR_L : STD_LOGIC_VECTOR (4 downto 0) := '0' & x"f";
+constant INDEX_LP_H : STD_LOGIC_VECTOR (4 downto 0) := '1' & x"0";
+constant INDEX_LP_L : STD_LOGIC_VECTOR (4 downto 0) := '1' & x"1";
+
+-- components
+component cursor_ctrl
+ port (
+ RESETn : in STD_LOGIC;
+ CLK : in STD_LOGIC;
+ RA : in STD_LOGIC_VECTOR (RA_WIDTH-1 downto 0);
+ CURSOR : out STD_LOGIC;
+ ACTIVE : in STD_LOGIC;
+ CURST : in STD_LOGIC_VECTOR (6 downto 0);
+ CUREND : in STD_LOGIC_VECTOR (4 downto 0)
+ );
+end component;
+
+-- 6845 registers R0-R17
+signal REG_HT : STD_LOGIC_VECTOR (7 downto 0);
+signal REG_HD : STD_LOGIC_VECTOR (7 downto 0);
+signal REG_HSP : STD_LOGIC_VECTOR (7 downto 0);
+signal REG_HSW : STD_LOGIC_VECTOR (3 downto 0);
+signal REG_VT : STD_LOGIC_VECTOR (6 downto 0);
+signal REG_ADJ : STD_LOGIC_VECTOR (4 downto 0);
+signal REG_VD : STD_LOGIC_VECTOR (6 downto 0);
+signal REG_VSP : STD_LOGIC_VECTOR (6 downto 0);
+signal REG_IM : STD_LOGIC_VECTOR (1 downto 0);
+signal REG_SL : STD_LOGIC_VECTOR (4 downto 0);
+signal REG_CURST : STD_LOGIC_VECTOR (6 downto 0);
+signal REG_CUREND : STD_LOGIC_VECTOR (4 downto 0);
+signal REG_SA_H : STD_LOGIC_VECTOR (5 downto 0);
+signal REG_SA_L : STD_LOGIC_VECTOR (7 downto 0);
+signal REG_CUR_H : STD_LOGIC_VECTOR (5 downto 0);
+signal REG_CUR_L : STD_LOGIC_VECTOR (7 downto 0);
+signal REG_LP_H : STD_LOGIC_VECTOR (5 downto 0);
+signal REG_LP_L : STD_LOGIC_VECTOR (7 downto 0);
+
+-- Counters
+signal CTR_HORIZ : UNSIGNED (7 downto 0);
+signal CTR_HSW : UNSIGNED (3 downto 0);
+signal CTR_SL : UNSIGNED (4 downto 0);
+signal CTR_VERT : UNSIGNED (6 downto 0);
+signal CTR_VSW : UNSIGNED (4 downto 0);
+signal CTR_LAG : UNSIGNED (13 downto 0);
+
+-- I/O address register
+signal REGIO_AR : STD_LOGIC_VECTOR (AR_WIDTH-1 downto 0);
+
+-- Interconnect signals (as in MC6845 datasheet)
+--pragma translate_off
+signal Hend: STD_LOGIC;
+signal HS: STD_LOGIC;
+signal CHROW_CLK: STD_LOGIC;
+signal Vend: STD_LOGIC;
+signal SLadj: STD_LOGIC;
+signal H: STD_LOGIC;
+signal V: STD_LOGIC;
+signal CURSOR_ACTIVE: STD_LOGIC;
+signal VERT_RST: STD_LOGIC;
+--pragma translate_on
+
+-- Shared Variables
+signal Hdisp: STD_LOGIC;
+signal Vdisp: STD_LOGIC;
+shared variable ROWaddr: UNSIGNED (13 downto 0);
+
+begin
+
+ext_read:
+process(E)
+begin
+ if rising_edge(E) then
+ if CSn = '0' and RW = '1' and RS = '1' then
+ case REGIO_AR is
+ when INDEX_CUR_H =>
+ DO(5 downto 0) <= REG_CUR_H;
+ DO(7 downto 6) <= "00";
+ when INDEX_CUR_L =>
+ DO <= REG_CUR_L;
+ when INDEX_LP_H =>
+ DO(5 downto 0) <= REG_LP_H;
+ DO(7 downto 6) <= "00";
+ when INDEX_LP_L =>
+ DO <= REG_LP_L;
+ when others =>
+ DO <= (others => '0');
+ end case;
+ end if;
+ end if;
+end process;
+
+ext_write:
+process(E,REG_INIT)
+begin
+ if falling_edge(E) then
+ if REG_INIT = '1' then
+ REGIO_AR <= b"0" & x"0";
+ REG_HT <= x"65";
+ REG_HD <= x"50";
+ REG_HSP <= x"56";
+ REG_HSW <= x"9";
+ REG_SL <= '0' & x"b";
+ REG_VT <= b"001" & x"8"; --18
+ REG_ADJ <= b"0" & x"a";
+ REG_VD <= b"001" & x"8"; --18
+ REG_VSP <= b"001" & x"8";--18
+ REG_CURST <= b"000" & x"0";
+ REG_CUREND <= b"0" & x"B";
+ REG_SA_H <= b"00" & x"0";
+ REG_SA_L <= x"80";
+ REG_CUR_H <= b"00" & x"0";
+ REG_CUR_L <= x"80";
+ end if;
+ end if;
+--pragma translate_off
+ if CSn = '0' and RW = '0' then
+ if RS = '0' then
+ REGIO_AR <= D (AR_WIDTH-1 downto 0);
+ else
+ case REGIO_AR is
+ when INDEX_HT =>
+ REG_HT <= DI;
+ when INDEX_HD =>
+ REG_HD <= DI;
+ when INDEX_HSP =>
+ REG_HSP <= DI;
+ when INDEX_HSW =>
+ REG_HSW <= DI(3 downto 0);
+ when INDEX_SL =>
+ REG_SL <= DI(4 downto 0);
+ when INDEX_VT =>
+ REG_VT <= DI(6 downto 0);
+ when INDEX_ADJ =>
+ REG_ADJ <= DI(4 downto 0);
+ when INDEX_VD =>
+ REG_VD <= DI(6 downto 0);
+ when INDEX_VSP =>
+ REG_VSP <= DI(6 downto 0);
+ when INDEX_CURST =>
+ REG_CURST <= DI(6 downto 0);
+ when INDEX_CUREND =>
+ REG_CUREND <= DI(4 downto 0);
+ when INDEX_SA_H =>
+ REG_SA_H <= DI(5 downto 0);
+ when INDEX_SA_L =>
+ REG_SA_L <= DI;
+ when INDEX_CUR_H =>
+ REG_CUR_H <= DI(5 downto 0);
+ when INDEX_CUR_L =>
+ REG_CUR_L <= DI;
+ when others =>
+ null;
+ end case;
+ end if;
+ end if;
+ end if;
+--pragma translate_on
+end process;
+
+--------------------------------------------
+-- Horizontal Sync --
+--------------------------------------------
+
+H_p:
+process(CLK, RESETn)
+begin
+ if RESETn = '0' then
+ CTR_HORIZ <= (others => '0');
+ elsif rising_edge(CLK) then
+ if std_logic_vector(CTR_HORIZ) = REG_HT then
+ H <= '1';
+ CTR_HORIZ <= (others => '0');
+ else
+ H <= '0';
+ CTR_HORIZ <= CTR_HORIZ + 1;
+ end if;
+ end if;
+end process;
+
+Hend_p:
+process(CTR_HORIZ, REG_HD)
+begin
+ if std_logic_vector(CTR_HORIZ) = REG_HD then
+ Hend <= '1';
+ else
+ Hend <= '0';
+ end if;
+end process;
+
+CTR_HSW_p:
+process(CLK, RESETn)
+begin
+ if RESETn = '0' then
+ CTR_HSW <= (others => '0');
+ elsif rising_edge(CLK) then
+ if HS = '1' then
+ CTR_HSW <= CTR_HSW + 1;
+ else
+ CTR_HSW <= (others => '0');
+ end if;
+ end if;
+end process;
+
+HS_p:
+process(CTR_HORIZ, CTR_HSW, REG_HSP, REG_HSW, HS)
+begin
+ if std_logic_vector(CTR_HORIZ) = REG_HSP then
+ HS <= '1';
+ elsif std_logic_vector(CTR_HSW) = REG_HSW then
+ HS <= '0';
+ else
+ HS <= HS;
+ end if;
+ HSYNC <= HS;
+end process;
+
+--------------------------------------------
+-- Display Enable --
+--------------------------------------------
+
+DE_p:
+process(H, Hend, V, Vend, Hdisp, Vdisp)
+begin
+ if H = '1' and Hend = '0' then
+ Hdisp <= '1';
+ elsif H = '0' and Hend = '1' then
+ Hdisp <= '0';
+ else
+ Hdisp <= Hdisp;
+ end if;
+ if V = '1' and Vend = '0' then
+ Vdisp <= '1';
+ elsif V = '0' and Vend = '1' then
+ Vdisp <= '0';
+ else
+ Vdisp <= Vdisp;
+ end if;
+end process;
+DE <= Hdisp and Vdisp;
+
+--------------------------------------------
+-- Scan Line Counter --
+--------------------------------------------
+
+CTR_SL_p:
+process(H, RESETn)
+begin
+ if RESETn = '0' then
+ CTR_SL <= (others => '0');
+ elsif rising_edge(H) then
+ if std_logic_vector(CTR_SL) = REG_SL then
+ CHROW_CLK <= '1';
+ CTR_SL <= (others => '0');
+ else
+ CHROW_CLK <= '0';
+ CTR_SL <= CTR_SL + 1;
+ end if;
+ end if;
+end process;
+RA <= std_logic_vector(CTR_SL);
+
+SLadj_p:
+process(CTR_SL, REG_ADJ)
+begin
+ if std_logic_vector(CTR_SL) = REG_ADJ then
+ SLadj <= '1';
+ else
+ SLadj <= '0';
+ end if;
+end process;
+
+--------------------------------------------
+-- Vertical Sync (Character Row CTR) --
+--------------------------------------------
+
+V_p:
+process(CHROW_CLK, RESETn)
+begin
+ if RESETn = '0' then
+ CTR_VERT <= (others => '0');
+ elsif rising_edge(CHROW_CLK) then
+ if std_logic_vector(CTR_VERT) = REG_VT then
+ V <= '1';
+-- if SLadj = '1' then
+ VERT_RST <= '1';
+ CTR_VERT <= (others => '0');
+-- end if;
+ else
+ VERT_RST <= '0';
+ V <= '0';
+ CTR_VERT <= CTR_VERT + 1;
+ end if;
+ end if;
+end process;
+
+Vend_p:
+process(CTR_VERT, REG_VD)
+begin
+ if std_logic_vector(CTR_VERT) = REG_VD then
+ Vend <= '1';
+ else
+ Vend <= '0';
+ end if;
+end process;
+
+CTR_VSW_p:
+process(H, RESETn, CTR_VERT, REG_VSP, CTR_VSW)
+begin
+ if RESETn = '0' then
+ CTR_VSW <= (others => '0');
+ elsif rising_edge(H) then
+ if std_logic_vector(CTR_VERT) = REG_VSP then
+ CTR_VSW <= (others => '0');
+ end if;
+ if CTR_VSW /= 16 then
+ CTR_VSW <= CTR_VSW + 1;
+ VSYNC <= '1';
+ else
+ VSYNC <= '0';
+ end if;
+ end if;
+end process;
+
+--------------------------------------------
+-- Linear Address Generator --
+--------------------------------------------
+
+ROWaddr_p:
+process(RESETn, CHROW_CLK, VERT_RST, REG_SA_H, REG_SA_L)
+begin
+ if RESETn = '0' then
+ ROWaddr := unsigned(REG_SA_H & REG_SA_L);
+ elsif rising_edge(CHROW_CLK) then
+ ROWaddr := ROWaddr + unsigned(REG_HD);
+ if VERT_RST = '1' then
+ ROWaddr := unsigned(REG_SA_H & REG_SA_L);
+ end if;
+ end if;
+end process;
+
+LAG_p:
+process(CLK, RESETn, H, REG_SA_H, REG_SA_L)
+begin
+ if RESETn = '0' then
+ CTR_LAG <= unsigned(REG_SA_H & REG_SA_L);
+ elsif rising_edge(CLK) then
+ if H = '1' then
+ CTR_LAG <= ROWaddr;
+ end if;
+ CTR_LAG <= CTR_LAG + 1;
+ end if;
+end process;
+
+MA <= std_logic_vector(CTR_LAG);
+
+--------------------------------------------
+-- Light Pen Capture --
+--------------------------------------------
+
+LP_p:
+process(CLK, LPSTBn)
+begin
+ if rising_edge(CLK) then
+ if LPSTBn = '0' then
+ REG_LP_H <= std_logic_vector(CTR_LAG(13 downto 8));
+ REG_LP_L <= std_logic_vector(CTR_LAG(7 downto 0));
+ end if;
+ end if;
+end process;
+
+--------------------------------------------
+-- Cursor Control Unit Instantiation --
+--------------------------------------------
+
+CURSOR_p:
+process(CTR_LAG, REG_CUR_H, REG_CUR_L)
+begin
+ if CTR_LAG = unsigned(REG_CUR_H & REG_CUR_L) then
+ CURSOR_ACTIVE <= '1';
+ else
+ CURSOR_ACTIVE <= '0';
+ end if;
+end process;
+
+cursor_ctrl_inst: cursor_ctrl
+ port map (
+ RESETn => RESETn,
+ CLK => V,
+ RA => std_logic_vector(CTR_SL),
+ CURSOR => CURSOR,
+ ACTIVE => CURSOR_ACTIVE,
+ CURST => REG_CURST,
+ CUREND => REG_CUREND
+ );
+
+end crtc6845_behav;
diff --git a/common/Video/saa505x.vhd b/common/Video/saa505x.vhd
new file mode 100644
index 00000000..808d0197
--- /dev/null
+++ b/common/Video/saa505x.vhd
@@ -0,0 +1,1349 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.std_logic_arith.all;
+use ieee.numeric_std.all;
+
+entity saa505x is
+ port
+ (
+ clk : in std_logic;
+ reset : in std_logic;
+
+ si_i_n : in std_logic;
+ si_o : out std_logic;
+ data_n : in std_logic;
+ d : in std_logic_vector(6 downto 0);
+ dlim : in std_logic;
+ glr : in std_logic;
+ dew : in std_logic;
+ crs : in std_logic;
+ bcs_n : in std_logic;
+ tlc_n : out std_logic;
+ tr6 : in std_logic;
+ f1 : in std_logic;
+ y : out std_logic;
+ b : out std_logic;
+ g : out std_logic;
+ r : out std_logic;
+ blan : out std_logic;
+ lose : in std_logic;
+ po : in std_logic;
+ de : in std_logic
+ );
+end entity saa505x;
+
+architecture SYN of saa505x is
+
+ type charset_row_t is array (0 to 9) of std_logic_vector(5 downto 0);
+ type charset_t is array (0 to 95) of charset_row_t;
+
+ constant charset : charset_t :=
+ (
+ -- $20
+ 0 => (
+ 0=>"000000",
+ 1=>"000000",
+ 2=>"000000",
+ 3=>"000000",
+ 4=>"000000",
+ 5=>"000000",
+ 6=>"000000",
+ 7=>"000000",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $21
+ 1 => (
+ 0=>"000000",
+ 1=>"000100",
+ 2=>"000100",
+ 3=>"000100",
+ 4=>"000100",
+ 5=>"000100",
+ 6=>"000000",
+ 7=>"000100",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $22
+ 2 => (
+ 0=>"000000",
+ 1=>"001010",
+ 2=>"001010",
+ 3=>"001010",
+ 4=>"000000",
+ 5=>"000000",
+ 6=>"000000",
+ 7=>"000000",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $23
+ 3 => (
+ 0=>"000000",
+ 1=>"000110",
+ 2=>"001001",
+ 3=>"001000",
+ 4=>"011100",
+ 5=>"001000",
+ 6=>"001000",
+ 7=>"011111",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $24
+ 4 => (
+ 0=>"000000",
+ 1=>"001110",
+ 2=>"010101",
+ 3=>"010100",
+ 4=>"001110",
+ 5=>"000101",
+ 6=>"010101",
+ 7=>"001110",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $25
+ 5 => (
+ 0=>"000000",
+ 1=>"011000",
+ 2=>"011001",
+ 3=>"000010",
+ 4=>"000100",
+ 5=>"001000",
+ 6=>"010011",
+ 7=>"000011",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $26
+ 6 => (
+ 0=>"000000",
+ 1=>"001000",
+ 2=>"010100",
+ 3=>"010100",
+ 4=>"001000",
+ 5=>"010101",
+ 6=>"010010",
+ 7=>"001101",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $27
+ 7 => (
+ 0=>"000000",
+ 1=>"000100",
+ 2=>"000100",
+ 3=>"000100",
+ 4=>"000000",
+ 5=>"000000",
+ 6=>"000000",
+ 7=>"000000",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $28
+ 8 => (
+ 0=>"000000",
+ 1=>"000010",
+ 2=>"000100",
+ 3=>"001000",
+ 4=>"001000",
+ 5=>"001000",
+ 6=>"000100",
+ 7=>"000010",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $29
+ 9 => (
+ 0=>"000000",
+ 1=>"001000",
+ 2=>"000100",
+ 3=>"000010",
+ 4=>"000010",
+ 5=>"000010",
+ 6=>"000100",
+ 7=>"001000",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $2A
+ 10 => (
+ 0=>"000000",
+ 1=>"000100",
+ 2=>"010101",
+ 3=>"001110",
+ 4=>"000100",
+ 5=>"001110",
+ 6=>"010101",
+ 7=>"000100",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $2B
+ 11 => (
+ 0=>"000000",
+ 1=>"000000",
+ 2=>"000100",
+ 3=>"000100",
+ 4=>"011111",
+ 5=>"000100",
+ 6=>"000100",
+ 7=>"000000",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $2C
+ 12 => (
+ 0=>"000000",
+ 1=>"000000",
+ 2=>"000000",
+ 3=>"000000",
+ 4=>"000000",
+ 5=>"000100",
+ 6=>"000100",
+ 7=>"001000",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $2D
+ 13 => (
+ 0=>"000000",
+ 1=>"000000",
+ 2=>"000000",
+ 3=>"001110",
+ 4=>"000000",
+ 5=>"000000",
+ 6=>"000000",
+ 7=>"000000",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $2E
+ 14 => (
+ 0=>"000000",
+ 1=>"000000",
+ 2=>"000000",
+ 3=>"000000",
+ 4=>"000000",
+ 5=>"000000",
+ 6=>"000000",
+ 7=>"000100",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $2F
+ 15 => (
+ 0=>"000000",
+ 1=>"000000",
+ 2=>"000001",
+ 3=>"000010",
+ 4=>"000100",
+ 5=>"001000",
+ 6=>"010000",
+ 7=>"000000",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $30
+ 16 => (
+ 0=>"000000",
+ 1=>"000100",
+ 2=>"001010",
+ 3=>"010001",
+ 4=>"010001",
+ 5=>"010001",
+ 6=>"001010",
+ 7=>"000100",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $31
+ 17 => (
+ 0=>"000000",
+ 1=>"000100",
+ 2=>"001100",
+ 3=>"000100",
+ 4=>"000100",
+ 5=>"000100",
+ 6=>"000100",
+ 7=>"001110",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $32
+ 18 => (
+ 0=>"000000",
+ 1=>"001110",
+ 2=>"010001",
+ 3=>"000001",
+ 4=>"000110",
+ 5=>"001000",
+ 6=>"010000",
+ 7=>"011111",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $33
+ 19 => (
+ 0=>"000000",
+ 1=>"011111",
+ 2=>"000001",
+ 3=>"000010",
+ 4=>"000110",
+ 5=>"000001",
+ 6=>"010001",
+ 7=>"001110",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $34
+ 20 => (
+ 0=>"000000",
+ 1=>"000010",
+ 2=>"000110",
+ 3=>"001010",
+ 4=>"010010",
+ 5=>"011111",
+ 6=>"000010",
+ 7=>"000010",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $35
+ 21 => (
+ 0=>"000000",
+ 1=>"011111",
+ 2=>"010000",
+ 3=>"011110",
+ 4=>"000001",
+ 5=>"000001",
+ 6=>"010001",
+ 7=>"001110",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $36
+ 22 => (
+ 0=>"000000",
+ 1=>"000110",
+ 2=>"001000",
+ 3=>"010000",
+ 4=>"011110",
+ 5=>"010001",
+ 6=>"010001",
+ 7=>"001110",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $37
+ 23 => (
+ 0=>"000000",
+ 1=>"011111",
+ 2=>"000001",
+ 3=>"000010",
+ 4=>"000100",
+ 5=>"001000",
+ 6=>"001000",
+ 7=>"001000",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $38
+ 24 => (
+ 0=>"000000",
+ 1=>"001110",
+ 2=>"010001",
+ 3=>"010001",
+ 4=>"001110",
+ 5=>"010001",
+ 6=>"010001",
+ 7=>"001110",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $39
+ 25 => (
+ 0=>"000000",
+ 1=>"001110",
+ 2=>"010001",
+ 3=>"010001",
+ 4=>"001111",
+ 5=>"000001",
+ 6=>"000010",
+ 7=>"001100",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $3A
+ 26 => (
+ 0=>"000000",
+ 1=>"000000",
+ 2=>"000000",
+ 3=>"000100",
+ 4=>"000000",
+ 5=>"000000",
+ 6=>"000100",
+ 7=>"000000",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $3B
+ 27 => (
+ 0=>"000000",
+ 1=>"000000",
+ 2=>"000000",
+ 3=>"000100",
+ 4=>"000000",
+ 5=>"000100",
+ 6=>"000100",
+ 7=>"001000",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $3C
+ 28 => (
+ 0=>"000000",
+ 1=>"000010",
+ 2=>"000100",
+ 3=>"001000",
+ 4=>"010000",
+ 5=>"001000",
+ 6=>"000100",
+ 7=>"000010",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $3D
+ 29 => (
+ 0=>"000000",
+ 1=>"000000",
+ 2=>"000000",
+ 3=>"011111",
+ 4=>"000000",
+ 5=>"011111",
+ 6=>"000000",
+ 7=>"000000",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $3E
+ 30 => (
+ 0=>"000000",
+ 1=>"001000",
+ 2=>"000100",
+ 3=>"000010",
+ 4=>"000001",
+ 5=>"000010",
+ 6=>"000100",
+ 7=>"001000",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $3F
+ 31 => (
+ 0=>"000000",
+ 1=>"001110",
+ 2=>"010001",
+ 3=>"000010",
+ 4=>"000100",
+ 5=>"000100",
+ 6=>"000000",
+ 7=>"000100",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $40
+ 32 => (
+ 0=>"000000",
+ 1=>"001110",
+ 2=>"010001",
+ 3=>"010111",
+ 4=>"010101",
+ 5=>"010111",
+ 6=>"010000",
+ 7=>"001111",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $41
+ 33 => (
+ 0=>"000000",
+ 1=>"000100",
+ 2=>"001010",
+ 3=>"010001",
+ 4=>"010001",
+ 5=>"011111",
+ 6=>"010001",
+ 7=>"010001",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $42
+ 34 => (
+ 0=>"000000",
+ 1=>"011110",
+ 2=>"010001",
+ 3=>"010001",
+ 4=>"011110",
+ 5=>"010001",
+ 6=>"010001",
+ 7=>"011110",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $43
+ 35 => (
+ 0=>"000000",
+ 1=>"001110",
+ 2=>"010001",
+ 3=>"010000",
+ 4=>"010000",
+ 5=>"010000",
+ 6=>"010001",
+ 7=>"001110",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $44
+ 36 => (
+ 0=>"000000",
+ 1=>"011110",
+ 2=>"010001",
+ 3=>"010001",
+ 4=>"010001",
+ 5=>"010001",
+ 6=>"010001",
+ 7=>"011110",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $45
+ 37 => (
+ 0=>"000000",
+ 1=>"011111",
+ 2=>"010000",
+ 3=>"010000",
+ 4=>"011110",
+ 5=>"010000",
+ 6=>"010000",
+ 7=>"011111",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $46
+ 38 => (
+ 0=>"000000",
+ 1=>"011111",
+ 2=>"010000",
+ 3=>"010000",
+ 4=>"011110",
+ 5=>"010000",
+ 6=>"010000",
+ 7=>"010000",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $47
+ 39 => (
+ 0=>"000000",
+ 1=>"001110",
+ 2=>"010001",
+ 3=>"010000",
+ 4=>"010000",
+ 5=>"010011",
+ 6=>"010001",
+ 7=>"001111",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $48
+ 40 => (
+ 0=>"000000",
+ 1=>"010001",
+ 2=>"010001",
+ 3=>"010001",
+ 4=>"011111",
+ 5=>"010001",
+ 6=>"010001",
+ 7=>"010001",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $49
+ 41 => (
+ 0=>"000000",
+ 1=>"001110",
+ 2=>"000100",
+ 3=>"000100",
+ 4=>"000100",
+ 5=>"000100",
+ 6=>"000100",
+ 7=>"001110",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $4A
+ 42 => (
+ 0=>"000000",
+ 1=>"000001",
+ 2=>"000001",
+ 3=>"000001",
+ 4=>"000001",
+ 5=>"000001",
+ 6=>"010001",
+ 7=>"001110",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $4B
+ 43 => (
+ 0=>"000000",
+ 1=>"010001",
+ 2=>"010010",
+ 3=>"010100",
+ 4=>"011000",
+ 5=>"010100",
+ 6=>"010010",
+ 7=>"010001",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $4C
+ 44 => (
+ 0=>"000000",
+ 1=>"010000",
+ 2=>"010000",
+ 3=>"010000",
+ 4=>"010000",
+ 5=>"010000",
+ 6=>"010000",
+ 7=>"011111",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $4D
+ 45 => (
+ 0=>"000000",
+ 1=>"010001",
+ 2=>"011011",
+ 3=>"010101",
+ 4=>"010001",
+ 5=>"010001",
+ 6=>"010001",
+ 7=>"010001",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $4E
+ 46 => (
+ 0=>"000000",
+ 1=>"010001",
+ 2=>"010001",
+ 3=>"011001",
+ 4=>"010101",
+ 5=>"010011",
+ 6=>"010001",
+ 7=>"010001",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $4F
+ 47 => (
+ 0=>"000000",
+ 1=>"001110",
+ 2=>"010001",
+ 3=>"010001",
+ 4=>"010001",
+ 5=>"010001",
+ 6=>"010001",
+ 7=>"001110",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $50
+ 48 => (
+ 0=>"000000",
+ 1=>"011110",
+ 2=>"010001",
+ 3=>"010001",
+ 4=>"011110",
+ 5=>"010000",
+ 6=>"010000",
+ 7=>"010000",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $51
+ 49 => (
+ 0=>"000000",
+ 1=>"001110",
+ 2=>"010001",
+ 3=>"010001",
+ 4=>"010001",
+ 5=>"010101",
+ 6=>"010010",
+ 7=>"001101",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $52
+ 50 => (
+ 0=>"000000",
+ 1=>"011110",
+ 2=>"010001",
+ 3=>"010001",
+ 4=>"011110",
+ 5=>"010100",
+ 6=>"010010",
+ 7=>"010001",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $53
+ 51 => (
+ 0=>"000000",
+ 1=>"001110",
+ 2=>"010001",
+ 3=>"010000",
+ 4=>"001110",
+ 5=>"000001",
+ 6=>"010001",
+ 7=>"001110",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $54
+ 52 => (
+ 0=>"000000",
+ 1=>"011111",
+ 2=>"000100",
+ 3=>"000100",
+ 4=>"000100",
+ 5=>"000100",
+ 6=>"000100",
+ 7=>"000100",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $55
+ 53 => (
+ 0=>"000000",
+ 1=>"010001",
+ 2=>"010001",
+ 3=>"010001",
+ 4=>"010001",
+ 5=>"010001",
+ 6=>"010001",
+ 7=>"001110",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $56
+ 54 => (
+ 0=>"000000",
+ 1=>"010001",
+ 2=>"010001",
+ 3=>"010001",
+ 4=>"001010",
+ 5=>"001010",
+ 6=>"000100",
+ 7=>"000100",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $57
+ 55 => (
+ 0=>"000000",
+ 1=>"010001",
+ 2=>"010001",
+ 3=>"010001",
+ 4=>"010101",
+ 5=>"010101",
+ 6=>"010101",
+ 7=>"001010",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $58
+ 56 => (
+ 0=>"000000",
+ 1=>"010001",
+ 2=>"010001",
+ 3=>"001010",
+ 4=>"000100",
+ 5=>"001010",
+ 6=>"010001",
+ 7=>"010001",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $59
+ 57 => (
+ 0=>"000000",
+ 1=>"010001",
+ 2=>"010001",
+ 3=>"001010",
+ 4=>"000100",
+ 5=>"000100",
+ 6=>"000100",
+ 7=>"000100",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $5A
+ 58 => (
+ 0=>"000000",
+ 1=>"011111",
+ 2=>"000001",
+ 3=>"000010",
+ 4=>"000100",
+ 5=>"001000",
+ 6=>"010000",
+ 7=>"011111",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $5B
+ 59 => (
+ 0=>"000000",
+ 1=>"000000",
+ 2=>"000100",
+ 3=>"001000",
+ 4=>"011111",
+ 5=>"001000",
+ 6=>"000100",
+ 7=>"000000",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $5C
+ 60 => (
+ 0=>"000000",
+ 1=>"010000",
+ 2=>"010000",
+ 3=>"010000",
+ 4=>"010110",
+ 5=>"000001",
+ 6=>"000010",
+ 7=>"000100",
+ 8=>"000111",
+ 9=>"000000"
+ ),
+ -- $5D
+ 61 => (
+ 0=>"000000",
+ 1=>"000000",
+ 2=>"000100",
+ 3=>"000010",
+ 4=>"011111",
+ 5=>"000010",
+ 6=>"000100",
+ 7=>"000000",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $5E
+ 62 => (
+ 0=>"000000",
+ 1=>"000000",
+ 2=>"000100",
+ 3=>"001110",
+ 4=>"010101",
+ 5=>"000100",
+ 6=>"000100",
+ 7=>"000000",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $5F
+ 63 => (
+ 0=>"000000",
+ 1=>"001010",
+ 2=>"001010",
+ 3=>"011111",
+ 4=>"001010",
+ 5=>"011111",
+ 6=>"001010",
+ 7=>"001010",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $60
+ 64 => (
+ 0=>"000000",
+ 1=>"000000",
+ 2=>"000000",
+ 3=>"000000",
+ 4=>"000000",
+ 5=>"011111",
+ 6=>"000000",
+ 7=>"000000",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $61
+ 65 => (
+ 0=>"000000",
+ 1=>"000000",
+ 2=>"000000",
+ 3=>"001110",
+ 4=>"000001",
+ 5=>"001111",
+ 6=>"010001",
+ 7=>"001111",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $62
+ 66 => (
+ 0=>"000000",
+ 1=>"010000",
+ 2=>"010000",
+ 3=>"011110",
+ 4=>"010001",
+ 5=>"010001",
+ 6=>"010001",
+ 7=>"011110",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $63
+ 67 => (
+ 0=>"000000",
+ 1=>"000000",
+ 2=>"000000",
+ 3=>"001111",
+ 4=>"010000",
+ 5=>"010000",
+ 6=>"010000",
+ 7=>"001111",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $64
+ 68 => (
+ 0=>"000000",
+ 1=>"000001",
+ 2=>"000001",
+ 3=>"001111",
+ 4=>"010001",
+ 5=>"010001",
+ 6=>"010001",
+ 7=>"001111",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $65
+ 69 => (
+ 0=>"000000",
+ 1=>"000000",
+ 2=>"000000",
+ 3=>"001110",
+ 4=>"010001",
+ 5=>"011111",
+ 6=>"010000",
+ 7=>"001110",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $66
+ 70 => (
+ 0=>"000000",
+ 1=>"000010",
+ 2=>"000100",
+ 3=>"000100",
+ 4=>"001110",
+ 5=>"000100",
+ 6=>"000100",
+ 7=>"000100",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $67
+ 71 => (
+ 0=>"000000",
+ 1=>"000000",
+ 2=>"000000",
+ 3=>"001111",
+ 4=>"010001",
+ 5=>"010001",
+ 6=>"010001",
+ 7=>"001111",
+ 8=>"000001",
+ 9=>"001110"
+ ),
+ -- $68
+ 72 => (
+ 0=>"000000",
+ 1=>"010000",
+ 2=>"010000",
+ 3=>"011110",
+ 4=>"010001",
+ 5=>"010001",
+ 6=>"010001",
+ 7=>"010001",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $69
+ 73 => (
+ 0=>"000000",
+ 1=>"000100",
+ 2=>"000000",
+ 3=>"001100",
+ 4=>"000100",
+ 5=>"000100",
+ 6=>"000100",
+ 7=>"001110",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $6A
+ 74 => (
+ 0=>"000000",
+ 1=>"000100",
+ 2=>"000000",
+ 3=>"000100",
+ 4=>"000100",
+ 5=>"000100",
+ 6=>"000100",
+ 7=>"000100",
+ 8=>"001000",
+ 9=>"000000"
+ ),
+ -- $6B
+ 75 => (
+ 0=>"000000",
+ 1=>"001000",
+ 2=>"001000",
+ 3=>"001001",
+ 4=>"001010",
+ 5=>"001100",
+ 6=>"001010",
+ 7=>"001001",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $6C
+ 76 => (
+ 0=>"000000",
+ 1=>"001100",
+ 2=>"000100",
+ 3=>"000100",
+ 4=>"000100",
+ 5=>"000100",
+ 6=>"000100",
+ 7=>"001110",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $6D
+ 77 => (
+ 0=>"000000",
+ 1=>"000000",
+ 2=>"000000",
+ 3=>"011010",
+ 4=>"010101",
+ 5=>"010101",
+ 6=>"010101",
+ 7=>"010101",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $6E
+ 78 => (
+ 0=>"000000",
+ 1=>"000000",
+ 2=>"000000",
+ 3=>"011110",
+ 4=>"010001",
+ 5=>"010001",
+ 6=>"010001",
+ 7=>"010001",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $6F
+ 79 => (
+ 0=>"000000",
+ 1=>"000000",
+ 2=>"000000",
+ 3=>"001110",
+ 4=>"010001",
+ 5=>"010001",
+ 6=>"010001",
+ 7=>"001110",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $70
+ 80 => (
+ 0=>"000000",
+ 1=>"000000",
+ 2=>"000000",
+ 3=>"011110",
+ 4=>"010001",
+ 5=>"010001",
+ 6=>"010001",
+ 7=>"011110",
+ 8=>"010000",
+ 9=>"010000"
+ ),
+ -- $71
+ 81 => (
+ 0=>"000000",
+ 1=>"000000",
+ 2=>"000000",
+ 3=>"001111",
+ 4=>"010001",
+ 5=>"010001",
+ 6=>"010001",
+ 7=>"001111",
+ 8=>"000001",
+ 9=>"000001"
+ ),
+ -- $72
+ 82 => (
+ 0=>"000000",
+ 1=>"000000",
+ 2=>"000000",
+ 3=>"001011",
+ 4=>"001100",
+ 5=>"001000",
+ 6=>"001000",
+ 7=>"001000",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $73
+ 83 => (
+ 0=>"000000",
+ 1=>"000000",
+ 2=>"000000",
+ 3=>"001111",
+ 4=>"010000",
+ 5=>"001110",
+ 6=>"000001",
+ 7=>"011110",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $74
+ 84 => (
+ 0=>"000000",
+ 1=>"000100",
+ 2=>"000100",
+ 3=>"001110",
+ 4=>"000100",
+ 5=>"000100",
+ 6=>"000100",
+ 7=>"000010",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $75
+ 85 => (
+ 0=>"000000",
+ 1=>"000000",
+ 2=>"000000",
+ 3=>"010001",
+ 4=>"010001",
+ 5=>"010001",
+ 6=>"010001",
+ 7=>"001111",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $76
+ 86 => (
+ 0=>"000000",
+ 1=>"000000",
+ 2=>"000000",
+ 3=>"010001",
+ 4=>"010001",
+ 5=>"001010",
+ 6=>"001010",
+ 7=>"000100",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $77
+ 87 => (
+ 0=>"000000",
+ 1=>"000000",
+ 2=>"000000",
+ 3=>"010001",
+ 4=>"010001",
+ 5=>"010101",
+ 6=>"010101",
+ 7=>"001010",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $78
+ 88 => (
+ 0=>"000000",
+ 1=>"000000",
+ 2=>"000000",
+ 3=>"010001",
+ 4=>"001010",
+ 5=>"000100",
+ 6=>"001010",
+ 7=>"010001",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $79
+ 89 => (
+ 0=>"000000",
+ 1=>"000000",
+ 2=>"000000",
+ 3=>"010001",
+ 4=>"010001",
+ 5=>"010001",
+ 6=>"010001",
+ 7=>"001111",
+ 8=>"000001",
+ 9=>"001110"
+ ),
+ -- $7A
+ 90 => (
+ 0=>"000000",
+ 1=>"000000",
+ 2=>"000000",
+ 3=>"011111",
+ 4=>"000010",
+ 5=>"000100",
+ 6=>"001000",
+ 7=>"011111",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $7B
+ 91 => (
+ 0=>"000000",
+ 1=>"001000",
+ 2=>"001000",
+ 3=>"001000",
+ 4=>"001001",
+ 5=>"000011",
+ 6=>"000101",
+ 7=>"000111",
+ 8=>"000001",
+ 9=>"000000"
+ ),
+ -- $7C
+ 92 => (
+ 0=>"000000",
+ 1=>"001010",
+ 2=>"001010",
+ 3=>"001010",
+ 4=>"001010",
+ 5=>"001010",
+ 6=>"001010",
+ 7=>"001010",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $7D
+ 93 => (
+ 0=>"000000",
+ 1=>"011000",
+ 2=>"000100",
+ 3=>"011000",
+ 4=>"000100",
+ 5=>"011001",
+ 6=>"000011",
+ 7=>"000101",
+ 8=>"000111",
+ 9=>"000001"
+ ),
+ -- $7E
+ 94 => (
+ 0=>"000000",
+ 1=>"000000",
+ 2=>"000100",
+ 3=>"000000",
+ 4=>"011111",
+ 5=>"000000",
+ 6=>"000100",
+ 7=>"000000",
+ 8=>"000000",
+ 9=>"000000"
+ ),
+ -- $7F
+ 95 => (
+ 0=>"000000",
+ 1=>"011111",
+ 2=>"011111",
+ 3=>"011111",
+ 4=>"011111",
+ 5=>"011111",
+ 6=>"011111",
+ 7=>"011111",
+ 8=>"000000",
+ 9=>"000000"
+ )
+ );
+
+ signal ra : integer range 0 to 9;
+
+begin
+
+ -- generate row address
+ process (clk, reset)
+ variable glr_r : std_logic;
+ begin
+ if reset = '1' then
+ elsif rising_edge(clk) then
+ -- VSYNC, reset row address
+ if dew = '1' then
+ ra <= 0;
+ -- HYSNC, increment row address
+ elsif glr = '1' and glr_r = '0' then
+ if ra = 9 then
+ ra <= 0;
+ else
+ ra <= ra + 1;
+ end if;
+ end if;
+ glr_r := glr;
+ end if;
+ end process;
+
+ -- latch and output data
+ process (clk, reset)
+ variable char_row_data : std_logic_vector(5 downto 0);
+ begin
+ if reset = '1' then
+ null;
+ elsif rising_edge(clk) then
+ if f1 = '1' then
+ --latch data
+ if d(6 downto 5) = "00" then
+ char_row_data := (others => '0');
+ else
+ char_row_data := charset(conv_integer(d)-32)(ra);
+ end if;
+ elsif tr6 = '1' then
+ -- shift data
+ char_row_data := char_row_data(4 downto 0) & '0';
+ end if;
+ end if;
+ -- assign output
+ r <= char_row_data(char_row_data'left);
+ g <= char_row_data(char_row_data'left);
+ b <= char_row_data(char_row_data'left);
+ end process;
+
+ -- not supported
+ si_o <= 'X';
+ tlc_n <= 'X';
+ y <= 'X';
+ blan <= 'X';
+
+end SYN;
diff --git a/common/Video/tms9918a_bartlett/Copyright.txt b/common/Video/tms9918a_bartlett/Copyright.txt
new file mode 100644
index 00000000..7c8922f1
--- /dev/null
+++ b/common/Video/tms9918a_bartlett/Copyright.txt
@@ -0,0 +1,11 @@
+The files available in this directory were created by me and I claim ownership
+and copyright. I grant to anyone and everyone the right to download, use, modify
+and redistribute them freely so long as this notice is included with any
+redistribution, in whole or in part, whether modified or not.
+
+All files in this directory are provided as-is for no charge. There is no
+warranty, guarantee, or claim of suitability for any purpose. No offer of
+support or service has been or will be made.
+
+Peter J. Bartlett
+2012
diff --git a/common/Video/tms9918a_bartlett/Readme.txt b/common/Video/tms9918a_bartlett/Readme.txt
new file mode 100644
index 00000000..520f471f
--- /dev/null
+++ b/common/Video/tms9918a_bartlett/Readme.txt
@@ -0,0 +1,48 @@
+This is a preliminary Verilog implemenation of a replacement for the TMS9918A
+VDP. It outputs 800x600 VGA @ 60Hz, with each of the colors (R/G/B) having 4-bit
+resolution. It is (insofar as I know how to make it) compatible with the
+original VDP. It has a software selectable mode that allows all 32 sprites on
+one line, however.
+
+The only FPGA-specific module at this time is "vdp_clkgen" that uses an embedded
+PLL to convert the 50MHz clock on my development board to 40MHz. Either replace
+it with your FPGA's equivalent or simply use an external 40MHz oscillator.
+
+At the current resolution and clock frequency, I'm using this with an external
+Alliance 512KB SRAM with 55ns access time. The design has been pre-planned to
+work with 25ns SRAMs at 65 MHz or more for 1024x768 SVGA resolution.
+
+There are a number of major changes planned. For example the non-working copy of
+all the sprite data, some 960 flip-flops, will be replaced by an embedded RAM.
+The pattern shift registers will be greatly simplified as well.
+
+This Verilog was written from scratch in a 2-week period, so it's not well
+commented. On the bright side, it's free.
+
+Externally, I went with a "poor man's DAC" to convert the 4-bit R/G/B signals
+into 1.4V for VGA. I used an AD813 triple video op-amp in an inverting
+configuration with resistors (20K, 10K, 5K, 2.5K, a clever young lad can
+imagine how to do that with few parts) on the minus input, a 1K
+potentiometer on the feedback path, and a 75 ohm series resistor on the
+output. Works perfectly.
+
+---
+
+Update: all planned TMS9918 emulation changes are in. The internal RAM is 256
+x 8-bit words, synchronous inputs and outputs. Making this change reduced
+utilization of the (rather small) Cyclone II FPGA I'm using from 76% to 46%.
+
+In order to enable "unlimited sprites per line" mode, set bit 0 of register 31.
+
+I'll probably be going forward with adding features of the V9938 VDP to the
+design such as 512 pixel width and 80-column text modes (using 1024x768 XVGA),
+but I won't be posting any of that here since it goes beyond the scope of
+recreating a historical TRS-80 peripheral device--the Mikrokolor.
+
+Pete.
+
+---
+
+By the way, I don't like the way the tabs in the Verilog files got converted; they were originally 3 spaces each.
+
+p.
diff --git a/common/Video/tms9918a_bartlett/vdp.sdc b/common/Video/tms9918a_bartlett/vdp.sdc
new file mode 100644
index 00000000..f2fee5e7
--- /dev/null
+++ b/common/Video/tms9918a_bartlett/vdp.sdc
@@ -0,0 +1,30 @@
+set_time_format -unit ns -decimal_places 3
+
+create_clock -name {clk50m_17} -period 20.000 -waveform { 0.000 10.000 } [get_ports {clk50m_17}]
+create_generated_clock -name {clkgen|altpll_component|pll|clk[0]} -source [get_pins {clkgen|altpll_component|pll|inclk[0]}] -duty_cycle 50.000 -multiply_by 4 -divide_by 5 -master_clock {clk50m_17} [get_pins {clkgen|altpll_component|pll|clk[0]}]
+
+set_false_path -from [get_ports {cpu_a[*] cpu_d[*] cpu_in_n cpu_out_n cpu_rst_n por_73_n push_144_n}] \
+ -to [get_clocks {clkgen|altpll_component|pll|clk[0]}]
+
+set_false_path -from [get_ports {cpu_a[*]}] -to [get_ports {cpu_d[*]}]
+
+set_false_path -from [get_registers {vdp_cpu:cpu|spr_mag vdp_cpu:cpu|spr_size}] \
+ -to [get_registers {vdp_fsm:fsm|spr_color[*] vdp_fsm:fsm|spr_pattern vdp_fsm:fsm|spr_collide \
+ vdp_fsm:fsm|spr_pat[*][*] vdp_fsm:fsm|spr_xvld[*] vdp_fsm:fsm|spr_odd[*]}]
+
+set_false_path -to [get_ports {led1_3_n led2_7_n led3_9_n}]
+set_false_path -from [get_ports {push_144_n por_73_n cpu_rst_n}]
+
+set_multicycle_path -setup -end -from [get_registers {vdp_fsm:fsm|spr_hcount[*] vdp_fsm:fsm|spr_col[*][*]}] \
+ -to [get_registers {vdp_fsm:fsm|spr_color[*] vdp_fsm:fsm|spr_pattern vdp_fsm:fsm|spr_collide vdp_fsm:fsm|spr_pat[*][*]}] 3
+set_multicycle_path -hold -end -from [get_registers {vdp_fsm:fsm|spr_hcount[*] vdp_fsm:fsm|spr_col[*][*]}] \
+ -to [get_registers {vdp_fsm:fsm|spr_color[*] vdp_fsm:fsm|spr_pattern vdp_fsm:fsm|spr_collide vdp_fsm:fsm|spr_pat[*][*]}] 3
+set_multicycle_path -setup -end -from [get_registers {vdp_fsm:fsm|spr_dly[*][*] vdp_fsm:fsm|spr_pat[*][*] vdp_fsm:fsm|spr_vld[*]}] \
+ -to [get_registers {vdp_fsm:fsm|spr_color[*] vdp_fsm:fsm|spr_pattern vdp_fsm:fsm|spr_collide vdp_fsm:fsm|spr_pat[*][*]}] 3
+set_multicycle_path -hold -end -from [get_registers {vdp_fsm:fsm|spr_dly[*][*] vdp_fsm:fsm|spr_pat[*][*] vdp_fsm:fsm|spr_vld[*]}] \
+ -to [get_registers {vdp_fsm:fsm|spr_color[*] vdp_fsm:fsm|spr_pattern vdp_fsm:fsm|spr_collide vdp_fsm:fsm|spr_pat[*][*]}] 3
+
+set_max_delay -from [get_clocks {clkgen|altpll_component|pll|clk[0]}] -to [get_ports {b[*] g[*] r[*] hsync vsync}] 5.000
+set_max_delay -from [get_clocks {clkgen|altpll_component|pll|clk[0]}] -to [get_ports {sram_a[*] sram_d[*] sram_oe_n sram_we_n}] 5.000
+set_max_delay -from [get_clocks {clkgen|altpll_component|pll|clk[0]}] -to [get_ports {cpu_int_n}] 8.000
+set_max_delay -from [get_ports {sram_d[*]}] -to [get_clocks {clkgen|altpll_component|pll|clk[0]}] 3.000
diff --git a/common/Video/tms9918a_bartlett/vdp.v b/common/Video/tms9918a_bartlett/vdp.v
new file mode 100644
index 00000000..53e84e4e
--- /dev/null
+++ b/common/Video/tms9918a_bartlett/vdp.v
@@ -0,0 +1,241 @@
+module vdp(
+ clk40m,
+ clk40m_n,
+ cpu_rst_n,
+ cpu_a,
+ cpu_din,
+ cpu_dout,
+ cpu_doe,
+ cpu_in_n,
+ cpu_out_n,
+ cpu_int_n,
+ sram_a,
+ sram_din,
+ sram_dout,
+ sram_doe,
+ sram_oe_n,
+ sram_we_n,
+ hsync,
+ vsync,
+ r,
+ g,
+ b
+);
+
+ // Clocks
+ input clk40m;
+ input clk40m_n;
+
+ // CPU interface
+ input cpu_rst_n;
+ input [ 7 : 0 ] cpu_a;
+ input [ 7 : 0 ] cpu_din;
+ output [ 7 : 0 ] cpu_dout;
+ output cpu_doe;
+ input cpu_in_n;
+ input cpu_out_n;
+ output cpu_int_n;
+
+ // SRAM interface
+ output [ 18 : 0 ] sram_a;
+ input [ 7 : 0 ] sram_din;
+ output [ 7 : 0 ] sram_dout;
+ output sram_doe;
+ output sram_oe_n;
+ output sram_we_n;
+
+ // VGA interface
+ output hsync; // Horizontal sync
+ output vsync; // Vertical sync
+ output [ 3 : 0 ] r;
+ output [ 3 : 0 ] g;
+ output [ 3 : 0 ] b;
+
+ // VDP I/O ports.
+ parameter [ 7 : 0 ] cpu_vram_port = 8'h01;
+ parameter [ 7 : 0 ] cpu_vdp_port = 8'h02;
+
+ wire rst_n;
+
+ wire vram_cpu_req;
+ wire vram_cpu_ack;
+ wire vram_cpu_wr;
+ wire vram_ack;
+ wire [ 13 : 0 ] vram_cpu_a;
+ wire [ 7 : 0 ] vram_cpu_rdata;
+
+ wire [ 7 : 0 ] vram_rdata;
+
+ wire g1_mode;
+ wire g2_mode;
+ wire multi_mode;
+ wire text_mode;
+ wire gmode;
+ wire blank_n;
+ wire spr_size;
+ wire spr_mag;
+ wire [ 3 : 0 ] ntb;
+ wire [ 7 : 0 ] colb;
+ wire [ 2 : 0 ] pgb;
+ wire [ 6 : 0 ] sab;
+ wire [ 2 : 0 ] spgb;
+ wire [ 3 : 0 ] color1;
+ wire [ 3 : 0 ] color0;
+
+ wire visible;
+ wire border;
+ wire start_vblank;
+ wire set_mode;
+ wire vram_req;
+ wire vram_wr;
+ wire [ 13 : 0 ] vram_addr;
+
+ wire [ 7 : 0 ] pattern;
+ wire [ 7 : 0 ] color;
+ wire load;
+ wire [ 3 : 0 ] color_1;
+ wire [ 3 : 0 ] color_0;
+ wire pixel;
+
+ wire spr_pattern;
+ wire [ 3 : 0 ] spr_color;
+ wire spr_collide;
+ wire spr_5;
+ wire [ 4 : 0 ] spr_5num;
+ wire spr_nolimit;
+
+ assign rst_n = cpu_rst_n;
+
+ assign sram_a[ 18 : 14 ] = 5'b00000;
+
+ vdp_colormap colormap(
+ clk40m,
+ rst_n,
+ visible,
+ border,
+ pixel,
+ color_1,
+ color_0,
+ color0,
+ spr_pattern,
+ spr_color,
+ r,
+ g,
+ b
+ );
+
+ vdp_shift shift(
+ clk40m,
+ rst_n,
+ pattern,
+ color,
+ color1,
+ color0,
+ load,
+ text_mode,
+ color_1,
+ color_0,
+ pixel
+ );
+
+ vdp_fsm fsm(
+ clk40m,
+ rst_n,
+ g1_mode,
+ g2_mode,
+ multi_mode,
+ gmode,
+ text_mode,
+ spr_size,
+ spr_mag,
+ blank_n,
+ ntb,
+ colb,
+ pgb,
+ sab,
+ spgb,
+ hsync,
+ vsync,
+ start_vblank,
+ set_mode,
+ visible,
+ border,
+ vram_req,
+ vram_wr,
+ vram_ack,
+ vram_addr,
+ vram_rdata,
+ vram_cpu_req,
+ vram_cpu_wr,
+ vram_cpu_ack,
+ vram_cpu_a,
+ pattern,
+ color,
+ load,
+ spr_pattern,
+ spr_color,
+ spr_collide,
+ spr_5,
+ spr_5num,
+ spr_nolimit
+ );
+
+ // SRAM interface.
+ vdp_sram sram(
+ clk40m,
+ clk40m_n,
+ rst_n,
+ vram_req,
+ vram_wr,
+ vram_ack,
+ vram_addr,
+ vram_rdata,
+ sram_a[ 13 : 0 ],
+ sram_din,
+ sram_doe,
+ sram_oe_n,
+ sram_we_n
+ );
+
+ // CPU interface.
+ vdp_cpu cpu(
+ clk40m,
+ rst_n,
+ cpu_vram_port,
+ cpu_vdp_port,
+ cpu_a,
+ cpu_din,
+ cpu_dout,
+ cpu_doe,
+ cpu_in_n,
+ cpu_out_n,
+ cpu_int_n,
+ vram_cpu_req,
+ vram_cpu_ack,
+ vram_cpu_wr,
+ vram_cpu_a,
+ sram_dout,
+ vram_rdata,
+ g1_mode,
+ g2_mode,
+ multi_mode,
+ text_mode,
+ gmode,
+ blank_n,
+ spr_size,
+ spr_mag,
+ ntb,
+ colb,
+ pgb,
+ sab,
+ spgb,
+ color1,
+ color0,
+ spr_nolimit,
+ spr_collide,
+ spr_5,spr_5num,
+ start_vblank,
+ set_mode
+ );
+
+endmodule
diff --git a/common/Video/tms9918a_bartlett/vdp_colormap.v b/common/Video/tms9918a_bartlett/vdp_colormap.v
new file mode 100644
index 00000000..673e08b2
--- /dev/null
+++ b/common/Video/tms9918a_bartlett/vdp_colormap.v
@@ -0,0 +1,168 @@
+module vdp_colormap(
+ clk,
+ rst_n,
+ visible,
+ border,
+ pattern,
+ color1,
+ color0,
+ bgcolor,
+ spr_pat,
+ spr_color,
+ r,
+ g,
+ b
+);
+
+ input clk;
+ input rst_n;
+ input visible;
+ input border;
+ input pattern;
+ input [ 3 : 0 ] color1;
+ input [ 3 : 0 ] color0;
+ input [ 3 : 0 ] bgcolor;
+ input spr_pat;
+ input [ 3 : 0 ] spr_color;
+ output [ 3 : 0 ] r;
+ output [ 3 : 0 ] g;
+ output [ 3 : 0 ] b;
+
+`define TRANSPARENT 0
+`define BLACK 1
+`define MEDIUM_GREEN 2
+`define LIGHT_GREEN 3
+`define DARK_BLUE 4
+`define LIGHT_BLUE 5
+`define DARK_RED 6
+`define CYAN 7
+`define MEDIUM_RED 8
+`define LIGHT_RED 9
+`define DARK_YELLOW 10
+`define LIGHT_YELLOW 11
+`define DARK_GREEN 12
+`define MAGENTA 13
+`define GRAY 14
+`define WHITE 15
+
+ reg [ 3 : 0 ] colorsel;
+ always @( visible or border or bgcolor
+ or spr_pat or spr_color
+ or pattern or color1 or color0 ) begin
+ colorsel = `TRANSPARENT;
+ if( !visible ) begin
+ colorsel = `BLACK;
+ end else if( border ) begin
+ colorsel = bgcolor;
+ end else if( spr_pat && spr_color != `TRANSPARENT ) begin
+ colorsel = spr_color;
+ end else if( pattern ) begin
+ colorsel = color1;
+ end else begin
+ colorsel = color0;
+ end
+ if( colorsel == `TRANSPARENT ) begin
+ colorsel = bgcolor;
+ end
+ end
+
+ reg [ 3 : 0 ] red;
+ reg [ 3 : 0 ] green;
+ reg [ 3 : 0 ] blue;
+ always @( colorsel ) begin
+ case( colorsel )
+ `TRANSPARENT, `BLACK: begin
+ red <= 0;
+ green <= 0;
+ blue <= 0;
+ end
+ `MEDIUM_GREEN: begin
+ red <= 3;
+ green <= 13;
+ blue <= 3;
+ end
+ `LIGHT_GREEN: begin
+ red <= 7;
+ green <= 15;
+ blue <= 7;
+ end
+ `DARK_BLUE: begin
+ red <= 3;
+ green <= 3;
+ blue <= 15;
+ end
+ `LIGHT_BLUE: begin
+ red <= 5;
+ green <= 7;
+ blue <= 15;
+ end
+ `DARK_RED: begin
+ red <= 11;
+ green <= 3;
+ blue <= 3;
+ end
+ `CYAN: begin
+ red <= 5;
+ green <= 13;
+ blue <= 15;
+ end
+ `MEDIUM_RED: begin
+ red <= 15;
+ green <= 3;
+ blue <= 3;
+ end
+ `LIGHT_RED: begin
+ red <= 15;
+ green <= 7;
+ blue <= 7;
+ end
+ `DARK_YELLOW: begin
+ red <= 13;
+ green <= 13;
+ blue <= 3;
+ end
+ `LIGHT_YELLOW: begin
+ red <= 13;
+ green <= 13;
+ blue <= 9;
+ end
+ `DARK_GREEN: begin
+ red <= 3;
+ green <= 9;
+ blue <= 3;
+ end
+ `MAGENTA: begin
+ red <= 13;
+ green <= 5;
+ blue <= 11;
+ end
+ `GRAY: begin
+ red <= 11;
+ green <= 11;
+ blue <= 11;
+ end
+ `WHITE: begin
+ red <= 15;
+ green <= 15;
+ blue <= 15;
+ end
+ endcase
+ end
+
+ reg [ 3 : 0 ] r;
+ reg [ 3 : 0 ] g;
+ reg [ 3 : 0 ] b;
+ always @( negedge rst_n or posedge clk ) begin
+ if( !rst_n ) begin
+ r <= 4'hF;
+ g <= 4'hF;
+ b <= 4'hF;
+ end else begin
+ // For inverting DAC.
+ r <= ~red;
+ g <= ~green;
+ b <= ~blue;
+ end
+ end
+
+endmodule
diff --git a/common/Video/tms9918a_bartlett/vdp_cpu.v b/common/Video/tms9918a_bartlett/vdp_cpu.v
new file mode 100644
index 00000000..63966a82
--- /dev/null
+++ b/common/Video/tms9918a_bartlett/vdp_cpu.v
@@ -0,0 +1,333 @@
+module vdp_cpu(
+ clk40m,
+ rst_n,
+ cpu_vram_port,
+ cpu_vdp_port,
+ cpu_a,
+ cpu_din,
+ cpu_dout,
+ cpu_doe,
+ cpu_in_n,
+ cpu_out_n,
+ cpu_int_n,
+ vram_cpu_req,
+ vram_cpu_ack,
+ vram_cpu_wr,
+ vram_cpu_a,
+ vram_cpu_wdata,
+ vram_cpu_rdata,
+ g1_mode,
+ g2_mode,
+ multi_mode,
+ text_mode,
+ gmode,
+ blank_n,
+ spr_size,
+ spr_mag,
+ ntb,
+ colb,
+ pgb,
+ sab,
+ spgb,
+ color1,
+ color0,
+ spr_nolimit,
+ spr_collide,
+ spr_5,
+ spr_5num,
+ start_vblank,
+ set_mode
+);
+
+ input clk40m;
+
+ input rst_n;
+ input [ 7 : 0 ] cpu_vram_port;
+ input [ 7 : 0 ] cpu_vdp_port;
+ input [ 7 : 0 ] cpu_a;
+ input [ 7 : 0 ] cpu_din;
+ output [ 7 : 0 ] cpu_dout;
+ output cpu_doe;
+ input cpu_in_n;
+ input cpu_out_n;
+ output cpu_int_n;
+
+ output vram_cpu_req;
+ input vram_cpu_ack;
+ output vram_cpu_wr;
+ output [ 13 : 0 ] vram_cpu_a;
+ output [ 7 : 0 ] vram_cpu_wdata;
+ input [ 7 : 0 ] vram_cpu_rdata;
+
+ output g1_mode;
+ output g2_mode;
+ output multi_mode;
+ output text_mode;
+ output gmode;
+ output blank_n;
+ output spr_size;
+ output spr_mag;
+ output [ 3 : 0 ] ntb;
+ output [ 7 : 0 ] colb;
+ output [ 2 : 0 ] pgb;
+ output [ 6 : 0 ] sab;
+ output [ 2 : 0 ] spgb;
+ output [ 3 : 0 ] color1;
+ output [ 3 : 0 ] color0;
+ output spr_nolimit;
+
+ input spr_collide;
+ input spr_5;
+ input [ 4 : 0 ] spr_5num;
+ input start_vblank;
+ input set_mode;
+
+ wire in_sel = !cpu_in_n && ( cpu_a == cpu_vram_port || cpu_a == cpu_vdp_port );
+ wire out_sel = !cpu_out_n && ( cpu_a == cpu_vram_port || cpu_a == cpu_vdp_port );
+ wire mode = ( cpu_a == cpu_vdp_port );
+
+ // Synchronize CPU interface.
+ reg in_1, in_2, in_3;
+ reg out_1, out_2, out_3;
+ always @( negedge rst_n or posedge clk40m ) begin
+ if( !rst_n ) begin
+ in_1 <= 0;
+ in_2 <= 0;
+ in_3 <= 0;
+ out_1 <= 0;
+ out_2 <= 0;
+ out_3 <= 0;
+ end else begin
+ in_1 <= in_sel;
+ in_2 <= in_1;
+ in_3 <= in_2;
+ out_1 <= out_sel;
+ out_2 <= out_1;
+ out_3 <= out_2;
+ end
+ end
+
+ wire cpu_wr = out_2 && !out_3;
+ wire cpu_rd = !in_2 && in_3; // After CPU has read data.
+
+ // Freeze status register at beginning of read.
+ // Must be sure what value of flags the CPU sees for auto-clearing.
+ // spr_5 must always correspond to spr_5num.
+ reg stat_f, stat_c, stat_5;
+ reg [ 4 : 0 ] stat_5num;
+ reg [ 7 : 0 ] stat;
+ always @( posedge clk40m ) begin
+ if( in_2 && !in_3 ) begin
+ stat <= { stat_f, stat_c, stat_5, stat_5num };
+ end
+ end
+
+ // Interrupt status.
+ always @( negedge rst_n or posedge clk40m ) begin
+ if( !rst_n ) begin
+ stat_f <= 0;
+ stat_c <= 0;
+ stat_5 <= 0;
+ end else if( start_vblank ) begin
+ stat_f <= 1;
+ stat_c <= spr_collide;
+ stat_5 <= spr_5;
+ stat_5num <= spr_5num;
+ end else if( cpu_rd && mode ) begin
+ stat_f <= 0;
+ stat_c <= 0;
+ stat_5 <= 0;
+ end
+ end
+
+ // Register fields.
+ reg xm3, xm2, xm1;
+ reg xblank_n;
+ reg ien;
+ reg xspr_size;
+ reg xspr_mag;
+ reg [ 3 : 0 ] ntb;
+ reg [ 7 : 0 ] colb;
+ reg [ 2 : 0 ] pgb;
+ reg [ 6 : 0 ] sab;
+ reg [ 2 : 0 ] spgb;
+ reg [ 3 : 0 ] color1;
+ reg [ 3 : 0 ] color0;
+
+ // Added (nonstandard) functions.
+ reg xspr_nolimit;
+
+ // Capture CPU write data.
+ reg cpu_byte2;
+ reg [ 7 : 0 ] vram_cpu_wdata;
+ always @( negedge rst_n or posedge clk40m ) begin
+ if( !rst_n ) begin
+ cpu_byte2 <= 0;
+ xm3 <= 0;
+ xm2 <= 0;
+ xm1 <= 0;
+ xblank_n <= 0;
+ ien <= 0;
+ xspr_size <= 0;
+ xspr_mag <= 0;
+ xspr_nolimit <= 0;
+ ntb <= 0;
+ colb <= 0;
+ pgb <= 0;
+ sab <= 0;
+ spgb <= 0;
+ color1 <= 0;
+ color0 <= 0;
+ end else begin
+ if( cpu_wr ) begin
+ if( mode ) begin
+ if( cpu_byte2 ) begin
+ if( cpu_din[ 7 ] ) begin
+ if( cpu_din[ 6 ] == 1'b0 ) begin
+ // Register write.
+ case( cpu_din[ 5 : 0 ] )
+ 0: begin
+ xm3 <= vram_cpu_a[ 1 ];
+ end
+ 1: begin
+ xspr_mag <= vram_cpu_a[ 0 ];
+ xspr_size <= vram_cpu_a[ 1 ];
+ xm2 <= vram_cpu_a[ 3 ];
+ xm1 <= vram_cpu_a[ 4 ];
+ ien <= vram_cpu_a[ 5 ];
+ xblank_n <= vram_cpu_a[ 6 ];
+ end
+ 2: begin
+ ntb <= vram_cpu_a[ 3 : 0 ];
+ end
+ 3: begin
+ colb <= vram_cpu_a[ 7 : 0 ];
+ end
+ 4: begin
+ pgb <= vram_cpu_a[ 2 : 0 ];
+ end
+ 5: begin
+ sab <= vram_cpu_a[ 6 : 0 ];
+ end
+ 6: begin
+ spgb <= vram_cpu_a[ 2 : 0 ];
+ end
+ 7: begin
+ color1 <= vram_cpu_a[ 7 : 4 ];
+ color0 <= vram_cpu_a[ 3 : 0 ];
+ end
+ 31: begin
+ xspr_nolimit <= vram_cpu_a[ 0 ];
+ end
+ default: begin
+ end
+ endcase
+ end
+ end
+ end
+ cpu_byte2 <= !cpu_byte2;
+ end else begin
+ // VRAM write (malformed if cpu_byte2, but do it anyway).
+ vram_cpu_wdata <= cpu_din;
+ cpu_byte2 <= 0;
+ end
+ end else if( cpu_rd ) begin
+ cpu_byte2 <= 0;
+ end
+ end
+ end
+
+ // Certain register bits mustn't change mid-screen.
+ reg g1_mode;
+ reg g2_mode;
+ reg multi_mode;
+ reg text_mode;
+ reg gmode; // Any valid graphics mode.
+ reg spr_size;
+ reg spr_mag;
+ reg spr_nolimit;
+ reg blank_n;
+ always @( negedge rst_n or posedge clk40m ) begin
+ if( !rst_n ) begin
+ g1_mode <= 1;
+ g2_mode <= 0;
+ multi_mode <= 0;
+ text_mode <= 0;
+ gmode <= 1;
+ spr_size <= 0;
+ spr_mag <= 0;
+ spr_nolimit <= 0;
+ blank_n <= 0;
+ end else if( set_mode ) begin
+ g1_mode <= ( { xm1, xm2, xm3 } == 3'b000 );
+ g2_mode <= ( { xm1, xm2, xm3 } == 3'b001 );
+ multi_mode <= ( { xm1, xm2, xm3 } == 3'b010 );
+ text_mode <= ( { xm1, xm2, xm3 } == 3'b100 );
+ gmode <= !xm1;
+ spr_size <= xspr_size;
+ spr_mag <= xspr_mag;
+ spr_nolimit <= xspr_nolimit;
+ blank_n <= xblank_n;
+ end
+ end
+
+ wire set_addr_lsb = cpu_wr && mode && !cpu_byte2;
+ wire set_addr_msb = cpu_wr && mode && cpu_byte2 && !cpu_din[ 7 ];
+
+ // VRAM CPU access state machine.
+ reg [ 13 : 0 ] vram_cpu_a;
+ reg [ 7 : 0 ] vram_rdata;
+ reg vram_cpu_req;
+ reg vram_cpu_wr;
+ reg addr_mod;
+ wire start_req = ( ( cpu_wr || cpu_rd ) && !mode && ( !vram_cpu_req || vram_cpu_ack ) )
+ || ( set_addr_msb && !cpu_din[ 6 ] && ( !vram_cpu_req || vram_cpu_ack ) );
+ wire start_wr = !mode && cpu_wr;
+ always @( negedge rst_n or posedge clk40m ) begin
+ if( !rst_n ) begin
+ vram_cpu_a <= 0;
+ vram_rdata <= 0;
+ vram_cpu_req <= 0;
+ vram_cpu_wr <= 0;
+ addr_mod <= 0;
+ end else begin
+ if( vram_cpu_req && vram_cpu_ack ) begin
+ if( !start_req ) begin
+ vram_cpu_req <= 0;
+ end
+ if( !addr_mod && !set_addr_lsb && !set_addr_msb ) begin
+ // Auto-increment CPU VRAM address.
+ vram_cpu_a <= vram_cpu_a + 1'b1;
+ end
+ addr_mod <= 0;
+ if( !vram_cpu_wr ) begin
+ vram_rdata <= vram_cpu_rdata;
+ end
+ end
+ if( start_req ) begin
+ vram_cpu_req <= 1;
+ vram_cpu_wr <= start_wr;
+ end
+ if( set_addr_lsb ) begin
+ if( vram_cpu_req && !vram_cpu_ack ) begin
+ addr_mod <= 1;
+ end
+ vram_cpu_a[ 7 : 0 ] <= cpu_din;
+ end
+ if( set_addr_msb ) begin
+ if( vram_cpu_req && !vram_cpu_ack ) begin
+ addr_mod <= 1;
+ end
+ vram_cpu_a[ 13 : 8 ] <= cpu_din[ 5 : 0 ];
+ end
+ end
+ end
+
+ // CPU read data.
+ assign cpu_dout = ( mode ? stat : vram_rdata );
+ assign cpu_doe = in_sel;
+
+ // CPU interrupt.
+ assign cpu_int_n = ( stat_f && ien ) ? 1'b0 : 1'bZ;
+
+endmodule
diff --git a/common/Video/tms9918a_bartlett/vdp_fsm.v b/common/Video/tms9918a_bartlett/vdp_fsm.v
new file mode 100644
index 00000000..ebf805c3
--- /dev/null
+++ b/common/Video/tms9918a_bartlett/vdp_fsm.v
@@ -0,0 +1,633 @@
+module vdp_fsm(
+ clk40m,
+ rst_n,
+ g1_mode,
+ g2_mode,
+ multi_mode,
+ gmode,
+ text_mode,
+ spr_size,
+ spr_mag,
+ blank_n,
+ ntb,
+ colb,
+ pgb,
+ sab,
+ spgb,
+ hsync,
+ vsync,
+ start_vblank,
+ set_mode,
+ visible,
+ border,
+ vram_req,
+ vram_wr,
+ vram_ack,
+ vram_addr,
+ vram_rdata,
+ vram_cpu_req,
+ vram_cpu_wr,
+ vram_cpu_ack,
+ vram_cpu_a,
+ pattern,
+ color,
+ load,
+ spr_pattern,
+ spr_color,
+ spr_collide,
+ spr_5,
+ spr_5num,
+ spr_nolimit
+);
+
+ input clk40m;
+ input rst_n;
+
+ input g1_mode;
+ input g2_mode;
+ input multi_mode;
+ input gmode;
+ input text_mode;
+ input spr_size;
+ input spr_mag;
+ input blank_n;
+
+ input [ 3 : 0 ] ntb;
+ input [ 7 : 0 ] colb;
+ input [ 2 : 0 ] pgb;
+ input [ 6 : 0 ] sab;
+ input [ 2 : 0 ] spgb;
+
+ output hsync;
+ output vsync;
+ output start_vblank;
+ output set_mode;
+ output visible;
+ output border;
+
+ output vram_req;
+ output vram_wr;
+ input vram_ack;
+ output [ 13 : 0 ] vram_addr;
+ input [ 7 : 0 ] vram_rdata;
+ input vram_cpu_req;
+ input vram_cpu_wr;
+ output vram_cpu_ack;
+ input [ 13 : 0 ] vram_cpu_a;
+
+ output [ 7 : 0 ] pattern;
+ output [ 7 : 0 ] color;
+ output load;
+
+ output spr_pattern;
+ output [ 3 : 0 ] spr_color;
+ output spr_collide;
+ output spr_5;
+ output [ 4 : 0 ] spr_5num;
+ input spr_nolimit;
+
+ // 800x600 @ 60 Hz SVGA, pixel frequency = 40 MHz, +HSYNC, +VSYNC.
+ // H: 800 active, 40 front porch, 128 sync, 88 back porch = 1056 pixel clocks per line.
+ // V: 600 active, 1 front porch, 4 sync, 23 back porch = 628 lines.
+ // TMS9918A pixels are 3x3 SVGA pixels each (768x576 visible non-border).
+`define H_ACT 800
+`define H_FP 40
+`define H_SYNC 128
+`define H_BP 88
+`define H_WIDTH `H_ACT+`H_FP+`H_SYNC+`H_BP
+`define V_ACT 600
+`define V_FP 1
+`define V_SYNC 4
+`define V_BP 23
+`define V_HEIGHT `V_ACT+`V_FP+`V_SYNC+`V_BP
+ reg [ 10 : 0 ] h;
+ reg [ 9 : 0 ] v;
+ reg hsync;
+ reg vsync;
+ reg start_vblank;
+ reg line_end;
+ reg set_mode;
+ reg visible;
+ always @( negedge rst_n or posedge clk40m ) begin
+ if( !rst_n ) begin
+ h <= 0;
+ v <= 0;
+ hsync <= 0;
+ vsync <= 0;
+ start_vblank <= 0;
+ line_end <= 0;
+ set_mode <= 0;
+ visible <= 1;
+ end else begin
+ hsync <= ( h >= `H_ACT+`H_FP-1 && h < `H_ACT+`H_FP+`H_SYNC-1 );
+ line_end <= ( h == `H_WIDTH-2 );
+ set_mode <= ( h == `H_WIDTH-3 ) && ( v == `V_HEIGHT-1 );
+ start_vblank <= ( h == `H_WIDTH-2 ) && ( v == `V_ACT-1 );
+ visible <= ( h >= `H_WIDTH-2 && ( v == `V_HEIGHT-1 || v < `V_ACT-1 ) )
+ || ( h < `H_ACT-2 && v <= `V_ACT-1 );
+ if( line_end ) begin
+ h <= 0;
+ if( v >= `V_ACT+`V_FP-1 && v < `V_ACT+`V_FP+`V_SYNC-1 ) begin
+ vsync <= 1;
+ end else begin
+ vsync <= 0;
+ end
+ if( v == `V_HEIGHT-1 ) begin
+ v <= 0;
+ end else begin
+ v <= v + 1'b1;
+ end
+ end else begin
+ h <= h + 1'b1;
+ end
+ end
+ end
+
+`define BORD_TOP 12
+`define BORD_BOT 12
+ reg [ 1 : 0 ] vrep; // Vertical line repeat x3.
+ reg [ 7 : 0 ] scan_line; // Active scan line, 0-191+.
+ reg [ 7 : 0 ] scan_next; // Scan line + 1.
+ always @( negedge rst_n or posedge clk40m ) begin
+ if( !rst_n ) begin
+ vrep <= 0;
+ scan_line <= 192;
+ scan_next <= 193;
+ end else if( line_end ) begin
+ if( v == `BORD_TOP-4 ) begin
+ // For sprite setup vrep must be valid for 3 scan lines before active region.
+ vrep <= 0;
+ scan_line <= 8'hFF; // Bit 3 must be odd for sprites.
+ scan_next <= 0;
+ end else if( vrep == 2 ) begin
+ vrep <= 0;
+ scan_line <= scan_next;
+ scan_next <= scan_next + 1'b1;
+ end else begin
+ vrep <= vrep + 1'b1;
+ end
+ end
+ end
+
+ wire [ 2 : 0 ] line = scan_line[ 2 : 0 ]; // Scan line within pattern, 0-7.
+ wire [ 5 : 0 ] multi_row = scan_line[ 7 : 2 ]; // Multicolor block row, 0-47.
+ wire [ 4 : 0 ] row = scan_line[ 7 : 3 ]; // Pattern row, 0-23.
+
+ // Border delineation.
+ // Top and bottom borders are 12 SVGA lines each.
+ // In text mode, left and right borders are 40 SVGA pixels each.
+ // In graphics modes, left and right borders are 16 SVGA pixels each.
+`define BORD_GRAPH 16
+`define BORD_TEXT 40
+ reg border;
+ always @( negedge rst_n or posedge clk40m ) begin
+ if( !rst_n ) begin
+ border <= 1;
+ end else if( v < `BORD_TOP || v >= `V_ACT-`BORD_BOT ) begin
+ border <= 1;
+ end else if( blank_n && text_mode ) begin
+ border <= !( h >= `BORD_TEXT-2 && h < `H_ACT-`BORD_TEXT-2 );
+ end else if( blank_n && gmode ) begin
+ border <= !( h >= `BORD_GRAPH-2 && h < `H_ACT-`BORD_GRAPH-2 );
+ end else begin
+ border <= 1;
+ end
+ end
+
+ // Horizontal pattern counter, all modes.
+ wire ghnext, thnext;
+ reg [ 5 : 0 ] col;
+ always @( negedge rst_n or posedge clk40m ) begin
+ if( !rst_n ) begin
+ col <= 0;
+ end else if( line_end ) begin
+ col <= 0;
+ end else if( ghnext || thnext ) begin
+ col <= col + 1'b1;
+ end
+ end
+
+ // Graphics modes horizontal counter.
+ reg [ 4 : 0 ] ghcount;
+ always @( negedge rst_n or posedge clk40m ) begin
+ if( !rst_n ) begin
+ ghcount <= 0;
+ end else if( line_end || ghnext || !gmode ) begin
+ ghcount <= 0;
+ end else begin
+ ghcount <= ghcount + 1'b1;
+ end
+ end
+
+ assign ghnext = ( ghcount == 23 );
+ wire ghload = ( ghcount == 14 );
+
+ // Text mode horizontal counter.
+ reg [ 4 : 0 ] thcount;
+ reg [ 9 : 0 ] text_pos; // 40*pattern row + column.
+ reg [ 9 : 0 ] save_pos;
+ always @( negedge rst_n or posedge clk40m ) begin
+ if( !rst_n ) begin
+ thcount <= 0;
+ text_pos <= 0;
+ save_pos <= 0;
+ end else if( !text_mode ) begin
+ thcount <= 0;
+ end else if( line_end ) begin
+ thcount <= 0;
+ if( v == `BORD_TOP-1 ) begin
+ text_pos <= 0;
+ save_pos <= 0;
+ end else if( vrep != 2 || line != 7 ) begin
+ // For 23 additional lines in text row, restore text position.
+ text_pos <= save_pos;
+ end else begin
+ save_pos <= text_pos;
+ end
+ end else if( thnext ) begin
+ thcount <= 0;
+ text_pos <= text_pos + 1'b1;
+ end else if( thcount == 3 && ( h < 24 || h >= 744 || v < `BORD_TOP || v >= `V_ACT-`BORD_BOT ) ) begin
+ // Allow more CPU accesses during non-active time.
+ thcount <= 0;
+ end else begin
+ thcount <= thcount + 1'b1;
+ end
+ end
+
+ assign thnext = ( thcount == 17 );
+ wire thload = ( thcount == 14 );
+
+ // Load pattern into pixel shifter.
+ assign load = ( ghload || thload );
+
+ reg [ 4 : 0 ] spr_num;
+ always @( vrep or col ) begin
+ spr_num = 5'hXX;
+ if( vrep == 0 ) begin
+ spr_num = { 1'b0, col[ 4 : 1 ] };
+ end else if( vrep == 1 ) begin
+ spr_num = { 1'b1, col[ 4 : 1 ] };
+ end else if( vrep == 2 ) begin
+ spr_num = col[ 4 : 0 ];
+ end
+ end
+
+ reg [ 31 : 0 ] spr_xvld;
+ reg spr_load;
+
+ // VRAM requests. Must be mutually exclusive and at least 4 clocks apart.
+ wire pre_gnreq = ( ghcount == 0 ) && ( col < 32 ) && gmode;
+ wire pre_gpreq = ( ghcount == 4 ) && ( col < 32 ) && gmode;
+ wire pre_gcreq = ( ghcount == 8 ) && ( col < 32 ) && ( g1_mode || g2_mode );
+ wire pre_gxreq = ( ghcount == 20 ) && gmode;
+
+ // Sprite data is read from VRAM during the three SVGA lines prior to the corresponding three VDP lines.
+ // Sprite 0 is read on v = 9,10,11 for the first active VDP line at v = 12,13,14.
+ // Sprite 31 is read on v = 582,583,584 for the last active VDP line at v = 585,586,587.
+ wire pre_svreq = ( ghcount == 12 ) && !col[ 0 ] && ( col < 32 )
+ && ( v > 8 ) && ( v < 585 ) && ( vrep == 0 || vrep == 1 )
+ && spr_load && blank_n && gmode;
+ wire pre_snreq = ( ghcount == 16 ) && !col[ 0 ] && ( col < 32 )
+ && ( v > 8 ) && ( v < 585 ) && ( vrep == 0 || vrep == 1 )
+ && spr_load && blank_n && gmode;
+ wire pre_sp0req = ( ghcount == 12 ) && col[ 0 ] && ( col < 32 )
+ && ( v > 8 ) && ( v < 585 ) && ( vrep == 0 || vrep == 1 )
+ && spr_xvld[ spr_num ] && blank_n && gmode;
+ wire pre_sp1req = ( ghcount == 16 ) && col[ 0 ] && ( col < 32 )
+ && ( v > 8 ) && ( v < 585 ) && ( vrep == 0 || vrep == 1 )
+ && spr_xvld[ spr_num ] && blank_n && gmode && spr_size;
+ wire pre_sareq = ( ghcount == 12 ) && ( col < 32 )
+ && ( v > 8 ) && ( v < 585 ) && vrep == 2
+ && spr_xvld[ spr_num ] && blank_n && gmode;
+ wire pre_shreq = ( ghcount == 16 ) && ( col < 32 )
+ && ( v > 8 ) && ( v < 585 ) && vrep == 2
+ && spr_xvld[ spr_num ] && blank_n && gmode;
+
+ wire pre_tnreq = ( thcount == 4 ) && text_mode;
+ wire pre_tpreq = ( thcount == 8 ) && text_mode;
+ wire pre_txreq = ( thcount == 0 || thcount == 12 ) && text_mode;
+
+ reg nreq, preq, creq, ureq, xureq;
+ reg svreq, shreq, snreq, sareq, sp0req, sp1req;
+ always @( negedge rst_n or posedge clk40m ) begin
+ if( !rst_n ) begin
+ nreq <= 0;
+ preq <= 0;
+ creq <= 0;
+ ureq <= 0;
+ svreq <= 0;
+ shreq <= 0;
+ snreq <= 0;
+ sareq <= 0;
+ sp0req <= 0;
+ end else begin
+ nreq <= blank_n && ( scan_line < 192 ) && ( pre_gnreq || pre_tnreq );
+ preq <= blank_n && ( scan_line < 192 ) && ( pre_gpreq || pre_tpreq );
+ creq <= blank_n && ( scan_line < 192 ) && pre_gcreq;
+ ureq <= ( v >= `BORD_TOP-4 && v < `V_ACT-`BORD_BOT ) && blank_n && ( pre_gxreq || pre_txreq );
+ xureq <= ( h[ 1 : 0 ] == 2'b00 ) && ( !blank_n
+ || ( !gmode && !text_mode )
+ || ( v < `BORD_TOP-4 || v >= `V_ACT-`BORD_BOT ) );
+ svreq <= pre_svreq;
+ shreq <= pre_shreq;
+ snreq <= pre_snreq;
+ sareq <= pre_sareq;
+ sp0req <= pre_sp0req;
+ sp1req <= pre_sp1req;
+ end
+ end
+
+ wire xreq = vram_cpu_req && ( ureq || xureq ) && !vram_cpu_ack;
+
+ wire vram_req = ( nreq || preq || creq || svreq || shreq || snreq || sareq || sp0req || sp1req || xreq );
+ wire vram_wr = ( xreq && vram_cpu_wr );
+
+ // With the 3-state SRAM controller, ACK is asserted one clock before valid read data.
+ reg vram_ack2;
+ always @( negedge rst_n or posedge clk40m ) begin
+ if( !rst_n ) begin
+ vram_ack2 <= 0;
+ end else begin
+ vram_ack2 <= vram_ack;
+ end
+ end
+
+ reg [ 9 : 0 ] reqs;
+ always @( posedge clk40m ) begin
+ if( vram_req ) begin
+ // Store each req so we know what to do with the ack.
+ reqs <= { svreq, shreq, snreq, sareq, sp0req, sp1req, nreq, preq, creq, xreq };
+ end else if( vram_ack2 ) begin
+ reqs <= 0;
+ end
+ end
+
+ assign vram_cpu_ack = reqs[ 0 ] && vram_ack2;
+
+ // Sprite data RAM, 256 x 8-bit words.
+ // Synchronous inputs and outputs.
+ reg [ 7 : 0 ] spr_addr;
+ wire spr_wren;
+ wire [ 7 : 0 ] spr_rdata;
+ vdp_sprdata sprdata(
+ spr_addr,
+ clk40m,
+ vram_rdata,
+ spr_wren,
+ spr_rdata
+ );
+
+ // Sprite data RAM address.
+ always @( col or scan_line or reqs or vrep or ghcount or spr_num ) begin
+ if( col < 32 ) begin
+ // Write data address.
+ spr_addr[ 7 : 2 ] = { !scan_line[ 0 ], spr_num };
+ spr_addr[ 1 : 0 ] = 2'bXX;
+ if( reqs[ 5 ] ) begin
+ spr_addr[ 1 : 0 ] = 2'b00; // Pattern 0.
+ end else if( reqs[ 4 ] ) begin
+ spr_addr[ 1 : 0 ] = 2'b01; // Pattern 1.
+ end else if( reqs[ 6 ] ) begin
+ spr_addr[ 1 : 0 ] = 2'b10; // Early clock/color.
+ end else if( reqs[ 8 ] ) begin
+ spr_addr[ 1 : 0 ] = 2'b11; // Horizontal position.
+ end
+ end else begin
+ // Read data address.
+ spr_addr = { ( vrep[ 1 ] ^ scan_line[ 0 ] ), col[ 2 : 0 ], ghcount[ 3 : 0 ] };
+ end
+ end
+
+ // Sprite RAM data write enable.
+ assign spr_wren = vram_ack2 && ( reqs[ 4 ] || reqs[ 5 ] || reqs[ 6 ] || reqs[ 8 ] );
+
+ // Sprite arithmetic.
+ wire [ 5 : 0 ] spr_side = spr_size ? ( spr_mag ? 6'd32 : 6'd16 ) : ( spr_mag ? 6'd16 : 6'd8 );
+ wire [ 7 : 0 ] spr_min = vram_rdata;
+ wire [ 7 : 0 ] spr_max = vram_rdata + spr_side;
+ wire spr_start = ( h == `H_WIDTH-1+`BORD_GRAPH-32*3-4 );
+ wire spr_setup = ( spr_start && vrep == 2 );
+
+ // Store VRAM read data.
+ reg [ 7 : 0 ] name;
+ reg [ 7 : 0 ] pattern;
+ reg [ 7 : 0 ] color;
+ reg [ 4 : 0 ] spr_line;
+ reg [ 7 : 0 ] spr_name;
+ reg spr_5;
+ reg [ 4 : 0 ] spr_5num;
+ reg [ 2 : 0 ] spr_count;
+ always @( negedge rst_n or posedge clk40m ) begin
+ if( !rst_n ) begin
+ spr_5 <= 0;
+ end else if( start_vblank ) begin
+ spr_5 <= 0;
+ end else if( spr_setup ) begin
+ spr_load <= 1;
+ spr_xvld <= 0;
+ spr_count <= 0;
+ end else if( vram_ack2 ) begin
+ if( reqs[ 3 ] ) begin
+ name <= vram_rdata;
+ end
+ if( reqs[ 2 ] ) begin
+ if( !multi_mode ) begin
+ pattern <= vram_rdata;
+ end else begin
+ pattern <= 8'hF0;
+ color <= vram_rdata;
+ end
+ end
+ if( reqs[ 1 ] ) begin
+ color <= vram_rdata;
+ end
+ if( reqs[ 9 ] ) begin
+ if( vram_rdata == 208 ) begin
+ spr_load <= 0;
+ end else if( !spr_nolimit && spr_count == 4 ) begin
+ if( !spr_5 ) begin
+ spr_5num <= spr_num;
+ end
+ spr_5 <= 1;
+ spr_load <= 0;
+ end else if( scan_next+8'd32 > spr_min+8'd32 && scan_next+8'd32 <= spr_max+8'd32 ) begin
+ spr_xvld[ spr_num ] <= 1;
+ spr_line <= scan_next[ 4 : 0 ]-vram_rdata[ 4 : 0 ]-5'h1;
+ spr_count <= spr_count + 1'b1;
+ end
+ end
+ if( reqs[ 7 ] ) begin
+ spr_name <= vram_rdata;
+ end
+ end
+ end
+
+ // VRAM address MUX. Big MUX.
+ reg [ 13 : 0 ] vram_addr;
+ always @( xreq or vram_cpu_a
+ or nreq or ntb or text_mode or row or col
+ or preq or g1_mode or g2_mode or multi_mode or pgb or name or line or multi_row or text_pos
+ or creq or colb or vram_rdata
+ or svreq or shreq or snreq or sareq or sp0req or sp1req
+ or spr_num or spr_size or spr_mag or spr_name or spr_line or spgb or sab ) begin
+ vram_addr = 14'hXXXX;
+ if( xreq ) begin
+ vram_addr = vram_cpu_a;
+ end
+ if( nreq ) begin
+ vram_addr[ 13 : 10 ] = ntb;
+ if( text_mode ) begin
+ vram_addr[ 9 : 0 ] = text_pos;
+ end else begin
+ vram_addr[ 9 : 0 ] = { row, col[ 4 : 0 ] };
+ end
+ end
+ if( preq ) begin
+ // Name is not set until next clock, use vram_rdata instead.
+ if( g1_mode || text_mode ) begin
+ vram_addr = { pgb, vram_rdata, line };
+ end else if( g2_mode ) begin
+ vram_addr = { pgb[ 2 ], row[ 4 : 3 ], vram_rdata, line };
+ end else if( multi_mode ) begin
+ vram_addr = { pgb, vram_rdata, multi_row[ 2 : 0 ] };
+ end
+ end
+ if( creq ) begin
+ if( g1_mode ) begin
+ vram_addr = { colb, 1'b0, name[ 7 : 3 ] };
+ end else if( g2_mode ) begin
+ vram_addr = { colb[ 2 ], row[ 4 : 3 ], name, line };
+ end
+ end
+ if( svreq ) begin
+ vram_addr = { sab, spr_num, 2'b00 };
+ end
+ if( shreq ) begin
+ vram_addr = { sab, spr_num, 2'b01 };
+ end
+ if( snreq ) begin
+ vram_addr = { sab, spr_num, 2'b10 };
+ end
+ if( sareq ) begin
+ vram_addr = { sab, spr_num, 2'b11 };
+ end
+ if( sp0req ) begin
+ if( !spr_size ) begin
+ if( !spr_mag ) begin
+ vram_addr = { spgb, spr_name, spr_line[ 2 : 0 ] };
+ end else begin
+ vram_addr = { spgb, spr_name, spr_line[ 3 : 1 ] };
+ end
+ end else begin
+ if( !spr_mag ) begin
+ vram_addr = { spgb, spr_name[ 7 : 2 ], 1'b0, spr_line[ 3 : 0 ] };
+ end else begin
+ vram_addr = { spgb, spr_name[ 7 : 2 ], 1'b0, spr_line[ 4 : 1 ] };
+ end
+ end
+ end
+ if( sp1req ) begin
+ if( !spr_mag ) begin
+ vram_addr = { spgb, spr_name[ 7 : 2 ], 1'b1, spr_line[ 3 : 0 ] };
+ end else begin
+ vram_addr = { spgb, spr_name[ 7 : 2 ], 1'b1, spr_line[ 4 : 1 ] };
+ end
+ end
+ end
+
+ // Sprite state machine.
+ integer i;
+ reg spr_found;
+ reg spr_active;
+ reg [ 1 : 0 ] spr_hrep;
+ reg spr_pattern;
+ reg [ 3 : 0 ] spr_color;
+ reg spr_collide;
+ reg [ 8 : 0 ] spr_hcount;
+ reg [ 31 : 0 ] spr_odd;
+ reg [ 4 : 0 ] snum;
+ reg early;
+ reg [ 31 : 0 ] spr_vld;
+ reg [ 3 : 0 ] spr_col [ 0 : 31 ];
+ reg [ 8 : 0 ] spr_dly [ 0 : 31 ];
+ reg [ 15 : 0 ] spr_pat [ 0 : 31 ];
+ always @( negedge rst_n or posedge clk40m ) begin
+ if( !rst_n ) begin
+ spr_collide <= 0;
+ spr_active <= 0;
+ end else if( start_vblank ) begin
+ spr_collide <= 0;
+ spr_vld <= 0;
+ end else if( col >= 32 && col < 40 && ghcount >= 2 && ghcount < 18 ) begin
+ spr_active <= 0;
+ // Unload sprite data from RAM.
+ snum = ( ( ghcount - 2'd2 ) & 4'b1100 ) >> 2;
+ snum[ 4 : 2 ] = col[ 2 : 0 ];
+ case( ghcount[ 1 : 0 ] )
+ 0: begin
+ spr_col[ snum ] <= spr_rdata[ 3 : 0 ];
+ early <= spr_rdata[ 7 ];
+ end
+ 1: begin
+ if( early ) begin
+ spr_dly[ snum ] <= { 1'b0, spr_rdata };
+ end else begin
+ spr_dly[ snum ] <= 9'd32 + spr_rdata;
+ end
+ end
+ 2: begin
+ spr_pat[ snum ][ 15 : 8 ] <= spr_rdata;
+ end
+ 3: begin
+ if( spr_size ) begin
+ spr_pat[ snum ][ 7 : 0 ] <= spr_rdata;
+ end else begin
+ spr_pat[ snum ][ 7 : 0 ] <= 8'h00;
+ end
+ end
+ endcase
+ end else if( spr_start ) begin
+ spr_hrep <= 2;
+ spr_pattern <= 0;
+ spr_odd <= 0;
+ spr_hcount <= 0;
+ spr_active <= 1;
+ if( spr_setup ) begin
+ spr_vld <= spr_xvld;
+ end
+ end else if( spr_active && spr_hrep == 1 ) begin
+ // Multicycle path:
+ // Count, pattern, color, collide clocked in when hrep 1->2 only.
+ spr_found = 0;
+ for( i = 0; i <= 31; i = i + 1 ) begin
+ if( spr_hcount >= spr_dly[ i ] ) begin
+ if( spr_vld[ i ] ) begin
+ if( spr_pat[ i ][ 15 ] ) begin
+ if( spr_found ) begin
+ // Sprite collision.
+ spr_collide <= 1;
+ end else begin
+ spr_color <= spr_col[ i ];
+ end
+ spr_found = 1;
+ end
+ if( !spr_mag || spr_odd[ i ] ) begin
+ // Shift pattern, zero backfill.
+ spr_pat[ i ] <= { spr_pat[ i ][ 14 : 0 ], 1'b0 };
+ end
+ end
+ spr_odd[ i ] <= ~spr_odd[ i ];
+ end
+ end
+ spr_pattern <= spr_found;
+ spr_hrep <= 2;
+ spr_hcount <= spr_hcount + 1'b1;
+ end else if( spr_hrep == 2 ) begin
+ spr_hrep <= 0;
+ end else begin
+ spr_hrep <= 1;
+ end
+ end
+
+endmodule
diff --git a/common/Video/tms9918a_bartlett/vdp_shift.v b/common/Video/tms9918a_bartlett/vdp_shift.v
new file mode 100644
index 00000000..964d7bcc
--- /dev/null
+++ b/common/Video/tms9918a_bartlett/vdp_shift.v
@@ -0,0 +1,58 @@
+module vdp_shift(
+ clk40m,
+ rst_n,
+ pattern,
+ color,
+ color1,
+ color0,
+ load,
+ text_mode,
+ color_1,
+ color_0,
+ pixel
+);
+
+ input clk40m;
+ input rst_n;
+ input [ 7 : 0 ] pattern;
+ input [ 7 : 0 ] color;
+ input [ 3 : 0 ] color1;
+ input [ 3 : 0 ] color0;
+ input load;
+ input text_mode;
+ output [ 3 : 0 ] color_1;
+ output [ 3 : 0 ] color_0;
+ output pixel;
+
+ reg [ 3 : 0 ] color_1;
+ reg [ 3 : 0 ] color_0;
+ always @( negedge rst_n or posedge clk40m ) begin
+ if( !rst_n ) begin
+ color_1 <= 0;
+ color_0 <= 0;
+ end else if( load ) begin
+ color_1 <= text_mode ? color1 : color[ 7 : 4 ];
+ color_0 <= text_mode ? color0 : color[ 3 : 0 ];
+ end
+ end
+
+ reg pixel;
+ reg [ 6 : 0 ] shift;
+ reg [ 1 : 0 ] hrep;
+ always @( negedge rst_n or posedge clk40m ) begin
+ if( !rst_n ) begin
+ pixel <= 0;
+ shift <= 0;
+ hrep <= 0;
+ end else if( load ) begin
+ hrep <= 0;
+ { pixel, shift } <= pattern;
+ end else if( hrep == 2 ) begin
+ hrep <= 0;
+ { pixel, shift } <= { shift[ 6 : 0 ], 1'b0 };
+ end else begin
+ hrep <= hrep + 1'b1;
+ end
+ end
+
+endmodule
diff --git a/common/Video/tms9918a_bartlett/vdp_sram.v b/common/Video/tms9918a_bartlett/vdp_sram.v
new file mode 100644
index 00000000..15e5d22b
--- /dev/null
+++ b/common/Video/tms9918a_bartlett/vdp_sram.v
@@ -0,0 +1,104 @@
+module vdp_sram(
+ clk40m,
+ clk40m_n,
+ rst_n,
+ vram_req,
+ vram_wr,
+ vram_ack,
+ vram_addr,
+ vram_rdata,
+ sram_a,
+ sram_din,
+ sram_doe,
+ sram_oe_n,
+ sram_we_n
+);
+
+ input clk40m;
+ input clk40m_n;
+ input rst_n;
+
+ input vram_req;
+ input vram_wr;
+ output vram_ack;
+ input [ 13 : 0 ] vram_addr;
+ output [ 7 : 0 ] vram_rdata;
+
+ output [ 13 : 0 ] sram_a;
+ input [ 7 : 0 ] sram_din;
+ output sram_doe;
+ output sram_oe_n;
+ output sram_we_n;
+
+ // SRAM controller, 3 cycles per access.
+ reg [ 7 : 0 ] vram_rdata;
+ reg vram_active;
+ reg [ 13 : 0 ] sram_a;
+ reg sram_doe;
+ reg sram_oe_n;
+ reg sram_pwe_n;
+ reg [ 1 : 0 ] vram_state;
+ reg vram_ack;
+ always @( negedge rst_n or posedge clk40m ) begin
+ if( !rst_n ) begin
+ vram_active <= 0;
+ sram_doe <= 0;
+ sram_oe_n <= 1;
+ sram_pwe_n <= 1;
+ vram_state <= 0;
+ vram_ack <= 0;
+ end else begin
+ case( vram_state )
+ 0: begin
+ if( vram_req ) begin
+ vram_active <= 1;
+ sram_a <= vram_addr;
+ sram_pwe_n <= !vram_wr;
+ vram_state <= 1;
+ end else begin
+ vram_active <= 0;
+ sram_pwe_n <= 1;
+ vram_state <= 0;
+ end
+ sram_doe <= 0;
+ sram_oe_n <= 1;
+ if( vram_active && !sram_oe_n ) begin
+ vram_rdata <= sram_din;
+ end
+ vram_ack <= 0;
+ end
+ 1: begin
+ sram_oe_n <= !( vram_active && sram_pwe_n );
+ sram_doe <= !sram_pwe_n;
+ vram_state <= 2;
+ vram_ack <= 0;
+ end
+ 2: begin
+ sram_pwe_n <= 1;
+ vram_state <= 0;
+ vram_ack <= 1;
+ end
+ 3: begin
+ // Illegal state.
+ vram_active <= 0;
+ sram_doe <= 0;
+ sram_oe_n <= 1;
+ sram_pwe_n <= 1;
+ vram_ack <= 0;
+ vram_state <= 0;
+ end
+ endcase
+ end
+ end
+
+ // WE* on half clock for pulse width, addr setup/hold.
+ reg sram_we_n;
+ always @( negedge rst_n or posedge clk40m_n ) begin
+ if( !rst_n ) begin
+ sram_we_n <= 1;
+ end else begin
+ sram_we_n <= sram_pwe_n;
+ end
+ end
+
+endmodule
diff --git a/common/Video/tms9918a_bartlett/vdp_wrap.v b/common/Video/tms9918a_bartlett/vdp_wrap.v
new file mode 100644
index 00000000..dd94ada5
--- /dev/null
+++ b/common/Video/tms9918a_bartlett/vdp_wrap.v
@@ -0,0 +1,105 @@
+module vdp_wrap(
+ por_73_n,
+ clk50m_17,
+ push_144_n,
+ led1_3_n,
+ led2_7_n,
+ led3_9_n,
+ cpu_rst_n,
+ cpu_a,
+ cpu_d,
+ cpu_in_n,
+ cpu_out_n,
+ cpu_int_n,
+ sram_a,
+ sram_d,
+ sram_oe_n,
+ sram_we_n,
+ hsync,
+ vsync,
+ r,
+ g,
+ b
+);
+
+ // Development board hardwired pins
+ input por_73_n; // 100 ms time constant RC POR on pin 73
+ input clk50m_17; // 50 MHz oscillator on pin 17
+ input push_144_n; // Pushbutton on pin 144
+ output led1_3_n; // LED on pin 3
+ output led2_7_n; // LED on pin 7
+ output led3_9_n; // LED on pin 9
+
+ // CPU interface
+ input cpu_rst_n;
+ input [ 7 : 0 ] cpu_a;
+ inout [ 7 : 0 ] cpu_d;
+ input cpu_in_n;
+ input cpu_out_n;
+ output cpu_int_n;
+
+ // SRAM interface
+ output [ 18 : 0 ] sram_a;
+ inout [ 7 : 0 ] sram_d;
+ output sram_oe_n;
+ output sram_we_n;
+
+ // VGA interface
+ output hsync; // Horizontal sync
+ output vsync; // Vertical sync
+ output [ 3 : 0 ] r;
+ output [ 3 : 0 ] g;
+ output [ 3 : 0 ] b;
+
+ wire [ 7 : 0 ] cpu_din;
+ wire [ 7 : 0 ] cpu_dout;
+ wire cpu_doe;
+
+ assign cpu_din = cpu_d;
+ assign cpu_d = cpu_doe ? cpu_dout : 8'hZZ;
+
+ wire [ 7 : 0 ] sram_din;
+ wire [ 7 : 0 ] sram_dout;
+ wire sram_doe;
+
+ assign sram_din = sram_d;
+ assign sram_d = sram_doe ? sram_dout : 8'hZZ;
+
+ // Give the LEDs something useless to do, to reduce synthesis warnings.
+ assign led1_3_n = !( !por_73_n || !push_144_n );
+ assign led2_7_n = !( !por_73_n || !push_144_n );
+ assign led3_9_n = !( !por_73_n || !push_144_n );
+
+ // PLL to convert 50 MHz to 40 MHz.
+ wire clk40m, clk40m_n;
+ vdp_clkgen clkgen(
+ clk50m_17,
+ clk40m,
+ clk40m_n
+ );
+
+ vdp vdp1(
+ clk40m,
+ clk40m_n,
+ cpu_rst_n,
+ cpu_a,
+ cpu_din,
+ cpu_dout,
+ cpu_doe,
+ cpu_in_n,
+ cpu_out_n,
+ cpu_int_n,
+ sram_a,
+ sram_din,
+ sram_dout,
+ sram_doe,
+ sram_oe_n,
+ sram_we_n,
+ hsync,
+ vsync,
+ r,
+ g,
+ b
+ );
+
+endmodule
\ No newline at end of file
diff --git a/common/Video/vdp18/README b/common/Video/vdp18/README
new file mode 100644
index 00000000..4576b2ec
--- /dev/null
+++ b/common/Video/vdp18/README
@@ -0,0 +1,201 @@
+
+A Synthesizable model of TI's TMS9918A, TMS9928A, TMS9929A
+==========================================================
+Version: $Date: 2006/06/18 19:28:06 $
+
+Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net)
+See the file COPYING.
+
+
+Integration
+-----------
+
+The vdp18 design exhibits a set of interface signals that is compatible to the
+original chips. It mainly differs in the video and VRAM interfaces, which are
+tailored to better fit a modern SoC.
+
+ generic (
+ is_pal_g : integer := 0;
+ -- Select PAL or NTSC video timing.
+ -- 0 = NTSC
+ -- 1 = PAL
+
+ compat_rgb_g : integer := 0
+ -- Select full or compatibility RGB palettes.
+ -- Refer to vdp18_col_pack-p.vhd for details.
+
+ );
+ port (
+ -- Global Interface -------------------------------------------------------
+ clk_i : in std_logic;
+ -- Global clock input
+ -- Equivalent to XTAL1/2 on TMS9918A.
+ -- Drive with the target frequency of 10.7 MHz or any integer multiple.
+
+ clk_en_10m7_i : in std_logic;
+ -- Clock enable
+ -- A '1' on this input qualifies a valid rising edge on clk_i. A '0'
+ -- disables the next rising clock edge, effectivley halting the design
+ -- until the next enabled rising clock edge.
+ -- Can be used to run the core at lower frequencies than applied on
+ -- clk_i.
+
+ reset_n_i : in std_logic;
+ -- Asynchronous low active reset input
+ -- Sets all sequential elements to a known state.
+ -- NOTE: SYNC operation not supported.
+
+ -- CPU Interface ----------------------------------------------------------
+ csr_n_i : in std_logic;
+ -- CPU-VDP read strobe, low active
+
+ csw_n_i : in std_logic;
+ -- CPU-VDP write strobe, low active
+
+ mode_i : in std_logic;
+ -- CPU interface mode select
+
+ int_n_o : out std_logic;
+ -- CPU interrupt output, low active
+
+ cd_i : in std_logic_vector(0 to 7);
+ -- CPU data bus input
+ -- MSB 0 ... 7 LSB
+
+ cd_o : out std_logic_vector(0 to 7);
+ -- CPU data bus output
+ -- MSB 0 ... 7 LSB
+
+ -- VRAM Interface ---------------------------------------------------------
+ vram_we_o : out std_logic;
+ -- VRAM write enable
+
+ vram_a_o : out std_logic_vector(0 to 13);
+ -- VRAM address output
+ -- MSB 0 ... 13 LSB
+
+ vram_d_o : out std_logic_vector(0 to 7);
+ -- VRAM data output
+ -- MSB 0 ... 7 LSB
+
+ vram_d_i : in std_logic_vector(0 to 7);
+ -- VRAM data input
+ -- MSB 0 ... 7 LSB
+
+ -- Video Interface --------------------------------------------------------
+ col_o : out std_logic_vector(0 to 3);
+ -- Color code output
+ -- Encoded pixel color information
+
+ rgb_r_o : out std_logic_vector(0 to 7);
+ -- Red color information
+
+ rgb_g_o : out std_logic_vector(0 to 7);
+ -- Green color information
+
+ rgb_b_o : out std_logic_vector(0 to 7);
+ -- Blue color information
+
+ hsync_n_o : out std_logic;
+ -- Horizontal synchronization pulse, active low
+
+ vsync_n_o : out std_logic;
+ -- Vertical synchronization pulse, active low
+
+ comp_sync_n_o : out std_logic
+ -- Composite synchronization pulse, active low
+ );
+
+
+All 8 bit vector ports are defined (0 to 7) which declares bit 0 to be the MSB
+and bit 7 to be the LSB. This has been implemented according to TI's data
+sheet, thus all register/data format figures apply 1:1 for this design.
+Many systems will flip the system data bus bit wise before it is connected to
+this PSG. This is simply achieved with the following VHDL construct:
+
+ signal data_s : std_logic_vector(7 downto 0);
+
+ ...
+ cd_i => data_s,
+ ...
+
+d_i and data_s will be assigned from left to right, resulting in the expected
+bit assignment:
+
+ cd_i data_s
+ 0 7
+ 1 6
+ ...
+ 6 1
+ 7 0
+
+
+As this design is fully synchronous, care has to be taken when the design
+replaces an TMS99x8 in asynchronous mode. No problems are expected when
+interfacing the code to other synchronous components.
+
+
+Design Hierarchy
+----------------
+
+ vdp18_core
+ |
+ +-- vdp18_clk_gen
+ |
+ +-- vdp18_hor_vert
+ |
+ +-- vdp18_ctrl
+ |
+ +-- vdp18_cpuio
+ |
+ +-- vdp18_addr_mux
+ |
+ +-- vdp18_pattern
+ |
+ +-- vdp18_sprite
+ |
+ \-- vdp18_col_mux
+
+Resulting compolation sequence:
+
+ vdp18_pack-p.vhd
+ vdp18_comp_pack-p.vhd
+ vdp18_core.vhd
+ vdp18_clk_gen.vhd
+ vdp18_clk_gen-c.vhd
+ vdp18_hor_vert.vhd
+ vdp18_hor_vert-c.vhd
+ vdp18_ctrl.vhd
+ vdp18_ctrl-c.vhd
+ vdp18_cpuio.vhd
+ vdp18_cpuio-c.vhd
+ vdp18_addr_mux.vhd
+ vdp18_addr_mux-c.vhd
+ vdp18_pattern.vhd
+ vdp18_pattern-c.vhd
+ vdp18_sprite.vhd
+ vdp18_sprite-c.vhd
+ vdp18_col_mux.vhd
+ vdp18_col_mux-c.vhd
+ vdp18_core-c.vhd
+ vdp18_core_com_pack-p.vhd
+
+Skip the files containing VHDL configurations when analyzing the code for
+synthesis.
+
+
+References
+----------
+
+* TI Data book TMS9918.pdf
+ http://www.bitsavers.org/pdf/ti/_dataBooks/TMS9918.pdf
+
+* Sean Young's tech article:
+ http://bifi.msxnet.org/msxnet/tech/tms9918a.txt
+
+* Paul Urbanus' discussion of the timing details
+ http://bifi.msxnet.org/msxnet/tech/tmsposting.txt
+
+* Richard F. Drushel's article series
+ "This Week With My Coleco ADAM"
+ http://junior.apk.net/~drushel/pub/coleco/twwmca/index.html
diff --git a/common/Video/vdp18/vdp18_addr_mux.vhd b/common/Video/vdp18/vdp18_addr_mux.vhd
new file mode 100644
index 00000000..9ff8c8f8
--- /dev/null
+++ b/common/Video/vdp18/vdp18_addr_mux.vhd
@@ -0,0 +1,228 @@
+-------------------------------------------------------------------------------
+--
+-- Synthesizable model of TI's TMS9918A, TMS9928A, TMS9929A.
+--
+-- $Id: vdp18_addr_mux.vhd,v 1.10 2006/06/18 10:47:01 arnim Exp $
+--
+-- Address Multiplexer / Generator
+--
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.vdp18_pack.access_t;
+use work.vdp18_pack.opmode_t;
+use work.vdp18_pack.hv_t;
+
+entity vdp18_addr_mux is
+
+ port (
+ access_type_i : in access_t;
+ opmode_i : in opmode_t;
+ num_line_i : in hv_t;
+ reg_ntb_i : in std_logic_vector(0 to 3);
+ reg_ctb_i : in std_logic_vector(0 to 7);
+ reg_pgb_i : in std_logic_vector(0 to 2);
+ reg_satb_i : in std_logic_vector(0 to 6);
+ reg_spgb_i : in std_logic_vector(0 to 2);
+ reg_size1_i : in boolean;
+ cpu_vram_a_i : in std_logic_vector(0 to 13);
+ pat_table_i : in std_logic_vector(0 to 9);
+ pat_name_i : in std_logic_vector(0 to 7);
+ spr_num_i : in std_logic_vector(0 to 4);
+ spr_line_i : in std_logic_vector(0 to 3);
+ spr_name_i : in std_logic_vector(0 to 7);
+ vram_a_o : out std_logic_vector(0 to 13)
+ );
+
+end vdp18_addr_mux;
+
+
+use work.vdp18_pack.all;
+
+architecture rtl of vdp18_addr_mux is
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process mux
+ --
+ -- Purpose:
+ -- Generates the VRAM address based on the current access type.
+ --
+ mux: process (access_type_i, opmode_i,
+ num_line_i,
+ reg_ntb_i, reg_ctb_i, reg_pgb_i,
+ reg_satb_i, reg_spgb_i,
+ reg_size1_i,
+ cpu_vram_a_i,
+ pat_table_i, pat_name_i,
+ spr_num_i, spr_name_i,
+ spr_line_i)
+ variable num_line_v : std_logic_vector(num_line_i'range);
+ begin
+ -- default assignment
+ vram_a_o <= (others => '0');
+ num_line_v := std_logic_vector(num_line_i);
+
+ case access_type_i is
+ -- CPU Access -----------------------------------------------------------
+ when AC_CPU =>
+ vram_a_o <= cpu_vram_a_i;
+
+ -- Pattern Name Table Access --------------------------------------------
+ when AC_PNT =>
+ vram_a_o(0 to 3) <= reg_ntb_i;
+ vram_a_o(4 to 13) <= pat_table_i;
+
+ -- Pattern Color Table Access -------------------------------------------
+ when AC_PCT =>
+ case opmode_i is
+ when OPMODE_GRAPH1 =>
+ vram_a_o( 0 to 7) <= reg_ctb_i;
+ vram_a_o( 8) <= '0';
+ vram_a_o( 9 to 13) <= pat_name_i(0 to 4);
+
+ when OPMODE_GRAPH2 =>
+ vram_a_o( 0) <= reg_ctb_i(0);
+ vram_a_o( 1 to 2) <= num_line_v(1 to 2) and
+ -- remaining bits in CTB mask color
+ -- lookups
+ (reg_ctb_i(1) & reg_ctb_i(2));
+ vram_a_o( 3 to 10) <= pat_name_i and
+ -- remaining bits in CTB mask color
+ -- lookups
+ (reg_ctb_i(3) & reg_ctb_i(4) &
+ reg_ctb_i(5) & reg_ctb_i(6) &
+ reg_ctb_i(7) & "111");
+ vram_a_o(11 to 13) <= num_line_v(6 to 8);
+
+ when others =>
+ null;
+ end case;
+
+ -- Pattern Generator Table Access ---------------------------------------
+ when AC_PGT =>
+ case opmode_i is
+ when OPMODE_TEXTM |
+ OPMODE_GRAPH1 =>
+ vram_a_o( 0 to 2) <= reg_pgb_i;
+ vram_a_o( 3 to 10) <= pat_name_i;
+ vram_a_o(11 to 13) <= num_line_v(6 to 8);
+
+ when OPMODE_MULTIC =>
+ vram_a_o( 0 to 2) <= reg_pgb_i;
+ vram_a_o( 3 to 10) <= pat_name_i;
+ vram_a_o(11 to 13) <= num_line_v(4 to 6);
+
+ when OPMODE_GRAPH2 =>
+ vram_a_o( 0) <= reg_pgb_i(0);
+ vram_a_o( 1 to 2) <= num_line_v(1 to 2) and
+ -- remaining bits in PGB mask pattern
+ -- lookups
+ (reg_pgb_i(1) & reg_pgb_i(2));
+ vram_a_o( 3 to 10) <= pat_name_i and
+ -- remaining bits in CTB mask pattern
+ -- lookups
+ (reg_ctb_i(3) & reg_ctb_i(4) &
+ reg_ctb_i(5) & reg_ctb_i(6) &
+ reg_ctb_i(7) & "111");
+ vram_a_o(11 to 13) <= num_line_v(6 to 8);
+
+ when others =>
+ null;
+ end case;
+
+ -- Sprite Test ----------------------------------------------------------
+ when AC_STST |
+ AC_SATY =>
+ vram_a_o( 0 to 6) <= reg_satb_i;
+ vram_a_o( 7 to 11) <= spr_num_i;
+ vram_a_o(12 to 13) <= "00";
+
+ -- Sprite Attribute Table: X --------------------------------------------
+ when AC_SATX =>
+ vram_a_o( 0 to 6) <= reg_satb_i;
+ vram_a_o( 7 to 11) <= spr_num_i;
+ vram_a_o(12 to 13) <= "01";
+
+ -- Sprite Attribute Table: Name -----------------------------------------
+ when AC_SATN =>
+ vram_a_o( 0 to 6) <= reg_satb_i;
+ vram_a_o( 7 to 11) <= spr_num_i;
+ vram_a_o(12 to 13) <= "10";
+
+ -- Sprite Attribute Table: Color ----------------------------------------
+ when AC_SATC =>
+ vram_a_o( 0 to 6) <= reg_satb_i;
+ vram_a_o( 7 to 11) <= spr_num_i;
+ vram_a_o(12 to 13) <= "11";
+
+ -- Sprite Pattern, Upper Part -------------------------------------------
+ when AC_SPTH =>
+ vram_a_o( 0 to 2) <= reg_spgb_i;
+ if not reg_size1_i then
+ -- 8x8 sprite
+ vram_a_o( 3 to 10) <= spr_name_i;
+ vram_a_o(11 to 13) <= spr_line_i(1 to 3);
+ else
+ -- 16x16 sprite
+ vram_a_o( 3 to 8) <= spr_name_i(0 to 5);
+ vram_a_o( 9) <= '0';
+ vram_a_o(10 to 13) <= spr_line_i;
+ end if;
+
+ -- Sprite Pattern, Lower Part -------------------------------------------
+ when AC_SPTL =>
+ vram_a_o( 0 to 2) <= reg_spgb_i;
+ vram_a_o( 3 to 8) <= spr_name_i(0 to 5);
+ vram_a_o( 9) <= '1';
+ vram_a_o(10 to 13) <= spr_line_i;
+
+ when others =>
+ null;
+
+ end case;
+
+ end process mux;
+ --
+ -----------------------------------------------------------------------------
+
+end rtl;
diff --git a/common/Video/vdp18/vdp18_clk_gen.vhd b/common/Video/vdp18/vdp18_clk_gen.vhd
new file mode 100644
index 00000000..6c208907
--- /dev/null
+++ b/common/Video/vdp18/vdp18_clk_gen.vhd
@@ -0,0 +1,154 @@
+-------------------------------------------------------------------------------
+--
+-- Synthesizable model of TI's TMS9918A, TMS9928A, TMS9929A.
+--
+-- $Id: vdp18_clk_gen.vhd,v 1.8 2006/06/18 10:47:01 arnim Exp $
+--
+-- Clock Generator
+--
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity vdp18_clk_gen is
+
+ port (
+ clock_i : in std_logic;
+ clk_en_10m7_i : in std_logic;
+ reset_i : in boolean;
+ clk_en_5m37_o : out boolean;
+ clk_en_3m58_o : out boolean;
+ clk_en_2m68_o : out boolean
+ );
+
+end vdp18_clk_gen;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+architecture rtl of vdp18_clk_gen is
+
+ signal cnt_q : unsigned(3 downto 0);
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process seq
+ --
+ -- Purpose:
+ -- Implements the sequential elements.
+ -- * clock counter
+ --
+ seq: process (clock_i, reset_i)
+ variable cnt_v : integer range -256 to 255;
+ begin
+ if reset_i then
+ cnt_q <= (others => '0');
+
+ elsif clock_i'event and clock_i = '1' then
+ if clk_en_10m7_i = '1' then
+ if cnt_q = 11 then
+ -- wrap after counting 12 clocks
+ cnt_q <= (others => '0');
+ else
+ cnt_q <= cnt_q + 1;
+ end if;
+ end if;
+
+ end if;
+ end process seq;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process clk_en
+ --
+ -- Purpose:
+ -- Generates the derived clock enable signals.
+ --
+ clk_en: process (clk_en_10m7_i,
+ cnt_q)
+ variable cnt_v : integer range -256 to 255;
+ begin
+ cnt_v := to_integer(cnt_q);
+
+ -- 5.37 MHz clock enable --------------------------------------------------
+ if clk_en_10m7_i = '1' then
+ case cnt_v is
+ when 1 | 3 | 5 | 7 | 9 | 11 =>
+ clk_en_5m37_o <= true;
+ when others =>
+ clk_en_5m37_o <= false;
+ end case;
+ else
+ clk_en_5m37_o <= false;
+ end if;
+
+ -- 3.58 MHz clock enable --------------------------------------------------
+ if clk_en_10m7_i = '1' then
+ case cnt_v is
+ when 2 | 5 | 8 | 11 =>
+ clk_en_3m58_o <= true;
+ when others =>
+ clk_en_3m58_o <= false;
+ end case;
+ else
+ clk_en_3m58_o <= false;
+ end if;
+
+ -- 2.68 MHz clock enable --------------------------------------------------
+ if clk_en_10m7_i = '1' then
+ case cnt_v is
+ when 3 | 7 | 11 =>
+ clk_en_2m68_o <= true;
+ when others =>
+ clk_en_2m68_o <= false;
+ end case;
+ else
+ clk_en_2m68_o <= false;
+ end if;
+
+ end process clk_en;
+ --
+ -----------------------------------------------------------------------------
+
+end rtl;
diff --git a/common/Video/vdp18/vdp18_col_mux.vhd b/common/Video/vdp18/vdp18_col_mux.vhd
new file mode 100644
index 00000000..e8c40327
--- /dev/null
+++ b/common/Video/vdp18/vdp18_col_mux.vhd
@@ -0,0 +1,184 @@
+-------------------------------------------------------------------------------
+--
+-- Synthesizable model of TI's TMS9918A, TMS9928A, TMS9929A.
+--
+-- $Id: vdp18_col_mux.vhd,v 1.10 2006/06/18 10:47:01 arnim Exp $
+--
+-- Color Information Multiplexer
+--
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity vdp18_col_mux is
+
+ generic (
+ compat_rgb_g : integer := 0
+ );
+ port (
+ clock_i : in std_logic;
+ clk_en_5m37_i : in boolean;
+ reset_i : in boolean;
+ vert_active_i : in boolean;
+ hor_active_i : in boolean;
+ blank_i : in boolean;
+ reg_col0_i : in std_logic_vector(0 to 3);
+ pat_col_i : in std_logic_vector(0 to 3);
+ spr0_col_i : in std_logic_vector(0 to 3);
+ spr1_col_i : in std_logic_vector(0 to 3);
+ spr2_col_i : in std_logic_vector(0 to 3);
+ spr3_col_i : in std_logic_vector(0 to 3);
+ col_o : out std_logic_vector(0 to 3);
+ rgb_r_o : out std_logic_vector(0 to 7);
+ rgb_g_o : out std_logic_vector(0 to 7);
+ rgb_b_o : out std_logic_vector(0 to 7)
+ );
+
+end vdp18_col_mux;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+use work.vdp18_col_pack.all;
+
+architecture rtl of vdp18_col_mux is
+
+ signal col_s : std_logic_vector(0 to 3);
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process col_mux
+ --
+ -- Purpose:
+ -- Multiplexes the color information from different sources.
+ --
+ col_mux: process (blank_i,
+ hor_active_i, vert_active_i,
+ spr0_col_i, spr1_col_i,
+ spr2_col_i, spr3_col_i,
+ pat_col_i,
+ reg_col0_i)
+ begin
+ if not blank_i then
+ if hor_active_i and vert_active_i then
+ -- priority decoder
+ if spr0_col_i /= "0000" then
+ col_s <= spr0_col_i;
+ elsif spr1_col_i /= "0000" then
+ col_s <= spr1_col_i;
+ elsif spr2_col_i /= "0000" then
+ col_s <= spr2_col_i;
+ elsif spr3_col_i /= "0000" then
+ col_s <= spr3_col_i;
+ elsif pat_col_i /= "0000" then
+ col_s <= pat_col_i;
+ else
+ col_s <= reg_col0_i;
+ end if;
+
+ else
+ -- display border
+ col_s <= reg_col0_i;
+ end if;
+
+ else
+ -- blank color channels during horizontal and vertical
+ -- trace back
+ -- required to initialize colors for each new scan line
+ col_s <= (others => '0');
+ end if;
+ end process col_mux;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process rgb_reg
+ --
+ -- Purpose:
+ -- Converts the color information to simple RGB and saves these in
+ -- output registers.
+ --
+ rgb_reg: process (clock_i, reset_i)
+ variable col_v : natural range 0 to 15;
+ variable rgb_r_v,
+ rgb_g_v,
+ rgb_b_v : rgb_val_t;
+ variable rgb_table_v : rgb_table_t;
+ begin
+ if reset_i then
+ rgb_r_o <= (others => '0');
+ rgb_g_o <= (others => '0');
+ rgb_b_o <= (others => '0');
+
+ elsif clock_i'event and clock_i = '1' then
+ if clk_en_5m37_i then
+ -- select requested RGB table
+ if compat_rgb_g = 1 then
+ rgb_table_v := compat_rgb_table_c;
+ else
+ rgb_table_v := full_rgb_table_c;
+ end if;
+
+ -- assign color to RGB channels
+ col_v := to_integer(unsigned(col_s));
+ rgb_r_v := rgb_table_v(col_v)(r_c);
+ rgb_g_v := rgb_table_v(col_v)(g_c);
+ rgb_b_v := rgb_table_v(col_v)(b_c);
+ --
+ rgb_r_o <= std_logic_vector(to_unsigned(rgb_r_v, 8));
+ rgb_g_o <= std_logic_vector(to_unsigned(rgb_g_v, 8));
+ rgb_b_o <= std_logic_vector(to_unsigned(rgb_b_v, 8));
+ end if;
+
+ end if;
+ end process rgb_reg;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Output mapping
+ -----------------------------------------------------------------------------
+ col_o <= col_s;
+
+end rtl;
diff --git a/common/Video/vdp18/vdp18_col_pack-p.vhd b/common/Video/vdp18/vdp18_col_pack-p.vhd
new file mode 100644
index 00000000..1d179def
--- /dev/null
+++ b/common/Video/vdp18/vdp18_col_pack-p.vhd
@@ -0,0 +1,83 @@
+-------------------------------------------------------------------------------
+--
+-- $Id: vdp18_col_pack-p.vhd,v 1.3 2006/02/28 22:30:41 arnim Exp $
+--
+-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+package vdp18_col_pack is
+
+ constant r_c : natural := 0;
+ constant g_c : natural := 1;
+ constant b_c : natural := 2;
+
+ subtype rgb_val_t is natural range 0 to 255;
+ type rgb_triple_t is array (natural range 0 to 2) of
+ rgb_val_t;
+ type rgb_table_t is array (natural range 0 to 15) of
+ rgb_triple_t;
+
+ -----------------------------------------------------------------------------
+ -- Simple RGB Value Array
+ --
+ -- Refer to http://junior.apk.net/~drushel/pub/coleco/twwmca/wk970202.html
+ -- This is the MF & MdK variant. Note: only the upper three bits are used.
+ --
+ --
+ constant compat_rgb_table_c : rgb_table_t := (
+ -- R G B
+ ( 0, 0, 0), -- Transparent
+ ( 0, 0, 0), -- Black
+ ( 32, 192, 32), -- Medium Green
+ ( 96, 224, 96), -- Light Green
+ ( 32, 32, 224), -- Dark Blue
+ ( 64, 96, 224), -- Light Blue
+ (160, 32, 32), -- Dark Red
+ ( 64, 192, 224), -- Cyan
+ (224, 32, 32), -- Medium Red
+ (224, 96, 96), -- Light Red
+ (192, 192, 32), -- Dark Yellow
+ (192, 192, 128), -- Light Yellow
+ ( 32, 128, 32), -- Dark Green
+ (192, 64, 160), -- Magenta
+ (160, 160, 160), -- Gray
+ (224, 224, 224) -- White
+ );
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Full RGB Value Array
+ --
+ -- Refer to tms9928a.c of the MAME source distribution.
+ --
+ constant full_rgb_table_c : rgb_table_t := (
+ -- R G B
+ ( 0, 0, 0), -- Transparent RGB
+ ( 0, 0, 0), -- Black 000
+ ( 33, 200, 66), -- Medium Green 162
+ ( 94, 220, 120), -- Light Green 263
+ ( 84, 85, 237), -- Dark Blue 227
+ (125, 118, 252), -- Light Blue 337
+ (212, 82, 77), -- Dark Red 622
+ ( 66, 235, 245), -- Cyan 277
+ (252, 85, 84), -- Medium Red 722
+ (255, 121, 120), -- Light Red 733
+ (212, 193, 84), -- Dark Yellow 662
+ (230, 206, 128), -- Light Yellow 764
+ ( 33, 176, 59), -- Dark Green 151
+ (201, 91, 186), -- Magenta 625
+ (204, 204, 204), -- Gray 333
+ (255, 255, 255) -- White 777
+ );
+ --
+ -----------------------------------------------------------------------------
+
+end vdp18_col_pack;
diff --git a/common/Video/vdp18/vdp18_comp_pack-p.vhd b/common/Video/vdp18/vdp18_comp_pack-p.vhd
new file mode 100644
index 00000000..b24b866a
--- /dev/null
+++ b/common/Video/vdp18/vdp18_comp_pack-p.vhd
@@ -0,0 +1,205 @@
+-------------------------------------------------------------------------------
+--
+-- $Id: vdp18_comp_pack-p.vhd,v 1.23 2006/02/28 22:30:41 arnim Exp $
+--
+-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.vdp18_pack.opmode_t;
+use work.vdp18_pack.hv_t;
+use work.vdp18_pack.access_t;
+
+package vdp18_comp_pack is
+
+ component vdp18_clk_gen
+ port (
+ clock_i : in std_logic;
+ clk_en_10m7_i : in std_logic;
+ reset_i : in boolean;
+ clk_en_5m37_o : out boolean;
+ clk_en_3m58_o : out boolean;
+ clk_en_2m68_o : out boolean
+ );
+ end component;
+
+ component vdp18_hor_vert
+ port (
+ clock_i : in std_logic;
+ clk_en_5m37_i : in boolean;
+ reset_i : in boolean;
+ opmode_i : in opmode_t;
+ ntsc_pal_i : in std_logic;
+ num_pix_o : out hv_t;
+ num_line_o : out hv_t;
+ vert_inc_o : out boolean;
+ hsync_n_o : out std_logic;
+ vsync_n_o : out std_logic;
+ blank_o : out boolean;
+ cnt_hor_o : out std_logic_vector(8 downto 0);
+ cnt_ver_o : out std_logic_vector(7 downto 0)
+ );
+ end component;
+
+ component vdp18_ctrl
+ port (
+ clock_i : in std_logic;
+ clk_en_5m37_i : in boolean;
+ reset_i : in boolean;
+ opmode_i : in opmode_t;
+ vram_read_i : in boolean;
+ vram_write_i : in boolean;
+ vram_ce_o : out std_logic;
+ vram_oe_o : out std_logic;
+ num_pix_i : in hv_t;
+ num_line_i : in hv_t;
+ vert_inc_i : in boolean;
+ reg_blank_i : in boolean;
+ reg_size1_i : in boolean;
+ stop_sprite_i : in boolean;
+ clk_en_acc_o : out boolean;
+ access_type_o : out access_t;
+ vert_active_o : out boolean;
+ hor_active_o : out boolean;
+ irq_o : out boolean
+ );
+ end component;
+
+ component vdp18_cpuio
+ port (
+ clock_i : in std_logic;
+ clk_en_10m7_i : in boolean;
+ clk_en_acc_i : in boolean;
+ reset_i : in boolean;
+ rd_i : in boolean;
+ wr_i : in boolean;
+ mode_i : in std_logic;
+ cd_i : in std_logic_vector(0 to 7);
+ cd_o : out std_logic_vector(0 to 7);
+ cd_oe_o : out std_logic;
+ access_type_i : in access_t;
+ opmode_o : out opmode_t;
+ vram_read_o : out boolean;
+ vram_write_o : out boolean;
+ vram_we_o : out std_logic;
+ vram_a_o : out std_logic_vector(0 to 13);
+ vram_d_o : out std_logic_vector(0 to 7);
+ vram_d_i : in std_logic_vector(0 to 7);
+ spr_coll_i : in boolean;
+ spr_5th_i : in boolean;
+ spr_5th_num_i : in std_logic_vector(0 to 4);
+ reg_ev_o : out boolean;
+ reg_16k_o : out boolean;
+ reg_blank_o : out boolean;
+ reg_size1_o : out boolean;
+ reg_mag1_o : out boolean;
+ reg_ntb_o : out std_logic_vector(0 to 3);
+ reg_ctb_o : out std_logic_vector(0 to 7);
+ reg_pgb_o : out std_logic_vector(0 to 2);
+ reg_satb_o : out std_logic_vector(0 to 6);
+ reg_spgb_o : out std_logic_vector(0 to 2);
+ reg_col1_o : out std_logic_vector(0 to 3);
+ reg_col0_o : out std_logic_vector(0 to 3);
+ irq_i : in boolean;
+ int_n_o : out std_logic
+ );
+ end component;
+
+ component vdp18_addr_mux
+ port (
+ access_type_i : in access_t;
+ opmode_i : in opmode_t;
+ num_line_i : in hv_t;
+ reg_ntb_i : in std_logic_vector(0 to 3);
+ reg_ctb_i : in std_logic_vector(0 to 7);
+ reg_pgb_i : in std_logic_vector(0 to 2);
+ reg_satb_i : in std_logic_vector(0 to 6);
+ reg_spgb_i : in std_logic_vector(0 to 2);
+ reg_size1_i : in boolean;
+ cpu_vram_a_i : in std_logic_vector(0 to 13);
+ pat_table_i : in std_logic_vector(0 to 9);
+ pat_name_i : in std_logic_vector(0 to 7);
+ spr_num_i : in std_logic_vector(0 to 4);
+ spr_line_i : in std_logic_vector(0 to 3);
+ spr_name_i : in std_logic_vector(0 to 7);
+ vram_a_o : out std_logic_vector(0 to 13)
+ );
+ end component;
+
+ component vdp18_pattern
+ port (
+ clock_i : in std_logic;
+ clk_en_5m37_i : in boolean;
+ clk_en_acc_i : in boolean;
+ reset_i : in boolean;
+ opmode_i : in opmode_t;
+ access_type_i : in access_t;
+ num_line_i : in hv_t;
+ vram_d_i : in std_logic_vector(0 to 7);
+ vert_inc_i : in boolean;
+ vsync_n_i : in std_logic;
+ reg_col1_i : in std_logic_vector(0 to 3);
+ reg_col0_i : in std_logic_vector(0 to 3);
+ pat_table_o : out std_logic_vector(0 to 9);
+ pat_name_o : out std_logic_vector(0 to 7);
+ pat_col_o : out std_logic_vector(0 to 3)
+ );
+ end component;
+
+ component vdp18_sprite
+ port (
+ clock_i : in std_logic;
+ clk_en_5m37_i : in boolean;
+ clk_en_acc_i : in boolean;
+ reset_i : in boolean;
+ access_type_i : in access_t;
+ num_pix_i : in hv_t;
+ num_line_i : in hv_t;
+ vram_d_i : in std_logic_vector(0 to 7);
+ vert_inc_i : in boolean;
+ reg_size1_i : in boolean;
+ reg_mag1_i : in boolean;
+ spr_5th_o : out boolean;
+ spr_5th_num_o : out std_logic_vector(0 to 4);
+ stop_sprite_o : out boolean;
+ spr_coll_o : out boolean;
+ spr_num_o : out std_logic_vector(0 to 4);
+ spr_line_o : out std_logic_vector(0 to 3);
+ spr_name_o : out std_logic_vector(0 to 7);
+ spr0_col_o : out std_logic_vector(0 to 3);
+ spr1_col_o : out std_logic_vector(0 to 3);
+ spr2_col_o : out std_logic_vector(0 to 3);
+ spr3_col_o : out std_logic_vector(0 to 3)
+ );
+ end component;
+
+ component vdp18_col_mux
+ generic (
+ compat_rgb_g : integer := 0
+ );
+ port (
+ clock_i : in std_logic;
+ clk_en_5m37_i : in boolean;
+ reset_i : in boolean;
+ vert_active_i : in boolean;
+ hor_active_i : in boolean;
+ blank_i : in boolean;
+ reg_col0_i : in std_logic_vector(0 to 3);
+ pat_col_i : in std_logic_vector(0 to 3);
+ spr0_col_i : in std_logic_vector(0 to 3);
+ spr1_col_i : in std_logic_vector(0 to 3);
+ spr2_col_i : in std_logic_vector(0 to 3);
+ spr3_col_i : in std_logic_vector(0 to 3);
+ col_o : out std_logic_vector(0 to 3);
+ rgb_r_o : out std_logic_vector(0 to 7);
+ rgb_g_o : out std_logic_vector(0 to 7);
+ rgb_b_o : out std_logic_vector(0 to 7)
+ );
+ end component;
+
+end vdp18_comp_pack;
diff --git a/common/Video/vdp18/vdp18_core.vhd b/common/Video/vdp18/vdp18_core.vhd
new file mode 100644
index 00000000..d263b914
--- /dev/null
+++ b/common/Video/vdp18/vdp18_core.vhd
@@ -0,0 +1,394 @@
+-------------------------------------------------------------------------------
+--
+-- Synthesizable model of TI's TMS9918A, TMS9928A, TMS9929A.
+--
+-- $Id: vdp18_core.vhd,v 1.28 2006/06/18 10:47:01 arnim Exp $
+--
+-- Core Toplevel
+--
+-- Notes:
+-- This core implements a simple VRAM interface which is suitable for a
+-- synchronous SRAM component. There is currently no support of the
+-- original DRAM interface.
+--
+-- Please be aware that the colors might me slightly different from the
+-- original TMS9918. It is assumed that the simplified conversion to RGB
+-- encoding is equivalent to the compatability mode of the V9938.
+-- Implementing a 100% correct color encoding for RGB would require
+-- significantly more logic and 8-bit wide RGB DACs.
+--
+-- References:
+--
+-- * TI Data book TMS9918.pdf
+-- http://www.bitsavers.org/pdf/ti/_dataBooks/TMS9918.pdf
+--
+-- * Sean Young's tech article:
+-- http://bifi.msxnet.org/msxnet/tech/tms9918a.txt
+--
+-- * Paul Urbanus' discussion of the timing details
+-- http://bifi.msxnet.org/msxnet/tech/tmsposting.txt
+--
+-- * Richard F. Drushel's article series
+-- "This Week With My Coleco ADAM"
+-- http://junior.apk.net/~drushel/pub/coleco/twwmca/index.html
+--
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity vdp18_core is
+ generic (
+ compat_rgb_g : integer := 0
+ );
+ port (
+ -- Global Interface -------------------------------------------------------
+ clock_i : in std_logic;
+ clk_en_10m7_i : in std_logic;
+ clk_en_5m37_i : in std_logic;
+ reset_n_i : in std_logic;
+ -- CPU Interface ----------------------------------------------------------
+ csr_n_i : in std_logic;
+ csw_n_i : in std_logic;
+ mode_i : in std_logic;
+ int_n_o : out std_logic;
+ cd_i : in std_logic_vector(0 to 7);
+ cd_o : out std_logic_vector(0 to 7);
+ -- VRAM Interface ---------------------------------------------------------
+ vram_ce_o : out std_logic;
+ vram_oe_o : out std_logic;
+ vram_we_o : out std_logic;
+ vram_a_o : out std_logic_vector(0 to 13);
+ vram_d_o : out std_logic_vector(0 to 7);
+ vram_d_i : in std_logic_vector(0 to 7);
+ -- Video Interface --------------------------------------------------------
+ col_o : out std_logic_vector(0 to 3);
+ cnt_hor_o : out std_logic_vector(8 downto 0);
+ cnt_ver_o : out std_logic_vector(7 downto 0);
+ rgb_r_o : out std_logic_vector(0 to 7);
+ rgb_g_o : out std_logic_vector(0 to 7);
+ rgb_b_o : out std_logic_vector(0 to 7);
+ hsync_n_o : out std_logic;
+ vsync_n_o : out std_logic;
+ comp_sync_n_o : out std_logic
+ );
+
+end vdp18_core;
+
+
+use work.vdp18_comp_pack.all;
+use work.vdp18_pack.opmode_t;
+use work.vdp18_pack.hv_t;
+use work.vdp18_pack.access_t;
+use work.vdp18_pack.to_boolean_f;
+
+architecture struct of vdp18_core is
+
+ signal reset_s : boolean;
+
+ signal clk_en_10m7_s,
+ clk_en_5m37_s,
+ clk_en_acc_s : boolean;
+
+ signal opmode_s : opmode_t;
+
+ signal access_type_s : access_t;
+
+ signal num_pix_s,
+ num_line_s : hv_t;
+ signal hsync_n_s,
+ vsync_n_s : std_logic;
+ signal blank_s : boolean;
+
+ signal vert_inc_s : boolean;
+
+ signal reg_blank_s,
+ reg_size1_s,
+ reg_mag1_s : boolean;
+
+ signal spr_5th_s : boolean;
+ signal spr_5th_num_s : std_logic_vector(0 to 4);
+
+ signal stop_sprite_s : boolean;
+ signal vert_active_s,
+ hor_active_s : boolean;
+
+ signal rd_s,
+ wr_s : boolean;
+
+ signal reg_ntb_s : std_logic_vector(0 to 3);
+ signal reg_ctb_s : std_logic_vector(0 to 7);
+ signal reg_pgb_s : std_logic_vector(0 to 2);
+ signal reg_satb_s : std_logic_vector(0 to 6);
+ signal reg_spgb_s : std_logic_vector(0 to 2);
+ signal reg_col1_s,
+ reg_col0_s : std_logic_vector(0 to 3);
+ signal cpu_vram_a_s : std_logic_vector(0 to 13);
+
+ signal pat_table_s : std_logic_vector(0 to 9);
+ signal pat_name_s : std_logic_vector(0 to 7);
+ signal pat_col_s : std_logic_vector(0 to 3);
+
+ signal spr_num_s : std_logic_vector(0 to 4);
+ signal spr_line_s : std_logic_vector(0 to 3);
+ signal spr_name_s : std_logic_vector(0 to 7);
+ signal spr0_col_s,
+ spr1_col_s,
+ spr2_col_s,
+ spr3_col_s : std_logic_vector(0 to 3);
+ signal spr_coll_s : boolean;
+
+ signal irq_s : boolean;
+
+-- signal false_s : boolean;
+
+ signal vram_read_s : boolean;
+ signal vram_write_s : boolean;
+
+begin
+
+ -- temporary defaults
+ -- false_s <= false;
+
+ clk_en_10m7_s <= to_boolean_f(clk_en_10m7_i);
+ clk_en_5m37_s <= to_boolean_f(clk_en_5m37_i);
+ rd_s <= not to_boolean_f(csr_n_i);
+ wr_s <= not to_boolean_f(csw_n_i);
+
+ reset_s <= reset_n_i = '0';
+
+ -----------------------------------------------------------------------------
+ -- Horizontal and Vertical Timing Generator
+ -----------------------------------------------------------------------------
+ hor_vert_b : vdp18_hor_vert
+ port map (
+ clock_i => clock_i,
+ clk_en_5m37_i => clk_en_5m37_s,
+ reset_i => reset_s,
+ opmode_i => opmode_s,
+ ntsc_pal_i => '0', -- NTSC
+ num_pix_o => num_pix_s,
+ num_line_o => num_line_s,
+ vert_inc_o => vert_inc_s,
+ hsync_n_o => hsync_n_s,
+ vsync_n_o => vsync_n_s,
+ blank_o => blank_s,
+ cnt_hor_o => cnt_hor_o,
+ cnt_ver_o => cnt_ver_o
+ );
+
+ hsync_n_o <= hsync_n_s;
+ vsync_n_o <= vsync_n_s;
+ comp_sync_n_o <= not (hsync_n_s xor vsync_n_s);
+
+
+ -----------------------------------------------------------------------------
+ -- Control Module
+ -----------------------------------------------------------------------------
+ ctrl_b : vdp18_ctrl
+ port map (
+ clock_i => clock_i,
+ clk_en_5m37_i => clk_en_5m37_s,
+ reset_i => reset_s,
+ opmode_i => opmode_s,
+ vram_read_i => vram_read_s,
+ vram_write_i => vram_write_s,
+ vram_ce_o => vram_ce_o,
+ vram_oe_o => vram_oe_o,
+ num_pix_i => num_pix_s,
+ num_line_i => num_line_s,
+ vert_inc_i => vert_inc_s,
+ reg_blank_i => reg_blank_s,
+ reg_size1_i => reg_size1_s,
+ stop_sprite_i => stop_sprite_s,
+ clk_en_acc_o => clk_en_acc_s,
+ access_type_o => access_type_s,
+ vert_active_o => vert_active_s,
+ hor_active_o => hor_active_s,
+ irq_o => irq_s
+ );
+
+
+ -----------------------------------------------------------------------------
+ -- CPU I/O Module
+ -----------------------------------------------------------------------------
+ cpu_io_b : vdp18_cpuio
+ port map (
+ clock_i => clock_i,
+ clk_en_10m7_i => clk_en_10m7_s,
+ clk_en_acc_i => clk_en_acc_s,
+ reset_i => reset_s,
+ rd_i => rd_s,
+ wr_i => wr_s,
+ mode_i => mode_i,
+ cd_i => cd_i,
+ cd_o => cd_o,
+ cd_oe_o => open,
+ access_type_i => access_type_s,
+ opmode_o => opmode_s,
+ vram_read_o => vram_read_s,
+ vram_write_o => vram_write_s,
+ vram_we_o => vram_we_o,
+ vram_a_o => cpu_vram_a_s,
+ vram_d_o => vram_d_o,
+ vram_d_i => vram_d_i,
+ spr_coll_i => spr_coll_s,
+ spr_5th_i => spr_5th_s,
+ spr_5th_num_i => spr_5th_num_s,
+ reg_ev_o => open,
+ reg_16k_o => open,
+ reg_blank_o => reg_blank_s,
+ reg_size1_o => reg_size1_s,
+ reg_mag1_o => reg_mag1_s,
+ reg_ntb_o => reg_ntb_s,
+ reg_ctb_o => reg_ctb_s,
+ reg_pgb_o => reg_pgb_s,
+ reg_satb_o => reg_satb_s,
+ reg_spgb_o => reg_spgb_s,
+ reg_col1_o => reg_col1_s,
+ reg_col0_o => reg_col0_s,
+ irq_i => irq_s,
+ int_n_o => int_n_o
+ );
+
+
+ -----------------------------------------------------------------------------
+ -- VRAM Address Multiplexer
+ -----------------------------------------------------------------------------
+ addr_mux_b : vdp18_addr_mux
+ port map (
+ access_type_i => access_type_s,
+ opmode_i => opmode_s,
+ num_line_i => num_line_s,
+ reg_ntb_i => reg_ntb_s,
+ reg_ctb_i => reg_ctb_s,
+ reg_pgb_i => reg_pgb_s,
+ reg_satb_i => reg_satb_s,
+ reg_spgb_i => reg_spgb_s,
+ reg_size1_i => reg_size1_s,
+ cpu_vram_a_i => cpu_vram_a_s,
+ pat_table_i => pat_table_s,
+ pat_name_i => pat_name_s,
+ spr_num_i => spr_num_s,
+ spr_line_i => spr_line_s,
+ spr_name_i => spr_name_s,
+ vram_a_o => vram_a_o
+ );
+
+
+ -----------------------------------------------------------------------------
+ -- Pattern Generator
+ -----------------------------------------------------------------------------
+ pattern_b : vdp18_pattern
+ port map (
+ clock_i => clock_i,
+ clk_en_5m37_i => clk_en_5m37_s,
+ clk_en_acc_i => clk_en_acc_s,
+ reset_i => reset_s,
+ opmode_i => opmode_s,
+ access_type_i => access_type_s,
+ num_line_i => num_line_s,
+ vram_d_i => vram_d_i,
+ vert_inc_i => vert_inc_s,
+ vsync_n_i => vsync_n_s,
+ reg_col1_i => reg_col1_s,
+ reg_col0_i => reg_col0_s,
+ pat_table_o => pat_table_s,
+ pat_name_o => pat_name_s,
+ pat_col_o => pat_col_s
+ );
+
+
+ -----------------------------------------------------------------------------
+ -- Sprite Generator
+ -----------------------------------------------------------------------------
+ sprite_b : vdp18_sprite
+ port map (
+ clock_i => clock_i,
+ clk_en_5m37_i => clk_en_5m37_s,
+ clk_en_acc_i => clk_en_acc_s,
+ reset_i => reset_s,
+ access_type_i => access_type_s,
+ num_pix_i => num_pix_s,
+ num_line_i => num_line_s,
+ vram_d_i => vram_d_i,
+ vert_inc_i => vert_inc_s,
+ reg_size1_i => reg_size1_s,
+ reg_mag1_i => reg_mag1_s,
+ spr_5th_o => spr_5th_s,
+ spr_5th_num_o => spr_5th_num_s,
+ stop_sprite_o => stop_sprite_s,
+ spr_coll_o => spr_coll_s,
+ spr_num_o => spr_num_s,
+ spr_line_o => spr_line_s,
+ spr_name_o => spr_name_s,
+ spr0_col_o => spr0_col_s,
+ spr1_col_o => spr1_col_s,
+ spr2_col_o => spr2_col_s,
+ spr3_col_o => spr3_col_s
+ );
+
+
+ -----------------------------------------------------------------------------
+ -- Color Multiplexer
+ -----------------------------------------------------------------------------
+ col_mux_b : vdp18_col_mux
+ generic map (
+ compat_rgb_g => compat_rgb_g
+ )
+ port map (
+ clock_i => clock_i,
+ clk_en_5m37_i => clk_en_5m37_s,
+ reset_i => reset_s,
+ vert_active_i => vert_active_s,
+ hor_active_i => hor_active_s,
+ blank_i => blank_s,
+ reg_col0_i => reg_col0_s,
+ pat_col_i => pat_col_s,
+ spr0_col_i => spr0_col_s,
+ spr1_col_i => spr1_col_s,
+ spr2_col_i => spr2_col_s,
+ spr3_col_i => spr3_col_s,
+ col_o => col_o,
+ rgb_r_o => rgb_r_o,
+ rgb_g_o => rgb_g_o,
+ rgb_b_o => rgb_b_o
+ );
+
+end struct;
diff --git a/common/Video/vdp18/vdp18_core_comp_pack-p.vhd b/common/Video/vdp18/vdp18_core_comp_pack-p.vhd
new file mode 100644
index 00000000..8cf260c0
--- /dev/null
+++ b/common/Video/vdp18/vdp18_core_comp_pack-p.vhd
@@ -0,0 +1,49 @@
+-------------------------------------------------------------------------------
+--
+-- $Id: vdp18_core_comp_pack-p.vhd,v 1.10 2006/02/28 22:30:41 arnim Exp $
+--
+-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+package vdp18_core_comp_pack is
+
+ component vdp18_core
+ generic (
+ is_pal_g : boolean := false;
+ compat_rgb_g : integer := 0
+ );
+ port (
+ clock_i : in std_logic;
+ clk_en_10m7_i : in std_logic;
+ reset_n_i : in std_logic;
+ csr_n_i : in std_logic;
+ csw_n_i : in std_logic;
+ mode_i : in std_logic;
+ int_n_o : out std_logic;
+ cd_i : in std_logic_vector(0 to 7);
+ cd_o : out std_logic_vector(0 to 7);
+ vram_ce_o : out std_logic;
+ vram_oe_o : out std_logic;
+ vram_we_o : out std_logic;
+ vram_a_o : out std_logic_vector(0 to 13);
+ vram_d_o : out std_logic_vector(0 to 7);
+ vram_d_i : in std_logic_vector(0 to 7);
+ col_o : out std_logic_vector(0 to 3);
+ cnt_hor_o : out std_logic_vector(8 downto 0);
+ cnt_ver_o : out std_logic_vector(7 downto 0);
+ rgb_r_o : out std_logic_vector(0 to 7);
+ rgb_g_o : out std_logic_vector(0 to 7);
+ rgb_b_o : out std_logic_vector(0 to 7);
+ hsync_n_o : out std_logic;
+ vsync_n_o : out std_logic;
+ comp_sync_n_o : out std_logic
+ );
+ end component;
+
+end vdp18_core_comp_pack;
diff --git a/common/Video/vdp18/vdp18_cpuio.vhd b/common/Video/vdp18/vdp18_cpuio.vhd
new file mode 100644
index 00000000..bdf78042
--- /dev/null
+++ b/common/Video/vdp18/vdp18_cpuio.vhd
@@ -0,0 +1,572 @@
+-------------------------------------------------------------------------------
+--
+-- Synthesizable model of TI's TMS9918A, TMS9928A, TMS9929A.
+--
+-- $Id: vdp18_cpuio.vhd,v 1.17 2006/06/18 10:47:01 arnim Exp $
+--
+-- CPU I/O Interface Module
+--
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.vdp18_pack.access_t;
+use work.vdp18_pack.opmode_t;
+
+entity vdp18_cpuio is
+
+ port (
+ clock_i : in std_logic;
+ clk_en_10m7_i : in boolean;
+ clk_en_acc_i : in boolean;
+ reset_i : in boolean;
+ rd_i : in boolean;
+ wr_i : in boolean;
+ mode_i : in std_logic;
+ cd_i : in std_logic_vector(0 to 7);
+ cd_o : out std_logic_vector(0 to 7);
+ cd_oe_o : out std_logic;
+ access_type_i : in access_t;
+ opmode_o : out opmode_t;
+ vram_read_o : out boolean;
+ vram_write_o : out boolean;
+ vram_we_o : out std_logic;
+ vram_a_o : out std_logic_vector(0 to 13);
+ vram_d_o : out std_logic_vector(0 to 7);
+ vram_d_i : in std_logic_vector(0 to 7);
+ spr_coll_i : in boolean;
+ spr_5th_i : in boolean;
+ spr_5th_num_i : in std_logic_vector(0 to 4);
+ reg_ev_o : out boolean;
+ reg_16k_o : out boolean;
+ reg_blank_o : out boolean;
+ reg_size1_o : out boolean;
+ reg_mag1_o : out boolean;
+ reg_ntb_o : out std_logic_vector(0 to 3);
+ reg_ctb_o : out std_logic_vector(0 to 7);
+ reg_pgb_o : out std_logic_vector(0 to 2);
+ reg_satb_o : out std_logic_vector(0 to 6);
+ reg_spgb_o : out std_logic_vector(0 to 2);
+ reg_col1_o : out std_logic_vector(0 to 3);
+ reg_col0_o : out std_logic_vector(0 to 3);
+ irq_i : in boolean;
+ int_n_o : out std_logic
+ );
+
+end vdp18_cpuio;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+use work.vdp18_pack.all;
+
+architecture rtl of vdp18_cpuio is
+
+ type state_t is (ST_IDLE,
+ ST_RD_MODE0, ST_WR_MODE0,
+ ST_RD_MODE1,
+ ST_WR_MODE1_1ST, ST_WR_MODE1_1ST_IDLE,
+ ST_WR_MODE1_2ND_VREAD, ST_WR_MODE1_2ND_VWRITE,
+ ST_WR_MODE1_2ND_RWRITE);
+ signal state_s,
+ state_q : state_t;
+
+ signal buffer_q : std_logic_vector(0 to 7);
+
+ signal addr_q : unsigned(0 to 13);
+
+ signal incr_addr_s,
+ load_addr_s : boolean;
+
+ signal wrbuf_cpu_s : boolean;
+ signal sched_rdvram_s,
+ rdvram_sched_q,
+ rdvram_q : boolean;
+ signal abort_wrvram_s,
+ sched_wrvram_s,
+ wrvram_sched_q,
+ wrvram_q : boolean;
+
+ signal write_tmp_s : boolean;
+ signal tmp_q : std_logic_vector(0 to 7);
+ signal write_reg_s : boolean;
+
+ -- control register bits ----------------------------------------------------
+ type ctrl_reg_t is array (natural range 7 downto 0) of
+ std_logic_vector(0 to 7);
+ signal ctrl_reg_q : ctrl_reg_t;
+
+ -- status register ----------------------------------------------------------
+ signal status_reg_s : std_logic_vector(0 to 7);
+ signal destr_rd_status_s : boolean;
+ signal sprite_5th_q : boolean;
+ signal sprite_5th_num_q : std_logic_vector(0 to 4);
+ signal sprite_coll_q : boolean;
+ signal int_n_q : std_logic;
+
+
+ type read_mux_t is (RDMUX_STATUS, RDMUX_READAHEAD);
+ signal read_mux_s : read_mux_t;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process seq
+ --
+ -- Purpose:
+ -- Implements the sequential elements.
+ --
+ seq: process (clock_i, reset_i)
+ variable incr_addr_v : boolean;
+ begin
+ if reset_i then
+ state_q <= ST_IDLE;
+ buffer_q <= (others => '0');
+ addr_q <= (others => '0');
+ rdvram_sched_q <= false;
+ rdvram_q <= false;
+ wrvram_sched_q <= false;
+ wrvram_q <= false;
+
+ elsif clock_i'event and clock_i = '1' then
+ -- default assignments
+ incr_addr_v := incr_addr_s;
+
+ if clk_en_10m7_i then
+ -- update state vector ------------------------------------------------
+ state_q <= state_s;
+
+ -- buffer and flag control --------------------------------------------
+ if wrbuf_cpu_s then
+ -- write read-ahead buffer from CPU bus
+ buffer_q <= cd_i;
+ -- immediately stop read-ahead
+ rdvram_sched_q <= false;
+ rdvram_q <= false;
+ elsif clk_en_acc_i and rdvram_q and access_type_i = AC_CPU then
+ -- write read-ahead buffer from VRAM during CPU access slot
+ buffer_q <= vram_d_i;
+ -- stop scanning for CPU data
+ rdvram_q <= false;
+ -- increment read-ahead address
+ incr_addr_v := true;
+ end if;
+
+ if sched_rdvram_s then
+ -- immediately stop write-back
+ wrvram_sched_q <= false;
+ wrvram_q <= false;
+ -- schedule read-ahead
+ rdvram_sched_q <= true;
+ end if;
+
+ if sched_wrvram_s then
+ -- schedule write-back
+ wrvram_sched_q <= true;
+ end if;
+
+ if abort_wrvram_s then
+ -- stop scanning for write-back
+ wrvram_q <= false;
+ end if;
+
+ if rdvram_sched_q and clk_en_acc_i then
+ -- align scheduled read-ahead with access slot phase
+ rdvram_sched_q <= false;
+ rdvram_q <= true;
+ end if;
+ if wrvram_sched_q and clk_en_acc_i then
+ -- align scheduled write-back with access slot phase
+ wrvram_sched_q <= false;
+ wrvram_q <= true;
+ end if;
+
+ -- manage address -----------------------------------------------------
+ if load_addr_s then
+ addr_q(6 to 13) <= unsigned(tmp_q);
+ addr_q(0 to 5) <= unsigned(cd_i(2 to 7));
+ elsif incr_addr_v then
+ addr_q <= addr_q + 1;
+ end if;
+
+ end if;
+ end if;
+ end process seq;
+ --
+ -----------------------------------------------------------------------------
+
+ vram_read_o <= rdvram_q;
+ vram_write_o <= wrvram_q;
+
+ -----------------------------------------------------------------------------
+ -- Process wback_ctrl
+ --
+ -- Purpose:
+ -- Write-back control.
+ --
+ wback_ctrl: process (clk_en_acc_i,
+ access_type_i,
+ wrvram_q)
+ begin
+ -- default assignments
+ abort_wrvram_s <= false;
+ incr_addr_s <= false;
+ vram_we_o <= '0';
+
+ if wrvram_q then
+ if access_type_i = AC_CPU then
+ -- signal write access to VRAM
+ vram_we_o <= '1';
+
+ if clk_en_acc_i then
+ -- clear write-back flag and increment address
+ abort_wrvram_s <= true;
+ incr_addr_s <= true;
+ end if;
+ end if;
+ end if;
+ end process wback_ctrl;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process reg_if
+ --
+ -- Purpose:
+ -- Implements the register interface.
+ --
+ reg_if: process (clock_i, reset_i)
+ variable reg_addr_v : unsigned(0 to 2);
+ begin
+ if reset_i then
+ tmp_q <= (others => '0');
+ ctrl_reg_q <= (others => (others => '0'));
+ sprite_coll_q <= false;
+ sprite_5th_q <= false;
+ sprite_5th_num_q <= (others => '0');
+ int_n_q <= '1';
+ ctrl_reg_q(1) <= X"C0";
+ ctrl_reg_q(2) <= X"02";
+ ctrl_reg_q(3) <= X"2C";
+ ctrl_reg_q(7) <= X"F7";
+
+ elsif clock_i'event and clock_i = '1' then
+ if clk_en_10m7_i then
+ -- Temporary register -------------------------------------------------
+ if write_tmp_s then
+ tmp_q <= cd_i;
+ end if;
+
+ -- Registers 0 to 7 ---------------------------------------------------
+ if write_reg_s then
+ reg_addr_v := unsigned(cd_i(5 to 7));
+ ctrl_reg_q(to_integer(reg_addr_v)) <= tmp_q;
+ end if;
+
+ end if;
+
+ -- Fifth sprite handling ------------------------------------------------
+ if spr_5th_i and not sprite_5th_q then
+ sprite_5th_q <= true;
+ sprite_5th_num_q <= spr_5th_num_i;
+ elsif destr_rd_status_s then
+ sprite_5th_q <= false;
+ end if;
+
+ -- Sprite collision flag ------------------------------------------------
+ if spr_coll_i then
+ sprite_coll_q <= true;
+ elsif destr_rd_status_s then
+ sprite_coll_q <= false;
+ end if;
+
+ -- Interrupt ------------------------------------------------------------
+ if irq_i then
+ int_n_q <= '0';
+ elsif destr_rd_status_s then
+ int_n_q <= '1';
+ end if;
+ end if;
+ end process reg_if;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process access_ctrl
+ --
+ -- Purpose:
+ -- Implements the combinational logic for the CPU I/F FSM.
+ -- Decodes the CPU I/F FSM state and generates the control signals for the
+ -- register and VRAM logic.
+ --
+ access_ctrl: process (state_q,
+ rd_i, wr_i,
+ mode_i,
+ cd_i)
+ type transfer_mode_t is (TM_NONE,
+ TM_RD_MODE0, TM_WR_MODE0,
+ TM_RD_MODE1, TM_WR_MODE1);
+ variable transfer_mode_v : transfer_mode_t;
+ begin
+ -- default assignments
+ state_s <= state_q;
+ sched_rdvram_s <= false;
+ sched_wrvram_s <= false;
+ wrbuf_cpu_s <= false;
+ write_tmp_s <= false;
+ write_reg_s <= false;
+ load_addr_s <= false;
+ read_mux_s <= RDMUX_STATUS;
+ destr_rd_status_s <= false;
+
+ -- determine transfer mode
+ transfer_mode_v := TM_NONE;
+ if mode_i = '0' then
+ if rd_i then
+ transfer_mode_v := TM_RD_MODE0;
+ end if;
+ if wr_i then
+ transfer_mode_v := TM_WR_MODE0;
+ end if;
+ else
+ if rd_i then
+ transfer_mode_v := TM_RD_MODE1;
+ end if;
+ if wr_i then
+ transfer_mode_v := TM_WR_MODE1;
+ end if;
+ end if;
+
+ -- FSM state transitions
+ case state_q is
+ -- ST_IDLE: waiting for CPU access --------------------------------------
+ when ST_IDLE =>
+ case transfer_mode_v is
+ when TM_RD_MODE0 =>
+ state_s <= ST_RD_MODE0;
+ when TM_WR_MODE0 =>
+ state_s <= ST_WR_MODE0;
+ when TM_RD_MODE1 =>
+ state_s <= ST_RD_MODE1;
+ when TM_WR_MODE1 =>
+ state_s <= ST_WR_MODE1_1ST;
+ when others =>
+ null;
+ end case;
+
+ -- ST_RD_MODE0: read from VRAM ------------------------------------------
+ when ST_RD_MODE0 =>
+ -- set read mux
+ read_mux_s <= RDMUX_READAHEAD;
+
+ if transfer_mode_v = TM_NONE then
+ -- CPU finished read access:
+ -- schedule new read-ahead and return to idle
+ state_s <= ST_IDLE;
+ sched_rdvram_s <= true;
+ end if;
+
+ -- ST_WR_MODE0: write to VRAM -------------------------------------------
+ when ST_WR_MODE0 =>
+ -- write data from CPU to write-back/read-ahead buffer
+ wrbuf_cpu_s <= true;
+
+ if transfer_mode_v = TM_NONE then
+ -- CPU finished write access:
+ -- schedule new write-back and return to idle
+ state_s <= ST_IDLE;
+ sched_wrvram_s <= true;
+ end if;
+
+ -- ST_RD_MODE1: read from status register -------------------------------
+ when ST_RD_MODE1 =>
+ -- set read mux
+ read_mux_s <= RDMUX_STATUS;
+
+ if transfer_mode_v = TM_NONE then
+ -- CPU finished read access:
+ -- destructive read of status register and return to IDLE
+ destr_rd_status_s <= true;
+ state_s <= ST_IDLE;
+ end if;
+
+ -- ST_WR_MODE1_1ST: save first byte -------------------------------------
+ when ST_WR_MODE1_1ST =>
+ -- update temp register
+ write_tmp_s <= true;
+
+ if transfer_mode_v = TM_NONE then
+ -- CPU finished write access:
+ -- become idle but remember that the first byte of a paired write
+ -- has been written
+ state_s <= ST_WR_MODE1_1ST_IDLE;
+ end if;
+
+ -- ST_WR_MODE1_1ST_IDLE: wait for next access ---------------------------
+ when ST_WR_MODE1_1ST_IDLE =>
+ -- determine type of next access
+ case transfer_mode_v is
+ when TM_RD_MODE0 =>
+ state_s <= ST_RD_MODE0;
+ when TM_WR_MODE0 =>
+ state_s <= ST_WR_MODE0;
+ when TM_RD_MODE1 =>
+ state_s <= ST_RD_MODE1;
+ when TM_WR_MODE1 =>
+ case cd_i(0 to 1) is
+ when "00" =>
+ state_s <= ST_WR_MODE1_2ND_VREAD;
+ when "01" =>
+ state_s <= ST_WR_MODE1_2ND_VWRITE;
+ when "10" | "11" =>
+ state_s <= ST_WR_MODE1_2ND_RWRITE;
+ when others =>
+ null;
+ end case;
+ when others =>
+ null;
+ end case;
+
+ -- ST_WR_MODE1_2ND_VREAD: write second byte of address, then read ahead -
+ when ST_WR_MODE1_2ND_VREAD =>
+ load_addr_s <= true;
+
+ if transfer_mode_v = TM_NONE then
+ -- CPU finished write access:
+ -- schedule new read-ahead and return to idle
+ sched_rdvram_s <= true;
+ state_s <= ST_IDLE;
+ end if;
+
+ -- ST_WR_MODE1_2ND_VWRITE: write second byte of address
+ when ST_WR_MODE1_2ND_VWRITE =>
+ load_addr_s <= true;
+
+ if transfer_mode_v = TM_NONE then
+ -- CPU finished write access:
+ -- return to idle
+ state_s <= ST_IDLE;
+ end if;
+
+ -- ST_WR_MODE1_2ND_RWRITE: write to register ----------------------------
+ when ST_WR_MODE1_2ND_RWRITE =>
+ write_reg_s <= true;
+
+ if transfer_mode_v = TM_NONE then
+ -- CPU finished write access:
+ -- return to idle
+ state_s <= ST_IDLE;
+ end if;
+
+ when others =>
+ null;
+
+ end case;
+
+ end process access_ctrl;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process mode_decode
+ --
+ -- Purpose:
+ -- Decodes the display mode from the M1, M2, M3 bits.
+ --
+ mode_decode: process (ctrl_reg_q)
+ variable mode_v : std_logic_vector(0 to 2);
+ begin
+ mode_v := ctrl_reg_q(1)(3) & -- M1
+ ctrl_reg_q(1)(4) & -- M2
+ ctrl_reg_q(0)(6); -- M3
+
+ case mode_v is
+ when "000" =>
+ opmode_o <= OPMODE_GRAPH1;
+ when "001" =>
+ opmode_o <= OPMODE_GRAPH2;
+ when "010" =>
+ opmode_o <= OPMODE_MULTIC;
+ when "100" =>
+ opmode_o <= OPMODE_TEXTM;
+ when others =>
+ opmode_o <= OPMODE_TEXTM;
+ end case;
+ end process mode_decode;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Build status register
+ -----------------------------------------------------------------------------
+ status_reg_s <= not int_n_q &
+ to_std_logic_f(sprite_5th_q) &
+ to_std_logic_f(sprite_coll_q) &
+ sprite_5th_num_q;
+
+ -----------------------------------------------------------------------------
+ -- Output mapping
+ -----------------------------------------------------------------------------
+ vram_a_o <= std_logic_vector(addr_q);
+ vram_d_o <= buffer_q;
+
+ cd_o <= buffer_q when read_mux_s = RDMUX_READAHEAD else status_reg_s;
+ cd_oe_o <= '1' when rd_i else '0';
+
+ reg_ev_o <= to_boolean_f(ctrl_reg_q(0)(7));
+ reg_16k_o <= to_boolean_f(ctrl_reg_q(1)(0));
+ reg_blank_o <= not to_boolean_f(ctrl_reg_q(1)(1));
+ reg_size1_o <= to_boolean_f(ctrl_reg_q(1)(6));
+ reg_mag1_o <= to_boolean_f(ctrl_reg_q(1)(7));
+ reg_ntb_o <= ctrl_reg_q(2)(4 to 7);
+ reg_ctb_o <= ctrl_reg_q(3);
+ reg_pgb_o <= ctrl_reg_q(4)(5 to 7);
+ reg_satb_o <= ctrl_reg_q(5)(1 to 7);
+ reg_spgb_o <= ctrl_reg_q(6)(5 to 7);
+ reg_col1_o <= ctrl_reg_q(7)(0 to 3);
+ reg_col0_o <= ctrl_reg_q(7)(4 to 7);
+ int_n_o <= int_n_q or not ctrl_reg_q(1)(2);
+
+end rtl;
diff --git a/common/Video/vdp18/vdp18_ctrl.vhd b/common/Video/vdp18/vdp18_ctrl.vhd
new file mode 100644
index 00000000..6b6f8b23
--- /dev/null
+++ b/common/Video/vdp18/vdp18_ctrl.vhd
@@ -0,0 +1,410 @@
+-------------------------------------------------------------------------------
+--
+-- Synthesizable model of TI's TMS9918A, TMS9928A, TMS9929A.
+--
+-- $Id: vdp18_ctrl.vhd,v 1.26 2006/06/18 10:47:01 arnim Exp $
+--
+-- Timing Controller
+--
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+use work.vdp18_pack.opmode_t;
+use work.vdp18_pack.hv_t;
+use work.vdp18_pack.access_t;
+
+entity vdp18_ctrl is
+
+ port (
+ clock_i : in std_logic;
+ clk_en_5m37_i : in boolean;
+ reset_i : in boolean;
+ opmode_i : in opmode_t;
+ vram_read_i : in boolean;
+ vram_write_i : in boolean;
+ vram_ce_o : out std_logic;
+ vram_oe_o : out std_logic;
+ num_pix_i : in hv_t;
+ num_line_i : in hv_t;
+ vert_inc_i : in boolean;
+ reg_blank_i : in boolean;
+ reg_size1_i : in boolean;
+ stop_sprite_i : in boolean;
+ clk_en_acc_o : out boolean;
+ access_type_o : out access_t;
+ vert_active_o : out boolean;
+ hor_active_o : out boolean;
+ irq_o : out boolean
+ );
+
+end vdp18_ctrl;
+
+
+use work.vdp18_pack.all;
+
+architecture rtl of vdp18_ctrl is
+
+ -----------------------------------------------------------------------------
+ -- This enables a workaround for a bug in XST.
+ -- ISE 8.1.02i implements wrong functionality otherwise :-(
+ --
+ constant xst_bug_wa_c : boolean := true;
+ --
+ -----------------------------------------------------------------------------
+
+ signal access_type_s : access_t;
+
+ -- pragma translate_off
+ -- Testbench signals --------------------------------------------------------
+ --
+ signal ac_s : std_logic_vector(3 downto 0);
+ --
+ -----------------------------------------------------------------------------
+ -- pragma translate_on
+
+ signal vert_active_q,
+ hor_active_q : boolean;
+ signal sprite_active_q : boolean;
+ signal sprite_line_act_q : boolean;
+
+begin
+
+ -- pragma translate_off
+ -- Testbench signals --------------------------------------------------------
+ --
+ ac_s <= enum_to_vec_f(access_type_s);
+ --
+ -----------------------------------------------------------------------------
+ -- pragma translate_on
+
+
+ -----------------------------------------------------------------------------
+ -- Process decode_access
+ --
+ -- Purpose:
+ -- Decode horizontal counter value to access type.
+ --
+ decode_access: process (opmode_i,
+ num_pix_i,
+ vert_active_q,
+ sprite_line_act_q,
+ reg_size1_i)
+ variable num_pix_plus_6_v : hv_t;
+ variable mod_6_v : hv_t;
+ variable num_pix_plus_8_v : hv_t;
+ variable num_pix_plus_32_v : hv_t;
+ variable num_pix_spr_v : integer;
+ begin
+ -- default assignment
+ access_type_s <= AC_CPU;
+
+ -- prepare number of pixels for pattern operations
+ num_pix_plus_6_v := num_pix_i + 6;
+ num_pix_plus_8_v := num_pix_i + 8;
+ num_pix_plus_32_v := num_pix_i + 32;
+ num_pix_spr_v := to_integer(num_pix_i and "111111110");
+
+ case opmode_i is
+ -- Graphics I, II and Multicolor Mode -----------------------------------
+ when OPMODE_GRAPH1 |
+ OPMODE_GRAPH2 |
+ OPMODE_MULTIC =>
+ --
+ -- Patterns
+ --
+ if vert_active_q then
+ if num_pix_plus_8_v(0) = '0' then
+ if not xst_bug_wa_c then
+
+ -- original code, we want this
+ case num_pix_plus_8_v(6 to 7) is
+ when "01" =>
+ access_type_s <= AC_PNT;
+ when "10" =>
+ if opmode_i /= OPMODE_MULTIC then
+ -- no access to pattern color table in multicolor mode
+ access_type_s <= AC_PCT;
+ end if;
+ when "11" =>
+ access_type_s <= AC_PGT;
+ when others =>
+ null;
+ end case;
+
+ else
+
+ -- workaround for XST bug, we need this
+ if num_pix_plus_8_v(6 to 7) = "01" then
+ access_type_s <= AC_PNT;
+ elsif num_pix_plus_8_v(6 to 7) = "10" then
+ if opmode_i /= OPMODE_MULTIC then
+ access_type_s <= AC_PCT;
+ end if;
+ elsif num_pix_plus_8_v(6 to 7) = "11" then
+ access_type_s <= AC_PGT;
+ end if;
+
+ end if;
+ end if;
+ end if;
+
+ --
+ -- Sprite test
+ --
+ if sprite_line_act_q then
+ if num_pix_i(0) = '0' and
+ num_pix_i(0 to 5) /= "011111" and
+ num_pix_i(6 to 7) = "00" and
+ num_pix_i(4 to 5) /= "00" then
+ -- sprite test interleaved with pattern accesses
+ access_type_s <= AC_STST;
+ end if;
+ if (num_pix_plus_32_v(0 to 4) = "00000" or
+ num_pix_plus_32_v(0 to 5) = "000010") and
+ num_pix_plus_32_v(6 to 7) /= "00" then
+ -- sprite tests before starting pattern phase
+ access_type_s <= AC_STST;
+ end if;
+
+ --
+ -- Sprite Attribute Table and Sprite Pattern Table
+ --
+ case num_pix_spr_v is
+ when 250 | -78 |
+ -62 | -46 =>
+ access_type_s <= AC_SATY;
+ when 254 | -76 |
+ -60 | -44 =>
+ access_type_s <= AC_SATX;
+ when 252 | -74 |
+ -58 | -42 =>
+ access_type_s <= AC_SATN;
+ when -86 | -70 |
+ -54 | -38 =>
+ access_type_s <= AC_SATC;
+ when -84 | -68 |
+ -52 | -36 =>
+ access_type_s <= AC_SPTH;
+ when -82 | -66 |
+ -50 | -34 =>
+ if reg_size1_i then
+ access_type_s <= AC_SPTL;
+ end if;
+ when others =>
+ null;
+ end case;
+ end if;
+
+ -- Text Mode ------------------------------------------------------------
+ when OPMODE_TEXTM =>
+ if vert_active_q and
+ num_pix_plus_6_v(0) = '0' and
+ num_pix_plus_6_v(0 to 4) /= "01111" then
+ mod_6_v := mod_6_f(num_pix_plus_6_v);
+ case mod_6_v(6 to 7) is
+ when "00" =>
+ access_type_s <= AC_PNT;
+ when "10" =>
+ access_type_s <= AC_PGT;
+ when others =>
+ null;
+ end case;
+ end if;
+
+ -- Unknown --------------------------------------------------------------
+-- when others =>
+-- null;
+
+ end case;
+
+ end process decode_access;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process vert_flags
+ --
+ -- Purpose:
+ -- Track the vertical position with flags.
+ --
+ vert_flags: process (clock_i, reset_i)
+ begin
+ if reset_i then
+ vert_active_q <= false;
+ sprite_active_q <= false;
+ sprite_line_act_q <= false;
+
+ elsif clock_i'event and clock_i = '1' then
+ if clk_en_5m37_i then
+ -- line-local sprite processing
+ if sprite_active_q then
+ -- sprites are globally enabled
+ if vert_inc_i then
+ -- reload at beginning of every new line
+ -- => scan with STST
+ sprite_line_act_q <= true;
+ end if;
+
+ if num_pix_i = hv_sprite_start_c then
+ -- reload when access to sprite memory starts
+ sprite_line_act_q <= true;
+ end if;
+ end if;
+
+ if vert_inc_i then
+ -- global sprite processing
+ if reg_blank_i then
+ sprite_active_q <= false;
+ sprite_line_act_q <= false;
+ elsif num_line_i = -2 then
+ -- start at line -1
+ sprite_active_q <= true;
+ -- initialize immediately
+ sprite_line_act_q <= true;
+ elsif num_line_i = 191 then
+ -- stop at line 192
+ sprite_active_q <= false;
+ -- force stop
+ sprite_line_act_q <= false;
+ end if;
+
+ -- global vertical display
+ if reg_blank_i then
+ vert_active_q <= false;
+ elsif num_line_i = -1 then
+ -- start vertical display at line 0
+ vert_active_q <= true;
+ elsif num_line_i = 191 then
+ -- stop at line 192
+ vert_active_q <= false;
+ end if;
+ end if;
+
+ if stop_sprite_i then
+ -- stop processing of sprites in this line
+ sprite_line_act_q <= false;
+ end if;
+
+ end if;
+ end if;
+ end process vert_flags;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process hor_flags
+ --
+ -- Purpose:
+ -- Track the horizontal position.
+ --
+ hor_flags: process (clock_i, reset_i)
+ begin
+ if reset_i then
+ hor_active_q <= false;
+
+ elsif clock_i'event and clock_i = '1' then
+ if clk_en_5m37_i then
+ if not reg_blank_i and
+ num_pix_i = -1 then
+ hor_active_q <= true;
+ end if;
+
+ if opmode_i = OPMODE_TEXTM then
+ if num_pix_i = 239 then
+ hor_active_q <= false;
+ end if;
+ else
+ if num_pix_i = 255 then
+ hor_active_q <= false;
+ end if;
+ end if;
+ end if;
+ end if;
+ end process hor_flags;
+ --
+ -----------------------------------------------------------------------------
+
+ vram_ctrl: process (clock_i)
+ variable read_b_v : boolean;
+ begin
+ if rising_edge(clock_i) then
+ if clk_en_5m37_i then
+ vram_ce_o <= '0';
+ vram_oe_o <= '0';
+ if access_type_s = AC_CPU then
+ if vram_read_i and not read_b_v then
+ vram_ce_o <= '1';
+ vram_oe_o <= '1';
+ read_b_v := true;
+ elsif vram_write_i and not read_b_v then
+ vram_ce_o <= '1';
+ --
+ read_b_v := true;
+ else
+ read_b_v := false;
+ end if;
+ else
+ if not read_b_v then
+ vram_ce_o <= '1';
+ vram_oe_o <= '1';
+ read_b_v := true;
+ else
+ read_b_v := false;
+ end if;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ -----------------------------------------------------------------------------
+ -- Ouput mapping
+ -----------------------------------------------------------------------------
+ -- generate clock enable for flip-flops working on access_type
+ clk_en_acc_o <= clk_en_5m37_i and num_pix_i(8) = '1';
+ access_type_o <= access_type_s;
+ vert_active_o <= vert_active_q;
+ hor_active_o <= hor_active_q;
+ irq_o <= vert_inc_i and num_line_i = 191;
+
+end rtl;
diff --git a/common/Video/vdp18/vdp18_hor_vert.vhd b/common/Video/vdp18/vdp18_hor_vert.vhd
new file mode 100644
index 00000000..07c7e63c
--- /dev/null
+++ b/common/Video/vdp18/vdp18_hor_vert.vhd
@@ -0,0 +1,243 @@
+-------------------------------------------------------------------------------
+--
+-- Synthesizable model of TI's TMS9918A, TMS9928A, TMS9929A.
+--
+-- $Id: vdp18_hor_vert.vhd,v 1.11 2006/06/18 10:47:01 arnim Exp $
+--
+-- Horizontal / Vertical Timing Generator
+--
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+use work.vdp18_pack.opmode_t;
+use work.vdp18_pack.hv_t;
+
+entity vdp18_hor_vert is
+ port (
+ clock_i : in std_logic;
+ clk_en_5m37_i : in boolean;
+ reset_i : in boolean;
+ opmode_i : in opmode_t;
+ ntsc_pal_i : in std_logic;
+ num_pix_o : out hv_t;
+ num_line_o : out hv_t;
+ vert_inc_o : out boolean;
+ hsync_n_o : out std_logic;
+ vsync_n_o : out std_logic;
+ blank_o : out boolean;
+ cnt_hor_o : out std_logic_vector(8 downto 0);
+ cnt_ver_o : out std_logic_vector(7 downto 0)
+ );
+
+end vdp18_hor_vert;
+
+
+use work.vdp18_pack.all;
+
+architecture rtl of vdp18_hor_vert is
+
+ signal last_line_s : hv_t;
+ signal first_line_s : hv_t;
+
+ signal first_pix_s : hv_t;
+ signal last_pix_s : hv_t;
+
+ signal cnt_hor_q : hv_t;
+ signal cnt_vert_q : hv_t;
+
+ signal vert_inc_s : boolean;
+
+ signal hblank_q,
+ vblank_q : boolean;
+
+ signal cnt_hor_s : unsigned(8 downto 0);
+ signal cnt_ver_s : unsigned(7 downto 0);
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Prepare comparison signals for NTSC and PAL.
+ --
+ first_line_s <= hv_first_line_ntsc_c when ntsc_pal_i = '0' else hv_first_line_pal_c;
+ last_line_s <= hv_last_line_ntsc_c when ntsc_pal_i = '0' else hv_last_line_pal_c;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process opmode_mux
+ --
+ -- Purpose:
+ -- Generates the horizontal counter limits based on the current operating
+ -- mode.
+ --
+ opmode_mux: process (opmode_i)
+ begin
+ if opmode_i = OPMODE_TEXTM then
+ first_pix_s <= hv_first_pix_text_c;
+ last_pix_s <= hv_last_pix_text_c;
+ else
+ first_pix_s <= hv_first_pix_graph_c;
+ last_pix_s <= hv_last_pix_graph_c;
+ end if;
+ end process opmode_mux;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process counters
+ --
+ -- Purpose:
+ -- Implements the horizontal and vertical counters.
+ --
+ counters: process (clock_i, reset_i, first_line_s)
+ begin
+ if reset_i then
+ cnt_hor_q <= hv_first_pix_text_c;
+ cnt_vert_q <= first_line_s;
+ hsync_n_o <= '1';
+ vsync_n_o <= '1';
+ hblank_q <= false;
+ vblank_q <= false;
+
+ elsif clock_i'event and clock_i = '1' then
+ if clk_en_5m37_i then
+ -- The horizontal counter ---------------------------------------------
+ if cnt_hor_q = last_pix_s then
+ cnt_hor_q <= first_pix_s;
+ else
+ cnt_hor_q <= cnt_hor_q + 1;
+ end if;
+
+ -- The vertical counter -----------------------------------------------
+ if cnt_vert_q = last_line_s then
+ cnt_vert_q <= first_line_s;
+ elsif vert_inc_s then
+ -- increment when horizontal counter is at trigger position
+ cnt_vert_q <= cnt_vert_q + 1;
+ end if;
+
+ -- Horizontal sync ----------------------------------------------------
+ if cnt_hor_q = -64 then -- -64 -44 -56
+ hsync_n_o <= '0';
+ elsif cnt_hor_q = -38 then -- -38 -18 -30
+ hsync_n_o <= '1';
+ end if;
+ if cnt_hor_q = -72 then -- -72 -62 -69
+ hblank_q <= true;
+ elsif cnt_hor_q = -13 then -- -14 -4 -11
+ hblank_q <= false;
+ end if;
+
+ -- Vertical sync ------------------------------------------------------
+ if ntsc_pal_i = '1' then
+ if cnt_vert_q = 244 then
+ vsync_n_o <= '0';
+ elsif cnt_vert_q = 247 then
+ vsync_n_o <= '1';
+ end if;
+
+ if cnt_vert_q = 242 then
+ vblank_q <= true;
+ elsif cnt_vert_q = first_line_s + 13 then
+ vblank_q <= false;
+ end if;
+ else
+ if cnt_vert_q = 218 then
+ vsync_n_o <= '0';
+ elsif cnt_vert_q = 221 then
+ vsync_n_o <= '1';
+ end if;
+
+ if cnt_vert_q = 215 then
+ vblank_q <= true;
+ elsif cnt_vert_q = first_line_s + 13 then
+ vblank_q <= false;
+ end if;
+ end if;
+ end if;
+ end if;
+ end process counters;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -- comparator for vertical line increment
+ vert_inc_s <= clk_en_5m37_i and cnt_hor_q = hv_vertical_inc_c;
+
+ -----------------------------------------------------------------------------
+ -- Output mapping
+ -----------------------------------------------------------------------------
+ num_pix_o <= cnt_hor_q;
+ num_line_o <= cnt_vert_q;
+ vert_inc_o <= vert_inc_s;
+ blank_o <= hblank_q or vblank_q;
+
+ -- Generate horizontal and vertical counters for VGA/HDMI (in top)
+ process (reset_i, clock_i)
+ begin
+ if reset_i then
+ cnt_hor_s <= (others => '0');
+ cnt_ver_s <= (others => '0');
+ elsif rising_edge(clock_i) then
+ if clk_en_5m37_i then
+ if cnt_hor_q = -12 then
+ cnt_hor_s <= (others => '0');
+ else
+ cnt_hor_s <= cnt_hor_s + 1;
+ end if;
+ if vert_inc_s then
+ if cnt_vert_q = -12 then
+ cnt_ver_s <= (others => '0');
+ else
+ cnt_ver_s <= cnt_ver_s + 1;
+ end if;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ cnt_hor_o <= std_logic_vector(cnt_hor_s);
+ cnt_ver_o <= std_logic_vector(cnt_ver_s);
+
+end rtl;
diff --git a/common/Video/vdp18/vdp18_pack-p.vhd b/common/Video/vdp18/vdp18_pack-p.vhd
new file mode 100644
index 00000000..74448868
--- /dev/null
+++ b/common/Video/vdp18/vdp18_pack-p.vhd
@@ -0,0 +1,281 @@
+-------------------------------------------------------------------------------
+--
+-- $Id: vdp18_pack-p.vhd,v 1.14 2006/02/22 23:07:05 arnim Exp $
+--
+-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+package vdp18_pack is
+
+ -----------------------------------------------------------------------------
+ -- Subtype for horizontal/vertical counters/positions.
+ --
+ subtype hv_t is signed(0 to 8);
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Constants for first and last vertical line of NTSC and PAL mode.
+ --
+ constant hv_first_line_ntsc_c : hv_t := to_signed(-40, hv_t'length); -- 262
+ constant hv_last_line_ntsc_c : hv_t := to_signed(221, hv_t'length);
+ --
+ constant hv_first_line_pal_c : hv_t := to_signed(-65, hv_t'length); -- 312
+ constant hv_last_line_pal_c : hv_t := to_signed(247, hv_t'length);
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Constants for first and last horizontal pixel in text and graphics.
+ --
+ constant hv_first_pix_text_c : hv_t := to_signed(-102, hv_t'length); -- 342
+ constant hv_last_pix_text_c : hv_t := to_signed(239, hv_t'length);
+ --
+ constant hv_first_pix_graph_c : hv_t := to_signed(-86, hv_t'length); -- 342
+ constant hv_last_pix_graph_c : hv_t := to_signed(255, hv_t'length);
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Miscellaneous constants for horizontal phases.
+ --
+ constant hv_vertical_inc_c : hv_t := to_signed(-32, hv_t'length);
+ constant hv_sprite_start_c : hv_t := to_signed(247, hv_t'length);
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Operating modes of the VDP18 core.
+ --
+ type opmode_t is (OPMODE_GRAPH1, OPMODE_GRAPH2,
+ OPMODE_MULTIC, OPMODE_TEXTM);
+ --
+ constant opmode_graph1_c : std_logic_vector(0 to 2) := "000";
+ constant opmode_graph2_c : std_logic_vector(0 to 2) := "001";
+ constant opmode_multic_c : std_logic_vector(0 to 2) := "010";
+ constant opmode_textm_c : std_logic_vector(0 to 2) := "100";
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Access types.
+ --
+ type access_t is (-- pattern access
+ -- read Pattern Name Table
+ AC_PNT,
+ -- read Pattern Generator Table
+ AC_PGT,
+ -- read Pattern Color Table
+ AC_PCT,
+ -- sprite access
+ -- sprite test read (y coordinate)
+ AC_STST,
+ -- read Sprite Attribute Table/Y
+ AC_SATY,
+ -- read Sprite Attribute Table/X
+ AC_SATX,
+ -- read Sprite Attribute Table/N
+ AC_SATN,
+ -- read Sprite Attribute Table/C
+ AC_SATC,
+ -- read Sprite Pattern Table/high quadrant
+ AC_SPTH,
+ -- read Sprite Pattern Table/low quadrant
+ AC_SPTL,
+ --
+ -- CPU access
+ AC_CPU,
+ --
+ -- no access at all
+ AC_NONE
+ );
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Function enum_to_vec_f
+ --
+ -- Purpose:
+ -- Translate access_t enumeration type to std_logic_vector.
+ --
+ function enum_to_vec_f(enum : in access_t) return
+ std_logic_vector;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Function to_boolean_f
+ --
+ -- Purpose:
+ -- Converts a std_logic value to boolean.
+ --
+ function to_boolean_f(val : in std_logic) return boolean;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Function to_std_logic_f
+ --
+ -- Purpose:
+ -- Converts a boolean value to std_logic.
+ --
+ function to_std_logic_f(val : in boolean) return std_logic;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Function mod_6_f
+ --
+ -- Purpose:
+ -- Calculate the modulo of 6.
+ -- Only the positive part is considered.
+ --
+ function mod_6_f(val : in hv_t) return hv_t;
+ --
+ -----------------------------------------------------------------------------
+
+end vdp18_pack;
+
+
+package body vdp18_pack is
+
+ -----------------------------------------------------------------------------
+ -- Function enum_to_vec_f
+ --
+ -- Purpose:
+ -- Translate access_t enumeration type to std_logic_vector.
+ --
+ function enum_to_vec_f(enum : in access_t) return
+ std_logic_vector is
+ variable result_v : std_logic_vector(3 downto 0);
+ begin
+ case enum is
+ when AC_NONE =>
+ result_v := "0000";
+ when AC_PNT =>
+ result_v := "0001";
+ when AC_PGT =>
+ result_v := "0010";
+ when AC_PCT =>
+ result_v := "0011";
+ when AC_STST =>
+ result_v := "0100";
+ when AC_SATY =>
+ result_v := "0101";
+ when AC_SATX =>
+ result_v := "0110";
+ when AC_SATN =>
+ result_v := "0111";
+ when AC_SATC =>
+ result_v := "1000";
+ when AC_SPTL =>
+ result_v := "1001";
+ when AC_SPTH =>
+ result_v := "1010";
+ when AC_CPU =>
+ result_v := "1111";
+ when others =>
+ result_v := "UUUU";
+ end case;
+
+ return result_v;
+ end;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Function to_boolean_f
+ --
+ -- Purpose:
+ -- Converts a std_logic value to boolean.
+ --
+ function to_boolean_f(val : in std_logic) return boolean is
+ variable result_v : boolean;
+ begin
+ case to_X01(val) is
+ when '1' =>
+ result_v := true;
+ when '0' =>
+ result_v := false;
+ when others =>
+ result_v := false;
+ end case;
+
+ return result_v;
+ end;
+ --
+ -----------------------------------------------------------------------------
+
+ -----------------------------------------------------------------------------
+ -- Function to_std_logic_f
+ --
+ -- Purpose:
+ -- Converts a boolean value to std_logic.
+ --
+ function to_std_logic_f(val : in boolean) return std_logic is
+ variable result_v : std_logic;
+ begin
+ case val is
+ when true =>
+ result_v := '1';
+ when false =>
+ result_v := '0';
+ end case;
+
+ return result_v;
+ end;
+ --
+ -----------------------------------------------------------------------------
+
+ -----------------------------------------------------------------------------
+ -- Function mod_6_f
+ --
+ -- Purpose:
+ -- Calculate the modulo of 6.
+ -- Only the positive part is considered.
+ --
+ function mod_6_f(val : in hv_t) return hv_t is
+ variable mod_v : natural;
+ variable result_v : hv_t;
+ begin
+ if val(0) = '0' then
+ result_v := (others => '0');
+ mod_v := 0;
+ for idx in 0 to 255 loop
+ if val = idx then
+ result_v := to_signed(mod_v, hv_t'length);
+ end if;
+
+ if mod_v < 5 then
+ mod_v := mod_v + 1;
+ else
+ mod_v := 0;
+ end if;
+ end loop;
+ else
+ result_v := (others => '-');
+ end if;
+
+ return result_v;
+ end;
+ --
+ -----------------------------------------------------------------------------
+
+end vdp18_pack;
diff --git a/common/Video/vdp18/vdp18_pattern.vhd b/common/Video/vdp18/vdp18_pattern.vhd
new file mode 100644
index 00000000..08b22092
--- /dev/null
+++ b/common/Video/vdp18/vdp18_pattern.vhd
@@ -0,0 +1,233 @@
+-------------------------------------------------------------------------------
+--
+-- Synthesizable model of TI's TMS9918A, TMS9928A, TMS9929A.
+--
+-- $Id: vdp18_pattern.vhd,v 1.8 2006/06/18 10:47:06 arnim Exp $
+--
+-- Pattern Generation Controller
+--
+-------------------------------------------------------------------------------
+--
+-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.vdp18_pack.opmode_t;
+use work.vdp18_pack.access_t;
+use work.vdp18_pack.hv_t;
+
+entity vdp18_pattern is
+
+ port (
+ clock_i : in std_logic;
+ clk_en_5m37_i : in boolean;
+ clk_en_acc_i : in boolean;
+ reset_i : in boolean;
+ opmode_i : in opmode_t;
+ access_type_i : in access_t;
+ num_line_i : in hv_t;
+ vram_d_i : in std_logic_vector(0 to 7);
+ vert_inc_i : in boolean;
+ vsync_n_i : in std_logic;
+ reg_col1_i : in std_logic_vector(0 to 3);
+ reg_col0_i : in std_logic_vector(0 to 3);
+ pat_table_o : out std_logic_vector(0 to 9);
+ pat_name_o : out std_logic_vector(0 to 7);
+ pat_col_o : out std_logic_vector(0 to 3)
+ );
+
+end vdp18_pattern;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+use work.vdp18_pack.all;
+
+architecture rtl of vdp18_pattern is
+
+ signal pat_cnt_q : unsigned(0 to 9);
+ signal pat_name_q,
+ pat_tmp_q,
+ pat_shift_q,
+ pat_col_q : std_logic_vector(0 to 7);
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process seq
+ --
+ -- Purpose:
+ -- Implements the sequential elements:
+ -- * pattern shift register
+ -- * pattern color register
+ -- * pattern counter
+ --
+ seq: process (clock_i, reset_i)
+ begin
+ if reset_i then
+ pat_cnt_q <= (others => '0');
+ pat_name_q <= (others => '0');
+ pat_tmp_q <= (others => '0');
+ pat_shift_q <= (others => '0');
+ pat_col_q <= (others => '0');
+
+ elsif clock_i'event and clock_i = '1' then
+ if clk_en_5m37_i then
+ -- shift pattern with every pixel clock
+ pat_shift_q(0 to 6) <= pat_shift_q(1 to 7);
+ end if;
+
+ if clk_en_acc_i then
+ -- determine register update based on current access type -------------
+ case access_type_i is
+ when AC_PNT =>
+ -- store pattern name
+ pat_name_q <= vram_d_i;
+ -- increment pattern counter
+ pat_cnt_q <= pat_cnt_q + 1;
+
+ when AC_PCT =>
+ -- store pattern color in temporary register
+ pat_tmp_q <= vram_d_i;
+
+ when AC_PGT =>
+ if opmode_i = OPMODE_MULTIC then
+ -- set shift register to constant value
+ -- this value generates 4 bits of color1
+ -- followed by 4 bits of color0
+ pat_shift_q <= "11110000";
+ -- set pattern color from pattern generator memory
+ pat_col_q <= vram_d_i;
+ else
+ -- all other modes:
+ -- store pattern line in shift register
+ pat_shift_q <= vram_d_i;
+ -- move pattern color from temporary register to color register
+ pat_col_q <= pat_tmp_q;
+ end if;
+
+ when others =>
+ null;
+
+ end case;
+
+ end if;
+
+ if vert_inc_i then
+ -- redo patterns of if there are more lines inside this pattern
+ if num_line_i(0) = '0' then
+ case opmode_i is
+ when OPMODE_TEXTM =>
+ if num_line_i(6 to 8) /= "111" then
+ pat_cnt_q <= pat_cnt_q - 40;
+ end if;
+
+ when OPMODE_GRAPH1 |
+ OPMODE_GRAPH2 |
+ OPMODE_MULTIC =>
+ if num_line_i(6 to 8) /= "111" then
+ pat_cnt_q <= pat_cnt_q - 32;
+ end if;
+ end case;
+ end if;
+ end if;
+
+ if vsync_n_i = '0' then
+ -- reset pattern counter at end of active display area
+ pat_cnt_q <= (others => '0');
+ end if;
+
+ end if;
+ end process seq;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process col_gen
+ --
+ -- Purpose:
+ -- Generates the color of the current pattern pixel.
+ --
+ col_gen: process (opmode_i,
+ pat_shift_q,
+ pat_col_q,
+ reg_col1_i,
+ reg_col0_i)
+ variable pix_v : std_logic;
+ begin
+ -- default assignment
+ pat_col_o <= "0000";
+ pix_v := pat_shift_q(0);
+
+ case opmode_i is
+ -- Text Mode ------------------------------------------------------------
+ when OPMODE_TEXTM =>
+ if pix_v = '1' then
+ pat_col_o <= reg_col1_i;
+ else
+ pat_col_o <= reg_col0_i;
+ end if;
+
+ -- Graphics I, II and Multicolor Mode -----------------------------------
+ when OPMODE_GRAPH1 |
+ OPMODE_GRAPH2 |
+ OPMODE_MULTIC =>
+ if pix_v = '1' then
+ pat_col_o <= pat_col_q(0 to 3);
+ else
+ pat_col_o <= pat_col_q(4 to 7);
+ end if;
+
+ when others =>
+ null;
+
+ end case;
+ end process col_gen;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Output Mapping
+ -----------------------------------------------------------------------------
+ pat_table_o <= std_logic_vector(pat_cnt_q);
+ pat_name_o <= pat_name_q;
+
+end rtl;
diff --git a/common/Video/vdp18/vdp18_sprite.vhd b/common/Video/vdp18/vdp18_sprite.vhd
new file mode 100644
index 00000000..d198f310
--- /dev/null
+++ b/common/Video/vdp18/vdp18_sprite.vhd
@@ -0,0 +1,441 @@
+-------------------------------------------------------------------------------
+--
+-- Synthesizable model of TI's TMS9918A, TMS9928A, TMS9929A.
+--
+-- $Id: vdp18_sprite.vhd,v 1.11 2006/06/18 10:47:06 arnim Exp $
+--
+-- Sprite Generation Controller
+--
+-- Copyright (c) 2006, Arnim Laeuger (arnim.laeuger@gmx.net)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+
+use work.vdp18_pack.hv_t;
+use work.vdp18_pack.access_t;
+
+entity vdp18_sprite is
+
+ port (
+ clock_i : in std_logic;
+ clk_en_5m37_i : in boolean;
+ clk_en_acc_i : in boolean;
+ reset_i : in boolean;
+ access_type_i : in access_t;
+ num_pix_i : in hv_t;
+ num_line_i : in hv_t;
+ vram_d_i : in std_logic_vector(0 to 7);
+ vert_inc_i : in boolean;
+ reg_size1_i : in boolean;
+ reg_mag1_i : in boolean;
+ spr_5th_o : out boolean;
+ spr_5th_num_o : out std_logic_vector(0 to 4);
+ stop_sprite_o : out boolean;
+ spr_coll_o : out boolean;
+ spr_num_o : out std_logic_vector(0 to 4);
+ spr_line_o : out std_logic_vector(0 to 3);
+ spr_name_o : out std_logic_vector(0 to 7);
+ spr0_col_o : out std_logic_vector(0 to 3);
+ spr1_col_o : out std_logic_vector(0 to 3);
+ spr2_col_o : out std_logic_vector(0 to 3);
+ spr3_col_o : out std_logic_vector(0 to 3)
+ );
+
+end vdp18_sprite;
+
+
+library ieee;
+use ieee.numeric_std.all;
+
+use work.vdp18_pack.all;
+
+architecture rtl of vdp18_sprite is
+
+ subtype sprite_number_t is unsigned(0 to 4);
+ type sprite_numbers_t is array (natural range 0 to 3) of sprite_number_t;
+ signal sprite_numbers_q : sprite_numbers_t;
+
+ signal sprite_num_q : unsigned(0 to 4);
+ signal sprite_idx_q : unsigned(0 to 2);
+ signal sprite_name_q : std_logic_vector(0 to 7);
+
+ subtype sprite_x_pos_t is unsigned(0 to 7);
+ type sprite_xpos_t is array (natural range 0 to 3) of sprite_x_pos_t;
+ signal sprite_xpos_q : sprite_xpos_t;
+ type sprite_ec_t is array (natural range 0 to 3) of std_logic;
+ signal sprite_ec_q : sprite_ec_t;
+ type sprite_xtog_t is array (natural range 0 to 3) of std_logic;
+ signal sprite_xtog_q : sprite_xtog_t;
+
+ subtype sprite_col_t is std_logic_vector(0 to 3);
+ type sprite_cols_t is array (natural range 0 to 3) of sprite_col_t;
+ signal sprite_cols_q : sprite_cols_t;
+
+ subtype sprite_pat_t is std_logic_vector(0 to 15);
+ type sprite_pats_t is array (natural range 0 to 3) of sprite_pat_t;
+ signal sprite_pats_q : sprite_pats_t;
+
+ signal sprite_line_s,
+ sprite_line_q : std_logic_vector(0 to 3);
+ signal sprite_visible_s : boolean;
+
+begin
+
+ -----------------------------------------------------------------------------
+ -- Process seq
+ --
+ -- Purpose:
+ -- Implements the sequential elements.
+ --
+ seq: process (clock_i, reset_i)
+ variable sprite_idx_inc_v,
+ sprite_idx_dec_v : unsigned(sprite_idx_q'range);
+ variable sprite_idx_v : natural range 0 to 3;
+ begin
+ if reset_i then
+ sprite_numbers_q <= (others => (others => '0'));
+ sprite_num_q <= (others => '0');
+ sprite_idx_q <= (others => '0');
+ sprite_line_q <= (others => '0');
+ sprite_name_q <= (others => '0');
+ sprite_cols_q <= (others => (others => '0'));
+ sprite_xpos_q <= (others => (others => '0'));
+ sprite_ec_q <= (others => '0');
+ sprite_xtog_q <= (others => '0');
+ sprite_pats_q <= (others => (others => '0'));
+
+ elsif clock_i'event and clock_i = '1' then
+ -- sprite index will be incremented during sprite tests
+ sprite_idx_inc_v := sprite_idx_q + 1;
+ -- sprite index will be decremented at end of sprite pattern data
+ sprite_idx_dec_v := sprite_idx_q - 1;
+ -- just save typing
+ sprite_idx_v := to_integer(sprite_idx_q(1 to 2));
+
+ if clk_en_5m37_i then
+ -- pre-decrement index counter when sprite reading starts
+ if num_pix_i = hv_sprite_start_c and sprite_idx_q > 0 then
+ sprite_idx_q <= sprite_idx_dec_v;
+ end if;
+
+ -----------------------------------------------------------------------
+ -- X position counters
+ -----------------------------------------------------------------------
+ for idx in 0 to 3 loop
+ if num_pix_i(0) = '0' or
+ (sprite_ec_q(idx) = '1' and num_pix_i(0 to 3) = "1111") then
+ if sprite_xpos_q(idx) /= 0 then
+ -- decrement counter until 0
+ sprite_xpos_q(idx) <= sprite_xpos_q(idx) - 1;
+ else
+ -- toggle magnification flag
+ sprite_xtog_q(idx) <= not sprite_xtog_q(idx);
+ end if;
+ end if;
+ end loop;
+
+ -----------------------------------------------------------------------
+ -- Sprite pattern shift registers
+ -----------------------------------------------------------------------
+ for idx in 0 to 3 loop
+ if sprite_xpos_q(idx) = 0 then -- x counter elapsed
+ -- decide when to shift pattern information
+ -- case 1: pixel number is >= 0
+ -- => active display area
+ -- case 2: early clock bit is set and pixel number is between
+ -- -32 and 0
+ -- shift if
+ -- magnification not enbled
+ -- or
+ -- magnification enabled and toggle marker true
+ if (num_pix_i(0) = '0' or
+ (sprite_ec_q(idx) = '1' and num_pix_i(0 to 3) = "1111")) and
+ (sprite_xtog_q(idx) = '1' or not reg_mag1_i) then
+ --
+ -- shift pattern left and fill vacated position with
+ -- transparent information
+ sprite_pats_q(idx)(0 to 14) <= sprite_pats_q(idx)(1 to 15);
+ sprite_pats_q(idx)(15) <= '0';
+ end if;
+ end if;
+
+ -- clear pattern at end of visible display
+ -- this removes "left-overs" when a sprite overlaps the right border
+ if num_pix_i = "011111111" then
+ sprite_pats_q(idx) <= (others => '0');
+ end if;
+ end loop;
+ end if;
+
+
+ if vert_inc_i then
+ -- reset sprite num counter and sprite index counter
+ sprite_num_q <= (others => '0');
+ sprite_idx_q <= (others => '0');
+
+ elsif clk_en_acc_i then
+ case access_type_i is
+ when AC_STST =>
+ -- increment sprite number counter
+ sprite_num_q <= sprite_num_q + 1;
+
+ if sprite_visible_s then
+ if sprite_idx_q < 4 then
+ -- store sprite number
+ sprite_numbers_q(sprite_idx_v) <= sprite_num_q;
+ -- and increment index counter
+ sprite_idx_q <= sprite_idx_inc_v;
+ end if;
+ end if;
+
+ when AC_SATY =>
+ -- store sprite line
+ sprite_line_q <= sprite_line_s;
+
+ when AC_SATX =>
+ -- save x position
+ sprite_xpos_q(sprite_idx_v) <= unsigned(vram_d_i);
+ -- reset toggle flag for magnified sprites
+ sprite_xtog_q(sprite_idx_v) <= '0';
+
+ when AC_SATN =>
+ -- save sprite name
+ sprite_name_q <= vram_d_i;
+
+ when AC_SATC =>
+ -- save sprite color
+ sprite_cols_q(sprite_idx_v) <= vram_d_i(4 to 7);
+ -- and save early clock bit
+ sprite_ec_q(sprite_idx_v) <= vram_d_i(0);
+
+ when AC_SPTH =>
+ -- save upper pattern data
+ sprite_pats_q(sprite_idx_v)(0 to 7)
+ <= vram_d_i;
+ -- set lower part to transparent
+ sprite_pats_q(sprite_idx_v)(8 to 15)
+ <= (others => '0');
+
+ if not reg_size1_i then
+ -- decrement index counter in 8-bit mode
+ sprite_idx_q <= sprite_idx_dec_v;
+ end if;
+
+ when AC_SPTL =>
+ -- save lower pattern data
+ sprite_pats_q(sprite_idx_v)(8 to 15) <= vram_d_i;
+
+ -- always decrement index counter
+ sprite_idx_q <= sprite_idx_dec_v;
+
+ when others =>
+ null;
+ end case;
+
+ end if;
+
+ end if;
+ end process seq;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process calc_vert
+ --
+ -- Purpose:
+ -- Calculates the displayed line of the sprite and determines whether it
+ -- is visible on the current line or not.
+ --
+ calc_vert: process (clk_en_acc_i, access_type_i,
+ vram_d_i,
+ num_pix_i, num_line_i,
+ sprite_num_q, sprite_idx_q,
+ reg_size1_i, reg_mag1_i)
+ variable sprite_line_v : signed(0 to 8);
+ variable vram_d_v : signed(0 to 8);
+ begin
+ -- default assignments
+ sprite_visible_s <= false;
+ stop_sprite_o <= false;
+
+ vram_d_v := resize(signed(vram_d_i), 9);
+ -- determine if y information from VRAM should be treated
+ -- as a signed or unsigned number
+ if vram_d_v < -31 then
+ -- treat as unsigned number
+ vram_d_v(0) := '0';
+ end if;
+
+ sprite_line_v := num_line_i - vram_d_v;
+ if reg_mag1_i then
+ -- unmagnify line number
+ sprite_line_v := shift_right(sprite_line_v, 1);
+ end if;
+
+ -- check result bounds
+ if sprite_line_v >= 0 then
+ if reg_size1_i then
+ -- double sized sprite: 16 data lines
+ if sprite_line_v < 16 then
+ sprite_visible_s <= true;
+ end if;
+ else
+ -- standard sized sprite: 8 data lines
+ if sprite_line_v < 8 then
+ sprite_visible_s <= true;
+ end if;
+ end if;
+ end if;
+
+ -- finally: line number of current sprite
+ sprite_line_s <= std_logic_vector(sprite_line_v(5 to 8));
+
+ if clk_en_acc_i then
+ -- determine when to stop sprite scanning
+ if access_type_i = AC_STST then
+ if vram_d_v = 208 then
+ -- stop upon Y position 208
+ stop_sprite_o <= true;
+ end if;
+
+ if sprite_idx_q = 4 then
+ -- stop when all sprite positions have been vacated
+ stop_sprite_o <= true;
+ end if;
+
+ if sprite_num_q = 31 then
+ -- stop when all sprites have been read
+ stop_sprite_o <= true;
+ end if;
+ end if;
+
+ -- stop sprite reading when last active sprite has been processed
+ if sprite_idx_q = 0 and
+ ( access_type_i = AC_SPTL or
+ (access_type_i = AC_SPTH and not reg_size1_i)) then
+ stop_sprite_o <= true;
+ end if;
+ end if;
+
+ -- stop sprite reading when no sprite is active on current line
+ if num_pix_i = hv_sprite_start_c and sprite_idx_q = 0 then
+ stop_sprite_o <= true;
+ end if;
+ end process calc_vert;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process fifth
+ --
+ -- Purpose:
+ -- Detects the fifth sprite.
+ --
+ fifth: process (clk_en_acc_i, access_type_i,
+ sprite_visible_s,
+ sprite_idx_q,
+ sprite_num_q)
+ begin
+ -- default assignments
+ spr_5th_o <= false;
+ spr_5th_num_o <= (others => '0');
+
+ if clk_en_acc_i and access_type_i = AC_STST then
+ if sprite_visible_s and sprite_idx_q = 4 then
+ spr_5th_o <= true;
+ spr_5th_num_o <= std_logic_vector(sprite_num_q);
+ end if;
+ end if;
+ end process fifth;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Process col_mux
+ --
+ -- Purpose:
+ -- Implements the color multiplexers.
+ --
+ col_mux: process (sprite_cols_q,
+ sprite_pats_q,
+ sprite_xpos_q)
+ variable num_spr_pix_v : unsigned(0 to 2);
+ begin
+ -- default assignments
+ -- sprite colors are set to transparent
+ spr0_col_o <= (others => '0');
+ spr1_col_o <= (others => '0');
+ spr2_col_o <= (others => '0');
+ spr3_col_o <= (others => '0');
+ num_spr_pix_v := (others => '0');
+
+ if sprite_xpos_q(0) = 0 and sprite_pats_q(0)(0) = '1' then
+ spr0_col_o <= sprite_cols_q(0);
+ num_spr_pix_v := num_spr_pix_v + 1;
+ end if;
+ if sprite_xpos_q(1) = 0 and sprite_pats_q(1)(0) = '1' then
+ spr1_col_o <= sprite_cols_q(1);
+ num_spr_pix_v := num_spr_pix_v + 1;
+ end if;
+ if sprite_xpos_q(2) = 0 and sprite_pats_q(2)(0) = '1' then
+ spr2_col_o <= sprite_cols_q(2);
+ num_spr_pix_v := num_spr_pix_v + 1;
+ end if;
+ if sprite_xpos_q(3) = 0 and sprite_pats_q(3)(0) = '1' then
+ spr3_col_o <= sprite_cols_q(3);
+ num_spr_pix_v := num_spr_pix_v + 1;
+ end if;
+
+ spr_coll_o <= num_spr_pix_v > 1;
+ end process col_mux;
+ --
+ -----------------------------------------------------------------------------
+
+
+ -----------------------------------------------------------------------------
+ -- Output mapping
+ -----------------------------------------------------------------------------
+ spr_num_o <= std_logic_vector(sprite_num_q)
+ when access_type_i = AC_STST else
+ std_logic_vector(sprite_numbers_q(to_integer(sprite_idx_q(1 to 2))));
+ spr_line_o <= sprite_line_q;
+ spr_name_o <= sprite_name_q;
+
+end rtl;
diff --git a/common/ay_3_8500NTSC.v b/common/ay_3_8500NTSC.v
new file mode 100644
index 00000000..0af5e47b
--- /dev/null
+++ b/common/ay_3_8500NTSC.v
@@ -0,0 +1,861 @@
+/*
+ * Release 1 7/3/2019
+ * Verilog description of the AY-3-8500 (NTSC varient)
+ * Generated from a transistor-level netlist by DLAET
+ * Some manual patches have been made (marked by comments)
+ *
+ * Thanks to Sean Riddle for decapping the speciman
+ * and to: Suverman, Erika, Ewen McNeill, and Dylan Lipsitz
+ * for supporting me on Patreon
+ */
+
+module ay_3_8500NTSC(
+ output pinRPout,
+ output pinLPout,
+ output pinBallOut,
+ input pinManualServe,
+ output pinRPin_DWN,
+ input pinRPin,
+ input pinBallAngle,
+ output pinLPin_DWN,
+ input pinLPin,
+ input pinBatSize,
+ input pinBallSpeed,
+ output pinSyncOut,
+ output pinSound,
+ input clk,
+ input pinHitIn,
+ output pinRifle1_DWN,
+ input pinRifle1,
+ input pinRifle2,
+ input pinShotIn,
+ output pinTennis_DWN,
+ input pinTennis,
+ output pinSFout,
+ input pinSoccer,
+ input pinSquash,
+ input pinPractice,
+ input reset,
+ output vsync,
+ output hsync);
+
+ assign vsync = flop6;
+ assign hsync= !flop7;
+
+ assign pinRPout = !or28;
+ assign pinLPout = !or38;
+ assign pinBallOut = !or2;
+ assign pinRPin_DWN = flop6;//MC: The ORs were bypassed
+ assign pinLPin_DWN = flop6;
+ assign pinSyncOut = !or56;
+ assign pinSound = or69;
+ assign pinRifle1_DWN = !or150;
+ assign pinTennis_DWN = !or211;
+ assign pinSFout = or212;
+ wire pulser0 = flop6;
+ wire pulser1 = (!or170 | pulser1_delay);
+ reg pulser1_delay = 0;
+ always @(negedge clk) begin
+ pulser1_delay <= or170;
+ end
+ reg flop0 = 0;
+ always @(posedge slow_clock) begin
+ flop0 <= flop2;
+ end
+ reg flop1 = 0;
+ wire flop1_reset = !or213 | counter5_2268;
+ wire flop1_set = !or3 | !or6;
+
+ // divide 16Mhz clock by 8
+ reg [2:0] clockdivider = 0;
+ wire slow_clock = clockdivider[2:2];
+ always @(posedge clk) begin
+ clockdivider <= clockdivider + 1;
+ end
+
+
+ always @(posedge flop1_reset or posedge flop1_set) begin
+ if(flop1_reset)
+ flop1 <= 0;
+ else
+ flop1 <= 1;
+ end
+ reg flop2 = 0;
+ wire flop2_reset = !or213 | counter4_2130;
+ wire flop2_set = !or18 | !or19;
+ always @(posedge flop2_reset or posedge flop2_set) begin
+ if(flop2_reset)
+ flop2 <= 0;
+ else
+ flop2 <= 1;
+ end
+ reg flop3 = 0;
+ wire flop3_reset = !or4;
+ wire flop3_set = !pinManualServe & reset;//MC: set/reset priority have been reversed + reset added to flop3_set's OR
+ always @(posedge flop3_set or posedge flop3_reset) begin
+ if(flop3_set)
+ flop3 <= 0;
+ else
+ flop3 <= 1;
+ end
+ reg flop4 = 0;
+ wire flop4_reset = !or16 | or24 | or27 | !or213;
+ wire flop4_set = !or15 | or23 | or22;
+ always @(posedge flop4_reset or posedge flop4_set) begin
+ if(flop4_reset)
+ flop4 <= 0;
+ else
+ flop4 <= 1;
+ end
+ reg flop5 = 0;
+ wire flop5_reset = or27 | or22;
+ wire flop5_set = or24 | or23 | !or213;
+ always @(posedge flop5_reset or posedge flop5_set) begin
+ if(flop5_reset)
+ flop5 <= 0;
+ else
+ flop5 <= 1;
+ end
+ reg flop6 = 0;
+ wire flop6_reset = !reset | !or88;
+ wire flop6_set = !or86;
+ always @(posedge flop6_reset or posedge flop6_set) begin
+ if(flop6_reset)
+ flop6 <= 0;
+ else
+ flop6 <= 1;
+ end
+ reg flop7 = 0;
+ wire flop7_reset = !reset | !or63;
+ wire flop7_set = !or74;
+ always @(posedge flop7_reset or posedge flop7_set) begin
+ if(flop7_reset)
+ flop7 <= 0;
+ else
+ flop7 <= 1;
+ end
+ reg flop8 = 0;
+ always @(negedge or8) begin
+ flop8 <= or55;
+ end
+ reg flop9 = 0;
+ always @(negedge or8) begin
+ flop9 <= !or49;
+ end
+ reg flop10 = 0;
+ always @(negedge or8) begin
+ flop10 <= or66;
+ end
+ reg flop11 = 0;
+ always @(negedge or8) begin
+ flop11 <= !or51;
+ end
+ reg flop12 = 0;
+ wire flop12_reset = !or92;
+ wire flop12_set = !or90;
+ always @(posedge flop12_reset or posedge flop12_set) begin
+ if(flop12_reset)
+ flop12 <= 0;
+ else
+ flop12 <= 1;
+ end
+ reg flop13 = 0;
+ wire flop13_reset = !or169;
+ wire flop13_set = !flop26 | !and18;
+ always @(posedge flop13_reset or posedge flop13_set) begin
+ if(flop13_reset)
+ flop13 <= 0;
+ else
+ flop13 <= 1;
+ end
+ reg flop14 = 0;
+ wire flop14_reset = !pulser1;
+ wire flop14_set = !and18;
+ always @(posedge flop14_reset or posedge flop14_set) begin
+ if(flop14_reset)
+ flop14 <= 0;
+ else
+ flop14 <= 1;
+ end
+ reg flop15 = 0;
+ wire flop15_reset = !or135;
+ wire flop15_set = !or136;
+ always @(posedge flop15_reset or posedge flop15_set) begin
+ if(flop15_reset)
+ flop15 <= 0;
+ else
+ flop15 <= 1;
+ end
+ reg flop16 = 0;
+ wire flop16_reset = or144;
+ wire flop16_set = !and18;
+ always @(posedge flop16_reset or posedge flop16_set) begin
+ if(flop16_reset)
+ flop16 <= 0;
+ else
+ flop16 <= 1;
+ end
+ reg flop17 = 0;
+ wire flop17_reset = or149;
+ wire flop17_set = or127 | !or153 | !or213;
+ always @(posedge flop17_reset or posedge flop17_set) begin
+ if(flop17_reset)
+ flop17 <= 0;
+ else
+ flop17 <= 1;
+ end
+ reg flop18 = 0;
+ wire flop18_reset = !reset;
+ wire flop18_set = !or193 | !or200;
+ always @(posedge flop18_reset or posedge flop18_set) begin
+ if(flop18_reset)
+ flop18 <= 0;
+ else
+ flop18 <= 1;
+ end
+ reg flop19 = 0;
+ wire flop19_reset = !or155;
+ wire flop19_set = !and18;
+ always @(posedge flop19_reset or posedge flop19_set) begin
+ if(flop19_reset)
+ flop19 <= 0;
+ else
+ flop19 <= 1;
+ end
+ reg flop20 = 0;
+ wire flop20_reset = !or143;
+ wire flop20_set = !or142;
+ always @(posedge flop20_reset or posedge flop20_set) begin
+ if(flop20_reset)
+ flop20 <= 0;
+ else
+ flop20 <= 1;
+ end
+ reg flop21 = 0;
+ wire flop21_reset = or146;
+ wire flop21_set = !or138;
+ always @(posedge flop21_reset or posedge flop21_set) begin
+ if(flop21_reset)
+ flop21 <= 0;
+ else
+ flop21 <= 1;
+ end
+ reg flop22 = 0;
+ always @(posedge or152) begin
+ flop22 <= flop21;
+ end
+ reg flop23 = 0;
+ wire flop23_reset = !or70;
+ wire flop23_set = !or68;
+ always @(posedge flop23_reset or posedge flop23_set) begin
+ if(flop23_reset)
+ flop23 <= 0;
+ else
+ flop23 <= 1;
+ end
+ reg flop24 = 0;
+ wire flop24_reset = !ripple_ctr9_2;
+ wire flop24_set = flop25;
+ always @(posedge flop24_reset or posedge flop24_set) begin
+ if(flop24_reset)
+ flop24 <= 0;
+ else
+ flop24 <= 1;
+ end
+ reg flop25 = 0;
+ wire flop25_reset = !ripple_ctr9_2 | flop24;
+ wire flop25_set = !or141;
+ always @(posedge flop25_reset or posedge flop25_set) begin
+ if(flop25_reset)
+ flop25 <= 0;
+ else
+ flop25 <= 1;
+ end
+ reg flop26 = 0;
+ wire flop26_reset = !pinHitIn;
+ wire flop26_set = !and18;
+ always @(posedge flop26_reset or posedge flop26_set) begin
+ if(flop26_reset)
+ flop26 <= 0;
+ else
+ flop26 <= 1;
+ end
+ reg flop27 = 0;
+ wire flop27_reset = !or199;
+ wire flop27_set = !or166;
+ always @(posedge flop27_reset or posedge flop27_set) begin
+ if(flop27_reset)
+ flop27 <= 0;
+ else
+ flop27 <= 1;
+ end
+ reg flop28 = 0;
+ wire flop28_reset = !or124;
+ wire flop28_set = !or70;
+ always @(posedge flop28_reset or posedge flop28_set) begin
+ if(flop28_reset)
+ flop28 <= 0;
+ else
+ flop28 <= 1;
+ end
+ reg flop29 = 0;
+ wire flop29_reset = !or164;
+ wire flop29_set = !or199;
+ always @(posedge flop29_reset or posedge flop29_set) begin
+ if(flop29_reset)
+ flop29 <= 0;
+ else
+ flop29 <= 1;
+ end
+ reg flop30 = 0;
+ wire flop30_reset = !or199 | or205;
+ wire flop30_set = !reset;
+ always @(posedge flop30_reset or posedge flop30_set) begin
+ if(flop30_reset)
+ flop30 <= 0;
+ else
+ flop30 <= 1;
+ end
+ reg flop31 = 0;
+ wire flop31_reset = !or188;
+ wire flop31_set = !and18;
+ always @(posedge flop31_reset or posedge flop31_set) begin
+ if(flop31_reset)
+ flop31 <= 0;
+ else
+ flop31 <= 1;
+ end
+ reg flop32 = 0;
+ wire flop32_reset = !flop13 | !or155 | or144 | !pulser1;
+ wire flop32_set = !and18;
+ always @(posedge flop32_reset or posedge flop32_set) begin
+ if(flop32_reset)
+ flop32 <= 0;
+ else
+ flop32 <= 1;
+ end
+ reg flop33 = 0;
+ wire flop33_reset = !or193 | !or200 | !or205;
+ wire flop33_set = !or210;
+ always @(posedge flop33_reset or posedge flop33_set) begin
+ if(flop33_reset)
+ flop33 <= 0;
+ else
+ flop33 <= 1;
+ end
+ reg flop34 = 0;
+ wire flop34_reset = !or181;
+ wire flop34_set = !or177;
+ always @(posedge flop34_reset or posedge flop34_set) begin
+ if(flop34_reset)
+ flop34 <= 0;
+ else
+ flop34 <= 1;
+ end
+ reg flop35 = 0;
+ wire flop35_reset = !or168;
+ wire flop35_set = !or178;
+ always @(posedge flop35_reset or posedge flop35_set) begin
+ if(flop35_reset)
+ flop35 <= 0;
+ else
+ flop35 <= 1;
+ end
+ wire and0 = !or26 & !or147;
+ wire and1 = !or29 & or118;
+ wire and2 = !or31 & !or147;
+ wire and3 = !or34 & or118;
+ wire and4 = !or36 & !or147;
+ wire and5 = !or39 & or118;
+ wire and6 = !or42 & !or147;
+ wire and7 = !or43 & or118;
+ wire and8 = !or117 & or0;
+ wire and9 = !flop23 & ripple_ctr1_4;
+ wire and10 = flop23 & ripple_ctr0_4;
+ wire and11 = !flop23 & ripple_ctr1_3;
+ wire and12 = flop23 & ripple_ctr0_3;
+ wire and13 = !flop23 & ripple_ctr1_2;
+ wire and14 = flop23 & ripple_ctr0_2;
+ wire and15 = !flop23 & ripple_ctr1_5;
+ wire and16 = flop23 & ripple_ctr0_5;
+ wire and17 = flop4 & !or214;
+ wire and18 = or1 & reset;
+ wire and19 = !or214 & flop17;
+ wire or0 = !or72 | !or73;
+ wire or1 = ripple_ctr4_4 | ripple_ctr4_3 | ripple_ctr4_2 | ripple_ctr4_5;
+ wire or2 = !or13 | or196 | pinHitIn;
+ wire or3 = !or205 | !counter5_2254;
+ wire or4 = !or176 | flop7;
+ wire or5 = !counter5_2265 | !flop0 | !or209;
+ wire or6 = or205 | !counter5_2263;
+ wire or7 = !flop2 | !flop1 | !or209;
+ wire or8 = !or16 | !or15 | or127 | or149 | !or213;
+ wire or9 = pinBallSpeed | flop8;
+ wire or10 = flop9 | pinBallSpeed;
+ wire or11 = pinBallSpeed | flop11;
+ wire or12 = !pinBallSpeed | flop10;
+ wire or13 = !or7 | !or214;
+ wire or14 = flop6 | !pinRPin;
+ wire or15 = !or13 | !or195;
+ wire or16 = !or13 | !or65;
+ wire or17 = !or16 | !or15 | !or152 | !or67;
+ wire or18 = !or205 | !counter4_2125;
+ wire or19 = or205 | !counter4_2128;
+ wire or20 = !ripple_ctr7_2 | !ripple_ctr7_3 | !ripple_ctr7_4 | !ripple_ctr7_5;
+ wire or21 = or14 | !or54 | !or20;
+ wire or22 = and6 | and7;
+ wire or23 = and4 | and5;
+ wire or24 = and2 | and3;
+ wire or25 = !ripple_ctr8_2 | !ripple_ctr8_3 | !ripple_ctr8_4 | !ripple_ctr8_5;
+ wire or26 = !ripple_ctr7_4 | !ripple_ctr7_5;
+ wire or27 = and0 | and1;
+ wire or28 = !or120 | flop34 | or14 | !or20 | or205;
+ wire or29 = !ripple_ctr8_4 | !ripple_ctr8_5;
+ wire or30 = !flop5 | !flop4;
+ wire or31 = ripple_ctr7_4 | !ripple_ctr7_5;
+ wire or32 = !flop17 | pinBallSpeed;
+ wire or33 = !flop5 | flop4;
+ wire or34 = ripple_ctr8_4 | !ripple_ctr8_5;
+ wire or35 = !flop4 | flop5;
+ wire or36 = !ripple_ctr7_4 | ripple_ctr7_5;
+ wire or37 = !flop17 | !pinBallSpeed;
+ wire or38 = !or119 | flop34 | or48 | !or25 | or205;
+ wire or39 = !ripple_ctr8_4 | ripple_ctr8_5;
+ wire or40 = flop17 | pinBallSpeed;
+ wire or41 = flop4 | flop5;
+ wire or42 = ripple_ctr7_4 | ripple_ctr7_5;
+ wire or43 = ripple_ctr8_5 | ripple_ctr8_4;
+ wire or44 = flop17 | !pinBallSpeed;
+ wire or45 = !or25 | !or54 | or48;
+ wire or46 = !pinBallAngle | or41;
+ wire or47 = !pinBallAngle | or35;
+ wire or48 = flop6 | !pinLPin;
+ wire or49 = !or47 | !or30;
+// wire or50 = !or32 | !or37 | !or40 | !or44 | !reset;
+ wire or51 = !or46 | !or33;
+ wire or52 = !pinBatSize | !ripple_ctr10_2;
+ wire or53 = flop7 | pinBatSize;
+ wire or54 = !or53 | !or52;
+ wire or55 = or35 | pinBallAngle;
+ wire or56 = flop6 | !flop7;
+ wire or57 = !reset | !or74;
+ wire or58 = !reset | !or88;
+ wire or59 = !pinBallSpeed | flop9;
+ wire or60 = pinBallSpeed | flop10;
+ wire or61 = !pinBallSpeed | flop8;
+ wire or62 = !pinBallSpeed | flop11;
+ wire or63 = ripple_ctr9_2 | !counter2_2060;
+ wire or64 = ripple_ctr9_2 | !counter2_2048;
+ wire or65 = !or181 | !or71;
+ wire or66 = or41 | pinBallAngle;
+ wire or67 = or158 | !or176;
+ wire or68 = ripple_ctr9_2 | !counter2_2031;
+ wire or69 = !or130 | !or133;
+ wire or70 = ripple_ctr9_2 | !counter2_2013;
+ wire or71 = !flop7 | !counter3_2020;
+ wire or72 = and11 | and12;
+ wire or73 = and9 | and10;
+ wire or74 = ripple_ctr9_2 | !counter2_2064;
+ wire or75 = !or117 | !or112 | !or72 | !or73;
+ wire or76 = or107 | or106 | or105 | !or95 | !or96 | !or97 | !or98 | or110 | or109;
+ wire or77 = or107 | or106 | !or96 | !or97 | !or98 | or110 | or109 | or108;
+ wire or78 = or107 | or106 | or105 | !or95 | !or96 | !or97 | !or98 | or110 | or109 | or108;
+ wire or79 = or107 | or106 | or105 | !or95 | !or97 | !or98 | or108;
+ wire or80 = or107 | or105 | !or95 | !or96 | !or97 | !or98 | or110 | or108;
+ wire or81 = or107 | or105 | !or95 | !or97 | !or98 | or110 | or108;
+ wire or82 = !or95 | !or97 | or110 | or108;
+ wire or83 = or107 | or106 | or105 | !or95 | !or97 | !or98 | or110 | or108;
+ wire or84 = or106 | or105 | !or95 | !or97 | !or98 | or110;
+ wire or85 = or107 | or106 | or105 | !or95 | !or96 | !or97 | !or98 | or110 | or108;
+ wire or86 = !or63 | !counter3_2129;
+ wire or87 = !or117 | or112 | !or72 | !or73;
+ wire or88 = !or63 | !counter3_2131;
+ wire or89 = !or117 | !or112 | or72 | !or73;
+ wire or90 = !flop7 | !counter3_2034;
+ wire or91 = !or117 | or112 | or72 | !or73;
+ wire or92 = !flop7 | !counter3_2022;
+ wire or93 = !or117 | !or112 | or73 | !or72;
+ wire or94 = !or117 | or112 | or73 | !or72;
+ wire or95 = !or117 | !or112 | or73 | or72;
+ wire or96 = !or117 | or112 | or73 | or72;
+ wire or97 = !or112 | or117 | !or72 | !or73;
+ wire or98 = or112 | or117 | !or72 | !or73;
+ wire or99 = !or112 | or117 | or72 | !or73;
+ wire or100 = or112 | or117 | or72 | !or73;
+ wire or101 = !or112 | or117 | or73 | !or72;
+ wire or102 = or112 | or117 | or73 | !or72;
+ wire or103 = !or112 | or117 | or73 | or72;
+ wire or104 = or112 | or117 | or73 | or72;
+ wire or105 = !or94 | !or104;
+ wire or106 = !or93 | !or103;
+ wire or107 = !or91 | !or102;
+ wire or108 = !or89 | !or101;
+ wire or109 = !or87 | !or100;
+ wire or110 = !or75 | !or99;
+ wire or111 = counter1_2000 | counter1_2006;
+ wire or112 = and13 | and14;
+ wire or113 = !and8 | or111;
+ wire or114 = mux2_100 | or111;
+ wire or115 = mux0_100 | or111;
+ wire or116 = mux1_100 | or111;
+ wire or117 = and15 | and16;
+ wire or118 = !or138 | !or128;
+ wire or119 = !or137 | !or132;
+ wire or120 = !or123 | !or122 | !or126;
+ wire or121 = ripple_ctr9_2 | !counter2_2014;
+ wire or122 = ripple_ctr9_2 | or204 | !counter2_2022;
+ wire or123 = ripple_ctr9_2 | or206 | !counter2_2039;
+ wire or124 = ripple_ctr9_2 | !counter2_2049;
+ wire or125 = flop18 | or28;
+ wire or126 = or202 | or64;
+ wire or127 = !or148 | !or134;
+ wire or128 = !or191 | or134;
+ wire or129 = or38 | flop18 | !or191;
+ wire or130 = !or131 | or205;
+ wire or131 = !or139 | !or140 | !or151;
+ wire or132 = or121 | or202;
+ wire or133 = !or205 | ripple_ctr3_2 | flop13;
+ wire or134 = !or176 | or129;
+ wire or135 = ripple_ctr9_2 | !counter2_2029;
+ wire or136 = ripple_ctr9_2 | !counter2_2024;
+ wire or137 = ripple_ctr9_2 | or207 | !counter2_2040;
+ wire or138 = or191 | !or176 | flop18 | or38 | !or165;
+ wire or139 = flop14 | ripple_ctr3_2;
+ wire or140 = flop16 | !ripple_ctr5_2;
+ wire or141 = !or142 | !or136;
+ wire or142 = ripple_ctr9_2 | !or189 | !counter2_2033;
+ wire or143 = ripple_ctr9_2 | !counter2_2038;
+ wire or144 = !or134 | !or147 | !or138;
+ wire or145 = !or182 | !or172;
+ wire or146 = !or147 | !reset;
+ wire or147 = or125 | !or176 | !or167;
+ wire or148 = or161 | !or176;
+ wire or149 = !or147 | !or138 | !or67;
+ wire or150 = !pinRifle1 | and17;
+ wire or151 = flop19 | !ripple_ctr6_2;
+ wire or152 = !or176 | or161;
+ wire or153 = pinRifle2 | !pinSoccer;
+ wire or154 = !flop17 | !or191;
+ wire or155 = !or17 | or170;
+ wire or156 = !flop21 | or191;
+ wire or157 = !or154 | !or156;
+ wire or158 = flop35 | or124 | or204 | !or153;
+ wire or159 = flop17 | !or191;
+ wire or160 = flop34 | or202 | or68;
+ wire or161 = flop35 | or70 | or203;
+ wire or162 = flop21 | or191;
+ wire or163 = !or159 | !or162;
+ wire or164 = !or163 | flop7 | !or176;
+ wire or165 = !flop22 | or191;
+ wire or166 = !or157 | flop7 | !or176;
+ wire or167 = flop22 | or191;
+ wire or168 = !flop7 | !counter3_2096;
+ wire or169 = flop26 | !pinHitIn;
+ wire or170 = !flop29 | flop27;
+ wire or171 = !or161 | !or158;
+ wire or172 = flop12 | !flop20 | ripple_ctr9_2;
+ wire or173 = !flop27 | or205 | flop18;
+ wire or174 = ripple_ctr10_2 | !or171 | flop34;
+ wire or175 = !or124 | !or70;
+ wire or176 = !or5 | !or214;
+ wire or177 = !flop7 | !counter3_2117;
+ wire or178 = !flop7 | or208 | !counter3_2041;
+ wire or179 = !or205 | flop18 | !pinShotIn;
+ wire or180 = !flop7 | !counter3_2116;
+ wire or181 = !flop7 | !counter3_2021;
+ wire or182 = flop12 | !flop15 | ripple_ctr9_2;
+ wire or183 = flop30 | !or179 | !or173;
+ wire or184 = !or160 | !or198 | !or174;
+ wire or185 = !or150 | !pinSoccer;
+ wire or186 = flop29 | or205 | flop18;
+ wire or187 = !or184 | or205;
+ wire or188 = !ripple_ctr6_2 | flop32;
+ wire or189 = !pinSoccer | pinPractice;
+ wire or190 = !or205 | flop18 | !pinHitIn;
+ wire or191 = !pinSoccer | pinSquash;
+ wire or192 = flop30 | !or186 | !or190;
+ wire or193 = ripple_ctr1_4 | ripple_ctr1_3 | ripple_ctr1_2 | ripple_ctr1_5 | or183;
+ wire or194 = !or180 | !or181;
+ wire or195 = !or177 | !or180;
+ wire or196 = flop34 | !flop28;
+ wire or197 = flop12 | shift_reg0_104 | flop33;
+ wire or198 = !or194 | !flop28 | ripple_ctr9_2;
+ wire or199 = !or175 | !or176;
+ wire or200 = ripple_ctr0_5 | ripple_ctr0_2 | ripple_ctr0_3 | ripple_ctr0_4 | or192;
+ wire or201 = !pinSoccer | !or211;
+ wire or202 = !or189 | !or191;
+ wire or203 = !or201 | !or153;
+ wire or204 = !or189 | !or191 | !or201;
+ wire or205 = !or185 | !or153;
+ wire or206 = !pinSoccer | !or201;
+ wire or207 = !or189 | !or201;
+ wire or208 = !or185 | !or189 | !or191;
+ wire or209 = pinPractice | pinSoccer;
+ wire or210 = reset | !or205;
+ wire or211 = !pinTennis | and19;
+ wire or212 = !or187 | !or197;
+ wire or213 = pinSquash | pinSoccer;
+ wire or214 = pinSoccer | pinRifle2;
+ reg [5:0] shift_reg0 = 0;
+ reg [3:0] shift_reg0_spot = 0;
+/* verilator lint_off WIDTH */
+ wire shift_reg0_104 = shift_reg0[shift_reg0_spot];
+/* verilator lint_on WIDTH */
+ always @(negedge or145 or posedge flop24) begin
+ if(flop24) begin
+ shift_reg0_spot <= 5;
+ end
+ else if(shift_reg0_spot!=0) begin
+ shift_reg0_spot <= shift_reg0_spot - 1;
+ end
+ end
+ //MC: This block had to be manually changed
+ always @(posedge flop24) begin
+ shift_reg0[0:0] <= 1;
+ shift_reg0[1:1] <= or115;
+ shift_reg0[2:2] <= or116;
+ shift_reg0[3:3] <= or114;
+ shift_reg0[4:4] <= 1;
+ shift_reg0[5:5] <= or113;
+ end
+ //MC: All ripple counter outputs (except paddle ones) have inverted resets & outputs
+ reg [4:0] ripple_ctr0 = 0;
+ wire ripple_ctr0_2 = !ripple_ctr0[0:0];
+ wire ripple_ctr0_3 = !ripple_ctr0[1:1];
+ wire ripple_ctr0_4 = !ripple_ctr0[2:2];
+ wire ripple_ctr0_5 = !ripple_ctr0[3:3];
+ always @(posedge or192 or negedge reset) begin
+ if(!reset)
+ ripple_ctr0 <= 0;
+ else
+ ripple_ctr0 <= ripple_ctr0 + 1;
+ end
+
+ reg [4:0] ripple_ctr1 = 0;
+ wire ripple_ctr1_2 = !ripple_ctr1[0:0];
+ wire ripple_ctr1_3 = !ripple_ctr1[1:1];
+ wire ripple_ctr1_4 = !ripple_ctr1[2:2];
+ wire ripple_ctr1_5 = !ripple_ctr1[3:3];
+ always @(posedge or183 or negedge reset) begin
+ if(!reset)
+ ripple_ctr1 <= 0;
+ else
+ ripple_ctr1 <= ripple_ctr1 + 1;
+ end
+
+ reg [1:0] ripple_ctr2 = 0;
+ wire ripple_ctr2_2 = !ripple_ctr2[0:0];
+ always @(negedge ripple_ctr10_2 or negedge or213) begin
+ if(!or213)
+ ripple_ctr2 <= 0;
+ else
+ ripple_ctr2 <= ripple_ctr2 + 1;
+ end
+
+ reg [1:0] ripple_ctr3 = 0;
+ wire ripple_ctr3_2 = !ripple_ctr3[0:0];
+ always @(negedge ripple_ctr2_2 or negedge or213) begin
+ if(!or213)
+ ripple_ctr3 <= 0;
+ else
+ ripple_ctr3 <= ripple_ctr3 + 1;
+ end
+
+ reg [4:0] ripple_ctr4 = 0;
+ wire ripple_ctr4_2 = !ripple_ctr4[0:0];
+ wire ripple_ctr4_3 = !ripple_ctr4[1:1];
+ wire ripple_ctr4_4 = !ripple_ctr4[2:2];
+ wire ripple_ctr4_5 = !ripple_ctr4[3:3];
+ always @(negedge or188 or posedge flop31) begin
+ if(flop31)
+ ripple_ctr4 <= 0;
+ else
+ ripple_ctr4 <= ripple_ctr4 + 1;
+ end
+
+ reg [1:0] ripple_ctr5 = 0;
+ wire ripple_ctr5_2 = !ripple_ctr5[0:0];
+ always @(negedge ripple_ctr3_2 or negedge reset) begin
+ if(!reset)
+ ripple_ctr5 <= 0;
+ else
+ ripple_ctr5 <= ripple_ctr5 + 1;
+ end
+
+ reg [1:0] ripple_ctr6 = 0;
+ wire ripple_ctr6_2 = !ripple_ctr6[0:0];
+ always @(negedge ripple_ctr5_2 or negedge reset) begin
+ if(!reset)
+ ripple_ctr6 <= 0;
+ else
+ ripple_ctr6 <= ripple_ctr6 + 1;
+ end
+
+ reg [4:0] ripple_ctr7 = 0;
+ wire ripple_ctr7_2 = ripple_ctr7[0:0];
+ wire ripple_ctr7_3 = ripple_ctr7[1:1];
+ wire ripple_ctr7_4 = ripple_ctr7[2:2];
+ wire ripple_ctr7_5 = ripple_ctr7[3:3];
+ always @(negedge or21 or posedge or14) begin
+ if(or14)
+ ripple_ctr7 <= 0;
+ else
+ ripple_ctr7 <= ripple_ctr7 + 1;
+ end
+
+ reg [4:0] ripple_ctr8 = 0;
+ wire ripple_ctr8_2 = ripple_ctr8[0:0];
+ wire ripple_ctr8_3 = ripple_ctr8[1:1];
+ wire ripple_ctr8_4 = ripple_ctr8[2:2];
+ wire ripple_ctr8_5 = ripple_ctr8[3:3];
+ always @(negedge or45 or posedge or48) begin
+ if(or48)
+ ripple_ctr8 <= 0;
+ else
+ ripple_ctr8 <= ripple_ctr8 + 1;
+ end
+
+ reg [1:0] ripple_ctr9 = 0;
+ wire ripple_ctr9_2 = !ripple_ctr9[0:0];
+ always @(negedge slow_clock or negedge or213) begin
+ if(!or213)
+ ripple_ctr9 <= 0;
+ else
+ ripple_ctr9 <= ripple_ctr9 + 1;
+ end
+
+ reg [1:0] ripple_ctr10 = 0;
+ wire ripple_ctr10_2 = !ripple_ctr10[0:0];
+ always @(posedge flop7 or negedge or213) begin
+ if(!or213)
+ ripple_ctr10 <= 0;
+ else
+ ripple_ctr10 <= ripple_ctr10 + 1;
+ end
+
+ //MC: Add flop12 reset
+ reg [2:0] counter0 = 0;
+ wire counter0_2003 = (counter0==3);
+ always @(negedge flop7 or posedge flop12) begin
+ if(flop12)
+ counter0 <= 0;
+ else if(counter0==3)
+ counter0 <= 0;
+ else
+ counter0 <= counter0 + 1;
+ end
+ reg [3:0] counter1 = 0;
+ wire counter1_2005 = (counter1==5);
+ wire counter1_2003 = (counter1==3);
+ wire counter1_2006 = (counter1==6);
+ wire counter1_2000 = (counter1==0);
+ wire counter1_2001 = (counter1==1);
+ wire counter1_2002 = (counter1==2);
+ wire counter1_2004 = (counter1==4);
+ always @(negedge counter0_2003 or posedge flop12) begin
+ if(flop12)
+ counter1 <= 0;
+ else if(counter1==6)
+ counter1 <= 0;
+ else
+ counter1 <= counter1 + 1;
+ end
+ reg [7:0] counter2 = 0;
+ wire counter2_2038 = (counter2==38);
+ wire counter2_2033 = (counter2==33);
+ wire counter2_2029 = (counter2==29);
+ wire counter2_2049 = (counter2==49);
+ wire counter2_2022 = (counter2==22);
+ wire counter2_2064 = (counter2==64);
+ wire counter2_2048 = (counter2==48);
+ wire counter2_2040 = (counter2==40);
+ wire counter2_2039 = (counter2==39);
+ wire counter2_2031 = (counter2==31);
+ wire counter2_2024 = (counter2==24);
+ wire counter2_2014 = (counter2==14);
+ wire counter2_2013 = (counter2==13);
+ wire counter2_2060 = (counter2==60);
+ always @(posedge ripple_ctr9_2 or posedge or57) begin
+ if(or57)
+ counter2 <= 0;
+ else if(counter2==126)
+ counter2 <= 0;
+ else
+ counter2 <= counter2 + 1;
+ end
+ reg [8:0] counter3 = 0;
+ wire counter3_2129 = (counter3==129);
+ wire counter3_2131 = (counter3==131);
+ wire counter3_2117 = (counter3==117);
+ wire counter3_2096 = (counter3==96);
+ wire counter3_2022 = (counter3==22);
+ wire counter3_2020 = (counter3==20);
+ wire counter3_2116 = (counter3==116);
+ wire counter3_2041 = (counter3==41);
+ wire counter3_2034 = (counter3==34);
+ wire counter3_2021 = (counter3==21);
+ always @(posedge ripple_ctr10_2 or posedge or58) begin
+ if(or58)
+ counter3 <= 0;
+ else if(counter3==216)
+ counter3 <= 0;
+ else
+ counter3 <= counter3 + 1;
+ end
+ //MC: Multiple changes to jumping counters
+ reg [8:0] counter4 = 0;
+ reg counter4_delay = 0;
+ reg counter4_jump = 0;
+ wire counter4_2130 = (counter4==129);
+ wire counter4_2125 = (counter4==125);
+ wire counter4_2128 = (counter4==128);
+ always @(posedge slow_clock) begin
+ if(!reset | flop3) begin
+ counter4 <= 0;
+ counter4_jump <= 0;
+ end
+ else begin
+ if(counter4==129) begin
+ counter4 <= !counter4_jump ? 2 : !or32 ? 0 : !or37 ? 1 : !or40 ? 4 : !or44 ? 3 : 0;//MC: 3 & 4 changed to 4 & 5
+ counter4_jump <= 0;
+ end
+ else begin
+ counter4_delay <= pulser0;
+ if(!counter4_delay && pulser0)
+ counter4_jump <= 1;
+ counter4 <= counter4 + 1;
+ end
+ end
+ end
+
+ reg [9:0] counter5 = 0;
+ reg counter5_delay = 0;
+ reg counter5_jump = 0;
+ wire counter5_2254 = (counter5==254);
+ wire counter5_2263 = (counter5==263);
+ wire counter5_2265 = (counter5==265);
+ wire counter5_2268 = (counter5==267);
+ always @(negedge flop7) begin
+ if(!reset) begin
+ counter5 <= 0;
+ counter5_jump <= 0;
+ end
+ else begin
+ if(counter5==267) begin//Values > non-jump must be increased by 4?
+ counter5 <= !counter5_jump ? 6 : !or59 ? 11 : !or9 ? 15 : !or10 ? 12 : !or62 ? 5 : !or61 ? 13 : !or11 ? 4 : !or12 ? 3 : !or60 ? 1 : 0;
+ counter5_jump <= 0;
+ end
+ else begin
+ counter5_delay <= pulser0;
+ if(!counter5_delay && pulser0)
+ counter5_jump <= 1;
+ counter5 <= counter5 + 1;
+ end
+ end
+ end
+ wire mux0_100 = (!or78 & counter1_2001) | (!or77 & counter1_2002) | (!or76 & counter1_2004);
+ //MC: Some changes to this line
+ wire mux1_100 = (!or81 & counter1_2005) | (!or80 & counter1_2001) | (!or79 & counter1_2003) | counter1_2002 | counter1_2004;//constants had to be added manually
+ wire mux2_100 = (!or81 & counter1_2005) | (!or85 & counter1_2001) | (!or83 & counter1_2003) | (!or84 & counter1_2002) | (!or82 & counter1_2004);
+endmodule
+/*verilator lint_on UNOPTFLAT */
diff --git a/common/k580wi53.v b/common/k580wi53.v
new file mode 100644
index 00000000..e11acba2
--- /dev/null
+++ b/common/k580wi53.v
@@ -0,0 +1,151 @@
+// ====================================================================
+// Bashkiria-2M FPGA REPLICA
+//
+// Copyright (C) 2010 Dmitry Tselikov
+//
+// This core is distributed under modified BSD license.
+// For complete licensing information see LICENSE.TXT.
+// --------------------------------------------------------------------
+//
+// An open implementation of Bashkiria-2M home computer
+//
+// Author: Dmitry Tselikov http://bashkiria-2m.narod.ru/
+//
+// Design File: k580wi53.v
+//
+// Interval timer k580wi53 design file of Bashkiria-2M replica.
+
+module k580wi53(input clk,
+ input c0, input c1, input c2,
+ input g0, input g1, input g2,
+ output out0, output out1, output out2,
+ input[1:0] addr, input rd, input we_n, input[7:0] idata, output reg[7:0] odata);
+
+wire[7:0] odata0;
+wire[7:0] odata1;
+wire[7:0] odata2;
+
+always @(*)
+ case (addr)
+ 2'b00: odata = odata0;
+ 2'b01: odata = odata1;
+ 2'b10: odata = odata2;
+ 2'b11: odata = 0;
+ endcase
+
+k580wi53channel ch0(.clk(clk), .c(c0), .gate(g0), .cout(out0), .addr(&addr), .rd(rd && addr==2'b00), .we_n(we_n || (addr!=2'b00 && (addr!=2'b11 || idata[7:6]!=2'b00))), .idata(idata), .odata(odata0));
+k580wi53channel ch1(.clk(clk), .c(c1), .gate(g1), .cout(out1), .addr(&addr), .rd(rd && addr==2'b01), .we_n(we_n || (addr!=2'b01 && (addr!=2'b11 || idata[7:6]!=2'b01))), .idata(idata), .odata(odata1));
+k580wi53channel ch2(.clk(clk), .c(c2), .gate(g2), .cout(out2), .addr(&addr), .rd(rd && addr==2'b10), .we_n(we_n || (addr!=2'b10 && (addr!=2'b11 || idata[7:6]!=2'b10))), .idata(idata), .odata(odata2));
+
+endmodule
+
+module k580wi53channel(input clk, input c, input gate, output reg cout,
+ input addr, input rd, input we_n, input[7:0] idata, output reg[7:0] odata);
+
+reg[5:0] mode;
+reg[15:0] init;
+reg[15:0] cntlatch;
+reg[15:0] counter;
+reg[15:0] sub1;
+reg[15:0] sub2;
+reg enabled;
+reg latched;
+reg loaded;
+reg ff;
+reg first;
+reg done;
+reg exc;
+reg exgate;
+reg exrd;
+reg exwe_n;
+
+always @(*)
+ case ({latched,ff})
+ 2'b00: odata = counter[7:0];
+ 2'b01: odata = counter[15:8];
+ 2'b10: odata = cntlatch[7:0];
+ 2'b11: odata = cntlatch[15:8];
+ endcase
+
+always @(*)
+ casex ({mode[0],|counter[15:12],|counter[11:8],|counter[7:4],|counter[3:0]})
+ 5'b10000: sub1 = 16'h9999;
+ 5'b11000: sub1 = 16'hF999;
+ 5'b1x100: sub1 = 16'hFF99;
+ 5'b1xx10: sub1 = 16'hFFF9;
+ default: sub1 = 16'hFFFF;
+ endcase
+
+always @(*)
+ casex ({mode[0],|counter[15:12],|counter[11:8],|counter[7:4],|counter[3:1]})
+ 5'b10000: sub2 = 16'h9998;
+ 5'b11000: sub2 = 16'hF998;
+ 5'b1x100: sub2 = 16'hFF98;
+ 5'b1xx10: sub2 = 16'hFFF8;
+ default: sub2 = 16'hFFFE;
+ endcase
+
+wire[15:0] new1 = counter + (first|~&mode[2:1]?sub1:sub2);
+wire[15:0] newvalue = {new1[15:1],new1[0]&~&mode[2:1]};
+
+always @(posedge clk)
+begin
+ exc <= c; exgate <= gate; exrd <= rd; exwe_n <= we_n;
+ if (enabled & c & ~exc) begin
+ if (loaded) begin
+ if (mode[2]==1'b1 && newvalue==0) begin
+ counter <= init;
+ first <= init[0]&~cout;
+ end else begin
+ counter <= newvalue;
+ first <= 0;
+ end
+ if (newvalue[15:1]==0 && ~done) begin
+ casex ({mode[3:1],newvalue[0]})
+ 4'b0000: {cout,done} <= 2'b11;
+ 4'b0010: {cout,done} <= 2'b11;
+ 4'bx100: cout <= 1'b1;
+ 4'bx101: cout <= 0;
+ 4'bx11x: cout <= ~cout;
+ 4'b1000: {cout,done} <= 2'b11;
+ 4'b1001: cout <= 0;
+ 4'b1010: {cout,done} <= 2'b11;
+ 4'b1011: cout <= 0;
+ endcase
+ end
+ end else begin
+ counter <= init; loaded <= 1'b1; first <= 1'b1; done <= 0;
+ if (mode[3:2]==0) cout <= 0;
+ end
+ end
+ if (exgate ^ gate) begin
+ if (mode[2:1]!=2'b01) enabled <= gate;
+ else if (gate) begin loaded <= 0; enabled <= 1; end
+ end
+ if (exrd & ~rd) begin
+ if (mode[5:4]==2'b11) ff <= ~ff;
+ if (mode[5:4]!=2'b11 || ff) latched <= 0;
+ end else
+ if (exwe_n & ~we_n) begin
+ if (addr) begin
+ if (idata[5:4]==0) begin
+ cntlatch <= counter; latched <= 1;
+ end else begin
+ mode <= idata[5:0]; enabled <= 0; loaded <= 0; done <= 1'b1;
+ latched <= 0; cout <= idata[3:1]!=0;
+ end
+ ff <= idata[5:4]==2'b10;
+ end else begin
+ casex ({mode[5:4],ff})
+ 3'b01x: begin init <= {8'h00,idata}; enabled <= gate; ff <= 0; end
+ 3'b10x: begin init <= {idata,8'h00}; enabled <= gate; ff <= 1; end
+ 3'b110: begin init[7:0] <= idata; enabled <= 0; ff <= 1; end
+ 3'b111: begin init[15:8] <= idata; enabled <= gate; ff <= 0; end
+ endcase
+ loaded <= mode[2:1]!=0 & ~done;
+ cout <= mode[3:1]!=0||(mode[5:4]==2'b01&&idata==8'b1);
+ end
+ end
+end
+
+endmodule
diff --git a/common/k580wm80a.v b/common/k580wm80a.v
new file mode 100644
index 00000000..89ccd2c8
--- /dev/null
+++ b/common/k580wm80a.v
@@ -0,0 +1,473 @@
+// ====================================================================
+// Bashkiria-2M FPGA REPLICA
+//
+// Copyright (C) 2010 Dmitry Tselikov
+//
+// This core is distributed under modified BSD license.
+// For complete licensing information see LICENSE.TXT.
+// --------------------------------------------------------------------
+//
+// An open implementation of Bashkiria-2M home computer
+//
+// Author: Dmitry Tselikov http://bashkiria-2m.narod.ru/
+//
+// Design File: k580wm80a.v
+//
+// Processor k580wm80a core design file of Bashkiria-2M replica.
+
+module k580wm80a(
+ input clk,
+ input ce,
+ input reset,
+ input intr,
+ input [7:0] idata,
+ output reg [15:0] addr,
+ output reg sync,
+ output rd,
+ output reg wr_n,
+ output inta_n,
+ output reg [7:0] odata,
+ output inte_o);
+
+reg M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16,M17,T5;
+reg[2:0] state;
+
+wire M1n = M2|M3|M4|M5|M6|M7|M8|M9|M10|M11|M12|M13|M14|M15|M16|M17;
+
+reg[15:0] PC;
+reg[15:0] SP;
+reg[7:0] B,C,D,E,H,L,A;
+reg[7:0] W,Z,IR;
+reg[9:0] ALU;
+reg FS,FZ,FA,FP,FC,_FA;
+
+reg rd_,intproc;
+assign rd = rd_&~intproc;
+assign inta_n = ~(rd_&intproc);
+assign inte_o = inte[1];
+
+reg[1:0] inte;
+reg jmp,call,halt;
+reg save_alu,save_a,save_r,save_rp,read_r,read_rp;
+reg incdec,xthl,xchg,sphl,daa;
+reg ccc;
+
+always @(*) begin
+ casex (IR[5:3])
+ 3'b00x: ALU = {1'b0,A,1'b1}+{1'b0,Z,FC&IR[3]};
+ 3'b01x: ALU = {1'b0,A,1'b0}-{1'b0,Z,FC&IR[3]};
+ 3'b100: ALU = {1'b0,A & Z,1'b0};
+ 3'b101: ALU = {1'b0,A ^ Z,1'b0};
+ 3'b110: ALU = {1'b0,A | Z,1'b0};
+ 3'b111: ALU = {1'b0,A,1'b0}-{1'b0,Z,1'b0};
+ endcase
+end
+
+always @(*) begin
+ casex (IR[5:3])
+ 3'b00x: _FA = A[4]^Z[4]^ALU[5];
+ 3'b100: _FA = A[3]|Z[3];
+ 3'b101: _FA = 1'b0;
+ 3'b110: _FA = 1'b0;
+ default: _FA = ~(A[4]^Z[4]^ALU[5]);
+ endcase
+end
+
+always @(*) begin
+ // SZ.A.P.C
+ case(idata[5:3])
+ 3'h0: ccc = ~FZ;
+ 3'h1: ccc = FZ;
+ 3'h2: ccc = ~FC;
+ 3'h3: ccc = FC;
+ 3'h4: ccc = ~FP;
+ 3'h5: ccc = FP;
+ 3'h6: ccc = ~FS;
+ 3'h7: ccc = FS;
+ endcase
+end
+
+wire[7:0] F = {FS,FZ,1'b0,FA,1'b0,FP,1'b1,FC};
+wire[7:0] Z1 = incdec ? Z+{{7{IR[0]}},1'b1} : Z;
+wire[15:0] WZ1 = incdec ? {W,Z}+{{15{IR[3]}},1'b1} : {W,Z};
+wire[3:0] daaZL = FA!=0 || A[3:0] > 4'h9 ? 4'h6 : 4'h0;
+wire[3:0] daaZH = FC!=0 || A[7:4] > {3'b100, A[3:0]>4'h9 ? 1'b0 : 1'b1} ? 4'h6 : 4'h0;
+
+always @(posedge clk or posedge reset)
+begin
+ if (reset) begin
+ {M1,M2,M3,M4,M5,M6,M7,M8,M9,M10,M11,M12,M13,M14,M15,M16,M17} <= 0;
+ state <= 0; PC <= 0; {FS,FZ,FA,FP,FC} <= 0; {addr,odata} <= 0;
+ {sync,rd_,jmp,halt,inte,save_alu,save_a,save_r,save_rp,incdec,intproc} <= 0;
+ wr_n <= 1'b1;
+ end else if (ce) begin
+ sync <= 0; rd_ <= 0; wr_n <= 1'b1;
+ if (halt&~(M1|(intr&inte[1]))) begin
+ sync <= 1'b1; // state: rd in m1 out hlt stk ~wr int
+ odata <= 8'b10001010; // rd? hlt ~wr
+ end else
+ if (M1|~M1n) begin
+ case (state)
+ 3'b000: begin
+ halt <= 0; intproc <= intr&inte[1]; inte[1] <= inte[0];
+ M1 <= 1'b1;
+ sync <= 1'b1;
+ odata <= {7'b1010001,intr&inte[1]}; // rd m1 ~wr
+ addr <= jmp ? {W,Z} : PC;
+ state <= 3'b001;
+ if (intr&inte[1]) inte <= 2'b0;
+ if (save_alu) begin
+ FS <= ALU[8];
+ FZ <= ~|ALU[8:1];
+ FA <= _FA;
+ FP <= ~^ALU[8:1];
+ FC <= ALU[9]|(FC&daa);
+ if (IR[5:3]!=3'b111) A <= ALU[8:1];
+ end else
+ if (save_a) begin
+ A <= Z1;
+ end else
+ if (save_r) begin
+ case (IR[5:3])
+ 3'b000: B <= Z1;
+ 3'b001: C <= Z1;
+ 3'b010: D <= Z1;
+ 3'b011: E <= Z1;
+ 3'b100: H <= Z1;
+ 3'b101: L <= Z1;
+ 3'b111: A <= Z1;
+ endcase
+ if (incdec) begin
+ FS <= Z1[7];
+ FZ <= ~|Z1;
+ FA <= IR[0] ? Z1[3:0]!=4'b1111 : Z1[3:0]==0;
+ FP <= ~^Z1;
+ end
+ end else
+ if (save_rp) begin
+ case (IR[5:4])
+ 2'b00: {B,C} <= WZ1;
+ 2'b01: {D,E} <= WZ1;
+ 2'b10: {H,L} <= WZ1;
+ 2'b11:
+ if (sphl || !IR[7]) begin
+ SP <= WZ1;
+ end else begin
+ {A,FS,FZ,FA,FP,FC} <= {WZ1[15:8],WZ1[7],WZ1[6],WZ1[4],WZ1[2],WZ1[0]};
+ end
+ endcase
+ end
+ end
+ 3'b001: begin
+ rd_ <= 1'b1;
+ PC <= addr+{15'b0,~intproc};
+ state <= 3'b010;
+ end
+ 3'b010: begin
+ IR <= idata;
+ {jmp,call,save_alu,save_a,save_r,save_rp,read_r,read_rp,incdec,xthl,xchg,sphl,T5,daa} <= 0;
+ casex (idata)
+ 8'b00xx0001: {save_rp,M2,M3} <= 3'b111;
+ 8'b00xx1001: {read_rp,M16,M17} <= 3'b111;
+ 8'b000x0010: {read_rp,M14} <= 2'b11;
+ 8'b00100010: {M2,M3,M14,M15} <= 4'b1111;
+ 8'b00110010: {M2,M3,M14} <= 3'b111;
+ 8'b000x1010: {read_rp,save_a,M12} <= 3'b111;
+ 8'b00101010: {save_rp,M2,M3,M12,M13} <= 5'b11111;
+ 8'b00111010: {save_a,M2,M3,M12} <= 4'b1111;
+ 8'b00xxx011: {read_rp,save_rp,incdec,T5} <= 4'b1111;
+ 8'b00xxx10x: {read_r,save_r,incdec,T5} <= {3'b111,idata[5:3]!=3'b110};
+ 8'b00xxx110: {save_r,M2} <= 2'b11;
+ 8'b00000111: {FC,A} <= {A,A[7]};
+ 8'b00001111: {A,FC} <= {A[0],A};
+ 8'b00010111: {FC,A} <= {A,FC};
+ 8'b00011111: {A,FC} <= {FC,A};
+ 8'b00100111: {daa,save_alu,IR[5:3],Z} <= {5'b11000,daaZH,daaZL};
+ 8'b00101111: A <= ~A;
+ 8'b00110111: FC <= 1'b1;
+ 8'b00111111: FC <= ~FC;
+ 8'b01xxxxxx: if (idata[5:0]==6'b110110) halt <= 1'b1; else {read_r,save_r,T5} <= {2'b11,~(idata[5:3]==3'b110||idata[2:0]==3'b110)};
+ 8'b10xxxxxx: {read_r,save_alu} <= 2'b11;
+ 8'b11xxx000: {jmp,M8,M9} <= {3{ccc}};
+ 8'b11xx0001: {save_rp,M8,M9} <= 3'b111;
+ 8'b110x1001: {jmp,M8,M9} <= 3'b111;
+ 8'b11101001: {read_rp,jmp,T5} <= 3'b111;
+ 8'b11111001: {read_rp,save_rp,T5,sphl} <= 4'b1111;
+ 8'b11xxx010: {jmp,M2,M3} <= {ccc,2'b11};
+ 8'b1100x011: {jmp,M2,M3} <= 3'b111;
+ 8'b11010011: {M2,M7} <= 2'b11;
+ 8'b11011011: {M2,M6} <= 2'b11;
+ 8'b11100011: {save_rp,M8,M9,M10,M11,xthl} <= 6'b111111;
+ 8'b11101011: {read_rp,save_rp,xchg} <= 3'b111;
+ 8'b1111x011: inte <= idata[3] ? 2'b1 : 2'b0;
+ 8'b11xxx100: {jmp,M2,M3,T5,M10,M11,call} <= {ccc,3'b111,{3{ccc}}};
+ 8'b11xx0101: {read_rp,T5,M10,M11} <= 4'b1111;
+ 8'b11xx1101: {jmp,M2,M3,T5,M10,M11,call} <= 7'b1111111;
+ 8'b11xxx110: {save_alu,M2} <= 2'b11;
+ 8'b11xxx111: {jmp,T5,M10,M11,call,W,Z} <= {5'b11111,10'b0,idata[5:3],3'b0};
+ endcase
+ state <= 3'b011;
+ end
+ 3'b011: begin
+ if (read_rp) begin
+ case (IR[5:4])
+ 2'b00: {W,Z} <= {B,C};
+ 2'b01: {W,Z} <= {D,E};
+ 2'b10: {W,Z} <= xchg ? {D,E} : {H,L};
+ 2'b11: {W,Z} <= sphl ? {H,L} : IR[7] ? {A,F} : SP;
+ endcase
+ if (xchg) {D,E} <= {H,L};
+ end else
+ if (~(jmp|daa)) begin
+ case (incdec?IR[5:3]:IR[2:0])
+ 3'b000: Z <= B;
+ 3'b001: Z <= C;
+ 3'b010: Z <= D;
+ 3'b011: Z <= E;
+ 3'b100: Z <= H;
+ 3'b101: Z <= L;
+ 3'b110: M4 <= read_r;
+ 3'b111: Z <= A;
+ endcase
+ M5 <= save_r && IR[5:3]==3'b110;
+ end
+ state <= T5 ? 3'b100 : 0;
+ M1 <= T5;
+ end
+ 3'b100: begin
+ if (M10) SP <= SP-16'b1;
+ state <= 0;
+ M1 <= 0;
+ end
+ endcase
+ end else
+ if (M2 || M3) begin
+ case (state)
+ 3'b000: begin
+ sync <= 1'b1;
+ odata <= {7'b1000001,intproc}; // rd ~wr
+ addr <= PC;
+ state <= 3'b001;
+ end
+ 3'b001: begin
+ rd_ <= 1'b1;
+ PC <= addr+{15'b0,~intproc};
+ state <= 3'b010;
+ end
+ 3'b010: begin
+ if (M2) begin
+ Z <= idata;
+ M2 <= 0;
+ end else begin
+ W <= idata;
+ M3 <= 0;
+ end
+ state <= 3'b000;
+ end
+ endcase
+ end else
+ if (M4) begin
+ case (state)
+ 3'b000: begin
+ sync <= 1'b1;
+ odata <= {7'b1000001,intproc}; // rd ~wr
+ addr <= {H,L};
+ state <= 3'b001;
+ end
+ 3'b001: begin
+ rd_ <= 1'b1;
+ state <= 3'b010;
+ end
+ 3'b010: begin
+ Z <= idata;
+ M4 <= 0;
+ state <= 3'b000;
+ end
+ endcase
+ end else
+ if (M5) begin
+ case (state)
+ 3'b000: begin
+ sync <= 1'b1;
+ odata <= {7'b0000000,intproc}; // ~wr=0
+ addr <= {H,L};
+ state <= 3'b001;
+ end
+ 3'b001: begin
+ odata <= Z1;
+ wr_n <= 1'b0;
+ state <= 3'b010;
+ end
+ 3'b010: begin
+ M5 <= 0;
+ state <= 3'b000;
+ end
+ endcase
+ end else
+ if (M6) begin
+ case (state)
+ 3'b000: begin
+ sync <= 1'b1;
+ odata <= {7'b0100001,intproc}; // in ~wr
+ addr <= {Z,Z};
+ state <= 3'b001;
+ end
+ 3'b001: begin
+ rd_ <= 1'b1;
+ state <= 3'b010;
+ end
+ 3'b010: begin
+ A <= idata;
+ M6 <= 0;
+ state <= 3'b000;
+ end
+ endcase
+ end else
+ if (M7) begin
+ case (state)
+ 3'b000: begin
+ sync <= 1'b1;
+ odata <= {7'b0001000,intproc}; // out
+ addr <= {Z,Z};
+ state <= 3'b001;
+ end
+ 3'b001: begin
+ odata <= A;
+ wr_n <= 1'b0;
+ state <= 3'b010;
+ end
+ 3'b010: begin
+ M7 <= 0;
+ state <= 3'b000;
+ end
+ endcase
+ end else
+ if (M8 || M9) begin
+ case (state)
+ 3'b000: begin
+ sync <= 1'b1;
+ odata <= {7'b1000011,intproc}; // rd stk ~wr
+ addr <= SP;
+ state <= 3'b001;
+ end
+ 3'b001: begin
+ rd_ <= 1'b1;
+ if (M8 || !xthl) SP <= SP+16'b1;
+ state <= 3'b010;
+ end
+ 3'b010: begin
+ if (M8) begin
+ Z <= idata;
+ M8 <= 0;
+ end else begin
+ W <= idata;
+ M9 <= 0;
+ end
+ state <= 3'b000;
+ end
+ endcase
+ end else
+ if (M10 || M11) begin
+ case (state)
+ 3'b000: begin
+ sync <= 1'b1;
+ odata <= {7'b0000010,intproc}; // stk
+ addr <= SP;
+ state <= 3'b001;
+ end
+ 3'b001: begin
+ if (M10) begin
+ SP <= SP-16'b1;
+ odata <= xthl ? H : call ? PC[15:8] : W;
+ end else begin
+ odata <= xthl ? L : call ? PC[7:0] : Z;
+ end
+ wr_n <= 1'b0;
+ state <= 3'b010;
+ end
+ 3'b010: begin
+ if (M10) begin
+ M10 <= 0;
+ end else begin
+ M11 <= 0;
+ end
+ state <= 3'b000;
+ end
+ endcase
+ end else
+ if (M12 || M13) begin
+ case (state)
+ 3'b000: begin
+ sync <= 1'b1;
+ odata <= {7'b1000001,intproc}; // rd ~wr
+ addr <= M12 ? {W,Z} : addr+16'b1;
+ state <= 3'b001;
+ end
+ 3'b001: begin
+ rd_ <= 1'b1;
+ state <= 3'b010;
+ end
+ 3'b010: begin
+ if (M12) begin
+ Z <= idata;
+ M12 <= 0;
+ end else begin
+ W <= idata;
+ M13 <= 0;
+ end
+ state <= 3'b000;
+ end
+ endcase
+ end else
+ if (M14 || M15) begin
+ case (state)
+ 3'b000: begin
+ sync <= 1'b1;
+ odata <= {7'b0000000,intproc}; // ~wr=0
+ addr <= M14 ? {W,Z} : addr+16'b1;
+ state <= 3'b001;
+ end
+ 3'b001: begin
+ if (M14) begin
+ odata <= M15 ? L : A;
+ end else begin
+ odata <= H;
+ end
+ wr_n <= 1'b0;
+ state <= 3'b010;
+ end
+ 3'b010: begin
+ if (M14) begin
+ M14 <= 0;
+ end else begin
+ M15 <= 0;
+ end
+ state <= 3'b000;
+ end
+ endcase
+ end else
+ if (M16 || M17) begin
+ case (state)
+ 3'b000: begin
+ sync <= 1'b1;
+ odata <= {7'b0000001,intproc}; // ~wr
+ state <= 3'b001;
+ end
+ 3'b001: begin
+ state <= 3'b010;
+ end
+ 3'b010: begin
+ if (M16) begin
+ M16 <= 0;
+ end else begin
+ {FC,H,L} <= {1'b0,H,L}+{1'b0,W,Z};
+ M17 <= 0;
+ end
+ state <= 3'b000;
+ end
+ endcase
+ end
+ end
+end
+
+endmodule
diff --git a/common/k580wn59.v b/common/k580wn59.v
new file mode 100644
index 00000000..6bbe2e38
--- /dev/null
+++ b/common/k580wn59.v
@@ -0,0 +1,95 @@
+// ====================================================================
+// Bashkiria-2M FPGA REPLICA
+//
+// Copyright (C) 2010 Dmitry Tselikov
+//
+// This core is distributed under modified BSD license.
+// For complete licensing information see LICENSE.TXT.
+// --------------------------------------------------------------------
+//
+// An open implementation of Bashkiria-2M home computer
+//
+// Author: Dmitry Tselikov http://bashkiria-2m.narod.ru/
+//
+// Design File: k580wn59.v
+//
+// Programmable interrupt controller k580wn59 design file of Bashkiria-2M replica.
+//
+// Warning: Interrupt level shift not supported.
+
+module k580wn59(
+ input clk, input reset, input addr, input we_n,
+ input[7:0] idata, output reg[7:0] odata,
+ output intr, input inta_n, input[7:0] irq);
+
+reg[1:0] state;
+reg[7:0] irqmask;
+reg[7:0] smask;
+reg[7:0] serviced;
+reg[2:0] addr0;
+reg[7:0] addr1;
+reg init;
+reg addrfmt;
+reg exinta_n;
+
+wire[7:0] r = irq & ~(irqmask | smask);
+assign intr = |r;
+
+reg[2:0] x;
+always @(*)
+ casex (r)
+ 8'bxxxxxxx1: x = 3'b000;
+ 8'bxxxxxx10: x = 3'b001;
+ 8'bxxxxx100: x = 3'b010;
+ 8'bxxxx1000: x = 3'b011;
+ 8'bxxx10000: x = 3'b100;
+ 8'bxx100000: x = 3'b101;
+ 8'bx1000000: x = 3'b110;
+ default: x = 3'b111;
+ endcase
+
+always @(*)
+ casex ({inta_n,state})
+ 3'b000: odata = 8'hCD;
+ 3'bx01: odata = addrfmt ? {addr0,x,2'b00} : {addr0[2:1],x,3'b000};
+ 3'bx1x: odata = addr1;
+ 3'b100: odata = addr ? irqmask : irq;
+ endcase
+
+always @(posedge clk or posedge reset) begin
+ if (reset) begin
+ state <= 0; init <= 0; irqmask <= 8'hFF; smask <= 8'hFF; serviced <= 0; exinta_n <= 1'b1;
+ end else begin
+ exinta_n <= inta_n;
+ smask <= smask & (irq|serviced);
+ case (state)
+ 2'b00: begin
+ if (~we_n) begin
+ init <= 0;
+ casex ({addr,idata[4:3]})
+ 3'b000:
+ case (idata[7:5])
+ 3'b001: serviced <= 0;
+ 3'b011: serviced[idata[2:0]] <= 0;
+ endcase
+ 3'b01x: begin init <= 1'b1; addr0 <= idata[7:5]; addrfmt <= idata[2]; end
+ 3'b1xx: if (init) addr1 <= idata; else irqmask <= idata;
+ endcase
+ end
+ if (inta_n&~exinta_n) state <= 2'b01;
+ end
+ 2'b01: begin
+ if (inta_n&~exinta_n) state <= 2'b10;
+ end
+ 2'b10: begin
+ if (inta_n&~exinta_n) begin
+ state <= 2'b00;
+ smask[x] <= 1'b1;
+ serviced[x] <= 1'b1;
+ end
+ end
+ endcase
+ end
+end
+
+endmodule
diff --git a/common/k580ww55.v b/common/k580ww55.v
new file mode 100644
index 00000000..6b575044
--- /dev/null
+++ b/common/k580ww55.v
@@ -0,0 +1,52 @@
+// ====================================================================
+// Bashkiria-2M FPGA REPLICA
+//
+// Copyright (C) 2010 Dmitry Tselikov
+//
+// This core is distributed under modified BSD license.
+// For complete licensing information see LICENSE.TXT.
+// --------------------------------------------------------------------
+//
+// An open implementation of Bashkiria-2M home computer
+//
+// Author: Dmitry Tselikov http://bashkiria-2m.narod.ru/
+//
+// Design File: k580ww55.v
+//
+// Parallel interface k580ww55 design file of Bashkiria-2M replica.
+//
+// Warning: This realization is not fully operational.
+
+module k580ww55(
+ input clk, input reset, input[1:0] addr, input we_n,
+ input[7:0] idata, output reg[7:0] odata,
+ input[7:0] ipa, output reg[7:0] opa,
+ input[7:0] ipb, output reg[7:0] opb,
+ input[7:0] ipc, output reg[7:0] opc);
+
+//reg[6:0] mode;
+
+always begin
+ case (addr)
+ 2'b00: odata = ipa;
+ 2'b01: odata = ipb;
+ 2'b10: odata = ipc;
+ 2'b11: odata = 8'h00;
+ endcase
+end
+
+always @(posedge clk or posedge reset) begin
+ if (reset) begin
+ //mode <= 7'b0011011;
+ {opa,opb,opc} <= {8'hFF,8'hFF,8'hFF};
+ end else
+ if (~we_n) begin
+ if (addr==2'b00) opa <= idata;
+ if (addr==2'b01) opb <= idata;
+ if (addr==2'b10) opc <= idata;
+ //if (addr==2'b11 && idata[7]) mode <= idata[6:0];
+ if (addr==2'b11 && ~idata[7]) opc[idata[3:1]] <= idata[0];
+ end
+end
+
+endmodule
diff --git a/common/make_vhdl_prom.exe b/common/make_vhdl_prom.exe
new file mode 100644
index 00000000..1e5618bf
Binary files /dev/null and b/common/make_vhdl_prom.exe differ
diff --git a/common/swap.exe b/common/swap.exe
new file mode 100644
index 00000000..206d6afc
Binary files /dev/null and b/common/swap.exe differ