Implementierung des Digilent EPP

Ich versuche, Digilent Parallel Interface aus ihrem SDK zu implementieren . In diesem Handbuch können Sie sich speziell über die Schnittstelle informieren . Ich verwende das Basys 2 250k Board.

Ich versuche herauszufinden, was ich falsch mache, was meiner Meinung nach nur ein Problem mit dem Timing in meinem VHDL ist.

Hier ist ein Zeitdiagramm zum Lesen von Daten aus dem FPGA:Digilent EPP Lesezeitdiagramm

Das VHDL sieht so aus:

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;

Nach der Simulation mit diesem Testbench-Stimulus erhalte ich diese Ergebnisse:

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

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

Timing-Simulation


Mein C++-Projekt lässt sich problemlos kompilieren, und ich habe das EPP-Performace-Projekt von Hamster als Basis verwendet (das problemlos funktionierte) und bin dann in die Demodatei des SDK-Downloads gegangen und habe die DoGetReg()Funktion aufgerufen, um mit dem Lesen von Bytes zu beginnen.

Immer wenn ich das Programm starte bekomme ich...

Opening
Enabling
Getting
DeppGetReg failed

Hier ist der 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);
}
Möglicherweise müssen Sie sich mit DeppGetReg befassen, um herauszufinden, warum es fehlschlägt.

Antworten (1)

Dank etwas Hilfe von Hamster habe ich es geschafft, es zum Laufen zu bringen.

Mein Code hatte viele Probleme, aber die Hauptsache, die ich falsch gemacht habe, war, keine writeBefehle zu unterstützen.

Hier ist mein 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;

Mein C++-Programm war in Ordnung. Sie können den Code im Hauptpost sehen.

Hallo @MLM, ich glaube, ich habe die gleiche Schwierigkeit, also finde ich mich durch Ihren Code (obwohl ich streng genommen kein VHDL spreche). Sie fragen sich, ob Sie am Ende auch einen Check für EppAstb = '1'den Koffer brauchen ?when stepWriteD | stepWriteA
@Edmund Es ist Jahre her, dass ich EPP berührt habe, also bin ich mir nicht ganz sicher. Ich habe ein Video-Tutorial darüber erstellt , wie man den Hamster-Code zum Laufen bringt, vielleicht hilft das. Ich vermute, dass es für die beiden letzten beiden Fälle eine sein muss, aber es hat ohne es gut funktioniert :/if EppDstb = '1' or EppAstb = '1' then