Search code examples
vhdlsimulation

Simple VHDL clocked counter simulation confusion


I am currently slightly confused about my simple counter. It is implemented as follows:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity simple_counter is
    port( 
        DOUT : out std_logic_vector(3 downto 0);
        CE : in std_logic;
        CLK : in std_logic;
        RSTN : in std_logic
    );
end simple_counter;

architecture behavioral of simple_counter is
    signal temp : unsigned(3 downto 0);

begin   

    process(CLK)
    begin
        if RSTN = '0' then
            temp <= (others => '0');
        elsif(rising_edge(CLK)) then
            if CE = '1' then
                if std_logic_vector(temp) = (temp'range => '1') then
                    temp <= (others => '0');
                else
                    temp <= temp + 1;
                end if;
            end if;
        end if;
    end process;

    DOUT <= std_logic_vector(temp);

end behavioral;

I use the following testbench for simulation:

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

use work.tools_pkg.all;

library work;

--! @class  tools_tb
--! @brief  Test bench for the tools_tb design
entity counter_tb is
  generic (
    VOID : integer := 0);
  port (
    void_i : in std_logic);
end entity counter_tb;

--! @brief
--! @details
architecture sim of counter_tb is

    -- Clock period definitions
    -- Clock, reset and baud rate definitions
    constant CLK_FREQ   : integer   := 100_000_000;
    constant clk_period : time      := (1.0 / real(CLK_FREQ)) * (1 sec);
    signal end_sim          : boolean := false;

    signal rstn             : std_logic;
    signal clk              : std_logic;
    signal s_en             : std_logic := '0';

    ------------------------------------------------------------------------------
    -- DUT signals
    ------------------------------------------------------------------------------

    signal s_dout        : std_logic_vector(3 downto 0) := (others => '0');
    signal s_ce          : std_logic := '0';

begin  -- architecture 


    fifo : entity work.simple_counter
    port map (
        DOUT => s_dout,
        CE  => s_ce,
        RSTN => rstn,
        CLK => clk
    );


    -- Clock process definitions (clock with 50% duty cycle is generated here).
    clk_process : process
    begin
        if end_sim = false then
            clk <= '1';
            wait for clk_period/2;
            clk <= '0';
            wait for clk_period/2;
        else
            wait;
        end if;
    end process;

    -- Stimulus process
    stim_proc: process
    begin
        -- startup and wait for some time
        rstn <= '0';
        wait for clk_period;
        rstn <= '1';
        wait for clk_period;
        wait for clk_period;
        wait for clk_period;

        s_ce <= '1';

        wait;
    end process;

end architecture sim;

I am confused why the counter increases instantly when I set CE <= '1 (see the attached simulation). enter image description here Since the counter is implemented in a synchrous process, shouldn't it take a single clock cycle until it is increased from '0' to '1'?

Thanks a lot!


Solution

  • You most likely have a race condition between s_ce and clk. If you will generate the s_ce on the rising edge of clk then you should see that counter works correctly.

    I don't know this simulator but to check the race you can expand deltas when counter changes 0->1