return self.huid
class Value(HUID):
+ """Base class for operands
+
+ Instances of `Value` or its subclasses can be operands to
+ arithmetic, comparison, bitwise, and logic operators.
+ They can be assigned (:meth:`eq`) or indexed/sliced (using the usual
+ Python indexing and slicing notation).
+
+ Values created from integers have the minimum bit width to necessary to
+ represent the integer.
+ """
def __invert__(self):
return _Operator("~", [self])
def __neg__(self):
raise KeyError
def eq(self, r):
+ """Assignment
+
+ Parameters
+ ----------
+ r : Value, in
+ Value to be assigned.
+
+ Returns
+ -------
+ _Assign
+ Assignment statement that can be used in combinatorial or
+ synchronous context.
+ """
return _Assign(self, r)
def __hash__(self):
self.operands = operands
def Mux(sel, val1, val0):
+ """Multiplex between two values
+
+ Parameters
+ ----------
+ sel : Value(1), in
+ Selector.
+ val1 : Value(N), in
+ val0 : Value(N), in
+ Input values.
+
+ Returns
+ -------
+ Value(N), out
+ Output `Value`. If `sel` is asserted, the Mux returns
+ `val1`, else `val0`.
+ """
return _Operator("m", [sel, val1, val0])
class _Slice(Value):
self.stop = stop
class Cat(Value):
+ """Concatenate values
+
+ Form a compound `Value` from several smaller ones by concatenation.
+ The first argument occupies the lower bits of the result.
+ The return value can be used on either side of an assignment, that
+ is, the concatenated value can be used as an argument on the RHS or
+ as a target on the LHS. If it is used on the LHS, it must solely
+ consist of `Signal` s. The bit length of the return value is the sum of
+ the bit lengths of the arguments::
+
+ flen(Cat(*args)) == sum(flen(arg) for arg in args)
+
+ Parameters
+ ----------
+ *args : Value, inout
+ `Value` s to be concatenated.
+
+ Returns
+ -------
+ Cat, inout
+ Resulting `Value` obtained by concatentation.
+ """
def __init__(self, *args):
Value.__init__(self)
self.l = args
class Replicate(Value):
+ """Replicate a value
+
+ An input value is replicated (repeated) several times
+ to be used on the RHS of assignments::
+
+ flen(Replicate(s, n)) == flen(s)*n
+
+ Parameters
+ ----------
+ v : Value, in
+ Input value to be replicated.
+ n : int
+ Number of replications.
+
+ Returns
+ -------
+ Replicate, out
+ Replicated value.
+ """
def __init__(self, v, n):
Value.__init__(self)
self.v = v
self.n = n
class Signal(Value):
+ """A `Value` that can change
+
+ The `Signal` object represents a value that is expected to change
+ in the circuit. It does exactly what Verilog's `wire` and
+ `reg` and VHDL's `signal` do.
+
+ A `Signal` can be indexed to access a subset of its bits. Negative
+ indices (`signal[-1]`) and the extended Python slicing notation
+ (`signal[start:stop:step]`) are supported.
+ The indeces 0 and -1 are the least and most significant bits
+ respectively.
+
+ Parameters
+ ----------
+ bits_sign : int or tuple
+ Either an integer `bits` or a tuple `(bits, signed)`
+ specifying the number of bits in this `Signal` and whether it is
+ signed (can represent negative values). `signed` defaults to
+ `False`.
+ name : str or None
+ Name hint for this signal. If `None` (default) the name is
+ inferred from the variable name this `Signal` is assigned to.
+ Name collisions are automatically resolved by prepending
+ names of objects that contain this `Signal` and by
+ appending integer sequences.
+ variable : bool
+ Deprecated.
+ reset : int
+ Reset (synchronous) or default (combinatorial) value.
+ When this `Signal` is assigned to in synchronous context and the
+ corresponding clock domain is reset, the `Signal` assumes the
+ given value. When this `Signal` is unassigned in combinatorial
+ context (due to conditional assignments not being taken),
+ the `Signal` assumes its `reset` value. Defaults to 0.
+ name_override : str or None
+ Do not use the inferred name but the given one.
+ min : int or None
+ max : int or None
+ If `bits_sign` is `None`, the signal bit width and signedness are
+ determined by the integer range given by `min` (inclusive,
+ defaults to 0) and `max` (exclusive, defaults to 2).
+ related : Signal or None
+ """
def __init__(self, bits_sign=None, name=None, variable=False, reset=0, name_override=None, min=None, max=None, related=None):
from migen.fhdl.size import bits_for
return "<Signal " + (self.backtrace[-1][0] or "anonymous") + " at " + hex(id(self)) + ">"
class ClockSignal(Value):
+ """Clock signal for a given clock domain
+
+ `ClockSignal` s for a given clock domain can be retrieved multiple
+ times. They all ultimately refer to the same signal.
+
+ Parameters
+ ----------
+ cd : str
+ Clock domain to obtain a clock signal for. Defaults to `"sys"`.
+ """
def __init__(self, cd="sys"):
Value.__init__(self)
self.cd = cd
class ResetSignal(Value):
+ """Reset signal for a given clock domain
+
+ `ResetSignal` s for a given clock domain can be retrieved multiple
+ times. They all ultimately refer to the same signal.
+
+ Parameters
+ ----------
+ cd : str
+ Clock domain to obtain a reset signal for. Defaults to `"sys"`.
+ """
def __init__(self, cd="sys"):
Value.__init__(self)
self.cd = cd
self.r = r
class If:
+ """Conditional execution of statements
+
+ Parameters
+ ----------
+ cond : Value(1), in
+ Condition
+ *t : Statements
+ Statements to execute if `cond` is asserted.
+
+ Examples
+ --------
+ >>> a = Signal()
+ >>> b = Signal()
+ >>> c = Signal()
+ >>> d = Signal()
+ >>> If(a,
+ ... b.eq(1)
+ ... ).Elif(c,
+ ... b.eq(0)
+ ... ).Else(
+ ... b.eq(d)
+ ... )
+ """
def __init__(self, cond, *t):
self.cond = cond
self.t = list(t)
self.f = []
def Else(self, *f):
+ """Add an `else` conditional block
+
+ Parameters
+ ----------
+ *f : Statements
+ Statements to execute if all previous conditions fail.
+ """
_insert_else(self, list(f))
return self
def Elif(self, cond, *t):
+ """Add an `else if` conditional block
+
+ Parameters
+ ----------
+ cond : Value(1), in
+ Condition
+ *t : Statements
+ Statements to execute if previous conditions fail and `cond`
+ is asserted.
+ """
_insert_else(self, [If(cond, *t)])
return self
o.f = clause
class Case:
+ """Case/Switch statement
+
+ Parameters
+ ----------
+ test : Value, in
+ Selector value used to decide which block to execute
+ cases : dict
+ Dictionary of cases. The keys are numeric constants to compare
+ with `test`. The values are statements to be executed the
+ corresponding key matches `test`. The dictionary may contain a
+ string key `"default"` to mark a fall-through case that is
+ executed if no other key matches.
+
+ Examples
+ --------
+ >>> a = Signal()
+ >>> b = Signal()
+ >>> Case(a, {
+ ... 0: b.eq(1),
+ ... 1: b.eq(0),
+ ... "default": b.eq(0),
+ ... })
+ """
def __init__(self, test, cases):
self.test = test
self.cases = cases
def makedefault(self, key=None):
+ """Mark a key as the default case
+
+ Deletes/Substitutes any previously existing default case.
+
+ Parameters
+ ----------
+ key : int or None
+ Key to use as default case if no other key matches.
+ By default, the largest key is the default key.
+ """
if key is None:
for choice in self.cases.keys():
if key is None or choice > key:
self.key)
class Array(list):
+ """Addressable multiplexer
+
+ An array is created from an iterable of values and indexed using the
+ usual Python simple indexing notation (no negative indices or
+ slices). It can be indexed by numeric constants, `Value` s, or
+ `Signal` s.
+
+ The result of indexing the array is a proxy for the entry at the
+ given index that can be used on either RHS or LHS of assignments.
+
+ An array can be indexed multiple times.
+
+ Multidimensional arrays are supported by packing inner arrays into
+ outer arrays.
+
+ Parameters
+ ----------
+ values : iterable of ints, Values, Signals
+ Entries of the array. Each entry can be a numeric constant, a
+ `Signal` or a `Record`.
+
+ Examples
+ --------
+ >>> a = Array(range(10))
+ >>> b = Signal(max=10)
+ >>> c = Signal(max=10)
+ >>> b.eq(a[9 - c])
+ """
def __getitem__(self, key):
if isinstance(key, Value):
return _ArrayProxy(self, key)
return list.__getitem__(self, key)
class ClockDomain:
+ """Synchronous domain
+
+ Parameters
+ ----------
+ name : str or None
+ Domain name. If None (the default) the name is inferred from the
+ variable name this `ClockDomain` is assigned to (stripping any
+ `"cd_"` prefix).
+ reset_less : bool
+ The domain does not use a reset signal. Registers within this
+ domain are still all initialized to their reset state once, e.g.
+ through Verilog `"initial"` statements.
+
+ Attributes
+ ----------
+ clk : Signal, inout
+ The clock for this domain. Can be driven or used to drive other
+ signals (preferably in combinatorial context).
+ rst : Signal or None, inout
+ Reset signal for this domain. Can be driven or used to drive.
+ """
def __init__(self, name=None, reset_less=False):
self.name = tracer.get_obj_var_name(name)
if self.name is None:
self.rst = Signal(name_override=self.name + "_rst")
def rename(self, new_name):
+ """Rename the clock domain
+
+ Parameters
+ ----------
+ new_name : str
+ New name
+ """
self.name = new_name
self.clk.name_override = new_name + "_clk"
if self.rst is not None: