-- DFF with preset, clear (no enable) and timing checking -- Author: B. Shepardson -- Date: 10/16/03 -- For use in EE365 class projects -- Revised 10/30/03 -- Fixed: added output changes to Q_L during clears and presets -- (previously only Q changed during clears and presets) -- Added: comments to generic timing parameters to clarify -- what each one stands for library ieee; use ieee.std_logic_1164.all; entity gate_74x74 is generic ( t_setup : time; -- setup time from D transition to rising clock edge t_hold : time; -- hold time from rising clock edge to D transition tp_hl : time; -- high-to-low propagation time (from rising clock edge) tp_lh : time; -- low-to-high propagation time (from rising clock edge) t_clr : time; -- time for CLR_L to drive Q from high to low (or -- time for PRE_L to drive Q_L from high to low) t_preset : time; -- time for CLR_L to drive Q from low to high (or -- time for PRE_L to drive Q_L from low to high) t_clr_pw : time; -- minimum pulse width for CLR_L t_preset_pw : time -- minimum pulse width for PRE_L ); port ( D : in std_logic; CLK : in std_logic; CLR_L : in std_logic; PRE_L : in std_logic; Q : out std_logic; Q_L : out std_logic ); end gate_74x74; architecture gate_74x74_behavioral of gate_74x74 is -- VHDL reference used in generation of this architecture: -- Accolade VHDL Reference Guide: http://www.acc-eda.com/vhdlref/ -- Digital Design Principles and Practices, 3e, John Wakerly -- These signals are used to calculate clear/preset pulse width violations -- (since we don't whether a signal is going to change until it changes, -- we're going to mirror the signals internally in order to know the last -- time the signal changed) signal INT_CLR_L : std_logic := '1'; signal INT_PRE_L : std_logic := '1'; -- This signal is the temp output for Q (used so we can give it a default value) signal INT_Q : std_logic := '0'; signal INT_Q_L : std_logic := '1'; begin Q <= INT_Q; Q_L <= INT_Q_L; MAIN: process(CLK, CLR_L, PRE_L, D) begin -- we handle the reset case first if (falling_edge(CLR_L)) then -- clear reset overrides everything -- first check that PRE_L is not also low if (PRE_L = '0') then assert (False) report "CLR_L and PRE_L asserted at same time" severity error; INT_Q <= 'U' after t_clr; INT_Q_L <= 'U' after t_clr; else -- correct reset behavior, so reset the output INT_Q <= '0' after t_clr; INT_Q_L <= '1' after t_preset; -- opposite transition used here end if; INT_CLR_L <= CLR_L; -- send data to the mirror signal elsif (rising_edge(CLR_L)) then -- check here for pulse width violations -- now we use the mirror signal's last event as compared to now -- in order to determine the pulse width if (INT_CLR_L'Last_event < t_clr_pw) then assert (False) report "CLR_L pulse width less than t_clr_pw" severity error; end if; INT_CLR_L <= CLR_L; -- reset the mirror signal -- next, the preset case elsif (falling_edge(PRE_L)) then -- first check that CLR_L is not also low if (CLR_L = '0') then assert (False) report "CLR_L and PRE_L asserted at same time" severity error; INT_Q <= 'U' after t_clr; INT_Q_L <= 'U' after t_clr; else -- correct preset behavior, so preset the output INT_Q <= '1' after t_preset; INT_Q_L <= '0' after t_clr; -- opposite transition used here end if; INT_PRE_L <= PRE_L; elsif (rising_edge(PRE_L)) then -- pulse width violation check, same as above if (INT_PRE_L'Last_event < t_preset_pw) then assert (False) report "PRE_L pulse width less than t_preset_pw" severity error; end if; INT_PRE_L <= PRE_L; -- now the actual flip flop behavior -- we wait for rising edge of clock before we do anything, -- also making sure preset and clear are not active elsif (rising_edge(CLK) and CLR_L = '1' and PRE_L = '1') then -- check setup time on D if (D'Last_event < t_setup) then assert (False) report "FF violated setup time" severity error; -- if D is high, use low-to-high prop time elsif (D = '1') then INT_Q <= D after tp_lh; INT_Q_L <= not D after tp_hl; -- otherwise, use high-to-low else INT_Q <= D after tp_hl; INT_Q_L <= not D after tp_lh; end if; elsif (D'event) then -- check hold time on D if (CLK = '1' and (CLK'Last_event < t_hold)) then assert (False) report "FF violated hold time" severity error; end if; end if; end process; end gate_74x74_behavioral;