Take the 2-minute tour ×
Electrical Engineering Stack Exchange is a question and answer site for electronics and electrical engineering professionals, students, and enthusiasts. It's 100% free, no registration required.

I am trying to implement Digilent Parallel Interface from their SDK. You can specifically read up on the interface in this manual. I am using the Basys 2 250k board.

I am trying to figure out what I am I doing wrong which I think is just an issue with timing in my VHDL.

Here is a timing diagram to read data from the FPGA: Digilent EPP Read Timing Diagram

The VHDL looks like:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity DeppSwitches is
    Port(
        mclk     : in std_logic;
        EppDB       : inout std_logic_vector(7 downto 0);
        EppAstb : in std_logic;
        EppDstb  : in std_logic;
        EppWR    : in std_logic;
        EppWait  : out std_logic;
        Led     : out std_logic_vector(7 downto 0);
        sw      : in std_logic_vector(7 downto 0);
        btn     : in std_logic_vector(4 downto 0);

        stepCurrOutDebug : out std_logic_vector(7 downto 0);
        stepNextOutDebug : out std_logic_vector(7 downto 0)
    );
end DeppSwitches;

architecture Behavioral of DeppSwitches is
    signal    busEppOut: std_logic_vector(7 downto 0); -- Channel to send bits to pc
    signal    busEppIn: std_logic_vector(7 downto 0); -- Address that the pc sends to fpga
    signal    busEppData: std_logic_vector(7 downto 0); -- Bits to send to PC

    signal peripheralWait: std_logic := '0';

    constant stepIdle: std_logic_vector(7 downto 0) := "0001" & "0000";
    constant stepRead: std_logic_vector(7 downto 0) := "0010" & "0000"; -- PC Read from FPGA
    constant stepRead2: std_logic_vector(7 downto 0) := "0100" & "0000"; -- PC Read from FPGA

    signal stepCurr: std_logic_vector(7 downto 0) := stepIdle;
    signal stepNext: std_logic_vector(7 downto 0);
begin
    Led <= sw;

    -- Handshake signal used to indicate when the peripheral is ready to accept data or has data available.
    EppWait <= peripheralWait;

    -- 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 <= EppDB;
    EppDB <= busEppOut;

    -- Hook the data bits to the switches
    busEppData <= sw;

    -- We need this to see the state when debugging
    stepCurrOutDebug <= stepCurr;
    stepNextOutDebug <= stepNext;

    -- Advance the state machine
    process(mclk)
    begin
        if rising_edge(mclk) then
            stepCurr <= stepNext;
        end if;
    end process;

    process(mclk)
    begin
        if rising_edge(mclk) then
            case stepCurr is
                when stepIdle =>
                    peripheralWait <= '0';
                    busEppOut <= "ZZZZZZZZ";

                    if EppWR = '1' then
                        stepNext <= stepRead;
                    else
                        stepNext <= stepIdle;
                    end if;

                when stepRead =>
                    if EppDstb = '0' then
                        busEppOut <= busEppData;
                        peripheralWait <= '1';

                        stepNext <= stepRead2;
                    end if;

                when stepRead2 =>
                    if EppDstb = '1' then
                        busEppOut <= "ZZZZZZZZ";

                        stepNext <= stepIdle;
                    else 
                        stepNext <= stepRead2;
                    end if;

                when others => stepNext <= stepIdle;
            end case;
        end if;
    end process;

end Behavioral;

After simulation with this test bench stimulus I get these results:

-- insert stimulus here 
EppWR <= '1';
EppDstb <= '1';
sw <= "00001111";

wait for 4 ns;
EppDstb <= '0';
wait for 50 ns;
EppDstb <= '1';

Timing Simulation


My C++ project compiles just fine and I used Hamsters EPP Performace project as my base (which I got working just fine) and then went into the demo file of the SDK download and grabbed the DoGetReg() function to start reading bytes.

Whenever I run the program I get...

Opening
Enabling
Getting
DeppGetReg failed

Here is the code:

// DeppSwitches.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include "dpcdecl.h"
#include "depp.h"
#include "dmgr.h"

static HIF hif = hifInvalid;

void ErrorExit();
void DoGetReg();

int main(int cszArg, char * rgszArg[]) 
{
    fprintf(stderr,"Opening\n");
    if(!DmgrOpen(&hif, "Basys2")) // Change to Basys2 for the other board.
    {  
        printf("DmgrOpen failed (check the device name you provided)\n");
        return 0;
    }

    fprintf(stderr,"Enabling\n");
    if(!DeppEnable(hif)) 
    {
        printf("DeppEnable failed\n");
        return 0;
    }

    fprintf(stderr,"Getting\n");
    DoGetReg();

    if( hif != hifInvalid ) 
    {
        DeppDisable(hif);
        DmgrClose(hif);
    }
    return 0;
}

void DoGetReg() 
{
    BYTE    idReg;
    BYTE    idData;

    idReg = (BYTE)0;

    // DEPP API Call: DeppGetReg
    if(!DeppGetReg(hif, idReg, &idData, fFalse)) { 
        printf("DeppGetReg failed\n");
        ErrorExit();
    }

    printf("Complete. Recieved data %d\n", idData);

    return;
}


/* ------------------------------------------------------------ */
/***    ErrorExit
**
**  Parameters:
**      none
**
**  Return Value:
**      none
**
**  Errors:
**      none
**
**  Description:
**      Disables DEPP, closes the device, close any open files, and exits the program
*/
void ErrorExit() {
    if( hif != hifInvalid ) {
        // DEPP API Call: DeppDisable
        DeppDisable(hif);

        // DMGR API Call: DmgrClose
        DmgrClose(hif);
    }

    exit(1);
}
share|improve this question
    
You may need to dig into DeppGetReg to find out why it is failing. –  Brian Drummond Dec 12 '12 at 12:13

1 Answer 1

up vote 2 down vote accepted

Thanks to some help from Hamster I managed to get it working.

My code had many problems but the main thing I was doing wrong was not supporting write commands.

Here is my VHDL:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity DeppSwitches is
    Port(
        mclk     : in std_logic;
        EppDB       : inout std_logic_vector(7 downto 0);
        EppAstb : in std_logic;
        EppDstb  : in std_logic;
        EppWR    : in std_logic;
        EppWait  : out std_logic;
        Led     : out std_logic_vector(7 downto 0);
        sw      : in std_logic_vector(7 downto 0);
        btn     : in std_logic_vector(4 downto 0);

        stepCurrOutDebug : out std_logic_vector(7 downto 0);
        stepNextOutDebug : out std_logic_vector(7 downto 0)
    );
end DeppSwitches;

architecture Behavioral of DeppSwitches is
    signal    busEppOut: std_logic_vector(7 downto 0); -- Channel to send bits to pc
    signal    busEppIn: std_logic_vector(7 downto 0); -- Address that the pc sends to fpga
    signal    busEppData: std_logic_vector(7 downto 0); -- Bits to send to PC

    signal peripheralWait: std_logic := '0';

    constant stepIdle: std_logic_vector(7 downto 0)     := "0000" & "0000";
    constant stepReadA: std_logic_vector(7 downto 0)    := "0001" & "0000"; -- PC Read from FPGA Address
    constant stepReadD: std_logic_vector(7 downto 0)    := "0010" & "0000"; -- PC Read from FPGA Data
    constant stepWriteA: std_logic_vector(7 downto 0)   := "0100" & "0000"; -- PC Write to FPGA Address
    constant stepWriteD: std_logic_vector(7 downto 0)   := "1000" & "0000"; -- PC Write to FPGA Data

    signal stepCurr: std_logic_vector(7 downto 0) := stepIdle;
    signal stepNext: std_logic_vector(7 downto 0);
begin
    Led <= sw;

    -- Handshake signal used to indicate when the peripheral is ready to accept data or has data available.
    EppWait <= peripheralWait;

    -- 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 <= EppDB;
    EppDB <= busEppOut;

    -- Hook the data bits to the switches
    busEppData <= sw;

    -- We need this to see the state when debugging
    stepCurrOutDebug <= stepCurr;
    stepNextOutDebug <= stepNext;

    -- Advance the state machine
    process(mclk)
    begin
        if rising_edge(mclk) then
            stepCurr <= stepNext;
        end if;
    end process;

    process(mclk)
    begin
        if rising_edge(mclk) then
            case stepCurr is                    
                when stepIdle =>
                    peripheralWait <= '0';
                    busEppOut <= "ZZZZZZZZ";

                    if EppDstb = '0' then 
                        if EppWr = '0' then
                            stepNext <= stepWriteD; -- PC Write to FPGA Data
                        else
                            stepNext <= stepReadD; -- PC Read from FPGA Data
                        end if;
                    end if;

                    if EppAstb = '0' then 
                        if EppWr = '0' then
                            stepNext <= stepWriteA; -- PC Write to FPGA Address
                        else
                            stepNext <= stepReadA; -- PC Read from FPGA Address
                        end if;
                    end if;
                -------------------------------------------------

                when stepReadD | stepReadA =>
                    busEppOut <= busEppData;
                    peripheralWait <= '1';

                    if EppDstb = '1' then
                        stepNext <= stepIdle;
                    end if;
                -------------------------------------------------

                when stepWriteD | stepWriteA =>
                    peripheralWait <= '1';
                    if EppDstb = '1' then
                        stepNext <= stepIdle;
                    end if;

                when others => stepNext <= stepIdle;
            end case;
        end if;
    end process;

end Behavioral;

My C++ program was just fine. You can see the code in the main post.

share|improve this answer
    
Hey there @MLM, I think I've got the same difficulty so I'm figuring my way through your code (though, strictly speaking, I don't speak VHDL). Wondering whether you also need a check for EppAstb = '1' under the when stepWriteD | stepWriteA case at the end? –  Edmund Nov 23 at 21:59
1  
@Edmund It has been years since I have touched EPP so I am not quite sure. I did make a video tutorial about how to get Hamsters code up and running so maybe that will help. I am guessing it may need to be a if EppDstb = '1' or EppAstb = '1' then for both of the last two cases but it worked just fine without it :/ –  MLM Nov 23 at 22:24

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.