CID Aplicatii 6

De la WikiLabs

1. Tri-State buffer

Tri-State Buffer este un circuit care, prin intermediul unui semnal de enable, controleaza daca intrarea sa va fi conectata la iesire sau nu. In cazul in care semnalul de enable este activ, la iesire va fi conectat semnalul de intrare (se comporta ca un buffer obisnuit). Daca enable nu este activ, iesirea sa va fi pusa in stare de high-Z (high-impendance sau open-circuit), deconectand iesirea de la circuitul la care este conectat.

Tri-State buffer.png

Acest tip de buffer permite mai multor circuite sa foloseasca aceeasi linie de iesire. O aplicatie comuna a acestui tip de buffer este conectarea unui circuit la o magistrala bidirectionala. Modalitatea de conectare a unui circuitului la o astfel de magistrala este descrisa in figura urmatoare:

Connecting Tri-State buffer.png

n schema de mai sus, TX reprezinta data ce trebuie transmisa, RX data ce se receptioneaza, data este magistrala bidirectionala, iar direction controleaza directia datelor (circuitul transmite sau receptioneaza). Transmisia si receptia nu se pot face in acelasi timp.

Implementarea Verilog a circuitului de conectare (magistrala pe 8 biti)

module Bidirectional(
    input [7:0] TX,
    input direction,
    output [7:0] RX,
    inout [7:0] data
);

//RX buffer
assign RX = data;
//TX Tri-State buffer
assign data = (direction == 1) ? TX : 8'bZ;

endmodule

Implementarea Verilog a modulului de test

Pentru a putea testa un circuit care contine un Tri-State buffer (un semnal de tip inout), trebuie sa procedam astfel: In modulul de test, pentru fiecare intrare se defineste un reg si pentru fiecare iesire se defineste un wire. Pentru fiecare semnal de tip inout se definesc doua semnale: un wire (aici, data_t), ce va fi conectat la modulul testat, si un reg (aici, data_in_t), ce va fi conectat printr-un Tri-State buffer (enable inversat fata de cel din modulul testat) la semnalul de tip wire (aici, data_t). Vom folosi acest reg pentru a genera stimuli in timpul simularii unei receptii.

Tri-State buffer TB.png

`timescale 1ns/1ps

module Bidirectional_TB();

reg [7:0] TX_t;
reg direction_t;
wire [7:0] RX_t;
wire [7:0] data_t;
reg [7:0] data_in_t;

assign data_t = (direction_t == 0) ? data_in_t : 8'dZ;

initial begin
       data_in_t = 8'd0;
       TX_t = 8'd1;
       direction_t = 1; //transmitere
    #2 data_in_t = 8'd7;
       direction_t = 0; //receptie
    #2 TX_t = 8'd3;
       direction_t = 1; //transmitere
    #5 $stop();
end

Bidirectional DUT(
    .TX(TX_t),
    .direction(direction_t),
    .RX(RX_t),
    .data(data_t)
);
endmodule

Observatii

1. Semnalul data ia valoarea lui TX atunci cand direction este 1. De asemenea, RX ia valoarea lui TX deoarece este conectat la data printr-un buffer simplu. Valoarea lui RX va trebui sa fie ignorata de circuit atunci cand direction este 1 (transmisie).

2. Atunci cand direction este 0 avem o receptie, data si RX actualizandu-se cu valoarea lui data_in_t, care simuleaza un alt modul ce transmite catre circuitul testat. TX nu se modifica in acest caz deoarece este deconectat de catre Tri-State buffer de la magistrala data.

2. Hazardul combinational

Hazardul apare atunci cand modificarea unei intrari a unui circuit combinational determina modificari nedorite ale iesirii. Aceste variatii apar datorita diferentelor de intarzieri ce apar pe diverse cai de la intrare catre iesire.

De unde aceste intarzieri? Fiecare poarta este, asa cum am vazut la inceputul aplicatiilor, un circuit electronic format, de obicei, din tranzistoare MOS. Raspunsul acestor dispozitive nu este instantaneu, introducand astfel intarzieri. Timpul scurs de la modificarea unei intrari a unei porti pana la modificarea corespunzatoare a iesirii se numeste timp de propagare.

In figura urmatoare avem evidentiat timpul de propagare printr-o poarta SAU. De la modificarea lui a pana la modificarea iesirii trece un interval de timp Tp. Acesta este timpul de propagare prin poarta.

Comutare poarta SAU.png

Avand un circuit cu mai multe porti in cascada, caile prin care anumite semnale ajung la intrarile unei anumite porti pot diferi. Datorita timpilor de propagare diferiti care afecteaza aceste semnale pana sa ajunga la poarta curenta si a timpului de propagare efectiv al porti curente, pot aparea la iesire tranzitii nedorite ale semnalelor. Daca la iesire se asteapta ca linia sa ramana constant in 1, dar apare o scurta tranzitie prin 0, hazardul se numeste 1 static. Daca la iesire se asteapta ca linia sa ramana constant in 0, dar apare o scurta tranzitie prin 1, hazardul se numeste 0 static. Daca se asteapta o tranzitie la iesire, dar apare un regim tranzitoriu cu numeroase tranzitii pana la stabilizare, hazardul se numeste dinamic.

Pentru a intelege mai bine, sa consideram exemplul de mai jos:

Circuit comb hazard.png

Observam ca intrarile portii P2 urmeaza cai diferite: semnalul c este iesirea unei porti, avand o intarziere cauzata de timpul de propagare al portii P1, pe cand semnalul b vine direct de la intrare, propagarea prin fir fiind neglijabila. Sa consideram cazul in care intrarea a ramane permanent in 0, iar intrarea b comuta la un moment dat din 0 in 1. Initial, semnalul de iesire c este 1, iar d este 1. Dupa comutarea lui b, semnalul c va comuta din 1 in 0, iar d va ramane 1. Acesta este cazul ideal. In realitate, datorita timpilor de propagare ai portilor logice P1 si P2, vom avea o scurta tranzitie prin 0:

Circuit comb hazard propagare.png


Implementarea Verilog a circuitului

Putem simula timpul de propagare (neobservabil in mod normal in simulare) prin introducerea unor intarzieri (care nu au efect asupra sintezei circuitului) pentru fiecare poarta din circuit:

`timescale 1ns/1ps
module Circuit(
    input a,
    input b,
    output c,
    output d
);

assign #1 c = ~(a | b);
assign #1 d = ~(c & b);

endmodule

Implementarea unui modul de test care sa evidentieze hazardul

`timescale 1ns/1ps

module Circuit_TB();

reg a_t, b_t;
wire c_t, d_t;

initial begin
       a_t = 0;
       b_t = 0;
    #5 b_t = 1;
    #5 $stop();
end

Circuit DUT(
    .a(a_t),
    .b(b_t),
    .c(c_t),
    .d(d_t)
);

endmodule