------------------------------------------------------------------------------- -- Copyright (c) 2003 Mentor Graphics Corporation -- -- This model is a component of the Mentor Graphics VHDL-AMS educational open -- source model library, and is covered by this license agreement. This model, -- including any updates, modifications, revisions, copies, and documentation -- are copyrighted works of Mentor Graphics. USE OF THIS MODEL INDICATES YOUR -- COMPLETE AND UNCONDITIONAL ACCEPTANCE OF THE TERMS AND CONDITIONS SET FORTH -- IN THIS LICENSE AGREEMENT. Mentor Graphics grants you a non-exclusive -- license to use, reproduce, modify and distribute this model, provided that: -- (a) no fee or other consideration is charged for any distribution except -- compilations distributed in accordance with Section (d) of this license -- agreement; (b) the comment text embedded in this model is included verbatim -- in each copy of this model made or distributed by you, whether or not such -- version is modified; (c) any modified version must include a conspicuous -- notice that this model has been modified and the date of modification; and -- (d) any compilations sold by you that include this model must include a -- conspicuous notice that this model is available from Mentor Graphics in its -- original form at no charge. -- -- THIS MODEL IS LICENSED TO YOU "AS IS" AND WITH NO WARRANTIES, EXPRESS OR -- IMPLIED. MENTOR GRAPHICS SPECIFICALLY DISCLAIMS ALL IMPLIED WARRANTIES OF -- MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. MENTOR GRAPHICS SHALL -- HAVE NO RESPONSIBILITY FOR ANY DAMAGES WHATSOEVER. ------------------------------------------------------------------------------- -- File : driver_cml_pe.vhd -- Author : Mentor Graphics -- Created : 2003-05-30 -- Last update: ------------------------------------------------------------------------------- -- Description: Complete Behavioral Model of a Differential CML Driver with -- Pre-Emphasis. Has an internal clock with jitter, so only the -- data stream is input to the model. Pre-emphasis is on the first bit -- after a transition. The pre-emphasis level is set with a generic. -- Note: If two or more of these drivers are used in a circuit, user -- must assign different "seed" values to have independent jitter behavior. ------------------------------------------------------------------------------- -- Revisions : -- Date Version Author Description -- 2003-05-30 1.0 Mentor Graphics Created ------------------------------------------------------------------------------- library IEEE; use IEEE.math_real.all; use IEEE.std_logic_1164.all; use IEEE.electrical_systems.all; entity driver_cml_pe is generic (icml_base : current := 20.0e-3; -- Base CML current level ipe : current := 20.0e-3; -- Pre-emphasis peak current (above icml_base) trans_time : real := 10.0e-12; -- Transition time of current switching R_cml_out : resistance := 50.0; -- CML output resistance period : time := 100 ps; -- Period of built-in clock init_delay : time := 10 ps; -- Initial delay to first clock rising edge seed1_init : positive := 53; -- Initial value of seed1. (1 <= seed1_init <= 2147483562) seed2_init : positive := 632; -- Initial value of seed2. (1 <= seed2_init <= 2147483562) jitter_max : real := 5.0e-12); -- Maximum (peak) value of clock jitter port (d_data : in std_logic; -- Input digital data terminal v_drv_p : electrical; -- CML differential output (positive "p" and negative "n") terminal v_drv_n : electrical; terminal v_vcc : electrical; -- CML references, VCC and Ground terminal a_gnd : electrical); end driver_cml_pe; architecture behavioral of driver_cml_pe is signal d_clk : std_logic := '0'; signal d_base, d_pe : std_logic := '0'; quantity i_p through v_drv_p to a_gnd; quantity i_n through v_drv_n to a_gnd; signal k_p, k_n : real := 0.0; quantity vcml_p across icml_p through v_vcc to v_drv_p; quantity vcml_n across icml_n through v_vcc to v_drv_n; TYPE program_logic_state IS (strong1, weak1, strong0, weak0); SIGNAL active_drive_state, next_drive_state : program_logic_state := weak0; signal clk_tick : std_logic := '0'; -- toggles on every '0' to '1' transition of d_clk constant jitter_max_time : time := integer(jitter_max * 1.0e15) * 1 fs; begin CreateClock: process variable out_variable : std_logic; variable seed1 : positive := seed1_init; variable seed2 : positive := seed2_init; variable scale_jit_0_1 : real := 0.5; -- Random number, jitter scale factor [0 to 1] variable jitter_real : real := 0.0; -- Jitter offset of next edge (real, 0 -> 2.0*jitter_max) variable jitter_time : time := 0.0 ps; -- Jitter offset of next edge (time equivalent of jitter_real) begin d_clk <= '0'; wait until domain = time_domain; wait for init_delay; out_variable := '1'; d_clk <= out_variable; clk_loop : loop -- Note: Can't have negative jitter delay, so must stop short of max jitter window wait for (period/2.0 - jitter_max_time); uniform(seed1, seed2, scale_jit_0_1); jitter_real := 2.0*jitter_max*scale_jit_0_1; jitter_time := integer(jitter_real * 1.0e15) * 1 fs; out_variable := not out_variable; d_clk <= out_variable after jitter_time; wait for (jitter_max_time); end loop clk_loop; end process CreateClock; set_next_state: PROCESS (d_data, clk_tick) BEGIN CASE active_drive_state IS WHEN strong1 => IF ((d_data = '0')) THEN next_drive_state <= strong0; ELSIF ((d_data = '1')) THEN next_drive_state <= weak1; ELSE -- Invalid input, stay in current state next_drive_state <= strong1; END IF; WHEN weak1 => IF (d_data = '0') THEN next_drive_state <= strong0; ELSE next_drive_state <= weak1; END IF; WHEN strong0 => IF ((d_data = '1')) THEN next_drive_state <= strong1; ELSIF ((d_data = '0')) THEN next_drive_state <= weak0; ELSE -- Invalid input, stay in current state next_drive_state <= strong0; END IF; WHEN weak0 => IF (d_data = '1') THEN next_drive_state <= strong1; ELSE next_drive_state <= weak0; END IF; END CASE; END PROCESS set_next_state; update_outputs: PROCESS (active_drive_state) BEGIN CASE active_drive_state IS WHEN strong1 => d_base <= ('1'); d_pe <= ('1'); WHEN weak1 => d_base <= ('1'); d_pe <= ('0'); WHEN strong0 => d_base <= ('0'); d_pe <= ('1'); WHEN weak0 => d_base <= ('0'); d_pe <= ('0'); END CASE; END PROCESS update_outputs; sync: PROCESS (d_clk) BEGIN IF (d_clk='1') THEN active_drive_state <= next_drive_state; clk_tick <= not clk_tick; END IF; END PROCESS sync; -- Set i_p and i_n sink currents as fraction or multiple of icml_base (k_p and k_n) PE_logic : process (d_base, d_pe) is begin if d_base = '1' and d_pe = '1' then k_p <= 0.0; k_n <= 1.0 + ipe/icml_base; elsif d_base = '1' and d_pe = '0' then k_p <= 0.0; k_n <= 1.0; elsif d_base = '0' and d_pe = '1' then k_p <= 1.0 + ipe/icml_base; k_n <= 0.0; else k_p <= 1.0; k_n <= 0.0; end if; end process PE_logic; -- Solve for sink currents and CML currents i_p == k_p'ramp(trans_time, trans_time)*icml_base; i_n == k_n'ramp(trans_time, trans_time)*icml_base; icml_p * R_cml_out == vcml_p; icml_n * R_cml_out == vcml_n; end behavioral; ------------------------------------------------------------------------------- -- Copyright (c) 2003 Mentor Graphics Corporation -------------------------------------------------------------------------------