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  l’Anno  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).  L’ID_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:

●  All’indirizzo 0 è memorizzato il numero di task attualmente presenti nella lista.
●  A  partire  dall’indirizzo  1  sono  memorizzati  i  task  all’interno  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). All’interno 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  l’ordinamento  che  avevano  prima dell’incremento 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  l’ordine  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  all’indirizzo  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  dall’esterno,  viene  posto  a  1  per  avviare  l’operazione
selezionata tramite OP.

●  START  deve  rimanere  a  1  fino  a quando il modulo non porta il segnale DONE a 1,

indicando che l’operazione è 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 all’indirizzo 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
l’azzeramento  è  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 dell’ordine 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  anch’esso  unico  per  tutto  il  sistema.  Tutti  i  segnali
sono sincroni e devono essere interpretati sul fronte di salita del clock. L’unica eccezione è
RESET  che,  invece,  è  asincrono.  RESET  può  essere  generato  in  qualsiasi  momento
dell’esecuzione.

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
l’impossibilità  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 l’operazione da dover effettuare sulla
lista di task;

●    o_done è il segnale DONE di uscita che comunica la fine dell’elaborazione;
●    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  l’indirizzo  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 all’interno 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
L’esempio   qui di seguito mostra il comportamento a seguito dei segnali di ingresso. Qui di
seguito è presente la situazione della memoria a seguito dell’inserimento di diversi task (fase
non  mostrata  nell’esempio).  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.

