VHDL – Clock Divider Problem

testbenchvhdl

I have a 100 Mhz clock and I need a 0.5 Khz clock. So I wrote this code:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity clkdiv is
    Port ( clk : in STD_LOGIC;
           reset : in STD_LOGIC;
           clkout : out STD_LOGIC);
end clkdiv;

architecture Behavioral of clkdiv is
signal temporal : std_logic := '0';
signal counter : integer range 0 to 99999 := 0;
begin
process (reset, clk) begin
if (reset = '1') then
       temporal <= '0';
       counter  <= 0;
elsif rising_edge(clk) then
    if (counter = 99999) then
        temporal <= not temporal;    
        counter <= 0;
    else
        counter <= counter + 1;
    end if;
end if;
end process;
clkout <= temporal;

end Behavioral;

And testbench for it:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;



entity testbench is
    
end testbench;

architecture Behavioral of testbench is
component clkdiv
Port ( clk : in STD_LOGIC;
           reset : in STD_LOGIC;
           clkout : out STD_LOGIC);
           end component;
 
signal clk : std_logic := '0';
signal reset : std_logic := '0';
signal clkout : std_logic;
constant clk_in_t : time := 10 ns;
        
begin
uut : clkdiv port map (
    clk => clk,
    reset => reset,
    clkout => clkout);
    
    process
    begin
    clk <= '0';
    wait for clk_in_t / 2;
    clk <= '1';
    wait for clk_in_t / 2;
    end process;
    
process
    begin
    reset <='1';
    wait for 100 ns;
    reset <= '0';
    wait;
    end process;
end;

However, testbench results are like that:
enter image description here

Can anyone tell me what's wrong? Thank you all.

Best Answer

I've rounded up all the good advice from the comments into an answer.

Clock Strobe

Generates a slower strobe from a faster clock.

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity ClockStrobe is
    generic
    (
        CLOCK_PERIOD : time := 20 ns;
        STROBE_PERIOD: time := 2 ms
    );
    port
    (
        reset : in std_logic;
        clock : in std_logic;
        strobe: out std_logic
    );
end entity;

architecture V1 of ClockStrobe is

    constant MAX_COUNT: natural := STROBE_PERIOD / CLOCK_PERIOD - 1;
    signal counter: natural range 0 to MAX_COUNT := 0;  -- Specify the range to reduce number of bits that are synthesised.

begin

    process(all)
    begin
        if reset then
            strobe <= '0';
            counter <= 0;
        elsif rising_edge(clock) then
            if counter = MAX_COUNT then
                strobe <= '1';
                counter <= 0;
            else
                strobe <= '0';
                counter <= counter + 1;
            end if;
        end if;
    end process;

end architecture;

Test Bench

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;

entity ClockStrobe_TB is
end;

architecture V1 of ClockStrobe_TB is

    constant clock_period : time := 10 ns;
    constant STROBE_PERIOD: time := 2 ms;
    -- constant CLOCK_PERIOD : time := 10 ns;
    -- constant STROBE_PERIOD: time := 40 ns;

    signal halt_sys_clock: boolean := false;

    signal reset: std_logic := '0';
    signal clock: std_logic := '0';
    signal strobe: std_logic;

    component ClockStrobe is
        generic
        (
            CLOCK_PERIOD : time := 20 ns;
            STROBE_PERIOD: time := 2 ms
        );
        port
        (
            reset : in std_logic;
            clock : in std_logic;
            strobe: out std_logic
        );
    end component;

begin

    ClockGenerator:
    process
    begin
        while not halt_sys_clock loop
            clock <= not clock;
            wait for CLOCK_PERIOD / 2.0;
        end loop;
        wait;
    end process ClockGenerator;

    Stimulus:
    process
    begin
        -- Do reset.
        wait for CLOCK_PERIOD / 4;
        reset <= '1';
        wait for CLOCK_PERIOD / 2;
        reset <= '0';

        -- Wait for a couple of strobes.
        wait for 2.1 * STROBE_PERIOD;

        -- Halt simulation.
        halt_sys_clock <= true;
        wait;
    end process;

    CS:
        ClockStrobe
        generic map
        (
            CLOCK_PERIOD => CLOCK_PERIOD,
            STROBE_PERIOD => STROBE_PERIOD
        )
        port map
        (
            reset => reset,
            clock => clock,
            strobe => strobe
        );

end architecture;

Simulation Results

Clock Strobe Simulation Results

Figure 1 – Clock strobe simulation results: 100 MHz clock; 500 Hz strobe.

Using the Clock Strobe

And here is how to use the clock strobe for slow logic.

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity SlowLogic is
    port
    (
        reset : in std_logic;
        clock : in std_logic;
        strobe: in std_logic
        -- Slow inputs and outputs here.
    );
end entity;

architecture V1 of SlowLogic is

begin

    process(all)
    begin
        if reset then
            -- Reset slow outputs, etc.
        elsif rising_edge(clock) then
            if strobe then
                -- Do slow logic on inputs and outputs.
            end if;
        end if;
    end process;

end architecture;
Related Topic