Using Perl to map FPGA pins from a board design to UCF pin constraints

This post was written by eli on March 27, 2009
Posted Under: FPGA,perl

One of the things I try to avoid as an FPGA engineer, is to manually configure the pin constraints (in the UCF file) in order to tell the tools which FPGA pin is connected to what. Not only is this extremely boring, but I also think that getting it done right (at the first go) is more or less a miracle.

If you insist on working with the Orcad schematics, you’re doomed. Yes, this graphical representation of the board is useful for getting an idea of what’s going on. But when I want to know for sure what is connected to what on the PCB, I read the netlist file. It’s that text file, which the board designer sends to the PCB manufacturing plant. So even if schematics is convincing, what counts is what the netlist file says. Sometimes reading the netlist reveals connections which were not obvious at all from looking at the schematics. But I’m diverting from the point, which is how to generate the UCF file sort-of automatically. Or at least spare most of the work.

So let’s have a look on what a netlist file looks like. This is a snippet from the middle, where the precious information is:

SIN_D8  = U43/V5 U48/42 ;
CLK_SEL  = R393/1 U52/36 ;
N14463023  = U29/7 R154/1 R326/2 ;
N16132557  = U64/1 C589/1 L90/1 L91/1
            C594/1 U64/2 ;
SOUT_A_A9  = U38/34 U43/AB21 ;
SENSOR_B_D3  = U43/N8 U49/11 ;
SIN_D9  = U43/U4 U48/44 ;

So the structure is very simple. A statement begins with the net’s name, an equation sign and then a listing of the connected pins. As you can see, each statement is terminated by a semicolon, and may consist of several lines.

The nets’ names are given by the board designer manually. There is no assurance that this name has anything to do with what the net is connected to, so if you’re really pedantic, you should verify that as well. Checking the schematics is fairly efficient, or you could verify the pin connections in the netlist, which may be fairly easy with some scripting skills.

Also, if no name was given to the net, but it’s a result of just connecting two pins, Orcad will make up a name, which usually looks something like N16132557. A common, and annoying case is when there is a resistor between two chips’ pins (say, for debouncing). Because of the resistor in the middle, two nets make the connection. If the board designer gives the name to the net between the FPGA and the resistor, we get the name for free. If not, we need to be smarter.

And that brings us to the pin listing  in the netlist. If we take the SOUT_A_A9 net for example, we can see that it’s connecting between pin 34 of device marked U38, and pin AB21 of U43. On this specific board, U43 happens to be the FPGA.

This leaves us with two possible strategies. One is to trust the net’s name, and make an entry in the UCF file, which binds pin AB21 to a Verilog/VHDL toplevel I/O port with a similar name, say “sout_a_a[9]“.  I’ll show an example script for this below.

The second strategy would try to find out what pin 34 of U38 stands for, and give the port’s name accordingly. This is trickier, of course, but given a reliable pin mapping of the other chip, this neutralizes any mistake possibly made by the board designer. This is where I’d like to mention, that certain board design tools create a “chip file”, which is a text file as well. This text file contains meaningful names for each chip included in the design (these are, in fact, the names that appear on the schematics). This file’s name is typically pstchip.dat. Unfortunately, the information in this file is commonly fed manually from a datasheet at some stage of the board design, so if an error was made during this stage, both the board and the FPGA pinout will get it wrong.

But let’s leave the pessimism for a while, and assume that we can rely on the nets’ names. Here’s a script, which finds the FPGA’s connections, an attempts to create a UCF file. Please keep in mind that it’s just an example, and that it doesn’t cover all nets even in the design I wrote it for. If you want to use this technique in your own designs, you’ll have to adapt it to the quirks of the netlist you’re facing.

Anyhow, here it is:

#!/usr/bin/perl
use warnings;
use strict;

undef $/; # Slurp mode. (Sane people use "local" instead)
my $file = <>;

my @chunks = ($file =~ /^([^ %].+?);/gsm);
my @out;

foreach my $chunk (@chunks) {
  my ($var, $rest) = ($chunk =~  /^([^ ]+)[ ]*=[ ]*(.*)/s);
  die("Failed to read line: $chunk\n")
    unless (defined $var);
  next if (grep { $_ eq lc $var }
	   qw[vcc_int vcc_aux v3_3 gnd]);
  my @pins = ($rest =~ /U43\/([^ \n\r\t]+)/gi);
  push @out, "NET \"".(lc $var)."\" LOC = \"$_\";\n" foreach (@pins);
}
print sort @out;

Just a few clarifications: U43 is the FPGA in my netlist, right? So that’s why I filter out anything else. And now a few Perl clarifications.

  • I begin with undeffing $/. This makes the single ‘$file=<>’ statement read the entire file at once (that’s why they call it slurp mode). The Perl manpage encourages to use “local” instead of “undef”, and it explains why, but it’s not relevant for a short script.
  • The first regular expression (feeding @chunks) cuts the file into pieces between semicolons.
  • The second regular expression splits each chunk into the string before ‘=’ (in $var) and everything that comes afterwards (in $rest, possibly longer than a single line).
  • The grep sentence checks if we’re not on a power net, which should be skipped.
  • The last regular expression looks for a ‘U43/’-something, and if that is found, the pins are stored in the @pins list (in a sane case, this will be only one pin, or we’re messed up)

As I said before, I don’t really expect this script to work out of the box for you, but I hope I made the point about using a Perl script on a netlist to make life easier. And in case you’re an FPGA Engineer, and don’t know Perl, I hope this gave an idea of why you should start learning…

Reader Comments

Hi,

I am working on a similar problem and would appreciate if you could please help me out.

I have 4 netlists(die, interposer, substrate and test baord) and I want to use perl to check the daisy chain connectivity. That is if I provide a test-in file that has starting pins for all daisy chain(from the test board), my output file should have all the connected points across all 4 tiers with the last point being a pin on the test board.
Could you please suggest an algorithm/approach to tackle this challenging problem?I would be really grateful.

Thank You
Anurag

#1 
Written By Anurag Gupta on July 30th, 2013 @ 18:26

Hi,

I’m afraid I can’t offer a piece of generic advice here. Having written a script or two of that sort, it boils down to munching the data in a way that is specific to your project.

It’s just a lot of dirty hacking, unfortunately.

#2 
Written By eli on July 30th, 2013 @ 18:56

Add a Comment

required, use real name
required, will not be published
optional, your blog address