Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

dvisampler: use hard differential phase detector

  • Loading branch information...
commit ffe4bff396f74e50317e526ca9459c5ea4c19053 1 parent 8bc1620
@sbourdeauducq sbourdeauducq authored
View
23 milkymist/dvisampler/__init__.py
@@ -18,27 +18,10 @@ def __init__(self, pads, asmiport, n_dma_slots=2):
for datan in range(3):
name = "data" + str(datan)
- invert = False
- if hasattr(pads, name + "_p"):
- s = Signal()
- self.specials += Instance("IBUFDS",
- Instance.Input("I", getattr(pads, name + "_p")),
- Instance.Input("IB", getattr(pads, name + "_n")),
- Instance.Output("O", s)
- )
- else:
- try:
- s = getattr(pads, name)
- except AttributeError:
- s = getattr(pads, name + "_n")
- invert = True
- cap = DataCapture(8, invert)
+ cap = DataCapture(getattr(pads, name + "_p"), getattr(pads, name + "_n"), 8)
setattr(self.submodules, name + "_cap", cap)
- self.comb += [
- cap.pad.eq(s),
- cap.serdesstrobe.eq(self.clocking.serdesstrobe)
- ]
+ self.comb += cap.serdesstrobe.eq(self.clocking.serdesstrobe)
charsync = CharSync()
setattr(self.submodules, name + "_charsync", charsync)
@@ -64,8 +47,6 @@ def __init__(self, pads, asmiport, n_dma_slots=2):
self.chansync.data_in2.eq(self.data2_decod.output),
]
- ###
-
self.submodules.syncpol = SyncPolarity()
self.comb += [
self.syncpol.valid_i.eq(self.chansync.chan_synced),
View
79 milkymist/dvisampler/clocking.py
@@ -12,77 +12,46 @@ def __init__(self, pads):
self.clock_domains._cd_pix = ClockDomain()
self.clock_domains._cd_pix5x = ClockDomain()
self.clock_domains._cd_pix10x = ClockDomain(reset_less=True)
- self.clock_domains._cd_pix20x = ClockDomain(reset_less=True)
###
- if hasattr(pads, "clk_p"):
- clkin = Signal()
- self.specials += Instance("IBUFDS",
- Instance.Input("I", pads.clk_p),
- Instance.Input("IB", pads.clk_n),
- Instance.Output("O", clkin)
- )
- else:
- clkin = pads.clk
+ clk_se = Signal()
+ self.specials += Instance("IBUFDS", i_I=pads.clk_p, i_IB=pads.clk_n, o_O=clk_se)
clkfbout = Signal()
pll_locked = Signal()
pll_clk0 = Signal()
pll_clk1 = Signal()
pll_clk2 = Signal()
- pll_clk3 = Signal()
self.specials += Instance("PLL_BASE",
- Instance.Parameter("CLKIN_PERIOD", 26.7),
- Instance.Parameter("CLKFBOUT_MULT", 20),
- Instance.Parameter("CLKOUT0_DIVIDE", 1), # pix20x
- Instance.Parameter("CLKOUT1_DIVIDE", 4), # pix5x
- Instance.Parameter("CLKOUT2_DIVIDE", 20), # pix
- Instance.Parameter("CLKOUT3_DIVIDE", 2), # pix10x
- Instance.Parameter("COMPENSATION", "INTERNAL"),
-
- Instance.Output("CLKFBOUT", clkfbout),
- # WARNING: Do not touch the order of those clocks, or PAR fails.
- Instance.Output("CLKOUT0", pll_clk0),
- Instance.Output("CLKOUT1", pll_clk1),
- Instance.Output("CLKOUT2", pll_clk2),
- Instance.Output("CLKOUT3", pll_clk3),
- Instance.Output("LOCKED", pll_locked),
- Instance.Input("CLKFBIN", clkfbout),
- Instance.Input("CLKIN", clkin),
- Instance.Input("RST", self._r_pll_reset.storage)
- )
+ p_CLKIN_PERIOD=26.7,
+ p_CLKFBOUT_MULT=20,
+ p_CLKOUT0_DIVIDE=2, # pix10x
+ p_CLKOUT1_DIVIDE=4, # pix5x
+ p_CLKOUT2_DIVIDE=20, # pix
+ p_COMPENSATION="INTERNAL",
+
+ i_CLKIN=clk_se,
+ o_CLKOUT0=pll_clk0, o_CLKOUT1=pll_clk1, o_CLKOUT2=pll_clk2,
+ o_CLKFBOUT=clkfbout, i_CLKFBIN=clkfbout,
+ o_LOCKED=pll_locked, i_RST=self._r_pll_reset.storage)
locked_async = Signal()
- self.specials += Instance("BUFPLL",
- Instance.Parameter("DIVIDE", 4),
- Instance.Input("PLLIN", pll_clk0),
- Instance.Input("GCLK", ClockSignal("pix5x")),
- Instance.Input("LOCKED", pll_locked),
- Instance.Output("IOCLK", self._cd_pix20x.clk),
- Instance.Output("LOCK", locked_async),
- Instance.Output("SERDESSTROBE", self.serdesstrobe)
- )
- self.specials += Instance("BUFG",
- Instance.Input("I", pll_clk1), Instance.Output("O", self._cd_pix5x.clk))
- self.specials += Instance("BUFG",
- Instance.Input("I", pll_clk2), Instance.Output("O", self._cd_pix.clk))
- self.specials += Instance("BUFG",
- Instance.Input("I", pll_clk3), Instance.Output("O", self._cd_pix10x.clk))
- self.specials += MultiReg(locked_async, self.locked, "sys")
+ self.specials += [
+ Instance("BUFPLL", p_DIVIDE=2,
+ i_PLLIN=pll_clk0, i_GCLK=ClockSignal("pix5x"), i_LOCKED=pll_locked,
+ o_IOCLK=self._cd_pix10x.clk, o_LOCK=locked_async, o_SERDESSTROBE=self.serdesstrobe),
+ Instance("BUFG", i_I=pll_clk1, o_O=self._cd_pix5x.clk),
+ Instance("BUFG", i_I=pll_clk2, o_O=self._cd_pix.clk),
+ MultiReg(locked_async, self.locked, "sys")
+ ]
self.comb += self._r_locked.status.eq(self.locked)
# sychronize pix+pix5x reset
pix_rst_n = 1
for i in range(2):
new_pix_rst_n = Signal()
- self.specials += Instance("FDCE",
- Instance.Input("D", pix_rst_n),
- Instance.Input("CE", 1),
- Instance.Input("C", ClockSignal("pix")),
- Instance.Input("CLR", ~locked_async),
- Instance.Output("Q", new_pix_rst_n)
- )
+ self.specials += Instance("FDCE", i_D=pix_rst_n, i_CE=1, i_C=ClockSignal("pix"),
+ i_CLR=~locked_async, o_Q=new_pix_rst_n)
pix_rst_n = new_pix_rst_n
- self.comb += self._cd_pix.rst.eq(~pix_rst_n)
- self.comb += self._cd_pix5x.rst.eq(~pix_rst_n)
+ self.comb += self._cd_pix.rst.eq(~pix_rst_n), self._cd_pix5x.rst.eq(~pix_rst_n)
View
210 milkymist/dvisampler/datacapture.py
@@ -3,66 +3,88 @@
from migen.bank.description import *
class DataCapture(Module, AutoCSR):
- def __init__(self, ntbits, invert):
- self.pad = Signal()
+ def __init__(self, pad_p, pad_n, ntbits):
self.serdesstrobe = Signal()
self.d = Signal(10)
- self._r_dly_ctl = CSR(4)
- self._r_dly_busy = CSRStatus()
+ self._r_dly_ctl = CSR(6)
+ self._r_dly_busy = CSRStatus(2)
self._r_phase = CSRStatus(2)
self._r_phase_reset = CSR()
###
# IO
- pad_delayed = Signal()
+ pad_se = Signal()
+ self.specials += Instance("IBUFDS", i_I=pad_p, i_IB=pad_n, o_O=pad_se)
+
+ pad_delayed_master = Signal()
+ pad_delayed_slave = Signal()
delay_inc = Signal()
delay_ce = Signal()
- delay_cal = Signal()
- delay_rst = Signal()
- delay_busy = Signal()
+ delay_master_cal = Signal()
+ delay_master_rst = Signal()
+ delay_master_busy = Signal()
+ delay_slave_cal = Signal()
+ delay_slave_rst = Signal()
+ delay_slave_busy = Signal()
+ self.specials += Instance("IODELAY2",
+ p_SERDES_MODE="MASTER",
+ p_DELAY_SRC="IDATAIN", p_IDELAY_TYPE="DIFF_PHASE_DETECTOR",
+ p_COUNTER_WRAPAROUND="STAY_AT_LIMIT", p_DATA_RATE="SDR",
+
+ i_IDATAIN=pad_se, o_DATAOUT=pad_delayed_master,
+ i_CLK=ClockSignal("pix5x"), i_IOCLK0=ClockSignal("pix10x"),
+
+ i_INC=delay_inc, i_CE=delay_ce,
+ i_CAL=delay_master_cal, i_RST=delay_master_rst, o_BUSY=delay_master_busy,
+ i_T=1)
self.specials += Instance("IODELAY2",
- Instance.Parameter("DELAY_SRC", "IDATAIN"),
- Instance.Parameter("IDELAY_TYPE", "VARIABLE_FROM_HALF_MAX"),
- Instance.Parameter("COUNTER_WRAPAROUND", "STAY_AT_LIMIT"),
- Instance.Parameter("DATA_RATE", "SDR"),
- Instance.Input("IDATAIN", self.pad),
- Instance.Output("DATAOUT", pad_delayed),
- Instance.Input("CLK", ClockSignal("pix5x")),
- Instance.Input("IOCLK0", ClockSignal("pix10x")),
- Instance.Input("INC", delay_inc),
- Instance.Input("CE", delay_ce),
- Instance.Input("CAL", delay_cal),
- Instance.Input("RST", delay_rst),
- Instance.Output("BUSY", delay_busy),
- Instance.Input("T", 1)
- )
+ p_SERDES_MODE="SLAVE",
+ p_DELAY_SRC="IDATAIN", p_IDELAY_TYPE="DIFF_PHASE_DETECTOR",
+ p_COUNTER_WRAPAROUND="STAY_AT_LIMIT", p_DATA_RATE="SDR",
+
+ i_IDATAIN=pad_se, o_DATAOUT=pad_delayed_slave,
+ i_CLK=ClockSignal("pix5x"), i_IOCLK0=ClockSignal("pix10x"),
+
+ i_INC=delay_inc, i_CE=delay_ce,
+ i_CAL=delay_slave_cal, i_RST=delay_slave_rst, o_BUSY=delay_slave_busy,
+ i_T=1)
d0 = Signal()
- d0p = Signal()
d1 = Signal()
- d1p = Signal()
+ pd_valid = Signal()
+ pd_incdec = Signal()
+ pd_edge = Signal()
+ pd_cascade = Signal()
self.specials += Instance("ISERDES2",
- Instance.Parameter("BITSLIP_ENABLE", "FALSE"),
- Instance.Parameter("DATA_RATE", "SDR"),
- Instance.Parameter("DATA_WIDTH", 4),
- Instance.Parameter("INTERFACE_TYPE", "RETIMED"),
- Instance.Parameter("SERDES_MODE", "NONE"),
- Instance.Output("Q4", d0),
- Instance.Output("Q3", d0p),
- Instance.Output("Q2", d1),
- Instance.Output("Q1", d1p),
- Instance.Input("BITSLIP", 0),
- Instance.Input("CE0", 1),
- Instance.Input("CLK0", ClockSignal("pix20x")),
- Instance.Input("CLKDIV", ClockSignal("pix5x")),
- Instance.Input("D", pad_delayed),
- Instance.Input("IOCE", self.serdesstrobe),
- Instance.Input("RST", 0)
- )
-
- # Phase detector
+ p_SERDES_MODE="MASTER",
+ p_BITSLIP_ENABLE="FALSE", p_DATA_RATE="SDR", p_DATA_WIDTH=2,
+ p_INTERFACE_TYPE="RETIMED",
+
+ i_D=pad_delayed_master,
+ o_Q4=d0, o_Q3=d1,
+
+ i_BITSLIP=0, i_CE0=1, i_RST=0,
+ i_CLK0=ClockSignal("pix10x"), i_CLKDIV=ClockSignal("pix5x"),
+ i_IOCE=self.serdesstrobe,
+
+ o_VALID=pd_valid, o_INCDEC=pd_incdec,
+ i_SHIFTIN=pd_edge, o_SHIFTOUT=pd_cascade)
+ self.specials += Instance("ISERDES2",
+ p_SERDES_MODE="SLAVE",
+ p_BITSLIP_ENABLE="FALSE", p_DATA_RATE="SDR", p_DATA_WIDTH=2,
+ p_INTERFACE_TYPE="RETIMED",
+
+ i_D=pad_delayed_slave,
+
+ i_BITSLIP=0, i_CE0=1, i_RST=0,
+ i_CLK0=ClockSignal("pix10x"), i_CLKDIV=ClockSignal("pix5x"),
+ i_IOCE=self.serdesstrobe,
+
+ i_SHIFTIN=pd_cascade, o_SHIFTOUT=pd_edge)
+
+ # Phase error accumulator
lateness = Signal(ntbits, reset=2**(ntbits - 1))
too_late = Signal()
too_early = Signal()
@@ -74,68 +96,80 @@ def __init__(self, ntbits, invert):
self.sync.pix5x += [
If(reset_lateness,
lateness.eq(2**(ntbits - 1))
- ).Elif(~delay_busy & ~too_late & ~too_early & (d0 != d1),
- If(d0,
- # 1 -----> 0
- # d0p
- If(d0p,
- lateness.eq(lateness - 1)
- ).Else(
- lateness.eq(lateness + 1)
- )
- ).Else(
- # 0 -----> 1
- # d0p
- If(d0p,
- lateness.eq(lateness + 1)
- ).Else(
- lateness.eq(lateness - 1)
- )
- )
+ ).Elif(~delay_master_busy & ~delay_slave_busy & ~too_late & ~too_early,
+ If(pd_valid & pd_incdec, lateness.eq(lateness - 1)),
+ If(pd_valid & ~pd_incdec, lateness.eq(lateness + 1))
)
]
# Delay control
- self.submodules.delay_done = PulseSynchronizer("pix5x", "sys")
- delay_pending = Signal()
+ self.submodules.delay_master_done = PulseSynchronizer("pix5x", "sys")
+ delay_master_pending = Signal()
+ self.sync.pix5x += [
+ self.delay_master_done.i.eq(0),
+ If(~delay_master_pending,
+ If(delay_master_cal | delay_ce, delay_master_pending.eq(1))
+ ).Else(
+ If(~delay_master_busy,
+ self.delay_master_done.i.eq(1),
+ delay_master_pending.eq(0)
+ )
+ )
+ ]
+ self.submodules.delay_slave_done = PulseSynchronizer("pix5x", "sys")
+ delay_slave_pending = Signal()
self.sync.pix5x += [
- self.delay_done.i.eq(0),
- If(~delay_pending,
- If(delay_cal | delay_ce, delay_pending.eq(1))
+ self.delay_slave_done.i.eq(0),
+ If(~delay_slave_pending,
+ If(delay_slave_cal | delay_ce, delay_slave_pending.eq(1))
).Else(
- If(~delay_busy,
- self.delay_done.i.eq(1),
- delay_pending.eq(0)
+ If(~delay_slave_busy,
+ self.delay_slave_done.i.eq(1),
+ delay_slave_pending.eq(0)
)
)
]
- self.submodules.do_delay_cal = PulseSynchronizer("sys", "pix5x")
- self.submodules.do_delay_rst = PulseSynchronizer("sys", "pix5x")
+ self.submodules.do_delay_master_cal = PulseSynchronizer("sys", "pix5x")
+ self.submodules.do_delay_master_rst = PulseSynchronizer("sys", "pix5x")
+ self.submodules.do_delay_slave_cal = PulseSynchronizer("sys", "pix5x")
+ self.submodules.do_delay_slave_rst = PulseSynchronizer("sys", "pix5x")
self.submodules.do_delay_inc = PulseSynchronizer("sys", "pix5x")
self.submodules.do_delay_dec = PulseSynchronizer("sys", "pix5x")
self.comb += [
- delay_cal.eq(self.do_delay_cal.o),
- delay_rst.eq(self.do_delay_rst.o),
+ delay_master_cal.eq(self.do_delay_master_cal.o),
+ delay_master_rst.eq(self.do_delay_master_rst.o),
+ delay_slave_cal.eq(self.do_delay_slave_cal.o),
+ delay_slave_rst.eq(self.do_delay_slave_rst.o),
delay_inc.eq(self.do_delay_inc.o),
delay_ce.eq(self.do_delay_inc.o | self.do_delay_dec.o),
]
- sys_delay_pending = Signal()
+ sys_delay_master_pending = Signal()
+ self.sync += [
+ If(self.do_delay_master_cal.i | self.do_delay_inc.i | self.do_delay_dec.i,
+ sys_delay_master_pending.eq(1)
+ ).Elif(self.delay_master_done.o,
+ sys_delay_master_pending.eq(0)
+ )
+ ]
+ sys_delay_slave_pending = Signal()
self.sync += [
- If(self.do_delay_cal.i | self.do_delay_inc.i | self.do_delay_dec.i,
- sys_delay_pending.eq(1)
- ).Elif(self.delay_done.o,
- sys_delay_pending.eq(0)
+ If(self.do_delay_slave_cal.i | self.do_delay_inc.i | self.do_delay_dec.i,
+ sys_delay_slave_pending.eq(1)
+ ).Elif(self.delay_slave_done.o,
+ sys_delay_slave_pending.eq(0)
)
]
self.comb += [
- self.do_delay_cal.i.eq(self._r_dly_ctl.re & self._r_dly_ctl.r[0]),
- self.do_delay_rst.i.eq(self._r_dly_ctl.re & self._r_dly_ctl.r[1]),
- self.do_delay_inc.i.eq(self._r_dly_ctl.re & self._r_dly_ctl.r[2]),
- self.do_delay_dec.i.eq(self._r_dly_ctl.re & self._r_dly_ctl.r[3]),
- self._r_dly_busy.status.eq(sys_delay_pending)
+ self.do_delay_master_cal.i.eq(self._r_dly_ctl.re & self._r_dly_ctl.r[0]),
+ self.do_delay_master_rst.i.eq(self._r_dly_ctl.re & self._r_dly_ctl.r[1]),
+ self.do_delay_slave_cal.i.eq(self._r_dly_ctl.re & self._r_dly_ctl.r[2]),
+ self.do_delay_slave_rst.i.eq(self._r_dly_ctl.re & self._r_dly_ctl.r[3]),
+ self.do_delay_inc.i.eq(self._r_dly_ctl.re & self._r_dly_ctl.r[4]),
+ self.do_delay_dec.i.eq(self._r_dly_ctl.re & self._r_dly_ctl.r[5]),
+ self._r_dly_busy.status.eq(Cat(sys_delay_master_pending, sys_delay_slave_pending))
]
# Phase detector control
@@ -147,12 +181,6 @@ def __init__(self, ntbits, invert):
]
# 2:10 deserialization
- d0i = Signal()
- d1i = Signal()
- self.comb += [
- d0i.eq(d0 ^ invert),
- d1i.eq(d1 ^ invert)
- ]
dsr = Signal(10)
- self.sync.pix5x += dsr.eq(Cat(dsr[2:], d1i, d0i))
+ self.sync.pix5x += dsr.eq(Cat(dsr[2:], d1, d0))
self.sync.pix += self.d.eq(dsr)
View
10 software/include/hw/flags.h
@@ -25,10 +25,12 @@
#define DVISAMPLER_TOO_LATE 0x1
#define DVISAMPLER_TOO_EARLY 0x2
-#define DVISAMPLER_DELAY_CAL 0x1
-#define DVISAMPLER_DELAY_RST 0x2
-#define DVISAMPLER_DELAY_INC 0x4
-#define DVISAMPLER_DELAY_DEC 0x8
+#define DVISAMPLER_DELAY_MASTER_CAL 0x01
+#define DVISAMPLER_DELAY_MASTER_RST 0x02
+#define DVISAMPLER_DELAY_SLAVE_CAL 0x04
+#define DVISAMPLER_DELAY_SLAVE_RST 0x08
+#define DVISAMPLER_DELAY_INC 0x10
+#define DVISAMPLER_DELAY_DEC 0x20
#define DVISAMPLER_SLOT_EMPTY 0
#define DVISAMPLER_SLOT_LOADED 1
View
12 software/videomixer/dvisamplerX.c
@@ -106,14 +106,14 @@ static int wait_idelays(void)
int dvisamplerX_calibrate_delays(void)
{
- dvisamplerX_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_CAL);
- dvisamplerX_data1_cap_dly_ctl_write(DVISAMPLER_DELAY_CAL);
- dvisamplerX_data2_cap_dly_ctl_write(DVISAMPLER_DELAY_CAL);
+ dvisamplerX_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_MASTER_CAL|DVISAMPLER_DELAY_SLAVE_CAL);
+ dvisamplerX_data1_cap_dly_ctl_write(DVISAMPLER_DELAY_MASTER_CAL|DVISAMPLER_DELAY_SLAVE_CAL);
+ dvisamplerX_data2_cap_dly_ctl_write(DVISAMPLER_DELAY_MASTER_CAL|DVISAMPLER_DELAY_SLAVE_CAL);
if(!wait_idelays())
return 0;
- dvisamplerX_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_RST);
- dvisamplerX_data1_cap_dly_ctl_write(DVISAMPLER_DELAY_RST);
- dvisamplerX_data2_cap_dly_ctl_write(DVISAMPLER_DELAY_RST);
+ dvisamplerX_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_MASTER_RST|DVISAMPLER_DELAY_SLAVE_RST);
+ dvisamplerX_data1_cap_dly_ctl_write(DVISAMPLER_DELAY_MASTER_RST|DVISAMPLER_DELAY_SLAVE_RST);
+ dvisamplerX_data2_cap_dly_ctl_write(DVISAMPLER_DELAY_MASTER_RST|DVISAMPLER_DELAY_SLAVE_RST);
dvisamplerX_data0_cap_phase_reset_write(1);
dvisamplerX_data1_cap_phase_reset_write(1);
dvisamplerX_data2_cap_phase_reset_write(1);
Please sign in to comment.
Something went wrong with that request. Please try again.