DETECTOR

Authors: Anthony Eshpeter & Andrew Dunmore

Description: This program uses three counters to find the time it takes the pulses created by the emitter to reach the sensors. Sensors are enabled one at a time based on a selection by the main controller.

 

 

library ieee;

use ieee.std_logic_1164.all;

use ieee.std_logic_arith.all;

use ieee.std_logic_unsigned.all;

 

library lpm;

use lpm.lpm_components.all;

 

entity detector is

generic( pos_width : positive := 13; -- width of position vectors

delay_count : positive := 7); -- width of delay counters

port( go, data_ack : in std_logic; -- from main controller

rec, clk : in std_logic; -- from external sources

done, timeout : out std_logic; -- to main controller

pos1, pos2 : out std_logic_vector(pos_width-1 downto 0)); -- to positional ALU

end entity detector;

 

architecture behavioural of detector is

 

type state_type is (wait_to_go,delay1_go,pos12_go,delay2_go,pos1_go,delay3_go,pos2_go,finish,time_out);

signal state : state_type;

signal pos1_cnt_en, pos2_cnt_en, delay_cnt_en : std_logic; -- counter enables

signal pos1_cnt_clr, pos2_cnt_clr, delay_cnt_clr : std_logic; -- counter clears

signal pos1_cnt_out, pos2_cnt_out : std_logic_vector(pos_width-1 downto 0); -- position counter outputs

signal delay_cnt_out : std_logic_vector(delay_count-1 downto 0); --delay counter output

 

begin

 

fsm:process(clk)

begin

if clk'EVENT and clk = '1' then

case state is

when wait_to_go =>

if go = '1' then -- enabled when any speaker "go" line goes high (emitter)

state <= delay1_go;

else

state <= wait_to_go;

end if;

when delay1_go =>

if rec = '1' then -- enabled when the first pulse has been received by sensor

if delay_cnt_out >= conv_std_logic_vector(74,delay_count) then

-- counting the delay between sending and receiving of 1st pulse

state<= pos1_go;

else

state <= delay2_go;

end if;

elsif delay_cnt_out >= conv_std_logic_vector(74,delay_count) then

state <= pos12_go;

elsif pos1_cnt_out = conv_std_logic_vector(8191,pos_width) then

-- error code occurs if nothing is received by a sensor

state <= time_out;

end if;

when pos12_go => -- position counters are enabled and delay counter is cleared

if rec = '1' then --indicates that pulse was received

state <= delay2_go;

else

state <= delay1_go;

end if;

when delay2_go => -- delay counter is enabled

if rec = '0' then

if delay_cnt_out >= conv_std_logic_vector(74,delay_count) then

state<= pos2_go;

else

state <= delay3_go;

end if;

elsif delay_cnt_out >= conv_std_logic_vector(74,delay_count) then

state <= pos1_go;

end if;

when pos1_go => -- position counter for 1st pulse is enabled

if rec = '0' then

state <= delay3_go;

elsif pos2_cnt_out = conv_std_logic_vector(8191,pos_width) then

state <= time_out;

else

state <= delay2_go;

end if;

when delay3_go => -- delay counter is enabled

if rec = '1' then

state <= finish;

elsif delay_cnt_out >= conv_std_logic_vector(74,pos_width) then

state <= pos2_go;

elsif pos2_cnt_out = conv_std_logic_vector(8191,pos_width) then

state <= time_out;

end if;

when pos2_go => -- position counter for 2nd pulse is enabled

if rec = '1' then

state <= finish;

else

state <= delay3_go;

end if;

when finish => -- finished finding time delays between sending and receiving for both pulses

if data_ack = '1' then

state <= wait_to_go;

end if;

when time_out => --error state (if no signal is received by a sensor)

state <= wait_to_go;

when others =>

state <= wait_to_go;

end case;

end if;

end process;

 

with state select

delay_cnt_en <= '1' when delay1_go,

'1' when delay2_go,

'1' when delay3_go,

'0' when others;

 

with state select

delay_cnt_clr <= '1' when wait_to_go,

'1' when pos12_go,

'1' when pos1_go,

'1' when pos2_go,

'0' when others;

 

with state select

pos1_cnt_en <= '1' when pos12_go,

'0' when others;

 

with state select

pos1_cnt_clr <= '1' when wait_to_go,

'0' when others;

 

with state select

pos2_cnt_en <= '1' when pos12_go,

'1' when pos1_go,

'1' when pos2_go,

'0' when others;

 

with state select

pos2_cnt_clr <= '1' when wait_to_go,

'0' when others;

 

with state select

done <= '1' when finish,

'0' when others;

 

with state select

timeout <= '1' when time_out,

'0' when others;

 

count_pos1: component lpm_counter -- finds position of 1st pulse (1 count = 1 mm travelled

generic map (LPM_WIDTH => pos_width)

port map (clock => clk,

cnt_en => pos1_cnt_en,

sclr => pos1_cnt_clr,

q => pos1_cnt_out);

 

count_pos2: component lpm_counter -- finds position of 1st pulse (1 count = 1 mm travelled

generic map (LPM_WIDTH => pos_width)

port map (clock => clk,

cnt_en => pos2_cnt_en,

sclr => pos2_cnt_clr,

q => pos2_cnt_out);

 

count_delay: component lpm_counter -- finds delay from sending to receiving

generic map (LPM_WIDTH => delay_count)

port map (clock => clk,

cnt_en => delay_cnt_en,

sclr => delay_cnt_clr,

q => delay_cnt_out);

 

pos1 <= pos1_cnt_out; -- outputs values of position counters to vectors for further computation

pos2 <= pos2_cnt_out;

 

end architecture behavioural;