1 # Generate signed and unsigned nonrecoded 
  2 # Wallace multiplier Verilog. 
  3 # v.0.2, 2017
  4 # John Bryan 
  5 # Perl v5.14.3
  6 # Usage: Script takes 5 arguments; 
  7 # 1.multiplicand length. 
  8 # 2.multiplier length.
  9 # 3.u (for unsigned) or s (for signed).
 10 # 4.d (deterministic) or r (random) tb inputs.
 11 # 5.integer = # increasing operand sizes to be tested
 12 # i.e., perl wallace.pl 16 16 u r 0 
 13 use strict;
 14 use warnings;
 15 use diagnostics;
 16 use 5.006;
 17 use FileHandle;
 18 use List::MoreUtils qw(firstidx);
 19 use IPC::System::Simple qw(system);
 20 local $| = 1;
 21 
 22 
 23 # ten global variables
 24 our @pp;
 25 our %pp;
 26 our $multiplicand_length=$ARGV[0];
 27 our $multiplier_length=$ARGV[1];
 28 our $us=$ARGV[2];
 29 our $dr=$ARGV[3];
 30 our $increment=$ARGV[4];
 31 our $pl;
 32 our %counts;
 33 our $counts=0;
 34 
 35 
 36 # six subroutines 
 37 sub   partial_products;
 38 sub   wallace_tree;
 39 sub   kogge_stone;
 40 sub   testbench;
 41 sub   generate_and_testbench;
 42 sub   generate_and_test;
 43 
 44 
 45 &generate_and_test();
 46 exit(0);
 47 
 48 
 49 sub generate_and_testbench 
 50 {
 51     &partial_products;
 52     &wallace_tree;
 53     &kogge_stone;
 54     &testbench;
 55     return;
 56 }
 57 
 58 
 59 sub partial_products 
 60 {
 61     my $ul =$multiplicand_length - 1;
 62     my $zl =$multiplier_length - 1;
 63     my $ul2 ="a" . "$ul";
 64     my $zl2 ="b" . "$zl";
 65     my @rmultiplicand;
 66     my $i; my $k; my $fh;
 67     for ($i=0; $i < $multiplicand_length; $i++)
 68         { $rmultiplicand[$i]= 'a'.$i; }
 69     my @multiplicand=reverse(@rmultiplicand);
 70     my $multiplicand = @multiplicand;
 71     my @rmultiplier;
 72     for ($i=0; $i < $multiplier_length; $i++)
 73         { $rmultiplier[$i]= 'b'.$i; }
 74     my @multiplier=reverse(@rmultiplier);
 75     my $multiplier = @multiplier;
 76     my $product = $multiplicand + $multiplier;
 77     $pl =$product - 1;
 78     for my $multiplier (@multiplier)
 79     {   for my $multiplicand (@multiplicand)
 80            {push @pp, $multiplier.$multiplicand;}
 81     }
 82     if ($us eq "u")
 83         {open $fh, ">", "wallace.vl";
 84          print $fh ("module wallace(a, b, product);\n");
 85          print $fh ("   // Unsigned nonrecoded Wallace multiplier.\n");}
 86     else {open $fh, ">", "signed_wallace.vl";
 87          print $fh ("module s_wallace(a, b, product);\n");
 88          print $fh ("   // Signed nonrecoded Wallace multiplier.\n");}
 89     print $fh ("   // John Bryan, v.02 2017.\n");
 90     print $fh ("   input [$ul:0] a;\n   input [$zl:0] b;\n");
 91     print $fh ("   output [$pl:0] product;\n");
 92     if ($us eq "s")
 93     {   print $fh ("   assign pho1 = 1'b1;\n");
 94         print $fh ("   assign pho2 = 1'b1;\n");
 95         if ($multiplicand_length != $multiplier_length)
 96             {print $fh ("   assign pho3 = 1'b1;\n");}
 97     }
 98     my $icount=$zl;
 99     my $jcount=$ul;
100     loop_g:
101     for($k = 0; $k < scalar(@pp); $k++)
102     {
103         if (($us eq "s") && ((($icount == $zl)&&($jcount != $ul)) ||
104             (($icount != $zl)&&($jcount == $ul))))
105              {print $fh ("   assign ", $pp[$k], " = ","~(b[",$icount,"]", " & ",
106                           "a[",$jcount,"]);\n");}
107          else
108              {print $fh ("   assign ", $pp[$k], " = ","b[",$icount,"]", " & ",
109                           "a[",$jcount,"];\n");}
110         if ($jcount==0)
111         {   $icount--;
112             $jcount=$ul; }
113         else
114         {   $jcount--; }
115     } #loop_g
116     close $fh;
117     return;
118 }
119 
120 
121 sub wallace_tree 
122 {
123     my $i;
124     my $j;
125     my $k;
126     my(@other_array)=();
127     my %pp_copy;
128     my $key;
129     my $fh;
130     my $value;
131     my $final_flag;
132     my $flag;
133     my $tag;
134     my $string="";
135     my $c_string="";
136     my $cutoff_count;
137     my @sum_array=();
138     my @carry_array=();
139     my @sorted_pp_keys = ();
140     my @sca=();
141     my @carries=();
142     my $sca_count;
143     my $sum_array_index=0;
144     my $carry_array_index=0;
145     my $array_index=0;
146     my $carries_index=0;
147     my @array = ("aaaa" .. "zzzz");
148     @pp{@pp} = (1) x @pp;
149     my @two_nums;
150     while (  ($key, $value) = each(%pp) )
151     {
152          @two_nums=$key =~ /(\d+)/g;
153          $pp{$key}=$two_nums[0]+$two_nums[1];
154     }
155     if ($us eq "s")
156     {
157         $pp{'pho1'}=$pl;
158         my $pho2w;
159         my $pho3w;
160         if ($multiplier_length==$multiplicand_length)
161            {$pp{'pho2'}=$multiplier_length;}
162         else
163            {$pho2w=$multiplier_length-1;
164             $pho3w=$multiplicand_length-1;
165             $pp{'pho2'}=$pho2w;
166             $pp{'pho3'}=$pho3w;}
167     }
168     @other_array=values %pp;       # weights of each pp
169     $counts{$_} ++ for @other_array;
170     $j=scalar(keys %counts)-1;
171     %pp_copy=%pp;
172     $sca_count=0;
173     $flag=1;
174     $tag=0;
175     loop_e:
176     while (($j>-1)&&($flag==1))
177     {
178        loop_d:
179        #loop_d for full adder
180        for ($i=0;$i<int($counts{$j}/3);$i++)
181        {
182            $cutoff_count=0;
183            $string=$array[$array_index];
184            $array_index++;
185            $c_string=$array[$array_index];
186            $array_index++;
187            loop_c:
188            while ( ($key, $value) = each(%pp_copy) )
189            {
190                conditional_b:
191                if (($value==$j) && ($cutoff_count < 3))
192                {
193                    $cutoff_count++;
194                    $pp{$string} = $pp{$key};
195                    $pp{$c_string} = $pp{$key};
196                    $sca[$sca_count] = $key;
197                    $sca_count++;
198                    delete($pp{$key});
199                    delete($pp_copy{$key});
200                    my $n = keys %pp;
201                    conditional_a:
202                    if ($cutoff_count==3)
203                    {
204                        $pp{$c_string} = int($pp{$c_string})+1;
205                        $sum_array[$sum_array_index]= "   assign $string" . ' = ' . "$sca[0]" .  ' ^ ' .
206                                                     "$sca[1]" . ' ^ ' . "$sca[2]" . ';';
207                        $carry_array[$carry_array_index]= "   assign $c_string" . ' = (' . "$sca[0]" .' & '.
208                                                          "$sca[1]" .') | ('.  "$sca[2]" .' & (' .
209                                                           "$sca[0]" .' ^ '. "$sca[1]" .'));';
210                        $sum_array_index++;
211                        $carry_array_index++;
212                        $sca_count=0;
213                    } #conditional_a  
214                } #conditional_b
215            } #loop_c
216            $tag=1;
217        } #loop_d
218        $counts{$j}=$counts{$j}-(3*($i));
219        loop_h:
220        #loop_h for half adder
221        for ($i=0;$i<int($counts{$j}/2);$i++)
222        {
223             $counts{$j}=$counts{$j}-2;
224             $cutoff_count=0;
225             $string=$array[$array_index];
226             $array_index++;
227             $c_string=$array[$array_index];
228             $array_index++;
229             loop_i:
230             while (  ($key, $value) = each(%pp_copy) )
231             {
232                 if (($value==$j) && ($cutoff_count < 2))
233                 {
234                    $cutoff_count++;
235                    $pp{$string} = $pp{$key};
236                    $pp{$c_string} = $pp{$key};
237                    $sca[$sca_count] = $key;
238                    $sca_count++;
239                    delete($pp{$key});
240                    delete($pp_copy{$key});
241                    if ($cutoff_count ==2 ) # half adder  
242                    {
243                        $pp{$c_string} = $pp{$c_string}+1;
244                        $sum_array[$sum_array_index]= "   assign $string" . ' = ' . "$sca[0]" .
245                                                       ' ^ ' . "$sca[1]" .  ';';
246                        $carry_array[$carry_array_index]= "   assign $c_string" . ' = ' . "$sca[0]" .
247                                                          ' & '. "$sca[1]" .';';
248                        $sum_array_index++;
249                        $carry_array_index++;
250                        $sca_count=0;
251                    }
252                }
253            } #loop_i
254            $tag=1;
255         } #loop_h
256         $j=$j-1;
257         conditional_c:
258         if (($tag==1) && ($j==-1))
259         {
260             @other_array=values %pp;
261             $_ = 0 for %counts;
262             $counts{$_} ++ for @other_array;
263             $j=scalar(keys %counts)-1;
264             %pp_copy=%pp;
265             $flag=0;
266             for my $i ( 0 .. (keys %counts) )
267             {
268                 if (defined $counts{$i})
269                 {   if ($counts{$i}>2)
270                     {   $flag=1; }
271                 }
272             }
273         } #conditional_c
274    } #loop_e
275    if ($us eq "u")
276        {open $fh, ">>", "wallace.vl";}
277    else
278        {open $fh, ">>", "signed_wallace.vl";}
279    for ($k = 0; $k < $sum_array_index; $k++)
280    {   print $fh "$sum_array[$k]\n";
281        print $fh "$carry_array[$k]\n";
282    }
283    close $fh;
284    return;
285 }
286 
287 
288 sub kogge_stone 
289 {
290    my @other_array;
291    my @sorted_counts=();
292    @other_array=values %pp;
293    $counts{$_}=0 for @other_array;
294    $counts{$_}++ for @other_array;
295    $sorted_counts[$_]=$counts{$_} for sort {$a <=> $b} keys %counts;
296    my @sorted_pp_keys = sort {$pp{$a} <=> $pp{$b}} keys %pp;
297    my $first_index= firstidx { $_ eq '2' } @sorted_counts;
298    my $adder_length=$pl+1-$first_index;
299    my @p0= ("p000" .. "p200");
300    my @p1= ("pa000" .. "pa200");
301    my @p2= ("pb000" .. "pb200");
302    my @p3= ("pc000" .. "pc200");
303    my @p4= ("pd000" .. "pd200");
304    my @p5= ("pe000" .. "pe200");
305    my @p6= ("pf000" .. "pf200");
306    my @p7= ("pg000" .. "pg200");
307    my @g0= ("g000" .. "g200");
308    my @g1= ("ga000" .. "ga200");
309    my @g2= ("gb000" .. "gb200");
310    my @g3= ("gc000" .. "gc200");
311    my @g4= ("gd000" .. "gd200");
312    my @g5= ("ge000" .. "ge200");
313    my @g6= ("gf000" .. "gf200");
314    my @g7= ("gg000" .. "gg200");
315    my $final_flag=0; my $i=0; my $k=0; my $gg=0; my $fh;
316    if ($us eq "u")
317        {open $fh, ">>", "wallace.vl";}
318    else {open $fh, ">>", "signed_wallace.vl";}
319    loop_k:
320    for my $k ( 0 .. $#sorted_counts )
321    {
322       if (($sorted_counts[$k]==1) && ($final_flag==0))
323       {
324           print $fh "   assign product[$k] = $sorted_pp_keys[$i];\n";
325           $i++;
326       }
327       conditional_d:
328       if (($sorted_counts[$k]==2) && ($final_flag==0))
329       {
330           print $fh "   assign $p0[$gg] = $sorted_pp_keys[$i] ^ $sorted_pp_keys[$i+1];\n";
331           print $fh "   assign product[$k] = $p0[$gg];\n";
332           print $fh "   assign $g0[$gg] = $sorted_pp_keys[$i] & $sorted_pp_keys[$i+1];\n";
333           if ($adder_length > 1)
334           {
335               print $fh "   buf($p1[$gg],$p0[$gg]);\n";
336               print $fh "   buf($g1[$gg],$g0[$gg]);\n";
337           }
338           if ($adder_length > 2)
339           {
340               print $fh "   buf($p2[$gg],$p1[$gg]);\n";
341               print $fh "   buf($g2[$gg],$g1[$gg]);\n";
342           }
343           if ($adder_length > 4)
344           {
345               print $fh "   buf($p3[$gg],$p2[$gg]);\n";
346               print $fh "   buf($g3[$gg],$g2[$gg]);\n";
347           }
348           if ($adder_length > 8)
349           {
350               print $fh "   buf($p4[$gg],$p3[$gg]);\n";
351               print $fh "   buf($g4[$gg],$g3[$gg]);\n";
352           }
353           if ($adder_length > 16)
354           {
355               print $fh "   buf($p5[$gg],$p4[$gg]);\n";
356               print $fh "   buf($g5[$gg],$g4[$gg]);\n";
357           }
358           if ($adder_length > 32)
359           {
360               print $fh "   buf($p6[$gg],$p5[$gg]);\n";
361               print $fh "   buf($g6[$gg],$g5[$gg]);\n";
362           }
363           if ($adder_length > 64)
364           {
365               print $fh "   buf($p7[$gg],$p6[$gg]);\n";
366               print $fh "   buf($g7[$gg],$g6[$gg]);\n";
367           }
368           $final_flag=1;
369           $gg=$gg+1;
370           $i=$i+2;
371           next;
372       } #conditional_d
373       conditional_e:
374       if ($final_flag==1)
375       {
376           conditional_f:
377           if ($k < $pl)
378           {
379              print $fh "   assign $p0[$gg] = $sorted_pp_keys[$i] ^ $sorted_pp_keys[$i+1];\n";
380              print $fh "   assign $g0[$gg] = $sorted_pp_keys[$i] & $sorted_pp_keys[$i+1];\n";
381              if ($adder_length==2)
382              { print $fh "   assign product[$k] = $p0[$gg];\n"; }
383              if ($adder_length==3)
384              { print $fh "   assign product[$k] = $p0[$gg] ^ $g1[$gg-1];\n"; }
385              if ((6> $adder_length) && ($adder_length > 3))
386              { print $fh "   assign product[$k] = $p0[$gg] ^ $g2[$gg-1];\n"; }
387              if ((9> $adder_length) && ($adder_length > 5))
388              { print $fh "   assign product[$k] = $p0[$gg] ^ $g3[$gg-1];\n"; }
389              if ((18> $adder_length) && ($adder_length > 8))
390              { print $fh "   assign product[$k] = $p0[$gg] ^ $g4[$gg-1];\n"; }
391              if ((34> $adder_length) && ($adder_length > 17))
392              { print $fh "   assign product[$k] = $p0[$gg] ^ $g5[$gg-1];\n"; }
393              if ((66> $adder_length) && ($adder_length > 33))
394              { print $fh "   assign product[$k] = $p0[$gg] ^ $g6[$gg-1];\n"; }
395              if ((130> $adder_length) && ($adder_length > 65))
396              { print $fh "   assign product[$k] = $p0[$gg] ^ $g7[$gg-1];\n"; }
397              if ($adder_length > 1)
398              { if ($gg>0)
399                  { print $fh "   assign $p1[$gg] = $p0[$gg] & $p0[$gg-1];\n";
400                    print $fh "   assign $g1[$gg] = $g0[$gg] | ($p0[$gg] & $g0[$gg-1]);\n"; }
401                  else
402                  { print $fh "   buf($p1[$gg],$p0[$gg]);\n";
403                    print $fh "   buf($g1[$gg],$g0[$gg]);\n"; }
404              }
405              if ($adder_length > 2)
406              { if ($gg>1)
407                 { print $fh "   assign $p2[$gg] = $p1[$gg] & $p1[$gg-2];\n";
408                   print $fh "   assign $g2[$gg] = $g1[$gg] | ($p1[$gg] & $g1[$gg-2]);\n"; }
409                 else
410                 { print $fh "   buf($p2[$gg],$p1[$gg]);\n";
411                   print $fh "   buf($g2[$gg],$g1[$gg]);\n"; }
412              }
413              if ($adder_length > 4)
414              { if ($gg>3)
415                 { print $fh "   assign $p3[$gg] = $p2[$gg] & $p2[$gg-4];\n";
416                   print $fh "   assign $g3[$gg] = $g2[$gg] | ($p2[$gg] & $g2[$gg-4]);\n"; }
417                 else
418                 { print $fh "   buf($p3[$gg],$p2[$gg]);\n";
419                   print $fh "   buf($g3[$gg],$g2[$gg]);\n"; }
420              }
421              if ($adder_length > 8)
422              { if ($gg>7)
423                 { print $fh "   assign $p4[$gg] = $p3[$gg] & $p3[$gg-8];\n";
424                   print $fh "   assign $g4[$gg] = $g3[$gg] | ($p3[$gg] & $g3[$gg-8]);\n"; }
425                 else
426                 { print $fh "   buf($p4[$gg],$p3[$gg]);\n";
427                   print $fh "   buf($g4[$gg],$g3[$gg]);\n"; }
428              }
429              if ($adder_length > 16)
430              { if ($gg>15)
431                 { print $fh "   assign $p5[$gg] = $p4[$gg] & $p4[$gg-16];\n";
432                   print $fh "   assign $g5[$gg] = $g4[$gg] | ($p4[$gg] & $g4[$gg-16]);\n"; }
433                 else
434                 { print $fh "   buf($p5[$gg],$p4[$gg]);\n";
435                   print $fh "   buf($g5[$gg],$g4[$gg]);\n"; }
436              }
437              if ($adder_length > 32)
438              { if ($gg>31)
439                 { print $fh "   assign $p6[$gg] = $p5[$gg] & $p5[$gg-32];\n";
440                   print $fh "   assign $g6[$gg] = $g5[$gg] | ($p5[$gg] & $g5[$gg-32]);\n"; }
441                 else
442                 { print $fh "   buf($p6[$gg],$p5[$gg]);\n";
443                   print $fh "   buf($g6[$gg],$g5[$gg]);\n"; }
444              }
445              if ($adder_length > 64)
446              { if ($gg>63)
447                 { print $fh "   assign $p7[$gg] = $p6[$gg] & $p6[$gg-64];\n";
448                   print $fh "   assign $g7[$gg] = $g6[$gg] | ($p6[$gg] & $g6[$gg-64]);\n"; }
449                 else
450                 { print $fh "   buf($p7[$gg],$p6[$gg]);\n";
451                   print $fh "   buf($g7[$gg],$g6[$gg]);\n"; }
452              }
453           }
454           else
455           {
456               if ($k==$pl)
457               {
458                   if ($sorted_counts[$k]==2)
459                       {print $fh "   assign $p0[$gg] = $sorted_pp_keys[$i] ^ $sorted_pp_keys[$i+1];\n";}
460                   else
461                       {print $fh "   assign $p0[$gg] = $sorted_pp_keys[$i];\n";}
462                   if ($adder_length==2)
463                   {
464                      print $fh "   assign product[$k] = $p0[$gg] ^ $g0[$gg-1];\n";
465                   }
466                   if ($adder_length==3)
467                   {
468                      print $fh "   assign product[$k] = $p0[$gg] ^ $g1[$gg-1];\n";
469                   }
470                   if (($adder_length==4) || ($adder_length == 5))
471                   {
472                      print $fh "   assign product[$k] = $p0[$gg] ^ $g2[$gg-1];\n";
473                   }
474                   if ((10> $adder_length) && ($adder_length > 5))
475                   {
476                      print $fh "   assign product[$k] = $p0[$gg] ^ $g3[$gg-1];\n";
477                   }
478                   if ((18> $adder_length) && ($adder_length > 9))
479                   {
480                      print $fh "   assign product[$k] = $p0[$gg] ^ $g4[$gg-1];\n";
481                   }
482                   if ((34> $adder_length) && ($adder_length > 17))
483                   {
484                      print $fh "   assign product[$k] = $p0[$gg] ^ $g5[$gg-1];\n";
485                   }
486                   if ((66> $adder_length) && ($adder_length > 33))
487                   {
488                      print $fh "   assign product[$k] = $p0[$gg] ^ $g6[$gg-1];\n";
489                   }
490                   if ((130> $adder_length) && ($adder_length > 65))
491                   {
492                      print $fh "   assign product[$k] = $p0[$gg] ^ $g7[$gg-1];\n";
493                   }
494               }
495           } #conditional_f
496           $i=$i+2;
497           $gg=$gg+1;
498       } #conditional_e
499    } #loop_k
500    if ($pl>$#sorted_counts)
501                {
502                   if ($adder_length==2)
503                   {
504                      print $fh "   assign product[$pl] = $g0[$gg-1];\n";
505                   }
506                   if ($adder_length==3)
507                   {
508                      print $fh "   assign product[$pl] =  $g1[$gg-1];\n";
509                   }
510                   if (($adder_length==4) || ($adder_length == 5))
511                   {
512                      print $fh "   assign product[$pl] = $g2[$gg-1];\n";
513                   }
514                   if (($adder_length>=6) && ($adder_length<=9))
515                   {
516                      print $fh "   assign product[$pl] = $g3[$gg-1];\n";
517                   }
518                   if (($adder_length>=10) && ($adder_length<=17))
519                   {
520                      print $fh "   assign product[$pl] = $g4[$gg-1];\n";
521                   }
522                   if (($adder_length>=18) && ($adder_length<=33))
523                   {
524                      print $fh "   assign product[$pl] = $g5[$gg-1];\n";
525                   }
526                   if (($adder_length>=34) && ($adder_length<=65))
527                   {
528                      print $fh "   assign product[$pl] = $g6[$gg-1];\n";
529                   }
530               }
531    print $fh "endmodule";
532    close $fh;
533    return;
534 }
535 
536 
537 sub testbench 
538 #generate testbench
539 {
540     my $mdl=$multiplicand_length;
541     my $mrl=$multiplier_length;
542     my $ul =$mdl - 1;
543     my $zl =$mrl - 1;
544     my $pl =$ul+$zl+1;
545     my $plplus1 =$pl+1;
546     my $fh;
547     if ($us eq "u")
548         {open  $fh, ">", "tb_wallace.vl";
549          print $fh "`timescale 1ns/1ns\n";
550          print $fh "module tb_wallace;\n";
551          print $fh "    // Unsigned multiplier testbench\n";
552          print $fh "    // John Bryan, 2017\n";
553          print $fh "    reg  [$ul:0] a;\n";
554          print $fh "    reg  [$zl:0] b;\n";
555          print $fh "    wire [$pl:0] product;\n";
556          print $fh "    reg  [$pl:0] check;\n";}
557     else
558         {open $fh, ">", "tb_swallace.vl";
559          print $fh "`timescale 1ns/1ns\n";
560          print $fh "module tb_swallace;\n";
561          print $fh "    // Signed multiplier testbench\n";
562          print $fh "    // John Bryan, 2017\n";
563          print $fh "    reg  signed  [$ul:0] a;\n";
564          print $fh "    reg  signed  [$zl:0] b;\n";
565          print $fh "    wire signed  [$pl:0] product;\n";
566          print $fh "    reg  signed  [$pl:0] check;\n";}
567         my $mdlul = 2**$mdl;
568          my $mrlul = 2**$mrl;
569          my $total_tested = $mdlul*$mrlul;
570          my $mdlp1 = $mdl+1;
571          my $mrlp1 = $mrl+1;
572     if ($dr eq "d")
573          {print $fh "    reg  [$mdl:0]  i,mdlul;\n";
574          print $fh "    reg  [$mrl:0]  j,mrlul;\n\n";}
575     else
576         {print $fh "    integer i;\n\n";}
577     if ($us eq "u")
578         {print $fh "    wallace wall0(a,b,product);\n\n";}
579     else
580         {print $fh "    s_wallace s_wall0(a,b,product);\n\n";}
581     print $fh "    initial\n";
582     print $fh "    begin\n";
583     if ($dr eq "d")
584     {
585         if ($us eq "u")
586             {print $fh "        a=$mdl\'d0;\n";
587              print $fh "        b=$mrl\'d0;\n";
588              print $fh "        mrlul=$mrlp1\'d$mrlul;\n";
589              print $fh "        mdlul=$mdlp1\'d$mdlul;\n";
590              print $fh "        for (i=0;i<mdlul;i=i+1)\n";
591              print $fh "        begin\n";
592              print $fh "            for (j=0;j<mrlul;j=j+1)\n";
593              print $fh "            begin\n";
594              print $fh "                check=a*b;\n";}
595         else #us eq "s" 
596         {
597              my $smdll = 2**$ul;
598              my $smrll = 2**$zl;
599              print $fh "        a=-$mdl\'d$smdll;\n";
600              print $fh "        b=-$mrl\'d$smrll;\n";
601              print $fh "        mrlul=$mrlp1\'d$mrlul;\n";
602              print $fh "        mdlul=$mdlp1\'d$mdlul;\n";
603              print $fh "        for (i=0;i<mdlul;i=i+1)\n";
604              print $fh "        begin\n";
605              print $fh "            for (j=0;j<mrlul;j=j+1)\n";
606              print $fh "            begin\n";
607              print $fh "                check=\$signed(a)*\$signed(b);\n";}
608         print $fh "                #1;\n";
609         print $fh "                if (product != check)\n";
610         print $fh "                begin\n";
611         print $fh "                    \$display(\"time=%0t\", \$time);\n";
612         print $fh "                    \$display(\"a =%0d, b=%0d\", a, b);\n";
613         print $fh "                    \$display(\"product=%0d, check=%0d\", product, check);\n";
614         print $fh "                    \$finish;\n";
615         print $fh "                end\n";
616         print $fh "                b=b+1'b1;\n";
617         print $fh "           end\n";
618         print $fh "           a=a+1'b1;\n";
619         print $fh "        end\n";
620         print $fh "        \$display(\"   All %0d were correct.\\n\", $total_tested);\n";
621         print $fh "        \$finish;\n";
622         print $fh "    end\n\n";}
623     else #dr eq "r"
624        {print $fh "        for (i=0;i<10000;i=i+1)\n";
625         print $fh "        begin\n";
626         if (($us eq "u") && ($ul <= 31))
627            {print $fh "            a=\$urandom;\n";}
628         if (($us eq "u") && ($ul > 31))
629            {print $fh "            a[31:0]=\$urandom;\n";
630             print $fh "            a[$ul:32]=\$urandom;\n";}
631         if (($us eq "u") && ($zl <= 31))
632            {print $fh "            b=\$urandom;\n";}
633         if (($us eq "u") && ($zl > 31))
634            {print $fh "            b[31:0]=\$urandom;\n";
635             print $fh "            b[$zl:32]=\$urandom;\n";}
636         if ($us eq "u")
637             {print $fh "            check=a*b;\n";}
638         if (($us eq "s") && ($ul <= 31))
639            {print $fh "            a=\$random;\n";}
640         if (($us eq "s") && ($ul > 31))
641            {print $fh "            a[31:0]=\$random;\n";
642             print $fh "            a[$ul:32]=\$random;\n";}
643         if (($us eq "s") && ($zl <= 31))
644            {print $fh  "            b=\$random;\n";}
645         if (($us eq "s") && ($zl > 31))
646            {print $fh "            b[31:0]=\$random;\n";
647             print $fh "            b[$ul:32]=\$random;\n";}
648         if ($us eq "s")
649             {print $fh "            check=\$signed(a)*\$signed(b);\n";}
650         print $fh "            #1;\n";
651         print $fh "            if (product != check)\n";
652         print $fh "            begin\n";
653         print $fh "                \$display(\"time=%0t\", \$time);\n";
654         print $fh "                \$display(\"a =%0d, b=%0d\", a, b);\n";
655         print $fh "                \$display(\"product=%0d, check=%0d\", product, check);\n";
656         print $fh "                \$finish;\n";
657         print $fh "            end\n";
658         print $fh "        end\n";
659         print $fh "        \$display(\"   All 10000 were correct.\\n\");\n";
660         print $fh "        \$finish;\n";
661         print $fh "    end\n\n";}
662     print $fh " endmodule\n";
663     close $fh;
664     return;
665 }
666 
667 
668 sub generate_and_test
669 {
670     my $i=$multiplicand_length;
671     my $j=$multiplier_length;
672     my $hl=$i+$j+$increment;
673     my $k;
674     my $ll=$i+$j;
675     my $left;
676     my $count=$ll;
677     us_conditional:
678     if ($us eq "u")
679     {
680         u_for:
681         for (;($i+$j)<=$hl;$i++)
682         {
683             $pl=$i+$j;
684             print "\n\n   Testing product length of $pl . . .\n\n";
685             $multiplicand_length=$i;
686             $multiplier_length=$j;
687             &generate_and_testbench;
688             system ("iverilog wallace.vl tb_wallace.vl");
689             system ("vvp a.out");
690             @pp=();
691             %pp=();
692             %counts=();
693             $count++;
694             $left=$hl-$count+1;
695             $j=$j+1;
696             if (($i+$j)<$hl)
697             {
698                 print "\n   $left tests to go . . .\n";
699                 $pl=$i+$j;
700                 print "\n\n   Testing product length of $pl . . .\n\n";
701                 $multiplicand_length=$i;
702                 $multiplier_length=$j;
703                 &generate_and_testbench;
704                 system ("iverilog wallace.vl tb_wallace.vl");
705                 system ("vvp a.out");
706                 @pp=();
707                 %pp=();
708                 %counts=();
709                 $count++;
710                 $left=$hl-$count;
711             }
712         } #u_for
713     } #us_conditional
714     else #$us eq "s"
715     {
716         s_loop:
717         for (;($i+$j)<=$hl;$i++)
718         {
719             $pl=$i+$j;
720             print "\n\n   Testing product length of $pl . . .\n\n";
721             $multiplicand_length=$i;
722             $multiplier_length=$j;
723             &generate_and_testbench;
724             system ("iverilog signed_wallace.vl tb_swallace.vl");
725             system ("vvp a.out");
726             @pp=();
727             %pp=();
728             %counts=();
729             $count++;
730             $left=$hl-$count+1;
731             if (($i+$j)<$hl)
732             {
733                 print "\n   $left tests to go . . .\n";
734                 $j=$j+1;
735                 $pl=$i+$j;
736                 print "\n\n   Testing product length of $pl . . .\n\n";
737                 $multiplicand_length=$i;
738                 $multiplier_length=$j;
739                 &generate_and_testbench;
740                 system ("iverilog signed_wallace.vl tb_swallace.vl");
741                 system ("vvp a.out");
742                 @pp=();
743                 %pp=();
744                 %counts=();
745                 $count++;
746                 $left=$hl-$count;
747             }
748         }#s_loop
749     } #us_conditional
750     return;
751 } #sub generate_and_test