I'm trying to model an SN74HC573 D-type latch in VHDL to get back into it. Here's what I got so far:

-- simple model of a SN74AHC573 D-type Transparent Latch
library ieee;
use ieee.std_logic_1164.all;

-- entity declaration
entity sn74ahc573 is
    port ( oe_n, le : in std_logic;     -- control signals
           d : in std_logic;            -- data input
           q : out std_logic );         -- data output

    -- TODO: add detailed timing constants
    constant t_pd   : delay_length := 9 ns;     -- Propagation delay
    constant t_w    : delay_length := 5 ns;     -- Pulse duration, LE high
    constant t_su   : delay_length := 3.5 ns;   -- Setup time, data before LE falling edge
    constant t_h    : delay_length := 1.5 ns;   -- Hold time, data after LE falling edge
end entity sn74ahc573;

-- rtl architecture to check metastability
architecture rtl of sn74ahc573 is
    signal intern : std_logic := 'X';
begin

    -- concurrent replacement of behavioral process
    -- TODO: replace with state machine for more precise propagation delays
    intern <= 'Z' when oe_n = '1' else              -- high-impedance state
               d  when oe_n = '0' and le = '1' else -- latch input
               unaffected;                          -- else, nothing happens

    -- check metastability of latch enable signal
    checkMetaStability : process is
    begin
        -- wait for LE falling edge
        wait until falling_edge(le);

        --check pulse width
        assert le'delayed'stable(t_w)
            report "LE pulse width too short!"
            severity failure;

        -- check setup time
        assert intern'delayed'stable(t_su)
            report "Input changed during setup time!"
            severity failure;

        -- check hold time
        wait for t_h;
        assert intern'delayed'stable(t_h + t_su)
            report "Input signal changed during hold time!"
            severity failure;

    end process checkMetaStability;

    -- update output
    q <= intern;

end architecture rtl;

I'm having trouble with the process checking metastability. Checking for pulse width and setup time works, but checking hold time will fail:

-- Test Bench for SN74AHC573 model
library ieee;
use ieee.std_logic_1164.all;

-- entity declaration
entity sn74ahc573_tb is
end entity sn74ahc573_tb;

-- test bench architecture
architecture test_bench of sn74ahc573_tb is
    signal oe_n, le, d, q : std_logic := '0';
begin

    dut : entity work.sn74ahc573(rtl)
        port map ( oe_n, le, d, q );

    stimulus : process is
    begin
        -- start in high-Z mode
        oe_n <= '1'; wait for 10 ns;

        -- WARNING: These signal changes violate metastability
        oe_n <= '0'; le <= '1'; d <= '1'; wait for 4 ns;
            -- violate minimal pulse width
        -- le <= '0'; wait for 1 ns;
            -- violate setup time
        -- d <= '0';  wait for 1 ns;
        -- le <= '0'; wait for 1 ns;
            -- violate hold time
         wait for 1 ns; le <= '0';
         wait for 1 ns; d <= '0';

        -- wait forever
        wait;

    end process stimulus;

end architecture test_bench;

This test bench will "fail" for pulse width and setup time, but not when checking hold time. What am I missing?

I'm using GHDL 0.36-dev on Arch Linux.

  • If the input is not repetitive, can you hold forever? – Tony EE rocketscientist Sep 23 at 2:34
  • I'm not sure what you're referencing; I want to check whether the signal intern changes within 1.5 ns after LE's falling edge. – georgjz Sep 23 at 2:40
  • got it....,,.... – Tony EE rocketscientist Sep 23 at 3:06
up vote 2 down vote accepted

I am answering because I can't comment.

You have deasserted le before changing the input d in your testbench.

In the DUT, however,

intern <= 'Z' when oe_n = '1' else              -- high-impedance state
           d  when oe_n = '0' and le = '1' else -- latch input
           unaffected;                          -- else, nothing happens

As intern is unaffected when le is deasserted and oe_n is asserted (0), it holds the previous value of d (in this case 1). When you check for the hold time, no matter how long you wait, the assert will not fail.

    -- check hold time
    wait for t_h;
    assert intern'delayed'stable(t_h + t_su)

This change in testbench (similar to what you have done for setup violation) should solve the problem. By deasserting le after input d changes, the hold check should fail.

stimulus : process is
begin
    -- start in high-Z mode
    oe_n <= '1'; wait for 10 ns;

    -- WARNING: These signal changes violate metastability
    oe_n <= '0'; le <= '1'; d <= '1'; wait for 4 ns;

    -- violate setup time
    -- d <= '0';  wait for 1 ns;
    -- le <= '0'; wait for 1 ns;

    -- violate hold time
     d <= '0';
     wait for 1 ns; le <= '0';

    -- wait forever
    wait;

end process stimulus;
  • It's not entirely what I'm looking for, since signal d needs to change after the le falling edge for a hold time violation. But I believe your general assessment is correct, I'll have a look again and come back when I had time to try it out. – georgjz Sep 25 at 20:46

Thanks to Vinay Madapura's answer, I found the error. I modified my signal assignments to this:

-- latch the input according to LE state
intern <= d when le = '1' else
          unaffected;

-- update output
q <= intern when oe_n = '0' else
     'Z';

This reflects the overall behavior better than my old code. The input is now correctly latched into intern regardless of oe_n's state.

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.