In [1]:
%pylab inline
Populating the interactive namespace from numpy and matplotlib
In [2]:
from __future__ import print_function
from deltasigma import *
from IPython.core.display import Image
In [3]:
# skip this, this is just to display nice tables.
from itertools import izip_longest
class Table(list):
    def _repr_html_(self):
        html = ["<table>"]
        for row in self:
            html.append("<tr>")
            for col in row:
                try:
                    float(col)
                    html.append("<td>%.6f</td>" % col)
                except(ValueError):
                    html.append("<td><b>%s</b></td>" % col)
            html.append("</tr>")
        html.append("</table>")
        return ''.join(html)

Modulator realization and dynamic range scaling - # demo3

In this ipython notebook, the following is demonstrated:

  • A 5th order delta sigma modulator is synthesized, with optimized zeros and an OSR equal to 42.

  • We then convert the synthesized NTF into a, g, b, c coefficients for the CRFB modulator structure.

  • The maxima for each state are evaluated.

  • The ABCD matrix is scaled so that the state maxima are less than the specified limit.

  • The state maxima are re-evaluated and limit compliance is checked.

NOTE: This is an ipython port of dsdemo3.m, from the MATLAB Delta Sigma Toolbox, written by Richard Schreier.

Delta sigma modulator synthesis

In [4]:
order = 5
R = 42
opt = 1
H = synthesizeNTF(order, R, opt)

Let's inspect the NTF, printing out the transfer function and plotting poles and zeros with respect to the unit circle.

In [5]:
print(pretty_lti(H))
        (z^2 - 1.995z + 1) (z^2 - 1.998z + 1) (z - 1)         
--------------------------------------------------------------
 (z^2 - 1.614z + 0.6657) (z^2 - 1.797z + 0.8552) (z - 0.7783) 
In [6]:
figure(figsize=(10, 5))
plotPZ(H, showlist=True)
title('NTF');

Evaluation of the coefficients for a CRFB topology

The CRFB topology is depicted in the following diagram.

In [7]:
Image(url='http://python-deltasigma.readthedocs.org/en/latest/_images/CRFB.png', retina=True)
Out[7]:

Since the modulator order is 5, we're interested in the topology for odd order modulators.

Unscaled modulator

Calculate the coefficients

In [8]:
a, g, b, c = realizeNTF(H)

Feed-in selection

We'll use a single feed-in for the input, to have a maximally flat STF.

This means setting $\ b_n = 0, \ \forall n > 1$.

In [9]:
b = np.concatenate((b[0].reshape((1, )), np.zeros((b.shape[0] - 1, ))), axis=0)
In [10]:
t = Table()
ilabels = ['#1', '#2', '#3', '#4', '#5', '#6']
t.append(['Coefficients', 'DAC feedback', 'Resonator feedback', 
          'Feed-in', 'Interstage'])
t.append(['', 'a(n)', 'g(n)', ' b(n)', ' c(n)'])
[t.append(x) for x in izip_longest(ilabels, a.tolist(), g.tolist(), b.tolist(), c.tolist(), fillvalue="")]
t
Out[10]:
CoefficientsDAC feedbackResonator feedbackFeed-inInterstage
a(n)g(n) b(n) c(n)
#10.0006670.0016220.0006671.000000
#20.0085830.0045930.0000001.000000
#30.0552010.0000001.000000
#40.2476070.0000001.000000
#50.5569350.0000001.000000
#60.000000

Calculate the state maxima

In [11]:
ABCD = stuffABCD(a, g, b, c);
u = np.linspace(0, 0.6, 30);
N = 1e4; 
T = np.ones((1, N))
maxima = np.zeros((order, len(u)))
for i in range(len(u)):
    ui = u[i]
    v, xn, xmax, _ = simulateDSM(ui*T, ABCD);
    maxima[:, i] = np.squeeze(xmax)
    if any(xmax > 1e2):
        umax = ui;
        u = u[:i];
        maxima = maxima[:, :i]
        break;
# save the maxima
prescale_maxima = np.copy(maxima)
print('The state maxima have been evaluated through simulation.')
The state maxima have been evaluated through simulation.

Plot of the state maxima

In [12]:
for i in range(order):
    semilogy(u, maxima[i, :], 'o-', label=('State %d' % (i+1)))
    if not i:
        hold(True)
grid(True)
title('State Maxima'); ylabel('Peak value'); xlabel('DC input')
xlim([0, 0.6]); ylim([1e-6, 10]);
legend(loc=4);

Scaled modulator

Calculate the scaled coefficients

In [13]:
ABCDs, umax, _ = scaleABCD(ABCD, N_sim=1e5)
as_, gs, bs, cs = mapABCD(ABCDs)
print('\nScaled modulator, umax = %.2f\n' % umax)
Scaled modulator, umax = 0.58

In [14]:
t = Table()
ilabels = ['#1', '#2', '#3', '#4', '#5', '#6']
t.append(['Coefficients', 'DAC feedback', 'Resonator feedback', 
          'Feed-in', 'Interstage'])
t.append(['', 'a(n)', 'g(n)', ' b(n)', ' c(n)'])
[t.append(x) for x in izip_longest(ilabels, as_.tolist(), gs.tolist(), bs.tolist(), cs.tolist(), fillvalue="")]
t
Out[14]:
CoefficientsDAC feedbackResonator feedbackFeed-inInterstage
a(n)g(n) b(n) c(n)
#10.1002980.0085080.1002980.135347
#20.1746560.0108170.0000000.190649
#30.2141650.0000000.380271
#40.3653040.0000000.424567
#50.3488520.0000001.596478
#60.000000

Calculate the state maxima

In [15]:
u = np.linspace(0, umax, 30)
N = 1e4
T = np.ones((N,))
maxima = np.zeros((order, len(u)))
for i in range(len(u)):
    ui = u[i]
    v, xn, xmax, _ = simulateDSM(ui*T, ABCDs)
    maxima[:, i] = xmax.squeeze()
    if any(xmax > 1e2):
        umax = ui;
        u = u[:i]
        maxima = maxima[:, :i]
        break
print('The state maxima have been re-evaluated through simulation.')
print("The maximum input was found to be %.6f" % umax)
The state maxima have been re-evaluated through simulation.
The maximum input was found to be 0.583333

Plot of the state maxima after scaling

In [16]:
for i in range(order):
    semilogy(u, maxima[i, :], 'o-', label=('State %d' % (i+1)))
    if not i:
        hold(True)
grid(True)
title('State Maxima'); ylabel('Peak value'); xlabel('DC input')
xlim([0, 0.6]); ylim([6e-2, 1.2]);
legend(loc=4);

System version information

In [17]:
#%install_ext http://raw.github.com/jrjohansson/version_information/master/version_information.py
%load_ext version_information
%reload_ext version_information

%version_information numpy, scipy, matplotlib, deltasigma
Out[17]:
SoftwareVersion
Python2.7.10 64bit [GCC 4.2.1 (Apple Inc. build 5577)]
IPython3.2.1
OSDarwin 14.4.0 x86_64 i386 64bit
numpy1.9.2
scipy0.16.0
matplotlib1.4.3
deltasigma0.2.2
Fri Aug 07 16:19:23 2015 CEST