Xilinx Synthesis Tool (XST). Turns HDL source and schematics into a binary netlist in NGC format. Most of the time you'll spend with it will be banging your head against the table trying to decode its many messages.

Example usage:

xst -intstyle ise -ifn [script file] -ofn [syr file]

The script file is a series of flags, one per line. Required flags:

set -tmpdir [temporary directory]
set -xsthdpdir [another temporary directory]
-ifn [PRJ file name]
-ofn [output NGC file name]
-p [device name]
-top [top-level module name]

Other optional flags may be specified as well.

The PRJ file is a text file containing a series of lines of the format [vhdl|verilog] [library name, default is “work”] [quoted path to source file]. The PRJ file must include the library file “${XILINX}/ISE_DS/ISE/verilog/src/glbl.v”.

The SYR file is a text output file containing the synthesis report.

Instantiate I/O directly

One issue with VHDL and verilog is that they are both strictly heirachical: any time you need to pass a signal from the middle of your design to I/O you must route through every module in between. This can be onerous, especially for debugging. However, its possible to directly instantiate an IOB and use a LOC synthesis directive to place it:

(* LOC="AH28" *) IOBUF #(.DRIVE(12), .IOSTANDARD("DEFAULT"), .SLEW("SLOW")) iobuf(
        .O(), .IO(), .I(GPIO_LED_S), .T(0));

This, for example, takes the signal (ie wire/register) GPIO_LED_S and routes it to pad AH28 (the south LED on the Virtex 6 ML605 board).

This allows you to bypass heirachical design as well as skip .ucf constraints. This is wildly outside of the normal toolchain flow and so I strongly reccomend this for debugging only.




(* KEEP = "TRUE" *) wire [31:0] a_signal;
(* KEEP = "TRUE" *) wire [31:0] my_signal_tig_path = my_signal;

CGD 14.5:

Constraints can also be specified in Verilog code using meta comments. The Verilog
format is the preferred syntax, but the meta comment style is still supported

Instead they reccomend these:

Verilog Attributes Syntax Example One
  (* clock_buffer = "IBUFG" *) input CLK;
Verilog Attributes Syntax Example Two
  (* INIT = "0000" *) reg [3:0] d_out;
Verilog Attributes Syntax Example Three
  always@(current_state or reset)
  begin (* parallel_case *) (* full_case *)
      case (current_state)
Verilog Attributes Syntax Example Four
  (* mult_style = "pipe_lut" *) MULT my_mult (a, b, c);


attribute keep:string;
signal a_signal : std_logic;
attribute keep of a_signal: signal is "true";
signal my_signal_tig_path : std_logic;
attribute keep of my_signal_tig_path: signal is "true";


my_module: WARNING:Xst:3136 - Property “KEEP” (value “TRUE”) has not been applied on proper HDL object.

You must apply these to wires/reg and cannot apply to entire module.  You must apply to individual wires that you want to keep within the module.


Preprocessor command line

This section is about pushing the pre-processor to its limit. You should start by reading Verilog Preprocessor: Force for `Good and `Evil. Of course, the ISE GUI won't let you do any of this, so you'll need to read up on the xst guide / command line tools reference if you aren't familiar with them

Section applies to ISE 14.5 unless otherwise noted. Makefile focused but should work for other build systems (ex: omake).

Problem: need to manage several build variants. How to do this cleanly? Start by exploring what is possible

Splitting xst options across files

Problem: an xst invocation looks something like this:

xst -intstyle ise -ifn proj.xst -ofn proj.srp

With proj.xst looking roughly like this:

set -tmpdir tmp
set -xsthdpdir tmp2
-ifn proj.prj
-ofn proj.ngc
-define {SUCK IT TREBEK=8}

Now lets say that the -define line specifies some project specific tweaks. For the other core tools (ex: par) you can specify additional -f options to add additional argument files. However, this doesn't work because xst scripts are designed to be able to support multiple synthesis targets per file which made it so that a run command cannot be split across multiple files.



set -tmpdir tmp
set -xsthdpdir tmp2
-ifn proj.prj
-ofn proj.ngc


-define {SUCK IT TREBEK=8}


proj.xst: xst1.arg xst2.arg
	cat xst1.arg xst2.arg >proj.xst
xst: proj.xst
	xst -intstyle ise -ifn proj.xst -ofn proj.srp

Other methods like using m4 or sed on a template xst file would of course work equally well

VERY IMPORTANT NOTE: the following proj.xst is invalid:

set -tmpdir tmp
set -xsthdpdir tmp2
-ifn proj.prj
-ofn proj.ngc

-define {SUCK IT TREBEK=8}

That is, a blank line ends/breaks a run command. Mind stray newlines when combining files

Multiple vlgincdir commands

This works:

-vlgincdir {../include ../include/subinc}

However, this IMHO should be equivalent but isn't:

-vlgincdir {../include/subinc}
-vlgincdir {../include}

xst takes the first vlgincdir command and ignores all subsequent invocations. Switching the two lines simply changes which includes fail. I also find this odd from a design perspective as in most systems the last directive overrides the previous directives

Workaround: create your include list in your Makefile. Use this to create a .arg file and combine these into a master .xst script

Multiple define commands

This works:

-define {SUCK IT TREBEK=8}

But this doesn't:

-define {SUCK IT}
-define {TREBEK=8}

Its the same problem as vlgincdir

Black boxes

VHDL has a separation between declaration and implementation (akin to C's .h vs .c files, etc). However, Verilog makes no such distinction (akin to Java, etc). To solve this, designs can instantiate an empty module that will get implicity treated like a black box. Say something like:

module secret_sauce(input wire i1, input wire i2, output wire o);

However, this generates xst warnings:

WARNING:HDLCompiler:1499 - "secret_sauce.v" Line 39: Empty module <secret_sauce> remains a black box.

One idea might be to export your IP cores as VHDL even if you have a Verilog audience since it handles this better.

But if you are a Verilog purist there is a way to eliminate the above warning using something like:

(* BOX_TYPE = "primitive" *)
secret_sauce saucy(.i1(stuff1), .i2(stuff2), .o(output));

Unfortunately you have to put this on every instantiation. If you had to do this a lot you could put a wrapper on secret_sauce. See XST User Guide “BoxType (BOX_TYPE)” for more detail.

xilinx/xst.txt · Last modified: 2015/07/20 22:35 by mcmaster-guest
Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution 4.0 International
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki