VHDL SPI xilinx spartan 3E

1

No tengo experiencia previa con VHDL y el profesor me da la mayor parte del código.

Estoy intentando comunicarme con un acelerómetro ADXL362 utilizando SPI en un Xilinx Sparten 3E. Por lo que puedo entender del esquema RTL del ADXL362, necesito hacer un módulo con 5 (?) Puertos. MISO, MOSI, SS (selección de esclavo), datos preparados y reloj del sistema para que el módulo superior pueda hablar con él.

La interfaz SPI se comporta como un submódulo del módulo ADXL362, ¿cuánto debo declarar de los puertos en mi módulo superior?

Por su aspecto, el ADXL es el esclavo y tengo que escribir un módulo maestro para poder hablar con él. Pero todos los ejemplos que he visto solo tienen muchos más cables que lo que obtuve en el código prefabricado. Así que estoy totalmente atascado a partir de ahora, por lo que cualquier ayuda sería muy apreciada.

Códigodecódigosuperior:

libraryIEEE;useIEEE.STD_LOGIC_1164.ALL;--Uncommentthefollowinglibrarydeclarationifusing--arithmeticfunctionswithSignedorUnsignedvalues--useIEEE.NUMERIC_STD.ALL;--Uncommentthefollowinglibrarydeclarationifinstantiating--anyXilinxprimitivesinthiscode.--libraryUNISIM;--useUNISIM.VComponents.all;entitytop_moduleisport(sysclk:instd_logic;--uart_tx:outstd_logic;btn:inSTD_LOGIC_VECTOR(3downto0);--miso:inSTD_LOGIC;tx:outstd_logic;led1:outstd_logic;led2:outstd_logic);endtop_module;architectureBehavioraloftop_moduleissignaltempX:std_logic_vector(11downto0);signaltempY:std_logic_vector(11downto0);signaltempZ:std_logic_vector(11downto0);signalZZ:std_logic_vector(7downto0);signalYY:std_logic_vector(7downto0);signalXX:std_logic_vector(7downto0);signalclr:std_logic;componentADXL362Ctrlport(SYSCLK:inSTD_LOGIC;--SystemClockRESET:inSTD_LOGIC;--AccelerometerdatasignalsACCEL_X:outSTD_LOGIC_VECTOR(11downto0);ACCEL_Y:outSTD_LOGIC_VECTOR(11downto0);ACCEL_Z:outSTD_LOGIC_VECTOR(11downto0);--SPIInterfaceSignalsSCLK:outSTD_LOGIC;MOSI:outSTD_LOGIC;MISO:inSTD_LOGIC;SS:outSTD_LOGIC);endcomponent;);endcomponent;--convertdatafrom12to8bitcomponentconvertionisport(ACCEL_X:inSTD_LOGIC_VECTOR(11downto0);ACCEL_Y:inSTD_LOGIC_VECTOR(11downto0);ACCEL_Z:inSTD_LOGIC_VECTOR(11downto0);Ax:outstd_logic_vector(7downto0);Ay:outstd_logic_vector(7downto0);Az:outstd_logic_vector(7downto0));endcomponent;beginA:ADXL362Ctrl--clr<=btn(3);portmap(MISO=>miso,SYSCLK=>sysclk,RESET=>btn(3),ACCEL_X=>tempX,ACCEL_Y=>tempY,ACCEL_Z=>tempZ,--SPIInterfaceSignalsSCLK=>sclk,MOSI=>mosi,MISO=>miso,SS=>ss);A3:convertionportmap(Ay=>YY,Az=>ZZ,Ax=>XX,ACCEL_X=>tempX,ACCEL_Y=>tempY,ACCEL_Z=>tempZ);'

interfazSPI enlace Código ADXL enlace

    
pregunta Runsiv

1 respuesta

2

Según su esquema (muy incompleto), se supone que debe usar:

  • un maestro SPI
  • un controlador para el ADXL362 que habla con el maestro SPI
  • el controlador lee la aceleración (X, Y, Z) y la temperatura (TMP), realiza la conversión necesaria y tiene la aceleración y la temperatura convertidas en sus salidas junto con una señal de data_ready que indica datos de salida válidos.

Ya tiene código VHDL para el maestro SPI y el controlador ADXL362. Antes de continuar, lea la teoría de operación de ambos archivos HDL (comentarios en la parte superior), así como la hoja de datos ADXL362 .

Debe crear una instancia del controlador ADXL362 y usar sus salidas:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity top_module is
    Generic (
        SYSCLK_FREQUENCY_HZ : integer := 100000000 ------- Change this to your actual frequency!
    );
    Port (
        --! System Clock
        SYSCLK : in std_logic;
        --! Buttons
        BTN    : in std_logic_vector(3 downto 0);
        --! LEDs
        LED    : out std_logic_vector(1 downto 0);
        --! SPI Signals
        SCLK   : out std_logic;
        MISO   : in  std_logic;
        MOSI   : out std_logic;
        SS_N   : out std_logic
    );
end entity top_module;

architecture Behavioral of top_module is

-----------------------------------------------------------------------
-- Components
-----------------------------------------------------------------------

component ADXL362Ctrl
    Generic (
        SYSCLK_FREQUENCY_HZ : integer := 100000000;
        SCLK_FREQUENCY_HZ   : integer := 1000000;
        NUM_READS_AVG       : integer := 16;
        UPDATE_FREQUENCY_HZ : integer := 1000
    );
    Port (
        SYSCLK      : in std_logic; -- System Clock
        RESET       : in std_logic;

        -- Accelerometer data signals
        ACCEL_X     : out std_logic_vector(11 downto 0);
        ACCEL_Y     : out std_logic_vector(11 downto 0);
        ACCEL_Z     : out std_logic_vector(11 downto 0);
        ACCEL_TMP   : out std_logic_vector(11 downto 0);
        Data_Ready  : out std_logic;

        --SPI Interface Signals
        SCLK        : out std_logic;
        MOSI        : out std_logic;
        MISO        : in  std_logic;
        SS          : out std_logic
    );
end component ADXL362Ctrl;

-----------------------------------------------------------------------
-- Signals
-----------------------------------------------------------------------

signal reset     : std_logic_vector(15 downto 0) := (others => '1');

signal ss        : std_logic;
signal accel_x   : std_logic_vector(11 downto 0);
signal accel_y   : std_logic_vector(11 downto 0);
signal accel_z   : std_logic_vector(11 downto 0);
signal accel_tmp : std_logic_vector(11 downto 0);
signal drdy      : std_logic;

begin

-- ADXL362 has low-active CS (SS_N)
-- SPI Master has high-active ss => invert
SS_N <= not ss;

reset_p : process (
    SYSCLK
    )
begin

    if (rising_edge(SYSCLK)) then

        reset <= reset(reset'left - 1 downto 0) & "0";

    end if;

end process reset_p;

led_p : process (
    SYSCLK
    )
begin

    if (rising_edge(SYSCLK)) then

        if (reset(reset'left) = '1') then

            LED <= (others => '0');

        elsif (drdy = '1') then

            -- accelerations are in two's complement
            -- put sign bit onto LEDs for testing
            LED(0) <= accel_x(accel_x'left);
            LED(1) <= accel_y(accel_y'left);

        end if;

    end if;

end process led_p;

-----------------------------------------------------------------------
-- Instances
-----------------------------------------------------------------------

ADXL362Ctrl_Inst : component ADXL362Ctrl
    Generic Map (
        SYSCLK_FREQUENCY_HZ => SYSCLK_FREQUENCY_HZ,
        SCLK_FREQUENCY_HZ   => 1000000,
        NUM_READS_AVG       => 16,
        UPDATE_FREQUENCY_HZ => 1000
    )
    Port Map (
        SYSCLK      => SYSCLK,
        RESET       => reset(reset'left),

        -- Accelerometer data signals
        ACCEL_X     => accel_x,
        ACCEL_Y     => accel_y,
        ACCEL_Z     => accel_z,
        ACCEL_TMP   => accel_tmp,
        Data_Ready  => drdy,

        --SPI Interface Signals
        SCLK        => SCLK,
        MOSI        => MOSI,
        MISO        => MISO,
        SS          => ss
    );
end architecture Behavioral;

Este es un ejemplo mínimo. Crea una instancia de un ADXL362Ctrl, lo restablece adecuadamente durante 16 ciclos de reloj y, dependiendo de accel_x y accel_y, permite que los LED muestren si tiene una aceleración positiva o negativa en los ejes X e Y.

No se olvide de LOCALIZAR sus pines en el archivo UCF usando las restricciones apropiadas. ¡Si no lo haces, puedes dañar tu placa de desarrollo!

Dependiendo de la configuración de su LED, es posible que deba invertir la salida del LED dentro de led_p. Un Administrador de Reloj Digital (DCM) sería apropiado, pero me temo que agregar uno aquí solo te confundiría más. Su maestro o asistente de enseñanza podrá decirle cómo crear una instancia adecuada de un DCM.

    
respondido por el FRob

Lea otras preguntas en las etiquetas