Implementación del EPP de Digilent

Estoy tratando de implementar Digilent Parallel Interface desde su SDK . Puede leer específicamente sobre la interfaz en este manual . Estoy usando la placa Basys 2 250k.

Estoy tratando de averiguar qué estoy haciendo mal, lo que creo que es solo un problema con el tiempo en mi VHDL.

Aquí hay un diagrama de tiempo para leer datos del FPGA:Diagrama de tiempo de lectura de Digilent EPP

El VHDL se parece a:

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;

Después de la simulación con este estímulo del banco de pruebas, obtengo estos resultados:

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

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

Simulación de tiempo


Mi proyecto C++ se compila perfectamente y utilicé el proyecto Hamsters EPP Performace como base (que funcionó perfectamente) y luego ingresé al archivo de demostración de la descarga del SDK y agarré la DoGetReg()función para comenzar a leer bytes.

Cada vez que ejecuto el programa me sale...

Opening
Enabling
Getting
DeppGetReg failed

Aquí está el código:

// 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);
}
Es posible que deba profundizar en DeppGetReg para averiguar por qué está fallando.

Respuestas (1)

Gracias a la ayuda de Hamster logré hacerlo funcionar.

Mi código tenía muchos problemas, pero lo principal que estaba haciendo mal era no admitir writecomandos.

Aquí está mi 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;

Mi programa C++ estaba bien. Puedes ver el código en la publicación principal.

Hola, @MLM, creo que tengo la misma dificultad, así que estoy descifrando mi camino a través de tu código (aunque, estrictamente hablando, no hablo VHDL). ¿Se pregunta si también necesita un cheque EppAstb = '1'debajo del when stepWriteD | stepWriteAestuche al final?
@Edmund Han pasado años desde que toqué EPP, así que no estoy muy seguro. Hice un video tutorial sobre cómo poner en funcionamiento el código de Hamsters , así que tal vez eso ayude. Supongo que puede ser necesario if EppDstb = '1' or EppAstb = '1' thenpara los dos últimos casos, pero funcionó bien sin él:/