diff --git a/soc/artiqlib/rtio/__init__.py b/soc/artiqlib/rtio/__init__.py new file mode 100644 index 000000000..d8a6c36e7 --- /dev/null +++ b/soc/artiqlib/rtio/__init__.py @@ -0,0 +1,62 @@ +from migen.fhdl.std import * +from migen.bank.description import * +from migen.genlib.fifo import SyncFIFOBuffered +from migen.genlib.cdc import MultiReg + +class RTIOChannelO(Module): + def __init__(self, signal, counter_width, fifo_depth): + self.submodules.fifo = SyncFIFOBuffered([ + ("timestamp", counter_width), ("level", 1)], + fifo_depth) + + self.event = self.fifo.din + self.writable = self.fifo.writable + self.we = self.fifo.we + self.underflow = Signal() + + ### + + counter = Signal(counter_width) + self.sync += counter.eq(counter + 1) + + self.sync += If(self.we & self.writable, + If(self.event.timestamp < counter + 2, + self.underflow.eq(1) + ) + ) + + time_hit = Signal() + self.comb += [ + time_hit.eq(self.fifo.readable & + (self.fifo.dout.timestamp == counter)), + self.fifo.re.eq(time_hit) + ] + self.sync += If(time_hit, signal.eq(self.fifo.dout.level)) + +class RTIO(Module, AutoCSR): + def __init__(self, channels, counter_width=32, ofifo_depth=8, ififo_depth=8): + self._r_reset = CSRStorage(reset=1) + self._r_chan_sel = CSRStorage(bits_for(len(channels)-1)) + self._r_o_timestamp = CSRStorage(counter_width) + self._r_o_level = CSRStorage() + self._r_o_writable = CSRStatus() + self._r_o_we = CSR() + self._r_o_underflow = CSRStatus() + + channel_os = [] + for n, channel in enumerate(channels): + channel_o = InsertReset(RTIOChannelO(channel, counter_width, ofifo_depth)) + self.submodules += channel_o + channel_os.append(channel_o) + self.comb += [ + channel_o.reset.eq(self._r_reset.storage), + channel_o.event.timestamp.eq(self._r_o_timestamp.storage), + channel_o.event.level.eq(self._r_o_level.storage), + channel_o.we.eq(self._r_o_we.re & (self._r_chan_sel == n)) + ] + + channel_o = Array(channel_os)[self._r_chan_sel.storage] + self.comb += [ + self._r_o_writable.status.eq(channel_o.writable), + self._r_o_underflow.status.eq(channel_o.underflow) + ] diff --git a/soc/targets/artiq.py b/soc/targets/artiq.py index e1050787e..511c7822e 100644 --- a/soc/targets/artiq.py +++ b/soc/targets/artiq.py @@ -1,11 +1,14 @@ from fractions import Fraction from migen.fhdl.std import * +from mibuild.generic_platform import * from misoclib import lasmicon, spiflash, gpio from misoclib.sdramphy import gensdrphy from misoclib.gensoc import SDRAMSoC +from artiqlib import rtio + class _CRG(Module): def __init__(self, platform, clk_freq): self.clock_domains.cd_sys = ClockDomain() @@ -57,13 +60,21 @@ class _CRG(Module): i_C0=self.cd_sys.clk, i_C1=~self.cd_sys.clk, o_Q=platform.request("sdram_clock")) +_ttl_io = [("ttl", i, Pins("C:"+str(i)), IOStandard("LVTTL")) for i in range(16)] + class ARTIQSoC(SDRAMSoC): default_platform = "papilio_pro" + csr_map = { + "rtio": 10 + } + csr_map.update(SDRAMSoC.csr_map) + def __init__(self, platform, cpu_type="or1k", **kwargs): clk_freq = 80*1000*1000 SDRAMSoC.__init__(self, platform, clk_freq, cpu_reset_address=0x160000, cpu_type=cpu_type, **kwargs) + platform.add_extension(_ttl_io) self.submodules.crg = _CRG(platform, clk_freq) @@ -93,5 +104,6 @@ class ARTIQSoC(SDRAMSoC): self.register_rom(self.spiflash.bus) self.submodules.leds = gpio.GPIOOut(platform.request("user_led")) + self.submodules.rtio = rtio.RTIO([platform.request("ttl", i) for i in range(16)]) default_subtarget = ARTIQSoC