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