--------------------------------------------------------------------------------- -- Digital RF Telemetry project -- -- file: vibinfo -- by: Alex Tong -- Nov 25, 1999 -- for EE552 -- -- purpose: to take in vibrational adc info and pass the data up -- function: This program samples data from a A-to-D converter -- and measures the rate at which the highest 3 ADC bits -- are latched. This rate determines whether the vibrational -- sensor is detecting no vibration/slight vibration/heavy vibration -- -- -- -- adc1_buffer1(0) = MSB of actual data stream -- adc1_buffer1(1) = Next data bit of actual data stream -- adc1_buffer1(5) = LSB of actual data stream -- -- adc1_buffer(0) is connected to segment A on the first flex 7 digit -- adc1_buffer(1) is connected to segment B on the first flex 7 digit -- -- Only 6 bits (including the MSB) is latched from each -- 12 bit ADC. Therefore, only 6 bits are displayed on each -- 7 segment hex display -- -- timer1 = whole bit timer (controls when next bit state is represented) -- timer2 = half bit timer (latching occurs on the middle of the bit) -- -- latchdata : makes sure data is latched only once -- (at the middle of a whole bit length) -- -- vib_count_timer1 = vibrational counter to measure the -- vibration sensitivity. -- -- vib_count_timer2 is the same as the first timer. It's used -- with vib_count_timer1 so that no extra time has to be spent -- resetting & restarting timer1 between samplings. -- -- sound controls the sound output. Vib_switch controls whether -- sound will be emitted with a light vibration or a heavy -- vibration -- -- cs control select line is used to enable the ADC -- dclock is required to clock the ADC -- -------------------------------------------------------- -- -- timers and counters to measure the sensitivity -- of the vibrational sensor -- vib_buf = "00" for no vibration -- = "10" for heavy vibration -- = "01" for no vibration -- -------------------------------------------------------- --------------------------------------------------------------------- library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; entity vibadc is port ( clock : in std_logic; pb1 : in std_logic; vib_switch : in std_logic; cs : out std_logic; -- dclock is only used in modular testing -- dclock is normally supplied by the top-level file -- dclock : out std_logic; adc1 : in std_logic; vib_buf : buffer std_logic_vector(1 downto 0); lights : out std_logic_vector(3 downto 0); sound : out std_logic -- LED used for testing -- led1 : out std_logic_vector(11 downto 0) ); end entity vibadc; architecture behaviour of vibadc is COMPONENT lpm_add_sub GENERIC (LPM_WIDTH: POSITIVE; LPM_REPRESENTATION: STRING := "SIGNED"; LPM_DIRECTION: STRING := "UNUSED"; LPM_HINT: STRING := "UNUSED"; LPM_PIPELINE: INTEGER := 0; LPM_TYPE: STRING := "L_ADD_SUB"); PORT (dataa, datab: IN STD_LOGIC_VECTOR(LPM_WIDTH-1 DOWNTO 0); aclr: IN STD_LOGIC := '0'; clock: IN STD_LOGIC := '0'; cin: IN STD_LOGIC := '0'; add_sub: IN STD_LOGIC := '1'; result: OUT STD_LOGIC_VECTOR(LPM_WIDTH-1 DOWNTO 0); cout, overflow: OUT STD_LOGIC); END COMPONENT; component timer generic( clock_period_multiplier: positive := 25600; -- this times a 512 kHz clock is 50 ms internal_counter_bit_width: positive := 24 -- number of bits wide the counter will be ); port ( clock: in std_logic; reset: in std_logic; start: in std_logic; running: out std_logic); end component; -- component makeclks -- generic( M : positive := 3; -- N : positive := 5; -- P : positive := 8); -- port(clock : in std_logic; -- clocko1, clocko2, datclk : out std_logic; -- store1, store2, store3 : buffer std_logic); -- end component; component debounce port ( inp, clk: in std_logic; outp: out std_logic ); end component; -- timer signals and timer control signals signal timer_reset1, timer_start1, timer_running1, timer_running2 : std_logic; signal restart_timer : std_logic; signal delaystate : std_logic_vector(3 downto 0); signal timer_reset3, timer_start3, timer_running3 : std_logic; signal timer_reset4, timer_start4, timer_running4 : std_logic; signal delay1 : std_logic_vector(2 downto 0); -- vibrational sensitivity counter signal count : std_logic_vector(7 downto 0); -- vibration data buffer signal adc1_buffer : std_logic_vector(5 downto 0); -- unconnected/unused ports signal nowhere1, nowhere2 : std_logic; --debouced pushbutton signal pb1_deb : std_logic; -- have bitcount to increment by 1 signal onebit : std_logic_vector(3 downto 0); signal addone : std_logic_vector(3 downto 0); signal latchdata : std_logic; signal bitcount : std_logic_vector(3 downto 0); begin addsub : lpm_add_sub generic map(LPM_WIDTH => 4) port map( dataa => bitcount, datab => onebit, result => addone); debouncepb1 : debounce port map( inp => pb1, clk => clock, outp => pb1_deb); wholebittimer1 : timer -- by simulation, run time on timer always -- extends by 4 extra clock periods -- i.e. multiplier =5 , clock = 40ns period -- timerunning = 5*40ns + 4*40ns = 360ns generic map( clock_period_multiplier => 13, -- multiplier = 25000000 for 1 sec. delay internal_counter_bit_width => 17) port map(clock => clock, reset => timer_reset1, start => timer_start1, running => timer_running1); latchingtimer : timer generic map( clock_period_multiplier => 12, -- multiplier = 25000000 for 1 sec. delay internal_counter_bit_width => 15) port map(clock => clock, reset => timer_reset1, start => timer_start1, running => timer_running2); vib_count_timer1 : timer generic map( clock_period_multiplier => 25000000, -- multiplier = 25000000 for 1 sec. delay internal_counter_bit_width => 25) port map(clock => clock, reset => timer_reset3, start => timer_start3, running => timer_running3); vib_count_timer2 : timer generic map( clock_period_multiplier => 25000000, -- multiplier = 25000000 for 1 sec. delay internal_counter_bit_width => 25) port map(clock => clock, reset => timer_reset4, start => timer_start4, running => timer_running4); -- dclock is only used in modular testing -- dclock is normally supplied by the top-level file -- makeclock2 : makeclks -- multiplier requires a clock period to operate -- i.e. for a 40ns period input clock, M=3 creates a -- (40ns + 40ns) *3 = 240ns period clock -- generic map( M => 10, --M=10 period=800ns -- N => 4, -- P => 1) -- 125000 -- 4 * 80ns => 3.125 MHz clock for DCLOCK -- port map(clock => clock, -- clocko1 => dclock, -- clocko2 => nowhere1, -- datclk => nowhere2); onebit <= "0001"; -------------------- Explanation of delaystate signal ---------------------- -- Potential Problem: -- System checks if the timer has stopped running -- No -> do nothing (restart timer = 0) -- Yes -> restart timer ( = '1' ) -- -- The problem is that after timer_start is set to '1', it takes -- a clock pulse for the timer to actually start running -- If the system latches on timer_running = 0 at this time, it thinks -- the timer is finished and must be restarted - but we don't want to -- restart the timer! -- -- Solution: A signal delaystate -- System checks if the timer has stopped running AND delay state = 3 -- No -> do nothing (restart timer = 0) -- Yes -> restart timer (= '1') ------------------------------------------------------------------------------ resettime : process (pb1_deb, clock) is begin if clock'event and clock = '1' then if pb1_deb = '1' or (bitcount = "1000") then timer_start1 <= '0'; timer_reset1 <= '1'; cs <= '1'; bitcount <= "0000"; delaystate <= "1001"; -- bunch of delaystates so that cs is long enough -- to be recognizable (150ns) by the ADC -- (probably not needed but I want to be sure) elsif delaystate = "1001" then delaystate <= "1000"; elsif delaystate = "1000" then delaystate <= "0111"; elsif delaystate = "0111" then delaystate <= "0110"; elsif delaystate = "0110" then delaystate <= "0001"; elsif pb1_deb = '0' and delaystate = "0001" then cs <= '0'; timer_start1 <= '1'; timer_reset1 <= '0'; delaystate <= "0010"; elsif delaystate = "0010" then delaystate <= "0011"; elsif restart_timer = '1' then timer_start1 <= '0'; timer_reset1 <= '1'; bitcount <= addone; delaystate <= "0001"; else end if; end if; end process resettime; getadinfo : process (clock) is begin if clock'event and clock = '1' then case bitcount is when "0000" => if pb1_deb = '1' then latchdata <= '0'; adc1_buffer <= "000000"; elsif timer_running1 = '0' and delaystate = "0011" then restart_timer <= '1'; latchdata <= '0'; elsif latchdata = '0' and timer_running1 = '1' and timer_running2 = '0' then latchdata <= '1'; else restart_timer <= '0'; end if; when "0001" => if pb1_deb = '1' then adc1_buffer <= "000000"; elsif timer_running1 = '0' and delaystate = "0011" then restart_timer <= '1'; latchdata <= '0'; elsif latchdata = '0' and timer_running1 = '1' and timer_running2 = '0' then latchdata <= '1'; else restart_timer <= '0'; end if; when "0010" => if pb1_deb = '1' then adc1_buffer <= "000000"; elsif timer_running1 = '0' and delaystate = "0011" then restart_timer <= '1'; latchdata <= '0'; elsif latchdata = '0' and timer_running1 = '1' and timer_running2 = '0' then adc1_buffer(0) <= adc1; latchdata <= '1'; else restart_timer <= '0'; end if; when "0011" => if pb1_deb = '1' then adc1_buffer <= "000000"; elsif timer_running1 = '0' and delaystate = "0011" then restart_timer <= '1'; latchdata <= '0'; elsif latchdata = '0' and timer_running1 = '1' and timer_running2 = '0' then adc1_buffer(1) <= adc1; latchdata <= '1'; else restart_timer <= '0'; end if; when "0100" => if pb1_deb = '1' then adc1_buffer <= "000000"; elsif timer_running1 = '0' and delaystate = "0011" then restart_timer <= '1'; latchdata <= '0'; elsif latchdata = '0' and timer_running1 = '1' and timer_running2 = '0' then adc1_buffer(2) <= adc1 after 10 ns; latchdata <= '1'; else restart_timer <= '0'; end if; when "0101" => if pb1_deb = '1' then adc1_buffer <= "000000"; elsif timer_running1 = '0' and delaystate = "0011" then restart_timer <= '1'; latchdata <= '0'; elsif latchdata = '0' and timer_running1 = '1' and timer_running2 = '0' then adc1_buffer(3) <= adc1 after 10 ns; latchdata <= '1'; else restart_timer <= '0'; end if; when "0110" => if pb1_deb = '1' then adc1_buffer <= "000000"; elsif timer_running1 = '0' and delaystate = "0011" then restart_timer <= '1'; latchdata <= '0'; elsif latchdata = '0' and timer_running1 = '1' and timer_running2 = '0' then adc1_buffer(4) <= adc1; latchdata <= '1'; else restart_timer <= '0'; end if; when "0111" => if pb1_deb = '1' then adc1_buffer <= "000000"; elsif timer_running1 = '0' and delaystate = "0011" then restart_timer <= '1'; latchdata <= '0'; elsif latchdata = '0' and timer_running1 = '1' and timer_running2 = '0' then adc1_buffer(5) <= adc1; latchdata <= '1'; else restart_timer <= '0'; end if; when others => -------------------------------------------------------- -- LEDs used for testing -- -- led1(0) <= not adc1_buffer(0); -- led1(1) <= not adc1_buffer(1); -- led1(2) <= not adc1_buffer(2); -- led1(3) <= not adc1_buffer(3); -- led1(4) <= not adc1_buffer(4); -- led1(5) <= not adc1_buffer(5); -- led1(6) <= '1'; -- led1(7) <= '1'; -- led1(8) <= '1'; -- led1(9) <= '1'; -- led1(10) <= '1'; -- led1(11) <= '1'; -- -------------------------------------------------------- end case; end if; end process getadinfo; -------------------------------------------------------- -- -- timers and counters to measure the sensitivity -- of the vibrational sensor -- vib_buf = "00" for no vibration -- = "10" for heavy vibration -- = "01" for no vibration -- -------------------------------------------------------- ctrl_lights : process(clock) is variable vib_count_light, vib_count_heavy : natural := 0; begin if clock'event and clock = '1' then if pb1 = '0' then delay1 <= "000"; timer_reset3 <= '1'; timer_reset4 <= '1'; timer_start3 <= '0'; timer_start4 <= '0'; vib_buf <= "00"; elsif delay1 = "000" and timer_running3 = '0' and timer_running4 = '0' then timer_reset3 <= '0'; timer_start3 <= '1'; timer_reset4 <= '1'; timer_start4 <= '0'; delay1 <= "001"; vib_count_light := 0; vib_count_heavy := 0; vib_buf <= "00"; elsif delay1 = "001" then delay1 <= "010"; elsif delay1 = "010" then delay1 <= "011"; elsif delay1 = "011" and timer_running3 = '0' and timer_running4 = '0' then delay1 <= "100"; timer_reset3 <= '1'; timer_start3 <= '0'; timer_reset4 <= '0'; timer_start4 <= '1'; vib_count_light := 0; vib_count_heavy := 0; vib_buf <= "00"; elsif delay1 = "100" then delay1 <= "101"; elsif delay1 = "101" then delay1 <= "110"; elsif delay1 = "110" then delay1 <= "000"; end if; -- Vibrational sensitivity is determined by measuring the rate -- of the first 3 MSB of the ADC data if timer_running3 = '1' or timer_running4 = '1' then if adc1_buffer(5 downto 3) = "111" then vib_count_light := vib_count_light +1; vib_count_heavy := vib_count_heavy +1; end if; else vib_count_light := 0; vib_count_heavy := 0; end if; if pb1 = '0' or (timer_running3 = '0' and timer_running4 = '0') then lights <= "1111"; sound <= '0'; elsif vib_count_light = 2 then lights <= "1100"; vib_buf <= "01"; if vib_switch = '1' then sound <= '1'; end if; elsif vib_count_heavy = 100000 then lights <= "0011"; vib_buf <= "10"; if vib_switch = '0' then sound <= '1'; end if; end if; end if; end process ctrl_lights; end behaviour;