-------------------------------------------------------------------------------- entity mip_device is port ( RESETn : in std_logic; CLK : in std_logic; -- Local Bus Clock ENABLE : inout std_logic; -- NOT(STATUS(15)) -- Inputs from the Top Level Entity: MIP_CLK : in std_logic; -- Outputs to the MIP Bus (we can read them too): STATUS : inout std_logic_vector(15 downto 0); MBX_W1 : inout std_logic_vector(15 downto 0); MBX_W2 : inout std_logic_vector(15 downto 0); MBX_W3 : inout std_logic_vector(15 downto 0); MBX_W4 : inout std_logic_vector(15 downto 0); -- Inputs from the MIP Bus: CTRL : in std_logic_vector(15 downto 0); MIP_RADDR : in std_logic; MIP_WADDR : in std_logic; BUF_OVERRUN : in std_logic; BUF_RDY : in std_logic; BUF : in mip_buf_t; -- Inputs from the Local Bus: LCS : in std_logic; -- Local Bus Chip Select LALE : in std_logic; -- Local Bus Address Latch Enable LOE : in std_logic; -- Local Bus Output Enable LWE : in std_logic; -- Local Bus Write Enable LADDR : in std_logic_vector(7 downto 0); -- Outputs: IRQn : inout std_logic; IO : inout std_logic_vector(15 downto 0); IRQ_OE : out std_logic; ioout : out std_logic_vector(7 downto 0) ); end mip_device; architecture behav of mip_device is component async_bidir is port ( bidir : inout std_logic_vector(15 downto 0); inp : in std_logic_vector(15 downto 0); outp : out std_logic_vector(15 downto 0); oe_n : in std_logic ); end component; component sync2dff is port ( SIN : in std_logic; CLK : in std_logic; SOUT : out std_logic ); end component; ---------------------------------------------------------------------------- -- Local Signal(s): ---------------------------------------------------------------------------- signal IO_in : std_logic_vector(15 downto 0); signal IO_out : std_logic_vector(15 downto 0); signal mip_clk_s : std_logic := '0'; signal mip_clk_loss : std_logic := '0'; signal mip_clk_loss_det : std_logic := '0'; signal buf_overrun_s : std_logic := '0'; signal buf_overrun_det : std_logic := '0'; signal mip_raddr_s : std_logic := '0'; signal mip_raddr_det : std_logic := '0'; signal mip_waddr_s : std_logic := '0'; signal mip_waddr_det : std_logic := '0'; signal buf_rdy_s : std_logic := '0'; signal buf_rdy_det : std_logic := '0'; begin ---------------------------------------------------------------------------- mip_dev_proc: process( CLK, RESETn ) ------------------------------------------------------------------------ -- local variables ------------------------------------------------------------------------ constant status_addr : std_logic_vector(7 downto 0) := "00100000";-- 32 constant mbx_w1_addr : std_logic_vector(7 downto 0) := "00100001";-- 33 constant mbx_w2_addr : std_logic_vector(7 downto 0) := "00100010";-- 34 constant mbx_w3_addr : std_logic_vector(7 downto 0) := "00100011";-- 35 constant mbx_w4_addr : std_logic_vector(7 downto 0) := "00100100";-- 36 constant ctrl_addr : std_logic_vector(7 downto 0) := "00100101";-- 37 constant status_id : integer := 32; variable mip_ctrl_q : std_logic_vector(15 downto 0) := x"0000"; variable status_q : std_logic_vector(15 downto 0) := x"8000"; variable addr : std_logic_vector(7 downto 0) := "00000000"; variable i : integer range 0 to 255 := 0; variable interrupt : std_logic := '0'; variable buf_dirty : std_logic := '0'; variable msg_dirty : std_logic := '0'; variable msg : mip_buf_t; begin if (RESETn = '0') then for i in 0 to 31 loop msg(i) := x"0000"; end loop; i := 0; addr := "00000000"; ------------------------------- ioout <= status_q(15 downto 8); ------------------------------- status_q := x"8000"; interrupt := '0'; msg_dirty := '0'; buf_dirty := '0'; ENABLE <= '0'; STATUS <= x"8000"; MBX_W1 <= x"0000"; MBX_W2 <= x"0000"; MBX_W3 <= x"0000"; MBX_W4 <= x"0000"; IO_out <= x"0000"; IRQ_OE <= '1'; IRQn <= '1'; mip_clk_loss_det <= '0'; buf_overrun_det <= '0'; buf_rdy_det <= '0'; mip_raddr_det <= '0'; mip_waddr_det <= '0'; elsif rising_edge(CLK) then mip_ctrl_q := CTRL; if (LALE = '1') then addr := LADDR; end if; -------------------------------------------------------------------- -- CPU WRITE -------------------------------------------------------------------- if (LCS = '0') and (LWE = '0') then if (addr = status_addr) then -- Write to the MIP Status Register status_q := IO_in; ENABLE <= not(IO_in(15)); elsif (addr = mbx_w1_addr) then -- Write to the MIP Mailbox Word 1 Register MBX_W1 <= IO_in; elsif (addr = mbx_w2_addr) then -- Write to the MIP Mailbox Word 2 Register MBX_W2 <= IO_in; elsif (addr = mbx_w3_addr) then -- Write to the MIP Mailbox Word 3 Register MBX_W3 <= IO_in; elsif (addr = mbx_w4_addr) then -- Write to the MIP Mailbox Word 4 Register MBX_W4 <= IO_in; else -- Set the Local Bus Write Address Error STATUS Bit (11) status_q(11) := '1'; interrupt := '1'; end if; end if; -- MIP Data Buffer Ready Rising Edge Detection -------------------------------------------------------------------- if (buf_rdy_s = '1') and (buf_rdy_det = '0') then -- Set the MIP Buffer Ready STATUS Bit (5) status_q(5) := '1'; interrupt := '1'; if (msg_dirty = '0') then for i in 0 to 31 loop msg(i) := BUF(i); end loop; msg_dirty := '1'; buf_dirty := '0'; else -- Tell the MIP to hold-off. buf_dirty := '1'; end if; end if; buf_rdy_det <= buf_rdy_s; -- MIP_RADDR (MIP Read Address Error) Rising Edge Detection -------------------------------------------------------------------- if (mip_raddr_s = '1') and (mip_raddr_det = '0') then -- Set the MIP Address Error During Read Cycle STATUS Bit (6) status_q(6) := '1'; interrupt := '1'; end if; mip_raddr_det <= mip_raddr_s; -- MIP_WADDR (MIP Write Address Error) Rising Edge Detection -------------------------------------------------------------------- if (mip_waddr_s = '1') and (mip_waddr_det = '0') then -- Set the MIP Address Error During Write Cycle STATUS Bit (7) status_q(7) := '1'; interrupt := '1'; end if; mip_waddr_det <= mip_waddr_s; -- MIP Bus Clock Loss Rising Edge Detection -------------------------------------------------------------------- if (mip_clk_loss = '1') and (mip_clk_loss_det = '0') then -- Set the MIP BUS Loss of Clock STATUS Bit (8) status_q(8) := '1'; interrupt := '1'; end if; mip_clk_loss_det <= mip_clk_loss; -- MIP Data Buffer Overrun Rising Edge Detection -------------------------------------------------------------------- if (buf_overrun_s = '1') and (buf_overrun_det = '0') then -- Set the MIP Data Buffer Overrun STATUS Bit (9) status_q(9) := '1'; interrupt := '1'; end if; buf_overrun_det <= buf_overrun_s; -------------------------------------------------------------------- -- CPU READ -------------------------------------------------------------------- if (LCS = '0') and (LOE = '0') then if (addr = status_addr) then ------------------------------- ioout <= status_q(15 downto 8); ------------------------------- -- Read the MIP Device Status Register IO_out <= status_q; elsif (addr = mbx_w1_addr) then -- Read the MIP Mailbox Word 1 Register IO_out <= MBX_W1; elsif (addr = mbx_w2_addr) then -- Read the MIP Mailbox Word 2 Register IO_out <= MBX_W2; elsif (addr = mbx_w3_addr) then -- Read the MIP Mailbox Word 3 Register IO_out <= MBX_W3; elsif (addr = mbx_w4_addr) then -- Read the MIP Mailbox Word 4 Register IO_out <= MBX_W4; elsif (addr = ctrl_addr) then -- Read the MIP Control Register IO_out <= mip_ctrl_q; else -- Convert addr to integer for indexing the Data Buffer i := to_integer( unsigned(addr) ); if (i < status_id) then -- Read the Message Buffer IO_out <= msg(i); -- Check for the End Of Message Bit. if (msg(i)(14) = '1') then -- The entire Message has been read. if (buf_dirty = '1') then for i in 0 to 31 loop msg(i) := BUF(i); end loop; msg_dirty := '1'; buf_dirty := '0'; interrupt := '1'; else msg_dirty := '0'; end if; end if; else -- Set the Local Bus Read Address Error STATUS Bit (10) status_q(10) := '1'; interrupt := '1'; IO_out <= x"0000"; end if; end if; end if; -- MIP Status Register READY Bit Logic: -------------------------------------------------------------------- if ( (ENABLE = '0') or ( (msg_dirty = '1') and (buf_dirty = '1') ) ) then status_q(0) := '0'; -- Drop the READY bit. else status_q(0) := '1'; end if; STATUS <= status_q; -------------------------------------------------------------------- if ((ENABLE = '1') and (interrupt = '1')) then -------------------------------------------------------------------- -- Interrupt CPU when status changes: ---------------------------------------------------------------- IRQ_OE <= '0'; -- Interrupt the CPU IRQn <= '0'; interrupt := '0'; else IRQ_OE <= '1'; IRQn <= '1'; -------------------------------------------------------------------- end if; -------------------------------------------------------------------- end if; end process; -- mip_dev_proc ----------------------------------------------------------------------------