Search code examples
vhdlclockdigital-design

VHDL clock divider flips between 0 and X every clk cycle


I'm starting out trying to learn VHDL after doing a little bit of Verilog.

This is my attempt at creating a clock divider: (largely taken from Making a clock divider)

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;

entity clock_192 is
    Port ( clk : in  STD_LOGIC;
           clr : in  STD_LOGIC;
           clk_out : out STD_LOGIC);
end clock_192;

architecture Behavioral of clock_192 is
signal q : std_logic_vector (23 downto 0);
begin
    clk_out <= q(23);
    process(clk,clr)
    begin
        if clr = '1' then
            q <= "000000000000000000000000";
        elsif clk'event and clk = '1' then
            q <= std_logic_vector(unsigned(q)+1);
        end if;
    end process;
end Behavioral;

And here is the test bench I'm using:

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 test_clock_192 IS
END test_clock_192;

ARCHITECTURE behavior OF test_clock_192 IS 

    -- Component Declaration for the Unit Under Test (UUT)

    COMPONENT clock_192
    PORT(
         clk : IN  std_logic;
         clr : IN  std_logic;
         clk_out : OUT  std_logic
        );
    END COMPONENT;


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

    --Outputs
   signal clk_out : std_logic;

   -- Clock period definitions
   constant clk_period : time := 10 ns;
   constant clk_out_period : time := 10 ns;

BEGIN

    -- Instantiate the Unit Under Test (UUT)
   uut: clock_192 PORT MAP (
          clk => clk,
          clr => clr,
          clk_out => clk_out
        );

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

   clk_out_process :process
   begin
        clk_out <= '0';
        wait for clk_out_period/2;
        clk_out <= '1';
        wait for clk_out_period/2;
   end process;


   -- Stimulus process
   stim_proc: process
   begin        
      -- hold reset state for 100 ns.
        clr <= '1';
      wait for 97 ns;   
        clr <= '0';

      wait for clk_period*10;

      -- insert stimulus here 

      wait;
   end process;

END;

The trouble is my clk_out signal keeps flipping between 0 and X with every cycle of clk. As seen here:

https://i.sstatic.net/RCvWi.png

Does anyone have an idea of what is going on?

EDIT: To fix the problem I had to change my test bench to look like this:

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 test_clock_192 IS
END test_clock_192;

ARCHITECTURE behavior OF test_clock_192 IS 

    -- Component Declaration for the Unit Under Test (UUT)

    COMPONENT clock_192
    PORT(
         clk : IN  std_logic;
         clr : IN  std_logic;
         clk_out : OUT  std_logic
        );
    END COMPONENT;


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

    --Outputs
   signal clk_out : std_logic;

   -- Clock period definitions
   constant clk_period : time := 10 ns;
   constant clk_out_period : time := 10 ns;

BEGIN

    -- Instantiate the Unit Under Test (UUT)
   uut: clock_192 PORT MAP (
          clk => clk,
          clr => clr,
          clk_out => clk_out
        );

   -- 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.
        clr <= '1';
      wait for 97 ns;   
        clr <= '0';

      wait for clk_period*10;

      -- insert stimulus here 

      wait;
   end process;

END;

Solution

  • The test bench drives the clk_out signal both from the uut instance and the clk_out_process process, and this makes the resolution function for the std_logic take effect.

    When both sources drive '0' then the resulting clk_out value will be '0', but if one source drives '0' and the other drives '1' then the resolution function will return 'X', as you see.

    You can look here for some description of "VHDL resolution function", or try google it.