--------------------------------------------------------------------------------
--
-- FileName: pmod_accelerometer_adxl345.vhd
-- Dependencies: spi_master.vhd
-- Design Software: Quartus Prime Version 17.0.0 Build 595 SJ Lite Edition
--
-- HDL CODE IS PROVIDED "AS IS." DIGI-KEY EXPRESSLY DISCLAIMS ANY
-- WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT
-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-- PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL DIGI-KEY
-- BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL
-- DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF
-- PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
-- BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF),
-- ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS.
--
-- Version History
-- Version 1.0 09/19/2019 Scott Larson
-- Initial Public Release
--
--------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY pmod_accelerometer_adxl345 IS
GENERIC(
--------------------
clk_freq : INTEGER := 100; --system clock frequency in MHz
spi_clk_div : INTEGER := 1; --spi_clk_div = clk_freq/100 (answer rounded up)
--------------------added --------------------------------------------
----rst_pwrctl_reg
rst_pwrctl_reg_ms_addr : std_logic_Vector( 7 downto 0) :=x"05" ;
rst_pwrctl_reg_ms_data : std_logic_Vector( 7 downto 0) :=x"69" ; ---first data need to send
rst_pwrctl_reg_ls_addr : std_logic_Vector( 7 downto 0) :=x"04" ;
rst_pwrctl_reg_ls_data : std_logic_Vector( 7 downto 0) :=x"00" ; ----- enable vdd alarm , input alarm , por reset,disable nap mode , put converter in active mode
------------sdi control register
sdi_ctl_reg_addr : std_logic_vector ( 7 downto 0) :=x"08" ;
sdi_mode :std_logic_vector (1 downto 0) :="00" ; ------spi mode cpol=0 cphase=0
----- sdo-ctl-reg---=====0ch =========================
sdo_ctl_reg_addr : std_logic_vector ( 7 downto 0) :=x"0C" ;
ssync_clk :std_logic :='0' ; --- 0 external clock 1- internal clock
sdo_mode :std_logic_vector(1 downto 0) :="0X" ; ---- follow same spi protocols that used for sdi mode
--------dataout control register ---- 11h
dataout_ctl_reg_ms_addr : std_logic_vector( 7 downto 0) :=x"11" ; --------------1st addr
device_addr_inc :std_logic :='0' ; --- '0' do not include the register value '1' include the register value
vdd_active_alarm_inc :std_logic_vector (1 downto 0) :="11" ; ---"11" include both vdd_h_flag and vdd_l_flag
in_active_alarm_inc :std_logic_vector (1 downto 0) :="11" ; ---"11" include both vdd_h_flag and vdd_l_flag
range_inc :std_logic :='1' ; ----- include range configuration value
dataout_ctl_reg_ls_addr : std_logic_vector ( 7 downto 0) :=x"10" ; ---------second addr ----------
par_en :std_logic :='0' ; --- 0 disable 1 enable
data_val :std_logic_vector (2 downto 0) :="0XX" ; ---------conversion data
-----------range selection register --- 14h
range_sel_addr : std_logic_vector ( 7 downto 0) :=x"14" ; --------
intref_dis:std_logic :='0' ; --- 0 disable 1 enable
range_sel:std_logic_vector(3 downto 0) :="0000" ; ---------range _+ 3*vref
write_MS : std_logic_vector ( 7 downto 0) := "11010010" ; ---ms of the 16 bit only written on the specified register address
write_LS : std_logic_vector ( 7 downto 0) := "11010100"; ---ls of the 16 bit only written on the specified register address
write_hword : std_logic_vector ( 7 downto 0) :="11010000" ; ---write half word on the specified memory location
-----------------
-- clk_freq : INTEGER := 50; --system clock frequency in MHz
data_rate : STD_LOGIC_VECTOR := "0100"; --data rate code to configure the accelerometer
data_range : STD_LOGIC_VECTOR := "00"); --data range code to configure the accelerometer
PORT(
clk : IN STD_LOGIC; --system clock
reset_n : IN STD_LOGIC; --active low asynchronous reset
miso : IN STD_LOGIC; --SPI bus: master in, slave out
sclk : BUFFER STD_LOGIC; --SPI bus: serial clock
rvs : out std_logic ;
adc_gpio : out std_logic ;
ss_n : BUFFER STD_LOGIC_VECTOR(0 DOWNTO 0); --SPI bus: slave select
mosi : OUT STD_LOGIC; --SPI bus: master out, slave in
acceleration_x : OUT STD_LOGIC_VECTOR(15 DOWNTO 0) --x-axis acceleration data
-- acceleration_y : OUT STD_LOGIC_VECTOR(15 DOWNTO 0); --y-axis acceleration data
-- acceleration_z : OUT STD_LOGIC_VECTOR(15 DOWNTO 0)--z-axis acceleration data
);
END pmod_accelerometer_adxl345;
ARCHITECTURE behavior OF pmod_accelerometer_adxl345 IS
TYPE machine IS(start, pause, configure, read_data, output_result); --needed states
SIGNAL state : machine := start; --state machine
SIGNAL parameter : INTEGER RANGE 0 TO 17; --parameter being configured
SIGNAL acceleration_y : STD_LOGIC_VECTOR(15 DOWNTO 0); --y-axis acceleration data
SIGNAL acceleration_z : STD_LOGIC_VECTOR(15 DOWNTO 0); --z-axis acceleration data
-- SIGNAL parameter_addr : STD_LOGIC_VECTOR(5 DOWNTO 0); --register address of configuration parameter
-- SIGNAL parameter_data : STD_LOGIC_VECTOR(3 DOWNTO 0); --value of configuration parameter
SIGNAL parameter_addr : STD_LOGIC_VECTOR(7 DOWNTO 0); --register address of configuration parameter
SIGNAL parameter_data : STD_LOGIC_VECTOR(7 DOWNTO 0); --value of configuration parameter
SIGNAL spi_busy_prev : STD_LOGIC; --previous value of the SPI component's busy signal
SIGNAL spi_busy : STD_LOGIC; --busy signal from SPI component
SIGNAL spi_ena : STD_LOGIC; --enable for SPI component
SIGNAL spi_cont : STD_LOGIC; --continuous mode signal for SPI component
SIGNAL spi_tx_data : STD_LOGIC_VECTOR(7 DOWNTO 0); --transmit data for SPI component
SIGNAL spi_rx_data : STD_LOGIC_VECTOR(7 DOWNTO 0); --received data from SPI component
SIGNAL acceleration_x_int : STD_LOGIC_VECTOR(15 DOWNTO 0); --internal x-axis acceleration data buffer
SIGNAL acceleration_y_int : STD_LOGIC_VECTOR(15 DOWNTO 0); --internal y-axis acceleration data buffer
SIGNAL acceleration_z_int : STD_LOGIC_VECTOR(15 DOWNTO 0); --internal z-axis acceleration data buffer
--declare SPI Master component
COMPONENT spi_master IS
GENERIC(
slaves : INTEGER := 1; --number of spi slaves
d_width : INTEGER := 8); --data bus width
PORT(
clock : IN STD_LOGIC; --system clock
reset_n : IN STD_LOGIC; --asynchronous reset
enable : IN STD_LOGIC; --initiate transaction
cpol : IN STD_LOGIC; --spi clock polarity
cpha : IN STD_LOGIC; --spi clock phase
cont : IN STD_LOGIC; --continuous mode command
clk_div : IN INTEGER; --system clock cycles per 1/2 period of sclk
addr : IN INTEGER; --address of slave
tx_data : IN STD_LOGIC_VECTOR(d_width-1 DOWNTO 0); --data to transmit
miso : IN STD_LOGIC; --master in, slave out
sclk : BUFFER STD_LOGIC; --spi clock
ss_n : BUFFER STD_LOGIC_VECTOR(slaves-1 DOWNTO 0); --slave select
mosi : OUT STD_LOGIC; --master out, slave in
busy : OUT STD_LOGIC; --busy / data ready signal
rx_data : OUT STD_LOGIC_VECTOR(d_width-1 DOWNTO 0)); --data received
END COMPONENT spi_master;
BEGIN
--instantiate the SPI Master component
spi_master_0: spi_master
GENERIC MAP(slaves => 1, d_width => 8)
PORT MAP(clock => clk, reset_n => reset_n, enable => spi_ena, cpol => '0', cpha => '0',
cont => spi_cont, clk_div => clk_freq/10, addr => 0, tx_data => spi_tx_data, miso => miso,
sclk => sclk, ss_n => ss_n, mosi => mosi, busy => spi_busy, rx_data => spi_rx_data);
PROCESS(clk , reset_n )
VARIABLE count : INTEGER := 0; --universal counter
BEGIN
IF(reset_n = '0') THEN --reset activated
spi_ena <= '0'; --clear SPI component enable
spi_cont <= '0'; --clear SPI component continuous mode signal
spi_tx_data <= (OTHERS => '0'); --clear SPI component transmit data
acceleration_x <= (OTHERS => '0'); --clear x-axis acceleration data
acceleration_y <= (OTHERS => '0'); --clear y-axis acceleration data
acceleration_z <= (OTHERS => '0'); --clear z-axis acceleration data
state <= start; --restart state machine
ELSIF(clk'EVENT AND clk = '1') THEN --rising edge of system clock
CASE state IS --state machine
--entry state
WHEN start =>
count := 0; --clear universal counter
parameter <= 0; --clear parameter indicator
state <= pause;
--pauses 200ns between SPI transactions and selects SPI transaction
WHEN pause =>
IF(spi_busy = '0') THEN --SPI component not busy
IF(count < clk_freq/5) THEN --less than 200ns
count := count + 1; --increment counter
report "count less than 200 ns " ;
state <= pause; --remain in pause state
ELSE --200ns has elapsed
count := 0; --clear counter
CASE parameter IS --select SPI transaction
--- nop
WHEN 0 => --SPI transaction to set range
parameter <= parameter + 1; --increment parameter for next transaction
parameter_addr <= x"00"; --register address with range setting
parameter_data <= x"00" ; --data to set specified range
state <= configure; --proceed to SPI transaction
WHEN 1 => --SPI transaction to set data rate
parameter <= parameter + 1; --increment parameter for next transaction
parameter_addr <= x"00"; --register address with range setting
parameter_data <= x"00" ; --data to set specified range
state <= configure; --proceed to SPI transaction
------------xxx--------------------------------
------rst1
WHEN 2 => --SPI transaction to enable measuring
parameter <= parameter + 1; --increment parameter for next transaction
parameter_addr <= write_hword ; --register address with range setting
parameter_data <= rst_pwrctl_reg_ms_addr ;
state <= configure; --proceed to SPI transaction
WHEN 3 =>
parameter <= parameter + 1;
parameter_addr <= rst_pwrctl_reg_ms_data;
parameter_data <= x"00" ;
state <= configure;
---------xxxx---------------
---rst2
WHEN 4=>
parameter <= parameter + 1;
parameter_addr <= write_hword;
parameter_data <= rst_pwrctl_reg_ls_addr ;
state <= configure;
WHEN 5 =>
parameter <= parameter + 1;
parameter_addr <=rst_pwrctl_reg_ls_data ;
parameter_data <= x"00" ;
state <= configure;
--------------xx----------------
----sdi
WHEN 6=>
parameter <= parameter + 1;
parameter_addr <= write_hword ;
parameter_data <= sdi_ctl_reg_addr ;
state <= configure;
WHEN 7=>
parameter <= parameter + 1;
parameter_addr <= "000000" & sdi_mode;
parameter_data <= x"00" ;
state <= configure;
-------- xxx-----------------
----sd0
WHEN 8=>
parameter <= parameter + 1;
parameter_addr <= write_hword ;
parameter_data <= sdo_ctl_reg_addr ;
state <= configure;
WHEN 9=>
parameter <= parameter + 1;
parameter_addr <= "0" & ssync_clk & "0000" & sdo_mode;
parameter_data <= x"00" ;
state <= configure;
---------------xxxxxxxxxxxx----------------------------
----data_out config1
WHEN 10=>
parameter <= parameter + 1;
parameter_addr <= write_hword ;
parameter_data <= dataout_ctl_reg_ms_addr ;
state <= configure;
WHEN 11=>
parameter <= parameter + 1;
parameter_addr <= '0' & device_addr_inc & vdd_active_alarm_inc & in_active_alarm_inc & '0' & range_inc;
parameter_data <= x"00" ;
state <= configure;
---------------xxxxxxxxxxxx----------------------------
----data_out config2
WHEN 12=>
parameter <= parameter + 1;
parameter_addr <= write_hword ;
parameter_data <= dataout_ctl_reg_ls_addr ;
state <= configure;
WHEN 13 =>
parameter <= parameter + 1;
parameter_addr <= "0000" & par_en & data_val ;
parameter_data <= x"00" ;
state <= configure;
---------------xxxxxxxxxxxx----------------------------
----range
WHEN 14=>
parameter <= parameter + 1;
parameter_addr <= write_hword ;
parameter_data <= range_sel_addr ;
state <= configure;
WHEN 15 =>
parameter <= parameter + 1;
parameter_addr <= '0' & intref_dis & "00" & range_sel ;
parameter_data <= x"00" ;
state <= configure;
---------------xxxxxxxxxxxx----------------------------
WHEN 16 => --SPI transaction to read data
state <= read_data; --proceed to SPI transaction
WHEN OTHERS => NULL;
END CASE;
END IF;
END IF;
--performs SPI transactions that write to configuration registers
WHEN configure =>
spi_busy_prev <= spi_busy; --capture the value of the previous spi busy signal
IF(spi_busy_prev = '1' AND spi_busy = '0') THEN --spi busy just went low
count := count + 1; --counts times busy goes from high to low during transaction
END IF;
CASE count IS --number of times busy has gone from high to low
WHEN 0 => --no busy deassertions
IF(spi_busy = '0') THEN --transaction not started
spi_cont <= '1'; --set to continuous mode
spi_ena <= '1'; --enable SPI transaction
report "configure spi_busy 0 count 0 " ;
spi_tx_data <= parameter_addr; --first information to send
ELSE --transaction has started
report "configure spi_busy 1" ;
spi_tx_data <= parameter_data; --second information to send (first has been latched in)
END IF;
WHEN 1 => --first busy deassertion
spi_cont <= '0'; --clear continous mode to end transaction
spi_ena <= '0'; --clear SPI transaction enable
count := 0; --clear universal counter
report "configure count1" ;
state <= pause; --return to pause state
WHEN OTHERS => NULL;
END CASE;
--performs SPI transactions that read acceleration data registers
WHEN read_data =>
spi_busy_prev <= spi_busy; --capture the value of the previous spi busy signal
IF(spi_busy_prev = '1' AND spi_busy = '0') THEN --spi busy just went low
count := count + 1; --counts the times busy goes from high to low during transaction
END IF;
CASE count IS --number of times busy has gone from high to low
WHEN 0 => --no busy deassertions
IF(spi_busy = '0') THEN --transaction not started
spi_cont <= '1'; --set to continuous mode
spi_ena <= '1'; --enable SPI transaction
-- spi_tx_data <= "11110010"; --first information to send
spi_tx_data <= "11001000";
ELSE --transaction has started
-- spi_tx_data <= "00000000"; --second information to send (first has been latched in)
spi_tx_data <= sdo_ctl_reg_addr ;
END IF;
WHEN 2 => --2nd busy deassertion
acceleration_x_int(7 DOWNTO 0) <= spi_rx_data; --latch in first received acceleration data
WHEN 3 => --3rd busy deassertion
acceleration_x_int(15 DOWNTO 8) <= spi_rx_data; --latch in second received acceleration data
WHEN 4 => --4th busy deassertion
acceleration_y_int(7 DOWNTO 0) <= spi_rx_data; --latch in third received acceleration data
WHEN 5 => --5th busy deassertion
acceleration_y_int(15 DOWNTO 8) <= spi_rx_data; --latch in fourth received acceleration data
WHEN 6 => --6th busy deassertion
spi_cont <= '0'; --clear continuous mode to end transaction
spi_ena <= '0'; --clear SPI transaction enable
acceleration_z_int(7 DOWNTO 0) <= spi_rx_data; --latch in fifth received acceleration data
WHEN 7 => --7th busy deassertion
acceleration_z_int(15 DOWNTO 8) <= spi_rx_data; --latch in sixth received acceleration data
count := 0; --clear universal counter
state <= output_result; --proceed to output result state
WHEN OTHERS => NULL;
END CASE;
--outputs acceleration data
WHEN output_result =>
acceleration_x <= acceleration_x_int; --output x-axis data
acceleration_y <= acceleration_y_int; --output y-axis data
acceleration_z <= acceleration_z_int; --output z-axis data
state <= pause; --return to pause state
--default to start state
WHEN OTHERS =>
state <= start;
END CASE;
END IF;
END PROCESS;
END behavior;
No comments:
Post a Comment