---------------------------------------------------------------------------- -- DPIMREF.VHD -- Digilent Parallel Interface Module Reference Design ---------------------------------------------------------------------------- -- Author: Gene Apperson -- Copyright 2004 Digilent, Inc. ---------------------------------------------------------------------------- -- IMPORTANT NOTE ABOUT BUILDING THIS LOGIC IN ISE -- -- Before building the Dpimref logic in ISE: -- 1. In Project Navigator, right-click on "Synthesize-XST" -- (in the Process View Tab) and select "Properties" -- 2. Click the "HDL Options" tab -- 3. Set the "FSM Encoding Algorithm" to "None" ---------------------------------------------------------------------------- -- ---------------------------------------------------------------------------- -- This module contains an example implementation of Digilent Parallel -- Interface Module logic. This interface is used in conjunction with the -- DPCUTIL DLL and a Digilent Communications Module (USB, EtherNet, Serial) -- to exchange data with an application running on a host PC and the logic -- implemented in a gate array. -- -- See the Digilent document, Digilent Parallel Interface Model Reference -- Manual (doc # 560-000) for a description of the interface. -- -- This design uses a state machine implementation to respond to transfer -- cycles. It implements an address register, 8 internal data registers -- that merely hold a value written, and interface registers to communicate -- with a Digilent DIO4 board. There is an LED output register whose value -- drives the 8 discrete leds on the DIO4. There are two input registers. -- One reads the switches on the DIO4 and the other reads the buttons. -- -- Interface signals used in top level entity port: -- mclk - master clock, generally 50Mhz osc on system board -- pdb - port data bus -- astb - address strobe -- dstb - data strobe -- pwr - data direction (described in reference manual as WRITE) -- pwait - transfer synchronization (described in reference manual -- as WAIT) -- rgLed - LED outputs to the DIO4 -- rgSwt - switch inputs from the DIO4 -- ldb - led gate signal for the DIO4 -- rgBtn - button inputs from the DIO4 -- btn - button on system board (D2SB or D2FT) -- led - led on the system board -- ---------------------------------------------------------------------------- -- Revision History: -- 06/09/2004(GeneA): created -- 08/10/2004(GeneA): initial public release -- 04/25/2006(JoshP): comment addition ---------------------------------------------------------------------------- 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 Port ( mclk : in std_logic; pdb : inout std_logic_vector(6 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; -- entity roboseg ------------------ l : inout std_logic ; b : inout std_logic ; h : inout std_logic ; h1 : inout std_logic ; rst : inout std_logic ; an : inout std_logic_vector (0 to 3) ; ss : inout std_logic_vector (0 to 2) ; ssg : out std_logic_vector (0 to 7) ); ------------------------------------------------------------------------ -- Component Declarations end dpimref; architecture Behavior of dpimref is ------------------------------------------------------------------------ ------------------------------------------------------------------------ -- Local Type Declarations ------------------------------------------------------------------------ ------------------------------------------------------------------------ -- Constant Declarations ------------------------------------------------------------------------ -- The following constants define state codes for the EPP port interface -- state machine. The high order bits of the state number give a unique -- state identifier. The low order bits are the state machine outputs for -- that state. This type of state machine implementation uses no -- combination logic to generate outputs which should produce glitch -- free outputs. constant stEppReady : std_logic_vector(7 downto 0) := "0000" & "0000"; constant stEppAwrA : std_logic_vector(7 downto 0) := "0001" & "0100"; constant stEppAwrB : std_logic_vector(7 downto 0) := "0010" & "0001"; constant stEppArdA : std_logic_vector(7 downto 0) := "0011" & "0010"; constant stEppArdB : std_logic_vector(7 downto 0) := "0100" & "0011"; constant stEppDwrA : std_logic_vector(7 downto 0) := "0101" & "1000"; constant stEppDwrB : std_logic_vector(7 downto 0) := "0110" & "0001"; constant stEppDrdA : std_logic_vector(7 downto 0) := "0111" & "0010"; constant stEppDrdB : std_logic_vector(7 downto 0) := "1000" & "0011"; ------------------------------------------------------------------------ -- Signal Declarations ------------------------------------------------------------------------ -- 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; 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(6 downto 0); signal busEppIn : std_logic_vector(6 downto 0); signal busEppData : std_logic_vector(6 downto 0); -- Registers signal regEppAdr : std_logic_vector(3 downto 0); signal regData0 : std_logic_vector(6 downto 0); signal regData1 : std_logic_vector(2 downto 0); signal regLed : std_logic_vector(7 downto 0); signal cntr : std_logic_vector(23 downto 0); ------------------------------------------------------------------------ -- Module Implementation ------------------------------------------------------------------------ ---------------- robotseg architecture synthesis ----------------- -- clock signal CTR : std_logic_vector (12 downto 0); -- buffer signals declarations signal ss_int : std_logic_vector (0 to 2) ; -- internal signals declarations signal jx : std_logic ; signal y : std_logic ; signal kx : std_logic ; signal x : std_logic ; signal jy : std_logic ; signal ky : std_logic ; -------------------------------------------------------------------- begin jx <= (not l) and (not b) and (not y) and (not x) ; kx <= (b and x) or (l and x) ; jy <= (x and (not y)) or ((not l) and b and (not y)) ; ky <= (l and (not b) and y) or (l and (not x) and y) ; ss_int(2) <= not x ; ss_int(1) <= (x and (not y)) or ((not x) and y) ; ss_int(0) <= not x ; -- buffer signals assignations ss(0 to 2) <= ss_int(0 to 2) ; rst <= regData0(3); h1 <= regData0(2); l <= regData0(1); b <= regData0(0); regData1(0) <= ss(0); regData1(1) <= ss(1); regData1(2) <= ss(2); process(mclk) begin if mclk'event and mclk= '1' then if (CTR="0000000000000") then if (an(3)='0') then an(3) <= '1'; an(0) <= '0'; ssg <="11111111"; elsif (an(0)='0') then an(0) <= '1'; an(1) <= '0'; if ss_int(2)='0' then ssg <="00000011"; else ssg <="10011111"; end if; elsif (an(1)='0') then an(1) <= '1'; an(2) <= '0'; if ss_int(1)='0' then ssg <="00000011"; else ssg <="10011111"; end if; elsif (an(2)='0') then an(2) <= '1'; an(3) <= '0'; if ss_int(0)='0' then ssg <="00000011"; else ssg <="10011111"; end if; end if; end if; CTR<=CTR+"0000000000001"; if (CTR > "1000000000000") then CTR<="0000000000000"; end if; end if; end process; -- sequential statements process (h1, rst) begin if rst = '1' then x <= '0' ; elsif h1'event and h1 = '1' then x <= ((not kx) and x) or (jx and (not x)) ; end if ; end process ; process (h1, rst) begin if rst = '1' then y <= '0' ; elsif h1'event and h1 = '1' then y <= ((not ky) and y) or (jy and (not y)) ; end if ; end process ; ------------------------------------------------------------------------ -- Map basic status and control signals ------------------------------------------------------------------------ clkMain <= mclk; 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 "ZZZZZZZ"; -- Select either address or data onto the internal output data bus. busEppOut <= regData1(2 downto 0) & regData0(3 downto 0) when ctlEppAstb = '0' else busEppData; -- Decode the address register and select the appropriate data register busEppData <= regData1(2 downto 0) & regData0(3 downto 0) when regEppAdr = "1010" else "0000000"; ------------------------------------------------------------------------ -- EPP Interface Control State Machine ------------------------------------------------------------------------ -- Map control signals from the current state ctlEppWait <= stEppCur(0); ctlEppDir <= stEppCur(1); ctlEppAwr <= stEppCur(2); ctlEppDwr <= stEppCur(3); -- This process moves the state machine to the next state -- on each clock cycle process (clkMain) begin if clkMain = '1' and clkMain'Event then stEppCur <= stEppNext; end if; end process; -- This process determines the next state machine state based -- on the current state and the state machine inputs. process (stEppCur, stEppNext, ctlEppAstb, ctlEppDstb, ctlEppWr) begin case stEppCur is -- Idle state waiting for the beginning of an EPP cycle when stEppReady => if ctlEppAstb = '0' then -- Address read or write cycle if ctlEppWr = '0' then stEppNext <= stEppAwrA; else stEppNext <= stEppArdA; end if; elsif ctlEppDstb = '0' then -- Data read or write cycle if ctlEppWr = '0' then stEppNext <= stEppDwrA; else stEppNext <= stEppDrdA; end if; else -- Remain in ready state stEppNext <= stEppReady; end if; -- Write address register when stEppAwrA => stEppNext <= stEppAwrB; when stEppAwrB => if ctlEppAstb = '0' then stEppNext <= stEppAwrB; else stEppNext <= stEppReady; end if; -- Read address register when stEppArdA => stEppNext <= stEppArdB; when stEppArdB => if ctlEppAstb = '0' then stEppNext <= stEppArdB; else stEppNext <= stEppReady; end if; -- Write data register when stEppDwrA => stEppNext <= stEppDwrB; when stEppDwrB => if ctlEppDstb = '0' then stEppNext <= stEppDwrB; else stEppNext <= stEppReady; end if; -- Read data register when stEppDrdA => stEppNext <= stEppDrdB; when stEppDrdB => if ctlEppDstb = '0' then stEppNext <= stEppDrdB; else stEppNext <= stEppReady; end if; -- Some unknown state when others => stEppNext <= stEppReady; end case; end process; ------------------------------------------------------------------------ -- EPP Address register ------------------------------------------------------------------------ process (clkMain, ctlEppAwr) begin if clkMain = '1' and clkMain'Event then if ctlEppAwr = '1' then regEppAdr <= busEppIn(3 downto 0); end if; end if; end process; ------------------------------------------------------------------------ -- EPP Data registers ------------------------------------------------------------------------ -- 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 = "1010" then regData0 <= busEppIn(6 downto 0); end if; end if; end process; ------------------------------------------------------------------------ -- Gate array configuration verification logic ------------------------------------------------------------------------ -- This logic will flash the led on the gate array. This is to verify -- that the gate array is properly configured for the test. This is a -- simple way to verify that the gate array actually got configured. led <= btn or cntr(23); process (clkMain) begin if clkMain = '1' and clkMain'Event then cntr <= cntr + 1; end if; end process; ---------------------------------------------------------------------------- end Behavior;