URL
https://opencores.org/ocsvn/pdp8/pdp8/trunk
Subversion Repositories pdp8
[/] [pdp8/] [trunk/] [pdp8/] [cpu/] [cpu.new] - Rev 2
Compare with Previous | Blame | View Log
--------------------------------------------------------------------------------
--!
--! PDP8 Processor
--!
--! \brief
--! Processor
--!
--! \details
--! I hope you like state machines because this is implemented as one big
--! state machine.
--!
--! \file
--! cpu.vhd
--!
--! \author
--! Rob Doyle - doyle (at) cox (dot) net
--!
--------------------------------------------------------------------------------
--
-- Copyright (C) 2009, 2010, 2011, 2012 Rob Doyle
--
-- 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; version 2.1 of the License.
--
-- 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.txt
--
--------------------------------------------------------------------------------
--
-- Comments are formatted for doxygen
--
library ieee; --! IEEE Library
use ieee.std_logic_1164.all; --! IEEE 1164
use ieee.numeric_std.all; --! IEEE Numeric Standard
use work.cpu_types.all;
-- synthesis translate_off
use std.textio.all;
use ieee.std_logic_textio.all;
use work.pck_fio.all;
-- synthesis translate_on
--
--! eCPU Entity
--
entity eCPU is port (
sys : in sys_t; --! Clock/Reset
swCPU : in swCPU_t; --! CPU Configuration
swOPT : in swOPT_t; --! Options Configuration
swDATA : in swDATA_t; --! Data Switch Inputs
swCNTL : in swCNTL_t; --! Control Switch Inputs
dev : in dev_t; --! Device Output
cpu : out cpu_t --! CPU Output
);
end eCPU;
--
--! eCPU RTL
--
architecture rtl of eCPU is
--
-- Registers
--
signal LAC : ldata_t; --! Link and Accumulator
alias L : std_logic is LAC (0); --! Link Bit
alias AC : data_t is LAC(1 to 12); --! Accumulator
signal IR : data_t; --! Instruction Register
signal PC : addr_t; --! Program Counter
signal MA : addr_t; --! Memory Address Register
signal MB : data_t; --! Memory Buffer (output)
signal MD : data_t; --! Memory Data Register (input)
signal MQ : data_t; --! MQ Register
signal MQA : data_t; --! MQA Register
signal SC : sc_t; --! SC Register
signal SP1 : addr_t; --! Stack Pointer
signal SP2 : addr_t; --! Stack Pointer
signal SR : data_t; --! Switch Register
--
-- Register Operation
--
signal acOP : acOP_t; --! AC operation
signal pcOP : pcOP_t; --! PC operation
signal irOP : irOP_t; --! IR operation
signal maOP : maOP_t; --! MA operation
signal mbOP : mbOP_t; --! MB operation
signal mqOP : mqOP_t; --! MQ operation
signal mqaOP : mqaOP_t; --! MQA operation
signal scOP : scOP_t; --! SC operation
signal sp1OP : spOP_t; --! SP1 operation
signal sp2OP : spOP_t; --! SP2 operation
signal srOP : srOP_t; --! SR operation
--
-- Memory Extension Control Registers
--
signal IB : field_t; --! Instruction Buffer
signal INF : field_t; --! Instruction Field
signal DF : field_t; --! Data Field
signal SF : sf_t; --! Save Field
signal UB : std_logic; --! User Buffer Flag
signal UF : std_logic; --! User Flag
--
-- Memory Extension Control Register Operations
--
signal ibOP : ibOP_t; --! IB operation
signal ifOP : ifOP_t; --! IF operation
signal dfOP : dfOP_t; --! DF operation
signal sfOP : sfOP_t; --! SF operation
signal ubOP : ubOP_t; --! User Buffer operation
signal ufOP : ufOP_t; --! USER Flag operation
signal IRQ : std_logic; --! IRQ Flag
--
-- BTSTRP:
--
signal BTSTRP : std_logic; --! BTSTRP Flag
signal btstrpOP : btstrpOP_t; --! BTSTRP operation
--
-- CTRLFF:
-- The Control Panel Flip-Flop (CTRLFF), is set when the CPREQ is granted.
-- CTRLFF prevents further CPREQs from being granted, bypasses the
-- interrupt enable system and redefines several of the internal control
-- instructions. As long as the CTRLFF is set, LXPAR is used for all
-- instruction, direct data and indirect pointer references. Also, while
-- CTRLFF is set, the INTGNT line is held inactive but the Interrupt Grant
-- Flip Flop is not cleared. IOTs executed while CTRLFF is set do not clear
-- the Interrupt grant flip flop.
--
signal CTRLFF : std_logic; --! CTRLFF
signal ctrlffOP : ctrlffOP_t; --! CTRLFF operation
--
-- EAE:
-- EAE Long Operations
--
signal EAE : eae_t; --! EAE Register
signal eaeOP : eaeOP_t; --! EAE operation
--
-- EMODE:
-- The EMODE bit is set at reset and is set by the SWAB and cleared by the
-- SWBA instructions. This enables EAE Mode A and EAE Mode B instructions.
--
signal EMODE : std_logic; --! EAE Mode
signal emodeOP : emodeOP_t; --! EAE Mode operation
--
-- FZ:
-- The Force Zero Flag (FZ) is used to implement Extended memory operations
-- for Panel Mode instructions. When set, forces control panel instruction
-- field access to field zero. Indirect data accesses are not affected.
--
signal FZ : std_logic; --! Force Zero
signal fzOP : fzOP_t; --! FZ operation
--
-- HLTTRP:
-- The HLTTRP flip-flop allows the cpu to single step through code.
-- The HLTTRP flip-flop is set by a HLT instruction.
--
signal HLTTRP : std_logic; --! HLTTRP Flip-Flop
signal hlttrpOP : hlttrpOP_t; --! HLTTRP operation
--
-- GTF:
--
signal GTF : std_logic; --! Greater than Flag
signal gtfOP : gtfOP_t; --! GTF operation
--
-- ID:
-- The Interrupt Enable Delay Flip-Flop (ID) delays the effect of the ION
-- instruction until the instruction after the ION instruction has executed.
-- This will allow a return from interrupt to be executed before the next
-- interrupt request is serviced.
--
signal ID : std_logic; --! ION Delay Flip-flop
signal idOP : idOP_t; --! ION Delay Operation
--
-- IE:
-- The Interrupt Enable Flip-Flop (IE) enables and disables interrupts.
--
signal IE : std_logic; --! Interrupt Enable
signal ieOP : ieOP_t; --! IE operation
--
-- II:
-- The Interrupt Inhibit (II) Flip-Flop is set whenever there is an
-- instruction executed that could change the Instruction Field. These
-- include CIF, CDI, RMF, RTF, CAF, CUF, SUF. The II Flip-Flop is
-- cleared when the next JMP, JMS, RTN1, or RTN2 instruction is executed.
-- This prevents an interrupt from occuring between the CIF (or like)
-- instruction and the return (or like) instruction.
--
signal II : std_logic; -- Interrupt Inhibit Flip-Flop
signal iiOP : iiOP_t; -- Interrupt Inhibit Operation
--
-- PDF:
-- The Panel Data Flag (PDF) is used to contol whether indirectly addressed
-- data references by Control Panel AND, TAD, ISZ or DCA instructions
-- reference panel memory or main memory. If PDF is set, this flag causes
-- indirect references from control panel memory to address control panel
-- memory by asserting LXPAR. If PDF is cleared, this flag causes indirect
-- references from control panel memory to address main memory by asserting
-- LXMAR. The PDF is cleared unconditionally whenever the panel mode is
-- entered for any reason. It is also cleared by the Clear Panel Data
-- (CPD) instruction. The PDF is set by the Set Panel Data (SPD)
-- instruction. The state of the Panel Data flag is ignored when not
-- operating in panel mode.
--
signal PDF : std_logic; --! Panel Data Flag
signal pdfOP : pdfOP_t; --! PDF operation
--
-- PEX:
-- The Panel Exit Delay (PEX) Flip-Flop is set by the PEX instruction.
-- When a JMP, JMS, RET1, or RET2 instruction is executed with the PEX
-- Flip-Flop set, the CPU will exit panel mode. The PEX Flip-Flop is
-- cleared by the JMP, JMS, RET1, or RET2 instruction.
--
signal PEX : std_logic; -- PEX Flip-Flop
signal pexOP : pexOP_t; -- PEX Operation
--
-- PNLTRP:
-- A Panel Trap is one of the many ways to enter panel mode. The Panel Trap
-- Flip-Flop (PNLTRP) is set by any of the PR0, PR1, PR2, PR3 instructions.
-- The PNLTRP flag can be examined and cleared by the PRS instruction.
--
signal PNLTRP : std_logic; --! PNLTRP Flag
signal pnltrpOP : pnltrpOP_t; --! PNLTRP operation
--
-- PRWON:
-- The Power-On Trap Flip-Flop (PWRTRP) is set when STRTUP is negated during
-- RESET, The Power-On Flip-Flop (PWRTRP) is reset by a PRS or PEX
-- instruction.
--
signal PWRTRP : std_logic; --! PWRTRP Flip-Flop
signal pwrtrpOP : pwrtrpOP_t; --! PWRTRP operation
--
-- USRTRP:
-- User Mode Trap.
--
signal USRTRP : std_logic; --! USR Interrupt
signal usrtrpOP : usrtrpOP_t; --! USR Interrupt operation
--
-- XMA
--
signal XMA : field_t; --! XMA Register
signal xmaOP : xmaOP_t; --! XMA operation
--
-- Bus Control Signals
--
signal busb : busOP_t; --! Bus Operation output
signal busOP : busOP_t; --! Bus Operation input
signal ioclrb : std_logic; --! IOCLR register output
signal ioclrOP : std_logic; --! IOCLR register input
signal wrb : std_logic; --! WR signal register input
signal wrOP : std_logic; --! WR signal register output
signal rdb : std_logic; --! RD signal register output
signal rdOP : std_logic; --! RD signal register input
signal ifetchb : std_logic; --! IFETCH signal register output
signal ifetchOP : std_logic; --! IFETCH signal register input
signal datafb : std_logic; --! DATAF signal register output
signal datafOP : std_logic; --! DATAF signal register input
signal lxdarb : std_logic; --! LXDAR signal register output
signal lxdarOP : std_logic; --! LXDAR signal register input
signal lxmarb : std_logic; --! LXMAR signal register output
signal lxmarOP : std_logic; --! LXMAR signal register input
signal lxparb : std_logic; --! LXPAR signal register output
signal lxparOP : std_logic; --! LXPAR signal register input
signal memselb : std_logic; --! MEMSEL signal register output
signal memselOP : std_logic; --! MEMSEL signal register input
signal intgntb : std_logic; --! INTGNT signal register output
signal dmagnt : std_logic; --! DMAGNT signal register input
signal intgntOP : std_logic; --! INTGNT signal register input
signal waitfb : std_logic; --! WAITF signal register output
signal waitfOP : std_logic; --! WAITF signal register input
signal oops : std_logic;
--
-- State Information
--
type state_t is (
stateReset,
stateInit,
stateCheckReq,
stateFetchAddr,
stateFetchData,
stateLoadIR,
stateDecodeInstruction,
--
-- MRI States
--
stateMRIreadAddr,
stateMRIreadDataIND,
stateMRIreadIncAddr,
stateMRIreadIndData,
stateMRIexecute,
--
-- IOT states
--
stateIOTdecode,
stateIOT,
--
-- Stack Operation States
--
statePOPaddr,
statePOPdata,
stateRTN1,
stateRTN2,
stateRTNaddr,
stateRTNdata,
--
-- OPR Groups
--
stateOprGroup1Seq3,
stateOprGroup1Seq4,
stateOprGroup2Seq2,
stateOprGroup3Seq3,
--
-- Front Panel States
--
stateHalt,
stateContinue,
stateLoadADDR,
stateLoadEXTD,
stateClear,
stateDepositWriteData,
stateDeposit,
stateExamine,
stateExamineReadAddr,
stateExamineReadData,
stateHaltDone,
--
-- EAE States
--
stateEAEfetchAddr,
stateEAEfetchData,
stateEAEindWrite,
stateEAEindReadAddr,
stateEAEindReadData,
stateEAEshift,
stateEAEwait,
stateEAEnmi,
stateEAEshiftDVI,
stateEAEsubDVI,
stateEAEmuy,
stateEAEreadDADaddr0,
stateEAEreadDADaddr1,
stateEAEreadDADdata0,
stateEAEreadDADdata1,
stateEAEdst,
--
-- HALT states
--
stateDone,
stateLALA
);
signal state : state_t;
signal nextState : state_t;
constant maAutoIncr : std_logic_vector(3 to 11) := o"001";
--
-- Output files for state dumpState
--
-- synthesis translate_off
file FIL : text is out "STD_OUTPUT";
file STDOUT : text is out "STD_OUTPUT";
--file FIL : text is out "trace.txt";
-- synthesis translate_on
--
-- vectorize
--
function vectorize(s: std_logic) return std_logic_vector is
variable v: std_logic_vector(0 to 0);
begin
v(0) := s;
return v;
end;
--
-- dumpState()
--
procedure dumpState(PC : in addr_t) is
-- synthesis translate_off
variable LIN : line;
-- synthesis translate_on
begin
-- synthesis translate_off
write (LIN, string'("ST:"));
write (LIN, string'(" PC="));
owrite(LIN, PC);
write (LIN, string'(", IR="));
owrite(LIN, IR);
write (LIN, string'(", LAC="));
owrite(LIN, "00" & LAC);
write (LIN, string'(", MQ="));
owrite(LIN, MQ);
write (LIN, string'(", SR="));
owrite(LIN, SR);
write (LIN, string'(", IF="));
owrite(LIN, INF);
write (LIN, string'(", DF="));
owrite(LIN, DF);
write (LIN, string'(", IB="));
owrite(LIN, IB);
write (LIN, string'(", UB="));
owrite(LIN, "00" & vectorize(UB));
write (LIN, string'(", UF="));
owrite(LIN, "00" & vectorize(UF));
write (LIN, string'(", USF="));
owrite(LIN, "00" & SF(0 to 0));
write (LIN, string'(", ISF="));
owrite(LIN, SF(1 to 3));
write (LIN, string'(", DSF="));
owrite(LIN, SF(4 to 6));
write (LIN, string'(", SC="));
owrite(LIN, '0' & SC);
write (LIN, string'(", GTF="));
owrite(LIN, "00" & vectorize(GTF));
write (LIN, string'(", EMODE="));
owrite(LIN, "00" & vectorize(EMODE));
write (LIN, string'(", IEFF="));
owrite(LIN, "00" & vectorize(IE));
write (LIN, string'(", IDFF="));
owrite(LIN, "00" & vectorize(ID));
write (LIN, string'(", IIFF="));
owrite(LIN, "00" & vectorize(II));
write (LIN, string'(", IRQ="));
owrite(LIN, "00" & vectorize(IRQ));
write (LIN, string'(", SP1="));
owrite(LIN, SP2);
write (LIN, string'(", SP2="));
owrite(LIN, SP1);
write (LIN, string'("; MA=00000"));
--owrite(LIN, XMA & MA);
writeline(FIL, LIN);
-- synthesis translate_on
end dumpState;
--
-- dispHALT
--
procedure dispHALT(signal PC : in addr_t) is
-- synthesis translate_off
variable LIN : line;
-- synthesis translate_on
begin
-- synthesis translate_off
write (LIN, string'("CPU Halted at PC = "));
owrite(LIN, PC);
writeline(STDOUT, LIN);
-- synthesis translate_on
end dispHALT;
--
-- dispCONT
--
procedure dispCONT(signal PC : in addr_t) is
-- synthesis translate_off
variable LIN : line;
-- synthesis translate_on
begin
-- synthesis translate_off
write (LIN, string'("CPU Continued at PC = "));
owrite(LIN, PC);
writeline(STDOUT, LIN);
-- synthesis translate_on
end dispCONT;
begin
IRQ <= '1' when ((dev.intr = '1') or
(USRTRP = '1' and swOPT.TSD = '0') or
(usrtrpOP = usrtrpopSET and swOPT.TSD = '0')) else '0';
--
-- ALU
--
iALU : entity work.eALU (rtl) port map (
sys => sys,
acOP => acOP,
BTSTRP => BTSTRP,
GTF => GTF,
HLTTRP => HLTTRP,
IE => IE,
IRQ => IRQ,
PNLTRP => PNLTRP,
PWRTRP => PWRTRP,
DF => DF,
EAE => EAE,
INF => INF,
IR => IR,
MA => MA,
MD => MD,
MQ => MQ,
SC => SC,
SF => SF,
SP1 => SP1,
SP2 => SP2,
SR => SR,
UF => UF,
LAC => LAC
);
--
-- CTRLFF
--
iCTRLFF : entity work.eCTRLFF (rtl) port map (
sys => sys,
ctrlffOP => ctrlffOP,
CTRLFF => CTRLFF
);
--
-- EAE Register
--
iEAE : entity work.eEAE (rtl) port map (
sys => sys,
eaeOP => eaeOP,
MD => MD,
MQ => MQ,
AC => AC,
EAE => EAE
);
--
-- EAE Mode A
--
iEMODE : entity work.eEMODE (rtl) port map (
sys => sys,
emodeOP => emodeOP,
EMODE => EMODE
);
--
-- FZ Flip Flop
--
iFZ : entity work.eFZ (rtl) port map (
sys => sys,
fzOP => fzOP,
FZ => FZ
);
--
-- GTF
--
iGTF : entity work.eGTF (rtl) port map (
sys => sys,
gtfOP => gtfOP,
AC => AC,
GTF => GTF
);
--
-- HLTTRP
--
iHLTTRP : entity work.eHLTTRP (rtl) port map (
sys => sys,
hlttrpOP => hlttrpOP,
HLTTRP => HLTTRP
);
--
-- Program Counter (PC)
--
iPC : entity work.ePC (rtl) port map (
sys => sys,
pcOP => pcOP,
IR => IR,
MA => MA,
MB => MB,
MD => MD,
SR => SR,
PC => PC
);
--
-- Multiplier Quotient Register (MQ)
--
iMQ : entity work.eMQ (rtl) port map (
sys => sys,
mqOP => mqOP,
AC => AC,
MD => MD,
EAE => EAE,
MQ => MQ
);
--
-- Auxillary Multiplier Quotient Register (MQA)
--
iMQA : entity work.eMQA (rtl) port map (
sys => sys,
mqaOP => mqaOP,
MQ => MQ,
MQA => MQA
);
--
-- Interrupt Enable Flip-Flop
--
iIE : entity work.eIE (rtl) port map (
sys => sys,
ieOP => ieOP,
IE => IE
);
--
-- Interrupt Inhibit Flip-Flop
--
iII : entity work.eII (rtl) port map (
sys => sys,
iiOP => iiOP,
II => II
);
--
-- USRTRP Flip-Flop
--
iUSRTRP : entity work.eUSRTRP (rtl) port map (
sys => sys,
usrtrpOP => usrtrpOP,
USRTRP => USRTRP
);
--
-- Instruction Register (IR)
--
iIR: entity work.eIR (rtl) port map (
sys => sys,
irOP => irOP,
MD => MD,
IR => IR
);
--
-- Memory Address Register (MA)
--
iMA : entity work.eMA (rtl) port map (
sys => sys,
maOP => maOP,
IR => IR,
MB => MB,
MD => MD,
PC => PC,
SP1 => SP1,
SP2 => SP2,
SR => SR,
MA => MA
);
--
-- Memory Buffer Register (MB)
--
iMB : entity work.eMB (rtl) port map (
sys => sys,
mbOP => mbOP,
AC => AC,
MA => MA,
MD => MD,
MQ => MQ,
PC => PC,
SR => SR,
MB => MB
);
--
-- Instruction Buffer Address Extension Register (IB)
--
iIB : entity work.eIB (rtl) port map (
sys => sys,
ibOP => ibOP,
SF => SF,
AC => AC,
IR => IR,
IB => IB
);
--
-- Instruction Field Address Extension Register (IF/INF)
--
iIF : entity work.eIF (rtl) port map (
sys => sys,
ifOP => ifOP,
IB => IB,
SR => SR,
INF => INF
);
--
-- ION Delay Flip-Flop
--
iID : entity work.eID (rtl) port map (
sys => sys,
idOP => idOP,
ID => ID
);
--
-- Data Field Address Extension Register (DF)
--
iDF : entity work.eDF (rtl) port map (
sys => sys,
dfOP => dfOP,
AC => AC,
IR => IR,
SF => SF,
SR => SR,
DF => DF
);
--
-- BTSTRP Flip-Flop
--
iBTSTRP : entity work.eBTSTRP (rtl) port map (
sys => sys,
btstrpOP => btstrpOP,
BTSTRP => BTSTRP
);
--
-- PDF Flip-Flop
--
iPDF : entity work.ePDF (rtl) port map (
sys => sys,
pdfOP => pdfOP,
PDF => PDF
);
--
-- PEX Flip-Flop
--
iPEX : entity work.ePEX (rtl) port map (
sys => sys,
pexOP => pexOP,
PEX => PEX
);
--
-- PNLTRP Flip-Flop
--
iPNLTRP : entity work.ePNLTRP (rtl) port map (
sys => sys,
pnltrpOP => pnltrpOP,
PNLTRP => PNLTRP
);
--
-- PWRTRP Flip-Flop
-- When set during reset, the unit will enter panel mode before executing
-- the first instruction.
--
iPWRTRP : entity work.ePWRTRP (rtl) port map (
sys => sys,
pwrtrpOP => pwrtrpOP,
PWRTRP => PWRTRP
);
--
-- SC
-- Step Counter
--
iSC : entity work.eeSC (rtl) port map (
sys => sys,
scOP => scOP,
AC => AC,
MD => MD,
SC => SC
);
--
-- SF
-- Save Field Address Extension Register (SF)
--
iSF : entity work.eSF (rtl) port map (
sys => sys,
sfOP => sfOP,
DF => DF,
IB => IB,
UB => UB,
SF => SF
);
--
-- SP1
-- Stack Pointer #1
--
iSP1 : entity work.eSP (rtl) port map (
sys => sys,
spOP => sp1OP,
AC => AC,
SP => SP1
);
--
-- SP2
-- Stack Pointer #2
--
iSP2: entity work.eSP (rtl) port map (
sys => sys,
spOP => sp2OP,
AC => AC,
SP => SP2
);
--
-- SR
-- Switch Register
--
iSR : entity work.eSR (rtl) port map (
sys => sys,
swCPU => swCPU,
srOP => srOP,
AC => AC,
SRD => swDATA,
SR => SR
);
--
-- UB
-- User Buffer Flag
--
iUB : entity work.eUB (rtl) port map (
sys => sys,
ubOP => ubOP,
AC5 => AC(5),
SF0 => SF(0),
UB => UB
);
--
-- UF
-- User Flag
--
iUF : entity work.eUF (rtl) port map (
sys => sys,
ufOP => ufOP,
UB => UB,
UF => UF
);
--
-- XMA
-- XMA is disabled by disabling the KM8E option
--
iXMA : entity work.eXMA (rtl) port map (
sys => sys,
xmaOP => xmaOP,
sWCPU => swCPU,
DF => DF,
INF => INF,
IB => IB,
XMA => XMA
);
--
-- Next State Decoder
--
process(swOPT, dev, IRQ, state, USRTRP, AC, L, MQA,
BTSTRP, CTRLFF, EMODE, GTF, HLTTRP, ID, IE, II,
LAC, MA, MD, MQ, PC, PEX, PNLTRP, PWRTRP, IR, SC, UF, swCPU,
swCNTL.halt, swCNTL.clear, swCNTL.exam, swCNTL.dep, swCNTL.lock,
swCNTL.step, swCNTL.cont, swCNTL.loadADDR, swCNTL.loadEXTD)
variable EAEIR : std_logic_vector(0 to 3);
begin
--
-- Control signal defaults
--
busOP <= busopNOP;
ioclrOP <= '0';
wrOP <= '0';
rdOP <= '0';
ifetchOP <= '0';
datafOP <= '0';
lxdarOP <= '0';
memselOP <= '0';
intgntOP <= '0';
--
-- Operation defaults
--
acOP <= acopNOP;
busOP <= busopNOP;
btstrpOP <= btstrpopNOP;
ctrlffOP <= ctrlffopNOP;
dfOP <= dfopNOP;
eaeOP <= eaeopNOP;
emodeOP <= emodeopNOP;
fzOP <= fzopNOP;
gtfOP <= gtfopNOP;
hlttrpOP <= hlttrpopNOP;
idOP <= idopNOP;
ieOP <= ieopNOP;
iiOP <= iiopNOP;
ibOP <= ibopNOP;
ifOP <= ifopNOP;
irOP <= iropNOP;
maOP <= maopNOP;
mbOP <= mbopNOP;
mqOP <= mqopNOP;
mqaOP <= mqaopNOP;
pcOP <= pcopNOP;
pdfOP <= pdfopNOP;
pexOP <= pexopNOP;
pnltrpOP <= pnltrpopNOP;
pwrtrpOP <= pwrtrpopNOP;
scOP <= scopNOP;
sfOP <= sfopNOP;
sp1OP <= spopNOP;
sp2OP <= spopNOP;
srOP <= sropNOP;
ubOP <= ubopNOP;
ufOP <= ufopNOP;
usrtrpOP <= usrtrpopNOP;
xmaOP <= xmaopNOP;
--
-- Default Next State
--
nextState <= stateLALA;
--
-- BTSTRP set when CPREQ is asserted
--
if dev.cpreq = '1' and swCPU = swHD6120 then
btstrpOP <= btstrpOPSET;
end if;
--
-- The State Machine
--
case state is
--
-- Reset State
--
when stateRESET =>
busOP <= busopRESET;
nextState <= stateInit;
--
--
-- Startup States
--
when stateInit =>
if swCPU = swHD6120 then
--
-- HD6120 Mode with STARTUP asserted.
-- Boot to front panel mode (PC=7777)
--
if swOPT.STARTUP = '1' then
pwrtrpOP <= pwrtrpopSET;
nextState <= stateCheckReq;
--
-- HD6120 Mode with STARTUP negated.
-- Begin executing at PC=0000
--
else
pwrtrpOP <= pwrtrpopCLR;
nextState <= stateCheckReq;
end if;
else
--
-- PDP8 Mode with STARTUP asserted.
-- Set PC to contents of switch register and start
-- execution.
--
if swOPT.STARTUP = '1' then
pcOP <= pcopSR;
nextState <= stateFetchAddr;
--
-- PDP8 Mode with STARTUP negated.
-- Start in HALT state. User must interact with front
-- panel.
--
else
nextState <= stateHalt;
end if;
end if;
--
-- This state occurs at the very top of the processing loop.
-- The priority hierarchy is:
-- 1. RESET - Clears Accummulator and Link registers and clears the
-- RUN output signal.
-- 2. CPREQ - If not RESET and CPREQ is asserted, the processor
-- enters Panel Mode.
-- 3. RUN/HLT - If neither RESET or CPREQ is asserted and HLT is
-- asserted (HLTFLAG = '1'), the processor should enter
-- the HALT state and the end of the current cycle.
-- 4. DEV.INTR - If no higher priority signal is asserted and IRQ is
-- asserted an interrup may be processed.
--
when stateCheckReq =>
--
-- HD6120:
-- Panel mode is entered because of the occurrence of any of
-- four events. Each of these events sets a status flag, as
-- well as causing the entry into panel mode. It should be
-- noted that more than one event might happen simultaneously.
--
-- These events are:
-- 1. PWRTRP - Power-up Trap
-- 2. PNLTRP - Panel Trap
-- 3. HLTTRP - HLT insruction
-- 4. BTSTRP - CPREQ asserted.
-- 5. Not already in panel mode
--
-- When a panel request is granted, the PC is stored in
-- location 0000 of the control panel memory and the CPU
-- resumes operation at location 7777 (octal) of the panel
-- memory. During the PC write, 0 appears on EMA0, EMA1 and
-- EMA2. The states of the IB, IF/INF, OF, ISF and DSF
-- registers are not disturbed by entry into the control
-- panel mode but execution is forced to commence in field
-- zero.
--
-- See also description of ID, IE, and II.
--
if (((swCPU = swHD6120) and (ID = '0') and (II = '0') and (CTRLFF = '0') and (PWRTRP = '1')) or
((swCPU = swHD6120) and (ID = '0') and (II = '0') and (CTRLFF = '0') and (PNLTRP = '1')) or
((swCPU = swHD6120) and (ID = '0') and (II = '0') and (CTRLFF = '0') and (BTSTRP = '1')) or
((swCPU = swHD6120) and (ID = '0') and (II = '0') and (CTRLFF = '0') and (HLTTRP = '1'))) then
ctrlffOP <= ctrlffopSET;
fzOP <= fzopSET;
pdfOP <= pdfopCLR;
maOP <= maop0000;
mbOP <= mbopPC;
pcOP <= pcop7777;
xmaOP <= xmaopCLR;
busOP <= busopWRZF;
assert false report "---------------------> Panel Trap <---------------------" severity note;
nextState <= stateFetchAddr;
--
-- HALT Mode is entered if the HLTTRP is set or the RUN/HALT
-- Switch is in the HALT position.
--
elsif (((swCPU /= swHD6120) and (HLTTRP = '1')) or
((swCPU /= swHD6120) and (swCNTL.halt = '1') and (swCNTL.lock = '0')) or
((swCPU /= swHD6120) and (swCNTL.step = '1') and (swCNTL.lock = '0'))) then
hlttrpOP <= hlttrpopCLR;
dispHALT(PC);
nextState <= stateHalt;
--
-- Interrupt Request
-- When an External Interrupt is asserted, the following occurs:
-- 1. The PC is stored in location 0000 of field 0.
-- 2. The Interrupt Enable Flip-Flop (IE) is disabled
-- which precludes automatically nested interupts.
-- 3. The INTGNT signal is is asserted.
-- 4. UF, IF/INF, DF is loaded into SF.
-- 5. IF/INF is cleared.
-- 6. IB is cleared.
-- 7. DF is cleared.
-- 8. UF is cleared.
-- 9. UB is cleared.
-- 10. The PC is set to "0001" of main memory field 0 so
-- that the next instruction is fetched from there.
--
-- See also description of ID, IE, and II.
--
elsif (IRQ = '1') and (ID = '0') and (IE = '1') and (II = '0') then
intgntOP <= '1';
maOP <= maop0000;
mbOP <= mbopPC;
ieOP <= ieopCLR;
sfOP <= sfopUBIBDF;
dfOP <= dfopCLR;
ifOP <= ifopCLR;
ibOP <= ibopCLR;
ufOP <= ufopCLR;
ubOP <= ubopCLR;
pcOP <= pcop0001;
xmaOP <= xmaopCLR;
busOP <= busopWRZF;
assert false report "---------------------> Interrupt <---------------------" severity note;
nextState <= stateFetchAddr;
--
-- No interrupts, halt, single step, or anthing else.
-- Just start to fetch the next instruction.
--
else
nextState <= stateFetchAddr;
end if;
--
-- HALT State
-- An HD6120 will never get to this state since halts are trapped
-- by the front panel.
--
when stateHalt =>
--
-- Continue Switch Pressed
--
if ((swCNTL.cont = '1' and swCNTL.lock = '0') or
(swCNTL.step = '1' and swCNTL.lock = '0')) then
dispCONT(PC);
nextState <= stateContinue;
--
-- Load Address Switch Pressed
-- This sets MA and PC to the contents of the switch register.
-- MA <- SR
-- PC <- SR
--
elsif swCNTL.loadADDR = '1' and swCNTL.lock = '0' then
pcOP <= pcopSR;
maOP <= maopSR;
nextState <= stateLoadADDR;
--
-- Load Extended Address Switch Pressed
-- This sets IF and DF to the contents of the switch register.
-- IF <- SR[6:8]
-- DF <- SR[9:11]
--
elsif swCNTL.loadEXTD = '1' and swCNTL.lock = '0' then
ifOP <= ifopSR6to8;
dfOP <= dfopSR9to11;
nextState <= stateLoadEXTD;
--
-- Clear Switch Pressed
--
elsif swCNTL.clear = '1' and swCNTL.lock = '0' then
acOP <= acopCLACLL;
mqOP <= mqopCLR;
ifOP <= ifopCLR;
dfOP <= dfopCLR;
sp1OP <= spopCLR;
sp2OP <= spopCLR;
gtfOP <= gtfopCLR;
emodeOP <= emodeopCLR;
ieOP <= ieopCLR;
idOP <= idopSET;
usrtrpOP <= usrtrpopCLR;
busOP <= busopIOCLR;
nextState <= stateClear;
--
-- Examine Switch Pressed
-- This loads the contents of the memory location addressed by
-- the MA register into the MD register and increments the MA
-- and PC registers.
-- MD <- MEM[IF'MA]
--
elsif swCNTL.exam = '1' and swCNTL.lock = '0' then
maOP <= maopPC;
xmaOP <= xmaopIF;
busOP <= busopRDIFaddr;
nextState <= stateExamineReadAddr;
--
-- Deposit Switch Pressed
-- This writes the contents of the Switch Register into the
-- memory location addressed by the MA register.
-- MEM[IF'MA] <- SR
--
elsif swCNTL.dep = '1' and swCNTL.lock = '0' then
maOP <= maopPC;
mbOP <= mbopSR;
xmaOP <= xmaopIF;
busOP <= busopWRIF;
nextState <= stateDepositWriteData;
else
nextState <= stateHalt;
end if;
--
-- Wait for Continue button to negate
--
when stateContinue =>
if swCNTL.cont = '1' then
nextState <= stateContinue;
else
nextState <= stateFetchAddr;
end if;
--
-- Wait for LoadADDR button to negate
--
when stateLoadADDR =>
if swCNTL.loadADDR = '1' then
nextState <= stateLoadADDR;
else
nextState <= stateHaltDone;
end if;
--
-- Wait for LoadEXTD button to negate
--
when stateLoadEXTD =>
if swCNTL.loadEXTD = '1' then
nextState <= stateLoadEXTD;
else
nextState <= stateHaltDone;
end if;
--
-- Wait for Clear button to negate
--
when stateClear =>
if swCNTL.clear = '1' then
nextState <= stateClear;
else
nextState <= stateHaltDone;
end if;
--
-- Examine Read Addr
-- This is the address phase of the read cycle.
-- MD <- MEM[IF'MA]
--
when stateExamineReadAddr =>
xmaOP <= xmaopIF;
busOP <= busopRDIFdata;
nextState <= stateExamineReadData;
--
-- Examine Read Data
-- This is the data phase of the read cycle.
-- At the end of this cycle, MD will have the data that was read.
-- This state increments the PC and MA register after the examine.
-- MD <- MEM[IF'MA]
-- MA <- MA + 1
-- PC <- PC + 1
--
when stateExamineReadData =>
maOP <= maopINC;
pcOP <= pcopINC;
nextState <= stateExamine;
--
-- Wait for Examine button to negate
--
when stateExamine =>
if swCNTL.exam = '1' then
nextState <= stateExamine;
else
nextState <= stateHaltDone;
end if;
--
-- This cycle writes data to memory. Once written
-- this state increments PC and MA.
-- MA <- MA + 1
-- PC <- PC + 1
--
when stateDepositWriteData =>
maOP <= maopINC;
pcOP <= pcopINC;
nextState <= stateDeposit;
--
-- Wait for Deposit button to negate
--
when stateDeposit =>
if swCNTL.dep = '1' then
nextState <= stateDeposit;
else
nextState <= stateHaltDone;
end if;
--
-- Update Front Panel display
--
when stateHaltDone =>
nextState <= stateHalt;
--
-- Begin Instruction Fetch. Perform Read Address Cycle.
-- MA <- PC
-- MD <- MEM[IF'MA]
--
when stateFetchAddr =>
maOP <= maopPC;
xmaOP <= xmaopIF;
busOP <= busopFETCHaddr;
nextState <= stateFetchData;
--
-- Continue Instruction Fetch. Perform Read Data Cycle.
-- The Interrupt Enable Delay Flip-Flop (ID) is cleared.
-- If the ID was set at the beginning of this instruction,
-- an interrupt, if present, was deferred. We clear it now.
-- Therefore this instruction will complete and then that
-- interrupt, if present, will be recognized.
-- MD <- MEM[IF'MA]
--
when stateFetchData =>
pcOP <= pcopINC;
idOP <= idopCLR;
xmaOP <= xmaopIF;
busOP <= busopFETCHdata;
nextState <= stateLoadIR;
--
-- Load IR with the instruction that was fetched.
-- Note: This state is a wasted state. We could have decoded the MD
-- and loaded the IR simultaneously.
-- IR <- MD
--
when stateLoadIR =>
irOP <= iropMD;
nextState <= stateDecodeInstruction;
--
-- Decode Instruction in IR
--
when stateDecodeInstruction =>
--
-- Default Next State
--
nextState <= stateLALA;
--
-- Parse OPCODE
--
case IR(0 to 2) is
--
-- AND Instruction
--
when opAND =>
case IR(3 to 4) is
--
-- AND, direct, zero page. Start Read Addr Cycle
-- MA <- 00000'IR(5:11)
--
when amDZ =>
maOP <= maopZP;
xmaOP <= xmaopIF;
busOP <= busopRDIFaddr;
nextState <= stateMRIreadAddr;
--
-- AND, direct, curr page. Start Read Addr Cycle
-- MA <- MA(0:4)'IR(5:11)
--
when amDC =>
maOP <= maopCP;
xmaOP <= xmaopIF;
busOP <= busopRDIFaddr;
nextState <= stateMRIreadAddr;
--
-- AND, indirect, zero page. Start Read Addr Cycle
-- MA <- 00000'IR(5:11)
--
when amIZ =>
maOP <= maopZP;
xmaOP <= xmaopIF;
busOP <= busopRDIFaddr;
nextState <= stateMRIreadAddr;
--
-- AND, indirect, curr page. Start Read Addr Cycle
-- MA <- MA(0:4)'IR(5:11)
--
when amIC =>
maOP <= maopCP;
xmaOP <= xmaopIF;
busOP <= busopRDIFaddr;
nextState <= stateMRIreadAddr;
--
-- Everthing else
--
when others =>
null;
end case;
--
-- TAD Instruction
--
when opTAD =>
case IR(3 to 4) is
--
-- TAD, direct, zero page. Start Read Addr Cycle
-- MA <- 00000'IR(5:11)
--
when amDZ =>
maOP <= maopZP;
xmaOP <= xmaopIF;
busOP <= busopRDIFaddr;
nextState <= stateMRIreadAddr;
--
-- TAD, direct, curr page. Start Read Addr Cycle
-- MA <- MA(0:4)'IR(5:11)
--
when amDC =>
maOP <= maopCP;
xmaOP <= xmaopIF;
busOP <= busopRDIFaddr;
nextState <= stateMRIreadAddr;
--
-- TAD, indirect, zero page. Start Read Addr Cycle
-- MA <- 00000'IR(5:11)
--
when amIZ =>
maOP <= maopZP;
xmaOP <= xmaopIF;
busOP <= busopRDIFaddr;
nextState <= stateMRIreadAddr;
--
-- TAD, indirect, curr page. Start Read Addr Cycle
-- MA <- MA(0:4)'IR(5:11)
--
when amIC =>
maOP <= maopCP;
xmaOP <= xmaopIF;
busOP <= busopRDIFaddr;
nextState <= stateMRIreadAddr;
--
-- Everything else
--
when others =>
null;
end case;
--
-- ISZ Instruction
--
when opISZ =>
case IR(3 to 4) is
--
-- ISZ, direct, zero page. Start Read Addr Cycle
-- MA <- 00000'IR(5:11)
--
when amDZ =>
maOP <= maopZP;
xmaOP <= xmaopIF;
busOP <= busopRDIFaddr;
nextState <= stateMRIreadAddr;
--
-- ISZ, direct, curr page. Start Read Addr Cycle
-- MA <- MA(0:4)'IR(5:11)
--
when amDC =>
maOP <= maopCP;
xmaOP <= xmaopIF;
busOP <= busopRDIFaddr;
nextState <= stateMRIreadAddr;
--
-- ISZ, indirect, zero page. Start Read Addr Cycle
-- MA <- 00000'IR(5:11)
--
when amIZ =>
maOP <= maopZP;
xmaOP <= xmaopIF;
busOP <= busopRDIFaddr;
nextState <= stateMRIreadAddr;
--
-- ISZ, indirect, curr page. Start Read Addr Cycle
-- MA <- MA(0:4)'IR(5:11)
--
when amIC =>
maOP <= maopCP;
xmaOP <= xmaopIF;
busOP <= busopRDIFaddr;
nextState <= stateMRIreadAddr;
--
-- Everything else
--
when others =>
null;
end case;
--
-- MRI DCA
--
when opDCA =>
case IR(3 to 4) is
--
-- DCA, direct, zero page. Start Write Cycle
-- MA <- 00000'IR(5:11)
--
when amDZ =>
wrOP <= '1';
acOP <= acopCLA;
maOP <= maopZP;
mbOP <= mbopAC;
xmaOP <= xmaopIF;
busOP <= busopRDIFaddr;
nextState <= stateDone;
--
-- DCA, direct, curr page. Start Write Cycle
-- MA <- MA(0:4)'IR(5:11)
--
when amDC =>
wrOP <= '1';
acOP <= acopCLA;
maOP <= maopCP;
mbOP <= mbopAC;
xmaOP <= xmaopIF;
busOP <= busopRDIFaddr;
nextState <= stateDone;
--
-- DCA, indirect, zero page. Start Read Addr Cycle.
-- MA <- 00000'IR(5:11)
--
when amIZ =>
maOP <= maopZP;
xmaOP <= xmaopIF;
busOP <= busopRDIFaddr;
nextState <= stateMRIreadAddr;
--
-- DCA, indirect, curr page. Start Read Addr Cycle.
-- MA <- MA(0:4)'IR(5:11)
--
when amIC =>
maOP <= maopCP;
xmaOP <= xmaopIF;
busOP <= busopRDIFaddr;
nextState <= stateMRIreadAddr;
--
-- Everything else
--
when others =>
null;
end case;
--
-- JMS Instruction
--
when opJMS =>
--
-- The II Flip-Flop is cleared.
-- The FZ Flip-Flop is cleared
--
iiOP <= iiopCLR;
fzOP <= fzopCLR;
case IR(3 to 4) is
--
-- JMS, direct, zero page. Start write cycle.
-- MA <- 00000'IR(5:11)
--
-- When the PEX Flip-flop is set, the CPU shall
-- exit from Panel Mode to Main Memory (i.e., clear
-- CTRLFF) during the next JMP, JMS, RTN1 or RTN2
-- instruction.
--
-- PEX is cleared by the JMP, JMS, RTN1 or RTN2
-- instruction.
--
when amDZ =>
ifOP <= ifopIB;
ufOP <= ufopUB;
maOP <= maopZP;
mbOP <= mbopPC;
pcOP <= pcopZPP1;
xmaOP <= xmaopIB;
busOP <= busopWRIB;
if PEX = '1' then
ctrlffOP <= ctrlffopCLR;
pexOP <= pexopCLR;
end if;
nextState <= stateDone;
--
-- JMS, direct, curr page. Start write cycle.
-- MA <- MA(0:4)'IR(5:11)
--
-- When the PEX Flip-flop is set, the CPU shall
-- exit from Panel Mode to Main Memory (i.e., clear
-- CTRLFF) during the next JMP, JMS, RTN1 or RTN2
-- instruction.
--
-- PEX is cleared by the JMP, JMS, RTN1 or RTN2
-- instruction.
--
when amDC =>
ifOP <= ifopIB;
ufOP <= ufopUB;
maOP <= maopCP;
mbOP <= mbopPC;
pcOP <= pcopCPP1;
xmaOP <= xmaopIB;
busOP <= busopWRIB;
if PEX = '1' then
ctrlffOP <= ctrlffopCLR;
pexOP <= pexopCLR;
end if;
nextState <= stateDone;
--
-- JMS, indirect, zero page. Start Read Addr Cycle.
-- MA <- 00000'IR(5:11)
--
when amIZ =>
maOP <= maopZP;
xmaOP <= xmaopIF;
busOP <= busopRDIFaddr;
nextState <= stateMRIreadAddr;
--
-- JMS, indirect, curr page. Start Read Addr Cycle.
-- MA <- MA(0:4)'IR(5:11)
--
when amIC =>
maOP <= maopCP;
xmaOP <= xmaopIF;
busOP <= busopRDIFaddr;
nextState <= stateMRIreadAddr;
--
-- Everthing else
--
when others =>
null;
end case;
--
-- JMP Instruction
--
when opJMP =>
--
-- The II Flip-Flop is cleared.
-- The FZ Flip-Flop is cleared
--
iiOP <= iiopCLR;
fzOP <= fzopCLR;
case IR(3 to 4) is
--
--
-- JMP, direct, zero page.
-- MA <- 00000'IR(5:11)
--
-- When the PEX Flip-flop is set, the CPU shall
-- exit from Panel Mode to Main Memory (i.e., clear
-- CTRLFF) during the next JMP, JMS, RTN1 or RTN2
-- instruction.
--
-- PEX is cleared by the JMP, JMS, RTN1 or RTN2
-- instruction.
--
when amDZ =>
maOP <= maopZP;
pcOP <= pcopZP;
ifOP <= ifopIB;
ufOP <= ufopUB;
if PEX = '1' then
ctrlffOP <= ctrlffopCLR;
pexOP <= pexopCLR;
end if;
nextState <= stateDone;
--
-- JMP, direct, curr page.
-- MA <- MA(0:4)'IR(5:11)
--
-- When the PEX Flip-flop is set, the CPU shall
-- exit from Panel Mode to Main Memory (i.e., clear
-- CTRLFF) during the next JMP, JMS, RTN1 or RTN2
-- instruction.
--
-- PEX is cleared by the JMP, JMS, RTN1 or RTN
-- instruction.
--
when amDC =>
maOP <= maopCP;
pcOP <= pcopCP;
ifOP <= ifopIB;
ufOP <= ufopUB;
if PEX = '1' then
ctrlffOP <= ctrlffopCLR;
pexOP <= pexopCLR;
end if;
nextState <= stateDone;
--
-- JMP, indirect, zero page. Start Read Addr Cycle.
-- MA <- 00000'IR(5:11)
--
when amIZ =>
maOP <= maopZP;
xmaOP <= xmaopIF;
busOP <= busopRDIFaddr;
nextState <= stateMRIreadAddr;
--
-- JMP, indirect, curr page. Start Read Addr Cycle.
-- MA <- MA(0:4)'IR(5:11)
--
when amIC =>
maOP <= maopCP;
xmaOP <= xmaopIF;
busOP <= busopRDIFaddr;
nextState <= stateMRIreadAddr;
--
-- Everything else
--
when others =>
null;
end case;
--
-- IOT Instructions
--
when opIOT =>
--
-- Default Next State
--
nextState <= stateDone;
--
-- Handle USR Mode interrupts
--
if (UF = '1') then
usrtrpOP <= usrtrpopSET;
nextState <= stateDone;
else
--
-- Internal IOT (CPU Control)
-- 600x, 62xx are internal IOTs
--
case IR(0 to 11) is
--
-- OP 6000: PRS/SKON
--
when o"6000" =>
--
-- HD6120 only
-- OP 6000: PRS - Panel Read Status Word.
-- Read panel status bits into AC<0-4>, 0
-- into AC<5:11>. Following the reading of
-- the flags into the AC, the flags are
-- cleared, with the exception of HLTTRP.
-- BTSTR is cleared only if a 1 was read
-- into AC<0>.
--
if swCPU = swHD6120 then
if CTRLFF = '1' then
acOP <= acopPRS;
pnltrpOP <= pnltrpopCLR;
pwrtrpOP <= pwrtrpopCLR;
btstrpOP <= btstrpopCLR;
end if;
--
-- PDP-8/E and later and HD-6120
-- SKON - Skip if interupt system is on,
-- turn it off.
--
elsif ((swCPU = swPDP8E) or
(swCPU = swPDP8F) or
(swCPU = swPDP8A) or
(swCPU = swHD6120)) then
if IE = '1' then
pcOP <= pcopINC;
end if;
ieOP <= ieopCLR;
--
-- Pre PDP8/E
-- This instruction was a NOP.
--
else
null;
end if;
--
-- IOT 6001: ION - Enable Interrupts.
-- The Interrupt Enable Flip-Flop (IE) is set.
-- The Interrupt Enable Delay Flip-Flop (ID)
-- is set.
--
-- Note: Setting the ID delays the interrupt
-- enable by one instruction so that a return
-- (from interrupt) may be executed before the
-- next interrupt request is serviced.
--
when o"6001" =>
ieOP <= ieopSET;
idOP <= idopSET;
--
-- IOT 6002: IOF - Disable Interrupts
-- The Interrupt Enable Flip Flop (IE) is cleared
-- immediately. If IRQ is low while this
-- instruction is being processed, the interrupt
-- will not be recognized.
--
when o"6002" =>
ieOP <= ieopCLR;
--
-- OP 6003: PGO/SRQ
--
when o"6003" =>
--
-- HD6120 only
-- OP 6003: PGO - Panel Go.
--
if swCPU = swHD6120 then
if CTRLFF = '1' then
hlttrpOP <= hlttrpopCLR;
end if;
--
-- PDP-8/E and later and HD-6120
-- OP 6003: SRQ - Skip on Interupt Request
--
elsif ((swCPU = swPDP8E) or
(swCPU = swPDP8F) or
(swCPU = swPDP8A) or
(swCPU = swHD6120)) then
if IRQ = '1' then
pcOP <= pcopINC;
end if;
--
-- Pre PDP-8/E
-- OP 6003: ION - This was equivalent to
-- the ION instruction.
--
else
ieOP <= ieopSET;
idOP <= idopSET;
end if;
--
-- IOT 6004: PEX/GTF
--
-- GTF - Get Flags
--
-- 00 01 02 03 04 05 06 07 08 09 10 11
-- +--+--+--+--+--+--+--------+--------+
-- | L|GT|IR|0 |IE|UF| IF | DF |
-- +--+--+--+--+--+--+--------+--------+
--
-- L - The link bit.
-- GT - The Greater Than bit
-- IR - The interrupt request status, as tested by SRQ.
-- IE - The state of the interrupt enable flip-flop (IE)
-- UF - User Flag
-- IF - The instruction field.
-- DF - The data field.
--
-- PEX - Panel Exit to Normal Mode
-- Exit from panel mode into main memory at the end
-- of the next JMP, JMS, RTN1 or RTN2 instruction.
--
when o"6004" =>
--
-- OP 6004: PEX - Panel Exit to Normal Mode
-- HD6120 in Panel Mode only
--
-- Set PEX Flip-flop
-- Clear PWRTRP and PNLTRP.
--
if swCPU = swHD6120 and CTRLFF = '1' then
pwrtrpOP <= pwrtrpopCLR;
pnltrpOP <= pnltrpopCLR;
pexOP <= pexopSET;
--
-- OP 6004: GTF - Get Flags
-- HD6120 in Normal Mode only
-- AC(4) is always set.
-- AC(5) is always cleared.
--
elsif swCPU = swHD6120 and CTRLFF = '0' then
acOP <= acopGTF1;
--
-- OP 6004: GTF - Get Flags
-- PDP-8/E and later with KM8E installed
-- AC(4) is set to state of the interrupt
--
elsif ((swCPU = swPDP8E and swOPT.KM8E = '1') or
(swCPU = swPDP8F and swOPT.KM8E = '1') or
(swCPU = swPDP8A and swOPT.KM8E = '1')) then
acOP <= acopGTF2;
--
-- Pre PDP-8/E
-- OP 6004: This was and ADC operation or a
-- NOP.
--
else
null;
end if;
--
-- IOT 6005: RTF - Restore Flags and Fields from AC.
-- The flags are set as follows:
--
-- 00 01 02 03 04 05 06 07 08 09 10 11
-- +--+--+--+--+--+--+--------+--------+
-- | L|GT| | |IE|UB| IB | DF |
-- +--+--+--+--+--+--+--------+--------+
--
when o"6005" =>
if ((swCPU = swPDP8E) or
(swCPU = swPDP8F) or
(swCPU = swPDP8A) or
(swCPU = swHD6120)) then
--
-- HD6120: The AC is cleared following
-- the load operation. The interrupt
-- is enabled per AC(4). See HD6120
-- GTF instruction.
--
if swCPU = swHD6120 then
if AC(0) = '1' then
acOP <= acopCLACLLCML;
else
acOP <= acopCLACLL;
end if;
if AC(4) = '1' then
ieOP <= ieopSET;
iiOP <= iiopSET;
end if;
--
-- PDP8/E and later: AC is not modified by
-- the instruction. AC(4) is ignored and
-- interrupts are unconditionally
-- re-enabled. AC(5) sets the UB bit.
-- See PDP/8 GTF instruction.
--
else
if AC(0) = '1' then
acOP <= acopCLLCML;
else
acOP <= acopCLL;
end if;
ieOP <= ieopSET;
iiOP <= iiopSET;
ubOP <= ubopAC5;
end if;
gtfOP <= gtfopAC1;
ibOP <= ibopAC6to8;
dfOP <= dfopAC9to11;
fzop <= fzopCLR;
--
-- Pre PDP8/E
-- OP 6005: ION ORed with ADC
--
else
ieOP <= ieopSET;
idOP <= idopSET;
end if;
--
-- OP 6006: SGT
--
when o"6006" =>
--
-- PDP8/E and later
-- OP 6006: SGT - Skip if the GT flag is set.
--
if ((swCPU = swPDP8E) or
(swCPU = swPDP8F) or
(swCPU = swPDP8A) or
(swCPU = swHD6120)) then
if GTF = '1' then
pcOP <= pcopINC;
end if;
--
-- Pre PDP8/E
-- OP 6006: This was equivalent to an IOF
-- ORed with and ADC op
--
else
ieOP <= ieopCLR;
end if;
--
-- OP 6007: CAF - Clear all flags.
--
when o"6007" =>
--
-- PDP8/E and Later
-- IOT 6007: CAF - Clear all flags.
-- The AC, LINK and GT flag are cleared.
-- Interrupt Enable Flip Flop (IE) is cleared.
-- IOCLR is generated with LXDAR high, causing
-- peripheral devices to clear their flags.
--
if ((swCPU = swPDP8E) or
(swCPU = swPDP8F) or
(swCPU = swPDP8A) or
(swCPU = swHD6120)) then
gtfOP <= gtfopCLR;
acOP <= acopCLACLL;
emodeOP <= emodeopCLR;
ieOP <= ieopCLR;
idOP <= idopSET;
busOP <= busopIOCLR;
usrtrpOP <= usrtrpopCLR;
--
-- Pre PDP8/E
-- OP 6007: ION ORed with ADC
--
else
ieOP <= ieopSET;
idOP <= idopSET;
end if;
--
-- IOT 6200: LXM - Load Extended Mode Register
-- On all machines without KT8-A this is executed
-- as a NOP instruction.
--
when o"6200" =>
null;
--
-- IOT 62x1: CDF - Change Data Field
-- The Data Field Register (DF) is loaded with IR<6:8>
-- of this instruction.
--
when o"6201" | o"6211" | o"6221" | o"6231" | o"6241" | o"6251" | o"6261" | o"6271" =>
dfOP <= dfopIR6to8;
--
-- IOT 62x2: CIF - Change Instruction Field
-- The Instruction Buffer (IB/IB) is loaded with
-- IR<6:8> of this instruction and the Interrupt
-- Inhibit Flip Flop (II) is set.
--
-- Note: Setting the II causes the CPU to ignore
-- interrupt requests until the next JMP, JMS,
-- RTN1 or RTN2 Instruction is executed. At that
-- time the contents of IB/IB are loaded into the
-- IF/INF and the II cleared.
--
when o"6202" | o"6212" | o"6222" | o"6232" | o"6242" | o"6252" | o"6262" | o"6272" =>
ibOP <= ibopIR6to8;
iiOP <= iiopSET;
fzop <= fzopCLR;
--
-- IOT 62x2: CIF/CDF (CDI) - Change Instruction
-- and Data Field.
-- A microprogrammed combination of CDF and CIF.
-- Both fields are set to X.
--
when o"6203" | o"6213" | o"6223" | o"6233" | o"6243" | o"6253" | o"6263" | o"6273" =>
dfOP <= dfopIR6to8;
ibOP <= ibopIR6to8;
iiOP <= iiopSET;
fzop <= fzopCLR;
--
-- IOT 6204: CINT - Clear User Interrupt Flag
--
when o"6204" =>
usrtrpOP <= usrtrpopCLR;
--
-- IOT 6205: PPC1 - Push (PC+1) to Stack 1
-- The contents of the PC are incremented by
-- one and the result is loaded into the memory
-- location pointed to by the contents of SP1.
-- SP1 is then decremented by 1.
--
-- The stacks are located in field 0 of memory.
--
when o"6205" =>
if swCPU = swHD6120 then
maOP <= maopSP1;
mbOP <= mbopPCP1;
sp1OP <= spopDEC;
xmaOP <= xmaopCLR;
busOP <= busopWRZF;
end if;
--
-- IOT 6206: PR0 - Panel Request 0
-- The PNLTRP flag is set. If the Interrupt Inhibit
-- Flip-Flop (ION) is not set, the CPU will enter
-- panel mode instead of executing the next
-- instruction. If the Interrupt Inhibit Flip Flop
-- is set, panel mode will be entered following the
-- next JMP, JMS, RTN1 or RTN2 which clears the
-- Interrupt inhibit flip flop. This is a NOP in
-- panel mode.
--
when o"6206" =>
if swCPU = swHD6120 then
if CTRLFF = '0' then
pnltrpOP <= pnltrpopSET;
end if;
end if;
--
-- IOT 6207: RSP1 - Read Stack 1 Pointer to AC
-- The contents of SP1 is loaded Into the AC.
--
when o"6207" =>
if swCPU = swHD6120 then
acOP <= acopSP1;
end if;
--
-- IOT 6214: RDF - Read Data Field to AC<6:8>
-- PDP8: The RDF ors the DF register with AC<6:8>.
-- HD6120: The RDF replaces AC<6:8> with DF<0:2>.
-- The other bits of the accumulator are unaffected
--
when o"6214" =>
if swCPU = swHD6120 then
acOP <= acopRDF0;
else
acOP <= acopRDF1;
end if;
--
-- IOT 6215: PAC1 - Push AC to Stack 1.
-- The contents of the AC is loaded into the
-- memory location pointed to by the contents
-- of SP1. The contents of SP1 is then
-- decremented by 1.
--
-- The stacks are located in field 0 of memory.
--
when o"6215" =>
if swCPU = swHD6120 then
maOP <= maopSP1;
mbOP <= mbopAC;
sp1OP <= spopDEC;
xmaOP <= xmaopCLR;
busOP <= busopWRZF;
end if;
--
-- IOT 6216: PR1 - Panel Request 1.
-- The PNLTRP flag is set. If the Interrupt Inhibit
-- Flip-Flop (ION) is not set, the CPU will enter
-- panel mode instead of executing the next
-- instruction. If the Interrupt Inhibit Flip Flop
-- is set, panel mode will be entered following the
-- next JMP, JMS, RTN1 or RTN2 which clears the
-- Interrupt inhibit flip flop. This is a NOP in
-- panel mode.
--
when o"6216" =>
if swCPU = swHD6120 then
if CTRLFF = '0' then
pnltrpOP <= pnltrpopSET;
end if;
end if;
--
-- IOT 6217: LSP1 - Load Stack 1 Pointer from AC.
-- The contents of the AC is loaded into SP1.
-- The AC is cleared.
--
when o"6217" =>
if swCPU = swHD6120 then
sp1OP <= spopAC;
acOP <= acopCLA;
end if;
--
-- IOT 6224: RIF - Read Instruction Field into AC<6:8>.
-- PDP8: The RIF ors the IF/INF register with AC<6:8>.
-- HD6120: The RIF replaces AC<6:8> with IF/INF<0:2>.
-- The other bits of the accumulator are unaffected
--
when o"6224" =>
if swCPU = swHD6120 then
acOP <= acopRIF0;
else
acOP <= acopRIF1;
end if;
--
-- IOT 6225: RTN1 - Pop top of Stack 1 to PC
--
-- The contents of the stack pointer (SP1) is
-- incremented by one. The contents of the
-- memory location pointed to by SP1 is loaded
-- into the PC.
--
when o"6225" =>
if swCPU = swHD6120 then
sp1OP <= spopINC;
nextState <= stateRTN1;
end if;
--
-- IOT 6226: PR2 - Panel Request 2.
-- The PNLTRP flag is set. If the Interrupt Inhibit
-- Flip-Flop (ION) is not set, the CPU will enter
-- panel mode instead of executing the next
-- instruction. If the Interrupt Inhibit Flip Flop
-- is set, panel mode will be entered following the
-- next JMP, JMS, RTN1 or RTN2 which clears the
-- Interrupt inhibit flip flop. This is a NOP in
-- panel mode.
--
when o"6226" =>
if swCPU = swHD6120 then
if CTRLFF = '0' then
pnltrpOP <= pnltrpopSET;
end if;
end if;
--
-- IOT 6227: RSP2 - Read Stack 2 Pointer to AC
-- The contents of SP2 is loaded Into the AC.
--
when o"6227" =>
if swCPU = swHD6120 then
acOP <= acopSP2;
end if;
--
-- IOT 6234: RIB - Read Instruction Save Field into AC<6:8>
-- and Data Save Field into AC<9:11>.
-- PDP8: The RIB ors the ISF/DSF register with AC<6:11>.
-- HD6120: The RIB replaces AC<6:11> with ISF/DSF.
-- The other bits of the accumulator are unaffected
--
when o"6234" =>
if swCPU = swHD6120 then
acOP <= acopRIB0;
else
acOP <= acopRIB1;
end if;
--
-- IOT 6235: POP1 - Pop top of Stack 1 to AC
-- The contents of SP1 is incremented by 1. The
-- contents of the memory location pointed to
-- by SP1 is then loaded into the AC.
--
-- The stacks are located in field 0 of memory.
--
when o"6235" =>
if swCPU = swHD6120 then
maOP <= maopSP1P1;
sp1OP <= spopINC;
xmaOP <= xmaopCLR;
busOP <= busopRDZFaddr;
nextState <= statePOPaddr;
end if;
--
-- IOT 6236: PR3 - Panel Request 3.
-- The PNLTRP flag is set. If the Interrupt Inhibit
-- Flip-Flop (ION) is not set, the CPU will enter
-- panel mode instead of executing the next
-- instruction. If the Interrupt Inhibit Flip Flop
-- is set, panel mode will be entered following the
-- next JMP, JMS, RTN1 or RTN2 which clears the
-- Interrupt inhibit flip flop. This is a NOP in
-- panel mode.
--
when o"6236" =>
if swCPU = swHD6120 then
if CTRLFF = '0' then
pnltrpOP <= pnltrpopSET;
end if;
end if;
--
-- IOT 6237: LSP2 - Load Stack 2 Pointer from AC.
-- The contents of the AC is loaded into SP2.
-- The AC is cleared.
--
when o"6237" =>
if swCPU = swHD6120 then
sp2OP <= spopAC;
acOP <= acopCLA;
end if;
--
-- IOT 6244: RMF - Restore Memory Fields.
-- Load the contents of ISF into IB, OSF into OF,
-- and set the Interrupt Inhibit Flip Flop. This instruction
-- is used to restore the contents of the memory
-- field registers to their values before an
-- interrupt occurred.
--
-- Note: Setting the II causes the CPU to ignore
-- interrupt requests until the next JMP, JMS,
-- RTN1 or RTN2 Instruction is executed. At that
-- time the contents of IB are loaded into the
-- IF/INF and the II cleared.
--
when o"6244" =>
ubOP <= ubopSF;
ibOP <= ibopSF1to3;
dfOP <= dfopSF4to6;
iiOP <= iiopSET;
fzop <= fzopCLR;
--
-- IOT 6245: PPC2 - Push (PC+1) to Stack 2
-- The contents of the PC are Incremented by
-- one and the result is loaded into the memory
-- location pointed to by the contents of SP2.
-- SP2 is then decremented by 1.
--
-- The stacks are located in field 0 of memory.
--
when o"6245" =>
if swCPU = swHD6120 then
maOP <= maopSP2;
mbOP <= mbopPCP1;
sp2OP <= spopDEC;
xmaOP <= xmaopCLR;
busOP <= busopWRZF;
end if;
--
-- IOT 6246: WSR - Write to Switch Register
-- The contents of AC are written to the switch
-- register and the AC is cleared. This allows
-- the switch register to be 'virtualized' in
-- from panel mode for units without front panel
-- interfaces.
--
when o"6246" =>
if swCPU = swHD6120 then
srOP <= sropAC;
acOP <= acopCLA;
end if;
--
-- IOT 6254: SINT - Skip on User Interrupt Flag
--
when o"6254" =>
if USRTRP = '1' then
pcOP <= pcopINC;
end if;
--
-- IOT 6255: PAC2 - Push AC to Stack 2.
-- The contents of the AC is loaded into the
-- memory location pointed to by the contents
-- of SP2. The contents of SP2 is then
-- decremented by 1.
--
-- The stacks are located in field 0 of memory.
--
when o"6255" =>
if swCPU = swHD6120 then
maOP <= maopSP2;
mbOP <= mbopAC;
sp1OP <= spopDEC;
xmaOP <= xmaopCLR;
busOP <= busopWRZF;
end if;
--
-- IOT 6256: GCF
-- Get current fields and flags
--
when o"6256" =>
acOP <= acopGCF;
--
-- IOF 6264: CUF - Clear User Flag
-- The CUF instruction clears the User Flag (UF) and
-- sets the Interrupt Inhibit Flip-Flop (II).
--
when o"6264" =>
ubOP <= ubopCLR;
iiOP <= iiopSET;
--
-- IOT 6265: RTN2 - Pop top of Stack 2 to PC
--
-- The contents of the stack pointer (SP2) is
-- incremented by one. The contents of the
-- memory location pointed to by SP2 is loaded
-- into the PC.
--
when o"6265" =>
if swCPU = swHD6120 then
sp2op <= spopINC;
nextState <= stateRTN2;
end if;
--
-- IOT 6266: CPD - Clear Panel Data Flag
-- Clears the Panel Data Flag (PDF) so that indirect
-- data operands of panel mode instructions are
-- obtained from main memory.
--
when o"6266" =>
if swCPU = swHD6120 then
if CTRLFF = '1' then
pdfOP <= pdfopCLR;
end if;
end if;
--
-- IOT 6274: SUF - Set User Flag
-- The SUF instruction sets the User Flag (UF) and
-- sets the Interrupt Inhibit Flip Flop (II).
--
when o"6274" =>
ubOP <= ubopSET;
iiOP <= iiopSET;
--
-- IOT 6275: POP2 - Pop top of Stack 2 to AC
-- The contents of SP2 is incremented by 1. The contents
-- of the memory location pointed to by SP2 is then
-- loaded into the AC.
--
-- The stacks are located in field 0 of memory.
--
when o"6275" =>
if swCPU = swHD6120 then
maOP <= maopSP2P1;
sp2OP <= spopINC;
xmaOP <= xmaopCLR;
busOP <= busopRDZFaddr;
nextState <= statePOPaddr;
end if;
--
-- IOT 6276: SPD - Set Panel Data Flag
-- Sets the Panel Data Flag (PDF) so that indirect
-- data operands of panel mode instructions are
-- obtained from panel memory.
--
when o"6276" =>
if swCPU = swHD6120 then
if CTRLFF = '1' then
pdfOP <= pdfopSET;
end if;
end if;
--
-- Unhandled IOTs
--
when others =>
if (IR(0 to 8) = o"600") or (IR(0 to 5) = o"62") then
--
-- Internal IOTS (600x and 62xx) that are
-- not handled above.
--
assert false report "Unhandled Internal IOT" severity warning;
nextState <= stateLaLa;
else
--
-- External IOTS. Handled by external
-- devices.
--
maOP <= maopIR;
mbOP <= mbopAC;
busOP <= busopIOTWR;
nextState <= stateIOTdecode;
end if;
end case;
end if;
--
-- Operate Instructions
--
when opOPR =>
if IR(3) = '0' then
--
-- Operate Group 1
--
-- Group 1
-- | | | | |
-- |---|---|---|---|---|---|---|---|---|---|---|---|
-- | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10| 11|
-- | 1 | 1 | 1 | 0 |CLA|CLL|CMA|CML| R1| R2| R3|IAC|
-- |---|---|---|---|---|---|---|---|---|---|---|---|
-- | | | | | | | |
-- Sequence: 1 1 2 2 4 4 4 3
--
--
--
-- Operate Group 1 Sequence 1 and Sequence 2
-- This state executes all combinations of Sequence 1
-- and Sequence 2 operations
--
case IR(4 to 7) is
--
-- OP 7000: NOP
--
when "0000" =>
null;
--
-- OP 7020: CML - Complement Link Register
-- The contents of the LINK is complemented.
--
when "0001" =>
acop <= acopCML;
--
-- OP 7040: CMA - Complement accumulator.
-- The contents of the AC is replaced by its
-- 1's complement.
--
when "0010" =>
acop <= acopCMA;
--
-- OP 7060: CMA CML
-- The contents of the LINK is complemented.
-- The contents of the AC is replaced by its
-- 1's complement.
when "0011" =>
acOP <= acopCMACML;
--
-- OP 7100: CLL - Clear LINK
-- The LINK is set to zero.
--
when "0100" => -- CLL
acOP <= acopCLL;
--
-- OP 7120: CLL CML (STL) - Set LINK.
-- Clear LINK then Complement LINK. The LINK
-- is set to one.
--
when "0101" =>
acop <= acopCLLCML;
--
-- OP 7140: CLL CMA -
-- Clear LINK and Complement accumulator,
--
when "0110" =>
acOP <= acopCLLCMA;
--
-- OP 7160: CLL CMA CML - STL CMA
-- Set LINK and Complement accumulator,
--
when "0111" =>
acOP <= acopCLLCMACML;
--
-- OP 7200: CLA - Clear accumulator
-- Load AC with "0000".
--
when "1000" =>
acOP <= acopCLA;
--
-- OP 7220: CLA CML
-- Clear Accumulator and Complement LINK
--
when "1001" =>
acOP <= acopCLACML;
--
-- OP 7240: CLA CMA (STA)
-- Clear Accumulator then Complement
-- Accumulator, or Set Accumulator.
--
when "1010" =>
acOP <= acopCLACMA;
--
-- OP 7260: CLA CMA CML (STA CML)
-- Set Accumulator and Complement LINK.
--
when "1011" =>
acOP <= acopCLACMACML;
--
-- OP 7300: CLA CLL
-- Clear AC and Clear LINK.
--
when "1100" =>
acOP <= acopCLACLL;
--
-- OP 7320: CLA CLL CML
-- Clear AC and Set LINK
--
when "1101" =>
acOP <= acopCLACLLCML;
--
-- OP 7340: CLA CLL CMA, STA CLL
-- Set Accumulator and Clear LINK
--
when "1110" =>
acOP <= acopCLACLLCMA;
--
-- OP 7360: CLA CLL CMA CML, STA STL
-- Set Accumulator and Set LINK
--
when "1111" =>
acOP <= acopCLACLLCMACML;
--
-- Everything else
--
when others =>
null;
end case;
--
-- Determine the next state. Skip states if
-- possible.
--
if IR(11) = '1' then
nextState <= stateOprGroup1Seq3;
else
if IR(8) = '1' or IR(9) = '1' or IR(10) = '1' then
nextState <= stateOprGroup1Seq4;
else
nextState <= stateDone;
end if;
end if;
else -- IR(3) = '1'
if IR(11) = '0' then
--
-- Operate Group 2
--
-- Group 2
-- | | | | |
-- |---|---|---|---|---|---|---|---|---|---|---|---|
-- | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10| 11|
-- | 1 | 1 | 1 | 1 |CLA|SMA|SZA|SNL| 0 |OSR|HLT| 0 |
-- | 1 | 1 | 1 | 1 |CLA|SPA|SNA|SZL| 1 |OSR|HLT| 0 |
-- |---|---|---|---|---|---|---|---|---|---|---|---|
-- | | | | | |
-- Sequence: 2 1 1 1 3 3
--
--
--
-- This state handles Operating Group 2
-- Sequence 1
--
case IR(5 to 8) is
--
-- OP 7400: NOP
--
when "0000" =>
null;
--
-- OP 7410: SKP - SKIP
-- The content of the PC is incremented by 1,
-- to skip the next Instruction.
--
when "0001" =>
pcop <= pcopINC;
--
-- OP 7420: SNL
-- Skip if LINK = 1
--
when "0010" =>
if L = '1' then
pcop <= pcopINC;
end if;
--
-- OP 7430: SZL
-- Skip if LINK = 0
--
when "0011" =>
if L = '0' then
pcop <= pcopINC;
end if;
--
-- OP 7440: SZA
-- Skip on zero accumulator (AC = "0000")
--
when "0100" =>
if AC = o"0000" then
pcop <= pcopINC;
end if;
--
-- OP 7450: SNA
-- Skip on non-zero accumulator
--
when "0101" =>
if AC /= o"0000" then
pcop <= pcopINC;
end if;
--
-- OP 7460: SZA SNL
-- Skip if AC="0000" or if LINK = 1
--
when "0110" =>
if ((AC = o"0000") or (L = '1')) then
pcop <= pcopINC;
end if;
--
-- OP 7470: SNA SZL
-- Skip if AC not "0000" and if LINK = 1
--
when "0111" =>
if ((AC /= o"0000") and (L = '0')) then
pcop <= pcopINC;
end if;
--
-- OP 7500: SMA
-- Skip on negative (minus) accumulator (AC0=1)
--
when "1000" =>
if AC(0) = '1' then
pcop <= pcopINC;
end if;
--
-- OP 7510: SPA
-- Skip on positive accumulator (AC0=0)
--
when "1001" =>
if AC(0) = '0' then
pcop <= pcopINC;
end if;
--
-- OP 7520: SMA SNL
-- Skip if AC is negative (minus) or if LINK is 1
--
when "1010" =>
if ((AC(0) = '1') or (L = '1')) then
pcop <= pcopINC;
end if;
--
-- OP 7530: SPA SZL
-- Skip if AC is positive and if LINK is 0
--
when "1011" =>
if ((AC(0) = '0') and (L = '0')) then
pcop <= pcopINC;
end if;
--
-- OP 7540: SMA SZA - Skip if AC is minus or zero
--
when "1100" =>
if ((AC(0) = '1') or (AC = o"0000")) then
pcop <= pcopINC;
end if;
--
-- OP 7550: SPA SNA
-- Skip if AC is positive and non-zero
--
when "1101" =>
if ((AC(0) = '0') and (AC /= o"0000")) then
pcop <= pcopINC;
end if;
--
-- OP 7560: SMA SZA SNL
-- Skip if AC is minus or if AC="0000" or if LINK is 1
--
when "1110" =>
if ((AC(0) = '1') or (AC = o"0000") or (L = '1')) then
pcop <= pcopINC;
end if;
--
-- OP 7570: SPA SNA SZL
-- Skip if AC is positive, nonzero, and if LINK is zero.
--
when "1111" =>
if ((AC(0) = '0') and (AC /= o"0000") and (L = '0')) then
pcop <= pcopINC;
end if;
--
-- Everything else
--
when others =>
null;
end case;
--
-- Determine if there are any Group 2 Sequence
-- 2 operations to perform. Skip states if not.
--
if IR(4) = '1' or IR(9) = '1' or IR(10) = '1' then
nextState <= stateOprGroup2Seq2;
else
nextstate <= stateDone;
end if;
else -- IR(11) = '1'
--
--
-- Decode Group 3 Sequence 1,2 Opcode
--
-- Group 3
-- | | | | |
-- |---|---|---|---|---|---|---|---|---|---|---|---|
-- | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10| 11|
-- | 1 | 1 | 1 | 1 |CLA|MQA| 0 |MQL| 0 | 0 | 0 | 1 |
-- |---|---|---|---|---|---|---|---|---|---|---|---|
-- | | |
-- Sequence: 1 2 2
--
-- Note: In the state machine, Sequence 1 and Sequence 2
-- are handled together to save time (cycles).
--
-- Operate Group 3, 3A and 3B instructions.
--
-- HD6120: If bits 6, 8, 9 or 10 are set to a
-- one, instruction execution is not altered but the
-- instruction becomes uninterruptable by either
-- panel or normal interrupts. That is, the next
-- instruction is guaranteed to be fetched barring
-- a reset, DMAREQ or RUN/HLT flip flop in the
-- HLT state.
--
if ((swCPU = swHD6120 and IR( 6) = '1') or
(swCPU = swHD6120 and IR( 8) = '1') or
(swCPU = swHD6120 and IR( 9) = '1') or
(swCPU = swHD6120 and IR(10) = '1')) then
idOP <= idopSET;
end if;
--
-- OP 74x1: EAE Instructions
--
-- The PDP8/L had no provision for EAE
--
-- These instructions were only available pre
-- PDP8/E if EAE was added.
--
-- These instruction work on PDP8/E and later
-- without EAE.
--
if ((swCPU = swPDP8 and swOPT.KE8 = '1') or
(swCPU = swPDP8S and swOPT.KE8 = '1') or
(swCPU = swPDP8I and swOPT.KE8 = '1') or
-- PDP8L never supported EAE
(swCPU = swPDP8E) or
(swCPU = swPDP8F) or
(swCPU = swPDP8M) or
(swCPU = swPDP8A) or
(swCPU = swHD6120)) then
EAEIR := IR(4) & IR(5) & IR(7) & '0';
case EAEIR(0 to 2) is
--
-- OP 7401: NOP
--
when "000" =>
null;
--
-- OP 7421: MQL - MQ register load
-- The MQ is loaded with the contents of the
-- AC and the AC is cleared. The original
-- contents of the MQ is lost.
--
when "001" =>
mqOP <= mqopAC;
acOP <= acopCLA;
--
-- OP 7501: MQA - MQ "OR" with accumulator.
-- OR the contents of the MQ is "OR"ed with
-- the contents of the AC, and the result left
-- in the AC. The MQ is not modified.
--
when "010" =>
acOP <= acopORMQ;
--
-- OP 7521: SWP - Swap contents of AC and MQ.
-- The contents of the AC and MQ are exchanged
--
-- The SWP instruction does not work on
-- Straight 8 (PDP8)
when "011" =>
if ((swCPU = swPDP8) or
(swCPU = swPDP8I)) then
-- What should this do?
acOP <= acopNOP;
mqOP <= mqopNOP;
else
acOP <= acopMQ;
mqOP <= mqopAC;
end if;
--
-- OP 7601: CLA - Clear Accumulator
-- The accumulator may be cleared prior to other
-- group three microcoded operations. Unless
-- microcoded with other group three instructions,
-- PDP-8 assemblers generally assume that the CLA
-- mnemonic refers to the group one instruction.
--
when "100" =>
acOP <= acopCLA;
--
-- OP 7621: CLA/MQL - CAM - Clear AC and MQ
-- This instruction first clears AC, so the
-- result is to clear both AC and MQ.
--
when "101" =>
acOP <= acopCLA;
mqOP <= mqopCLR;
--
-- OP 7701: CLA MQA - ACL - Microcode CLA MQA
-- This instruction first clears AC, so the
-- result is to load AC with the contents
-- of MQ.
--
when "110" =>
acOP <= acopMQ;
--
-- OP 7721: CLA SWP - Clear AC, then swap.
-- The MQ is loaded into the AC;
-- "0000" is loaded into the MQ.
--
when "111" =>
acOP <= acopMQ;
mqOP <= mqopCLR;
--
-- Everything else
--
when others =>
null;
end case;
--
-- Group 3 Sequence 3 instruction are
-- supported with EAE installed.
--
if swOPT.KE8 = '1' then
nextState <= stateOprGroup3Seq3;
else
nextstate <= stateDone;
end if;
end if; -- Group 3
end if; -- IR(11)
end if; -- IR(3)
--
-- Everything else
--
when others =>
null;
end case;
--
-- IOT Decode State
-- The previous state peformed an IOT write cycle. This state
-- decides the devc and skip that is return by the IOT interface.
--
when stateIOTdecode =>
--
-- Handle Skip
--
if dev.skip = '1' then
pcOP <= pcopINC;
end if;
--
-- Handle CLA
--
if dev.devc = devWRCLR or dev.devc = devRDCLR then
acOP <= acopCLA;
end if;
--
-- Handle RD and WR
--
if dev.devc = devRD or dev.devc = devRDCLR then
busOP <= busopRDIOT;
nextState <= stateIOT;
else
nextState <= stateDone;
end if;
--
-- stateIOT:
-- The previous state performed a Read Data Cycle. OR the IOT data
-- that was read with AC.
--
when stateIOT =>
acOP <= acopORMD;
nextState <= stateDone;
--
-- Operate Group1 Sequence 3 State
--
when stateOprGroup1Seq3 =>
--
-- OP 7001: IAC - Increment accumulator.
-- The contents of the AC is incremented by 1.
-- Carry out complements the LINK.
--
if IR(11) = '1' then
acOP <= acopIAC;
end if;
--
-- Determine the next state
--
if IR(8) = '1' or IR(9) = '1' or IR(10) = '1' then
nextState <= stateOprGroup1Seq4;
else
nextState <= stateDone;
end if;
--
-- Operate Group1 Sequence 4 State
--
when stateOprGroup1Seq4 =>
case IR(8 to 10) is
--
-- OP 7000: NOP
--
when "000" =>
null;
--
-- OP 7002: BSW - Byte swap
--
when "001" =>
--
-- PDP-8/E and later
-- OP 7002: BSW - Byte swap
-- AC<O-5> are exchanged with AC<6-11> respectively.
-- The LINK is not changed.
--
if ((swCPU = swPDP8E) or
(swCPU = swPDP8F) or
(swCPU = swPDP8A) or
(swCPU = swHD6120)) then
acOP <= acopBSW;
--
-- Pre PDP8/E
-- OP 7002: Equivalent to a NOP
--
else
null;
end if;
--
-- OP 7004: RAL - Rotate accumulator left.
-- The contents of the AC and LINK are rotated one
-- binary position to the left. AC(O) is shifted to
-- LINK and LINK is shifted to AC(11).
--
-- RAL combined with IAC only works on PDP8I and later
-- RAL combined with CMA is broke on on PDP8S
--
when "010" =>
if ((swCPU = swPDP8 and IR(11) = '1') or
(swCPU = swPDP8S and IR(11) = '1')) then
-- What should this do?
acOP <= acopNOP;
elsif swCPU = swPDP8S and IR(6) = '1' then
-- What should this do?
acOP <= acopNOP;
else
acOP <= acopRAL;
end if;
--
-- OP 7006: RTL - Rotate two left.
-- Equivalent to two RAL's.
--
-- RTL combined with IAC only works on PDP8I and later
-- RTL combined with CMA is broke on on PDP8S
--
when "011" =>
if ((swCPU = swPDP8 and IR(11) = '1') or
(swCPU = swPDP8S and IR(11) = '1')) then
-- What should this do?
acOP <= acopNOP;
elsif swCPU = swPDP8S and IR(6) = '1' then
-- What should this do?
acOP <= acopNOP;
else
acOP <= acopRTL;
end if;
--
-- OP 7010: RAR - Rotate accumulator right.
-- The contents of the AC and LINK are rotated one
-- binary position to the right. AC(11) is shifted
-- into the LINK, and LINK is shifted to AC(O).
--
-- RAR combined with IAC only works on PDP8I and later
-- RAR combined with CMA is broke on on PDP8S
--
when "100" =>
if ((swCPU = swPDP8 and IR(11) = '1') or
(swCPU = swPDP8S and IR(11) = '1')) then
-- What should this do?
acOP <= acopNOP;
elsif swCPU = swPDP8S and IR(6) = '1' then
-- What should this do?
acOP <= acopNOP;
else
acOP <= acopRAR;
end if;
--
-- OP 7012: RTR - Rotate two right.
-- Equivalent to two RAR's.
--
-- RTR combined with IAC only works on PDP8I and later
-- RTR combined with CMA is broke on on PDP8S
--
when "101" =>
if ((swCPU = swPDP8 and IR(11) = '1') or
(swCPU = swPDP8S and IR(11) = '1')) then
-- What should this do?
acOP <= acopNOP;
elsif swCPU = swPDP8S and IR(6) = '1' then
-- What should this do?
acOP <= acopNOP;
else
acOP <= acopRTR;
end if;
--
-- OP 7014: PDP8: UNDEF1
-- Sneak path though the AND array This instruction
-- produced predicable but undocumented results.
-- OP 7014: PDP8E, PDP8F, PDP8M, PDP8A
-- NOP. Verified on David Gesswein's PDP8E
-- OP 7014: HD6120: R3L - Rotate 3 Left.
-- Rotate AC (but not LINK) left 3 places.
-- AC(0) is rotated into AC(9),
-- AC(1) is rotated into AC(10),
-- AC(2) is rotated into AC(11),
-- AC(3) is rotated into AC(1), etc
--
when "110" =>
if swCPU = swHD6120 then
acOP <= acopR3L;
elsif ((swCPU = swPDP8E) or
(swCPU = swPDP8F) or
(swCPU = swPDP8M) or
(swCPU = swPDP8A)) then
acOP <= acopNOP;
else
acOP <= acopUNDEF1;
end if;
--
-- OP 7016: UNDEF2: Sneak though addr. This instruction
-- produced predicable but undocumented results.
-- Verified on David Gesswein's PDP8E
--
when "111" =>
acOP <= acopUNDEF2;
--
-- Everything else
--
when others =>
null;
end case;
nextState <= stateDone;
--
-- Operate Group 2 Sequence 2 State
--
when stateOprGroup2Seq2 =>
--
-- In USER mode, the OSR and HLT instructions are privledged
-- and generate a User Mode interrupt.
--
if ((UF = '1' and IR( 9) = '1') or
(UF = '1' and IR(10) = '1')) then
if IR(4) = '1' then
acOP <= acopCLA;
end if;
usrtrpOP <= usrtrpopSET;
else
--
-- OP 7402: HLT - HALT
-- OP 7406: OSR HLT - HALT
-- OP 7606: CLA OSR HLT, LAS HLT - HALT
-- The HALT Operation is not particularly sequence
-- sensitive so it is decoded here. The CPU will halt at
-- the end of the current instruction.
--
if IR(10) = '1' then
hlttrpOP <= hlttrpopSET;
end if;
if IR(9) = '1' then
--
-- OP 7604: LAS : Load AC with Switches.
--
if IR(4) = '1' then
acOP <= acopLAS;
--
-- OP 7404: OSR : OR Switch Register with accumulator.
--
else
acOP <= acopOSR;
end if;
else
--
-- OP 7600: CLA - Clear Accumulator
--
if IR(4) = '1' then
acOP <= acopCLA;
end if;
end if;
end if;
nextState <= stateDone;
--
-- Operate Group 3 Sequence 3 Mode A State
--
when stateOprGroup3Seq3 =>
--
-- Group 3 Mode A
--
-- | | | | |
-- |---|---|---|---|---|---|---|---|---|---|---|---|
-- | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10| 11|
-- | 1 | 1 | 1 | 1 |CLA|MQA|SCA|MQL| | | | 1 |
-- |---|---|---|---|---|---|---|---|---|---|---|---|
-- | | | | |
-- Sequence: 1 2 2 \____3____/
-- V
-- 0 = NOP 4 = NMI
-- 1 = SCL 5 = SHL
-- 2 = MUY 6 = ASR
-- 3 = DVI 7 = LSR
--
--
-- Group 3 Mode B
--
-- | | | | |
-- |---|---|---|---|---|---|---|---|---|---|---|---|
-- | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10| 11|
-- | 1 | 1 | 1 | 1 |CLA|MQA| |MQL| | | | 1 |
-- |---|---|---|---|---|---|---|---|---|---|---|---|
-- | | | | |
-- Sequence: 1 2 \ 2 /
-- \_______3_______/
-- V
-- 0 = NOP 10 = SCA
-- 1 = ACS 11 = DAD
-- 2 = MUY 12 = DST
-- 3 = DVI 13 = SWBA
-- 4 = NMI 14 = DPSZ
-- 5 = SHL 15 = DPIC (MQL & MQA set)
-- 6 = ASR 16 = DCM (MQL & MQA set)
-- 7 = LSR 17 = SAM
--
if IR = o"7431" then
--
-- OP 7431: SWAB - Switch from A to B. The SWAB
-- instruction cannot be microprogrammed with any of the
-- Mode 3A or Mode 3B instructions.
--
-- EAE Mode B was only available on PDP8/E, PDP8/F, PDP8/M,
-- PDP8/A with EAE.
--
if ((swCPU = swPDP8E) or
(swCPU = swPDP8F) or
(swCPU = swPDP8M) or
(swCPU = swPDP8A)) then
emodeOP <= emodeopSET;
nextState <= stateDone;
end if;
elsif IR = o"7447" then
--
-- SWBA - Switch from B to A. Clear GTF. The SWBA
-- instruction cannot be microprogrammed with any of the
-- Mode 3A or Mode 3B instructions.
--
emodeOP <= emodeopCLR;
gtfOP <= gtfopCLR;
nextState <= stateDone;
else
--
-- EAE Mode A Operations clear GTF
--
if EMODE = '0' then
gtfOP <= gtfopCLR;
end if;
--
-- All the Mode 3A and Mode 3B instructions
--
EAEIR := IR(6) & IR(8) & IR(9) & IR(10);
case EAEIR is
--
-- OP 7401: NOP
--
when opEAENOP =>
nextState <= stateDone;
--
-- OP 7403: MODEA: SCL
-- MODEB: ACS
--
when "0001" =>
if EMODE = '0' then
--
-- SCL - Step Counter Load from Memory. The SCL
-- instruction is a two-word instruction. The
-- value to load is contained in the operand
-- which is located at the next memory
-- location. Begin the fetch of the operand.
--
maOP <= maopPC;
pcOP <= pcopINC;
xmaOP <= xmaopIF;
busOP <= busopRDIFaddr;
nextState <= stateEAEfetchAddr;
else
--
-- ACS - Accumulator to Step Count.
-- AC(7 to 11) are loaded into the Step Counter
-- then the AC is cleared.
--
scOP <= scopAC7to11;
acOP <= acopCLA;
nextState <= stateDone;
end if;
--
-- OP 7405: MUY - Multiply. The Multiply instruction
-- is a two-word instruction. The second word is
-- either the multiplier or the address of the multiplier
-- depending on the mode. Begin the fetch of the operand.
--
when opEAEMUY =>
maOP <= maopPC;
pcOP <= pcopINC;
xmaOP <= xmaopIF;
busOP <= busopRDIFaddr;
nextState <= stateEAEfetchAddr;
--
-- OP 7407: DVI - Divide. The Divide instruction
-- is a two-word instruction. The second word is
-- either the divisor or the address of the divisor
-- depending on the mode. Begin the fetch of the operand.
--
when opEAEDVI =>
maOP <= maopPC;
pcOP <= pcopINC;
xmaOP <= xmaopIF;
busOP <= busopRDIFaddr;
nextState <= stateEAEfetchAddr;
--
-- OP 7411: NMI
-- The Step Counter is initially cleared.
--
when opEAENMI =>
scOP <= scopCLR;
nextState <= stateEAEnmi;
--
-- OP 7413: SHL - Shift Left. The shift left
-- instruction is a two-word instruction. The number of
-- shifts is contained in operand which is located at
-- the next memory location. Begin the fetch of the operand.
--
when opEAESHL =>
maOP <= maopPC;
xmaOP <= xmaopIF;
pcOP <= pcopINC;
xmaOP <= xmaopIF;
busOP <= busopRDIFaddr;
nextState <= stateEAEfetchAddr;
--
-- OP 7415: ASR - Arithmetic Shift Right.
-- The number of shifts is contained in operand which
-- is contained in the next memory location. Begin the
-- fetch of the operand.
--
when opEAEASR =>
maOP <= maopPC;
xmaOP <= xmaopIF;
pcOP <= pcopINC;
busOP <= busopRDIFaddr;
nextState <= stateEAEfetchAddr;
--
-- OP 7417: LSR - Logical Shift Right
-- The number of shifts is contained in operand which
-- is located at the next memory location. Begin the
-- fetch of the operand.
--
when opEAELSR =>
maOP <= maopPC;
xmaOP <= xmaopIF;
pcOP <= pcopINC;
busOP <= busopRDIFaddr;
nextState <= stateEAEfetchAddr;
--
-- OP 7441: SCA - Step Count OR with AC
--
when opEAESCA =>
acop <= acopSCA;
nextState <= stateDone;
--
-- OP 7443: MODEA SCA/SCL
-- MODEB DAD
--
when opEAEDAD =>
if EMODE = '0' then
--
-- SCA/SCL - Step Counter Load from Memory. The SCL
-- instruction is a two-word instruction. The
-- value to load is contained in the operand
-- which is located at the next memory
-- location. Begin the fetch of the operand.
--
acop <= acopSCA;
pcOP <= pcopINC;
maOP <= maopPC;
xmaOP <= xmaopIF;
busOP <= busopRDIFaddr;
nextState <= stateEAEfetchAddr;
else
--
-- DAD - Double Precision Add. The DAD
-- instruction is a three-word instruction. The
-- second word is the first operand which is
-- the address of the LSW of the addend. Begin
-- the fetch of the first operand.
--
pcOP <= pcopINC;
maOP <= maopPC;
xmaOP <= xmaopIF;
busOP <= busopRDIFaddr;
nextState <= stateEAEfetchAddr;
end if;
--
-- OP 7445: MODEA: SCA/MUY
-- MODEB: DST
when opEAEDST =>
if EMODE = '0' then
--
-- SCA/MUY - Multiply. The Multiply instruction
-- is a two-word instruction. The second word is
-- either the multiplier or the address of the multiplier
-- depending on the mode. Begin the fetch of the operand.
--
acop <= acopSCA;
pcOP <= pcopINC;
maOP <= maopPC;
xmaOP <= xmaopIF;
busOP <= busopRDIFaddr;
nextState <= stateEAEfetchAddr;
else
--
-- DST - Double Precision Store.
--
pcOP <= pcopINC;
maOP <= maopPC;
xmaOP <= xmaopIF;
busOP <= busopRDIFaddr;
nextState <= stateEAEfetchAddr;
end if;
--
-- OP 7451: MODEA: SCA/NMI
-- MODEB: DPSZ
--
when opEAEDPSZ =>
if EMODE = '0' then
--
-- SCA/NMI -
-- The Step Counter is initially cleared.
--
acop <= acopSCA;
scOP <= scopCLR;
nextState <= stateDone;
else
--
-- DPSZ - Double Precision Skip if Zero
--
if AC = o"0000" and MQ = o"0000" then
pcop <= pcopINC;
end if;
nextState <= stateDone;
end if;
--
-- OP 7453: MODEA: SCA/SHL
-- MODEB: DPIC
--
when opEAEDPIC =>
if EMODE = '0' then
--
-- SCA/SHL - SCA combined with SHL
--
acOP <= acopSCA;
maOP <= maopPC;
xmaOP <= xmaopIF;
pcOP <= pcopINC;
busOP <= busopRDIFaddr;
nextState <= stateEAEfetchAddr;
else
--
-- DPIC - Double Precision Increment
-- Note: AC and MQ were previously swapped because
-- this instruction must be micro-coded with MQL and MQA.
--
if AC = o"7777" then
mqOP <= mqopCLR;
if MQ = o"7777" then
acOP <= acopCLACLLCML;
else
acOP <= acopMQP1;
end if;
else
mqOP <= mqopACP1;
acOP <= acopZMQ;
end if;
nextState <= stateDone;
end if;
--
-- OP 7455: MODEA: SCA/ASR
-- MODEB: DCM
--
when opEAEDCM =>
if EMODE = '0' then
--
-- SCA/ASR - SCA combined with ASR
--
maOP <= maopPC;
xmaOP <= xmaopIF;
acOP <= acopSCA;
pcOP <= pcopINC;
busOP <= busopRDIFaddr;
nextState <= stateEAEfetchAddr;
else
--
-- DCM - Double Precision Complement.
-- The 24-bit number in AC and MQ is complemented and
-- incremented. This has the effect of two complementing
-- the 24-bit number. The high-order carry is propigated
-- into the link register.
-- Note: AC and MQ were previously swapped because
-- this instruction must be micro-coded with MQL and MQA.
--
if AC = o"0000" then
mqOP <= mqopCLR;
if MQ = o"0000" then
acOP <= acopCLACLLCML;
else
acOP <= acopNEGMQ;
end if;
else
mqOP <= mqopNEGAC;
acOP <= acopNOTMQ;
end if;
nextState <= stateDone;
end if;
--
-- OP 7457: MODEA: SCA/LSR
-- MODEB: SAM
--
when opEAESAM =>
if EMODE = '0' then
--
-- SCA/LSR - SCA combined with LSR
--
maOP <= maopPC;
xmaOP <= xmaopIF;
pcOP <= pcopINC;
acOP <= acopSCA;
busOP <= busopRDIFaddr;
nextState <= stateEAEfetchAddr;
else
--
-- SAM - Subtract AC from MQ.
-- GTF is set if signed MQ >= signed AC
-- otherwise GTF is cleared.
--
acOP <= acopMQSUB;
if signed(MQ) >= signed(AC) then
gtfOP <= gtfopSET;
else
gtfOP <= gtfopCLR;
end if;
nextState <= stateDone;
end if;
--
-- Everything else
--
when others =>
assert false report "stateOprGroup3Seq3: Undecoded instruction" severity warning;
nextState <= stateDone;
end case;
end if;
--
-- This state performs a read address cycle.
-- The next state will do a read data bus.
--
when stateMRIreadAddr =>
xmaOP <= xmaopIF;
busOP <= busopRDIFaddr;
if ((IR(3 to 4) = amDZ) or IR(3 to 4) = amDC) then
nextState <= stateMRIexecute;
else
nextState <= stateMRIreadDataIND;
end if;
--
-- This state perfored a read data bus cycle.
-- The data that was read is in MD.
--
when stateMRIreadDataIND =>
if MA(0 to 8) = maAutoIncr then
--
-- Writeback auto incremented data.
-- MB <- MD + 1
-- MEM[IF'MA] <- MB
--
mbOP <= mbopMDP1;
xmaOP <= xmaopIF;
busOP <= busopWRIF;
nextState <= stateMRIreadINCaddr;
else
--
-- Non-autoincrement addresses
-- Start address phase of indirect data read
-- Address input is in MD
--
case IR(0 to 2) is
--
-- MA <- MD
-- MD <- MEM[IB'MA]
--
when opJMS | opJMP =>
maOP <= maopMD;
xmaOP <= xmaopIB;
busOP <= busopRDIBaddr;
nextState <= stateMRIexecute;
--
-- MA <- MB
-- MD <- MEM[DF'MA]
--
when others =>
maOP <= maopMD;
xmaOP <= xmaopDF;
busOP <= busopRDDFaddr;
nextState <= stateMRIreadINDdata;
end case;
end if;
--
-- Start address phase of indirect data read
-- Address input is in MB
--
when stateMRIreadINCaddr =>
case IR(0 to 2) is
--
-- MA <- MB
-- MD <- MEM[IB'MA]
--
when opJMS | opJMP =>
maOP <= maopMB;
xmaOP <= xmaopIB;
busOP <= busopRDIBaddr;
nextState <= stateMRIexecute;
--
-- MA <- MB
-- MD <- MEM[DF'MA]
--
when others =>
maOP <= maopMB;
xmaOP <= xmaopDF;
busOP <= busopRDDFaddr;
nextState <= stateMRIreadINDdata;
end case;
--
-- Start data phase of indirect data read
-- MD <- MEM[DF'MA]
--
when stateMRIreadINDdata =>
xmaOP <= xmaopDF;
busOP <= busopRDDFdata;
nextState <= stateMRIexecute;
--
-- Dispatch the MRI ops. The previous state was a read data cycle.
-- The data is in MD and the address is MA.
--
when stateMRIexecute =>
case IR(0 to 2) is
--
-- AC <- AC and MD
--
when opAND =>
acOP <= acopANDMD;
nextState <= stateDone;
--
-- AC <- AC + MD
--
when opTAD =>
acOP <= acopADDMD;
nextState <= stateDone;
--
-- MB <- MD + 1
-- IF MD = 7777 (or MB = 0000) Then
-- PC <- PC + 1;
-- ENDIF
-- IF ISZ DIRECT THEN
-- MEM[IF'MA] <- MB
-- ELSE
-- MEM[DF'MA] <- MB
-- ENDIF
-- Note: Checking MD against 7777 saves a state...
--
when opISZ =>
mbOP <= mbopMDP1;
if MD = o"7777" then
pcOP <= pcopINC;
end if;
if ((IR(3 to 4) = amDZ) or IR(3 to 4) = amDC) then
xmaOP <= xmaopIF;
busOP <= busopWRIF;
else
xmaOP <= xmaopDF;
busOP <= busopWRDF;
end if;
nextState <= stateDone;
--
-- MB <- AC
-- AC <- 0000
-- IF DCA DIRECT THEN
-- MEM[IF'MA] <- MB
-- ELSE
-- MEM[DF'MA] <- MB
-- ENDIF
--
when opDCA =>
mbOP <= mbopAC;
acOP <= acopCLA;
if ((IR(3 to 4) = amDZ) or IR(3 to 4) = amDC) then
xmaOP <= xmaopIF;
busOP <= busopWRIF;
else
xmaOP <= xmaopDF;
busOP <= busopWRDF;
end if;
nextState <= stateDone;
--
-- opJMS
--
-- When the PEX Flip-flop is set, the CPU shall exit from
-- Panel Mode to Main Memory (i.e., clear CTRLFF) during
-- the next JMP, JMS, RTN1 or RTN2 instruction. PEX is
-- cleared by the JMP, JMS, RTN1 or RTN instruction.
--
-- IF <- IB
-- UF <- UB
-- IIFF <- '0'
-- MB <- PC
-- MEM[IB'MA] <- MB
-- IF PEX = '1' THEN
-- CTRLFF <- '0'
-- PEX <- '0'
-- ENDIF
--
when opJMS =>
ifOP <= ifopIB;
ufOP <= ufopUB;
wrOP <= '1';
mbOP <= mbopPC;
pcOP <= pcopMAP1;
xmaOP <= xmaopIB;
memselOP <= '1';
busOP <= busopWRIB;
if PEX = '1' then
ctrlffOP <= ctrlffopCLR;
pexOP <= pexopCLR;
end if;
nextState <= stateDone;
--
-- opJMP
--
-- When the PEX Flip-flop is set, the CPU shall exit from
-- Panel Mode to Main Memory (i.e., clear CTRLFF) during
-- the next JMP, JMS, RTN1 or RTN2 instruction. PEX is
-- cleared by the JMP, JMS, RTN1 or RTN instruction.
--
-- IF <- IB
-- UF <- UB
-- PC <- MA
-- IF PEX = '1' THEN
-- CTRLFF <- '0'
-- PEX <- '0'
-- ENDIF
--
when opJMP =>
ifOP <= ifopIB;
ufOP <= ufopUB;
pcOP <= pcopMA;
if PEX = '1' then
ctrlffOP <= ctrlffopCLR;
pexOP <= pexopCLR;
end if;
nextState <= stateDone;
--
-- Can't get to any of these
--
when opIOT =>
assert false report "stateMRIexecute: IOT direct." severity warning;
nextState <= stateDone;
when opOPR =>
assert false report "stateMRIexecute: OPR direct." severity warning;
nextState <= stateDone;
when others =>
assert false report "stateMRIexecute: Others direct." severity warning;
nextState <= stateDone;
end case;
--
-- The previous state set the MA register
-- This state handles the address phase of the read cycle.
-- MD <- MEM[IF,MA]
--
when stateEAEfetchAddr =>
busOP <= busopRDIFdata;
nextState <= stateEAEfetchData;
--
-- This is the data phase of the EAE second word read.
-- At the end of this cycle, the second word is in the MD register.
-- MD <- MEM[IF,MA]
--
-- This state will re-dispatch EAE ops that have a single operand
-- that is used as 'immediate data'. This state will begin the
-- fetch of indirect data for EAE ops with indirect operands.
--
when stateEAEfetchData =>
EAEIR := IR(6) & IR(8) & IR(9) & IR(10);
case EAEIR is
--
-- OP 7401: NOP
--
when opEAENOP =>
nextState <= stateDone;
--
-- OP 7403: MODEA: SCL
-- MODEB: ACS
--
when opEAEACS =>
if EMODE = '0' then
--
-- SCL - The ones complement of the last five bits
-- of this operand are loaded into the Step Counter
-- and the program resumes at the instruction word
-- following the operand.
--
scOP <= scopNOTMD7to11;
nextState <= stateDone;
else
--
-- ACS - Accumulator to Step Count.
-- The ACS instruction doesn't re-dispatch here.
-- You shouldn't get here.
--
assert false report "stateEAEfetchData: ACS should not re-dispatch here" severity warning;
nextState <= stateLALA;
end if;
--
-- OP 7405: MUY - Multiply.
-- In MODEA, the operand is the multiplier.
-- In MODEB, the operand is the address of the multipler,
-- which is possibly pre-incremented before use. Start the
-- multiply operation.
--
when opEAEMUY =>
if EMODE = '0' then
EAEop <= eaeopMUY;
nextState <= stateEAEmuy;
else
if MA(3 to 11) = maAutoIncr then
--
-- Start the writeback of the incremented data
--
wrOP <= '1';
mbOP <= mbopMDP1;
--XMAOPTBD
datafOP <= '1';
memselOP <= '1';
nextState <= stateEAEindWrite;
else
--
-- Start address phase of indirect data read
--
maOP <= maopMD;
--XMAOPTBD
datafOP <= '1';
memselOP <= '1';
nextState <= stateEAEindReadAddr;
end if;
end if;
--
-- OP 7407: DVI - Divide
-- In MODEA, the operand is the divisor
-- In MODEB, the operand is the address of the divisor
-- which is possibly pre-incremented before use. The
-- divisor is in MD.
--
when opEAEDVI =>
if EMODE = '0' then
--
-- Handle divide overflow condition
--
if AC >= MD then
scOP <= scopCLR;
acOP <= acopCLLCML;
mqOP <= mqopSHL1;
nextState <= stateDone;
--
-- Handle normal divide condition
--
else
mqaOP <= mqaopMQ;
scOP <= scopCLR;
acOP <= acopCLL;
nextState <= stateEAEsubDVI;
end if;
else
if MA(3 to 11) = maAutoIncr then
--
-- Start the writeback of the incremented data
--
wrOP <= '1';
mbOP <= mbopMDP1;
--XMAOPTBD
--DATAFOP OR IFETCHOP
memselOP <= '1';
nextState <= stateEAEindWrite;
else
--
-- Start address phase of indirect data read
--
maOP <= maopMD;
--XMAOPTBD
datafOP <= '1';
memselOP <= '1';
nextState <= stateEAEindReadAddr;
end if;
end if;
--
-- OP 7411: NMI - Normalize
-- The NMI instruction doesn't re-dispatch here.
-- You shouldn't get here.
--
when opEAENMI =>
assert false report "stateEAEfetchData: NMI should not re-dispatch here" severity warning;
nextState <= stateLALA;
--
-- OP 7413: SHL - Shift Left.
-- The second word of the two-word instruction defines the
-- number of shifts to be performed. In Mode A, the number
-- of shifts performed is equal to one more than the number
-- in the last five bits of the second word. In Mode B,
-- the number of shifts performed is equal to the number in
-- the last five bits of the second word. A shift count of
-- zero is legal, and leaves the link, AC, and MQ registers
-- unchaged.
--
when opEAESHL =>
if EMODE = '0' then
--
-- Mode A:
-- Handle case where SHL Shift count is maxed out.
--
if unsigned(MD(7 to 11)) > 24 then
scOP <= scopCLR;
mqOP <= mqopCLR;
acOP <= acopCLACLL;
nextState <= stateDone;
--
-- Mode A:
-- Normal case where SHL shift count not maxed out.
--
else
scOP <= scopMDP1;
nextState <= stateEAEshift;
end if;
else
--
-- Mode B:
-- Handle case where SHL Shift count is maxed out.
--
if unsigned(MD(7 to 11)) > 25 then
scOP <= scopSET;
mqOP <= mqopCLR;
acOP <= acopCLACLL;
nextState <= stateDone;
--
-- Mode B:
-- Handle case where SHL Shift count is zero
--
elsif unsigned(MD(7 to 11)) = 0 then
scOP <= scopSET;
nextState <= stateDone;
--
-- Mode B:
-- Normal case where SHL shift count not maxed out.
--
else
scOP <= scopMD7to11;
nextState <= stateEAEshift;
end if;
end if;
--
-- OP 7415: ASR - Arithmetic Shift Right.
-- The second word of the two-word instruction defines the
-- number of shifts to be performed. In Mode A, the number
-- of shifts performed is equal to one more than the number
-- in the last five bits of the second word. In Mode B,
-- the number of shifts performed is equal to the number in
-- the last five bits of the second word. A shift count of
-- zero is legal, and loads the link from AC(0) but leaves
-- the AC and MQ registers unchaged.
--
when opEAEASR =>
if EMODE = '0' then
--
-- Mode A:
-- Handle case where ASR Shift count is maxed out.
-- Sign extended AC into L and MQ
--
if unsigned(MD(7 to 11)) > 23 then
if AC(0) = '0' then
acOP <= acopCLACLL;
mqOP <= mqopCLR;
else
acOP <= acopCLACLLCMACML;
mqOP <= mqopSET;
end if;
scOP <= scopCLR;
nextState <= stateDone;
--
-- Mode A:
-- Normal case where ASR shift count not maxed out.
-- Sign extend AC into L
--
else
scOP <= scopMDP1;
if AC(0) = '0' then
acOP <= acopCLL;
else
acOP <= acopCLLCML;
end if;
nextState <= stateEAEshift;
end if;
else
--
-- Mode B:
-- Handle case where ASR Shift count is maxed out.
-- Shift sign extended AC
--
if unsigned(MD(7 to 11)) > 25 then
if AC(0) = '0' then
acOP <= acopCLACLL;
mqOP <= mqopCLR;
gtfOP <= gtfopCLR;
else
acOP <= acopCLACLLCMACML;
mqOP <= mqopSET;
gtfOP <= gtfopSET;
end if;
scOP <= scopSET;
nextState <= stateDone;
--
-- Mode B:
-- Handle case where ASR Shift count is zero
-- Sign extend AC into L
--
elsif unsigned(MD(7 to 11)) = 0 then
if AC(0) = '0' then
acOP <= acopCLL;
else
acOP <= acopCLLCML;
end if;
nextState <= stateDone;
--
-- Mode B:
-- Normal case where ASR shift count not maxed out.
--
else
scOP <= scopMD7to11;
if AC(0) = '0' then
acOP <= acopCLL;
else
acOP <= acopCLLCML;
end if;
nextState <= stateEAEshift;
end if;
end if;
--
-- OP 7417: LSR - Logical Shift Right
-- The second word of the two-word instruction defines the
-- number of shifts to be performed. In Mode A, the number
-- of shifts performed is equal to one more than the number
-- in the last five bits of the second word. In Mode B,
-- the number of shifts performed is equal to the number in
-- the last five bits of the second word. A shift count of
-- zero is legal, and clears the link without changing the
-- AC or MQ registers.
--
when opEAELSR =>
if EMODE = '0' then
--
-- Mode A:
-- Handle case where LSR Shift count is maxed out.
--
if unsigned(MD) > 23 then
scOP <= scopCLR;
acOP <= acopCLACLL;
mqOP <= mqopCLR;
nextState <= stateDone;
--
-- Mode A:
-- Normal case where LSR shift count not maxed out.
--
else
scOP <= scopMDP1;
acOP <= acopCLL;
nextState <= stateEAEshift;
end if;
else
--
-- Mode B:
-- Handle case where LSR Shift count is maxed out.
--
if unsigned(MD) > 24 then
scOP <= scopCLR;
acOP <= acopCLACLL;
mqOP <= mqopCLR;
gtfOP <= gtfopCLR;
nextState <= stateEAEshift;
--
-- Mode B:
-- Handle case where LSR Shift count is zero
--
elsif unsigned(MD(7 to 11)) = 0 then
acOP <= acopCLL;
nextState <= stateDone;
--
-- Mode B:
-- Normal case where LSR shift count not maxed out.
--
else
scOP <= scopMD7to11;
acOP <= acopCLL;
nextState <= stateEAEshift;
end if;
end if;
--
-- OP 7441: SCA - Step Count OR with AC
--
-- The ones complement of the last five bits of this
-- operand are loaded into the Step Counter and the
-- program resumes at the instruction word following
-- the operand.
--
when opEAESCA =>
assert false report "stateEAEfetchData: SCA should not re-dispatch here" severity warning;
nextState <= stateLALA;
--
-- OP 7407: DAD - Double Precision Add. DAD is MODEB only.
-- In MODEB, the operand is the address of the quotient,
-- which is possibly pre-incremented before use.
--
when opEAEDAD =>
if EMODE = '0' then
assert false report "stateEAEfetchData: SCA/SCL should not re-dispath here" severity warning;
nextState <= stateLALA;
else
if MA(3 to 11) = maAutoIncr then
--
-- Start the writeback of the incremented data
--
wrOP <= '1';
mbOP <= mbopMDP1;
--XMAOPTBD
--DATAFOP OR IFETCHOP
memselOP <= '1';
nextState <= stateEAEindWrite;
else
--
-- Start address phase of indirect data
--
maOP <= maopMD;
--XMAOPTBD
datafOP <= '1';
memselOP <= '1';
nextState <= stateEAEindReadAddr;
end if;
end if;
--
-- OP 7445: SCA/MUY -
-- DST - Double Precision Store.
--
when opEAEDST =>
if EMODE = '0' then
EAEop <= eaeopMUY;
nextState <= stateEAEmuy;
else
if MA(3 to 11) = maAutoIncr then
--
-- Start the writeback of the incremented data
--
wrOP <= '1';
mbOP <= mbopMDP1;
--XMAOPTBD
--DATAFOP OR IFETCHOP
memselOP <= '1';
nextState <= stateEAEindWrite;
else
--
-- Start address phase of indirect data
--
maOP <= maopMD;
xmaOP <= xmaopDF;
datafOP <= '1';
memselOP <= '1';
nextState <= stateEAEindReadAddr;
end if;
end if;
--
-- OP 7451: DPSZ - Double Precision Skip if Zero
--
when opEAEDPSZ =>
assert false report "stateEAEfetchData: DPSZ should not re-dispatch here" severity warning;
nextState <= stateLALA;
--
-- OP 7453: DPIC - Double Precision Increment
--
when opEAEDPIC =>
assert false report "stateEAEfetchData: DPIC should not re-dispatch here" severity warning;
nextState <= stateLALA;
--
-- OP 7455: DCM - Double Precision Complement.
--
when opEAEDCM =>
assert false report "stateEAEfetchData: DCM should not re-dispatch here" severity warning;
nextState <= stateLALA;
--
-- OP 7457: SAM - Subtract AC from MQ.
--
when opEAESAM =>
assert false report "stateEAEfetchData: SAM should not re-dispatch here" severity warning;
nextState <= stateLALA;
--
-- Everything else.
--
when others =>
assert false report "stateEAEfetchData: Unimplemented EAE case" severity warning;
nextState <= stateDone;
end case;
--
-- statePOPaddr
-- This state increments the stack pointer SP1 or SP2, sets
-- the MA to the incremented value, and performs a Read Addr cycle.
-- MD <- MEM[000'MA]
when statePOPaddr =>
acOP <= acopCLA;
xmaOP <= xmaopCLR;
busOP <= busopRDZFdata;
nextState <= statePOPdata;
--
-- statePOPdata
-- This state completed the read of the top-of-stack and
-- placed the data in the MD. It also cleared AC so that
-- we can add MD to the AC.
-- AC <- MD
--
when statePOPdata =>
acOP <= acopADDMD;
nextState <= stateDone;
--
-- RTN1 Read State
-- The previous state incremented SP1.
-- This state sets up a Read Addr Cycle to the memory location
-- pointed to by SP2.
--
-- If Instructions are being fetched from main memory, the stacks
-- are located in field 0 of main memory. If Instructions are
-- being fetched from panel memory, the stacks are located in field
-- 0 of panel memory, except for the case of a RTN from control
-- panel memory via a RTN1 or RTN2 Instruction. In this case, the
-- main memory stack is accessed by the instruction fetched from
-- panel memory.
--
when stateRTN1 =>
maOP <= maopSP1;
xmaOP <= xmaopCLR;
busOP <= stateRDZFaddr;
nextState <= stateRTNaddr;
--
-- RTN2 Read State
-- The previous state incremented SP2.
-- This state sets up a Read Addr Cycle to the memory location
-- pointed to by SP2.
--
-- If Instructions are being fetched from main memory, the stacks
-- are located in field 0 of main memory. If Instructions are
-- being fetched from panel memory, the stacks are located in field
-- 0 of panel memory, except for the case of a RTN from control
-- panel memory via a RTN1 or RTN2 Instruction. In this case, the
-- main memory stack is accessed by the instruction fetched from
-- panel memory.
--
when stateRTN2 =>
maOP <= maopSP2;
xmaOP <= xmaopCLR;
busOP <= stateRDZFaddr;
nextState <= stateRTNaddr;
--
-- stateRTNaddr
-- The previous state peformed a Read Addr cycle to the top-of-stack.
-- This state sets up a Read Data Cycle.
--
-- If Instructions are being fetched from main memory, the stacks
-- are located in field 0 of main memory. If Instructions are
-- being fetched from panel memory, the stacks are located in field
-- 0 of panel memory, except for the case of a RTN from control
-- panel memory via a RTN1 or RTN2 Instruction. In this case, the
-- main memory stack is accessed by the instruction fetched from
-- panel memory.
--
when stateRTNaddr =>
xmaOP <= xmaopCLR;
busOP <= busopRDZFdata;
nextState <= stateRTNdata;
--
-- stateRTNdata
-- The previous state performed a Read Data Cycle to the
-- top-of-stack.
--
-- The contents of the Instruction Buffer (IB) is loaded into the
-- Instruction Field (IF) register.
--
-- If the Interrupt Inhibit Flip Flop (II) is set, then the Force
-- Zero (FZ) flag is cleared.
--
-- When the PEX Flip-flop is set, the CPU shall exit from Panel
-- Mode to Main Memory (i.e., clear CTRLFF) during the next JMP,
-- JMS, RTN1 or RTN2 instruction.
--
-- PEX is cleared by the JMP, JMS, RTN1 or RTN2 instruction.
--
when stateRTNdata =>
ifOP <= ifopIB;
pcOP <= pcopMD;
if PEX = '1' then
ctrlffOP <= ctrlffopCLR;
pexOP <= pexopCLR;
end if;
if II = '1' then
fzOP <= fzopCLR;
end if;
nextState <= stateDone;
--
-- stateEAEindWrite
-- This state performs an indirect write
--
when stateEAEindWrite =>
maOP <= maopMB;
--XMAOPTBD
datafOP <= '1';
memselOP <= '1';
nextState <= stateEAEindReadAddr;
--
-- stateEAEindReadAddr -
-- The previous state set the MA register to the indirect address.
-- This state handles the address phase of the EAE indirect read cycle.
--
when stateEAEindReadAddr =>
rdOP <= '1';
--XMAOPTBD
datafOP <= '1';
memselOP <= '1';
nextState <= stateEAEindReadData;
--
-- stateEAEindReadData -
-- This state handles the data phase of the EAE indirect read cycle.
-- At the end of this state, the indirect data should be in the MD
-- register. This state then redispatches the MUY, DVI, DAD, and
-- DST instructions. At this point the operand is in the MD register.
--
when stateEAEindReadData =>
EAEIR := IR(6) & IR(8) & IR(9) & IR(10);
case EAEIR is
--
-- MUY - Setup EAE and go to next state.
--
when opEAEMUY =>
eaeOP <= eaeopMUY;
nextState <= stateEAEmuy;
--
-- DVI - Check for overflow right away. If overflow, then
-- set state and exit. Otherwise setup EAE, MQ, SC, and go to
-- next state. The Divisor is in MD.
--
when opEAEDVI =>
--
-- Handle divide overflow condition
--
if AC >= MD then
scOP <= scopCLR;
acOP <= acopCLLCML;
mqOP <= mqopSHL1;
nextState <= stateDone;
--
-- Handle normal divide condition
--
else
mqaOP <= mqaopMQ;
scOP <= scopCLR;
acOP <= acopCLL;
nextState <= stateEAEsubDVI;
end if;
--
-- DAD - Add the contents of MD to MQ.
--
--
when opEAEDAD =>
maOP <= maopINC;
mqOP <= mqopADDMD;
--XMAOPTBD
datafOP <= '1';
memselOP <= '1';
--
-- Handle cases where carry does/doesnot come from MQ
--
if (unsigned('0'& MQ) + unsigned('0' & MD)) > 4095 then
nextState <= stateEAEreadDADaddr1;
else
nextState <= stateEAEreadDADaddr0;
end if;
--
-- DST - Stores the MQ data to MEM[XMA & MA]
--
when opEAEDST =>
wrOP <= '1';
mbOP <= mbopMQ;
--XMAOPTBD
--DATAFOP OR IFETCHOP
memselOP <= '1';
nextState <= stateEAEdst;
--
-- Everything else.
--
when others =>
nextState <= stateLALA;
end case;
--
-- StateEAEshift - This is where all the shift loop for the EAE ASR,
-- LSR, and SHR instructions occurs. On right shifts, bits shifted
-- out of of EAE(24) are shifted into the GTF to facillitate
-- round-off operations. In Mode A, the shift operations complete
-- with SC set to zero. In Mode B the shift operations complete
-- with the SC set to 31.
--
when stateEAEshift =>
EAEIR := IR(6) & IR(8) & IR(9) & IR(10);
if unsigned(SC) = 0 then
if EAEIR = opEAELSR then
acOP <= acopCLL;
end if;
if EMODE = '0' then
scOP <= scopCLR;
else
scOP <= scopSET;
end if;
nextState <= stateDone;
else
case EAEIR is
when opEAELSR =>
if EMODE = '1' then
if MQ(11) = '0' then
gtfOP <= gtfopCLR;
else
gtfOP <= gtfopSET;
end if;
end if;
acOP <= acopLSR;
if AC(11) = '0' then
mqOP <= mqopSHR0;
else
mqOP <= mqopSHR1;
end if;
when opEAEASR =>
if EMODE = '1' then
if MQ(11) = '0' then
gtfOP <= gtfopCLR;
else
gtfOP <= gtfopSET;
end if;
end if;
acOP <= acopASR;
if AC(11) = '0' then
mqOP <= mqopSHR0;
else
mqOP <= mqopSHR1;
end if;
when opEAESHL =>
mqOP <= mqopSHL0;
if MQ(0) = '0' then
acOP <= acopSHL0;
else
acOP <= acopSHL1;
end if;
when others =>
assert false report "stateEAEshift: Not a shift OP" severity warning;
end case;
scOP <= scopDEC;
nextState <= stateEAEwait;
end if;
--
-- stateEAEwait
-- stateEAEshift has a hard time meeting timing. This gives the
-- accumulators a little extra time to settle.
--
when stateEAEwait =>
nextState <= stateEAEshift;
--
-- stateEAEnmi
-- The Step Counter is initially cleared. The contents of the
-- Link, AC, and MQ registers are are shifted left until AC(0) and
-- AC(1) are different or until AC(2) through MQ(11) are all zero.
-- The Step Count register is increment once for every shift. If
-- MODE B, and the contents of AC & MQ is o"4000_0000", the AC is
-- cleared.
--
when stateEAEnmi =>
if (AC(0) /= AC(1)) or (unsigned(AC(2 to 11)) = 0 and unsigned(MQ) = 0) then
if EMODE = '1' and unsigned(AC) = 2048 and unsigned(MQ) = 0 then
acOP <= acopCLA;
end if;
nextState <= stateDone;
else
scOP <= scopINC;
mqOP <= mqopSHL0;
if MQ(0) = '0' then
acOP <= acopSHL0;
else
acOP <= acopSHL1;
end if;
nextState <= stateEAEnmi;
end if;
--
-- The contents of the MQ are multiplied by the multiplier (in the
-- MD) and the MSBs of the 24 bit result are left in the AC and the
-- LSBs are left in the MQ. The multiplication is unsigned. If AC
-- is non-zero, the product is added to AC.
--
when stateEAEmuy =>
acOP <= acopEAEZAC;
mqOP <= mqopEAE;
scOP <= scop12;
nextState <= stateDone;
--
-- stateEAEsubDVI - Long division is a shift and subtract
-- operation. This state handles the subtraction.
-- MQ = (AC & MQ) / MD
-- AC = (AC & MQ) % MD
--
when stateEAEsubDVI =>
if unsigned(LAC) >= unsigned(MD) then
mqOP <= mqopSHL1;
acOP <= acopSUBMD;
else
mqOP <= mqopSHL0;
end if;
scOP <= scopINC;
nextState <= stateEAEshiftDVI;
--
-- stateEAEshiftDVI - Long division is a shift and subtract
-- operation. This state handles the shift operation.
--
when stateEAEshiftDVI =>
--
-- Check for loop exit condtions
--
if unsigned(SC) = 13 then
acOP <= acopCLL;
nextState <= stateDone;
--
-- Shift L, AC, and MQ left
--
else
mqaOP <= mqaopSHL;
if MQA(0) = '0' then
acOP <= acopSHL0;
else
acOP <= acopSHL1;
end if;
nextState <= stateEAEsubDVI;
end if;
--
-- stateEAEreadDADaddr0
-- This is the address phase of the read cycle for the second
-- operand (third word). This state is for cases where there is no
-- carry from the addition of MQ.
--
when stateEAEreadDADaddr0 =>
rdOP <= '1';
acOP <= acopCLL;
--XMAOPTBD
datafOP <= '1';
memselOP <= '1';
nextState <= stateEAEreadDADdata0;
--
-- stateEAEreadDADaddr1
-- This is the address phase of the read cycle for the second
-- operand (third word). This state is for cases where there is a
-- carry from the addition of MQ. Clear the link for the add
-- instruction in the next state.
--
when stateEAEreadDADaddr1 =>
rdOP <= '1';
acOP <= acopCLL;
--XMAOPTBD
datafOP <= '1';
memselOP <= '1';
nextState <= stateEAEreadDADdata1;
--
-- stateEAEreadDADdata0
-- This is the data phase of the read cycle for the second operand
-- (third word). This state is for cases where there is no carry
-- from the addition of MQ. Clear the link for the add instruction
-- in the next state.
--
when stateEAEreadDADdata0 =>
acOP <= acopADDMD;
nextState <= stateDone;
--
-- stateEAEreadDADdata1
-- This is the data phase of the read cycle for the second operand
-- (third word). This state is for cases where there is a carry
-- from the addition of MQ.
--
when stateEAEreadDADdata1 =>
acOP <= acopADDMDP1;
nextState <= stateDone;
--
-- stateEAEdst - This state stores the AC data to MEM[XMA & (MA + 1)]
--
when stateEAEdst =>
wrOP <= '1';
maOP <= maopINC;
mbOP <= mbopAC;
xmaOP <= xmaopDF;
memselOP <= '1';
datafOP <= '1';
nextState <= stateDone;
--
-- Done State
-- This is the last state of the instruction. This wastes a state
-- but makes it easy to 'see' the end of the instruction cycle.
--
when stateDone =>
nextstate <= stateCheckReq;
--
-- You've landed in LA-LA land. You shouldn't get here. Somehow
-- some OPCODE was not decoded correctly or the next state for the
-- State Machine was not set. Plug your ears, close your eyes and
-- scream LA-LA-LA-LA-LA-LA-LA-LA-LA-LA-LA.
--
when stateLALA =>
nextState <= stateLALA;
end case;
end process;
mem : block
begin
--!
--! LXPAR is generated for panel memory accesses: It is asserted when:
--! #. MEMSEL asserted and CPU is HD6120 and Panel Mode and Direct
--! Memory Op with PDF in any state (two cases of CTRLFF).
--! #. MEMSEL asserted and CPU is HD6120 and Panel Mode and Indirect
--! Memory Op with PDF asserted (two cases of CTRLFF).
--!
lxparOP <= '1' when ((memselOP = '1' and swCPU = swHD6120 and CTRLFF = '0' and ctrlffOP = ctrlffopSET and datafOP = '0') or
(memselOP = '1' and swCPU = swHD6120 and CTRLFF = '1' and ctrlffOP /= ctrlffopCLR and datafOP = '0') or
(memselOP = '1' and swCPU = swHD6120 and CTRLFF = '0' and ctrlffOP = ctrlffopSET and datafOP = '1' and PDF = '1') or
(memselOP = '1' and swCPU = swHD6120 and CTRLFF = '1' and ctrlffOP /= ctrlffopCLR and datafOP = '1' and PDF = '1')) else
'0';
--!
--! LXMAR is generated for normal memory accesses. It is asserted when:
--! #. MEMSEL asserted and CPU is HD6120 and Panel Mode and Indirect
--! Memory Op with PDF negated (two cases of CRTLFF).
--! #. MEMSEL asserted and CPU is HD6120 and Normal Mode (two cases of
--! CTRLFF).
--! #. MEMSEL asserted and not HD6120.
--!
lxmarOP <= '1' when ((memselOP = '1' and swCPU = swHD6120 and CTRLFF = '0' and ctrlffOP = ctrlffopSET and datafOP = '1' and PDF = '0') or
(memselOP = '1' and swCPU = swHD6120 and CTRLFF = '1' and ctrlffOP /= ctrlffopCLR and datafOP = '1' and PDF = '0') or
(memselOP = '1' and swCPU = swHD6120 and CTRLFF = '0' and ctrlffOP /= ctrlffopSET) or
(memselOP = '1' and swCPU = swHD6120 and CTRLFF = '1' and ctrlffOP = ctrlffopCLR) or
(memselOP = '1' and swCPU /= swHD6120)) else
'0';
--!
--! Wait for Bus ACK on:
--! #. DMA access
--! #. Memory accesses
--! #. Reads to devices
--! #. Writes to devices
--!
waitfOP <= '1' when ((memselOP = '1') or
(lxdarOP = '1' and rdOP = '1') or
(lxdarOP = '1' and wrOP = '1')) else
'0';
end block;
--!
--! DMA Request.
--! Only start DMA cycle when MEM cycle is unused.
--!
process(sys.clk, sys.rst)
begin
if sys.rst = '1' then
dmagnt <= '0';
elsif rising_edge(sys.clk) then
if dev.dma.req = '1' then
if memselOP = '0' then
dmagnt <= '1';
end if;
else
dmagnt <= '0';
end if;
end if;
end process;
--!
--! State Machine
--! The state only changes when properly ack'd and when not doing DMA.
--!
process(sys.clk, sys.rst)
variable lastdma : std_logic;
-- synthesis translate_off
variable LIN : line;
-- synthesis translate_on
begin
if sys.rst = '1' then
ioclrb <= '1';
wrb <= '0';
rdb <= '0';
ifetchb <= '0';
datafb <= '0';
lxdarb <= '0';
lxmarb <= '0';
lxparb <= '0';
memselb <= '0';
intgntb <= '0';
waitfb <= '0';
lastdma := '0';
state <= stateReset;
elsif rising_edge(sys.clk) then
ioclrb <= '0';
wrb <= '0';
rdb <= '0';
ifetchb <= '0';
datafb <= '0';
lxdarb <= '0';
lxmarb <= lxmarOP;
lxparb <= lxparOP;
memselb <= '0';
if dmagnt = '1' and memselOP = '1' then
null;
else
if waitfb = '0' or dev.ack = '1' then
case busOP is
when busopNOP =>
null;
when busopRESET =>
ioclrb <= '1';
when busopIOCLR =>
ioclrb <= '1';
lxdarb <= '1';
datafb <= '1';
when busopPANELWR =>
wrb <= '1';
memselb <= '1';
when busopPANELRDaddr =>
memselb <= '1';
when busopPANELRDdata =>
rdb <= '1';
memselb <= '1';
when busopFETCHaddr =>
ifetchb <= '1';
memselb <= '1';
when busopFETCHdata =>
rdb <= '1';
ifetchb <= '1';
memselb <= '1';
when busopWRIB =>
wrb <= '1';
memselb <= '1';
when busopRDIBaddr =>
memselb <= '1';
when busopRDIBdata =>
memselb <= '1';
when busopWRIF =>
wrb <= '1';
memselb <= '1';
when busopRDIFaddr =>
memselb <= '1';
when busopRDIFdata =>
rdb <= '1';
memselb <= '1';
when busopWRDF =>
wrb <= '1';
memselb <= '1';
when busopRDDFaddr =>
datafb <= '1';
memselb <= '1';
when busopRDDFdata =>
rdb <= '1';
datafb <= '1';
memselb <= '1';
when busopIOTWR =>
wrb <= '1';
datafb <= '1';
lxdarb <= '1';
when busopIOTRD =>
rdb <= '1';
datafb <= '1';
lxdarb <= '1';
when busopWR0 =>
wrOP <= '1';
memselb <= '1';
when busopWRTBD =>
memselb <= '1';
when busopRDTBDaddr =>
memselb <= '1';
when busopRDTBDdata =>
rdb <= '1';
memselb <= '1';
when others =>
null;
end case;
ioclrb <= ioclrOP;
wrb <= wrOP;
rdb <= rdOP;
ifetchb <= ifetchOP;
datafb <= datafOP;
lxdarb <= lxdarOP;
lxmarb <= lxmarOP;
lxparb <= lxparOP;
memselb <= memselOP;
intgntb <= intgntOP;
waitfb <= waitfOP;
state <= nextState;
end if;
end if;
-- synthesis translate_off
if dmagnt = '1' and lastdma = '0' then
assert false report "-------------> DMA Asserted <------------" severity note;
elsif dmagnt = '0' and lastdma = '1' then
assert false report "-------------> DMA Negated <------------" severity note;
end if;
lastdma := dmagnt;
-- synthesis translate_on
end if;
end process;
-- oops <= '1' when ((xmaOP = xmaopIF and datafOP = '1') or
-- (xmaOP = xmaopDF and datafOP = '0') or
-- (xmaOP /= xmaopIF and memselOP = '1') or
-- (xmaOP /= xmaopDF and memselOP = '1')) else '0';
oops <= '1' when ((busOP = busopRESET and ioclrOP = '0') or -- IOCLR should be set
(busOP = busopIOCLR and ioclrOP = '0') or -- IOCLR should be set
(busOP = busopIOCLR and lxdarOP = '0') or -- LXDAR should be set
(busOP = busopIOCLR and datafOP = '0') or -- DATAF should be set
(busOP = busopFETCHaddr and xmaOP /= xmaopIF) or
(busOP = busopFETCHaddr and ifetchOP = '0') or
(busOP = busopFETCHaddr and memselOP = '0') or
(busOP = busopFETCHdata and xmaOP /= xmaopIF) or
(busOP = busopFETCHdata and ifetchOP = '0') or
(busOP = busopFETCHdata and memselOP = '0') or
(busOP = busopFETCHdata and rdOP = '0') or
(busOP = busopWRIB and xmaOP /= xmaopIB) or
(busOP = busopWRIB and memselOP = '0') or
(busOP = busopWRIB and wrOP = '0') or
(busOP = busopRDIBaddr and xmaOP /= xmaopIB) or
(busOP = busopRDIBaddr and memselOP = '0') or
(busOP = busopRDIBdata and xmaOP /= xmaopIB) or
(busOP = busopRDIBdata and memselOP = '0') or
(busOP = busopRDIBdata and rdOP = '0') or
(busOP = busopWRIF and xmaOP /= xmaopIF) or
(busOP = busopWRIF and memselOP = '0') or
(busOP = busopWRIF and wrOP = '0') or
(busOP = busopRDIFaddr and xmaOP /= xmaopIF) or
(busOP = busopRDIFaddr and memselOP = '0') or
(busOP = busopRDIFdata and xmaOP /= xmaopIF) or
(busOP = busopRDIFdata and memselOP = '0') or
(busOP = busopRDIFdata and rdOP = '0') or
(busOP = busopWRDF and xmaOP /= xmaopDF) or
(busOP = busopWRDF and memselOP = '0') or
(busOP = busopRDDFaddr and datafOP = '0') or
(busOP = busopWRDF and wrOP = '0') or
(busOP = busopRDDFaddr and xmaOP /= xmaopDF) or
(busOP = busopRDDFaddr and memselOP = '0') or
(busOP = busopRDDFaddr and datafOP = '0') or
(busOP = busopRDDFdata and xmaOP /= xmaopDF) or
(busOP = busopRDDFdata and memselOP = '0') or
(busOP = busopRDDFdata and datafOP = '0') or
(busOP = busopRDDFdata and rdOP = '0') or
(busOP = busopWRZF and xmaOP /= xmaopCLR) or
(busOP = busopWRZF and memselOP = '0') or
(busOP = busopWRZF and wrOP = '0') or
(busOP = busopRDZFaddr and xmaOP /= xmaopCLR) or
(busOP = busopRDZFaddr and memselOP = '0') or
(busOP = busopRDZFdata and xmaOP /= xmaopCLR) or
(busOP = busopRDZFdata and memselOP = '0') or
(busOP = busopRDZFdata and rdOP = '0') or
(busOP = busopWRIOT and datafOP = '0') or
(busOP = busopWRIOT and lxdarOP = '0') or
(busOP = busopWRIOT and wrOP = '0') or
(busOP = busopRDIOT and datafOP = '0') or
(busOP = busopRDIOT and lxdarOP = '0') or
(busOP = busopRDIOT and rdOP = '0')) else '0';
--!
--! Externally visable (front panel) register state is only updated at
--! certain times in the instruction cycle.
--!
process(sys.clk, sys.rst)
variable CPC : addr_t;
begin
if sys.rst = '1' then
cpu.regs.PC <= (others => '0');
cpu.regs.AC <= (others => '0');
cpu.regs.IR <= (others => '0');
cpu.regs.MQ <= (others => '0');
cpu.regs.ST <= (others => '0');
cpu.regs.SC <= (others => '0');
cpu.regs.MD <= (others => '0');
cpu.regs.MA <= (others => '0');
cpu.regs.XMA <= (others => '0');
CPC := (others => '0');
elsif rising_edge(sys.clk) then
--
-- Handle reads are writes
--
if lxmarb = '1' then
if rdb = '1' then
cpu.regs.MD <= MD;
elsif wrb = '1' then
cpu.regs.MD <= MB;
end if;
cpu.regs.MA <= MA;
cpu.regs.XMA <= XMA;
end if;
--
-- State-based updates
--
case state is
--
-- Instruction Fetch
--
when stateFetchAddr =>
CPC := PC;
--
-- State Halt Done
--
when stateHaltDone =>
cpu.regs.PC <= PC;
cpu.regs.AC <= AC;
cpu.regs.IR <= IR;
cpu.regs.MA <= MA;
cpu.regs.MQ <= MQ;
cpu.regs.ST <= L & GTF & IRQ & II & ID & UF & INF & DF;
cpu.regs.SC <= "0000000" & SC;
--
-- Last state of instruction
--
when stateDone =>
cpu.regs.PC <= PC;
cpu.regs.AC <= AC;
cpu.regs.IR <= IR;
cpu.regs.MQ <= MQ;
cpu.regs.ST <= L & GTF & IRQ & II & ID & UF & INF & DF;
cpu.regs.SC <= "0000000" & SC;
--dumpState(CPC);
--
-- Anything else?
--
when others =>
null;
end case;
end if;
end process;
--!
--! DMA Bus Switch
--!
process(dmagnt, dev.dma.rd, dev.dma.wr, dev.dma.lxpar, dev.dma.lxmar, dev.dma.memsel,
dev.dma.addr, dev.dma.eaddr, dev.data, rdb, wrb, ifetchb, lxmarb, lxparb,
lxdarb, memselb, datafb, MA, MB, XMA)
begin
if dmagnt = '1' then
cpu.buss.rd <= dev.dma.rd;
cpu.buss.wr <= dev.dma.wr;
cpu.buss.ifetch <= '0';
cpu.buss.dataf <= '0';
cpu.buss.lxmar <= dev.dma.lxmar;
cpu.buss.lxpar <= dev.dma.lxpar;
cpu.buss.lxdar <= '0';
cpu.buss.memsel <= dev.dma.memsel;
cpu.buss.addr <= dev.dma.addr;
cpu.buss.eaddr <= dev.dma.eaddr;
cpu.buss.data <= dev.data;
else
cpu.buss.rd <= rdb;
cpu.buss.wr <= wrb;
cpu.buss.ifetch <= ifetchb;
cpu.buss.dataf <= datafb;
cpu.buss.lxmar <= lxmarb;
cpu.buss.lxpar <= lxparb;
cpu.buss.lxdar <= lxdarb;
cpu.buss.memsel <= memselb;
cpu.buss.addr <= MA;
cpu.buss.eaddr <= XMA;
cpu.buss.data <= MB;
end if;
end process;
--!
--! Data Latch
--!
process(sys.rst, rdb, dev.data, MD)
begin
if sys.rst = '1' then
MD <= (others => '0');
elsif rdb = '1' then
MD <= dev.data;
else
MD <= MD;
end if;
end process;
--!
--! CPU combinational outputs
--!
cpu.buss.ioclr <= ioclrb;
cpu.buss.intgnt <= intgntb;
cpu.buss.dmagnt <= dmagnt;
cpu.run <= '0' when ((state = stateReset ) or
(state = stateInit ) or
(state = stateHalt ) or
(state = stateContinue ) or
(state = stateLoadADDR ) or
(state = stateLoadEXTD ) or
(state = stateClear ) or
(state = stateDepositWriteData ) or
(state = stateDeposit ) or
(state = stateExamine ) or
(state = stateExamineReadAddr ) or
(state = stateExamineReadData ) or
(state = stateHaltDone ) or
(state = stateLALA )) else
'1';
end rtl;