The Digilent Communications Interface DLL, dpcutil.dll, provides a set of API functions for applications
programs running on a Microsoft Windows based computer to exchange data with logic implemented
in a Digilent system board. Various Digilent applications programs, such as Transport component of
the Adept Suite, depend on the data interchange API functions in dpcutil. The operation of these
functions depends on the presence of a Digilent communications subsystem component running the
appropriate firmware and the implementation of the appropriate interface logic in the gate array. This
document describes the functional requirements of the communications interface logic and provides a
sample implementation.
The logic described in this document implements are set of registers in the gate array. An application
on the host PC exchanges data with the design in the gate array by reading or writing these registers.
Digilent Communications Interface modules implement the interface described in this document to
control the reading and writing of these registers.
Functional Description
The Digilent Port Interface is patterned after the EPP mode of the parallel port interface on an IBM PC
type computer. This interface provides an 8 bit bi-directional parallel data bus and six handshaking
lines to control the data transfer. The actual data transfer speed that can be achieved depends on the
particular communications subsystem and firmware version being used.
The parallel port interface is made up of an eight bit wide address register and a set of eight bit wide
data registers. The address register holds the address of the data register currently being accessed.
Access to the registers is accomplished via transfer cycles. The four types of transfer cycles allowed
are: address read, address write, data read, and data write. Address read and address write cycles
read from or write to the address register. Data read and data write cycles read or write the data
register whose address is currently held in the address register.
The address register can be implemented with any number of bits up to the maximum size of eight
bits. Since the maximum size of the address register is eight bits, the maximum number of data
registers that can be implemented is 256. It isn’t necessary to implement all 256 possible data
registers. Only the registers needed for a particular application need to be implemented. It is
necessary for the application program using the interface to know which data registers are
implemented and what functions the implemented data registers perform.
Signal Descriptions
In the following description, the term host represents the host PC running the dpcutil application.
Signals sourced by the host are generated by the Digilent communication interface and are inputs to
the logic in the gate array. The term peripheral refers to the logic implemented in the gate array of the
system board. Signals sourced by the peripheral are outputs from the logic implemented in the gate
array.
The following signals make up the interface:
Name Source Description
DB0 – DB7 bidir Data bus. The host is the source during write cycles and the
peripheral is the source during read cycles.
WRITE host Transfer direction control. High = read, Low = write
Copyright Digilent, Inc. 11 pages Doc: 560-000
Digilent Parallel Interface Model Digilent, Inc.
ASTB host Address strobe. Causes data to be read or written to the address
register
DSTB host Data strobe. Causes data to be read or written to a data register
WAIT peripheral Synchronization signal used to indicate when the peripheral is
read to accept data or has data available.
INT peripheral Interrupt. Used by the peripheral to interrupt the host to request
service. Not used by all Digilent communications subsystems.
RESET host Reset. Allows host to reset logic in the peripheral. Not currently
used by all Digilent communications subsystems.
Transfers from the host to the peripheral or from the peripheral to the host are accomplished using
one of four transfer bus cycles. The four possible bus cycles are: Address Read, Address Write, Data
Read, Data Write. The direction of the data transfer is controlled by the WRITE signal. If WRITE is
high (indicating a READ cycle) the peripheral is the source of the data and drives its data onto the
bidirectional data bus at the appropriate time in the cycle. If WRITE is low (indicating a WR ITE cycle)
the host is the source of the data and drives its data onto the bidirectional data bus. It is extremely
important that the peripheral logic in the gate array not drive data onto the data bus except during a
READ cycle. If the data bus is driven by the peripheral at incorrect times, it is possible to create bus
contention that can damage either the gate array or the communications subsystem. All bus cycles
are initiated and controlled by the host.
The WAIT signal is used to synchronize transfers between the host and the peripheral. The host will
not begin a transfer unless the wait signal is low. Once the host begins a bus cycle, it will hold the
strobe (either ASTB or DSTB) in the active state (prolonging the bus cycle) until WAIT goes high.
WAIT going high signals that the peripheral has completed its processing of the cycle. The host will
then bring the strobe to the inactive state completing the bus cycle. The peripheral then brings WAIT
low when it is ready for another transfer to begin.
Timing Diagrams
The following diagrams illustrate the signal timing for the various transfer cycles. For write
cycles, the rising edge of the strobe signal (ASTB or DSTB) is the active edge and causes
the data to be latched into the register in the gate array. For read cycles, the WRITE signal
and the appropriate strobe are combined to enable to bus buffers to drive data onto the bus
when it is a read cycle and the strobe is active.
WAIT must be in the inactive state (low) before the communications module will start a
transfer cycle. The communications module will not complete a transfer cycle until WAIT goes
high. The gate array logic may delay bringing WAIT high to until data is available if
necessary. However, if WAIT is not brought high within approximately 10ms of the start of a
transfer, the communications module will abort the transfer and report a time out error back to
the host. Similarly if WAIT does not come low to allow a transfer to begin within
approximately 10ms, the communications module will report a time out error to the host.
www.digilentinc.com Copyright Digilent, Inc. Page 2
Digilent Parallel Interface Model Digilent, Inc.
Address Write
DB
WRITE
ASTB
WAIT
Address Read
DB
WRITE
ASTB
WAIT
Data Write
DB
WRITE
DSTB
WAIT
www.digilentinc.com Copyright Digilent, Inc. Page 3
Digilent Parallel Interface Model Digilent, Inc.
Data Read
DB
WRITE
DSTB
WAIT
www.digilentinc.com Copyright Digilent, Inc. Page 4
Digilent Parallel Interface Model Digilent, Inc.
Example Source Code:
The following is an example of the interface implemented in VHDL.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
-- Uncomment the following lines to use the declarations that are
-- provided for instantiating Xilinx primitive components.
--library UNISIM;
--use UNISIM.VComponents.all;
entity dpimref is
www.digilentinc.com Copyright Digilent, Inc. Page 5
Digilent Parallel Interface Model Digilent, Inc.
Port (
mclk : in std_logic;
pdb : inout std_logic_vector(7 downto 0);
astb : in std_logic;
dstb : in std_logic;
pwr : in std_logic;
pwait : out std_logic;
rgLed : out std_logic_vector(7 downto 0);
rgSwt : in std_logic_vector(7 downto 0);
rgBtn : in std_logic_vector(4 downto 0);
btn : in std_logic;
ldg : out std_logic;
led : out std_logic
);
end dpimref;
-- State machine current state register
signal stEppCur : std_logic_vector(7 downto 0) := stEppReady;
signal stEppNext : std_logic_vector(7 downto 0);
signal clkMain : std_logic;
-- Internal control signales
signal ctlEppWait : std_logic;
www.digilentinc.com Copyright Digilent, Inc. Page 6
Digilent Parallel Interface Model Digilent, Inc.
signal ctlEppAstb : std_logic;
signal ctlEppDstb : std_logic;
signal ctlEppDir : std_logic;
signal ctlEppWr : std_logic;
signal ctlEppAwr : std_logic;
signal ctlEppDwr : std_logic;
signal busEppOut : std_logic_vector(7 downto 0);
signal busEppIn : std_logic_vector(7 downto 0);
signal busEppData : std_logic_vector(7 downto 0);
-- Registers
signal regEppAdr : std_logic_vector(3 downto 0);
signal regData0 : std_logic_vector(7 downto 0);
signal regData1 : std_logic_vector(7 downto 0);
signal regData2 : std_logic_vector(7 downto 0);
signal regData3 : std_logic_vector(7 downto 0);
signal regData4 : std_logic_vector(7 downto 0);
signal regData5 : std_logic_vector(7 downto 0);
signal regData6 : std_logic_vector(7 downto 0);
signal regData7 : std_logic_vector(7 downto 0);
signal regLed : std_logic_vector(7 downto 0);
ctlEppAstb <= astb;
ctlEppDstb <= dstb;
ctlEppWr <= pwr;
pwait <= ctlEppWait; -- drive WAIT from state machine output
-- Data bus direction control. The internal input data bus always
-- gets the port data bus. The port data bus drives the internal
-- output data bus onto the pins when the interface says we are doing
-- a read cycle and we are in one of the read cycles states in the
-- state machine.
busEppIn <= pdb;
pdb <= busEppOut when ctlEppWr = '1' and ctlEppDir = '1' else "ZZZZZZZZ";
-- Select either address or data onto the internal output data bus.
busEppOut <= "0000" & regEppAdr when ctlEppAstb = '0' else busEppData;
rgLed <= regLed;
ldg <= '1';
-- Decode the address register and select the appropriate data register
busEppData <= regData0 when regEppAdr = "0000" else
regData1 when regEppAdr = "0001" else
regData2 when regEppAdr = "0010" else
www.digilentinc.com Copyright Digilent, Inc. Page 7
Digilent Parallel Interface Model Digilent, Inc.
regData3 when regEppAdr = "0011" else
regData4 when regEppAdr = "0100" else
regData5 when regEppAdr = "0101" else
regData6 when regEppAdr = "0110" else
regData7 when regEppAdr = "0111" else
rgSwt when regEppAdr = "1000" else
"000" & rgBtn when regEppAdr = "1001" else
"00000000";
-- The following processes implement the interface registers. These
-- registers just hold the value written so that it can be read back.
-- In a real design, the contents of these registers would drive additional
-- logic.
-- The ctlEppDwr signal is an output from the state machine that says
-- we are in a 'write data register' state. This is combined with the
-- address in the address register to determine which register to write.
process (clkMain, regEppAdr, ctlEppDwr, busEppIn)
begin
if clkMain = '1' and clkMain'Event then
if ctlEppDwr = '1' and regEppAdr = "0000" then
regData0 <= busEppIn;
end if;
end if;
end process;
process (clkMain, regEppAdr, ctlEppDwr, busEppIn)
begin
if clkMain = '1' and clkMain'Event then
if ctlEppDwr = '1' and regEppAdr = "0001" then
regData1 <= busEppIn;
end if;
end if;
end process;
process (clkMain, regEppAdr, ctlEppDwr, busEppIn)
begin
if clkMain = '1' and clkMain'Event then
if ctlEppDwr = '1' and regEppAdr = "0010" then
regData2 <= busEppIn;
end if;
end if;
end process;
process (clkMain, regEppAdr, ctlEppDwr, busEppIn)
begin
if clkMain = '1' and clkMain'Event then
if ctlEppDwr = '1' and regEppAdr = "0011" then
regData3 <= busEppIn;
end if;
end if;
end process;
process (clkMain, regEppAdr, ctlEppDwr, busEppIn)
begin
if clkMain = '1' and clkMain'Event then
if ctlEppDwr = '1' and regEppAdr = "0100" then
regData4 <= busEppIn;
end if;
end if;
end process;
www.digilentinc.com Copyright Digilent, Inc. Page 10
Digilent Parallel Interface Model Digilent, Inc.
process (clkMain, regEppAdr, ctlEppDwr, busEppIn)
begin
if clkMain = '1' and clkMain'Event then
if ctlEppDwr = '1' and regEppAdr = "0101" then
regData5 <= busEppIn;
end if;
end if;
end process;
process (clkMain, regEppAdr, ctlEppDwr, busEppIn)
begin
if clkMain = '1' and clkMain'Event then
if ctlEppDwr = '1' and regEppAdr = "0110" then
regData6 <= busEppIn;
end if;
end if;
end process;
process (clkMain, regEppAdr, ctlEppDwr, busEppIn)
begin
if clkMain = '1' and clkMain'Event then
if ctlEppDwr = '1' and regEppAdr = "0111" then
regData7 <= busEppIn;
end if;
end if;
end process;
process (clkMain, regEppAdr, ctlEppDwr, busEppIn)
begin
if clkMain = '1' and clkMain'Event then
if ctlEppDwr = '1' and regEppAdr = "1010" then
regLed <= busEppIn;
end if;
end if;
end process;