SoynuevoenlaprogramacióndeVerilog.EstoytratandodetrabajarconunCLAde64bitsmediantelacreacióndeunCLAde4bits,luegode8bits(de2instanciasde4bits),luegode16bits(de2instanciasdeUnode8bits).Proporcionarémicódigo,luegounaexplicacióndelproblemaqueestoyteniendo.Código:
//4-BITCLACODEmoduleCLA4Bit(A,B,carryIn,carryOut,PG,GG,Sum);input[3:0]A,B;inputcarryIn;outputcarryOut;outputPG;outputGG;output[3:0]Sum;wire[3:0]G,P,C;assignG=A&B;assignP=A^B;assignSum=P^C;assignC[0]=carryIn;assignC[1]=G[0]|(P[0]&C[0]);assignC[2]=G[1]|(P[1]&G[0])|(P[1]&P[0]&C[0]);assignC[3]=G[2]|(P[2]&G[1])|(P[2]&P[1]&G[0])|(P[2]&P[1]&P[0]&C[0]);assignPG=P[3]&P[2]&P[1]&P[0];assignGG=G[3]|(P[3]&G[2])|(P[3]&P[2]&G[1])|(P[3]&P[2]&P[1]&G[0]);endmodule//8-BITCLACODEmoduleCLA8Bit(A,B,carryIn,carryOut,Sum);input[7:0]A,B;inputcarryIn;outputcarryOut;output[7:0]Sum;//BlockPropagate(BP)andGroupPropagate(BG)//foreach4-bitCLA"Block"
wire [1:0] BP, BG;
// carryPipe that represents the carryIn for each
// 4-bit CLA group. Calculated by the 2-block LCU
wire [1:0] carryPipe;
// Lookahead Carry Unit (LCU)
LCU2Block LCU8Bit(carryIn, carryOut, BP, BG, carryPipe);
// The two 4-bit CLA blocks that make up the 8-bit CLA
CLA4Bit block1(A[3:0], B[3:0], carryIn, carryPipe[0], BP[0], BG[0], Sum[3:0]);
CLA4Bit block2(A[7:4], B[7:4], carryPipe[0], carryPipe[1], BP[1], BG[1], Sum[7:4]);
endmodule
// 16-BIT CLA
module CLA16Bit_8Bit(A, B, carryIn, carryOut, Sum);
input[15:0] A, B;
input carryIn;
output carryOut;
output[15:0] Sum;
// Block Propagate (BP) and Block Generate (BG)
wire [1:0] BP16Bit, BG16Bit;
// carryPipe that represents the carryIn for each
// 8-bit CLA group; Calculated by the LCU
wire [1:0] carryPipe;
// Lookahead Carry Unit (LCU)
LCU2Block LCU16Bit(carryIn, carryOut, BP16Bit, BG16Bit, carryPipe);
// The 2 instances/"blocks" of 8-bit CLAs that
// make up the 16-bit CLA
CLA8Bit block1(A[7:0], B[7:0], carryIn, carryPipe[0], Sum[7:0]);
CLA8Bit block2(A[15:8], B[15:8], carryPipe[0], carryPipe[1], Sum[15:8]);
endmodule
// THIS IS THE LCU THAT CALCULATES THE CARRIES
module LCU2Block (carryIn, carryOut, BP, BG, carryPipe);
input carryIn;
output carryOut;
// Block Propagate (BP) and Block Generate (BG)
// represent the Group Propagate (PG) and Group
// Generate (GG) of each "Block" of CLAs that are using
// a particular LCU
input[1:0] BP, BG;
// carryPipe represents the carryIn for each 4-bit group of a 16-bit CLA,
// and every 16-bit group of a 64-bit CLA.
output[1:0] carryPipe;
assign carryPipe[0] = BG[0] | (BP[0] & carryIn);
assign carryPipe[1] = BG[1] | (BP[1] & carryPipe[0]);
endmodule
Escribí un banco de pruebas simple para probar mi código:
module CLA_TB();
// Inputs
reg[15:0] A;
reg[15:0] B;
reg carryIn;
// Outputs
wire carryOut;
wire[15:0] Sum;
CLA16Bit_8Bit CLA16Bit_8BitDUT(
.A(A),
.B(B),
.carryIn(carryIn),
.carryOut(carryOut),
.Sum(Sum)
);
initial
begin
assign carryIn = 0;
// Answer should be
// Sum = b0000 0000 0000 0010 = h0002
assign A = 16'b0000000000000001;
assign B = 16'b0000000000000001;
#20
// Answer should be
// Sum = b0000 0000 0100 1001 = h0049
assign A = 16'b0000000000010010;
assign B = 16'b0000000000110111;
#20
// Answer should be
// Sum = 0000 1001 1110 1101 = h09ED
assign A = 16'b0000011001011100;
assign B = 16'b0000001110010001;
#20
// Answer should be
// Sum = b0001 0101 1110 1110 = h15EE (with overflow carry!)
assign A = 16'b1011011111010011;
assign B = 16'b0101111000011011;
#20
$finish;
end
endmodule
Entonces, el problema que tengo es que el CLA de 16 bits calcula correctamente todas las sumas de 4 bits EXCEPTO para el segundo desde la izquierda, que se ve como una X (consulte la imagen).
Sé que las X se muestran en Verilog cuando un cable tiene más de un controlador (fuente de señal), y recientemente descubrí que también mostrará una X si no se le asigna un valor a un cable o si Z es utilizado en una expresión (sin embargo, nunca usé Z en ninguna expresión en mi banco de pruebas).
Sé que mi carryOut es una "Z", pero ese cable es solo un remanente de atrás cuando estaba experimentando con diferentes implementaciones de los CLA; ni siquiera debería haber arrastrado eso al gráfico Wave para mostrarlo. Nunca se utiliza en el cálculo de los acarreos (consulte el código CLA / LCU).
Ya probé mis CLA de 4 bits y 8 bits; ambos funcionan perfectamente bien y agregan con precisión a pesar de la Z en la línea carryOut, así que realmente no creo que ese sea el problema.
No entiendo por qué sucede esto. Mi única suposición es que tiene algo que ver con la forma en que interactúan las dos LCU (la del CLA de 8 bits y la del CLA de 16 bits), ¿tal vez algo vaya mal?
Todavía estoy tratando de solucionar el problema, pero básicamente estoy perplejo, así que decidí publicar aquí en busca de ayuda. ¿Por qué está pasando esto? ¿Cómo puedo solucionarlo?