Compare commits

...

4 Commits

11 changed files with 632 additions and 186 deletions

BIN
Choutouridis_8997.zip Normal file

Binary file not shown.

View File

@ -11,7 +11,7 @@ module fp_mult_top (
logic [31:0] a1, b1; // Floating-Point numbers
logic [2:0] rnd1; // Rounding signal
logic [31:0] z1; // a ± b
logic [31:0] z1; // a * b
logic [7:0] status1; // Status Flags
fp_mult multiplier(a1,b1,rnd1,z1,status1,clk,rst);

View File

@ -2304,25 +2304,27 @@ suppress = 8780 ;an explanation can be had by running: verror 8780
Project_Version = 6
Project_DefaultLib = work
Project_SortMethod = unused
Project_Files_Count = 9
Project_File_0 = /home/hoo2/Public/AUTH/HWDigSys-II/fpu_mult/fp_mult_top.sv
Project_File_P_0 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 vlog_noload 0 folder {Top Level} last_compile 1749470139 cover_fsm 0 cover_branch 0 cover_excludedefault 0 vlog_enable0In 0 vlog_disableopt 0 cover_covercells 0 voptflow 1 vlog_showsource 0 vlog_hazard 0 cover_optlevel 3 toggle - vlog_0InOptions {} ood 0 cover_noshort 0 vlog_upper 0 compile_to work vlog_options {} compile_order 0 cover_expr 0 dont_compile 0 cover_stmt 0
Project_File_1 = /home/hoo2/Public/AUTH/HWDigSys-II/fpu_mult/src/normalize_mult.sv
Project_File_P_1 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 vlog_noload 0 folder src last_compile 1749838823 cover_fsm 0 cover_branch 0 vlog_enable0In 0 cover_excludedefault 0 vlog_disableopt 0 cover_covercells 0 cover_optlevel 3 vlog_hazard 0 vlog_showsource 0 voptflow 1 ood 0 vlog_0InOptions {} toggle - vlog_options {} compile_to work vlog_upper 0 cover_noshort 0 compile_order 2 dont_compile 0 cover_expr 0 cover_stmt 0
Project_File_2 = /home/hoo2/Public/AUTH/HWDigSys-II/fpu_mult/src/round_modes.sv
Project_File_P_2 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 folder src last_compile 1749985365 cover_fsm 0 cover_branch 0 vlog_noload 0 cover_excludedefault 0 vlog_enable0In 0 vlog_disableopt 0 cover_covercells 0 voptflow 1 vlog_showsource 0 vlog_hazard 0 cover_optlevel 3 toggle - vlog_0InOptions {} ood 0 cover_noshort 0 vlog_upper 0 compile_to work vlog_options {} compile_order 8 cover_expr 0 dont_compile 0 cover_stmt 0
Project_Files_Count = 10
Project_File_0 = /home/hoo2/Public/AUTH/HWDigSys-II/fpu_mult/src/normalize_mult.sv
Project_File_P_0 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 last_compile 1749838823 cover_fsm 0 cover_branch 0 vlog_noload 0 folder src vlog_enable0In 0 cover_excludedefault 0 vlog_disableopt 0 cover_covercells 0 cover_optlevel 3 vlog_hazard 0 vlog_showsource 0 voptflow 1 ood 0 vlog_0InOptions {} toggle - vlog_options {} compile_to work vlog_upper 0 cover_noshort 0 compile_order 2 dont_compile 0 cover_expr 0 cover_stmt 0
Project_File_1 = /home/hoo2/Public/AUTH/HWDigSys-II/fpu_mult/fp_mult_top.sv
Project_File_P_1 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 cover_fsm 0 cover_branch 0 vlog_noload 0 folder {Top Level} last_compile 1750010789 cover_excludedefault 0 vlog_enable0In 0 vlog_disableopt 0 cover_covercells 0 voptflow 1 vlog_showsource 0 vlog_hazard 0 cover_optlevel 3 toggle - vlog_0InOptions {} ood 0 cover_noshort 0 vlog_upper 0 compile_to work vlog_options {} compile_order 0 cover_expr 0 dont_compile 0 cover_stmt 0
Project_File_2 = /home/hoo2/Public/AUTH/HWDigSys-II/fpu_mult/sim/round_mult_tb.sv
Project_File_P_2 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 cover_branch 0 vlog_noload 0 folder sim last_compile 1749484994 cover_fsm 0 cover_excludedefault 0 vlog_enable0In 0 vlog_disableopt 0 cover_covercells 0 voptflow 1 vlog_showsource 0 vlog_hazard 0 cover_optlevel 3 toggle - vlog_0InOptions {} ood 0 cover_noshort 0 vlog_upper 0 compile_to work vlog_options {} compile_order 6 cover_expr 0 dont_compile 0 cover_stmt 0
Project_File_3 = /home/hoo2/Public/AUTH/HWDigSys-II/fpu_mult/src/fp_mult.sv
Project_File_P_3 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 vlog_noload 0 folder src last_compile 1749991254 cover_fsm 0 cover_branch 0 vlog_enable0In 0 cover_excludedefault 0 vlog_disableopt 0 cover_covercells 0 cover_optlevel 3 vlog_hazard 0 vlog_showsource 0 voptflow 1 ood 0 vlog_0InOptions {} toggle - vlog_options {} compile_to work vlog_upper 0 cover_noshort 0 compile_order 3 dont_compile 0 cover_expr 0 cover_stmt 0
Project_File_4 = /home/hoo2/Public/AUTH/HWDigSys-II/fpu_mult/sim/round_mult_tb.sv
Project_File_P_4 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 last_compile 1749484994 cover_fsm 0 cover_branch 0 vlog_noload 0 folder sim cover_excludedefault 0 vlog_enable0In 0 vlog_disableopt 0 cover_covercells 0 voptflow 1 vlog_showsource 0 vlog_hazard 0 cover_optlevel 3 toggle - vlog_0InOptions {} ood 0 cover_noshort 0 vlog_upper 0 compile_to work vlog_options {} compile_order 6 cover_expr 0 dont_compile 0 cover_stmt 0
Project_File_5 = /home/hoo2/Public/AUTH/HWDigSys-II/fpu_mult/src/exception_mult.sv
Project_File_P_5 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 cover_fsm 0 cover_branch 0 vlog_noload 0 folder src last_compile 1749989714 vlog_enable0In 0 cover_excludedefault 0 vlog_disableopt 0 cover_covercells 0 cover_optlevel 3 vlog_hazard 0 vlog_showsource 0 voptflow 1 ood 0 vlog_0InOptions {} toggle - vlog_options {} compile_to work vlog_upper 0 cover_noshort 0 compile_order 7 dont_compile 0 cover_expr 0 cover_stmt 0
Project_File_P_3 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 vlog_noload 0 folder src last_compile 1750010789 cover_fsm 0 cover_branch 0 vlog_enable0In 0 cover_excludedefault 0 vlog_disableopt 0 cover_covercells 0 cover_optlevel 3 vlog_hazard 0 vlog_showsource 0 voptflow 1 ood 0 vlog_0InOptions {} toggle - vlog_options {} compile_to work vlog_upper 0 cover_noshort 0 compile_order 3 dont_compile 0 cover_expr 0 cover_stmt 0
Project_File_4 = /home/hoo2/Public/AUTH/HWDigSys-II/fpu_mult/src/round_modes.sv
Project_File_P_4 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 cover_fsm 0 cover_branch 0 vlog_noload 0 folder src last_compile 1749985365 cover_excludedefault 0 vlog_enable0In 0 vlog_disableopt 0 cover_covercells 0 voptflow 1 vlog_showsource 0 vlog_hazard 0 cover_optlevel 3 toggle - vlog_0InOptions {} ood 0 cover_noshort 0 vlog_upper 0 compile_to work vlog_options {} compile_order 8 cover_expr 0 dont_compile 0 cover_stmt 0
Project_File_5 = /home/hoo2/Public/AUTH/HWDigSys-II/fpu_mult/sim/fp_mult_top_tb.sv
Project_File_P_5 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 last_compile 1750010789 cover_fsm 0 cover_branch 0 vlog_noload 0 folder sim cover_excludedefault 0 vlog_enable0In 0 vlog_disableopt 0 cover_covercells 0 voptflow 1 vlog_showsource 0 vlog_hazard 0 cover_optlevel 3 toggle - vlog_0InOptions {} ood 0 cover_noshort 0 vlog_upper 0 compile_to work vlog_options {} compile_order 9 cover_expr 0 dont_compile 0 cover_stmt 0
Project_File_6 = /home/hoo2/Public/AUTH/HWDigSys-II/fpu_mult/sim/normalize_mult_tb.sv
Project_File_P_6 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 folder sim last_compile 1749840708 cover_fsm 0 cover_branch 0 vlog_noload 0 vlog_enable0In 0 cover_excludedefault 0 vlog_disableopt 0 cover_covercells 0 cover_optlevel 3 vlog_hazard 0 vlog_showsource 0 voptflow 1 ood 0 vlog_0InOptions {} toggle - vlog_options {} compile_to work vlog_upper 0 cover_noshort 0 compile_order 5 dont_compile 0 cover_expr 0 cover_stmt 0
Project_File_7 = /home/hoo2/Public/AUTH/HWDigSys-II/fpu_mult/src/round_mult.sv
Project_File_P_7 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 cover_fsm 0 cover_branch 0 vlog_noload 0 folder src last_compile 1749991129 cover_excludedefault 0 vlog_enable0In 0 vlog_disableopt 0 cover_covercells 0 voptflow 1 vlog_showsource 0 vlog_hazard 0 cover_optlevel 3 toggle - vlog_0InOptions {} ood 0 cover_noshort 0 vlog_upper 0 compile_to work vlog_options {} compile_order 1 cover_expr 0 dont_compile 0 cover_stmt 0
Project_File_P_6 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 cover_fsm 0 cover_branch 0 vlog_noload 0 folder sim last_compile 1749840708 vlog_enable0In 0 cover_excludedefault 0 vlog_disableopt 0 cover_covercells 0 cover_optlevel 3 vlog_hazard 0 vlog_showsource 0 voptflow 1 ood 0 vlog_0InOptions {} toggle - vlog_options {} compile_to work vlog_upper 0 cover_noshort 0 compile_order 5 dont_compile 0 cover_expr 0 cover_stmt 0
Project_File_7 = /home/hoo2/Public/AUTH/HWDigSys-II/fpu_mult/src/exception_mult.sv
Project_File_P_7 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 cover_fsm 0 cover_branch 0 vlog_noload 0 folder src last_compile 1750016331 cover_excludedefault 0 vlog_enable0In 0 vlog_disableopt 0 cover_covercells 0 voptflow 1 vlog_showsource 0 vlog_hazard 0 cover_optlevel 3 toggle - vlog_0InOptions {} ood 0 cover_noshort 0 vlog_upper 0 compile_to work vlog_options {} compile_order 7 cover_expr 0 dont_compile 0 cover_stmt 0
Project_File_8 = /home/hoo2/Public/AUTH/HWDigSys-II/fpu_mult/sim/fp_mult_tb.sv
Project_File_P_8 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 last_compile 1749991928 cover_fsm 0 cover_branch 0 vlog_noload 0 folder sim vlog_enable0In 0 cover_excludedefault 0 vlog_disableopt 0 cover_covercells 0 cover_optlevel 3 vlog_hazard 0 vlog_showsource 0 voptflow 1 ood 0 vlog_0InOptions {} toggle - vlog_options {} compile_to work vlog_upper 0 cover_noshort 0 compile_order 4 dont_compile 0 cover_expr 0 cover_stmt 0
Project_File_P_8 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 last_compile 1750010789 cover_fsm 0 cover_branch 0 vlog_noload 0 folder sim vlog_enable0In 0 cover_excludedefault 0 vlog_disableopt 0 cover_covercells 0 cover_optlevel 3 vlog_hazard 0 vlog_showsource 0 voptflow 1 ood 0 vlog_0InOptions {} toggle - vlog_options {} compile_to work vlog_upper 0 cover_noshort 0 compile_order 4 dont_compile 0 cover_expr 0 cover_stmt 0
Project_File_9 = /home/hoo2/Public/AUTH/HWDigSys-II/fpu_mult/src/round_mult.sv
Project_File_P_9 = cover_toggle 0 file_type systemverilog group_id 0 cover_exttoggle 0 cover_nofec 0 cover_cond 0 vlog_1995compat SV vlog_nodebug 0 vlog_noload 0 folder src last_compile 1749991129 cover_fsm 0 cover_branch 0 cover_excludedefault 0 vlog_enable0In 0 vlog_disableopt 0 cover_covercells 0 voptflow 1 vlog_showsource 0 vlog_hazard 0 cover_optlevel 3 toggle - vlog_0InOptions {} ood 0 cover_noshort 0 vlog_upper 0 compile_to work vlog_options {} compile_order 1 cover_expr 0 dont_compile 0 cover_stmt 0
Project_Sim_Count = 0
Project_Folder_Count = 2
Project_Folder_0 = src

7
report/.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
# TeX auxiliary files
*.aux
*.log
*.out
*.synctex.gz
_minted-report/

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
report/report.pdf Normal file

Binary file not shown.

344
report/report.tex Normal file
View File

@ -0,0 +1,344 @@
%
% !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}

111
sim/fp_mult_tb.sv Normal file → Executable file
View File

@ -1,3 +1,4 @@
// sim/fp_mult_tb.sv
`timescale 1ns/1ps
@ -6,18 +7,8 @@ module fp_mult_tb;
logic [31:0] a, b, z;
logic [2:0] rnd;
logic [7:0] status;
logic clk = 0, rst = 0;
/*
// DEBUG signals
logic sign_res_;
logic [9:0] exp_sum_;
logic [47:0] mant_prod_;
logic [22:0] mant_norm_;
logic [9:0] exp_norm_;
logic guard_, sticky_;
logic [24:0] mant_post_rnd_;
logic [9:0] exp_post_rnd_;
*/
logic clk = 0, rst = 1;
// DUT
fp_mult dut (
.a(a),
@ -27,21 +18,10 @@ module fp_mult_tb;
.status(status),
.clk(clk),
.rst(rst)
/*
// DEBUG signals
.sign_res_(sign_res_),
.exp_sum_(exp_sum_),
.mant_prod_(mant_prod_),
.mant_norm_(mant_norm_),
.exp_norm_(exp_norm_),
.guard_(guard_),
.sticky_(sticky_),
.mant_post_rnd_(mant_post_rnd_),
.exp_post_rnd_(exp_post_rnd_)
*/
);
// Clock generation
always #1 rst = 1;
always #5 clk = ~clk;
typedef struct {
@ -50,59 +30,58 @@ module fp_mult_tb;
logic [31:0] expected;
string desc;
} test_vector_t;
int i =0, j=0;
test_vector_t tests [14];
test_vector_t tests [20];
initial begin
$display("Starting fp_mult test...\n");
// Normal multiplication 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"};
tests[4] = '{32'h3f000000, 32'h3f000000, 32'h3e800000, "0.5 * 0.5 = 0.25"};
tests[5] = '{32'h3f800000, 32'h00000000, 32'h00000000, "1.0 * 0.0 = 0.0"};
tests[6] = '{32'h42280000, 32'hc0e00000, 32'hc3930000, "42.0 * -7.0 = -294.0"};
tests[7] = '{32'h414570a4, 32'hb8d1b717, 32'hbaa1be2b, "12.34 * -0.0001 = -0.001234"};
// Test vectors
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"};
tests[4] = '{32'h3f000000, 32'h3f000000, 32'h3e800000, "+0.5 * +0.5 = +0.25"};
tests[5] = '{32'h3f800000, 32'h00000000, 32'h00000000, "1.0 * +0.0 = +0.0"};
tests[6] = '{32'h42280000, 32'hc0e00000, 32'hc3930000, "+42.0 * -7.0 = -294.0"};
tests[7] = '{32'h414570a4, 32'hb8d1b717, 32'hbaa1be2b, "+12.34 * -0.0001 = -0.001234"};
// Corner cases (some may fail if not handled yet)
tests[8] = '{32'h00000000, 32'h80000000, 32'h80000000, "0.0 * -0.0 = -0.0"};
tests[9] = '{32'h3f800000, 32'h80000000, 32'h80000000, "1.0 * -0.0 = -0.0"};
tests[10] = '{32'h7f800000, 32'h3f800000, 32'h7f800000, "inf * 1.0 = inf"};
tests[11] = '{32'hff800000, 32'h7f800000, 32'hff800000, "-inf * inf = -inf"};
tests[12] = '{32'h00000000, 32'h7f800000, 32'h7f800000, "0.0 * inf = inf - nan"};
tests[13] = '{32'h80000000, 32'hff800000, 32'h7f800000, "-0.0 * -inf = inf - nan"};
tests[8] = '{32'h00000000, 32'h00000000, 32'h00000000, "0.0 * 0.0 = 0.0"};
tests[9] = '{32'h80000000, 32'h80000000, 32'h00000000, "-0.0 * -0.0 = 0.0"};
tests[10] = '{32'h00000000, 32'h80000000, 32'h80000000, "0.0 * -0.0 = -0.0"};
tests[11] = '{32'h3f800000, 32'h80000000, 32'h80000000, "1.0 * -0.0 = -0.0"};
tests[12] = '{32'h7f800000, 32'h3f800000, 32'h7f800000, "inf * 1.0 = inf"};
tests[13] = '{32'hff800000, 32'h3f800000, 32'hff800000, "-inf * 1.0 = -inf"};
tests[14] = '{32'h7f800000, 32'hbf800000, 32'hff800000, "inf * -1.0 = -inf"};
tests[15] = '{32'hff800000, 32'h7f800000, 32'hff800000, "-inf * inf = -inf"};
tests[16] = '{32'hff800000, 32'hff800000, 32'h7f800000, "-inf * -inf = +inf"};
tests[17] = '{32'h00000000, 32'h7f800000, 32'h7f800000, "0.0 * inf = inf"};
tests[18] = '{32'h80000000, 32'hff800000, 32'h7f800000, "-0.0 * -inf = inf"};
tests[19] = '{32'h00000000, 32'hff800000, 32'hff800000, "0.0 * -inf = -inf"};
end
logic [31:0] z_pipe [2:0];
rnd = 3'b000; // default round to nearest
rst = 1; #10;
rst = 0; #10;
always_ff @(negedge clk) begin
z_pipe[2] <= z_pipe[1];
z_pipe[1] <= z_pipe[0];
z_pipe[0] <= z;
for (int i = 0; i < 14; i++) begin
a = tests[i].a;
b = tests[i].b;
#20;
$display("[%0d] %s", i+1, tests[i].desc);
/*
// DEBUG prints
$display("fp_mult: sign bit = %h", sign_res_);
$display("fp_mult: exp (pre norm) = %h", exp_sum_);
$display("fp_mult: mant (pre norm) = %h", mant_prod_);
$display("fp_mult: exp (norm) = %h", exp_norm_);
$display("fp_mult: mant (norm) = %h", mant_norm_);
$display("fp_mult: guard,sticky = %h,%h", guard_,sticky_);
$display("fp_mult: exp (post rnd) = %h", exp_post_rnd_);
$display("fp_mult: mant (post rnd) = %h", mant_post_rnd_);
*/
$display(" A=%h B=%h => Z=%h (expected %h) %s\n",
a, b, z, tests[i].expected,
(z === tests[i].expected) ? "PASS" : "FAIL");
if (i >= 5) begin
j = i - 5;
$display("[%0d] %s", j+1, tests[j].desc);
$display(" A=%h B=%h => Z=%h (expected %h) %s\n",
tests[j].a, tests[j].b, z_pipe[0], tests[j].expected,
(z_pipe[0] === tests[j].expected) ? "PASS" : "FAIL");
end
$display("\nFinished fp_mult test.");
$stop;
a <= tests[i].a;
b <= tests[i].b;
i <= i + 1;
if (i == 19 + 5) $stop;
end
endmodule
endmodule

89
sim/fp_mult_top_tb.sv Executable file
View File

@ -0,0 +1,89 @@
// sim/fp_mult_top_tb.sv
`timescale 1ns/1ps
module fp_mult_top_tb;
logic [31:0] a, b, z;
logic [2:0] rnd;
logic [7:0] status;
logic clk = 0, rst = 1;
// DUT
fp_mult_top dut (
.a(a),
.b(b),
.rnd(rnd),
.z(z),
.status(status),
.clk(clk),
.rst(rst)
);
// Clock generation
always #1 rst = 1;
always #5 clk = ~clk;
typedef struct {
logic [31:0] a;
logic [31:0] b;
logic [31:0] expected;
string desc;
} test_vector_t;
int i =0, j=0;
// Test vectors
test_vector_t tests [20];
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"};
tests[4] = '{32'h3f000000, 32'h3f000000, 32'h3e800000, "+0.5 * +0.5 = +0.25"};
tests[5] = '{32'h3f800000, 32'h00000000, 32'h00000000, "1.0 * +0.0 = +0.0"};
tests[6] = '{32'h42280000, 32'hc0e00000, 32'hc3930000, "+42.0 * -7.0 = -294.0"};
tests[7] = '{32'h414570a4, 32'hb8d1b717, 32'hbaa1be2b, "+12.34 * -0.0001 = -0.001234"};
tests[8] = '{32'h00000000, 32'h00000000, 32'h00000000, "0.0 * 0.0 = 0.0"};
tests[9] = '{32'h80000000, 32'h80000000, 32'h00000000, "-0.0 * -0.0 = 0.0"};
tests[10] = '{32'h00000000, 32'h80000000, 32'h80000000, "0.0 * -0.0 = -0.0"};
tests[11] = '{32'h3f800000, 32'h80000000, 32'h80000000, "1.0 * -0.0 = -0.0"};
tests[12] = '{32'h7f800000, 32'h3f800000, 32'h7f800000, "inf * 1.0 = inf"};
tests[13] = '{32'hff800000, 32'h3f800000, 32'hff800000, "-inf * 1.0 = -inf"};
tests[14] = '{32'h7f800000, 32'hbf800000, 32'hff800000, "inf * -1.0 = -inf"};
tests[15] = '{32'hff800000, 32'h7f800000, 32'hff800000, "-inf * inf = -inf"};
tests[16] = '{32'hff800000, 32'hff800000, 32'h7f800000, "-inf * -inf = +inf"};
tests[17] = '{32'h00000000, 32'h7f800000, 32'h7f800000, "0.0 * inf = inf"};
tests[18] = '{32'h80000000, 32'hff800000, 32'h7f800000, "-0.0 * -inf = inf"};
tests[19] = '{32'h00000000, 32'hff800000, 32'hff800000, "0.0 * -inf = -inf"};
end
logic [31:0] z_pipe [2:0];
always_ff @(negedge clk) begin
z_pipe[2] <= z_pipe[1];
z_pipe[1] <= z_pipe[0];
z_pipe[0] <= z;
if (i >= 7) begin
j = i - 7;
$display("[%0d] %s", j+1, tests[j].desc);
$display(" A=%h B=%h => Z=%h (expected %h) %s\n",
tests[j].a, tests[j].b, z_pipe[0], tests[j].expected,
(z_pipe[0] == tests[j].expected) ? "PASS" : "FAIL");
end
a <= tests[i].a;
b <= tests[i].b;
i <= i + 1;
if (i == 19 + 7) $stop;
end
endmodule

View File

@ -1,7 +1,6 @@
/*
*
*/
// exception_mult.sv
// Handles the exceptional cases
`include "round_modes.sv"
module exception_mult (
@ -72,7 +71,7 @@ module exception_mult (
{ZERO, INF}, {INF, ZERO}:
begin
z = {1'b0, z_num(INF)};
z = {sign, z_num(INF)};
nan_f = 1;
end

View File

@ -6,125 +6,151 @@ module fp_mult (
input logic [31:0] b, // input operand B
input logic [2:0] round, // rounding mode
output logic [31:0] z, // result
output logic [7:0] status, // status flags (placeholder)
output logic [7:0] status, // status flags
input logic clk,
input logic rst
/*
// debug outputs
output logic sign_res_,
output logic [9:0] exp_sum_,
output logic [47:0] mant_prod_,
output logic [22:0] mant_norm_,
output logic [9:0] exp_norm_,
output logic guard_, sticky_,
output logic [24:0] mant_post_rnd_,
output logic [9:0] exp_post_rnd_
*/
);
// === STEP 0: Parse inputs
logic sign_a, sign_b;
logic [7:0] exp_a, exp_b;
logic [23:0] mant_a, mant_b; // includes hidden bit
// Stage 0: Decode inputs
logic sign;
logic [7:0] exp_a, exp_b;
logic [23:0] mant_a, mant_b;
logic [47:0] s0_mantissa;
logic [9:0] s0_exponent;
always_comb begin
sign_a = a[31];
sign_b = b[31];
exp_a = a[30:23];
exp_b = b[30:23];
mant_a = (exp_a == 8'd0) ? {1'b0, a[22:0]} : {1'b1, a[22:0]};
mant_b = (exp_b == 8'd0) ? {1'b0, b[22:0]} : {1'b1, b[22:0]};
// ^ Add hiden leading '1' on normalized numbers
// This will lead to always 24-bits mantissa internal representation
// for multiplication
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
// === STEP 1: Floating point number sign calculation
logic sign_res;
assign sign_res = sign_a ^ sign_b;
//assign sign_res_ = sign_res; // DEBUG
// === Stage 1: Normalize ===
logic [47:0] s1_mant_in;
logic [9:0] s1_exp_in;
logic [22:0] s1_mant_out;
logic [9:0] s1_exp_out;
logic s1_guard_out, s1_sticky_out;
logic [31:0] s1_a, s1_b;
logic s1_sign;
// === STEP 2,3. Exponent addition, Exponent subtraction of bias
logic [9:0] exp_sum;
always_comb begin
exp_sum = exp_a + exp_b - 127; // apply bias
//exp_sum_ = exp_sum; // DEBUG
end
// === STEP 4: Mantissa multiplication (including leading ones)
logic [47:0] mant_prod;
always_comb begin
mant_prod = mant_a * mant_b;
//mant_prod_ = mant_prod; // DEBUG
end
// === STEP 5: Truncation and normalization
logic [22:0] mant_norm;
logic [9:0] exp_norm;
logic guard, sticky;
normalize_mult norm_inst (
.mantissa_in(mant_prod),
.exponent_in(exp_sum),
.mantissa_out(mant_norm),
.exponent_out(exp_norm),
.guard_bit(guard),
.sticky_bit(sticky)
normalize_mult normalize_inst (
.mantissa_in(s1_mant_in),
.exponent_in(s1_exp_in),
.mantissa_out(s1_mant_out),
.exponent_out(s1_exp_out),
.guard_bit(s1_guard_out),
.sticky_bit(s1_sticky_out)
);
//assign mant_norm_ = mant_norm; // DEBUG
//assign exp_norm_ = exp_norm; // DEBUG
//assign guard_ = guard; // DEBUG
//assign sticky_ = sticky; // DEBUG
// === STEP 6: Pipeline stage
// Ehhh... We dont do that here...
always_ff @(posedge clk or negedge rst) begin
if (!rst) begin
s1_mant_in <= 0;
s1_exp_in <= 0;
s1_a <= 0;
s1_b <= 0;
s1_sign <= 0;
end else begin
s1_mant_in <= s0_mantissa;
s1_exp_in <= s0_exponent;
s1_a <= a;
s1_b <= b;
s1_sign <= sign;
end
end
// === STEP 7: Rounding
logic [24:0] mant_post_rnd;
logic [9:0] exp_post_rnd;
logic inexact;
// === Stage 2: Round ===
logic [22:0] s2_mant_in;
logic [9:0] s2_exp_in;
logic s2_guard_in, s2_sticky_in;
logic [31:0] s2_a, s2_b;
logic s2_sign;
logic [24:0] s2_mant_out;
logic [9:0] s2_exp_out;
logic s2_inexact;
round_mult round_inst (
.mantissa_in(mant_norm),
.exponent_in(exp_norm),
.sign_in(sign_res),
.guard_bit(guard),
.sticky_bit(sticky),
.mantissa_in(s2_mant_in),
.exponent_in(s2_exp_in),
.sign_in(s2_sign),
.guard_bit(s2_guard_in),
.sticky_bit(s2_sticky_in),
.round(round),
.mantissa_out(mant_post_rnd),
.exponent_out(exp_post_rnd),
.inexact(inexact)
.mantissa_out(s2_mant_out),
.exponent_out(s2_exp_out),
.inexact(s2_inexact)
);
//assign mant_post_rnd_ = mant_post_rnd; // DEBUG
//assign exp_post_rnd_ = exp_post_rnd; // DEBUG
// === STEP 8: Exception handling
// overflow / underflow:
logic [31:0] z_calc;
logic ovf, unf;
assign z_calc = {sign_res, exp_post_rnd[7:0], mant_post_rnd[22:0]};
always_comb begin
ovf = (exp_post_rnd > 10'd254); // MAX normal exponent
unf = (exp_post_rnd < 10'd1); // MIN normal exponent
always_ff @(posedge clk or negedge rst) begin
if (!rst) begin
s2_mant_in <= 0;
s2_exp_in <= 0;
s2_guard_in <= 0;
s2_sticky_in <= 0;
s2_a <= 0;
s2_b <= 0;
s2_sign <= 0;
end else begin
s2_mant_in <= s1_mant_out;
s2_exp_in <= s1_exp_out;
s2_guard_in <= s1_guard_out;
s2_sticky_in <= s1_sticky_out;
s2_a <= s1_a;
s2_b <= s1_b;
s2_sign <= s1_sign;
end
end
exception_mult exc_inst (
.a(a),
.b(b),
.z_calc(z_calc),
.ovf(ovf),
.unf(unf),
.inexact(inexact),
// === Stage 3: Exception Handling ===
logic [31:0] s3_a, s3_b;
logic [31:0] s3_z_calc_in;
logic s3_ovf_in, s3_unf_in;
logic s3_inexact;
logic [31:0] s3_z_out;
logic [7:0] s3_status_out;
exception_mult exception_handler (
.a(s3_a),
.b(s3_b),
.z_calc(s3_z_calc_in),
.ovf(s3_ovf_in),
.unf(s3_unf_in),
.inexact(s3_inexact),
.round(round),
.z(z),
.zero_f(status[0]),
.inf_f(status[1]),
.nan_f(status[2]),
.tiny_f(status[3]),
.huge_f(status[4]),
.inexact_f(status[5])
.z(s3_z_out),
.zero_f(s3_status_out[0]),
.inf_f(s3_status_out[1]),
.nan_f(s3_status_out[2]),
.tiny_f(s3_status_out[3]),
.huge_f(s3_status_out[4]),
.inexact_f(s3_status_out[5])
);
always_ff @(posedge clk or negedge rst) begin
if (!rst) begin
s3_a <= 0;
s3_b <= 0;
s3_z_calc_in <= 0;
s3_ovf_in <= 0;
s3_unf_in <= 0;
s3_inexact <= 0;
z <= 0;
status <= 0;
end else begin
s3_a <= s2_a;
s3_b <= s2_b;
s3_z_calc_in <= {s2_sign, s2_exp_out[7:0], s2_mant_out[22:0]};
s3_ovf_in <= (s2_exp_out > 8'd254);
s3_unf_in <= (s2_exp_out < 8'd1);
s3_inexact <= s2_inexact;
z <= s3_z_out;
status <= s3_status_out;
end
end
endmodule