HWDigSys-II/report/report.tex

345 lines
22 KiB
TeX
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

%
% !TEX TS-program = xelatex
% !TEX encoding = UTF-8 Unicode
% !TEX spellcheck = el-GR
%
% Low-Level HW Digital Systems II coursework report
%
%
% authors:
% Χρήστος Χουτουρίδης ΑΕΜ 8997
% cchoutou@ece.auth.gr
% Options:
%
% 1) mainlang=<language>
% Default: english
% Set the default language of the document which affects hyphenations,
% localization (section, dates, etc...)
%
% example: \documentclass[mainlang=greek]{AUThReport}
%
% 2) <language>
% Add hyphenation and typesetting support for other languages
% Currently supports: english, greek, german, frenc
%
% example: \documentclass[english, greek]{AUThReport}
%
% 3) short: Requests a shorter title for the document
% Default: no short
%
% example: \documentclass[short]{AUThReport}
%
\documentclass[a4paper, 11pt, mainlang=greek, english]{AUThReport}
\CurrentDate{\today}
% Greek report document setup suggestions
%---------------------------------
% Document configuration
\AuthorName{Χρήστος Χουτουρίδης}
\AuthorAEM{8997}
\AuthorMail{cchoutou@ece.auth.gr}
%\CoAuthorName{CoAuthor Name}
%\CoAuthorAEM{AEM}
%\CoAuthorMail{CoAuthor Mail}
% \WorkGroup{Ομάδα Χ}
\DocTitle{Εργασία}
\DocSubTitle{Πολλαπλασιασμός αριθμών κινητής υποδιαστολής}
\Department{Τμήμα ΗΜΜΥ. Τομέας Ηλεκτρονικής}
\ClassName{Ψηφιακά Συστήματα HW σε Χαμηλά Επίπεδα Λογικής II}
\InstructorName{Βασίλης Παυλίδης}
\InstructorMail{ }
\CoInstructorName{Ευάγγελος Τζουβάρας}
\CoInstructorMail{ }
% Local package requirements
%---------------------------------
%\usepackage{tabularx}
%\usepackage{array}
%\usepackage{commath}
\usepackage{amsmath, amssymb, amsfonts}
\usepackage{graphicx}
\usepackage{subcaption}
\usepackage{float}
% Requires: -shell-escape compile argument
\usepackage{minted}
\usepackage{xcolor}
\newminted{verilog}{
fontsize=\small,
breaklines,
autogobble,
%frame=lines,
%framesep=5pt,
baselinestretch=1.1,
tabsize=2,
%bgcolor=LightGray,
numbersep=8pt,
gobble=0
}
\newcommand{\icode}[1]{\mintinline{verilog}{#1}}
\newcommand{\repo}{https://git.hoo2.net/hoo2/HWDigSys-II}
\newcommand{\repoNopipeline}{https://git.hoo2.net/hoo2/HWDigSys-II/src/branch/no-pipeline}
\begin{document}
% Request a title page or header
\InsertTitle
\section{Εισαγωγή}
Η παρούσα εργασία αφορά στην υλοποίηση ενός πολλαπλασιαστή αριθμών κινητής υποδιαστολής μονής ακρίβειας (IEEE-754 single-precision) σε γλώσσα περιγραφής υλικού SystemVerilog.
Η σχεδίαση του κυκλώματος ακολουθεί μια αρθρωτή και κλιμακούμενη προσέγγιση, βασισμένη σε δομή pipeline τριών σταδίων.
Το κύριο ζητούμενο ήταν η διαχωρισμένη υλοποίηση της κανονικοποίησης, της στρογγυλοποίησης και της διαχείρισης εξαιρέσεων, με δυνατότητα ελέγχου διαφορετικών τρόπων στρογγυλοποίησης.
\par
Στόχος της εργασίας είναι η κατανόηση της εσωτερικής λειτουργίας των αριθμητικών μονάδων κινητής υποδιαστολής, η υλοποίηση τους σε επίπεδο RTL και η επαλήθευση της σωστής λειτουργίας τους μέσω εκτενούς ελέγχου με test benches.
Η εργασία απαιτεί κατανόηση τόσο της γλώσσας SystemVerilog όσο και του προτύπου IEEE-754, και συνδυάζει αρχιτεκτονική σχεδίαση, ψηφιακή λογική και επαλήθευση μέσω προσομοίωσης.
\subsection{Παραδοτέα}
Τα παραδοτέα της εργασίας αποτελούνται από:
\begin{itemize}
\item Την παρούσα αναφορά.
\item Τον κατάλογο \textbf{src/}, που περιέχει τον κώδικα της SystemVerilog με τα ζητηθέντα modules.
\item Τον κατάλογο \textbf{sim/}, που περιέχει το ζητηθέν test bench αλλά και επιμέρους tests για τα υπόλοιπα modules (πλην του exception handler).
\item Το \href{\repo}{σύνδεσμο} με το αποθετήριο που περιέχει όλο το project στο vsim, τους κώδικες της SystemVerilog και της αναφοράς καθώς και τα παραδοτέα.
\end{itemize}
Στην εργασία \textbf{δεν} υλοποιήθηκαν τα εξής:
\begin{itemize}
\item \textit{Όλοι οι 144} συνδυασμοί των corner cases για το test bench με βάση τους τυχαίους αριθμούς και τον έλεγχο μέσω multiplication.sv.
Αντ' αυτού δημιουργήθηκαν test cases που ελέγχουν τόσο την “κανονική” λειτουργία όσο και αρκετά corner cases αλλά οι τιμές τους εισήχθηκαν \textit{με το χέρι}.
\item Το μέρος με τα \textit{immediate assertions}.
\end{itemize}
\section{Προσέγγιση Υλοποίησης}
Για την εργασία χρησιμοποιήσαμε μια \textbf{αρθρωτή} προσέγγιση.
Καθώς η πολυπλοκότητα έμοιαζε αρκετά μεγάλη, σε συνδυασμό με τη μικρή προσωπική εμπειρία σε ψηφιακή σχεδίαση με verilog, προτιμήσαμε να ακολουθήσουμε μια \textbf{test driven} προσέγγιση ανά module.
Έτσι χωρίσαμε την ανάπτυξη στα modules που πρότεινε η εκφώνηση και για αυτά δημιουργήσαμε test benches.
Τα βασικά tests που θα χρειαζόταν να υλοποιηθούν πρώτα ήταν για τα \textit{normalize} και \textit{round}.
Το \textit{exception handler} θα μπορούσε να εκμαιευτεί με “αφαίρεση” των παραπάνω από το συνολικό test bench του \textit{fp\_mult}.
Όλα αυτά τα αρχεία μπορούν να βρεθούν στον κατάλογο \textit{sim/}.
\par
Τα test αυτά αν και κάπως τετριμμένα, έπαιξαν πολύ σημαντικό ρόλο στην υλοποίηση καθώς μας δώσανε τη δυνατότητα να χωριστούν τα interfaces των modules και να πιστοποιήσουν ότι η αναγκαία λειτουργικότητα είναι παρούσα.
Κάτι που φυσικά μας βοήθησε στην απομόνωση των σφαλμάτων κλπ...
\par
Έχοντας υλοποιήσει λοιπόν τα test προβήκαμε στην υλοποίηση των ίδιων των modules.
Αρχικά υλοποιήσαμε τα \textit{normalize} και \textit{round} και έπειτα το \textit{fp\_mult}.
Με αυτά τα τρία να περνούν τα επιμέρους tests προχωρήσαμε στην υλοποίηση του \textit{exception handler}.
Για αυτό το module δεν υλοποιήσαμε πρώτα tests καθώς υπήρχαν τα συνολικά tests και το μόνο modul-άκι που “άλλαζε” ήταν αυτό.
\par
Τέλος με όλη τη λειτουργικότητα έτοιμη, προβήκαμε στην τελευταία αλλαγή, που ήταν η μετατροπή της λογικής για χρήση \textbf{pipeline τριών σταδίων}.
Μιας και τα αρχεία για τα tests για το pipeline είναι διαφορετικά από τα αρχικά, ο αναγνώστης μπορεί \href{\repoNopipeline}{εδώ} να βρει αυτή την ενδιάμεση έκδοση.
\subsection{Pipeline}
Η αρχική υλοποίηση όπως είδαμε είχε combinational logic.
Επομένως το αποτέλεσμα του πολλαπλασιασμού θα ήταν διαθέσιμο σε κάθε clock του ρολογιού του \textit{fp\_mult\_top}.
Παρόλα αυτά ο διαχωρισμός σε 3 στάδια μειώνει αρκετά το βάθος, χωρίς να μεγαλώνει την ανάγκη για extra clock ticks.
Αντ' αυτού μειώνει το συνολικό latency.
Τα στάδια που χρησιμοποιήθηκαν είναι με τη σειρά τα εξής:
\begin{enumerate}
\item \textbf{Normalize}: Όπου καλείται το normalize\_mult.
\item \textbf{Round}: Όπου καλείται το round\_mult και το
\item \textbf{Exception handler}: Όπου καλείται το exception\_mult
\end{enumerate}
\par
Για το pipeline εργαστήκαμε με γνώμονα τη διατήρηση όλης της απαραίτητης πληροφορίας στα στάδια, ούτως ώστε ο χρήστης να μπορεί σε κάθε clock να τροφοδοτεί το module με διαφορετικούς αριθμούς για πολλαπλασιασμό.
Όλα τα σήματα από την είσοδο τροφοδοτούνται από το ένα στάδιο στο επόμενο.
Η μετάδοση αυτή σταματάει μόνο αν τα σήματα δεν είναι απαραίτητα για τη λειτουργία του επόμενου module.
Με αυτό τον τρόπο για παράδειγμα όλη η απαραίτητη πληροφορία για το κάθε module, περνάει από το ένα στάδιο στο επόμενο σε κάθε clock.
Για την ακρίβεια, μετά τον αρχικό υπολογισμό του πρόσημου καθώς και του αποτελέσματος του πολλαπλασιασμού για τον εκθέτη και τη mantissa:
\begin{itemize}
\item Οι \textbf{αριθμοί} προς πολλαπλασιασμό φτάνουνε μέχρι τον exception handler.
\item Ο \textbf{εκθέτης} και η \textbf{mantissa} φτάνει μέχρι τον exception handler, όπου και συνθέτει τον τελικό αριθμό πριν την είσοδο.
\item To υπολογισμένο \textbf{πρόσημο} του τελικού αριθμού φτάνει μέχρι το round module.
\item Τα \textbf{guard} και \textbf{sticky} bits φτάνουν από το normalize μέχρι το round module.
\item To \textbf{inexact} bit από το round μέχρι το exception handler.
\end{itemize}
\par
Ενώ επιλέξαμε να υποστηρίξουμε με pipeline όλη σχεδόν την πληροφορία, ένα σήμα δεν ακολουθεί την οδό των σταδίων.
Πρόκειται για το \textbf{round}.
Ενώ για τα υπόλοιπα θεωρήσαμε πως ο χρήστης πρέπει να μπορεί να τα αλλάζει σε κάθε clock του ρολογιού, αυτό υποθέσαμε ότι θα επιλέγεται κατά την έναρξη και θα \textbf{παραμένει αμετάβλητο κάθ' όλη τη διάρκεια λειτουργίας}.
Για το λόγο αυτό, δεν χρειάστηκε να το “περάσουμε” από τα στάδια.
\section{Λεπτομέρειες Υλοποίησης}
\subsection{\texttt{fp\_mult.sv} --- Floating Point Multiplier (Top Module)}
Το module \texttt{fp\_mult} υλοποιεί έναν πλήρως καταχωρημένο πολλαπλασιαστή αριθμών κινητής υποδιαστολής μονής ακρίβειας (IEEE-754).
Αποτελείται από ένα pipeline 3 σταδίων:
\begin{itemize}
\item \textbf{Stage 0 (Decode)}:
Εξάγει πρόσημο, εκθέτες και mantissas από τις εισόδους \texttt{a}, \texttt{b}.
Υπολογίζει το αρχικό γινόμενο mantissas και το bias-adjusted εκθέτη.
Η λειτουρία αυτή βρίσκεται σε ένα section με combinational logic.
\begin{verilogcode}
sign = a[31] ^ b[31];
exp_a = a[30:23];
exp_b = b[30:23];
s0_exponent = exp_a + exp_b - 127;
mant_a = (exp_a == 0) ? {1'b0, a[22:0]} : {1'b1, a[22:0]};
mant_b = (exp_b == 0) ? {1'b0, b[22:0]} : {1'b1, b[22:0]};
s0_mantissa = mant_a * mant_b;
\end{verilogcode}
\item \textbf{Stage 1 (Normalize)}:
Κανονικοποιεί το αποτέλεσμα, προσαρμόζοντας την mantissa και τον εκθέτη.
Παράγει επίσης guard και sticky bits για στρογγυλοποίηση.
\item \textbf{Stage 2 (Round)}:
Εφαρμόζει τον επιλεγμένο τρόπο στρογγυλοποίησης και υπολογίζει την τελική mantissa και εκθέτη καθώς και το σήμα inexact.
\item \textbf{Stage 3 (Exception Handling)}:
Εντοπίζει καταστάσεις όπως NaN, infinities, overflow/underflow, μηδενικά και υπολογίζει την τελική έξοδο \texttt{z} και το flag \texttt{status}.
\end{itemize}
Υποστηρίζει ασύγχρονη επαναφορά (\texttt{rst}) και συγχρονισμό μέσω ρολογιού (\texttt{clk}).
\subsection{\texttt{normalize\_mult.sv} --- Normalize Stage}
Το module αυτό δέχεται ένα 48-bit mantissa και έναν 10-bit εκθέτη. Ελέγχει εάν χρειάζεται shift για κανονικοποίηση της mantissa (ώστε να ξεκινά από MSB=1) και αντίστοιχα προσαρμόζει τον εκθέτη.
\begin{itemize}
\item \texttt{mantissa\_out}: Κανονικοποιημένη mantissa (23 bits)
\item \texttt{guard\_bit, sticky\_bit}: Χρήσιμα για την ακρίβεια στη στρογγυλοποίηση
\item \texttt{exponent\_out}: Νέος εκθέτης μετά την κανονικοποίηση
\end{itemize}
\subsection{\texttt{round\_mult.sv} --- Round Stage}
Το module εφαρμόζει έναν από τους υποστηριζόμενους τρόπους στρογγυλοποίησης σύμφωνα με το IEEE-754 standard:
\begin{itemize}
\item Round to Nearest Even
\item Round Toward Zero
\item Round Toward $\inf$
\item Round Toward $-\inf$
\item Near-Up
\item Away from Zero
\end{itemize}
Για κάθε διαφορετικό mode με βάση το round υλοποιεί διαφορετική προσέγγιση.
Για παράδειγμα για IEEE nearest\ event έχουμε:
\begin{verilogcode}
if (guard_bit && (sticky_bit || mantissa_extended[0])) begin
mantissa_rounded = mantissa_extended + 1;
end
\end{verilogcode}
Ενώ για IEEE pinf:
\begin{verilogcode}
if (!sign_in && (guard_bit | sticky_bit)) begin
mantissa_rounded = mantissa_extended + 1;
end
\end{verilogcode}
Η υλοποίηση των modes έγινε με διαφορετικές συναρτήσεις, μέσα στο module.
Οι είσοδοι περιλαμβάνουν την mantissa, τον εκθέτη, το πρόσημο και τα bits \texttt{guard} και \texttt{sticky}.
Οι έξοδοι είναι η νέα mantissa και ο εκθέτης μετά τη στρογγυλοποίηση, καθώς και το σήμα \texttt{inexact}.
\subsection{\texttt{round\_modes.sv} --- Round Mode Helpers}
Ορίζει ένα enumeration τύπο \texttt{round\_mode\_t} για τους 6 υποστηριζόμενους τρόπους στρογγυλοποίησης, που χρησιμοποιούνται κυρίως κατά τον χειρισμό overflow και underflow στην εξαίρεση.
\begin{verilogcode}
typedef enum logic [2:0] {
RND_IEEE_NEAREST_EVEN = 3'd0,
RND_IEEE_ZERO = 3'd1,
RND_IEEE_PINF = 3'd2,
RND_IEEE_NINF = 3'd3,
RND_NEAR_UP = 3'd4,
RND_AWAY_ZERO = 3'd5
} round_mode_t;
\end{verilogcode}
\subsection{\texttt{exception\_mult.sv} --- Exception Handling}
Αυτό το module χειρίζεται corner cases και ειδικές τιμές:
\begin{itemize}
\item Ανίχνευση και χειρισμός NaNs, infinities, zero
\item Overflow/underflow μετά τη στρογγυλοποίηση
\item Ορισμός της τελικής τιμής \texttt{z}
\item Ορισμός των status flags: \texttt{zero\_f}, \texttt{inf\_f}, \texttt{nan\_f}, \texttt{tiny\_f}, \texttt{huge\_f}, \texttt{inexact\_f}
\end{itemize}
Χρησιμοποιεί ένα \texttt{enum interp\_t} για την κατηγοριοποίηση αριθμών (ZERO, INF, NORM, MIN\_NORM, MAX\_NORM) και δύο συναρτήσεις:
\begin{itemize}
\item \texttt{num\_interp()}: Επιστρέφει το είδος του αριθμού (π.χ., αν είναι infinity ή zero)
\item \texttt{z\_num()}: Επιστρέφει την bitwise αναπαράσταση ενός αριθμού βάσει του είδους του
\end{itemize}
Η λογική ελέγχει τους συνδυασμούς εισόδων και εφαρμόζει τις κατάλληλες ενέργειες βάσει πίνακα (table 4) και του rounding mode.
Ο βασικός κορμός είναι μια switch case όπου γίνεται το dispatch όλων των corner cases:
\begin{verilogcode}
a_class = num_interp(a);
b_class = num_interp(b);
case ({a_class, b_class})
{ZERO, ZERO}, {ZERO, NORM}, {NORM, ZERO}: // ...
{ZERO, INF}, {INF, ZERO}: // ...
{INF, INF}, {NORM, INF}, {INF, NORM}: // ...
default: // {NORM, NORM} ...
endcase
\end{verilogcode}
Ειδικά στο default βρίσκεται η λογική του extra rounding όταν έχουμε NaN, Inf, κλπ.
\section{Επαλήθευση και Επικύρωση}
Όπως αναφέραμε παραπάνω οι επαλήθευση έγινε σταδιακά.
Σε κάθε αρχείο στον κατάλογο \textit{sim/} υπάρχουν tests που επιβεβαιώνουν την ορθή λειτουργία του κάθε module.
Για να τρέξουμε τα test χρησιμοποιήσαμε το vsim.
Για παράδειγμα για τα test του round\_mult:
\begin{verbatim}
vlog sim/round_mult_tb
vsim -voptargs=+acc work.round_tb
run 400ns
\end{verbatim}
Όλες οι εκτελέσεις εμφανίζουν μηνύματα στην κονσόλα με τα αποτελέσματα.
\par
Τα τελικά tests που ανήκουν στο fp\_mult\_top\_tb έχουν ελέγχους που ακολουθούν κάποια test vectors όπως παρακάτω:
\begin{verilogcode}
initial begin
$display("Starting fp_mult test...\n");
// Test cases
tests[0] = '{32'h3f800000, 32'h40000000, 32'h40000000, "+1.0 * +2.0 = +2.0"};
tests[1] = '{32'h40400000, 32'h40400000, 32'h41100000, "+3.0 * +3.0 = +9.0"};
tests[2] = '{32'hc0400000, 32'h40400000, 32'hc1100000, "-3.0 * +3.0 = -9.0"};
tests[3] = '{32'hbf800000, 32'h40000000, 32'hc0000000, "-1.0 * +2.0 = -2.0"};
// ...
end
\end{verilogcode}
Με βάση αυτά τα vectors, παράγονται μηνύματα που έχουν τη μορφή:
\begin{verbatim}
# [8] +12.34 * -0.0001 = -0.001234
# A=414570a4 B=b8d1b717 => Z=baa1be2b (expected baa1be2b) PASS
\end{verbatim}
Ένα στιγμιότυπο από την έξοδο φαίνεται στην εικόνα \ref{fig:output}.
\begin{figure}[!ht]
\centering
\includegraphics[width=0.9\textwidth]{img/ConsoleOutput.png}
\caption{Στιγμιότυπο εξόδου.}
\label{fig:output}
\end{figure}
\section{Συμπεράσματα}
Μέσα από την παρούσα εργασία υλοποιήθηκε με επιτυχία μια πλήρως καταχωρημένη αριθμητική μονάδα πολλαπλασιασμού αριθμών κινητής υποδιαστολής, σύμφωνα με το πρότυπο IEEE-754.
Η υλοποίηση με χρήση pipeline τριών σταδίων προσέφερε βελτιωμένη απόδοση και σαφή διαχωρισμό λειτουργιών, καθιστώντας τη σχεδίαση πιο ευέλικτη και επεκτάσιμη.
Ο διαχωρισμός σε modules με αυστηρά ορισμένα interfaces διευκόλυνε την ανάπτυξη και τον έλεγχο των επιμέρους λειτουργιών, ενώ η προσέγγιση βασισμένη σε επαλήθευση (test-driven development) διασφάλισε την ορθότητα κάθε σταδίου.
\par
Αν και δεν καλύφθηκαν όλοι οι δυνατοί συνδυασμοί corner cases, η λογική του κυκλώματος και οι ενδείξεις των αποτελεσμάτων επαληθεύουν ότι η λειτουργία του multiplier είναι σε μεγάλο βαθμό ορθή.
Η εργασία παρείχε μια ουσιαστική εμπειρία στην πρακτική υλοποίηση σύνθετων αριθμητικών μονάδων σε χαμηλό επίπεδο, αναδεικνύοντας τις προκλήσεις αλλά και τις δυνατότητες της σύγχρονης ψηφιακής σχεδίασης.
\end{document}