library ieee;
use ieee.std_logic_1164.all;

entity D_LATCH is
  generic ( TPH : time := 3 ns);
  port ( LATCH_EN, OUT_EN, D : in std_logic;
         Q : out std_logic);
end entity D_LATCH;
  
architecture TIMING of D_LATCH is
  signal TEMP, LATCH_EN_DELAYED : std_logic;
begin
  LATCH_EN_DELAYED <= LATCH_EN'DELAYED(TPH);
  process (LATCH_EN_DELAYED)
  begin
    if (LATCH_EN_DELAYED = '1') then
      assert D'stable (TPH)
      report "Hold time violated"
      severity warning;
    end if;
  end process;
  
  process (D,  LATCH_EN)
  begin
    if (D'event and LATCH_EN = '1') then
      TEMP <= D after 4 ns;
    elsif (LATCH_EN'event and LATCH_EN = '1') then
      TEMP <= D after 3 ns;
    end if;
  end process;
  
  process ( TEMP, OUT_EN )
  begin
    if OUT_EN then
      Q <= TEMP after 2 ns;
    else
      Q <= 'Z' after 5 ns;
    end if;
  end process;
end TIMING;

library ieee;
use ieee.std_logic_1164.all;

entity LATCH_TB is
end LATCH_TB;

architecture LATCH_TB of LATCH_TB is
  signal LATCH_EN, D, Q, OUT_EN : std_logic;
begin
  U1 : entity work.D_LATCH(TIMING)
       port map (D => D, LATCH_EN => LATCH_EN, 
                 OUT_EN => OUT_EN, Q => Q);
  process
  begin
    D <= '0' after 5 ns, '1' after 25 ns, '0' after 40 ns,
        '1' after 67 ns;
    LATCH_EN <= '0' after 2 ns, '1' after 20 ns, 
                '0' after 35 ns, '1' after 65 ns;
    OUT_EN <= '0' after 0 ns, '1' after 22 ns,
                '0' after 35 ns, '1' after 70 ns;
    wait;
  end process;  
end architecture;   
  
    
    
