En este post veremos como hacer la Programación de ALU en tarjeta Altera; por sus siglas en ingles; Aritmetic Logic Unit. El desarrollo se generó en un Verilog, el cual es un lenguaje de programación de descripción de hardware. La herramienta utilizada será Quartus en su versión II a 64 bits.
Definiremos con ALU a la unidad aritmética lógica, la cual es un circuito que tiene la capacidad de calcular operaciones aritméticas y lógicas.
Se utilizo una tarjeta EP3C16F484 para las pruebas.
DESCRIPCIÓN DEL CIRCUITO
El modulo tiene 3 entradas que serán Operador A , Operador B y Operación:
La siguiente tabla describe cada entrada.
1 | Operador A | El operador A, será el primer operando para la ALU. El tamaño será de 4 bits |
2 | Operador B | El operador A, será el segundo operando para la ALU. El tamaño será de 4 bits |
3 | Operación | La Operación podrá ser algebraica o logica El tamaño será de 3 bits |
TIPOS DE OPERACIONES QUE SOPORTA LA ALU
La ALU desarrollada soporta 8 operaciones descritas a continuación.
Operación | Identificador | Descripción |
ADD | 3’h0 | Suma Operando A y operando B |
SUB | 3’h1 | Resta Operando A y operando B |
AND | 3’h2 | Genera un AND de Operando A y operando B |
OR | 3’h3 | Genera un OR de Operando A y operando B |
XOR | 3’h4 | Genera un XOR de Operando A y operando B |
NOTA | 3’h5 | Regresa la negación de A |
NOTB | 3’h6 | Regresa la negación de B |
ADDp | 3’h7 | Al resultado suma un 1 |
DIAGRAMA DE BLOQUES DEL CIRCUITO
RTL VIEWER
TABLA FUNCIONAL DEL CIRCUITO
Operación | Resultado | Banderas | Descripción | Evidencia |
000 | A + B | Carry = off por default Carry = on si existe acarreo en F[4] | Suma | |
001 | A – B | Flag = En caso de B > A | Resta | |
010 | A and B | N/A | Bitwise | |
011 | A OR B | N/A | Bitwise | |
100 | A XOR B | N/A | Bitwise | |
101 | NOT A | N/A | Niega A | |
110 | NOT B | N/A | Niega B | |
111 | A + B + 1 | N/A | Suma de A + B y un 1 mas |
CODIGO EN FORMATO IMPRIMIR PANTALLA
SIMULACION Y RESULTADOS
Se generaron 2 ALU para validar el correcto funcionamiento de las mismas.
Para probar las 2 ALU, se genero una prueba de Simulación con el siguiente código, donde compara todas las posibles combinaciones.
Programación de ALU en tarjeta Altera en Código de 2 ALU y Simulación
for (i=0;i<7;i=i+1) //Controla operacion
begin
Op = i;
#10
for (j=0;j<15;j=j+1) //Controla valor A
begin
#10
A = j;
for (k=0;k<15;k=k+1) //Controlar valor B
begin
#10
B = k;
if ((F1==F2) && (Sign2==Sign1)) //compara resultado de F1 y F2
begin
$display(“test PASSED con los siguientes valores:”);
$monitor(“TIME=%d, Variable_A=%d, Variable_B=%d, Resultado_Alu1=%d, Resultado_Alu2=%d, Operador=%d, Signo_Alu1=%d, Signo_Alu2=%d”,$time, A, B, F1, F2, i, Sign1, Sign2); //Imprime los valores c
end
else
begin
$display(“test FAILED con los siguientes valores:”);
$monitor(“TIME=%d, Variable_A=%d, Variable_B=%d, Resultado_Alu1=%d, Resultado_Alu2=%d, Operador=%d, Signo_Alu1=%d, Signo_Alu2=%d”,$time, A, B, F1, F2, i, Sign1, Sign2); //Imprime los valores cuando ambas alu son iguales
end
end
end
end
Diagrama de Bloques de 2 ALU + Simulación
Impresión de pantalla de simulación
La siguiente imagen muestra la simulación desde el menú Transcript y wave.
CODIGO
module alu4b(A,B,Op,F,Co,Sign);
//Código para Programación de ALU en tarjeta Altera
//Se definen los parametros
parameter ADD = 3’h0;
parameter SUB = 3’h1;
parameter AND = 3’h2;
parameter OR = 3’h3;
parameter XOR = 3’h4;
parameter NOTA = 3’h5;
parameter NOTB = 3’h6;
parameter ADDp = 3’h7;
input [3:0] A; //Entrada de A
input [3:0] B; //Entrada de B
input [2:0] Op; //Entrada de operacion
output [3:0] F; //salida de F
output Co ; //tarea
output Sign ; //tarea
reg [4:0] F_temp; //Almacenara los resultados de las op temporalmente
reg S_temp;
assign F=F_temp[3:0];
assign Co = F_temp[4];
assign Sign = (Op == SUB)?S_temp:1’b0; //Operador ternar
//Always se ejecuta cuando hay un CAMBIO en la lista de sencibilidad
always@(*)
begin
case(Op)
ADD:
begin
F_temp = A + B;
S_temp=1’b0;
end
SUB:
begin
if(A>=B)
begin
F_temp = A – B;
S_temp=1’b0; //Signo positivo por ser resta A-B 0, NO HAY SIGNO
end
else
begin
F_temp = B – A;
S_temp=1’b1; //signo negativo por ser una resta B-A 1, SI HAY SIGNO
end
end
AND:
begin
F_temp = A & B;
end
default: F_temp = 5’h0;
OR:
begin
F_temp = A | B;
end
XOR:
begin
F_temp = A ^ B;
end
NOTA:
begin
F_temp = ~A;
end
NOTB:
begin
F_temp = ~B;
end
ADDp: // A + B + 1 . Sirve para trabajar incrementos
begin
F_temp = A + B + 1;
end
endcase
end
endmodule
*****************************************
module alu4b_top(a,B,Op,dF,dA,dB,dS);
input [3:0] a; //Se puso minuscula a, para poder relacionar directamente con otro archivo
input [3:0] B;
input [2:0] Op; //Bit 2 y 1 es swicht y el 0 es el button
//variables para decoder
output [6:0] dF;
output [6:0] dA;
output [6:0] dB;
output [2:0] dS;
//output dCo; Display Co, se utilizo en dS 1 y 0
//Wire conecta dos modulos internos, en este caso se conectaran las senales internas y tambien puede pasar entre archivos
wire [3:0] wF;
wire wCo; //se comentan por que no usaran deco
wire wSign;
wire nOp0; //creamos nOp0 que lo usaremos para negar el bit 0 de Op
//Instancia de un circuito de otro documento
//U0 una etiqueta
alu4b U0 ( .A(a),
.B(B),
//.Op(Op),
.Op({Op[2:1],nOp0}),
.F(wF),
.Co(wCo),
.Sign(wSign));
//Agregamos el decodificadoraa
// La ” U ” es una etiqueta para saber que circuito se usa
deco U1(.datain(a),.dataout(dA));
deco U2(.datain(B),.dataout(dB));
deco U3(.datain(wF),.dataout(dF));
//Deco para signo y acarreo
//decoSC U4(.datainS(wSign),.datainC(WCo).dataout(dS));
//decoSC U5(.datain(wCo),.dataout(dCo));
assign dS[2] = ~wSign;
assign dS[1:0] = (wCo) ? ~2’b11:~2’b00;
assign nOp0 = ~Op[0];
endmodule
**************************
module deco (datain,dataout);
input [3:0] datain;
output reg [6:0] dataout;
//input [2:0] datainCo;
//input datainS;
//
//assign f= (hjdasjdljask) Asi si fuera asignacion continua
//reg dataout;
always@(*) //always@(datain)
begin
if(datain==4’b0000) dataout=~7’b0111111; //0
else if(datain==4’b0001) dataout=~7’b0000110; //1
else if(datain==4’b0010) dataout=~7’b1011011; //2
else if(datain==4’b0011) dataout=~7’b1001111; //3
else if(datain==4’b0100) dataout=~7’b1100110; //4
else if(datain==4’b0101) dataout=~7’b1101101; //5
else if(datain==4’b0110) dataout=~7’b1111101; //6
else if(datain==4’b0111) dataout=~7’b0000111; //7
else if(datain==4’b1000) dataout=~7’b1111111; //8//El mas facil
else if(datain==4’b1001) dataout=~7’b1101111; //9
else if(datain==4’b1010) dataout=~7’b1110111; //A
else if(datain==4’b1011) dataout=~7’b1111100; //B
else if(datain==4’b1100) dataout=~7’b0111001; //C
else if(datain==4’b1101) dataout=~7’b1011110; //D
else if(datain==4’b1110) dataout=~7’b1111001; //E
else if(datain==4’b1111) dataout=~7’b1110001; //F
else dataout=~7’b1111111;
//else dataout=~7’b0000000;
end
endmodule
Pruebas en la tarjeta
Al final de la Programación de ALU en tarjeta Altera debemos ver en la placa los siguientes resultados .