Modules in pybert package

pybert - Main PyBERT class definition, as well as some helper classes.

Bit error rate tester (BERT) simulator, written in Python.

Original Author: David Banas <capn.freako@gmail.com>

Original Date: 17 June 2014

Testing by: Mark Marlett <mark.marlett@gmail.com>

This Python script provides a GUI interface to a BERT simulator, which can be used to explore the concepts of serial communication link design.

Copyright (c) 2014 by David Banas; All rights reserved World wide.

class pybert.pybert.StoppableThread[source]

Thread class with a stop() method.

The thread itself has to check regularly for the stopped() condition.

All PyBERT thread classes are subclasses of this class.

stop()[source]

Called by thread invoker, when thread should be stopped prematurely.

stopped()[source]

Should be called by thread (i.e. - subclass) periodically and, if this function returns True, thread should clean itself up and quit ASAP.

class pybert.pybert.TxOptThread[source]

Used to run Tx tap weight optimization in its own thread, in order to preserve GUI responsiveness.

do_opt_tx(taps)[source]

Run the Tx Optimization.

run()[source]

Run the Tx equalization optimization thread.

class pybert.pybert.RxOptThread[source]

Used to run Rx tap weight optimization in its own thread, in order to preserve GUI responsiveness.

do_opt_rx(peak_mag)[source]

Run the Rx Optimization.

run()[source]

Run the Rx equalization optimization thread.

class pybert.pybert.CoOptThread[source]

Used to run co-optimization in its own thread, in order to preserve GUI responsiveness.

do_coopt(peak_mag)[source]

Run the Tx and Rx Co-Optimization.

run()[source]

Run the Tx/Rx equalization co-optimization thread.

class pybert.pybert.TxTapTuner(name='(noname)', enabled=False, min_val=0.0, max_val=0.0, value=0.0, steps=0)[source]

Object used to populate the rows of the Tx FFE tap tuning table.

class pybert.pybert.PyBERT(run_simulation=True)[source]

A serial communication link bit error rate tester (BERT) simulator with a GUI interface.

Useful for exploring the concepts of serial communication link design.

R0 = None

Channel skin effect resistance (Ohms/m).

Rdc = None

Channel d.c. resistance (Ohms/m).

Theta0 = None

Channel loss tangent (unitless).

Z0 = None

Channel characteristic impedance, in LC region (Ohms).

Zref = None

Reference (or, nominal) channel impedance.

alpha = None

CDR integral branch magnitude (unitless).

bit_errs = None

# of bit errors observed in last run.

bit_rate = None

(Gbps)

cac = None

Rx a.c. coupling capacitance (uF)

calc_chnl_h()[source]

Calculates the channel impulse response.

Also sets, in ‘self’:
  • chnl_dly:

    group delay of channel

  • start_ix:

    first element of trimmed response

  • t_ns_chnl:

    the x-values, in ns, for plotting ‘chnl_h’

  • chnl_H:

    channel frequency response

  • chnl_s:

    channel step response

  • chnl_p:

    channel pulse response

cfg_file = None

PyBERT configuration data storage file (File).

ch_file = None

Channel file name.

chnl_dly = None

Estimated channel delay (s).

chnl_valid = None

Channel file is valid.

cin = None

Rx parasitic input capacitance (pF)

coopt_thread = None

EQ co-optimization thread.

cout = None

Tx parasitic output capacitance (pF)

ctle_file = None

CTLE response file (when use_ctle_file = True).

ctle_mode = None

CTLE mode (‘Off’, ‘Passive’, ‘AGC’, ‘Manual’).

ctle_mode_tune = None

EQ optimizer CTLE mode (‘Off’, ‘Passive’, ‘AGC’, ‘Manual’).

ctle_offset = None

CTLE d.c. offset (dB)

ctle_offset_tune = None

EQ optimizer CTLE d.c. offset (dB).

data_file = None

PyBERT results data storage file (File).

debug = None

Send log messages to terminal, as well as console, when True. (Default = False)

decision_scaler = None

DFE slicer output voltage (V).

delta_t = None

CDR proportional branch magnitude (ps).

do_sweep = None

Run sweeps? (Default = False)

eye_bits = None

# of bits used to form eye. (Default = last 20%)

f_step = None

Frequency step to use when constructing H(f). (Default = 10 MHz)

gain = None

DFE error gain (unitless).

impulse_length = None

Impulse response length. (Determined automatically, when 0.)

l_ch = None

Channel length (m).

lock_sustain = None

CDR hysteresis to use in determining lock.

log(msg, alert=False, exception=None)[source]

Log a message to the console and, optionally, to terminal and/or pop-up dialog.

max_iter = None

EQ optimizer max. # of optimization iterations.

mod_type = None

0 = NRZ; 1 = Duo-binary; 2 = PAM-4

n_ave = None

DFE # of averages to take, before making tap corrections.

n_lock_ave = None

CDR # of averages to take in determining lock.

n_taps = None

DFE # of taps.

n_taps_tune = None

EQ optimizer # DFE taps.

nbits = None

Number of bits to simulate.

nspb = None

Signal vector samples per bit.

num_sweeps = None

Number of sweeps to run.

padded = None

Zero pad imported Touchstone data? (Default = False)

pattern_len = None

PRBS pattern length.

peak_freq = None

CTLE peaking frequency (GHz)

peak_freq_tune = None

EQ optimizer CTLE peaking freq. (GHz).

peak_mag = None

CTLE peaking magnitude (dB)

peak_mag_tune = None

EQ optimizer CTLE peaking mag. (dB).

pn_freq = None

Periodic noise frequency (MHz).

pn_mag = None

Periodic noise magnitude (V).

rel_lock_tol = None

CDR relative tolerance to use in determining lock.

rel_power = None

Tx power dissipation (W).

rin = None

Rx input impedance (Ohm)

rn = None

Standard deviation of Gaussian random noise (V).

rs = None

Tx source impedance (Ohms)

rx_ami_file = None

(File)

rx_ami_valid = None

(Bool)

rx_bw = None

CTLE bandwidth (GHz).

rx_bw_tune = None

EQ optimizer CTLE bandwidth (GHz).

rx_dll_file = None

(File)

rx_dll_valid = None

(Bool)

rx_has_getwave = None

(Bool)

rx_ibis_file = None

(File)

rx_ibis_valid = None

(Bool)

rx_opt_thread = None

Rx EQ optimization thread.

rx_use_ami = None

(Bool)

rx_use_getwave = None

(Bool)

rx_use_ibis = None

(Bool)

status = None

PyBERT status (String).

sum_bw = None

DFE summing node bandwidth (Used when sum_ideal=False.) (GHz).

sum_ideal = None

True = use an ideal (i.e. - infinite bandwidth) summing node (Bool).

thresh = None

Threshold for identifying periodic jitter components (sigma).

tx_ami_file = None

(File)

tx_ami_valid = None

(Bool)

tx_dll_file = None

(File)

tx_dll_valid = None

(Bool)

tx_has_getwave = None

(Bool)

tx_ibis_file = None

(File)

tx_ibis_valid = None

(Bool)

tx_opt_thread = None

Tx EQ optimization thread.

tx_tap_tuners = None

EQ optimizer list of TxTapTuner objects.

tx_taps = None

List of TxTapTuner objects.

tx_use_ami = None

(Bool)

tx_use_getwave = None

(Bool)

tx_use_ibis = None

(Bool)

use_ch_file = None

Import channel description from file? (Default = False)

use_ctle_file = None

For importing CTLE impulse/step response directly.

use_dfe = None

True = use a DFE (Bool).

use_dfe_tune = None

EQ optimizer DFE select (Bool).

v0 = None

Channel relative propagation velocity (c).

vod = None

Tx differential output voltage (V)

w0 = None

Channel transition frequency (rads./s).

windowed = None

Apply windowing to the Touchstone data? (Default = False)

pybert_cntrl - Model control logic.

Default controller definition for PyBERT class.

Original author: David Banas <capn.freako@gmail.com>

Original date: August 24, 2014 (Copied from pybert.py, as part of a major code cleanup.)

Copyright (c) 2014 David Banas; all rights reserved World wide.

pybert.pybert_cntrl.my_run_sweeps(self)[source]

Runs the simulation sweeps.

Parameters

self (PyBERT) – Reference to an instance of the PyBERT class.

pybert.pybert_cntrl.my_run_simulation(self, initial_run=False, update_plots=True)[source]

Runs the simulation.

Parameters
  • self (PyBERT) – Reference to an instance of the PyBERT class.

  • initial_run (Bool) – If True, don’t update the eye diagrams, since they haven’t been created, yet. (Optional; default = False.)

  • update_plots (Bool) – If True, update the plots, after simulation completes. This option can be used by larger scripts, which import pybert, in order to avoid graphical back-end conflicts and speed up this function’s execution time. (Optional; default = True.)

pybert.pybert_cntrl.update_results(self)[source]

Updates all plot data used by GUI.

Parameters

self (PyBERT) – Reference to an instance of the PyBERT class.

pybert.pybert_cntrl.update_eyes(self)[source]

Update the heat plots representing the eye diagrams.

Parameters

self (PyBERT) – Reference to an instance of the PyBERT class.

pybert_view - Main GUI window layout definition.

Default view definition for PyBERT class.

Original author: David Banas <capn.freako@gmail.com>

Original date: August 24, 2014 (Copied from pybert.py, as part of a major code cleanup.)

Copyright (c) 2014 David Banas; all rights reserved World wide.

class pybert.pybert_view.MyHandler[source]

This handler is instantiated by the View and handles user button clicks.

do_load_cfg(info)[source]

Read in the pickled configuration.

do_load_data(info)[source]

Read in the pickled data.’

do_run_simulation(info)[source]

Spawn a simulation thread and run with the current settings.

do_save_cfg(info)[source]

Pickle out the current configuration.

do_save_data(info)[source]

Pickle out all the generated data.

do_stop_simulation()[source]

Kill the simulation thread.

class pybert.pybert_view.RunSimThread(group=None, target=None, name=None, args=(), kwargs=None, *, daemon=None)[source]

Used to run the simulation in its own thread, in order to preserve GUI responsiveness.

run()[source]

Run the simulation(s).

pybert_util - Various utilities used by other modules.

General purpose utilities for PyBERT.

Original author: David Banas <capn.freako@gmail.com>

Original date: September 27, 2014 (Copied from pybert_cntrl.py.)

Copyright (c) 2014 David Banas; all rights reserved World wide.

pybert.pybert_util.moving_average(a, n=3)[source]

Calculates a sliding average over the input vector.

Parameters
  • a ([float]) – Input vector to be averaged.

  • n (int) – Width of averaging window, in vector samples. (Optional; default = 3.)

Returns

the moving average of the input vector, leaving the input

vector unchanged.

Return type

[float]

pybert.pybert_util.find_crossing_times(t, x, min_delay: float = 0.0, rising_first: bool = True, min_init_dev: float = 0.1, thresh: float = 0.0)[source]

Finds the threshold crossing times of the input signal.

Parameters
  • t ([float]) – Vector of sample times. Intervals do NOT need to be uniform.

  • x ([float]) – Sampled input vector.

  • min_delay (float) – Minimum delay required, before allowing crossings. (Helps avoid false crossings at beginning of signal.) (Optional; default = 0.)

  • rising_first (bool) – When True, start with the first rising edge found. (Optional; default = True.) When this option is True, the first rising edge crossing is the first crossing returned. This is the desired behavior for PyBERT, because we always initialize the bit stream with [0, 0, 1, 1], in order to provide a known synchronization point for jitter analysis.

  • min_init_dev (float) – The minimum initial deviation from zero, which must be detected, before searching for crossings. Normalized to maximum input signal magnitude. (Optional; default = 0.1.)

  • thresh (float) – Vertical crossing threshold.

Returns

Array of signal threshold crossing times.

Return type

[float]

pybert.pybert_util.find_crossings(t, x, amplitude, min_delay: float = 0.0, rising_first: bool = True, min_init_dev=0.1, mod_type=0)[source]

Finds the crossing times in a signal, according to the modulation type.

Parameters
  • t ([float]) – The times associated with each signal sample.

  • x ([float]) – The signal samples.

  • amplitude (float) – The nominal signal amplitude. (Used for determining thresholds, in the case of some modulation types.)

  • min_delay (float) – The earliest possible sample time we want returned. (Optional; default = 0.)

  • rising_first (bool) – When True, start with the first rising edge found. When this option is True, the first rising edge crossing is the first crossing returned. This is the desired behavior for PyBERT, because we always initialize the bit stream with [0, 1, 1], in order to provide a known synchronization point for jitter analysis. (Optional; default = True.)

  • min_init_dev (float) – The minimum initial deviation from zero, which must be detected, before searching for crossings. Normalized to maximum input signal magnitude. (Optional; default = 0.1.)

  • mod_type (int) – The modulation type. Allowed values are: {0: NRZ, 1: Duo-binary, 2: PAM-4} (Optional; default = 0.)

Returns

The signal threshold crossing times.

Return type

[float]

pybert.pybert_util.calc_jitter(ui, nui, pattern_len, ideal_xings, actual_xings, rel_thresh=6, num_bins=99, zero_mean=True)[source]

Calculate the jitter in a set of actual zero crossings, given the ideal crossings and unit interval.

Inputs:

  • ui : The nominal unit interval.

  • nui : The number of unit intervals spanned by the input signal.

  • pattern_len : The number of unit intervals, before input symbol stream repeats.

  • ideal_xings : The ideal zero crossing locations of the edges.

  • actual_xings : The actual zero crossing locations of the edges.

  • rel_thresh : (optional) The threshold for determining periodic jitter spectral components (sigma).

  • num_bins : (optional) The number of bins to use, when forming histograms.

  • zero_mean : (optional) Force the mean jitter to zero, when True.

Outputs:

  • jitter : The total jitter.

  • t_jitter : The times (taken from ‘ideal_xings’) corresponding to the returned jitter values.

  • isi : The peak to peak jitter due to intersymbol interference.

  • dcd : The peak to peak jitter due to duty cycle distortion.

  • pj : The peak to peak jitter due to uncorrelated periodic sources.

  • rj : The standard deviation of the jitter due to uncorrelated unbounded random sources.

  • tie_ind : The data independent jitter.

  • thresh : Threshold for determining periodic components.

  • jitter_spectrum : The spectral magnitude of the total jitter.

  • tie_ind_spectrum : The spectral magnitude of the data independent jitter.

  • spectrum_freqs : The frequencies corresponding to the spectrum components.

  • hist : The histogram of the actual jitter.

  • hist_synth : The histogram of the extrapolated jitter.

  • bin_centers : The bin center values for both histograms.

pybert.pybert_util.make_uniform(t, jitter, ui, nbits)[source]

Make the jitter vector uniformly sampled in time, by zero-filling where necessary.

The trick, here, is creating a uniformly sampled input vector for the FFT operation, since the jitter samples are almost certainly not uniformly sampled. We do this by simply zero padding the missing samples.

Inputs:

  • t : The sample times for the ‘jitter’ vector.

  • jitter : The input jitter samples.

  • ui : The nominal unit interval.

  • nbits : The desired number of unit intervals, in the time domain.

Output:

  • y : The uniformly sampled, zero padded jitter vector.

  • y_ix : The indices where y is valid (i.e. - not zero padded).

pybert.pybert_util.calc_gamma(R0, w0, Rdc, Z0, v0, Theta0, ws)[source]

Calculates propagation constant from cross-sectional parameters.

The formula’s applied are taken from Howard Johnson’s “Metallic Transmission Model” (See “High Speed Signal Propagation”, Sec. 3.1.)

Inputs:
  • R0 skin effect resistance (Ohms/m)

  • w0 cross-over freq.

  • Rdc d.c. resistance (Ohms/m)

  • Z0 characteristic impedance in LC region (Ohms)

  • v0 propagation velocity (m/s)

  • Theta0 loss tangent

  • ws frequency sample points vector

Outputs:
  • gamma frequency dependent propagation constant

  • Zc frequency dependent characteristic impedance

pybert.pybert_util.calc_G(H, Rs, Cs, Zc, RL, Cp, CL, ws)[source]

Calculates fully loaded transfer function of complete channel.

Inputs:
  • H unloaded transfer function of interconnect

  • Rs source series resistance

  • Cs source parallel (parasitic) capacitance

  • Zc frequency dependent characteristic impedance of the interconnect

  • RL load resistance (differential)

  • Cp load parallel (parasitic) capacitance (single ended)

  • CL load series (d.c. blocking) capacitance (single ended)

  • ws frequency sample points vector

Outputs:
  • G frequency dependent transfer function of channel

pybert.pybert_util.calc_eye(ui, samps_per_ui, height, ys, y_max, clock_times=None)[source]

Calculates the “eye” diagram of the input signal vector.

Parameters
  • ui (float) – unit interval (s)

  • samps_per_ui (int) – # of samples per unit interval

  • height (int) – height of output image data array

  • ys ([float]) – signal vector of interest

  • y_max (float) – max. +/- vertical extremity of plot

Keyword Arguments

clock_times ([float]) – (optional) vector of clock times to use for eye centers. If not provided, just use mean zero-crossing and assume constant UI and no phase jumps. (This allows the same function to be used for eye diagram creation, for both pre and post-CDR signals.)

Returns

The “heat map” representing the eye diagram. Each grid

location contains a value indicating the number of times the signal passed through that location.

Return type

2D NumPy array

pybert.pybert_util.make_ctle(rx_bw, peak_freq, peak_mag, w, mode='Passive', dc_offset=0)[source]

Generate the frequency response of a continuous time linear equalizer (CTLE), given the:

  • signal path bandwidth,

  • peaking specification

  • list of frequencies of interest, and

  • operational mode/offset.

We use the ‘invres()’ function from scipy.signal, as it suggests itself as a natural approach, given our chosen use model of having the user provide the peaking frequency and degree of peaking.

That is, we define our desired frequency response using one zero and two poles, where:

  • The pole locations are equal to:
    • the signal path natural bandwidth, and

    • the user specified peaking frequency.

  • The zero location is chosen, so as to provide the desired degree of peaking.

Inputs:

  • rx_bw The natural (or, unequalized) signal path bandwidth (Hz).

  • peak_freq The location of the desired peak in the frequency

    response (Hz).

  • peak_mag The desired relative magnitude of the peak (dB). (mag(H(0)) = 1)

  • w The list of frequencies of interest (rads./s).

  • mode The operational mode; must be one of:
    • ‘Off’ : CTLE is disengaged.

    • ‘Passive’: Maximum frequency response has magnitude one.

    • ‘AGC’ : Automatic gain control. (Handled by calling routine.)

    • ‘Manual’ : D.C. offset is set manually.

  • dc_offset The d.c. offset of the CTLE gain curve (dB).

    (Only valid, when ‘mode’ = ‘Manual’.)

Outputs:

  • w, H The resultant complex frequency response, at the

    given frequencies.

pybert.pybert_util.trim_impulse(g, min_len=0, max_len=1000000)[source]
Trim impulse response, for more useful display, by:
  • clipping off the tail, after 99.8% of the total power has been captured (Using 99.9% was causing problems; I don’t know why.), and

  • setting the “front porch” length equal to 20% of the total length.

Inputs:

  • g impulse response

  • min_len (optional) minimum length of returned vector

  • max_len (optional) maximum length of returned vector

Outputs:

  • g_trim trimmed impulse response

  • start_ix index of first returned sample

pybert.pybert_util.import_channel(filename, sample_per, padded=False, windowed=False)[source]

Read in a channel file.

Parameters
  • filename (str) – Name of file from which to import channel description.

  • sample_per (float) – Sample period of signal vector (s).

  • padded (Bool) – (Optional) Zero pad s4p data, such that fmax >= 1/(2*sample_per)? (Default = False)

  • windowed (Bool) – (Optional) Window s4p data, before converting to time domain? (Default = False)

Returns

Imported channel impulse, or step, response.

Return type

[float]

pybert.pybert_util.interp_time(ts, xs, sample_per)[source]

Resample time domain data, using linear interpolation.

Parameters
  • ts ([float]) – Original time values.

  • xs ([float]) – Original signal values.

  • sample_per (float) – System sample period.

Returns

Resampled waveform.

Return type

[float]

pybert.pybert_util.import_time(filename, sample_per)[source]

Read in a time domain waveform file, resampling as appropriate, via linear interpolation.

Parameters
  • filename (str) – Name of waveform file to read in.

  • sample_per (float) – New sample interval

Returns

Resampled waveform.

Return type

[float]

pybert.pybert_util.sdd_21(ntwk)[source]

Given a 4-port single-ended network, return its differential throughput.

Parameters

ntwk (skrf.Network) – 4-port single ended network.

Returns

Sdd[2,1].

Return type

[float]

pybert.pybert_util.import_freq(filename, sample_per, padded=False, windowed=False, f_step=10000000.0)[source]

Read in a single ended 4-port Touchstone file, and extract the differential throughput step response, resampling as appropriate, via linear interpolation.

Parameters
  • filename (str) – Name of Touchstone file to read in.

  • sample_per (float) – New sample interval

  • padded (Bool) – (Optional) Zero pad s4p data, such that fmax >= 1/(2*sample_per)? (Default = False)

  • windowed (Bool) – (Optional) Window s4p data, before converting to time domain? (Default = False)

Returns

Resampled step response waveform.

Return type

[float]

pybert.pybert_util.lfsr_bits(taps, seed)[source]

Given a set of tap indices and a seed, generate a PRBS.

Parameters
  • taps ([int]) – The set of fed back taps. (Largest determines order of generator.)

  • seed (int) – The initial value of the shift register.

Returns

A PRBS generator object with a next() method, for retrieving

the next bit in the sequence.

Return type

generator

pybert.pybert_util.safe_log10(x)[source]

Guards against pesky ‘Divide by 0’ error messages.

pybert.pybert_util.pulse_center(p, nspui)[source]

Determines the center of the pulse response, using the “Hula Hoop” algorithm (See SiSoft/Tellian’s DesignCon 2016 paper.)

Parameters
  • p ([Float]) – The single bit pulse response.

  • nspui (Int) – The number of vector elements per unit interval.

Returns

The estimated index at which the clock will

sample the main lobe, and the vertical threshold at which the main lobe is UI wide.

Return type

(Int, float)

pybert_plot - Plot definitions for the PyBERT GUI.

Plot definitions for PyBERT class.

Original author: David Banas <capn.freako@gmail.com>

Original date: February 21, 2015 (Copied from pybert.py, as part of a major code cleanup.)

Copyright (c) 2015 David Banas; all rights reserved World wide.

pybert_help - Contents of the Help tab of the PyBERT GUI.

User instructions for PyBERT class.

Original author: David Banas <capn.freako@gmail.com>

Original date: April 15, 2015 (Copied from pybert.py.)

Copyright (c) 2015 David Banas; all rights reserved World wide.

pybert_cfg - Data structure for saving PyBERT configuration.

Simulation configuration data encapsulation, for PyBERT.

Original Author: David Banas <capn.freako@gmail.com>

Original Date: 5 May 2017

This Python script provides a data structure for encapsulating the simulation configuration data of a PyBERT instance. It was first created, as a way to facilitate easier pickling, so that a particular configuration could be saved and later restored.

Copyright (c) 2017 by David Banas; All rights reserved World wide.

class pybert.pybert_cfg.PyBertCfg(the_PyBERT)[source]

PyBERT simulation configuration data encapsulation class.

This class is used to encapsulate that subset of the configuration data for a PyBERT instance, which is to be saved when the user clicks the “Save Config.” button.

pybert_data - Data structure for saving PyBERT results.

Simulation results data encapsulation, for PyBERT.

Original Author: David Banas <capn.freako@gmail.com>

Original Date: 9 May 2017

This Python script provides a data structure for encapsulating the simulation results data of a PyBERT instance. It was first created, as a way to facilitate easier pickling, so that a particular result could be saved and later restored, as a reference waveform.

Copyright (c) 2017 by David Banas; All rights reserved World wide.

class pybert.pybert_data.PyBertData(the_PyBERT)[source]

PyBERT simulation results data encapsulation class.

This class is used to encapsulate that subset of the results data for a PyBERT instance, which is to be saved when the user clicks the “Save Results” button.

dfe - DFE behavioral model.

Behavioral model of a decision feedback equalizer (DFE).

Original Author: David Banas <capn.freako@gmail.com>

Original Date: 17 June 2014

This Python script provides a behavioral model of a decision feedback equalizer (DFE). The class defined, here, is intended for integration into the larger PyBERT framework.

Copyright (c) 2014 by David Banas; All rights reserved World wide.

class pybert.dfe.LfilterSS(b, a)[source]

A single steppable version of scipy.signal.lfilter().

step(x)[source]

Step the filter.

Parameters

x (float) – Next input value.

Returns

Next output value.

Return type

(float)

class pybert.dfe.DFE(n_taps, gain, delta_t, alpha, ui, n_spb, decision_scaler, mod_type=0, bandwidth=100000000000.0, n_ave=10, n_lock_ave=500, rel_lock_tol=0.01, lock_sustain=500, ideal=True)[source]

Behavioral model of a decision feedback equalizer (DFE).

decide(x)[source]

Make the bit decisions, according to modulation type.

Parameters

x (float) – The signal value, at the decision time.

Returns

The members of the returned tuple are:

decision:

One of:

  • {-1, 1} (NRZ)

  • {-1, 0, +1} (Duo-binary)

  • {-1, -1/3, +1/3, +1} (PAM-4)

according to what the ideal signal level should have been. (‘decision_scaler’ normalized)

bits: The list of bits recovered.

Return type

tuple(float, [int])

Raises

RuntimeError – If the requested modulation type is unknown.

run(sample_times, signal)[source]

Run the DFE on the input signal.

Parameters
  • sample_times ([float]) – Vector of time values at wich corresponding signal values were sampled.

  • signal ([float]) – Vector of sampled signal values.

Returns

The members of the returned tuple, in order, are:

res([float]):

Samples of the summing node output, taken at the times given in sample_times.

tap_weights([[float]]):

List of list of tap weights showing how the DFE adapted over time.

ui_ests([float]):

List of unit interval estimates, showing how the CDR adapted.

clocks([int]):

List of mostly zeros with ones at the recovered clocking instants. Useful for overlaying the clock times on signal waveforms, in plots.

lockeds([bool]):

List of Booleans indicating state of CDR lock.

clock_times([float]):

List of clocking instants, as recovered by the CDR.

bits([int]):

List of recovered bits.

Return type

tuple(([float], [[float]], [float], [int], [bool], [float], [int]))

Raises

RuntimeError – If the requested modulation type is unknown.

step(decision, error, update)[source]

Step the DFE, according to the new decision and error inputs.

Parameters
  • decision (float) – Current slicer output.

  • error (float) – Difference between summing node and slicer outputs.

  • update (bool) – If true, update tap weights.

Returns

New backward filter output value.

Return type

res(float)

cdr - CDR behavioral model.

Behavioral model of a “bang-bang” clock data recovery (CDR) unit.

Original Author: David Banas <capn.freako@gmail.com>

Original Date: 17 June 2014

This Python script provides a behavioral model of a “bang-bang” clock data recovery (CDR) unit. The class defined, here, is intended for integration into the larger PyBERT framework.

Copyright (c) 2019 by David Banas; All rights reserved World wide.

class pybert.cdr.CDR(delta_t: float, alpha: float, ui: float, n_lock_ave: int = 500, rel_lock_tol: float = 0.01, lock_sustain: int = 500)[source]

A class providing behavioral modeling of a ‘bang- bang’ clock data recovery (CDR) unit.

adapt(samples: Sequence[float]) → Tuple[float, bool][source]

Adapt period/phase, according to 3 samples.

Should be called, when the clock has just struck.

Synopsis:

(ui, locked) = adapt(samples)

Parameters

samples

A list of 3 samples of the input waveform, as follows:

  • at the last clock time

  • at the last unit interval boundary time

  • at the current clock time

Returns

The new unit interval estimate, in seconds, and

a flag indicating ‘locked’ status.

Return type

(float, bool)

property locked

The current locked state.

property ui

The current unit interval estimate.