Kleinere Änderungen

This commit is contained in:
Matthias Biermann
2025-02-17 11:02:02 +01:00
parent f7fd82380f
commit 0cda8a9bd1
5 changed files with 51 additions and 46 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 143 KiB

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.
+14 -14
View File
@@ -6,10 +6,10 @@ Dieses Projekt umfasst die Konzeptionierung und Implementierung eines IPs zur Be
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, welche die Konfiguration und Steuerung des IP-Cores übernimmt.
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, welches 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, welches die Funktionalität des IP-Cores überprüft.
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}
@@ -29,7 +29,7 @@ Die Anforderungen an das Projekt und an das zu erstellende IP umfassen folgende
\subsection{CRC - Theoretische Grundlagen} \label{sec:CRCGrundlagen}
Der Cyclic Redundancy Check (CRC) ist ein Verfahren zur Fehlererkennung, welches in der Regel in digitalen Kommunikationssystemen eingesetzt wird.
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.
@@ -53,7 +53,7 @@ Mit diesen Parametern lässt sich jeder standartisierte CRC-Algorithmus definier
\section{Konzept und Umsetzung des CRC-DMA-IP}
Im Rahmen dieses Projektes wurde ein IP-Block entwickelt, welcher die komplette CRC-DMA Funktionalität beinhaltet.
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.
@@ -194,7 +194,7 @@ Die Schreib- und Leseburst sind in zwei separaten Prozessen bzw. endlichen Autom
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, welche zur Konfiguration der CRC-Berechnung dienen, sind als Ausgänge nach Außen geführt.
Die Register, die zur Konfiguration der CRC-Berechnung dienen, sind als Ausgänge nach Außen geführt.
\subsubsection{CRC-Berechnungskomponente - axis\_crc}
@@ -211,7 +211,7 @@ 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, welches in die Berechnung der CRC-Prüfsumme einfließt.
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.
@@ -330,11 +330,11 @@ Daher liegt ein besonderes Augenmerk auf der Verifikation dieser Komponente.
\subsubsection{Referenzprogramm}
Zunächst wurde das C-Programm \emph{crc.c} geschrieben, welches CRC-Prüfsummen in Software berechnet.
Zunächst wurde das C-Programm \emph{crc.c} geschrieben, das CRC-Prüfsummen in Software berechnet.
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(...)}, welche die CRC-Prüfsumme über ein Datenpaket berechnet.
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.
@@ -423,7 +423,7 @@ Die in dieser Arbeit erstellte CRC-Berechnungskomponente wurde mithilfe dieser T
\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, welches in Abbildung~\ref{fig:BlockschaltbildCRC_DMA_IP_Simulation} dargestellt ist.
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.
@@ -465,7 +465,7 @@ Zusätzlich wurden dabei verschiedene Konfigurationen des IPs getstest, um auch
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, welches im Kontext eines Linux Betriebssystems ausgeführt wird.
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}
@@ -473,13 +473,13 @@ Der Ablauf eines Testlaufs ist wie folgt:
\item Zufällige Datenpakete erzeugen mit einer zufälligen Paketanzahl und -größe
\item Konfiguration der CRC-DMA-IPs
\item Starten des CRC-DMA-IPs
\item Berechnen der CRC-Prüfsummen in Software zur Verifikation
\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 Ausgabe des Programms erfolgt sowohl über die Konsole als auch in eine Logdatei, die automatisch erstellt wird.
\begin{figure}[H]
\centering
@@ -492,7 +492,7 @@ In Abbildung~\ref{fig:AusgabeTestprogramm} ist exemplarisch die Ausgabe des Test
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, welche die Ausgabe für 100 Testläufe enthält.
Anbei dieser Projektarbeit befindet sich eine Logdatei des Testprogramms, die die Ausgabe für 100 Testläufe enthält.
Ergebnis dieses Tests ist, dass bei insgesamt gelesenen Menge von ca. 100MB Daten keine Fehler aufgetreten sind.
Alle Daten wurden korrekt in den Speicher geschrieben.
+1 -1
View File
@@ -45,7 +45,7 @@
breaklines=true, % Automatischer Zeilenumbruch
frame=single, % Rahmen um den Codeblock
captionpos=b, % Position der Beschriftung
morekeywords={uint32_t, uint16_t, uint8_t, size_t},
morekeywords={uint32_t, uint16_t, uint8_t, size_t, CrcParameterSet, PCRC_DMA_Typedef, CRC_DMA_Typedef},
}
%Zum Zusammenfügen von Spalten in tabular
+36 -31
View File
@@ -14,7 +14,6 @@
#include <time.h>
#include "axi_crc_dma.h"
#include "gip.h"
// #define DEBUG
@@ -38,7 +37,23 @@ uint32_t calcCRC32(
int main(int argc, char** argv)
{
int testRuns;
// Testlaeufe, Paketgroesse und Paketanzahl
int testRuns = TEST_RUNS;
// int maxPacketSize = MAX_PACKET_SIZE;
// int maxNumberPackets = MAX_NUMBER_PACKETS;
// Argumente auswerten
if (argc > 1) {
testRuns = atoi(argv[1]);
}
// if (argc > 2) {
// maxPacketSize = atoi(argv[2]);
// }
// if (argc > 3) {
// maxNumberPackets = atoi(argv[3]);
// }
// Logdatei anlegen
char logFileName[100];
time_t now = time(NULL);
struct tm *t = localtime(&now);
@@ -51,13 +66,6 @@ int main(int argc, char** argv)
return 1;
}
if (argc < 2) {
testRuns = TEST_RUNS;
}
else {
testRuns = atoi(argv[1]);
}
// some established CRC32 Parameter sets. Source: https://reveng.sourceforge.io/crc-catalogue/ (13.02.2025)
const CrcParameterSet CRC32_AIXM = {
.Polynomial = 0x814141ab,
@@ -110,9 +118,6 @@ int main(int argc, char** argv)
PCRC_DMA_Typedef CRC = (PCRC_DMA_Typedef) mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fdCRC, 0);
uint32_t* pMem = (uint32_t*) mmap(NULL, 0x20000000, PROT_READ | PROT_WRITE, MAP_SHARED, fdMem, 0);
// Interrupt zuruecksetzen
CRC->InterruptStatus = 0;
// Physische Adressen anlegen
uint32_t uio16PhysBase = 0x30000000; // UIO16 physical Baseaddress
uint32_t* pDataPhy = (uint32_t*) uio16PhysBase;
@@ -170,6 +175,21 @@ int main(int argc, char** argv)
fprintf(logFile, "CRC-Berechnung in Hardware starten\n");
CRC->Control |= (1<<0);
// Auf INT warten
printf("Auf Interrupt warten...\n");
fprintf(logFile, "Auf Interrupt warten...\n");
int pending;
read(fdCRC, (void*) &pending, 4);
CRC->InterruptStatus = 0;
write(fdCRC, (void*) &reenable, 4);
printf("Interrupt erhalten\n");
fprintf(logFile, "Interrupt erhalten\n");
// Hardwareergebnis in Array ablegen
for (int p = 0; p < number_packets; p++) {
crc_hw[p] = DataDest[p][packet_size];
}
// CRC Berechnung in Software durchfuehren
printf("CRC-Berechnung in Software durchfuehren\n");
fprintf(logFile, "CRC-Berechnung in Software durchfuehren\n");
@@ -187,21 +207,6 @@ int main(int argc, char** argv)
// fprintf(logFile, "Packet %i:\t0x%08x\n", p, crc_sw[p]);
}
// Auf INT warten
printf("Auf Interrupt warten...\n");
fprintf(logFile, "Auf Interrupt warten...\n");
int pending;
read(fdCRC, (void*) &pending, 4);
CRC->InterruptStatus = 0;
write(fdCRC, (void*) &reenable, 4);
printf("Interrupt erhalten\n");
fprintf(logFile, "Interrupt erhalten\n");
// Hardwareergebnis in Array ablegen
for (int p = 0; p < number_packets; p++) {
crc_hw[p] = DataDest[p][packet_size];
}
#ifdef DEBUG
// data und DataDest komplett ausgeben
printf("\ndata\tDataDest:\n");
@@ -225,8 +230,8 @@ int main(int argc, char** argv)
// Daten und Ergebnisse vergleichen
unsigned int wrongWords = 0; // Zaehler fuer Anzahl der fehlerhaften Worte im (Ziel-)Speicher
printf("Daten und Ergebnisse vergleichen\n\n");
fprintf(logFile, "Daten und Ergebnisse vergleichen\n\n");
printf("Daten und Ergebnisse vergleichen:\n");
fprintf(logFile, "Daten und Ergebnisse vergleichen:\n");
bool allPaketsOK = true;
for (int p = 0; p < number_packets; p++) {
bool dataOK = true;
@@ -272,8 +277,8 @@ int main(int argc, char** argv)
}
if (allPaketsOK) {
printf("Alle Pakete OK\nTestdurchlauf erfolgreich abgeschlossen!\n");
fprintf(logFile, "Alle Pakete OK\nTestdurchlauf erfolgreich abgeschlossen!\n");
printf("Alle Pakete OK\nTestlauf erfolgreich abgeschlossen!\n");
fprintf(logFile, "Alle Pakete OK\nTestlauf erfolgreich abgeschlossen!\n");
} else {
allTestrunsOK = false;
printf("Ein oder mehrere Pakete nicht OK.\n");