1
\$\begingroup\$

I have nearly non previous experience with VHDL and the most of the code here is given to me by the teacher.

I'm trying to communicate with a ADXL362 accelerometer using SPI on a Xilinx Sparten 3E. As far as I can understand from the RTL schematic of the ADXL362 I need to make a module with 5(?) ports. MISO, MOSI, SS(slave select), data ready and system clock for the top module to talk with it.

The SPI interface behaves like a submodule of the ADXL362 module, so how much to I need to declare of the ports in my top module then?

By the looks of it, the ADXL is the slave and I have to write a master module to be able to talk with it. But all the examples I have seen just got a lot more wires then what I got in the premade code. So I'm totally stuck as of now, so any help would be greatly appreciated.

figure1

Top modlue code:

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 top_module is

    port(
        sysclk :in std_logic;

        --uart_tx: out std_logic;
        btn : in  STD_LOGIC_VECTOR (3 downto 0);
        --miso : in STD_LOGIC;
        tx : out std_logic;

        led1 : out std_logic;
        led2 : out std_logic        

        );

end top_module;

architecture Behavioral of top_module is

signal tempX : std_logic_vector (11 downto 0);
signal tempY : std_logic_vector (11 downto 0);
signal tempZ : std_logic_vector (11 downto 0);
signal ZZ : std_logic_vector (7 downto 0);
signal YY : std_logic_vector (7 downto 0);
signal XX : std_logic_vector (7 downto 0);

signal clr: std_logic;



component ADXL362Ctrl
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);

   --SPI Interface Signals
   SCLK       : out STD_LOGIC;
    MOSI       : out STD_LOGIC;
    MISO       : in STD_LOGIC;
    SS         : out STD_LOGIC

);
end component;

);
end component;

-- convert data from 12 to 8 bit
component convertion is
port (
   ACCEL_X    : in STD_LOGIC_VECTOR (11 downto 0);
   ACCEL_Y    : in STD_LOGIC_VECTOR (11 downto 0);
   ACCEL_Z    : in STD_LOGIC_VECTOR (11 downto 0);

    Ax : out std_logic_vector (7 downto 0);
    Ay : out std_logic_vector (7 downto 0);
    Az : out std_logic_vector (7 downto 0)
    );
end component;

begin
    A : ADXL362Ctrl
--clr <= btn(3);
        port map
        (
            MISO => miso,
            SYSCLK => sysclk,
            RESET => btn(3),

            ACCEL_X => tempX,
            ACCEL_Y => tempY,
            ACCEL_Z => tempZ,                       
            --SPI Interface Signals
            SCLK        => sclk,
            MOSI        => mosi,
            MISO        => miso,
            SS          => ss
        );





    A3: convertion
        port map
            (
            Ay => YY,
            Az => ZZ,
            Ax => XX,
            ACCEL_X => tempX,
            ACCEL_Y => tempY,
            ACCEL_Z => tempZ
            );`

SPI interface http://pastebin.com/t7LFnvDp ADXL code http://pastebin.com/uwZ8mZBH

\$\endgroup\$
0

1 Answer 1

2
\$\begingroup\$

Based on your (very incomplete) schematic, you're supposed to use:

  • an SPI master
  • a controller for the ADXL362 that talks to the SPI master
  • controller reads acceleration (X, Y, Z) and temperature (TMP), does necessary conversion and has the converted acceleration and temperature at its outputs along with a data_ready signal indicating valid output data.

You have VHDL code for the SPI master and the ADXL362 controller already. Before you go any further, read the theory of operation of both HDL files (comments at the top) as well as the ADXL362 datasheet.

You need to instantiate the ADXL362 controller and use its outputs:

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;

This is a minimal example. It instantiates one ADXL362Ctrl, resets it properly for 16 clock cycles and -- depending on accel_x and accel_y -- lets the LEDs show if you have negative or positive acceleration on the X and Y axes.

Do not forget to LOC your pins in the UCF file using appropriate constraints. You can damage your development board if you don't!

Depending on your LED setup, you might need to invert the LED output inside led_p. A Digital Clock Manager (DCM) would be appropriate, but I fear adding one here would only confuse you more. Your teacher or teaching assistant will be able to tell you how to properly instantiate a DCM.

\$\endgroup\$
8
  • \$\begingroup\$ Thank you so very much. Finally I got a clear idea of what I got to do. My other group member has been saying that it wasn't necessary to do anything the spi and the teacher is not available. \$\endgroup\$
    – Runsiv
    May 23, 2015 at 11:04
  • \$\begingroup\$ I have run into a small problem. "SYSCLK_FREQUENCY_HZ => SYSCLK_FREQUENCY_HZ," gives me error, undefined symbol if I don't give it a numeric value. And I don't understand why since it's defined. \$\endgroup\$
    – Runsiv
    May 23, 2015 at 15:07
  • \$\begingroup\$ What synthesis tool do you use? Some need you to explicitly define top-level generics in the options. So if you don't define it in the options, the default value won't be used and the generic would be undefined. \$\endgroup\$
    – FRob
    May 23, 2015 at 20:16
  • \$\begingroup\$ I'm using the XST from ISE 14.7. \$\endgroup\$
    – Runsiv
    May 24, 2015 at 0:24
  • \$\begingroup\$ Well, ISE's XST should "just work". I have just confirmed this to work in a dummy project. Are you sure you didn't forget to add the generic to your toplevel entity? Please post the actual error message. Without an actual message, there is little I can do. Make sure there aren't any syntax errors in the parts you added for your design. \$\endgroup\$
    – FRob
    May 24, 2015 at 10:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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