forked from M-Labs/artiq
1
0
Fork 0

soc/dds: fix timing

This commit is contained in:
Robert Jördens 2014-07-22 17:43:50 -06:00 committed by Sebastien Bourdeauducq
parent 2358b218bf
commit 005d66c7cd
2 changed files with 67 additions and 44 deletions

View File

@ -23,9 +23,16 @@ class AD9858(Module):
rd_n is asserted for 3 cycles. rd_n is asserted for 3 cycles.
Data is sampled 2 cycles into the assertion of rd_n. Data is sampled 2 cycles into the assertion of rd_n.
FUD is asserted for fud_cycles cycles. Design:
All IO pads are registered.
LVDS driver/receiver propagation delays are 3.6+4.5 ns max
LVDS state transition delays are 20, 15 ns max
Schmitt trigger delays are 6.4ns max
Round-trip addr A setup (> RX, RD, D to Z), RD prop, D valid (< D
valid), D prop is ~15 + 10 + 20 + 10 = 55ns
""" """
def __init__(self, pads, fud_cycles=3, bus=None): def __init__(self, pads, bus=None):
if bus is None: if bus is None:
bus = wishbone.Interface() bus = wishbone.Interface()
self.bus = bus self.bus = bus
@ -35,46 +42,39 @@ class AD9858(Module):
dts = TSTriple(8) dts = TSTriple(8)
self.specials += dts.get_tristate(pads.d) self.specials += dts.get_tristate(pads.d)
dr = Signal(8) dr = Signal(8)
oe_p = Signal() rx = Signal()
self.sync += [ self.sync += [
pads.a.eq(bus.adr[:6]), pads.a.eq(bus.adr),
dts.o.eq(bus.dat_w), dts.o.eq(bus.dat_w),
dr.eq(dts.i), dr.eq(dts.i),
dts.oe.eq(oe_p) dts.oe.eq(~rx)
] ]
gpio = Signal(flen(pads.sel) + flen(pads.p) + 1) gpio = Signal(flen(pads.sel) + flen(pads.p) + 1)
gpio_load = Signal() gpio_load = Signal()
self.sync += If(gpio_load, gpio.eq(bus.dat_w)) self.sync += If(gpio_load, gpio.eq(bus.dat_w))
self.comb += Cat(pads.sel, pads.p, pads.reset).eq(gpio) self.comb += [
Cat(pads.sel, pads.p).eq(gpio),
pads.rst_n.eq(~gpio[-1]),
]
bus_r_sel_gpio = Signal() bus_r_gpio = Signal()
self.comb += If(bus_r_sel_gpio, self.comb += If(bus_r_gpio,
bus.dat_r.eq(gpio) bus.dat_r.eq(gpio)
).Else( ).Else(
bus.dat_r.eq(dr) bus.dat_r.eq(dr)
) )
fud_p = Signal() fud = Signal()
self.sync += pads.fud.eq(fud_p) self.sync += pads.fud_n.eq(~fud)
fud_counter_max = fud_cycles - 1
fud_counter = Signal(max=fud_counter_max+1)
fud_counter_en = Signal()
fud_counter_done = Signal()
self.comb += fud_counter_done.eq(fud_counter == fud_counter_max)
self.sync += If(fud_counter_en,
fud_counter.eq(fud_counter + 1)
).Else(
fud_counter.eq(0)
)
pads.wr_n.reset = 1 pads.wr_n.reset = 1
pads.rd_n.reset = 1 pads.rd_n.reset = 1
wr_n_p = Signal(reset=1) wr = Signal()
rd_n_p = Signal(reset=1) rd = Signal()
self.sync += pads.wr_n.eq(wr_n_p), pads.rd_n.eq(rd_n_p) self.sync += pads.wr_n.eq(~wr), pads.rd_n.eq(~rd)
fsm = FSM() fsm = FSM("IDLE")
self.submodules += fsm self.submodules += fsm
fsm.act("IDLE", fsm.act("IDLE",
@ -95,60 +95,83 @@ class AD9858(Module):
) )
) )
fsm.act("WRITE", fsm.act("WRITE",
oe_p.eq(1), # 3ns A setup to WR active
wr_n_p.eq(0), wr.eq(1),
NextState("WRITE0")
)
fsm.act("WRITE0",
# 3.5ns D setup to WR inactive
# 0ns D and A hold to WR inactive
bus.ack.eq(1), bus.ack.eq(1),
NextState("IDLE") NextState("IDLE")
) )
fsm.act("READ", fsm.act("READ",
rd_n_p.eq(0), # 15ns D valid to A setup
# 15ns D valid to RD active
rx.eq(1),
rd.eq(1),
NextState("READ0") NextState("READ0")
) )
fsm.act("READ0", fsm.act("READ0",
rd_n_p.eq(0), rx.eq(1),
rd.eq(1),
NextState("READ1") NextState("READ1")
) )
fsm.act("READ1", fsm.act("READ1",
rd_n_p.eq(0), rx.eq(1),
rd.eq(1),
NextState("READ2") NextState("READ2")
) )
fsm.act("READ2", fsm.act("READ2",
rx.eq(1),
rd.eq(1),
NextState("READ3") NextState("READ3")
) )
fsm.act("READ3", fsm.act("READ3",
rx.eq(1),
rd.eq(1),
NextState("READ4")
)
fsm.act("READ4",
rx.eq(1),
NextState("READ5")
)
fsm.act("READ5",
# 5ns D three-state to RD inactive
# 10ns A hold to RD inactive
rx.eq(1),
bus.ack.eq(1), bus.ack.eq(1),
NextState("IDLE") NextState("IDLE")
) )
fsm.act("GPIO", fsm.act("GPIO",
bus.ack.eq(1), bus.ack.eq(1),
bus_r_sel_gpio.eq(1), bus_r_gpio.eq(1),
If(bus.we, gpio_load.eq(1)), If(bus.we, gpio_load.eq(1)),
NextState("IDLE") NextState("IDLE")
) )
fsm.act("FUD", fsm.act("FUD",
fud_p.eq(1), # 4ns FUD setup to SYNCLK
fud_counter_en.eq(1), # 0ns FUD hold to SYNCLK
If(fud_counter_done, fud.eq(1),
bus.ack.eq(1), bus.ack.eq(1),
NextState("IDLE") NextState("IDLE")
)
) )
def _test_gen(): def _test_gen():
# Test external bus writes # Test external bus writes
yield TWrite(4, 2) yield TWrite(4, 2)
yield TWrite(5, 3) yield TWrite(5, 3)
yield
# Test external bus reads # Test external bus reads
yield TRead(14) yield TRead(14)
yield TRead(15) yield TRead(15)
yield
# Test FUD # Test FUD
yield TWrite(64, 0) yield TWrite(64, 0)
yield
# Test GPIO # Test GPIO
yield TWrite(65, 0xff) yield TWrite(65, 0xff)
yield None yield
class _TestPads: class _TestPads:
def __init__(self): def __init__(self):
@ -156,10 +179,10 @@ class _TestPads:
self.d = Signal(8) self.d = Signal(8)
self.sel = Signal(5) self.sel = Signal(5)
self.p = Signal(2) self.p = Signal(2)
self.fud = Signal() self.fud_n = Signal()
self.wr_n = Signal() self.wr_n = Signal()
self.rd_n = Signal() self.rd_n = Signal()
self.reset = Signal() self.rst_n = Signal()
class _TB(Module): class _TB(Module):
def __init__(self): def __init__(self):

View File

@ -72,10 +72,10 @@ _tester_io = [
Subsignal("d", Pins("A:12 B:3 A:13 B:2 A:14 B:1 A:15 B:0")), Subsignal("d", Pins("A:12 B:3 A:13 B:2 A:14 B:1 A:15 B:0")),
Subsignal("sel", Pins("A:2 B:14 A:1 B:15 A:0")), Subsignal("sel", Pins("A:2 B:14 A:1 B:15 A:0")),
Subsignal("p", Pins("A:8 B:12")), Subsignal("p", Pins("A:8 B:12")),
Subsignal("fud", Pins("B:11")), Subsignal("fud_n", Pins("B:11")),
Subsignal("wr_n", Pins("A:4")), Subsignal("wr_n", Pins("A:4")),
Subsignal("rd_n", Pins("B:13")), Subsignal("rd_n", Pins("B:13")),
Subsignal("reset", Pins("A:3")), Subsignal("rst_n", Pins("A:3")),
IOStandard("LVTTL")), IOStandard("LVTTL")),
] ]