-- -- -- DISCLAIMER -- -- This code is the sole property of the Institute for Technology -- Development (ITD), Jackson, Mississippi, and is distributed for -- the purpose of providing examples of VHDL models written to -- modeling standards. This code may not be used for commercial -- purposes, and may not be redistributed without permission from -- the Institute for Technology Development. ITD assumes no -- responsibility for errors, omissions, uses made, or decisions -- based on its use. No warranties, expressed or implied, are given. -- --------------------------------------------------------------------------- -- Note: -- -- The timing relationships of the SN54S251 are complicated -- if several inputs change in close sequence. In order to assign -- the correct propagation delay to an input signal, one must determine -- the future output after a particular propagation delay. However, -- an input with a shorter delay may preempt a previous input with a -- longer delay, thus making any previous assumptions about the output -- value incorrect. -- -- To handle this problem, this SN54S251 model is based on the logic -- diagram on page 2-716 of the 1988 TTL Data Book. This model converts -- the single enable input into four separate enable signals, each -- assigned after a respective propagation delay (tpZL,tpZH,tpHZ,tpLZ). -- These four signals trigger a "zero-time" output process, which -- responds based on the present state of the output at the instant -- an event occurs on one of the enable lines. -- -- This technique eliminates the need to predict the value of the output -- pin at some future time in order to assign a propagation delay to -- an input transition. Although the logic diagram does not necessarily -- represent the actual implementation of the circuit, it does allow -- the model to accurately implement the timing behavior of the part. --------------------------------------------------------------------------- architecture behavioral of SN54S251 is -- ARCHITECTURE DECLARATIVE REGION constant generic_loads : loads := (tld_P5, tld_P6) ; constant generic_times : times := (tplh_bs_y, tphl_bs_y, tplh_bs_w, tphl_bs_w, tplh_d_y, tphl_d_y, tplh_d_w, tphl_d_w, tpzh_g_y, tpzl_g_y, tpzh_g_w, tpzl_g_w, tphz_g_y, tplz_g_y, tphz_g_w, tplz_g_w) ; constant model_times : sim_timing := get_timing(generic_loads,generic_times) ; -- Local signal declarations signal strin,ain,bin,cin : logic_mv := 'U' ; signal din0,din1,din2,din3 : logic_mv := 'U' ; signal din4,din5,din6,din7 : logic_mv := 'U' ; signal y0,y1,y2,y3,y4,y5,y6,y7 : logic_mv := 'U' ; signal w0,w1,w2,w3,w4,w5,w6,w7 : logic_mv := 'U' ; signal ystate, wstate : logic_mv := 'U' ; signal yout,wout : logic_mv := 'U' ; -- the following signals provide the correct propagation delay -- caused by a transition on the enable input. signal y_enable_ZL, w_enable_ZL : logic_mv := 'U' ; signal y_enable_ZH, w_enable_ZH : logic_mv := 'U' ; signal y_enable_LZ, w_enable_LZ : logic_mv := 'U' ; signal y_enable_HZ, w_enable_HZ : logic_mv := 'U' ; -- ARCHITECTURE FUNCTIONAL REGION begin -- assign pin values to internal signals after wire delay -- 'H' is to be treated as a '1', and 'L' is to be treated as '0' ain <= transport Filter2(A) after twd_P11 ; bin <= transport Filter2(B) after twd_P10 ; cin <= transport Filter2(C) after twd_P9 ; strin <= transport Filter2(STR) after twd_P7 ; din0 <= transport Filter2(D0) after twd_P4 ; din1 <= transport Filter2(D1) after twd_P3 ; din2 <= transport Filter2(D2) after twd_P2 ; din3 <= transport Filter2(D3) after twd_P1 ; din4 <= transport Filter2(D4) after twd_P15 ; din5 <= transport Filter2(D5) after twd_P14 ; din6 <= transport Filter2(D6) after twd_P13 ; din7 <= transport Filter2(D7) after twd_P12 ; ystate <= y0 or y1 or y2 or y3 or y4 or y5 or y6 or y7 ; wstate <= not (w0 or w1 or w2 or w3 or w4 or w5 or w6 or w7) ; -- Assign internal values to output pins Y <= yout ; W <= wout ; -- Check for invalid inputs on control input ports assert not (STR'event and ((STR = 'U') or (STR = 'X') or (STR = 'Z') or (STR = 'W'))) report "{" & ref & "} " & enum_to_char(STR) & " STATE ON STR INPUT" severity warning ; assert not (A'event and ((A = 'U') or (A = 'X') or (A = 'Z') or (A = 'W'))) report "{" & ref & "} " & enum_to_char(A) & " STATE ON A INPUT" severity warning ; assert not (B'event and ((B = 'U') or (B = 'X') or (B = 'Z') or (B = 'W'))) report "{" & ref & "} " & enum_to_char(B) & " STATE ON B INPUT" severity warning ; assert not (C'event and ((C = 'U') or (C = 'X') or (C = 'Z') or (C = 'W'))) report "{" & ref & "} " & enum_to_char(C) & " STATE ON C INPUT" severity warning ; ------------------------------------------------------------------------------ data0 : process (din0,ain,bin,cin) variable output_value : logic_mv ; begin output_value := din0 and not cin and not bin and not ain ; if (din0'event) then y0 <= transport output_value after tp_delay(output_value,model_times.prop_delays.tplh_d_y, model_times.prop_delays.tphl_d_y) ; w0 <= transport output_value after tp_delay(output_value,model_times.prop_delays.tplh_d_w, model_times.prop_delays.tphl_d_w); else y0 <= transport output_value after tp_delay(output_value,model_times.prop_delays.tplh_bs_y, model_times.prop_delays.tphl_bs_y) ; w0 <= transport output_value after tp_delay(output_value,model_times.prop_delays.tplh_bs_w, model_times.prop_delays.tphl_bs_w) ; end if; end process data0; ------------------------------------------------------------------------------ data1 : process (din1,ain,bin,cin) variable output_value : logic_mv ; begin output_value := din1 and not cin and not bin and ain ; if (din1'event) then y1 <= transport output_value after tp_delay(output_value,model_times.prop_delays.tplh_d_y, model_times.prop_delays.tphl_d_y) ; w1 <= transport output_value after tp_delay(output_value,model_times.prop_delays.tplh_d_w, model_times.prop_delays.tphl_d_w) ; else y1 <= transport output_value after tp_delay(output_value,model_times.prop_delays.tplh_bs_y, model_times.prop_delays.tphl_bs_y) ; w1 <= transport output_value after tp_delay(output_value,model_times.prop_delays.tplh_bs_w, model_times.prop_delays.tphl_bs_w) ; end if; end process data1; ------------------------------------------------------------------------------ data2: process (din2,ain,bin,cin) variable output_value : logic_mv ; begin output_value := din2 and not cin and bin and not ain ; if (din2'event) then y2 <= transport output_value after tp_delay(output_value,model_times.prop_delays.tplh_d_y, model_times.prop_delays.tphl_d_y) ; w2 <= transport output_value after tp_delay(output_value,model_times.prop_delays.tplh_d_w, model_times.prop_delays.tphl_d_w) ; else y2 <= transport output_value after tp_delay(output_value,model_times.prop_delays.tplh_bs_y, model_times.prop_delays.tphl_bs_y) ; w2 <= transport output_value after tp_delay(output_value,model_times.prop_delays.tplh_bs_w, model_times.prop_delays.tphl_bs_w) ; end if; end process data2; ------------------------------------------------------------------------------ data3 : process (din3,ain,bin,cin) variable output_value : logic_mv ; begin output_value := din3 and not cin and bin and ain ; if (din3'event) then y3 <= transport output_value after tp_delay(output_value,model_times.prop_delays.tplh_d_y, model_times.prop_delays.tphl_d_y) ; w3 <= transport output_value after tp_delay(output_value,model_times.prop_delays.tplh_d_w, model_times.prop_delays.tphl_d_w) ; else y3 <= transport output_value after tp_delay(output_value,model_times.prop_delays.tplh_bs_y, model_times.prop_delays.tphl_bs_y) ; w3 <= transport output_value after tp_delay(output_value,model_times.prop_delays.tplh_bs_w, model_times.prop_delays.tphl_bs_w) ; end if; end process data3; ------------------------------------------------------------------------------ data4 : process (din4,ain,bin,cin) variable output_value : logic_mv ; begin output_value := din4 and cin and not bin and not ain ; if (din4'event) then y4 <= transport output_value after tp_delay(output_value,model_times.prop_delays.tplh_d_y, model_times.prop_delays.tphl_d_y) ; w4 <= transport output_value after tp_delay(output_value,model_times.prop_delays.tplh_d_w, model_times.prop_delays.tphl_d_w) ; else y4 <= transport output_value after tp_delay(output_value,model_times.prop_delays.tplh_bs_y, model_times.prop_delays.tphl_bs_y) ; w4 <= transport output_value after tp_delay(output_value,model_times.prop_delays.tplh_bs_w, model_times.prop_delays.tphl_bs_w) ; end if; end process data4; ------------------------------------------------------------------------------ data5 : process (din5,ain,bin,cin) variable output_value : logic_mv ; begin output_value := din5 and cin and not bin and ain ; if (din5'event) then y5 <= transport output_value after tp_delay(output_value,model_times.prop_delays.tplh_d_y, model_times.prop_delays.tphl_d_y) ; w5 <= transport output_value after tp_delay(output_value,model_times.prop_delays.tplh_d_w, model_times.prop_delays.tphl_d_w) ; else y5 <= transport output_value after tp_delay(output_value,model_times.prop_delays.tplh_bs_y, model_times.prop_delays.tphl_bs_y) ; w5 <= transport output_value after tp_delay(output_value,model_times.prop_delays.tplh_bs_w, model_times.prop_delays.tphl_bs_w) ; end if; end process data5; ------------------------------------------------------------------------------ data6 : process (din6,ain,bin,cin) variable output_value : logic_mv ; begin output_value := din6 and cin and bin and not ain ; if (din6'event) then y6 <= transport output_value after tp_delay(output_value,model_times.prop_delays.tplh_d_y, model_times.prop_delays.tphl_d_y) ; w6 <= transport output_value after tp_delay(output_value,model_times.prop_delays.tplh_d_w, model_times.prop_delays.tphl_d_w) ; else y6 <= transport output_value after tp_delay(output_value,model_times.prop_delays.tplh_bs_y, model_times.prop_delays.tphl_bs_y) ; w6 <= transport output_value after tp_delay(output_value,model_times.prop_delays.tplh_bs_w, model_times.prop_delays.tphl_bs_w) ; end if; end process data6; ------------------------------------------------------------------------------ data7 : process (din7,ain,bin,cin) variable output_value : logic_mv ; begin output_value := din7 and cin and bin and ain ; if (din7'event) then y7 <= transport output_value after tp_delay(output_value,model_times.prop_delays.tplh_d_y, model_times.prop_delays.tphl_d_y) ; w7 <= transport output_value after tp_delay(output_value,model_times.prop_delays.tplh_d_w, model_times.prop_delays.tphl_d_w) ; else y7 <= transport output_value after tp_delay(output_value,model_times.prop_delays.tplh_bs_y, model_times.prop_delays.tphl_bs_y) ; w7 <= transport output_value after tp_delay(output_value,model_times.prop_delays.tplh_bs_w, model_times.prop_delays.tphl_bs_w) ; end if; end process data7; --**************************************************************************** enable_zl : process (strin, y_enable_LZ, w_enable_LZ) begin if (strin = '1') then -- trigger enable_LZ by negating enable_ZL y_enable_ZL <= transport '0' after model_times.prop_delays.tplz_g_y ; w_enable_ZL <= transport '0' after model_times.prop_delays.tplz_g_w ; elsif (bit_unknown(strin)) then y_enable_ZL <= strin ; w_enable_ZL <= strin ; else if (y_enable_LZ = '0') then y_enable_ZL <= '1' ; end if; if (w_enable_LZ = '0') then w_enable_ZL <= '1' ; end if; end if; end process enable_zl ; ------------------------------------------------------------------------------ enable_zh : process (strin, y_enable_HZ, w_enable_HZ) begin if (strin = '1') then -- trigger y_enable_HZ by negating y_enable_ZH y_enable_ZH <= transport '0' after model_times.prop_delays.tphz_g_y ; w_enable_ZH <= transport '0' after model_times.prop_delays.tphz_g_w ; elsif (bit_unknown(strin)) then y_enable_ZH <= strin ; w_enable_ZH <= strin ; else if (y_enable_HZ = '0') then y_enable_ZH <= '1' ; end if; if (w_enable_HZ = '0') then w_enable_ZH <= '1' ; end if; end if; end process enable_zh ; ------------------------------------------------------------------------------ enable_lz : process (strin, y_enable_ZL, w_enable_ZL) begin if (strin = '0') then -- trigger y_enable_ZL by negating y_enable_LZ y_enable_LZ <= transport '0' after model_times.prop_delays.tpzl_g_y ; w_enable_LZ <= transport '0' after model_times.prop_delays.tpzl_g_w ; elsif (bit_unknown(strin)) then y_enable_LZ <= strin ; w_enable_LZ <= strin ; else if (y_enable_ZL = '0') then y_enable_LZ <= '1' ; end if; if (w_enable_ZL = '0') then w_enable_LZ <= '1' ; end if; end if; end process enable_lz ; ------------------------------------------------------------------------------ enable_hz : process (strin, y_enable_ZH, w_enable_ZH) begin if (strin = '0') then -- trigger y_enable_ZH by negating y_enable_HZ y_enable_HZ <= transport '0' after model_times.prop_delays.tpzh_g_y ; w_enable_HZ <= transport '0' after model_times.prop_delays.tpzh_g_w ; elsif (bit_unknown(strin)) then y_enable_HZ <= strin ; w_enable_HZ <= strin ; else if (y_enable_ZH = '0') then y_enable_HZ <= '1' ; end if; if (w_enable_ZH = '0') then w_enable_HZ <= '1' ; end if; end if; end process enable_hz ; --**************************************************************************** mux_y : process(ystate, y_enable_HZ, y_enable_LZ, y_enable_ZL, y_enable_ZH) begin if (bit_unknown(y_enable_ZL) and bit_unknown(y_enable_ZH) and bit_unknown(y_enable_LZ) and bit_unknown(y_enable_HZ)) then yout <= y_enable_ZL ; -- They should all be the same elsif (y_enable_ZL = '1' and (ystate = '0' or bit_unknown(ystate))) or (y_enable_ZH = '1' and (ystate = '1' or bit_unknown(ystate))) then yout <= ystate ; elsif (y_enable_LZ = '1' and yout = '0') or (y_enable_HZ = '1' and yout = '1') or (y_enable_LZ = '1' and y_enable_HZ = '1' and bit_unknown(yout)) then yout <= 'Z'; end if; end process mux_y; ------------------------------------------------------------------------------ mux_w : process(wstate, w_enable_HZ, w_enable_LZ, w_enable_ZL, w_enable_ZH) begin if (bit_unknown(w_enable_ZL) and bit_unknown(w_enable_ZH) and bit_unknown(w_enable_LZ) and bit_unknown(w_enable_HZ)) then wout <= w_enable_ZL ; -- They should all be the same elsif (w_enable_ZL = '1' and (wstate = '0' or bit_unknown(wstate))) or (w_enable_ZH = '1' and (wstate = '1' or bit_unknown(wstate))) then wout <= wstate ; elsif (w_enable_LZ = '1' and wout = '0') or (w_enable_HZ = '1' and wout = '1') or (w_enable_LZ = '1' and w_enable_HZ = '1' and bit_unknown(wout)) then wout <= 'Z'; end if; end process mux_w; end behavioral ;