Пример #1
0
class Top(Elaboratable):
    def __init__(self):
        self.reset = ControlSignal()
        self.to_write = ControlSignal(reset=32 * 1024 * 1024)
        self.data_counter = StatusSignal(32)
        self.perf_counter = StatusSignal(32)
        self.data_valid = ControlSignal()
        self.data_ready = StatusSignal()

    def elaborate(self, platform: ZynqSocPlatform):
        m = Module()

        platform.ps7.fck_domain(requested_frequency=200e6)
        m.d.comb += ResetSignal().eq(self.reset)

        ring_buffer = RingBufferAddressStorage(buffer_size=0x1200000, n=4)

        stream_source = StreamEndpoint(64, is_sink=False, has_last=True)
        m.d.comb += self.data_ready.eq(stream_source.ready)
        m.d.comb += stream_source.valid.eq(self.data_valid)

        clock_signal = Signal()
        m.d.comb += clock_signal.eq(ClockSignal())
        axi_slave = platform.ps7.get_axi_hp_slave(clock_signal)
        axi_writer = m.submodules.axi_writer = AxiBufferWriter(ring_buffer, stream_source, axi_slave=axi_slave)

        with m.If(axi_writer.stream_source.ready & axi_writer.stream_source.valid):
            m.d.sync += self.data_counter.eq(self.data_counter + 1)
        m.d.comb += stream_source.payload.eq(Cat(self.data_counter, self.data_counter+1000))

        with m.If((stream_source.valid) & (axi_writer.words_written < (self.to_write >> int(math.log2(axi_slave.data_bytes))))):
            m.d.sync += self.perf_counter.eq(self.perf_counter+1)

        return m
Пример #2
0
    def __init__(self,
                 video_timing,
                 vertical_signals_shape=range(8000),
                 horizontal_signals_shape=range(4000)):
        self.hscan = ControlSignal(horizontal_signals_shape,
                                   reset=video_timing.hscan)
        self.vscan = ControlSignal(vertical_signals_shape,
                                   reset=video_timing.vscan)
        self.width = ControlSignal(horizontal_signals_shape,
                                   reset=video_timing.hres)
        self.height = ControlSignal(vertical_signals_shape,
                                    reset=video_timing.vres)
        self.hsync_start = ControlSignal(horizontal_signals_shape,
                                         reset=video_timing.hsync_start)
        self.hsync_end = ControlSignal(horizontal_signals_shape,
                                       reset=video_timing.hsync_end)
        self.vsync_start = ControlSignal(vertical_signals_shape,
                                         reset=video_timing.vsync_start)
        self.vsync_end = ControlSignal(vertical_signals_shape,
                                       reset=video_timing.vsync_end)

        self.x = StatusSignal(horizontal_signals_shape, name="x")
        self.y = StatusSignal(vertical_signals_shape, name="y")
        self.active = StatusSignal(name="active")
        self.hsync = StatusSignal(name="hsync")
        self.vsync = StatusSignal(name="vsync")
Пример #3
0
    def __init__(self, plugin):
        """
        This module needs to run in the word clock domain of the bus.
        """
        self.plugin = plugin
        self.output = StreamEndpoint(32, is_sink=False, has_last=False)

        self.ready = StatusSignal()
Пример #4
0
    def __init__(self, num_lanes=4, bits=12):
        assert bits == 12

        self.hispi_clk = Signal()
        self.hispi_lanes = Signal(num_lanes)

        self.bitslip = [Signal() for _ in range(num_lanes)]
        self.out = [Signal(12) for _ in range(num_lanes)]

        self.hispi_x6_in_domain_counter = StatusSignal(32)
Пример #5
0
    def __init__(
            self,
            address_source: StreamEndpoint,
            axi_slave=None, axi_data_width=64
    ):
        assert address_source.has_last is False
        self.address_source = address_source
        self.axi_slave = axi_slave
        self.output = StreamEndpoint(axi_data_width, is_sink=False, has_last=False)

        self.last_resp = StatusSignal(Response)
        self.error_count = StatusSignal(32)
Пример #6
0
    def __init__(self, streams):
        self._streams = streams

        self.has_last = self._streams[0].has_last
        assert not any(self.has_last is not other.has_last
                       for other in self._streams)

        width = sum(len(stream.payload) for stream in self._streams)
        self.output = StreamEndpoint(width,
                                     is_sink=False,
                                     has_last=self.has_last)

        self.different_last_error = StatusSignal()
        self.different_valid_error = StatusSignal()
Пример #7
0
class AxiBufferReader(Elaboratable):
    def __init__(
            self,
            address_source: StreamEndpoint,
            axi_slave=None, axi_data_width=64
    ):
        assert address_source.has_last is False
        self.address_source = address_source
        self.axi_slave = axi_slave
        self.output = StreamEndpoint(axi_data_width, is_sink=False, has_last=False)

        self.last_resp = StatusSignal(Response)
        self.error_count = StatusSignal(32)

    def elaborate(self, platform):
        m = Module()

        if self.axi_slave is not None:
            assert not self.axi_slave.is_lite
            assert not self.axi_slave.is_master
            axi_slave = self.axi_slave
        else:
            clock_signal = Signal()
            m.d.comb += clock_signal.eq(ClockSignal())
            axi_slave = platform.ps7.get_axi_hp_slave(clock_signal)
        axi = AxiEndpoint.like(axi_slave, master=True)
        m.d.comb += axi.connect_slave(axi_slave)

        assert len(self.output.payload) == axi.data_bits

        address_stream = StreamEndpoint.like(self.address_source, is_sink=True, name="address_sink")
        m.d.comb += address_stream.connect(self.address_source)
        assert len(address_stream.payload) == axi.addr_bits

        # we dont generate bursts for now
        m.d.comb += axi.read_address.valid.eq(address_stream.valid)
        m.d.comb += axi.read_address.value.eq(address_stream.payload)
        m.d.comb += address_stream.ready.eq(axi.read_address.ready)
        m.d.comb += axi.read_address.burst_len.eq(0)

        m.d.comb += axi.read_data.ready.eq(self.output.ready)
        m.d.comb += axi.read_data.last.eq(1)
        m.d.comb += self.output.valid.eq(axi.read_data.valid)
        m.d.comb += self.output.payload.eq(axi.read_data.value)

        m.d.sync += self.last_resp.eq(axi.read_data.resp)
        with m.If(axi.read_data.valid & (axi.read_data.resp != Response.OKAY)):
            m.d.sync += self.error_count.eq(self.error_count + 1)

        return m
Пример #8
0
    def __init__(self,
                 input: StreamEndpoint,
                 depth: int,
                 buffered=True,
                 fwtf=False):
        assert input.is_sink is False
        self.input = input
        self.output = StreamEndpoint.like(input, name="stream_fifo_output")
        self.depth = depth
        self.buffered = buffered
        self.fwtf = fwtf

        self.max_w_level = StatusSignal(range(depth))
        self.overflow_cnt = StatusSignal(32)
        self.underrun_cnt = StatusSignal(32)
        self.r_level = StatusSignal(range(depth + 1))
        self.w_level = StatusSignal(range(depth + 1))
Пример #9
0
    def __init__(self, input_clock, vco_mul, vco_div, input_domain="sync"):
        Mmcm.is_valid_vco_conf(input_clock, vco_mul, vco_div, exception=True)
        self._mmcm = InstanceHelper("+/xilinx/cells_xtra.v", "MMCME2_ADV")(
            clkin1_period=1 / input_clock * 1e9,
            clkfbout_mult_f=vco_mul,
            divclk_divide=vco_div,
        )
        m = self.m = Module()
        m.d.comb += self._mmcm.clk.fbin.eq(self._mmcm.clk.fbout)
        m.d.comb += self._mmcm.clk.in_[1].eq(ClockSignal(input_domain))
        m.d.comb += self._mmcm.clk.ins.el.eq(1)  # HIGH for clkin1

        self.locked = StatusSignal()

        self._input_domain = input_domain
        self._input_clock = input_clock
        self._vco = Clock(input_clock * vco_mul / vco_div)
        self._clock_constraints = {}
Пример #10
0
    def __init__(self, input_freq, vco_mul, vco_div, input_domain="sync"):
        Pll.is_valid_vco_conf(input_freq, vco_mul, vco_div, exception=True)
        self._pll = RawPll(
            clkin1_period=1 / input_freq * 1e9,
            clkfbout_mult=vco_mul,
            divclk_divide=vco_div,
        )
        m = self.m = Module()
        m.d.comb += self._pll.clk.fbin.eq(self._pll.clk.fbout)
        m.d.comb += self._pll.clk.in_[1].eq(ClockSignal(input_domain))
        m.d.comb += self._pll.clk.insel.eq(1)  # HIGH for clkin1

        self.locked = StatusSignal()

        self._input_domain = input_domain
        self._input_freq = input_freq
        self._vco = Clock(input_freq * vco_mul / vco_div)
        self._clock_constraints = {}
Пример #11
0
class Top(Elaboratable):
    def __init__(self):
        self.counter = StatusSignal(32)
        self.test_reg = ControlSignal(32)

    def elaborate(self, platform):
        m = Module()

        if isinstance(platform, ZynqSocPlatform):
            platform.ps7.fck_domain(requested_frequency=100e6)
            m.d.sync += self.counter.eq(self.counter + 1)
        elif isinstance(platform, LatticeMachXO2Platform):
            osc = m.submodules.osc = Osc()
            m.d.sync += self.counter.eq(self.counter + 1)
        else:
            m.d.comb += self.counter.eq(
                42)  # we dont have a clock source so we cant count

        return m
Пример #12
0
class StreamCombiner(Elaboratable):
    def __init__(self, streams):
        self._streams = streams

        self.has_last = self._streams[0].has_last
        assert not any(self.has_last is not other.has_last
                       for other in self._streams)

        width = sum(len(stream.payload) for stream in self._streams)
        self.output = StreamEndpoint(width,
                                     is_sink=False,
                                     has_last=self.has_last)

        self.different_last_error = StatusSignal()
        self.different_valid_error = StatusSignal()

    def elaborate(self, platform):
        m = Module()

        highest_bit = 0
        for i, stream in enumerate(self._streams):
            sink = StreamEndpoint.like(
                stream, is_sink=True, name="stream_combiner_sink_{}".format(i))
            sink.connect(stream)
            m.d.comb += stream.ready.eq(self.output.ready)
            m.d.comb += self.output.payload[highest_bit:highest_bit +
                                            len(stream.payload)].eq(
                                                stream.payload)
            highest_bit += len(stream.payload)

            m.d.comb += self.output.valid.eq(stream.valid)
            with m.If(self.output.valid != stream.valid):
                m.d.sync += self.different_valid_error.eq(1)

            if self.has_last:
                m.d.comb += self.output.last.eq(stream.last)
                with m.If(self.output.last != stream.last):
                    m.d.sync += self.different_last_error.eq(1)

        return m
Пример #13
0
 def __init__(self):
     self.reset = ControlSignal()
     self.to_write = ControlSignal(reset=32 * 1024 * 1024)
     self.data_counter = StatusSignal(32)
     self.perf_counter = StatusSignal(32)
     self.data_valid = ControlSignal()
     self.data_ready = StatusSignal()
Пример #14
0
    def __init__(self, pads, name_suffix=""):
        """ A simple gpio peripheral, that is compatible with the gpio-mmio.c linux kernel pydriver.
        see https://github.com/torvalds/linux/blob/master/drivers/gpio/gpio-mmio.c
        """
        self._pads = pads

        # see https://github.com/torvalds/linux/blob/master/drivers/gpio/gpio-mmio.c#L473
        # we are using a configuration with one output one input and one direction register
        w = len(self._pads)
        self.set = ControlSignal(w)
        self.dat = StatusSignal(w)
        self.dirout = ControlSignal(w)

        self.devicetree_name = "mmio_gpio" + name_suffix
Пример #15
0
    def __init__(
            self,
            ringbuffer: RingBufferAddressStorage,
            stream_source: StreamEndpoint,
            axi_slave=None,
            fifo_depth=32, max_burst_length=16
    ):
        self.ringbuffer = ringbuffer
        self.current_buffer = ringbuffer.current_write_buffer

        assert stream_source.is_sink is False
        assert stream_source.has_last
        self.stream_source = stream_source

        self.axi_slave = axi_slave

        self.fifo_depth = fifo_depth
        self.max_burst_length = max_burst_length

        self.error = StatusSignal()
        self.state = StatusSignal(32)
        self.burst_position = StatusSignal(range(self.max_burst_length))
        self.words_written = StatusSignal(32)
        self.buffers_written = StatusSignal(32)
Пример #16
0
class TimingGenerator(Elaboratable):
    def __init__(self,
                 video_timing,
                 vertical_signals_shape=range(8000),
                 horizontal_signals_shape=range(4000)):
        self.hscan = ControlSignal(horizontal_signals_shape,
                                   reset=video_timing.hscan)
        self.vscan = ControlSignal(vertical_signals_shape,
                                   reset=video_timing.vscan)
        self.width = ControlSignal(horizontal_signals_shape,
                                   reset=video_timing.hres)
        self.height = ControlSignal(vertical_signals_shape,
                                    reset=video_timing.vres)
        self.hsync_start = ControlSignal(horizontal_signals_shape,
                                         reset=video_timing.hsync_start)
        self.hsync_end = ControlSignal(horizontal_signals_shape,
                                       reset=video_timing.hsync_end)
        self.vsync_start = ControlSignal(vertical_signals_shape,
                                         reset=video_timing.vsync_start)
        self.vsync_end = ControlSignal(vertical_signals_shape,
                                       reset=video_timing.vsync_end)

        self.x = StatusSignal(horizontal_signals_shape, name="x")
        self.y = StatusSignal(vertical_signals_shape, name="y")
        self.active = StatusSignal(name="active")
        self.hsync = StatusSignal(name="hsync")
        self.vsync = StatusSignal(name="vsync")

    def elaborate(self, plat):
        m = Module()

        # set the xy coordinates
        with m.If(self.x < self.hscan - 1):
            m.d.sync += self.x.eq(self.x + 1)
        with m.Else():
            m.d.sync += self.x.eq(0)
            with m.If(self.y < self.vscan - 1):
                m.d.sync += self.y.eq(self.y + 1)
            with m.Else():
                m.d.sync += self.y.eq(0)

        m.d.comb += [
            self.active.eq((self.x < self.width) & (self.y < self.height)),
            self.hsync.eq((self.x >= self.hsync_start)
                          & (self.x < self.hsync_end)),
            self.vsync.eq((self.y >= self.vsync_start)
                          & (self.y < self.vsync_end))
        ]

        return m
Пример #17
0
class PluginModuleStreamerRx(Elaboratable):
    def __init__(self, plugin):
        """
        This module needs to run in the word clock domain of the bus.
        """
        self.plugin = plugin
        self.output = StreamEndpoint(32, is_sink=False, has_last=False)

        self.ready = StatusSignal()

    def elaborate(self, platform):
        m = Module()

        m.domains += ClockDomain("wclk_in")
        m.d.comb += ClockSignal("wclk_in").eq(self.plugin.clk_word)

        pll = m.submodules.pll = Pll(50e6, 4, 1, "wclk_in")
        pll.output_domain("ddr_domain", 1)

        m.submodules.eclk_ddr = EClkSync("ddr_domain", "ddr_domain_eclk")
        m.submodules.clk_div_half = ClkDiv("ddr_domain_eclk",
                                           "ddr_domain_x1_1",
                                           "word_x2",
                                           div=2)
        m.submodules.clk_div_quater = ClkDiv("ddr_domain_eclk",
                                             "ddr_domain_x1_2",
                                             "sync",
                                             div=4)

        lanes = []
        for i in range(4):
            lane = m.submodules["lane{}".format(i)] = LaneAligner(
                i=self.plugin["lvds{}".format(i)],
                in_testpattern_mode=~self.output.valid,
                ddr_domain="ddr_domain_eclk",
                word_x2_domain="word_x2",
            )
            lanes.append(lane)

        m.d.sync += self.output.valid.eq(self.plugin.valid)
        m.d.sync += self.output.payload.eq(
            Cat(*[lane.output for lane in lanes]))
        m.d.comb += self.ready.eq(self.output.ready & (
            reduce(lambda a, b: a & b,
                   [lane.word_aligned & lane.bit_aligned for lane in lanes])))

        return m
Пример #18
0
    def __init__(self,
                 i,
                 in_testpattern_mode,
                 ddr_domain,
                 word_x2_domain,
                 testpattern=0b00000110):
        """
        Does bit and lane alignment of one lane usig a given testpattern if in_testpattern_mode is high
        """
        self.i = i
        self.in_testpattern_mode = in_testpattern_mode
        self.testpattern = testpattern
        self.word_x2_domain = word_x2_domain
        self.ddr_domain = ddr_domain

        self.output = Signal(8)
        self.bit_aligned = StatusSignal()
        self.word_aligned = StatusSignal()

        self.bitslips = StatusSignal(32)
        self.delay = StatusSignal(5)
        self.error = StatusSignal()
Пример #19
0
    def __init__(self,
                 input,
                 depth,
                 r_domain,
                 w_domain,
                 buffered=True,
                 exact_depth=False):
        assert input.is_sink is False
        self.input = input
        self.output = StreamEndpoint.like(input, name="stream_fifo_output")

        self.r_domain = r_domain
        self.w_domain = w_domain
        self.depth = depth
        self.exact_depth = exact_depth
        self.buffered = buffered

        self.overflow_cnt = StatusSignal(32)
        self.underrun_cnt = StatusSignal(32)
        self.r_level = StatusSignal(range(depth + 1))
        self.w_level = StatusSignal(range(depth + 1))
Пример #20
0
    def __init__(
        self,
        ringbuffer: RingBufferAddressStorage,
        max_line_width=5000,
        address_width=32,
        data_width=64,
    ):
        self.next_frame = Signal()
        self.line_words_total = ControlSignal(32, reset=2304 // 4)
        self.line_words_read = StatusSignal(32)

        self.ringbuffer = ringbuffer
        self.address_width = address_width
        self.data_width = data_width
        self.max_line_width = max_line_width

        self.output = StreamEndpoint(address_width,
                                     is_sink=False,
                                     has_last=False)
Пример #21
0
    def __init__(self, input_freq, vco_mul, vco_div, input_domain="sync"):
        Pll.is_valid_vco_conf(input_freq, vco_mul, vco_div, exception=True)
        self.vco_freq = input_freq * vco_mul / vco_div

        self.locked = StatusSignal()

        m = self.m = Module()
        clkop = Signal()
        clkfb = Signal()
        m.submodules.clkbufa = Instance("CLKFBBUFA", i_A=clkop, o_Z=clkfb)

        self.output_port_names = ["CLKOS", "CLKOS2", "CLKOS3"]

        self.params = {
            "CLKI_DIV": vco_div,

            # we use OLKOP as our feedback path
            "CLKFB_DIV": vco_mul,
            "FEEDBK_PATH": "USERCLOCK",
            "CLKOP_DIV": 1,
            **{
                "{}_ENABLE".format(output): "DISABLED"
                for output in self.output_port_names
            }
        }
        self.attributes = {
            "FREQUENCY_PIN_CLKI": str(input_freq / 1e6),
            "FREQUENCY_PIN_CLKOP": str(self.vco_freq / 1e6)
        }
        self.inputs = {
            "CLKI": ClockSignal(input_domain),
            "RST": ResetSignal(input_domain),
            "CLKFB": clkfb,
        }
        self.outputs = {
            "LOCK": self.locked,
            "CLKOP": clkop,
        }
Пример #22
0
class LaneAligner(Elaboratable):
    def __init__(self,
                 i,
                 in_testpattern_mode,
                 ddr_domain,
                 word_x2_domain,
                 testpattern=0b00000110):
        """
        Does bit and lane alignment of one lane usig a given testpattern if in_testpattern_mode is high
        """
        self.i = i
        self.in_testpattern_mode = in_testpattern_mode
        self.testpattern = testpattern
        self.word_x2_domain = word_x2_domain
        self.ddr_domain = ddr_domain

        self.output = Signal(8)
        self.bit_aligned = StatusSignal()
        self.word_aligned = StatusSignal()

        self.bitslips = StatusSignal(32)
        self.delay = StatusSignal(5)
        self.error = StatusSignal()

    def elaborate(self, platform):
        m = Module()

        delayed = Signal()
        m.submodules.delayd = Instance(
            "DELAYD",
            i_A=self.i,
            i_DEL0=self.delay[0],
            i_DEL1=self.delay[1],
            i_DEL2=self.delay[2],
            i_DEL3=self.delay[3],
            i_DEL4=self.delay[4],
            o_Z=delayed,
        )

        iserdes = m.submodules.iserdes = FakeX8ISerdes(delayed,
                                                       self.ddr_domain,
                                                       self.word_x2_domain)

        with m.If(self.in_testpattern_mode):
            with m.FSM():
                last_captured_word = Signal(8)
                with m.State("INITIAL"):
                    m.d.sync += last_captured_word.eq(self.output)
                    m.next = "ALIGN_BIT"

                with m.State("ALIGN_BIT"):
                    start_longest = Signal.like(self.delay)
                    len_longest = Signal.like(self.delay)
                    start_current = Signal.like(self.delay)

                    m.d.sync += last_captured_word.eq(self.output)

                    with m.If((self.output != last_captured_word)
                              | (self.delay == ((2**len(self.delay)) - 1))):
                        m.d.sync += start_current.eq(self.delay)
                        len_current = (self.delay - start_current)
                        with m.If(len_current > len_longest):
                            m.d.sync += len_longest.eq(len_current)
                            m.d.sync += start_longest.eq(start_current)

                    with m.If(self.delay < 2**len(self.delay)):
                        m.d.sync += self.delay.eq(self.delay + 1)
                    with m.Else():
                        m.d.sync += self.delay.eq(start_longest +
                                                  (len_longest >> 1))
                        m.d.sync += self.bit_aligned.eq(1)
                        m.next = "ALIGN_WORD"

                with m.State("ALIGN_WORD"):
                    with m.If(self.output != self.testpattern):
                        m.d.comb += iserdes.bitslip.eq(1)
                        m.next = "ALIGN_WORD"
                    with m.Else():
                        m.d.sync += self.word_aligned.eq(1)
                        m.next = "ALIGNED"

                with m.State("ALIGNED"):
                    with m.If(self.output != self.testpattern):
                        m.d.sync += self.error.eq(1)
                        # TODO: retrain if this is the case after we finished basic debugging

        return m
Пример #23
0
class SyncStreamFifo(Elaboratable):
    def __init__(self,
                 input: StreamEndpoint,
                 depth: int,
                 buffered=True,
                 fwtf=False):
        assert input.is_sink is False
        self.input = input
        self.output = StreamEndpoint.like(input, name="stream_fifo_output")
        self.depth = depth
        self.buffered = buffered
        self.fwtf = fwtf

        self.max_w_level = StatusSignal(range(depth))
        self.overflow_cnt = StatusSignal(32)
        self.underrun_cnt = StatusSignal(32)
        self.r_level = StatusSignal(range(depth + 1))
        self.w_level = StatusSignal(range(depth + 1))

    def elaborate(self, platform):
        m = Module()

        input_sink = StreamEndpoint.like(self.input,
                                         is_sink=True,
                                         name="stream_fifo_input")
        m.d.comb += input_sink.connect(self.input)
        if input_sink.has_last:
            fifo_data = Cat(input_sink.payload, input_sink.last)
        else:
            fifo_data = input_sink.payload

        if self.buffered:
            assert not self.fwtf
            fifo = m.submodules.fifo = SyncFIFOBuffered(width=len(fifo_data),
                                                        depth=self.depth)
        else:
            fifo = m.submodules.fifo = SyncFIFO(width=len(fifo_data),
                                                depth=self.depth,
                                                fwft=self.fwtf)

        m.d.comb += self.r_level.eq(fifo.r_level)
        m.d.comb += self.w_level.eq(fifo.w_level)

        with m.If(self.w_level > self.max_w_level):
            m.d.sync += self.max_w_level.eq(self.w_level)

        m.d.comb += input_sink.ready.eq(fifo.w_rdy)
        m.d.comb += fifo.w_data.eq(fifo_data)
        m.d.comb += fifo.w_en.eq(input_sink.valid)

        with m.If(input_sink.valid & (~input_sink.ready)):
            m.d.sync += self.overflow_cnt.eq(self.overflow_cnt + 1)
        with m.If(self.output.ready & (~self.output.valid)):
            m.d.sync += self.underrun_cnt.eq(self.underrun_cnt + 1)

        if self.output.has_last:
            m.d.comb += Cat(self.output.payload,
                            self.output.last).eq(fifo.r_data)
        else:
            m.d.comb += self.output.payload.eq(fifo.r_data)
        m.d.comb += self.output.valid.eq(fifo.r_rdy)
        m.d.comb += fifo.r_en.eq(self.output.ready)

        return m
Пример #24
0
    def elaborate(self, platform: ZynqSocPlatform):
        m = Module()

        # clock_setup: the serdes clockdomain has double the frequency of fclk1
        platform.ps7.fck_domain()
        pll = m.submodules.pll = RawPll(startup_wait=False,
                                        ref_jitter1=0.01,
                                        clkin1_period=8.0,
                                        clkfbout_mult=8,
                                        divclk_divide=1,
                                        clkout0_divide=16,
                                        clkout0_phase=0.0,
                                        clkout1_divide=4,
                                        clkout1_phase=0.0)
        platform.ps7.fck_domain(requested_frequency=200e6,
                                domain_name="pll_clk_in")
        m.d.comb += pll.clk.in_[1].eq(ClockSignal("pll_clk_in"))
        m.d.comb += pll.clk.fbin.eq(pll.clk.fbout)
        bufg_serdes = m.submodules.bufg_serdes = Bufg(pll.clk.out[0])
        m.domains += ClockDomain("serdes")
        m.d.comb += ClockSignal("serdes").eq(bufg_serdes.o)
        bufg_serdes_4x = m.submodules.bufg_serdes_4x = Bufg(pll.clk.out[1])
        m.domains += ClockDomain("serdes_4x")
        m.d.comb += ClockSignal("serdes_4x").eq(bufg_serdes_4x.o)

        # make the design resettable via a axi register
        reset_serdes = ControlSignal()
        for domain in ["sync", "serdes", "serdes_4x"]:
            m.d.comb += ResetSignal(domain).eq(reset_serdes)

        # loopback
        loopback = platform.request("loopback")

        ## sender side
        to_oserdes = Signal(8)

        oserdes = m.submodules.oserdes = Oserdes(data_width=8,
                                                 tristate_width=1,
                                                 data_rate_oq="ddr",
                                                 serdes_mode="master",
                                                 data_rate_tq="buf")
        m.d.comb += oserdes.oce.eq(1)
        m.d.comb += oserdes.clk.eq(ClockSignal("serdes_4x"))
        m.d.comb += oserdes.clkdiv.eq(ClockSignal("serdes"))
        m.d.comb += oserdes.rst.eq(ResetSignal("serdes"))
        m.d.comb += Cat(oserdes.d[i] for i in reversed(range(1, 9))).eq(
            to_oserdes)  # reversed is needed!!1
        m.d.comb += loopback.tx.eq(oserdes.oq)

        ## reciver side
        bufg_idelay_refclk = m.submodules.bufg_idelay_refclk = Bufg(
            pll.clk.out[1])
        m.domains += ClockDomain("idelay_refclk")
        m.d.comb += ClockSignal("idelay_refclk").eq(bufg_idelay_refclk.o)
        idelay_ctl = m.submodules.idelay_ctl = IdelayCtrl()
        m.d.comb += StatusSignal(name="idelay_crl_rdy").eq(idelay_ctl.rdy)
        m.d.comb += idelay_ctl.refclk.eq(ClockSignal("idelay_refclk"))
        m.d.comb += idelay_ctl.rst.eq(ResetSignal("idelay_refclk"))
        idelay = m.submodules.idelay = Idelay(delay_src="iDataIn",
                                              signal_pattern="data",
                                              cinvctrl_sel=False,
                                              high_performance_mode=True,
                                              refclk_frequency=200.0,
                                              pipe_sel=False,
                                              idelay_type="var_load",
                                              idelay_value=0)
        m.d.comb += idelay.c.eq(
            ClockSignal()
        )  # this is really the clock to which the control inputs are syncronous!
        m.d.comb += idelay.ld.eq(ControlSignal(name="idelay_ld"))
        m.d.comb += idelay.ldpipeen.eq(0)
        m.d.comb += idelay.ce.eq(0)
        m.d.comb += idelay.inc.eq(0)
        m.d.comb += idelay.cntvalue.in_.eq(
            ControlSignal(5, name="idelay_cntvaluein"))
        m.d.comb += StatusSignal(5, name="idelay_cntvalueout").eq(
            idelay.cntvalue.out)
        m.d.comb += idelay.idatain.eq(loopback.rx)
        idelay_out = Signal()
        m.d.comb += idelay_out.eq(idelay.data.out)

        iserdes = m.submodules.iserdes = Iserdes(
            data_width=8,
            data_rate="ddr",
            serdes_mode="master",
            interface_type="networking",
            num_ce=1,
            iobDelay="ifd",
        )
        m.d.comb += iserdes.ddly.eq(idelay_out)
        m.d.comb += iserdes.ce[1].eq(1)
        m.d.comb += iserdes.clk.eq(ClockSignal("serdes_4x"))
        m.d.comb += iserdes.clkb.eq(~ClockSignal("serdes_4x"))
        m.d.comb += iserdes.rst.eq(ResetSignal("serdes"))
        m.d.comb += iserdes.clkdiv.eq(ClockSignal("serdes"))
        from_iserdes = Signal(8)
        m.d.comb += from_iserdes.eq(Cat(iserdes.q[i] for i in range(1, 9)))

        ## check logic
        last_received = StatusSignal(8, name="last_received")

        current_state = StatusSignal(32, name="current_state")
        training_cycles = StatusSignal(32, name="training_cycles")
        slipped_bits = StatusSignal(32, name="slipped_bits")
        error_cnt = StatusSignal(32, name="error_cnt")
        success_cnt = StatusSignal(32, name="success_cnt")
        last_current_out = StatusSignal(24, name="last_current_out")
        test_pattern = ControlSignal(8, name="test_patern")

        with m.FSM(domain="serdes"):
            with m.State("TRAINING"):
                m.d.comb += current_state.eq(0)
                # start the link with correcting for the bitslip
                training_pattern = 0b00001111
                m.d.serdes += to_oserdes.eq(training_pattern)
                since_bitslip = Signal(2)
                m.d.serdes += training_cycles.eq(training_cycles + 1)
                with m.If(iserdes.bitslip == 1):
                    m.d.serdes += iserdes.bitslip.eq(0)
                    m.d.serdes += since_bitslip.eq(0)
                with m.Elif(since_bitslip < 3):
                    m.d.serdes += since_bitslip.eq(since_bitslip + 1)
                with m.Elif(from_iserdes != training_pattern):
                    m.d.serdes += iserdes.bitslip.eq(1)
                    m.d.serdes += slipped_bits.eq(slipped_bits + 1)
                with m.Else():
                    m.d.serdes += to_oserdes.eq(0x00)
                    m.next = "RUNNING"
            with m.State("RUNNING"):
                m.d.comb += current_state.eq(1)

                with m.If(test_pattern):
                    m.d.serdes += to_oserdes.eq(test_pattern)
                    with m.If(from_iserdes == test_pattern):
                        m.d.serdes += success_cnt.eq(success_cnt + 1)
                    with m.Else():
                        m.d.serdes += error_cnt.eq(error_cnt + 1)
                with m.Else():
                    m.d.serdes += to_oserdes.eq(to_oserdes + 1)
                    with m.If(from_iserdes == (last_received + 1)[0:8]):
                        m.d.serdes += success_cnt.eq(success_cnt + 1)
                    with m.Else():
                        m.d.serdes += error_cnt.eq(error_cnt + 1)

                m.d.serdes += last_received.eq(from_iserdes)
                m.d.comb += last_current_out.eq(
                    Cat(last_received, from_iserdes, to_oserdes))

        return m
Пример #25
0
class AsyncStreamFifo(Elaboratable):
    def __init__(self,
                 input,
                 depth,
                 r_domain,
                 w_domain,
                 buffered=True,
                 exact_depth=False):
        assert input.is_sink is False
        self.input = input
        self.output = StreamEndpoint.like(input, name="stream_fifo_output")

        self.r_domain = r_domain
        self.w_domain = w_domain
        self.depth = depth
        self.exact_depth = exact_depth
        self.buffered = buffered

        self.overflow_cnt = StatusSignal(32)
        self.underrun_cnt = StatusSignal(32)
        self.r_level = StatusSignal(range(depth + 1))
        self.w_level = StatusSignal(range(depth + 1))

    def elaborate(self, platform):
        m = Module()

        input_sink = StreamEndpoint.like(self.input,
                                         is_sink=True,
                                         name="stream_fifo_input")
        m.d.comb += input_sink.connect(self.input)
        if input_sink.has_last:
            fifo_data = Cat(input_sink.payload, input_sink.last)
        else:
            fifo_data = input_sink.payload

        fifo_type = AsyncFIFOBuffered if self.buffered else AsyncFIFO
        fifo = m.submodules.fifo = fifo_type(width=len(fifo_data),
                                             depth=self.depth,
                                             r_domain=self.r_domain,
                                             w_domain=self.w_domain,
                                             exact_depth=self.exact_depth)

        m.d.comb += self.r_level.eq(fifo.r_level)
        m.d.comb += self.w_level.eq(fifo.w_level)

        m.d.comb += input_sink.ready.eq(fifo.w_rdy)
        m.d.comb += fifo.w_data.eq(fifo_data)
        m.d.comb += fifo.w_en.eq(input_sink.valid)

        with m.If(input_sink.valid & (~input_sink.ready)):
            m.d[self.w_domain] += self.overflow_cnt.eq(self.overflow_cnt + 1)
        with m.If(self.output.ready & (~self.output.valid)):
            m.d[self.r_domain] += self.underrun_cnt.eq(self.underrun_cnt + 1)

        if self.output.has_last:
            m.d.comb += Cat(self.output.payload,
                            self.output.last).eq(fifo.r_data)
        else:
            m.d.comb += self.output.payload.eq(fifo.r_data)
        m.d.comb += self.output.valid.eq(fifo.r_rdy)
        m.d.comb += fifo.r_en.eq(self.output.ready)

        return m
Пример #26
0
class Pll(Elaboratable):
    vco_multipliers = list(range(2, 64))
    vco_dividers = list(range(1, 56))
    output_dividers = list(range(1, 128))

    @staticmethod
    def is_valid_vco_conf(input_freq, mul, div, exception=False):
        if not mul in Pll.vco_multipliers:
            if exception:
                raise ValueError
            return False
        if not div in Pll.vco_dividers:
            if exception:
                raise ValueError
            return False
        vco_freq = input_freq * mul / div
        if 800e6 > vco_freq:
            if exception:
                raise ValueError(vco_freq)
            return False
        if 1600e6 < vco_freq:
            if exception:
                raise ValueError(vco_freq)
            return False
        return True

    def __init__(self, input_freq, vco_mul, vco_div, input_domain="sync"):
        Pll.is_valid_vco_conf(input_freq, vco_mul, vco_div, exception=True)
        self._pll = RawPll(
            clkin1_period=1 / input_freq * 1e9,
            clkfbout_mult=vco_mul,
            divclk_divide=vco_div,
        )
        m = self.m = Module()
        m.d.comb += self._pll.clk.fbin.eq(self._pll.clk.fbout)
        m.d.comb += self._pll.clk.in_[1].eq(ClockSignal(input_domain))
        m.d.comb += self._pll.clk.insel.eq(1)  # HIGH for clkin1

        self.locked = StatusSignal()

        self._input_domain = input_domain
        self._input_freq = input_freq
        self._vco = Clock(input_freq * vco_mul / vco_div)
        self._clock_constraints = {}

    def output_domain(self, domain_name, divisor, number=None, bufg=True):
        if number is None:
            number = next(x for x in range(6)
                          if x not in self._clock_constraints.keys())
        assert number not in self._clock_constraints.keys(
        ), "port {} is already taken".format(number)

        assert divisor in Mmcm.output_dividers

        self._pll.parameters["CLKOUT{}_DIVIDE".format(number)] = divisor
        self._pll.parameters["CLKOUT{}_PHASE".format(number)] = 0.0

        m = self.m

        clock_signal = Signal(name="pll_out_{}".format(number),
                              attrs={"KEEP": "TRUE"})
        m.d.comb += clock_signal.eq(self._pll.clk.out[number])

        if bufg:
            # TODO: seems to not change anything
            bufg = m.submodules["bufg_{}".format(number)] = Bufg(clock_signal)
            output = bufg.o
        else:
            output = clock_signal

        m.domains += ClockDomain(domain_name)
        m.d.comb += ClockSignal(domain_name).eq(output)
        m.d.comb += ResetSignal(domain_name).eq(~self.locked)

        frequency = self._vco.frequency / divisor
        self._clock_constraints[number] = (clock_signal, frequency)
        return Clock(frequency)

    def elaborate(self, platform):
        m = Module()

        m.submodules.pll_block = self._pll
        m.submodules.connections = self.m

        for i, (clock_signal, frequency) in self._clock_constraints.items():
            platform.add_clock_constraint(clock_signal, frequency)

        m.d.comb += self.locked.eq(self._pll.locked)
        m.d.comb += self._pll.rst.eq(ResetSignal(self._input_domain))

        if isinstance(platform, SocPlatform):
            m.submodules.drp_bridge = DrpBridge(
                DrpInterface(self._pll.dwe, self._pll.den, self._pll.daddr,
                             self._pll.di, self._pll.do, self._pll.drdy,
                             self._pll.dclk))

        return m
Пример #27
0
class Mmcm(Elaboratable):
    vco_multipliers = list(decimal_range(2, 64, 0.125))
    vco_dividers = list(range(1, 106))
    output_0_dividers = list(decimal_range(1, 128, 0.125))
    output_dividers = list(range(1, 128))

    @staticmethod
    def is_valid_vco_conf(input_freq, mul, div, exception=False):
        if not mul in Mmcm.vco_multipliers:
            if exception:
                raise ValueError
            return False
        if not div in Mmcm.vco_dividers:
            if exception:
                raise ValueError
            return False
        vco_freq = input_freq * mul / div
        if 600e6 > vco_freq:
            if exception:
                raise ValueError
            return False
        if 1200e6 < vco_freq:
            if exception:
                raise ValueError
            return False
        return True

    def __init__(self, input_clock, vco_mul, vco_div, input_domain="sync"):
        Mmcm.is_valid_vco_conf(input_clock, vco_mul, vco_div, exception=True)
        self._mmcm = InstanceHelper("+/xilinx/cells_xtra.v", "MMCME2_ADV")(
            clkin1_period=1 / input_clock * 1e9,
            clkfbout_mult_f=vco_mul,
            divclk_divide=vco_div,
        )
        m = self.m = Module()
        m.d.comb += self._mmcm.clk.fbin.eq(self._mmcm.clk.fbout)
        m.d.comb += self._mmcm.clk.in_[1].eq(ClockSignal(input_domain))
        m.d.comb += self._mmcm.clk.ins.el.eq(1)  # HIGH for clkin1

        self.locked = StatusSignal()

        self._input_domain = input_domain
        self._input_clock = input_clock
        self._vco = Clock(input_clock * vco_mul / vco_div)
        self._clock_constraints = {}

    def output_domain(self, domain_name, divisor, number=None, bufg=True):
        if number is None:
            number = next(x for x in range(7)
                          if x not in self._clock_constraints.keys())
        assert number not in self._clock_constraints.keys(
        ), "port {} is already taken".format(number)

        assert divisor in (Mmcm.output_dividers
                           if number != 0 else Mmcm.output_0_dividers)

        divide_param = "CLKOUT{}_DIVIDE{}".format(number,
                                                  "_f" if number == 0 else "")
        self._mmcm.parameters[divide_param] = divisor
        self._mmcm.parameters["CLKOUT{}_PHASE".format(number)] = 0.0

        m = self.m

        clock_signal = Signal(name="mmcm_out_{}".format(number),
                              attrs={"KEEP": "TRUE"})
        m.d.comb += clock_signal.eq(self._mmcm.clk.out[number])

        if bufg:
            # TODO: seems to not change anything
            bufg = m.submodules["bufg_{}".format(number)] = Bufg(clock_signal)
            output = bufg.o
        else:
            output = clock_signal

        m.domains += ClockDomain(domain_name)
        m.d.comb += ClockSignal(domain_name).eq(output)
        m.d.comb += ResetSignal(domain_name).eq(~self.locked)

        frequency = self._vco.frequency / divisor
        self._clock_constraints[number] = (clock_signal, frequency)
        return Clock(frequency)

    def elaborate(self, platform):
        m = Module()

        m.submodules.mmcm_block = self._mmcm
        m.submodules.connections = self.m

        for i, (clock_signal, frequency) in self._clock_constraints.items():
            platform.add_clock_constraint(clock_signal, frequency)

        m.d.comb += self.locked.eq(self._mmcm.locked)
        m.d.comb += self._mmcm.rst.eq(ResetSignal(self._input_domain))

        if isinstance(platform, SocPlatform):
            m.submodules.drp_bridge = DrpBridge(
                DrpInterface(self._mmcm.dwe, self._mmcm.den, self._mmcm.daddr,
                             self._mmcm.di, self._mmcm.do, self._mmcm.drdy,
                             self._mmcm.dclk))

        return m
Пример #28
0
 def __init__(self):
     self.counter = StatusSignal(32)
     self.test_reg = ControlSignal(32)
Пример #29
0
 def __init__(self, buffer_size, n, base_address=0x0f80_0000):
     super().__init__()
     self.buffer_size = buffer_size
     self.buffer_base_list = Array([base_address + buffer_size * i for i in range(n)])
     self.current_write_buffer = StatusSignal(range(n))
Пример #30
0
class HispiPhy(Elaboratable):
    def __init__(self, num_lanes=4, bits=12):
        assert bits == 12

        self.hispi_clk = Signal()
        self.hispi_lanes = Signal(num_lanes)

        self.bitslip = [Signal() for _ in range(num_lanes)]
        self.out = [Signal(12) for _ in range(num_lanes)]

        self.hispi_x6_in_domain_counter = StatusSignal(32)

    def elaborate(self, platform):
        m = Module()

        m.domains += ClockDomain("hispi_x6_in")
        m.d.comb += ClockSignal("hispi_x6_in").eq(self.hispi_clk)
        m.d.hispi_x6_in += self.hispi_x6_in_domain_counter.eq(
            self.hispi_x6_in_domain_counter + 1)

        mul = 3
        pll = m.submodules.pll = Mmcm(300e6,
                                      mul,
                                      1,
                                      input_domain="hispi_x6_in")
        pll.output_domain("hispi_x6", mul * 1)
        pll.output_domain("hispi_x3", mul * 2)
        pll.output_domain("hispi_x2", mul * 3)
        pll.output_domain("hispi", mul * 6)

        for i in range(0, len(self.hispi_lanes)):
            iserdes = m.submodules["hispi_iserdes_" + str(i)] = Iserdes(
                data_width=6,
                data_rate="ddr",
                serdes_mode="master",
                interface_type="networking",
                num_ce=1,
                iobDelay="none",
            )

            m.d.comb += iserdes.d.eq(self.hispi_lanes[i])
            m.d.comb += iserdes.ce[1].eq(1)
            m.d.comb += iserdes.clk.eq(ClockSignal("hispi_x6"))
            m.d.comb += iserdes.clkb.eq(~ClockSignal("hispi_x6"))
            m.d.comb += iserdes.rst.eq(ResetSignal("hispi_x6"))
            m.d.comb += iserdes.clkdiv.eq(ClockSignal("hispi_x2"))

            real_bitslip = Signal()
            with m.If(self.bitslip[i]):
                m.d.hispi += real_bitslip.eq(~real_bitslip)

            m.d.comb += iserdes.bitslip.eq(self.bitslip[i] & real_bitslip)

            iserdes_output = Cat(iserdes.q[j] for j in reversed(range(1, 7)))
            # iserdes_output = Cat(iserdes.q[j] for j in range(1, 7))
            with m.FSM(domain="hispi_x2"):
                with m.State("lower"):
                    m.d.hispi_x2 += self.out[i][0:6].eq(iserdes_output)
                    with m.If(real_bitslip & self.bitslip[i]):
                        m.next = "lower"
                    with m.Else():
                        m.next = "upper"
                with m.State("upper"):
                    m.d.hispi_x2 += self.out[i][6:12].eq(iserdes_output)
                    with m.If(real_bitslip & self.bitslip[i]):
                        m.next = "upper"
                    with m.Else():
                        m.next = "lower"

        return m