Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/migen
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 49cfba50fabf
Choose a base ref
...
head repository: m-labs/migen
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 38664d6e163e
Choose a head ref
  • 2 commits
  • 3 files changed
  • 1 contributor

Commits on Feb 22, 2013

  1. doc: new 'specials' API

    Sebastien Bourdeauducq committed Feb 22, 2013
    Copy the full SHA
    587f50c View commit details
  2. fhdl: inline synthesis directive support

    Sebastien Bourdeauducq committed Feb 22, 2013
    Copy the full SHA
    38664d6 View commit details
Showing with 53 additions and 25 deletions.
  1. +29 −23 doc/fhdl.rst
  2. +9 −2 examples/basic/psync.py
  3. +15 −0 migen/fhdl/specials.py
52 changes: 29 additions & 23 deletions doc/fhdl.rst
Original file line number Diff line number Diff line change
@@ -132,8 +132,27 @@ and write it with: ::

Since they have no direct equivalent in Verilog, ``Array`` objects are lowered into multiplexers and conditional statements before the actual conversion takes place. Such lowering happens automatically without any user intervention.

Special elements
****************
Specials
********

Tri-state I/O
=============
A triplet (O, OE, I) of one-way signals defining a tri-state I/O port is represented by the ``TSTriple`` object. Such objects are only containers for signals that are intended to be later connected to a tri-state I/O buffer, and cannot be used in fragments. Such objects, however, should be kept in the design as long as possible as they allow the individual one-way signals to be manipulated in a non-ambiguous way.

The object that can be used in a ``Fragment`` is ``Tristate``, and it behaves exactly like an instance of a tri-state I/O buffer that would be defined as follows: ::

Instance("Tristate",
Instance.Inout("target", target),
Instance.Input("o", o),
Instance.Input("oe", oe),
Instance.Output("i", i)
)

Signals ``target``, ``o`` and ``i`` can have any width, while ``oe`` is 1-bit wide. The ``target`` signal should go to a port and not be used elsewhere in the design. Like modern FPGA architectures, Migen does not support internal tri-states.

A ``Tristate`` object can be created from a ``TSTriple`` object by calling the ``get_tristate`` method.

By default, Migen emits technology-independent behavioral code for a tri-state buffer. If a specific code is needed, the tristate handler can be overriden using the appropriate parameter of the V*HDL conversion function.

Instances
=========
@@ -178,42 +197,30 @@ Options to ``get_port`` are:

* ``clock_domain`` (default: ``"sys"``): the clock domain used for reading and writing from this port.

Migen generates behavioural V*HDL code that should be compatible with all simulators and, if the number of ports is <= 2, most FPGA synthesizers. If a specific code is needed, the memory generator function can be overriden using the ``memory_handler`` parameter of the conversion function.
Migen generates behavioural V*HDL code that should be compatible with all simulators and, if the number of ports is <= 2, most FPGA synthesizers. If a specific code is needed, the memory handler can be overriden using the appropriate parameter of the V*HDL conversion function.

Tri-state I/O
=============
A triplet (O, OE, I) of one-way signals defining a tri-state I/O port is represented by the ``TSTriple`` object. Such objects are only containers for signals that are intended to be later connected to a tri-state I/O buffer, and cannot be used in fragments. Such objects, however, should be kept in the design as long as possible as they allow the individual one-way signals to be manipulated in a non-ambiguous way.
Inline synthesis directives
===========================

The object that can be used in a ``Fragment`` is ``Tristate``, and it behaves exactly like an instance of a tri-state I/O buffer that would be defined as follows: ::
Inline synthesis directives (pseudo-comments such as ``// synthesis attribute keep of clock_signal_name is true``) are supported using the ``SynthesisDirective`` object. Its constructor takes as parameters a string containing the body of the directive, and optional keyword parameters that are used to replace signal names similarly to the Python string method ``format``. The above example could be represented as follows: ::

Instance("Tristate",
Instance.Inout("target", target),
Instance.Input("o", o),
Instance.Input("oe", oe),
Instance.Output("i", i)
)

Signals ``target``, ``o`` and ``i`` can have any width, while ``oe`` is 1-bit wide. The ``target`` signal should go to a port and not be used elsewhere in the design. Like modern FPGA architectures, Migen does not support internal tri-states.

A ``Tristate`` object can be created from a ``TSTriple`` object by calling the ``get_tristate`` method.

By default, Migen emits technology-independent behavioral code for a tri-state buffer. If a specific code is needed, the tristate generator function can be overriden using the ``tristate_handler`` parameter of the conversion function.
SynthesisDirective("attribute keep of {clksig} is true", clksig=clock_domain.clk)

Fragments
*********
A "fragment" is a unit of logic, which is composed of:

* A list of combinatorial statements.
* A list of synchronous statements, or a clock domain name -> synchronous statements dictionary.
* A list of instances.
* A list of tri-states.
* A list of memories.
* A set of specials (memories, instances, etc.)
* A list of simulation functions (see :ref:`simulating`).

Fragments can reference arbitrary signals, including signals that are referenced in other fragments. Fragments can be combined using the "+" operator, which returns a new fragment containing the concatenation of each matched pair of lists.

Fragments can be passed to the back-end for conversion to Verilog.

Specials are using a set, not a list, to facilitate sharing of certain elements by different components of a design. For example, one component may use a static memory buffer that another component would map onto a bus, using another port to that memory. Both components should reference the memory object in their fragments, but that memory should appear only once in the final design. The Python ``set`` provides this functionality.

By convention, classes that generate logic implement a method called ``get_fragment``. When called, this method builds a new fragment implementing the desired functionality of the class, and returns it. This convention allows fragments to be built automatically by combining the fragments from all relevant objects in the local scope, by using the autofragment module.

Conversion for synthesis
@@ -225,7 +232,6 @@ Migen does not provide support for any specific synthesis tools or ASIC/FPGA tec

The Mibuild package, available separately from the Migen website, provides scripts to interface third-party FPGA tools to Migen and a database of boards for the easy deployment of designs.


Multi-clock-domain designs
**************************

11 changes: 9 additions & 2 deletions examples/basic/psync.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from migen.fhdl.structure import *
from migen.fhdl.specials import SynthesisDirective
from migen.fhdl import verilog

# convert pulse into level change
@@ -14,10 +15,16 @@
slevel[2].eq(slevel[1])
]

# disable shift register extraction
disable_srl = {
SynthesisDirective("attribute shreg_extract of {signal} is no", signal=slevel[0]),
SynthesisDirective("attribute shreg_extract of {signal} is no", signal=slevel[1])
}

# regenerate pulse
o = Signal()
comb = [o.eq(slevel[1] ^ slevel[2])]

f = Fragment(comb, {"i": isync, "o": osync})
v = verilog.convert(f, ios={i, o})
f = Fragment(comb, {"i": isync, "o": osync}, specials=disable_srl)
v = verilog.convert(f, {i, o})
print(v)
15 changes: 15 additions & 0 deletions migen/fhdl/specials.py
Original file line number Diff line number Diff line change
@@ -309,3 +309,18 @@ def emit_verilog(memory, ns, clock_domains):
r += "end\n\n"

return r

class SynthesisDirective(Special):
def __init__(self, template, **signals):
Special.__init__(self)
self.template = template
self.signals = signals

def list_ios(self, ins, outs, inouts):
return set()

@staticmethod
def emit_verilog(directive, ns, clock_domains):
name_dict = dict((k, ns.get_name(sig)) for k, sig in directive.signals.items())
formatted = directive.template.format(**name_dict)
return "// synthesis " + formatted + "\n"