soc: add DDS interface core

This commit is contained in:
Sebastien Bourdeauducq 2014-07-22 11:37:53 -06:00
parent dec7c1438f
commit 2358b218bf
2 changed files with 175 additions and 1 deletions

View File

@ -0,0 +1,172 @@
from migen.fhdl.std import *
from migen.genlib.fsm import *
from migen.bus import wishbone
from migen.bus.transactions import *
from migen.sim.generic import run_simulation
class AD9858(Module):
"""Wishbone interface to the AD9858 DDS chip.
Addresses 0-63 map the AD9858 registers.
Data is zero-padded.
Write to address 64 to pulse the FUD signal.
Address 65 is a GPIO register that controls the sel, p and reset signals.
sel is mapped to the lower bits, followed by p and reset.
Write timing:
Address is set one cycle before assertion of we_n.
we_n is asserted for one cycle, at the same time as valid data is driven.
Read timing:
Address is set one cycle before assertion of rd_n.
rd_n is asserted for 3 cycles.
Data is sampled 2 cycles into the assertion of rd_n.
FUD is asserted for fud_cycles cycles.
"""
def __init__(self, pads, fud_cycles=3, bus=None):
if bus is None:
bus = wishbone.Interface()
self.bus = bus
###
dts = TSTriple(8)
self.specials += dts.get_tristate(pads.d)
dr = Signal(8)
oe_p = Signal()
self.sync += [
pads.a.eq(bus.adr[:6]),
dts.o.eq(bus.dat_w),
dr.eq(dts.i),
dts.oe.eq(oe_p)
]
gpio = Signal(flen(pads.sel) + flen(pads.p) + 1)
gpio_load = Signal()
self.sync += If(gpio_load, gpio.eq(bus.dat_w))
self.comb += Cat(pads.sel, pads.p, pads.reset).eq(gpio)
bus_r_sel_gpio = Signal()
self.comb += If(bus_r_sel_gpio,
bus.dat_r.eq(gpio)
).Else(
bus.dat_r.eq(dr)
)
fud_p = Signal()
self.sync += pads.fud.eq(fud_p)
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.rd_n.reset = 1
wr_n_p = Signal(reset=1)
rd_n_p = Signal(reset=1)
self.sync += pads.wr_n.eq(wr_n_p), pads.rd_n.eq(rd_n_p)
fsm = FSM()
self.submodules += fsm
fsm.act("IDLE",
If(bus.cyc & bus.stb,
If(bus.adr[6],
If(bus.adr[0],
NextState("GPIO")
).Else(
NextState("FUD")
)
).Else(
If(bus.we,
NextState("WRITE")
).Else(
NextState("READ")
)
)
)
)
fsm.act("WRITE",
oe_p.eq(1),
wr_n_p.eq(0),
bus.ack.eq(1),
NextState("IDLE")
)
fsm.act("READ",
rd_n_p.eq(0),
NextState("READ0")
)
fsm.act("READ0",
rd_n_p.eq(0),
NextState("READ1")
)
fsm.act("READ1",
rd_n_p.eq(0),
NextState("READ2")
)
fsm.act("READ2",
NextState("READ3")
)
fsm.act("READ3",
bus.ack.eq(1),
NextState("IDLE")
)
fsm.act("GPIO",
bus.ack.eq(1),
bus_r_sel_gpio.eq(1),
If(bus.we, gpio_load.eq(1)),
NextState("IDLE")
)
fsm.act("FUD",
fud_p.eq(1),
fud_counter_en.eq(1),
If(fud_counter_done,
bus.ack.eq(1),
NextState("IDLE")
)
)
def _test_gen():
# Test external bus writes
yield TWrite(4, 2)
yield TWrite(5, 3)
# Test external bus reads
yield TRead(14)
yield TRead(15)
# Test FUD
yield TWrite(64, 0)
# Test GPIO
yield TWrite(65, 0xff)
yield None
class _TestPads:
def __init__(self):
self.a = Signal(6)
self.d = Signal(8)
self.sel = Signal(5)
self.p = Signal(2)
self.fud = Signal()
self.wr_n = Signal()
self.rd_n = Signal()
self.reset = Signal()
class _TB(Module):
def __init__(self):
pads = _TestPads()
self.submodules.dut = AD9858(pads)
self.submodules.initiator = wishbone.Initiator(_test_gen())
self.submodules.interconnect = wishbone.InterconnectPointToPoint(self.initiator.bus, self.dut.bus)
if __name__ == "__main__":
run_simulation(_TB(), vcd_name="ad9858.vcd")

View File

@ -7,7 +7,7 @@ from misoclib import lasmicon, spiflash, gpio
from misoclib.sdramphy import gensdrphy from misoclib.sdramphy import gensdrphy
from misoclib.gensoc import SDRAMSoC from misoclib.gensoc import SDRAMSoC
from artiqlib import rtio from artiqlib import rtio, ad9858
class _CRG(Module): class _CRG(Module):
def __init__(self, platform, clk_freq): def __init__(self, platform, clk_freq):
@ -124,5 +124,7 @@ class ARTIQSoC(SDRAMSoC):
platform.request("user_led", 1))) platform.request("user_led", 1)))
self.comb += platform.request("ttl_tx_en").eq(1) self.comb += platform.request("ttl_tx_en").eq(1)
self.submodules.rtio = rtio.RTIO([platform.request("ttl", i) for i in range(4)]) self.submodules.rtio = rtio.RTIO([platform.request("ttl", i) for i in range(4)])
self.submodules.dds = ad9858.AD9858(platform.request("dds"))
self.add_wb_slave(lambda a: a[26:29] == 3, self.dds.bus)
default_subtarget = ARTIQSoC default_subtarget = ARTIQSoC