Compare commits
10 commits
e85998b890
...
9fc251fcdb
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9fc251fcdb | ||
|
|
f96019aec4 | ||
|
|
928da9be7f | ||
|
|
af6241f6e4 | ||
|
|
211f7937b2 | ||
|
|
e978abbb51 | ||
|
|
5c19e50aea | ||
|
|
1a4e33dec6 | ||
|
|
6d9d6f48be | ||
|
|
9b17647040 |
7
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
*.aux
|
||||||
|
*.log
|
||||||
|
*.nav
|
||||||
|
*.out
|
||||||
|
*.snm
|
||||||
|
*.toc
|
||||||
|
|
||||||
BIN
100px-AND_ANSI.png
Normal file
|
After Width: | Height: | Size: 724 B |
BIN
100px-NOT_ANSI.png
Normal file
|
After Width: | Height: | Size: 789 B |
BIN
100px-OR_ANSI.png
Normal file
|
After Width: | Height: | Size: 969 B |
BIN
100px-XOR_ANSI.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
125px-Logic-gate-inv-de.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
125px-Logic-gate-or-de.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
125px-Logic-gate-xor-de-2.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
7400.jpg
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
Logic-gate-and-de.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
TTL_npn_nand.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
16
counter.v
Normal 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
3533
frontend.dia
Normal file
BIN
irena.pdf
Normal file
359
irena.tex
|
|
@ -1,7 +1,7 @@
|
||||||
\errorcontextlines=10
|
\errorcontextlines=10
|
||||||
\documentclass{beamer}
|
\documentclass{beamer}
|
||||||
|
|
||||||
\mode<presentation>{\usetheme[compress]{LEC}}
|
\mode<presentation>{\usetheme[compress]{SWRI}}
|
||||||
|
|
||||||
\usepackage[utf8]{inputenc}
|
\usepackage[utf8]{inputenc}
|
||||||
\usepackage{graphics}
|
\usepackage{graphics}
|
||||||
|
|
@ -271,10 +271,12 @@
|
||||||
\begin{frame}[t]
|
\begin{frame}[t]
|
||||||
\imageat{0.05}{0.1}{0.9}{preamp-shaper-filter}
|
\imageat{0.05}{0.1}{0.9}{preamp-shaper-filter}
|
||||||
\begin{mpat}{0.1}{0.45}{0.9}
|
\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},
|
$H_\CSA = \frac{1}{C_r}\,\frac{\tau_\CSA}{1+s\tau_\CSA},
|
||||||
\qquad \qquad
|
\qquad
|
||||||
H_\FSH = \frac{a\tau}{\tau_\PZC}\,\frac{1+s\tau_\PZC}{(1+s\tau)^2},
|
H_\FSH = \frac{as\tau\tau_\PZC}{\tau_\CSA}\,\frac{1+s\tau_\CSA}{(1+s\tau)^2(1+s\tau_\PZC)},
|
||||||
\qquad \qquad
|
\qquad
|
||||||
H_\FIL = \frac{1}{1+s\tau_\FIL} $ \\
|
H_\FIL = \frac{1}{1+s\tau_\FIL} $ \\
|
||||||
|
|
||||||
$H(s) = H_\CSA(s) H_\FSH(s) H_\FIL(s) =
|
$H(s) = H_\CSA(s) H_\FSH(s) H_\FIL(s) =
|
||||||
|
|
@ -355,6 +357,7 @@
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item Resolution, number of output bits.
|
\item Resolution, number of output bits.
|
||||||
\item Sample rate.
|
\item Sample rate.
|
||||||
|
\item Input range and format.
|
||||||
\item Input multiplexer, track and hold.
|
\item Input multiplexer, track and hold.
|
||||||
\item Output format, serial/parallel.
|
\item Output format, serial/parallel.
|
||||||
\item Supply voltage, power consumption.
|
\item Supply voltage, power consumption.
|
||||||
|
|
@ -398,4 +401,352 @@
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
\end{frame}
|
\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}
|
\end{document}
|
||||||
|
|
|
||||||
BIN
m2_m2_pu_ramp.pdf
Normal file
12
mux.v
Normal 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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
272
shaper.tex
Normal 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
|
|
@ -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
|
||||||
|
|
||||||