cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
rgaddi
Adventurer
Adventurer
1,001 Views
Registered: ‎04-22-2008

Drive '0' on all unused IOs

Jump to solution

I'd like to have my design drive '0' onto all unused I/O pins so that I can connect them to ground on the PCB to reduce ground bounce.  I figure this should be something that I can run after place/route/optimize so that these low-priority connections don't get in the way of the important stuff.

Finding the unused pins is fairly straightforward:

package require struct::set

set all_pins [get_package_pins -filter {IS_GENERAL_PURPOSE && IS_BONDED}]
set used_pins [get_property package_pin [get_ports]]
set unused_pins [struct::set difference $all_pins $used_pins]

How can I go through this list making these pins drive '0'?

0 Kudos
1 Solution

Accepted Solutions
rgaddi
Adventurer
Adventurer
852 Views
Registered: ‎04-22-2008

This works well enough for my purposes.  In the event it works for someone else's, here it is.

# Ground all IOs in the design that are unused but bonded.
#
# Rob Gaddi, Highland Technology.  April 2, 2020
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED

namespace eval ground_unused {
    namespace export remove_grounds ground_unused_pins
}

package require struct::set

# Return a list of unused package pins.  If the optional bank argument is
# given, only return pins in that bank
proc ground_unused::get_unused_pins {{bank {}}} {
    set filter {IS_GENERAL_PURPOSE && IS_BONDED}
    if {$bank ne {}} {
        set filter "$filter && BANK == $bank"
    }
    set all_pins [get_package_pins -filter $filter]
    set used_pins [get_property package_pin [get_ports]]
    set unused_pins [struct::set difference $all_pins $used_pins]
    return $unused_pins
}

# Return the net of the global ground (usually <const0>) or create it
# if necessary.
proc ground_unused::get_ground_net {} {
    set gnd [get_cells -filter {REF_NAME == GND} -quiet]
    if {$gnd eq {}} {
        set gnd [create_cell -reference GND gndio_GND]
        set net [create_net gndio_net_GND]
        connect_net -net $net -objects [get_pins gndio_GND/G]
    } else {
        set net [lindex [get_nets -of_objects $gnd] 0]
    }
    return $net
}

# Create an IO port for a given package pin.
# Return a list of the port and the input pin for its OBUF.
proc ground_unused::create_io_port {package_pin} {
    set obufname "gndio_obuf_$package_pin"
    set portname "gndio_port_$package_pin"
    
    set port [create_port -direction OUT $portname]
    set obuf [create_cell -reference OBUF $obufname]
    set_property PACKAGE_PIN $package_pin $port

    set io_pins [concat [get_pins "$obufname/O"] $port]
    connect_net -net [create_net "gndio_net_$package_pin"] -objects $io_pins
    return [concat $port [get_pins "$obufname/I"]]
}

proc ground_unused::lshift {inputlist} {
  # Summary : Pop the head argument off input list and return it.
  upvar $inputlist argv
  set arg  [lindex $argv 0]
  set argv [lrange $argv 1 end]
  return $arg
}

##############################################################################
# Public functions
##############################################################################

# Clean up all added ground connections.
proc ground_unused::remove_grounds {} {
    remove_net gndio* -quiet
    remove_port gndio* -quiet
    remove_cell gndio* -quiet
    puts {All gndio features removed.}
}

proc ground_unused::ground_unused_pins {args} {
    # Summary : Connect all unused IOs to ground.  These I/Os can
    # then be grounded on the PCB to reduce ground bounce.
    #
    # Argument Usage:
    # -iobank <bankNumber> : Limit the operation to one I/O bank.
    # -iostandard <iostandard> : Set IOStandard for the new ground ports
    # -quiet : Suppress reporting of the new ports
    #
    # Return Value:
    # A list of the newly added ports

    set IOBank {}
    set IOStandard {}
    set help 0
    set errors 0
    set loud 1
    
    while {[llength $args]} {
        set option [lshift args]
        switch -exact -- $option {
            -iobank {
                set IOBank [lshift args]
            }
            -iostandard {
                set IOStandard [lshift args]
            }
            -quiet {
                set loud 0
            }
            -h -
            -help -
            -u -
            -usage {
                set help 1
            }
            default {
                if {[string match "-*" $option]} {
                    puts " -E- option '$option' is not a valid option."
                    incr errors
                } else {
                    puts " -E- option '$option' is not a valid option."
                    incr errors
                }
            }
        }
    }

    if {$help} {
        puts [format {
    Usage: ground_unused_pins
            [-iobank <bankNumber>]      - Limit the operation to one I/O bank.
            [-iostandard <iostandard>]  - Set IOStandard for the new ground ports
            [-usage|-u]                 - This help message

    Description:  Connect all unused IOs to ground.  These I/Os can then be
    grounded on the PCB to reduce ground bounce.

    Example:
        ground_unused_pins -iobank 35 -iostandard LVCMOS33
        }]
        return -code ok
    }
    if {$errors} {
        error " -E- some error(s) happened. Cannot continue"
    }
    
    set gnd_net [get_ground_net]
    set pins [get_unused_pins $IOBank]
    if {$pins eq {}} {
        if {$loud} {
            puts "No unused pins"
        }
        return -code ok {}
    }
    
    set obuf_pins {}
    set ports {}
    foreach {pin} $pins {
        set rv  [create_io_port $pin]
        lappend ports [lshift rv]
        lappend obuf_pins $rv
    }
    connect_net -net $gnd_net -objects $obuf_pins
    if {$IOStandard ne {}} {
        set_property IOSTANDARD $IOStandard $ports
    }
    if {$loud} {
        puts "Created [llength $ports] ground pins"
    }
    return $ports
}

View solution in original post

6 Replies
rshekhaw
Xilinx Employee
Xilinx Employee
980 Views
Registered: ‎05-22-2018

Hi @rgaddi ,

The unused pins do not need to be grounded or otherwise connected because by default unused pins will be pulled low (or high).

Or otherwise check this AR#:

https://www.xilinx.com/support/answers/1481.html

Thanks,

Raj

0 Kudos
rgaddi
Adventurer
Adventurer
971 Views
Registered: ‎04-22-2008

Hi @rshekhaw, thanks for your response.  Unfortunately, that only creates weak pullups/pulldowns to make sure that the inputs don't float and create noise.  I'm looking to actively drive 0, then connect that pin to ground on the PCB.  The theory is that these additional parallel ground connections reduce the total inductance of the ground connection, and thus the total voltage ripple caused by the di/dt transient when the internal logic gates all transition on the clock edge.  That only works with a low impedance connection though; I need the active low drive of only a couple of ohms rather than the weak pull resistors of 10k+.

0 Kudos
rgaddi
Adventurer
Adventurer
932 Views
Registered: ‎04-22-2008

There's another similar question on here at https://forums.xilinx.com/t5/Vivado-TCL-Community/How-to-add-an-IO-pad-using-TCL/m-p/483824 in which the advice given is:


Check this article http://www.xilinx.com/support/answers/53266.htm . You can use the tcl scripts provided in the article.

That link is dead, and I can't find any record of AR: 53266.  Any idea what it might be?

0 Kudos
tonys
Xilinx Employee
Xilinx Employee
926 Views
Registered: ‎03-03-2009

That AR might have been terminated because the add_probe script was added to the Xilinx Tcl Store. Load the Debug Utilities apps and take a look at the add_probe script.

0 Kudos
rgaddi
Adventurer
Adventurer
872 Views
Registered: ‎04-22-2008

Thanks, @tonys.  add_probe does all the same things I need to do; I just need to figure out how to harvest the parts I need.  I'll post my code when I've got a working solution.

Relatedly, Xilinx house style should have people put their names to their code.  Whoever did add_probe did a really nice job with it; all super cleanly put together and clear how it all works.

0 Kudos
rgaddi
Adventurer
Adventurer
853 Views
Registered: ‎04-22-2008

This works well enough for my purposes.  In the event it works for someone else's, here it is.

# Ground all IOs in the design that are unused but bonded.
#
# Rob Gaddi, Highland Technology.  April 2, 2020
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED

namespace eval ground_unused {
    namespace export remove_grounds ground_unused_pins
}

package require struct::set

# Return a list of unused package pins.  If the optional bank argument is
# given, only return pins in that bank
proc ground_unused::get_unused_pins {{bank {}}} {
    set filter {IS_GENERAL_PURPOSE && IS_BONDED}
    if {$bank ne {}} {
        set filter "$filter && BANK == $bank"
    }
    set all_pins [get_package_pins -filter $filter]
    set used_pins [get_property package_pin [get_ports]]
    set unused_pins [struct::set difference $all_pins $used_pins]
    return $unused_pins
}

# Return the net of the global ground (usually <const0>) or create it
# if necessary.
proc ground_unused::get_ground_net {} {
    set gnd [get_cells -filter {REF_NAME == GND} -quiet]
    if {$gnd eq {}} {
        set gnd [create_cell -reference GND gndio_GND]
        set net [create_net gndio_net_GND]
        connect_net -net $net -objects [get_pins gndio_GND/G]
    } else {
        set net [lindex [get_nets -of_objects $gnd] 0]
    }
    return $net
}

# Create an IO port for a given package pin.
# Return a list of the port and the input pin for its OBUF.
proc ground_unused::create_io_port {package_pin} {
    set obufname "gndio_obuf_$package_pin"
    set portname "gndio_port_$package_pin"
    
    set port [create_port -direction OUT $portname]
    set obuf [create_cell -reference OBUF $obufname]
    set_property PACKAGE_PIN $package_pin $port

    set io_pins [concat [get_pins "$obufname/O"] $port]
    connect_net -net [create_net "gndio_net_$package_pin"] -objects $io_pins
    return [concat $port [get_pins "$obufname/I"]]
}

proc ground_unused::lshift {inputlist} {
  # Summary : Pop the head argument off input list and return it.
  upvar $inputlist argv
  set arg  [lindex $argv 0]
  set argv [lrange $argv 1 end]
  return $arg
}

##############################################################################
# Public functions
##############################################################################

# Clean up all added ground connections.
proc ground_unused::remove_grounds {} {
    remove_net gndio* -quiet
    remove_port gndio* -quiet
    remove_cell gndio* -quiet
    puts {All gndio features removed.}
}

proc ground_unused::ground_unused_pins {args} {
    # Summary : Connect all unused IOs to ground.  These I/Os can
    # then be grounded on the PCB to reduce ground bounce.
    #
    # Argument Usage:
    # -iobank <bankNumber> : Limit the operation to one I/O bank.
    # -iostandard <iostandard> : Set IOStandard for the new ground ports
    # -quiet : Suppress reporting of the new ports
    #
    # Return Value:
    # A list of the newly added ports

    set IOBank {}
    set IOStandard {}
    set help 0
    set errors 0
    set loud 1
    
    while {[llength $args]} {
        set option [lshift args]
        switch -exact -- $option {
            -iobank {
                set IOBank [lshift args]
            }
            -iostandard {
                set IOStandard [lshift args]
            }
            -quiet {
                set loud 0
            }
            -h -
            -help -
            -u -
            -usage {
                set help 1
            }
            default {
                if {[string match "-*" $option]} {
                    puts " -E- option '$option' is not a valid option."
                    incr errors
                } else {
                    puts " -E- option '$option' is not a valid option."
                    incr errors
                }
            }
        }
    }

    if {$help} {
        puts [format {
    Usage: ground_unused_pins
            [-iobank <bankNumber>]      - Limit the operation to one I/O bank.
            [-iostandard <iostandard>]  - Set IOStandard for the new ground ports
            [-usage|-u]                 - This help message

    Description:  Connect all unused IOs to ground.  These I/Os can then be
    grounded on the PCB to reduce ground bounce.

    Example:
        ground_unused_pins -iobank 35 -iostandard LVCMOS33
        }]
        return -code ok
    }
    if {$errors} {
        error " -E- some error(s) happened. Cannot continue"
    }
    
    set gnd_net [get_ground_net]
    set pins [get_unused_pins $IOBank]
    if {$pins eq {}} {
        if {$loud} {
            puts "No unused pins"
        }
        return -code ok {}
    }
    
    set obuf_pins {}
    set ports {}
    foreach {pin} $pins {
        set rv  [create_io_port $pin]
        lappend ports [lshift rv]
        lappend obuf_pins $rv
    }
    connect_net -net $gnd_net -objects $obuf_pins
    if {$IOStandard ne {}} {
        set_property IOSTANDARD $IOStandard $ports
    }
    if {$loud} {
        puts "Created [llength $ports] ground pins"
    }
    return $ports
}

View solution in original post