614 lines
26 KiB
VHDL
614 lines
26 KiB
VHDL
----------------------------------------------------------------------
|
|
---- ----
|
|
---- WF5380 IP Core ----
|
|
---- ----
|
|
---- Description: ----
|
|
---- This model provides an asynchronous SCSI interface compa- ----
|
|
---- tible to the DP5380 from National Semiconductor and others. ----
|
|
---- ----
|
|
---- This file is the 5380's system controller. ----
|
|
---- ----
|
|
---- ----
|
|
---- Author(s): ----
|
|
---- - Wolfgang Foerster, wf@experiment-s.de; wf@inventronik.de ----
|
|
---- ----
|
|
----------------------------------------------------------------------
|
|
---- ----
|
|
---- Copyright © 2009-2010 Wolfgang Foerster Inventronik GmbH. ----
|
|
---- All rights reserved. No portion of this sourcecode may be ----
|
|
---- reproduced or transmitted in any form by any means, whether ----
|
|
---- by electronic, mechanical, photocopying, recording or ----
|
|
---- otherwise, without my written permission. ----
|
|
---- ----
|
|
----------------------------------------------------------------------
|
|
--
|
|
-- Revision History
|
|
--
|
|
-- Revision 2K9A 2009/06/20 WF
|
|
-- Initial Release.
|
|
--
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.std_logic_unsigned.all;
|
|
|
|
entity WF5380_CONTROL is
|
|
port (
|
|
-- System controls:
|
|
CLK : in bit;
|
|
RESETn : in bit; -- System reset.
|
|
|
|
-- System controls:
|
|
BSY_INn : in bit; -- SCSI BSY_INn bit.
|
|
BSY_OUTn : out bit; -- SCSI BSY_INn bit.
|
|
DATA_EN : out bit; -- Enable the SCSI data lines.
|
|
SEL_INn : in bit; -- SCSI SEL_INn bit.
|
|
ARB_EN : in bit; -- Arbitration enable.
|
|
BSY_DISn : in bit; -- BSY monitoring enable.
|
|
RSTn : in bit; -- SCSI reset.
|
|
|
|
ARB : out bit; -- Arbitration flag.
|
|
AIP : out bit; -- Arbitration in progress flag.
|
|
LA : out bit; -- Lost arbitration flag.
|
|
|
|
ACK_INn : in bit;
|
|
ACK_OUTn : out bit;
|
|
REQ_INn : in bit;
|
|
REQ_OUTn : out bit;
|
|
|
|
DACKn : in bit; -- Data acknowledge.
|
|
READY : out bit;
|
|
DRQ : out bit; -- Data request.
|
|
|
|
TARG : in bit; -- Target mode indicator.
|
|
BLK : in bit; -- Block mode indicator.
|
|
PINT_EN : in bit; -- Parity interrupt enable.
|
|
SPER : in bit; -- Parity error.
|
|
SER_ID : in bit; -- SER matches ODR bits.
|
|
RPI : in bit; -- Reset interrupts.
|
|
DMA_EN : in bit; -- DMA mode enable.
|
|
SDS : in bit; -- Start DMA send, write only.
|
|
SDT : in bit; -- Start DMA target receive, write only.
|
|
SDI : in bit; -- Start DMA initiator receive, write only.
|
|
EOP_EN : in bit; -- EOP interrupt enable.
|
|
EOPn : in bit; -- End of process indicator.
|
|
PHSM : in bit; -- Phase match flag.
|
|
|
|
INT : out bit; -- Interrupt.
|
|
IDR_WR : out bit; -- Write input data register during DMA.
|
|
ODR_WR : out bit; -- Write output data register, during DMA.
|
|
CHK_PAR : out bit; -- Check Parity during DMA operation.
|
|
BSY_ERR : out bit; -- Busy monitoring error.
|
|
DMA_SND : out bit; -- Indicates direction of target DMA.
|
|
DMA_ACTIVE : out bit -- DMA is active.
|
|
);
|
|
end entity WF5380_CONTROL;
|
|
|
|
architecture BEHAVIOUR of WF5380_CONTROL is
|
|
type CTRL_STATES is (IDLE, WAIT_800ns, WAIT_2200ns, DMA_SEND, DMA_TARG_RCV, DMA_INIT_RCV);
|
|
type DMA_STATES is (IDLE, DMA_STEP_1, DMA_STEP_2, DMA_STEP_3, DMA_STEP_4);
|
|
signal CTRL_STATE : CTRL_STATES;
|
|
signal NEXT_CTRL_STATE : CTRL_STATES;
|
|
signal DMA_STATE : DMA_STATES;
|
|
signal NEXT_DMA_STATE : DMA_STATES;
|
|
signal BUS_FREE : bit;
|
|
signal DELAY_800ns : boolean;
|
|
signal DELAY_2200ns : boolean;
|
|
signal DMA_ACTIVE_I : bit;
|
|
signal EOP_In : bit;
|
|
begin
|
|
IN_BUFFER: process
|
|
-- This buffer shall prevent some signals against
|
|
-- setup hold effects and thus the state machine
|
|
-- against unpredictable behaviour.
|
|
begin
|
|
wait until CLK = '1' and CLK' event;
|
|
EOP_In <= EOPn;
|
|
end process IN_BUFFER;
|
|
|
|
STATE_REGISTERS: process(RESETn, CLK)
|
|
-- This is the controller's state machine register.
|
|
variable BSY_LOCK : boolean;
|
|
begin
|
|
if RESETn = '0' then
|
|
CTRL_STATE <= IDLE;
|
|
DMA_STATE <= IDLE;
|
|
elsif CLK = '1' and CLK' event then
|
|
if RSTn = '0' then -- SCSI reset.
|
|
CTRL_STATE <= IDLE;
|
|
DMA_STATE <= IDLE;
|
|
else
|
|
CTRL_STATE <= NEXT_CTRL_STATE;
|
|
DMA_STATE <= NEXT_DMA_STATE;
|
|
end if;
|
|
--
|
|
if DMA_EN = '0' then
|
|
DMA_STATE <= IDLE;
|
|
end if;
|
|
end if;
|
|
end process STATE_REGISTERS;
|
|
|
|
CTRL_DECODER: process(CTRL_STATE, ARB_EN, BUS_FREE, DELAY_800ns, SEL_INn, DMA_ACTIVE_I, SDS, SDT, SDI)
|
|
-- This is the controller's state machine decoder.
|
|
variable BSY_LOCK : boolean;
|
|
begin
|
|
-- Defaults.
|
|
DMA_SND <= '0';
|
|
--
|
|
case CTRL_STATE is
|
|
when IDLE =>
|
|
if ARB_EN = '1' and BUS_FREE = '1' then
|
|
NEXT_CTRL_STATE <= WAIT_800ns;
|
|
else
|
|
NEXT_CTRL_STATE <= IDLE;
|
|
end if;
|
|
when WAIT_800ns =>
|
|
if DELAY_800ns = true then
|
|
NEXT_CTRL_STATE <= WAIT_2200ns;
|
|
else
|
|
NEXT_CTRL_STATE <= WAIT_800ns;
|
|
end if;
|
|
when WAIT_2200ns =>
|
|
-- In this state the delay is provided by the
|
|
-- microprocessor and is at least 2.2us. The
|
|
-- delay is released by deasserting SELn.
|
|
if SEL_INn = '1' and SDS = '1' then
|
|
NEXT_CTRL_STATE <= DMA_SEND;
|
|
elsif SEL_INn = '1' and SDT = '1' then
|
|
NEXT_CTRL_STATE <= DMA_TARG_RCV;
|
|
elsif SEL_INn = '1' and SDI = '1' then
|
|
NEXT_CTRL_STATE <= DMA_INIT_RCV;
|
|
else
|
|
NEXT_CTRL_STATE <= WAIT_2200ns;
|
|
end if;
|
|
when DMA_SEND =>
|
|
if DMA_ACTIVE_I = '0' then
|
|
NEXT_CTRL_STATE <= IDLE;
|
|
else
|
|
NEXT_CTRL_STATE <= DMA_SEND;
|
|
end if;
|
|
--
|
|
DMA_SND <= '1';
|
|
when DMA_TARG_RCV =>
|
|
if DMA_ACTIVE_I = '0' then
|
|
NEXT_CTRL_STATE <= IDLE;
|
|
else
|
|
NEXT_CTRL_STATE <= DMA_TARG_RCV;
|
|
end if;
|
|
when DMA_INIT_RCV =>
|
|
if DMA_ACTIVE_I = '0' then
|
|
NEXT_CTRL_STATE <= IDLE;
|
|
else
|
|
NEXT_CTRL_STATE <= DMA_INIT_RCV;
|
|
end if;
|
|
end case;
|
|
end process CTRL_DECODER;
|
|
|
|
DMA_DECODER: process(CTRL_STATE, DMA_STATE, TARG, BLK, DACKn, REQ_INn, ACK_INn)
|
|
-- This is the DMA state machine decoder.
|
|
begin
|
|
-- Defaults:
|
|
IDR_WR <= '0';
|
|
ODR_WR <= '0';
|
|
CHK_PAR <= '0';
|
|
--
|
|
case DMA_STATE is
|
|
when IDLE =>
|
|
if CTRL_STATE = DMA_SEND then
|
|
NEXT_DMA_STATE <= DMA_STEP_1;
|
|
elsif CTRL_STATE = DMA_INIT_RCV then
|
|
NEXT_DMA_STATE <= DMA_STEP_1;
|
|
elsif CTRL_STATE = DMA_TARG_RCV then
|
|
NEXT_DMA_STATE <= DMA_STEP_1;
|
|
else
|
|
NEXT_DMA_STATE <= IDLE;
|
|
end if;
|
|
when DMA_STEP_1 =>
|
|
-- Initiator modes:
|
|
if CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '0' and DACKn = '0' then
|
|
NEXT_DMA_STATE <= DMA_STEP_2; -- Wait for DACKn asserted.
|
|
ODR_WR <= '1';
|
|
elsif CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '1' and DACKn = '0' then
|
|
NEXT_DMA_STATE <= DMA_STEP_2; -- Wait for DACKn asserted.
|
|
ODR_WR <= '1';
|
|
elsif CTRL_STATE = DMA_INIT_RCV and BLK = '0' and REQ_INn = '0' then
|
|
NEXT_DMA_STATE <= DMA_STEP_2; -- Wait for REQn asserted.
|
|
IDR_WR <= '1';
|
|
elsif CTRL_STATE = DMA_INIT_RCV and BLK = '1' and REQ_INn = '0' then
|
|
NEXT_DMA_STATE <= DMA_STEP_2; -- Wait for REQn asserted.
|
|
IDR_WR <= '1';
|
|
-- Target modes:
|
|
elsif CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '0' and DACKn = '0' then
|
|
NEXT_DMA_STATE <= DMA_STEP_2; -- Wait for DACKn asserted.
|
|
ODR_WR <= '1';
|
|
elsif CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '1' and DACKn = '0' then
|
|
NEXT_DMA_STATE <= DMA_STEP_2; -- Wait for DACKn asserted.
|
|
ODR_WR <= '1';
|
|
elsif CTRL_STATE = DMA_TARG_RCV and BLK = '0' and ACK_INn = '0' then
|
|
NEXT_DMA_STATE <= DMA_STEP_2; -- Wait for ACKn asserted.
|
|
IDR_WR <= '1';
|
|
elsif CTRL_STATE = DMA_TARG_RCV and BLK = '1' and ACK_INn = '0' then
|
|
NEXT_DMA_STATE <= DMA_STEP_2; -- Wait for ACKn asserted.
|
|
IDR_WR <= '1';
|
|
else
|
|
NEXT_DMA_STATE <= DMA_STEP_1;
|
|
end if;
|
|
when DMA_STEP_2 =>
|
|
-- Initiator modes:
|
|
if CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '0' and DACKn = '1' then
|
|
NEXT_DMA_STATE <= DMA_STEP_3; -- Wait for DACKn deasserted.
|
|
elsif CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '1' and DACKn = '1' then
|
|
NEXT_DMA_STATE <= DMA_STEP_3; -- Wait for DACKn deasserted.
|
|
elsif CTRL_STATE = DMA_INIT_RCV and BLK = '0' and REQ_INn = '1' then
|
|
NEXT_DMA_STATE <= DMA_STEP_3; -- Wait for REQn deasserted.
|
|
elsif CTRL_STATE = DMA_INIT_RCV and BLK = '1' and REQ_INn = '1' then
|
|
NEXT_DMA_STATE <= DMA_STEP_3; -- Wait for REQn deasserted.
|
|
-- Target modes:
|
|
elsif CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '0' and DACKn = '1' then
|
|
NEXT_DMA_STATE <= DMA_STEP_3; -- Wait for DACKn deasserted.
|
|
elsif CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '1' and DACKn = '1' then
|
|
NEXT_DMA_STATE <= DMA_STEP_3; -- Wait for DACKn deasserted.
|
|
elsif CTRL_STATE = DMA_TARG_RCV and BLK = '0' and ACK_INn = '1' then
|
|
NEXT_DMA_STATE <= DMA_STEP_3; -- Wait for ACKn deasserted.
|
|
elsif CTRL_STATE = DMA_TARG_RCV and BLK = '1' and ACK_INn = '1' then
|
|
NEXT_DMA_STATE <= DMA_STEP_3; -- Wait for ACKn deasserted.
|
|
else
|
|
NEXT_DMA_STATE <= DMA_STEP_2;
|
|
end if;
|
|
when DMA_STEP_3 =>
|
|
-- Initiator modes:
|
|
if CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '0' and REQ_INn = '0' then
|
|
NEXT_DMA_STATE <= DMA_STEP_4; -- Wait REQn asserted.
|
|
elsif CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '1' and REQ_INn = '0' then
|
|
NEXT_DMA_STATE <= DMA_STEP_4; -- Wait REQn asserted.
|
|
elsif CTRL_STATE = DMA_INIT_RCV and BLK = '0' and DACKn = '0' then
|
|
NEXT_DMA_STATE <= DMA_STEP_4; -- Wait DACKn asserted.
|
|
CHK_PAR <= '1';
|
|
elsif CTRL_STATE = DMA_INIT_RCV and BLK = '1' and DACKn = '0' then
|
|
NEXT_DMA_STATE <= DMA_STEP_4; -- Wait DACKn asserted.
|
|
CHK_PAR <= '1';
|
|
-- Target modes:
|
|
elsif CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '0' and ACK_INn = '0' then
|
|
NEXT_DMA_STATE <= DMA_STEP_4; -- Wait ACKn asserted.
|
|
elsif CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '1' and ACK_INn = '0' then
|
|
NEXT_DMA_STATE <= DMA_STEP_4; -- Wait ACKn asserted.
|
|
elsif CTRL_STATE = DMA_TARG_RCV and BLK = '0' and DACKn = '0' then
|
|
NEXT_DMA_STATE <= DMA_STEP_4; -- Wait DACKn asserted.
|
|
CHK_PAR <= '1';
|
|
elsif CTRL_STATE = DMA_TARG_RCV and BLK = '1' and DACKn = '0' then
|
|
NEXT_DMA_STATE <= DMA_STEP_4; -- Wait DACKn asserted.
|
|
CHK_PAR <= '1';
|
|
else
|
|
NEXT_DMA_STATE <= DMA_STEP_3;
|
|
end if;
|
|
when DMA_STEP_4 =>
|
|
-- Initiator modes:
|
|
if CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '0' and REQ_INn = '1' then
|
|
NEXT_DMA_STATE <= DMA_STEP_1; -- Wait REQn deasserted.
|
|
elsif CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '1' and REQ_INn = '1' then
|
|
NEXT_DMA_STATE <= DMA_STEP_1; -- Wait REQn deasserted.
|
|
elsif CTRL_STATE = DMA_INIT_RCV and BLK = '0' and DACKn = '1' then
|
|
NEXT_DMA_STATE <= DMA_STEP_1; -- Wait DACKn deasserted.
|
|
elsif CTRL_STATE = DMA_INIT_RCV and BLK = '1' and DACKn = '1' then
|
|
NEXT_DMA_STATE <= DMA_STEP_1; -- Wait DACKn deasserted.
|
|
-- Target modes:
|
|
elsif CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '0' and ACK_INn = '1' then
|
|
NEXT_DMA_STATE <= DMA_STEP_1; -- Wait ACKn deasserted.
|
|
elsif CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '1' and ACK_INn = '1' then
|
|
NEXT_DMA_STATE <= DMA_STEP_1; -- Wait ACKn deasserted.
|
|
elsif CTRL_STATE = DMA_TARG_RCV and BLK = '0' and DACKn = '1' then
|
|
NEXT_DMA_STATE <= DMA_STEP_1; -- Wait DACKn deasserted.
|
|
elsif CTRL_STATE = DMA_TARG_RCV and BLK = '1' and DACKn = '1' then
|
|
NEXT_DMA_STATE <= DMA_STEP_1; -- Wait DACKn deasserted.
|
|
else
|
|
NEXT_DMA_STATE <= DMA_STEP_4;
|
|
end if;
|
|
end case;
|
|
end process DMA_DECODER;
|
|
|
|
P_REQn: process(DMA_STATE, CTRL_STATE, TARG, BLK)
|
|
-- This logic controls the REQn output in target mode.
|
|
begin
|
|
if DMA_STATE = DMA_STEP_1 and CTRL_STATE = DMA_TARG_RCV and BLK = '0' then
|
|
REQ_OUTn <= '0';
|
|
elsif DMA_STATE = DMA_STEP_1 and CTRL_STATE = DMA_TARG_RCV and BLK = '1' then
|
|
REQ_OUTn <= '0';
|
|
elsif DMA_STATE = DMA_STEP_3 and CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '0' then
|
|
REQ_OUTn <= '0';
|
|
elsif DMA_STATE = DMA_STEP_3 and CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '1' then
|
|
REQ_OUTn <= '0';
|
|
else
|
|
REQ_OUTn <= '1';
|
|
end if;
|
|
end process P_REQn;
|
|
|
|
P_ACKn: process(DMA_STATE, CTRL_STATE, TARG, BLK)
|
|
-- This logic controls the ACKn output in initiator mode.
|
|
begin
|
|
if DMA_STATE = DMA_STEP_2 and CTRL_STATE = DMA_INIT_RCV and BLK = '0' then
|
|
ACK_OUTn <= '0';
|
|
elsif DMA_STATE = DMA_STEP_2 and CTRL_STATE = DMA_INIT_RCV and BLK = '1' then
|
|
ACK_OUTn <= '0';
|
|
elsif DMA_STATE = DMA_STEP_4 and CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '0' then
|
|
ACK_OUTn <= '0';
|
|
elsif DMA_STATE = DMA_STEP_4 and CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '1' then
|
|
ACK_OUTn <= '0';
|
|
else
|
|
ACK_OUTn <= '1';
|
|
end if;
|
|
end process P_ACKn;
|
|
|
|
P_READY: process(DMA_STATE, CTRL_STATE, TARG, BLK)
|
|
-- This logic controls the READY output in initiator and target block mode.
|
|
begin
|
|
if DMA_STATE = DMA_STEP_1 and CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '1' then
|
|
READY <= '1';
|
|
elsif DMA_STATE = DMA_STEP_1 and CTRL_STATE = DMA_TARG_RCV and BLK = '1' then
|
|
READY <= '1';
|
|
elsif DMA_STATE = DMA_STEP_3 and CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '1' then
|
|
READY <= '1';
|
|
elsif DMA_STATE = DMA_STEP_3 and CTRL_STATE = DMA_INIT_RCV and BLK = '1' then
|
|
READY <= '1';
|
|
else
|
|
READY <= '0';
|
|
end if;
|
|
end process P_READY;
|
|
|
|
P_DRQ: process(RESETn, CLK)
|
|
-- This flip flop controls the DRQ flag during all initiator and all target modes
|
|
-- for both block mode and non block mode operation.
|
|
variable LOCK : boolean;
|
|
begin
|
|
if RESETn = '0' then
|
|
DRQ <= '0';
|
|
LOCK := false;
|
|
elsif CLK = '1' and CLK' event then
|
|
-- Initiator modes:
|
|
if DMA_STATE = DMA_STEP_1 and CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '0' then
|
|
DRQ <= '1';
|
|
elsif DMA_STATE = DMA_STEP_1 and CTRL_STATE = DMA_SEND and TARG = '0' and BLK = '1' and LOCK = false then
|
|
DRQ <= '1';
|
|
LOCK := true;
|
|
elsif DMA_STATE = DMA_STEP_3 and CTRL_STATE = DMA_INIT_RCV and BLK = '0' then
|
|
DRQ <= '1';
|
|
elsif DMA_STATE = DMA_STEP_3 and CTRL_STATE = DMA_INIT_RCV and BLK = '1' then
|
|
DRQ <= '1';
|
|
LOCK := true;
|
|
-- Target modes:
|
|
elsif DMA_STATE = DMA_STEP_3 and CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '0' then
|
|
DRQ <= '1';
|
|
elsif DMA_STATE = DMA_STEP_3 and CTRL_STATE = DMA_SEND and TARG = '1' and BLK = '1' then
|
|
DRQ <= '1';
|
|
LOCK := true;
|
|
elsif DMA_STATE = DMA_STEP_1 and CTRL_STATE = DMA_TARG_RCV and BLK = '0' then
|
|
DRQ <= '1';
|
|
elsif DMA_STATE = DMA_STEP_1 and CTRL_STATE = DMA_TARG_RCV and BLK = '1' then
|
|
DRQ <= '1';
|
|
LOCK := true;
|
|
elsif DACKn = '0' and LOCK = false then
|
|
DRQ <= '0';
|
|
elsif EOPn = '0' and DACKn = '0' then
|
|
DRQ <= '0';
|
|
LOCK := false;
|
|
end if;
|
|
end if;
|
|
end process P_DRQ;
|
|
|
|
P_BUSFREE: process(RESETn, CLK)
|
|
-- This is the logic for the bus free signal.
|
|
-- A bus free is valid if the BSY_INn signal is
|
|
-- at least 437.5ns inactive ans SEL_INn is inactive.
|
|
-- The delay are 7 clock cycles of 16MHz.
|
|
variable TMP : std_logic_vector(2 downto 0);
|
|
begin
|
|
if RESETn = '0' then
|
|
BUS_FREE <= '0';
|
|
TMP := "000";
|
|
elsif CLK = '1' and CLK' event then
|
|
if BSY_INn = '1' and TMP < x"111" then
|
|
TMP := TMP + '1';
|
|
elsif BSY_INn = '0' then
|
|
TMP := "000";
|
|
end if;
|
|
--
|
|
if RSTn = '0' then -- SCSI reset.
|
|
BUS_FREE <= '0';
|
|
elsif SEL_INn = '1' and TMP = "111" then
|
|
BUS_FREE <= '1';
|
|
else
|
|
BUS_FREE <= '0';
|
|
end if;
|
|
end if;
|
|
end process P_BUSFREE;
|
|
|
|
DELAY_800: process(RESETn, CLK)
|
|
-- This is the delay of 812.5ns.
|
|
-- It is derived from 13 16MHz clock cycles.
|
|
variable TMP : std_logic_vector(3 downto 0);
|
|
begin
|
|
if RESETn = '0' then
|
|
DELAY_800ns <= false;
|
|
TMP := x"0";
|
|
elsif CLK = '1' and CLK' event then
|
|
if CTRL_STATE /= WAIT_800ns then
|
|
TMP := x"0";
|
|
elsif TMP <= x"D" then
|
|
TMP := TMP + '1';
|
|
end if;
|
|
--
|
|
if TMP = x"D" then
|
|
DELAY_800ns <= true;
|
|
else
|
|
DELAY_800ns <= false;
|
|
end if;
|
|
end if;
|
|
end process DELAY_800;
|
|
|
|
P_ARB: process(RESETn, CLK)
|
|
-- This flip flop controls the ARB flag read back
|
|
-- by the microcontroller.
|
|
begin
|
|
if RESETn = '0' then
|
|
ARB <= '0';
|
|
elsif CLK = '1' and CLK' event then
|
|
if CTRL_STATE /= WAIT_800ns and NEXT_CTRL_STATE = WAIT_800ns then
|
|
ARB <= '1';
|
|
elsif ARB_EN = '0' then
|
|
ARB <= '0';
|
|
end if;
|
|
end if;
|
|
end process P_ARB;
|
|
|
|
P_AIP: process(RESETn, CLK)
|
|
-- This flip flop controls the AIP flag read back
|
|
-- by the microcontroller.
|
|
begin
|
|
if RESETn = '0' then
|
|
AIP <= '0';
|
|
elsif CLK = '1' and CLK' event then
|
|
if CTRL_STATE = WAIT_800ns and NEXT_CTRL_STATE /= WAIT_800ns then
|
|
AIP <= '1';
|
|
elsif ARB_EN = '0' then
|
|
AIP <= '0';
|
|
end if;
|
|
end if;
|
|
end process P_AIP;
|
|
|
|
P_BSY: process
|
|
-- This flip flop controls the BSYn output
|
|
-- to the SCSI bus.
|
|
begin
|
|
wait until CLK = '1' and CLK' event;
|
|
if RESETn = '0' then
|
|
BSY_OUTn <= '1';
|
|
elsif CTRL_STATE = WAIT_800ns and NEXT_CTRL_STATE /= WAIT_800ns then
|
|
BSY_OUTn <= '0';
|
|
elsif ARB_EN = '0' then
|
|
BSY_OUTn <= '1';
|
|
end if;
|
|
end process P_BSY;
|
|
|
|
P_DATA_EN: process(RESETn, CLK)
|
|
-- This flip flop controls the data enable
|
|
-- of the SCSI bus.
|
|
begin
|
|
if RESETn = '0' then
|
|
DATA_EN <= '0';
|
|
elsif CLK = '1' and CLK' event then
|
|
if CTRL_STATE = WAIT_800ns and NEXT_CTRL_STATE /= WAIT_800ns then
|
|
DATA_EN <= '1';
|
|
elsif ARB_EN = '0' then
|
|
DATA_EN <= '0';
|
|
end if;
|
|
end if;
|
|
end process P_DATA_EN;
|
|
|
|
P_LA: process(RESETn, CLK)
|
|
-- This flip flop controls the LA
|
|
-- (lost arbitration) flag.
|
|
begin
|
|
if RESETn = '0' then
|
|
LA <= '0';
|
|
elsif CLK = '1' and CLK' event then
|
|
if (CTRL_STATE = WAIT_800ns or CTRL_STATE = WAIT_2200ns) and SEL_INn = '0' then
|
|
LA <= '1';
|
|
elsif ARB_EN = '0' then
|
|
LA <= '0';
|
|
end if;
|
|
end if;
|
|
end process P_LA;
|
|
|
|
P_DMA_ACTIVE: process(RESETn, CLK, DMA_ACTIVE_I)
|
|
-- This is the Flip Flop indicating if there is DMA
|
|
-- operation.
|
|
begin
|
|
if RESETn = '0' then
|
|
DMA_ACTIVE_I <= '0';
|
|
elsif CLK = '1' and CLK' event then
|
|
if DMA_EN = '1' and SDS = '1' then
|
|
DMA_ACTIVE_I <= '1'; -- Start DMA send.
|
|
elsif DMA_EN = '1' and SDT = '1' then
|
|
DMA_ACTIVE_I <= '1'; -- Start DMA target receive.
|
|
elsif DMA_EN = '1' and SDI = '1' then
|
|
DMA_ACTIVE_I <= '1'; -- Start DMA initiator receive.
|
|
elsif DMA_EN = '0' then
|
|
DMA_ACTIVE_I <= '0'; -- Halt DMA via DMA flag in MR2.
|
|
elsif EOP_In = '0' then
|
|
DMA_ACTIVE_I <= '0'; -- Halt DMA via EOPn.
|
|
elsif PHSM = '0' then
|
|
DMA_ACTIVE_I <= '0'; -- Halt DMA via phase mismatch.
|
|
end if;
|
|
end if;
|
|
--
|
|
DMA_ACTIVE <= DMA_ACTIVE_I;
|
|
end process P_DMA_ACTIVE;
|
|
|
|
INTERRUPTS: process(RESETn, CLK)
|
|
-- This is the logic for all DP5380's interrupt sources.
|
|
-- A busy interrupt occurs if the BSY_INn signal is at
|
|
-- least 437.5ns inactive. The delay are 7 clock cycles
|
|
-- of 16MHz. This logic also provides the respective
|
|
-- error flags for the BSR.
|
|
variable TMP : std_logic_vector(2 downto 0);
|
|
begin
|
|
if RESETn = '0' then
|
|
INT <= '0';
|
|
BSY_ERR <= '0';
|
|
TMP := "000";
|
|
elsif CLK = '1' and CLK' event then
|
|
if SPER = '1' and PINT_EN = '1' then
|
|
INT <= '1'; -- Parity interrupt.
|
|
elsif RPI = '0' then -- Reset interrupts.
|
|
INT <= '0';
|
|
end if;
|
|
--
|
|
if EOP_In = '0' and CTRL_STATE = DMA_SEND then
|
|
BSY_ERR <= '1'; -- End of DMA error.
|
|
elsif EOP_In = '0' and CTRL_STATE = DMA_TARG_RCV then
|
|
BSY_ERR <= '1'; -- End of DMA error.
|
|
elsif EOP_In = '0' and CTRL_STATE = DMA_INIT_RCV then
|
|
BSY_ERR <= '1'; -- End of DMA error.
|
|
elsif DMA_EN = '0' then -- Reset error.
|
|
INT <= '0';
|
|
end if;
|
|
--
|
|
if EOP_EN = '1' and EOP_In = '0' and CTRL_STATE = DMA_SEND then
|
|
INT <= '1'; -- End of DMA interrupt.
|
|
elsif EOP_EN = '1' and EOP_In = '0' and CTRL_STATE = DMA_TARG_RCV then
|
|
INT <= '1'; -- End of DMA interrupt.
|
|
elsif EOP_EN = '1' and EOP_In = '0' and CTRL_STATE = DMA_INIT_RCV then
|
|
INT <= '1'; -- End of DMA interrupt.
|
|
elsif DMA_EN = '0' then -- Reset interrupt.
|
|
INT <= '0';
|
|
end if;
|
|
|
|
--
|
|
if PHSM = '0' then
|
|
INT <= '1'; -- Phase mismatch interrupt.
|
|
elsif DMA_EN = '0' then -- Reset interrupts.
|
|
INT <= '0';
|
|
end if;
|
|
--
|
|
if SEL_INn = '0' and BSY_INn = '1' and SER_ID = '1' then
|
|
INT <= '1'; -- (Re)Selection interrupt.
|
|
elsif RPI = '1' then -- Reset interrupts.
|
|
INT <= '0';
|
|
end if;
|
|
--
|
|
if BSY_INn = '1' and TMP < x"111" then
|
|
TMP := TMP + '1'; -- Bus settle delay.
|
|
elsif BSY_INn = '0' then
|
|
TMP := "000";
|
|
end if;
|
|
--
|
|
if BSY_DISn = '1' and BSY_INn = '1' and TMP = x"111" then
|
|
INT <= '1'; -- Busy monitoring interrupt.
|
|
BSY_ERR <= '1';
|
|
elsif RPI = '1' then -- Reset interrupts.
|
|
INT <= '0';
|
|
BSY_ERR <= '0';
|
|
end if;
|
|
--
|
|
end if;
|
|
end process INTERRUPTS;
|
|
end BEHAVIOUR; |