Stimulus Counter (from Opto-Sensors)

J

james.purvis

Hi,

I am a student of robotics at Plymouth University, England. I have
been using VHDL pretty solidly for about 5 months now and I have come
up against a rather devious problem. The project at hand is using a
small differential drive robot with an Altera Cyclone II FPGA and an
ATmel 64. Using the two active IR sensors on the robot we are to make
a line follower (easy part) that makes a "Happy" sound when it detects
that it has been on a black line twice (or more) within ten seconds
and a "Sad" sound if it has hit the line less than twice. The code
below is an entity which I intend to chose one of the two input
frequencies (Happy and Sad) and output the relevant one according to
the conditions previously specified.

Code:
library IEEE;
Use IEEE.std_logic_1164.all;
Use IEEE.numeric_std.all;
Use IEEE.math_real.all;

entity NoiseSelect is
port
(
-- Input ports
LftS		: in	std_logic;   -- Left Opto-Sensor
RgtS		: in	std_logic;   -- Right Opto-Sensor
Happy		: in	std_logic;
Sad			: in  	std_logic;
HappyDone	: in	std_logic;
SadDone		: in	std_logic;
Clk			: in	std_logic;   -- 1 Hz
SysClk		: in	std_logic;   -- 50 MHz

-- Output ports
TenFlagOut : out std_logic;
Outfreq	: out std_logic
);
end NoiseSelect;

architecture Selecter of NoiseSelect is

signal CanPlay			:	std_logic;
signal Count			:	unsigned (3 downto 0);
signal TenFlag 			:	std_logic;
signal StimCount		:	unsigned (5 downto 0);
signal StimCountFlag	        :	std_logic;
signal StimCountReset	:	std_logic;

begin

TenFlagOut <= TenFlag;
StimCountFlag <= RgtS or LftS;

--CanPlay <= not(HappyDone) and not(sadDone);
--------------------------------------------
TenSecCount: process(Clk,Count,TenFlag)
begin
if (Clk'event) and (Clk = '1') then -- Every one second
if (TenFlag = '0') then			-- provided Tens flag is 0
Count <= Count + 1;			-- increment counter
elsif (TenFlag = '1') then		-- until counter reaches 9 (0 to 9 =
10)
Count <= "0000";			-- then reset counter to 0
end if;
end if;
end process;
--------------------------------------------
CountReset:	process(Clk,Count,TenFlag)
begin
if (Count = "1001") then			-- When counter reaches 9
TenFlag <= '1';					-- Show that 10 seconds have passed
else
TenFlag <= '0';					-- Else keep 10 sec flag low
end if;
end process;
--------------------------------------------
StimulusCount: process(RgtS,LftS,TenFlag,StimCount)
begin
if (SysClk'event) and (SysClk = '1') then
if (StimCountFlag = '1') and (StimCountReset = '0') then
StimCount <= StimCount + 1;
elsif (StimCountFlag = '0') and (StimCountReset = '0') then
StimCount <= StimCount;
elsif (StimCountReset = '1') then
StimCount <= "000000";
end if;
end if;
end process;
--------------------------------------------
StimCountRes: process(TenFlag,StimCountReset)
begin
if (TenFlag'event) and (TenFlag = '0') then
StimCountReset <= '1';
end if;
if (TenFlag = '1') then
StimCountReset <= '0';
elsif (TenFlag = '0') then
StimCountReset <= '0';
end if;
end process;
--------------------------------------------
end Selecter;

I have also tried the following amendment:
Code:
--------------------------------------------
StimulusCount: process(RgtS,LftS,TenFlag,StimCount)
begin
if (SysClk'event) and (SysClk = '1') then
if (StimCountFlag = '1') then
StimCount <= StimCount + 1;
elsif (StimCountReset = '1') then
StimCount <= "000000";
end if;
end if;
end process;
--------------------------------------------
StimCountRes: process(TenFlag,StimCountReset)
begin
if (TenFlag'event) and (TenFlag = '0') then
StimCountReset <= '1';
else
StimCountReset <= '0';
end if;
end process;
--------------------------------------------

I have tried a lot of different methods to get this to work, but my
biggest gripe at the moment is that when using SignalTap II
"StimCount" is determined to be a Combinational Group and I cannot
prove that it counts, whilst "Count" is a Registered group and works
perfectly. I will be honest, I'm pretty sure that I've got completely
the wrong method for StimCount at the moment, so any help or insight
would be greatly appreciated.

Image of node finder: http://imageshack.us/photo/my-images/685/nodefinder.png/

Cheers

James
 
G

Gabor

Hi,

I am a student of robotics at Plymouth University, England. I have
been using VHDL pretty solidly for about 5 months now and I have come
up against a rather devious problem. The project at hand is using a
small differential drive robot with an Altera Cyclone II FPGA and an
ATmel 64. Using the two active IR sensors on the robot we are to make
a line follower (easy part) that makes a "Happy" sound when it detects
that it has been on a black line twice (or more) within ten seconds
and a "Sad" sound if it has hit the line less than twice. The code
below is an entity which I intend to chose one of the two input
frequencies (Happy and Sad) and output the relevant one according to
the conditions previously specified.

Code:
library IEEE;
Use IEEE.std_logic_1164.all;
Use IEEE.numeric_std.all;
Use IEEE.math_real.all;

entity NoiseSelect is
	port
	(
		-- Input ports
		LftS		: in	std_logic;   -- Left Opto-Sensor
		RgtS		: in	std_logic;   -- Right Opto-Sensor
		Happy		: in	std_logic;
		Sad			: in  	std_logic;
		HappyDone	: in	std_logic;
		SadDone		: in	std_logic;
		Clk			: in	std_logic;   -- 1 Hz
		SysClk		: in	std_logic;   -- 50 MHz

		-- Output ports
		TenFlagOut : out std_logic;
		Outfreq	: out std_logic
	);
end NoiseSelect;

architecture Selecter of NoiseSelect is

	signal CanPlay			:	std_logic;
	signal Count			:	unsigned (3 downto 0);
	signal TenFlag 			:	std_logic;
	signal StimCount		:	unsigned (5 downto 0);
	signal StimCountFlag	        :	std_logic;
	signal StimCountReset	:	std_logic;

begin

TenFlagOut <= TenFlag;
StimCountFlag <= RgtS or LftS;

--CanPlay <= not(HappyDone) and not(sadDone);
--------------------------------------------
	TenSecCount: process(Clk,Count,TenFlag)
	begin
		if (Clk'event) and (Clk = '1') then -- Every one second
			if (TenFlag = '0') then			-- provided Tens flag is 0
				Count <= Count + 1;			-- increment counter
			elsif (TenFlag = '1') then		-- until counter reaches 9 (0 to 9 =
10)
				Count <= "0000";			-- then reset counter to 0
			end if;
		end if;
	end process;
--------------------------------------------
	CountReset:	process(Clk,Count,TenFlag)
	begin
		if (Count = "1001") then			-- When counter reaches 9
			TenFlag <= '1';					-- Show that 10 seconds have passed
		else
			TenFlag <= '0';					-- Else keep 10 sec flag low
		end if;
	end process;
--------------------------------------------
	StimulusCount: process(RgtS,LftS,TenFlag,StimCount)
	begin
		if (SysClk'event) and (SysClk = '1') then
			if (StimCountFlag = '1') and (StimCountReset = '0') then
				StimCount <= StimCount + 1;
			elsif (StimCountFlag = '0') and (StimCountReset = '0') then
				StimCount <= StimCount;
			elsif (StimCountReset = '1') then
				StimCount <= "000000";
			end if;
		end if;
	end process;
--------------------------------------------
	StimCountRes: process(TenFlag,StimCountReset)
	begin
		if (TenFlag'event) and (TenFlag = '0') then
			StimCountReset <= '1';
		end if;
		if (TenFlag = '1') then
			StimCountReset <= '0';
		elsif (TenFlag = '0') then
			StimCountReset <= '0';
		end if;
	end process;
--------------------------------------------
end Selecter;

I have also tried the following amendment:
Code:
--------------------------------------------
	StimulusCount: process(RgtS,LftS,TenFlag,StimCount)
	begin
		if (SysClk'event) and (SysClk = '1') then
			if (StimCountFlag = '1') then
				StimCount <= StimCount + 1;
			elsif (StimCountReset = '1') then
				StimCount <= "000000";
			end if;
		end if;
	end process;
--------------------------------------------
	StimCountRes: process(TenFlag,StimCountReset)
	begin
		if (TenFlag'event) and (TenFlag = '0') then
			StimCountReset <= '1';
		else
			StimCountReset <= '0';
		end if;
	end process;
--------------------------------------------

I have tried a lot of different methods to get this to work, but my
biggest gripe at the moment is that when using SignalTap II
"StimCount" is determined to be a Combinational Group and I cannot
prove that it counts, whilst "Count" is a Registered group and works
perfectly. I will be honest, I'm pretty sure that I've got completely
the wrong method for StimCount at the moment, so any help or insight
would be greatly appreciated.

Image of node finder: http://imageshack.us/photo/my-images/685/nodefinder.png/

Cheers

James

For a clocked process, ONLY the clock should be in the sensitivity list.
The only exception is a clocked process with async reset, in which case
the sensitivity list should contain clock and reset. For example:

StimulusCount: process(SysClk)
begin
if (SysClk'event) and (SysClk = '1') then
if (StimCountFlag = '1') then
StimCount <= StimCount + 1;
elsif (StimCountReset = '1') then
StimCount <= "000000";
end if;
end if;
end process;

For a process to be combinatorial, there should be no 'event
dependencies and all of the right hand side signals should
be in the sensitivity list. For example:

StimCountRes: process(TenFlag)
begin
if (TenFlag = '0') then
StimCountReset <= '1';
else
StimCountReset <= '0';
end if;
end process;

This describes a simple inverter. If you really wanted a pulse on the
falling edge of TenFlag, then you would need some other event like
a SysClk edge to reset the signal. As originally coded only an
edge on TenFlag would cause the else clause to trigger, and that
would probably only work for simulation. I would have expected
synthesis to give an error.

-- Gabor
 
T

Tricky

I am a student of robotics at Plymouth University, England. I have
been using VHDL pretty solidly for about 5 months now and I have come
up against a rather devious problem. The project at hand is using a
small differential drive robot with an Altera Cyclone II FPGA and an
ATmel 64. Using the two active IR sensors on the robot we are to make
a line follower (easy part) that makes a "Happy" sound when it detects
that it has been on a black line twice (or more) within ten seconds
and a "Sad" sound if it has hit the line less than twice. The code
below is an entity which I intend to chose one of the two input
frequencies (Happy and Sad) and output the relevant one according to
the conditions previously specified.
Code:
library IEEE;
Use IEEE.std_logic_1164.all;
Use IEEE.numeric_std.all;
Use IEEE.math_real.all;[/QUOTE]
[QUOTE]
entity NoiseSelect is
   port
   (
           -- Input ports
           LftS            : in    std_logic;   -- Left Opto-Sensor
           RgtS            : in    std_logic;   -- Right Opto-Sensor
           Happy           : in    std_logic;
           Sad                     : in   std_logic;
           HappyDone       : in    std_logic;
           SadDone         : in    std_logic;
           Clk                     : in   std_logic;   -- 1 Hz
           SysClk          : in    std_logic;  -- 50 MHz[/QUOTE]
[QUOTE]
           -- Output ports
           TenFlagOut : out std_logic;
           Outfreq : out std_logic
   );
end NoiseSelect;[/QUOTE]
[QUOTE]
architecture Selecter of NoiseSelect is[/QUOTE]
[QUOTE]
   signal CanPlay                  :       std_logic;
   signal Count                    :       unsigned (3 downto 0);
   signal TenFlag                  :       std_logic;
   signal StimCount                :       unsigned (5 downto 0);
   signal StimCountFlag            :       std_logic;
   signal StimCountReset   :       std_logic; 

TenFlagOut <= TenFlag;
StimCountFlag <= RgtS or LftS;[/QUOTE]
[QUOTE]
--CanPlay <= not(HappyDone) and not(sadDone);
--------------------------------------------
   TenSecCount: process(Clk,Count,TenFlag)
   begin
           if (Clk'event) and (Clk = '1') then -- Every one second
                   if (TenFlag = '0') then                 -- provided Tens flag is 0
                           Count <= Count+ 1;                  -- increment counter
                   elsif (TenFlag = '1') then             -- until counter reaches 9 (0 to 9 =
10)
                           Count <= "0000";                   -- then reset counter to 0
                   end if;
           end if;
   end process;
--------------------------------------------
   CountReset:     process(Clk,Count,TenFlag)
   begin
           if (Count = "1001") then                      -- When counter reaches 9
                   TenFlag <= '1';                                      -- Show that10 seconds have passed
           else
                   TenFlag <= '0';                                      -- Else keep10 sec flag low
           end if;
   end process;
--------------------------------------------
   StimulusCount: process(RgtS,LftS,TenFlag,StimCount)
   begin
           if (SysClk'event) and (SysClk = '1') then
                   if (StimCountFlag = '1') and (StimCountReset = '0') then
                           StimCount <= StimCount + 1;
                   elsif (StimCountFlag = '0') and (StimCountReset = '0') then
                           StimCount <= StimCount;
                   elsif (StimCountReset = '1') then
                           StimCount <= "000000";
                   end if;
           end if;
   end process;
--------------------------------------------
   StimCountRes: process(TenFlag,StimCountReset)
   begin
           if (TenFlag'event) and (TenFlag = '0') then
                   StimCountReset <= '1';
           end if;
           if (TenFlag = '1') then
                   StimCountReset <= '0';
           elsif (TenFlag = '0') then
                   StimCountReset <= '0';
           end if;
   end process;[/QUOTE]
[QUOTE]
I have also tried the following amendment:
[code]
--------------------------------------------
   StimulusCount: process(RgtS,LftS,TenFlag,StimCount)
   begin
           if (SysClk'event) and (SysClk = '1') then
                   if (StimCountFlag = '1') then
                           StimCount <= StimCount + 1;
                   elsif (StimCountReset = '1') then
                           StimCount <= "000000";
                   end if;
           end if;
   end process;
--------------------------------------------
   StimCountRes: process(TenFlag,StimCountReset)
   begin
           if (TenFlag'event) and (TenFlag = '0') then
                   StimCountReset <= '1';
           else
                   StimCountReset <= '0';
           end if;
   end process;[/QUOTE]
[QUOTE]
I have tried a lot of different methods to get this to work, but my
biggest gripe at the moment is that when using SignalTap II
"StimCount" is determined to be a Combinational Group and I cannot
prove that it counts, whilst "Count" is a Registered group and works
perfectly. I will be honest, I'm pretty sure that I've got completely
the wrong method for StimCount at the moment, so any help or insight
would be greatly appreciated.[/QUOTE]
[QUOTE]
Image of node finder:http://imageshack.us/photo/my-images/685/nodefinder.png/ 

James[/QUOTE]

For a clocked process, ONLY the clock should be in the sensitivity list.
The only exception is a clocked process with async reset, in which case
the sensitivity list should contain clock and reset.  For example:

StimulusCount: process(SysClk)
begin
        if (SysClk'event) and (SysClk = '1') then
                if (StimCountFlag = '1') then
                        StimCount <= StimCount + 1;
                elsif (StimCountReset = '1') then
                        StimCount <= "000000";
                end if;
        end if;
end process;

For a process to be combinatorial, there should be no 'event
dependencies and all of the right hand side signals should
be in the sensitivity list.  For example:

StimCountRes: process(TenFlag)
begin
        if (TenFlag = '0') then
                StimCountReset <= '1';
        else
                StimCountReset <= '0';
        end if;
end process;

This describes a simple inverter.  If you really wanted a pulse on the
falling edge of TenFlag, then you would need some other event like
a SysClk edge to reset the signal.  As originally coded only an
edge on TenFlag would cause the else clause to trigger, and that
would probably only work for simulation.  I would have expected
synthesis to give an error.

-- Gabor[/QUOTE]

It wont cause an error, because synthesisors ignore sensitivity lists,
and in this case will simply put an inverter, as you suggested. The
only reason to tidy up excessive sensitivity lists is for speeding up
simulation - it has no effect on synthesis. A bigger issue is when
signal are missed from the sensitivity list (like the 3rd process in
the OPs code - Sysclk is missing) because then the hardware will not
behave like the code.
 
T

Thomas Stanka

Use IEEE.math_real.all;

I would first get rid of unused libraries, you never know when they
strike back.

Your design uses 3 different clock domains (Clk, SysClk and TenFlag)
the signal crossings between these clock domains are not secure, this
will screw up your hardware.

Your StimCountRes-Process is complete weird. I can't think of a
hardware representation that would represent the code behavior.

I would start using only one clock domain (SysClk) and use
oversampling to detect rising edge of Clk every second.
A lot of the code seems to me quite complex description of simple
needed functionality (eg in clocked prcoess you don't need line to
hold value (A <= A);

On a first glance all your code could be written in the following
process syncronous to SysClk. I would prefer to use reset in every
case, to ensure your design starts in defined state.

signal Clk_Edge_Sr : std_ulogic_vector(3 downto 0);
process(SysClk, Reset)
if Reset = RESET_ACTIVE then
Clk_Edgedetect <= '0';
Clk_Edge_Sr <= (others => '0');
Second <= 0;
TenFlag <= '0'
elsif rising_egde(SysClk)
Clk_Edge_Sr <= Clk_Edge_Sr(2 downto 0) & Clk;
if StimCountFlag = '1' then
StimCount <= StimCount+1;
end if;
if Clk_Edge_Sr(3 downto 1) = "011" then
StimCount <= (others => '0);
if Second < 9 then
Second <= Second +1
TenFlag <= '0';
else
Second <= 0;
TenFlag <= '1';
end if;
end if;
end if;
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top