Studio, sintesi e implementazione di un timer digitale su FPGA · contatore che controlla...

18
Studio, sintesi e implementazione di un timer digitale su FPGA Introduzione Il seguente progetto ha come obiettivo lo studio, la sintesi e la successiva implementazione di un timer su una FPGA. Le FPGA (field programmable gate array) sono dispositivi programmabili costituiti da un array blocchi logici configurabili (CBL), disposti secondo una matrice bidimensionale, collegati tra loro attraverso delle opportune interconnessioni. Tali blocchi logici contengono delle Look-up Table basate su Ram statica che implementano una generica funzione logica o possono essere usate come elementi di memoria SRAM o come registri. Oltre ai CLB, gli elementi essenziali di una FPGA sono: Blocchi di input/output (IOB). La loro funzione è interfacciare la logica interna con i pin di I/O del dispositivo, configurare il flusso dei dati come ingresso, uscita o bidirezionale, adattare i pin di I/O agli standard più diffusi (TTL, CMOS). Digital Clock Manager (DCM). Distribuiscono i segnali di clock all’interno della FPGA, inoltre, permettono di moltiplicare o dividere la frequenza di clock, di variare la fase e di correggere eventuali problemi di clock skew. Blocchi moltiplicatori. Calcolano il prodotto di due numeri a 18 bit. Il numero di tali componenti e il tipo di specifiche di ciascun componente variano in base al modello di FPGA utilizzato.

Transcript of Studio, sintesi e implementazione di un timer digitale su FPGA · contatore che controlla...

Page 1: Studio, sintesi e implementazione di un timer digitale su FPGA · contatore che controlla contemporaneamente un multiplexer e un anode decoder rispettivamente a quattro ingressi e

Studio, sintesi e implementazione di un

timer digitale su FPGA

Introduzione Il seguente progetto ha come obiettivo lo studio, la sintesi e la successiva

implementazione di un timer su una FPGA.

Le FPGA (field programmable gate array) sono dispositivi programmabili costituiti

da un array blocchi logici configurabili (CBL), disposti secondo una matrice

bidimensionale, collegati tra loro attraverso delle opportune interconnessioni.

Tali blocchi logici contengono delle Look-up Table basate su Ram statica che

implementano una generica funzione logica o possono essere usate come elementi di

memoria SRAM o come registri. Oltre ai CLB, gli elementi essenziali di una FPGA

sono:

• Blocchi di input/output (IOB). La loro funzione è interfacciare la logica

interna con i pin di I/O del dispositivo, configurare il flusso dei dati come

ingresso, uscita o bidirezionale, adattare i pin di I/O agli standard più diffusi

(TTL, CMOS).

• Digital Clock Manager (DCM). Distribuiscono i segnali di clock all’interno

della FPGA, inoltre, permettono di moltiplicare o dividere la frequenza di

clock, di variare la fase e di correggere eventuali problemi di clock skew.

• Blocchi moltiplicatori. Calcolano il prodotto di due numeri a 18 bit.

Il numero di tali componenti e il tipo di specifiche di ciascun componente variano in

base al modello di FPGA utilizzato.

Page 2: Studio, sintesi e implementazione di un timer digitale su FPGA · contatore che controlla contemporaneamente un multiplexer e un anode decoder rispettivamente a quattro ingressi e

Al fine di svolgere una determinata funzione, è necessario programmare la FPGA con

un software che ha il compito di creare le interconnessioni tra i vari componenti.

Come linguaggio di programmazione è stato usato Verilog che permette di descrivere

i circuiti digitali secondo vari livelli di astrazione (in ordine dal più basso al più alto):

• Switch level : il sistema è descritto a livello dei transistor.

• Gate level: il sistema è descritto in termini di porte logiche con le loro relative

interconnessioni.

• Register Transfer level: l’hardware è descritto attraverso un modello formato

da reti combinatorie il cui compito è la trasformazione e l’elaborazione dei

dati e da registri cui spetta il compito di memorizzare tali valori nelle fasi

intermedie delle elaborazioni.

• Behavioural level: è il livello più alto di astrazione e descrive il sistema

mediante algoritmi e funzioni la cui sintassi è simile al C.

Nei circuiti integrati particolarmente complessi, spesso, si preferisce usare una

tipologia mista che comprende i due livelli di astrazione più alti (RTL e Behaviour

level) attraverso i quali si ottiene una completa descrizione del funzionamento di un

circuito e in seguito si utilizzano dei software automatici che generano la descrizione

dello stesso in termini di reti composte da porte logiche elementari.

Obiettivo del Progetto L’obiettivo del progetto consiste nel progettare un timer dalle caratteristiche elencate:

• Abbia una risoluzione al centesimo di secondo.

• Abbia un display a quattro cifre con il seguente formato [00:00] (decine di

secondi, secondi, decimi di secondo, centesimi di secondo).

• Sia controllato da un pulsante di Start/Pausa, e uno di Clear.

Per affrontare lo studio di un circuito digitale complesso si segue una strategia di

progettazione di tipo Top-down ovvero, si scompone un sistema fisico in più blocchi

ognuno dei quali può contenere al suo interno dei sotto-moduli appartenenti ad un

Page 3: Studio, sintesi e implementazione di un timer digitale su FPGA · contatore che controlla contemporaneamente un multiplexer e un anode decoder rispettivamente a quattro ingressi e

livello più basso di gerarchia. Ognuno di essi è studiato separatamente e implementato

in un blocco logico ben definito. Pertanto, si è deciso di scomporre il progetto del

circuito in tre blocchi fondamentali:

• Logica di controllo.

• Logica di conteggio.

• Logica di visualizzazione.

Logica di controllo Il modulo della logica di controllo è responsabile di tutte le operazioni di controllo del

timing come l’inizializzazione, lo stop, la ripresa e l’azzeramento del conteggio in

base ai segnali ricevuti dall’utente. E’ possibile costruire un diagramma degli stati

(modello di Moore) sulla base delle seguenti considerazioni. Per prima cosa la logica

di controllo ha due ingressi con i quali l’utente può interagire con la macchina: un

pulsante di Start, e un pulsante di Clear, indicati con i1, i2 che rappresentano

rispettivamente i segnali di start e azzera.

                                                                                                                               Schema  della  logica  di  controllo

Inoltre esso dispone di un segnale di reset (asincrono) che pone il circuito in uno stato

iniziale S0 (o di riposo detto IDLE). Tutte le operazioni sono scandite dal fronte di

salita di un segnale di clock.

Page 4: Studio, sintesi e implementazione di un timer digitale su FPGA · contatore che controlla contemporaneamente un multiplexer e un anode decoder rispettivamente a quattro ingressi e

 Diagramma  a  stati  della  macchina  di  controllo                                                                                                                                        Tabella  degli  stati  

In uscita alla logica di controllo vi sono due segnali u1, u2 che rappresentano

rispettivamente il segnale di enable, e il segnale di clear, entrambi responsabili del

controllo del modulo di conteggio.

Dunque, la logica di controllo ha essenzialmente sei stati:

• Lo stato di IDLE, in cui la macchina si trova al momento dell’accensione

quando riceve un segnale di RESET, oppure dopo uno stato di CLEAR, in

seguito al rilascio del pulsante di CLEAR. In questa fase i contatori non sono

abilitati al conteggio (u1=0) e sono azzerati (u2=1).

• Lo stato di RUN, in cui la macchina si trova nel momento in cui viene premuto

il tasto START e viene generato un segnale di start (i1=1). In questo nuovo

stato, le uscite si portano rispettivamente a u1=1 e u2=0, ovvero, il conteggio è

abilitato. Tuttavia la macchina rimane in questo stato solamente se la

condizione i1=1 (il tasto START è premuto) continua ad essere verificata. Per

risolvere tale inconveniente, si crea uno stato intermedio RUN1 che ha le

stesse caratteristiche del precedente, in cui la macchina si porta nel momento

in cui il tasto viene rilasciato. Se nessun tasto viene premuto, la macchina

rimane in questo stato per un tempo indefinito.

• Se nella fase di RUN1 viene nuovamente premuto il tasto START (i1=1), la

macchina si porterà in uno stato di PAUSA, in cui i contatori vengono

“congelati” nella loro posizione, portando il segnale di enable a zero (u1=0).

Anche qui, per le stesse ragioni spiegate in precedenza, si inserisce uno stato

supplementare PAUSA1 in cui la macchina si porta una volta che il pulsante di

START è stato rilasciato (i1=0). A questo punto la macchina rimane

indefinitamente in questo stato se nessun pulsante viene premuto (i1=0, i2=0).

Stati  S0   IDLE  S1   RUN  S2   RUN1  S3   PAUSA  S4   PAUSA1  S5   CLEAR  

Page 5: Studio, sintesi e implementazione di un timer digitale su FPGA · contatore che controlla contemporaneamente un multiplexer e un anode decoder rispettivamente a quattro ingressi e

In questo stato vi sono due possibilità: se viene nuovamente premuto START,

la macchina si porta nello stato RUN, e il conteggio riprende dal punto in cui

si era fermato.

• Lo stato di CLEAR, in cui la macchina si trova quando nello stato di PAUSA1

viene premuto il tasto di CLEAR e viene generato un segnale di azzera (i2=1).

In questa fase il conteggio continua ad essere fermo (u1=0) ma i contatori

vengono azzerati (u2=1). Una volta rilasciato il pulsante (i2=0), la macchina si

riporta nello stato di riposo.

Logica di conteggio Il modulo della logica di conteggio ha la funzione di generare l’informazione

temporale da un segnale di clock la cui frequenza è settata a 1KHz. La struttura del

modulo è la seguente: oltre ai segnali di clock e di reset, in comune con il modulo di

controllo, esso riceve in ingresso i due segnali di enable e di clear, mentre in uscita

fornisce l’informazione ai quattro display in formato BCD per un totale di sedici linee

dati. Il modulo è formato da cinque contatori ognuno dei quali divide la frequenza del

contatore precedente per dieci, in modo che il contatore D possa contare i centesimi,

il contatore C i decimi di secondo, il contatore B i secondi, e infine il contatore A le

decine di secondi.

           Schema  del  blocco  di  conteggio                                                                                Schema  logico  del    contatore

Ogni contatore presenta dieci stati identificati dalla notazione Si con i da 0 a 9,

ognuno dei quali identifica l’uscita corrispondente al valore decimale rappresentato.

Page 6: Studio, sintesi e implementazione di un timer digitale su FPGA · contatore che controlla contemporaneamente un multiplexer e un anode decoder rispettivamente a quattro ingressi e

                                                                                                                           Diagramma  degli  stati  di  un  contatore  decimale                                                                                              

Ogni contatore ha in ingresso (oltre ai segnali di clock e reset) il segnale di enable_in

che se abilitato (enable_in=1) porta la macchina nello stato successivo, in presenza di

una transizione positiva del segnale di clock, fino al raggiungimento dello stato S9. In

questo stato viene attivata l’uscita del contatore enable_out per poi essere disattivata

nell’istante in cui si riporta in S0. Quando enable_out=1, il contatore posto in cascata,

il cui ingresso enable_in è collegato all’uscita enable_out del contatore precedente, è

abilitato al conteggio. Pertanto, ogni 10 conteggi, il contatore successivo incrementa

di una unità, e quest’ultimo una volta raggiunti i 10 conteggi, farà incrementare il

contatore posto in cascata di una unità, e così via.

Logica di visualizzazione Il modulo di visualizzazione è responsabile della decodifica dei segnali BCD

provenienti dalle uscite dei contatori e dell’invio di tali informazioni ai quattro

display a sette segmenti. Dalle specifiche della scheda utilizzata emerge che ogni

display è ad anodo comune e condivide assieme agli altri le otto linee dati (sette per i

segmenti più una per il punto che sarà trascurata). Pertanto, l’informazione deve

essere inviata ai display tramite le otto linee di dati collegati ai catodi, mentre

l’accensione di un determinato display avviene contemporaneamente se il relativo

anodo è a livello logico basso. Per tale ragione è dunque necessario implementare un

circuito addizionale che controlli con l’opportuna temporizzazione l’invio della parola

corretta ad ognuno dei display. Se l’accensione di ogni display avviene con una

frequenza superiore rispetto a quella massima percepibile dall’occhio umano, si ha il

Page 7: Studio, sintesi e implementazione di un timer digitale su FPGA · contatore che controlla contemporaneamente un multiplexer e un anode decoder rispettivamente a quattro ingressi e

cosiddetto fenomeno di persistenza della visione, secondo il quale il cervello

interpreta i display come se fossero costantemente accesi.

                                                                                                                                               Schema  del  modulo  di  visualizzazione

Entrando più nel dettaglio, si può vedere come il modulo sia composto da un

contatore che controlla contemporaneamente un multiplexer e un anode decoder

rispettivamente a quattro ingressi e a quattro uscite. Per tale ragione se ne deduce che

quattro stati sono sufficienti per controllare entrambi i dispositivi.

 Schema  della  logica  di  visualizzazione

Contatore Il contatore riceve in ingresso il segnale di clock, la cui frequenza è pari a 1KHz, e un

segnale di reset che lo riporta eventualmente in uno stato iniziale S0. Presenta due

uscite attraverso le quali può scambiare la parola binaria a 2bit con il multiplexer e

l'anode decoder. Dopo un fronte di salita del clock, la macchina si porta dallo stato S0

a quello successivo S1 (e così via), caratterizzato da una differente configurazione

Page 8: Studio, sintesi e implementazione di un timer digitale su FPGA · contatore che controlla contemporaneamente un multiplexer e un anode decoder rispettivamente a quattro ingressi e

delle uscite (indicata in tabella). Essendo il contatore a 2 bit, dopo quattro periodi di

clock, il contatore si riporta nello stato iniziale S0.

Multiplexer, anode decoder, decoder BCD

La necessità di utilizzare un multiplexer nasce dal fatto che, sulla piattaforma di

sviluppo, sono presenti solamente sette linee in comune per comandare i catodi.

Collegando le uscite BCD dei quattro contatori agli ingressi del decoder, ognuna di

queste verrà selezionata di volta in volta e ripresentata in uscita per un tempo pari alla

durata di un periodo di clock. La parola a due bit generata dal contatore comanda gli

ingressi del decoder, in modo tale che in un tempo di 4 ms pari cioè a quattro periodi

di clock, tutte le parole siano state inviate ai display.

Modellazione dei blocchi logici tramite Verilog Il percorso che porta dalla descrizione astratta di un circuito digitale fino alla sua

effettiva implementazione su chip può essere suddiviso in varie fasi. Il primo passo

consiste nella descrizione dei modelli circuitali, mediante un linguaggio ad alto livello

come Verilog attraverso uno dei tanti programmi commerciali come NCVerilog di

Cadence. In questa fase sono prima descritti separatamente i blocchi elementari e

contatore  stati   uscite  

S0   0   0  S1   0   1  S2   1   0  S3   1   1  

               Diagramma  a  stati  del  contatore                                                                                            tabella  degli  stati

Page 9: Studio, sintesi e implementazione di un timer digitale su FPGA · contatore che controlla contemporaneamente un multiplexer e un anode decoder rispettivamente a quattro ingressi e

successivamente istanziati nel modulo Timer che rappresenta il modulo a livello

gerarchico più alto.

Macchina a stati finiti

Il seguente programma ha la funzione di simulare la macchina a stati descritta in

precedenza.

`timescale 1ns/100ps // imposta la scala temporale e la relativa precisione module FSM (enable, clear, start, azzera, clock, reset); // definisce il modulo output enable, clear; //definisce uscite input start, azzera, clock, reset; //definisce entrate reg enable, clear; // dichiara varibili registro reg [2:0] stato; // dichiara variabile stato a 3bit parameter IDLE=0, RUN=1, RUN1=2, PAUSA=3, PAUSA1=4, CLEAR=5; always @(posedge clock or posedge reset) // esegue il modulo ogni volta che si presenta una if (reset) //transizione L->H di clock o di reset begin stato<=IDLE; enable<=0; clear<=1; end else begin case(stato) IDLE: begin enable<=0; clear<=1; if(start) stato<=RUN; end RUN

Page 10: Studio, sintesi e implementazione di un timer digitale su FPGA · contatore che controlla contemporaneamente un multiplexer e un anode decoder rispettivamente a quattro ingressi e

begin enable<=1; clear<=0; if(~start) stato<=RUN1; end RUN1 begin enable<=1; clear<=0; if(start) stato<=PAUSA; end PAUSA begin enable<=0; //blocca il conteggio clear<=0 if(~start) stato<=PAUSA1; // se il pulsante di start è rilasciato rimani in stato di pausa(PAUSA1) end PAUSA1 begin enable<=0; //il conteggio rimane bloccato clear<=0; if(start) stato<=RUN; // se il pulsante di start è premuto torna in RUN if(azzera) stato<=CLEAR; end CLEAR: begin enable<=0; // il conteggio rimane ancora bloccato clear<=1; if(~azzera) stato<=IDLE; end endcase // chiude case end // chiude begin endmodule // chiude module

Modulo Prescaler

La piattaforma di sviluppo FPGA è dotata di un oscillatore al quarzo la cui frequenza

è pari a 50MHz. Per abbassare tale valore alla frequenza utile ai fini del progetto

(1kHz) è necessario implementare un modulo di Clock Prescaler che ha il compito di

svolgere tale funzione. Tale modulo presenta in ingresso il segnale proveniente

dall'oscillatore Clk50 e un segnale di reset e presenta in uscita il segnale di clock. Per

ottenere un periodo di 1!" è dunque necessario moltiplicare il periodo di 20ns per un

fattore 50 ∙ 10!. L'operazione è effettuata attraverso un contatore che conta i fronti di

salita del segnale Clk50 mentre il segnale di clock è a zero (o uno). Una volta

Page 11: Studio, sintesi e implementazione di un timer digitale su FPGA · contatore che controlla contemporaneamente un multiplexer e un anode decoder rispettivamente a quattro ingressi e

raggiunto il fronte di salita numero 25000 (pari a metà dei cicli di clock effettuati in

un periodo) il segnale di clock è ribaltato e rimane in questo valore per altri 24999

fronti di salita. In questa maniera si ottiene un segnale il cui periodo è proprio quello

cercato. `timescale 1ns/100ps // imposta la scala temporale e la relativa precisione module clkPrescaler(clock,reset,Clk50); //definisce il modulo output clock; input reset, Clk50; reg[17:0] counter; // registro da 18 bit per contare fino a 25000 conteggi reg clock; always @(posedge Clk50 or posedge reset) //esegue il blocco in presenza di una transizione L-> H di Clk50 o del segnale di //reset begin if(reset) // in presenza di un segnale di reset begin counter<=0; // metti il contatore a zero

clock<=0; // e metti il segnale di clock a zero end else begin if(counter==24999) //se il conteggio arriva 24999 begin clock<=~clock; // ribalta il segnale counter<=0; // e metti il conteggio a zero end else counter<=counter+1; // incrementa il contatore end // chiudi begin end // chiudi begin endmodule // chiudi module

Modulo contatore decimale Il seguente programma simula un blocco elementare predisposto al conteggio di una

cifra decimale. Per tale ragione la variabile count è un registro a 4 bit ed è perciò

necessario introdurre nel programma delle strutture di controllo, che riportino count a

0 dopo aver assunto il valore decimale 9, o in ogni caso se vi è un segnale di reset o di

clear.

`timescale 1ns/100ps // imposta la timeline temporale e la relativa precisione module Decimal_counter (count,enable_out,clock,reset,clear,enable_in); output[3:0] count; // vettore dati output enable_out; input clock,reset,clear,enable_in; //il valore di enable_out è 1 se contemporaneamente assign enable_out=count==9 && enable_in; // si verifica la condizione count==9 e enable_in è pari a 1 always @(posedge clock or posedge reset) reg[3:0] count; reg enable_out,clear; begin //b1 if(reset||clear) count<=0;

contatore  decimale  

                   clock  prescaler  

Page 12: Studio, sintesi e implementazione di un timer digitale su FPGA · contatore che controlla contemporaneamente un multiplexer e un anode decoder rispettivamente a quattro ingressi e

else begin //b2 if(enable_in) begin //b3 if(count==9) count<=0; else count<=count+1; end // chiudo begin 3 end// chiudo begin2 end // chiudo begin1 endmodule // chiudo module

Modulo Decoder BCD/ display 7 segmenti

Il seguente modulo converte l'uscita del multiplexer out_mux (numero binario in

formato BCD) in una parola binaria di 7 bit di lunghezza CAT. Attraverso il costrutto

case, a seconda del valore di out_mux, è possibile scrivere in CAT la parola binaria

corrispondente alla cifra decimale. La corrispondenza segue la codifica riportata nella

tabella seguente.

 

Codifica  display  7  segmenti  ad  anodo  comune  

In figura vi è il principio di funzionamento di ciascun diodo led. Se ANi è a livello

logico basso, il transistor PNP è in saturazione e pertanto se il catodo si trova a 0!

allora il diodo led è polarizzato direttamente e risulta acceso .

           Circuito  di  polarizzazione  di  un  segmento  led                                                        Display  a  sette  segmenti

carattere a b c d e f g 0 0 0 0 0 0 0 1 1 1 0 0 1 1 1 1 2 0 0 1 0 0 1 0 3 0 0 0 0 1 1 0 4 1 0 0 1 1 0 0 5 0 1 0 0 1 0 0 6 0 1 0 0 0 0 0 7 0 0 0 1 1 1 1 8 0 0 0 0 0 0 0 9 0 0 0 0 1 0 0

Page 13: Studio, sintesi e implementazione di un timer digitale su FPGA · contatore che controlla contemporaneamente un multiplexer e un anode decoder rispettivamente a quattro ingressi e

`timescale 1ns/100ps // imposta la timeline temporale e la relativa precisione module bcd(CAT, out_mux); output[6:0] CAT; // vettore dati uscita per pilotare i catodi input[3:0] out_mux; // vettore di 4 bit reg[6:0] CAT; always @(out_mux) begin case(out_mux) // il carattere _ non è interpretato dal compilatore 0:CAT <=7'b00_00_00_1; 1:CAT <=7'b10_01_11_1; 2:CAT <=7'b00_10_01_0; 3:CAT <=7'b00_00_11_0 4:CAT <=7'b10_01_10_0; 5:CAT <=7'b01_00_10_0; 6:CAT <=7'b01_00_00_0; 7:CAT <=7'b00_01_11_1; 8:CAT <=7'b00_00_00_0; 9:CAT <=7'b00_00_10_0; endcase end // chiudo begin endmodule // chiudo modulo

       

Modulo Display Controller Tale modulo è responsabile, attraverso i tre blocchi always, della simulazione del

contatore, del multiplexer e del decoder anodico. La variabile count è definita come

un registro a 2 bit ed è inizializzata a 0 dal segnale di reset. Contemporaneamente

viene selezionata dal multiplexer la parola presente all'ingresso inA, mentre le uscite

del decoder assumono la configurazione 0111. In seguito, sul fronte di salita di un

nuovo impulso di clock, count incrementa di una unità, parallelamente viene

selezionata la parola presente all'ingresso inB, e viene acceso il secondo display. E

cosi via, fino a quando, durante il quarto ciclo di clock, quando count è pari a 3, un

ulteriore incremento di una unità lo riporta a zero, ripetendo così il ciclo.

`timescale 1ns/100ps // imposta la timeline temporale e la relativa precisione module display_controller(inA,inB,inC,inD,clock,reset,CAT,AN); output[6:0] CAT; output[3:0] AN; input[3:0] inA,inB,inC,inD; input clock,reset; reg[3:0] AN; wire[6:0] CAT;

display  controller  

modulo  BCD  

Page 14: Studio, sintesi e implementazione di un timer digitale su FPGA · contatore che controlla contemporaneamente un multiplexer e un anode decoder rispettivamente a quattro ingressi e

reg[3:0] out_mux; reg [1:0] count; bcd decoderbcd(.CAT(CAT),.out_mux(out_mux)); //creo un'istanza di un decoder BCD all'interno del display controller always @(posedge clock or posedge reset) if (reset) count<=0; else count<=count+1; always @(count or inA or inB or inC or inD) // ad ogni cambiamento della variabile count case(count) // seleziona una delle quattro parole in ingresso 0:out_mux <= inA; 1:out_mux <= inB; 2:out_mux <= inC; 3:out_mux <= inD; endcase always @(count) // ad ogni cambiamento della variabile count accende un diverso display attivandolo case (count) // ponendo l'uscita interessata a livello logico basso 0:AN <= 4'b01_11; 1:AN <= 4'b10_11; 2:AN <= 4'b11_01; 3:AN <= 4'b11_10; endcase endmodule

Modulo TIMER

Il modulo TIMER racchiude tutte le istanze dei moduli precedenti tra cui i cinque

contatori decimali: un divisore di frequenza che divide il clock da 1kHz a 100Hz, i

contatori relativi alle quattro cifre, il modulo di clock prescaler, e il modulo di

controllo dei display. Una volta instanziati, i moduli sono collegati tra loro attraverso

dei wire, i quali provvedono anche a collegare il modulo con i pin esterni.

`timescale 1ns/100 ps module TIMER(CAT,AN,Clk50,start,azzera,reset); output[6:0] CAT; output[3:0] AN; input start,azzera,Clk50,reset; wire enable,clear,clock; wire[3:0] inA,inB,inC,inD; wire enable_in_A,enable_in_B,enable_in_C,enable_in_D; module FSM TIMER(.enable(enable),.clear(clear),.start(start),.azzera(azzera),.clock(clock),.reset(reset));

   

   

ANODE  DECODER   MULTIPLEXER  

contatore uscite ingressi selezionati

uscite AN0 AN1 AN2 AN3 inA inB inC inD

0 0 0 1 1 1 selected 0 1 1 0 1 1 selected 1 0 1 1 0 1 selected 1 1 1 1 1 1 selected

modulo  Timer  

Page 15: Studio, sintesi e implementazione di un timer digitale su FPGA · contatore che controlla contemporaneamente un multiplexer e un anode decoder rispettivamente a quattro ingressi e

Decimal_counter Dcounter (.count(), .enable_out(enable_in_D), .clock(clock), .reset(reset), .clear(clear), .enable_in(enable)); Decimal_counter Dcounter_D (.count(inD), .enable_out(enable_in_C), .clock(clock), .reset(reset), .clear(clear), .enable_in(enable_in_D)); Decimal_counter Dcounter_C (.count(inC), .enable_out(enable_in_B), .clock(clock), .reset(reset), .clear(clear), .enable_in(enable_in_C)); Decimal_counter Dcounter_B (.count(inB), .enable_out(enable_in_A), .clock(clock), .reset(reset), .clear(clear), .enable_in(enable_in_B)); Decimal_counter Dcounter_A (.count(inA), .enable_out(), .clock(clock), .reset(reset), .clear(clear), .enable_in(enable_in_A)); display_control DisplayControl (.AN(AN), .CAT(CAT), .clock(clock), .reset(reset), .inA(inA), .inB(inB), .inC(inC), .inD(inD)); clkPrescaler Prescaler (.clock(clock), .reset(reset), .Clk50(Clk50)); endmodule

Simulazione funzionale

Una volta termina la scrittura dei programmi, si effettua una prima simulazione il cui

scopo è verificare che il codice scritto funzioni secondo le specifiche di progetto. Tale

simulazione è realizzata istanziando dei moduli di Test Bench (il cui codice è simile ai

programmi già visti) all'interno dei quali sono istanziati i moduli da testare (UUT unit

under test), per mezzo di opportuni segnali detti stimoli. Solitamente un modulo di

test contiene un blocco initial in quanto, a differenza del blocco always che viene

ripetuto ciclicamente, questo viene eseguito una volta sola per tutta la durata della

simulazione. Inoltre nel modulo di test compaiono dei Task che sono delle direttive

per salvare il database di simulazione in un file, oppure visualizzarlo in forma grafica.

Esempio di codice per generare un segnale di reset con durata pari a 20ns.

… reg reset; initial begin reset=0; // creo un segnale di reset con durata pari a 10 ns. #20 reset=1; // aspetta 20 ns e poni reset a 1. #10 reset=0; // aspetta 10 ns e poni reset a 0. end

Blocco always per la generazione di un clock a 50MHz …. reg clock; always begin #10 clock=~clock; //dopo 10 ns ribalta il segnale di clock end

Esempio  di  modulo  di  test  bench  

Page 16: Studio, sintesi e implementazione di un timer digitale su FPGA · contatore che controlla contemporaneamente un multiplexer e un anode decoder rispettivamente a quattro ingressi e

Blocco initial per visualizzare il valore di clock (in formato binario) e la variabile

count (in formato decimale) e l’istante (mediante il task $time) in cui tali valori sono

calcolati. initial begin $monitor($time, “clock=%b, count=%d”, clock, count); end Comando per bloccare la simulazione dopo 100 ns `timescale 1ns/100 ps initial begin #100 $finish end

Processo di Sintesi

Il processo di sintesi, attraverso il software FPGA Compiler II di Synopsys, traduce il

codice Verilog in una descrizione a livello di porte logiche (netlist). In questa fase si

crea un nuovo progetto nel quale vengono aggiunti tutti i file sorgenti relativi ai

moduli, specificando infine il modulo Top Level. Successivamente si selezionano le

specifiche relative alla FPGA da programmare, che in questo caso sono:

• Produttore: Xilinx

• Famiglia: Spartan 3

• Dispositivo: XC3S200FT256

• Speedgrade: -4

Una volta selezionate le caratteristiche del dispositivo, è possibile scegliere se

ottimizzare il circuito per area occupata o per velocità. Nel nostro caso, è stata scelta

quest’ultima opzione. Il software provvede quindi a creare la netlist ottimizzata (file

.EDIF) che servirà per la fase successiva di Place and Route e a generare dei file

Verilog tramite i quali, attraverso una nuova simulazione funzionale, si può verificare

la correttezza del sistema descritto dalla netlist stessa.

Page 17: Studio, sintesi e implementazione di un timer digitale su FPGA · contatore che controlla contemporaneamente un multiplexer e un anode decoder rispettivamente a quattro ingressi e

 Flusso di Progetto

Processo di implementazione

In questa fase, attraverso il tool dedicato presente nell’ISE design suite di Xilinx, si

assegnano gli ingressi e le uscite dei moduli agli elementi fisici presenti sulla scheda

come switch, display a quattro cifre, e oscillatore, specificando anche i vincoli

temporali richiesti. L'informazione è immagazzinata all'interno di un file di estensione

".UCF". Una volta definiti i vincoli, il software svolge un’operazione di traduzione

(Translating), in cui è creata una nuova netlist che tiene conto delle informazioni

appena acquisite generando un file ".NGD". In seguito, attraverso il processo di

Mapping si stabilisce la corrispondenza tra i componenti virtuali del disegno e i

componenti della FPGA (celle di logica, celle di I/O) e viene creato un file ".NCD"

(Native Circuit Description) .

Page 18: Studio, sintesi e implementazione di un timer digitale su FPGA · contatore che controlla contemporaneamente un multiplexer e un anode decoder rispettivamente a quattro ingressi e

Nome I/O Pin CAT 0 Output N16 CAT 1 Output F13 CAT 2 Output R16 CAT 3 Output P15 CAT 4 Output N15 CAT 5 Output G13 CAT 6 Output E14 AN 0 Output E13 AN 1 Output F14 AN 2 Output G14 AN 3 Output D14 Clk50 Input T9 start Input M14

azzera Input M13 reset Input L14

 

Tabella  delle  connessioni

In seguito, durante l'operazione di Place and Route i componenti sono piazzati

all'interno dei blocchi logici tenendo conto dei vincoli temporali, della lunghezza

delle connessioni, e della disponibilità delle risorse di instradamento disponibili.

Mentre, nella fase di Route, il software analizza il miglior instradamento possibile tra

i vari blocchi per soddisfare i requisiti temporali richiesti.

Analisi statica dei ritardi

Prima di passare alla fase successiva, attraverso il tool Xilinx Timing Analyzer, con il

quale è possibile analizzare in dettaglio tutti i ritardi dei segnali all’interno della rete,

e a verificare che i ritardi lungo dei determinati percorsi siano compatibili con i

vincoli temporali imposti dalle specifiche.

Processo di Programmazione

Prima di essere caricato su FPGA, il disegno completo deve essere convertito in un

formato compatibile dal chip. Attraverso il tool BitGen, il file (.NCD) viene

convertito in una sequenza di bit bitstream . Il file così ottenuto (.BIT) può essere ora

caricato, tramite cavo parallelo JTAG3, su chip FPGA, attraverso il tool Impact.

Verifica sperimentale

Nell’ultima fase è stato possibile verificare sperimentalmente il corretto

comportamento del timer così implementato, attraverso i pulsanti di start e clear. Tale

verifica ha dato esito positivo.