Search code examples
timervhdlcounter

Generating second counter in VHDL


I am new to VHDL and trying to generate 1 second counter. For simplicity, I am using the clock frequency of 10 Hz. For this purpose I am using a clk as an input and LED as an output. My VHDL code is given below:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
USE ieee.std_logic_unsigned.ALL;
use ieee.numeric_std.all;

entity tick_counter is
    generic(FrequencyHz : integer := 10);
    Port ( clk : in  STD_LOGIC;
           led : out  STD_LOGIC);
end tick_counter;

architecture Behavioral of tick_counter is
    signal tick :integer;
    signal counter :integer;
begin
    process(clk, tick, counter)
    begin
        if rising_edge(clk) then
            if tick = FrequencyHz - 1 then
                tick <= 0;
                counter <= counter + 1;
            else
                tick <= tick + 1;
            end if;
        end if;
    end process;

    led <= '1' when counter = 3 else '0';
end Behavioral;

I tried to write the code in such a way so that, when three seconds pass, the LED turns ON. My test bench code is given below:

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.ALL;
use ieee.numeric_std.all;
 
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
 
ENTITY tick_counter_tb IS
END tick_counter_tb;
 
ARCHITECTURE behavior OF tick_counter_tb IS 
 
    -- Component Declaration for the Unit Under Test (UUT)
     -- We're slowing down the clock to speed up simulation time
    constant FrequencyHz : integer := 10; -- 10 Hz
    constant clk_period  : time    := 1000 ms / FrequencyHz;
 
    COMPONENT tick_counter
    PORT( clk : IN  std_logic;
          led : OUT  std_logic);
    END COMPONENT;

    --Inputs
    signal clk : std_logic := '0';

    --Outputs
    signal led : std_logic;

BEGIN
 
    -- Instantiate the Unit Under Test (UUT)
    uut : entity work.tick_counter
        generic map(FrequencyHz => FrequencyHz) 
        PORT MAP (clk => clk,
                  led => led);

    -- Clock process definitions
    clk_process :process
    begin
        clk <= '0';
        wait for clk_period/2;
        clk <= '1';
        wait for clk_period/2;
    end process;

    -- Stimulus process
    stim_proc: process
    begin       
        -- hold reset state for 100 ns.
        wait until rising_edge(clk);
        -- insert stimulus here 

        wait;
    end process;

END;

But in the simulation result, I am just seeing a blank diagram as shown below (link given):

Simulation Results

I don't understand where I am making a mistake. Any help would be highly appreciated.


Solution

  • The default initial value of an integer is INTEGER'LOW (a very negative number).

    That means counter won't become 3 for a very long time (as the busybee indicated).

    You can constrain and/or provide an initial value for tick. counter appears to be meant as a modulo counter range 0 to 3. It's modulus could be passed identically to tick which uses FrequencyHZ. Also note that any integer counter needs explicit roll over, it's an error if the result of an addition doesn't fall with the range INTEGER'LOW to INTEGER'HIGH or the constrained range.

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    -- USE ieee.std_logic_unsigned.ALL;
    -- use ieee.numeric_std.all;
    
    entity tick_counter is
        generic(FrequencyHz : integer := 10);
        Port ( clk : in  STD_LOGIC;
               led : out  STD_LOGIC);
    end tick_counter;
    
    architecture Behavioral of tick_counter is
        -- Initial value of integers is INTEGER'LOW (a large negative number)
        signal tick:    integer range 0 to FrequencyHz - 1 := 0;
        signal counter: integer := 0;   -- ADDED default initial value
    begin
        process(clk, tick, counter)
        begin
            if rising_edge(clk) then
                if tick = FrequencyHz - 1 then
                    tick <= 0;
                    if counter = 3 then  -- ADDED MODULUS 4 test for counter
                        counter <= 0;
                    else
                        counter <= counter + 1;
                    end if;
                else
                    tick <= tick + 1;
                end if;
            end if;
        end process;
    
        led <= '1' when counter = 3 else '0';
    end Behavioral;
    

    With the changes the simulation will cause led to be a '1' for one second every four seconds.

    enter image description here