Forum Discussion

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

problem (?) using shared variables

Hi,

I need your kind opinion. Please, anyone explain me why the following code is not running.

VHDL code (sel-explainable)


------------------------------------------------------
entity counter_with_sharedvar is
   port (clk: in bit;
         digit1, digit2: out integer range 0 to 9);
end entity;
------------------------------------------------------
architecture counter of counter_with_sharedvar is
   shared variable temp1, temp2: integer range 0 to 9;
begin
----------------------------------
   proc1: process (clk)
   begin
      if (clk'EVENT and clk='1') then
         if (temp1=9) then
            temp1 := 0;
         else
            temp1 := temp1 + 1;
         end if;
      end if;
   end process proc1;
----------------------------------
   proc2: process (clk)
   begin
      if (clk'EVENT and clk='1') then
         if (temp1=9) then
            if (temp2=9) then
               temp2 := 0;
            else
               temp2 := temp2 + 1;  
            end if;
         end if;
      end if;
   end process proc2;
----------------------------------
   digit1 <= temp1;
   digit2 <= temp2;
end architecture;

VHDL testbench code


entity tb_cct is
end entity tb_cct;
architecture arch of tb_cct is
   constant T: time := 20 ns;
   signal t_clk: bit;
    signal t_d1: integer range 0 to 9;
    signal t_d2: integer range 0 to 9;
begin
   uut: entity work.counter_with_sharedvar(counter)
         port map(clk => t_clk, digit1 => t_d1, digit2 => t_d2);
   process
    begin
       t_clk <= '0';
        wait for T/2;
        t_clk <= '1';
        wait for T/2;
    end process;
end arch;

simulation result (50 MHz oscilator)

https://www.alteraforum.com/forum/attachment.php?attachmentid=7548

Any ideas?

Regards

Jaraqui

26 Replies

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

    --- Quote Start ---

    you shouldnt use clk_en to generate a clock. Forget about generating a 2nd clock. Just use the clk_en directly.

    --- Quote End ---

    Hi,

    Based on your recommendation, I developed the following code:

    
    library ieee;
    use ieee.std_logic_1164.all;
    entity clock_gen is
       generic(N: integer := 10);
       port(
          mclk:  in std_logic;
          rst:  in std_logic;
          clk: out std_logic);
    end clock_gen;
    architecture arch of clock_gen is
       signal cnt: integer := 0;
    begin
       process(mclk, rst)
       begin
          if(rst = '1') then
             cnt <= 0;
    	 clk <= '0';
          elsif(rising_edge(mclk)) then
             cnt <= cnt + 1;
    	 if(cnt = N) then -- this will give you an enable rate of clk/N
                clk <= '1';
             else
                clk <= '0';
             end if;
          end if;
       end process;
    end arch;
    

    The simulation of this code produced the following result:

    https://www.alteraforum.com/forum/attachment.php?attachmentid=7549

    A "return to zero" was needed. Also, I would prefer a 50% duty cycle clock generator. So I did some modifications on your recommendation and produced the following code:

    
    library ieee;
    use ieee.std_logic_1164.all;
    entity clock_gen is
       generic(N: integer := 20);
       port(
    	   mclk:  in std_logic;
               rst:  in std_logic;
    	   clk: out std_logic);
    end clock_gen;
    architecture arch of clock_gen is
       signal    cnt: integer := 0;
    begin
       process(mclk, rst)
       begin
          if(rst = '1') then
             cnt <= 0;
    	 clk <= '0';
          elsif(rising_edge(mclk)) then
             cnt <= cnt + 1;
    	 if(cnt >= (N - 1)/2) then -- this will give you an enable rate of clk/N
                if(cnt = (N - 1)) then
                   clk <= '0';
    	       cnt <= 0;
    	    else
    	       clk <= '1';
    	    end if;
             else
                clk <= '0';
             end if;
          end if;
       end process;
    end arch;
    

    Regards

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

    This is the point, you're not supposed to generate a 50% duty cycle, as the "other" bit of code should also be using mclk as the clock. But it is only enabled with clk_en (hence it only works one in every N clocks)

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

    --- Quote Start ---

    This is the point, you're not supposed to generate a 50% duty cycle, as the "other" bit of code should also be using mclk as the clock. But it is only enabled with clk_en (hence it only works one in every N clocks)

    --- Quote End ---

    Sorry Tricky, my English is not so good... I didn´t understand very well this last message. Could you explain in other words, please?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    The problem is, you're generating a clock. You should never generate a clock. You should clock all logic with mclk. Then use clock_en to activate it:

    
    process(mclk)
    begin
      if rising_edge(mclk) then
        if clk_en = '1' then
          --only do something when clk_en is active, say 1 in every 50
        end if;
      end if;
    end process;
    

    So this way divides your clock without having any problems associated with a generated clock.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    The problem is, you're generating a clock. You should never generate a clock. You should clock all logic with mclk. Then use clock_en to activate it:

    
    process(mclk)
    begin
      if rising_edge(mclk) then
        if clk_en = '1' then
          --only do something when clk_en is active, say 1 in every 50
        end if;
      end if;
    end process;
    

    So this way divides your clock without having any problems associated with a generated clock.

    --- Quote End ---

    Ok! Now I understood! Thank you!

    Regards

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

    The main use for shared variables is in test benches

    have a look at OSVVM. ORG

    the free packages there make extensive use of SHARED VARIABLES

    They are also very useful verification packages.

    creating good stimulus is often a lot of work & is boring.

    SAVE YOURSELF A LOT OF WORK

    have a look at intelligent coverage at OSVVM. ORG

    Those packages can create intelligent random functional coverage stimulus for you.

    With very little effort from you they can create stimulus for all the functions you ask them to cover in your testbench.

    They are written by Jim Lewis & he leads the IEEE VHDL standard group who are working on the next version of VHDL after VHDL2008.