This commit is contained in:
631
FalconIO_SDCard_IDE_CF/WF5380/wf5380_control.vhd
Normal file
631
FalconIO_SDCard_IDE_CF/WF5380/wf5380_control.vhd
Normal file
@@ -0,0 +1,631 @@
|
||||
----------------------------------------------------------------------
|
||||
---- ----
|
||||
---- 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 (C) 2009 Wolfgang Foerster ----
|
||||
---- ----
|
||||
---- This source file may be used and distributed without ----
|
||||
---- restriction provided that this copyright statement is not ----
|
||||
---- removed from the file and that any derivative work contains ----
|
||||
---- the original copyright notice and the associated disclaimer. ----
|
||||
---- ----
|
||||
---- This source file is free software; you can redistribute it ----
|
||||
---- and/or modify it under the terms of the GNU Lesser General ----
|
||||
---- Public License as published by the Free Software Foundation; ----
|
||||
---- either version 2.1 of the License, or (at your option) any ----
|
||||
---- later version. ----
|
||||
---- ----
|
||||
---- This source is distributed in the hope that it will be ----
|
||||
---- useful, but WITHOUT ANY WARRANTY; without even the implied ----
|
||||
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ----
|
||||
---- PURPOSE. See the GNU Lesser General Public License for more ----
|
||||
---- details. ----
|
||||
---- ----
|
||||
---- You should have received a copy of the GNU Lesser General ----
|
||||
---- Public License along with this source; if not, download it ----
|
||||
---- from http://www.gnu.org/licenses/lgpl.html ----
|
||||
---- ----
|
||||
----------------------------------------------------------------------
|
||||
--
|
||||
-- Revision History
|
||||
--
|
||||
-- Revision 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;
|
||||
Reference in New Issue
Block a user