Search code examples
genericsvhdlflip-flop

How Can I Modify This D-FF For Generic Setup/Hold Times?


I have coded the following negative-edge triggered D-FF below:

ENTITY d_ff IS
PORT (d, cl : IN BIT; q, qbar : INOUT BIT);
END d_ff;

ARCHITECTURE dataflow of d_ff IS

BEGIN
  PROCESS (clk)
  IF (clk = '0' AND clk'EVENT)
    q <= d;
  ELSE
  q <= q;
 END IF;
 END dataflow;

My question is, if I want to modify this code to include generic setup/hold times (say of 8 and 5 ns respectively), how would I do it? I know I should add a GENERIC statement in the entity for those times, but how would I use them in conditions? Could I not say something like:

If (d'STABLE(hold))
q <= d AFTER setup;

Or something similar?

Thanks for any and all help provided!


Solution

  • To check hold time you have to implement the DFF using wait statements. This allows you to manually control the progression through time to check parameters after the clock edge as well as before. One non-obvious "trick" is the use of d'delayed to create a new signal with a delta-cycle delay that allows us to avoid measuring the hold stable attribute from any simultaneous transition on d but rather from the previous transition on d.

    I've separated the Clock-to-Q parameter as an independent generic since this isn't generally the same as the hold time. Also note that this technique doesn't work with negative hold or setup times so I've restricted the generics to positive values using delay_length.

    library ieee;
    use ieee.std_logic_1164.all;
    
    entity dff is
      generic (
        Tsu  : delay_length := 8 ns; -- Setup
        Thld : delay_length := 5 ns; -- Hold
        Tcq  : delay_length := 6 ns  -- Clock to Q delay
      );
      port (
        clock, d : in std_logic;
        q : out std_logic
      );
    end entity;
    
    architecture behavior of dff is
    begin
    
      process
      begin
        assert Tcq >= Thld report "Tcq must be >= Thld" severity failure;
    
        wait until falling_edge(clock);
        if d'stable(Tsu) then
          wait for Thld;
          if d'delayed'stable(Thld) then
            q <= d after Tcq - Thld;
          else -- Hold violation
            report "Hold violation" severity warning;
            q <= 'X' after Tcq - Thld;
          end if;
        else -- Setup violation
          report "Setup violation" severity warning;
          q <= 'X' after Tcq;
        end if;
    
      end process;
    end architecture;