cores/video: Add VideoECP5HDMI PHY and move 10to1 Serializer to Generic, share it for Spartan6/ECP5.
This commit is contained in:
parent
e5695f9934
commit
8460523f27
|
@ -674,9 +674,9 @@ class VideoDVIPHY(Module):
|
||||||
self.specials += SDROutput(i=sink.g[cshift + i], o=pads.g[i], clk=ClockSignal(clock_domain))
|
self.specials += SDROutput(i=sink.g[cshift + i], o=pads.g[i], clk=ClockSignal(clock_domain))
|
||||||
self.specials += SDROutput(i=sink.b[cshift + i], o=pads.b[i], clk=ClockSignal(clock_domain))
|
self.specials += SDROutput(i=sink.b[cshift + i], o=pads.b[i], clk=ClockSignal(clock_domain))
|
||||||
|
|
||||||
# HDMI (Xilinx Spartan6).
|
# HDMI (Generic).
|
||||||
|
|
||||||
class VideoS6HDMI10to1Serializer(Module):
|
class VideoHDMI10to1Serializer(Module):
|
||||||
def __init__(self, data_i, data_o, clock_domain):
|
def __init__(self, data_i, data_o, clock_domain):
|
||||||
# Clock Domain Crossing.
|
# Clock Domain Crossing.
|
||||||
self.submodules.cdc = stream.ClockDomainCrossing([("data", 10)], cd_from=clock_domain, cd_to=clock_domain + "5x")
|
self.submodules.cdc = stream.ClockDomainCrossing([("data", 10)], cd_from=clock_domain, cd_to=clock_domain + "5x")
|
||||||
|
@ -696,6 +696,8 @@ class VideoS6HDMI10to1Serializer(Module):
|
||||||
o = data_o,
|
o = data_o,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# HDMI (Xilinx Spartan6).
|
||||||
|
|
||||||
class VideoS6HDMIPHY(Module):
|
class VideoS6HDMIPHY(Module):
|
||||||
def __init__(self, pads, clock_domain="sys"):
|
def __init__(self, pads, clock_domain="sys"):
|
||||||
self.sink = sink = stream.Endpoint(video_data_layout)
|
self.sink = sink = stream.Endpoint(video_data_layout)
|
||||||
|
@ -722,7 +724,7 @@ class VideoS6HDMIPHY(Module):
|
||||||
|
|
||||||
# 10:1 Serialization + Differential Signaling.
|
# 10:1 Serialization + Differential Signaling.
|
||||||
pad_o = Signal()
|
pad_o = Signal()
|
||||||
serializer = VideoS6HDMI10to1Serializer(
|
serializer = VideoHDMI10to1Serializer(
|
||||||
data_i = encoder.out,
|
data_i = encoder.out,
|
||||||
data_o = pad_o,
|
data_o = pad_o,
|
||||||
clock_domain = clock_domain,
|
clock_domain = clock_domain,
|
||||||
|
@ -813,3 +815,37 @@ class VideoS7HDMIPHY(Module):
|
||||||
pad_p = getattr(pads, f"data{c2d[color]}_p")
|
pad_p = getattr(pads, f"data{c2d[color]}_p")
|
||||||
pad_n = getattr(pads, f"data{c2d[color]}_n")
|
pad_n = getattr(pads, f"data{c2d[color]}_n")
|
||||||
self.specials += Instance("OBUFDS", i_I=pad_o, o_O=pad_p, o_OB=pad_n)
|
self.specials += Instance("OBUFDS", i_I=pad_o, o_O=pad_p, o_OB=pad_n)
|
||||||
|
|
||||||
|
|
||||||
|
# HDMI (Lattice ECP5).
|
||||||
|
|
||||||
|
class VideoECP5HDMIPHY(Module):
|
||||||
|
def __init__(self, pads, clock_domain="sys"):
|
||||||
|
self.sink = sink = stream.Endpoint(video_data_layout)
|
||||||
|
|
||||||
|
# # #
|
||||||
|
|
||||||
|
# Always ack Sink, no backpressure.
|
||||||
|
self.comb += sink.ready.eq(1)
|
||||||
|
|
||||||
|
# Clocking + Pseudo Differential Signaling.
|
||||||
|
self.specials += DDROutput(i1=1, i2=0, o=pads.clk_p, clk=ClockSignal(clock_domain))
|
||||||
|
|
||||||
|
# Encode/Serialize Datas.
|
||||||
|
for color in ["r", "g", "b"]:
|
||||||
|
|
||||||
|
# TMDS Encoding.
|
||||||
|
encoder = ClockDomainsRenamer(clock_domain)(TMDSEncoder())
|
||||||
|
setattr(self.submodules, f"{color}_encoder", encoder)
|
||||||
|
self.comb += encoder.d.eq(getattr(sink, color))
|
||||||
|
self.comb += encoder.c.eq(Cat(sink.hsync, sink.vsync) if color == "r" else 0)
|
||||||
|
self.comb += encoder.de.eq(sink.de)
|
||||||
|
|
||||||
|
# 10:1 Serialization + Pseudo Differential Signaling.
|
||||||
|
c2d = {"r": 0, "g": 1, "b": 2}
|
||||||
|
serializer = VideoHDMI10to1Serializer(
|
||||||
|
data_i = encoder.out,
|
||||||
|
data_o = getattr(pads, f"data{c2d[color]}_p"),
|
||||||
|
clock_domain = clock_domain,
|
||||||
|
)
|
||||||
|
setattr(self.submodules, f"{color}_serializer", serializer)
|
||||||
|
|
Loading…
Reference in New Issue