Initial commit

This commit is contained in:
2026-06-12 20:37:03 +02:00
commit 259f6d5803
305 changed files with 32830 additions and 0 deletions
+229
View File
@@ -0,0 +1,229 @@
Progetto di Reti Logiche
Prof. Fornaciari, Prof. Palermo e Prof. Salice
Anno Accademico 2025 - 2026
REGOLE per lo svolgimento del progetto
(Aggiornamento del 27 Novembre 2025)
Compito dello studente è quello di descrivere in VHDL e sintetizzare il componente HW che
implementa la specifica richiesta, interfacciandosi con una memoria dove sono memorizzati i
dati e dove andrà scritto il risultato finale. Allo studente verrà fornito un Test Bench di
esempio (che include la memoria) per validare il corretto funzionamento del modulo
implementato.
Il progetto può essere svolto in gruppi composti da un massimo di 2 studenti che
debbono avere il medesimo docente di riferimento.
Il progetto è una attività autonoma che non coinvolge in nessun modo il corpo
docente a meno di chiarimenti sulla specifica di progetto.
● Nel caso il testo di specifica risulti incompleto, è compito del gruppo di lavoro
contattare i docenti motivando accuratamente la ragione della incompletezza.
● Strumento di sintesi da usare è XILINX VIVADO WEBPACK e la FPGA target può
essere qualunque perchè il progetto è talmente piccolo che non ha problemi.
(Esempio: Artix-7 FPGA xc7a200tfbg484-1)
Il progetto deve funzionare con un periodo di clock di almeno 20 ns;
Criteri di valutazione
● Un componente descritto e simulabile correttamente in pre-sintesi viene valutato fino
ad un massimo di 24.
● Un componente sintetizzabile e correttamente simulabile in post-sintesi può ottenere
una valutazione superiore a 24: fino a 30 per un progetto fatto in coppia, fino a 30L
per un progetto svolto da un singolo studente.
● Lo studente deve allegare al progetto come documentazione una relazione.
Questultima deve includere: 1) specifiche di progetto 2) scelte progettuali 3) risultati
dei test fatti e le ragioni di tali test (motivare le scelte) 4) risultati della sintesi. Nel
caso di un componente descritto e simulabile correttamente in pre-sintesi questo
deve essere chiaramente segnalato anche nella relazione. La qualità della relazione
concorre alla definizione del voto complessivo.
Il voto finale, in entrambi i casi, terrà conto dei test superati dal componente, dalla
qualità del codice VHDL e della relazione presentata (incluse le scelte progettuali).
Un progetto fatto in coppia può comunque raggiungere la lode grazie alla valutazione
complessiva dellimplementazione e della relazione.
● ATTENZIONE: non è possibile rifiutare il voto finale. Questo è dovuto alla
tipologia del progetto che è considerato, da regolamento didattico, una “PROVA
FINALE”.
● E facoltà dei docenti richiedere un'integrazione mediante una discussione orale o
una prova pratica relativamente allo sviluppo del progetto nell'ambiente suggerito, in
aggiunta alla valutazione basata sulla prova di funzionamento del codice e della
relazione.
Criteri di Consegna
● La specifica del progetto resta invariata per tutto lanno accademico. La consegna
del progetto può essere fatta solo una volta nellarco dellanno accademico con la
possibilità di una ed unica risottomissione in caso di insufficienza (si legga la nota
successiva).
● NOTA: nel caso che la prima consegna risulti insufficiente (9<x<18) viene consentita,
a parere insindacabile del docente, una successiva consegna; la valutazione, in
questo frangente, non potrà superare in nessun caso 24/30. Non sono né previste
né eccezioni e/o compensazioni. Ai progetti la cui valutazione è inferiore ai 10/30
non verrà offerta la possibilità di riconsegna.
Il progetto e la relativa relazione è personale (o del gruppo di due studenti) e
per nessun motivo deve essere condiviso con colleghi della propria o di altre
sezioni. Il progetto verrà sottoposto ad un controllo anti-plagio confrontandolo con
tutti i progetti delle 3 sezioni a partire dalla prima consegna. Nel caso venga
identificato un plagio evidente, la prova verrà considerata con valutazione 0/30
con relative conseguenze anche di carattere disciplinare. In caso di plagio
verrà presa in considerazione anche la/le persone sorgenti del materiale con
rettifica del voto anche laddove già verbalizzato.
● ATTENZIONE: in caso di bocciatura (valutazione che si ottiene in due casi: progetti la
cui valutazione è inizialmente inferiore ai 10/30, progetti risultati insufficiente dopo la
seconda consegna) il candidato verrà rimandato allanno accademico successivo.
● ATTENZIONE: Nel caso il candidato non riesca a superare positivamente la
valutazione del progetto entro l'ultima consegna, dovrà sostenere la “PROVA
FINALE” con il progetto dell'anno accademico successivo.
IMPORTANTE: La "Prova Finale, Progetto di Reti Logiche" è un esame, anzi è da
considerarsi alla stregua di una tesi personale, e come tale il progetto DEVE
contenere lavoro che deve essere considerabile come dello studente. L'uso di
strumenti di AI per supportare la risoluzione dell'assegnamento (o parte di esso) e
consegnarlo come se fosse proprio lavoro è considerato una cattiva condotta
accademica che è considerata al pari del plagio. Inoltre, se usato da più studenti,
strumenti di GenAI, quali ad esempio GitHub-copilot/ChatGPT etc…, generano codice
simile tra gli studenti. Questo porta inoltre allidentificazione dello stesso come
cross-plagio e quindi come tale verrà trattato. Si può essere ispirati (molto
limitatamente), ma non si può sottomettere codice o materiale generato o fortemente
derivato/copiato da altri.
Modalità di consegna:
Le date previste per le tre sessioni sono:
I consegna entro 1 Febbraio 2026
○ per potersi laureare a Marzo (verbalizzazione entro il 20.02.2026)
II consegna entro 15 Marzo 2026
III consegna entro 26 Aprile 2026
IV consegna entro 7 Giugno 2026
○ per potersi laureare a Luglio (verbalizzazione entro il 1.07.2024)
● V consegna entro 13 Luglio 2026
● VI consegna entro 28 Agosto 2026
○ per potersi laureare a Settembre/Ottobre (con verbalizzazione entro il
11.09.2026)
● VII consegna 11 Settembre 2026
*** Consegna EXTRA *** 1 Dicembre 2026
● Questa consegna fa parte delle consegne del nuovo anno accademico
(26/27). Questa data consente agli iscritti alla prova finale 25/26 di
usufruire di un'ulteriore consegna nel nuovo anno accademico con la
specifica dellanno precedente.
Dopo lultima consegna si passa al progetto che verrà proposto per lanno successivo.
Per la consegna dei progetti verrà predisposta una cartella su WeBeeP per ogni sessione
desame. Allinterno di questa cartella ogni studente o gruppo di studenti dovrà caricare
esattamente due file:
● un solo file con il codice VHDL - Il file caricato dovrà essere nominato
codicePersona.vhd (esempio 10499233.vhd).
IMPORTANTE: gli studenti che
lavorano in gruppo dovranno caricare un file solo, usando il codice persona di
entrambi
i due studenti (codicePersona1_codicePersona2.vhd). Deve essere
effettuata la consegna da uno solo dei componenti del gruppo. La descrizione della
composizione del gruppo dovrà essere anche esplicitamente menzionata nella
documentazione allegata.
● un solo file PDF con la documentazione - In questo caso il nome del file caricato
dovrà essere codicePersona.pdf, o codicePersona1_codicePersona2.pdf con lo
stesso ordine usato per il file VHDL di cui sopra.
IMPORTANTE: gli studenti che hanno lavorato in gruppo dovranno assicurarsi di
specificare in modo chiaro la composizione del gruppo (max 2 persone) nella
documentazione oltre che nel nome di file. La mancata specifica della composizione
del gruppo farà riconoscere il voto solo allo studente il cui codice persona
corrisponde a quello dei file caricati.
● La cartella di consegna verrà chiusa automaticamente dal sistema allo scadere della
data prevista. Il progetto verrà considerato consegnato se alla scadenza saranno
presenti i due file descritti sopra, con le caratteristiche specificate. La correzione del
progetto non è immediata e richiede la verifica tramite diversi test prima della sua
valutazione definitiva.
IMPORTANTE: qualora i file caricati non rispettassero tali caratteristiche, il progetto
verrà considerato non consegnato. !!! Non mettete nulla della descrizione del file
quando lo caricate su Webeep, altrimenti questo cambierà nome.
● Come già ricordato, si utilizzerà un software di analisi per identificare eventuali
copie del codice dei progetti che include tutte e 3 le sezioni del corso ed ogni
consegna fatta nelle sessioni precedenti. Anche a seguito della consegna, è
obbligatorio mantenere privato e personale il progetto sviluppato fino al 31
Dicembre 2026, evitando ovviamente anche di pubblicarlo on-line (si presti
attenzione alla nota sul fatto di essere sorgente di plagio e alle relative
conseguenze).
Schema della Relazione
Qui di seguito vengono riportate delle indicazioni sui punti fondamentali che devono essere
trattati allinterno della relazione. Si presti attenzione al fatto che la relazione deve essere
sintetica, completa e chiara; lo scopo è quello di per permettere di comprendere come il
progetto è stato svolto.
1. Introduzione: L'obiettivo non è la "copia" della specifica ma una elaborazione, con un
esempio e, se è possibile, un disegno e/o una immagine, che spieghi cosa succede;
2. Architettura: Lobiettivo è quello di riportare uno schema funzionale che consenta di
valutare come la rete sia stata progettata (schema in moduli... un bel disegno
chiaro... i segnali i bus, il/i clock, reset… i segnali interni che interconnettono i moduli,
… ):
a. Modulo 1 (la descrizione - sottoparagrafo - di ogni modulo e la scelta
implementativa - per esempio, il modulo ... è una collezione di process che
implementano la macchina a stati e la parte di registri, .... La macchina a stati,
il cui schema in termini di diagramma degli stati, ha 8 stati. Il primo
rappresenta .... e svolge le operazioni di ... il secondo... etc etc)
b. Modulo …
3. Risultati sperimentali:
a. Sintesi (Report del tool di sintesi adeguatamente commentato)
b. Simulazioni: L'obiettivo non è solo riportare i risultati ottenuti attraverso la
simulazione test bench forniti dai docenti, ma anche una analisi personale e
una identificazione dei casi particolari; il fine è mostrare in modo convincente
e più completo possibile, che il problema è stato esaminato a fondo e che,
quanto sviluppato, soddisfa completamente i requisiti.
i.
test bench 1 (cosa fa e perchè lo fa e cosa verifica; per esempio,
controlla una condizione limite)
test bench 2 (....)
ii.
iii. …
4. Conclusioni (mezza pagina max)
+660
View File
@@ -0,0 +1,660 @@
Progetto di Reti Logiche
Prof. Fornaciari, Prof. Palermo e Prof. Salice
Anno Accademico 2025 - 2026
SPECIFICA per lo svolgimento del progetto
Revisione del 24 Febbraio 2026
Descrizione generale
La specifica della “Prova Finale (Progetto di Reti Logiche)” per lAnno Accademico
2025/2026 chiede di implementare un modulo HW (descritto in VHDL) che si interfacci con
una memoria e che rispetti le indicazioni riportate nella seguente specifica.
Si richiede di progettare e implementare in VHDL un modulo hardware che gestisce una lista
ordinata di task memorizzati in una memoria esterna. Ogni task è rappresentato da una
coppia di campi: ID_TASK (6 bit) e PRIORITY (2 bit). Ad esempio, 00100111 indica il task
con ID 001001 che ha priorità 11. Le priorità vanno da 0 (più alta) a 3 (più bassa). Non
possono esistere due task con lo stesso ID_TASK (questo implica che non possono esistere
più di 63 task nella lista). LID_TASK è sempre un numero positivo e 0 rappresenta una
condizione di errore (lista vuota).
La lista dei task è memorizzata in una memoria con la seguente struttura:
● Allindirizzo 0 è memorizzato il numero di task attualmente presenti nella lista.
● A partire dallindirizzo 1 sono memorizzati i task allinterno di un byte di memoria
(ID_TASK & PRIORITY), che devono essere sempre mantenuti ordinati in base alla
priorità (priorità più bassa numericamente = più alta gerarchicamente, e quindi prima
nella lista). Allinterno del byte, ID_TASK occupa i 6 bit più alti e PRIORITY i 2 bit più
bassi. Ad esempio, 0x00001100 è il task con ID_TASK 3 e PRIORITY 0.
Il modulo deve supportare quattro operazioni, selezionate tramite un ingresso di controllo a 2
bit denominato OP:
● OP = 00: decrementa la priorità di tutti i task presenti nella lista. Ogni indicatore di
priorità deve essere incrementato di 1, senza superare il valore numerico massimo (3
- priorità più bassa). Il valore di priorità satura a 3 (priorità minima). Tutti i task
mantengono lordinamento che avevano prima dellincremento del valore di priorità.
In particolare, la lista dei task a priorità 3 vedrà prima tutti i task che avevano priorità
2 e poi quelli che già erano a priorità 3 (in pratica sarà sufficiente modificare i valori di
priorità senza alcun riordino).
● OP = 01: Rimuove dalla lista il primo task (indirizzo 1). Tutti i task successivi devono
essere spostati di una posizione, il numero di task deve essere decrementato, e il
numero del task estratto deve essere fornito in uscita dal modulo. Il primo task della
lista potrebbe avere una priorità qualunque (0, 1, 2 o 3). In caso di lista vuota, deve
essere fornito in uscita il valore di ID_TASK 0 (0x000000) . Il valore ID_TASK deve
essere valido quando DONE viene portato a 1.
● OP = 10: Aggiunge un nuovo task alla lista, inserendolo in coda ai task a pari priorità,
preservando lordine di tutti gli altri task. Se la lista è vuota, il task deve essere
inserito in prima posizione.
● OP = 11: Svuota completamente la lista. Il valore in memoria allindirizzo 0 deve
essere posto a zero; il contenuto degli altri indirizzi può essere ignorato (quello che è
stato scritto in passato riamane invariato) o resettato (tutti i valori sono posti a zero).
Il modulo utilizza un protocollo di hand-shake START-DONE per la sincronizzazione con la
logica esterna. Il comportamento richiesto è il seguente:
Il segnale START, generato dallesterno, viene posto a 1 per avviare loperazione
selezionata tramite OP.
● START deve rimanere a 1 fino a quando il modulo non porta il segnale DONE a 1,
indicando che loperazione è stata completata.
● Quando DONE è a 1, la logica esterna deve riportare START a 0.
● Quando START torna a 0, il modulo può riportare DONE a 0 e prepararsi a ricevere
una nuova operazione.
● Una nuova operazione può essere avviata solo quando DONE è a 0.
Dopo che il modulo viene resettato (quindi subito dopo la transizione RESET 1 -> 0), esso
deve comportarsi come segue:
● Dopo un reset, la lista deve essere considerata vuota. Il modulo deve quindi scrivere
il valore zero allindirizzo 0 della memoria.
● Durante questa fase di inizializzazione, il segnale DONE deve essere mantenuto a 1,
indicando che il modulo non è ancora pronto a ricevere operazioni, e solo dopo che
lazzeramento è stato effettuato, il modulo può riportare DONE a 0 e rendersi
disponibile a nuove operazioni.
Il modulo deve garantire:
Il corretto aggiornamento della memoria in seguito a ogni operazione.
Il mantenimento dellordine dei task nella lista.
● La gestione appropriata dei casi limite, ad esempio lista vuota.
Il rispetto del protocollo START-DONE come descritto.
Si precisa che
la presente specifica descrive un comportamento completamente
deterministico: a parità di sequenze di ingresso, le uscite generate e il contenuto della
memoria nella parte valida (lista dei task) risultano invariati. Qualsiasi eventuale scenario
che presenti ambiguità o comportamenti non univocamente determinati dovrà essere
identificato e prontamente segnalato.
Interfaccia del Componente
Il modulo da implementare ha 4 ingressi primari, uno ad 1 bit (i_start), uno a 6 bit (i_task_id),
uno a 2 bit (i_task_priority) e uno da 2 bit (i_op), e due uscite primarie, una da 1 bit (o_done)
e una da 6 bit (o_task_id). Inoltre, il modulo ha un segnale di clock CLK, unico per tutto il
sistema e un segnale di reset RESET anchesso unico per tutto il sistema. Tutti i segnali
sono sincroni e devono essere interpretati sul fronte di salita del clock. Lunica eccezione è
RESET che, invece, è asincrono. RESET può essere generato in qualsiasi momento
dellesecuzione.
Il componente da descrivere deve avere la seguente interfaccia.
entity project_reti_logiche is
port (
i_clk : in std_logic;
i_rst : in std_logic;
i_start
: in std_logic;
i_task_id
: in std_logic_vector(5 downto 0);
i_task_priority : in std_logic_vector(1 downto 0);
i_op : in std_logic_vector(1 downto 0);
o_done : out std_logic;
o_task_id : out std_logic_vector(5 downto 0);
o_mem_addr : out std_logic_vector(15 downto 0);
i_mem_data : in std_logic_vector(7 downto 0);
o_mem_data : out std_logic_vector(7 downto 0);
o_mem_we : out std_logic;
o_mem_en : out std_logic
);
end project_reti_logiche;
In particolare:
il nome del modulo deve essere project_reti_logiche e deve essere
presente una sola architettura per ogni entità; la violazione di queste
indicazioni comporta
il Test Bench e una
limpossibilità di eseguire
conseguente valutazione di zero;
i_clk è il segnale di CLOCK in ingresso generato dal Test Bench;
i_rst è il segnale di RESET che inizializza la macchina pronta per ricevere il
primo segnale di START;
i_start è il segnale di START generato dal Test Bench;
i_task_id è il vettore di bit rappresentante il ID_TASK generato dal Test
Bench;
i_task_priority è il vettore di bit rappresentante il PRIORITY generato dal Test
Bench;
i_op è il vettore di 2 bit rappresentante loperazione da dover effettuare sulla
lista di task;
● o_done è il segnale DONE di uscita che comunica la fine dellelaborazione;
● o_task_id è il vettore di bit rappresentante il ID_TASK del task a priorità più
alta estratto dalla memoria;
● o_mem_addr è il segnale (vettore) di uscita che manda lindirizzo alla
memoria;
i_mem_data è il segnale (vettore) che arriva dalla memoria e contiene il dato
in seguito ad una richiesta di lettura;
● o_mem_data è il segnale (vettore) che va verso la memoria e contiene il dato
che verrà successivamente scritto;
● o_mem_en è il segnale di ENABLE da dover mandare alla memoria per poter
comunicare (sia in lettura che in scrittura);
● o_mem_we è il segnale di WRITE ENABLE da dover mandare alla memoria
(=1) per poter scriverci. Per leggere da memoria, esso deve essere 0.
APPENDICE: Descrizione Memoria
NOTA: La memoria è già istanziata allinterno del Test Bench e non va sintetizzata
La memoria e il suo protocollo può essere estratto dalla seguente descrizione VHDL che fa
parte del test bench e che è derivata dalla User guide di VIVADO disponibile al seguente
link:
https://www.xilinx.com/support/documentation/sw_manuals/xilinx2017_3/ug901-vivado-synth
esis.pdf
-- Single-Port Block RAM Write-First Mode (recommended template)
--
-- File: rams_02.vhd
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity rams_sp_wf is
port(
clk : in std_logic;
we : in std_logic;
en : in std_logic;
addr : in std_logic_vector(15 downto 0);
di : in std_logic_vector(7 downto 0);
do : out std_logic_vector(7 downto 0)
);
end rams_sp_wf;
architecture syn of rams_sp_wf is
type ram_type is array (65535 downto 0) of std_logic_vector(7 downto 0);
signal RAM : ram_type;
begin
process(clk)
begin
if clk'event and clk = '1' then
if en = '1' then
if we = '1' then
RAM(conv_integer(addr)) <= di;
do
<= di after 2 ns;
else
do <= RAM(conv_integer(addr)) after 2 ns;
end if;
end if;
end if;
end process;
end syn;
ESEMPIO
Lesempio qui di seguito mostra il comportamento a seguito dei segnali di ingresso. Qui di
seguito è presente la situazione della memoria a seguito dellinserimento di diversi task (fase
non mostrata nellesempio). I valori non espliciti sono valori di memoria che non vengono
considerati per il normale funzionamento.
SITUAZIONE INIZIALE (6 task già in tabella)
MEMORIA
INDIRIZZO
VALORE
ID_TASK PRIORITY
0x00000110
0x01000000
0x01011000
0x01011100
0x01010101
0x01110010
0x00010011
16
22
23
21
28
4
0
0
0
1
2
3
0
1
2
3
4
5
6
7
OPERAZIONE: 00 (incremento valore di priorità)
MEMORIA
INDIRIZZO
VALORE
ID_TASK PRIORITY
0x00000110
0x01000001
0x01011001
0x01011101
0x01010110
0x01110011
0x00010011
16
22
23
21
28
4
1
1
1
2
3
3
0
1
2
3
4
5
6
7
OPERAZIONE: 10 (aggiunge un task) - ID_TASK: 19 - PRIORITY: 2
MEMORIA
INDIRIZZO
VALORE
ID_TASK PRIORITY
0x00000111
0x01000001
0x01011001
0x01011101
0x01010110
0x01001110
0x01110011
0x00010011
16
22
23
21
19
28
4
1
1
1
2
2
3
3
0
1
2
3
4
5
6
7
8
OPERAZIONE: 01 (rimuove il primo task)
MEMORIA
INDIRIZZO
VALORE
ID_TASK PRIORITY
0x00000110
0x01011001
0x01011101
0x01010110
0x01001110
0x01110011
0x00010011
22
23
21
19
28
4
1
1
2
2
3
3
0
1
2
3
4
5
6
7
OPERAZIONE: 11 (svuota la lista)
MEMORIA
INDIRIZZO
VALORE
ID_TASK PRIORITY
0x00000000
0
1
OPERAZIONE: 10 (aggiunge un task) - ID_TASK: 31 - PRIORITY: 3
MEMORIA
INDIRIZZO
VALORE
ID_TASK PRIORITY
0x00000001
0x01111111
0
1
2
OPERAZIONE: 10 (aggiunge un task) - ID_TASK: 15 - PRIORITY: 0
MEMORIA
INDIRIZZO
VALORE
ID_TASK PRIORITY
0x00000010
0x00111100
0x01111111
15
31
0
3
0
1
2
3
OPERAZIONE: 10 (aggiunge un task) - ID_TASK: 20 - PRIORITY: 0
MEMORIA
INDIRIZZO
VALORE
ID_TASK PRIORITY
0
1
2
3
0x000000011
0x00111100
0x01010000
0x01111111
15
20
31
0
0
3
Progetto di Reti Logiche
Prof. Fornaciari, Prof. Palermo e Prof. Salice
Anno Accademico 2025 - 2026
NOTE DI AGGIORNAMENTO DELLA SPECIFICA
In questa pagina potete trovare le modifiche fatte alla specifica del progetto dal suo primo rilascio.
Tutti i cambiamenti con data annessa saranno riportati qui sotto e sono mantenuti in rosso nel testo.
Errata Corrige:
- Aggiornamento 24.02.2026:
-
Il numero massimo di task nella lista non è 31 come nella versione originale ma 63.
Questo è derivato dal fatto che il numero di bit per il task_id è 6.
+793
View File
@@ -0,0 +1,793 @@
\documentclass[12pt,a4paper]{article}
% --- Preambolo ---
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[italian]{babel}
\usepackage{amsmath, amsfonts, amssymb}
\usepackage{geometry}
\usepackage{graphicx}
\usepackage{listings}
\usepackage{xcolor}
\usepackage{lstautogobble}
\usepackage{booktabs}
\usepackage{xcolor}
\usepackage{colortbl}
\usepackage{float}
\usepackage{caption}
\usepackage{hyperref}
\hypersetup{
colorlinks=false,
pdfborder={0 0 0}
}
\geometry{a4paper, margin=3cm}
% Configurazione professionale per il codice VHDL
\lstset{
language=VHDL,
basicstyle=\ttfamily\small, % Font monospaziato piccolo
keywordstyle=\color{blue}, % Parole chiave in blu
commentstyle=\color{gray}, % Commenti in grigio
breaklines=true, % VA A CAPO AUTOMATICAMENTE
frame=single, % Bordo attorno al codice
numbers=left, % Numeri di riga a sinistra
numberstyle=\tiny\color{gray},
xleftmargin=10pt, % Margine per far rientrare i numeri di riga
showstringspaces=false,
autogobble=true,
tabsize=2,
}
\begin{document}
\begin{titlepage}
\centering
{\large \textbf{POLITECNICO DI MILANO 1863}} \\
\vspace{1cm}
\includegraphics[width=0.4\textwidth]{logo_polimi.jpg} \\
\vspace{2cm}
{\Large \textbf{Relazione Progetto Reti Logiche}} \\
\vspace{1cm}
{\large Aleandro Pagani} \\
\vspace{0.5cm}
{\large Giugno 2026} \\
\vfill
{\large Matricola: 236992} \\
{\large Codice persona: 10893566} \\
\vspace{1cm}
{\large Professore: Fabio Salice}
\end{titlepage}
\newpage
\pagenumbering{roman}
\tableofcontents
\newpage
\pagenumbering{arabic}
\section{Introduzione}
\subsection{Specifiche generali}
\subsubsection{Descrizione}
Il progetto consiste nel descrivere un modulo hardware che si interfaccia con una memoria in cui la prima cella contiene il contatore dei task e le celle successive la lista ordinata. Il modulo deve supportare quattro tipi di operazioni il cui codice identificativo è fornito in ingresso:
\begin{itemize}
\item \textbf{00}: Decrementa la priorità di tutti i task
\item \textbf{01}: Rimuove il primo task della lista
\item \textbf{10}: Aggiunge un nuovo task in lista
\item \textbf{11}: Svuota completamente la lista
\end{itemize}
\begin{figure}[H]
\centering
\begin{minipage}{0.45\textwidth}
\centering
\includegraphics[width=\textwidth]{INTRODUZIONE/OP_00.png}
\caption*{OP 00.}
\label{fig:00}
\end{minipage}
\hfill
\begin{minipage}{0.45\textwidth}
\centering
\includegraphics[width=\textwidth]{INTRODUZIONE/OP_01.png}
\caption*{OP 01.}
\label{fig:01}
\end{minipage}
\end{figure}
\begin{figure}[H]
\centering
\begin{minipage}{0.45\textwidth}
\centering
\includegraphics[width=\textwidth]{INTRODUZIONE/OP_10.png}
\caption*{OP 10 (inserisco task 000000 01).}
\label{fig:10}
\end{minipage}
\hfill
\begin{minipage}{0.45\textwidth}
\centering
\includegraphics[width=\textwidth]{INTRODUZIONE/OP_11.png}
\caption*{OP 11.}
\label{fig:11}
\end{minipage}
\end{figure}
\newpage
\subsubsection{Funzionamento}
La sincronizzazione tra la logica esterna e il modulo hardware avviene tramite un protocollo di handshake \textbf{START-DONE}.
Il funzionamento del modulo è scandito attraverso 5 fasi:
\begin{itemize}
\item \textbf{Inizializzazione:} Vengono forniti i dati e posto il segnale \textbf{START} a 1.
\item \textbf{Elaborazione:} Il modulo avvia le operazioni e interagisce con la memoria.
\item \textbf{Completamento:} Terminate le operazioni, il modulo imposta il segnale \textbf{DONE} a 1.
\item \textbf{Riconoscimento:} La logica esterna pone il segnale \textbf{START} a 0.
\item \textbf{Ripristino:} Il modulo riporta il segnale \textbf{DONE} a 0 e torna in attesa di nuove direttive.
\end{itemize}
\vspace{0.5cm}
\centerline{\includegraphics[width=0.6\textwidth]{START-DONE handshake.png}}
\newpage
\subsection{Descrizione modulo}
\begin{lstlisting}
entity project_reti_logiche is
port (
i_clk: in std_logic;
i_rst: in std_logic;
i_start: in std_logic;
i_task_id: in std_logic_vector(5 downto 0);
i_task_priority : in std_logic_vector(1 downto 0);
i_op: in std_logic_vector(1 downto 0);
o_done: out std_logic;
o_task_id: out std_logic_vector(5 downto 0);
o_mem_addr : out std_logic_vector(15 downto 0);
i_mem_data : in std_logic_vector(7 downto 0);
o_mem_data : out std_logic_vector(7 downto 0);
o_mem_we: out std_logic;
o_mem_en: out std_logic
);
end project_reti_logiche;
\end{lstlisting}
\begin{itemize}
\item \textbf{i\_clk:} Segnale di clock
\item \textbf{i\_rst:} Segnale di reset
\vspace{0.5cm}
\item \textbf{i\_start:} Segnale \textbf{START} di handshake
\item \textbf{i\_task\_id:} Codice del task da inserire
\item \textbf{i\_task\_priority:} Priorità del task da inserire
\item \textbf{i\_op:} ID dell'operazione da eseguire
\vspace{0.5cm}
\item \textbf{o\_done:} Segnale \textbf{DONE} di handshake
\item \textbf{o\_task\_id:} Codice del task restituito dall'eliminazione
\vspace{0.5cm}
\item \textbf{o\_mem\_addr:} Indirizzo di memoria con cui interagire
\item \textbf{i\_mem\_data:} Informazioni lette dalla memoria
\item \textbf{o\_mem\_data:} Informazioni da scrivere in memoria
\item \textbf{o\_mem\_we:} Flag per abilitare la scrittura in memoria
\item \textbf{o\_mem\_en:} Flag per abilitare la lettura in memoria
\end{itemize}
\newpage
\subsection{Descrizione memoria}
\subsubsection{Implementazione fornita}
\begin{lstlisting}
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity rams_sp_wf is
port(
clk : in std_logic;
we : in std_logic;
en : in std_logic;
addr : in std_logic_vector(15 downto 0);
di : in std_logic_vector(7 downto 0);
do : out std_logic_vector(7 downto 0)
);
end rams_sp_wf;
architecture syn of rams_sp_wf is
type ram_type is array (65535 downto 0) of std_logic_vector(7 downto 0);
signal RAM : ram_type;
begin
process(clk)
begin
if clk'event and clk = '1' then
if en = '1' then
if we = '1' then
RAM(conv_integer(addr)) <= di;
do <= di; -- Write-First
else
do <= RAM(conv_integer(addr));
end if;
end if;
end if;
end process;
end syn;
\end{lstlisting}
\begin{itemize}
\item \textbf{clk:} Segnale di clock
\item \textbf{we:} Flag di scrittura
\item \textbf{en:} Flag di lettura
\item \textbf{addr:} Indirizzo con cui interagire
\item \textbf{di:} Dati in ingresso
\item \textbf{do:} Dati in uscita
\end{itemize}
\newpage
\subsubsection{Layout di memoria}
La RAM indirizza 65536 celle da un byte (indirizzi a 16 bit); la lista ne utilizza al più 64: la prima (\textbf{0}) rappresenta il numero di task presenti, le successive contengono i task (al massimo 63, dato che gli ID sono a 6 bit e l'ID 0 è riservato).\\
Per ogni task, i primi 6 bit ne identificano il codice, mentre gli ultimi 2 la priorità.
\vspace{0.7cm}
\begin{minipage}[c]{0.30\textwidth}
\centering
\includegraphics[width=\textwidth]{MemoryDiagram.png}
\end{minipage}
\hfill
\begin{minipage}[c]{0.60\textwidth}
In questo esempio abbiamo 3 task:
\begin{itemize}
\item \textbf{001111 00:} Task con codice 15 e priorità 0
\item \textbf{010100 00:} Task con codice 20 e priorità 0
\item \textbf{011011 11:} Task con codice 27 e priorità 3
\end{itemize}
Tutti gli altri elementi in memoria non vengono considerati validi.
\end{minipage}
\newpage
\section{Architettura}
Data la dimensione ridotta del progetto, il componente è composto da un unico modulo con due processi: uno sincrono e uno combinatorio.
Nell'implementazione presentata è stata privilegiata la leggibilità rispetto all'efficienza e alla minimizzazione del numero di segnali.
\subsection{Segnali interni}
\begin{lstlisting}
signal state : state_type;
signal next_state : state_type;
signal current_mem_addr : std_logic_vector(15 downto 0);
signal next_mem_addr : std_logic_vector(15 downto 0);
signal current_task_count : std_logic_vector(7 downto 0);
signal next_task_count : std_logic_vector(7 downto 0);
signal current_popped_id : std_logic_vector(5 downto 0);
signal next_popped_id : std_logic_vector(5 downto 0);
signal ctrl_done : std_logic;
signal ctrl_mem_en : std_logic;
signal ctrl_mem_we : std_logic;
signal ctrl_mem_data : std_logic_vector(7 downto 0);
signal ctrl_task_id : std_logic_vector(5 downto 0);
\end{lstlisting}
I registri interni sono organizzati in coppie \textbf{current\_*}/\textbf{next\_*}: il processo combinatorio calcola il valore \textbf{next\_*}, il processo sincrono lo registra in \textbf{current\_*} sul fronte di clock.
\begin{itemize}
\item \textbf{state:} Stato attuale dell'FSM
\item \textbf{next\_state:} Prossimo stato dell'FSM
\vspace{0.5cm}
\item \textbf{current\_mem\_addr / next\_mem\_addr:} Indirizzo di memoria su cui la FSM sta lavorando (0 = contatore, 1..N = task)
\item \textbf{current\_task\_count / next\_task\_count:} Copia locale del numero di task presenti in lista (cella 0 della memoria)
\item \textbf{current\_popped\_id / next\_popped\_id:} ID estratto dall'ultima rimozione, presentato su \textbf{o\_task\_id} quando \textbf{DONE} viene alzato
\vspace{0.5cm}
\item \textbf{ctrl\_done:} Segnale di controllo di \textbf{DONE}
\item \textbf{ctrl\_mem\_en:} Segnale per abilitare la lettura in memoria
\item \textbf{ctrl\_mem\_we:} Segnale per abilitare la scrittura in memoria
\item \textbf{ctrl\_mem\_data:} Dati da scrivere in memoria
\item \textbf{ctrl\_task\_id:} Valore da presentare sull'uscita \textbf{o\_task\_id}
\end{itemize}
\subsection{Processo sincrono}
Questo processo registra sul fronte di salita del clock lo stato, i registri e tutte le uscite del modulo.
\begin{lstlisting}
process(i_clk, i_rst)
begin
if i_rst = '1' then
state <= S_RESET;
o_done <= '1';
o_mem_en <= '0';
o_mem_we <= '0';
elsif rising_edge(i_clk) then
state <= next_state;
current_mem_addr <= next_mem_addr;
current_task_count <= next_task_count;
current_popped_id <= next_popped_id;
o_done <= ctrl_done;
o_mem_en <= ctrl_mem_en;
o_mem_we <= ctrl_mem_we;
o_mem_addr <= next_mem_addr;
o_mem_data <= ctrl_mem_data;
o_task_id <= ctrl_task_id;
end if;
end process;
\end{lstlisting}
Sul fronte di salita del clock i registri \textbf{current\_*} vengono aggiornati con i corrispettivi valori \textbf{next\_*} e, contemporaneamente, vengono scritti sui bus di uscita \textbf{o\_*} i valori calcolati dal processo combinatorio.
Il reset, asincrono, porta la FSM in \textbf{S\_RESET} con \textbf{DONE} a 1 (come richiesto dalla specifica) e disabilita l'interfaccia verso la memoria: in questo modo il modulo non può produrre scritture involontarie mentre il reset è attivo, indipendentemente dall'istante in cui arriva.
\vspace{0.5cm}
Due scelte progettuali meritano attenzione:
\begin{itemize}
\item \textbf{Uscite registrate:} I segnali interni \textbf{ctrl\_*} vengono assegnati alle uscite \textbf{o\_*} solo nel processo sincrono: oltre a separare la logica di controllo dall'aggiornamento delle uscite, questo garantisce che i segnali verso la memoria siano privi di glitch.
\item \textbf{Indirizzo anticipato:} \textbf{o\_mem\_addr} viene registrato da \textbf{next\_mem\_addr} (e non da \textbf{current\_mem\_addr}): l'indirizzo arriva così alla memoria con un ciclo di anticipo rispetto allo stato che ne consumerà il dato. Poiché la memoria ha lettura sincrona con latenza di un ciclo, questa convenzione permette a ogni stato di richiedere una lettura e allo stato successivo (dopo un solo ciclo "cuscinetto") di usarne il risultato.
\end{itemize}
\newpage
\subsection{Processo combinatorio}
Questo è il processo principale del modulo hardware: esso è responsabile della logica interna e della gestione degli stati FSM.\\
Vengono di seguito analizzati tutti gli stati presenti.
\begin{lstlisting}
type state_type is (
S_IDLE, S_RESET, S_DONE,
S_00_READ, S_00_WAIT, S_00_CHECK, S_00_GO_NEXT,
S_01_CHECK_NUMBER, S_01_WAIT, S_01_WRITE, S_01_CHECK_END, S_01_COPY, S_01_GO_NEXT, S_01_WAIT_FOR_COUNT,
S_10_PLACE_AT_START, S_10_WAIT_FOR_CHECK, S_10_CHECK_ID, S_10_WAIT, S_10_COMPARE, S_10_GO_NEXT, S_10_UPDATE_COUNT, S_10_WAIT_FOR_COUNT,
S_11_UPDATE_COUNT, S_11_WAIT_FOR_COUNT
);
\end{lstlisting}
\subsubsection{Stati di gestione del protocollo}
\begin{itemize}
\item \textbf{S\_IDLE:} Stato di attesa. Quando viene rilevato il segnale \textbf{START=1}, viene avviata l'operazione indicata dal codice \textbf{i\_op}. Al dispatch viene anche azzerato il registro \textbf{popped\_id}, così \textbf{o\_task\_id} varrà 0 per ogni operazione diversa da una rimozione andata a buon fine.
\item \textbf{S\_RESET:} Stato di reset. Imposta il contatore nella prima cella di memoria a 0, invalidando tutte le altre, mentre \textbf{DONE} rimane a 1 come richiesto dalla specifica.
\item \textbf{S\_DONE:} Alza \textbf{DONE} e lo tiene a 1 finché \textbf{START} non torna a 0, come richiesto dal protocollo di handshake. Tutte le operazioni raggiungono questo stato un ciclo dopo il proprio stato terminale: \textbf{DONE} sale quindi sempre \emph{dopo} il commit in memoria dell'ultima scrittura, e la logica esterna che campiona la memoria sul fronte di \textbf{DONE} legge dati già aggiornati.
\end{itemize}
\newpage
\subsubsection{Operazione 00}
Questa operazione decrementa la priorità di tutti i task presenti in lista.
Se un task ha già la priorità minima \textbf{11}, questa non viene modificata.
\vspace{0.5cm}
\centerline{\includegraphics[width=0.4\textwidth]{DIAGRAMS/S_00_DIAGRAM.png}}
\vspace{0.5cm}
Gli stati presenti sono 4:
\begin{itemize}
\item \textbf{S\_00\_READ:} Seleziona il primo elemento in lista
\item \textbf{S\_00\_WAIT:} Stato cuscinetto. Serve per dare tempo alla RAM di leggere il contenuto del task selezionato
\item \textbf{S\_00\_CHECK:} Controlla se l'indirizzo selezionato è un task valido. In tal caso, se possibile, ne incrementa la priorità numerica di 1.
\item \textbf{S\_00\_GO\_NEXT:} Seleziona la cella di memoria successiva
\end{itemize}
\newpage
\subsubsection{Operazione 01}
Questa operazione rimuove il primo task della lista e sposta in alto tutti i task sottostanti.
\vspace{0.5cm}
\centerline{\includegraphics[width=0.7\textwidth]{DIAGRAMS/S_01_DIAGRAM.png}}
\vspace{0.5cm}
Gli stati presenti sono 7:
\begin{itemize}
\item \textbf{S\_01\_CHECK\_NUMBER:} Se non ci sono task termina subito (\textbf{o\_task\_id} resterà \textbf{000000}). Altrimenti avvia la lettura del primo task.
\item \textbf{S\_01\_WAIT:} Stato cuscinetto. Serve per dare tempo alla RAM di leggere il contenuto del task selezionato
\item \textbf{S\_01\_WRITE:} Salva l'ID del primo task nel registro \textbf{popped\_id} (verrà presentato su \textbf{o\_task\_id} in \textbf{S\_DONE}) e avvia la lettura del task successivo.
\item \textbf{S\_01\_CHECK\_END:} Controlla se ha raggiunto la fine della lista. In tal caso scrive nella prima cella il valore del contatore decrementato di uno.
\item \textbf{S\_01\_COPY:} Copia il contenuto della cella \textbf{n+1} dentro alla cella \textbf{n}.
\item \textbf{S\_01\_GO\_NEXT:} Passa al task successivo.
\item \textbf{S\_01\_WAIT\_FOR\_COUNT:} Attende il commit della scrittura del contatore, poi transita in \textbf{S\_DONE}.
\end{itemize}
\newpage
\subsubsection{Operazione 10}
Questa operazione inserisce un nuovo task nella posizione corretta secondo la sua priorità, in coda ai task di pari priorità. L'operazione è divisa in due fasi:
\begin{enumerate}
\item \textbf{Scansione duplicati:} la lista viene percorsa dall'ultimo task verso il primo; se viene trovato un task con lo stesso ID, l'inserimento viene ignorato (la specifica vieta la presenza di due task con lo stesso ID). Vengono inoltre scartate immediatamente le richieste con ID = 0, valore riservato dalla specifica come condizione di errore.
\item \textbf{Inserimento dal fondo:} partendo dall'ultimo task e salendo, viene controllata la priorità del task corrente. Se questa risulta numericamente maggiore (gerarchicamente inferiore) rispetto a quella del task da inserire, la cella viene copiata in quella sottostante e il confronto prosegue verso l'alto. Contrariamente, se la priorità dovesse risultare minore o uguale, il nuovo task viene inserito nella cella sottostante: il confronto "minore o uguale" è ciò che colloca il nuovo task \emph{dopo} quelli di pari priorità, garantendo l'ordine FIFO richiesto.
\end{enumerate}
Si fa notare come il caso limite di lista piena non può verificarsi: con ID a 6 bit e ID = 0 escluso esistono al più 63 task distinti, e un 64-esimo inserimento sarebbe necessariamente un duplicato, quindi ignorato dalla fase di scansione.
\vspace{0.5cm}
Di seguito viene illustrato un esempio di inserimento del task \textbf{011110 01}.
Nota: la scansione iniziale per identificare i duplicati viene ignorata nell'esempio.
\begin{itemize}
\item Lultimo task presenta una priorità gerarchicamente minore, di conseguenza viene copiato nella cella sottostante.
\includegraphics[width=0.7\textwidth]{S_10_EXAMPLE/S_10_ITERATION1.png}
\item Si passa quindi al task soprastante. Anche questo presenta una priorità inferiore e viene pertanto copiato nella cella sottostante.
\includegraphics[width=0.7\textwidth]{S_10_EXAMPLE/S_10_ITERATION2.png}
\item Il task nella cella 1 presenta invece una priorità maggiore o uguale: il nuovo task viene quindi inserito nella cella sottostante.
\includegraphics[width=0.87\textwidth]{S_10_EXAMPLE/S_10_ITERATION3.png}
\item Infine, viene aggiornato il contatore.
\end{itemize}
\newpage
\vspace{0.5cm}
\centerline{\includegraphics[width=0.7\textwidth]{DIAGRAMS/S_10_DIAGRAM.png}}
\vspace{0.5cm}
Gli stati presenti sono 8:
\begin{itemize}
\item \textbf{S\_10\_PLACE\_AT\_START:} Scarta le richieste con ID = 0 e avvia la scansione duplicati dall'ultimo task della lista.
\item \textbf{S\_10\_WAIT\_FOR\_CHECK:} Stato cuscinetto della fase di scansione. Serve per dare tempo alla RAM di leggere il contenuto del task selezionato.
\item \textbf{S\_10\_CHECK\_ID:} Confronta l'ID del task letto con quello da inserire. Se coincidono, l'operazione termina senza modifiche; se la scansione ha raggiunto la cima della lista, rilegge l'ultimo task e passa alla fase di inserimento; altrimenti prosegue la scansione verso l'alto.
\item \textbf{S\_10\_WAIT:} Stato cuscinetto della fase di inserimento. Serve per dare tempo alla RAM di leggere il contenuto del task selezionato.
\item \textbf{S\_10\_COMPARE:} Verifica la condizione di inserimento del nuovo task.
Se tutta la lista è stata scorsa (o era vuota), il nuovo task viene scritto in testa.
In caso contrario, se il task da inserire presenta una priorità numericamente maggiore o uguale rispetto al task corrente, viene scritto nella cella sottostante;
se invece presenta una priorità numericamente minore, è il task corrente a venire copiato nella cella sottostante.
\item \textbf{S\_10\_GO\_NEXT:} Seleziona il task precedente nella lista, da confrontare al giro successivo.
\item \textbf{S\_10\_UPDATE\_COUNT:} Aggiorna il contatore con il numero totale di task presenti nella lista.
\item \textbf{S\_10\_WAIT\_FOR\_COUNT:} Attende il commit della scrittura del contatore, poi transita in \textbf{S\_DONE}.
\end{itemize}
\newpage
\subsubsection{Operazione 11}
Questa operazione svuota completamente la lista impostando il contatore dei task a 0 (non è necessario resettare tutti i valori nella memoria).
\vspace{0.5cm}
\centerline{\includegraphics[width=0.7\textwidth]{DIAGRAMS/S_11_DIAGRAM.png}}
\vspace{0.5cm}
Gli stati presenti sono 2:
\begin{itemize}
\item \textbf{S\_11\_UPDATE\_COUNT:} Imposta il contatore a 0.
\item \textbf{S\_11\_WAIT\_FOR\_COUNT:} Attende il commit della scrittura del contatore, poi transita in \textbf{S\_DONE}.
\end{itemize}
\newpage
\section{Risultati sperimentali}
\subsection{Report di sintesi}
\subsubsection{Risorse utilizzate}
La seguente tabella mostra le risorse hardware occupate dal design sul dispositivo target Artix-7 FPGA xc7a200tfbg484-1. L'utilizzo è estremamente contenuto: le Slice LUT occupano solo lo 0.13\% delle risorse disponibili e i registri lo 0.03\%, confermando che il modulo è decisamente leggero. Inoltre, non è stato inferito alcun latch: tutti gli elementi di memoria sono flip-flop, a conferma che il processo combinatorio assegna un valore di default a ogni segnale in ogni ramo.
\begin{table}[H]
\centering
\caption{Risorse utilizzate -- Slice Logic}
\label{tab:utilization}
\begin{tabular}{lrrrrr}
\toprule
\textbf{Site Type} & \textbf{Used} & \textbf{Fixed} & \textbf{Prohibited} & \textbf{Available} & \textbf{Util\%} \\
\midrule
Slice LUTs* & 181 & 0 & 0 & 134600 & 0.13 \\
\quad LUT as Logic & 181 & 0 & 0 & 134600 & 0.13 \\
\quad LUT as Memory & 0 & 0 & 0 & 46200 & 0.00 \\
Slice Registers & 71 & 0 & 0 & 269200 & 0.03 \\
\quad Register as Flip Flop & 71 & 0 & 0 & 269200 & 0.03 \\
\quad Register as Latch & 0 & 0 & 0 & 269200 & 0.00 \\
F7 Muxes & 0 & 0 & 0 & 67300 & 0.00 \\
F8 Muxes & 0 & 0 & 0 & 33650 & 0.00 \\
Unique Control Sets & 6 & -- & 0 & 33650 & 0.02 \\
\bottomrule
\end{tabular}
\end{table}
\newpage
\subsubsection{FSM codificata}
La tabella riporta la codifica degli stati FSM generata automaticamente dal tool di sintesi. Sono presenti in totale 24 stati. Vivado ha scelto una codifica \textbf{one-hot} (un flip-flop per stato, 24 bit complessivi), tipica sulle FPGA: aumenta il numero di registri, risorsa abbondante, ma minimizza la logica di decodifica dello stato e ne accorcia i percorsi combinatori. Per compattezza la tabella riporta, per ogni stato, l'indice del bit attivo della codifica one-hot e la codifica sequenziale a 5 bit di partenza.
\begin{table}[H]
\caption{FSM -- Codifica degli stati}
\label{tab:fsm-encoding}
\centering
\begin{tabular}{lcc}
\toprule
\textbf{Stato} & \textbf{One-hot (bit attivo)} & \textbf{Previous Encoding} \\
\midrule
\texttt{s\_reset} & 0 & 00001 \\
\texttt{s\_done} & 1 & 00010 \\
\texttt{s\_idle} & 2 & 00000 \\
\texttt{s\_00\_read} & 3 & 00011 \\
\texttt{s\_00\_wait} & 4 & 00100 \\
\texttt{s\_00\_check} & 5 & 00101 \\
\texttt{s\_00\_go\_next} & 6 & 00110 \\
\texttt{s\_01\_check\_number} & 7 & 00111 \\
\texttt{s\_01\_wait} & 8 & 01000 \\
\texttt{s\_01\_write} & 9 & 01001 \\
\texttt{s\_01\_check\_end} & 10 & 01010 \\
\texttt{s\_01\_wait\_for\_count}& 11 & 01101 \\
\texttt{s\_01\_copy} & 12 & 01011 \\
\texttt{s\_01\_go\_next} & 13 & 01100 \\
\texttt{s\_10\_place\_at\_start}& 14 & 01110 \\
\texttt{s\_10\_wait\_for\_check}& 15 & 01111 \\
\texttt{s\_10\_check\_id} & 16 & 10000 \\
\texttt{s\_10\_wait} & 17 & 10001 \\
\texttt{s\_10\_compare} & 18 & 10010 \\
\texttt{s\_10\_update\_count} & 19 & 10100 \\
\texttt{s\_10\_wait\_for\_count}& 20 & 10101 \\
\texttt{s\_10\_go\_next} & 21 & 10011 \\
\texttt{s\_11\_update\_count} & 22 & 10110 \\
\texttt{s\_11\_wait\_for\_count}& 23 & 10111 \\
\bottomrule
\end{tabular}
\end{table}
\newpage
\subsubsection{Statistiche RTL}
La tabella dettaglia i componenti RTL inferiti dal tool di sintesi a partire dal codice VHDL. Sono presenti sommatori a 16, 9 e 8 bit per l'aritmetica su indirizzi, priorità e contatore. I registri a 16, 8, 6 e 1 bit corrispondono ai segnali interni e alle uscite registrate del design. I multiplexer a 24 ingressi riflettono la selezione tra i 24 stati della FSM (quelli a 24 bit operano sulla codifica one-hot dello stato).
\begin{table}[H]
\caption{Statistiche RTL -- Componenti}
\label{tab:rtl-stats}
\centering
\small
\begin{tabular}{rlrl}
\toprule
\textbf{Ingressi} & \textbf{Bit} & \textbf{Tipo} & \textbf{Quantità} \\
\midrule
\multicolumn{4}{l}{\textit{Adders}} \\
2 & 16 bit & Adder & 4 \\
2 & 9 bit & Adder & 1 \\
2 & 8 bit & Adder & 3 \\
\midrule
\multicolumn{4}{l}{\textit{Registers}} \\
-- & 16 bit & Register & 1 \\
-- & 8 bit & Register & 2 \\
-- & 6 bit & Register & 2 \\
-- & 1 bit & Register & 3 \\
\midrule
\multicolumn{4}{l}{\textit{Muxes}} \\
24 & 24 bit & Mux & 1 \\
4 & 24 bit & Mux & 1 \\
2 & 24 bit & Mux & 7 \\
2 & 16 bit & Mux & 3 \\
24 & 16 bit & Mux & 1 \\
2 & 8 bit & Mux & 4 \\
24 & 8 bit & Mux & 2 \\
2 & 6 bit & Mux & 1 \\
24 & 6 bit & Mux & 2 \\
2 & 1 bit & Mux & 1 \\
24 & 1 bit & Mux & 6 \\
\bottomrule
\end{tabular}
\end{table}
\newpage
\subsubsection{Timing}
La specifica richiede che il progetto funzioni con un periodo di clock di almeno 20 ns. Il requisito è stato verificato in sintesi applicando il vincolo \texttt{create\_clock -period 20.000} sul segnale \texttt{i\_clk}:
\begin{table}[H]
\centering
\caption{Design Timing Summary (periodo di clock 20 ns)}
\label{tab:timing}
\begin{tabular}{lrr}
\toprule
\textbf{Metrica} & \textbf{Slack (ns)} & \textbf{Endpoint in violazione} \\
\midrule
Worst Negative Slack (setup, WNS) & $+14.786$ & 0 / 114 \\
Worst Hold Slack (WHS) & $+0.149$ & 0 / 114 \\
Worst Pulse Width Slack (WPWS) & $+9.500$ & 0 / 72 \\
\bottomrule
\end{tabular}
\end{table}
Lo slack di setup ampiamente positivo indica che il percorso critico è di circa 5.2 ns: il modulo rispetta il vincolo dei 20 ns con un margine di quasi 4 volte. La correttezza funzionale del circuito sintetizzato è inoltre confermata dalla simulazione post-sintesi (functional) di tutti i test bench descritti nella sezione successiva.
\newpage
\subsection{Report di simulazioni}
\subsubsection{Test bench 1}
Il test bench di esempio fornito dal docente copre le operazioni base quali reset, inserimento in lista, rimozione dalla lista, decremento di priorità e svuotamento della lista.
Seppur non vengano coperti molti casi limite, questo test bench ci offre la possibilità di analizzare facilmente i tempi di esecuzione delle singole operazioni.
Le 10 operazioni, infatti, vengono eseguite correttamente in 2540 ns.\\
In particolar modo, le latenze in cicli di clock (periodo 20 ns), con \textbf{N} task presenti in lista e \textbf{k} task spostati, sono le seguenti:
\begin{itemize}
\item \textbf{OP 00}: $(4 + 3N) \cdot 20\,$ns
\item \textbf{OP 01}: $(6 + 3k) \cdot 20\,$ns, con $k = N - 1$; lista vuota: $2 \cdot 20\,$ns
\item \textbf{OP 10}: $(6 + 2\max(N,1) + 3k) \cdot 20\,$ns
\item \textbf{OP 11}: $3 \cdot 20\,$ns
\end{itemize}
Nota: nell'operazione \textbf{10} il termine $2\max(N,1)$ è il costo della scansione duplicati, che percorre sempre l'intera lista, mentre $3k$ è il costo degli spostamenti, con $k$ compreso tra 0 (inserimento in fondo) e $N$ (inserimento in testa).
Per caratterizzare il comportamento medio, si considera una distribuzione delle priorità equiprobabile: $E[T] = \left(6 + \frac{25}{8}N\right) \cdot 20\,$ns.
Tutte le formule sono state verificate al ciclo esatto da un test bench dedicato (par. 3.2.3).
\begin{figure}[H]
\centering
\includegraphics[width=1\textwidth]{WAVEFORM/RESET.png}
\caption{Operazione di reset.}
\label{fig:reset}
\end{figure}
\begin{figure}[H]
\centering
\includegraphics[width=1\textwidth]{WAVEFORM/INSERIMENTO_VUOTA.png}
\caption{Operazione di inserimento in lista vuota.}
\label{fig:insert_empty}
\end{figure}
\begin{figure}[H]
\centering
\includegraphics[width=1\textwidth]{WAVEFORM/SVUOTA.png}
\caption{Operazione di svuotamento della lista.}
\label{fig:empty}
\end{figure}
\begin{figure}[H]
\centering
\includegraphics[width=1\textwidth]{WAVEFORM/INSERIMENTO_PIENA.png}
\caption{Operazione di inserimento in lista popolata.}
\label{fig:insert_full}
\end{figure}
\begin{figure}[H]
\centering
\includegraphics[width=1\textwidth]{WAVEFORM/RIMOZIONE.png}
\caption{Operazione di rimozione di un task.}
\label{fig:remove}
\end{figure}
\begin{figure}[H]
\centering
\includegraphics[width=1\textwidth]{WAVEFORM/DECREMENTA.png}
\caption{Operazione di decremento della priorità.}
\label{fig:decrease}
\end{figure}
\newpage
\subsubsection{Test bench 2 (casi limite)}
Il secondo test bench è stato pensato per coprire i possibili casi limite che potrebbero presentarsi:
\begin{table}[H]
\centering
\renewcommand{\arraystretch}{1.6}
\begin{tabular}{|m{6cm}|m{8cm}|}
\hline
\textbf{Caso testato} & \textbf{Descrizione} \\
\hline
DONE durante il reset & DONE rimane a 1 durante reset e inizializzazione. \\
\hline
Reset asincrono & Reset durante operazioni in corso: il modulo torna allo stato iniziale senza corrompere la memoria. \\
\hline
Operazioni su lista vuota & Rimozione, decremento e svuotamento su lista vuota non producono scritture. La rimozione restituisce ID = 000000. \\
\hline
Saturazione della priorità & Task già a priorità 11 non vengono modificati da ulteriori decrementi. \\
\hline
Ordinamento e FIFO & Inserimenti con priorità diverse e tra task di pari priorità; l'ordine di estrazione è verificato con rimozioni successive. \\
\hline
ID duplicati e ID = 0 & L'inserimento viene ignorato se l'ID è già presente o vale 0; DONE viene emesso comunque. \\
\hline
Sequenza di stress & Inserimenti, invecchiamenti, rimozioni e svuotamento in sequenza mista. \\
\hline
\end{tabular}
\caption*{Casi limite testati nel test bench 2}
\label{tab:testbench2}
\end{table}
\subsubsection{Test bench 3 (latenze)}
Un terzo test bench misura, per ciascuna operazione, il numero esatto di cicli di clock che intercorrono tra il campionamento di START e l'assertion di DONE, confrontandolo con le formule di latenza riportate nel paragrafo 3.2.1. Le 15 misure (inserimenti con 0--3 spostamenti e inserimento in fondo, rimozioni con lista vuota e con 1--4 task, invecchiamenti con 0--4 task incluso il caso di saturazione completa) coincidono tutte al ciclo esatto con il valore atteso: la FSM non contiene quindi stati morti né attese superflue.
Tutti e tre i test bench passano sia in simulazione comportamentale sia in simulazione post-sintesi functional.
\newpage
\section{Conclusioni}
I test comportamentali e post-sintesi mostrano che il modulo funziona correttamente, rispettando la specifica.
Il componente completa l'elaborazione del test bench di esempio in 2540 ns, con un utilizzo delle risorse hardware
estremamente contenuto: le Slice LUT occupano lo 0.13\% delle risorse disponibili sul
dispositivo target Artix-7 FPGA xc7a200tfbg484-1, senza alcun latch inferito, confermando la leggerezza e la pulizia del design. Il vincolo di clock di 20 ns è rispettato con ampio margine (WNS $+14.786$ ns, percorso critico $\approx 5.2$ ns).
In fase di progettazione ho scelto deliberatamente di adottare un numero di stati superiore allo stretto necessario, privilegiando la leggibilità rispetto all'efficienza. Questa scelta, pur garantendo la correttezza del comportamento, introduce una leggera inefficienza temporale:
accorpando o eliminando alcuni stati intermedi sarebbe possibile ridurre la latenza complessiva di qualche punto percentuale.
Ad esempio, gli stati iniziali di alcune operazioni possono essere accorpati nello stato \textbf{S\_IDLE}, all'interno del ramo di decodifica dell'operazione corrispondente.
\end{document}