drtio: share CDC

This commit is contained in:
Sebastien Bourdeauducq 2018-09-02 14:37:23 +08:00
parent 078c862618
commit 88b7529d09
2 changed files with 9 additions and 60 deletions

View File

@ -3,63 +3,12 @@
from migen import * from migen import *
from migen.genlib.fsm import * from migen.genlib.fsm import *
from migen.genlib.fifo import AsyncFIFO from migen.genlib.fifo import AsyncFIFO
from migen.genlib.cdc import PulseSynchronizer
from artiq.gateware.rtio.cdc import GrayCodeTransfer, BlindTransfer from artiq.gateware.rtio.cdc import GrayCodeTransfer, BlindTransfer
from artiq.gateware.drtio.cdc import CrossDomainRequest, CrossDomainNotification
from artiq.gateware.drtio.rt_serializer import * from artiq.gateware.drtio.rt_serializer import *
class _CrossDomainRequest(Module):
def __init__(self, domain,
req_stb, req_ack, req_data,
srv_stb, srv_ack, srv_data):
dsync = getattr(self.sync, domain)
request = PulseSynchronizer("sys", domain)
reply = PulseSynchronizer(domain, "sys")
self.submodules += request, reply
ongoing = Signal()
self.comb += request.i.eq(~ongoing & req_stb)
self.sync += [
req_ack.eq(reply.o),
If(req_stb, ongoing.eq(1)),
If(req_ack, ongoing.eq(0))
]
if req_data is not None:
req_data_r = Signal.like(req_data)
req_data_r.attr.add("no_retiming")
self.sync += If(req_stb, req_data_r.eq(req_data))
dsync += [
If(request.o, srv_stb.eq(1)),
If(srv_ack, srv_stb.eq(0))
]
if req_data is not None:
dsync += If(request.o, srv_data.eq(req_data_r))
self.comb += reply.i.eq(srv_stb & srv_ack)
class _CrossDomainNotification(Module):
def __init__(self, domain,
emi_stb, emi_data,
rec_stb, rec_ack, rec_data):
emi_data_r = Signal(len(emi_data))
emi_data_r.attr.add("no_retiming")
dsync = getattr(self.sync, domain)
dsync += If(emi_stb, emi_data_r.eq(emi_data))
ps = PulseSynchronizer(domain, "sys")
self.submodules += ps
self.comb += ps.i.eq(emi_stb)
self.sync += [
If(rec_ack, rec_stb.eq(0)),
If(ps.o,
rec_data.eq(emi_data_r),
rec_stb.eq(1)
)
]
class RTPacketMaster(Module): class RTPacketMaster(Module):
def __init__(self, link_layer, sr_fifo_depth=4): def __init__(self, link_layer, sr_fifo_depth=4):
# all interface signals in sys domain unless otherwise specified # all interface signals in sys domain unless otherwise specified
@ -206,19 +155,19 @@ class RTPacketMaster(Module):
# CDC # CDC
buffer_space_not = Signal() buffer_space_not = Signal()
buffer_space = Signal(16) buffer_space = Signal(16)
self.submodules += _CrossDomainNotification("rtio_rx", self.submodules += CrossDomainNotification("rtio_rx", "sys",
buffer_space_not, buffer_space, buffer_space_not, buffer_space,
self.buffer_space_not, self.buffer_space_not_ack, self.buffer_space) self.buffer_space_not, self.buffer_space_not_ack, self.buffer_space)
set_time_stb = Signal() set_time_stb = Signal()
set_time_ack = Signal() set_time_ack = Signal()
self.submodules += _CrossDomainRequest("rtio", self.submodules += CrossDomainRequest("rtio",
self.set_time_stb, self.set_time_ack, None, self.set_time_stb, self.set_time_ack, None,
set_time_stb, set_time_ack, None) set_time_stb, set_time_ack, None)
echo_stb = Signal() echo_stb = Signal()
echo_ack = Signal() echo_ack = Signal()
self.submodules += _CrossDomainRequest("rtio", self.submodules += CrossDomainRequest("rtio",
self.echo_stb, self.echo_ack, None, self.echo_stb, self.echo_ack, None,
echo_stb, echo_ack, None) echo_stb, echo_ack, None)
@ -227,7 +176,7 @@ class RTPacketMaster(Module):
read_is_overflow = Signal() read_is_overflow = Signal()
read_data = Signal(32) read_data = Signal(32)
read_timestamp = Signal(64) read_timestamp = Signal(64)
self.submodules += _CrossDomainNotification("rtio_rx", self.submodules += CrossDomainNotification("rtio_rx", "sys",
read_not, read_not,
Cat(read_no_event, read_is_overflow, read_data, read_timestamp), Cat(read_no_event, read_is_overflow, read_data, read_timestamp),

View File

@ -3,8 +3,8 @@ import random
from migen import * from migen import *
from artiq.gateware.drtio.rt_packet_master import (_CrossDomainRequest, from artiq.gateware.drtio.cdc import CrossDomainRequest, CrossDomainNotification
_CrossDomainNotification)
class TestCDC(unittest.TestCase): class TestCDC(unittest.TestCase):
def test_cross_domain_request(self): def test_cross_domain_request(self):
@ -43,7 +43,7 @@ class TestCDC(unittest.TestCase):
yield srv_ack.eq(0) yield srv_ack.eq(0)
yield yield
dut = _CrossDomainRequest("srv", dut = CrossDomainRequest("srv",
req_stb, req_ack, req_data, req_stb, req_ack, req_data,
srv_stb, srv_ack, srv_data) srv_stb, srv_ack, srv_data)
run_simulation(dut, run_simulation(dut,
@ -85,7 +85,7 @@ class TestCDC(unittest.TestCase):
for j in range(prng.randrange(0, 3)): for j in range(prng.randrange(0, 3)):
yield yield
dut = _CrossDomainNotification("emi", dut = CrossDomainNotification("emi", "sys",
emi_stb, emi_data, emi_stb, emi_data,
rec_stb, rec_ack, rec_data) rec_stb, rec_ack, rec_data)
run_simulation(dut, run_simulation(dut,