runsiv

AccCtrl

May 22nd, 2015
892
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
VHDL 44.51 KB | None | 0 0
  1. ----------------------------------------------------------------------------------
  2. ----------------------------------------------------------------------------
  3. -- Author:  Albert Fazakas
  4. --          Copyright 2014 Digilent, Inc.
  5. ----------------------------------------------------------------------------
  6. --
  7. -- Create Date:    16:48:39 02/20/2014
  8. -- Design Name:
  9. -- Module Name:    ADXL362Ctrl - Behavioral
  10. -- Project Name:
  11. -- Target Devices:
  12. -- Tool versions:
  13. -- Description:
  14. --       This module represents the controller for the Nexys4 onboard ADXL362 Accelerometer device.
  15. --    The module uses the SPI Interface component to communicate with the ADXL362.
  16. --    At initialization time, the module resets the ADXL362, then configures its internal registers.
  17. --       After configuring its internal registers, the acceleration will be read on the three axes followed
  18. --    by the temperature data: A set of 8 data bytes are read: XDATA_L, XDATA_H, YDATA_L, YDATA_H, ZDATA_L,
  19. --    ZDATA_H, TEMP_L and TEMP_H, see the ADXL362 datasheet for details.
  20. --       Reading is done continuously and an average is made from a number of reads. The number of reads
  21. --    for which average is made should be a power of two and is determined by the NUM_READS_AVG parameter,
  22. --    by default 16. The UPDATE_FREQUENCY_HZ parameter sets a counter to a period of 1/UPDATE_FREQUENCY_HZ.
  23. --    The state machine will wait for this period of time before starting a number of NUM_READS_AVG times
  24. --    data read procedure.
  25. --       Before reading a set of data, the state machine reads and checks the status register to see when
  26. --    new data is available at the ADXL362. Therefore the real sample time depends on the ADXL362 sample
  27. --    frequency, set in the Filter Control Register, address 0x2C, in this project set by default to 200Hz.
  28. --
  29. --       The module consists of three state machines, named by the signals holding the states:
  30. --       - SPI Send/Receive Control State Machine: StC_Spi_SendRec. This state machine creates a handshake transaction
  31. --    with the SPI Interface component, using the Start and Done signals to:
  32. --             - Send the number of bytes specified by the Cnt_Bytes_Sent counter (3 when configuring an ADXL362 internal
  33. --          register, 2 when sending a Read Command). The bytes to be sent through the SPI interface are taken from the
  34. --          command register, Cmd_Reg.
  35. --             - Receive the number of bytes specified by the Cnt_Bytes_Rec counter (8 when reading acceleration and
  36. --          temperature data, 1 when reading the status register), when reading is required (SPI_RnW = 1).
  37. --          The acceleration and temperature data is stored in the data register, Data_Reg
  38. --
  39. --       - SPI Transaction State machine, StC_Spi_Trans. This state machine controls the previously described SPI
  40. --    Send/Receive Control State Machine, using handshake with the the StartSpiSendRec (write) and SPI_SendRec_Done (read)
  41. --    signals:
  42. --            - Prepares and loads the command register, Cmd_Reg with the appropiate command string (configure a specific
  43. --          register, read data or read status)
  44. --            - Loads Cnt_Bytes_Sent and Cnt_Bytes_Rec with the number of bytes to be sent and/or received
  45. --            - Activates StartSpiSendRec to start the SPI Send/Receive Control State Machine and wait for its answer
  46. --          by reading the SPI_SendRec_Done signal
  47. --
  48. --          Note that between each SPI transaction (Register write or Register read) the SS signal has to be deactivated
  49. --          for at least 10nS before a new command is issued
  50. --
  51. --       - ADXL 362 Control State Machine, StC_Adxl_Ctrl. This state machine controls the previously described SPI
  52. --    Transaction State machine, also by using handshake with the StartSpiTr (write) and SPI_Trans_Done (read) signals:
  53. --            1. First, Cmd_Reg will be loaded with the reset command from the Cmd_Reg_Data ROM and the state machine starts
  54. --          the SPI Transaction State Machine to send the reset command to the ADXL362 accelerometer
  55. --            2. The state machine waits for a period of time and then sends the remaining configuration register data from
  56. --          Cmd_Reg_Data to the ADXL362 accelerometer
  57. --            3. After configuring ADXL362, the state machine waits for a period of time equal to 1/UPDATE_FREQUENCY_HZ
  58. --          before starts reading
  59. --            4. After the period of time elapsed the state machine reads the status register and, when there is new data available, reads the
  60. --          reads the X, Y and Z acceleration data, followed by temperature data.
  61. --               A number of reads equal to NUM_READS_AVG is performed, i.e. Step 4 is repeated NUM_READS_AVG times.
  62. --            5. The data read is averaged in the ACCEL_X_SUM, ACCEL_Y_SUM, ACCEL_Z_SUM and ACCEL_TMP_SUM registers. The
  63. --          NUM_READS_AVG is power of 2 in order to make averaging easier by removing the least significant bits. After
  64. --          a number of reads equal to NUM_READS_AVG is done, the state machine updates the output data, ACCEL_X, ACCEL_Y,
  65. --          ACCEL_Z and ACCEL_TMP, stored in 12-bit two's complement format and signals to the output by activating for one
  66. --          clock period the Data_Ready signal.
  67. --               After that the state machine proceeds to Step 3, in an infinite loop. The state machine restarts from Step 1 only
  68. --          when the FPGA is reconfigured or the Reset signal is activated.
  69. --
  70. -- Revision:
  71. -- Revision 0.01 - File Created
  72. -- Additional Comments:
  73. --
  74. ----------------------------------------------------------------------------------
  75. library IEEE;
  76. use IEEE.STD_LOGIC_1164.ALL;
  77.  
  78. -- Uncomment the following library declaration if using
  79. -- arithmetic functions with Signed or Unsigned values
  80. use IEEE.NUMERIC_STD.ALL;
  81. use IEEE.std_logic_signed.all;
  82. use IEEE.math_real.all;
  83.  
  84. -- Uncomment the following library declaration if instantiating
  85. -- any Xilinx primitives in this code.
  86. --library UNISIM;
  87. --use UNISIM.VComponents.all;
  88.  
  89. entity ADXL362Ctrl is
  90. generic
  91. (
  92.    SYSCLK_FREQUENCY_HZ : integer := 100000000;
  93.    SCLK_FREQUENCY_HZ   : integer := 1000000;
  94.    NUM_READS_AVG       : integer := 16;
  95.    UPDATE_FREQUENCY_HZ : integer := 1000
  96. );
  97. port
  98. (
  99.    SYSCLK     : in STD_LOGIC; -- System Clock
  100.    RESET      : in STD_LOGIC;
  101.  
  102.    -- Accelerometer data signals
  103.    ACCEL_X    : out STD_LOGIC_VECTOR (11 downto 0);
  104.    ACCEL_Y    : out STD_LOGIC_VECTOR (11 downto 0);
  105.    ACCEL_Z    : out STD_LOGIC_VECTOR (11 downto 0);
  106.    ACCEL_TMP  : out STD_LOGIC_VECTOR (11 downto 0);
  107.    Data_Ready : out STD_LOGIC;
  108.  
  109.    --SPI Interface Signals
  110.    SCLK       : out STD_LOGIC;
  111.    MOSI       : out STD_LOGIC;
  112.    MISO       : in STD_LOGIC;
  113.    SS         : out STD_LOGIC
  114. );
  115. end ADXL362Ctrl;
  116.  
  117. architecture Behavioral of ADXL362Ctrl is
  118.  
  119. -- SPI Interface component declaration
  120. component SPI_If is
  121. generic
  122. (
  123.    SYSCLK_FREQUENCY_HZ : integer:= 100000000;
  124.    SCLK_FREQUENCY_HZ : integer:= 1000000
  125. );
  126. port
  127. (
  128.  SYSCLK     : in STD_LOGIC; -- System Clock
  129.  RESET      : in STD_LOGIC;
  130.  Din        : in STD_LOGIC_VECTOR (7 downto 0); -- Data to be transmitted
  131.  Dout       : out STD_LOGIC_VECTOR (7 downto 0); -- Data received;
  132.  Start      : in STD_LOGIC; -- used to start the transmission
  133.  Done       : out STD_LOGIC; -- Signaling that transmission ended
  134.  HOLD_SS   : in STD_LOGIC; -- Signal that forces SS low in the case of multiple byte
  135.                            -- transmit/receive mode
  136.  --SPI Interface Signals
  137.  SCLK       : out STD_LOGIC;
  138.  MOSI       : out STD_LOGIC;
  139.  MISO       : in STD_LOGIC;
  140.  SS         : out STD_LOGIC
  141. );
  142. end component;
  143.  
  144. --**************************************
  145. -- Constant Definitions
  146. --**************************************
  147.  
  148. -- To create the update frequency counter
  149. constant UPDATE_DIV_RATE : integer := (SYSCLK_FREQUENCY_HZ / UPDATE_FREQUENCY_HZ);
  150. constant SYS_CLK_PERIOD_PS : integer := ((1000000000 / SYSCLK_FREQUENCY_HZ) * 1000);
  151.  
  152. --ADXL 362 Read and Write Command
  153. constant READ_CMD : STD_LOGIC_VECTOR (7 downto 0) := X"0B";
  154. constant WRITE_CMD : STD_LOGIC_VECTOR (7 downto 0) := X"0A";
  155. -- Data read will be always performed starting from Address X"0E",
  156. -- representing XACC_H. A total number of 8 bytes will be read.
  157. constant READ_STARTING_ADDR : STD_LOGIC_VECTOR (7 downto 0):= X"0E";
  158. -- Status Register Read will be used to check when new data is available (Bit 0 is 1)
  159. constant STATUS_REG_ADDR : STD_LOGIC_VECTOR (7 downto 0):= X"0B";
  160.  
  161. -- Number of bytes to write when configuring registers
  162. constant NUMBYTES_CMD_CONFIG_REG : integer := 3;
  163. -- Number of bytes to write when reading registers
  164. constant NUMBYTES_CMD_READ : integer := 2;
  165.  
  166. -- Number of bytes to read when reading data from ADXL362
  167. constant NUMBYTES_READ_DATA : integer := 8;
  168. -- Number of bytes to read when reading status register from ADXL362
  169. constant NUMBYTES_READ_STATUS : integer := 1;
  170.  
  171. -- number of command vectors to send, one command vector
  172. -- represents ADXL362 register address followed by command byte,
  173. -- i.e. one command vector will mean two bytes
  174. constant NUM_COMMAND_VEC : integer := 4;
  175.  
  176. -- Number of reads to be performed for which average is calculated, default is 16
  177. constant NUM_READS : natural := NUM_READS_AVG;
  178. -- Number of extra bits when creating the average of the reads
  179. constant NUM_READS_BITS : natural := natural(ceil(log(real(NUM_READS), 2.0)));
  180.  
  181. -- after each SPI transaction, SS needs to be inactive for at least 10ns before a new command is issued
  182. constant SS_INACTIVE_PERIOD_NS : integer := 10000;
  183. constant SS_INACTIVE_CLOCKS   : integer := (SS_INACTIVE_PERIOD_NS/(SYS_CLK_PERIOD_PS/1000));
  184.  
  185. -- To specify encoding of the state machines
  186. attribute FSM_ENCODING : string;
  187.  
  188. --SPI Interface Control Signals
  189. signal Start      :  STD_LOGIC; -- Signal controlling the SPI interface, controlled by the SPI Send/Receive State Machine
  190. signal Done       :  STD_LOGIC; -- Signaling that transmission ended, coming from the SPI interface
  191. signal HOLD_SS    :  STD_LOGIC; -- Signal that forces SS low in the case of multiple byte
  192.                            -- transmit/receive mode, controlled by the SPI Transaction State Machine
  193.                            
  194. -- Create the initialization vector, i.e.
  195. -- the register data to be written to initialize ADXL362
  196. type rom_type is array (0 to ((2* NUM_COMMAND_VEC)-1)) of STD_LOGIC_VECTOR (7 downto 0);
  197.  
  198. constant Cmd_Reg_Data : rom_type := ( X"1F", X"52", -- Soft Reset Register Address and Reset Command
  199.                                       X"1F", X"00", -- Soft Reset Register Address, clear Command
  200.                                       X"2D", X"02", -- Power Control Register, Enable Measure Command
  201.                                       X"2C", X"14"  -- Filter Control Register, 2g range, 1/4 Bandwidth, 200HZ Output Data Rate                                      
  202.                                      );
  203.  
  204. --address the reg_data ROM
  205. signal Cmd_Reg_Data_Addr: integer range 0 to (NUM_COMMAND_VEC - 1) := 0;
  206. -- Enable Incrementing Cmd_Reg_Data_Addr, controlled by the ADXL Control State machine
  207. signal EN_Advance_Cmd_Reg_Addr:  STD_LOGIC := '0';
  208. -- will enable incrementing by 2 Cmd_Reg_Data_Addr
  209. signal Advance_Cmd_Reg_Addr:  STD_LOGIC := '0';
  210. -- signal that shows that all of the addresses were read
  211. signal Cmd_Reg_Addr_Done : STD_LOGIC := '0';
  212.  
  213. -- SPI Transfer Send Data signals. Writing Commands will be always a 3-byte transfer,
  214. -- therefore commands will be temporarry stored in a 3X8 shift register.
  215. type command_reg_type is array (0 to 2) of STD_LOGIC_VECTOR (7 downto 0);
  216. signal Cmd_Reg: command_reg_type := (X"00", X"00", WRITE_CMD);
  217.  
  218. -- command_reg control signals
  219. signal Load_Cmd_Reg : STD_LOGIC := '0';  -- Controlled by the SPI Transaction State Machine,
  220.                                          -- the command register is load with the appropiate command
  221. signal Shift_Cmd_Reg : STD_LOGIC := '0'; -- Controlled by the SPI Send/Receive State Machine,
  222.                                          -- advance to the next command when a byte was sent
  223.                                            
  224. -- to count the bytes to be sent
  225. -- Cnt_Bytes_Sent will decrement at the same time when
  226. -- cmd_reg is shifted, therefore its control signal is the same as
  227. -- for Cmd_Reg: EN_Shift_Cmd_Reg
  228. signal Cnt_Bytes_Sent : integer range 0 to 3 :=0;
  229. -- Load Cnt_Bytes_Sent with the number of bytes to be sent
  230. -- according to the command to be sent
  231. signal Load_Cnt_Bytes_Sent : STD_LOGIC := '0'; -- controlled by the SPI Transaction State Machine
  232.  
  233. signal Reset_Cnt_Bytes : STD_LOGIC := '0'; -- Controlled by the Main State Machine
  234.                                            -- will reset both the sent and received byte counter
  235.  
  236. -- SPI Transfer Receive Data signals. Reading data will be a 8-byte transfer:
  237. -- XACC_H, XACC_L, YACC_H, YACC_L, ZACC_H, ZACC_L, TEMP_H, TEMP_L
  238. -- therefore an 8X8 shift register is created.
  239. type data_reg_type is array (0 to (NUMBYTES_READ_DATA - 1)) of STD_LOGIC_VECTOR (7 downto 0);
  240. signal Data_Reg: data_reg_type := (others => X"00");
  241.  
  242. -- data_reg control signals:
  243. signal EN_Shift_Data_Reg : STD_LOGIC := '0'; -- Controlled by the SPI Send/Receive State Machine
  244.                                              -- Shift when a new byte was received
  245. -- Data Reg will be shifted when a new byte comes, i.e. Shift_Data_Reg <= EN_Shift_Data_Reg AND Done;
  246. signal Shift_Data_Reg : STD_LOGIC := '0';                                            
  247.  
  248. -- to count the bytes to be received
  249. -- Cnt_Bytes_Rec will decrement at the same time when Data_Reg is shifted,
  250. -- therefore its control signal is the same as for Data_Reg: Shift_Data_Reg
  251. signal Cnt_Bytes_Rec : integer range 0 to NUMBYTES_READ_DATA - 1 := 0;
  252. -- Load Cnt_Bytes_Rec with the number of bytes to be received, controlled by the SPI Transaction State Machine
  253. signal Load_Cnt_Bytes_Rec : STD_LOGIC := '0';
  254.  
  255. -- SPI Data to Send and Data Received registers
  256. -- Data to send register will be loaded together with shifting
  257. -- a new byte in Cmd_Reg, i.e. its control signal is Shift_Cmd_Reg
  258. -- Data Received Register will be read when shifting Data_Reg
  259. signal D_Send   : STD_LOGIC_VECTOR (7 downto 0) := X"00";
  260. signal D_Rec   : STD_LOGIC_VECTOR (7 downto 0) := X"00";
  261.  
  262. -- SPI Send/Receive State Machine internal condition signals
  263. signal StartSpiSendRec  : STD_LOGIC := '0'; -- Start SPI transfer, controlled by the SPI Transaction State Machine
  264. signal SPI_RnW  : STD_LOGIC := '0'; -- Write 3 bytes or write 2 bytes followed by read 1 byte or 8 bytes
  265. signal SPI_WR_Done   : STD_LOGIC := '0'; -- Active when the write transfer is done, i.e. 2 or 3 bytes were written
  266. signal SPI_RD_Done   : STD_LOGIC := '0'; -- Active when the read transfer is done, i.e. 8 bytes were read
  267.  
  268. -- SPI Send/Receive State Machine status signals, used by the SPI Transaction State Machine
  269. signal SPI_SendRec_Done  : STD_LOGIC := '0';
  270.  
  271. -- Define Control Signals, Status signals and States for the SPI Send/Receive State Machine
  272. -- From MSB: 6:Shift_Cmd_Reg, 5:EN_Shift_Data_Reg, 4:SPI_SendRec_Done, 3:Start, 2:STC(2), 1:STC(1), 0:STC(0)
  273.                                                           -- bit  6543210
  274. constant stSpiSendRecIdle     : STD_LOGIC_VECTOR (6 downto 0) := "0000000"; -- Idle state, wait for StartSpiSendRec
  275. constant stSpiPrepareCmd      : STD_LOGIC_VECTOR (6 downto 0) := "1000001"; -- Load D_Send with the next byte and shift the command register
  276. constant stSpiSendStartW      : STD_LOGIC_VECTOR (6 downto 0) := "0001011"; -- Send the Start command to the SPI interface
  277. constant stSpiWaitOnDoneW     : STD_LOGIC_VECTOR (6 downto 0) := "0000111"; -- Wait until Done comes
  278. constant stSpiSendStartR      : STD_LOGIC_VECTOR (6 downto 0) := "0001110"; -- Send Start command again to the SPI interface if read was requested
  279. constant stSpiWaitOnDoneR     : STD_LOGIC_VECTOR (6 downto 0) := "0100100"; -- Wait until Done comes
  280. constant stSpiSendRecDone     : STD_LOGIC_VECTOR (6 downto 0) := "0010101"; -- Done state, return to Idle
  281.  
  282. --State Machine Signal Definitions
  283. signal StC_Spi_SendRec, StN_Spi_SendRec   :  STD_LOGIC_VECTOR (6 downto 0) := stSpiSendRecIdle;
  284. --Force User Encoding for the State Machine
  285. attribute FSM_ENCODING of StC_Spi_SendRec: signal is "USER";
  286.  
  287. -- Self-blocking counter for SS_INACTIVE_CLOCKS periods while SS is inactive
  288. signal Cnt_SS_Inactive : integer range 0 to (SS_INACTIVE_CLOCKS -1) := 0;
  289. -- controlled by the SPI Transaction State Machine
  290. signal Reset_Cnt_SS_Inactive : STD_LOGIC := '0';
  291. -- Signaling that SS_INACTIVE_PERIOD passed
  292. signal Cnt_SS_Inactive_done : STD_LOGIC := '0';
  293.  
  294. -- Signaling that SPI Transaction is done
  295. signal SPI_Trans_Done   : STD_LOGIC := '0';
  296.  
  297. -- SPI Transaction State Machine internal Condition Signals, controlled
  298. -- by the ADXL 362 Control State Machine
  299. signal StartSpiTr  : STD_LOGIC := '0'; -- Start SPI transaction
  300.  
  301. -- Define Control Signals, Status signals and States for the SPI Transaction State Machine
  302. -- From MSB: 9:Load_Cmd_Reg, 8:Load_Cnt_Bytes_Sent, 7:Load_Cnt_Bytes_Rec, 6:StartSpiSendRec,
  303. -- 5:HOLD_SS, 4:Reset_Cnt_SS_Inactive, 3:SPI_Trans_Done, 2:STC(2), 1:STC(1), 0:STC(0)
  304.                                                           -- bit  9876543210
  305. constant stSpiTransIdle       : STD_LOGIC_VECTOR (9 downto 0) := "0000000000"; -- Idle state, wait for StartSpiTr
  306. constant stSpiPrepAndSendCmd  : STD_LOGIC_VECTOR (9 downto 0) := "1111100001"; -- Load Cmd_Reg with the command string and activate StartSpiSendRec
  307. constant stSpiWaitonDoneSR    : STD_LOGIC_VECTOR (9 downto 0) := "0000110011"; -- Wait until SPI_SendRec_Done becomes active
  308. constant stSpiWaitForSsInact  : STD_LOGIC_VECTOR (9 downto 0) := "0000000010"; -- Wait for SS_INACTIVE_PERIOD
  309. constant stSpiTransDone       : STD_LOGIC_VECTOR (9 downto 0) := "0000001110"; -- Done state, return to Idle
  310.  
  311. --State Machine Signal Definitions
  312. signal StC_Spi_Trans, StN_Spi_Trans : STD_LOGIC_VECTOR (9 downto 0) := stSpiTransIdle;
  313. --Force User Encoding for the State Machine
  314. attribute FSM_ENCODING of StC_Spi_Trans: signal is "USER";
  315.  
  316. -- Data from the ADXL 362 will be sampled at a period defined by UPDATE_DIV_RATE
  317. -- Divider used to generate the Sample_Rate_Tick, used also for timing
  318. signal Sample_Rate_Div        : integer range 0 to (UPDATE_DIV_RATE - 1) := 0;
  319. signal Reset_Sample_Rate_Div  : STD_LOGIC := '0';
  320. signal Sample_Rate_Tick       : STD_LOGIC := '0';
  321.  
  322. -- A number of 16 reads will be performed from the ADXL 362,
  323. -- and their average will be sent as data
  324. signal Cnt_Num_Reads : integer range 0 to (NUM_READS - 1) := 0;
  325. signal CE_Cnt_Num_Reads : STD_LOGIC := '0'; -- enable counting, controlled by the ADXL 362 Control State Machine
  326. signal Reset_Cnt_Num_Reads : STD_LOGIC := '0';
  327. --Signaling that a number of 16 reads were done
  328. signal Cnt_Num_Reads_Done : STD_LOGIC := '0';
  329.  
  330. -- Summing of incoming data will be stored in these signals
  331. -- These will be used as accumulators, on two's complement
  332. signal ACCEL_X_SUM   : STD_LOGIC_VECTOR ((11 + (NUM_READS_BITS)) downto 0) := (others => '0');
  333. signal ACCEL_Y_SUM   : STD_LOGIC_VECTOR ((11 + (NUM_READS_BITS)) downto 0) := (others => '0');
  334. signal ACCEL_Z_SUM   : STD_LOGIC_VECTOR ((11 + (NUM_READS_BITS)) downto 0) := (others => '0');
  335. signal ACCEL_TMP_SUM : STD_LOGIC_VECTOR ((11 + (NUM_READS_BITS)) downto 0) := (others => '0');
  336.  
  337. -- Enables Summing the incomming data
  338. signal Enable_Sum : STD_LOGIC := '0';
  339. -- Pipe Data_Ready to have stable data at the output when activates
  340. signal Data_Ready_1 : STD_LOGIC := '0';
  341.  
  342. -- ADXL 362 Control State Machine - The Main State Machine Internal Condition Signal
  343. signal Adxl_Data_Ready : STD_LOGIC := '0'; -- showing that data is ready, read from the ADXL 362 Status Register
  344. signal Adxl_Conf_Err : STD_LOGIC := '0'; -- showing that a configuration error ocurred, read from the ADXL 362 Status Register
  345.  
  346. -- Define Control Signals, Status signals and States for the ADXL 362 Control State Machine
  347. -- From MSB: 11:Reset_Cnt_Bytes, 10:EN_Advance_Cmd_Reg_Addr, 9:StartSpiTr, 8:Reset_Cnt_Num_Reads,
  348. -- 7:CE_Cnt_Num_Reads, 6:Reset_Sample_Rate_Div, 5:Enable_Sum, 4:Data_Ready_1, 3:STC(3), 2:STC(2), 1:STC(1), 0:STC(0)
  349.                                                                --       11
  350.                                                                -- bit   109876543210
  351. constant stAdxlCtrlIdle            : STD_LOGIC_VECTOR (11 downto 0) := "100100000000"; -- Idle state, wait for 10 clock periods before start
  352. constant stAdxlSendResetCmd        : STD_LOGIC_VECTOR (11 downto 0) := "011001000001"; -- Send the Reset Command for ADXL
  353. constant stAdxlWaitResetDone       : STD_LOGIC_VECTOR (11 downto 0) := "010000000011"; -- Wait for some time until ADXL initializes.
  354.                                                                                                -- The sample rate divider is used for timing
  355. constant stAdxlConf_Remaining      : STD_LOGIC_VECTOR (11 downto 0) := "011001000010"; -- Clear the Reset Register,
  356.                                                                                                -- then configure the remaining registers
  357. constant stAdxlWaitSampleRateTick  : STD_LOGIC_VECTOR (11 downto 0) := "000100000110"; -- wait until the sample time passes
  358. constant stAdxlRead_Status         : STD_LOGIC_VECTOR (11 downto 0) := "011001000111"; -- Read the status register from ADXL 362
  359. constant stAdxlRead_Data           : STD_LOGIC_VECTOR (11 downto 0) := "011000000101"; -- Read the data from ADXL 362
  360. constant stAdxlFormatandSum        : STD_LOGIC_VECTOR (11 downto 0) := "000010101101"; -- Store and sum the received data
  361.                                                                                                -- If 16 reads were done, go to the Done state
  362. constant stAdxlRead_Done           : STD_LOGIC_VECTOR (11 downto 0) := "000001011111"; -- Done state, return to stAdxlWaitSampleRateTick
  363.  
  364. --State Machine Signal Definitions
  365. signal StC_Adxl_Ctrl, StN_Adxl_Ctrl : STD_LOGIC_VECTOR (11 downto 0) := stAdxlCtrlIdle;
  366. --Force User Encoding for the State Machine
  367. attribute FSM_ENCODING of StC_Adxl_Ctrl: signal is "USER";
  368.  
  369.  
  370. begin
  371.  
  372. --Instantiate the SPI interface first
  373. SPI_Interface: SPI_If
  374. generic map
  375. (
  376.    SYSCLK_FREQUENCY_HZ => SYSCLK_FREQUENCY_HZ,
  377.    SCLK_FREQUENCY_HZ => SCLK_FREQUENCY_HZ
  378. )
  379. port map
  380. (
  381.  SYSCLK => SYSCLK,  
  382.  RESET  => RESET,
  383.  Din    => D_Send,
  384.  Dout   => D_Rec,
  385.  Start  => Start,
  386.  Done   => Done,
  387.  HOLD_SS => HOLD_SS,
  388.  --SPI Interface Signals
  389.  SCLK  => SCLK,
  390.  MOSI  => MOSI,
  391.  MISO  => MISO,
  392.  SS    => SS
  393. );
  394.  
  395. -- Assign the control and status signals of the SPI Send/Receive State Machine
  396. Shift_Cmd_Reg     <= StC_Spi_SendRec(6); -- Shift Cmd_Reg when New data is loading into D_Send
  397. EN_Shift_Data_Reg <= StC_Spi_SendRec(5); -- Enable shifting the data register from D_Rec, shifting is performed when a new byte comes, i.e Done becomes active
  398. SPI_SendRec_Done  <= StC_Spi_SendRec(4); -- Transfer of the number of bytes is done
  399. Start             <= StC_Spi_SendRec(3); -- Send the Start command to the SPI interface
  400.                                           --in the stSpiSendStartW (writing) or stSpiSendStartR (Reading) states
  401. -- Load D_Send with the new data to be transmitted
  402. Load_D_Send: process (SYSCLK, RESET, Cmd_Reg, Shift_Cmd_Reg)
  403. begin
  404.    if SYSCLK'EVENT AND SYSCLK = '1' then
  405.       if RESET = '1' then
  406.          D_Send <= X"00";
  407.       elsif Shift_Cmd_Reg = '1' then
  408.          D_Send <= Cmd_Reg (2);
  409.       end if;
  410.    end if;
  411. end process Load_D_Send;
  412.  
  413.  
  414. -- Assign the control and status signals of the SPI Transaction State Machine
  415. Load_Cmd_Reg          <= StC_Spi_Trans(9); -- Load the Command Register when preparing the command to be sent to ADXL
  416. Load_Cnt_Bytes_Sent   <= StC_Spi_Trans(8); -- Also load the counter of bytes to be sent
  417. Load_Cnt_Bytes_Rec    <= StC_Spi_Trans(7); -- And, in the case of reception, the counter of bytes to be received
  418. StartSpiSendRec       <= StC_Spi_Trans(6); -- Also send the start command to the SPI Send/Receive State Machine
  419. -- Note that the signals above are active at the same time, i.e identical. They will be optimized by the synthesizer
  420.  
  421. HOLD_SS               <= StC_Spi_Trans(5); -- Each SPI send/receive will be multiple byte transfer, so activate HOLD_SS
  422. Reset_Cnt_SS_Inactive <= StC_Spi_Trans(4); -- Keep the Cnt_SS_Inactive counter reset, until the transfer is done
  423.                                           -- in the next state the state machine will raise SS for a period of SS_INACTIVE_PERIOD_NS
  424. SPI_Trans_Done        <= StC_Spi_Trans(3); -- Signals that the SPI transfer is done
  425.  
  426.  
  427.  
  428. -- Assign the control and status signals of the ADXL 362 Control State Machine
  429. Reset_Cnt_Bytes         <= StC_Adxl_Ctrl(11); -- Reset the counters for bytes to send and receive. These counters are reset
  430.                                               -- at initializing, then reloaded at each new transaction
  431. EN_Advance_Cmd_Reg_Addr <= StC_Adxl_Ctrl(10); -- Advance the address of the command vectors, to load a new command
  432. StartSpiTr              <= StC_Adxl_Ctrl(9);  -- Send the Start command to the SPI Transaction State Machine
  433. Reset_Cnt_Num_Reads     <= StC_Adxl_Ctrl(8);  -- Reset the counter, once at initialization time, then before starting data read,
  434.                                               -- i.e in the stAdxlRead_Status state
  435. CE_Cnt_Num_Reads        <= StC_Adxl_Ctrl(7);  -- Increment Cnt_Num_Reads after a new set of data come i.e. in the stAdxlFormatandSum state
  436. Reset_Sample_Rate_Div   <= StC_Adxl_Ctrl(6);  -- Reset the Sample_Rate_Div counter before entering in the sample period wait state
  437.                                               -- i.e. in the stAdxlConf_Remaining and the stAdxlRead_Done
  438. Enable_Sum              <= StC_Adxl_Ctrl(5);  -- After new data set come, enable summing
  439. Data_Ready_1            <= StC_Adxl_Ctrl(4);  -- To signal external components that new data set is available, coming from 16 reads
  440.  
  441.  
  442. -- Load and shift Cmd_Reg according to the active commands
  443. Load_Shift_Cmd_Reg: process (SYSCLK, Cmd_Reg, Cmd_Reg_Data_Addr, StC_Adxl_Ctrl, Load_Cmd_Reg, Shift_Cmd_Reg)
  444. begin
  445.    if SYSCLK'EVENT AND SYSCLK = '1' then
  446.       if Load_Cmd_Reg = '1' then -- Load with data
  447.          if       (StC_Adxl_Ctrl = stAdxlSendResetCmd)
  448.                or (StC_Adxl_Ctrl = stAdxlConf_Remaining) then -- In this case load with command vectors
  449.  
  450.                   Cmd_Reg(2) <= WRITE_CMD;
  451.                   Cmd_Reg(1) <= Cmd_Reg_Data (2 * Cmd_Reg_Data_Addr);
  452.                   Cmd_Reg(0) <= Cmd_Reg_Data ((2 * Cmd_Reg_Data_Addr) + 1);
  453.  
  454.          elsif    (StC_Adxl_Ctrl = stAdxlRead_Status) then
  455.  
  456.                   Cmd_Reg(2) <= READ_CMD;
  457.                   Cmd_Reg(1) <= STATUS_REG_ADDR;
  458.                   Cmd_Reg(0) <= X"00";
  459.          
  460.          elsif (StC_Adxl_Ctrl = stAdxlRead_Data) then -- In this case load with command vectors
  461.  
  462.                   Cmd_Reg(2) <= READ_CMD;
  463.                   Cmd_Reg(1) <= READ_STARTING_ADDR;
  464.                   Cmd_Reg(0) <= X"00";
  465.          end if;
  466.          
  467.       elsif Shift_Cmd_Reg = '1' then -- shift to load D_send with the new command byte
  468.  
  469.                   Cmd_Reg(2) <= Cmd_Reg(1);
  470.                   Cmd_Reg(1) <= Cmd_Reg(0);
  471.                   Cmd_Reg(0) <= X"00";
  472.       end if;
  473.    end if;
  474. end process Load_Shift_Cmd_Reg;
  475.  
  476. -- Create the address counter for the Cmd_Reg_Data command vectors
  477. -- Increment by two the Cmd_Reg_Data_Addr after a SPI Register Write transaction is done
  478. Advance_Cmd_Reg_Addr <= EN_Advance_Cmd_Reg_Addr AND SPI_Trans_Done;
  479.  
  480. Count_Addr: process (SYSCLK, RESET, Cmd_Reg_Data_Addr, StC_Adxl_Ctrl, Advance_Cmd_Reg_Addr)
  481. begin
  482.    if SYSCLK'EVENT AND SYSCLK = '1' then
  483.       if RESET = '1'  or StC_Adxl_Ctrl = stAdxlCtrlIdle then
  484.          Cmd_Reg_Data_Addr <= 0;
  485.       elsif Advance_Cmd_Reg_Addr = '1' then
  486.          if Cmd_Reg_Data_Addr =  (NUM_COMMAND_VEC - 1) then -- Avoid to address Cmd_Reg_Data out of range
  487.             Cmd_Reg_Data_Addr <= 0;
  488.          else
  489.             Cmd_Reg_Data_Addr <= Cmd_Reg_Data_Addr + 1;
  490.          end if;
  491.       end if;
  492.    end if;
  493. end process Count_Addr;
  494.  
  495. -- Signal when all of the addresses were read
  496. Cmd_Reg_Addr_Done <= '1' when Cmd_Reg_Data_Addr = (NUM_COMMAND_VEC - 1) else '0';
  497.  
  498.  
  499. -- Shift Data_Reg when a new byte comes
  500. Shift_Data_Reg <= EN_Shift_Data_Reg AND Done;
  501. -- Read incoming data
  502. Read_Data: process (SYSCLK, Shift_Data_Reg, D_Rec, Data_Reg) -- When reading the status register, one byte is read, therefore
  503. variable i: integer range 0 to 6 := 0;                       -- the status register data will be on Data_Reg(0)
  504. begin                                                        -- When reading incoming data, exactly 8 reads are performed,
  505.    if SYSCLK'EVENT AND SYSCLK = '1' then                     -- therefore no initialization is required for Data_Reg
  506.       if Shift_Data_Reg = '1' then                    
  507.          for i in 0 to 6 loop
  508.             Data_Reg(i+1) <= Data_Reg(i);
  509.          end loop;
  510.             Data_Reg(0) <= D_Rec;
  511.       end if;
  512.    end if;
  513. end process Read_Data;
  514.  
  515. -- Count the bytes to be send and to be received
  516. Count_Bytes_Send: process (SYSCLK, Reset_Cnt_Bytes, Load_Cnt_Bytes_Sent, Shift_Cmd_Reg, Cnt_Bytes_Sent)
  517. begin
  518.    if SYSCLK'EVENT AND SYSCLK = '1' then
  519.       if Reset_Cnt_Bytes = '1' then
  520.           Cnt_Bytes_Sent <= 0;
  521.          
  522.       elsif Load_Cnt_Bytes_Sent = '1' then
  523.  
  524.         if   (StC_Adxl_Ctrl = stAdxlSendResetCmd)
  525.           or (StC_Adxl_Ctrl = stAdxlConf_Remaining) then -- In this case send 3 command bytes
  526.                   -- Decrementing and shifting Cmd_Reg will be done BEFORE sending data
  527.                   -- through the serial interface, therefore load NUMBYTES_CMD_CONFIG_REG or NUMBYTES_CMD_READ.
  528.                   -- The condition to end SPI send operation is Cnt_Bytes_Sent = 0 AND Done = '1'
  529.                   Cnt_Bytes_Sent <= NUMBYTES_CMD_CONFIG_REG;
  530.  
  531.         elsif  (StC_Adxl_Ctrl = stAdxlRead_Status)
  532.             or (StC_Adxl_Ctrl = stAdxlRead_Data) then -- In the case of read command, send 2 command bytes
  533.  
  534.                   Cnt_Bytes_Sent <= NUMBYTES_CMD_READ;
  535.         else
  536.                   Cnt_Bytes_Sent <= 0;
  537.         end if;
  538.  
  539.       elsif Shift_Cmd_Reg = '1' then -- When shifting Cmd_Reg, decrement the counter
  540.            if Cnt_Bytes_Sent = 0 then
  541.                Cnt_Bytes_Sent <= 0; -- Stay at 0, reload at the next SPI transaction
  542.            else
  543.                Cnt_Bytes_Sent <= Cnt_Bytes_Sent - 1;
  544.            end if;
  545.       end if;
  546.    end if;
  547. end process Count_Bytes_Send;
  548.  
  549.  
  550. Count_Bytes_Rec: process (SYSCLK, Reset_Cnt_Bytes, Load_Cnt_Bytes_Rec, Shift_Data_Reg, Cnt_Bytes_Rec)
  551. begin
  552.    if SYSCLK'EVENT AND SYSCLK = '1' then
  553.       if Reset_Cnt_Bytes = '1' then
  554.           Cnt_Bytes_Rec <= 0;
  555.  
  556.      elsif Load_Cnt_Bytes_Rec = '1' then
  557.         if   (StC_Adxl_Ctrl = stAdxlRead_Status)  then -- In this case we have to read 1 byte
  558.                  -- Decrementing and shifting Data_Reg will be done AFTER sending data
  559.                  -- through the serial interface, therefore load NUMBYTES_READ_STATUS - 1 or NUMBYTES_READ_DATA - 1.
  560.                  -- The condition to end SPI receive operation is Cnt_Bytes_Rec = 0 AND Done = '1'
  561.                   Cnt_Bytes_Rec <= NUMBYTES_READ_STATUS - 1;
  562.  
  563.         elsif (StC_Adxl_Ctrl = stAdxlRead_Data) then -- In the case we have to read 8 bytes
  564.                   Cnt_Bytes_Rec <= NUMBYTES_READ_DATA -1;
  565.         else
  566.                   Cnt_Bytes_Rec <= 0;
  567.         end if;
  568.        
  569.       elsif Shift_Data_Reg = '1' then -- When shifting Data_Reg, decrement the counter
  570.            if Cnt_Bytes_Rec = 0 then
  571.                Cnt_Bytes_Rec <= 0; -- Stay at 0, reload at the next SPI transaction
  572.            else
  573.                Cnt_Bytes_Rec <= Cnt_Bytes_Rec - 1;
  574.            end if;
  575.       end if;
  576.    end if;
  577. end process Count_Bytes_Rec;
  578.  
  579. -- Create the Sample_Rate_Div counter and the Sample_Rate_Tick signal
  580. Count_Sample_Rate_Div: process (SYSCLK, Reset_Sample_Rate_Div, Sample_Rate_Div)
  581. begin
  582.    if SYSCLK'EVENT AND SYSCLK = '1' then
  583.       if Reset_Sample_Rate_Div = '1' then
  584.          Sample_Rate_Div <= 0;
  585.       elsif Sample_Rate_Div = (UPDATE_DIV_RATE - 1) then  
  586.          Sample_Rate_Div <= 0;
  587.       else
  588.          Sample_Rate_Div <= Sample_Rate_Div + 1;
  589.       end if;
  590.    end if;
  591. end process Count_Sample_Rate_Div;
  592.  
  593. Sample_Rate_Tick  <= '1' when Sample_Rate_Div = (UPDATE_DIV_RATE - 1) else '0';
  594.  
  595.  
  596. -- Create the Cnt_Num_Reads counter, self-blocking
  597. Count_Num_Reads: process (SYSCLK, Reset_Cnt_Num_Reads, CE_Cnt_Num_Reads, Cnt_Num_Reads)
  598. begin
  599.    if SYSCLK'EVENT AND SYSCLK = '1' then
  600.       if Reset_Cnt_Num_Reads = '1' then
  601.          Cnt_Num_Reads <= 0;
  602.       elsif CE_Cnt_Num_Reads = '1' then
  603.             if Cnt_Num_Reads = (NUM_READS - 1) then  
  604.                Cnt_Num_Reads <= (NUM_READS - 1);
  605.             else
  606.                Cnt_Num_Reads <= Cnt_Num_Reads + 1;
  607.             end if;
  608.       end if;
  609.    end if;
  610. end process Count_Num_Reads;
  611.  
  612. Cnt_Num_Reads_Done <= '1' when Cnt_Num_Reads = (NUM_READS - 1) else '0';
  613.  
  614. -- Create the Cnt_SS_Inactive counter, also self_blocking
  615. Count_SS_Inactive: process (SYSCLK, RESET, Reset_Cnt_SS_Inactive, Cnt_SS_Inactive)
  616. begin
  617.    if SYSCLK'EVENT AND SYSCLK = '1' then
  618.       if RESET = '1' or Reset_Cnt_SS_Inactive = '1' then
  619.          Cnt_SS_Inactive <= 0;
  620.       elsif Cnt_SS_Inactive = (SS_INACTIVE_CLOCKS - 1) then  
  621.          Cnt_SS_Inactive <= (SS_INACTIVE_CLOCKS - 1);
  622.       else
  623.          Cnt_SS_Inactive <= Cnt_SS_Inactive + 1;
  624.       end if;
  625.    end if;
  626. end process Count_SS_Inactive;
  627.  
  628. Cnt_SS_Inactive_done <= '1' when Cnt_SS_Inactive = (SS_INACTIVE_CLOCKS - 1) else '0';
  629.  
  630.  
  631. -- SPI Send/Receive State Machine internal condition signals
  632. -- SPI_RnW will be controlled according to the states of the Adxl 362 Control state machine
  633. Set_SPI_RnW: process (SYSCLK, StC_Adxl_Ctrl)
  634. begin
  635.    if SYSCLK'EVENT AND SYSCLK = '1' then
  636.          if    (StC_Adxl_Ctrl = stAdxlRead_Status)
  637.             or (StC_Adxl_Ctrl = stAdxlRead_Data) then
  638.                   SPI_RnW <= '1';
  639.          else
  640.                   SPI_RnW <= '0';
  641.          end if;
  642.    end if;
  643. end process Set_SPI_RnW;
  644.  
  645.  
  646. -- SPI Send/Receive State machine internal condition signals
  647. SPI_WR_Done <= '1' when Cnt_Bytes_Sent = 0 AND Done = '1' else '0';
  648. SPI_RD_Done <= '1' when Cnt_Bytes_Rec = 0 AND Done = '1' else '0';
  649.  
  650. -- Spi Send/Receive State Machine register process
  651. Register_StC_Spi_SendRec: process (SYSCLK, RESET, StN_Spi_SendRec)
  652. begin
  653.       if SYSCLK'EVENT AND SYSCLK = '1' then
  654.          if RESET = '1' then
  655.             StC_Spi_SendRec <= stSpiSendRecIdle;
  656.          else
  657.             StC_Spi_SendRec <= StN_Spi_SendRec;
  658.          end if;
  659.       end if;
  660. end process Register_StC_Spi_SendRec;
  661.  
  662. -- Spi Send/Receive State Machine transitions process
  663. Cmb_StC_Spi_SendRec: process (StC_Spi_SendRec, StartSpiSendRec, StartSpiSendRec,
  664.                               SPI_WR_Done, SPI_RD_Done, SPI_RnW, Done)
  665. begin
  666.    StN_Spi_SendRec <= StC_Spi_SendRec; -- Default: Stay in the current state
  667.    case (StC_Spi_SendRec) is
  668.       when stSpiSendRecIdle => if (StartSpiSendRec = '1') then StN_Spi_SendRec <= stSpiPrepareCmd; end if;
  669.       when stSpiPrepareCmd  => StN_Spi_SendRec <= stSpiSendStartW;
  670.       when stSpiSendStartW  => StN_Spi_SendRec <= stSpiWaitOnDoneW;
  671.       when stSpiWaitOnDoneW => if (SPI_RnW = '1') then -- in the case of a read command proceed to reading data, if writing is done
  672.                                    if (SPI_WR_Done = '1') then StN_Spi_SendRec <= stSpiSendStartR;
  673.                                    elsif (Done = '1') then StN_Spi_SendRec <= stSpiPrepareCmd; -- Return to send the next command byte
  674.                                    end if;
  675.                                else
  676.                                     if (SPI_WR_Done = '1') then StN_Spi_SendRec <= stSpiSendRecDone; -- Sending command bytes finished
  677.                                     elsif (Done = '1') then StN_Spi_SendRec <= stSpiPrepareCmd; -- Return to send the next command byte
  678.                                     end if;
  679.                                end if;
  680.       when stSpiSendStartR  => StN_Spi_SendRec <= stSpiWaitOnDoneR; --Send Start command to the SPI interface and wait until reads a byte
  681.       when stSpiWaitOnDoneR => if (SPI_RD_Done = '1') then StN_Spi_SendRec <= stSpiSendRecDone; -- If all of the bytes were read
  682.                                elsif (Done = '1') then StN_Spi_SendRec <= stSpiSendStartR; -- Return and send another Start command to read
  683.                                end if;                                                     -- the next byte
  684.       when stSpiSendRecDone => StN_Spi_SendRec <= stSpiSendRecIdle;
  685.       when others => StN_Spi_SendRec <= stSpiSendRecIdle;
  686.    end case;
  687. end process Cmb_StC_Spi_SendRec;
  688.  
  689.  
  690. -- SPI Transaction State Machine register process
  691. Register_StC_Spi_Trans: process (SYSCLK, RESET, StN_Spi_Trans)
  692. begin
  693.       if SYSCLK'EVENT AND SYSCLK = '1' then
  694.          if RESET = '1' then
  695.             StC_Spi_Trans <= stSpiTransIdle;
  696.          else
  697.             StC_Spi_Trans <= StN_Spi_Trans;
  698.          end if;
  699.       end if;
  700. end process Register_StC_Spi_Trans;
  701.  
  702.  
  703. -- SPI Transaction State Machine transitions process
  704. Cmb_StC_Spi_Trans: process (StC_Spi_Trans, StartSpiTr, Cnt_SS_Inactive_done, SPI_SendRec_Done)
  705. begin
  706.    StN_Spi_Trans <= StC_Spi_Trans; -- Default: Stay in the current state
  707.    case (StC_Spi_Trans) is
  708.       when stSpiTransIdle      => if (StartSpiTr = '1') then StN_Spi_Trans <= stSpiPrepAndSendCmd; end if; -- Start SPI Transaction
  709.       when stSpiPrepAndSendCmd => StN_Spi_Trans <= stSpiWaitonDoneSR; -- Load Cmd_Reg, the Cnt_Bytes_Sent and Cnt_Bytes_Rec counters and send
  710.                                                                       -- the Start command to the Spi Send/Receive state machine
  711.       when stSpiWaitonDoneSR   => if (SPI_SendRec_Done = '1') then StN_Spi_Trans <= stSpiWaitForSsInact; end if; -- SPI Send/Receive done,
  712.                                                                                                            -- Discativate SS for SS_INACTIVE_CLOCKS
  713.       when stSpiWaitForSsInact => if (Cnt_SS_Inactive_done = '1') then StN_Spi_Trans <= stSpiTransDone; end if; -- SS_INACTIVE_CLOCKS passed, go to
  714.                                                                                                           -- the Done state
  715.       when stSpiTransDone      => StN_Spi_Trans <= stSpiTransIdle;
  716.       when others => StN_Spi_Trans <= stSpiTransIdle;
  717.    end case;
  718. end process Cmb_StC_Spi_Trans;
  719.  
  720. -- The Status Register read will be on Data_Reg(0), bit 0 shows if new data is ready
  721. -- Adxl_Data_Ready and Adxl_Conf_Err will be tested in the ADXL 362 Control State Machine, in the stAdxlRead_Status state
  722. Adxl_Data_Ready <= Data_Reg(0)(0);
  723. Adxl_Conf_Err <= Data_Reg(0)(7);
  724.  
  725. -- ADXL 362 Control State Machine register process
  726. Register_StC_Adxl_Ctrl: process (SYSCLK, RESET, StN_Adxl_Ctrl)
  727. begin
  728.       if SYSCLK'EVENT AND SYSCLK = '1' then
  729.          if RESET = '1' then
  730.             StC_Adxl_Ctrl <= stAdxlCtrlIdle;
  731.          else
  732.             StC_Adxl_Ctrl <= StN_Adxl_Ctrl;
  733.          end if;
  734.       end if;
  735. end process Register_StC_Adxl_Ctrl;
  736.  
  737. -- ADXL 362 Control State Machine Transitions process
  738. Cmb_StC_Adxl_Ctrl: process (StC_Adxl_Ctrl, Cnt_SS_Inactive_done, SPI_Trans_Done, Sample_Rate_Tick,
  739.                             Cmd_Reg_Addr_Done, Adxl_Data_Ready, Adxl_Conf_Err, Cnt_Num_Reads_Done)
  740. begin
  741.    StN_Adxl_Ctrl <= StC_Adxl_Ctrl; -- Default: Stay in the current state
  742.    case (StC_Adxl_Ctrl) is
  743.       when stAdxlCtrlIdle           => if (Sample_Rate_Tick = '1') then StN_Adxl_Ctrl <= stAdxlSendResetCmd; end if; -- wait for some clock periods
  744.                                                                                                                          -- before start
  745.       when stAdxlSendResetCmd       => if (SPI_Trans_Done = '1') then StN_Adxl_Ctrl <= stAdxlWaitResetDone; end if; -- Send the Reset command to the ADXL 362
  746.       when stAdxlWaitResetDone      => if (Sample_Rate_Tick = '1') then StN_Adxl_Ctrl <= stAdxlConf_Remaining; end if; -- wait for about 1mS for the
  747.                                                                                                                        -- ADXL 362 to initialize
  748.       when stAdxlConf_Remaining     => if ( Cmd_Reg_Addr_Done = '1' AND SPI_Trans_Done = '1') then -- all of the configuration register data were written
  749.                                              StN_Adxl_Ctrl <= stAdxlWaitSampleRateTick;      -- into the ADXL 362
  750.                                        end if;
  751.       when stAdxlWaitSampleRateTick => if (Sample_Rate_Tick = '1') then StN_Adxl_Ctrl <= stAdxlRead_Status; end if; -- Read and check the
  752.                                                                                                                      --status register
  753.       when stAdxlRead_Status        => if SPI_Trans_Done = '1' then
  754.                                                 if Adxl_Conf_Err = '1' then StN_Adxl_Ctrl <= stAdxlCtrlIdle; -- if error ocurred in configuration, go to the ilde state
  755.                                                                                                              -- and send reset command again
  756.                                                 elsif Adxl_Data_Ready = '1' then StN_Adxl_Ctrl <= stAdxlRead_Data; -- If data is available, start data read
  757.                                                 end if;
  758.                                        end if;
  759.       when stAdxlRead_Data          => if (SPI_Trans_Done = '1') then StN_Adxl_Ctrl <= stAdxlFormatandSum; end if; -- If a set of data is read,
  760.                                                                                                                    -- add it to the accumulators
  761.       when stAdxlFormatandSum       => if (Cnt_Num_Reads_Done = '1') then
  762.                                             StN_Adxl_Ctrl <= stAdxlRead_Done; -- done 16 reads, go to the Done state
  763.                                        else
  764.                                             StN_Adxl_Ctrl <= stAdxlRead_Status; -- Proceed to the next read
  765.                                        end if;
  766.       when stAdxlRead_Done          => StN_Adxl_Ctrl <= stAdxlWaitSampleRateTick; -- Wait for the next Sample_Rate_Tick, in an infinite loop
  767.       when others => StN_Adxl_Ctrl <= stAdxlCtrlIdle;
  768.    end case;
  769. end process Cmb_StC_Adxl_Ctrl;
  770.  
  771. -- Create the accumulators
  772. -- Data_Reg is shifted from 0 to 7, it means that after reading a set of data, Data_Reg will contain
  773. -- Data_Reg(7) = XDATA_L,
  774. -- Data_Reg(6) = XDATA_H,
  775. -- Data_Reg(5) = YDATA_L,
  776. -- Data_Reg(4) = YDATA_H,
  777. -- Data_Reg(3) = ZDATA_L,
  778. -- Data_Reg(2) = ZDATA_H,
  779. -- Data_Reg(1) = TEMP_L,
  780. -- Data_Reg(0) = TEMP_H
  781. Sum_Data: process (SYSCLK, RESET, Data_Ready_1, Enable_Sum, Data_Reg,
  782.                    ACCEL_X_SUM, ACCEL_Y_SUM, ACCEL_Z_SUM, ACCEL_TMP_SUM)
  783. begin
  784.     if SYSCLK'EVENT AND SYSCLK = '1' then
  785.          if (RESET = '1' OR Data_Ready_1 = '1') then
  786.             ACCEL_X_SUM <= (others => '0');
  787.             ACCEL_Y_SUM <= (others => '0');
  788.             ACCEL_Z_SUM <= (others => '0');
  789.             ACCEL_TMP_SUM <= (others => '0');
  790.          elsif Enable_Sum = '1' then
  791.             ACCEL_X_SUM <= ACCEL_X_SUM + (Data_Reg(6)((3 + (NUM_READS_BITS)) downto 0) & Data_Reg(7));
  792.             ACCEL_Y_SUM <= ACCEL_Y_SUM + (Data_Reg(4)((3 + (NUM_READS_BITS)) downto 0) & Data_Reg(5));
  793.             ACCEL_Z_SUM <= ACCEL_Z_SUM + (Data_Reg(2)((3 + (NUM_READS_BITS)) downto 0) & Data_Reg(3));
  794.             ACCEL_TMP_SUM <= ACCEL_TMP_SUM + (Data_Reg(0)((3 + (NUM_READS_BITS)) downto 0) & Data_Reg(1));
  795.          end if;
  796.     end if;
  797. end process Sum_Data;
  798.                  
  799. -- Register the output data
  800. Register_Output_Data: process (SYSCLK, RESET, Data_Ready_1, ACCEL_X_SUM,
  801.                                ACCEL_Y_SUM, ACCEL_Z_SUM, ACCEL_TMP_SUM)
  802. begin
  803.     if SYSCLK'EVENT AND SYSCLK = '1' then
  804.          if RESET = '1' then
  805.             ACCEL_X <= (others => '0');
  806.             ACCEL_Y <= (others => '0');
  807.             ACCEL_Z <= (others => '0');
  808.             ACCEL_TMP <= (others => '0');
  809.          elsif Data_Ready_1 = '1' then -- Divide by NUM_READS to create the average and set the output data
  810.             ACCEL_X <= ACCEL_X_SUM ((11 + (NUM_READS_BITS)) downto (NUM_READS_BITS)); -- 12 bits
  811.             ACCEL_Y <= ACCEL_Y_SUM ((11 + (NUM_READS_BITS)) downto (NUM_READS_BITS));
  812.             ACCEL_Z <= ACCEL_Z_SUM ((11 + (NUM_READS_BITS)) downto (NUM_READS_BITS));
  813.             ACCEL_TMP <= ACCEL_TMP_SUM ((11 + (NUM_READS_BITS)) downto (NUM_READS_BITS));
  814.          end if;
  815.     end if;
  816. end process Register_Output_Data;
  817.  
  818. -- Pipe Data_Ready from Data_Ready_1
  819. -- to have stable output data when Data_Ready becomes active
  820. Pipe_Data_Ready: process (SYSCLK, RESET, Data_Ready_1)
  821. begin
  822.     if SYSCLK'EVENT AND SYSCLK = '1' then
  823.          if RESET = '1' then
  824.             Data_Ready <= '0';
  825.          else
  826.             Data_Ready <= Data_Ready_1;
  827.          end if;
  828.     end if;
  829. end process Pipe_Data_Ready;
  830.  
  831. end Behavioral;
Advertisement
Add Comment
Please, Sign In to add comment