|
|
Finding eigen values and corresponding eigen vectors in Verilog
This example works on FinSim 10_05_92 and subsequent versions.
This example shows how to find the eigen values and eigen vectors of a matrix and how to test that indeed they are correct eigenvectors corresponding to given eigen values.
module top;
`include
parameter size = 3;
real p[0:size];
VpFCartesian eval[0:size-1], evct[0:size-1][0:size-1];
VpFCartesian A[0:size-1][0:size-1], I[0:size-1][0:size-1], LI[0:size-1][0:size-1];
integer i, j, k, r;
VpFCartesian B[0:size-1][0:size-1];
VpFCartesian P[0:size-1][0:0];
real norm;
view VpFCartesian evctk[0:size-1][0:0] as evct[$I1][k];
VpFCartesian l;
initial begin
/* initialize matrix A */
A[0][0].Re = 1;
A[0][0].Im = 1;
A[0][1].Re = -1;
A[0][1].Im = -1;
A[0][2].Re = 2;
A[0][2].Im = 2;
A[1][0].Re = 0;
A[1][0].Im = 0;
A[1][1].Re = 0;
A[1][1].Im = 1;
A[1][2].Re = 2;
A[1][2].Im = 0;
A[2][0].Re = 0;
A[2][0].Im = 0;
A[2][1].Re = -1;
A[2][1].Im = 0;
A[2][2].Re = 3;
A[2][2].Im = 1;
$PrintM(A, "%e");
/* compute eigenvalues and eigenvectors of matrix A */
eval = $Eig(A, evct);
$PrintM(eval, "%e");
$PrintM(evct, "%e");
/* check correctness */
$InitM(I, ($I1 == $I2) ? 1 : 0, 0);
k = 0;
i = 0;
while (i < size) begin
// get next distinct root
if (i < (size-1)) begin
while (($VpAbs(eval[i].Re-eval[i+1].Re) < 0.0000001) &&
($VpAbs(eval[i].Im-eval[i+1].Im) < 0.0000001)) begin
i = i + 1;
end
end
l = eval[i];
$display("\n\nTesting root %d: Re=%e Im=%e\n", i, l.Re, l.Im);
LI = l*I;
B = A - LI;
r = $Rank(B);
$display("Rank(B) = %d\n", r);
// check each eigenvalue against its corresponding eigenvectors
$display("There are %d eigenvectors\n", size-r);
for (j = 0; j < size-r; j++) begin
P = B*evctk;
norm = $VpNormAbsMax(P);
if (norm > 0.0001) $display("ERROR: for evect %d norm is %e\n", k, norm);
else $display("OK: for evect %d norm is %e\n", k, norm);
k = k + 1;
end
i = i + 1;
end
$display("Test completed\n");
end
endmodule // top
|