
This also reorganizes README to more clearly describe what nMigen is, since it was getting quite outdated.
68 lines
2.2 KiB
Python
68 lines
2.2 KiB
Python
from .. import tracer
|
|
from .ast import Signal
|
|
|
|
|
|
__all__ = ["ClockDomain", "DomainError"]
|
|
|
|
|
|
class DomainError(Exception):
|
|
pass
|
|
|
|
|
|
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
|
|
If ``True``, 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.
|
|
async_reset : bool
|
|
If ``True``, the domain uses an asynchronous reset, and registers within this domain
|
|
are initialized to their reset state when reset level changes. Otherwise, registers
|
|
are initialized to reset state at the next clock cycle when reset is asserted.
|
|
|
|
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.
|
|
"""
|
|
|
|
@staticmethod
|
|
def _name_for(domain_name, signal_name):
|
|
if domain_name == "sync":
|
|
return signal_name
|
|
else:
|
|
return "{}_{}".format(domain_name, signal_name)
|
|
|
|
def __init__(self, name=None, reset_less=False, async_reset=False):
|
|
if name is None:
|
|
try:
|
|
name = tracer.get_var_name()
|
|
except tracer.NameNotFound:
|
|
raise ValueError("Clock domain name must be specified explicitly")
|
|
if name.startswith("cd_"):
|
|
name = name[3:]
|
|
self.name = name
|
|
|
|
self.clk = Signal(name=self._name_for(name, "clk"), src_loc_at=1)
|
|
if reset_less:
|
|
self.rst = None
|
|
else:
|
|
self.rst = Signal(name=self._name_for(name, "rst"), src_loc_at=1)
|
|
|
|
self.async_reset = async_reset
|
|
|
|
def rename(self, new_name):
|
|
self.name = new_name
|
|
self.clk.name = self._name_for(new_name, "clk")
|
|
if self.rst is not None:
|
|
self.rst.name = self._name_for(new_name, "rst")
|