CID Aplicatii 5

De la WikiLabs
Jump to navigationJump to search

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