PDA

View Full Version : [VHDL] cronometro


selion
27-12-2008, 14:27
ciao a tutti, sto cercando un cronometro in VHDL che conti da 0 a 60 secondi... qualcuno sa dirmi dove ne posso trovare uno per prendere spunto?

Grazie mille

selion
27-12-2008, 22:52
nessuno ? :muro:

cionci
28-12-2008, 09:23
Ma questo timer deve essere regolato su un clock esterno ? Se sai la frequenza del clock esterno è semplice realizzare il timer è semplicemente un contatore su uno o più registri.

cionci
28-12-2008, 09:26
Usare Time ha poco senso perché misura solo il tempo di simulazione, quindi non è sintetizzabile in hardware.

selion
28-12-2008, 12:27
non sono molto pratico di vhdl... i nteoria io devo solo saper fare un cronometro che vada da 0 a 60...

cionci
28-12-2008, 12:57
Ripeto, senza un clock esterno non ha molto senso (come fai a temporizzare il conteggio ?). Le specifiche del progetto ti devono dire la frequenza del clock, in alternativa dovresti presentare in ingresso il numero di cicli di clock corrispondenti alla durata di un secondo (direi che su un numero a 32 bit va bene), quindi anche un segnale di write/enable che fa in modo di abilitare la scrittura del valore in un registro e di inizializzare il conteggio.

selion
28-12-2008, 13:20
Input: start/restart, stop, reset.
Output: num_sec, num_centsec.
La gestione del sistema deve garantire una reattività agli
ingressi pari a 10 microsec.

queste sono le uniche specifiche che ho..

cionci
28-12-2008, 13:37
Allora includi un generatore di clock nel modulo VHDL...
Questo è un generatore di clock:
process
begin
loop
CLK <= not CLK;
wait for 5 us;
end loop;
end process;
Permette una reattività di 10 microsecondi agli ingressi, come richiesto dal testo. Infatti lo puoi usare anche per sincronizzare la lettura dei segnali in ingresso. Dopo è semplice, basta usare un contatore che conta i colpi di clock.

Una curiosità studi a Pisa ?

selion
28-12-2008, 13:47
nu a genova... ok quello mi serve per il clock... ora come ci costruisco attorno il cronometro ?_?

cionci
28-12-2008, 14:04
nu a genova... ok quello mi serve per il clock... ora come ci costruisco attorno il cronometro ?_?
Bastano due contatori, dopo 100 colpi di clock incrementi i millisecondi, quando i millisecondi arrivano a 1000 incrementi i secondi.

selion
28-12-2008, 14:24
ehm... ho qualche lacuna di vhdl :eek:

cionci
28-12-2008, 14:36
ehm... ho qualche lacuna di vhdl :eek:
Basta studiare, non ci vuole molto :D
In una giornata le cose basilari (e queste sono basilari) le impari.

selion
28-12-2008, 15:07
mi sai indicare una sorta di tutorial inerente al caso ? :o

cionci
28-12-2008, 15:15
Prova questo: http://xoomer.alice.it/nitorqua/vhdl/vhdl.html

selion
29-12-2008, 09:41
sto cercando di smanettare con il link che mi hai passato, una curiosità:

ora io devo fare due contatori ok? Pero' poi come realizzo i due output? cioè mi è richiesto in output solo il numero di sec e il numero dei centesimi di sec...

cionci
29-12-2008, 10:01
Definirai un'entity con gli input e gli ouptput richiesti. Ovviamente visto che l'output dovrà essere un numero binario dovranno essere due numeri binari dovrai usare un vettore di bit per rappresentarlo nella entity:

MSEC_OUT : out std_logic_vector(9 downto 0);
SEC_OUT : out std_logic_vector(5 downto 0);

Ho usato quel numero di bit perché i millisecondi dovranno avere un range da 0 a 1000 (2^10 = 1024) mentre i secondi solo fino a 60 (2^6 = 64).
Quando hai definito la entity e la sua implementazione, puoi passare alla simulazione del funzionamento, ovviamente dipende dall'ambiente che usi per simulare il tutto, ma in teoria basta realizzare un processo quantizzato ogni tot secondi (sempre con la tecnica del wait). Puoi settare reset e start/stop ai valori che vuoi testare (ad esempio potresti esaurire tutti i vari input come una tavola di verità) e vedere l'ouput del contatore dopo 1 ms (+ 10 ns) verificando che abbia effettua un conteggio sui ms e dopo 1 secondo verificando che abbia conteggiato anche il secondo. E così via per verificare che l'output sia quello desiderato ad ogni istante (in realtà non importa verificare ogni istante, l'importante è verificare che i ms arrivati a 999 poi tornino a 0 e i secondi vengano incrementati e che arrivato a 60 secondi l'aggeggio si fermi).
Ovviamente dovrai verificare anche la funzionalità di start/stop e del reset.

selion
29-12-2008, 10:09
sei enorme :cool:

comunque dev'essere perforza un binario in uscita ?

cionci
29-12-2008, 10:10
comunque dev'essere perforza un binario in uscita ?
Sai...nel mondo digitale :D

selion
29-12-2008, 10:16
ora cerco di capire come fare il contatore... in caso ti richiedo :D

cionci
29-12-2008, 10:19
ora cerco di capire come fare il contatore... in caso ti richiedo :D
Intanto prova a fare qualcosa temporizzato dal clock, non direttamente l'intero problema. Fai ad esempio un contatore infinito. Incrementi di 1 un registro e lo assegni in output. Aggiungici anche un reset in modo da resettare il valore del registro (il reset solitamente è attivo basso).
A quel punto diventa semplice generalizzare il tutto ;)

selion
29-12-2008, 10:23
Intanto prova a fare qualcosa temporizzato dal clock, non direttamente l'intero problema. Fai ad esempio un contatore infinito. Incrementi di 1 un registro e lo assegni in output. Aggiungici anche un reset in modo da resettare il valore del registro (il reset solitamente è attivo basso).
A quel punto diventa semplice generalizzare il tutto ;)

eh ma considera che anche quello che hai appena detto per me è totalemente nuovo :P

cionci
29-12-2008, 10:25
eh ma considera che anche quello che hai appena detto per me è totalemente nuovo :P
Lo è per tutti la prima volta che lo si usa ;)

selion
03-01-2009, 09:59
ciao, innanzitutto colgo l'occasione per farti gli auguri :cool:

poi... dici che cosi funziona ?

ENTITY dff_cnt IS

PORT (CLK : IN std_logic;
RST_N : IN std_logic;
EN : IN std_logic;
Q : OUT std_logic_vector(3 DOWNTO 0));

END dff_cnt;


ARCHITECTURE rtl OF dff_cnt IS

SIGNAL i_q : std_logic_vector(3 DOWNTO 0);

BEGIN -- rtl

Q <= i_q;

p_ff: PROCESS (CLK, RST_N)

BEGIN -- PROCESS p_ff

IF RST_N = '0' THEN
i_q <= (OTHERS => '0');

ELSIF CLK'event AND CLK = '1' THEN
IF (EN = '1') THEN
i_q <= i_q + 1;
END IF;
END IF;

END PROCESS p_ff;

END rtl;

cionci
03-01-2009, 16:11
Questo è un contatore sincronizzato da 0 a 15...dovrebbe funzionare. Quando arriva a 15 però al clock successivo ritorna a zero.

selion
03-01-2009, 16:46
scusa ma dove lo vedi che arriva a 15?

al posto dell'azzeramento dovrei incrementare le due uscite che pero' non ho messo :

MSEC_OUT : out std_logic_vector(9 downto 0);
SEC_OUT : out std_logic_vector(5 downto 0);

come mi avevi suggerito... ma basta fare ad esempio MSEC_OUT +1; ?

cionci
03-01-2009, 16:54
Q : OUT std_logic_vector(3 DOWNTO 0)
Sono 4 bit, quindi va da 0 a 15. Se il clock è a 10us conta solo fino a 160 us. A te serve che arrivi a 1000us. Il contatore deve arrivare a 100 e quando arriva a 100 devi incrementare i msec.

selion
03-01-2009, 17:04
ENTITY dff_cnt IS

PORT (CLK : IN std_logic;
RST_N : IN std_logic;
EN : IN std_logic;
Q : OUT std_logic_vector(24 DOWNTO 0));

MSEC_OUT : out std_logic_vector(9 downto 0);
SEC_OUT : out std_logic_vector(5 downto 0);

END dff_cnt;


ARCHITECTURE rtl OF dff_cnt IS

SIGNAL i_q : std_logic_vector(24 DOWNTO 0);

BEGIN -- rtl

Q <= i_q;

p_ff: PROCESS (CLK, RST_N)

BEGIN -- PROCESS p_ff

IF RST_N = '0' THEN
i_q <= (OTHERS => '0');

ELSIF CLK'event AND CLK = '1' THEN
IF (EN = '1') THEN
i_q <= i_q + 1;

ELSIF (Q = i_q) THEN
MSEC_OUT +1;

END IF
END IF;
END IF;

END PROCESS p_ff;

END rtl;

così, parzialmente dici che ci siamo ?

cionci
03-01-2009, 17:18
Q è sempre uguale a i_q ;)
Q non ti serve più come uscita, devi memorizzare il valore interno del contatore di MSEC.

selion
03-01-2009, 17:23
si ma a me interessa incrementare MSEC_OUT (si incrementa come ho fatto io?) solo dopo che ha fatto un giro completo...

l'unica cosa che mi viene in mente è mettere l'incremento dell'uscita fuori dal processo rtl ma mi sembra una cosa un po improvvisata..

cionci
03-01-2009, 17:33
si ma a me interessa incrementare MSEC_OUT (si incrementa come ho fatto io?) solo dopo che ha fatto un giro completo...

Non dopo un giro completo, ma quando arriva a 100 (ti servono 7 bit, non 24), quindi se i_q = 100 incrementi MSEC e azzeri i_q.

Non si fa come hai fatto te, deve esserci un registro interno che contiene il valore dato in uscita MSEC_OUT, quindi assegnare il registro interno all'uscita (così come avviene per Q nel sorgente ora). Tu devi lavorare sul registro interno incrementandolo di uno nella situazione descritta sopra.
Per incrementarlo si fa allo stesso modo in cui hai incrementato i_q.

selion
03-01-2009, 18:01
ok forse ci sono quasi :D intanto ti chiedo, l'output richiesto era centsec non millisec... i bit cambiano quindi giusto ?

MSEC_OUT : out std_logic_vector(9 downto 0); questi diventano 7 giusto ???

cionci
03-01-2009, 18:04
Certo, bastano 7, ovviamente devi verificare che il contatore arrivi a 1000 e non a 100.

selion
03-01-2009, 18:07
ENTITY dff_cnt IS

PORT (CLK : IN std_logic;
RST_N : IN std_logic;
EN : IN std_logic;
Q : OUT std_logic_vector(9 DOWNTO 0));

CSEC_OUT : out std_logic_vector(7 downto 0);
SEC_OUT : out std_logic_vector(5 downto 0);

END dff_cnt;


ARCHITECTURE rtl OF dff_cnt IS

SIGNAL i_q : std_logic_vector(9 DOWNTO 0);
SIGNAL i_CS : std_logic_vector(7 DOWNTO 0);
SIGNAL i_S : std_logic_vector(5 DOWNTO 0);

BEGIN -- rtl

process
begin
loop
CLK <= not CLK;
wait for 5 us;
end loop;
end process;

Q <= i_q;
CSEC_OUT <= i_CS;
SEC_OUT <= i_S;

p_ff: PROCESS (CLK, RST_N)

BEGIN -- PROCESS p_ff

IF RST_N = '0' THEN
i_q <= (OTHERS => '0');

ELSIF CLK'event AND CLK = '1' THEN
IF (EN = '1') THEN
i_q <= i_q + 1;

ELSIF (i_q = 1000) THEN
i_q = 0; i_CS <= i_CS +1;

ELSIF (i_CS = 100) THEN
i_S <= i_S + 1; i_CS = 0;

END IF;
END IF;

END PROCESS p_ff;

END rtl;

a logica mi sto avvicinando:D

xke se non sbaglio ora i bit di Q devono essere 9...

gli errori che mi da sono : il wait non me lo fa sintetizzare

mi dice che non posso fare = 0, se metto <= mi dice che sono di tipo diverso e non posso farlo.. se metto <= "0" mi dice che la dimensione è sbagliata

pensavo, ma se nell'architecture mettessi, anziche i tre vettori, una cosa simile :

ARCHITECTURE rtl OF dff_cnt IS

SIGNAL i_q : natural;
SIGNAL i_CS : natural;
SIGNAL i_S : natural;

cosi da azzerare piu facilmente? in uscita puo andare un natural no ?

selion
04-01-2009, 15:48
ok ho editato il messaggio precedente cosi è tutto piu chiaro :stordita:

selion
05-01-2009, 11:40
cionci non mi abbadonare proprio ora che sono ad un passo:cry: