Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
9 years ago

Why a second process requires a signal "conditional" statement in order to work

Hi guys.

I'm working on an exercise for an undergraduate class, where I want the students to learn about different "processes" running in a single VHDL architecture. The goal is show them, it is possible to control where a process gets executed through the usage of a "user internal" signal.

So, I've thought about a time based process, that will give me a "call rate" for a 2nd process. The second one can be a 1s counter or just provide different output values each second.

We use DE0-Nano boards, so our clock source is a 50MHz oscillator.

I am able to synthesize the hardware for that, the point is, the second process only works if I add an "if" statement to test the signal in the sensitivity list. :confused: I can't understand why, can someone help me to make this clear?

I am sure the process gets executed each second, since I use out1 to toggle a LED. I want to remove the "inc" conditional test. I managed to make it count each second by reducing "CLK_FREQ to 25E06" but the other way looks just fine to me and should be working either, don't you think?

I appretiate any comment.

Thank you all.

Alex


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity countVHDL is
   port (Clock: in std_logic;
            Qc  : out integer range 15 downto 0;
            out1: out std_logic);
end countVHDL;
 
architecture behavior_counter of countVHDL is
    SIGNAL inc : std_logic := '0';        
    CONSTANT CLK_FREQ : integer := 50E06;
    
begin
    --the so called 2nd process...
    process(inc)
        variable q: integer range 0 to 15 := 0;
        
    begin
        if inc='1' then -- want to remove
            q:=q+1; --this should increase each second, since "inc" gets changed at 1s rate, doesn't it?
        end if;
        Qc<=q;
        out1<=inc;
    end process;
      
        --1st process, generates a 1s time base
    process(Clock)    
        variable prescaler: integer := 0;
    begin
        if (Clock = '1') then
            prescaler:=prescaler+1;
            if prescaler >= CLK_FREQ then
                inc<=not(inc);
                
                prescaler := 0;
            end if;
        end if;
    end process;
    
end behavior_counter;

4 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I Dont want to sound offensive, but as a teacher, you have written VHDL in a very bad style. Please Please read up on VHDL and good practice in regards to coding templates as you will be be passing on whatever you write. Your clocked process does not create a register - it tranditionally creates a transparent latch (although new versions of the tool WILL create a register, but I would not rely on this)

    The problem here is the way synthesis handles VHDL compared to the simulator handles VHDL, and the poor choice of VHDL used to produce the counter.

    As a rule, you should treat sensitivity lists as non-existent in the synthesis engine. So while it may work perfectly fine without the if statement in simulation, the synthesised hardware just makes Q into an adder that attempts to feedback itself and increment in 0 time. With the inc there, you just made a latch - which is very poor design pratice in FPGAs as they are prone timing issues (and they dont exist on an FPGA and have to be emulated).

    Using good practice, I would make inc the clock enable of a counter. I would also steer clear of using variables at all in beginner classes - there is NOTHING in VHDL you can do in synthesisable VHDL that requires a variable and cannot be done using signals. If they have any programming knowledge, variables are going to confuse them. Please stick to signals only.

    There is also another problem - integers do not roll over in VHDL - but the synthesised hardware will - another simulation/synthesis missmatch. The fix here is to use the unsigned type which does roll over as expected, and is part of the VHDL standard (Also - please never use std_logic_arith or std_logic_signed/unsigned packages, as these are NOT part of the VHDL standard):

    
    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;  -- for unsigned type
    Qc : out unsigned(3 downto 0);  -- 4 bit output 0 to 15
    ....
    signal qc_i : unsigned(3 downto 0) := x"0";
    process(clk)
    begin
      if rising_edge(clk) then
        if inc = '1' then
          qc_i <= qc_i + 1;
        end if;
      end if;
    end process;
    Qc <= qc_i;
    

    Ill leave you to fix the "1st" process
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    Hi guys.

    I'm working on an exercise for an undergraduate class, where I want the students to learn about different "processes" running in a single VHDL architecture. The goal is show them, it is possible to control where a process gets executed through the usage of a "user internal" signal.

    So, I've thought about a time based process, that will give me a "call rate" for a 2nd process. The second one can be a 1s counter or just provide different output values each second.

    We use DE0-Nano boards, so our clock source is a 50MHz oscillator.

    I am able to synthesize the hardware for that, the point is, the second process only works if I add an "if" statement to test the signal in the sensitivity list. :confused: I can't understand why, can someone help me to make this clear?

    I am sure the process gets executed each second, since I use out1 to toggle a LED. I want to remove the "inc" conditional test. I managed to make it count each second by reducing "CLK_FREQ to 25E06" but the other way looks just fine to me and should be working either, don't you think?

    I appretiate any comment.

    Thank you all.

    Alex

    
    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    entity countVHDL is
       port (Clock: in std_logic;
                Qc  : out integer range 15 downto 0;
                out1: out std_logic);
    end countVHDL;
     
    architecture behavior_counter of countVHDL is
        SIGNAL inc : std_logic := '0';        
        CONSTANT CLK_FREQ : integer := 50E06;
        
    begin
        --the so called 2nd process...
        process(inc)
            variable q: integer range 0 to 15 := 0;
            
        begin
            if inc='1' then -- want to remove
                q:=q+1; --this should increase each second, since "inc" gets changed at 1s rate, doesn't it?
            end if;
            Qc<=q;
            out1<=inc;
        end process;
          
            --1st process, generates a 1s time base
        process(Clock)    
            variable prescaler: integer := 0;
        begin
            if (Clock = '1') then
                prescaler:=prescaler+1;
                if prescaler >= CLK_FREQ then
                    inc<=not(inc);
                    
                    prescaler := 0;
                end if;
            end if;
        end process;
        
    end behavior_counter;
    

    --- Quote End ---

    two proesses are parallel and the inc must be included in that red coloured line so that the process can see it, otherwise it wouldn't and will keep incrementing q nonstop in a comb. feedback.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Not taken @Tricky, it is always time to learn more..

    Nevertheless, @kaz got the synthesised behavior.

    But "inc" is present in the second process "out1 <=inc;", why the signal is not seen without the red lines?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Modelsim will probably do the job you expect but synthesis tool ignores sensitivity list though wants it there. It is tool issue, nothing else. Hence from synthesis perspective presence of inc in second process is unrelated to q:= q+1 which will be seen as create comb feedback