Compare commits
No commits in common. "9fc251fcdb5031b8b9252bbadb5979f05cc91da6" and "e85998b89093580ceb838c38e6648782b6683af2" have entirely different histories.
9fc251fcdb
...
e85998b890
7
.gitignore
vendored
|
|
@ -1,7 +0,0 @@
|
||||||
*.aux
|
|
||||||
*.log
|
|
||||||
*.nav
|
|
||||||
*.out
|
|
||||||
*.snm
|
|
||||||
*.toc
|
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 724 B |
|
Before Width: | Height: | Size: 789 B |
|
Before Width: | Height: | Size: 969 B |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
BIN
7400.jpg
|
Before Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
BIN
TTL_npn_nand.png
|
Before Width: | Height: | Size: 13 KiB |
16
counter.v
|
|
@ -1,16 +0,0 @@
|
||||||
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
3533
frontend.dia
BIN
irena.pdf
359
irena.tex
|
|
@ -1,7 +1,7 @@
|
||||||
\errorcontextlines=10
|
\errorcontextlines=10
|
||||||
\documentclass{beamer}
|
\documentclass{beamer}
|
||||||
|
|
||||||
\mode<presentation>{\usetheme[compress]{SWRI}}
|
\mode<presentation>{\usetheme[compress]{LEC}}
|
||||||
|
|
||||||
\usepackage[utf8]{inputenc}
|
\usepackage[utf8]{inputenc}
|
||||||
\usepackage{graphics}
|
\usepackage{graphics}
|
||||||
|
|
@ -271,12 +271,10 @@
|
||||||
\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{as\tau\tau_\PZC}{\tau_\CSA}\,\frac{1+s\tau_\CSA}{(1+s\tau)^2(1+s\tau_\PZC)},
|
H_\FSH = \frac{a\tau}{\tau_\PZC}\,\frac{1+s\tau_\PZC}{(1+s\tau)^2},
|
||||||
\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) =
|
||||||
|
|
@ -357,7 +355,6 @@
|
||||||
\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.
|
||||||
|
|
@ -401,352 +398,4 @@
|
||||||
\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}
|
||||||
|
|
|
||||||
12
mux.v
|
|
@ -1,12 +0,0 @@
|
||||||
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
|
|
@ -1,15 +0,0 @@
|
||||||
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
|
|
@ -1,16 +0,0 @@
|
||||||
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
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
$ 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
|
|
@ -1,20 +0,0 @@
|
||||||
`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
|
|
@ -1,13 +0,0 @@
|
||||||
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
|
|
@ -1,16 +0,0 @@
|
||||||
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
272
shaper.tex
|
|
@ -1,272 +0,0 @@
|
||||||
\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
|
|
@ -1,16 +0,0 @@
|
||||||
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
|
|
||||||
|
|
||||||