XNF To VHDL Script  Go To Script Pool
# This perl script takes an XNF netlist and returns a VHDL architecture
# containing a series of continuous assignments and clocked-register
# instantiations that implement the same function specified in the
# XNF netlist. This tool is useful when you're not sure whether
# Xilinx spit out the correct synthesis result, and you want to
# simulate the resulting code against your VHDL behavioral code.

# ################################################
# Open the XVF file. Hey Rex! Make this a bit more
# pleasant, OK?
$xnffilename = $ARGV[0];
$hackfilename = $ARGV[1];

# ################################################
# Read in all signals and figure out which are internal and which
# are external. Build signal definitions for all internal signals.
&BuildSignalList($xnffilename);
# Print the architecture header
$archfilename = $xnffilename;
$archfilename =~ s/\.xnf/_netlist.vhd/;
open(ARCHFILE,"> ".$archfilename);
&PrintHeader($archfilename);
&PrintSignals();
&HackSignals($hackfilename);
&PrintNetlist($xnffilename);
&PrintAliases($xnffilename);
&HackNetlist($hackfilename);
&PrintTrailer($archfilename);

# #################################################
# Clean up after yourself...

# #################################################
# Some useful subroutines

sub BuildSignalList {
local($xnffilename) = @_;

open(XNFFILE,$xnffilename);
while($theline = <XNFFILE>) {
# If the line has a PIN declaration, go to work
if(($theline =~ /^PIN/) && !($theline =~ /\$\$/)) {
# For each PIN declaration, split to find the name
($type, $formal, $direction, $name) = split(/,/,$theline);
# Remove spaces and newlines and $ signs
$name =~ s/[ \n]+//g;
# If the name has a < in it, it's a bus of some sort
if($name =~ /\</) {
# Split the name out from the bit indicator
($name,$size) = split(/</,$name);
# Hack the > off the end of the bit indicator
$size =~ s/>//;
# Add 1 to it, because we want the number of pins
$size = $size + 1;
# Check to see if the name is in the assiociative array
if($namearray{$name} eq "") {
# If not, put it there with the current size estimate
$namearray{$name} = $size;
}
else {
# If it's already in, check to see if the new pin
# uses a larger bit indicator than the currently
# stored one.
if($namearray{$name} < $size) {
# If this is a higher pin number, put that in
# the associative array as the new size estimate
$namearray{$name} = $size;
}
}
}
else {
# For single-bit buses, set the associative array entry
# to 1.
if($namearray{$name} eq "") {
$namearray{$name} = 1;
}
}
}
# If the line contains a SYM declaration with a BOUNDS
# directive, use the bounds to set the highest bit number for the
# bus.
if($theline =~ /^SYM/) {
if($theline =~ /BUS_DEF/) {
# Find the name and the bounds directive in the line
($type, $name, $blocktype, $def, $bounds) = split(/,/,$theline);
# Clean up the name
$name =~ s/[ \n]+//g;
# Clean up the bounds directive and find the upper and lower
$bounds =~ s/[\=a-zA-Z]+//g;
($left, $right) = split(/:/,$bounds);
if($left > $right) {
$aliasarray{$name} = $left + 1;
}
else {
$aliasarray{$name} = $right + 1;
}
}
}
# If the line contains an EXT declaration, store it in
# the EXT array, with size.
if($theline =~ /^EXT/) {
# For each EXT declaration, split to find the name
($type, $name, $direction) = split(/,/,$theline);
# Remove spaces and newlines
$name =~ s/[ \n]+//g;
# If the name has a < in it, it's a bus of some sort
if($name =~ /\</) {
# Split the name out from the bit indicator
($name,$size) = split(/</,$name);
# Hack the > off the end of the bit indicator
$size =~ s/>//;
# Add 1 to it, because we want the number of pins
$size = $size + 1;
# Check to see if the name is in the assiociative array
if($extarray{$name} eq "") {
# If not, put it there with the current size estimate
$extarray{$name} = $size;
}
else {
# If it's already in, check to see if the new pin
# uses a larger bit indicator than the currently
# stored one.
if($extarray{$name} < $size) {
# If this is a higher pin number, put that in
# the associative array as the new size estimate
$extarray{$name} = $size;
}
}
}
else {
# For single-bit buses, set the associative array entry
# to 1.
$extarray{$name} = 1;
}
}
}
# foreach $name (sort(keys(%namearray))) {
# if($extarray{$name} eq "") {
# printf("PIN: %s\t%d\n",$name,$namearray{$name});
# }
# }
# foreach $name (sort(keys(%extarray))) {
# printf("EXT: %s\t%d\n",$name,$extarray{$name});
# }
close(XNFFILE);
}

sub PrintHeader {
local($archfilename) = @_;

($entname, $archname) = split(/_/,$archfilename);
$archname =~ s/\.vhd//;
printf(ARCHFILE "library lib;\n");
printf(ARCHFILE "use ieee.std_logic_arith.all;\n");
printf(ARCHFILE "\n");
printf(ARCHFILE "architecture %s of %s is\n",$archname,$entname);
printf(ARCHFILE "\n");
}

sub PrintSignals {
foreach $signal (sort(keys(%namearray))) {
if(($extarray{$signal} eq "") && ($aliasarray{$signal} eq "")) {
if($namearray{$signal} == 1) {
printf(ARCHFILE "signal %s:std_logic;\n",$signal);
}
else {
printf(ARCHFILE "signal %s:std_logic_vector(%d downto %d);\n",
$signal, $namearray{$signal}-1, 0);
}
}
}
foreach $signal (sort(keys(%aliasarray))) {
if($aliasarray{$signal} ne "") {
printf(ARCHFILE "signal %s:std_logic_vector(%d downto %d);\n",
$signal, $aliasarray{$signal}-1, 0);
}
}
}

sub PrintAliases {
local($xnffilename) = @_;

# Start building the list signals for each alias we'll need.
foreach $signal (sort(keys(%aliasarray))) {
$aliaselement{$signal} = "";
}
open(XNFFILE,$xnffilename);
# For each SYM block found in the file, convert it into a corresponding
# function.
while($theline = <XNFFILE>) {
# Look for a symbol instantiation
if($theline =~ /^SYM/) {
($sym, $name, $type) = split(/,/,$theline);
$type =~ s/[ \n]+//g;
if($type eq "ELEMENT") {
&AddElement($theline);
}
}
}
# Start building the list signals for each alias we'll need.
foreach $signal (sort(keys(%aliasarray))) {
&PrintAlias($signal);
}
close(XNFFILE);
}

sub PrintNetlist {
local($xnffilename) = @_;

printf(ARCHFILE "\nbegin\n");
printf(ARCHFILE " VCC <= '1';\n");
printf(ARCHFILE " GND <= '0';\n");
open(XNFFILE,$xnffilename);
# For each SYM block found in the file, convert it into a corresponding
# function.
while($theline = <XNFFILE>) {
# Look for a symbol instantiation
if($theline =~ /^SYM/) {
($sym, $name, $type) = split(/,/,$theline);
$type =~ s/[ \n]+//g;
if($type eq "AND") {
&PrintGATE($theline,"and");
}
if($type eq "OR") {
&PrintGATE($theline,"or");
}
if($type eq "BUFGP") {
&PrintBUF($theline,"");
}
if($type eq "INV") {
&PrintBUF($theline,"not");
}
if($type eq "OBUF") {
&PrintBUF($theline,"");
}
if($type eq "IBUF") {
&PrintBUF($theline,"");
}
if($type eq "OBUFT") {
&PrintOBUFT($theline);
}
if($type eq "DFF") {
&PrintDFF($theline,0);
}
if($type eq "OUTFFT") {
&PrintDFF($theline,1);
}
if($type eq "ADD_SUB") {
&PrintADDSUB($theline);
}
if($type eq "COMPARE") {
&PrintCOMPARE($theline);
}
}
}
close(XNFFILE);
}

sub PrintGATE {
local($theline,$optype) = @_;
local(%inputarray,$output);

$done = 0;
%inputarray = ();
while(!$done) {
$theline = <XNFFILE>;
$theline =~ s/[ \n]+//g;
if($theline =~ /END/) {
$done = 1;
}
else {
$invert = "NORM";
($pin, $formal, $direction, $name,$blank,$invert) = split(/,/,$theli
ne);
$name = &FixName($name);
if($direction eq "I") {
if($invert eq "INV") {
$inputarray{$name} = -1;
}
else {
$inputarray{$name} = 1;
}
}
else {
$output = $name;
}
}
}
printf(ARCHFILE " %s <=",$output);
$firstprinted = 0;
foreach $input (sort(keys(%inputarray))) {
if($firstprinted) {
printf(ARCHFILE " and");
}
else {
$firstprinted = 1;
}
if($inputarray{$input} == -1) {
printf(ARCHFILE " not");
}
printf(ARCHFILE " %s",$input);
}
printf(ARCHFILE ";\n");
}

sub PrintBUF {
local($theline,$optype) = @_;
local($input,$output);

$done = 0;
while(!$done) {
$theline = <XNFFILE>;
$theline =~ s/[ \n]+//g;
if($theline =~ /END/) {
$done = 1;
}
else {
($pin, $formal, $direction, $name) = split(/,/,$theline);
$name = &FixName($name);
if($direction eq "I") {
$input = $name;
}
else {
$output = $name;
}
}
}
printf(ARCHFILE " %s <=",$output);
printf(ARCHFILE " %s",$optype);
printf(ARCHFILE " %s",$input);
printf(ARCHFILE ";\n");
}

sub PrintOBUFT {
local($theline) = @_;
local($input,$output,$tristate);

$done = 0;
while(!$done) {
$theline = <XNFFILE>;
$theline =~ s/[ \n]+//g;
if($theline =~ /END/) {
$done = 1;
}
else {
($pin, $formal, $direction, $name) = split(/,/,$theline);
$name = &FixName($name);
if($formal eq "I") {
$input = $name;
}
if($formal eq "O") {
$output = $name;
}
if($formal eq "T") {
$tristate = $name;
}
}
}
printf(ARCHFILE " %s <= %s when %s = '0' else 'Z'",$output,$input,$tristate
);
printf(ARCHFILE ";\n");
}

sub PrintDFF {
local($theline,$tristateable) = @_;
local($input,$output,$clock,$tristate);

$done = 0;
while(!$done) {
$theline = <XNFFILE>;
$theline =~ s/[ \n]+//g;
if($theline =~ /END/) {
$done = 1;
}
else {
($pin, $formal, $direction, $name) = split(/,/,$theline);
$name = &FixName($name);
if($formal eq "D") {
$input = $name;
}
if(($formal eq "Q") || ($formal eq "O")) {
$output = $name;
}
if($formal eq "C") {
$clock = $name;
}
if($formal eq "T") {
$tristate = $name;
}
}
}
printf(ARCHFILE "process begin\n");
printf(ARCHFILE " wait until %s'event and %s = '1';\n",$clock,$clock);
if($tristateable) {
printf(ARCHFILE " if(%s = '0') then %s <= %s; else %s <= 'Z'; end if;\n
",
$tristate, $output, $input,
$output);
}
else {
printf(ARCHFILE " %s <= %s;\n",$output,$input);
}
printf(ARCHFILE "end process;\n");
}

sub PrintADDSUB {
local($theline) = @_;
local($inputa,$inputb,$output);

$done = 0;
while(!$done) {
$theline = <XNFFILE>;
$theline =~ s/[ \n]+//g;
if($theline =~ /END/) {
$done = 1;
}
else {
($pin, $formal, $direction, $name) = split(/,/,$theline);
$name = &FixName($name);
if($formal eq "A") {
$inputa = $name;
}
if($formal eq "B") {
$inputb = $name;
}
if($formal eq "FUNC") {
$output = $name;
}
}
}
printf(ARCHFILE " %s <= %s + %s;\n",$output,$inputa,$inputb);
}

sub PrintCOMPARE {
local($theline) = @_;
local($inputa,$inputb,$output);

$done = 0;
while(!$done) {
$theline = <XNFFILE>;
$theline =~ s/[ \n]+//g;
if($theline =~ /END/) {
$done = 1;
}
else {
($pin, $formal, $direction, $name) = split(/,/,$theline);
$name = &FixName($name);
if($formal eq "A") {
$inputa = $name;
}
if($formal eq "B") {
$inputb = $name;
}
if($formal eq "A_EQ_B") {
$output = $name;
}
}
}
printf(ARCHFILE " %s <= '1' when (%s = %s) else '0';\n",$output,$inputa,$in
putb);
}

sub AddElement {
local($theline) = @_;
local($busname,$signame);

$done = 0;
# Extract the element number from the first line
($sym, $name, $type, $def, $elemnum) = split(/,/,$theline);
$elemnum =~ s/[ =ELEM]+//g;
# Find the bus name and the individual signal name
while(!$done) {
$theline = <XNFFILE>;
$theline =~ s/[ \n]+//g;
if($theline =~ /END/) {
$done = 1;
}
else {
($pin, $formal, $direction, $name) = split(/,/,$theline);
$name = &FixName($name);
if($formal eq "XBLOX_BUS") {
$busname = $name;
}
if($formal eq "ELEM") {
$signame = $name;
}
}
}
# If the signal name is just the bus-ripped version of the bus name,
# clear the list. It will be deleted and no alias will be constructed.
# If the signal name is different, add it to the list.
if($signame =~ /\(/) {
$aliaselement{$busname} = "";
}
else {
$aliaselement{$busname} = $aliaselement{$busname} .
$signame . "," . $elemnum . ":";
}
}

sub PrintAlias {
local($signal) = @_;
local($busname,$signame);

$elementlist = $aliaselement{$signal};
if($elementlist ne "") {
@elementarray = split(/:/,$elementlist);
@sortedelement = ();
for($i=0; $i<=$#elementarray; $i=$i+1) {
($element,$elemnum) = split(/,/,$elementarray[$i]);
$sortedelement[$elemnum] = $element;
}
printf(ARCHFILE " %s <= (",$signal,$aliasarray{$signal});
for($i=$#sortedelement; $i>=1; $i=$i-1) {
printf(ARCHFILE "%s & ",$sortedelement[$i]);
}
printf(ARCHFILE "%s);\n",$sortedelement[0]);
}
}

sub FixName {
local($name) = @_;
$name =~ s/\</\(/;
$name =~ s/\>/\)/;
$name =~ s/\$+//;
return $name;
}

sub PrintTrailer {
local($archfilename) = @_;

($entname, $archname) = split(/_/,$archfilename);
$archname =~ s/\.vhd//;
printf(ARCHFILE "\n");
printf(ARCHFILE "end %s;\n",$archname);
}

sub HackSignals {
local($hackfilename) = @_;

open(HACKFILE,$hackfilename);
while($theline = <HACKFILE>) {
if($theline =~ /^signal/) {
printf(ARCHFILE "%s",$theline);
}
}
close(HACKFILE);
}

sub HackNetlist {
local($hackfilename) = @_;

open(HACKFILE,$hackfilename);
while($theline = <HACKFILE>) {
if($theline =~ /<=/) {
printf(ARCHFILE "%s",$theline);
}
}
close(HACKFILE);
}
 

Other Scripts:

Batch Simulation
Compare Files
Convert
Def2Verilog
Gen XOR Tree
GetValue
IHEX2VHEX
nand tree
Name Instance
OnesCompSum
Preprocessor
Verilog Tag

Verilog Tag2
Verilog2DEF
VHDL2HTML
VRename
XNF2VHDL

 

Products:

Undertow Suite
Undertow
Interactive_tool
Optimizing_tool
VeriPower
Power_tool
Toggle_tool
Express_VCT
Personal_VCT
VBIT«
verilog2vhdl™
vhdl2verilogmkt
Script Pool


 

 Company    Products     News    Assistance     Download     Contact Us    Sales

Veritools, Inc.
459 Hamilton Avenue, Suite 100, Palo Alto, California 94301
(650) 462 - 5590 Main    (650) 462 - 5593 Fax
inquiry@veritools.com

For Web site information please email Webmaster