Stimulus Counter (from Opto-Sensors)

Guest
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:1:99b07bdbad]
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;
[/code:1:99b07bdbad]

I have also tried the following amendment:
[code:1:99b07bdbad]
--------------------------------------------
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;
--------------------------------------------
[/code:1:99b07bdbad]

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
 
james.purvis@students.plymouth.ac.uk wrote:
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:1:fd5de77af1]
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;
[/code:1:fd5de77af1]

I have also tried the following amendment:
[code:1:fd5de77af1]
--------------------------------------------
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;
--------------------------------------------
[/code:1:fd5de77af1]

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
 
On Jan 27, 7:45 pm, Gabor <ga...@szakacs.invalid> wrote:
james.pur...@students.plymouth.ac.uk wrote:
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:1:31e48a3730]
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;
[/code:1:31e48a3730]

I have also tried the following amendment:
[code:1:31e48a3730]
--------------------------------------------
   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;
--------------------------------------------
[/code:1:31e48a3730]

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
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.
 
On 27 Jan., 17:50, james.pur...@students.plymouth.ac.uk wrote:

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;
 

Welcome to EDABoard.com

Sponsor

Back
Top