Files
es-abschlussprojekt/Projektbericht/content.tex
T
Matthias Biermann 3fa4317f7f Kapitel Anhang
2025-02-18 13:48:28 +01:00

567 lines
32 KiB
TeX

\section{Einleitung}
\subsection{Projektbeschreibung und Zielsetzung}
Dieses Projekt umfasst die Konzeptionierung und Implementierung eines IPs zur Berechnung einer 32 Bit Cyclic Redundancy Check (CRC)-Prüfsumme.
Die Verarbeitung erfolgt paketweise, wobei die Daten aus dem Speicher gelesen, verarbeitet und mit angehängter Prüfsumme wieder zurückgeschrieben werden.
Der Speicherzugriff erfolgt über eine AXI-Master-Schnittstelle.
Nach Implementierung der Hardware erfolgt die Erstellung von Software, die die Konfiguration und Steuerung des IP-Cores übernimmt.
Der Softwarepart dieser Arbeit besteht aus zwei Programmen.
Beim ersten handelt es sich um ein C-Programm, das ohne Betriebssystem auf dem Mikroprozessor des hier verwendeten Entwicklungsboards \cite{ZyboBoard} ausgeführt wird.
Das zweite Programm wird im Kontext eines Linux Betriebssystems ausgeführt und beinhaltet die Implementierung eines ausführlichen Testprogramms, das die Funktionalität des IP-Cores überprüft.
\subsection{Anforderungen} \label{sec:Anforderungen}
Die Anforderungen an das Projekt und an das zu erstellende IP umfassen folgende Punkte:
\begin{itemize}
\item Implementierung eines \textbf{CRC-Berechnungsmoduls} als \textbf{IP-Core}
\item \textbf{Paketweises Einlesen} von Daten aus dem Speicher über einen \textbf{Full-AXI-Master}
\item Berechnung einer korrekten CRC-Prüfsumme mit \textbf{konfigurierbaren Parametern} (InitialValue, Polynomial, FinalXOR, Input/OutputReflected)
\item \textbf{Anfügen der Prüfsumme} an das ursprüngliche Datenpaket
\item \textbf{Zurückschreiben} der Daten über einen \textbf{Full-AXI-Master}
\item Unterstützung von \textbf{Interrupts} zur Synchronisation mit der CPU
\item Validierung der Hardwareimplementierung durch \textbf{Simulation und Messungen}
\item Implementierung eines \textbf{Testprogramms} zur Überprüfung der Funktionalität
\item Möglichst hoher \textbf{Datendurchsatz} bei einer Frequenz von \qty{100}{\MHz}
\end{itemize}
\subsection{CRC - Theoretische Grundlagen} \label{sec:CRCGrundlagen}
Der Cyclic Redundancy Check (CRC) ist ein Verfahren zur Fehlererkennung, das in der Regel in digitalen Kommunikationssystemen eingesetzt wird.
Die CRC-Berechnung basiert auf der Division eines Datenwortes durch ein Generatorpolynom.
Der Rest der Division ist die CRC-Prüfsumme.
Die Berechnung der CRC-Prüfsumme erfolgt dabei mit verschiedenen Parametern \cite{SunshineCrcErklärung}.
Ein spezifischer Satz von Parametern definiert einen standart CRC-Algorithmus.
Folgende Parameter sind definiert:
\begin{itemize}
\item \textbf{CRC-Länge / Width:} Die CRC-Länge definiert die Länge der Prüfsumme in Bit. In dieser Arbeit ist sie auf 32 Bit festgelegt.
\item \textbf{Generatorpolynom / Polynomial:} Das verwendete Generatorpolynom für die Polynomdivision.
\item \textbf{Initialwert / Initial Value:} Der Initialwert ist der Wert, mit dem das CRC-Register initialisiert wird.
\item \textbf{Eingangsreflexion / Input Reflected:} Die Bits des Eingangsdatenwortes werden vor der Berechnung umgekehrt.
\item \textbf{Ergebnisreflexion / Output Reflected:} Das Ergebnis wird nach der Berechnung über die gesamte Bitbreite reflektiert.
\item \textbf{Finales XOR / Final XOR:} Der finale CRC-Wert wird mit diesem Wert XOR-verknüpft, bevor er zurückgegeben wird.
\end{itemize}
Mit diesen Parametern lässt sich jeder standartisierte CRC-Algorithmus definieren.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Konzept und Umsetzung des CRC-DMA-IP}
Im Rahmen dieses Projektes wurde ein IP-Block entwickelt, der die komplette CRC-DMA Funktionalität beinhaltet.
Dieser kann anschließend in ein größeres System eingebunden werden, um die CRC-Prüfsummen von Datenpaketen zu berechnen und diese wieder zurückzuschreiben.
Die Einbindung in ein Gesamtsystem wird in Abschnitt~\ref{sec:Einbindung} beschrieben.
Alle im Folgenden dargestellten Blockschaltbilder und VHDL-Quelldateien befinden sich im Vivadoprojekt \texttt{axi\_crc\_dma} in den beigefügten Dateien.
\subsection{Entity / Schnittstellen}
\begin{figure}[H]
\centering
\includegraphics[width=0.6\textwidth]{Blockschaltbilder/axi_crc_dma_ip_entity.png}
\caption{Entity des IP \texttt{axi\_crc\_dma\_ip}}
\label{fig:CRC_DMA_IP_Entity}
\end{figure}
In Abbildung~\ref{fig:CRC_DMA_IP_Entity} ist die Entity des IPs \texttt{axi\_crc\_dma\_ip} dargestellt.
Die AXI-Master Schnittstelle \emph{M\_AXI} dient zum Lesen und Schreiben der Daten aus dem Speicher.
Über die \emph{S\_AXIL} Schnittstelle kann das IP gesteuert und konfiguriert werden.
In Tabelle~\ref{tab:crc_dma_registers} sind die dafür zur Verfügung stehenden Register aufgelistet.
\begin{table}[H]
\centering
\begin{tabular}{|c|l|l|}
\hline
\textbf{Adresse} & \textbf{Registername} & \textbf{Beschreibung} \\ \hline
\multirow{3}{*}{0x00} & \multirow{3}{*}{\texttt{Control}}
& [0] Run \\ \cline{3-3}
& & [1] Interrupt Enable \\ \cline{3-3}
& & [31:2] Reserved \\ \hline
\multirow{2}{*}{0x04} & \multirow{2}{*}{\texttt{Interrupt Status}}
& [0] Interrupt Status \\ \cline{3-3}
& & [31:1] Reserved \\ \hline
\multirow{1}{*}{0x08} & \texttt{Read Address}
& [31:0] Startadresse der zu lesenden Datenpakete \\ \hline
\multirow{1}{*}{0x0C} & \texttt{Write Address}
& [31:0] Zieladresse für Daten + Prüfsumme \\ \hline
\multirow{2}{*}{0x10} & \multirow{2}{*}{\texttt{Packet Size}}
& [15:0] Paketgröße Minus 1 in Worte \\ \cline{3-3}
& & [31:16] Reserved \\ \hline
\multirow{2}{*}{0x14} & \multirow{2}{*}{\texttt{Number Packets}}
& [15:0] Anzahl der Pakete Minus 1 \\ \cline{3-3}
& & [31:16] Reserved \\ \hline
\multirow{1}{*}{0x18} & \texttt{Polynomial}
& [31:0] Generatorpolynom für CRC-Berechnung \\ \hline
\multirow{1}{*}{0x1C} & \texttt{Initial Value}
& [31:0] Initialwert der CRC-Berechnung \\ \hline
\multirow{1}{*}{0x20} & \texttt{Final XOR}
& [31:0] Wert für Finale XOR-Verknüpfung \\ \hline
\multirow{3}{*}{0x24} & \multirow{3}{*}{\texttt{InOutReflected}}
& [0] Input Reflected \\ \cline{3-3}
& & [1] Output Reflected \\ \cline{3-3}
& & [31:2] Reserved \\ \hline
\multirow{3}{*}{0x28} & \multirow{3}{*}{\texttt{AxCache}}
& [3:0] M\_AXI AWCache \\ \cline{3-3}
& & [7:4] M\_AXI ARCache \\ \cline{3-3}
& & [31:8] Reserved \\ \hline
\end{tabular}
\caption{Registerübersicht der CRC-DMA IP}
\label{tab:crc_dma_registers}
\end{table}
Mit dem Register \texttt{Control} kann das IP gesteuert werden.
Um die CRC-Berechnung zu starten, muss Bit 0 gesetzt werden.
Solange das IP aktive ist, bleibt das Bit 0 gesetzt.
Das Löschen des Bit 0 hat keine Wirkung.
Ein gestarteter Vorgang kann also nicht vorzeitig abgebrochen werden.
Mit dem Register \texttt{Interrupt Status} kann der Status des Interrupts ausgelesen werden.
Wenn der Interrupt aktiviert ist, wird dieser gesetzt, sobald die CRC-Berechnung abgeschlossen ist.
Zeitgleich wird der Interruptausgang des IPs auf High gesetzt.
Bevor das IP erneut gestartet werden kann, muss der Interrupt durch das Löschen des Bits 0 zurückgesetzt werden.
Die Register \texttt{Read Address} und \texttt{Write Address} dienen zur Konfiguration der Speicheradressen, von denen die Daten gelesen und wieder zurückgeschrieben werden.
Die Register \texttt{Packet Size} und \texttt{Number Packets} dienen zur Konfiguration der Paketgröße und der Anzahl der zu verarbeitenden Pakete.
Das IP arbeitet wort-weise.
Es können keine einzelnen Bytes adressiert werden.
Das heißt, dass die konfigurierten Adressen word-aligned sein müssen und die Paketgröße und -anzahl in Worten angegeben werden müssen.
Die Register \texttt{Polynomial}, \texttt{Initial Value}, \texttt{Final XOR} und \texttt{InOutReflected} dienen zur Konfiguration der CRC-Berechnung.
Während eine CRC-Berechnung aktiv ist, dürfen diese Register nicht geändert werden, da es sich direkt auf die CRC-Berechnung auswirkt.
Mit dem Register \texttt{AxCache} können die Werte für die \emph{ARCache} und \emph{AWCache} Signale der AXI-Master Schnittstelle konfiguriert werden.
Das Verändern dieses Registers ist nicht notwendig, da der Standartwert bereits eine korrekte Funktionalität des IPs gewährleistet.
Es kann im Folgenden vernachlässigt werden.
\subsection{Architecture}
\begin{figure}[H]
\centering
\includegraphics[width=1.0\textwidth]{Blockschaltbilder/axi_crc_dma_ip_interfaces_view.png}
\caption{Architecture des IP \texttt{axi\_crc\_dma\_ip} im Interfaces-View}
\label{fig:CRC_DMA_IP_ArchitectureInterfaces}
\end{figure}
In Abbildung~\ref{fig:CRC_DMA_IP_ArchitectureInterfaces} ist der grundlegende Aufbau des IPs \texttt{axi\_crc\_dma\_ip} dargestellt.
Es ist als Block-Design in Vivado unter der Bezeichnung \emph{axi\_crc\_dma\_ip} zu finden.
Das IP besteht aus insgesamt vier Komponenten, die untereinander über AXI-Stream Schnittstellen kommunizieren und Daten weitergeben.
In den folgenden Abschnitten werden die einzelnen Komponenten genauer beschrieben.
\subsubsection{DMA Komponente - axis\_dma} \label{sec:DMAKomponente}
\begin{figure}[H]
\centering
\includegraphics[width=0.5\textwidth]{Blockschaltbilder/axis_dma_entity.png}
\caption{Entity der Komponente \texttt{axis\_dma}}
\label{fig:AxisDMA_entity}
\end{figure}
Die Komponente \texttt{axis\_dma} ist die steuernde Komponente in diesem System.
Sie ist für das Lesen und Schreiben der Daten aus dem Speicher über die \emph{M\_AXI} Schnittstelle zuständig.
Dabei werden die gelesenen Datenpakete zunächst an einen FIFO-Speicher über die \emph{M\_AXIS} Schnittstelle weitergegeben.
Über die \emph{M\_AXIS} Schnittstelle werden die Datenpakete mit angehängter Prüfsumme wieder angenommen und zurück in den Speicher geschrieben.
Die Komponente arbeitet bei den Speicherzugriffen über die \emph{M\_AXI} Schnittstelle immer mit möglichst großen Burstlängen, um möglichst effiziente Speicherzugriffe zu gewährleisten.
Um sicherzustellen, dass das System dabei genug Daten aufnehmen bzw. zur Verfügung stellen kann, werden zwei FIFO-Speicher verwendet.
Die maximale Burstlänge in diesem System beträgt 16 Worte.
Die FIFO-Speicher haben eine Tiefe von 256 Worten, um ausreichend Daten puffern zu können, damit bei Verzögerungen der \emph{M\_AXI} Lesezugriffe die CRC-Berechnungskomponente trotzdem ununterbrochen Daten verarbeiten kann.
Die Eingänge \emph{S\_AXIS\_NUM\_AVIL} und \emph{M\_AXIS\_NUM\_FREE} dienen zur Überwachung der Füllstände der FIFO-Speicher.
Abhängig davon, ob genug Daten zum Schreiben oder genug freier Speicher zu Verfügung steht, werden die \emph{M\_AXI} Zugriffe gestartet.
Beim Ausgeben des Datenstroms über die \emph{M\_AXIS} Schnittstelle markiert das \emph{M\_AXIS\_TLAST} Signal das letzte Datenwort eines Pakets.
Die Komponente ist bei Schreib- und Lesebursts in der Lage, 4kB-Adressgrenzen zu erkennen und passt die Burstlängen und die Adressen entsprechend des nächsten Zugriffs an.
Die Schreib- und Leseburst sind in zwei separaten Prozessen bzw. endlichen Automaten aufgeteilt, die weitgehend unabhängig voneinander arbeiten.
Daher kann die Komponente parallel Daten lesen und schreiben.
Des Weiteren hält diese Komponente alle AXIL-Register des IPs, wofür sie eine \emph{S\_AXIL} Schnittstelle besitzt.
Die Register, die zur Konfiguration der CRC-Berechnung dienen, sind als Ausgänge nach Außen geführt.
\subsubsection{CRC-Berechnungskomponente - axis\_crc} \label{sec:CRCBerechnungskomponente}
\begin{figure}[H]
\centering
\includegraphics[width=0.5\textwidth]{Blockschaltbilder/axis_crc_entity.png}
\caption{Entity der Komponente \texttt{axis\_crc}}
\label{fig:AxisCRC_entity}
\end{figure}
In Abbildung~\ref{fig:AxisCRC_entity} ist die Entity der Komponente \texttt{axis\_crc} dargestellt.
Die Eingänge \emph{initialValue}, \emph{polynomial}, \emph{finalXOR} und \emph{inOutReflected} dienen zur Konfiguration der CRC-Berechnung.
Sie fließen in die Kombinatoriken der CRC-Berechnung ein.
Die Berechnung der CRC-Prüfsumme erfolgt wort-weise.
Der Datenstrom von 32-Bit Worten wird über die \emph{S\_AXIS} Schnittstelle eingelesen und wieder über die \emph{M\_AXIS} Schnittstelle ausgegeben.
Dabei kann maximal alle 3 Takte ein Wort eingelesen werden, das in die Berechnung der CRC-Prüfsumme einfließt.
Das Ende eines Datenpaketes wird durch das \emph{S\_AXIS\_TLAST} Signal markiert.
Wenn die Komponente dieses Signal erhält, beendet sie die CRC-Berechnung und gibt das berechnete CRC-Wort über die \emph{M\_AXIS} Schnittstelle aus.
Die CRC-Prüfsumme wird dadurch an den Datenstrom des ursprünglichen Datenpakets angehängt.
Das \emph{LAST}-Signal wird nicht mehr beim letzten Wort des Datenpakets, sondern bei der CRC-Prüfsumme gesetzt.
Nachdem die CRC-Prüfsumme ausgegeben wurde, wird intern das CRC-Register wieder mit dem Initialwert initialisiert.
Die Komponente ist dann wieder bereit, eine neue CRC-Prüfsumme zu berechnen.
Intern erfolgt die Berechnung der CRC-Prüfsumme mithilfe eines endlichen Automaten.
Um keine Timingprobleme zu verursachen, wurde so die Berechnung der CRC-Prüfsumme auf drei Takte aufgeteilt.
\subsection{AXI-CRC-DMA-IP} \label{sec:AXI_CRC_DMA_IP}
\begin{figure}[H]
\centering
\includegraphics[width=1.0\textwidth]{Blockschaltbilder/axi_crc_dma_ip_default_view.png}
\caption{Architecture des IP \texttt{axi\_crc\_dma\_ip}}
\label{fig:CRC_DMA_IP_Architecture}
\end{figure}
In Abbildung~\ref{fig:CRC_DMA_IP_Architecture} ist die Gesamtarchitektur des IPs \texttt{axi\_crc\_dma\_ip} im Detail dargestellt.
Da die Bestandteile des IPs in den vorherigen Abschnitten beschrieben wurden, erfolgt hier noch eine kurze Erläuterung der Gesamtarchitektur des CRC-DMA-IPs.
Die Komponente \texttt{axis\_dma} ist für das Lesen und Schreiben der Daten aus dem Speicher zuständig.
Sie liest so viele Daten, wie zuvor über die AXIL-Register \texttt{Packet Size} und \texttt{Number Packets} konfiguriert wurden.
Die Daten, die aus dem Speicher gelesen werden, werden als AXI-Stream-Datenstrom an das erste FIFO weitergegeben.
Dieses puffert den Datenstrom und gibt ihn an die CRC-Berechnungskomponente \texttt{axis\_crc} weiter, wo aus dem Datenstrom eine bzw. mehrere CRC-Prüfsummen berechnet werden.
Die CRC-Prüfsumme wird an den Datenstrom angehängt und über das zweite FIFO an die DMA-Komponente \emph{axis\_dma} zurückgegeben, um sie zurück in den Speicher zu schreiben.
Sobald alle Datenpakete verarbeitet und wieder in den Speicher geschrieben wurden, wird ein Interrupt ausgelöst, um die CPU zu informieren, dass die CRC-Berechnung abgeschlossen ist.
\subsection{Einbindung in das Gesamtsystem} \label{sec:Einbindung}
\begin{figure}[H]
\centering
\includegraphics[width=1.0\textwidth]{Blockschaltbilder/axi_crc_dma_syn_default_view.png}
\caption{Block-Design des Gesamtsystems: \emph{axi\_crc\_dma\_syn\_1}}
\label{fig:GesamtsystemDefaultView}
\end{figure}
Um das CRC-DMA-IP in ein Gesamtsystem einzubinden, müssen die AXI-Lite und Full-AXI Schnittstellen mit dem Processing System (PS) des Zynq-SoC verbunden werden.
Im hier erstellten Gesamtsystem wurde die Full-AXI-Master Schnittstelle mit der ACP-Schnittstelle verbunden.
Da Speicherzugriffe auf das SDRAM mit der ACP-Schnittstelle über den Cache erfolgen, sind die Daten so stets mit der CPU synchronisiert.
Die GP-Master-AXI Schnittstelle ist mit der AXIL-Slave Schnittstelle des IPs verbunden.
Damit ist die CPU in der Lage, die Konfigurationsregister des IPs zu schreiben und das IP zu starten.
Die Interruptleitung des IPs ist mit dem Interrupt-Controller des Zynq-SoC verbunden.
Der System ILA dient zur genaueren Betrachung der Full-AXI-Bursts IPs auf der Hardware.
Dies wird in Abschnitt~\ref{sec:VerifikationGesamtsystem} genauer beschrieben.
Dieses Gesamtsystem kann nun synthetisiert und implementiert werden.
\newpage
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Software - Treiberfunktion} \label{sec:Software_Treiberfunktion}
\begin{lstlisting}[caption={Struct für CRC-DMA-IP}, label={code:StructCRC}]
typedef struct
{
volatile uint32_t Control; // [0] Run, [1] INT Enable
volatile uint32_t InterruptStatus; // [0] INT Status
volatile uint32_t ReadAddress; // [31:0] Read Address of Data
volatile uint32_t WriteAddress; // [31:0] Write Address of Data + CRC Checksums
volatile uint32_t PacketSize; // [15:0] Size of Packets Minus 1 in 32 Bit words
volatile uint32_t NumberPackets; // [15:0] Number of Packets Minus 1
volatile uint32_t Polynomial; // [31:0] Polynomial for CRC Calculation
volatile uint32_t InitialValue; // [31:0] Initial Value of CRC Calculation
volatile uint32_t FinalXOR; // [31:0] Final XOR Value
volatile uint32_t InOutReflected; // [0] Input Reflected, [1] Output Reflected
volatile uint32_t AxCache; // [3:0] M_AXI AWCache, [7:4] M_AXI ARCache
} CRC_DMA_Typedef;
typedef CRC_DMA_Typedef *PCRC_DMA_Typedef;
\end{lstlisting}
Zur vereinfachten Handhabung des CRC-DMA-IPs wurde ein Struct und eine Treiberfunktion erstellt.
In Codeausschnitt~\ref{code:StructCRC} ist das Struct für das CRC-DMA-IP dargestellt.
\begin{lstlisting}[caption={Struct für CRC-Parameter}, label={code:StructCRCSet}]
typedef struct
{
uint32_t Polynomial;
uint32_t InitalValue;
uint32_t FinalXOR;
bool InputReflected;
bool OutputReflected;
} CrcParameterSet;
// load a specific set of CRC parameters into Hardware
void CRC_DMA_set_parameters(PCRC_DMA_Typedef baseAddr, const CrcParameterSet* parameterSet);
\end{lstlisting}
Für einen einfacheren Umgang mit den CRC-Parametern befindet sich zusätzlich ein Struct für einen Satz an CRC-Parametern.
Diese Struct is in Codeausschnitt~\ref{code:StructCRCSet} dargestellt.
Zum einfachen Setzen der CRC-Parameter im IP kann die Funktion \texttt{void CRC\_DMA\_set\_parameters(...)} genutzt werden.
Beide gezeigten Codeausschnitte sind in der Headerdatei \texttt{axi\_crc\_dma.h} zu finden.
\newpage
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Testkonzept und Ergebnisse}
\subsection{Verifikation der CRC-Berechungskomponente}
Die Korrektheit der von der CRC-Berechnungskomponente berechneten CRC-Prüfsumme ist für das Gesamtsystem von essentieller Bedeutung.
Daher liegt ein besonderes Augenmerk auf der Verifikation dieser Komponente.
\subsubsection{Referenzprogramm} \label{sec:Referenzprogramm}
Zunächst wurde das C-Programm \emph{crc.c} geschrieben, das CRC-Prüfsummen in Software berechnet.
Dieses Programm dient bei der Entwicklung der Hardware als Referenz für die berechneten CRC-Prüfsummen.
Der CRC-Algorithmus wurde hauptsächlich mithilfe von Sunshine2k.de \cite{SunshineCrcErklärung} erstellt.
Parallel wurden die Ergebnisse mit anderen CRC-Online Rechnern verglichen, um die Korrektheit der Berechnung zu überprüfen \cite{crcCalc}.
Kern dieses Programms ist die Funktion \texttt{uint32\_t calcCRC32(...)}, die die CRC-Prüfsumme über ein Datenpaket berechnet.
Mithilfe dieser Funktion können CRC-Prüfsummen für beliebige Datenpakete und für eine beliebige Kombination an CRC-Parametern berechnet werden.
Neben dem testweise Berechnen von Prüfsummen werden in der \texttt{main}-Funktion auch die CRC-Prüfsummen für die Testbench der CRC-Berechnungskomponente berechnet.
Dies geschieht in der Funktion \texttt{void calc\_axis\_crc\_tb()}.
% \begin{lstlisting}[caption={Starten und Stoppen der Übertragung}, label={code:OW_start_transmission}]
% uint32_t calcCRC32(
% uint8_t* inBytes,
% size_t size,
% uint32_t polynomial,
% uint32_t initialValue,
% uint32_t finalXOR,
% uint8_t inputReflected,
% uint8_t outputReflected
% ) {
% uint32_t crc = initialValue;
% uint8_t byte;
% for (size_t i = 0; i < size; i++) {
% byte = inBytes[i];
% if (inputReflected != 0) {
% uint8_t reflected = 0;
% for (int b = 0; b < 8; b++) {
% if ((byte & (1<<b)) != 0) {
% reflected |= (uint8_t) (1<<(7-b));
% }
% }
% byte = reflected;
% }
% crc ^= (uint32_t) (byte << 24);
% for (int bit = 0; bit < 8; bit++) {
% if ((crc & (uint32_t)(1<<31)) != 0) {
% crc = (uint32_t) (crc << 1) ^ polynomial;
% } else {
% crc <<= 1;
% }
% }
% }
% if (outputReflected != 0) {
% uint32_t reflected = 0;
% for (int i = 0; i < 32; i++) {
% if ((crc & (uint32_t) (1<<i)) != 0) {
% reflected |= (uint32_t) (1<<(31-i));
% }
% }
% crc = reflected;
% }
% return crc ^ finalXOR;
% }
% \end{lstlisting}
\subsubsection{Simulation / Testbench} \label{sec:Simulation_CRC_Berechnungskomponente}
Um die Korrektheit der CRC-Berechnungskomponente \emph{axis\_crc} zu gewährleisten, wurde eine Testbench erstellt.
In dieser Testbench werden von der CRC-Berechnungskomponente insgesamt 24 Prüfsummen über dasselbe Datenpaket von drei 32-Bit-Worten mit verschiedenen Parametern berechnet.
Da auch nur ein kleinster Fehler in der Implementierung des CRC-Algorithmus völlig andere Ergebnisse zur Folge hätte, genügt es zunächst nur ein Datenpaket für die Verifikation zu nutzen.
Die Testbench wurde in VHDL geschrieben und überprüft automatisch die Korrektheit der berechneten CRC-Prüfsummen sowie das korrekte Ausgeben der Daten.
\begin{figure}[H]
\centering
\includegraphics[width=1.0\textwidth]{wave_axis_crc.png}
\caption{Wave-Diagramm der \emph{axis\_crc} Testbench}
\label{fig:AxisCrcTestbenchWave}
\end{figure}
In Abbildung~\ref{fig:AxisCrcTestbenchWave} ist ein Ausschnitt des Wave-Diagramms der Testbench dargestellt.
Falls einer der 24 Testfälle fehlschlägt, das heißt, wenn entweder die zugeführten Daten nicht wieder korrekt ausgegeben werden oder wenn die CRC-Prüfsumme falsch ist, wird eine Fehlermeldung ausgegeben.
Somit kann die korrekte Funktionalität der CRC-Berechnungskomponente gewährleistet werden.
Die in dieser Arbeit erstellte CRC-Berechnungskomponente wurde mithilfe dieser Testbench erfolgriech verfiziert.
\subsection{Simulation des CRC-DMA-IPs} \label{sec:Simulation_CRC_DMA_IP}
\begin{figure}[H]
\centering
\includegraphics[width=1.0\textwidth]{Blockschaltbilder/axi_crc_dma_sim_default_view.png}
\caption{Simulation des CRC-DMA-IPs}
\label{fig:BlockschaltbildCRC_DMA_IP_Simulation}
\end{figure}
Zur Simulation des gesamten CRC-DMA-IPs wird das Block-Design \emph{axi\_crc\_dma\_sim\_01} verwendet, das in Abbildung~\ref{fig:BlockschaltbildCRC_DMA_IP_Simulation} dargestellt ist.
Das IP \emph{axil\_master\_with\_rom} ist ein AXIL-Master, der die nötige Konfiguration des CRC-DMA-IPs durchführt und den Vorgang anschließend startet.
Er stammt aus dem IP-Verzeichnis dieser Vorlesung.
Die AXIL-Schreibbefehle für den AXIL-Master sind im Stimuli-Script \emph{axi\_crc\_dma\_sim.stm} definiert.
Das IP \emph{axi3\_slave\_verif} ist ein Baustein, der als Full-AXI-Slave fungiert.
Er akzeptiert Schreibbursts und gibt bei Lesebursts selbst erzeugte Daten wieder.
Dabei hat diese Komponente jedoch keinen internen Speicher, sondern dient nur dazu, korrekte Reaktionen auf Lese- und Schreibbursts zu erzeugen.
Die Adressen und die eigentlichen Daten werden von dieser Komponente nicht verarbeitet.
Das Grundgerüst dieser Komponente wurde mithilfe von ChatGPT erstellt und anschließend in der Simulation etwas angepasst, sodass das Verhalten möglichst dem korrekten Verhalten einer Full-AXI-Slave Schnittstelle entspricht.
In diesem Simulations-Block-Design wird zum einen die Funktionsweise der AXIL-Schnittstelle überprüft.
Das heißt, dass die AXIL-Register richtig geschrieben und gelesen werden können und dass der CRC-DMA-Vorgang über das Kontrollregister gestartet werden kann.
Zum anderen wird vornehmlich das richtige DMA-Verhalten des IPs überprüft.
Dabei sind unter anderem folgende Punkte von Bedeutung:
\begin{itemize}
\item Werden die Valid/Ready-Handshakes korrekt durchgeführt?
\item Werden die korrekten Adressen übergeben?
\item Werden die korrekten Daten übergeben?
\item Wird die korrekte Menge an Daten entsprechend der Konfiguration gelesen?
\item Wird die korrekte Menge an Daten entsprechend der Konfiguration geschrieben?
\item Werden stets maximal mögliche Burstlängen verwendet?
\item Werden 4kB-Adressgrenzen korrekt behandelt?
\item Wird die Interruptleitung nach dem Vorgang korrekt gesetzt?
\end{itemize}
Da es sich um eine manuelle Testbench handelt, werden all diese Punkte durch das Betrachten des Wave-Diagramms überprüft.
Zusätzlich wurden dabei verschiedene Konfigurationen des IPs getetest, um auch die Funktionalität bei unterschiedlichen Parametern zu überprüfen und Edge-Cases mit abzudecken.
\begin{figure}[H]
\centering
\includegraphics[width=1.0\textwidth]{wave_axi_dma_sim_1_ausschnitt.png}
\caption{Exemplarisches Wave-Diagramm der Simulation des CRC-DMA-IPs}
\label{fig:CRC_DMA_IP_SimulationWave}
\end{figure}
\subsection{Verifikation des Gesamtsystems} \label{sec:VerifikationGesamtsystem}
\subsubsection{Testprogramm} \label{sec:Testprogramm}
Die Verifikation des Gesamtsystems erfolgt auf der Hardware.
Für die finale Verifikation des CRC-DMA-IPs bzw. des Gesamtsystems wurde das Testprogramm \texttt{CRC\_DMA.cpp} erstellt, das im Kontext eines Linux Betriebssystems ausgeführt wird.
Das Testprogramm ist in mehrere Testläufe unterteilt.
Der Ablauf eines Testlaufs ist wie folgt:
\begin{enumerate}
\item Auswählen eines neuen CRC-Parameter-Satzes
\item Zufällige Datenpakete erzeugen mit einer zufälligen Paketanzahl und -größe
\item Konfiguration des CRC-DMA-IPs
\item Starten des CRC-DMA-IPs
\item Warten auf den Interrupt des IPs
\item Berechnen der CRC-Prüfsummen in Software zur Verifikation
\item Überprüfen der vom IP geschriebenen Daten und CRC-Prüfsummen
\end{enumerate}
Die Anzahl der Testläufe wird dem Programm als Argument beim Ausführen übergeben.
Die Ausgabe des Programms erfolgt sowohl über die Konsole als auch in eine Logdatei, die automatisch erstellt wird.
\begin{figure}[H]
\centering
\includegraphics[width=0.5\textwidth]{TestprogrammBeispielausgabe.png}
\caption{Ausgabe des Testprogramms}
\label{fig:AusgabeTestprogramm}
\end{figure}
In Abbildung~\ref{fig:AusgabeTestprogramm} ist exemplarisch die Ausgabe des Testprogramms für einen Testlauf dargestellt.
Zur Verifikation des CRC-DMA-IPs können nun mithilfe dieses Programms im großen Umfang CRC-Berechnungsvorgänge ausgeführt werden.
Durch eine große Anzahl an Testläufen kann so sichergestellt werden, dass, wenn das IP fehlerhaft ist, diese Fehler auch entdeckt werden.
Anbei dieser Projektarbeit befindet sich eine Logdatei des Testprogramms, die die Ausgabe für 250 Testläufe enthält.
Ergebnis dieses Tests ist, dass bei einer gelesenen Menge von ca. 1,4 GB Daten keine Fehler aufgetreten sind.
Alle Daten wurden korrekt in den Speicher geschrieben.
Dabei ist anzumerken, dass nur bis zu einer Paketanzahl von 100 und einer Paketgröße von 10000 getestet wurde, auch wenn technisch gesehen sowohl Paketgröße als auch Paketanzahl auf einen Wert bis zu 65535 konfiguriert werden können.
\subsubsection{ILA-Messung}
\begin{figure}[H]
\centering
\includegraphics[width=1.0\textwidth]{ILA_wave_write_4k_boundry_crossing_ausschnitt.png}
\caption{ILA-Messung der Full-AXI-Master Schnittstelle}
\label{fig:ILA_Messung}
\end{figure}
Parallel zur Entwicklung des Testprogramms wurde mithilfe von ILA-Messungen die Funktionalität der Full-AXI-Master Schnittstelle überprüft.
Eine Beispielmessung ist in Abbildung~\ref{fig:ILA_Messung} dargestellt.
So konnte final die korrekte Kommunikation des IPs mit dem Restsystem festgestellt werden.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Fazit und Ausblick}
Es ist gelungen, ein CRC-DMA-IP gemäß den in Abschnitt~\ref{sec:Anforderungen} definierten Anforderungen zu erstellen und umfangreich mit einem Testprogramm zu testen.
Eine mögliche Verbesserung des IPs wäre die Optimierung der CRC-Berechnungskomponente.
Diese ist aktuell der limitierende Faktor für den Datendurchsatz des IPs.
Zum Beispiel könnte die CRC-Berechnung in mehrere Pipeline-Stufen aufgeteilt werden, wodurch der Datendurchsatz theoretisch auf ein 32-Bit-Wort pro Takt erhöht werden kann.
Damit wäre der Datendurchsatz verdreifacht.
Des weiteren könnte eine auf ein Byte genaue Addressieung der Daten implementiert werden.
Damit könnten Datenpakete auch innerhalb eines 32-Bit-Wortes beginnen und/oder enden.
Eine weitere Verbesserungsmöglichkeit wäre die Implementierung einer Stoppfunktion.
Wenn ein Vorgang gestartet wurde, kann dieser aktuell nicht vorzeitig abgebrochen werden.
Dies führt unter Umständen zu unnötigen Wartezeiten.
\newpage
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Anahng}
\subsection{Hardware}
Jegliche Hardwarequelldateien sind im Vivadoprojekt \texttt{axi\_crc\_dma} zu finden.
Dieses beinhaltet folgende VHDL-Quelldateien:
\begin{itemize}
\item \textbf{axis\_crc.vhd}: CRC-Berechnungskomponente siehe Abschnitt~\ref{sec:CRCBerechnungskomponente}
\item \textbf{axis\_crc\_tb.vhd}: Testbench für die CRC-Berechnungskomponente siehe Abschnitt~\ref{sec:Simulation_CRC_Berechnungskomponente}
\item \textbf{axis\_dma.vhd}: DMA-Komponente siehe Abschnitt~\ref{sec:DMAKomponente}
\item \textbf{axi3\_slave\_verif.vhd}: Full-AXI-Slave zur Verifikation des Gesamtsystems siehe Abschnitt~\ref{sec:Simulation_CRC_DMA_IP}
\end{itemize}
Dazu beinhaltet das Vivadoprojekt folgende Block-Designs:
\begin{itemize}
\item \textbf{axi\_crc\_dma\_ip}: Block-Design des CRC-DMA-IPs siehe Abschnitt~\ref{sec:AXI_CRC_DMA_IP}
\item \textbf{axi\_crc\_dma\_sim\_01}: Block-Design zur Simulation des CRC-DMA-IPs siehe Abschnitt~\ref{sec:Simulation_CRC_DMA_IP}
\item \textbf{axi\_crc\_dma\_syn\_01}: Block-Design zur Synthese des Gesamtsystems mit CRC-DMA-IP siehe Abschnitt~\ref{sec:Einbindung}
\end{itemize}
\subsection{Software}
Folgende Programme bzw. Software-Quelldateien wurden erstellt:
\begin{itemize}
\item \textbf{crc.c}: Referenzprogramm zur Berechnung von CRC-Prüfsummen in Software siehe Abschnitt~\ref{sec:Referenzprogramm}
\item \textbf{axi\_crc\_dma.h}: Headerdatei für das CRC-DMA-IP siehe Abschnitt~\ref{sec:Software_Treiberfunktion}
\item \textbf{axi\_crc\_dma.cpp}: Treiberfunktion für das CRC-DMA-IP siehe Abschnitt~\ref{sec:Software_Treiberfunktion}
\item \textbf{CRC\_DMA.cpp}: Testprogramm zur Verifikation des Gesamtsystems siehe Abschnitt~\ref{sec:Testprogramm}
\end{itemize}
%Anhang im ZIP-Ornder außer Litaratur