-- Model Name : Bidirectional Switch Model -- Author : John Arthur Dube -- Last Updated : 09 / 15 / 1996 -- This document is © copyrighted by the Author.

    
    
    PACKAGE mos_utilities IS TYPE seven_value IS ('U', 'Z', 'L', 'H', '0', '1', 'X'); TYPE seven_vector IS ARRAY ( INTEGER RANGE <> ) OF seven_value; TYPE four_value IS ('Z', '0', '1', 'X'); TYPE real_vector IS ARRAY ( INTEGER RANGE <> ) OF REAL; TYPE integer_vector IS ARRAY ( INTEGER RANGE <> ) OF INTEGER; TYPE pr IS RANGE 0.0 TO REAL'HIGH; TYPE pr_vector IS ARRAY (INTEGER RANGE <> ) OF pr; TYPE delay_data IS ARRAY (1 to 3) OF REAL; TYPE data_table IS ARRAY (INTEGER RANGE <>,INTEGER RANGE <>) OF REAL; TYPE seven_value_table IS ARRAY (seven_value,seven_value) OF seven_value; TYPE seven_to_four_table IS ARRAY (seven_value) OF four_value; TYPE four_to_seven_table IS ARRAY (four_value) OF seven_value; FUNCTION wiring (drivers : seven_vector ) RETURN seven_value; FUNCTION loading (caps : pr_vector) RETURN pr; FUNCTION quickest (edgespeeds : real_vector) RETURN REAL; FUNCTION get_delay_data(table : data_table; inESratio: REAL) RETURN delay_data; SUBTYPE wired_seven IS wiring seven_value; SUBTYPE loading_effect IS loading pr; SUBTYPE quickest_transition IS quickest REAL; TYPE line IS RECORD logic : wired_seven; load : loading_effect; transition : quickest_transition; END RECORD; FUNCTION line_to_fv (in_logic : line) RETURN four_value; FUNCTION fv_to_line (in_logic : four_value) RETURN line; CONSTANT n_drive_table : seven_value_table := (('U','U','U','U','U','U','U'), ('U','Z','Z','Z','Z','Z','X'), ('U','L','Z','L','Z','L','X'), ('U','H','Z','H','Z','H','X'), ('U','0','Z','0','Z','0','X'), ('U','H','Z','H','Z','H','X'), ('U','X','Z','X','Z','X','X')); CONSTANT p_drive_table : seven_value_table := (('U','U','U','U','U','U','U'), ('U','Z','Z','Z','Z','Z','X'), ('U','Z','L','Z','L','Z','X'), ('U','Z','H','Z','H','Z','X'), ('U','Z','L','Z','L','Z','X'), ('U','Z','1','Z','1','Z','X'), ('U','Z','X','Z','X','Z','X')); END mos_utilities; USE utilities.mos_utilities.ALL; ENTITY n_switch IS GENERIC (length,width : pr); PORT (gate,source,drain : INOUT line); END n_switch;






    
    
    LIBRARY utilities; USE utilities.mos_utilities.ALL; USE utilities.data.ALL; ARCHITECTURE bi_directional OF n_switch IS SIGNAL effective_gate : wired_seven; CONSTANT Cgate : pr := n_cperarea*length*width; CONSTANT Cin : pr := n_cperwidth*width; CONSTANT aspect : pr := length/width; SIGNAL d_self,s_self : BIT; BEGIN gate.logic <= 'Z'; source.logic <= 'U'; drain.logic <= 'U'; gate.load <= n_cperarea*length*width; source.load <= n_cperwidth*width; drain.load <= n_cperwidth*width; gating: PROCESS (gate.logic) BEGIN IF gate.logic = 'Z' THEN effective_gate <= 'X' AFTER INTEGER(n_decay*gate.load) NS; ELSE effective_gate <= gate.logic; END IF; END PROCESS gating; outing: PROCESS VARIABLE inES,s_inESratio,d_inESratio : REAL := 0.000; VARIABLE s_nativeOutES, d_nativeOutES : REAL := 0.000; VARIABLE s_out_trans, d_out_trans : REAL := 0.000; VARIABLE s_delay_values, d_delay_values : delay_data; VARIABLE s_out_delay, d_out_delay : TIME; VARIABLE s_to_d, d_to_s : BIT; VARIABLE temp_logic : seven_value; VARIABLE temp_table : data_table(1 TO 11, 1 TO 3); BEGIN WAIT ON drain.logic, source.logic, effective_gate; IF ((drain.load > 0.0) AND (source.load > 0.0)) THEN IF ((NOT s_self'ACTIVE) AND (NOT d_self'ACTIVE)) THEN IF (effective_gate = '1' OR effective_gate = 'H') THEN IF (effective_gate'EVENT) THEN WAIT FOR 1 FS; temp_logic := n_drive_table(wiring(drain.logic & source.logic), effective_gate); IF (temp_logic /= 'Z') THEN IF (temp_logic = n_drive_table(drain.logic,effective_gate)) THEN d_to_s := '1'; ELSE s_to_d := '1'; END IF; END IF inES := gate.transition; IF (temp_logic = 'H' OR temp_logic = 'X') THEN temp_table := n_gate_up; ELSIF (temp_logic = '0' OR temp_logic = 'L') THEN temp_table := n_gate_down; END IF; ELSIF (source.logic'EVENT) THEN WAIT FOR 1 FS; temp_logic := n_drive_table(source.logic, effective_gate); s_to_d := '1'; inES := source.transition; IF (temp_logic = 'H' OR temp_logic = 'X') THEN temp_table := n_source_up; ELSIF (temp_logic = '0' OR temp_logic = 'L') THEN temp_table := n_source_down; END IF; ELSIF (drain.logic'EVENT) THEN WAIT FOR 1 FS; temp_logic := n_drive_table(drain.logic,effective_gate); d_to_s := '1'; inES := drain.transition; IF (temp_logic = 'H' OR temp_logic = 'X') THEN temp_table := n_source_up; ELSIF (temp_logic = '0' OR temp_logic = 'L') THEN temp_table := n_source_down; END IF; END IF; IF (temp_logic /= 'Z') THEN d_nativeOutES := temp_table(1,3)*REAL(drain.load)*REAL(aspect); s_nativeOutES := temp_table(1,3)*REAL(source.load)*REAL(aspect); d_inESratio := inES/d_nativeOutES; s_inESratio := inES/s_nativeOutES; d_delay_values := get_delay_data(temp_table,d_inESratio); s_delay_values := get_delay_data(temp_table,s_inESratio); IF d_delay_values(2) < 0.00 THEN d_delay_values(2):= 0.000; END IF; IF s_delay_values(2) < 0.00 THEN s_delay_values(2):= 0.000; END IF; d_out_delay:=INTEGER(d_delay_values(2)*REAL(drain.load)* REAL(aspect)*1.0E6)*1 FS; d_out_trans := d_delay_values(3)*REAL(drain.load)*REAL(aspect); s_out_delay:=INTEGER(s_delay_values(2)*REAL(source.load)* REAL(aspect)*1.0E6)*1 FS; s_out_trans := s_delay_values(3)*REAL(source.load)*REAL(aspect); ELSE d_out_delay := 0 FS; s_out_delay := 0 FS; d_out_trans := -1.00; s_out_trans := -1.00; END IF; IF (s_to_d = '1') THEN drain.logic <= temp_logic AFTER d_out_delay; drain.transition <= d_out_trans AFTER d_out_delay; d_self <= NOT d_self AFTER d_out_delay; source.logic <= 'Z'; source.transition <= -1.00; s_self <= NOT s_self; s_to_d := '0'; ELSIF (d_to_s = '1') THEN source.logic <= temp_logic AFTER s_out_delay; source.transition <= s_out_trans AFTER s_out_delay; s_self <= NOT s_self AFTER s_out_delay; drain.logic <= 'Z'; drain.transition <= -1.00; d_self <= NOT d_self; d_to_s := '0'; ELSE drain.logic <= temp_logic AFTER d_out_delay; drain.transition <= d_out_trans AFTER d_out_delay; d_self <= NOT d_self AFTER d_out_delay; source.logic <= temp_logic AFTER s_out_delay; source.transition <= s_out_trans AFTER s_out_delay; s_self <= NOT s_self AFTER s_out_delay; END IF; ELSE IF (effective_gate'EVENT) THEN drain.logic <= 'Z'; source.logic <= 'Z'; drain.transition <= -1.00; source.transition <= -1.00; d_self <= NOT d_self; s_self <= NOT s_self; END IF; END IF; END IF; END IF; END PROCESS outing; END bi_directional;






    
    
    LIBRARY utilities; USE utilities.mos_utilities.ALL; USE utilities.data.ALL; ARCHITECTURE bi_directional OF p_switch IS SIGNAL effective_gate : wired_seven; CONSTANT Cgate : pr := p_cperarea*length*width; CONSTANT Cin : pr := p_cperwidth*width; CONSTANT aspect : pr := length/width; SIGNAL d_self, s_self : BIT; BEGIN gate.logic <= 'Z'; source.logic <= 'U'; drain.logic <= 'U'; gate.load <= p_cperarea*length*width; source.load <= p_cperwidth*width; drain.load <= p_cperwidth*width; gating: PROCESS (gate.logic) BEGIN IF gate.logic = 'Z' THEN effective_gate <= 'X' AFTER INTEGER(p_decay*gate.load) NS; ELSE effective_gate <= gate.logic; END IF; END PROCESS gating; outing: PROCESS VARIABLE inES,s_inESratio,d_inESratio : REAL := 0.000; VARIABLE s_nativeOutES, d_nativeOutES : REAL := 0.000; VARIABLE s_out_trans, d_out_trans : REAL:= 0.000; VARIABLE s_delay_values, d_delay_values : delay_data; VARIABLE s_out_delay,d_out_delay : TIME; VARIABLE temp_logic : wired_seven; VARIABLE temp_table : data_table(1 TO 11, 1 TO 3); BEGIN WAIT ON drain.logic, source.logic, effective_gate; IF ((drain.load > 0.0) AND (source.load > 0.0)) THEN IF ((NOT d_self'ACTIVE) AND (NOT s_self'ACTIVE)) THEN IF (effective_gate = '0' OR effective_gate = 'L') THEN IF (effective_gate'EVENT) THEN WAIT FOR 1 FS; temp_logic := p_drive_table(wiring(drain.logic&source.logic), effective_gate); IF (temp_logic /= 'Z') THEN IF (temp_logic = n_drive_table(drain.logic,effective_gate)) THEN d_to_s := '1'; ELSE s_to_d := '1'; END IF; END IF inES := gate.transition; IF (temp_logic = '1' OR temp_logic = 'H') THEN temp_table := p_gate_up; ELSIF (temp_logic = 'L' OR temp_logic = 'X') THEN temp_table := p_gate_down; END IF; ELSIF (source.logic'EVENT) THEN WAIT FOR 1 FS; temp_logic := p_drive_table(source.logic, effective_gate); inES := source.transition; IF (temp_logic = '1' OR temp_logic = 'H') THEN temp_table := p_source_up; ELSIF (temp_logic = 'L' OR temp_logic = 'X') THEN temp_table := p_source_down; END IF; ELSIF (drain.logic'EVENT) THEN WAIT FOR 1 FS; temp_logic := p_drive_table(drain.logic,effective_gate); inES := drain.transition; IF (temp_logic = '1' OR temp_logic = 'H') THEN temp_table := p_source_up; ELSIF (temp_logic = 'L' OR temp_logic = 'X') THEN temp_table := p_source_down; END IF; END IF; IF (temp_logic /= 'Z') THEN d_nativeOutES := temp_table(1,3)*REAL(drain.load)*REAL(aspect); s_nativeOutES := temp_table(1,3)*REAL(source.load)*REAL(aspect); d_inESratio := inES/d_nativeOutES; s_inESratio := inES/s_nativeOutES; d_delay_values := get_delay_data(temp_table,d_inESratio); s_delay_values := get_delay_data(temp_table,s_inESratio); IF d_delay_values(2) < 0.00 THEN d_delay_values(2):= 0.000; END IF; IF s_delay_values(2) < 0.00 THEN s_delay_values(2):= 0.000; END IF; d_out_delay :=INTEGER(d_delay_values(2)*REAL(drain.load)* REAL(aspect)*1.0E6)*1 FS; d_out_trans := d_delay_values(3)*REAL(drain.load)*REAL(aspect); s_out_delay:=INTEGER(s_delay_values(2)*REAL(source.load)* REAL(aspect)*1.0E6)*1 FS; s_out_trans := s_delay_values(3)*REAL(source.load)*REAL(aspect); ELSE d_out_delay := 0 FS; s_out_delay := 0 FS; d_out_trans := -1.00; s_out_trans := -1.00; END IF; IF (s_to_d = '1') THEN drain.logic <= temp_logic AFTER d_out_delay; drain.transition <= d_out_trans AFTER d_out_delay; d_self <= NOT d_self AFTER d_out_delay; source.logic <= 'Z'; source.transition <= -1.00; s_self <= NOT s_self; s_to_d := '0'; ELSIF (d_to_s = '1') THEN source.logic <= temp_logic AFTER s_out_delay; source.transition <= s_out_trans AFTER s_out_delay; s_self <= NOT s_self AFTER s_out_delay; drain.logic <= 'Z'; drain.transition <= -1.00; d_self <= NOT d_self; d_to_s := '0'; ELSE drain.logic <= temp_logic AFTER d_out_delay; drain.transition <= d_out_trans AFTER d_out_delay; d_self <= NOT d_self AFTER d_out_delay; source.logic <= temp_logic AFTER s_out_delay; source.transition <= s_out_trans AFTER s_out_delay; s_self <= NOT s_self AFTER s_out_delay; END IF; ELSE IF (effective_gate'EVENT) THEN drain.logic <= 'Z'; source.logic <= 'Z'; drain.transition <= -1.00; source.transition <= -1.00; s_self <= NOT s_self; d_self <= NOT d_self; END IF; END IF; END IF; END IF; END PROCESS outing; END bi_directional;






    
    
    LIBRARY utilities; USE utilities.mos_utilities.ALL; USE utilities.data.ALL; ENTITY pullup IS GENERIC (length,width : pr); PORT (drain : INOUT line); END pullup; ARCHITECTURE uni_directional OF pullup IS CONSTANT Cin : pr := p_cperwidth*width; CONSTANT aspect : pr := length/width; BEGIN drain.load <= Cin; outing: PROCESS VARIABLE out_trans : REAL := 0.000; VARIABLE out_delay : TIME := 0 FS; VARIABLE pulling_up : BIT := '0'; BEGIN WAIT ON drain.logic; IF drain.load > 0.0 THEN IF ((pulling_up = '1') AND (drain.logic /= 'H')) THEN pulling_up := '0'; drain.logic <= 'Z'; ELSIF ((pulling_up = '0') AND (drain.logic /= 'H')) THEN out_delay := INTEGER(REAL(rpullup)*REAL(drain.load)* REAL(aspect)*1.0E6)*1 FS; out_trans := REAL(tpullup)*REAL(drain.load)*REAL(aspect); drain.logic <= 'H' AFTER out_delay; drain.transition <= out_trans AFTER out_delay; pulling_up := '1'; END IF; END IF; END PROCESS outing; END uni_directional;