CID Aplicatii 5
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.
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:
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.
`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.
Realizarea unei unitati de adunare ce are capacitatea de a selecta intre mai multi operanzi
Circuitul ALU este format din trei module: doua multiplexoare identice (M1 si M2) si un modul de adunare (ADD). Modulul MUX are doua intrari pe 8 biti, selectand la iesire una dintre acestea pe baza intrarii de selectie (SEL). De exemplu, daca SEL este 0, iesirea multiplexorului va fi A. Daca SEL este 1, iesirea multiplexorului este B.
Sumatorul ADD va folosi ca operanzi cele doua iesiri ale multiplexoarelor. Daca SEL este 0, M1 va avea la iesire A, iar M2 va avea la iesire C. Asadar, operanzii sumatorului vor fi A si C, iar iesirea modulului ALU va fi A + C. Daca SEL este 1, M1 va avea la iesire B, iar M2 va avea la iesire D. Asadar, operanzii sumatorului vor fi B si D, iar iesirea modulului ALU va fi B + D.
Implementarea Verilog a modulului MUX
module MUX(
input [7:0] in0,
input [7:0] in1,
input sel,
output [7:0] out
);
assign out = (sel == 0) ? in0 : in1;
endmodule
Implementarea Verilog a modulului Adder
module Adder(
input [7:0] in0,
input [7:0] in1,
output [7:0] sum
);
assign sum = in0 + in1;
endmodule
Implementarea Verilog a modulului ALU
module ALU(
input [7:0] A,
input [7:0] B,
input [7:0] C,
input [7:0] D,
input SEL,
output [7:0] OUT
);
wire [7:0] w1, w2;
MUX M1(
.in0(A),
.in1(B),
.sel(SEL),
.out(w1)
);
MUX M2(
.in0(C),
.in1(D),
.sel(SEL),
.out(w2)
);
Adder ADD(
.in0(w1),
.in1(w2),
.sum(OUT)
);
endmodule
Implementarea Verilog a modulului de test
module ALU_TB();
reg [7:0] A_t, B_t, C_t, D_t;
reg SEL_t;
wire OUT_t;
initial begin
A_t = 8'b00000001;
B_t = 8'b00000101;
C_t = 8'b00001111;
D_t = 8'b00001101;
SEL_t = 0;
#1 SEL_t = 1;
#1 B_t = 8'b00000000;
A_t = 8'b00000011;
#1 SEL_t = 0;
#1 $stop();
end
ALU DUT(
.A(A_t),
.B(B_t),
.C(C_t),
.D(D_t),
.SEL(SEL_t),
.OUT(OUT_t)
);
endmodule