forked from M-Labs/artiq-zynq
si549 gateware
kasli_soc: add --with-wrpll arg to switch from si5324 to si549 kasli_soc: default to use si5435 kasli_soc: add main and helper si549 for satellite si549: add i2c and adpll programmer
This commit is contained in:
parent
cf0b83c3f9
commit
3972efc61e
|
@ -26,6 +26,7 @@ import analyzer
|
||||||
import acpki
|
import acpki
|
||||||
import drtio_aux_controller
|
import drtio_aux_controller
|
||||||
import zynq_clocking
|
import zynq_clocking
|
||||||
|
import si549
|
||||||
from config import write_csr_file, write_mem_file, write_rustc_cfg_file
|
from config import write_csr_file, write_mem_file, write_rustc_cfg_file
|
||||||
|
|
||||||
eem_iostandard_dict = {
|
eem_iostandard_dict = {
|
||||||
|
@ -105,7 +106,7 @@ class GTPBootstrapClock(Module):
|
||||||
|
|
||||||
|
|
||||||
class GenericStandalone(SoCCore):
|
class GenericStandalone(SoCCore):
|
||||||
def __init__(self, description, acpki=False):
|
def __init__(self, description, acpki=False, with_wrpll=False):
|
||||||
self.acpki = acpki
|
self.acpki = acpki
|
||||||
clk_freq = description["rtio_frequency"]
|
clk_freq = description["rtio_frequency"]
|
||||||
|
|
||||||
|
@ -205,7 +206,7 @@ class GenericStandalone(SoCCore):
|
||||||
|
|
||||||
|
|
||||||
class GenericMaster(SoCCore):
|
class GenericMaster(SoCCore):
|
||||||
def __init__(self, description, acpki=False):
|
def __init__(self, description, acpki=False, with_wrpll=False):
|
||||||
clk_freq = description["rtio_frequency"]
|
clk_freq = description["rtio_frequency"]
|
||||||
|
|
||||||
has_drtio_over_eem = any(peripheral["type"] == "shuttler" for peripheral in description["peripherals"])
|
has_drtio_over_eem = any(peripheral["type"] == "shuttler" for peripheral in description["peripherals"])
|
||||||
|
@ -398,7 +399,7 @@ class GenericMaster(SoCCore):
|
||||||
|
|
||||||
|
|
||||||
class GenericSatellite(SoCCore):
|
class GenericSatellite(SoCCore):
|
||||||
def __init__(self, description, acpki=False):
|
def __init__(self, description, acpki=False, with_wrpll=False):
|
||||||
clk_freq = description["rtio_frequency"]
|
clk_freq = description["rtio_frequency"]
|
||||||
|
|
||||||
self.acpki = acpki
|
self.acpki = acpki
|
||||||
|
@ -551,6 +552,11 @@ class GenericSatellite(SoCCore):
|
||||||
self.config["RTIO_FREQUENCY"] = str(clk_freq/1e6)
|
self.config["RTIO_FREQUENCY"] = str(clk_freq/1e6)
|
||||||
self.config["CLOCK_FREQUENCY"] = int(clk_freq)
|
self.config["CLOCK_FREQUENCY"] = int(clk_freq)
|
||||||
|
|
||||||
|
if with_wrpll:
|
||||||
|
self.submodules.main_dcxo = si549.Si549(platform.request("ddmtd_main_dcxo_i2c"))
|
||||||
|
self.submodules.helper_dcxo = si549.Si549(platform.request("ddmtd_helper_dcxo_i2c"))
|
||||||
|
self.config["HAS_SI549"] = None
|
||||||
|
else:
|
||||||
self.submodules.siphaser = SiPhaser7Series(
|
self.submodules.siphaser = SiPhaser7Series(
|
||||||
si5324_clkin=platform.request("cdr_clk"),
|
si5324_clkin=platform.request("cdr_clk"),
|
||||||
rx_synchronizer=self.rx_synchronizer,
|
rx_synchronizer=self.rx_synchronizer,
|
||||||
|
@ -588,6 +594,8 @@ def main():
|
||||||
help="build gateware into the specified directory")
|
help="build gateware into the specified directory")
|
||||||
parser.add_argument("--acpki", default=False, action="store_true",
|
parser.add_argument("--acpki", default=False, action="store_true",
|
||||||
help="enable ACPKI")
|
help="enable ACPKI")
|
||||||
|
parser.add_argument("--with-wrpll", default=False, action="store_true",
|
||||||
|
help="enable WRPLL")
|
||||||
parser.add_argument("description", metavar="DESCRIPTION",
|
parser.add_argument("description", metavar="DESCRIPTION",
|
||||||
help="JSON system description file")
|
help="JSON system description file")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
@ -605,7 +613,7 @@ def main():
|
||||||
else:
|
else:
|
||||||
raise ValueError("Invalid DRTIO role")
|
raise ValueError("Invalid DRTIO role")
|
||||||
|
|
||||||
soc = cls(description, acpki=args.acpki)
|
soc = cls(description, acpki=args.acpki, with_wrpll=args.with_wrpll)
|
||||||
soc.finalize()
|
soc.finalize()
|
||||||
|
|
||||||
if args.r is not None:
|
if args.r is not None:
|
||||||
|
|
|
@ -0,0 +1,278 @@
|
||||||
|
from migen import *
|
||||||
|
from migen.genlib.fsm import *
|
||||||
|
|
||||||
|
from misoc.interconnect.csr import *
|
||||||
|
|
||||||
|
|
||||||
|
class I2CClockGen(Module):
|
||||||
|
def __init__(self, width):
|
||||||
|
self.load = Signal(width)
|
||||||
|
self.clk2x = Signal()
|
||||||
|
|
||||||
|
cnt = Signal.like(self.load)
|
||||||
|
self.comb += [
|
||||||
|
self.clk2x.eq(cnt == 0),
|
||||||
|
]
|
||||||
|
self.sync += [
|
||||||
|
If(self.clk2x,
|
||||||
|
cnt.eq(self.load),
|
||||||
|
).Else(
|
||||||
|
cnt.eq(cnt - 1),
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class I2CMasterMachine(Module):
|
||||||
|
def __init__(self, clock_width):
|
||||||
|
self.scl = Signal(reset=1)
|
||||||
|
self.sda_o = Signal(reset=1)
|
||||||
|
self.sda_i = Signal()
|
||||||
|
|
||||||
|
self.submodules.cg = CEInserter()(I2CClockGen(clock_width))
|
||||||
|
self.start = Signal()
|
||||||
|
self.stop = Signal()
|
||||||
|
self.write = Signal()
|
||||||
|
self.ack = Signal()
|
||||||
|
self.data = Signal(8)
|
||||||
|
self.ready = Signal()
|
||||||
|
|
||||||
|
# # #
|
||||||
|
|
||||||
|
bits = Signal(4)
|
||||||
|
data = Signal(8)
|
||||||
|
|
||||||
|
fsm = CEInserter()(FSM("IDLE"))
|
||||||
|
self.submodules += fsm
|
||||||
|
|
||||||
|
fsm.act("IDLE",
|
||||||
|
self.ready.eq(1),
|
||||||
|
If(self.start,
|
||||||
|
NextState("START0"),
|
||||||
|
).Elif(self.stop,
|
||||||
|
NextState("STOP0"),
|
||||||
|
).Elif(self.write,
|
||||||
|
NextValue(bits, 8),
|
||||||
|
NextValue(data, self.data),
|
||||||
|
NextState("WRITE0")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
fsm.act("START0",
|
||||||
|
NextValue(self.scl, 1),
|
||||||
|
NextState("START1")
|
||||||
|
)
|
||||||
|
fsm.act("START1",
|
||||||
|
NextValue(self.sda_o, 0),
|
||||||
|
NextState("IDLE")
|
||||||
|
)
|
||||||
|
|
||||||
|
fsm.act("STOP0",
|
||||||
|
NextValue(self.scl, 0),
|
||||||
|
NextState("STOP1")
|
||||||
|
)
|
||||||
|
fsm.act("STOP1",
|
||||||
|
NextValue(self.sda_o, 0),
|
||||||
|
NextState("STOP2")
|
||||||
|
)
|
||||||
|
fsm.act("STOP2",
|
||||||
|
NextValue(self.scl, 1),
|
||||||
|
NextState("STOP3")
|
||||||
|
)
|
||||||
|
fsm.act("STOP3",
|
||||||
|
NextValue(self.sda_o, 1),
|
||||||
|
NextState("IDLE")
|
||||||
|
)
|
||||||
|
|
||||||
|
fsm.act("WRITE0",
|
||||||
|
NextValue(self.scl, 0),
|
||||||
|
NextState("WRITE1")
|
||||||
|
)
|
||||||
|
fsm.act("WRITE1",
|
||||||
|
If(bits == 0,
|
||||||
|
NextValue(self.sda_o, 1),
|
||||||
|
NextState("READACK0"),
|
||||||
|
).Else(
|
||||||
|
NextValue(self.sda_o, data[7]),
|
||||||
|
NextState("WRITE2"),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
fsm.act("WRITE2",
|
||||||
|
NextValue(self.scl, 1),
|
||||||
|
NextValue(data[1:], data[:-1]),
|
||||||
|
NextValue(bits, bits - 1),
|
||||||
|
NextState("WRITE0"),
|
||||||
|
)
|
||||||
|
fsm.act("READACK0",
|
||||||
|
NextValue(self.scl, 1),
|
||||||
|
NextState("READACK1"),
|
||||||
|
)
|
||||||
|
fsm.act("READACK1",
|
||||||
|
NextValue(self.ack, ~self.sda_i),
|
||||||
|
NextState("IDLE")
|
||||||
|
)
|
||||||
|
|
||||||
|
run = Signal()
|
||||||
|
idle = Signal()
|
||||||
|
self.comb += [
|
||||||
|
run.eq((self.start | self.stop | self.write) & self.ready),
|
||||||
|
idle.eq(~run & fsm.ongoing("IDLE")),
|
||||||
|
self.cg.ce.eq(~idle),
|
||||||
|
fsm.ce.eq(run | self.cg.clk2x),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class ADPLLProgrammer(Module):
|
||||||
|
def __init__(self):
|
||||||
|
self.i2c_divider = Signal(16)
|
||||||
|
self.i2c_address = Signal(7)
|
||||||
|
|
||||||
|
self.adpll = Signal(24)
|
||||||
|
self.stb = Signal()
|
||||||
|
self.busy = Signal()
|
||||||
|
self.nack = Signal()
|
||||||
|
|
||||||
|
self.scl = Signal()
|
||||||
|
self.sda_i = Signal()
|
||||||
|
self.sda_o = Signal()
|
||||||
|
|
||||||
|
# # #
|
||||||
|
|
||||||
|
master = I2CMasterMachine(16)
|
||||||
|
self.submodules += master
|
||||||
|
|
||||||
|
self.comb += [
|
||||||
|
master.cg.load.eq(self.i2c_divider),
|
||||||
|
self.scl.eq(master.scl),
|
||||||
|
master.sda_i.eq(self.sda_i),
|
||||||
|
self.sda_o.eq(master.sda_o)
|
||||||
|
]
|
||||||
|
|
||||||
|
fsm = FSM()
|
||||||
|
self.submodules += fsm
|
||||||
|
|
||||||
|
adpll = Signal.like(self.adpll)
|
||||||
|
|
||||||
|
fsm.act("IDLE",
|
||||||
|
If(self.stb,
|
||||||
|
NextValue(adpll, self.adpll),
|
||||||
|
NextState("START")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
fsm.act("START",
|
||||||
|
master.start.eq(1),
|
||||||
|
If(master.ready, NextState("DEVADDRESS"))
|
||||||
|
)
|
||||||
|
fsm.act("DEVADDRESS",
|
||||||
|
master.data.eq(self.i2c_address << 1),
|
||||||
|
master.write.eq(1),
|
||||||
|
If(master.ready, NextState("REGADRESS"))
|
||||||
|
)
|
||||||
|
fsm.act("REGADRESS",
|
||||||
|
master.data.eq(231),
|
||||||
|
master.write.eq(1),
|
||||||
|
If(master.ready,
|
||||||
|
If(master.ack,
|
||||||
|
NextState("DATA0")
|
||||||
|
).Else(
|
||||||
|
self.nack.eq(1),
|
||||||
|
NextState("STOP")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
fsm.act("DATA0",
|
||||||
|
master.data.eq(adpll[0:8]),
|
||||||
|
master.write.eq(1),
|
||||||
|
If(master.ready,
|
||||||
|
If(master.ack,
|
||||||
|
NextState("DATA1")
|
||||||
|
).Else(
|
||||||
|
self.nack.eq(1),
|
||||||
|
NextState("STOP")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
fsm.act("DATA1",
|
||||||
|
master.data.eq(adpll[8:16]),
|
||||||
|
master.write.eq(1),
|
||||||
|
If(master.ready,
|
||||||
|
If(master.ack,
|
||||||
|
NextState("DATA2")
|
||||||
|
).Else(
|
||||||
|
self.nack.eq(1),
|
||||||
|
NextState("STOP")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
fsm.act("DATA2",
|
||||||
|
master.data.eq(adpll[16:24]),
|
||||||
|
master.write.eq(1),
|
||||||
|
If(master.ready,
|
||||||
|
If(~master.ack, self.nack.eq(1)),
|
||||||
|
NextState("STOP")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
fsm.act("STOP",
|
||||||
|
master.stop.eq(1),
|
||||||
|
If(master.ready,
|
||||||
|
If(~master.ack, self.nack.eq(1)),
|
||||||
|
NextState("IDLE")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.comb += self.busy.eq(~fsm.ongoing("IDLE"))
|
||||||
|
|
||||||
|
|
||||||
|
class Si549(Module, AutoCSR):
|
||||||
|
def __init__(self, pads):
|
||||||
|
self.i2c_divider = CSRStorage(16, reset=75)
|
||||||
|
self.i2c_address = CSRStorage(7)
|
||||||
|
|
||||||
|
self.adpll = CSRStorage(24)
|
||||||
|
self.adpll_stb = CSRStorage()
|
||||||
|
self.adpll_busy = CSRStatus()
|
||||||
|
self.nack = CSRStatus()
|
||||||
|
|
||||||
|
self.bitbang_enable = CSRStorage()
|
||||||
|
|
||||||
|
self.sda_oe = CSRStorage()
|
||||||
|
self.sda_out = CSRStorage()
|
||||||
|
self.sda_in = CSRStatus()
|
||||||
|
self.scl_oe = CSRStorage()
|
||||||
|
self.scl_out = CSRStorage()
|
||||||
|
|
||||||
|
# # #
|
||||||
|
|
||||||
|
self.submodules.programmer = ADPLLProgrammer()
|
||||||
|
|
||||||
|
self.comb += [
|
||||||
|
self.programmer.i2c_divider.eq(self.i2c_divider.storage),
|
||||||
|
self.programmer.i2c_address.eq(self.i2c_address.storage),
|
||||||
|
self.programmer.adpll.eq(self.adpll.storage),
|
||||||
|
self.programmer.stb.eq(self.adpll_stb.storage),
|
||||||
|
self.adpll_busy.status.eq(self.programmer.busy),
|
||||||
|
self.nack.status.eq(self.programmer.nack)
|
||||||
|
]
|
||||||
|
|
||||||
|
# I2C with bitbang/gateware mode select
|
||||||
|
sda_t = TSTriple(1)
|
||||||
|
scl_t = TSTriple(1)
|
||||||
|
self.specials += [
|
||||||
|
sda_t.get_tristate(pads.sda),
|
||||||
|
scl_t.get_tristate(pads.scl)
|
||||||
|
]
|
||||||
|
|
||||||
|
self.comb += [
|
||||||
|
If(self.bitbang_enable.storage,
|
||||||
|
sda_t.oe.eq(self.sda_oe.storage),
|
||||||
|
sda_t.o.eq(self.sda_out.storage),
|
||||||
|
self.sda_in.status.eq(sda_t.i),
|
||||||
|
scl_t.oe.eq(self.scl_oe.storage),
|
||||||
|
scl_t.o.eq(self.scl_out.storage)
|
||||||
|
).Else(
|
||||||
|
sda_t.oe.eq(~self.programmer.sda_o),
|
||||||
|
sda_t.o.eq(0),
|
||||||
|
self.programmer.sda_i.eq(sda_t.i),
|
||||||
|
scl_t.oe.eq(~self.programmer.scl),
|
||||||
|
scl_t.o.eq(0),
|
||||||
|
)
|
||||||
|
]
|
Loading…
Reference in New Issue