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;