------------------------------------------------------------------------------- -- File Name: ad7305.vhd ------------------------------------------------------------------------------- -- Copyright (C) 2005 Free Model Foundry; http://www.FreeModelFoundry.com -- -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License version 2 as -- published by the Free Software Foundation. -- -- MODIFICATION HISTORY: -- -- version: | author: | mod date: | changes made: -- V1.0 V.Ljubisavljevic 05 Apr 01 Initial release -- ------------------------------------------------------------------------------- -- IMPORTANT -- This model must be compiled without VITAL compliance checking ------------------------------------------------------------------------------- -- PART DESCRIPTION: -- -- Library: CONVERTER_VHDL -- Technology: CMOS -- Part: AD7305 -- Description: 3V/5V, Rail to Rail, Quad, 8-Bit DAC, w/Parallel Interface ------------------------------------------------------------------------------- -- NOTE -- Hardware Shutdown SHDN mode is not implemented -- because it is voltage dependent. -- It is adopted for Output voltage in shutdown mode to be 0 V because it is -- pooled down to ground through resistor of 120 ohms resistance. ------------------------------------------------------------------------------- LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; USE IEEE.VITAL_timing.ALL; USE IEEE.VITAL_primitives.ALL; LIBRARY FMF; USE FMF.gen_utils.ALL; USE FMF.conversions.ALL; ------------------------------------------------------------------------------- -- ENTITY DECLARATION ------------------------------------------------------------------------------- ENTITY ad7305 IS GENERIC ( -- tipd delays: interconnect path delays tipd_DB0 : VitalDelayType01 := VitalZeroDelay01; tipd_DB1 : VitalDelayType01 := VitalZeroDelay01; tipd_DB2 : VitalDelayType01 := VitalZeroDelay01; tipd_DB3 : VitalDelayType01 := VitalZeroDelay01; tipd_DB4 : VitalDelayType01 := VitalZeroDelay01; tipd_DB5 : VitalDelayType01 := VitalZeroDelay01; tipd_DB6 : VitalDelayType01 := VitalZeroDelay01; tipd_DB7 : VitalDelayType01 := VitalZeroDelay01; tipd_A0 : VitalDelayType01 := VitalZeroDelay01; tipd_A1 : VitalDelayType01 := VitalZeroDelay01; tipd_WRNeg : VitalDelayType01 := VitalZeroDelay01; tipd_LDACNeg : VitalDelayType01 := VitalZeroDelay01; -- tsetup values: setup times -- tas setup hi and low tsetup_A0_WRNeg : VitalDelayType := UnitDelay; -- tds setup hi and low tsetup_DB0_WRNeg : VitalDelayType := UnitDelay; -- tls setup low tsetup_LDACNeg_WRNeg : VitalDelayType := UnitDelay; -- thold values: hold times -- tah hold hi and low thold_A0_WRNeg : VitalDelayType := UnitDelay; -- tdh hold hi and low thold_DB0_WRNeg : VitalDelayType := UnitDelay; -- tlh hold low thold_LDACNeg_WRNeg : VitalDelayType := UnitDelay; -- tpw values: pulse widths -- twr low puls tpw_WRNeg_negedge : VitalDelayType := UnitDelay; -- tldw low puls tpw_LDACNeg_negedge : VitalDelayType := UnitDelay; -- analog generics: values of Vref inputs In Volts Vdd : real; Vss : real; -- generic control parameters InstancePath : STRING := DefaultInstancePath; TimingChecksOn : BOOLEAN := DefaultTimingChecks; MsgOn : BOOLEAN := DefaultMsgOn; XOn : BOOLEAN := DefaultXon; -- For FMF SDF technology file usage TimingModel : STRING := DefaultTimingModel ); PORT ( DB0 : IN std_ulogic := 'U'; DB1 : IN std_ulogic := 'U'; DB2 : IN std_ulogic := 'U'; DB3 : IN std_ulogic := 'U'; DB4 : IN std_ulogic := 'U'; DB5 : IN std_ulogic := 'U'; DB6 : IN std_ulogic := 'U'; DB7 : IN std_ulogic := 'U'; A0 : IN std_ulogic := 'U'; A1 : IN std_ulogic := 'U'; Vref : IN real := 0.0; VOUTA : OUT real := 0.0; VOUTB : OUT real := 0.0; VOUTC : OUT real := 0.0; VOUTD : OUT real := 0.0; LDACNeg : IN std_ulogic := 'U'; WRNeg : IN std_ulogic := 'U' ); ATTRIBUTE VITAL_LEVEL0 of ad7305 : ENTITY IS TRUE; END ad7305; ------------------------------------------------------------------------------- -- ARCHITECTURE DECLARATION ------------------------------------------------------------------------------- ARCHITECTURE vhdl_behavioral of ad7305 IS ATTRIBUTE VITAL_LEVEL0 of vhdl_behavioral : ARCHITECTURE IS TRUE; CONSTANT partID : STRING := "ad7305"; CONSTANT resolution : INTEGER := 8; SUBTYPE dacval_type IS NATURAL RANGE 0 TO (2**resolution-1); SUBTYPE stdl8 IS STD_LOGIC_VECTOR (resolution-1 DOWNTO 0); SIGNAL DB0_ipd : std_ulogic := 'U'; SIGNAL DB1_ipd : std_ulogic := 'U'; SIGNAL DB2_ipd : std_ulogic := 'U'; SIGNAL DB3_ipd : std_ulogic := 'U'; SIGNAL DB4_ipd : std_ulogic := 'U'; SIGNAL DB5_ipd : std_ulogic := 'U'; SIGNAL DB6_ipd : std_ulogic := 'U'; SIGNAL DB7_ipd : std_ulogic := 'U'; SIGNAL A0_ipd : std_ulogic := 'U'; SIGNAL A1_ipd : std_ulogic := 'U'; SIGNAL WRNeg_ipd : std_ulogic := 'U'; SIGNAL LDACNeg_ipd : std_ulogic := 'U'; -- No weak values SIGNAL DB0_nwv : STD_LOGIC := 'U'; SIGNAL DB1_nwv : STD_LOGIC := 'U'; SIGNAL DB2_nwv : STD_LOGIC := 'U'; SIGNAL DB3_nwv : STD_LOGIC := 'U'; SIGNAL DB4_nwv : STD_LOGIC := 'U'; SIGNAL DB5_nwv : STD_LOGIC := 'U'; SIGNAL DB6_nwv : STD_LOGIC := 'U'; SIGNAL DB7_nwv : STD_LOGIC := 'U'; SIGNAL A0_nwv : std_logic := 'U'; SIGNAL A1_nwv : std_logic := 'U'; BEGIN --------------------------------------------------------------------------- -- Wire Delays --------------------------------------------------------------------------- WireDelay : BLOCK BEGIN w_1 : VitalWireDelay (WRNeg_ipd, WRNeg, tipd_WRNeg); w_2 : VitalWireDelay (A0_ipd, A0, tipd_A0); w_3 : VitalWireDelay (A1_ipd, A1, tipd_A1); w_4 : VitalWireDelay (LDACNeg_ipd, LDACNeg, tipd_LDACNeg); w_5 : VitalWireDelay (DB0_ipd, DB0, tipd_DB0); w_6 : VitalWireDelay (DB1_ipd, DB1, tipd_DB1); w_7 : VitalWireDelay (DB2_ipd, DB2, tipd_DB2); w_8 : VitalWireDelay (DB3_ipd, DB3, tipd_DB3); w_9 : VitalWireDelay (DB4_ipd, DB4, tipd_DB4); w_10 : VitalWireDelay (DB5_ipd, DB5, tipd_DB5); w_11 : VitalWireDelay (DB6_ipd, DB6, tipd_DB6); w_12 : VitalWireDelay (DB7_ipd, DB7, tipd_DB7); END BLOCK; DB0_nwv <= DB0_ipd; DB1_nwv <= DB1_ipd; DB2_nwv <= DB2_ipd; DB3_nwv <= DB3_ipd; DB4_nwv <= DB4_ipd; DB5_nwv <= DB5_ipd; DB6_nwv <= DB6_ipd; DB7_nwv <= DB7_ipd; A0_nwv <= A0_ipd; A1_nwv <= A1_ipd; Behavior : BLOCK PORT ( DB : IN stdl8; A : IN STD_LOGIC_VECTOR(1 DOWNTO 0); LDACNeg : IN std_ulogic; WRNeg : IN std_ulogic); PORT MAP ( DB(0) => DB0_nwv, DB(1) => DB1_nwv, DB(2) => DB2_nwv, DB(3) => DB3_nwv, DB(4) => DB4_nwv, DB(5) => DB5_nwv, DB(6) => DB6_nwv, DB(7) => DB7_nwv, A(0) => A0_nwv, A(1) => A1_nwv, LDACNeg => LDACNeg_ipd, WRNeg => WRNeg_ipd ); CONSTANT tsettle : time := 2 us; CONSTANT tsdr : time := 2 us; -- recovery from shutdown CONSTANT tsdn : time := 15 us; -- time to shut down -- Internal signals SIGNAL VOUTA_zd : real := 0.0; SIGNAL VOUTB_zd : real := 0.0; SIGNAL VOUTC_zd : real := 0.0; SIGNAL VOUTD_zd : real := 0.0; SIGNAL Vref_int : real; -- Internal Vref voltage -- signals for upadating output SIGNAL settleA : STD_LOGIC := '0'; SIGNAL settleB : STD_LOGIC := '0'; SIGNAL settleC : STD_LOGIC := '0'; SIGNAL settleD : STD_LOGIC := '0'; SIGNAL decregA : stdl8 := (OTHERS => '0'); SIGNAL decregB : stdl8 := (OTHERS => '0'); SIGNAL decregC : stdl8 := (OTHERS => '0'); SIGNAL decregD : stdl8 := (OTHERS => '0'); SIGNAL update_outA : BOOLEAN := false; SIGNAL update_outB : BOOLEAN := false; SIGNAL update_outC : BOOLEAN := false; SIGNAL update_outD : BOOLEAN := false; -- Increment values for output SHARED VARIABLE StepA : real := 0.0; SHARED VARIABLE StepB : real := 0.0; SHARED VARIABLE StepC : real := 0.0; SHARED VARIABLE StepD : real := 0.0; --End values on outputs SHARED VARIABLE EndValA : real := 0.0; SHARED VARIABLE EndValB : real := 0.0; SHARED VARIABLE EndValC : real := 0.0; SHARED VARIABLE EndValD : real := 0.0; -- Pull up signals SIGNAL LDACNeg_nwv : X01; SIGNAL WRNeg_nwv : X01; -- purpose: Calculate output voltage from 8 bit input PROCEDURE DAConvert ( in_reg : IN stdl8; vref_in : IN real; out_v : OUT real) IS BEGIN -- PROCEDURE DAConvert out_v := vref_in * (real(to_nat(in_reg)) / real(2**resolution)); END PROCEDURE DAConvert; BEGIN LDACNeg_nwv <= to_X01(LDACNeg); WRNeg_nwv <= to_X01(WRNeg); ---------------------------------------------------------------------- -- Behavior Process ---------------------------------------------------------------------- -- purpose: Control of referent voltages -- type : combinational -- inputs : VrefA, VrefB, VrefC, VrefD Vref_contorl: PROCESS (Vref) VARIABLE MaxV : real := Vdd; VARIABLE MinV : real := Vss; BEGIN -- PROCESS Vref_contorl IF NOT (Vref <= MaxV AND Vref >= MinV) THEN ASSERT false REPORT LF & InstancePath & partID & ": simulation may be"& LF&"inaccurate due to VrefA range exceeding violations" SEVERITY WARNING; -- If reference voltage is out of range -- set it to first closest valid value. IF Vref > MaxV THEN Vref_int <= Vdd; ELSE Vref_int <= Vss; END IF; ELSE Vref_int <= Vref; END IF; END PROCESS Vref_contorl; digital : PROCESS (A, DB,WRNeg_nwv, LDACNeg_nwv) -- Timing Check Variables VARIABLE Tviol_A_WRNeg : X01 := '0'; VARIABLE TD_A_WRNeg : VitalTimingDataType; VARIABLE Tviol_DB_WRNeg : X01 := '0'; VARIABLE TD_DB_WRNeg : VitalTimingDataType; VARIABLE Tviol_LDACNeg_WRNeg : X01 := '0'; VARIABLE TD_LDACNeg_WRNeg : VitalTimingDataType; VARIABLE PD_LDACNeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_LDACNeg : X01 := '0'; VARIABLE PD_WRNeg : VitalPeriodDataType := VitalPeriodDataInit; VARIABLE Pviol_WRNeg : X01 := '0'; VARIABLE Violation : X01 := '0'; VARIABLE inregA : stdl8 := (OTHERS => '0'); VARIABLE inregB : stdl8 := (OTHERS => '0'); VARIABLE inregC : stdl8 := (OTHERS => '0'); VARIABLE inregD : stdl8 := (OTHERS => '0'); BEGIN ------------------------------------------------------------------- -- Timing Check Section ------------------------------------------------------------------- IF (TimingChecksOn) THEN VitalSetupHoldCheck ( TestSignal => A, TestSignalName => "A", RefSignal => WRNeg, RefSignalName => "WRNeg", SetupLow => tsetup_A0_WRNeg, SetupHigh => tsetup_A0_WRNeg, HoldLow => thold_A0_WRNeg, HoldHigh => thold_A0_WRNeg, CheckEnabled => true, RefTransition => '/', HeaderMsg => InstancePath & partID, TimingData => TD_A_WRNeg, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_A_WRNeg ); VitalSetupHoldCheck ( TestSignal => DB, TestSignalName => "DB", RefSignal => WRNeg, RefSignalName => "WRNeg", SetupHigh => tsetup_DB0_WRNeg, SetupLow => tsetup_DB0_WRNeg, HoldHigh => thold_DB0_WRNeg, HoldLow => thold_DB0_WRNeg, CheckEnabled => true, RefTransition => '/', HeaderMsg => InstancePath & partID, TimingData => TD_DB_WRNeg, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_DB_WRNeg ); VitalSetupHoldCheck ( TestSignal => LDACNeg, TestSignalName => "LDACNeg", RefSignal => WRNeg, RefSignalName => "WRNeg", SetupLow => tsetup_LDACNeg_WRNeg, HoldLow => thold_LDACNeg_WRNeg, CheckEnabled => true, RefTransition => '/', HeaderMsg => InstancePath & partID, TimingData => TD_LDACNeg_WRNeg, XOn => XOn, MsgOn => MsgOn, Violation => Tviol_LDACNeg_WRNeg ); VitalPeriodPulseCheck ( TestSignal => WRNeg, TestSignalName => "WRNeg", PulseWidthLow => tpw_WRNeg_negedge, HeaderMsg => InstancePath & partID, CheckEnabled => TRUE, PeriodData => PD_WRNeg, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_WRNeg ); VitalPeriodPulseCheck ( TestSignal => LDACNeg, TestSignalName => "LDACNeg", PulseWidthLow => tpw_LDACNeg_negedge, HeaderMsg => InstancePath & partID, CheckEnabled => TRUE, PeriodData => PD_LDACNeg, XOn => XOn, MsgOn => MsgOn, Violation => Pviol_LDACNeg ); Violation := Tviol_DB_WRNeg OR Tviol_A_WRNeg OR Tviol_LDACNeg_WRNeg OR Pviol_WRNeg OR Pviol_LDACNeg; ASSERT Violation = '0' REPORT InstancePath & partID & ": simulation may be" & " inaccurate due to timing violations" SEVERITY Warning; END IF; ------------------------------------------------------------------- -- Functionality Section ------------------------------------------------------------------- IF WRNeg = '0' THEN CASE to_nat(A) IS WHEN 0 => inregA := DB; WHEN 1 => inregB := DB; WHEN 2 => inregC := DB; WHEN 3 => inregD := DB; WHEN OTHERS => NULL; END CASE; END IF; IF LDACNeg = '0' THEN decregD <= inregD; decregC <= inregC; decregB <= inregB; decregA <= inregA; END IF; END PROCESS digital; -- purpose: Convert to analog value -- type : combinational -- inputs : decregA -- outputs: VOUTA DACA : PROCESS (decregA,Vref_int) VARIABLE timeout_A : time := tsettle; VARIABLE start_value : real := 0.0; -- previous shut down VARIABLE prev_SD : BOOLEAN := true; BEGIN -- PROCESS DACA start_value := VOUTA_zd; DAConvert(decregA,Vref_int,EndValA); -- this part stores previous mode of operation, shut down or -- normal,and calculate time needed for settling of output. IF prev_SD THEN prev_SD := false; timeout_A := tsdr; ELSE timeout_A := tsettle; END IF; StepA := (EndValA - start_value) / real((timeout_A)/100 ns); settleA <= '1', '0' AFTER timeout_A; END PROCESS DACA; out_A: PROCESS (update_outA, settleA) IS BEGIN -- PROCESS out_A IF settleA = '0' THEN VOUTA_zd <= EndValA; ELSE update_outA <= NOT update_outA AFTER 100 ns; IF update_outA'event THEN VOUTA_zd <= VOUTA_zd + StepA; END IF; END IF; END PROCESS out_A; DACB : PROCESS (decregB,Vref_int) VARIABLE timeout_B : time := tsettle; VARIABLE start_value : real := 0.0; -- previous shut down VARIABLE prev_SD : BOOLEAN := true; BEGIN -- PROCESS DACB start_value := VOUTB_zd; DAConvert(decregB,Vref_int,EndValB); -- this part stores previous mode of operation, shut down or -- normal,and calculate time needed for settling of output. IF prev_SD THEN prev_SD := false; timeout_B := tsdr; ELSE timeout_B := tsettle; END IF; StepB := (EndValB - start_value) / real((timeout_B)/100 ns); settleB <= '1', '0' AFTER timeout_B; END PROCESS DACB; out_B: PROCESS (update_outB, settleB) IS BEGIN -- PROCESS out_B IF settleB = '0' THEN VOUTB_zd <= EndValB; ELSE update_outB <= (NOT update_outB) AFTER 100 ns; IF update_outB'event THEN VOUTB_zd <= VOUTB_zd + StepB; END IF; END IF; END PROCESS out_B; DACC : PROCESS (decregC,Vref_int) VARIABLE timeout_C : time := tsettle; VARIABLE start_value : real := 0.0; -- previous shut down VARIABLE prev_SD : BOOLEAN := true; BEGIN -- PROCESS DACC start_value := VOUTC_zd; DAConvert(decregC,Vref_int,EndValC); -- this part stores previous mode of operation, shut down or -- normal,and calculate time needed for settling of output. IF prev_SD THEN prev_SD := false; timeout_C := tsdr; ELSE timeout_C := tsettle; END IF; StepC := (EndValC - start_value) / real((timeout_C)/100 ns); settleC <= '1', '0' AFTER timeout_C; END PROCESS DACC; out_C: PROCESS (update_outC, settleC) IS BEGIN -- PROCESS out_C IF settleC = '0' THEN VOUTC_zd <= EndValC; ELSE update_outC <= (NOT update_outC) AFTER 100 ns; IF update_outC'event THEN VOUTC_zd <= VOUTC_zd + StepC; END IF; END IF; END PROCESS out_C; DACD : PROCESS (decregD,Vref_int) VARIABLE timeout_D : time := tsettle; VARIABLE start_value : real := 0.0; -- previous shut down VARIABLE prev_SD : BOOLEAN := true; BEGIN -- PROCESS DACD start_value := VOUTD_zd; DAConvert(decregD,Vref_int,EndValD); -- this part stores previous mode of operation, shut down or -- normal,and calculate time needed for settling of output. IF prev_SD THEN prev_SD := false; timeout_D := tsdr; ELSE timeout_D := tsettle; END IF; StepD := (EndValD - start_value) / real((timeout_D)/100 ns); settleD <= '1', '0' AFTER timeout_D; END PROCESS DACD; out_D: PROCESS (update_outD, settleD) IS BEGIN -- PROCESS out_D IF settleD = '0' THEN VOUTD_zd <= EndValD; ELSE update_outD <= (NOT update_outD) AFTER 100 ns; IF update_outD'event THEN VOUTD_zd <= VOUTD_zd + StepD; END IF; END IF; END PROCESS out_D; VOUTA <= VOUTA_zd; VOUTB <= VOUTB_zd; VOUTC <= VOUTC_zd; VOUTD <= VOUTD_zd; END BLOCK; END vhdl_behavioral;