CID Aplicatii 5: Diferență între versiuni

De la WikiLabs
Jump to navigationJump to search
(Pagină nouă: ==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...)
 
Fără descriere a modificării
 
(Nu s-a afișat o versiune intermediară efectuată de același utilizator)
Linia 1: Linia 1:
==Tri-State buffer==
==1. Barrel shifter==
'''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.


[[Fișier:Tri-State buffer.png]]
'''Barrel shifter''' este un circuit combinational folosit pentru operatiile de rotire si deplasare. Acest circuit primeste la intrare un sir de ''n'' biti ('''in [n-1:0]''') si un alt semnal de ''m'' biti (''amount [m-1:0]''), cu ajutorul caruia se comanda numarul de pozitii cu care se va efectua operatia de rotire/deplasare. Intre dimensiunile celor doua semnale exista relatia ''n = 2<sup>m</sup>''.  


Acest tip de buffer permite mai multor circuite sa foloseasca aceeasi linie de iesire.
Pentru implementarea eficienta a unui astfel de circuit, il vom imparti in ''m'' etape: ''stage_0, stage_1 … stage_m-1''. In fiecare din cele ''m'' etape, vom avea un multiplexor care va avea urmatoarul comportament: daca etapa curenta este ''p'', multiplexorul va folosi ca semnal de selectie ''amount[p]''. Daca ''amount[p]'' este 0, mai departe va trece semnalul din etapa anterioara, nemodificat. Altfel, daca ''amount[p]'' este 1, va trece mai departe semnalul din etapa anterioara, deplasat sau rotit cu ''2<sup>p</sup>'' pozitii.
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:


[[Fișier:Connecting Tri-State buffer.png|300px]]
'''Circuit de deplasare la dreapta pentru siruri de 8 biti'''


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.
[[Fișier:Barrel shift right.png]]


'''Implementarea Verilog a circuitului de conectare (magistrala pe 8 biti)'''
<syntaxhighlight lang="Verilog">
<syntaxhighlight lang="Verilog">
module Bidirectional(
module barrel_right_shifter(
     input [7:0] TX,
     input [7:0] in,
     input direction,
     input [2:0] amount,
    output [7:0] RX,
     output [7:0] out
     inout [7:0] data
);
);
wire [7:0] stage0, stage1;


//RX buffer
assign stage0 = (amount[0] == 1) ? {1'b0, in[7:1]} : in;
assign RX = data;
assign stage1 = (amount[1] == 1) ? {2'b0, stage0[7:2]} : stage0;
//TX Tri-State buffer
assign out = (amount[2] == 1) ? {4'b0, stage1[7:4]} : stage1;
assign data = (direction == 1) ? TX : 8'bZ;


endmodule
endmodule
</syntaxhighlight>
</syntaxhighlight>


'''Implementarea Verilog a modulului de test'''
'''Exemplu de modul de test pentru circuitul de deplasare la dreapta pentru siruri de 8 biti'''
 
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.
 
[[Fișier:Tri-State buffer TB.png]]


<syntaxhighlight lang="Verilog">
<syntaxhighlight lang="Verilog">
`timescale 1ns/1ps
`timescale 1ns/1ps


module Bidirectional_TB();
module barrel_right_shifter_TB();


reg [7:0] TX_t;
reg [7:0] in_t;
reg direction_t;
reg [2:0] amount_t;
wire [7:0] RX_t;
wire [7:0] out_t;
wire [7:0] data_t;
reg [7:0] data_in_t;


assign data_t = (direction_t == 0) ? data_in_t : 8'dZ;
integer idx;
reg flag;


initial begin
initial begin
      data_in_t = 8'd0;
    flag = 0;
      TX_t = 8'd1;
    in_t = 8'b11000011;
      direction_t = 1; //transmitere
   
     #2 data_in_t = 8'd7;
     for(idx = 0; idx < 8; idx = idx + 1) begin
      direction_t = 0; //receptie
        amount_t = idx[2:0];
    #2 TX_t = 8'd3;
        #1;
      direction_t = 1; //transmitere
        if(out_t != (in_t >> amount_t))
     #5 $stop();
            flag = 1;
    end
   
    if(flag == 0) $display("TEST_PASS");
    else $display("TEST_FAIL");
      
    $stop();
end
end


Bidirectional DUT(
barrel_right_shifter DUT(
     .TX(TX_t),
     .in(in_t),
     .direction(direction_t),
     .amount(amount_t),
     .RX(RX_t),
     .out(out_t)
    .data(data_t)
);
);
 
endmodule
endmodule
</syntaxhighlight>
</syntaxhighlight>


'''Observatii'''
'''Circuit de rotire la dreapta pentru siruri de 8 biti'''


'''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).  
[[Fișier:Barrel rotate right.png]]


'''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'''.
<syntaxhighlight lang="Verilog">
module  barrel_right_shifter(
    input [7:0] in,
    input [2:0] amount,
    output [7:0] out
);
wire [7:0] stage0, stage1;
 
assign stage0 = (amount[0] == 1) ? {in[0], in[7:1]} : in;
assign stage1 = (amount[1] == 1) ? {stage0[1:0], stage0[7:2]} : stage0;
assign out = (amount[2] == 1) ? {stage1[3:0], stage1[7:4]} : stage1;


endmodule
</syntaxhighlight>


==Realizarea unei unitati de adunare ce are capacitatea de a selecta intre mai multi operanzi==
==2. Realizarea unei unitati de adunare ce are capacitatea de a selecta intre mai multi operanzi==


[[Fișier:Adder 4 inputs.png]]
[[Fișier:Adder 4 inputs.png]]


Circuitul ALU este format din trei module: doua multiplexoare identice ('''M1''' si '''M2''') si un modul de adunare ('''ADD''').
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'''.
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'''.
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'''
'''Implementarea Verilog a modulului MUX'''

Versiunea curentă din 27 martie 2021 10:10

1. Barrel shifter

Barrel shifter este un circuit combinational folosit pentru operatiile de rotire si deplasare. Acest circuit primeste la intrare un sir de n biti (in [n-1:0]) si un alt semnal de m biti (amount [m-1:0]), cu ajutorul caruia se comanda numarul de pozitii cu care se va efectua operatia de rotire/deplasare. Intre dimensiunile celor doua semnale exista relatia n = 2m.

Pentru implementarea eficienta a unui astfel de circuit, il vom imparti in m etape: stage_0, stage_1 … stage_m-1. In fiecare din cele m etape, vom avea un multiplexor care va avea urmatoarul comportament: daca etapa curenta este p, multiplexorul va folosi ca semnal de selectie amount[p]. Daca amount[p] este 0, mai departe va trece semnalul din etapa anterioara, nemodificat. Altfel, daca amount[p] este 1, va trece mai departe semnalul din etapa anterioara, deplasat sau rotit cu 2p pozitii.

Circuit de deplasare la dreapta pentru siruri de 8 biti

module  barrel_right_shifter(
    input [7:0] in,
    input [2:0] amount,
    output [7:0] out
);
 
wire [7:0] stage0, stage1;

assign stage0 = (amount[0] == 1) ? {1'b0, in[7:1]} : in;
assign stage1 = (amount[1] == 1) ? {2'b0, stage0[7:2]} : stage0;
assign out = (amount[2] == 1) ? {4'b0, stage1[7:4]} : stage1;

endmodule

Exemplu de modul de test pentru circuitul de deplasare la dreapta pentru siruri de 8 biti

`timescale 1ns/1ps

module barrel_right_shifter_TB();

reg [7:0] in_t;
reg [2:0] amount_t;
wire [7:0] out_t;

integer idx;
reg flag;

initial begin
    flag = 0;
    in_t = 8'b11000011;
    
    for(idx = 0; idx < 8; idx = idx + 1) begin
        amount_t = idx[2:0];
        #1;
        if(out_t != (in_t >> amount_t))
            flag = 1;
    end
    
    if(flag == 0) $display("TEST_PASS");
    else $display("TEST_FAIL");
    
    $stop();
end

barrel_right_shifter DUT(
    .in(in_t),
    .amount(amount_t),
    .out(out_t)
); 

endmodule

Circuit de rotire la dreapta pentru siruri de 8 biti

module  barrel_right_shifter(
    input [7:0] in,
    input [2:0] amount,
    output [7:0] out
);
 
wire [7:0] stage0, stage1;

assign stage0 = (amount[0] == 1) ? {in[0], in[7:1]} : in;
assign stage1 = (amount[1] == 1) ? {stage0[1:0], stage0[7:2]} : stage0;
assign out = (amount[2] == 1) ? {stage1[3:0], stage1[7:4]} : stage1;

endmodule

2. 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