Commit 040b6224 authored by Javier Serrano's avatar Javier Serrano

Some small changes concerning synchronisation between clock domains, and…

Some small changes concerning synchronisation between clock domains, and 1-tick-long control signals.
parent e18af504
......@@ -8,7 +8,7 @@
\pdfcompresslevel=9
\pdfinfo
{ /Title (Guidelines for VHDL Coding)
/Author (Patrick Loschmidt, Natasa Simanic, Cesar Prados)
/Author (Patrick Loschmidt, Natasa Simanic, Cesar Prados, Pablo Alvarez, Javier Serrano)
/Subject (VHDL)}
%\pdftrue
\fi
......@@ -53,13 +53,16 @@
\date{\svnyear-\svnmonth-\svnday}
\author{Patrick Loschmidt$^{1}$, Nata$\check{s}$a Simani\'{c}$^{1}$, C\'{e}sar Prados$^{2}$\\
\author{Patrick Loschmidt$^{1}$, Nata$\check{s}$a Simani\'{c}$^{1}$, C\'{e}sar Prados$^{2}$,\\Pablo Alvarez$^3$, Javier Serrano$^3$\\
{\footnotesize
$^{1}$Research Unit for Integrated Sensor Systems, Austrian Academy of Sciences}\\
{\footnotesize \{Patrick.Loschmidt, Natasa.Simanic\}@OEAW.ac.at}\\
{\footnotesize
$^{2}$Gesellschaft fr Schwerionenforschung mbH, GSI}\\
{\footnotesize \ C.Prados@GSI.de}}
{\footnotesize \ C.Prados@GSI.de}\\
{\footnotesize
$^{3}$European Organization for Nuclear Research, CERN}\\
{\footnotesize \ \{Pablo.Alvarez.Sanchez, Javier.Serrano\}@cern.ch}}
\title{Guidelines for VHDL Coding}
\begin{document}
......@@ -79,6 +82,12 @@ This version was printed on \today.
\section*{Changelog for rev. \svnrev}
\footnotesize
2010-09-15
\begin{itemize}
\item Added recommendation for using 1-tick-long control signals.
\item Added references for synchronisation and VHDL synthesis.
\item Suppressed recommendation of grouping signals into records in component ports.
\end{itemize}
2009-04-21
\begin{itemize}
......@@ -149,6 +158,8 @@ This version was printed on \today.
\bibitem[DXGN]{DXGN}\emph{doxygen} website,
\url{www.doxygen.org}
\bibitem[Rus00]{Rus00}\emph{Andrew Rushton}: VHDL for logic synthesis, Wiley, 2nd edition.
\end{thebibliography}
\end{flushleft}
\end{appendix}
......
......@@ -617,9 +617,10 @@ end process p_my_FSM_output;
%\subsection{(x) Avoid Three-State Signals}
%\subsection{(x) Path Routing Through Units}
\subsection{(o) Input Double Buffers}
If you are going to use a synchronous design, it is highly recommended to use double buffers to synchronise all asynchronous input ports. This avoids metastability and/or spikes on these signals. Figure \ref{fig:DBuffer} shows some code segments which you might want to use to get around these problems.
\subsection{(o) Input Synchronisation}
If you are going to use a synchronous design, it is highly recommended to use a chain of flip-flops to synchronise all asynchronous input ports. This avoids metastability and/or spikes on these signals. Figure \ref{fig:DBuffer} shows some code segments which you might want to use to get around these problems.
\begin{figure}[htbp]
......@@ -654,7 +655,7 @@ signal s_buff1, s_buff2: std_logic; -- internal signal buffers (stage 1 and 2)
-- Begin of double buffer
--=============================================================================
-- read: clk_i, reset_n_i, input_i, g_DEFAULT
-- write: output_i
-- write: output_o
-- r/w: s_buff1, s_buff2
p_buffer: process (clk_i)
begin
......@@ -678,6 +679,66 @@ end process p_buffer;
\label{fig:DBuffer}
\end{figure}
\subsection{(o) One-tick-long control signals}
Control signals like "data ready" or "reset" which are 1-tick long leave no doubt as to when things are happening. The synchronous edge detector circuit is very handy to generate 1-tick-long signals from edges. Figure \ref{fig:edge_detect} shows a modified synchroniser with edge detection. The \emph{output\_o} signal goes to '1' for one clock tick upon detecting a rising edge of the \emph{input\_i} signal. Notice that the edge detector does not use the \emph{s\_buff1} signal since it could still be subject to metastability. Edge detection of an external signal needs a chain of at least three flip-flops.
\begin{figure}[htbp]
\begin{lstlisting}
--=============================================================================
-- Entity declaration for double buffer
--=============================================================================
entity double_buffer is
generic (
g_DEFAULT : in std_logic := 0 -- reset value for internal buffers
);
port (
clk_i : in std_logic; -- buffer clock
reset_n_i : in std_logic; -- reset for internal buffers
input_i : in std_logic; -- input signal
output_o : out std_logic -- double buffered output signal
);
end entity double_buffer;
\end{lstlisting}
\dots
\begin{lstlisting}
--=============================================================================
-- architecture declaration
--=============================================================================
architecture rtl of double_buffer is
signal s_buff1, s_buff2, s_buff3: std_logic; -- internal signal buffers (stage 1 and 2)
\end{lstlisting}
\dots
\begin{lstlisting}
--=============================================================================
-- Begin of double buffer
--=============================================================================
-- read: clk_i, reset_n_i, input_i, g_DEFAULT
-- write: output_o
-- r/w: s_buff1, s_buff2, s_buff3
p_buffer: process (clk_i)
begin
if (clk_i'event and clk_i = '1') then
if reset_n_i = '0' then
-- reset all internal buffers to default value
s_buff1 <= g_DEFAULT;
s_buff2 <= g_DEFAULT;
output_o <= g_DEFAULT;
else
-- propagate signal through buffers (delay = 3 cycles)
s_buff1 <= input_i;
s_buff2 <= s_buff1;
s_buff3 <= s_buff2;
output_o <= s_buff2 and not s_buff3;
end if;
end if;
end process p_buffer;
\end{lstlisting}
\caption{Code segments for a double buffer with edge detection}
\label{fig:edge_detect}
\end{figure}
\subsection{(o) Operator Precedence}
Do not rely on the default operator precedence. Use brackets to specify the intended precedence in particular, which makes your code more readable and avoids misunderstanding.
......@@ -815,7 +876,6 @@ end component <name>; end component;
\subsection{(x) Readability, Reusability, Reliability - General Advices}
\begin{itemize}
\item If an interface structure repeats in a design, use a record to represent it as a single signal. This reduces your code size and gives you the possibility to easily modify the interface.
\item Whenever you find yourself coping and pasting some code, think of writing a function or procedure instead.
\item Make use of constants and generics for buffer sizes, bus width and all other unit parameters. This provides more readability and reusability of the code.
\item Try to use configuration to map entities, architectures and components (i.\,e. to define such mapping explicitly). That way tracing changes between different architectures can be in a single file. This can be useful to change simulation from high level to low level architectures.
......@@ -889,7 +949,7 @@ VHDL for RTL should be as generic as possible. Stick to standard templates for c
\label{fig:CombBlck}
\end{figure}
Critical paths should be entirely included in a single design entity.
Critical paths should be entirely included in a single design entity. As a general rule, a design should exist in a designer's mind before describing it in VHDL (the 'D' stands for Description). See for example \cite{Rus00} as a book which emphasises this approach.
\subsubsection{Instantiating IP Cores}
......@@ -904,7 +964,7 @@ All core's external I/Os should be registered. It prevents long timing paths and
Design should be fully synchronous. Avoid asynchronous logic.
Try to stick to one single system clock. This simplifies the synchronisation and timing analysis. If you ever feel the necessity of clocking a part of your design with an extra clock domain, reduce this new domain to the minimum necessary. For example, if a VHDL custom CPU requires to serialize data clocked by an external source of unknown frequency, it makes sense to clock the serializer with the external clock and fixed frequency quartz as system clock. Data exchange should be done through a deterministic synchronization algorithm between the CPU and the serializer. This will result in much faster serializer and a robust CPU.
Try to stick to one single system clock. This simplifies the synchronisation and timing analysis. If you ever feel the necessity of clocking a part of your design with an extra clock domain, reduce this new domain to the minimum necessary. For example, if a VHDL custom CPU requires to serialize data clocked by an external source of unknown frequency, it makes sense to clock the serializer with the external clock and have a fixed frequency quartz as system clock. Data exchange should be done through a deterministic synchronization algorithm between the CPU and the serializer\footnote{The recipes for good synchronisation are well known but too long to describe here. See for example \href{http://www.ohwr.org/documents/22}{http://www.ohwr.org/documents/22}}. This will result in much faster serializer and a robust CPU.
Clocks must not be ``gated''. If your design ever requires an internally generated clock use the FPGA clock manager.
......
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