Commit 9c682a16 authored by David Cussans's avatar David Cussans

Remoivng firmware source files (VHD) and Bitfiles before pushing to OHWR

parent 867eafc8
\chapter{DUT signals}\label{ch:DUTsignals}
In the old versions of the \gls{tlu} the direction of the signals on the \verb|HDMI*| connectors were pre-defined. The new hardware has separate lines for signals going into the \gls{tlu} and signals out of the \gls{tlu}. See section~\ref{ch:hwDUT} for further details.\\
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
%% Creator: Inkscape 0.48.3.1, www.inkscape.org
%% PDF/EPS/PS + LaTeX output extension by Johan Engelen, 2010
%% Accompanies image file 'tlu_trigger_logic2.pdf' (pdf, eps, ps)
%%
%% To include the image in your LaTeX document, write
%% \input{<filename>.pdf_tex}
%% instead of
%% \includegraphics{<filename>.pdf}
%% To scale the image, write
%% \def\svgwidth{<desired width>}
%% \input{<filename>.pdf_tex}
%% instead of
%% \includegraphics[width=<desired width>]{<filename>.pdf}
%%
%% Images with a different path to the parent latex file can
%% be accessed with the `import' package (which may need to be
%% installed) using
%% \usepackage{import}
%% in the preamble, and then including the image with
%% \import{<path to file>}{<filename>.pdf_tex}
%% Alternatively, one can specify
%% \graphicspath{{<path to file>/}}
%%
%% For more information, please see info/svg-inkscape on CTAN:
%% http://tug.ctan.org/tex-archive/info/svg-inkscape
%%
\begingroup%
\makeatletter%
\providecommand\color[2][]{%
\errmessage{(Inkscape) Color is used for the text in Inkscape, but the package 'color.sty' is not loaded}%
\renewcommand\color[2][]{}%
}%
\providecommand\transparent[1]{%
\errmessage{(Inkscape) Transparency is used (non-zero) for the text in Inkscape, but the package 'transparent.sty' is not loaded}%
\renewcommand\transparent[1]{}%
}%
\providecommand\rotatebox[2]{#2}%
\ifx\svgwidth\undefined%
\setlength{\unitlength}{526.93890012bp}%
\ifx\svgscale\undefined%
\relax%
\else%
\setlength{\unitlength}{\unitlength * \real{\svgscale}}%
\fi%
\else%
\setlength{\unitlength}{\svgwidth}%
\fi%
\global\let\svgwidth\undefined%
\global\let\svgscale\undefined%
\makeatother%
\begin{picture}(1,0.26872186)%
\put(0,0){\includegraphics[width=\unitlength]{tlu_trigger_logic2.pdf}}%
\put(0.13385461,0.23835781){\color[rgb]{0,0.25490196,0.76862745}\makebox(0,0)[rb]{\smash{clk_160 (MHz)}}}%
\put(0.13385461,0.19281173){\color[rgb]{0,0.25490196,0.76862745}\makebox(0,0)[rb]{\smash{in1}}}%
\put(0.13385461,0.14726565){\color[rgb]{0,0.25490196,0.76862745}\makebox(0,0)[rb]{\smash{in1_del_str}}}%
\put(0.13385461,0.10171957){\color[rgb]{0,0.25490196,0.76862745}\makebox(0,0)[rb]{\smash{in5}}}%
\put(0.13385461,0.01062742){\color[rgb]{0,0.25490196,0.76862745}\makebox(0,0)[rb]{\smash{trigger}}}%
\put(0.27960206,0.17307509){\makebox(0,0)[b]{\smash{t1}}}%
\put(0.55287853,0.15030206){\makebox(0,0)[b]{\smash{t2}}}%
\put(0.21887396,0.19736634){\makebox(0,0)[b]{\smash{a}}}%
\put(0.34033017,0.15182026){\makebox(0,0)[b]{\smash{b}}}%
\put(0.40105827,0.15182026){\makebox(0,0)[b]{\smash{c}}}%
\put(0.70469879,0.15182026){\makebox(0,0)[b]{\smash{d}}}%
\end{picture}%
\endgroup%
\documentclass[10pt,twoside, fleqn]{memoir}
%\usepackage{createspace}
%\usepackage[size=pocket,noicc]{createspace}
%\usepackage[paperwidth=4.25in, paperght=6.875in,bindingoffset=.75in]{geometry}
\usepackage[T1]{fontenc}
\usepackage{mathpazo} % USE PALATINO FONT
%\usepackage{newpxtext,newpxmath}
\usepackage[latin1]{inputenc}
%\usepackage[xindy]{imakeidx}
%\usepackage{imakeidx}
\usepackage[nomain,acronym,xindy,toc]{glossaries}
%\usepackage{glossaries} %For acronyms
\usepackage[british]{babel}
%\usepackage{tgtermes}
%\usepackage[framed, numbered, autolinebreaks]{mcode} %MATLAB Snippet code
\usepackage{listings}
\usepackage{graphicx}
\usepackage{glossaries}
\usepackage{hyperref} % HYPERLINKS
\usepackage[font=footnotesize]{caption}
%\usepackage[hidelinks]{hyperref}
%\usepackage{xcolor}
\usepackage{subcaption}
\usepackage{pdflscape} %Landscape pages
\usepackage{pdfpages} %Insert pdf in document
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{gensymb} %Degree sign
\usepackage{footnote} %Footnotes in tabulars
\usepackage{xcolor,framed,marginnote,blindtext}
\hypersetup{
colorlinks,
linkcolor={blue!50!black},
citecolor={blue!50!black},
urlcolor={blue!80!black}
}% Get rid of that MySpace feeling in hypelinks...
\usepackage{listings} %Include code
\usepackage{multirow}
\usepackage{datetime}
%\usepackage{svg}
\definecolor{infobackground}{RGB}{217,237,247}
\definecolor{infoforeground}{RGB}{58,135,173}
\definecolor{infoborder}{RGB}{188,232,241}
\usepackage{environ}
\usepackage{tikz} %TO CREATE BLOCK DIAGRAMS
\usetikzlibrary{fit,backgrounds,calc}
%\usepackage{vrsion}
\colorlet{shadecolor}{blue!10}
%\usepackage[fleqn]{amsmath}
\usetikzlibrary{shapes,arrows}
\usetikzlibrary{positioning}
\setcounter{tocdepth}{2} % DEPTH OF TABLE OF CONTENTS; 2= SUBSECTIONS INCLUDED
\setcounter{secnumdepth}{2} % SUBSECTIONS ARE NUMBERED
\usepackage[clockwise, figuresright]{rotating}
\usepackage{longtable}
\usepackage{tabu}
\NewEnviron{alertinfo}[1]
{
\begin{tikzpicture}
\node[inner sep=0pt,
draw=infoborder,
line width=1.2pt,
fill=infobackground] (box) {\parbox[t]{.99\textwidth}
{%
\begin{minipage}{.15\textwidth}
\centering\tikz[scale=3]
\node[scale=1]
{
\includegraphics[scale=0.04]{./Images/Warning.png}
};
\end{minipage}%
\begin{minipage}{.80\textwidth}
\vskip 10pt
\textbf{\textcolor{infoforeground}{#1}}\par\smallskip
\textcolor{infoforeground}{\BODY}
\par\smallskip
\end{minipage}\hfill
}%
};
\end{tikzpicture}
}
\newdateformat{monthyeardate}{%
\monthname[\THEMONTH], \THEYEAR}
%\usepackage{mathpazo}
%\usepackage[protrusion=true,expansion=true]{microtype}
%\usepackage{type1cm}
%\usepackage{lettrine}
%\checkandfixthelayout
% See the ``Memoir customise'' template for some common customisations
% Don't forget to read the Memoir manual: memman.pdf
%\title{TITLE OF BOOK}
%\author{NAME OF AUTHOR}
%\date{} % Delete this line to display the current date
%% BEGIN TITLE
\makeatletter
\def\maketitle{%
\null
\thispagestyle{empty}%
\vfill
\begin{center}\leavevmode
\normalfont
{\LARGE\raggedleft \@author\par}%
\hrulefill\par
{\huge\raggedright \@title\par}%
\vskip 1cm
{\Large \@date\par}%
\end{center}%
\vfill
\null
\cleardoublepage
}
\makeatother
\author{Paolo Baesso}
\title{AIDA Trigger logic unit (TLU v1E)}
\date{\today}
%\loadglsentries{O:/LatexFiles/Glossary/myGlossary.tex}
\loadglsentries{//ads.bris.ac.uk/filestore/MyFiles/Staff3/phpgb/LatexFiles/Glossary/myGlossary.tex}
%\input{O:/LatexFiles/Glossary/myGlossary.tex}
%\makeglossaries
%%% BEGIN DOCUMENT
\makeindex
\begin{document}
\def\brd{FMC\_TLU\_v1E }
\def\oldbrd{FMC\_TLU\_v1C }
\let\cleardoublepage\clearpage
\maketitle
\frontmatter
\null\vfill
\begin{flushleft}
\textit{Documentation for \brd.}\newline
\newline
Paolo Baesso - \monthname, \the\year
\newline paolo.baesso@bristol.ac.uk
\newline
\newline Please report any error or omission to the author.
\bigskip
\end{flushleft}
\let\cleardoublepage\clearpage
\newpage
\tableofcontents
\mainmatter
\sloppy
\newenvironment{SpecialPar}
{\begin{shaded}\noindent}
{\end{shaded}}
%%% INCLUDE CHAPTERS
%\def\conn{\verb|HDMI1|}
%\def\conn{\verb|HDMI2|}
%\def\conn{\verb|HDMI3|}
%\def\conn{\verb|HDMI4|}
%\include{ch_Introduction}
\include{ch_TLU_Preparation}
\include{ch_TLU_Hardware}
\include{ch_TLU_clock}
\include{DUT_signals}
\include{ch_TLU_triggerInputs}
\include{ch_EventBuffer}
\include{ch_TLU_Functions}
\include{ch_TLU_IPBusRegs}
\include{ch_EUDAQParameters}
\include{ch_EUDAQProducer}
\include{ch_TLU_Appendix}
%\begin{figure}[h]
% \centering
% \includegraphics[width=1.62\textwidth, angle=90]{./Images/protoDUNE_fmc_sfp_to_slave_v0-7.pdf}
% \caption{Sketch of the connections and signal names between the elements of the board.}\label{fig:Connections}
%\end{figure}
%\section{Schematic}
%\includepdf[pages={1-},scale=0.99, landscape=true]{./Images/PC053A.pdf}
%%\includepdf[pages={1-},scale=0.99, landscape=true]{./Images/PC053A_TOPLEVEL.pdf}
%%% GLOSSARY
\printglossaries
%\printglossary[type=\acronymtype]
\printglossary[type=\acronymtype,title=Abbreviations]
%%% BIBLIOGRAPHY
%\bibliographystyle{unsrt}
%\bibliography{./../../Bibliography/myBibliography}
\end{document}
\ No newline at end of file
This diff is collapsed.
\chapter{Control software}\label{ch:controlsw}
The preferred method to run the \gls{tlu} is by using the \href{https://github.com/eudaq/eudaq}{EUDAQ}\footnote{https://github.com/eudaq/eudaq} data acquisition framework.\\
A \gls{tlu} producer, based on C++, has been written to integrate the hardware in EUDAQ and is regularly pushed to the master repository. Checking out the latest EUDAQ software ensures to also have a stable version of the producer.\\
In addition to the EUDAQ producer, a set of Python scripts has been developed to enable users to configure and run the \gls{tlu} using a minimal environment without having to setup the whole data acquisition framework. The scripts are meant to reflect all the functionalities in the EUDAQ producers, i.e. using the scripts it should be possible to perform any operation available on the EUDAQ producer. However, they should only be used for local debugging and testing.\\
\begin{alertinfo}{Warning}
When fixing bus or developing new software for the \gls{tlu}, priority will be given to ensure that the EUDAQ producer is patched first. As a consequence, there is a higher chance to find bugs in the Python scripts.
\end{alertinfo}
\section{EUDAQ Producer}\label{ch:eudaqprod}
Current structure of a fmctlu producer event:
\lstset{language=XML}
\scriptsize
\begin{lstlisting}
<Event>
<Type>2149999981</Type>
<Extendword>171577627</Extendword>
<Description>Ex0Tg</Description>
<Flag>0x00000018</Flag>
<RunN>0</RunN>
<StreamN>0</StreamN>
<EventN>0</EventN>
<TriggerN>88</TriggerN>
<Timestamp>0x0000000000000000 -> 0x0000000000000000</Timestamp>
<Timestamp>0 -> 0</Timestamp>
<Block_Size>0</Block_Size>
<SubEvents>
<Size>1</Size>
<Event>
<Type>2149999981</Type>
<Extendword>3634980144</Extendword>
<Description>TluRawDataEvent</Description>
<Flag>0x00000010</Flag>
<RunN>96</RunN>
<StreamN>4008428646</StreamN>
<EventN>88</EventN>
<TriggerN>88</TriggerN>
<Timestamp>0x0000000105b44f91 -> 0x0000000105b44faa</Timestamp>
<Timestamp>4390670225 -> 4390670250</Timestamp>
<Tags>
<Tag>PARTICLES=89</Tag>
<Tag>SCALER0=93</Tag>
<Tag>SCALER1=93</Tag>
<Tag>SCALER2=0</Tag>
<Tag>SCALER3=0</Tag>
<Tag>SCALER4=0</Tag>
<Tag>SCALER5=0</Tag>
<Tag>TEST=110011</Tag>
<Tag>trigger=</Tag>
</Tags>
<Block_Size>0</Block_Size>
</Event>
</SubEvents>
</Event>
\end{lstlisting}
\normalsize
\begin{description}
\item[Type] ??
\item[ExtendWord] ??
\item[Description]
\item[Flag] Independent from producer. See the \href{https://github.com/eudaq/eudaq/blob/master/main/lib/core/include/eudaq/Event.hh#L87}{EUDAQ documentation} for details.
\item[RunN]
\item[StreamN]
\item[EventN]
\item[TriggerN] Both in the event and subevent this is written byt the producer with \verb|ev->SetTriggerN(trigger_n);|
\item[Timestamp] The event timestamp is currently always 0. The subevent timestamps is written by the producer \verb|ev->SetTimestamp(ts_ns, ts_ns+25, false);|. The top line (0x0000000105b44f91, in the example) is coarse time stamp multiplied by 25, so it represents the time in nanoseconds. The bottom one (4390670225) is the same number but written in decimal format instead of hexadecimal.
\item[PARTICLES] Number of pre-veto triggers recorded by the \gls{tlu}: the trigger logic can detect a valid trigger condition even when the unit is vetoed. In this case no trigger is issued to the \gls{dut}s but the number of such triggers is stored as number of particles. \verb|ev->SetTag("PARTICLES", std::to_string(pt));|
\item[SCALER\#] Number of triggers edges seen by the specific discriminator. \verb|ev->SetTag("SCALER", std::to_string(sl));|
\item[???] Event type from \gls{tlu} is missing?
\item[???] Input trig, i.e. the actual firing inputs should be in TRIGGER but there seems to be nothing there
\end{description}
\section{Python scripts}
The scripts used to debug work locally with the \gls{tlu} are located in a dedicated folder in the \href{https://github.com/PaoloGB/firmware_AIDA/tree/master/TLU_v1e/scripts}{firmware repository}\footnote{https://github.com/PaoloGB/firmware\_AIDA/tree/master/TLU\_v1e/scripts} and rely on additional packages and software.
First of all, the user should download the \href{https://github.com/PaoloGB/firmware_AIDA/tree/master/packages}{packages} used to control the various components of the hardware\footnote{https://github.com/PaoloGB/firmware\_AIDA/tree/master/packages}. It is also necessary to have a local installation of \href{https://ipbus.web.cern.ch/ipbus/doc/user/html/index.html}{IPBUS and uHAL}\footnote{https://ipbus.web.cern.ch/ipbus/doc/user/html/index.html}.\\
Once all the necessary packages have been installed and the environment is set to point to the right folders, it is possible to run the \verb|startTLU_v1e.py| script to start an interface that allows to operate the \gls{tlu}.
\ No newline at end of file
\section{Event buffer}\label{ch:eventBuffer}
The event buffer IPBus slave has four registers.
Writing to \verb|EventFifoCSR| will reset the \gls{fifo}. Reading from either of the register will put their data on the IPBus data line.\\
Reading from \verb|EventFifoCSR| returns the following:
\begin{itemize}
\item bit 0: \gls{fifo} empty flag
\item bit 1: \gls{fifo} almost empty flag
\item bit 2: \gls{fifo} almost full flag
\item bit 3: \gls{fifo} full flag
\item bit 4: \gls{fifo} programmable full flag
\item other bits: 0
\end{itemize}
The status register (SerdesRst) is as follows:
\begin{itemize}
\item bit 0: reset the ISERDES
\item bit 1: reset the trigger counters
\item bit 2: calibrate IDELAY: This seems to be disconnected at the moment.
\item bit 3: fixed to 0
\item bit 4, 5: status of \verb|thresholdDeserializer(Input0)|. When the IDELAY modules (prompt, delayed) have reached the correct delay, these two bits should read 00.
\item bit 6, 7: status of \verb|thresholdDeserializer(Input1)|
\item bit 8, 9: status of \verb|thresholdDeserializer(Input2)|
\item bit 10, 11: status of \verb|thresholdDeserializer(Input3)|
\item bit 12, 13: status of \verb|thresholdDeserializer(Input4)|
\item bit 14, 15: status of \verb|thresholdDeserializer(Input5)|
\item bit 16, 19: fixed to 0
\item bit 20: \verb|s_deserialized_threshold_data(Input0)(7)|
\item bit 21: \verb|s_deserialized_threshold_data(Input1)(7)|
\item bit 22: \verb|s_deserialized_threshold_data(Input2)(7)|
\item bit 23: \verb|s_deserialized_threshold_data(Input3)(7)|
\item bit 24: \verb|s_deserialized_threshold_data(Input4)(7)|
\item bit 25: \verb|s_deserialized_threshold_data(Input5)(7)|
\end{itemize}
9 bits are used to determine trigger edges. 8 are from the deserializers, 1 is added as the LSB and is the MSB from the previous word.
\begin{figure}
\centering
\includegraphics[width=.95\textwidth]{./Images/fifo_words.pdf}
\caption{Event structure}
\label{fig:fifo_event}
\end{figure}
\chapter{Appendix}\label{ch:appendix}
\section{Layout of Enclustra FPGA.}
\includepdf[link,pages={1}]{./Docs/PM3TopView.pdf}
\section{Connections between TLU and FPGA package.}
\includepdf[link,pages=-, angle=90]{./Docs/Connections.pdf}
\section{Schematics for main TLU electronics.}
\includepdf[link,pages=-, angle=90]{./Docs/schematics.pdf}
\section{Schematics for LED and PMT power module.}
\includepdf[link,pages=-, angle=90]{./Docs/schematicsLED.pdf}
\ No newline at end of file
\chapter{Functions}\label{ch:functions}
The following is a list of files containing the code for the \gls{tlu}:
\begin{itemize}
\item \verb|./eudaq2/user/eudet/misc/aida_tlu_test.ini|:\newline initialization file for the hardware. The location of the file can be passed to the EUDAQ code in the \gls{gui}.
\item \verb|./eudaq2/user/eudet/misc/aida_tlu_test.conf|:\newline configuration file. It contains all the parameters to be loaded in the \gls{tlu} at the beginning of the run. If this file is not found, EUDAQ will use a list of default settings. The location of the file (and its name) can be passed to the EUDAQ code in the \gls{gui}.
\item \verb|./eudaq2/user/eudet/misc/aida_tlu_test_connection.xml|:\newline define the IP address and address map of the \gls{tlu}. The one listed is the default location for the file. A different location can be specified with the \verb|ConnectionFile| option in the \emph{conf} file for the \gls{tlu}.
\item \verb|./eudaq2/user/eudet/misc/aida_tlu_test_address.xml|:\newline address map for the \gls{tlu}. The location of the file is specified in the \verb|fmctlu_connection.xml| file.
\item \verb|./eudaq2/user/eudet/misc/aida_tlu_test_clock_config.txt|:\newline configuration for the Si5345 clock chip. In order for the hardware to work a configuration file must be present. Those listed are the default name and location for the file; a different file can be specified with the \verb|CLOCK_CFG_FILE| option in the \emph{conf} file for the \gls{tlu}.
\item \verb|./eudaq2/user/eudet/module/src/FMCTLU_Producer.cc|:\newline eudaq producer for the \gls{tlu}. Contains the methods to initialize, configure, start, stop the \gls{tlu} producer.
\item \verb|./eudaq2/user/eudet/hardware/src/AidaTluController.cc|:\newline Contains the definition of the hardware class for the \gls{tlu} and the methods to set and read from its hardware, such as clock chip, DAC, etc. This lever is abstract with respect to the actual hardware, so that if a future version of the board uses different components it should be possible to re-use this code.
\item \verb|./eudaq2/user/eudet/hardware/include/AidaTluController.hh|:\newline Headers for the controller.
\item \verb|./eudaq2/user/eudet/hardware/src/AidaTluController.cxx|:\newline Executable for the controller.
\item \verb|./eudaq2/user/eudet/hardware/src/AidaTluHardware.cc|:\newline This is the code that deals with the actual hardware on the \gls{tlu}, and contains specific instructions for the chips mounted in the current version. It contains several classes for the ADC, the clock chip, the I/O expanders etc.
\item \verb|./eudaq2/user/eudet/hardware/include/AidaTluHardware.hh|:\newline Header for the hardware.
\item \verb|./eudaq2/user/eudet/hardware/src/AidaTluI2c.cc|:\newline core functions used to read and write from \gls{i2c} compatible slaves.
\item \verb|./eudaq2/user/eudet/hardware/include/AidaTluI2c.hh|:\newline Headers for the \gls{i2c} core.
\end{itemize}
\section{Functions}
\begin{description}
\item[enableClkLEMO] Enable or disable the output clock to the differential LEMO connector.
\item[enableHDMI] Set the status of the transceivers for a specific HDMI connector. When enable= False the transceivers are disabled and the connector cannot send signals from FPGA to the outside world. When enable= True then signals from the FPGA will be sent out to the HDMI.\\ In the configuration file use \verb|HDMIx_on = 0| to disable a channel and \verb|HDMI1_on = 1| to enable it (x can be 1, 2, 3, 4).\\
NOTE: the other direction is always enabled, i.e. signals from the DUTs are always sent to the FPGA.\\
NOTE: Clock source must be defined separately using SetDutClkSrc (DUTClkSrc in python script).\\
NOTE: this is called \verb|DUTOutputs| on the python scripts.
\item[GetFW] dsds
\item[getSN] dsd
\item[I2C\_enable] dsd
\item[InitializeClkChip]
\item[InitializeDAC]
\item[InitializeIOexp]
\item[InitializeI2C]
\item[PopFrontEvent]
\item[ReadRRegister]
\item[ReceiveEvents]
\item[ResetEventsBuffer]
\item[SetDutClkSrc] Set the clock source for a specific \gls{hdmi} connector. The source can be set to 0 (no clock), 1 (Si5345) or 2 (FPGA). In the configuration file use \verb|HDMIx_on = N| to select the source (x can be 1, 2, 3, 4, N is the clock source).\\
NOTE: this is called \verb|DUTClkSrc| on python scripts.
\item[SetPulseStretchPk] Takes a vector of six numbers, packs them (5-bits each) and sends them to the PulseStretch register.
\item[SetThresholdValue]
\item[setTrgPattern] Writes two 32-bit words to define the trigger pattern for the inputs. See section~\ref{ch:triggerinputs} for details.
\item[SetWRegister]
\item[SetUhalLogLevel]
\end{description}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
\chapter{Preparation}\label{ch:preparation}
Before powering the \gls{tlu} it is necessary to follow a few steps to ensure the board and the \gls{fpga} work correctly.\\
The \brd is designed to plug onto a carrier \gls{fpga} board like any other \gls{fmc} mezzanine board, although its form factor does not comply with the ANSI-VITA-57-1 standard.\\
The firmware developed at University of Bristol is targeted to work with the Enclustra AX3 board, which must be plugged onto a PM3 base, also produced by \href{http://www.enclustra.com/en/home/}{Enclustra}. The firmware is written on the \gls{fpga} using a \gls{jtag} interface. Typically a breakout board will be required to connect the Xilinx programming cable to the Enclustra PM3.\\
Currently, it is recommended to use the following:
\begin{itemize}
\item MA-PM3-W-R5: Mars PM3 base board
\item MA-AX3-35-1I-D8-R3: Marx AX3 module (hosts a Xilinx XC7A35T-1CSG324I )
\item MA-PM3-ACC-BASE: Accessory kit, including a \gls{jtag} breakout board to connect Xilinx programming cables. Also includes a 12~V power supply to power the PM3.
\end{itemize}
\section{I/O voltage setting}
The I/O pins of the PM3 can be configured to operate at 2.5~V or 3.3~V; the factory default is 2.5~V but the \brd requires 3.3~V logic. The user should make sure to select the appropriate voltage by operating on DIP-switch CFG-A/S1200 (pin 1 set to ON).\\For reference, a top view of the board is provided in the appendix at page~\pageref{ch:appendix}.\\
\begin{alertinfo}{Warning}
Please double check the PM3 board manual for the correct way to change the I/O voltage setting. Enclustra has been changing their hardware recently.
\end{alertinfo}
\section{Xilinx programming cable}
The \gls{jtag} pins on the PM3 are located on the header J800 (20-way, 2.54~mm pitch). The breakout board provided by Enclustra sits on top of the header and connects the pins to a 14-way Molex milli-grid header so that it is possible to plug the Xiling programming cable directly onto it. However, when the \brd is mounted on a base plate as shown in figure~\ref{fig:TLUplate}, the breakout board has to be detached from the PM3 because it interferes with the mounting screws.\\
The connection between J800 and the breakout can be achieved by using two standard 20-way \gls{idc} cables as shown in figure~\ref{fig:XilinxCable}.
\begin{figure}[h]
\centering
\includegraphics[width=.50\textwidth]{./Images/TLU_plate.jpg}
\caption{\brd and PM3 mounted on a base plate: in this configuration it is not possible to install the breakout board on the PM3 because the mountings screws are in the way.}\label{fig:TLUplate}
\end{figure}
\begin{figure}
\centering
\includegraphics[width=.80\textwidth]{./Images/XilinxCable.jpg}
\caption{Connecting the Xilinx programming cable to the PM3 in an ugly (but effective) way.}\label{fig:XilinxCable}
\end{figure}
\chapter{Clock}\label{ch:clock}
The \gls{tlu} can use various sources to produce a stable 40~MHz clock\footnote{For some applications a 50~MHz clock will be required instead}. A \gls{lvpecl} crystal provides the reference 50~MHz clock for a Si5345A jitter attenuator. The Si5345A can accept up to four clock sources and use them to generate the required output clocks.\\
In \brd the possible sources are: differential LEMO connector LM1\_9, one of the four \gls{hdmi} connectors (\verb|HDMI4|), a \gls{cdr} chip connected to the \gls{sfp} cage. The fourht input is used to provide a zero-delay feedback loop.\\
The low-jitter clock generated by the Si5345A can be distributed to up to ten recipients. In the \gls{tlu} these are: the four \gls{dut}s via \gls{hdmi} connectors, the differential LEMO cable, the \gls{fpga}, connector J1 as a differential pair (pins 4 and 6) and as a single ended signal (pin 8). The final output is connected to the zero-delay feedback loop. Note that it is possible to program the clock chip to generate a different frequency for each of its outputs.\\
The \gls{dut}s can receive the clock either from the Si5435A or directly from the \gls{fpga}: when provided by the clock generator, the signal name is \verb|CLK\_TO\_DUT| and is enabled by signal \verb|ENABLE_CLK_TO_DUT|; when the signal is provided directly from the \gls{fpga} the line used is \verb|DUT_CLK_FROM_FPGA| and is enabled by \verb|ENABLE_DUT_CLK_FROM_FPGA|.\\
The firmware uses the clock generated by the Si5345A except for the block \verb|enclustra_ax3_pm3_infra| which relies on a crystal mounted on the Enclustra board to provide the IPBus functionalities (in this way, at power up the board can communicate via IPBus even if the Si5345A is not configured).
\section{Input selection}
The Si5345 has four inputs that can be selected to provide the clock alignment; the selection can be automatic or user-defined. For further details on this aspect the user should consult the \href{https://www.silabs.com/documents/public/data-sheets/Si5345-44-42-D-DataSheet.pdf}{chip documentation}\footnote{https://www.silabs.com/documents/public/data-sheets/Si5345-44-42-D-DataSheet.pdf}.
\begin{table}[]
\small
\centering
\caption{Si5345 Input Selection Configuration.}
\label{tab:si5345inputs}
\begin{tabular}{|l|l|l|}
\hline
\textbf{Register Name} & \textbf{Hex Address {[}Bit Field{]}} & \textbf{Function} \\ \hline
CLK\_SWITCH\_MODE & 0x0536{[}1:0{]} & \begin{tabular}[c]{@{}l@{}}Selects manual or automatic switching modes.\\ Automatic mode can be revertive or non-revertive.\\ Selections are the following:\\00 Manual\\01 Automatic non-revertive\\02 Automatic revertive\\03 Reserved\end{tabular} \\ \hline
IN\_SEL\_REGCTRL & 0x052A {[}0{]} & \begin{tabular}[c]{@{}l@{}}0 for pin controlled clock selection\\ 1 for register controlled clock selection\end{tabular} \\ \hline
IN\_SEL & 0x052A {[}2:1{]} & \begin{tabular}[c]{@{}l@{}}0 for IN0\\ 1 for IN1\\ 2 for IN2\\ 3 for IN3 (or FB\_IN)\end{tabular} \\ \hline
\end{tabular}
\end{table}
\section{Logic clocks registers}\label{ch:logicClock}
LogicClocksCSR: in the new TLU the selection of the clock source is done by programming the Si5345. As a consequence, there is no reason to write to this register. Reading it back returns the status of the PLL on bit 0, so this should read 0x1.
\ No newline at end of file
This diff is collapsed.
# firmware_AIDA
Firmware for the AIDA TLU Hardware
This repository contains the VHL used to generate the firmware for the AIDA TLU, both versions V1C (T-shaped pcb) and V1E (rectangular PCB; the one most likely to be used outside the UoB lab).
## Firmware for the AIDA TLU Hardware
This repository contains the VHL used to generate the firmware for the AIDA TLU, all version: V1C (T-shaped pcb) and V1E,V1F (rectangular PCB; the ones most likely to be used outside the UoB lab).
# Scripts
The repository also contains Python scripts used to test the hardware. These scripts rely on a few libraries contained in the "packages" folder as well as on uHAL.
......@@ -12,6 +13,19 @@ uHAL can be installed from here:
http://ipbus.web.cern.ch/ipbus/doc/user/html/software/index.html
## Controlling AIDA TLU with Python Script
```startTLU_v1e.py```
Connects to TLU. Allows interactive control.
Reads initialization (start up) parameters from `localIni.ini` ( default clock generator configuration file in `localClock.txt`)
Reads configuration parameters from `localConf.conf`
Initialization and configuration files are in EUDAQ format.
# EUDAQ2
The best way to operate on the TLU is by using the EUDAQ2 tools.
Refer to the official EUDAQ2 page for instructions on how to install it.
......
--=============================================================================
--! @file DUTInterface_AIDA_rtl.vhd
--=============================================================================
--
-------------------------------------------------------------------------------
-- --
-- University of Bristol, High Energy Physics Group.
-- --
------------------------------------------------------------------------------- --
-- VHDL Architecture fmc_mTLU_lib.DUTInterface_AIDA.rtl
--
--------------------------------------------------------------------------------
--
LIBRARY ieee;
USE ieee.std_logic_1164.all;
--! @brief "AIDA Style" Interface to a Device Under Test (DUT) connector.
--! factorized from original DUTInterfaces_rtl.vhd firmware.
--!
--! @author David Cussans , David.Cussans@bristol.ac.uk
--!
--! @date 1/Sept/2015
--!
--! @version v0.1
--!
--! @details
--
ENTITY DUTInterface_AIDA IS
GENERIC(
g_IPBUS_WIDTH : positive := 32
);
PORT(
clk_4x_logic_i : IN std_logic;
strobe_4x_logic_i : IN std_logic; --! goes high every 4th clock cycle
trigger_counter_i : IN std_logic_vector (g_IPBUS_WIDTH-1 DOWNTO 0); --! Number of trigger events since last reset
trigger_i : IN std_logic; --! goes high when trigger logic issues a trigger
reset_or_clk_to_dut_i : IN std_logic; --! Synchronization signal. Passed to DUT pins
shutter_to_dut_i : IN std_logic; --! Goes high to indicate data-taking active. DUTs report busy unless ignore_shutter_veto flag is set high
ignore_shutter_veto_i : in std_logic;
ignore_dut_busy_i : in std_logic;
dut_mask_i : in std_logic; --! Set high if DUT is active.
busy_o : OUT std_logic; --! goes high when DUT is busy or vetoed by shutter
-- Signals to/from DUT
dut_busy_i : IN std_logic; --! BUSY input from DUTs
dut_clk_o : OUT std_logic; --! clocks trigger data when in EUDET mode
dut_reset_or_clk_o : OUT std_logic; --! Either reset line or trigger
dut_shutter_o : OUT std_logic; --! Shutter output. Output 0 (RJ45) has no shutter signal
dut_trigger_o : OUT std_logic --! Trigger output
);
-- Declarations
END ENTITY DUTInterface_AIDA ;
--
ARCHITECTURE rtl OF DUTInterface_AIDA IS
signal s_strobe_4x_logic_d1 : std_logic;
signal s_dut_clk : std_logic := '0'; -- Clock to be sent to DUT connectors ( before final register )
signal s_dut_clk_sr : std_logic_vector(2 downto 0) := "001"; --! Gets shifted out by clk_4x logic. Loaded by strobe_4x_logic
signal s_stretch_trig_in : std_logic := '0'; -- ! stretched version of trigger_i
signal s_stretch_trig_in_sr : std_logic_vector(2 downto 0) := "111"; --! Gets shifted out by clk_4x logic. Loaded by trigger_i
signal s_trigger_out : std_logic := '0'; -- ! trigger shifted to start on strobe_4x_logic
-- Set length of output trigger here ( output length = length of this vector + 1 )
signal s_trigger_out_sr : std_logic_vector(2 downto 0) := ( others => '1'); --! Gets shifted out by clk_4x logic. Loaded by strobe_4x_logic.
BEGIN
-- Copy reset/clk signal straight through
dut_reset_or_clk_o <= reset_or_clk_to_dut_i;
dut_shutter_o <= shutter_to_dut_i;
-- purpose: generates a clock from 4x clock and strobe ( high once every 4 cycles )
-- should produce 11001100... etc. ie. 40MHz clock from 160MHz clock
-- type : combinational
-- inputs : clk_4x_logic_i , strobe_4x_i
-- outputs: s_dut_clk
p_dut_clk_gen: process (clk_4x_logic_i , strobe_4x_logic_i) is
begin -- process p_dut_clk_gen
if rising_edge(clk_4x_logic_i) then
if (strobe_4x_logic_i = '1') then
s_dut_clk <= '1';
s_dut_clk_sr <= "001";
else
s_dut_clk <= s_dut_clk_sr(0);
s_dut_clk_sr <= '0' & s_dut_clk_sr(s_dut_clk_sr'left downto 1);
end if;
end if;
end process p_dut_clk_gen;
-- purpose: re-times a single cycle pulse on trigger on clk_4x_logic onto clk_logic
-- type : combinational
-- inputs : clk_4x_logic_i , strobe_4x_logic_i , trigger_i
-- outputs: s_premask_trigger_to_dut
p_dut_trig_retime: process (clk_4x_logic_i , strobe_4x_logic_i , trigger_i) is
begin -- process p_dut_trig_retime
if rising_edge(clk_4x_logic_i) then
-- Stretch trigger_i pulse to 4 clock cycles on clk4x
if trigger_i = '1' then
s_stretch_trig_in <= '1';
s_stretch_trig_in_sr <= ( others => '1' );
else
s_stretch_trig_in <= s_stretch_trig_in_sr(0);
s_stretch_trig_in_sr <= '0' & s_stretch_trig_in_sr(s_stretch_trig_in_sr'left downto 1);
end if;
--
if (strobe_4x_logic_i = '1') and ( s_stretch_trig_in = '1' ) then
s_trigger_out <= '1';
s_trigger_out_sr <= ( others => '1' );
else
s_trigger_out <= s_trigger_out_sr(0);
s_trigger_out_sr <= '0' & s_trigger_out_sr(s_trigger_out_sr'left downto 1);
end if;
end if;
end process p_dut_trig_retime;
-- purpose: register for internal signals and output signals
-- type : combinational
-- inputs : clk_4x_logic_i , strobe_4x_logic_i , s_veto
-- outputs: busy_o
register_signals: process (clk_4x_logic_i)-- , strobe_4x_logic_i , s_veto)
begin -- process register_signals
if rising_edge(clk_4x_logic_i) then
s_strobe_4x_logic_d1 <= strobe_4x_logic_i;
busy_o <= ((not ignore_shutter_veto_i ) and (not shutter_to_dut_i)) or
((dut_busy_i and DUT_mask_i ) and (not ignore_dut_busy_i) );
dut_clk_o <= s_dut_clk ;
dut_trigger_o <= DUT_mask_i and s_trigger_out;
end if;
end process register_signals;
END ARCHITECTURE rtl;
--! @file
-------------------------------------------------------------------------------
--
--
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
--! @brief "EUDET style" interfaces to a DUT connection. Outputs TRIGGER and receives DUT_CLK and BUSY
--! lines. Adapted from Trigger_Signal_Controller from EUDET TLU firmware.
--!
--! @author David.Cussans@bristol.ac.uk
--! @date 1/Sept/2015
------------------------------------------------------------------------------------
entity DUTInterface_EUDET is
GENERIC(
g_TRIGGER_DATA_WIDTH : positive := 32 -- was32
);
port (
rst_i : in std_logic; --! asynchronous reset. Active high
busy_o : out std_logic; --! low if FSM is in IDLE state, high otherwise
fsm_state_value_o : out std_logic_vector(3 downto 0); --! detailed status of FSM.
trigger_i : in std_logic; --! Trigger retimed onto system clock.active high.
trigger_counter_i : in std_logic_vector(g_TRIGGER_DATA_WIDTH-1 downto 0); --! event number
system_clk_i : in std_logic; --! rising edge active clock from TLU
reset_or_clk_to_dut_i : IN std_logic; --! Synchronization signal. Passed to DUT pins
shutter_to_dut_i : IN std_logic; --! Goes high to indicate data-taking active. DUTs report busy unless ignoreShutterVeto flag set high
ignore_shutter_veto_i : in std_logic;
enable_dut_veto_i : in std_logic; --! If high: if DUT raises dut_busy_i, then busy_o is raised
-- Connections to DUT:
dut_clk_i : in std_logic; --! rising edge active clock from DUT
dut_busy_i : in std_logic; --! from DUT
dut_shutter_o : OUT std_logic; --! Shutter output.
dut_trigger_o : out std_logic --! trigger to DUT
);
end DUTInterface_EUDET;
architecture rtl of DUTInterface_EUDET is
-----------------------------------------------------------------------------
-- Declarations for state machine
type state_type is (IDLE , WAIT_FOR_BUSY_HIGH , TRIGGER_DEGLITCH_DELAY1 ,
TRIGGER_DEGLITCH_DELAY2 , WAIT_FOR_BUSY_LOW
, DUT_INITIATED_VETO );
-- );
signal state , next_state : state_type;
-- Xilinx Voodoo for state machine
attribute SAFE_IMPLEMENTATION : string;
attribute SAFE_IMPLEMENTATION of state : signal is "yes";
-- End of Xilinx Voodoo
-----------------------------------------------------------------------------
-- signal internal_clk : std_logic;
signal serial_trig_data : std_logic;
signal trig_shift_reg : std_logic_vector(g_TRIGGER_DATA_WIDTH-1 downto 0);
-- shift register storing parallel trigger data
-- signal d1_output : std_logic;
-- signal d2_output : std_logic;
signal dut_rising_edge : std_logic;
signal shift_reg_ce : std_logic;
signal dut_busy_r1 , dut_busy_r2 , dut_clk_r1 , dut_clk_r2 : std_logic; -- ! registered values
begin -- rtl
dut_shutter_o <= shutter_to_dut_i ; -- for now just pass through.
-- purpose: suppress meta-stability by registering input signals.
-- type : combinational
-- inputs : dut_busy_r1 , dut_busy_r2 , dut_clk_r1 , dut_clk_r2
-- outputs: dut_busy_r2 , dut_clk_r2
register_signals: process ( dut_busy_r1 , dut_clk_r1 , system_clk_i )
begin -- process register_signals
if rising_edge(system_clk_i) then
dut_busy_r2 <= dut_busy_r1 ;
dut_clk_r2 <= dut_clk_r1;
dut_busy_r1 <= dut_busy_i ;
dut_clk_r1 <= dut_clk_i;
end if;
end process register_signals;
rising_edge_pulse: entity work.single_pulse
port map (
level => dut_clk_i,
clk => system_clk_i,
pulse => dut_rising_edge);
-- look for the rising edge of DUT clock and enable CE for one cycle.
-- I have a nasty suspicion that meta-stability issues may make this
-- go horribly wrong .
-- Need to add timing constraint that shift_reg_ce must arrive before clock at trig_data_driver
-- also WAIT_FOR_BUSY_LOW must not mess things up.
clk_enable_select: process (state, dut_rising_edge)
begin -- process
if (state=WAIT_FOR_BUSY_LOW) then
shift_reg_ce <= dut_rising_edge;
else
shift_reg_ce <= '0';
end if;
end process;
-- purpose: controls the serial_trig_data line
-- type : combinational
-- inputs : system_clk_i , trigger_counter_i
-- outputs: serial_trig_data
trig_data_driver: process (system_clk_i , trigger_counter_i , shift_reg_ce , trig_shift_reg , state)
begin
if rising_edge( system_clk_i ) then
-- if busy is high in response to a trigger shift data out of
-- register on rising edge of DUT clock . This is done by having a slow
-- DUT clock and setting shift_reg_ce for one cycle of system_clk_i when
-- the DUT clock rising edge comes by.
if (shift_reg_ce ='1' ) then
trig_shift_reg <= '0' & trig_shift_reg(g_TRIGGER_DATA_WIDTH-1 downto 1);
serial_trig_data <= trig_shift_reg(0);
-- otherwise load shift register if we have just had a trigger.
elsif (state = WAIT_FOR_BUSY_HIGH ) then
-- only clock out bottom 15 bits of data.
-- (replace fixed width with a mask at some stage ?)
trig_shift_reg <= "00000000000000000" & trigger_counter_i(14 downto 0);
serial_trig_data <= '0';
end if;
end if;
end process trig_data_driver;
-- purpose: Determine the next state
-- type : combinational
-- inputs : state,Dut_Busy_r2, trigger_i
state_logic: process (state, trigger_i , enable_dut_veto_i , dut_clk_r2, dut_busy_r2 )
begin -- process state_logic
case state is
when IDLE =>
if ( trigger_i = '1') then -- respond to trigger going high
next_state <= WAIT_FOR_BUSY_HIGH; -- wait for DUT to respond to busy
elsif ( (dut_clk_r2 = '1') and (enable_dut_veto_i = '1') ) then -- If DUT asserts DUT_CLK_I then veto triggers
next_state <= DUT_INITIATED_VETO;
else
next_state <= IDLE;
end if;
when WAIT_FOR_BUSY_HIGH =>
if (DUT_Busy_r2 = '1') then
next_state <= TRIGGER_DEGLITCH_DELAY1;
else
next_state <= WAIT_FOR_BUSY_HIGH;
end if;
-- put in a pause to supress glitch in output trigger
-- this is an inelegant (to say the least ) way of doing it.
when TRIGGER_DEGLITCH_DELAY1 =>
next_state <= TRIGGER_DEGLITCH_DELAY2;
-- delay for two clock cycles.
when TRIGGER_DEGLITCH_DELAY2 =>
next_state <= WAIT_FOR_BUSY_LOW;
when WAIT_FOR_BUSY_LOW =>
if (DUT_Busy_r2 = '1') then
next_state <= WAIT_FOR_BUSY_LOW;
else
next_state <= IDLE;
end if;
when DUT_INITIATED_VETO =>
if (( dut_clk_r2 = '0' ) or ( enable_dut_veto_i = '0')) then
next_state <= IDLE;
else
next_state <= DUT_INITIATED_VETO;
end if;
end case;
end process state_logic;
-- determine clock select and trigger_mux from FSM state
-- purpose: Determines the state of the dut_trigger_o output based on the state of the FSM
-- type : combinational
-- inputs : state
-- outputs: dut_trigger_o
output_logic: process (state,serial_trig_data)
begin -- process output_logic
if ( state = IDLE ) then
-- waiting for external trigger to arrive...
dut_trigger_o <= '0';
elsif ((state = WAIT_FOR_BUSY_HIGH) or ( state=TRIGGER_DEGLITCH_DELAY1) or (state=TRIGGER_DEGLITCH_DELAY2) ) then
-- wait until the BUSY line goes high, then continue to hold TRIGGER high for two clock cycles.
dut_trigger_o <= '1';
elsif (state = WAIT_FOR_BUSY_LOW) then
-- if BUSY is high then connect TRIGGER to serial trigger number register.
dut_trigger_o <= serial_trig_data;
else
dut_trigger_o <= '0';
end if;
end process output_logic;
-- purpose: Register that holds the current state of the FSM
-- type : combinational
-- inputs : system_clk_i , rst_i
-- outputs: state
state_register: process (system_clk_i , rst_i)
begin -- process state_register
if (rst_i = '1') then
state <= IDLE;
elsif rising_edge(system_clk_i) then
state <= next_state;
end if;
end process state_register;
-- purpose: sets the value of clock_select based on FSM state
-- type : combinational
-- inputs : state
-- outputs: clock_select , trigger_muxsel , fsm_state
set_busy: process (system_clk_i , state)
begin -- process set_muxsel
if rising_edge(system_clk_i) then
if (state = IDLE) then
busy_o <= '0';
else
busy_o <= '1';
end if;
end if;
end process set_busy;
-- purpose: Sets the fsm_state_value_o vector to a number representing the current state
-- type : combinational
-- inputs : system_clk_i , state
-- outputs: fsm_state_value_o
store_state: process (system_clk_i , state)
begin -- process store_state
case state is
when IDLE =>
fsm_state_value_o <= "0000";
when WAIT_FOR_BUSY_HIGH =>
fsm_state_value_o <= "0001";
when TRIGGER_DEGLITCH_DELAY1 =>
fsm_state_value_o <= "0010";
when TRIGGER_DEGLITCH_DELAY2 =>
fsm_state_value_o <= "0011";
when WAIT_FOR_BUSY_LOW =>
fsm_state_value_o <= "0100";
when DUT_INITIATED_VETO =>
fsm_state_value_o <= "0101";
when others =>
fsm_state_value_o <= "1111";
end case;
end process store_state;
end rtl;
This diff is collapsed.
This diff is collapsed.
----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 15.02.2017 13:17:26
-- Design Name:
-- Module Name: DUTs_outputs - Behavioral
-- Project Name:
-- Target Devices:
-- Tool Versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity DUTs_outputs is
Port ( clk_in : in STD_LOGIC;
d_clk_o : out STD_LOGIC_VECTOR (3 downto 0);
d_trg_o : out STD_LOGIC_VECTOR (3 downto 0);
d_busy_o : out STD_LOGIC_VECTOR (3 downto 0);
d_cont_o : out STD_LOGIC_VECTOR (3 downto 0);
d_spare_o : out STD_LOGIC_VECTOR (3 downto 0));
end DUTs_outputs;
architecture Behavioral of DUTs_outputs is
signal toggleme : std_logic := '0';
begin
gen_clk : process (clk_in)
begin -- process gen_clk
if rising_edge(clk_in) then -- rising clock edge
toggleme <= not toggleme;
d_clk_o(1) <= toggleme;
d_clk_o(2) <= '0';
d_clk_o(3) <= '0';
d_trg_o <= ('0' & '0' & '0' & '0');
d_busy_o <= ('0' & '0' & '0' & '0');
d_cont_o <= ('0' & '0' & '0' & '0');
d_spare_o <=('0' & '0' & '0' & '0');
end if;
d_clk_o(0) <= clk_in;
end process gen_clk;
end Behavioral;
--! @file dtype_fds.vhdl
--
-------------------------------------------------------------------------------
-- --
-- (c) University of Bristol, High Energy Physics Group --
-- --
-------------------------------------------------------------------------------
--
--
-- This file is part of IPBus.
--
-- IPBus is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- IPBus is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with IPBus. If not, see <http://www.gnu.org/licenses/>.
--
-- IPBus is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- IPBus is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with IPBus. If not, see <http://www.gnu.org/licenses/>.
--
--
--! Standard library
library IEEE;
-- Standard logic defintions.
use IEEE.STD_LOGIC_1164.all;
--
-- unit name: dtype_fds
--
--! @brief Aims to be the same as the Xilinx "FDS" primitive - D-Type flip-flop
--
--
--! @author David.Cussans@bristol.ac.uk
--
--! @date 7/May/2011
--
--! @version 0.1
--
--! @details -- Modified from D-type example in VHDL book.
--! See Xilinx spartan6_scm.pdf
--! Output goes high when input goes high ( asyncnronous to system clock).
--
--! <b>Dependencies:</b>\n
--!
--! <b>References:</b>\n
--! <reference one> \n
--! <reference two>
--!
--! <b>Modified by:</b>\n
--! Author: <name>
-------------------------------------------------------------------------------
--! \n\n<b>Last changes:</b>\n
--! <date> <initials> <log>\n
--! <extended description>
-------------------------------------------------------------------------------
--! @todo <next thing to do> \n
--! <another thing to do> \n
--
-------------------------------------------------------------------------------
This diff is collapsed.
--=============================================================================
--! @file IODELAYCal_FSM_rtl.vhd
--=============================================================================
--
-------------------------------------------------------------------------------
-- --
-- UoB , USC
-- --
------------------------------------------------------------------------------- --
--
--! @brief Finite-state machine to control calibration and reset signals to
--! Iserdes, IDelay
--! based on code by Alvaro Dosil\n
--
--! @author Alvaro Dosil
--
--! @date 22/Feb/2014
--
--! @version v0.1
--
--! @details
--
-------------------------------------------------------------------------------
--! \n\n<b>Last changes:</b>\n
-------------------------------------------------------------------------------
--! @todo Implement a periodic calibration sequence\n
--! <another thing to do> \n
LIBRARY ieee;
USE ieee.std_logic_1164.all;
entity IODELAYCal_FSM is
port (
clk_i : in std_logic; --! Global clock
startcal_i : in std_logic; --! Start calibration
busy_i : in std_logic; --! Status of the IDELAY component
calibrate_o : out std_logic; --! Calibration signals to IODELAY
reset_o : out std_logic --! Reset to IODELAY component
);
end entity IODELAYCal_FSM;
architecture rtl of IODELAYCal_FSM is
--! Calibration FSM state values
type state_values is (st0, st1, st2, st3);
signal pres_state, next_state: state_values := st0;
signal s_cal_FSM : std_logic := '0'; -- IODELAY reset
signal s_rst_FSM : std_logic := '0'; -- IODELAY reset
begin -- rtl
--! Calibration FSM register
statereg: process(clk_i)
begin
if rising_edge(clk_i) then
pres_state <= next_state; -- Move to next state
end if;
end process statereg;
--! Calibration FSM combinational block
fsm: process(pres_state, startcal_i, busy_i)
begin
next_state <= pres_state;
-- Default values
s_Rst_FSM <= '0';
s_cal_FSM <= '0';
case pres_state is
-- st0 - IDLE
when st0=>
if ( startcal_i = '1') then
next_state <= st1; -- Next state is "st1 - SEND CALIBRATION SIGNAL"
end if;
-- st1 - SEND CALIBRATION SIGNAL
when st1=>
s_cal_FSM <= '1';
next_state <= st2; -- Next state is "st2 - WAIT BUSY = '0'"
-- st2 - WAIT BUSY = '0'
when st2=>
if busy_i = '0' then
next_state <= st3; -- Next state is "st3 - RESET STATE"
end if;
-- st3 - RESET STATE
when st3=>
s_Rst_FSM <= '1';
next_state <= st0; -- Next state is "st0 - IDLE"
end case;
end process fsm;
calibrate_o <= s_cal_FSM;
reset_o <= s_Rst_FSM;
end rtl;
--=============================================================================
--! @file IPBusInterface_rtl.vhd
--=============================================================================
--
-------------------------------------------------------------------------------
-- --
-- University of Bristol, High Energy Physics Group.
-- --
------------------------------------------------------------------------------- --
-- VHDL Architecture fmc_mTLU_lib.IPBusInterface.rtl
--
--
-- Created using using Mentor Graphics HDL Designer(TM) 2010.3 (Build 21)
--
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
USE work.ipbus.all;
--! @brief IPBus interface between 1GBit/s Ethernet and IPBus internal bus
--
--! @author David Cussans , David.Cussans@bristol.ac.uk
--
--! @date 16:06:57 11/09/12
--
--! @version v0.1
--
--! @details
--!
--! <b>Modified by:</b>\n
--! Author:
-------------------------------------------------------------------------------
--! \n\n<b>Last changes:</b>\n
-------------------------------------------------------------------------------
ENTITY IPBusInterface IS
GENERIC(
NUM_EXT_SLAVES : positive := 5;
BUILD_SIMULATED_ETHERNET : integer := 0 --! Set to 1 to build simulated Ethernet interface using Modelsim FLI
);
PORT(
gmii_rx_clk_i : IN std_logic;
gmii_rx_dv_i : IN std_logic;
gmii_rx_er_i : IN std_logic;
gmii_rxd_i : IN std_logic_vector (7 DOWNTO 0);
ipbr_i : IN ipb_rbus_array (NUM_EXT_SLAVES-1 DOWNTO 0); --! IPBus read signals
sysclk_n_i : IN std_logic;
sysclk_p_i : IN std_logic; --! 200 MHz xtal clock
clocks_locked_o : OUT std_logic;
gmii_gtx_clk_o : OUT std_logic;
gmii_tx_en_o : OUT std_logic;
gmii_tx_er_o : OUT std_logic;
gmii_txd_o : OUT std_logic_vector (7 DOWNTO 0);
ipb_clk_o : OUT std_logic; --! IPBus clock to slaves
ipb_rst_o : OUT std_logic; --! IPBus reset to slaves
ipbw_o : OUT ipb_wbus_array (NUM_EXT_SLAVES-1 DOWNTO 0); --! IBus write signals
onehz_o : OUT std_logic;
phy_rstb_o : OUT std_logic;
dip_switch_i : IN std_logic_vector (3 DOWNTO 0); --! Used to select IP address
clk_logic_xtal_o : OUT std_logic --! 40MHz clock that can be used for logic if not using external clock
);
-- Declarations
END ENTITY IPBusInterface ;
--
ARCHITECTURE rtl OF IPBusInterface IS
--! Number of slaves inside the IPBusInterface block.
constant c_NUM_INTERNAL_SLAVES : positive := 1;
signal clk125, rst_125, rst_ipb: STD_LOGIC;
signal mac_txd, mac_rxd : STD_LOGIC_VECTOR(7 downto 0);
signal mac_txdvld, mac_txack, mac_rxclko, mac_rxdvld, mac_rxgoodframe, mac_rxbadframe : STD_LOGIC;
signal ipb_master_out : ipb_wbus;
signal ipb_master_in : ipb_rbus;
signal mac_addr: std_logic_vector(47 downto 0);
signal mac_tx_data, mac_rx_data: std_logic_vector(7 downto 0);
signal mac_tx_valid, mac_tx_last, mac_tx_error, mac_tx_ready, mac_rx_valid, mac_rx_last, mac_rx_error: std_logic;
signal ip_addr: std_logic_vector(31 downto 0);
signal s_ipb_clk : std_logic;
signal s_ipbw_internal: ipb_wbus_array (NUM_EXT_SLAVES+c_NUM_INTERNAL_SLAVES-1 DOWNTO 0);
signal s_ipbr_internal: ipb_rbus_array (NUM_EXT_SLAVES+c_NUM_INTERNAL_SLAVES-1 DOWNTO 0);
signal s_sysclk : std_logic;
signal pkt_rx, pkt_tx, pkt_rx_led, pkt_tx_led, sys_rst: std_logic;
BEGIN
-- Connect IPBus clock and reset to output ports.
ipb_clk_o <= s_ipb_clk;
ipb_rst_o <= rst_ipb;
--! By default generate a physical MAC
generate_physicalmac: if ( BUILD_SIMULATED_ETHERNET /= 1 ) generate
-- DCM clock generation for internal bus, ethernet
-- clocks: entity work.clocks_s6_extphy port map(
-- sysclk_p => sysclk_p_i,
-- sysclk_n => sysclk_n_i,
-- clk_logic_xtal_o => clk_logic_xtal_o,
-- clko_125 => clk125,
-- clko_ipb => s_ipb_clk,
-- locked => clocks_locked_o,
-- rsto_125 => rst_125,
-- rsto_ipb => rst_ipb,
-- onehz => onehz_o
-- );
clocks: entity work.clocks_7s_extphy_Se port map(
sysclk_p => sysclk_p_i,
sysclk_n => sysclk_n_i,
clk_logic_xtal_o => clk_logic_xtal_o,
clko_125 => clk125,
clko_ipb => s_ipb_clk,
locked => clocks_locked_o,
rsto_125 => rst_125,
rsto_ipb => rst_ipb,
onehz => onehz_o
);
-- leds <= ('0', '0', locked, onehz);
-- Ethernet MAC core and PHY interface
-- In this version, consists of hard MAC core and GMII interface to external PHY
-- Can be replaced by any other MAC / PHY combination
-- eth: entity work.eth_s6_gmii port map(
-- clk125 => clk125,
-- rst => rst_125,
-- gmii_gtx_clk => gmii_gtx_clk_o,
-- gmii_tx_en => gmii_tx_en_o,
-- gmii_tx_er => gmii_tx_er_o,
-- gmii_txd => gmii_txd_o,
-- gmii_rx_clk => gmii_rx_clk_i,
-- gmii_rx_dv => gmii_rx_dv_i,
-- gmii_rx_er => gmii_rx_er_i,
-- gmii_rxd => gmii_rxd_i,
-- tx_data => mac_tx_data,
-- tx_valid => mac_tx_valid,
-- tx_last => mac_tx_last,
-- tx_error => mac_tx_error,
-- tx_ready => mac_tx_ready,
-- rx_data => mac_rx_data,
-- rx_valid => mac_rx_valid,
-- rx_last => mac_rx_last,
-- rx_error => mac_rx_error
-- );
eth: entity work.eth_7s_rgmii port map(
clk125 => clk125,
rst => rst_125,
tx_data => mac_tx_data,
tx_valid => mac_tx_valid,
tx_last => mac_tx_last,
tx_error => mac_tx_error,
tx_ready => mac_tx_ready,
rx_data => mac_rx_data,
rx_valid => mac_rx_valid,
rx_last => mac_rx_last,
rx_error => mac_rx_error,
gmii_gtx_clk => gmii_gtx_clk_o,
gmii_tx_en => gmii_tx_en_o,
gmii_tx_er => gmii_tx_er_o,
gmii_txd => gmii_txd_o,
gmii_rx_clk => gmii_rx_clk_i,
gmii_rx_dv => gmii_rx_dv_i,
gmii_rx_er => gmii_rx_er_i,
gmii_rxd => gmii_rxd_i
);
end generate generate_physicalmac;
--! Set generic BUILD_SIMULATED_ETHERNET to 1 to generate a simulated MAC
generate_simulatedmac: if ( BUILD_SIMULATED_ETHERNET = 1 ) generate
sim_clocks: entity work.clock_sim
port map (
clko125 => clk125,
clko25 => s_ipb_clk,
clko40 => clk_logic_xtal_o,
nuke => '0',
rsto => rst_125
);
rst_ipb <= rst_125;
clocks_locked_o <= '1';
-- clk125 <= sysclk_i; -- *must* run this simulation with 125MHz sysclk...
simulated_eth: entity work.eth_mac_sim
port map(
clk => clk125,
rst => rst_125,
tx_data => mac_tx_data,
tx_valid => mac_tx_valid,
tx_last => mac_tx_last,
tx_error => mac_tx_error,
tx_ready => mac_tx_ready,
rx_data => mac_rx_data,
rx_valid => mac_rx_valid,
rx_last => mac_rx_last,
rx_error => mac_rx_error
);
end generate generate_simulatedmac;
phy_rstb_o <= '1';
-- ipbus control logic
ipbus: entity work.ipbus_ctrl
generic map (
BUFWIDTH => 2)
port map(
mac_clk => clk125,
rst_macclk => rst_125,
ipb_clk => s_ipb_clk,
rst_ipb => rst_ipb,
mac_rx_data => mac_rx_data,
mac_rx_valid => mac_rx_valid,
mac_rx_last => mac_rx_last,
mac_rx_error => mac_rx_error,
mac_tx_data => mac_tx_data,
mac_tx_valid => mac_tx_valid,
mac_tx_last => mac_tx_last,
mac_tx_error => mac_tx_error,
mac_tx_ready => mac_tx_ready,
ipb_out => ipb_master_out,
ipb_in => ipb_master_in,
mac_addr => mac_addr,
ip_addr => ip_addr,
pkt_rx => pkt_rx,
pkt_tx => pkt_tx,
pkt_rx_led => pkt_rx_led,
pkt_tx_led => pkt_tx_led
);
mac_addr <= X"020ddba115" & dip_switch_i & X"0"; -- Careful here, arbitrary addresses do not always work
ip_addr <= X"c0a8c8" & dip_switch_i & X"0"; -- 192.168.200.X
fabric: entity work.ipbus_fabric
generic map(NSLV => NUM_EXT_SLAVES+c_NUM_INTERNAL_SLAVES)
port map(
ipb_in => ipb_master_out,
ipb_out => ipb_master_in,
ipb_to_slaves => s_ipbw_internal,
ipb_from_slaves => s_ipbr_internal
);
ipbw_o <= s_ipbw_internal(NUM_EXT_SLAVES-1 downto 0);
s_ipbr_internal(NUM_EXT_SLAVES-1 downto 0) <= ipbr_i;
-- Slave: firmware ID
firmware_id: entity work.ipbus_ver
port map(
ipbus_in => s_ipbw_internal(NUM_EXT_SLAVES+c_NUM_INTERNAL_SLAVES-1),
ipbus_out => s_ipbr_internal(NUM_EXT_SLAVES+c_NUM_INTERNAL_SLAVES-1)
);
END ARCHITECTURE rtl;
----------------------------------------------------------------------------------
-- Company: Universidade de Santiago de Compostela
-- Engineer: Alvaro Dosil
--
-- Create Date: 31/07/2012
-- Module Name: Reg_2clks - Behavioral
-- Revision 0.01 - File Created
-- Additional Comments:
----------------------------------------------------------------------------------
-------------------------------------------------------
--! @file
--! @brief Synchronization module 1b
--! @author Alvaro Dosil
-------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Reg_2clks is
port(
clk_i : in std_logic; --! Synchronous clock
async_i : in std_logic; --! Asynchronous input data
sync_o : out std_logic --! Synchronous output data
);
end Reg_2clks;
--! @brief
--! @details Synchronize 1 bit of data
architecture Behavioral of Reg_2clks is
signal sreg : std_logic_vector(1 downto 0);
attribute TIG : string;
attribute IOB : string;
attribute ASYNC_REG : string;
attribute SHIFT_EXTRACT : string;
attribute HBLKNM : string;
attribute TIG of async_i : signal is "TRUE";
attribute IOB of async_i : signal is "FALSE";
attribute ASYNC_REG of sreg : signal is "TRUE";
attribute SHIFT_EXTRACT of sreg : signal is "NO";
attribute HBLKNM of sreg : signal is "sync_reg";
begin
process (clk_i)
begin
if rising_edge(clk_i) then
sync_o <= sreg(1);
sreg <= sreg(0) & async_i;
end if;
end process;
end Behavioral;
--! @file T0_Shutter_Iface_rtl.vhd
--
LIBRARY ieee;
USE ieee.std_logic_1164.all;
library unisim;
use unisim.VComponents.all;
USE work.ipbus.all;
use work.ipbus_reg_types.all;
--! @brief Simple module to generate T0 and shutter signals under IPBus control
--! Similar interface to TPx3_iface_rtl.vhd
--
--! @details
--! \n \n IPBus address map:
--! \li 00 - shutter. Bit 0. Output shutter = value of bit-0
--! \li 01 - T0 write to pulse T0.
--
--! @author David Cussans
entity T0_Shutter_Iface is
port (
clk_4x_i : in std_logic; --! system clock
clk_4x_strobe : in std_logic; --! strobes high for one cycle every 4 of clk_4x
T0_o : out std_logic; --! T0 signal retimed onto system clock
shutter_o : out std_logic; --! shutter signal retimed onto system clock
ipbus_clk_i : IN std_logic; --! IPBus system clock
ipbus_i : IN ipb_wbus;
ipbus_o : OUT ipb_rbus
);
end entity T0_Shutter_Iface;
architecture rtl of T0_Shutter_Iface is
signal s_T0 , s_T0_d1 , s_T0_d2 , s_stretch_T0_in: std_logic := '0'; -- signal after IBufDS and sampled onto clk_4x
signal s_stretch_T0_in_sr : std_logic_vector(2 downto 0) := "111"; --! Gets shifted out by clk_4x logic. Loaded by T0ger_i
signal s_T0_out_sr : std_logic_vector(2 downto 0) := "111"; --! Gets shifted out by clk_4x logic. Loaded by strobe_4x_logic
signal s_shutter , s_shutter_d1 , s_shutter_d2 : std_logic := '0'; -- signal after IBufDS and sampled onto clk_4x
signal s_T0_ipbus , s_T0_ipbus_d1 , s_T0_ipbus_d2: std_logic := '0'; -- Signals that get combined with incoming hardware signals from TPIx3 telescope
signal s_shutter_ipbus , s_shutter_ipbus_d1 , s_shutter_ipbus_d2: std_logic := '0'; -- Signals that get combined with incoming hardware signals from TPIx3 telescope
signal s_ipbus_ack : std_logic := '0'; -- used to produce a delayed IPBus ack signal
begin -- architecture rtl
--------------------
ipbus_write: process (ipbus_clk_i)
begin -- process ipb_clk_i
if rising_edge(ipbus_clk_i) then
s_T0_ipbus <= '0';
if (ipbus_i.ipb_strobe = '1' and ipbus_i.ipb_write = '1') then
case ipbus_i.ipb_addr(1 downto 0) is
when "00" => s_shutter_ipbus <= ipbus_i.ipb_wdata(0) ; -- Set IPBus shutter
when "01" => s_T0_ipbus <= '1';
when others => null;
end case;
end if;
s_ipbus_ack <= ipbus_i.ipb_strobe and not s_ipbus_ack;
end if;
end process ipbus_write;
ipbus_o.ipb_ack <= s_ipbus_ack;
ipbus_o.ipb_err <= '0';
------------------
p_T0_retime: process (clk_4x_i , clk_4x_strobe , s_T0) is
begin -- process p_T0_retime
if rising_edge(clk_4x_i) then
-- Register IPBus clocked signals onto clk 4x. So clk4x must be faster
-- than ipbus_clk for this to work.
s_T0_ipbus_d1 <= s_T0_ipbus;
s_T0_ipbus_d2 <= s_T0_ipbus_d1;
-- Shutter is a DC level, so clock speeds don't matter.
s_shutter_ipbus_d1 <= s_shutter_ipbus;
s_shutter_ipbus_d2 <= s_shutter_ipbus_d1;
-- Stretch T0_i pulse to 4 clock cycles on clk4x
if ( s_T0_ipbus_d2 = '1' ) then
s_stretch_T0_in <= '1';
s_stretch_T0_in_sr <= "111";
else
s_stretch_T0_in <= s_stretch_T0_in_sr(0);
s_stretch_T0_in_sr <= '0' & s_stretch_T0_in_sr(s_stretch_T0_in_sr'left downto 1);
end if;
if (clk_4x_strobe = '1') and ( s_stretch_T0_in = '1' ) then
T0_o <= '1';
s_T0_out_sr <= "111";
else
T0_o <= s_T0_out_sr(0);
s_T0_out_sr <= '0' & s_T0_out_sr(s_T0_out_sr'left downto 1);
end if;
end if;
end process p_T0_retime;
-- Just retime onto the 4x clock. Probably should retime onto 1x clock.
p_shutter_retime: process (s_shutter , clk_4x_i) is
begin -- process p_shutter_retime
if rising_edge(clk_4x_i) then
s_shutter_d1 <= ( s_shutter_ipbus );
s_shutter_d2 <= s_shutter_d1;
shutter_o <= s_shutter_d2;
end if;
end process p_shutter_retime;
end architecture rtl;
--=============================================================================
--! @file TPx3Logic_rtl.vhd
--=============================================================================
--
-------------------------------------------------------------------------------
-- --
-- University of Santiago de Compostela, High Energy Physics Group.
-- --
------------------------------------------------------------------------------- --
-- VHDL Architecture fmc_mTLU_lib.TPx3Logic.rtl
--
--! @brief Produces shutters \n
--! IPBus address map:\n
--
--! @author Alvaro Dosil , alvaro.dosil@usc.es
--
--! @date 16:06:19 11/06/14
--
--! @version v0.1
--
--! @details
--!
--!
--! <b>Dependencies:</b>\n
--!
--! <b>References:</b>\n
--!
--! <b>Modified by: Alvaro Dosil , alvaro.dosil@usc.es </b>\n
--! Author:
-------------------------------------------------------------------------------
--! \n\n<b>Last changes:</b>\n
--! Move all IPBus stuff into ipbus_syncreg_v , which also handles clock domain
--! crossing. 20/Feb/2014 , David Cussans
-------------------------------------------------------------------------------
--! @todo <next thing to do> \n
--! <another thing to do> \n
--
--------------------------------------------------------------------------------
--
-- Created using using Mentor Graphics HDL Designer(TM) 2010.3 (Build 21)
--
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
USE work.ipbus.all;
use work.ipbus_reg_types.all;
ENTITY TPx3Logic IS
GENERIC(
g_IPBUS_WIDTH : positive := 32
);
PORT(
clk_i : IN std_logic; -- ! Rising edge active
Start_T0sync_i : IN std_logic;
T0syncLen_i : IN std_logic_vector(g_IPBUS_WIDTH-1 DOWNTO 0);
logic_reset_i : IN std_logic; -- active high. Synchronous with clk_4x_logic
Busy_i : IN std_logic;
Veto_i : IN std_logic;
Shutter_o : OUT std_logic;
T0sync_o : OUT std_logic
);
-- Declarations
END ENTITY TPx3Logic ;
--
ARCHITECTURE rtl OF TPx3Logic IS
type state_values is (st0, st1);
signal pres_state, next_state: state_values;
signal s_Enable : std_logic := '0';
signal s_Shutter, s_Shutter_d1f, s_Shutter_d1, s_T0sync, s_T0sync_d1f : std_logic := '0';
signal s_Start_T0sync, s_Start_T0sync_d1, s_Start_T0sync_d2, s_Start_T0sync_d3 : std_logic;
signal Rst_T0sync, T0syncT : std_logic; --Load signal and flag for the T0sync
signal s_RunNumber : unsigned(g_IPBUS_WIDTH-1 downto 0) := (others => '0'); -- ! counters for runs
BEGIN
-----------------------------------------------------------------------------
-- Counters
-----------------------------------------------------------------------------
--T0sync counter
c_T0sync: entity work.CounterDown
generic map(
MAX_WIDTH => g_IPBUS_WIDTH
)
port map(
Clk => clk_i,
Reset => '0',
Load => Rst_T0sync,
InitVal => std_logic_vector(unsigned(T0syncLen_i)-1),
Count => open,
Q => T0syncT
);
-----------------------------------------------------------------------------
-- FSM register
-----------------------------------------------------------------------------
statereg: process(clk_i)
begin
if rising_edge(clk_i) then
pres_state <= next_state; --Move to the next state
end if;
end process statereg;
-----------------------------------------------------------------------------
-- FSM combinational block
-----------------------------------------------------------------------------
fsm: process(pres_state, s_Start_T0sync, T0syncT)
begin
next_state<=pres_state;
s_T0sync <='0';
Rst_T0sync <= '1';
case pres_state is
when st0=>
if s_Start_T0sync = '1' then
next_state <= st1; --Next state is "Whait for end of T0sync signal"
end if;
when st1 =>
Rst_T0sync <='0';
s_T0sync <='1';
if T0syncT = '1' then
next_state<=st0; --Next state is "Whait for end of T0-sync counter"
end if;
when others=>
next_state<=st0; --Next state is "Whait for T0sync start"
end case;
end process fsm;
-----------------------------------------------------------------------------
-- Busy signals
-----------------------------------------------------------------------------
s_Enable <= not Veto_i;
s_Shutter <= not Busy_i and not Veto_i;
--Shutter_o <= s_Shutter;
--T0sync_o <= s_T0sync;
-----------------------------------------------------------------------------
-- Count runs and synchronization
-----------------------------------------------------------------------------
p_run_counter: process (clk_i )
begin -- process p_run_counter
if rising_edge(clk_i) then
s_Start_T0sync_d1 <= Start_T0sync_i;
s_Start_T0sync_d2 <= s_Start_T0sync_d1;
s_Start_T0sync_d3 <= s_Start_T0sync_d2;
s_Start_T0sync <= s_Start_T0sync_d2 and ( not s_Start_T0sync_d3);
s_Shutter_d1 <= s_Shutter;
if logic_reset_i = '1' then
s_RunNumber <= (others => '0');
elsif s_Shutter='1' and s_Shutter_d1='0' then
s_RunNumber <= s_RunNumber + 1;
end if;
end if;
-- Signals synchronous with falling edge clock
if falling_edge(clk_i) then
s_Shutter_d1f <= s_Shutter;
Shutter_o <= s_Shutter_d1f;
s_T0sync_d1f <= s_T0sync;
T0sync_o <= s_T0sync_d1f;
end if;
end process p_run_counter;
END ARCHITECTURE rtl;
--! @file TPx3_iface_rtl.vhd
--! @brief Simple module to interface AIDA TLU to LHCb TimePix3 telescope.
--! Accepts T0 sync signal and shutter signal from telescope and re-transmits.
--! @details
--! IPBus address map:
--! 00 - shutter. Bit 0. Output shutter = external shutter XOR ipbus shutter
--! 01 - T0 write to pulse T0.
--! @author David Cussans
LIBRARY ieee;
USE ieee.std_logic_1164.all;
library unisim;
use unisim.VComponents.all;
USE work.ipbus.all;
use work.ipbus_reg_types.all;
entity TPx3_iface is
port (
clk_4x_i : in std_logic; --! system clock
clk_4x_strobe : in std_logic; --! strobes high for one cycle every 4 of clk_4x
T0_p_i : in std_logic; --! T0 signal from timepix telescope clk/sync system
T0_n_i : in std_logic; --! T0 signal from timepix telescope clk/sync system
T0_o : out std_logic; --! T0 signal retimed onto system clock
shutter_p_i : in std_logic; --! shutter signal from timepix telescope clk/sync system
shutter_n_i : in std_logic; --! shutter signal from timepix telescope clk/sync system
shutter_o : out std_logic; --! shutter signal retimed onto system clock
ipbus_clk_i : IN std_logic; --! IPBus system clock
ipbus_i : IN ipb_wbus;
ipbus_o : OUT ipb_rbus
);
end entity TPx3_iface;
architecture rtl of TPx3_iface is
signal s_T0 , s_T0_d1 , s_T0_d2 , s_stretch_T0_in: std_logic := '0'; -- signal after IBufDS and sampled onto clk_4x
signal s_stretch_T0_in_sr : std_logic_vector(2 downto 0) := "111"; --! Gets shifted out by clk_4x logic. Loaded by T0ger_i
signal s_T0_out_sr : std_logic_vector(2 downto 0) := "111"; --! Gets shifted out by clk_4x logic. Loaded by strobe_4x_logic
signal s_shutter , s_shutter_d1 , s_shutter_d2 : std_logic := '0'; -- signal after IBufDS and sampled onto clk_4x
signal s_T0_ipbus , s_T0_ipbus_d1 , s_T0_ipbus_d2: std_logic := '0'; -- Signals that get combined with incoming hardware signals from TPIx3 telescope
signal s_shutter_ipbus , s_shutter_ipbus_d1 , s_shutter_ipbus_d2: std_logic := '0'; -- Signals that get combined with incoming hardware signals from TPIx3 telescope
signal s_external_signal_mask : std_logic_vector(ipbus_i.ipb_wdata'range) := ( others => '0'); --! Set bits to mask external signals : 0 to mask external T0 , set bit 1 to mask external shutter
signal s_maskExternalShutter , s_maskExternalT0 : std_logic := '0'; -- ! Set to 1 to mask external signals
signal s_ipbus_ack : std_logic := '0'; -- used to produce a delayed IPBus ack signal
begin -- architecture rtl
--------------------
ipbus_write: process (ipbus_clk_i)
begin -- process ipb_clk_i
if rising_edge(ipbus_clk_i) then
s_T0_ipbus <= '0';
if (ipbus_i.ipb_strobe = '1' and ipbus_i.ipb_write = '1') then
case ipbus_i.ipb_addr(1 downto 0) is
when "00" => s_shutter_ipbus <= ipbus_i.ipb_wdata(0) ; -- Set IPBus shutter
when "01" => s_T0_ipbus <= '1';
when "10" => s_external_signal_mask <= ipbus_i.ipb_wdata;
when others => null;
end case;
end if;
s_ipbus_ack <= ipbus_i.ipb_strobe and not s_ipbus_ack;
end if;
end process ipbus_write;
ipbus_o.ipb_ack <= s_ipbus_ack;
ipbus_o.ipb_err <= '0';
------------------
cmp_IBUFDS_T0 : IBUFDS
generic map (
DIFF_TERM => TRUE, -- Differential Termination
IBUF_LOW_PWR => TRUE, -- Low power (TRUE) vs. performance (FALSE) setting for referenced I/O standards
IOSTANDARD => "LVDS_25")
port map (
O => s_T0, -- Buffer output
I => T0_p_i, -- Diff_p buffer input (connect directly to top-level port)
IB => T0_n_i -- Diff_n buffer input (connect directly to top-level port)
);
p_T0_retime: process (clk_4x_i , clk_4x_strobe , s_T0) is
begin -- process p_T0_retime
if rising_edge(clk_4x_i) then
s_maskExternalShutter <= s_external_signal_mask(1);
s_maskExternalT0 <= s_external_signal_mask(0);
s_T0_d1 <= s_T0;
s_T0_d2 <= s_T0_d1;
-- Register IPBus clocked signals onto clk 4x. So clk4x must be faster
-- than ipbus_clk for this to work.
s_T0_ipbus_d1 <= s_T0_ipbus;
s_T0_ipbus_d2 <= s_T0_ipbus_d1;
-- Shutter is a DC level, so clock speeds don't matter.
s_shutter_ipbus_d1 <= s_shutter_ipbus;
s_shutter_ipbus_d2 <= s_shutter_ipbus_d1;
-- Stretch T0_i pulse to 4 clock cycles on clk4x
if ( (( s_T0_d2 = '1' ) and ( s_maskExternalT0 = '0')) or ( s_T0_ipbus_d2 = '1' )) then
s_stretch_T0_in <= '1';
s_stretch_T0_in_sr <= "111";
else
s_stretch_T0_in <= s_stretch_T0_in_sr(0);
s_stretch_T0_in_sr <= '0' & s_stretch_T0_in_sr(s_stretch_T0_in_sr'left downto 1);
end if;
--
if (clk_4x_strobe = '1') and ( s_stretch_T0_in = '1' ) then
T0_o <= '1';
s_T0_out_sr <= "111";
else
T0_o <= s_T0_out_sr(0);
s_T0_out_sr <= '0' & s_T0_out_sr(s_T0_out_sr'left downto 1);
end if;
end if;
end process p_T0_retime;
cmp_IBUFDS_shutter : IBUFDS
generic map (
DIFF_TERM => TRUE, -- Differential Termination
IBUF_LOW_PWR => TRUE, -- Low power (TRUE) vs. performance (FALSE) setting for referenced I/O standards
IOSTANDARD => "LVDS_25")
port map (
O => s_shutter, -- Buffer output
I => shutter_p_i, -- Diff_p buffer input (connect directly to top-level port)
IB => shutter_n_i -- Diff_n buffer input (connect directly to top-level port)
);
-- Just retime onto the 4x clock. Probably should retime onto 1x clock.
p_shutter_retime: process (s_shutter , clk_4x_i) is
begin -- process p_shutter_retime
if rising_edge(clk_4x_i) then
s_shutter_d1 <= ( ( s_shutter and not s_maskExternalShutter ) xor s_shutter_ipbus );
s_shutter_d2 <= s_shutter_d1;
shutter_o <= s_shutter_d2;
end if;
end process p_shutter_retime;
end architecture rtl;
This diff is collapsed.
This diff is collapsed.
-- Behavioural model of clocks for ipbus testing
--
-- The clock edges are *not* delta cycle accurate
-- Do not assume any phase relationship between clk125, clk25
--
-- Dave Newbold, March 2011
library ieee;
use ieee.std_logic_1164.all;
entity clock_sim is
port(
clko125: out std_logic;
clko25: out std_logic;
clko40: out std_logic;
nuke: in std_logic;
rsto: out std_logic
);
end clock_sim;
architecture behavioural of clock_sim is
signal clk125, clk25, clk40, nuke_del: std_logic := '0';
signal reset_vec: std_logic_vector(3 downto 0) := X"f";
begin
clk125 <= not clk125 after 4 ns;
clk25 <= not clk25 after 20 ns;
clk40 <= not clk40 after 12.5ns;
clko125 <= clk125;
clko25 <= clk25;
clko40 <= clk40;
process(clk25)
begin
if rising_edge(clk25) then
reset_vec <= '0' & reset_vec(3 downto 1);
end if;
end process;
nuke_del <= nuke after 50us;
rsto <= reset_vec(0) or nuke_del;
end behavioural;
\ No newline at end of file
-- clocks_7s_extphy
--
-- Generates a 125MHz ethernet clock and 31MHz ipbus clock from the 200MHz reference
-- Also an unbuffered 200MHz clock for IO delay calibration block
-- Includes reset logic for ipbus
--
-- Dave Newbold, April 2011
--
-- $Id$
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library unisim;
use unisim.VComponents.all;
entity clocks_7s_extphy is
port(
sysclk_p: in std_logic;
sysclk_n: in std_logic;
clko_125: out std_logic;
clko_125_90: out std_logic;
clko_200: out std_logic;
clko_ipb: out std_logic;
locked: out std_logic;
nuke: in std_logic;
soft_rst: in std_logic;
rsto_125: out std_logic;
rsto_ipb: out std_logic;
rsto_ipb_ctrl: out std_logic;
onehz: out std_logic
);
end clocks_7s_extphy;
architecture rtl of clocks_7s_extphy is
signal dcm_locked, sysclk, clk_ipb_i, clk_125_i, clk_125_90_i, clkfb, clk_ipb_b, clk_125_b: std_logic;
signal d17, d17_d: std_logic;
signal nuke_i, nuke_d, nuke_d2: std_logic := '0';
signal rst, srst, rst_ipb, rst_125, rst_ipb_ctrl: std_logic := '1';
signal rctr: unsigned(3 downto 0) := "0000";
begin
ibufgds0: IBUFGDS port map(
i => sysclk_p,
ib => sysclk_n,
o => sysclk
);
clko_200 <= sysclk; -- io delay ref clock only, no bufg
bufg125: BUFG port map(
i => clk_125_i,
o => clk_125_b
);
clko_125 <= clk_125_b;
bufg125_90: BUFG port map(
i => clk_125_90_i,
o => clk_125_90
);
bufgipb: BUFG port map(
i => clk_ipb_i,
o => clk_ipb_b
);
clko_ipb <= clk_ipb_b;
mmcm: MMCME2_BASE
generic map(
clkfbout_mult_f => 5.0,
clkout1_divide => 8,
clkout2_divide => 8,
clkout2_phase => 90,
clkout3_divide => 32,
clkin1_period => 5.0
)
port map(
clkin1 => sysclk,
clkfbin => clkfb,
clkfbout => clkfb,
clkout1 => clk_125_i,
clkout2 => clk125_90_i,
clkout3 => clk_ipb_i,
locked => dcm_locked,
rst => '0',
pwrdwn => '0'
);
clkdiv: entity work.ipbus_clock_div
port map(
clk => sysclk,
d17 => d17,
d28 => onehz
);
process(sysclk)
begin
if rising_edge(sysclk) then
d17_d <= d17;
if d17='1' and d17_d='0' then
rst <= nuke_d2 or not dcm_locked;
nuke_d <= nuke_i; -- Time bomb (allows return packet to be sent)
nuke_d2 <= nuke_d;
end if;
end if;
end process;
locked <= dcm_locked;
srst <= '1' when rctr /= "0000" else '0';
process(clk_ipb_b)
begin
if rising_edge(clk_ipb_b) then
rst_ipb <= rst or srst;
nuke_i <= nuke;
if srst = '1' or soft_rst = '1' then
rctr <= rctr + 1;
end if;
end if;
end process;
rsto_ipb <= rst_ipb;
process(clk_ipb_b)
begin
if rising_edge(clk_ipb_b) then
rst_ipb_ctrl <= rst;
end if;
end process;
rsto_ipb_ctrl <= rst_ipb_ctrl;
process(clk_125_b)
begin
if rising_edge(clk_125_b) then
rst_125 <= rst;
end if;
end process;
rsto_125 <= rst_125;
end rtl;
-- clocks_7s_extphy_se
--
-- Generates a 125MHz ethernet clock and 31MHz ipbus clock from the 50MHz reference
-- Also an unbuffered 200MHz clock for IO delay calibration block
-- Includes reset logic for ipbus
--
-- Dave Newbold, April 2011
--
-- $Id$
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library unisim;
use unisim.VComponents.all;
entity clocks_7s_extphy_Se is
port(
sysclk: in std_logic;
clko_125: out std_logic;
clko_125_90: out std_logic;
clko_200: out std_logic;
clko_ipb: out std_logic;
locked: out std_logic;
nuke: in std_logic;
soft_rst: in std_logic;
rsto_125: out std_logic;
rsto_ipb: out std_logic;
rsto_ipb_ctrl: out std_logic;
onehz: out std_logic
);
end clocks_7s_extphy_se;
architecture rtl of clocks_7s_extphy_se is
signal dcm_locked, sysclk_i, clk_ipb_i, clk_125_i, clk_125_90_i, clkfb, clk_ipb_b, clk_125_b, clk_200_i: std_logic;
signal d17, d17_d: std_logic;
signal nuke_i, nuke_d, nuke_d2: std_logic := '0';
signal rst, srst, rst_ipb, rst_125, rst_ipb_ctrl: std_logic := '1';
signal rctr: unsigned(3 downto 0) := "0000";
begin
ibufgds0: IBUFG port map(
i => sysclk,
o => sysclk_i
);
bufg125: BUFG port map(
i => clk_125_i,
o => clk_125_b
);
clko_125 <= clk_125_b;
bufg125_90: BUFG port map(
i => clk_125_90_i,
o => clko_125_90
);
bufgipb: BUFG port map(
i => clk_ipb_i,
o => clk_ipb_b
);
clko_ipb <= clk_ipb_b;
bufg200: BUFG port map(
i => clk_200_i,
o => clko_200
);
mmcm: MMCME2_BASE
generic map(
clkfbout_mult_f => 20.0,
clkout1_divide => 8,
clkout2_divide => 8,
clkout2_phase => 90.0,
clkout3_divide => 32,
clkout4_divide => 5,
clkin1_period => 20.0
)
port map(
clkin1 => sysclk_i,
clkfbin => clkfb,
clkfbout => clkfb,
clkout1 => clk_125_i,
clkout2 => clk_125_90_i,
clkout3 => clk_ipb_i,
clkout4 => clk_200_i,
locked => dcm_locked,
rst => '0',
pwrdwn => '0'
);
clkdiv: entity work.ipbus_clock_div
port map(
clk => sysclk_i,
d17 => d17,
d28 => onehz
);
process(sysclk_i)
begin
if rising_edge(sysclk_i) then
d17_d <= d17;
if d17='1' and d17_d='0' then
rst <= nuke_d2 or not dcm_locked;
nuke_d <= nuke_i; -- Time bomb (allows return packet to be sent)
nuke_d2 <= nuke_d;
end if;
end if;
end process;
locked <= dcm_locked;
srst <= '1' when rctr /= "0000" else '0';
process(clk_ipb_b)
begin
if rising_edge(clk_ipb_b) then
rst_ipb <= rst or srst;
nuke_i <= nuke;
if srst = '1' or soft_rst = '1' then
rctr <= rctr + 1;
end if;
end if;
end process;
rsto_ipb <= rst_ipb;
process(clk_ipb_b)
begin
if rising_edge(clk_ipb_b) then
rst_ipb_ctrl <= rst;
end if;
end process;
rsto_ipb_ctrl <= rst_ipb_ctrl;
process(clk_125_b)
begin
if rising_edge(clk_125_b) then
rst_125 <= rst;
end if;
end process;
rsto_125 <= rst_125;
end rtl;
-- clocks_7s_extphy_se
--
-- Generates a 125MHz ethernet clock and 31MHz ipbus clock from the 50MHz reference
-- Also an unbuffered 200MHz clock for IO delay calibration block
-- Includes reset logic for ipbus
--
-- Dave Newbold, April 2011
--
-- $Id$
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library unisim;
use unisim.VComponents.all;
entity clocks_7s_extphy_Se is
port(
--sysclk: in std_logic;
sysclk_p: in std_logic;--
sysclk_n: in std_logic;--
clko_125: out std_logic;--
clko_125_90: out std_logic;
clko_200: out std_logic;
clko_ipb: out std_logic;
locked: out std_logic;--
nuke: in std_logic;
soft_rst: in std_logic;
rsto_125: out std_logic;--
rsto_ipb: out std_logic;--
rsto_ipb_ctrl: out std_logic;
onehz: out std_logic--
);
end clocks_7s_extphy_se;
architecture rtl of clocks_7s_extphy_se is
signal dcm_locked, sysclk_i, sysclk, clk_ipb_i, clk_125_i, clk_125_90_i, clkfb, clk_ipb_b, clk_125_b, clk_200_i: std_logic;
signal d17, d17_d: std_logic;
signal nuke_i, nuke_d, nuke_d2: std_logic := '0';
signal rst, srst, rst_ipb, rst_125, rst_ipb_ctrl: std_logic := '1';
signal rctr: unsigned(3 downto 0) := "0000";
begin
-- ibufgds0: IBUFG port map(
-- i => sysclk,
-- o => sysclk_i
-- );
ibufgds0: IBUFGDS port map(
i => sysclk_p,
ib => sysclk_n,
o => sysclk
);
bufg125: BUFG port map(
i => clk_125_i,
o => clk_125_b
);
clko_125 <= clk_125_b;
bufg125_90: BUFG port map(
i => clk_125_90_i,
o => clko_125_90
);
bufgipb: BUFG port map(
i => clk_ipb_i,
o => clk_ipb_b
);
clko_ipb <= clk_ipb_b;
bufg200: BUFG port map(
i => clk_200_i,
o => clko_200
);
mmcm: MMCME2_BASE
generic map(
clkfbout_mult_f => 20.0,
clkout1_divide => 8,
clkout2_divide => 8,
clkout2_phase => 90.0,
clkout3_divide => 32,
clkout4_divide => 5,
clkin1_period => 20.0
)
port map(
clkin1 => sysclk_i,
clkfbin => clkfb,
clkfbout => clkfb,
clkout1 => clk_125_i,
clkout2 => clk_125_90_i,
clkout3 => clk_ipb_i,
clkout4 => clk_200_i,
locked => dcm_locked,
rst => '0',
pwrdwn => '0'
);
clkdiv: entity work.ipbus_clock_div
port map(
clk => sysclk_i,
d17 => d17,
d28 => onehz
);
process(sysclk_i)
begin
if rising_edge(sysclk_i) then
d17_d <= d17;
if d17='1' and d17_d='0' then
rst <= nuke_d2 or not dcm_locked;
nuke_d <= nuke_i; -- Time bomb (allows return packet to be sent)
nuke_d2 <= nuke_d;
end if;
end if;
end process;
locked <= dcm_locked;
srst <= '1' when rctr /= "0000" else '0';
process(clk_ipb_b)
begin
if rising_edge(clk_ipb_b) then
rst_ipb <= rst or srst;
nuke_i <= nuke;
if srst = '1' or soft_rst = '1' then
rctr <= rctr + 1;
end if;
end if;
end process;
rsto_ipb <= rst_ipb;
process(clk_ipb_b)
begin
if rising_edge(clk_ipb_b) then
rst_ipb_ctrl <= rst;
end if;
end process;
rsto_ipb_ctrl <= rst_ipb_ctrl;
process(clk_125_b)
begin
if rising_edge(clk_125_b) then
rst_125 <= rst;
end if;
end process;
rsto_125 <= rst_125;
end rtl;
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
--=============================================================================
--! @file fmcTLU_pkg_body.vhd
--=============================================================================
---
--! @brief VHDL Package Body fmc_mTLU_lib.fmcTLU
--
--! @author phdgc
--! @date 16:45:08 11/08/12
--
-- using Mentor Graphics HDL Designer(TM) 2010.3 (Build 21)
--
PACKAGE BODY fmcTLU IS
END fmcTLU;
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment