--=========================================================================== -- This file was written by Arpad Muranyi, Intel Corporation. It does not -- contain any confidential or proprietary information, and it is made -- available to the public with the intent of promoting the usage of the -- Multi-Lingual Extensions of the IBIS specification and to help pave the -- way for more accurate behavioral I/O buffer models and simulations. This -- file may be used, modified, and distributed without any limitations; -- however, this file is provided "as is" with no warranties whatsoever, -- including any warranty of merchantability, noninfringement, fitness for -- any particular purpose, or any warranty otherwise arising out of any -- proposal, specification or sample. Intel and the author disclaim all -- liability, including liability or infringement of any proprietary rights, -- including rights to use the information in this file. No license, -- express or implied, by estoppel or otherwise, to any intellectual -- property rights is granted herein. --=========================================================================== -- Base model v2.1 -- -- This version combines the analog equations in order to reduce the -- number of quantities used. A.M. 4/5/2005 -- -- Base model v2.0 -- -- This version uses a different digital logic to find the state of the -- buffer. Process "Catch" was changed, processes "pu_on_event_time", -- "pu_off_event_time", "pd_on_event_time", "pd_off_event_time" were -- added, and the "simultaneous analog equations" section was also -- modified to accomodate the above changes. This model is more compact -- compared with the older version. A.M. 2/27/2004 -- -- Features: -- -- 1) This model supports only basic (incomplete) IBIS 2.1 features -- -- 2) This model uses 4 IV curves (I/O buffer model) -- -- 3) This model uses 4 Vt curves (I/O buffer model) -- Vt tables do not have to be the same length, -- Vt tables do not have to start and/or end at the same time, -- Vt tables do not have to have the same time points -- -- 4) Model has common time axis generator for the Vt curves (executes -- once during initialization of constants) -- -- 5) Model has time axis interpolator for improved resolution with Vt -- curves having a few points, or large dt between points (executes -- once during initialization of constants) -- -- 6) Includes Vt curve to scaling coefficient converter (executes once -- during initialization of constants) -- -- 7) This model has a 4-way split constant C_comp -- -- 8) Includes complete logic for Input and Enable -- High-to-Low / Low-to-High while enable is on or off -- Enable / Disable while input is High or Low -- Enable / Disable while input goes High-to-Low or Low-to-High -- -- To be done: -- -- 1) Add receiver model (threshold sensing, etc...) -- 2) Add support for the Ramp keyword -- 3) Provisions for switching into unfinished edges -- 4) Test terminations using voltages other than V_fixture -- 5) Provide on-die terminations as used with Submodel, etc. -- 6) Data dependent switching and strength characteristics support -- 7) Covering other buffer types (input, output, open_***, etc...) -- 8) Receiver threshold modeling and logic -- 9) File I/O to read IV, Vt, etc. data from external files -- 10) Differencial I/O model version --=========================================================================== library IEEE; use IEEE.math_real.all; use IEEE.std_logic_1164.all; use IEEE.electrical_systems.all; use IEEE.energy_systems.all; --=========================================================================== entity IBIS_IO is generic (C_comp : real := 4.55e-12; -- Default C_comp value and k_C_comp_pc : real := 0.25; -- splitting coefficients k_C_comp_pu : real := 0.25; k_C_comp_pd : real := 0.25; k_C_comp_gc : real := 0.25; ------------------------------------------------------------------ -- [Pullup Reference] and [Pulldown Reference] values ------------------------------------------------------------------ V_pu_ref : real := 5.0; V_pd_ref : real := 0.0; ------------------------------------------------------------------ -- Vectors of the IV curve tables ------------------------------------------------------------------ I_pc : real_vector := ( 0.08, 0.00, 0.00, 0.00); V_pc : real_vector := (-5.00, -1.00, 5.00, 10.00); I_pu : real_vector := ( 0.10, 0.00, -0.10, -0.20); V_pu : real_vector := (-5.00, 0.00, 5.00, 10.00); I_pd : real_vector := (-0.10, 0.00, 0.10, 0.20); V_pd : real_vector := (-5.00, 0.00, 5.00, 10.00); I_gc : real_vector := (-0.08, 0.00, 0.00, 0.00); V_gc : real_vector := (-5.00, -1.00, 5.00, 10.00); ------------------------------------------------------------------ -- Vectors of the Vt curve tables ------------------------------------------------------------------ V_pu_on : real_vector := ( 0.00, 0.00, 2.50, 2.50); T_pu_on : real_vector := ( 0.00, 1.00e-9, 2.00e-9, 3.00e-9); V_pu_off : real_vector := ( 2.50, 2.50, 0.00, 0.00); T_pu_off : real_vector := ( 0.00, 0.50e-9, 0.80e-9, 3.00e-9); V_pd_on : real_vector := ( 5.00, 5.00, 2.50, 2.50); T_pd_on : real_vector := ( 0.00, 1.00e-9, 2.00e-9, 3.00e-9); V_pd_off : real_vector := ( 2.50, 2.50, 5.00, 5.00); T_pd_off : real_vector := ( 0.00, 0.50e-9, 0.80e-9, 3.00e-9); ------------------------------------------------------------------ -- V_fixture and R_fixture values ------------------------------------------------------------------ Vfx_pu_on : real := 0.0; Vfx_pu_off : real := 0.0; Vfx_pd_on : real := 5.0; Vfx_pd_off : real := 5.0; Rfx_pu_on : real := 50.0; Rfx_pu_off : real := 50.0; Rfx_pd_on : real := 50.0; Rfx_pd_off : real := 50.0; ------------------------------------------------------------------ Delta_t : real := 10.0e-12); -- This parameter -- determines what the maximum time delta will be between the -- points of the Vt curves and scaling coefficient curves -- after preprocessing the input data. ------------------------------------------------------------------------ port (signal In_D : in std_logic; signal En_D : in std_logic; signal Rcv_D : out std_logic; terminal IO : electrical; terminal PC_ref : electrical; terminal PU_ref : electrical; terminal PD_ref : electrical; terminal GC_ref : electrical); end entity IBIS_IO; --=========================================================================== architecture IO_1EQ of IBIS_IO is quantity Vpc across Ipc through PC_ref to IO; quantity Vpu across Ipu through PU_ref to IO; quantity Vpd across Ipd through IO to PD_ref; quantity Vgc across Igc through IO to GC_ref; signal pu_on : std_logic := '0'; signal pu_off : std_logic := '0'; signal pd_on : std_logic := '0'; signal pd_off : std_logic := '0'; signal Tpu_on_event : real := 0.0; signal Tpd_off_event : real := 0.0; signal Tpd_on_event : real := 0.0; signal Tpu_off_event : real := 0.0; quantity k_pu : real := 0.0; quantity k_pd : real := 0.0; --=========================================================================== function Lookup (Extrapolation : in string := "IV"; X : in real; Ydata : in real_vector; Xdata : in real_vector) return real is --------------------------------------------------------------------------- -- This function is basically the equivalent of a PWL function in SPICE. -- It returns "Y" that corresponds to "X" in the "Ydata" "Xdata" input pair -- using linear interpolation. -- -- If the "X" input value lies outside the range of "Xdata", the returned -- "Y" value will either be equal to the first or last point in "Ydata", -- or it will be calculated using the slope between the first or last two -- points of "Ydata". The extrapolation method is determined by the string -- in "Extrapolation". "Vt" selects the repeated points method, "IV" -- selects the last slopes method. -- -- (The original code of this function was received from Mentor Graphics, -- modifications written by Arpad Muranyi, Intel Corporation). --------------------------------------------------------------------------- variable xvalue, yvalue, m : real; variable start, fin, mid : integer; --------------------------------------------------------------------------- begin ------------------------------------------------------------------------- -- Handle cases when "X" is outside the range of "Xdata" ------------------------------------------------------------------------- if (Extrapolation = "IV") and (X <= Xdata(0)) then m := (Ydata(1) - Ydata(0)) / (Xdata(1) - Xdata(0)); yvalue := Ydata(0) + m * (X - Xdata(0)); return yvalue; elsif (Extrapolation = "Vt") and (X <= Xdata(0)) then yvalue := Ydata(0); return yvalue; elsif (Extrapolation = "IV") and (X >= Xdata(Xdata'right)) then m := (Ydata(Ydata'right) - Ydata(Ydata'right - 1)) / (Xdata(Xdata'right) - Xdata(Xdata'right - 1)); yvalue := Ydata(Ydata'right) + m * (X - Xdata(Xdata'right)); return yvalue; elsif (Extrapolation = "Vt") and (X >= Xdata(Xdata'right)) then yvalue := Ydata(Ydata'right); return yvalue; ------------------------------------------------------------------------- -- Handle cases when "X" is in the range of "Xdata" ------------------------------------------------------------------------- else start:= 0; fin := Xdata'right; while start <= fin loop mid := (start + fin) / 2; if Xdata(mid) < X then start := mid + 1; else fin := mid - 1; end if; end loop; if Xdata(mid) > X then mid := mid - 1; end if; ----------------------------------------------------------------------- -- Find "Y" by linear interpolation ----------------------------------------------------------------------- yvalue := Ydata(mid) + (X - Xdata(mid)) * (Ydata(mid+1) - Ydata(mid)) / (Xdata(mid+1) - Xdata(mid)); return yvalue; ------------------------------------------------------------------------- end if; ------------------------------------------------------------------------- end function Lookup; --=========================================================================== function Find_common_length (Max_dt : real := 1.0e-12; Twfm_1 : in real_vector; Twfm_2 : in real_vector; Twfm_3 : in real_vector; Twfm_4 : in real_vector) return integer is --------------------------------------------------------------------------- -- This function finds the total number of points needed for having a -- common time axis for all Vt curves, such that the maximum delta time -- between each time point doesn't exceed the value provided in "Max_dt". --------------------------------------------------------------------------- variable Common_length : integer := 0; variable Return_val : integer := 0; variable index_1 : integer := Twfm_1'left; variable index_2 : integer := Twfm_2'left; variable index_3 : integer := Twfm_3'left; variable index_4 : integer := Twfm_4'left; variable new_index_1 : integer := Twfm_1'left; variable new_index_2 : integer := Twfm_2'left; variable new_index_3 : integer := Twfm_3'left; variable new_index_4 : integer := Twfm_4'left; variable old_t : real := 0.0; variable new_t : real := 0.0; variable remainder : real := 0.0; variable min_dt : real := 1.0e-3; -- This sets the size of the -- roundoff error relative to -- "Max_dt" --------------------------------------------------------------------------- begin --------------------------------------------------------------------------- -- Put the earliest time value of all given time vectors into "old_t" --------------------------------------------------------------------------- old_t := Twfm_1(Twfm_1'left); if (Twfm_2(Twfm_2'left) < old_t) then old_t := Twfm_2(Twfm_2'left); end if; if (Twfm_3(Twfm_3'left) < old_t) then old_t := Twfm_3(Twfm_3'left); end if; if (Twfm_4(Twfm_4'left) < old_t) then old_t := Twfm_4(Twfm_4'left); end if; --------------------------------------------------------------------------- -- Put the latest time value of all given time vectors into "new_t" --------------------------------------------------------------------------- new_t := Twfm_1(Twfm_1'right); if (Twfm_2(Twfm_2'right) > new_t) then new_t := Twfm_2(Twfm_2'right); end if; if (Twfm_3(Twfm_3'right) > new_t) then new_t := Twfm_3(Twfm_3'right); end if; if (Twfm_4(Twfm_4'right) > new_t) then new_t := Twfm_4(Twfm_4'right); end if; new_t := new_t; --------------------------------------------------------------------------- -- Loop until latest time value is reached in each given time vector --------------------------------------------------------------------------- while (old_t < new_t) loop ------------------------------------------------------------------------- -- Find which given time vector(s) have the lowest time value and -- advance their temporary indexes ------------------------------------------------------------------------- if (Twfm_1(index_1) <= old_t) then new_index_1 := index_1 + 1; end if; if (Twfm_2(index_2) <= old_t) then new_index_2 := index_2 + 1; end if; if (Twfm_3(index_3) <= old_t) then new_index_3 := index_3 + 1; end if; if (Twfm_4(index_4) <= old_t) then new_index_4 := index_4 + 1; end if; ------------------------------------------------------------------------- -- Find the lowest value at the new indexes in the given vector(s) and -- update indexes for next iteration ------------------------------------------------------------------------- if (new_index_1 <= Twfm_1'right) then if (Twfm_1(new_index_1) < new_t) then new_t := Twfm_1(new_index_1); end if; index_1 := new_index_1; end if; if (new_index_2 <= Twfm_2'right) then if (Twfm_2(new_index_2) < new_t) then new_t := Twfm_2(new_index_2); end if; index_2 := new_index_2; end if; if (new_index_3 <= Twfm_3'right) then if (Twfm_3(new_index_3) < new_t) then new_t := Twfm_3(new_index_3); end if; index_3 := new_index_3; end if; if (new_index_4 <= Twfm_4'right) then if (Twfm_4(new_index_4) < new_t) then new_t := Twfm_4(new_index_4); end if; index_4 := new_index_4; end if; ------------------------------------------------------------------------- -- Calculate how many additional points are needed between the given -- points to satisfy the "Max_dt" separation criteria. Note: the extra -- logic is needed due to floating point inaccuracies. ------------------------------------------------------------------------- Common_length := Common_length + integer(ceil((new_t-old_t)/Max_dt)); remainder := "mod"((new_t-old_t),Max_dt); if (remainder < (min_dt * Max_dt)) and (remainder > 0.0) then Common_length := Common_length - 1; end if; ------------------------------------------------------------------------- -- Update variables for next iteration ------------------------------------------------------------------------- old_t := new_t; new_t := Twfm_1(Twfm_1'right); if (Twfm_2(Twfm_2'right) > new_t) then new_t := Twfm_2(Twfm_2'right); end if; if (Twfm_3(Twfm_3'right) > new_t) then new_t := Twfm_3(Twfm_3'right); end if; if (Twfm_4(Twfm_4'right) > new_t) then new_t := Twfm_4(Twfm_4'right); end if; new_t := new_t; --------------------------------------------------------------------------- end loop; --------------------------------------------------------------------------- return Common_length; end function Find_common_length; --=========================================================================== function Common_time (Max_dt : real := 1.0e-12; Twfm_1 : in real_vector; Twfm_2 : in real_vector; Twfm_3 : in real_vector; Twfm_4 : in real_vector) return real_vector is --------------------------------------------------------------------------- -- This function generates a vector that serves as a common time axis for -- all Vt curves, such that the maximum delta time between each time point -- doesn't exceed the value provided in "Max_dt". --------------------------------------------------------------------------- variable New_time : real_vector(0 to Find_common_length(Max_dt, Twfm_1, Twfm_2, Twfm_3, Twfm_4)-1) := (others => 0.0); variable index : integer := 0; variable extra_start : integer := 0; variable extra_points : integer := 0; variable index_1 : integer := Twfm_1'left; variable index_2 : integer := Twfm_2'left; variable index_3 : integer := Twfm_3'left; variable index_4 : integer := Twfm_4'left; variable new_index_1 : integer := Twfm_1'left; variable new_index_2 : integer := Twfm_2'left; variable new_index_3 : integer := Twfm_3'left; variable new_index_4 : integer := Twfm_4'left; variable old_t : real := 0.0; variable new_t : real := 0.0; variable remainder : real := 0.0; variable min_dt : real := 1.0e-3; -- This sets the size of the -- roundoff error relative to -- "Max_dt" --------------------------------------------------------------------------- begin --------------------------------------------------------------------------- -- Put the earliest time value of all given time vectors into "old_t" --------------------------------------------------------------------------- old_t := Twfm_1(Twfm_1'left); if (Twfm_2(Twfm_2'left) < old_t) then old_t := Twfm_2(Twfm_2'left); end if; if (Twfm_3(Twfm_3'left) < old_t) then old_t := Twfm_3(Twfm_3'left); end if; if (Twfm_4(Twfm_4'left) < old_t) then old_t := Twfm_4(Twfm_4'left); end if; --------------------------------------------------------------------------- -- Put the latest time value of all given time vectors into "new_t" --------------------------------------------------------------------------- new_t := Twfm_1(Twfm_1'right); if (Twfm_2(Twfm_2'right) > new_t) then new_t := Twfm_2(Twfm_2'right); end if; if (Twfm_3(Twfm_3'right) > new_t) then new_t := Twfm_3(Twfm_3'right); end if; if (Twfm_4(Twfm_4'right) > new_t) then new_t := Twfm_4(Twfm_4'right); end if; new_t := new_t; --------------------------------------------------------------------------- -- Loop until last index is reached in each given time vector --------------------------------------------------------------------------- index := New_time'left; while (old_t < new_t) loop ------------------------------------------------------------------------- -- Find which given time vector(s) have the lowest time value and -- advance their temporary indexes ------------------------------------------------------------------------- if (Twfm_1(index_1) <= old_t) then new_index_1 := index_1 + 1; end if; if (Twfm_2(index_2) <= old_t) then new_index_2 := index_2 + 1; end if; if (Twfm_3(index_3) <= old_t) then new_index_3 := index_3 + 1; end if; if (Twfm_4(index_4) <= old_t) then new_index_4 := index_4 + 1; end if; ------------------------------------------------------------------------- -- Find the lowest value at the new indexes in the given vector(s) and -- update indexes for next iteration ------------------------------------------------------------------------- if (new_index_1 <= Twfm_1'right) then if (Twfm_1(new_index_1) < new_t) then new_t := Twfm_1(new_index_1); end if; index_1 := new_index_1; end if; if (new_index_2 <= Twfm_2'right) then if (Twfm_2(new_index_2) < new_t) then new_t := Twfm_2(new_index_2); end if; index_2 := new_index_2; end if; if (new_index_3 <= Twfm_3'right) then if (Twfm_3(new_index_3) < new_t) then new_t := Twfm_3(new_index_3); end if; index_3 := new_index_3; end if; if (new_index_4 <= Twfm_4'right) then if (Twfm_4(new_index_4) < new_t) then new_t := Twfm_4(new_index_4); end if; index_4 := new_index_4; end if; ------------------------------------------------------------------------- -- Calculate how many additional points are needed between the given -- points to satisfy the "Max_dt" separation criteria. Note: the extra -- logic is needed due to floating point inaccuracies. ------------------------------------------------------------------------- extra_points := integer(ceil((new_t-old_t)/Max_dt)); remainder := "mod"((new_t-old_t),Max_dt); if remainder < (min_dt * Max_dt) and remainder > 0.0 then extra_points := extra_points - 1; end if; ------------------------------------------------------------------------- -- Calculate and write the values of points into the "New_time" vector ------------------------------------------------------------------------- for x_index in 0 to (extra_points - 1) loop New_time(index) := old_t + (real(x_index) * (new_t-old_t)) / real(extra_points); index := index + 1; end loop; ------------------------------------------------------------------------- -- Update variables for next iteration ------------------------------------------------------------------------- old_t := new_t; new_t := Twfm_1(Twfm_1'right); if (Twfm_2(Twfm_2'right) > new_t) then new_t := Twfm_2(Twfm_2'right); end if; if (Twfm_3(Twfm_3'right) > new_t) then new_t := Twfm_3(Twfm_3'right); end if; if (Twfm_4(Twfm_4'right) > new_t) then new_t := Twfm_4(Twfm_4'right); end if; new_t := new_t; --------------------------------------------------------------------------- end loop; --------------------------------------------------------------------------- -- Insert the largest value at the end of the given vector(s) into the -- last position of "New_time". (The loop above stops at the next to -- the last point). --------------------------------------------------------------------------- New_time(New_time'right) := new_t; --------------------------------------------------------------------------- return New_time; end function Common_time; --=========================================================================== function Common_wfm (New_t : in real_vector; Vwfm : in real_vector; Twfm : in real_vector) return real_vector is --------------------------------------------------------------------------- -- This function generates an interpolated vector based on the input vector -- "New_t" using the input vector pair "Vwfm" and "Twfm". --------------------------------------------------------------------------- variable New_v : real_vector(New_t'range) := (others => 1.0); --------------------------------------------------------------------------- begin -- This is the better notation -- but it doesn't work due to -- for index in New_v'range loop -- a bug in SystemVision for index in New_v'left to New_v'right loop New_v(index) := Lookup("Vt", New_t(index), Vwfm, Twfm); end loop; return New_v; end function Common_wfm; --=========================================================================== constant T_common : real_vector := Common_time(Delta_t, T_pu_on, T_pu_off, T_pd_on, T_pd_off); constant V_pu_on_common : real_vector := Common_wfm(T_common, V_pu_on, T_pu_on); constant V_pu_off_common : real_vector := Common_wfm(T_common, V_pu_off, T_pu_off); constant V_pd_on_common : real_vector := Common_wfm(T_common, V_pd_on, T_pd_on); constant V_pd_off_common : real_vector := Common_wfm(T_common, V_pd_off, T_pd_off); --=========================================================================== function Coeff (Edge : in string; Vwfm : in real_vector; Twfm : in real_vector; Rfx : in real; Vfx : in real; Iiv : in real_vector; Viv : in real_vector; Vref : in real) return real_vector is --------------------------------------------------------------------------- -- This function converts the Vt curve to a corresponding scaling -- coefficient curve that is used to scale the IV curve with respect -- to time. The effects of C_comp on the waveforms are included in the -- scaling coefficient, so that the presence of C_comp in the output -- stage will not "load" the driver, i.e. C_comp in the output stage -- will not derate the original waveforms in the Vt curves. --------------------------------------------------------------------------- variable Kout : real_vector(Vwfm'range); variable dVwfm : real_vector(Vwfm'range); variable I1 : real := 1.0; variable Ifx1 : real := 0.0; --------------------------------------------------------------------------- begin for index in Vwfm'range loop ------------------------------------------------------------------------- -- Generate the derivative of the waveform -- Force the derivatives of the first and last points to zero ------------------------------------------------------------------------- if (index = Vwfm'left) then dVwfm(index) := 0.0; dVwfm(index) := 0.0; elsif (index = Vwfm'right) then dVwfm(index) := 0.0; dVwfm(index) := 0.0; ----------------------------------------------------------------------- -- Calculate the derivative of a point using both of its neighbors ----------------------------------------------------------------------- else dVwfm(index) := ((Vwfm(index) - Vwfm(index-1))/(Twfm(index) - Twfm(index-1)) + (Vwfm(index+1) - Vwfm(index))/(Twfm(index+1) - Twfm(index)))/2.0; end if; ----------------------------------------------------------------------- -- Calculate intermediate currents ----------------------------------------------------------------------- if (Edge = "K_pu_on") or (Edge = "K_pu_off") then I1 := Lookup("IV", Vref - Vwfm(index), Iiv, Viv); Ifx1 := realmin(((Vfx - Vwfm(index)) / Rfx), 0.0) - C_comp * dVwfm(index); elsif (Edge = "K_pd_on") or (Edge = "K_pd_off") then I1 := Lookup("IV", Vwfm(index) - Vref, Iiv, Viv); Ifx1 := realmax(((Vfx - Vwfm(index)) / Rfx), 0.0) - C_comp * dVwfm(index); else I1 := 1.0; Ifx1 := 0.0; end if; Kout(index) := Ifx1 / I1; ------------------------------------------------------------------------- end loop; ------------------------------------------------------------------------- return Kout; end function Coeff; --=========================================================================== constant K_pu_on : real_vector := Coeff("K_pu_on", V_pu_on_common, T_common, Rfx_pu_on, Vfx_pu_on, I_pu, V_pu, V_pu_ref); constant K_pd_off : real_vector := Coeff("K_pd_off", V_pd_off_common, T_common, Rfx_pd_off, Vfx_pd_off, I_pd, V_pd, V_pd_ref); constant K_pd_on : real_vector := Coeff("K_pd_on", V_pd_on_common, T_common, Rfx_pd_on, Vfx_pd_on, I_pd, V_pd, V_pd_ref); constant K_pu_off : real_vector := Coeff("K_pu_off", V_pu_off_common, T_common, Rfx_pu_off, Vfx_pu_off, I_pu, V_pu, V_pu_ref); --=========================================================================== begin --=========================================================================== Catch: process (In_D, En_D) is --------------------------------------------------------------------------- begin Rcv_D <= In_D; -- Dummy receiver logic ------------------------------------------------------------------------- if (En_D = '1') and (In_D = '1') then -- Find logic state pu_on <= '1'; pd_off <= '1'; pd_on <= '0'; pu_off <= '0'; elsif (En_D = '1') and (In_D = '0') then pu_on <= '0'; pd_off <= '0'; pd_on <= '1'; pu_off <= '1'; elsif (En_D = '0') then pu_on <= '0'; pd_off <= '1'; pd_on <= '0'; pu_off <= '1'; else pu_on <= '1'; pd_off <= '0'; pd_on <= '1'; pu_off <= '0'; end if; --------------------------------------------------------------------------- end process Catch; --=========================================================================== pu_on_event_time: process (pu_on) is -- Update event time if changed --------------------------------------------------------------------------- begin Tpu_on_event <= now; --------------------------------------------------------------------------- end process pu_on_event_time; --=========================================================================== pu_off_event_time: process (pu_off) is -- Update event time if changed --------------------------------------------------------------------------- begin Tpu_off_event <= now; --------------------------------------------------------------------------- end process pu_off_event_time; --=========================================================================== pd_on_event_time: process (pd_on) is -- Update event time if changed --------------------------------------------------------------------------- begin Tpd_on_event <= now; --------------------------------------------------------------------------- end process pd_on_event_time; --=========================================================================== pd_off_event_time: process (pd_off) is -- Update event time if changed --------------------------------------------------------------------------- begin Tpd_off_event <= now; --------------------------------------------------------------------------- end process pd_off_event_time; --=========================================================================== break on pu_on; break on pu_off; break on pd_on; break on pd_off; --=========================================================================== -- This section contains the simultaneous analog equations to find the -- appropriate scaling coefficients according to the state the buffer. --------------------------------------------------------------------------- if (Tpu_on_event = 0.0 and Tpu_off_event = 0.0 and Tpd_on_event = 0.0 and Tpd_off_event = 0.0) use -- Initialization if (pu_on = '1') use -- Start with the end of the k_pu == K_pu_on(K_pu_on'right); -- Vt curves for those which elsif (pu_off = '1') use -- are fully on initially k_pu == K_pu_off(K_pu_off'right); else k_pu == 0.0; end use; if (pd_on = '1') use k_pd == K_pd_on(K_pd_on'right); elsif (pd_off = '1') use k_pd == K_pd_off(K_pd_off'right); else k_pd == 0.0; end use; else -- Look up coefficients in normal operation if (pu_on = '1') use k_pu == Lookup("Vt", now - Tpu_on_event, K_pu_on, T_common); elsif (pu_off = '1') use k_pu == Lookup("Vt", now - Tpu_off_event, K_pu_off, T_common); else k_pu == K_pu_on(K_pu_on'left); end use; if (pd_on = '1') use k_pd == Lookup("Vt", now - Tpd_on_event, K_pd_on, T_common); elsif (pd_off = '1') use k_pd == Lookup("Vt", now - Tpd_off_event, K_pd_off, T_common); else k_pd == K_pd_on(K_pd_on'left); end use; end use; --=========================================================================== -- This section contains the simultaneous analog equations which calculate -- the output currents of the IV curves and C_comp capacitors. --------------------------------------------------------------------------- Ipc == -1.0 *Lookup("IV", Vpc, I_pc, V_pc) + k_C_comp_pc*C_comp*Vpc'dot; Ipu == -1.0*k_pu*Lookup("IV", Vpu, I_pu, V_pu) + k_C_comp_pu*C_comp*Vpu'dot; Ipd == k_pd*Lookup("IV", Vpd, I_pd, V_pd) + k_C_comp_pd*C_comp*Vpd'dot; Igc == Lookup("IV", Vgc, I_gc, V_gc) + k_C_comp_gc*C_comp*Vgc'dot; --=========================================================================== end architecture IO_1EQ; --=========================================================================== --*************************************************************************** --=========================================================================== architecture IO_2EQ of IBIS_IO is quantity Vpc across Ipc through PC_ref to IO; quantity Vpu across Ipu through PU_ref to IO; quantity Vpd across Ipd through IO to PD_ref; quantity Vgc across Igc through IO to GC_ref; signal pu_on : std_logic := '0'; signal pu_off : std_logic := '0'; signal pd_on : std_logic := '0'; signal pd_off : std_logic := '0'; signal Tpu_on_event : real := 0.0; signal Tpd_off_event : real := 0.0; signal Tpd_on_event : real := 0.0; signal Tpu_off_event : real := 0.0; quantity k_pu : real := 0.0; quantity k_pd : real := 0.0; --=========================================================================== function Lookup (Extrapolation : in string := "IV"; X : in real; Ydata : in real_vector; Xdata : in real_vector) return real is --------------------------------------------------------------------------- -- This function is basically the equivalent of a PWL function in SPICE. -- It returns "Y" that corresponds to "X" in the "Ydata" "Xdata" input pair -- using linear interpolation. -- -- If the "X" input value lies outside the range of "Xdata", the returned -- "Y" value will either be equal to the first or last point in "Ydata", -- or it will be calculated using the slope between the first or last two -- points of "Ydata". The extrapolation method is determined by the string -- in "Extrapolation". "Vt" selects the repeated points method, "IV" -- selects the last slopes method. -- -- (The original code of this function was received from Mentor Graphics, -- modifications written by Arpad Muranyi, Intel Corporation). --------------------------------------------------------------------------- variable xvalue, yvalue, m : real; variable start, fin, mid : integer; --------------------------------------------------------------------------- begin ------------------------------------------------------------------------- -- Handle cases when "X" is outside the range of "Xdata" ------------------------------------------------------------------------- if (Extrapolation = "IV") and (X <= Xdata(0)) then m := (Ydata(1) - Ydata(0)) / (Xdata(1) - Xdata(0)); yvalue := Ydata(0) + m * (X - Xdata(0)); return yvalue; elsif (Extrapolation = "Vt") and (X <= Xdata(0)) then yvalue := Ydata(0); return yvalue; elsif (Extrapolation = "IV") and (X >= Xdata(Xdata'right)) then m := (Ydata(Ydata'right) - Ydata(Ydata'right - 1)) / (Xdata(Xdata'right) - Xdata(Xdata'right - 1)); yvalue := Ydata(Ydata'right) + m * (X - Xdata(Xdata'right)); return yvalue; elsif (Extrapolation = "Vt") and (X >= Xdata(Xdata'right)) then yvalue := Ydata(Ydata'right); return yvalue; ------------------------------------------------------------------------- -- Handle cases when "X" is in the range of "Xdata" ------------------------------------------------------------------------- else start:= 0; fin := Xdata'right; while start <= fin loop mid := (start + fin) / 2; if Xdata(mid) < X then start := mid + 1; else fin := mid - 1; end if; end loop; if Xdata(mid) > X then mid := mid - 1; end if; ----------------------------------------------------------------------- -- Find "Y" by linear interpolation ----------------------------------------------------------------------- yvalue := Ydata(mid) + (X - Xdata(mid)) * (Ydata(mid+1) - Ydata(mid)) / (Xdata(mid+1) - Xdata(mid)); return yvalue; ------------------------------------------------------------------------- end if; ------------------------------------------------------------------------- end function Lookup; --=========================================================================== function Find_common_length (Max_dt : real := 1.0e-12; Twfm_1 : in real_vector; Twfm_2 : in real_vector; Twfm_3 : in real_vector; Twfm_4 : in real_vector) return integer is --------------------------------------------------------------------------- -- This function finds the total number of points needed for having a -- common time axis for all Vt curves, such that the maximum delta time -- between each time point doesn't exceed the value provided in "Max_dt". --------------------------------------------------------------------------- variable Common_length : integer := 0; variable Return_val : integer := 0; variable index_1 : integer := Twfm_1'left; variable index_2 : integer := Twfm_2'left; variable index_3 : integer := Twfm_3'left; variable index_4 : integer := Twfm_4'left; variable new_index_1 : integer := Twfm_1'left; variable new_index_2 : integer := Twfm_2'left; variable new_index_3 : integer := Twfm_3'left; variable new_index_4 : integer := Twfm_4'left; variable old_t : real := 0.0; variable new_t : real := 0.0; variable remainder : real := 0.0; variable min_dt : real := 1.0e-3; -- This sets the size of the -- roundoff error relative to -- "Max_dt" --------------------------------------------------------------------------- begin --------------------------------------------------------------------------- -- Put the earliest time value of all given time vectors into "old_t" --------------------------------------------------------------------------- old_t := Twfm_1(Twfm_1'left); if (Twfm_2(Twfm_2'left) < old_t) then old_t := Twfm_2(Twfm_2'left); end if; if (Twfm_3(Twfm_3'left) < old_t) then old_t := Twfm_3(Twfm_3'left); end if; if (Twfm_4(Twfm_4'left) < old_t) then old_t := Twfm_4(Twfm_4'left); end if; --------------------------------------------------------------------------- -- Put the latest time value of all given time vectors into "new_t" --------------------------------------------------------------------------- new_t := Twfm_1(Twfm_1'right); if (Twfm_2(Twfm_2'right) > new_t) then new_t := Twfm_2(Twfm_2'right); end if; if (Twfm_3(Twfm_3'right) > new_t) then new_t := Twfm_3(Twfm_3'right); end if; if (Twfm_4(Twfm_4'right) > new_t) then new_t := Twfm_4(Twfm_4'right); end if; new_t := new_t; --------------------------------------------------------------------------- -- Loop until latest time value is reached in each given time vector --------------------------------------------------------------------------- while (old_t < new_t) loop ------------------------------------------------------------------------- -- Find which given time vector(s) have the lowest time value and -- advance their temporary indexes ------------------------------------------------------------------------- if (Twfm_1(index_1) <= old_t) then new_index_1 := index_1 + 1; end if; if (Twfm_2(index_2) <= old_t) then new_index_2 := index_2 + 1; end if; if (Twfm_3(index_3) <= old_t) then new_index_3 := index_3 + 1; end if; if (Twfm_4(index_4) <= old_t) then new_index_4 := index_4 + 1; end if; ------------------------------------------------------------------------- -- Find the lowest value at the new indexes in the given vector(s) and -- update indexes for next iteration ------------------------------------------------------------------------- if (new_index_1 <= Twfm_1'right) then if (Twfm_1(new_index_1) < new_t) then new_t := Twfm_1(new_index_1); end if; index_1 := new_index_1; end if; if (new_index_2 <= Twfm_2'right) then if (Twfm_2(new_index_2) < new_t) then new_t := Twfm_2(new_index_2); end if; index_2 := new_index_2; end if; if (new_index_3 <= Twfm_3'right) then if (Twfm_3(new_index_3) < new_t) then new_t := Twfm_3(new_index_3); end if; index_3 := new_index_3; end if; if (new_index_4 <= Twfm_4'right) then if (Twfm_4(new_index_4) < new_t) then new_t := Twfm_4(new_index_4); end if; index_4 := new_index_4; end if; ------------------------------------------------------------------------- -- Calculate how many additional points are needed between the given -- points to satisfy the "Max_dt" separation criteria. Note: the extra -- logic is needed due to floating point inaccuracies. ------------------------------------------------------------------------- Common_length := Common_length + integer(ceil((new_t-old_t)/Max_dt)); remainder := "mod"((new_t-old_t),Max_dt); if (remainder < (min_dt * Max_dt)) and (remainder > 0.0) then Common_length := Common_length - 1; end if; ------------------------------------------------------------------------- -- Update variables for next iteration ------------------------------------------------------------------------- old_t := new_t; new_t := Twfm_1(Twfm_1'right); if (Twfm_2(Twfm_2'right) > new_t) then new_t := Twfm_2(Twfm_2'right); end if; if (Twfm_3(Twfm_3'right) > new_t) then new_t := Twfm_3(Twfm_3'right); end if; if (Twfm_4(Twfm_4'right) > new_t) then new_t := Twfm_4(Twfm_4'right); end if; new_t := new_t; --------------------------------------------------------------------------- end loop; --------------------------------------------------------------------------- return Common_length; end function Find_common_length; --=========================================================================== function Common_time (Max_dt : real := 1.0e-12; Twfm_1 : in real_vector; Twfm_2 : in real_vector; Twfm_3 : in real_vector; Twfm_4 : in real_vector) return real_vector is --------------------------------------------------------------------------- -- This function generates a vector that serves as a common time axis for -- all Vt curves, such that the maximum delta time between each time point -- doesn't exceed the value provided in "Max_dt". --------------------------------------------------------------------------- variable New_time : real_vector(0 to Find_common_length(Max_dt, Twfm_1, Twfm_2, Twfm_3, Twfm_4)-1) := (others => 0.0); variable index : integer := 0; variable extra_start : integer := 0; variable extra_points : integer := 0; variable index_1 : integer := Twfm_1'left; variable index_2 : integer := Twfm_2'left; variable index_3 : integer := Twfm_3'left; variable index_4 : integer := Twfm_4'left; variable new_index_1 : integer := Twfm_1'left; variable new_index_2 : integer := Twfm_2'left; variable new_index_3 : integer := Twfm_3'left; variable new_index_4 : integer := Twfm_4'left; variable old_t : real := 0.0; variable new_t : real := 0.0; variable remainder : real := 0.0; variable min_dt : real := 1.0e-3; -- This sets the size of the -- roundoff error relative to -- "Max_dt" --------------------------------------------------------------------------- begin --------------------------------------------------------------------------- -- Put the earliest time value of all given time vectors into "old_t" --------------------------------------------------------------------------- old_t := Twfm_1(Twfm_1'left); if (Twfm_2(Twfm_2'left) < old_t) then old_t := Twfm_2(Twfm_2'left); end if; if (Twfm_3(Twfm_3'left) < old_t) then old_t := Twfm_3(Twfm_3'left); end if; if (Twfm_4(Twfm_4'left) < old_t) then old_t := Twfm_4(Twfm_4'left); end if; --------------------------------------------------------------------------- -- Put the latest time value of all given time vectors into "new_t" --------------------------------------------------------------------------- new_t := Twfm_1(Twfm_1'right); if (Twfm_2(Twfm_2'right) > new_t) then new_t := Twfm_2(Twfm_2'right); end if; if (Twfm_3(Twfm_3'right) > new_t) then new_t := Twfm_3(Twfm_3'right); end if; if (Twfm_4(Twfm_4'right) > new_t) then new_t := Twfm_4(Twfm_4'right); end if; new_t := new_t; --------------------------------------------------------------------------- -- Loop until last index is reached in each given time vector --------------------------------------------------------------------------- index := New_time'left; while (old_t < new_t) loop ------------------------------------------------------------------------- -- Find which given time vector(s) have the lowest time value and -- advance their temporary indexes ------------------------------------------------------------------------- if (Twfm_1(index_1) <= old_t) then new_index_1 := index_1 + 1; end if; if (Twfm_2(index_2) <= old_t) then new_index_2 := index_2 + 1; end if; if (Twfm_3(index_3) <= old_t) then new_index_3 := index_3 + 1; end if; if (Twfm_4(index_4) <= old_t) then new_index_4 := index_4 + 1; end if; ------------------------------------------------------------------------- -- Find the lowest value at the new indexes in the given vector(s) and -- update indexes for next iteration ------------------------------------------------------------------------- if (new_index_1 <= Twfm_1'right) then if (Twfm_1(new_index_1) < new_t) then new_t := Twfm_1(new_index_1); end if; index_1 := new_index_1; end if; if (new_index_2 <= Twfm_2'right) then if (Twfm_2(new_index_2) < new_t) then new_t := Twfm_2(new_index_2); end if; index_2 := new_index_2; end if; if (new_index_3 <= Twfm_3'right) then if (Twfm_3(new_index_3) < new_t) then new_t := Twfm_3(new_index_3); end if; index_3 := new_index_3; end if; if (new_index_4 <= Twfm_4'right) then if (Twfm_4(new_index_4) < new_t) then new_t := Twfm_4(new_index_4); end if; index_4 := new_index_4; end if; ------------------------------------------------------------------------- -- Calculate how many additional points are needed between the given -- points to satisfy the "Max_dt" separation criteria. Note: the extra -- logic is needed due to floating point inaccuracies. ------------------------------------------------------------------------- extra_points := integer(ceil((new_t-old_t)/Max_dt)); remainder := "mod"((new_t-old_t),Max_dt); if remainder < (min_dt * Max_dt) and remainder > 0.0 then extra_points := extra_points - 1; end if; ------------------------------------------------------------------------- -- Calculate and write the values of points into the "New_time" vector ------------------------------------------------------------------------- for x_index in 0 to (extra_points - 1) loop New_time(index) := old_t + (real(x_index) * (new_t-old_t)) / real(extra_points); index := index + 1; end loop; ------------------------------------------------------------------------- -- Update variables for next iteration ------------------------------------------------------------------------- old_t := new_t; new_t := Twfm_1(Twfm_1'right); if (Twfm_2(Twfm_2'right) > new_t) then new_t := Twfm_2(Twfm_2'right); end if; if (Twfm_3(Twfm_3'right) > new_t) then new_t := Twfm_3(Twfm_3'right); end if; if (Twfm_4(Twfm_4'right) > new_t) then new_t := Twfm_4(Twfm_4'right); end if; new_t := new_t; --------------------------------------------------------------------------- end loop; --------------------------------------------------------------------------- -- Insert the largest value at the end of the given vector(s) into the -- last position of "New_time". (The loop above stops at the next to -- the last point). --------------------------------------------------------------------------- New_time(New_time'right) := new_t; --------------------------------------------------------------------------- return New_time; end function Common_time; --=========================================================================== function Common_wfm (New_t : in real_vector; Vwfm : in real_vector; Twfm : in real_vector) return real_vector is --------------------------------------------------------------------------- -- This function generates an interpolated vector based on the input vector -- "New_t" using the input vector pair "Vwfm" and "Twfm". --------------------------------------------------------------------------- variable New_v : real_vector(New_t'range) := (others => 1.0); --------------------------------------------------------------------------- begin -- This is the better notation -- but it doesn't work due to -- for index in New_v'range loop -- a bug in SystemVision for index in New_v'left to New_v'right loop New_v(index) := Lookup("Vt", New_t(index), Vwfm, Twfm); end loop; return New_v; end function Common_wfm; --=========================================================================== constant T_common : real_vector := Common_time(Delta_t, T_pu_on, T_pu_off, T_pd_on, T_pd_off); constant V_pu_on_common : real_vector := Common_wfm(T_common, V_pu_on, T_pu_on); constant V_pu_off_common : real_vector := Common_wfm(T_common, V_pu_off, T_pu_off); constant V_pd_on_common : real_vector := Common_wfm(T_common, V_pd_on, T_pd_on); constant V_pd_off_common : real_vector := Common_wfm(T_common, V_pd_off, T_pd_off); --=========================================================================== function Coeff (Edge : in string; Vwfm_pu : in real_vector; Vwfm_pd : in real_vector; Twfm : in real_vector; Rfx_pu : in real; Rfx_pd : in real; Vfx_pu : in real; Vfx_pd : in real; Iiv_pu : in real_vector; Viv_pu : in real_vector; Iiv_pd : in real_vector; Viv_pd : in real_vector; V_pu_ref : in real; V_pd_ref : in real) return real_vector is --------------------------------------------------------------------------- -- This function converts each Vt curve to a corresponding scaling -- coefficient curve that is used to scale the IV curves with respect -- to time. The effects of C_comp on the waveforms are included in the -- scaling coefficients, so that the presence of C_comp in the output -- stage will not "load" the driver, i.e. C_comp in the output stage -- will not derate the original waveforms in the Vt curves. --------------------------------------------------------------------------- variable Kout : real_vector(Vwfm_pu'range); variable dVwfm_pu : real_vector(Vwfm_pu'range); variable dVwfm_pd : real_vector(Vwfm_pd'range); variable I1 : real := 0.0; variable I2 : real := 0.0; variable I3 : real := 0.0; variable I4 : real := 0.0; variable Ifx1 : real := 0.0; variable Ifx2 : real := 0.0; variable num : real := 0.0; variable den : real := 1.0; --------------------------------------------------------------------------- begin --------------------------------------------------------------------------- -- Generate the derivative of each waveform --------------------------------------------------------------------------- for index in Vwfm_pu'range loop ------------------------------------------------------------------------- -- Force the derivatives of the first and last points to zero ------------------------------------------------------------------------- if (index = Vwfm_pu'left) then dVwfm_pu(index) := 0.0; dVwfm_pd(index) := 0.0; elsif (index = Vwfm_pu'right) then dVwfm_pu(index) := 0.0; dVwfm_pd(index) := 0.0; ----------------------------------------------------------------------- -- Calculate the derivative of a point using both of its neighbors ----------------------------------------------------------------------- else dVwfm_pu(index) := ((Vwfm_pu(index) - Vwfm_pu(index-1))/(Twfm(index) - Twfm(index-1)) + (Vwfm_pu(index+1) - Vwfm_pu(index))/(Twfm(index+1) - Twfm(index)))/2.0; dVwfm_pd(index) := ((Vwfm_pd(index) - Vwfm_pd(index-1))/(Twfm(index) - Twfm(index-1)) + (Vwfm_pd(index+1) - Vwfm_pd(index))/(Twfm(index+1) - Twfm(index)))/2.0; end if; ----------------------------------------------------------------------- -- Calculate intermediate (current) variables ----------------------------------------------------------------------- I1 := Lookup("IV", Vwfm_pd(index) - V_pd_ref, Iiv_pd, Viv_pd); I2 := Lookup("IV", Vwfm_pu(index) - V_pd_ref, Iiv_pd, Viv_pd); I3 := -1.0 * Lookup("IV", V_pu_ref - Vwfm_pu(index), Iiv_pu, Viv_pu); I4 := -1.0 * Lookup("IV", V_pu_ref - Vwfm_pd(index), Iiv_pu, Viv_pu); ----------------------------------------------------------------------- -- Calculate intermediate (fixture) variables ----------------------------------------------------------------------- Ifx1 := ((Vwfm_pu(index) - Vfx_pu) / Rfx_pu) + C_comp * dVwfm_pu(index); Ifx2 := ((Vfx_pd - Vwfm_pd(index)) / Rfx_pd) - C_comp * dVwfm_pd(index); ----------------------------------------------------------------------- -- Set up the numerator of the equation depending on the direction of -- the transition, and set up denominator of the equation. ----------------------------------------------------------------------- if (Edge = "K_pu_on") or (Edge = "K_pu_off") then num := (Ifx1 * I1) + (Ifx2 * I2); elsif (Edge = "K_pd_on") or (Edge = "K_pd_off") then num := (Ifx1 * I4) + (Ifx2 * I3); else num := 0.0; end if; den := (I1 * I3) - (I2 * I4); ----------------------------------------------------------------------- -- This is the master equation that solves for the scaling coefficients ----------------------------------------------------------------------- Kout(index) := num / den; ------------------------------------------------------------------------- end loop; ------------------------------------------------------------------------- return Kout; end function Coeff; --=========================================================================== constant K_pu_on : real_vector := Coeff("K_pu_on", V_pu_on_common, V_pd_off_common, T_common, Rfx_pu_on, Rfx_pd_off, Vfx_pu_on, Vfx_pd_off, I_pu, V_pu, I_pd, V_pd, V_pu_ref, V_pd_ref); constant K_pd_off : real_vector := Coeff("K_pd_off", V_pu_on_common, V_pd_off_common, T_common, Rfx_pu_on, Rfx_pd_off, Vfx_pu_on, Vfx_pd_off, I_pu, V_pu, I_pd, V_pd, V_pu_ref, V_pd_ref); constant K_pd_on : real_vector := Coeff("K_pd_on", V_pu_off_common, V_pd_on_common, T_common, Rfx_pu_off, Rfx_pd_on, Vfx_pu_off, Vfx_pd_on, I_pu, V_pu, I_pd, V_pd, V_pu_ref, V_pd_ref); constant K_pu_off : real_vector := Coeff("K_pu_off", V_pu_off_common, V_pd_on_common, T_common, Rfx_pu_off, Rfx_pd_on, Vfx_pu_off, Vfx_pd_on, I_pu, V_pu, I_pd, V_pd, V_pu_ref, V_pd_ref); --=========================================================================== begin --=========================================================================== Catch: process (In_D, En_D) is --------------------------------------------------------------------------- begin Rcv_D <= In_D; -- Dummy receiver logic ------------------------------------------------------------------------- if (En_D = '1') and (In_D = '1') then -- Find logic state pu_on <= '1'; pd_off <= '1'; pd_on <= '0'; pu_off <= '0'; elsif (En_D = '1') and (In_D = '0') then pu_on <= '0'; pd_off <= '0'; pd_on <= '1'; pu_off <= '1'; elsif (En_D = '0') then pu_on <= '0'; pd_off <= '1'; pd_on <= '0'; pu_off <= '1'; else pu_on <= '1'; pd_off <= '0'; pd_on <= '1'; pu_off <= '0'; end if; --------------------------------------------------------------------------- end process Catch; --=========================================================================== pu_on_event_time: process (pu_on) is -- Update event time if changed --------------------------------------------------------------------------- begin Tpu_on_event <= now; --------------------------------------------------------------------------- end process pu_on_event_time; --=========================================================================== pu_off_event_time: process (pu_off) is -- Update event time if changed --------------------------------------------------------------------------- begin Tpu_off_event <= now; --------------------------------------------------------------------------- end process pu_off_event_time; --=========================================================================== pd_on_event_time: process (pd_on) is -- Update event time if changed --------------------------------------------------------------------------- begin Tpd_on_event <= now; --------------------------------------------------------------------------- end process pd_on_event_time; --=========================================================================== pd_off_event_time: process (pd_off) is -- Update event time if changed --------------------------------------------------------------------------- begin Tpd_off_event <= now; --------------------------------------------------------------------------- end process pd_off_event_time; --=========================================================================== break on pu_on; break on pu_off; break on pd_on; break on pd_off; --=========================================================================== -- This section contains the simultaneous analog equations to find the -- appropriate scaling coefficients according to the state the buffer. --------------------------------------------------------------------------- if (Tpu_on_event = 0.0 and Tpu_off_event = 0.0 and Tpd_on_event = 0.0 and Tpd_off_event = 0.0) use -- Initialization if (pu_on = '1') use -- Start with the end of the k_pu == K_pu_on(K_pu_on'right); -- Vt curves for those which elsif (pu_off = '1') use -- are fully on initially k_pu == K_pu_off(K_pu_off'right); else k_pu == 0.0; end use; if (pd_on = '1') use k_pd == K_pd_on(K_pd_on'right); elsif (pd_off = '1') use k_pd == K_pd_off(K_pd_off'right); else k_pd == 0.0; end use; else -- Look up coefficients in normal operation if (pu_on = '1') use k_pu == Lookup("Vt", now - Tpu_on_event, K_pu_on, T_common); elsif (pu_off = '1') use k_pu == Lookup("Vt", now - Tpu_off_event, K_pu_off, T_common); else k_pu == K_pu_on(K_pu_on'left); end use; if (pd_on = '1') use k_pd == Lookup("Vt", now - Tpd_on_event, K_pd_on, T_common); elsif (pd_off = '1') use k_pd == Lookup("Vt", now - Tpd_off_event, K_pd_off, T_common); else k_pd == K_pd_on(K_pd_on'left); end use; end use; --=========================================================================== -- This section contains the simultaneous analog equations which calculate -- the output currents of the IV curves and C_comp capacitors. --------------------------------------------------------------------------- Ipc == -1.0 *Lookup("IV", Vpc, I_pc, V_pc) + k_C_comp_pc*C_comp*Vpc'dot; Ipu == -1.0*k_pu*Lookup("IV", Vpu, I_pu, V_pu) + k_C_comp_pu*C_comp*Vpu'dot; Ipd == k_pd*Lookup("IV", Vpd, I_pd, V_pd) + k_C_comp_pd*C_comp*Vpd'dot; Igc == Lookup("IV", Vgc, I_gc, V_gc) + k_C_comp_gc*C_comp*Vgc'dot; --=========================================================================== end architecture IO_2EQ; --===========================================================================