1
0
Fork 0
mirror of https://github.com/RobotechLille/cdf2018-principal synced 2024-12-04 14:06:05 +01:00
cdf2018-principal/fpga/hcsr04.vhd

107 lines
4 KiB
VHDL

LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY hcsr04 IS
GENERIC(
fFpga : INTEGER := 50_000_000 -- frequency of the FPGA clock (Hz)
);
PORT(
clk : IN STD_LOGIC; -- clock of the FPGA
reset : IN STD_LOGIC; -- hard reset
echo : IN STD_LOGIC; -- echo pin of the hcsr04
distance : OUT INTEGER; -- Divide by 58 to get the value in cm
trigger : OUT STD_LOGIC; -- trigger pin of the hcsr04
start : IN STD_LOGIC; -- Set to '1' everytime a measurement is needed (or keep at '1' for continuous measurement)
finished : OUT STD_LOGIC -- Driven to '1' everytime a measurement has finished
);
END hcsr04;
ARCHITECTURE Behavioral OF hcsr04 IS
-- Generate us clock
CONSTANT fUs : INTEGER := 1_000_000; -- Frequency of the microsecond clock
CONSTANT usTicks : INTEGER := fFPGA / fUs / 2; -- Number of FPGA tick that makes a demi-microsecond
SIGNAL fpgaCounter : INTEGER; -- Count the microsecond
SIGNAL usClk : STD_LOGIC := '0'; -- Clock that ticks every us
-- Trigger
CONSTANT triggerDuration : INTEGER := 10; -- Number of us that makes up a trigger sequence
SIGNAL triggerCounter : INTEGER; -- Progress in the trigger sequence
SIGNAL theTrigger : STD_LOGIC := '0'; -- Trigger pin but with default value
-- Measurement
CONSTANT measurementDuration : INTEGER := 60_000; -- Number of us that makes up a measurement cycle
SIGNAL measurementCounter : INTEGER := 0; -- Progress in the measurement cycle
-- Distance
CONSTANT maxDistance : INTEGER := 29000; -- 5m
SIGNAL distanceCounter : INTEGER := 0; -- Distance measured (in us)
-- State machine
TYPE stateType IS (waiting, triggering, measuring);
SIGNAL state : stateType;
SIGNAL startUs : STD_LOGIC := '0'; -- A propagation of the start signal
BEGIN
us : process(clk, reset)
begin
if reset = '1' then
usClk <= '0';
fpgaCounter <= 0;
startUs <= '0';
elsif rising_edge(clk) then
if start = '1' then
startUs <= '1';
elsif state /= waiting then
startUs <= '0';
end if;
if fpgaCounter >= usTicks - 1 then
fpgaCounter <= 0;
usClk <= not usClk;
else
fpgaCounter <= fpgaCounter + 1;
end if;
end if;
end process;
trigger <= theTrigger;
measure : process(usClk, reset)
begin
if reset = '1' then
state <= waiting;
finished <= '0';
distance <= 0;
elsif rising_edge(usClk) then
CASE state IS
WHEN waiting =>
finished <= '0';
IF startUs = '1' THEN
theTrigger <= '1';
triggerCounter <= 0;
state <= triggering;
END IF;
WHEN triggering =>
triggerCounter <= triggerCounter + 1;
IF triggerCounter >= triggerDuration - 1 THEN
theTrigger <= '0';
measurementCounter <= 0;
distanceCounter <= 0;
state <= measuring;
END IF;
WHEN measuring =>
IF echo = '1' and distanceCounter < maxDistance THEN
distanceCounter <= distanceCounter + 1;
END IF;
measurementCounter <= measurementCounter + 1;
IF measurementCounter >= measurementDuration - 1 THEN
distance <= distanceCounter;
finished <= '1';
state <= waiting;
END IF;
END CASE;
end if;
end process;
END Behavioral;