Skip to content

Operazioni aritmetiche e introduzione al VHDL

La sottrazione funziona in modo simile alla somma; l’unico problema è rappresentare i numeri negativi. Si può realizzare una cella sottrattore a 1 bit con un input di prestito.

Il complemento a 2 di un numero mm è dato da 2nm2^n - m, dove nn è il numero di bit usati per rappresentare il numero.

Vantaggi della codifica in complemento a 2:

  • se sommo 2 numeri positivi ottengo il risultato corretto;
  • se sommo un positivo con un negativo ottengo la differenza;
  • se sommo 2 negativi ottengo di nuovo il risultato corretto;
  • c’è una sola rappresentazione per lo zero (niente zero positivo e zero negativo).

Per fare il complemento a 2 di un numero mm basterebbe fare 2nm2^n - m. Però ci troviamo a dover eseguire un’altra sottrazione.

Possiamo raggirare il problema calcolando il complemento a 1: 2n1m2^n - 1 - m. Notiamo che 2n12^n - 1 è un numero con tutti 11, quindi il risultato della sottrazione con mm è semplicemente il complemento bit a bit di mm.

Per ottenere il complemento a 2 basta poi sommare 11 al complemento a 1.

Posso semplicemente usare un sommatore che prende in input il complemento a 2 del sottraendo.

Sommatore con sottrattore

Quindi posso aggiungere un XOR sui bit in entrata del sommatore, che si attiverà quando immetto un numero negativo. Inoltre per aggiungere 1 basta dare un segnale 1 al primo input del prestito.

Il moltiplicatore a 1 bit funziona esattamente come una AND.

Moltiplicatore 4x3

Per avere una moltiplicazione tra 2 moltiplicandi, uno da nn bit e l’altro da mm bit:

  1. Prendo il moltiplicando con nn bit.
  2. Per ogni suo kk-esimo bit faccio un AND tra quel bit e l’altro moltiplicando. Quindi ottengo o tutti 0 o il valore del moltiplicando.
  3. Sommo tutti gli nn risultati di ogni bit, traslati di kk bit a seconda del bit preso.

Quindi per fare la moltiplicazione di 2 numeri con nn bit servono fino a 2n2n bit per il risultato.

  • divisione;
  • radice quadrata;
  • comparatori;
  • rotazioni e shift (di bit);
  • funzioni trigonometriche;

Possono tutte essere realizzate con porte logiche (almeno in maniera approssimata).

A differenza dei linguaggi software (come il C compilato da gcc), non si ottimizza il codice per le prestazioni: bisogna ottimizzare il numero di porte utilizzate.

L’entità è l’oggetto base del VHDL, corrisponde ad un blocco del circuito. Ogni entità è identificata da un nome e dispone di un certo numero di ingressi ed uscite.

-- entity entity_name is
-- [port (interface_signal_declaration);]
-- end [entity] entity_name;
entity full_adder is
port (
a, b, cin : in bit;
s, cout : out bit
);
end;

L’architettura definisce il comportamento di un blocco. Ne descrive il funzionamento tramite equazioni, connessioni di altri blocchi o tramite un algoritmo.

Ogni entità può avere più architetture diverse.

-- architecture architecture_name of entity_name is
-- [declarations]
-- begin
-- [architecture body]
-- end [architecture] [architecture_name];
architecture componenti of full_adder is
-- dichiarazioni di variabili, etc...
begin
-- descrizione dell'architettura
end;

Se vogliamo fare un paragone con il C, l’entità è la dichiarazione di una funzione, mentre l’architettura ne è la definizione.

  • data flow o equazioni: descrivono il funzionamento tramite equazioni booleane
    • esprimono la dipendenza delle uscite in funzione degli ingressi;
    • vengono descritte tramite sistemi di equazioni;
  • strutturale: collegamento di componenti in una gerarchia;
  • behavioral (comportamentale): descrive il funzionamento tramite un algoritmo;

Esempio: porta AND a 2 ingressi:

entity And2 is
port (
x,y : in bit;
z : out bit;
);
end;
architecture ex1 of And2 is
begin
z <= x and y;
end;

<= è l’operatore di assegnazione.

VHDL dispone di tutti gli operatori dell’algebra booleana:

  • not
  • and
  • or
  • nand
  • nor
  • xor
  • xnor

not ha la precedenza su tutti, mentre gli altri vengono applicati da sinistra verso destra.

Vengono utilizzati per nomi di entità, architetture e segnali. VHDL è case insensitive quindi x e X sono la stessa cosa.

Il testbench è una tipologia di blocchi che si usa per testare il funzionamento di altri blocchi. Con il testbench si decide il valore da dare agli ingressi del blocco da testare.

entity TestAnd2 is
end;
architecture simple of TestAnd2 is
-- Segnali interni al componente.
signal a, b, c : bit;
begin
-- Istanza del modulo da testare.
g1: And2 port map (x => a, y => b, z => c);
-- Definizione degli stimoli sugli ingressi.
a <= '0', '1' after 100ns, '0' after 200ns;
b <= '0', '1' after 150ns, '0' after 200ns;
end;