Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
16597 Discussions

VHDL Code For Ultrasonic Distance Sensor HC-SR04

Altera_Forum
Honored Contributor II
10,824 Views

I am trying to write the VHDL code for it but it is not working, it shows always 00 ( cm1 = 0 and cm0 = 0). Can you pleaseee help me? Do you detect any problem in the code: 

 

Summation of how the sensor works: you send 10 us trigger to the sensor and then wait for the echo signal from it. The width of the echo determines the distance. In 5800 clk cycles of echo you measure 1 cm( with 100 MHZ clk of BASYS 3). Here is the code: 

 

 

 

library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity sonar is Port ( clk : in STD_LOGIC; trig : out STD_LOGIC;--trigger echo : in STD_LOGIC; cm1 : out unsigned(3 downto 0); --most significant bit of distance in binary form cm0 : out unsigned(3 downto 0)); end sonar; architecture sonar_arch of sonar is signal count: integer range 0 to 5800; -- I will only measure up to 100 cm signal tmpcm1: unsigned(3 downto 0) := "0000"; --most significant bit of ditance signal tmpcm0: unsigned(3 downto 0) := "0000"; signal sendTrig: std_logic := '1'; begin process(clk) begin if rising_edge(clk) then if sendTrig = '1' then -- send 10us trig if count = 10000 then -- 10 us trig is completed, reset tmp signals for the new calculation trig <= '0'; sendTrig <= '0'; count <= 0; tmpcm0 <= "0000"; tmpcm1 <= "0000"; else trig <= '1'; count <= count + 1; end if; else -- stop sending trig, do the calculation (5800 clk cycle = 1cm)(count enters here as 0) if echo = '1' then -- we can start calculating the width of the echo if count = 5799 then--we measuered 1 cm if tmpcm0 = "1001" then if tmpcm1 = "1001" then sendTrig <= '1';--max distance to be measured(100 cm), stop measuring, re-send the trig(also update the output) cm0 <= tmpcm0; cm1 <= tmpcm1; else tmpcm1 <= tmpcm1 + "0001"; tmpcm0 <= "0000"; end if; else tmpcm0 <= tmpcm0 + "0001"; end if; count <= 0; else count <= count + 1; end if; if echo = '0' then --equivalent of if falling_edge(echo), distance is measured, send another trig(also update te output) sendTrig <= '1'; cm0 <= tmpcm0; cm1 <= tmpcm1; end if; end if; end if; end if; end process; end sonar_arch;
0 Kudos
3 Replies
Altera_Forum
Honored Contributor II
6,147 Views

Well, for a start, you have the following structure: 

 

if echo = '1' then if echo = '0' then --this is impossible, as echo cannot be '1' and '0' at the same time  

 

This case will never occur. 

 

If you have a "working" simulation, but it's not working in hardware, then I suggest there is something wrong with how you're testing your code. Maybe you misunderstood how the echo works? or how some other interface should work?
0 Kudos
Altera_Forum
Honored Contributor II
6,147 Views

Yes I realized that mistake. I edited my code accordingly this way, but it still does not work. It either shows 99 or 00 after each reprograming the FPGA. Also I don't know how to write the testbench:( I would appreciate if you write it for me( I believe it is quite easy for a given code, otherwise I wouldn't ask such a thing.). The new code is: 

 

 

library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity sonar is Port ( clk : in STD_LOGIC; trig : out STD_LOGIC;--trigger echo : in STD_LOGIC; cm1 : out unsigned(3 downto 0); --most significant bit of distance in binary form cm0 : out unsigned(3 downto 0)); end sonar; architecture sonar_arch of sonar is begin process(clk) variable count: integer range 0 to 10000; variable tmpcm1: unsigned(3 downto 0) := "0000"; variable tmpcm0 : unsigned(3 downto 0) := "0000"; variable sendTrig: std_logic := '1'; variable echoPrev: std_logic:= '0'; variable echoCurrent : std_logic:= '0'; begin if rising_edge(clk) then if sendTrig = '1' then -- send 10us trig if count = 1000 then -- 10 us trig is completed, reset tmp signals for the new calculation trig <= '0'; sendTrig := '0'; count := 0; tmpcm0 := "0000"; tmpcm1 := "0000"; else trig <= '1'; count := count + 1; end if; else -- stop sending trig, do the calculation (5800 clk cycle = 1cm)(count enters here as 0) if echo = '1' then -- we can start calculating the width of the echo if count = 5799 then--we measuered 1 cm if tmpcm0 = "1001" then if tmpcm1 = "1001" then sendTrig := '1';--max distance to be measured(100 cm), stop measuring, re-send the trig(also update the output) cm0 <= tmpcm0; cm1 <= tmpcm1; else tmpcm1 := tmpcm1 + "0001"; tmpcm0 := "0000"; end if; else tmpcm0 := tmpcm0 + "0001"; end if; count := 0; else count := count + 1; end if; if echoPrev = '1' and echoCurrent = '0' then --falling edge of echo, edit the output, start sending new trigger sendTrig := '1'; cm0 <= tmpcm0; cm1 <= tmpcm1; end if; end if; end if; echoPrev := echoCurrent; echoCurrent := echo; end if; end process; end sonar_arch;
0 Kudos
Altera_Forum
Honored Contributor II
6,147 Views

There are many tutorials on the internet on how to write a testbench. 

I suggest having a go yourself, and coming back here with any issues you are having. 

 

One thing I would recommend is that you do not use variables. Use all signals
0 Kudos
Reply