amaranth/nmigen/fhdl/cd.py

68 lines
2.2 KiB
Python
Raw Normal View History

2018-12-11 13:50:56 -07:00
from .. import tracer
from .ast import Signal
2018-12-14 03:56:53 -07:00
__all__ = ["ClockDomain", "DomainError"]
class DomainError(Exception):
pass
2018-12-11 13:50:56 -07:00
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
2018-12-11 13:50:56 -07:00
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)
2018-12-11 13:50:56 -07:00
def __init__(self, name=None, reset_less=False, async_reset=False):
if name is None:
2018-12-13 02:19:16 -07:00
try:
name = tracer.get_var_name()
except tracer.NameNotFound:
raise ValueError("Clock domain name must be specified explicitly")
2018-12-11 13:50:56 -07:00
if name.startswith("cd_"):
name = name[3:]
self.name = name
self.clk = Signal(name=self._name_for(name, "clk"), src_loc_at=1)
2018-12-11 13:50:56 -07:00
if reset_less:
self.rst = None
2018-12-11 13:50:56 -07:00
else:
self.rst = Signal(name=self._name_for(name, "rst"), src_loc_at=1)
2018-12-11 13:50:56 -07:00
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")