from migen import * from artiq.gateware.rtio.phy import ttl_serdes_generic class _OSERDESE2_8X(Module): def __init__(self, invert=False): self.ser_out = Signal() self.o = Signal(8) self.t_in = Signal() self.t_out = Signal() # # # o = self.o self.specials += Instance("OSERDESE2", p_DATA_RATE_OQ="DDR", p_DATA_RATE_TQ="BUF", p_DATA_WIDTH=8, p_TRISTATE_WIDTH=1, p_INIT_OQ=0b11111111 if invert else 0b00000000, o_OQ=self.ser_out, o_TQ=self.t_out, i_RST=ResetSignal("rio_phy"), i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal("rio_phy"), i_D1=o[0] ^ invert, i_D2=o[1] ^ invert, i_D3=o[2] ^ invert, i_D4=o[3] ^ invert, i_D5=o[4] ^ invert, i_D6=o[5] ^ invert, i_D7=o[6] ^ invert, i_D8=o[7] ^ invert, i_TCE=1, i_OCE=1, i_T1=self.t_in) class _ISERDESE2_8X(Module): def __init__(self): self.ser_in = Signal() self.o = Signal(8) self.i = Signal(8) self.oe = Signal() # # # i = self.i self.specials += Instance("ISERDESE2", p_DATA_RATE="DDR", p_DATA_WIDTH=8, p_INTERFACE_TYPE="NETWORKING", p_NUM_CE=1, o_Q1=i[7], o_Q2=i[6], o_Q3=i[5], o_Q4=i[4], o_Q5=i[3], o_Q6=i[2], o_Q7=i[1], o_Q8=i[0], i_D=self.ser_in, i_CLK=ClockSignal("sys4x"), i_CLKB=~ClockSignal("sys4x"), i_CE1=1, i_RST=ResetSignal("rio_phy"), i_CLKDIV=ClockSignal("rio_phy")) class _IOSERDESE2_8X(Module): def __init__(self): self.o = Signal(8) self.i = Signal(8) self.oe = Signal() # # # iserdes = _ISERDESE2_8X() oserdes = _OSERDESE2_8X() self.submodules += iserdes, oserdes self.comb += [ self.i.eq(iserdes.i), oserdes.o.eq(self.o), oserdes.t_in.eq(~self.oe), ] self.ser_out = oserdes.ser_out self.ser_in = iserdes.ser_in self.t_out = oserdes.t_out class Output_8X(ttl_serdes_generic.Output): def __init__(self, pad, pad_n=None, invert=False, dci=False): serdes = _OSERDESE2_8X(invert) self.submodules += serdes ttl_serdes_generic.Output.__init__(self, serdes) if pad_n is None: self.comb += pad.eq(serdes.ser_out) else: self.specials += Instance("IOBUFDS", i_I=serdes.ser_out, i_T=serdes.t_out, io_IO=pad, io_IOB=pad_n) class InOut_8X(ttl_serdes_generic.InOut): def __init__(self, pad, pad_n=None, dci=False): serdes = _IOSERDESE2_8X() self.submodules += serdes ttl_serdes_generic.InOut.__init__(self, serdes) if pad_n is None: self.specials += Instance("IOBUF", i_I=serdes.ser_out, o_O=serdes.ser_in, i_T=serdes.t_out, io_IO=pad) else: if dci: self.specials += Instance("IOBUFDS_DCIEN", p_DIFF_TERM="TRUE", p_IBUF_LOW_PWR="TRUE", p_USE_IBUFDISABLE="TRUE", i_IBUFDISABLE=~serdes.t_out, i_DCITERMDISABLE=~serdes.t_out, i_I=serdes.ser_out, o_O=serdes.ser_in, i_T=serdes.t_out, io_IO=pad, io_IOB=pad_n) else: self.specials += Instance("IOBUFDS_INTERMDISABLE", p_DIFF_TERM="TRUE", p_IBUF_LOW_PWR="TRUE", p_USE_IBUFDISABLE="TRUE", i_IBUFDISABLE=~serdes.t_out, i_INTERMDISABLE=~serdes.t_out, i_I=serdes.ser_out, o_O=serdes.ser_in, i_T=serdes.t_out, io_IO=pad, io_IOB=pad_n)