Compare commits

...

10 commits

Author SHA1 Message Date
Stephan I. Böttcher
9fc251fcdb add .gitignore, pdf output 2025-02-03 08:42:04 +01:00
stephan
f96019aec4 doc: late add image
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/instrumentation@9236 bc5caf13-1734-44f8-af43-603852e9ee25
2025-02-03 07:39:18 +00:00
stephan
928da9be7f doc: rename beamer style
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/instrumentation@9235 bc5caf13-1734-44f8-af43-603852e9ee25
2025-02-03 07:28:48 +00:00
stephan
af6241f6e4 frontend.v block diagram
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/instrumentation@1729 bc5caf13-1734-44f8-af43-603852e9ee25
2013-06-05 18:43:08 +00:00
stephan
211f7937b2 frontend block diagram
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/instrumentation@1716 bc5caf13-1734-44f8-af43-603852e9ee25
2013-05-28 21:31:50 +00:00
stephan
e978abbb51 DIRENA
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/instrumentation@1680 bc5caf13-1734-44f8-af43-603852e9ee25
2013-05-15 20:11:01 +00:00
stephan
5c19e50aea Verilog chapter
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/instrumentation@1628 bc5caf13-1734-44f8-af43-603852e9ee25
2013-04-27 22:45:00 +00:00
stephan
1a4e33dec6 FPGA section, unfinished
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/instrumentation@1626 bc5caf13-1734-44f8-af43-603852e9ee25
2013-04-24 21:47:06 +00:00
stephan
6d9d6f48be the shaper transfer function
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/instrumentation@1614 bc5caf13-1734-44f8-af43-603852e9ee25
2013-04-21 13:27:38 +00:00
stephan
9b17647040 fix shaper transfer function
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/instrumentation@1610 bc5caf13-1734-44f8-af43-603852e9ee25
2013-04-17 21:32:43 +00:00
28 changed files with 4311 additions and 4 deletions

7
.gitignore vendored Normal file
View file

@ -0,0 +1,7 @@
*.aux
*.log
*.nav
*.out
*.snm
*.toc

BIN
100px-AND_ANSI.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 724 B

BIN
100px-NOT_ANSI.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 789 B

BIN
100px-OR_ANSI.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 969 B

BIN
100px-XOR_ANSI.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
125px-Logic-gate-inv-de.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
125px-Logic-gate-or-de.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
7400.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
Logic-gate-and-de.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
TTL_npn_nand.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

16
counter.v Normal file
View file

@ -0,0 +1,16 @@
module counter #(parameter N=8, TC=100)
( input clk,
input reset,
input enable,
output [N-1:0] q
);
reg [N-1:0] c;
always @(posedge clk)
if (reset)
c <= 0;
else if (enable & c < TC)
c <= c + 1;
assign q = c;
endmodule

BIN
frontend-dia.pdf Normal file

Binary file not shown.

3533
frontend.dia Normal file

File diff suppressed because it is too large Load diff

BIN
irena.pdf Normal file

Binary file not shown.

359
irena.tex
View file

@ -1,7 +1,7 @@
\errorcontextlines=10
\documentclass{beamer}
\mode<presentation>{\usetheme[compress]{LEC}}
\mode<presentation>{\usetheme[compress]{SWRI}}
\usepackage[utf8]{inputenc}
\usepackage{graphics}
@ -271,10 +271,12 @@
\begin{frame}[t]
\imageat{0.05}{0.1}{0.9}{preamp-shaper-filter}
\begin{mpat}{0.1}{0.45}{0.9}
$\tau=R_1C_1=R_2C_2, \quad \tau_\CSA = R_rC_r = R_0C_1, \quad
\tau_\PZC = C_0R_0, \quad \tau_\FIL = R_fC_f $\\[1ex]
$H_\CSA = \frac{1}{C_r}\,\frac{\tau_\CSA}{1+s\tau_\CSA},
\qquad \qquad
H_\FSH = \frac{a\tau}{\tau_\PZC}\,\frac{1+s\tau_\PZC}{(1+s\tau)^2},
\qquad \qquad
\qquad
H_\FSH = \frac{as\tau\tau_\PZC}{\tau_\CSA}\,\frac{1+s\tau_\CSA}{(1+s\tau)^2(1+s\tau_\PZC)},
\qquad
H_\FIL = \frac{1}{1+s\tau_\FIL} $ \\
$H(s) = H_\CSA(s) H_\FSH(s) H_\FIL(s) =
@ -355,6 +357,7 @@
\begin{itemize}
\item Resolution, number of output bits.
\item Sample rate.
\item Input range and format.
\item Input multiplexer, track and hold.
\item Output format, serial/parallel.
\item Supply voltage, power consumption.
@ -398,4 +401,352 @@
\end{itemize}
\end{frame}
\section{FPGA}
\subsection{Field Programmable Gate Arrays}
\begin{frame}
\begin{itemize}
\item Notations
\item Boolean algebra
\item Signaling: TTL, CMOS, LVDS, PECL
\item Logic gate yechnology: TTL, CMOS
\item flip-flops
\item Counter: ripple, synchronous
\item Karnaugh-Veitch (KV) diagrams
\item FPGA logic cell
\end{itemize}
\end{frame}
\def\AND{{\cdot}}
\def\OR{{+}}
\newbox\Bbox
\def\NOT#1{%
\setbox\Bbox\hbox{b}%
\setbox\Bbox\hbox{\vrule height \ht\Bbox depth 0pt width 0pt}%
\overline{\relax\box\Bbox #1}}
\subsection{Logic Notations}
\def\gate#1{\resizebox{1cm}{!}{\includegraphics{#1}}}
\begin{frame}
\begin{tabular}[c]{l|c|c|c|c|c|c}
Math & false & true & $\lnot a$ & $a \wedge b$ & $a \vee b$ &
$a\neq b$ \\[1ex]
& 0 & 1 & $\overline{a}$ & $a \cdot b$ & $a+b$ & \\[1ex]
Python & False & True & not & and & or & \\[1ex]
C & 0 & 1 & ! & \&\& & \textbar\textbar & \\[1ex]
C bitwise & 0 & -1 & \~{} & \& & \textbar & \^{} \\[1ex]
ANSI & L & H &
\gate{100px-NOT_ANSI} &
\gate{100px-AND_ANSI} &
\gate{100px-OR_ANSI} &
\gate{100px-XOR_ANSI} \\[1ex]
DIN & L & H &
\gate{125px-Logic-gate-inv-de} &
\gate{Logic-gate-and-de} &
\gate{125px-Logic-gate-or-de} &
\gate{125px-Logic-gate-xor-de-2} \\
Table & & &
\tiny
\begin{tabular}[t]{c|c}
A & Q \\
\hline
0 & 1 \\
1 & 0
\end{tabular} &
\tiny
\begin{tabular}[t]{c@{\,}c|c}
A & B & Q \\
\hline
0 & 0 & 0 \\
0 & 1 & 0 \\
1 & 0 & 0 \\
1 & 1 & 1 \\
\end{tabular} &
\tiny
\begin{tabular}[t]{c@{\,}c|c}
A & B & Q \\
\hline
0 & 0 & 0 \\
0 & 1 & 1 \\
1 & 0 & 1 \\
1 & 1 & 1 \\
\end{tabular} &
\tiny
\begin{tabular}[t]{c@{\,}c|c}
A & B & Q \\
\hline
0 & 0 & 0 \\
0 & 1 & 1 \\
1 & 0 & 1 \\
1 & 1 & 0 \\
\end{tabular}
\end{tabular}
\end{frame}
\subsection{Boolean Algebra}
\begin{frame}
\begin{tabular}{lcc}
Commutativity & $a \AND b = b \AND a $
& $a \OR b = b \OR a $
\\
Associativity & $a \AND ( b \AND c) = (a \AND b)\AND c$
& $a \OR (b\OR c) = (a \OR b) \OR c$
\\
Distributivity & $a \AND (b \OR c) = (a\AND b) \OR (a\AND c)$
& $a \OR (b \AND c) = (a \OR b) \AND (a \OR c)$
\\
Identity & $a \AND 1 = a$ & $a \OR 0 = a$ \\
Annihilation & $a \AND 0 = 0$ & $a \OR 1 = 1$ \\
Idempotence & $a \AND a = a$ & $a \OR a = a$ \\
Absorption & $ a \AND (a \OR b) = a$ & $a \OR (a \AND b) = a$ \\
Complementation & $a \AND \NOT a = 0$ & $a \OR \NOT a = 1$ \\
Double negation & \multicolumn{2}{c}{$ \NOT{\NOT{a}} = a$}
\\
De Morgan & $\NOT a \AND \NOT b = \NOT{a \OR b}$
& $\NOT a \OR \NOT b = \NOT{a \AND b}$ \\
Duality & $\NOT 1 = 0$ & $ \NOT 0 = 1$
\end{tabular}
\end{frame}
\subsection{TTL}
\begin{frame}
\fullwidthline{\fullheightimage{7400}
\resizebox{0.4\paperwidth}{!}{\includegraphics{TTL_npn_nand.png}}}
\end{frame}
\section{Verilog}
\subsection{Logic Design with Verilog Hardware Description Language}
\begin{frame}
\begin{itemize}
\item Module definition
\item Module instances
\item Module Parameters
\item Signals, wire, assign
\item reg, always, nonblocking assignment
\item Simulation, Testbenches
\item initial
\item Verilog Change Dump (vcd, lxt)
\end{itemize}
\end{frame}
\def\kw{\texttt}
\subsection{Module Definition}
\begin{frame}
A Verilog module defines a logic circuit or subcircuit. The module
definition syntax is basically
\begin{itemize}
\item the keyword \kw{module}
\item a module name
\item port declarations
\item the module body
\item the keyword \kw{endmodule}
\end{itemize}
The ports are the inputs and outputs of the module. Modules without
ports are toplevel modules for simulation. The ports of the
toplevel module for the target design are the actual input and
outputs of the chip/FPGA.
\end{frame}
\begin{frame}
\verbatiminput{mux4.v}
\end{frame}
\subsection{Module Instances}
\begin{frame}
Modules can be instantiated inside higher level modules. There can
be multiple instances. Each instance needs a name which must be
unique among the items defined in the enclosing module body.
The ports of a module instance can be connected to signals defined
earlier in the enclosing module body, including ports of the
enclosing module. Inputs can be connected to any signal, outputs
must be connected to wires, not registers. A port need not be
connected. If a port is connected to an undefined name, or a name
that is defined later in the module body, a wire of that name is
automatically defined, which can lead to confusing error messages,
don't do that.
There are multiple syntactic ways to declare and connect ports. The
syntax presented here is more verbose but easier to read than the
alternative.
\end{frame}
\begin{frame}
\verbatiminput{mux4_8.v}
\end{frame}
\subsection{Module Parameters}
\begin{frame}
Module can have parameters that are evaluated during the elaboration
of the Verilog code by the compiler. The parameters are constants
for each instance of the module, but different instances can have
different values for the parameters.
Again, there are different syntax available both to declare
parameters for a module and to set the value of a parameter for a
module instance. The syntax presented here is the only one that is
supported by all Verilog compilers we use.
\end{frame}
\begin{frame}
\verbatiminput{mux.v}
\end{frame}
\begin{frame}
\verbatiminput{muxp_8.v}
\end{frame}
\subsection{Signals, wires, assign}
\begin{frame}
A signal can be a single bit, or multiple bits that form a number or
a bus of logic signals. Signals are either wires or registers.
Module ports are signals, output ports can be registers.
A wire is a signal that can be connected to output ports of a module
instance or assigned to a logic expression of other signals.
Each bit in a signal carries a logic state that can have four
different values: 0 (false), 1 (true), \kw{x} (unknown), or \kw{z}
(high impedance).
A wire can be connected to multiple drivers. If different values
(not \kw z) are driven on a wire the resulting value is \kw{x}
(unknown). If all drivers are \kw{z} (high impedance) an expression
that depends on the signal may become \kw x (undefined).
An assignment to a wire may be written as part of the wire
declaration or with a separate \kw{assign} statement. The state of
the wire changes whenever the value of the assigned expression
changes.
\end{frame}
\begin{frame}
\verbatiminput{muxsw.v}
\end{frame}
\subsection{\kw{reg}, \kw{always}, nonblocking assignment}
\begin{frame}
A register is a signal that changes its state whenever a new value
is assigned to it in an \kw{always} or \kw{initial} block. These
blocks are sequences of commands.
An \kw{initial} block is executed once at the beginning of a
simulation. This cannot be used to describe a circuit. It may be
used to define the power-on state of a register with some tools.
An \kw{always} block is executed in an infinite loop. A block can
(and should) include statements that wait for certain events. The
only synthesizable thing to wait for is for some signal to change.
\kw{always} blocks can describe combinatorial logic or
sequencial logic, i.e., flip-flops. A combinatorial block will
wait for some signals to change and then do a blocking assignment to a
register, evaluated from those signals.
A sequencial block will wait for a clock edge, and then perform
non-blocking assignements to registers.
% Each register that is part of a circuit description should be
% assigned to in only one \kw{always} block. Since all \kw{always}
% block are executed simultaniously, if multiple block assign to a
% register the effects may be undefined or at least confusing. All
% assignements to a register shall depend on different conditions.
\end{frame}
\begin{frame}
Blocking assignments (\kw{=}) are executed immediately, and all
expressions that drive wires and depend of the assigned register
will change state at that moment in the simulation. This can be
used to describe combinatorial logic, where the output depends only
on the state of the inputs.
Non-blocking assignments (\kw{<=}) are queued at the end of the list
of things to execute at the current simulation time. The same list
includes all blocks that were waiting for some event that just
happened. When a clock edge occurs, all always blocks that where
waiting for that clock edge are queued up for execution. During
execution, these always blocks queue up assignments to registers.
These assignments will be executed after all always blocks were
executed, so all always blocks see the old values of all those
registers before they change. This is exactly how a synchronous
circuit is supposed to work. The registers represent the
flip-flops.
\end{frame}
\begin{frame}
\verbatiminput{switch.v}
\end{frame}
\begin{frame}
\verbatiminput{counter.v}
\end{frame}
\subsection{Simulation, Testbenches}
\begin{frame} \footnotesize
\verbatiminput{mux8_test.v}
\end{frame}
\begin{frame} \footnotesize
\verbatiminput{mux8_test.txt}
\end{frame}
\section{DIRENA}
\subsection{Resources}
\begin{frame}
\begin{description}
\item [AD\,7276] ~\\
ADC, 12-bit, 3\,MSPS, serial output, small package.
\begin{itemize}
\item $48\units{MHz}$ ADC clock -- $96\units{MHz}$ main clock.
\end{itemize}
\item [EP2C8T144] ~\\
FPGA, small, easy package, 144 pin.
\begin{itemize}
\item 18 embedded multipliers -- 18 channels.
\item 36 embedded RAM blocks -- 1 block per channel, plus FIFOs.
\end{itemize}
\end{description}
\end{frame}
\subsection{Algorithm}
\begin{frame}
\begin{itemize}
\item Store the new sample $S_0$.
\item Compute
\begin{eqnarray*}
A &=& \sum\limits_{i=0}^{15} a_i S_{n_i} \\
B &=& \sum\limits_{i=0}^{15} b_i S_{n_i} \\
\end{eqnarray*}
\item Deliver $S_Q$ for sample readout.
\end{itemize}
\end{frame}
\begin{frame}
In 32 clock cycles, we need to do 32 multiplications, read 16
samples~$S_{n_i}$, $S_Q$ and 16 sets of coefficients $a_i$, $b_i$,
$n_i$ from the RAM, and write one sample~$S_0$. \\[5pt]
With implicit $n_0=0$. I.e., the first sample is always $S_0$, which
need not be read from the RAM. The read slot for $S_0$ is used to
read $S_Q$, and the storage for the coefficient $n_0=Q$ is used to
tell how far back in time the sample readout shall happen. \\[5pt]
The RAM is 128 words deep, by 32 bits. Coefficients are stored in
the even addresses, the samples in the odd addresses. Coefficients
waste $3/4$ of the addresses, the samples leave 20 bits unused.
There is space for 64 samples, that is how far back in time the
analysis can go. \\[5pt]
\end{frame}
\section{ARM}
\subsection{FPGA frontend}
\begin{frame}
\fullwidthimage[0.70]{frontend-dia}
\end{frame}
\end{document}

BIN
m2_m2_pu_ramp.pdf Normal file

Binary file not shown.

12
mux.v Normal file
View file

@ -0,0 +1,12 @@
module mux #(parameter N=4)
(
input clk,
input sel,
input [N-1:0] a,
input [N-1:0] b,
output reg [N-1:0] q
);
always @(posedge clk)
q <= sel ? a : b;
endmodule

15
mux4.v Normal file
View file

@ -0,0 +1,15 @@
module mux4
(
input clk,
input sel,
input [3:0] a,
input [3:0] b,
output reg [3:0] qs,
output [3:0] qa
);
assign qa = sel ? a : b;
always @(posedge clk)
qs <= qa;
endmodule

16
mux4_8.v Normal file
View file

@ -0,0 +1,16 @@
module mux8
(
input clk,
input sel,
input [7:0] a,
input [7:0] b,
output [7:0] q
);
mux4 muxlo( .clk(clk),
.sel(sel), .a(a[3:0]), .b(b[3:0]),
.qs(q[3:0]) );
mux4 muxhi( .clk(clk),
.sel(sel), .a(a[7:4]), .b(b[7:4]),
.qs(q[7:4]) );
endmodule

20
mux8_test.txt Normal file
View file

@ -0,0 +1,20 @@
$ iverilog mux8_test.v mux4.v mux4_8.v -o mux.vvp
$ ./mux.vvp -lxt2
LXT2 info: dumpfile mux8.lxt opened for output.
10: sel=x a=12 b=34 q=xxxxxxxx
30: sel=1 a=12 b=34 q=00x10xx0
50: sel=0 a=12 b=34 q=00010010
70: sel=1 a=12 b=34 q=00110100
90: sel=z a=12 b=34 q=00010010
110: sel=z a=12 b=34 q=00x10xx0
$ iverilog mux8_test.v mux.v muxp_8.v -o mux.vvp
$ iverilog mux8_test.v muxsw.v muxp_8.v -o mux.vvp
$ ./mux.vvp -lxt2
LXT2 info: dumpfile mux8.lxt opened for output.
10: sel=x a=12 b=34 q=xxxxxxxx
30: sel=1 a=12 b=34 q=xxxxxxxx
50: sel=0 a=12 b=34 q=00010010
70: sel=1 a=12 b=34 q=00110100
90: sel=z a=12 b=34 q=00010010
110: sel=z a=12 b=34 q=xxxxxxxx
$ gtkwave mux8.lxt

20
mux8_test.v Normal file
View file

@ -0,0 +1,20 @@
`timescale 1ns/1ps
module mux_test;
reg clk, sel;
reg [7:0] a, b;
wire [7:0] q;
mux8 dut(.clk(clk), .sel(sel), .a(a), .b(b), .q(q));
always @(posedge clk)
$display("%5d: sel=%d a=%h b=%h q=%b", $time, sel, a, b, q);
initial begin
$dumpfile("mux8.lxt");
$dumpvars(0);
clk =0; a=8'h 12; b=8'h 34;
#10 clk=1; #10 clk=0; sel=1;
#10 clk=1; #10 clk=0; sel=0;
#10 clk=1; #10 clk=0; sel=1;
#10 clk=1; #10 clk=0; sel='bz;
#10 clk=1; #10 clk=0;
#10 clk=1; #10 clk=0;
end
endmodule

13
muxp_8.v Normal file
View file

@ -0,0 +1,13 @@
module mux8
(
input clk,
input sel,
input [7:0] a,
input [7:0] b,
output [7:0] q
);
mux #(.N(8)) m( .clk(clk),
.sel(sel), .a(a), .b(b),
.q(q) );
endmodule

16
muxsw.v Normal file
View file

@ -0,0 +1,16 @@
module switch #(parameter N=4)
(input en, input [N-1:0] a, output [N-1:0] q);
assign q = en ? a : {N{1'b z}};
endmodule
module mux #(parameter N=4)
( input clk, input sel,
input [N-1:0] a, input [N-1:0] b,
output reg [N-1:0] q );
wire [N-1:0] qq;
switch #(.N(N)) sa(.en(sel), .a(a), .q(qq) );
switch #(.N(N)) sb(.en(~sel), .a(b), .q(qq) );
always @(posedge clk)
q <= qq;
endmodule

BIN
shaper.pdf Normal file

Binary file not shown.

272
shaper.tex Normal file
View file

@ -0,0 +1,272 @@
\documentclass[12pt,a4paper]{article}
\usepackage[utf8]{inputenc}
\errorcontextlines=100
\usepackage{graphics}
\title{Shaper Transfer Function}
\author{Stephan I. Böttcher}
\def\units{\,\mathrm}
\def\P{{\mathrm P}}
\begin{document}
\maketitle
\noindent\resizebox{\linewidth}{!}{\includegraphics{preamp-shaper-filter}}
\noindent In this note we derive the transfer function of the Solar
Orbiter shaper with pole-zero-cancelation. The desired form of this
function is
\begin{equation}
\label{eq:Hdes}
H(s) = a
\, \frac{\tau\tau_0}{\tau_\P}
\, \frac{s\,(1+s\tau_\P)}{(1+s\tau)^2\,(1+s\tau_0)}
\end{equation}
The shaper gain is set by the constant
\begin{equation}
\label{eq:a}
a = \frac{R_2}{R_1}.
\end{equation}
The basic shaper is described by
\begin{equation}
\label{eq:Hs}
H_\mathrm{sh}(s) = \frac{s\tau}{(1+s\tau)^2}
\end{equation}
which is what you get without the pole-zero-cancelation network. The
zero $(1+s\tau_\P)$ shall cancel with the pole of the
preamplifier
\begin{equation}
\label{eq:tauP}
\tau_\P = R_rC_r = R_0C_1.
\end{equation}
The large capacitor~$C_0$ needs to be added to avoid a non-zero
DC-gain of the shaper circuit. The leads to the addition of the pole
$(1+s\tau_0)$. The peramplifier pole is in effect replaced by a pole
with a longer time constant $\tau_0=R_0C_0$, but not totally
eliminated.
These time constant calculations are approximations. We are going to
calculate them correctly to the order of~$\tau/\tau_\P$,
but still drop corrections of the order~$\tau/\tau_0$.
\section{Impedance of the amplifier network}
The shaper is a simple operational amplifier circuit in inverting
configuration. The transfer function~$H(s)$ is the ratio of the
feedback impedance~$Z_2$ to the input impedance~$Z_1$
\begin{equation}
\label{eq:ZZ}
H(s) = \frac{Z_2(s)}{Z_1(s)}.
\end{equation}
\subsection{Feedback Impedance}
The feedback impedance is the parallel circuit of the capacitor~$C_2$
and the resistor~$R_2$
\begin{equation}
\label{eq:Z2}
Z_2(j\omega)
= \frac{\frac{R2}{j\omega C_2}}{R_2 + \frac{1}{j\omega C_2}}
= \frac{R2}{1 + j\omega \tau},
\end{equation}
with the shaper time constant
\begin{equation}
\label{eq:tau2}
\tau_2 = R_2C_2 = \tau.
\end{equation}
This term contributes one pole to the shaper transfer function.
\subsection{Input Impedance}
The input impedance is the resistor~$R_1$ in series with the
capacitor~$C_1$, and the pole-zero-cancelation $R_0$--$C_0$ in
parallel with~$C_1$:
\begin{eqnarray}
\label{eq:Z1}
Z_1(j\omega) &=& R_1
+ \frac{\frac{1}{j\omega C_1}\,\left(R_0+\frac{1}{j\omega
C_0}\right)}
{\frac{1}{j\omega C_0} + \frac{1}{j\omega C_1} + R0}
\\&=& \frac{R_1}{j\omega \tau_1}
\, \frac{(j\omega)^2\tau_0\tau_1
+ j\omega\,\left(\tau_0+\tau_1+\frac{\tau_0\tau_1}{\tau_\P}\right)
+ 1}
{1 + \frac{\tau_0}{\tau_\P} + j\omega\tau_0}
\\&=& \frac{R_1\tau_\P'}{\tau_1\tau_0}
\, \frac{(j\omega)^2\tau_0\tau_1
+ j\omega\,\left(\tau_0+\tau_1+\frac{\tau_0\tau_1}{\tau_\P}\right)
+ 1}
{j\omega\,(1+j\omega\tau_\P') }
\label{eq:Z1-2}
\end{eqnarray}
with $\tau_1 = R_1C_1$, $\tau_\P = R_0C_1$, $\tau_0=R_0C_0$, and the pole-zero-cancelation time constant
\begin{equation}
\label{eq:tauPp}
\tau_\P' = \frac{\tau_0\tau_\P}{\tau_0+\tau_P}
= \tau_\P\,\left(1+\frac{\tau_\P}{\tau_0}\right)^{-1}.
\end{equation}
\section{Terms of the transfer function}
From this point we set $s=j\omega$. The transfer function is
\begin{equation}
\label{eq:H12}
H(s) = \frac{R2}{R1}
\,
\frac{\tau_1\tau_0}{\tau_\P'}
\,
\frac{s\,(1+s\tau_\P')} {(1 + s\tau_2)\,\left(s^2\tau_0\tau_1
+ s\,\left(\tau_0+\tau_1+\frac{\tau_0\tau_1}{\tau_\P}\right)
+ 1\right)},
\end{equation}
containing most of the desired terms, except for two poles, which we
need to find by factorizing the term
\begin{equation}
\label{eq:qef}
s^2\tau_0\tau_1
+ s\,\left(\tau_0+\tau_1+\frac{\tau_0\tau_1}{\tau_\P}\right)
+ 1 = (1+s\tau_0')(1+s\tau_1').
\end{equation}
with $\tau_0' \approx \tau_0$ and $\tau_1' \approx \tau_1$.
\subsection{Time constant hierarchy}
The shaper time constant is
\begin{equation}
\label{eq:htau}
\tau = \tau_2 = R_2C_2 = \tau_1' \approx \tau_1 = R_1C_1 \approx
1\dots2.2\units{\mu s}.
\end{equation}
The time constant of the preamplifier pole is one order of magnitude
larger
\begin{equation}
\label{eq:htauP}
\tau_\P' = R_rC_r = 100\units{\mu s} \approx R_0C_1.
\end{equation}
The new pole introduced by the pole-zero-cancelation circuit shall be
at least one order of magnitude larger than~$\tau_\P$
\begin{equation}
\label{eq:htau0}
\tau_0' \approx \tau_0 = R_0C_0 \approx 2000\units{\mu s}.
\end{equation}
We assume
\begin{equation}
\label{eq:hneq}
\tau_2 \ll \tau_\P \ll \tau_0.
\end{equation}
\subsection{Solving the Quadratic Term}
The solution of the quadratic euqation
\begin{equation}
\label{eq:qe}
s^2\tau_0\tau_1
+ s\,\left(\tau_0+\tau_1+\frac{\tau_0\tau_1}{\tau_\P}\right)
+ 1 = 0
\end{equation}
yields two poles at
\begin{equation}
\label{eq:s12}
s_{1/2} = -\,\frac{\tau_0\tau_\P+\tau_0\tau_1+\tau_\P\tau_1
\pm \sqrt{(\tau_0-\tau_1)^2\tau_\P^2 + 2\tau_1\tau_\P\tau_0(\tau_0+\tau_1) + \tau_0^2\tau_1^2}}{2\tau_0\tau_\P\tau_1}
\end{equation}
We do not want any square root in our results, so we need to do an
aproximation. Dropping terms of the order $\tau_1/\tau_0$ we can
replace
\begin{equation}
\label{eq:app}
(\tau_0-\tau_1) \approx (\tau_0+\tau_1) \approx \tau_0.
\end{equation}
With these approximations, the root can be solved:
\begin{equation}
\label{eq:s12a}
s_{1/2} = -\,\frac{\tau_0\tau_\P+\tau_0\tau_1+\tau_\P\tau_1
\pm \tau_0\,(\tau_p+\tau_1)}{2\tau_0\tau_\P\tau_1}.
\end{equation}
The first root, choosing the~$+$, is
\begin{equation}
\label{eq:s1}
s_1 = -\,\frac{1}{\tau_1'}, \qquad \tau_1' = \tau_1 \, \left(1+\frac{\tau_1}{\tau_\P}\right)^{-1}.
\end{equation}
The second root derived from Eq.~\ref{eq:s12a} is obviously nonsense
\begin{equation}
\label{eq:s2n}
s_2 = -\,\frac{1}{2\tau_0}
\end{equation}
because we subtract two large terms to derive a small difference, with
one of the terms carrying an approximation. The error made here is
about a factor two. From the form of Eq.~\ref{eq:qef} we see that
\begin{equation}
\label{eq:s1s2}
\tau_0' \tau_1' = \tau_0\tau_1.
\end{equation}
and the proper second root is~\footnote{This is how we learned to solve
quadratic equations in school, didn't we?}
\begin{equation}
\label{eq:s2}
s_2 = -\,\frac{1}{\tau_0'} = - \,\frac {\tau_1'}{\tau_0\tau_1},
\qquad
\tau_0' = \tau_0\,\left(1+\frac{\tau_1}{\tau_\P}\right).
\end{equation}
\section{Conclusions}
The shaper transfer function is
\begin{equation}
\label{eq:Hfin}
H(s) = a
\,\frac{\tau\tau_0}{\tau_\P'}
\, \frac{s\,(1+s\tau_\P')}{(1+s\tau_1')(1+s\tau_2)(1+s\tau_0')}
\end{equation}
with
\begin{eqnarray}
\label{eq:HfinP}
a &=& \frac{R_2}{R_1}, \\
\tau_2 &=& R_2C_2, \\
\tau_1 &=& R_1C_1, \qquad
\tau_1' = \tau_1\,\left(1+\frac{\tau_1}{\tau_\P}\right)^{-1}, \\
\tau_\P &=& R_0C_1, \qquad
\tau_\P' = \tau_\P \, \left(1+\frac{\tau_P}{\tau_0}\right)^{-1}, \\
\tau_0 &=& R_0C_0,
\qquad \tau_0' = \tau_0 \,\left(1+\frac{\tau_1}{\tau_\P}\right) .
\end{eqnarray}
The correction to the preamplifier pole cancelation time
constant~$\tau_\P$ is
\begin{equation}
\label{eq:corrP}
\left(1+\frac{\tau_P}{\tau_0}\right) \approx 1.05, \qquad 5\units\%,
\end{equation}
which is negligible compared to the typical precision of the
preamplifier feedback capacitor. The correction to the shaper
pole time constant~$\tau_1$ is
\begin{equation}
\label{eq:corr1}
\left(1+\frac{\tau_1}{\tau_\P}\right) \approx 1.02, \qquad 2\units\%,
\end{equation}
which is smaller than typical capacitor tolerances in the shaper
feedback network. In most cases the corrections can be omitted.
\section{Appendix}
The first order taylor series for the square root yields
\begin{eqnarray}
\label{eq:tylor}
\sqrt{\cdot} &=& \tau_0\,(\tau_\P+\tau_1)
\sqrt{1 - \frac{\tau_1^2\tau_\P^2+2\tau_0\tau_\P^2\tau_1
-2\tau_0\tau_\P\tau_1^2}{\tau_0^2\tau_\P^2 + \tau_0^2\tau_1^2}}
\\ &=& \tau_0\,(\tau_\P+\tau_1)\,
\left(
1-\frac12\,\frac{ 2\tau_0\tau_\P^2\tau_1
\,\left(1+\mathcal O(\frac{\tau_1}{\tau_\P})
+\mathcal
O(\frac{\tau_1}{\tau_0})\right)}
{\tau_0^2\tau_1^2
\,\left(1+\mathcal O(\frac{\tau_1^2}{\tau_\P^2})\right)}
\right)
\\ &=& \tau_0\,(\tau_\P+\tau_1)\,\left(1 - \frac{\tau_1}{\tau_0} +
\mathcal O\left(\frac{\tau_1^2}{\tau_0\tau_\P}\right)\right).
\end{eqnarray}
This is formal support for our claim that the approximations were of
the order~$\mathcal O(\frac{\tau_1}{\tau_0})$.
\end{document}

16
switch.v Normal file
View file

@ -0,0 +1,16 @@
module switch #(parameter N=4)
( input en,
input [N-1:0] a,
output [N-1:0] q
);
reg [N-1:0] qq;
always @(en or a)
if (en)
qq = a;
else
qq = 'bz;
assign q = qq;
endmodule