-- -- -- 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. -- -- ------------------------------------------------------------------ architecture behavioral of SN54S175 is -- ARCHITECTURE DECLARATIVE REGION -- Following signals added for incorporating timing constant generic_loads : loads := (tld_P2, tld_P3, tld_P6, tld_P7, tld_P10, tld_P11, tld_P14, tld_P15) ; constant generic_times : times := (tplh_clk_q, tplh_clr_q, tphl_clk_q, tphl_clr_q, tsu, th, tw_clk, tw_clr); constant model_times : sim_timing := get_timing(generic_loads,generic_times) ; -- user may turn off timing violation assertions constant do_timing : boolean := ((model_times.sim_messages.tl = ONLY_DISPLAY) or (model_times.sim_messages.tl = FULL_TIM)); -- Local signal declarations signal clock,clear : logic_mv := 'U' ; signal data1,data2,data3,data4 : logic_mv := 'U' ; signal qout1,qout2,qout3,qout4 : logic_mv := 'U' ; signal qbout1,qbout2,qbout3,qbout4 : logic_mv := 'U' ; -- Global signal declarations signal violate : violate_flags ; signal clear_last : time ; signal clock_last : time ; -- 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' clock <= transport Filter2(CLK) after twd_P9 ; data1 <= transport Filter2(D1) after twd_P4 ; data2 <= transport Filter2(D2) after twd_P5 ; data3 <= transport Filter2(D3) after twd_P12 ; data4 <= transport Filter2(D4) after twd_P13 ; clear <= transport Filter2(CLR) after twd_P1 ; -- Assign internal values to output pins Q1 <= qout1 ; QB1 <= qbout1 ; Q2 <= qout2 ; QB2 <= qbout2 ; Q3 <= qout3 ; QB3 <= qbout3 ; Q4 <= qout4 ; QB4 <= qbout4 ; -- Check for invalid inputs on control input ports assert not (CLK'event and ((CLK = 'U') or (CLK = 'X') or (CLK = 'Z') or (CLK = 'W'))) report "{" & ref & "} " & enum_to_char(CLK) & " STATE ON CLK INPUT" severity warning ; assert not (CLR'event and ((CLR = 'U') or (CLR = 'X') or (CLR = 'Z') or (CLR = 'W'))) report "{" & ref & "} " & enum_to_char(CLR) & " STATE ON CLR INPUT" severity warning ; -- Timing Violation Processes ------------------------------------------------------------------------- CLK_PULSE_CHECK : process variable clk_violate : boolean ; begin wait on clock until (do_timing and (clear = '1') and (posedge(clock) or negedge(clock))) ; if clock = '0' then clk_violate := PULSE_CHECK(clock_last,model_times.prop_delays.tw_clk,ref, "PULSE CHECK WARNING: CLK - HIGH",warning) ; elsif clock = '1' then clk_violate := PULSE_CHECK(clock_last,model_times.prop_delays.tw_clk,ref, "PULSE CHECK WARNING: CLK - LOW",warning) ; end if ; violate.clock <= clk_violate and model_times.error_flags.x_out ; wait for 0 ns ; violate.clock <= FALSE ; end process CLK_PULSE_CHECK ; ------------------------------------------------------------------------- CLR_PULSE_CHECK : process variable clr_violate : boolean ; begin wait on clear until (do_timing and posedge(clear)) ; clr_violate := PULSE_CHECK(clear_last,model_times.prop_delays.tw_clr,ref, "PULSE CHECK WARNING: CLR - LOW",warning) ; violate.clear <= clr_violate and model_times.error_flags.x_out ; wait for 0 ns ; violate.clear <= FALSE ; end process CLR_PULSE_CHECK ; ------------------------------------------------------------------------- D_SETUP_CHECK : process variable setup_data1_violate : boolean ; variable setup_data2_violate : boolean ; variable setup_data3_violate : boolean ; variable setup_data4_violate : boolean ; variable setup_clear_violate : boolean ; begin wait on clock until (do_timing and (clear = '1') and posedge(clock)) ; setup_data1_violate := SETUP_CHECK(data1'last_event, model_times.prop_delays.tsu,ref, "SETUP CHECK WARNING: D1", warning) ; setup_data2_violate := SETUP_CHECK(data2'last_event, model_times.prop_delays.tsu,ref, "SETUP CHECK WARNING: D2", warning) ; setup_data3_violate := SETUP_CHECK(data3'last_event, model_times.prop_delays.tsu,ref, "SETUP CHECK WARNING: D3", warning) ; setup_data4_violate := SETUP_CHECK(data4'last_event, model_times.prop_delays.tsu,ref, "SETUP CHECK WARNING: D4", warning) ; setup_clear_violate := SETUP_CHECK(clear'last_event, model_times.prop_delays.tsu,ref, "SETUP CHECK WARNING: CLR", warning) ; violate.d1_setup <= setup_data1_violate and model_times.error_flags.x_out ; violate.d2_setup <= setup_data2_violate and model_times.error_flags.x_out ; violate.d3_setup <= setup_data3_violate and model_times.error_flags.x_out ; violate.d4_setup <= setup_data4_violate and model_times.error_flags.x_out ; violate .clr_setup <= setup_clear_violate and model_times.error_flags.x_out ; wait for 0 ns ; violate.d1_setup <= FALSE ; violate.d2_setup <= FALSE ; violate.d3_setup <= FALSE ; violate.d4_setup <= FALSE ; violate.clr_setup <= FALSE ; end process D_SETUP_CHECK ; ------------------------------------------------------------------------- D1_HOLD_CHECK : process variable hold_data1_violate : boolean ; begin wait on data1 until (do_timing and (clear = '1') and (clock'last_value = '0') and (clock = '1')); hold_data1_violate := HOLD_CHECK(clock'last_event, model_times.prop_delays.th,ref, "HOLD CHECK WARNING: D1",warning) ; violate.d1_hold <= hold_data1_violate and model_times.error_flags.x_out ; wait for 0 ns ; violate.d1_hold <= FALSE ; end process D1_HOLD_CHECK ; ------------------------------------------------------------------------- D2_HOLD_CHECK : process variable hold_data2_violate : boolean ; begin wait on data2 until (do_timing and (clear = '1') and (clock'last_value = '0') and (clock = '1')); hold_data2_violate := HOLD_CHECK(clock'last_event, model_times.prop_delays.th,ref, "HOLD CHECK WARNING: D2",warning) ; violate.d2_hold <= hold_data2_violate and model_times.error_flags.x_out ; wait for 0 ns ; violate.d2_hold <= FALSE ; end process D2_HOLD_CHECK ; ------------------------------------------------------------------------- D3_HOLD_CHECK : process variable hold_data3_violate : boolean ; begin wait on data3 until (do_timing and (clear = '1') and (clock'last_value = '0') and (clock = '1')); hold_data3_violate := HOLD_CHECK(clock'last_event, model_times.prop_delays.th,ref, "HOLD CHECK WARNING: D3",warning) ; violate.d3_hold <= hold_data3_violate and model_times.error_flags.x_out ; wait for 0 ns ; violate.d3_hold <= FALSE ; end process D3_HOLD_CHECK ; ------------------------------------------------------------------------- D4_HOLD_CHECK : process variable hold_data4_violate : boolean ; begin wait on data4 until (do_timing and (clear = '1') and (clock'last_value = '0') and (clock = '1')); hold_data4_violate := HOLD_CHECK(clock'last_event, model_times.prop_delays.th,ref, "HOLD CHECK WARNING: D4",warning) ; violate.d4_hold <= hold_data4_violate and model_times.error_flags.x_out ; wait for 0 ns ; violate.d4_hold <= FALSE ; end process D4_HOLD_CHECK ; ------------------------------------------------------------------------- LAST_EVENT : process (clear,clock) begin if (clear'event = TRUE) then clear_last <= now ; end if ; if (clock'event = TRUE) then clock_last <= now ; end if ; end process LAST_EVENT ; ------------------------------------------------------------------------- DFF1 : process variable ffmode : modetype; begin wait on clear,clock,violate ; if (violate.clock or violate.clear or violate.d1_setup or violate.clr_setup or violate.d1_hold) then ffmode := ERROR ; elsif (clear = '0') then ffmode := CLR_FF; elsif (clear = '1') then ffmode := LATCH; else ffmode := ERROR; end if ; -------------- case ffmode is when ERROR => if (clear = 'U' or clock = 'U' or data1 = 'U') then qout1 <= 'U' ; qbout1 <= 'U' ; else qout1 <= 'X' ; qbout1 <= 'X' ; end if ; when CLR_FF => qout1 <= transport '0' after model_times.prop_delays.tphl_clr_q ; qbout1 <= transport '1' after model_times.prop_delays.tplh_clr_q ; when LATCH => if (posedge(clock)) then if data1 = '0' then qout1 <= transport '0' after model_times.prop_delays.tphl_clk_q ; qbout1 <= transport '1' after model_times.prop_delays.tplh_clk_q ; elsif data1 = '1' then qout1 <= transport '1' after model_times.prop_delays.tplh_clk_q ; qbout1 <= transport '0' after model_times.prop_delays.tphl_clk_q ; elsif data1 = 'U' then qout1 <= 'U' ; qbout1 <= 'U' ; else qout1 <= 'X' ; qbout1 <= 'X' ; end if ; elsif (clock = 'X' or clock = 'U') then if (data1 /= qout1) then if (data1 = 'U' or clock = 'U') then qout1 <= 'U' ; qbout1 <= 'U' ; else qout1 <= 'X' ; qbout1 <= 'X' ; end if ; end if; end if ; end case ; end process DFF1 ; ------------------------------------------------------------------------- DFF2 : process variable ffmode : modetype; begin wait on clear,clock,violate ; if (violate.clock or violate.clear or violate.d2_setup or violate.clr_setup or violate.d2_hold) then ffmode := ERROR ; elsif (clear = '0') then ffmode := CLR_FF; elsif (clear = '1') then ffmode := LATCH; else ffmode := ERROR; end if ; case ffmode is when ERROR => if (clear = 'U' or clock = 'U' or data2 = 'U') then qout2 <= 'U' ; qbout2 <= 'U' ; else qout2 <= 'X' ; qbout2 <= 'X' ; end if ; when CLR_FF => qout2 <= transport '0' after model_times.prop_delays.tphl_clr_q ; qbout2 <= transport '1' after model_times.prop_delays.tplh_clr_q ; when LATCH => if (posedge(clock)) then if data2 = '0' then qout2 <= transport '0' after model_times.prop_delays.tphl_clk_q ; qbout2 <= transport '1' after model_times.prop_delays.tplh_clk_q ; elsif data2 = '1' then qout2 <= transport '1' after model_times.prop_delays.tplh_clk_q ; qbout2 <= transport '0' after model_times.prop_delays.tphl_clk_q ; elsif data2 = 'U' then qout2 <= 'U' ; qbout2 <= 'U' ; else qout2 <= 'X' ; qbout2 <= 'X' ; end if ; elsif (clock = 'X' or clock = 'U') then if (data2 /= qout2) then if (data2 = 'U' or clock = 'U') then qout2 <= 'U' ; qbout2 <= 'U' ; else qout2 <= 'X' ; qbout2 <= 'X' ; end if ; end if; end if ; end case ; end process DFF2 ; ------------------------------------------------------------------------- DFF3 : process variable ffmode : modetype; begin wait on clear,clock,violate ; if (violate.clock or violate.clear or violate.d3_setup or violate.clr_setup or violate.d3_hold) then ffmode := ERROR ; elsif (clear = '0') then ffmode := CLR_FF; elsif (clear = '1') then ffmode := LATCH; else ffmode := ERROR; end if ; case ffmode is when ERROR => if (clear = 'U' or clock = 'U' or data3 = 'U') then qout3 <= 'U' ; qbout3 <= 'U' ; else qout3 <= 'X' ; qbout3 <= 'X' ; end if; when CLR_FF => qout3 <= transport '0' after model_times.prop_delays.tphl_clr_q ; qbout3 <= transport '1' after model_times.prop_delays.tplh_clr_q ; when LATCH => if (posedge(clock)) then if data3 = '0' then qout3 <= transport '0' after model_times.prop_delays.tphl_clk_q ; qbout3 <= transport '1' after model_times.prop_delays.tplh_clk_q ; elsif data3 = '1' then qout3 <= transport '1' after model_times.prop_delays.tplh_clk_q ; qbout3 <= transport '0' after model_times.prop_delays.tphl_clk_q ; elsif data3 = 'U' then qout3 <= 'U' ; qbout3 <= 'U' ; else qout3 <= 'X' ; qbout3 <= 'X' ; end if ; elsif (clock = 'X' or clock = 'U') then if (data3 /= qout3) then if (data3 = 'U' or clock = 'U') then qout3 <= 'U' ; qbout3 <= 'U' ; else qout3 <= 'X' ; qbout3 <= 'X' ; end if ; end if; end if ; end case ; end process DFF3 ; ------------------------------------------------------------------------- DFF4 : process variable ffmode : modetype; begin wait on clear,clock,violate ; if (violate.clock or violate.clear or violate.d4_setup or violate.clr_setup or violate.d4_hold) then ffmode := ERROR ; elsif (clear = '0') then ffmode := CLR_FF; elsif (clear = '1') then ffmode := LATCH; else ffmode := ERROR; end if ; case ffmode is when ERROR => if (clear = 'U' or clock = 'U' or data4 = 'U') then qout4 <= 'U' ; qbout4 <= 'U' ; else qout4 <= 'X' ; qbout4 <= 'X' ; end if; when CLR_FF => qout4 <= transport '0' after model_times.prop_delays.tphl_clr_q ; qbout4 <= transport '1' after model_times.prop_delays.tplh_clr_q ; when LATCH => if (posedge(clock)) then if data4 = '0' then qout4 <= transport '0' after model_times.prop_delays.tphl_clk_q ; qbout4 <= transport '1' after model_times.prop_delays.tplh_clk_q ; elsif data4 = '1' then qout4 <= transport '1' after model_times.prop_delays.tplh_clk_q ; qbout4 <= transport '0' after model_times.prop_delays.tphl_clk_q ; elsif data4 = 'U' then qout4 <= 'U' ; qbout4 <= 'U' ; else qout4 <= 'X' ; qbout4 <= 'X' ; end if ; elsif (clock = 'X' or clock = 'U') then if (data4 /= qout4) then if (data4 = 'U' or clock = 'U') then qout4 <= 'U' ; qbout4 <= 'U' ; else qout4 <= 'X' ; qbout4 <= 'X' ; end if ; end if; end if ; end case ; end process DFF4 ; end behavioral ;