--------------------------------------------------------------------------------
--
-- 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;
--------------------------------------------------------------------------------
--
-- 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;