Monday, October 26, 2020

ads8661---updated with spi master

-------------top file ----------

--------------------------------------------------------------------------------
--
--   FileName:         pmod_dac_ad5628.vhd
--   Dependencies:     spi_master.vhd

--------------------------------------------------------------------------------

LIBRARY ieee;
USE ieee.std_logic_1164.all;

ENTITY pmod_dac_ads8661 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 
    
    );
    
  PORT(
                clk        : IN      STD_LOGIC;                      --system clock
                reset_n    : IN      STD_LOGIC;                      --active low asynchronous reset
                dac_tx_ena : IN      STD_LOGIC;                      --enable transaction with DAC
                rvs_in  :  in   std_logic ; 
                rvs_out : out std_logic ; 
                data_in_0   :  IN      STD_LOGIC;                      --channel 0 serial data from ADC  ----added 
                adc_0_data  :  OUT     STD_LOGIC_VECTOR(11 DOWNTO 0);  --channel 0 ADC result     ----added    
                busy       : OUT     STD_LOGIC;                      --indicates when transactions with DAC can be initiated
                mosi       : OUT     STD_LOGIC;                      --SPI bus to DAC: master out, slave in (DIN)
                sclk       : BUFFER  STD_LOGIC;                      --SPI bus to DAC: serial clock (SCLK)
                ss_n       : BUFFER  STD_LOGIC_VECTOR(0 DOWNTO 0)
                );  --SPI bus to DAC: slave select (~SYNC)
END pmod_dac_ads8661;

ARCHITECTURE Behavioral OF pmod_dac_ads8661 IS

  TYPE machine IS(start, nopb1, nopb2 , 
rst_pwr_configb11 , rst_pwr_configb12 , 
rst_pwr_configb21 , rst_pwr_configb22 , 
sdi_configb1 ,     sdi_configb2 ,
data_out_configb11, data_out_configb12 ,
data_out_configb21,  data_out_configb22,
range_configb1,   range_configb2,
sdo_configb1 , sdo_configb2 ,
read_commandb1 ,  read_commandb2 ,
 read_data ,output_result, pause,  stop
  ); --needed states
  
  SIGNAL state  ,next_state       : machine := start;                    --state machine
    SIGNAL  spi_rx_data_0  : STD_LOGIC_VECTOR(15 DOWNTO 0);  --latest channel 0 data received    
    
  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_tx_data   : STD_LOGIC_VECTOR(15 DOWNTO 0);       --transmit data for SPI component

attribute keep : string;
attribute keep of state : signal is "true";

  --declare SPI Master component
  COMPONENT spi_master_ads8661 IS
    GENERIC(
      slaves  : INTEGER := 1;   --number of spi slaves
      d_width : INTEGER := 16); --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_ads8661;

------------------added ---signal ----------------------------------

--TYPE machine IS(start, pause, configure, read_data, output_result); --needed states
--  SIGNAL state              : machine := start;                       --state machine
--  SIGNAL parameter          : INTEGER RANGE 0 TO 7;                   --parameter being configured
--  SIGNAL parameter_addr     : STD_LOGIC_VECTOR(5 DOWNTO 0);           --register address of configuration parameter
--  SIGNAL parameter_data     : STD_LOGIC_VECTOR(31 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(31 DOWNTO 0);           --transmit data for SPI component
--  SIGNAL spi_rx_data        : STD_LOGIC_VECTOR(31 DOWNTO 0);           --received data from SPI component
--  SIGNAL acceleration_x_int : STD_LOGIC_VECTOR(31 DOWNTO 0);          --internal x-axis acceleration data buffer
--  SIGNAL acceleration_y_int : STD_LOGIC_VECTOR(31 DOWNTO 0);          --internal y-axis acceleration data buffer
--  SIGNAL acceleration_z_int : STD_LOGIC_VECTOR(31 DOWNTO 0);          --internal z-axis acceleration data buffer

--SIGNAL adc_0_data :      STD_LOGIC_VECTOR(31 DOWNTO 0);  --x-axis acceleration data
--  SIGNAL  acceleration_y :      STD_LOGIC_VECTOR(31 DOWNTO 0);  --y-axis acceleration data
--  SIGNAL  acceleration_z :      STD_LOGIC_VECTOR(31 DOWNTO 0); --z-axis acceleration data

signal  rst_data1, rst_data2, sdi_data , sdo_data , data_out1, data_out2, range_data : std_logic_vector(15 downto 0) ; 
signal rvs_reg : std_logic ; 


------added signal end -----------------------





BEGIN

  --instantiate the SPI Master component
  spi_master_u1:  spi_master_ads8661
    GENERIC MAP(slaves => 1, d_width => 16)
    PORT MAP(clock => clk, reset_n => reset_n, enable => spi_ena, cpol => '0', cpha => '0',
             cont => '0', clk_div => spi_clk_div, addr => 0, tx_data => spi_tx_data, miso => data_in_0,
             sclk => sclk, ss_n => ss_n, mosi => mosi, busy => spi_busy, rx_data => spi_rx_data_0);


process ( clk ,reset_n) 
begin 
    if ( reset_n='0')  then  
        rvs_reg  <='0' ; 
    elsif rising_edge ( clk ) then 
       rvs_reg <=rvs_in ; 
      end if ; 
      
  end process ; 
  
  rvs_out <= rvs_reg ; 
  

PROCESS(clk, reset_n)
    VARIABLE count : INTEGER RANGE 0 TO clk_freq*100 := 0; --counter
  BEGIN
  
    IF(reset_n = '0') THEN              --reset activated
      spi_ena <= '0';                     --clear SPI component enable
   spi_cont <= '0';   
      spi_tx_data <= (OTHERS => '0');     --clear SPI component transmit data
      busy <= '1';                        --indication component is unavailable
      sdo_data<=(OTHERS=>'0') ; 
      state <= start;                     --restart state machine
--      next_state <=rst_pwr_config1 ; 
   next_state <= nopb1 ; 
    ELSIF(clk'EVENT AND clk = '1') THEN --rising edge of system clock

      spi_busy_prev <= spi_busy;          --collect previous spi_busy
   
      CASE state IS                       --state machine

        --entry state, give DAC 100us to power up before communicating
        WHEN start =>
          busy <= '1';                     --component is busy, DAC not yet available
--          IF(count < clk_freq*100) THEN    --100us not yet reached
          IF(count < 3) THEN    --100us not yet reached
            count := count + 1;              --increment counter
          ELSE                             --100us reached
            count := 0;                      --clear counter
            state <= pause;                --advance to configure the DAC
            next_state <= nopb1 ; 
            
          END IF;
          
             --perform SPI transaction to turn on internal voltage reference  
        WHEN nopb1 =>
          if ( dac_tx_ena='1') then  ----------------for trigger option 
                   IF(spi_busy = '0' AND spi_busy_prev = '0') THEN      --no command sent
                    spi_ena <= '1';                                      --enable transaction with DAC
                    spi_cont <= '1';   
                    spi_tx_data <= x"0000" ; ---- nop command first byte          
                  ELSIF(spi_busy = '1') THEN                           --transaction underway
                    spi_ena <= '0';                                      --clear transaction enable
                  ELSE                                                 --transaction complete
                    state <= pause;                                      --advance to pause state
                    next_state <= nopb2  ; 
                  END IF;       
           end if ; 
          
          
          
                 --perform SPI transaction to turn on internal voltage reference  
        WHEN nopb2=>
          IF(spi_busy = '0' AND spi_busy_prev = '0') THEN      --no command sent
            spi_ena <= '1';                                      --enable transaction with DAC
            spi_cont <= '1';   
            spi_tx_data <= x"0000" ; ---- nop command first byte          
          ELSIF(spi_busy = '1') THEN                           --transaction underway
            spi_ena <= '0';                                      --clear transaction enable
          ELSE                                                 --transaction complete
            state <= pause;                                      --advance to pause state
--            next_state <= rst_pwr_configb11  ; 
                next_state <=    sdi_configb1;
          END IF;       
          
--------------------------------1st byte rst ---------------
        --perform SPI transaction to turn on internal voltage reference  
        WHEN rst_pwr_configb11 =>
          IF(spi_busy = '0' AND spi_busy_prev = '0') THEN      --no command sent
            spi_ena <= '1';                                      --enable transaction with DAC
            spi_cont <= '1';   
--            spi_tx_data <= write_ms  &  rst_pwrctl_reg_ms_addr  & rst_pwrctl_reg_ms_data  & x"00" ;    --data to set specified range        
             spi_tx_data <= write_hword  &  rst_pwrctl_reg_ms_addr   ;    --data to set specified range        
          ELSIF(spi_busy = '1') THEN                           --transaction underway
            spi_ena <= '0';                                      --clear transaction enable
          ELSE                                                 --transaction complete
            state <= pause;                                      --advance to pause state
--            next_state <= rst_pwr_config2  ; 
            next_state <= rst_pwr_configb12  ; 
          END IF;       
          
          WHEN rst_pwr_configb12=>
                  IF(spi_busy = '0' AND spi_busy_prev = '0') THEN      --no command sent
                    spi_ena <= '1';                                      --enable transaction with DAC
                     spi_cont <= '1';   
--                    spi_tx_data <= write_ms  &  rst_pwrctl_reg_ls_addr  & rst_pwrctl_reg_ls_data  & x"00" ;
                   spi_tx_data <=  rst_pwrctl_reg_ms_data  & x"00" ;    --data to set specified range        
                  ELSIF(spi_busy = '1') THEN                           --transaction underway
                    spi_ena <= '0';                                      --clear transaction enable
                  ELSE                                                 --transaction complete
                    state <= pause;                                      --advance to pause state
--                    next_state <= sdi_config ; 
                     next_state <= rst_pwr_configb21 ; 
                  END IF;       
                  
                  
               ------------------------rst 2nd byte ----------------
               
          
--------------------------------1st byte rst ---------------
        --perform SPI transaction to turn on internal voltage reference  
        WHEN rst_pwr_configb21 =>
          IF(spi_busy = '0' AND spi_busy_prev = '0') THEN      --no command sent
            spi_ena <= '1';                                      --enable transaction with DAC
            spi_cont <= '1';   
  
                              spi_tx_data <= write_hword  &  rst_pwrctl_reg_ls_addr ;
          ELSIF(spi_busy = '1') THEN                           --transaction underway
            spi_ena <= '0';                                      --clear transaction enable
          ELSE                                                 --transaction complete
            state <= pause;                                      --advance to pause state
--            next_state <= rst_pwr_config2  ; 
            next_state <= rst_pwr_configb22  ; 
          END IF;       
          
          WHEN rst_pwr_configb22=>
                  IF(spi_busy = '0' AND spi_busy_prev = '0') THEN      --no command sent
                    spi_ena <= '1';                                      --enable transaction with DAC
                     spi_cont <= '1';   
                    spi_tx_data <=  rst_pwrctl_reg_ls_data  & x"00" ;  
                  ELSIF(spi_busy = '1') THEN                           --transaction underway
                    spi_ena <= '0';                                      --clear transaction enable
                  ELSE                                                 --transaction complete
                    state <= pause;                                      --advance to pause state
--                    next_state <= sdi_config ; 
                     next_state <= sdi_configb1 ; 
                  END IF;       
               
               -------------xxx--------------------------   
                  
                  
                  
                  
                  
           WHEN sdi_configb1=>
                                IF(spi_busy = '0' AND spi_busy_prev = '0') THEN      --no command sent
                                  spi_ena <= '1';                                      --enable transaction with DAC
                                spi_cont <= '1';   
--                                  spi_tx_data  <= write_ms  &  sdi_ctl_reg_addr  & "000000"  & sdi_mode    & x"00" ;   
                                 spi_tx_data  <= write_hword  &  sdi_ctl_reg_addr ; 
                                ELSIF(spi_busy = '1') THEN                           --transaction underway
                                  spi_ena <= '0';                                      --clear transaction enable
                                ELSE                                                 --transaction complete
                                  state <= pause;                                      --advance to pause state
                                  next_state <= sdi_configb2 ; 
                                  END IF;        
                                  
                          WHEN sdi_configb2=>
                                IF(spi_busy = '0' AND spi_busy_prev = '0') THEN      --no command sent
                                  spi_ena <= '1';                                      --enable transaction with DAC
                                spi_cont <= '1';   
                                  spi_tx_data  <=  "000000"  & sdi_mode    & x"00" ;   
                                ELSIF(spi_busy = '1') THEN                           --transaction underway
                                  spi_ena <= '0';                                      --clear transaction enable
                                ELSE                                                 --transaction complete
                                  state <= pause;                                      --advance to pause state
                                  next_state <= sdo_configb1  ; 
                                  END IF;                    
                                  
                                  
                                  
                                  
                                            
            WHEN sdo_configb1=>
                    IF(spi_busy = '0' AND spi_busy_prev = '0') THEN      --no command sent
                    spi_ena <= '1';                                      --enable transaction with DAC
                  spi_cont <= '1';   
--                    spi_tx_data<= write_ms  &  sdo_ctl_reg_addr  & "0"  &  ssync_clk & "0000" &  sdo_mode    & x"00" ;   
                    spi_tx_data<= write_hword  &  sdo_ctl_reg_addr ;    
                    ELSIF(spi_busy = '1') THEN                           --transaction underway
                    spi_ena <= '0';                                      --clear transaction enable
                    ELSE                                                 --transaction complete
                    state <= pause;                                      --advance to pause state
                    next_state <= sdo_configb2   ; 
                    END IF;          
                    
                   WHEN sdo_configb2=>
                    IF(spi_busy = '0' AND spi_busy_prev = '0') THEN      --no command sent
                    spi_ena <= '1';                                      --enable transaction with DAC
                  spi_cont <= '1';   
--                    spi_tx_data<= write_ms  &  sdo_ctl_reg_addr  & "0"  &  ssync_clk & "0000" &  sdo_mode    & x"00" ;   
                    spi_tx_data<=  "0"  &  ssync_clk & "0000" &  sdo_mode    & x"00" ;    
                    ELSIF(spi_busy = '1') THEN                           --transaction underway
                    spi_ena <= '0';                                      --clear transaction enable
                    ELSE                                                 --transaction complete
                    state <= pause;                                      --advance to pause state
                    next_state <= data_out_configb11   ; 
                    END IF;       
                    
                    
                    
                      

                    
           WHEN data_out_configb11=>
                                IF(spi_busy = '0' AND spi_busy_prev = '0') THEN      --no command sent
                                  spi_ena <= '1';                                      --enable transaction with DAC
                                spi_cont <= '1';   
--                                  spi_tx_data  <= write_ms  &  dataout_ctl_reg_ms_addr   & '0'  &   device_addr_inc  &  vdd_active_alarm_inc  &  in_active_alarm_inc  &  '0'  &    range_inc  & x"00" ;
                                       spi_tx_data  <= write_hword  &  dataout_ctl_reg_ms_addr  ;
                                ELSIF(spi_busy = '1') THEN                           --transaction underway
                                  spi_ena <= '0';                                      --clear transaction enable
                                ELSE                                                 --transaction complete
                                  state <= pause;                                      --advance to pause state
                                  next_state <= data_out_configb12  ; 
                                  END IF;        
                                  
                          
                             WHEN data_out_configb12=>
                                IF(spi_busy = '0' AND spi_busy_prev = '0') THEN      --no command sent
                                  spi_ena <= '1';                                      --enable transaction with DAC
                                spi_cont <= '1';   
--                                  spi_tx_data  <= write_ms  &  dataout_ctl_reg_ms_addr   & '0'  &   device_addr_inc  &  vdd_active_alarm_inc  &  in_active_alarm_inc  &  '0'  &    range_inc  & x"00" ;
                                       spi_tx_data  <= '0'  &   device_addr_inc  &  vdd_active_alarm_inc  &  in_active_alarm_inc  &  '0'  &    range_inc  & x"00" ;
                                ELSIF(spi_busy = '1') THEN                           --transaction underway
                                  spi_ena <= '0';                                      --clear transaction enable
                                ELSE                                                 --transaction complete
                                  state <= pause;                                      --advance to pause state
                                  next_state <= data_out_configb21  ; 
                                  END IF;       
                                
           WHEN data_out_configb21=>
                                IF(spi_busy = '0' AND spi_busy_prev = '0') THEN      --no command sent
                                  spi_ena <= '1';                                      --enable transaction with DAC
                               spi_cont <= '1';   
--                                  spi_tx_data <= write_ms  &  dataout_ctl_reg_ms_addr   & "0000"   &     par_en   &  data_val  &  x"00" ;
                                          spi_tx_data <= write_hword  &  dataout_ctl_reg_ms_addr ; 
                                ELSIF(spi_busy = '1') THEN                           --transaction underway
                                  spi_ena <= '0';                                      --clear transaction enable
                                ELSE                                                 --transaction complete
                                  state <= pause;                                      --advance to pause state
                                  next_state <= data_out_configb22  ; 
                                  END IF;       
                                  
                                  
                               WHEN data_out_configb22=>
                                IF(spi_busy = '0' AND spi_busy_prev = '0') THEN      --no command sent
                                  spi_ena <= '1';                                      --enable transaction with DAC
                               spi_cont <= '1';   
--                                  spi_tx_data <= write_ms  &  dataout_ctl_reg_ms_addr   & "0000"   &     par_en   &  data_val  &  x"00" ;
                                          spi_tx_data <= "0000"   &     par_en   &  data_val  &  x"00" ;
                                ELSIF(spi_busy = '1') THEN                           --transaction underway
                                  spi_ena <= '0';                                      --clear transaction enable
                                ELSE                                                 --transaction complete
                                  state <= pause;                                      --advance to pause state
                                  next_state <= range_configb1  ; 
                                  END IF;        
                                   
                                  
                                  
        WHEN range_configb1=>
                                IF(spi_busy = '0' AND spi_busy_prev = '0') THEN      --no command sent
                                  spi_ena <= '1';                                      --enable transaction with DAC
                                spi_cont <= '1';   
--                                  spi_tx_data <= write_ms    &  range_sel_addr     & '0'   &   intref_dis   &  "00"   &   range_sel &  x"00" ;
                                      spi_tx_data <= write_hword    &  range_sel_addr   ;
                                ELSIF(spi_busy = '1') THEN                           --transaction underway
                                  spi_ena <= '0';                                      --clear transaction enable
                                ELSE                                                 --transaction complete
                                  state <= pause;                                      --advance to pause state
                                  next_state <= range_configb2 ; 
                                  END IF;     
                                  
                                     
                  WHEN range_configb2=>
                                IF(spi_busy = '0' AND spi_busy_prev = '0') THEN      --no command sent
                                  spi_ena <= '1';                                      --enable transaction with DAC
                                spi_cont <= '1';   
                                  spi_tx_data <= '0'   &   intref_dis   &  "00"   &   range_sel &  x"00" ;
                                ELSIF(spi_busy = '1') THEN                           --transaction underway
                                  spi_ena <= '0';                                      --clear transaction enable
                                ELSE                                                 --transaction complete
                                  state <= pause;                                      --advance to pause state
                                  next_state <= read_commandb1 ; 
                                  END IF;                            
                                  
                                  
          
          
          WHEN read_commandb1=>
                                IF(spi_busy = '0' AND spi_busy_prev = '0') THEN      --no command sent
                                  spi_ena <= '1';                                      --enable transaction with DAC
                                  spi_cont <= '1';   
--                                  spi_tx_data <= "11001XX0" & sdo_ctl_reg_addr & X"0000" ; 
                                    spi_tx_data <= "11001000" & sdo_ctl_reg_addr  ; 
                                ELSIF(spi_busy = '1') THEN                           --transaction underway
                                  spi_ena <= '0';                                      --clear transaction enable
                                ELSE                                                 --transaction complete
                                  state <= pause;                                      --advance to pause state
                                  next_state <= read_commandb2; 
                                  END IF;        
                                  
                                  
                                  
                                   WHEN read_commandb2=>
                                IF(spi_busy = '0' AND spi_busy_prev = '0') THEN      --no command sent
                                  spi_ena <= '1';                                      --enable transaction with DAC
                                  spi_cont <= '1';   
                                  spi_tx_data <= X"0000" ; 
                                ELSIF(spi_busy = '1') THEN                           --transaction underway
                                  spi_ena <= '0';                                      --clear transaction enable
                                ELSE                                                 --transaction complete
                                  state <= pause;                                      --advance to pause state
                                  next_state <= read_data; 
                                  END IF;        
                             
                             
              WHEN read_data=>
                                IF(spi_busy = '0' AND spi_busy_prev = '0') THEN      --no command sent
                                  spi_ena <= '1';                                      --enable transaction with DAC
                                  spi_cont <= '1';   
                                 sdo_data  <= spi_rx_data_0;    --latch in first received acceleration data
                                ELSIF(spi_busy = '1') THEN                           --transaction underway
                                  spi_ena <= '0';                                      --clear transaction enable
                                ELSE                                                 --transaction complete
                                   STATE <=  pause  ;
                                    next_state <= output_result ; 
                                  END IF;                          
                                  
                  
          
            
        --outputs acceleration data
        WHEN output_result =>
          adc_0_data <=  sdo_data(15 DOWNTO 4); --assign channel 0 ADC data bits to output   
            state <= pause;                        --return to pause state
            next_state <=read_data;
        
     
         
        --pauses 20ns between SPI transactions
        WHEN pause =>
          IF(count < clk_freq/5) THEN   --less than 20ns
            count := count + 1;            --increment counter
          ELSE                           --20ns has elapsed
            count := 0;                    --clear counter
            busy <= '0';                   --indicate component is ready for a transaction
            state <=next_state;   
          END IF;
          
       when stop => 
            state <= stop ; 
        --default to start state
        WHEN OTHERS => 
          state <= start;

      END CASE;      
    END IF;
  END PROCESS;
  
--    adc_0_data <= spi_rx_data_0(31 DOWNTO 20); --assign channel 0 ADC data bits to output   
  ------------------coment end --------------------------------------
  
  ------added -------------------------
  
  
--   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
--        adc_0_data  <=(others=>'0') ; 
--        rst_data1<=(others=>'0') ;
--         rst_data2 <=(others=>'0') ; 
--         sdi_data <=(others=>'0') ; 
--         sdo_data <=(others=>'0') ; 
--         data_out1 <=(others=>'0') ; 
--         data_out2 <=(others=>'0') ; 
--         range_data <=(others=>'0') ;  
--          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
--                            state <= pause;                        --remain in pause state
--                          ELSE                                   --200ns has elapsed
--                          count := 0;                            --clear counter
--                          CASE parameter IS                      --select SPI transaction
--                            WHEN 0 =>                             -----rst_pwrt configure  ------
--                              parameter <= parameter + 1;            --increment parameter for next transaction
--            --                  parameter_addr <= "110001";            --register address with range setting
--                                rst_data1 <= write_ms  &  rst_pwrctl_reg_ms_addr  & rst_pwrctl_reg_ms_data  & x"00" ;    --data to set specified range                   
--                              state <= configure;                    --proceed to SPI transaction
--                            WHEN 1 =>                             -----rst pwr configure 
--                             rst_data2 <= write_ms  &  rst_pwrctl_reg_ls_addr  & rst_pwrctl_reg_ls_data  & x"00" ;
--                              state <= configure;                    --proceed to SPI transaction
                     
--                           WHEN 2 =>                            ---sdi ctl configure 
--                             sdi_data <= write_ms  &  sdi_ctl_reg_addr  & "000000"  & sdi_mode    & x"00" ;   
--                              state <= configure;      
                              
--                                WHEN 3 =>                            -----sdo configure -----       
--                             sdo_data <= write_ms  &  sdo_ctl_reg_addr  & "0"  &  ssync_clk & "0000" &  sdo_mode    & x"00" ;   
--                              state <= configure;      
                              
--                                WHEN 4 =>                            --- data out control register      ms 
--                             data_out1 <= write_ms  &  dataout_ctl_reg_ms_addr   & '0'  &   device_addr_inc  &  vdd_active_alarm_inc  &  in_active_alarm_inc  &  '0'  &    range_inc  & x"00" ;
--                              state <= configure;      
                              
--                                WHEN 5 =>                             ----data pit cpmtrp; regoster  ls      
--                              data_out2 <= write_ms  &  dataout_ctl_reg_ms_addr   & "0000"   &     par_en   &  data_val  &  x"00" ;
--                              state <= configure;      
                              
--                                WHEN 6=>                             --range selection  register  
--                             range_data <= write_ms    &  range_sel_addr     & '0'   &   intref_dis   &  "00"   &   range_sel &  x"00" ;
--                              state <= configure;      
                           
--                            WHEN 7 =>                             --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
--                spi_tx_data <=rst_data1 ; ----- "00" & parameter_addr;           --first information to send
--              ELSE                                            --transaction has started
--                spi_tx_data <= rst_data2 ; --- "0000" & parameter_data;         --second information to send (first has been latched in)
--              END IF;
              
--              when 1=> 
--                  if ( spi_busy='0') then 
--                   spi_cont<='1' ; 
--                   spi_ena <='1' ; 
--                   spi_tx_data <=sdi_data ; 
--                  else 
--                       spi_tx_data <=sdo_data ; 
--                    end if ; 
                    
                    
--                    when 2=> 
--                  if ( spi_busy='0') then 
--                   spi_cont<='1' ; 
--                   spi_ena <='1' ; 
--                   spi_tx_data <=data_out1 ; 
--                  else 
--                       spi_tx_data <=data_out2 ; 
--                    end if ; 
                   
--                       when 3=> 
--                  if ( spi_busy='0') then 
--                   spi_cont<='1' ; 
--                   spi_ena <='1' ; 
--                   spi_tx_data <=range_data ; 
                
--                    end if ; 
                    
              
--            WHEN 4 =>                                       --first busy deassertion
--              spi_cont <= '0';                                --clear continous mode to end transaction
--              spi_ena <= '0';                                 --clear SPI transaction enable
--              count := 0;                                     --clear universal counter
--              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 <= (others=>'1')  ;                        --first information to send
--              ELSE                                              --transaction has started
--                spi_tx_data <=  (others=>'1')  ;                        --second information to send (first has been latched in)              
--              END IF;
--            WHEN 2 =>                                         --2nd busy deassertion
--              adc_0_data <= spi_rx_data;    --latch in first received acceleration data
--            WHEN 3 =>                                         --3rd busy deassertion
--              adc_0_data <= spi_rx_data;   --latch in second received acceleration data
--            WHEN 4 =>                                         --4th busy deassertion
--              adc_0_data<= spi_rx_data;    --latch in third received acceleration data
--            WHEN 5 =>                                         --5th busy deassertion
--              adc_0_data <= 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
--              adc_0_data <= spi_rx_data;    --latch in fifth received acceleration data
--            WHEN 7 =>                                         --7th busy deassertion
--              adc_0_data <= 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 =>
         
--            adc_0_data1 <= adc_0_data(31 DOWNTO 20);  --output z-axis data
--            state <= pause;                        --return to pause state
        
--        --default to start state
--        WHEN OTHERS => 
--          state <= start;

--      END CASE;      
----    END IF;
--  END PROCESS;
  
  
  -----added end ------------------------------------------
  
  
END Behavioral;


-------xxxxxxxxxxxx------------------



------spi----master ---

--------------------------------------------------------------------------------
--
--   FileName:         spi_master.vhd
--   Dependencies:     none
--   Design Software:  Quartus II Version 9.0 Build 132 SJ Full Version
--
--   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 7/23/2010 Scott Larson
--     Initial Public Release
--   Version 1.1 4/11/2013 Scott Larson
--     Corrected ModelSim simulation error (explicitly reset clk_toggles signal)
--    
--------------------------------------------------------------------------------

LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
USE ieee.std_logic_unsigned.all;

ENTITY spi_master_ads8661 IS
  GENERIC(
    slaves  : INTEGER := 4;  --number of spi slaves
    d_width : INTEGER := 2); --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 spi_master_ads8661;

ARCHITECTURE Behavioral OF spi_master_ads8661 IS
   TYPE machine IS(ready, convert , execute);                           --state machine data type
  SIGNAL state  ,   next_state  : machine;                              --current state
  SIGNAL slave       : INTEGER;                              --slave selected for current transaction
  SIGNAL clk_ratio   : INTEGER;                              --current clk_div
  SIGNAL count       : INTEGER;                              --counter to trigger sclk from system clock
  SIGNAL clk_toggles : INTEGER RANGE 0 TO d_width*2 + 1;     --count spi clock toggles
  SIGNAL assert_data : STD_LOGIC;                            --'1' is tx sclk toggle, '0' is rx sclk toggle
  SIGNAL continue    : STD_LOGIC;                            --flag to continue transaction
  SIGNAL rx_buffer   : STD_LOGIC_VECTOR(d_width-1 DOWNTO 0); --receive data buffer
  SIGNAL tx_buffer   : STD_LOGIC_VECTOR(d_width-1 DOWNTO 0); --transmit data buffer
  SIGNAL last_bit_rx : INTEGER RANGE 0 TO d_width*2;         --last rx data bit location
   signal convert_count : natural range 0 to  24:=0 ; 
   
   BEGIN
  PROCESS(clock, reset_n)
  BEGIN

    IF(reset_n = '0') THEN        --reset system
      busy <= '1';                --set busy signal
      ss_n <= (OTHERS => '1');    --deassert all slave select lines
      mosi <= 'Z';                --set master out to high impedance
      rx_data <= (OTHERS => '0'); --clear receive data port
      state <= ready;             --go to ready state when reset is exited
      next_state<=execute ;    ---addded 
     convert_count <= 0 ; 
    ELSIF(clock'EVENT AND clock = '1') THEN
      CASE state IS               --state machine

        WHEN ready =>
              busy <= '0';             --clock out not busy signal
              ss_n <= (OTHERS => '1'); --set all slave select outputs high
              mosi <= 'Z';             --set mosi output high impedance
              continue <= '0';         --clear continue flag
              
              --user input to initiate transaction
              IF(enable = '1') THEN       
                busy <= '1';             --set busy signal
            
                    IF(addr < slaves) THEN   --check for valid slave address
                      slave <= addr;         --clock in current slave selection if valid
                    ELSE
                      slave <= 0;            --set to first slave if not valid
                    END IF;
                    
                    
                    IF(clk_div = 0) THEN     --check for valid spi speed
                      clk_ratio <= 1;        --set to maximum speed if zero
                      count <= 1;            --initiate system-to-spi clock counter
                    ELSE
                      clk_ratio <= clk_div;  --set to input selection if valid
                      count <= clk_div;      --initiate system-to-spi clock counter
                    END IF;
                    
                sclk <= cpol;            --set spi clock polarity
                assert_data <= NOT cpha; --set spi clock phase
                tx_buffer <= tx_data;    --clock in data for transmit into buffer
                clk_toggles <= 0;        --initiate clock toggle counter
                last_bit_rx <= d_width*2 + conv_integer(cpha) - 1; --set last rx data bit
--                 state <= execute;           --proceed to execute state
----------------------added---
              
                  state <= convert; 
                  next_state <=execute ; 
                
              ELSE
                state <= ready;          --remain in ready state
              END IF;
              
         when convert=>
                     report "convert state " ; 
                     ss_n <= (OTHERS => '1');    --deassert all slave select lines
                     if ( convert_count=40) then 
                       convert_count <= 0 ;
                       state <=next_state ; 
                     else 
                     convert_count <= convert_count +1 ; 
                   end if ; 
                   
          
          

        WHEN execute =>
                  busy <= '1';        --set busy signal
                  ss_n(slave) <= '0'; --set proper slave select output
                  
                  --system clock to sclk ratio is met
                  IF(count = clk_ratio) THEN        
                    count <= 1;                     --reset system-to-spi clock counter
                    assert_data <= NOT assert_data; --switch transmit/receive indicator
                    
                            IF(clk_toggles = d_width*2 + 1) THEN
                              clk_toggles <= 0;               --reset spi clock toggles counter
                            ELSE
                              clk_toggles <= clk_toggles + 1; --increment spi clock toggles counter
                            END IF;
            
                            --spi clock toggle needed
                            IF(clk_toggles <= d_width*2 AND ss_n(slave) = '0') THEN 
                              sclk <= NOT sclk; --toggle spi clock
                            END IF;
            
                            --receive spi clock toggle
                            IF(assert_data = '0' AND clk_toggles < last_bit_rx + 1 AND ss_n(slave) = '0') THEN 
                              rx_buffer <= rx_buffer(d_width-2 DOWNTO 0) & miso; --shift in received bit
                            END IF;
                            
                            --transmit spi clock toggle
                            IF(assert_data = '1' AND clk_toggles < last_bit_rx) THEN 
                              mosi <= tx_buffer(d_width-1);                     --clock out data bit
                              tx_buffer <= tx_buffer(d_width-2 DOWNTO 0) & '0'; --shift data transmit buffer
                            END IF;
            
                        --last data receive, but continue
                        IF(clk_toggles = last_bit_rx AND cont = '1') THEN 
                          tx_buffer <= tx_data;                       --reload transmit buffer
                          clk_toggles <= last_bit_rx - d_width*2 + 1; --reset spi clock toggle counter
                          continue <= '1';                            --set continue flag
                        END IF;
                        
                    --normal end of transaction, but continue
                    IF(continue = '1') THEN  
                      continue <= '0';      --clear continue flag
                      busy <= '0';          --clock out signal that first receive data is ready
                      rx_data <= rx_buffer; --clock out received data to output port    
                    END IF;
            
                    --end of transaction
                    IF((clk_toggles = d_width*2 + 1) AND cont = '0') THEN   
                      busy <= '0';             --clock out not busy signal
                      ss_n <= (OTHERS => '1'); --set all slave selects high
                      mosi <= 'Z';             --set mosi output high impedance
                      rx_data <= rx_buffer;    --clock out received data to output port
                      state <= ready;          --return to ready state
   
                 
                    ELSE                       --not end of transaction
                      state <= execute;        --remain in execute state
                    END IF;
          
             ELSE        --system clock to sclk ratio not met
                    count <= count + 1; --increment counter
                 state <= execute;   --remain in execute state
          END IF;

      END CASE;
    END IF;
  END PROCESS; 
   
  END Behavioral;




-----xxxx-------------------------

No comments:

Post a Comment

spyglass lint 1