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