Sunteți pe pagina 1din 5

http://arh.pub.

ro/lab/cid1

Circuite Integrate Digitale

Circuite secventiale. Memoria sincrona. Circuitul de debounce


Implementare in Verilog si sinteza.
Notiuni de Verilog necesare in acest laborator:

In verilog se pot folosi doua tipuri de atribuiri: blocking si non-blocking.


Atribuire blocking (=): atribuirea se face inainte sa se treaca la urmatoarea instructiune. De exemplu
daca scriem b=a; c=b; a=c; dupa parcurgerea acestora toate vor avea valoarea a.
Atribuire non-blocking (<=): evalueza partea dreapta a expresiei la inceputul unitatii de timp si atribuie
partea stanga a expresiei la sfarsitul unitatii de timp. Daca avem exemplul de mai sus cu atribuirea nonblocking b<=a; c<=b; a<=c; dupa parcurgerea acestora vom observa ca b va avea valoarea a, c va avea
valoarea b iar a va avea valoare c. Spre deosebire de atribuirea blocking, atribuirea non-blocking
introduce o intarziere controlata. Efectul atribuirii non-blocking esta acela ca se folosesc valorile vechi
ale variabilelor la inceputul unitatii de timp si la sfarsitul acesteia sunt atribuite noile valori.
Atribuire non-blocking se foloseste in circuitele secventiale, cu mentiunea ca variabilele folosite pentru
atribuire sunt de tip reg.

Instantierea modulelor.
Un tip de instantiere l-ati intalnit in laboratorul 3 cand se instantia modulul ce trebuia sa fie testat in
modulul de test. Asemanator se pot instantia si alte oricare 2 module. De exemplu daca avem modulul
sumatorului pe un bit definit cu intrarile si iesirile definite ca mai jos:

module adder (
output sum,
output carry_out,
input a,
input b,
input carry_in
);
assign {carry_out,sum}=a + b + carry_in;
endmodule
Pentru a putea face suma a doua numere pe 4 biti vom instantia modulul sumatorului pe un bit de patru
ori in noul modul:

module four_bit_adder ( sum, carry_out, a, b, carry_in ) ;


input carry_in;
input[3:0] a, b;
output carry_out;
output[3:0] sum;
wire carry_l, carry_2, carry_3; //decl conexiunilor interne
adder

add_3 (sum[3], carry_out, a[3], b[3], carry_3),


add_2 (sum[2], carry_3, a[2], b[2], carry_2),
add_1 (sum[1], carry_2, a[1], b[1], carry_1),
add_0 (sum[0], carry_1, a[0], b[0], carry_in);

endmodule

Ca si in C/C++ si Verilog pot fi decalrati diferiti parametri (in C/C++ constante). Acest lucru se face cu
ajutorul cuvantului cheie parameter. De exemplu definim numarul de biti ca parametru: parameter
NrBiti=20; . Acest parametru il putem utiliza de fiecare data cand este nevoie (de exemplu la definirea
unei intrari: input [NrBiti-1:0] in; ).

1/5

http://arh.pub.ro/lab/cid1

Circuite Integrate Digitale

1. Memoria sincrona
In cele ce urmeaza vom afla cum se poate descrie o memorie in limbajul Verilog. Schema bloc a unei
memorii sincrone este data in figura de mai jos. Semnalele de intrare si iesire au urmatoarea semnificatie:
data_in intrare pe 4 biti sunt datele ce pot fi scrise in memorie la adresa indicata de campul address
address intrare pe 4 biti este va indica adresa de scriere si citire (sunt 16 locatii de 4 biti fiecare)
data_out iesire pe 4 biti sunt datele care se citesc de la adresa address
clock intrare pe un bit este semnalul de ceas
enable_write intrare pe un bit este un semnal care valideaza scrierea(daca acest semnal este 1 se face
scrierea, daca este 0 se face doar citire).
data_in
4

addres
s

RAM
16x4

data_out

Codul verilog pentru memoria descrisa mai sus este:

module memorie (
input clock,
input enable_write,
input[3:0] address,
input[3:0] data_in,
output reg[3:0] data_out
);
reg[3:0] mem[0:15];
always @ (posedge clock)
begin
if (enable_write)
begin
mem[address] <= data_in;
end
data_out <= mem[address];
end
endmodule

Modulul de test pentru simulare este dat mai jos.


2/5

clock
enable_writ
e

http://arh.pub.ro/lab/cid1

Circuite Integrate Digitale

module test_mem;
reg clock;
reg enable_write;
reg[3:0] data_in;
reg[3:0] address;
wire[3:0] data_out;
initial
begin
clock = 0;
forever #1 clock =~ clock;
end
initial
begin
address= 0;
enable_write = 0;
data_in = 4'b1001;
$readmemb(lab4_mem.txt, memorie0.mem);
// instructiunea $readmemb citeste
// fisierul lab4_mem.txt care contine date binare
// Aceste date sunt incarcate in memoria
memorie0.mem
// Fisierul lab4_mem.txt poate fi gasit aici
#2 address = address+1;
#2 address = address+1;
#2 address = address+1;
#2 address = address+1;
#2 enable_write=1;
#2 enable_write=0;
#2 data_in=4'b1100;
#2 enable_write=1;
#2 data_in=4'b1011;
#2 enable_write=0;
#4 $stop;
//se opreste simularea
end
memorie memorie0 (
.clock (clock),
.enable_write (enable_write),
.address (address),
.data_in (data_in),
.data_out (data_out)
);
endmodule
3/5

http://arh.pub.ro/lab/cid1

Circuite Integrate Digitale

Sa se faca sintetiza modulului memorie dupa cum urmeaza:


intrarea clock se leaga la generator de ceas extern (P77)
intrarea enable_write trebuie asignata la BTN0
intrarea data_in trebuie asignata la SW4 SW7
intrarea address trebuie asignata la SW0 SW3
iesirea data_out trebuie asignata la LD0 LD3

2. Circuitul de debounce
In circuitele secventiale orice variabila de intrare care nu este dependenta de ceasul sistemului este o
intrare asincrona. Majoritatea acestor intrari asincrone provin de la dispozitive mecanice, cum ar fi cele patru
butoane de pe placa de dezvoltare din laborator.
Pe langa faptul ca sunt asincrone aceste semnale nu sunt perfect dreptunghiulare, elementele mecanice
din interiorul butoanelor avand nevoie de un mic timp pentru a se stabiliza. In acest timp semnalul generat este
format din multe spike-uri, care conduc la functionarea gresita a circuitului nostru (se comporta ca un semnal
dreptunghiular de frecventa foarte mare).
Ne propunem sa rezolvam aceasta problema prin ignorarea acelei perioade din semnal (cateva
milisecunde). Acest lucru il face circuitul de Debounce, care primeste la intrare un semnal, asemanator lui in din
figura de mai jos si genereaza la iesire un semnal perfect dreptunghiular de durata unui singur tact de ceas
(out din figura de mai jos).
Circuitul de Debounce se va folosi numai cand circuitul nostru foloseste ca intrari butoanele de pe
placa (pentru switch-uri nu se foloseste).

650000

clock
in
out

Codul verilog pentru circuitul de debounce este prezentat mai jos:

4/5

http://arh.pub.ro/lab/cid1

Circuite Integrate Digitale

module debounce (
input reset,
input clock,
input in,
output reg out
);
parameter NDELAY = 650000;
parameter NBITS = 20;
reg [NBITS-1:0] count;
reg lastin;
always @ (posedge clock or posedge reset) begin
if (reset) begin
lastin <= 0;
out <= 0;
count <= 0;
end else if (out) begin
out <= 0;
end else if (in != lastin) begin
lastin <= in;
count <= in;
end else if (count == NDELAY) begin
out <= 1;
count <= 0;
end else if (count != 0) begin
count <= count+1;
end
end //end of always block
endmodule
Nu este nevoie sa se faca simulare sau sinteza pentru circuitul de debounce. Acest circuit va fi de folos
pentru a implementa exercitiile.

3. Exercitii pentru laborator:


1.

Simulati circuitul de memorie sincrona.

2.

Modificati modulul numarator din laboratorul 2 astfel incat incrementarea sa se faca la apasarea unuia
dintre butoane. Daca se apasa butonul de 3 ori numaratorul trebuie sa aiba valoarea 3.
Hint: Se foloseste circuitul de debounce. Acesta trebuie instantiat in modulul numarator. Detalii legate
de instantiere gasiti pe prima pagina a acestui laborator.

3. Modificati modulul de memorie sincrona astfel incat pe comutatoarele SW3-SW0 sa setati data_in, pe
comutatoarele SW7-SW4 sa setati adresa, pe BTN0 sa setati enable_write, pe LD3-LD0 sa afisati
data_out. Folositi un debouncer pentru enable_write.

5/5

S-ar putea să vă placă și