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

Subversion Repositories pdp8

[/] [pdp8/] [trunk/] [pdp8/] [busmux.vhd] - Rev 2

Compare with Previous | Blame | View Log

--------------------------------------------------------------------
--!
--! PDP-8 Processor
--!
--! \brief
--!      PDP8 Bus Multiplexer
--!
--! \details
--!      This package contains the multiplexer that simulates a
--!      bi-directional bus.
--!
--!      External IOTs are different that other bus cycles.  If
--!      an external IOT is not implemented, it behaves like a
--!      no-op.  In order to keep the system from 'hanging' on
--!      a unimplemented IOT, this device start an ACK  Timer
--!      when an external IOT is detected.  If no external device
--!      acknowledges the IOT cycle, the ACK Timer will handle it
--!      when it times out.  The ACK Timer should be set for
--!      longer than the most amount of wait-states for a normal
--!      bus cycle.
--!
--! \todo
--!      DMA Request and DMA Grant logic is incorrect.  This code
--!      assumes the only DMA source is the disk.   The DMA should
--!      be aribrated like everything else.
--!
--! \file
--!      busmux.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 work.cpu_types.all;                         --! CPU Types
 
--
--! PDP8 Bus Multiplexer Entity
--
 
entity eBUSMUX is port (
    sys      : in  sys_t;                       --! Clock / Reset
    cpu      : in  cpu_t;                       --! CPU Registers
    ramDEV   : in  dev_t;                       --! RAM Device
    diskDEV  : in  dev_t;                       --! DISK Disk Device
    tty1DEV  : in  dev_t;                       --! TTY1 Device
    tty2DEV  : in  dev_t;                       --! TTY2 Device
    lprDEV   : in  dev_t;                       --! LPR Device
    ptrDEV   : in  dev_t;                       --! PTR Device
    rtcDEV   : in  dev_t;                       --! Real Time Clock
    xramDEV  : in  dev_t;                       --! External RAM Device
    romDEV   : in  dev_t;                       --! ROM Device
    panelDEV : in  dev_t;                       --! Front Panel Device
    postDEV  : in  dev_t;                       --! POST Device
    mmapDEV  : in  dev_t;                       --! Memory Map Device
    cpuDEV   : out dev_t                        --! CPU Device
);
end eBUSMUX;
 
--
--!  PDP8 Bus Multiplexer RTL
--
 
architecture rtl of eBUSMUX is
 
    type   ackSTATE_t is (idle, run, done);
    signal ackSTATE   : ackSTATE_t;
    signal ackSTART   : std_logic;
    signal ackIOT     : std_logic;
    signal ackTIMER   : integer range 0 to 10;
    signal ackDEV     : std_logic;
    signal muxDEV     : dev_t;
 
begin
 
    --
    --! ACK Timer:
    --! This process will eventually generate a Bus Ack for an
    --! unimplemented internal IOT.
    --
 
    ACK_TIMER : process(sys)
    begin
        if sys.rst = '1' then
            ackTIMER <= 0;
            ackSTATE <= idle;
        elsif rising_edge(sys.clk) then
            case ackSTATE is
                when idle =>
                    if ackSTART = '1' then
                        ackTIMER <= ackTIMER + 1;
                        ackSTATE <= run;
                    else
                        ackTIMER <= 0;
                    end if;
                when run =>
                    if ackDEV = '1' then
                        ackState <= idle;
                    else
                        if ackTIMER = 10 then
                            ackTIMER <= 0;
                            ackSTATE <= done;
                        else
                            ackTIMER <= ackTIMER + 1;
                        end if;
                    end if;
                when done =>
                    ackSTATE <= idle;
                when others =>
                    null;
            end case;
        end if;
    end process ACK_TIMER;
 
    --
    -- ackIOT during last state of state machine
    --
 
    ackIOT       <= '1' when ackSTATE = done else
                    '0';
 
    --
    -- This is the bus multiplexer.  It simulates a bi-directional bus.
    --
 
    muxDEV       <= ramDEV   when ramDEV.ack   = '1' else
                    diskDEV  when diskDEV.ack  = '1' else
                    tty1DEV  when tty1DEV.ack  = '1' else
                    tty2DEV  when tty2DEV.ack  = '1' else
                    lprDEV   when lprDEV.ack   = '1' else
                    ptrDEV   when ptrDEV.ack   = '1' else
                    rtcDEV   when rtcDEV.ack   = '1' else
                    xramDEV  when xramDEV.ack  = '1' else
                    romDEV   when romDEV.ack   = '1' else
                    panelDEV when panelDEV.ack = '1' else
                    postDEV  when postDEV.ack  = '1' else
                    mmapDEV  when mmapDEV.ack  = '1' else
                    nullDEV;
 
    --
    --! Detect External IOTs for ACK timer.
    --
 
    ackSTART     <= '1' when ((cpu.buss.lxdar = '1' and cpu.buss.wr = '1' and muxDEV.ack = '0') or
                              (cpu.buss.lxdar = '1' and cpu.buss.rd = '1' and muxDEV.ack = '0')) else
                    '0';
 
    --
    -- ACK is combinational.  This is the fastest way to
    -- generate an ACK signal.
    --
 
    ackDEV       <= ramDEV.ack  or diskDEV.ack or tty1DEV.ack or tty2DEV.ack or lprDEV.ack   or
                    ptrDEV.ack  or rtcDEV.ack  or xramDEV.ack or romDEV.ack  or panelDEV.ack or
                    postDEV.ack or mmapDEV.ack;
 
    --
    -- Muxed signals.
    --
 
    cpuDEV.ack   <= ackDEV or ackIOT;
    cpuDEV.devc  <= muxDEV.devc;
    cpuDEV.skip  <= muxDEV.skip;
 
    --
    -- INTR  comes from most IO Devices
    -- CPREQ comes from Panel only
    --
 
    cpuDEV.intr  <= diskDEV.intr or tty1DEV.intr or tty2DEV.intr or lprDEV.intr or ptrDEV.intr or rtcDEV.intr;
    cpuDEV.cpreq <= panelDEV.intr;
 
    --
    -- FIXME: This isn't right.  It should arbirtrate, but right
    -- now disk is the only DMA.
    --
 
    cpuDEV.dma   <= diskDEV.dma;
    cpuDEV.data  <= diskDEV.data when cpu.buss.dmagnt = '1' and diskDEV.dma.wr = '1' else
                    muxDEV.data;
 
end rtl;
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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