Saturday, June 22, 2013

Scan Insertion

Hello,

Scan insertion is the process of converting the flip flops present in a circuit into scan flip flops
The flip-flops in the circuit, shown in Figure, are connected together in a chain to form a shift register, also called scan chain. This makes all flip-flops in the circuit controllable and observable leaving behind only the combinational logic to be tested. 

During scan mode, the test vectors are shifted into (scan-in) the scan chain by shift operations. The test vectors are then applied to the combinational logic and the response is clocked back into the flip-flops. The response is then shifted out (scan-out) from the scan chain to test as the next test vector is being scanned in. This DFT converts the difficult to test sequential circuit into a fully combinational circuit.

For large designs, the long chain is split into several smaller chains in order to cope with the large number of test patterns. The chains can have different lengths and the depth is defined by the length of the longest chain. This splitting of the scan chain increases the test speed because several chains can now be operated in parallel but has the added cost of additional pins and channels. 

You can use commercial tools like Synopsys Tetramax to do scan insertion for you. Otherwise you can write your own script that does scan insertion. Here is a script that converts DFF to Scan DFF in a verilog file. The name of the scan flip-flop and necessary connections can be identified using the library. Flip flops are identified, their names changed, connections re-connected and additional pins are added at the primary input.

PERL SCRIPT THAT DOES SCAN INSERTION
  
 #!/usr/bin/perl  
 #scan_insertion.plx  
 use warnings;  
 use Data::Dumper;  
 use List::Util qw(min);  
 my $bench_file = $ARGV[0];  
 my $file_name;  
 #Test netlist file  
 if($bench_file =~ /(.*).v/){  
 $file_name = $1;  
 }   
 else{  
 print "Format of bench file name: circuit_name.v \n example : s1423.v\n";  
 }  
 $file_name_scan_ins = $file_name.'_scan_inserted.v';  
 open($FILEREAD, $bench_file) or die "could not open file to read";  
 open($FILEWRITE, '>', $file_name_scan_ins) or die "Could not open\n";  
 #Read Netlist File - count #FF  
 while(<$FILEREAD>){  
   my $INPUT_DATA = $_;  
   chomp($INPUT_DATA);  
   if($INPUT_DATA =~ m/^\s*(DFFX1)\s*(.*)\s*\(\.CK\((.*)\),\s*\.D\((.*)\),\s*\.Q\((.*)\)\);$/){  
      $count++;  
   }  
 }  
 close(FILEREAD);  
 #Modify netlist  
 $max_count = $count;  
 my $modified_data;  
 my $prev_op;  
 open($FILEREAD, $bench_file) or die "could not open file to read";  
 while(<$FILEREAD>){  
   $INPUT_DATA = $_;  
   chomp($INPUT_DATA);  
   if($INPUT_DATA =~ /module\s*(.*)\s*\((.*)\);/){  
      $circuit_name = $1;  
      print $FILEWRITE "module "."$1 "."($2,scan_data_in,scan_data_out,scan_enable);\n";  
   }  
   elsif($INPUT_DATA =~ /^\s*input\s*(.*);/){  
      print $FILEWRITE "input ".$1.",scan_data_in,scan_enable;"."\n";  
   }  
   elsif($INPUT_DATA =~ /^\s*output\s*(.*);/){  
      print $FILEWRITE "output ".$1.",scan_data_out;"."\n";  
   }  
   elsif($INPUT_DATA =~ m/^\s*(DFFX1)\s*(.*)\s*\(\.CK\((.*)\),\s*\.D\((.*)\),\s*\.Q\((.*)\)\);$/){  
      if($count == $max_count){  
        print $FILEWRITE "S_DFFX1"." ".$2."(.CK($3),.D($4),.SE(scan_enable),.SI(scan_data_in),.Q($5));\n";  
        $prev_op = $5;  
      }  
      else{  
        print $FILEWRITE "S_DFFX1"." ".$2."(.CK($3),.D($4),.SE(scan_enable),.SI($prev_op),.Q($5));\n";  
        $prev_op=$5;  
        if($count == 1){  
           print $FILEWRITE "BUFX1 scan_buff_op (.A($5),.Y(scan_data_out));\n"  
        }  
      }  
      $count--;  
   }  
   else{  
      print $FILEWRITE $INPUT_DATA."\n";  
   }  
 }  
 close(FILEREAD);  
 close(FILEWRITE);  
 



No comments:

Post a Comment