Ejemplo n.º 1
0
    def __init__(self, platform, *args, **kwargs):
        BaseSoC.__init__(self, platform, *args, **kwargs)

        # # #

        pix_freq = 148.50e6

        # hdmi in
        hdmi_in0_pads = platform.request("hdmi_in")
        self.submodules.hdmi_in0_freq = FrequencyMeter(period=self.clk_freq)
        self.submodules.hdmi_in0 = HDMIIn(
            hdmi_in0_pads,
            self.sdram.crossbar.get_port(mode="write"),
            fifo_depth=512,
            device="xc7")
        self.comb += self.hdmi_in0_freq.clk.eq(
            self.hdmi_in0.clocking.cd_pix.clk)
        self.platform.add_period_constraint(self.hdmi_in0.clocking.cd_pix.clk,
                                            period_ns(1 * pix_freq))
        self.platform.add_period_constraint(
            self.hdmi_in0.clocking.cd_pix1p25x.clk, period_ns(1.25 * pix_freq))
        self.platform.add_period_constraint(
            self.hdmi_in0.clocking.cd_pix5x.clk, period_ns(5 * pix_freq))

        self.platform.add_false_path_constraints(
            self.crg.cd_sys.clk, self.hdmi_in0.clocking.cd_pix.clk,
            self.hdmi_in0.clocking.cd_pix1p25x.clk,
            self.hdmi_in0.clocking.cd_pix5x.clk)

        # hdmi out
        hdmi_out0_dram_port = self.sdram.crossbar.get_port(mode="read",
                                                           dw=16,
                                                           cd="hdmi_out0_pix",
                                                           reverse=True)
        self.submodules.hdmi_out0 = VideoOut(platform.device,
                                             platform.request("hdmi_out"),
                                             hdmi_out0_dram_port,
                                             "ycbcr422",
                                             fifo_depth=4096)

        self.platform.add_period_constraint(
            self.hdmi_out0.driver.clocking.cd_pix.clk, period_ns(1 * pix_freq))
        self.platform.add_period_constraint(
            self.hdmi_out0.driver.clocking.cd_pix5x.clk,
            period_ns(5 * pix_freq))

        self.platform.add_false_path_constraints(
            self.crg.cd_sys.clk, self.hdmi_out0.driver.clocking.cd_pix.clk,
            self.hdmi_out0.driver.clocking.cd_pix5x.clk)

        # hdmi over
        self.comb += [
            platform.request("hdmi_sda_over_up").eq(0),
            platform.request("hdmi_sda_over_dn").eq(0),
            platform.request("hdmi_hdp_over").eq(0),
        ]
Ejemplo n.º 2
0
    def __init__(self, **kwargs):
        from litescope import LiteScopeAnalyzer
        HelloETH.__init__(self, **kwargs)
        p = self.platform
        self.submodules.blink_rx = ClockDomainsRenamer("eth_rx")(
            LedBlinker(125e6))
        self.submodules.blink_tx = ClockDomainsRenamer("eth_tx")(
            LedBlinker(125e6))
        self.submodules.f_tx = FrequencyMeter(int(100e6))
        self.comb += [
            p.request("user_led").eq(self.blink_rx.out),
            p.request("user_led").eq(self.blink_tx.out),
            self.f_tx.clk.eq(ClockSignal("eth_tx"))
        ]

        debug = [
            p.lookup_request("eth").tx_en,
            p.lookup_request("eth").tx_er,
            p.lookup_request("eth").tx_data,
            p.lookup_request("eth").mdc,

            # MAC interface
            self.core.mac.core.sink.valid,
            self.core.mac.core.sink.last,
            self.core.mac.core.sink.ready,
            self.core.mac.core.sink.data,
            self.core.mac.core.source.valid,
            self.core.mac.core.source.last,
            self.core.mac.core.source.ready,
            self.core.mac.core.source.data,

            # ICMP interface
            self.core.icmp.echo.sink.valid,
            self.core.icmp.echo.sink.last,
            self.core.icmp.echo.sink.ready,
            self.core.icmp.echo.sink.data,
            self.core.icmp.echo.source.valid,
            self.core.icmp.echo.source.last,
            self.core.icmp.echo.source.ready,
            self.core.icmp.echo.source.data,

            # IP interface
            self.core.ip.crossbar.master.sink.valid,
            self.core.ip.crossbar.master.sink.last,
            self.core.ip.crossbar.master.sink.ready,
            self.core.ip.crossbar.master.sink.data,
            self.core.ip.crossbar.master.sink.ip_address,
            self.core.ip.crossbar.master.sink.protocol
        ]
        self.submodules.analyzer = LiteScopeAnalyzer(debug, 4096)
Ejemplo n.º 3
0
    def __init__(self, platform, *args, **kwargs):
        BaseSoC.__init__(self, platform, *args, **kwargs)

        mode = "ycbcr422"
        if mode == "ycbcr422":
            dw = 16
        elif mode == "rgb":
            dw = 32
        else:
            raise SystemError("Unknown pixel mode.")

        pix_freq = 148.50e6

        # hdmi in 0
        hdmi_in0_pads = platform.request("hdmi_in")

        self.submodules.hdmi_in0 = HDMIIn(
            hdmi_in0_pads,
            self.sdram.crossbar.get_port(mode="write"),
            fifo_depth=512,
            device="xc7")

        self.submodules.hdmi_in0_freq = FrequencyMeter(period=self.clk_freq)

        self.comb += [
            self.hdmi_in0_freq.clk.eq(self.hdmi_in0.clocking.cd_pix.clk),
            hdmi_in0_pads.txen.eq(1)
        ]
        self.platform.add_period_constraint(self.hdmi_in0.clocking.cd_pix.clk,
                                            period_ns(1 * pix_freq))
        self.platform.add_period_constraint(
            self.hdmi_in0.clocking.cd_pix1p25x.clk, period_ns(1.25 * pix_freq))
        self.platform.add_period_constraint(
            self.hdmi_in0.clocking.cd_pix5x.clk, period_ns(5 * pix_freq))

        self.platform.add_false_path_constraints(
            self.crg.cd_sys.clk, self.hdmi_in0.clocking.cd_pix.clk,
            self.hdmi_in0.clocking.cd_pix1p25x.clk,
            self.hdmi_in0.clocking.cd_pix5x.clk)

        # hdmi out 0
        hdmi_out0_pads = platform.request("hdmi_out")

        hdmi_out0_dram_port = self.sdram.crossbar.get_port(mode="read",
                                                           dw=dw,
                                                           cd="hdmi_out0_pix",
                                                           reverse=True)

        self.submodules.hdmi_out0 = VideoOut(platform.device,
                                             hdmi_out0_pads,
                                             hdmi_out0_dram_port,
                                             mode=mode,
                                             fifo_depth=4096)

        self.platform.add_false_path_constraints(
            self.crg.cd_sys.clk, self.hdmi_out0.driver.clocking.cd_pix.clk)

        self.platform.add_period_constraint(
            self.hdmi_out0.driver.clocking.cd_pix.clk, period_ns(1 * pix_freq))
        self.platform.add_period_constraint(
            self.hdmi_out0.driver.clocking.cd_pix5x.clk,
            period_ns(5 * pix_freq))

        self.platform.add_false_path_constraints(
            self.crg.cd_sys.clk, self.hdmi_out0.driver.clocking.cd_pix.clk,
            self.hdmi_out0.driver.clocking.cd_pix5x.clk)

        for name, value in sorted(self.platform.hdmi_infos.items()):
            self.add_constant(name, value)
Ejemplo n.º 4
0
    def __init__(self, platform, *args, **kwargs):
        BaseSoC.__init__(self, platform, *args, **kwargs)

        # # #

        pix_freq = 148.50e6

        ########## hdmi in 0 (raw tmds)
        hdmi_in0_pads = platform.request("hdmi_in", 0)
        self.submodules.hdmi_in0_freq = FrequencyMeter(period=self.clk_freq)
        self.submodules.hdmi_in0 = HDMIIn(hdmi_in0_pads, device="xc7", split_mmcm=True, hdmi=True)
        self.comb += self.hdmi_in0_freq.clk.eq(self.hdmi_in0.clocking.cd_pix.clk)
        # don't add clock timings here, we add a root clock constraint that derives the rest automatically

        # define path constraints individually to sysclk to avoid accidentally declaring other inter-clock paths as false paths
        self.platform.add_false_path_constraints(
            self.crg.cd_sys.clk,
            self.hdmi_in0.clocking.cd_pix.clk
        )
        self.platform.add_false_path_constraints(
            self.crg.cd_sys.clk,
            self.hdmi_in0.clocking.cd_pix1p25x.clk
        )
        self.platform.add_false_path_constraints(
            self.crg.cd_sys.clk,
            self.hdmi_in0.clocking.cd_pix5x.clk
        )
        self.platform.add_false_path_constraints(
            self.crg.cd_sys.clk,
            self.hdmi_in0.clocking.cd_pix_o.clk
        )
        self.platform.add_false_path_constraints(
            self.crg.cd_sys.clk,
            self.hdmi_in0.clocking.cd_pix5x_o.clk
        )

        hdmi_out0_pads = platform.request("hdmi_out", 0)
        self.submodules.hdmi_out0_clk_gen = S7HDMIOutEncoderSerializer(hdmi_out0_pads.clk_p, hdmi_out0_pads.clk_n, bypass_encoder=True)
        self.comb += self.hdmi_out0_clk_gen.data.eq(Signal(10, reset=0b0000011111))
        self.submodules.hdmi_out0_phy = S7HDMIOutPHY(hdmi_out0_pads, mode="raw")

        # hdmi over
        self.comb += [
            platform.request("hdmi_sda_over_up").eq(0),
            platform.request("hdmi_sda_over_dn").eq(0),
        ]

        platform.add_platform_command(
            "set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets hdmi_in_ibufds/ob]")

        # extract timing info from HDMI input 0, and put it into a stream that we can pass later on as a genlock object
        self.hdmi_in0_timing = hdmi_in0_timing = stream.Endpoint(frame_timing_layout)
        self.sync.pix_o += [
            hdmi_in0_timing.de.eq(self.hdmi_in0.syncpol.de),
            hdmi_in0_timing.hsync.eq(self.hdmi_in0.syncpol.hsync),
            hdmi_in0_timing.vsync.eq(self.hdmi_in0.syncpol.vsync),
            If(self.hdmi_in0.syncpol.valid_o,
                hdmi_in0_timing.valid.eq(1),
            ).Else(
                hdmi_in0_timing.valid.eq(0),
            )
        ]

        ########## hdmi in 1
        hdmi_in1_pads = platform.request("hdmi_in", 1)
        self.submodules.hdmi_in1_freq = FrequencyMeter(period=self.clk_freq)
        self.submodules.hdmi_in1 = HDMIIn(hdmi_in1_pads,
                                         self.sdram.crossbar.get_port(mode="write"),
                                         fifo_depth=1024,
                                         device="xc7",
                                         split_mmcm=False,
                                         mode="rgb"
                                          )
        self.comb += self.hdmi_in1_freq.clk.eq(self.hdmi_in1.clocking.cd_pix.clk)

        self.platform.add_false_path_constraints(
            self.crg.cd_sys.clk,
            self.hdmi_in1.clocking.cd_pix.clk
        )
        self.platform.add_false_path_constraints(
            self.crg.cd_sys.clk,
            self.hdmi_in1.clocking.cd_pix1p25x.clk
        )
        self.platform.add_false_path_constraints(
            self.crg.cd_sys.clk,
            self.hdmi_in1.clocking.cd_pix5x.clk
        )

        ######## Constraints
        # instantiate fundamental clocks -- Vivado will derive the rest via PLL programmings
        self.platform.add_platform_command(
            "create_clock -name clk50 -period 20.0 [get_nets clk50]")
        self.platform.add_platform_command(
            "create_clock -name hdmi_in0_clk_p -period 6.734006734006734 [get_nets hdmi_in0_clk_p]")
        self.platform.add_platform_command(
            "create_clock -name hdmi_in1_clk_p -period 6.734006734006734 [get_nets hdmi_in1_clk_p]")

        # exclude all generated clocks from the fundamental HDMI cloks and sys clocks
        self.platform.add_platform_command("set_clock_groups -group [get_clocks -include_generated_clocks -of [get_nets sys_clk]] -group [get_clocks -include_generated_clocks -of [get_nets hdmi_in0_clk_p]] -asynchronous")
        self.platform.add_platform_command("set_clock_groups -group [get_clocks -include_generated_clocks -of [get_nets sys_clk]] -group [get_clocks -include_generated_clocks -of [get_nets hdmi_in1_clk_p]] -asynchronous")

        # make sure derived clocks get named correctly
        self.platform.add_platform_command("create_clock_generated_clock -name hdmi_in0_pix_clk [get_pins MMCME2_ADV/CLKOUT0]")
        self.platform.add_platform_command("create_clock_generated_clock -name hdmi_in0_pix1p25x_clk [get_pins MMCME2_ADV/CLKOUT1]")
        self.platform.add_platform_command("create_clock_generated_clock -name hdmi_in0_pix5x_clk [get_pins MMCME2_ADV/CLKOUT2]")
        self.platform.add_platform_command("create_clock_generated_clock -name pix_o_clk [get_pins PLLE2_ADV/CLKOUT0]")
        self.platform.add_platform_command("create_clock_generated_clock -name pix5x_o_clk [get_pins PLLE2_ADV/CLKOUT2]")

        self.platform.add_platform_command("create_clock_generated_clock -name hdmi_in1_pix_clk [get_pins MMCME2_ADV_1/CLKOUT0]")
        self.platform.add_platform_command("create_clock_generated_clock -name hdmi_in1_pix1p25x_clk [get_pins MMCME2_ADV_1/CLKOUT1]")
        self.platform.add_platform_command("create_clock_generated_clock -name hdmi_in1_pix5x_clk [get_pins MMCME2_ADV_1/CLKOUT2]")

        # don't time the high-fanout reset paths
        self.platform.add_platform_command("set_false_path -through [get_nets hdmi_in1_pix_rst]")
        self.platform.add_platform_command("set_false_path -through [get_nets hdmi_in0_pix_rst]")
        self.platform.add_platform_command("set_false_path -through [get_nets hdmi_in1_pix1p25x_rst]")
        self.platform.add_platform_command("set_false_path -through [get_nets hdmi_in0_pix1p25x_rst]")
        self.platform.add_platform_command("set_false_path -through [get_nets pix_o_rst]")
        self.platform.add_platform_command("set_false_path -through [get_nets videooverlaysoc_hdmi_out0_clk_gen_ce]") # derived from reset

        # gearbox timing is a multi-cycle path: FAST to SLOW synchronous clock domains
        self.platform.add_platform_command("set_multicycle_path 2 -setup -start -from [get_clocks videooverlaysoc_hdmi_in0_mmcm_clk1] -to [get_clocks videooverlaysoc_hdmi_in0_mmcm_clk0]")
        self.platform.add_platform_command("set_multicycle_path 1 -hold -from [get_clocks videooverlaysoc_hdmi_in0_mmcm_clk1] -to [get_clocks videooverlaysoc_hdmi_in0_mmcm_clk0]")
        self.platform.add_platform_command("set_multicycle_path 2 -setup -start -from [get_clocks videooverlaysoc_hdmi_in1_mmcm_clk1] -to [get_clocks videooverlaysoc_hdmi_in1_mmcm_clk0]")
        self.platform.add_platform_command("set_multicycle_path 1 -hold -from [get_clocks videooverlaysoc_hdmi_in1_mmcm_clk1] -to [get_clocks videooverlaysoc_hdmi_in1_mmcm_clk0]")


        ###############  hdmi out 1 (overlay rgb)

        out_dram_port = self.sdram.crossbar.get_port(mode="read", cd="pix_o", dw=32, reverse=True)
        self.submodules.hdmi_core_out0 = VideoOutCore(out_dram_port, mode="rgb", fifo_depth=1024, genlock_stream=hdmi_in0_timing)

        core_source_valid_d = Signal()
        core_source_data_d = Signal(32)
        sync_cd = getattr(self.sync, out_dram_port.cd)
        sync_cd += [
            core_source_valid_d.eq(self.hdmi_core_out0.source.valid),
            core_source_data_d.eq(self.hdmi_core_out0.source.data),
        ]

        timing_rgb_delay = TimingDelayRGB(4) # create the delay element with specified delay...note if you say TimingDelay() the code runs happily with no error, because Python doesn't typecheck
        timing_rgb_delay = ClockDomainsRenamer("pix_o")(timing_rgb_delay) # assign a clock domain to the delay element
        self.submodules += timing_rgb_delay  # DONT FORGET THIS LINE OR ELSE NOTHING HAPPENS....
        self.hdmi_out0_rgb = hdmi_out0_rgb = stream.Endpoint(rgb_layout) # instantiate the input record
        self.hdmi_out0_rgb_d = hdmi_out0_rgb_d = stream.Endpoint(rgb_layout) # instantiate the output record
        self.comb += [
            self.hdmi_core_out0.source.ready.eq(1), # don't forget to tell the upstream component that we're ready, or we get a monochrome screen...
            hdmi_out0_rgb.b.eq(core_source_data_d[0:8]),  # wire up the specific elements of the input record
            hdmi_out0_rgb.g.eq(core_source_data_d[8:16]),
            hdmi_out0_rgb.r.eq(core_source_data_d[16:24]),
            hdmi_out0_rgb.valid.eq(core_source_valid_d),  # not used, but hook it up anyways in case we need it later...
            timing_rgb_delay.sink.eq(hdmi_out0_rgb), # assign input stream to the delay element
            hdmi_out0_rgb_d.eq(timing_rgb_delay.source) # grab output stream from the delay element
            # the output records are directly consumed down below
        ]

        self.submodules.encoder_red = encoder_red = ClockDomainsRenamer("pix_o")(Encoder())
        self.submodules.encoder_grn = encoder_grn = ClockDomainsRenamer("pix_o")(Encoder())
        self.submodules.encoder_blu = encoder_blu = ClockDomainsRenamer("pix_o")(Encoder())

        self.comb += [

            encoder_red.d.eq(hdmi_out0_rgb.r),
            encoder_red.de.eq(1),
            encoder_red.c.eq(0), # we promise to use this only during video areas, so "c" is always 0

            encoder_grn.d.eq(hdmi_out0_rgb.g),
            encoder_grn.de.eq(1),
            encoder_grn.c.eq(0),

            encoder_blu.d.eq(hdmi_out0_rgb.b),
            encoder_blu.de.eq(1),
            encoder_blu.c.eq(0),
        ]

        # hdmi in to hdmi out
        c0_pix_o = Signal(10)
        c1_pix_o = Signal(10)
        c2_pix_o = Signal(10)
        self.sync.pix_o += [  # extra delay to absorb cross-domain jitter & routing
            c0_pix_o.eq(self.hdmi_in0.syncpol.c0),
            c1_pix_o.eq(self.hdmi_in0.syncpol.c1),
            c2_pix_o.eq(self.hdmi_in0.syncpol.c2)
        ]

        rect_on = Signal()

        self.submodules.rectangle = rectangle = ClockDomainsRenamer("pix_o")( RectOpening(hdmi_in0_timing) )
        self.comb += rect_on.eq(rectangle.rect_on)

        self.sync.pix_o += [
            If(rect_on & (hdmi_out0_rgb_d.r >= 128) & (hdmi_out0_rgb_d.g >= 128) & (hdmi_out0_rgb_d.b >= 128),
#            If(rect_on,
                    self.hdmi_out0_phy.sink.c0.eq(encoder_blu.out),
                    self.hdmi_out0_phy.sink.c1.eq(encoder_grn.out),
                    self.hdmi_out0_phy.sink.c2.eq(encoder_red.out),
            ).Else(
                    self.hdmi_out0_phy.sink.c0.eq(c0_pix_o),
                    self.hdmi_out0_phy.sink.c1.eq(c1_pix_o),
                    self.hdmi_out0_phy.sink.c2.eq(c2_pix_o),
            )
        ]

        # analyzer
        from litex.soc.cores.uart import UARTWishboneBridge
        from litescope import LiteScopeAnalyzer

        #            platform.request("serial",1), self.clk_freq, baudrate=3000000)
        self.submodules.bridge = UARTWishboneBridge(
            platform.request("serial",1), self.clk_freq, baudrate=115200)
        self.add_wb_master(self.bridge.wishbone)

        analyzer_signals = [
            hdmi_in0_timing,
            self.hdmi_in0.syncpol.hsync,
            self.hdmi_in0.syncpol.vsync,
            self.hdmi_in0.syncpol.de,
            self.hdmi_in0.chansync.data_in0.de,
#            self.hdmi_in0.decode_terc4.de_o,
            self.hdmi_in0.chansync.data_out0,
            self.hdmi_in0.data0_decod.output,
        ]
        self.submodules.analyzer = LiteScopeAnalyzer(analyzer_signals, 256, cd="hdmi_in0_pix", cd_ratio=2)
Ejemplo n.º 5
0
    def __init__(self, platform, *args, **kwargs):
        BaseSoC.__init__(self, platform, *args, **kwargs)

        # # #

        pix_freq = 148.50e6

        ########## hdmi in 0 (raw tmds)
        hdmi_in0_pads = platform.request("hdmi_in", 0)
        self.submodules.hdmi_in0_freq = FrequencyMeter(period=self.clk_freq)
        self.submodules.hdmi_in0 = hdmi_in0 = HDMIIn(hdmi_in0_pads,
                                                     device="xc7",
                                                     split_mmcm=True,
                                                     hdmi=True)
        self.comb += self.hdmi_in0_freq.clk.eq(
            self.hdmi_in0.clocking.cd_pix.clk)
        # don't add clock timings here, we add a root clock constraint that derives the rest automatically

        # define path constraints individually to sysclk to avoid accidentally declaring other inter-clock paths as false paths
        self.platform.add_false_path_constraints(
            self.crg.cd_sys.clk, self.hdmi_in0.clocking.cd_pix.clk)
        self.platform.add_false_path_constraints(
            self.crg.cd_sys.clk, self.hdmi_in0.clocking.cd_pix1p25x.clk)
        self.platform.add_false_path_constraints(
            self.crg.cd_sys.clk, self.hdmi_in0.clocking.cd_pix5x.clk)
        self.platform.add_false_path_constraints(
            self.crg.cd_sys.clk, self.hdmi_in0.clocking.cd_pix_o.clk)
        self.platform.add_false_path_constraints(
            self.crg.cd_sys.clk, self.hdmi_in0.clocking.cd_pix5x_o.clk)

        hdmi_out0_pads = platform.request("hdmi_out", 0)
        self.submodules.hdmi_out0_clk_gen = S7HDMIOutEncoderSerializer(
            hdmi_out0_pads.clk_p, hdmi_out0_pads.clk_n, bypass_encoder=True)
        self.comb += self.hdmi_out0_clk_gen.data.eq(
            Signal(10, reset=0b0000011111))
        self.submodules.hdmi_out0_phy = S7HDMIOutPHY(hdmi_out0_pads,
                                                     mode="raw")

        # hdmi over
        self.comb += [
            platform.request("hdmi_sda_over_up").eq(0),
            platform.request("hdmi_sda_over_dn").eq(0),
        ]

        platform.add_platform_command(
            "set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets hdmi_in_ibufds/ob]"
        )

        # extract timing info from HDMI input 0, and put it into a stream that we can pass later on as a genlock object
        self.hdmi_in0_timing = hdmi_in0_timing = stream.Endpoint(
            frame_timing_layout)
        self.sync.pix_o += [
            hdmi_in0_timing.de.eq(self.hdmi_in0.syncpol.de),
            hdmi_in0_timing.hsync.eq(self.hdmi_in0.syncpol.hsync),
            hdmi_in0_timing.vsync.eq(self.hdmi_in0.syncpol.vsync),
            If(
                self.hdmi_in0.syncpol.valid_o,
                hdmi_in0_timing.valid.eq(1),
            ).Else(hdmi_in0_timing.valid.eq(0), )
        ]
        early_line_end = Signal()
        self.comb += early_line_end.eq(hdmi_in0_timing.de
                                       & ~self.hdmi_in0.syncpol.de)

        ########## hdmi in 1
        hdmi_in1_pads = platform.request("hdmi_in", 1)
        self.submodules.hdmi_in1_freq = FrequencyMeter(period=self.clk_freq)
        self.submodules.hdmi_in1 = HDMIIn(
            hdmi_in1_pads,
            self.sdram.crossbar.get_port(mode="write"),
            fifo_depth=1024,
            device="xc7",
            split_mmcm=False,
            mode="rgb",
            hdmi=True)
        self.comb += self.hdmi_in1_freq.clk.eq(
            self.hdmi_in1.clocking.cd_pix.clk)

        self.platform.add_false_path_constraints(
            self.crg.cd_sys.clk, self.hdmi_in1.clocking.cd_pix.clk)
        self.platform.add_false_path_constraints(
            self.crg.cd_sys.clk, self.hdmi_in1.clocking.cd_pix1p25x.clk)
        self.platform.add_false_path_constraints(
            self.crg.cd_sys.clk, self.hdmi_in1.clocking.cd_pix5x.clk)

        ######## Constraints
        # instantiate fundamental clocks -- Vivado will derive the rest via PLL programmings
        self.platform.add_platform_command(
            "create_clock -name clk50 -period 20.0 [get_nets clk50]")
        self.platform.add_platform_command(
            "create_clock -name hdmi_in0_clk_p -period 6.734006734006734 [get_nets hdmi_in0_clk_p]"
        )
        self.platform.add_platform_command(
            "create_clock -name hdmi_in1_clk_p -period 6.734006734006734 [get_nets hdmi_in1_clk_p]"
        )

        # exclude all generated clocks from the fundamental HDMI cloks and sys clocks
        self.platform.add_platform_command(
            "set_clock_groups -group [get_clocks -include_generated_clocks -of [get_nets sys_clk]] -group [get_clocks -include_generated_clocks -of [get_nets hdmi_in0_clk_p]] -asynchronous"
        )
        self.platform.add_platform_command(
            "set_clock_groups -group [get_clocks -include_generated_clocks -of [get_nets sys_clk]] -group [get_clocks -include_generated_clocks -of [get_nets hdmi_in1_clk_p]] -asynchronous"
        )

        # make sure derived clocks get named correctly; I think this is now being done right without these args
        # self.platform.add_platform_command("create_generated_clock -name hdmi_in0_pix_clk [get_pins MMCME2_ADV/CLKOUT0]")
        # self.platform.add_platform_command("create_generated_clock -name hdmi_in0_pix1p25x_clk [get_pins MMCME2_ADV/CLKOUT1]")
        # self.platform.add_platform_command("create_generated_clock -name hdmi_in0_pix5x_clk [get_pins MMCME2_ADV/CLKOUT2]")
        # self.platform.add_platform_command("create_generated_clock -name pix_o_clk [get_pins PLLE2_ADV/CLKOUT0]")
        # self.platform.add_platform_command("create_generated_clock -name pix5x_o_clk [get_pins PLLE2_ADV/CLKOUT2]")
        #
        # self.platform.add_platform_command("create_generated_clock -name hdmi_in1_pix_clk [get_pins MMCME2_ADV_1/CLKOUT0]")
        # self.platform.add_platform_command("create_generated_clock -name hdmi_in1_pix1p25x_clk [get_pins MMCME2_ADV_1/CLKOUT1]")
        # self.platform.add_platform_command("create_generated_clock -name hdmi_in1_pix5x_clk [get_pins MMCME2_ADV_1/CLKOUT2]")

        # don't time the high-fanout reset paths
        self.platform.add_platform_command(
            "set_false_path -through [get_nets hdmi_in1_pix_rst]")
        self.platform.add_platform_command(
            "set_false_path -through [get_nets hdmi_in0_pix_rst]")
        self.platform.add_platform_command(
            "set_false_path -through [get_nets hdmi_in1_pix1p25x_rst]")
        self.platform.add_platform_command(
            "set_false_path -through [get_nets hdmi_in0_pix1p25x_rst]")
        self.platform.add_platform_command(
            "set_false_path -through [get_nets pix_o_rst]")
        self.platform.add_platform_command(
            "set_false_path -through [get_nets soc_videooverlaysoc_hdmi_out0_clk_gen_ce]"
        )  # derived from reset

        # gearbox timing is a multi-cycle path: FAST to SLOW synchronous clock domains
        self.platform.add_platform_command(
            "set_multicycle_path 2 -setup -start -from [get_clocks soc_videooverlaysoc_hdmi_in0_mmcm_clk1] -to [get_clocks soc_videooverlaysoc_hdmi_in0_mmcm_clk0]"
        )
        self.platform.add_platform_command(
            "set_multicycle_path 1 -hold -from [get_clocks soc_videooverlaysoc_hdmi_in0_mmcm_clk1] -to [get_clocks soc_videooverlaysoc_hdmi_in0_mmcm_clk0]"
        )
        self.platform.add_platform_command(
            "set_multicycle_path 2 -setup -start -from [get_clocks soc_videooverlaysoc_hdmi_in1_mmcm_clk1] -to [get_clocks soc_videooverlaysoc_hdmi_in1_mmcm_clk0]"
        )
        self.platform.add_platform_command(
            "set_multicycle_path 1 -hold -from [get_clocks soc_videooverlaysoc_hdmi_in1_mmcm_clk1] -to [get_clocks soc_videooverlaysoc_hdmi_in1_mmcm_clk0]"
        )

        ###############  hdmi out 1 (overlay rgb)

        out_dram_port = self.sdram.crossbar.get_port(mode="read",
                                                     cd="pix_o",
                                                     dw=32,
                                                     reverse=True)
        self.submodules.hdmi_core_out0 = VideoOutCore(
            out_dram_port,
            mode="rgb",
            fifo_depth=1024,
            genlock_stream=hdmi_in0_timing)

        core_source_valid_d = Signal()
        core_source_data_d = Signal(32)
        sync_cd = getattr(self.sync, out_dram_port.cd)
        sync_cd += [
            core_source_valid_d.eq(self.hdmi_core_out0.source.valid),
            core_source_data_d.eq(self.hdmi_core_out0.source.data),
        ]

        ####### timing stream extraction
        timing_rgb_delay = TimingDelayRGB(
            4
        )  # create the delay element with specified delay...note if you say TimingDelay() the code runs happily with no error, because Python doesn't typecheck
        timing_rgb_delay = ClockDomainsRenamer("pix_o")(
            timing_rgb_delay)  # assign a clock domain to the delay element
        self.submodules += timing_rgb_delay  # DONT FORGET THIS LINE OR ELSE NOTHING HAPPENS....
        self.hdmi_out0_rgb = hdmi_out0_rgb = stream.Endpoint(
            rgb_layout)  # instantiate the input record
        self.hdmi_out0_rgb_d = hdmi_out0_rgb_d = stream.Endpoint(
            rgb_layout)  # instantiate the output record
        self.comb += [
            self.hdmi_core_out0.source.ready.eq(
                1
            ),  # don't forget to tell the upstream component that we're ready, or we get a monochrome screen...
            hdmi_out0_rgb.b.eq(
                core_source_data_d[0:8]
            ),  # wire up the specific elements of the input record
            hdmi_out0_rgb.g.eq(core_source_data_d[8:16]),
            hdmi_out0_rgb.r.eq(core_source_data_d[16:24]),
            hdmi_out0_rgb.valid.eq(
                core_source_valid_d
            ),  # not used, but hook it up anyways in case we need it later...
            timing_rgb_delay.sink.eq(
                hdmi_out0_rgb),  # assign input stream to the delay element
            hdmi_out0_rgb_d.eq(timing_rgb_delay.source
                               )  # grab output stream from the delay element
            # the output records are directly consumed down below
        ]

        ##### HDCP engine
        platform.add_source(os.path.join("overlay", "i2c_snoop.v"))
        platform.add_source(os.path.join("overlay", "diff_network.v"))
        platform.add_source(os.path.join("overlay", "hdcp_block.v"))
        platform.add_source(os.path.join("overlay", "hdcp_cipher.v"))
        platform.add_source(os.path.join("overlay", "hdcp_lfsr.v"))
        platform.add_source(os.path.join("overlay", "shuffle_network.v"))
        platform.add_source(os.path.join("overlay", "hdcp_mod.v"))

        self.submodules.i2c_snoop = i2c_snoop = I2Csnoop(hdmi_in0_pads)
        self.submodules.hdcp = hdcp = HDCP(hdmi_in0_timing)
        self.comb += hdcp.line_end.eq(
            early_line_end
        )  # wire up an early line-end signal to meet rekey timing
        Aksv14 = Signal()
        Aksv14_r = Signal()
        self.specials += MultiReg(i2c_snoop.Aksv14_write,
                                  Aksv14,
                                  odomain="pix_o")
        self.sync.pix_o += [
            Aksv14_r.eq(Aksv14),
            hdcp.Aksv14_write.eq(
                Aksv14 & ~Aksv14_r),  # should be a rising-edge strobe only
            #            hdcp.hpd.eq(hdmi_in0.edid._hpd_notif.status),
            hdcp.hdcp_ena.eq(hdmi_in0.decode_terc4.encrypting_video
                             | hdmi_in0.decode_terc4.encrypting_data),
            hdcp.hpd.eq(hdmi_in0_pads.hpd_notif),
            hdcp.An.eq(i2c_snoop.An),
            hdcp.ctl_code.eq(hdmi_in0.decode_terc4.ctl_code),
        ]
        self.comb += platform.request("hpd_en").eq(hdcp.hpd_ena.storage)

        ###### overlay pixel encoders
        self.submodules.encoder_red = encoder_red = ClockDomainsRenamer(
            "pix_o")(Encoder())
        self.submodules.encoder_grn = encoder_grn = ClockDomainsRenamer(
            "pix_o")(Encoder())
        self.submodules.encoder_blu = encoder_blu = ClockDomainsRenamer(
            "pix_o")(Encoder())

        self.comb += [
            If(
                hdcp.Km_valid.
                storage,  # this is a proxy for HDCP being initialized
                encoder_red.d.eq(hdmi_out0_rgb.r
                                 ^ hdcp.cipher_stream[16:]),  # 23:16
                encoder_grn.d.eq(hdmi_out0_rgb.g
                                 ^ hdcp.cipher_stream[8:16]),  # 15:8
                encoder_blu.d.eq(
                    (hdmi_out0_rgb.b ^ hdcp.cipher_stream[0:8])),  # 7:0
                #               encoder_red.d.eq(hdcp.cipher_stream[16:]), # 23:16
                #               encoder_grn.d.eq(hdcp.cipher_stream[8:16]),  # 15:8
                #               encoder_blu.d.eq(hdcp.cipher_stream[0:8]),  # 7:0
            ).Else(
                encoder_red.d.eq(hdmi_out0_rgb.r),
                encoder_grn.d.eq(hdmi_out0_rgb.g),
                encoder_blu.d.eq(hdmi_out0_rgb.b),
            ),
            encoder_red.de.eq(1),
            encoder_red.c.eq(
                0
            ),  # we promise to use this only during video areas, so "c" is always 0
            encoder_grn.de.eq(1),
            encoder_grn.c.eq(0),
            encoder_blu.de.eq(1),
            encoder_blu.c.eq(0),
        ]

        # hdmi in to hdmi out
        c0_pix_o = Signal(10)
        c1_pix_o = Signal(10)
        c2_pix_o = Signal(10)
        c0 = Signal(10)
        c1 = Signal(10)
        c2 = Signal(10)
        self.comb += [
            c0.eq(self.hdmi_in0.syncpol.c0),
            c1.eq(self.hdmi_in0.syncpol.c1),
            c2.eq(self.hdmi_in0.syncpol.c2),
        ]
        for i in range(
                6
        ):  # either 5 or 6; 5 if the first pixel is encrypted by the idle cipher; 6 if the cipher has to be pumped before encryption
            c0_next = Signal(10)
            c1_next = Signal(10)
            c2_next = Signal(10)
            self.sync.pix_o += [  # extra delay to absorb cross-domain jitter & routing
                c0_next.eq(c0),
                c1_next.eq(c1),
                c2_next.eq(c2),
            ]
            c0 = c0_next
            c1 = c1_next
            c2 = c2_next

        self.sync.pix_o += [  # extra delay to absorb cross-domain jitter & routing
            c0_pix_o.eq(c0_next),
            c1_pix_o.eq(c1_next),
            c2_pix_o.eq(c2_next)
        ]

        rect_on = Signal()
        rect_thresh = Signal(8)

        self.submodules.rectangle = rectangle = ClockDomainsRenamer("pix_o")(
            RectOpening(hdmi_in0_timing))
        self.comb += rect_on.eq(rectangle.rect_on)
        self.comb += rect_thresh.eq(rectangle.rect_thresh.storage)

        self.sync.pix_o += [
            #            If(rect_on & (hdmi_out0_rgb_d.r >= 128) & (hdmi_out0_rgb_d.g >= 128) & (hdmi_out0_rgb_d.b >= 128),
            If(
                rect_on & (hdmi_out0_rgb_d.r >= rect_thresh) &
                (hdmi_out0_rgb_d.g >= rect_thresh) &
                (hdmi_out0_rgb_d.b >= rect_thresh),
                #            If(rect_on,
                self.hdmi_out0_phy.sink.c0.eq(encoder_blu.out),
                self.hdmi_out0_phy.sink.c1.eq(encoder_grn.out),
                self.hdmi_out0_phy.sink.c2.eq(encoder_red.out),
            ).Else(
                self.hdmi_out0_phy.sink.c0.eq(c0_pix_o),
                self.hdmi_out0_phy.sink.c1.eq(c1_pix_o),
                self.hdmi_out0_phy.sink.c2.eq(c2_pix_o),
            )
        ]

        self.comb += platform.request("fpga_led2", 0).eq(
            self.hdmi_in0.clocking.locked)  # RX0 green
        self.comb += platform.request("fpga_led3", 0).eq(0)  # RX0 red
        #        self.comb += platform.request("fpga_led4", 0).eq(0)  # OV0 red
        self.comb += platform.request("fpga_led5", 0).eq(
            self.hdmi_in1.clocking.locked)  # OV0 green

        # analyzer ethernet
        from liteeth.phy.rmii import LiteEthPHYRMII
        from liteeth.core import LiteEthUDPIPCore
        from liteeth.frontend.etherbone import LiteEthEtherbone

        fast_eth = False  # fast_eth puts etherbone in 100MHz domain; otherwise try to put it in 50MHz domain.
        # 100 MHz domain works but timing closure is hard
        # 50 MHz domain should also work but I'm not 100% of the syntax to create the clock domains correctly
        if fast_eth:
            self.submodules.phy = phy = LiteEthPHYRMII(
                platform.request("rmii_eth_clocks"),
                platform.request("rmii_eth"))
            mac_address = 0x1337320dbabe
            ip_address = "10.0.11.2"
            self.submodules.core = LiteEthUDPIPCore(self.phy, mac_address,
                                                    convert_ip(ip_address),
                                                    int(100e6))
            self.submodules.etherbone = LiteEthEtherbone(self.core.udp,
                                                         1234,
                                                         mode="master")
            self.add_wb_master(self.etherbone.wishbone.bus)
        else:
            phy = LiteEthPHYRMII(platform.request("rmii_eth_clocks"),
                                 platform.request("rmii_eth"))
            phy = ClockDomainsRenamer("eth")(phy)
            mac_address = 0x1337320dbabe
            ip_address = "10.0.11.2"
            core = LiteEthUDPIPCore(phy,
                                    mac_address,
                                    convert_ip(ip_address),
                                    int(50e6),
                                    with_icmp=True)
            core = ClockDomainsRenamer("eth")(core)
            self.submodules += phy, core

            etherbone_cd = ClockDomain("etherbone")
            self.clock_domains += etherbone_cd
            self.comb += [
                etherbone_cd.clk.eq(ClockSignal("sys")),
                etherbone_cd.rst.eq(ResetSignal("sys"))
            ]
            self.submodules.etherbone = LiteEthEtherbone(core.udp,
                                                         1234,
                                                         mode="master",
                                                         cd="etherbone")
            self.add_wb_master(self.etherbone.wishbone.bus)

        # Attach the VexRiscv debug bus to RAM
        self.register_mem("vexriscv_debug", self.mem_map["vexriscv_debug"],
                          self.cpu_or_bridge.debug_bus, 0x10)

        self.platform.add_false_path_constraints(self.crg.cd_sys.clk,
                                                 self.crg.cd_eth.clk)

        self.sync += platform.request("fpga_led4", 0).eq(0)  # OV0 red
Ejemplo n.º 6
0
    def __init__(self,
                 platform,
                 with_sdram=True,
                 with_ethernet=False,
                 with_etherbone=True,
                 with_sdcard=True,
                 with_pcie=False,
                 with_hdmi_in0=False,
                 with_hdmi_out0=False,
                 with_hdmi_in1=False,
                 with_hdmi_out1=False,
                 with_interboard_communication=False):
        assert not (with_pcie and with_interboard_communication)
        sys_clk_freq = int(100e6)
        sd_freq = int(100e6)
        SoCSDRAM.__init__(
            self,
            platform,
            sys_clk_freq,
            #cpu_type="vexriscv", l2_size=32,
            cpu_type=None,
            l2_size=32,
            #csr_data_width=8, csr_address_width=14,
            csr_data_width=32,
            csr_address_width=14,
            integrated_rom_size=0x8000,
            integrated_sram_size=0x4000,
            integrated_main_ram_size=0x8000 if not with_sdram else 0,
            ident="NeTV2 LiteX Test SoC",
            ident_version=True,
            reserve_nmi_interrupt=False)

        # crg
        self.submodules.crg = CRG(platform, sys_clk_freq)

        # dnax
        self.submodules.dna = dna.DNA()

        # xadc
        self.submodules.xadc = xadc.XADC()

        # icap
        self.submodules.icap = ICAP(platform)

        # flash
        self.submodules.flash = Flash(platform.request("flash"),
                                      div=math.ceil(sys_clk_freq / 25e6))

        # sdram
        if with_sdram:
            self.submodules.ddrphy = a7ddrphy.A7DDRPHY(
                platform.request("ddram"),
                sys_clk_freq=sys_clk_freq,
                iodelay_clk_freq=200e6)
            sdram_module = MT41J128M16(sys_clk_freq, "1:4")
            self.register_sdram(self.ddrphy,
                                sdram_module.geom_settings,
                                sdram_module.timing_settings,
                                controller_settings=ControllerSettings(
                                    with_bandwidth=True,
                                    cmd_buffer_depth=8,
                                    with_refresh=True))
        # ethernet
        if with_ethernet:
            self.submodules.ethphy = LiteEthPHYRMII(
                self.platform.request("eth_clocks"),
                self.platform.request("eth"))
            self.submodules.ethmac = LiteEthMAC(phy=self.ethphy,
                                                dw=32,
                                                interface="wishbone")
            self.add_wb_slave(mem_decoder(self.mem_map["ethmac"]),
                              self.ethmac.bus)
            self.add_memory_region("ethmac",
                                   self.mem_map["ethmac"] | self.shadow_base,
                                   0x2000)

            self.crg.cd_eth.clk.attr.add("keep")
            self.platform.add_false_path_constraints(self.crg.cd_sys.clk,
                                                     self.crg.cd_eth.clk)

        # etherbone
        if with_etherbone:
            self.submodules.ethphy = LiteEthPHYRMII(
                self.platform.request("eth_clocks"),
                self.platform.request("eth"))
            self.submodules.ethcore = LiteEthUDPIPCore(
                self.ethphy, 0x10e2d5000000, convert_ip("192.168.1.50"),
                sys_clk_freq)
            self.add_cpu(
                LiteEthEtherbone(self.ethcore.udp, 1234, mode="master"))
            self.add_wb_master(self.cpu.wishbone.bus)
            #self.submodules.etherbone = LiteEthEtherbone(self.ethcore.udp, 1234, mode="master")
            #self.add_wb_master(self.etherbone.wishbone.bus)

            self.crg.cd_eth.clk.attr.add("keep")
            self.platform.add_false_path_constraints(self.crg.cd_sys.clk,
                                                     self.crg.cd_eth.clk)

        # sdcard
        self.submodules.sdclk = SDClockerS7()
        self.submodules.sdphy = SDPHY(platform.request("sdcard"),
                                      platform.device)
        self.submodules.sdcore = SDCore(self.sdphy)
        self.submodules.sdtimer = Timer()

        self.submodules.bist_generator = BISTBlockGenerator(random=True)
        self.submodules.bist_checker = BISTBlockChecker(random=True)

        self.comb += [
            self.sdcore.source.connect(self.bist_checker.sink),
            self.bist_generator.source.connect(self.sdcore.sink)
        ]

        self.platform.add_period_constraint(self.crg.cd_sys.clk,
                                            1e9 / sys_clk_freq)
        self.platform.add_period_constraint(self.sdclk.cd_sd.clk,
                                            1e9 / sd_freq)
        self.platform.add_period_constraint(self.sdclk.cd_sd_fb.clk,
                                            1e9 / sd_freq)

        self.crg.cd_sys.clk.attr.add("keep")
        self.sdclk.cd_sd.clk.attr.add("keep")
        self.sdclk.cd_sd_fb.clk.attr.add("keep")
        self.platform.add_false_path_constraints(self.crg.cd_sys.clk,
                                                 self.sdclk.cd_sd.clk,
                                                 self.sdclk.cd_sd_fb.clk)

        # pcie
        if with_pcie:
            # pcie phy
            self.submodules.pcie_phy = S7PCIEPHY(platform,
                                                 platform.request("pcie_x2"))
            platform.add_false_path_constraints(self.crg.cd_sys.clk,
                                                self.pcie_phy.cd_pcie.clk)

            # pcie endpoint
            self.submodules.pcie_endpoint = LitePCIeEndpoint(
                self.pcie_phy, with_reordering=True)

            # pcie wishbone bridge
            self.submodules.pcie_bridge = LitePCIeWishboneBridge(
                self.pcie_endpoint, lambda a: 1, shadow_base=0x80000000)
            self.add_wb_master(self.pcie_bridge.wishbone)

            # pcie dma
            self.submodules.pcie_dma0 = LitePCIeDMA(self.pcie_phy,
                                                    self.pcie_endpoint,
                                                    with_loopback=True)

            # pcie msi
            self.submodules.pcie_msi = LitePCIeMSI()
            self.comb += self.pcie_msi.source.connect(self.pcie_phy.msi)
            self.interrupts = {
                "PCIE_DMA0_WRITER": self.pcie_dma0.writer.irq,
                "PCIE_DMA0_READER": self.pcie_dma0.reader.irq
            }
            for i, (k, v) in enumerate(sorted(self.interrupts.items())):
                self.comb += self.pcie_msi.irqs[i].eq(v)
                self.add_constant(k + "_INTERRUPT", i)

        # interboard communication
        if with_interboard_communication:
            self.clock_domains.cd_refclk = ClockDomain()
            self.submodules.refclk_pll = refclk_pll = S7PLL()
            refclk_pll.register_clkin(platform.lookup_request("clk50"), 50e6)
            refclk_pll.create_clkout(self.cd_refclk, 125e6)

            platform.add_platform_command(
                "set_property SEVERITY {{Warning}} [get_drc_checks REQP-49]")

            # qpll
            qpll = GTPQuadPLL(ClockSignal("refclk"), 125e6, 1.25e9)
            print(qpll)
            self.submodules += qpll

            # gtp
            gtp = GTP(qpll,
                      platform.request("interboard_comm_tx"),
                      platform.request("interboard_comm_rx"),
                      sys_clk_freq,
                      clock_aligner=True,
                      internal_loopback=False)
            self.submodules += gtp

            counter = Signal(32)
            self.sync.tx += counter.eq(counter + 1)

            # send counter to other-board
            self.comb += [
                gtp.encoder.k[0].eq(1), gtp.encoder.d[0].eq((5 << 5) | 28),
                gtp.encoder.k[1].eq(0), gtp.encoder.d[1].eq(counter[26:])
            ]

            # receive counter and display it on leds
            self.comb += [
                platform.request("user_led", 3).eq(gtp.rx_ready),
                platform.request("user_led", 4).eq(gtp.decoders[1].d[0]),
                platform.request("user_led", 5).eq(gtp.decoders[1].d[1])
            ]

            gtp.cd_tx.clk.attr.add("keep")
            gtp.cd_rx.clk.attr.add("keep")
            platform.add_period_constraint(gtp.cd_tx.clk,
                                           1e9 / gtp.tx_clk_freq)
            platform.add_period_constraint(gtp.cd_rx.clk,
                                           1e9 / gtp.tx_clk_freq)
            self.platform.add_false_path_constraints(self.crg.cd_sys.clk,
                                                     gtp.cd_tx.clk,
                                                     gtp.cd_rx.clk)

        # hdmi in 0
        if with_hdmi_in0:
            hdmi_in0_pads = platform.request("hdmi_in", 0)
            self.submodules.hdmi_in0_freq = FrequencyMeter(period=sys_clk_freq)
            self.submodules.hdmi_in0 = HDMIIn(
                hdmi_in0_pads,
                self.sdram.crossbar.get_port(mode="write"),
                fifo_depth=512,
                device="xc7",
                split_mmcm=True)
            self.comb += self.hdmi_in0_freq.clk.eq(
                self.hdmi_in0.clocking.cd_pix.clk),
            for clk in [
                    self.hdmi_in0.clocking.cd_pix.clk,
                    self.hdmi_in0.clocking.cd_pix1p25x.clk,
                    self.hdmi_in0.clocking.cd_pix5x.clk
            ]:
                self.platform.add_false_path_constraints(
                    self.crg.cd_sys.clk, clk)
            self.platform.add_period_constraint(
                platform.lookup_request("hdmi_in", 0).clk_p,
                period_ns(148.5e6))

        # hdmi out 0
        if with_hdmi_out0:
            hdmi_out0_dram_port = self.sdram.crossbar.get_port(
                mode="read", dw=16, cd="hdmi_out0_pix", reverse=True)
            self.submodules.hdmi_out0 = VideoOut(platform.device,
                                                 platform.request(
                                                     "hdmi_out", 0),
                                                 hdmi_out0_dram_port,
                                                 "ycbcr422",
                                                 fifo_depth=4096)
            for clk in [
                    self.hdmi_out0.driver.clocking.cd_pix.clk,
                    self.hdmi_out0.driver.clocking.cd_pix5x.clk
            ]:
                self.platform.add_false_path_constraints(
                    self.crg.cd_sys.clk, clk)

        # hdmi in 1
        if with_hdmi_in1:
            hdmi_in1_pads = platform.request("hdmi_in", 1)
            self.submodules.hdmi_in1_freq = FrequencyMeter(period=sys_clk_freq)
            self.submodules.hdmi_in1 = HDMIIn(
                hdmi_in1_pads,
                self.sdram.crossbar.get_port(mode="write"),
                fifo_depth=512,
                device="xc7",
                split_mmcm=True)
            self.comb += self.hdmi_in1_freq.clk.eq(
                self.hdmi_in1.clocking.cd_pix.clk),
            for clk in [
                    self.hdmi_in1.clocking.cd_pix.clk,
                    self.hdmi_in1.clocking.cd_pix1p25x.clk,
                    self.hdmi_in1.clocking.cd_pix5x.clk
            ]:
                self.platform.add_false_path_constraints(
                    self.crg.cd_sys.clk, clk)
            self.platform.add_period_constraint(
                platform.lookup_request("hdmi_in", 1).clk_p,
                period_ns(148.5e6))

        # hdmi out 1
        if with_hdmi_out1:
            hdmi_out1_dram_port = self.sdram.crossbar.get_port(
                mode="read", dw=16, cd="hdmi_out1_pix", reverse=True)
            self.submodules.hdmi_out1 = VideoOut(platform.device,
                                                 platform.request(
                                                     "hdmi_out", 1),
                                                 hdmi_out1_dram_port,
                                                 "ycbcr422",
                                                 fifo_depth=4096)
            for clk in [
                    self.hdmi_out1.driver.clocking.cd_pix.clk,
                    self.hdmi_out1.driver.clocking.cd_pix5x.clk
            ]:
                self.platform.add_false_path_constraints(
                    self.crg.cd_sys.clk, clk)

        # led blinking (sys)
        sys_counter = Signal(32)
        self.sync.sys += sys_counter.eq(sys_counter + 1)
        self.comb += platform.request("user_led", 0).eq(sys_counter[26])

        # led blinking (pcie)
        if with_pcie:
            pcie_counter = Signal(32)
            self.sync.pcie += pcie_counter.eq(pcie_counter + 1)
            self.comb += platform.request("user_led", 1).eq(pcie_counter[26])

        # led blinking (sdcard)
        if with_sdcard:
            sd_counter = Signal(32)
            self.sync.sd += sd_counter.eq(sd_counter + 1)
            self.comb += platform.request("user_led", 1).eq(sd_counter[26])