Exemple #1
0
def synchronize(m, signal, *, output=None, o_domain='sync', stages=2):
    """ Convenience function. Synchronizes a signal, or equivalent collection.

    Parameters:
        input   -- The signal to be synchronized.
        output  -- The signal to output the result of the synchronization
                   to, or None to have one created for you.
        domain  -- The name of the domain to be synchronized to.
        stages  -- The depth (in FFs) of the synchronization chain.
                   Longer incurs more delay. Must be >= 2 to avoid metastability.

    Returns:
        record  -- The post-synchronization signal. Will be equivalent to the
                   `output` record if provided, or a new, created signal otherwise.
    """

    # Quick function to create a synchronizer with our domain and stages.
    def create_synchronizer(signal, output):
        return FFSynchronizer(signal, output, o_domain=o_domain, stages=stages)

    if output is None:
        if isinstance(signal, Signal):
            output = Signal.like(signal)
        else:
            output = Record.like(signal)

    # If the object knows how to synchronize itself, let it.
    if hasattr(signal, '_synchronize_'):
        signal._synchronize_(m, output, o_domain=o_domain, stages=stages)
        return output

    # Trivial case: if this element doesn't have a layout,
    # we can just synchronize it directly.
    if not hasattr(signal, 'layout'):
        m.submodules += create_synchronizer(signal, output)
        return output

    # Otherwise, we'll need to make sure we only synchronize
    # elements with non-output directions.
    for name, layout, direction in signal.layout:

        # If this is a record itself, we'll need to recurse.
        if isinstance(signal[name], (Record, Pin)):
            synchronize(m,
                        signal[name],
                        output=output[name],
                        o_domain=o_domain,
                        stages=stages)
            continue

        # Skip any output elements, as they're already
        # in our clock domain, and we don't want to drive them.
        if (direction == DIR_FANOUT) or (hasattr(signal[name], 'o')
                                         and ~hasattr(signal[name], 'i')):
            m.d.comb += signal[name].eq(output[name])
            continue

        m.submodules += create_synchronizer(signal[name], output[name])

    return output
Exemple #2
0
 def __init__(self):
     super().__init__()
     self.reg_verify_value = Signal(32)
     self.accelerator_start = Signal()
     self.accelerator_reset = Signal()
     self.config = Record(ACCELERATOR_CONFIGURATION_LAYOUT)
     self.filter_output = Endpoint(FILTER_WRITE_COMMAND)
     self.post_process_params = Endpoint(POST_PROCESS_PARAMS)
Exemple #3
0
    def instantiate_dut(self):
        # Create a record that recreates the layout of our RAM signals.
        self.ram_signals = Record([("clk", 1), ("clkN", 1),
                                   ("dq", [("i", 8), ("o", 8), ("oe", 1)]),
                                   ("rwds", [("i", 1), ("o", 1), ("oe", 1)]),
                                   ("cs", 1), ("reset", 1)])

        # Create our HyperRAM interface...
        return HyperRAMInterface(bus=self.ram_signals)
Exemple #4
0
    def test_nested_record(self):
        m = Module()

        record = Record([('sig_in', 1, DIR_FANIN), ('sig_out', 1, DIR_FANOUT),
                         ('nested', [
                             ('subsig_in', 1, DIR_FANIN),
                             ('subsig_out', 1, DIR_FANOUT),
                         ])])
        synchronize(m, record)
Exemple #5
0
 def get_axi(self, axi):
     assert axi in self.MAXI + self.SAXI
     if axi in self.MAXI:
         layout = get_axi_layout('master')
     elif axi in self.SAXI:
         layout = get_axi_layout('slave')
     fields = {f: self._ports[axi.upper() + f] for f, w, d in layout}
     layout = [(f, w) for f, w, _ in layout]
     rec = Record(layout, fields=fields, name=axi)
     return rec
Exemple #6
0
 def instantiate_dut(self):
     self.utmi = Record([
         ('tx_data', 8),
         ('rx_data', 8),
         ('rx_valid', 1),
         ('rx_active', 1),
         ('rx_error', 1),
         ('rx_complete', 1),
     ])
     return USBAnalyzer(utmi_interface=self.utmi, mem_depth=128)
Exemple #7
0
    def instantiate_dut(self):

        self.ulpi = Record([
            ("dir", 1),
            ("nxt", 1),
            ("data", [
                ("i", 8),
            ])
        ])

        return ULPIRxEventDecoder(ulpi_bus=self.ulpi)
Exemple #8
0
    def __init__(self, specialize_nx=False):
        self._specialize_nx = specialize_nx
        self.reset = Signal()
        self.start = Signal()
        self.config = Record(ACCELERATOR_CONFIGURATION_LAYOUT)

        self.write_filter_input = Endpoint(FILTER_WRITE_COMMAND)
        self.lram_addr = [Signal(14, name=f"lram_addr{i}") for i in range(4)]
        self.lram_data = [Signal(32, name=f"lram_data{i}") for i in range(4)]
        self.post_process_params = Endpoint(POST_PROCESS_PARAMS)
        self.output = Endpoint(unsigned(32))
Exemple #9
0
    def instantiate_dut(self):

        from ..interface.ulpi import UTMITranslator

        self.ulpi = Record([('data', [
            ('i', 8),
            ('o', 8),
            ('oe', 8),
        ]), ('nxt', 1), ('stp', 1), ('dir', [('i', 1)]), ('clk', 1),
                            ('rst', 1)])

        # Create a stack of our UTMITranslator and our USBAnalyzer.
        # We'll wrap the both in a module to establish a synthetic hierarchy.
        m = Module()
        m.submodules.translator = self.translator = UTMITranslator(
            ulpi=self.ulpi, handle_clocking=False)
        m.submodules.analyzer = self.analyzer = USBAnalyzer(
            utmi_interface=self.translator, mem_depth=128)
        return m
Exemple #10
0
    def test_directional_record(self):
        m = Module()

        record = Record([('sig_in', 1, DIR_FANIN), ('sig_out', 1, DIR_FANOUT)])
        synchronize(m, record)
Exemple #11
0
 def __init__(self):
     self.sizes = Record(POST_PROCESS_SIZES)
     self.reset = Signal()
     self.output_data = Endpoint(POST_PROCESS_PARAMS)
     self.mem_addr = Signal(range(Constants.MAX_CHANNEL_DEPTH))
     self.mem_data = Signal(POST_PROCESS_PARAMS_WIDTH)
Exemple #12
0
    """
    name = signal.name
    for i in range(cycles):
        delayed = Signal.like(signal, name=f"{name}_delay_{i}")
        m.d.sync += delayed.eq(signal)
        signal = delayed
    return signal


POST_PROCESS_PARAMS = [
    ('bias', signed(18)),
    ('multiplier', signed(32)),
    ('shift', unsigned(4)),
]

POST_PROCESS_PARAMS_WIDTH = len(Record(POST_PROCESS_PARAMS))


class PostProcessPipeline(SimpleElaboratable):
    """Converts an accumulator into an 8-bit value

    Attributes
    ----------

    input: Endpoint(signed(32)), in
      The accumulated value to convert

    params: Endpoint(POST_PROCESS_PARAMS), in
      Parameters assumed always ready and then read on input

    output: Endpoint(signed(8)), out