CID Aplicatii 5
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