From 6a88229e6ac5fc36ab73b11312604ec8e711bcdd Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 20 Oct 2016 23:37:59 +0800 Subject: [PATCH] drtio: CrossDomainRequest --- artiq/gateware/drtio/rt_packets.py | 33 +++++++++++++ artiq/test/gateware/drtio/test_rt_packets.py | 49 ++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/artiq/gateware/drtio/rt_packets.py b/artiq/gateware/drtio/rt_packets.py index 93e7781eb..b243f4065 100644 --- a/artiq/gateware/drtio/rt_packets.py +++ b/artiq/gateware/drtio/rt_packets.py @@ -2,6 +2,8 @@ from types import SimpleNamespace from migen import * from migen.genlib.fsm import * +from migen.genlib.fifo import AsyncFIFO +from migen.genlib.cdc import PulseSynchronizer, NoRetiming def layout_len(l): @@ -311,3 +313,34 @@ class RTPacketSatellite(Module): tx_dp.stb.eq(1), If(tx_dp.done, NextState("IDLE")) ) + + +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: + srv_data_r = Signal.like(srv_data) + dsync += If(srv_stb & srv_ack, srv_data_r.eq(srv_data)) + self.specials += NoRetiming(srv_data_r) + self.sync += If(reply.o, req_data.eq(srv_data_r)) + dsync += [ + If(request.o, srv_stb.eq(1)), + If(srv_ack, srv_stb.eq(0)) + ] + self.comb += reply.i.eq(srv_stb & srv_ack) + + diff --git a/artiq/test/gateware/drtio/test_rt_packets.py b/artiq/test/gateware/drtio/test_rt_packets.py index 8709c596b..b1168d424 100644 --- a/artiq/test/gateware/drtio/test_rt_packets.py +++ b/artiq/test/gateware/drtio/test_rt_packets.py @@ -1,9 +1,11 @@ import unittest from types import SimpleNamespace +import random from migen import * from artiq.gateware.drtio.rt_packets import * +from artiq.gateware.drtio.rt_packets import _CrossDomainRequest class PacketInterface: @@ -119,3 +121,50 @@ class TestSatellite(unittest.TestCase): yield run_simulation(dut, [send(), receive()]) self.assertEqual(tx_times, rx_times) + + +class TestCrossDomainRequest(unittest.TestCase): + def test_cross_domain_request(self): + for sys_freq in 3, 6, 11: + for srv_freq in 3, 6, 11: + prng = random.Random(1) + + req_stb = Signal() + req_ack = Signal() + req_data = Signal(8) + srv_stb = Signal() + srv_ack = Signal() + srv_data = Signal(8) + test_seq = [93, 92, 19, 39, 91, 30, 12, 91, 38, 42] + received_seq = [] + + def requester(): + for i in range(len(test_seq)): + yield req_stb.eq(1) + yield + while not (yield req_ack): + yield + received_seq.append((yield req_data)) + yield req_stb.eq(0) + for j in range(prng.randrange(0, 10)): + yield + + def server(): + for data in test_seq: + while not (yield srv_stb): + yield + for j in range(prng.randrange(0, 10)): + yield + yield srv_data.eq(data) + yield srv_ack.eq(1) + yield + yield srv_ack.eq(0) + yield + + dut = _CrossDomainRequest("srv", + req_stb, req_ack, req_data, + srv_stb, srv_ack, srv_data) + run_simulation(dut, + {"sys": requester(), "srv": server()}, + {"sys": sys_freq, "srv": srv_freq}) + self.assertEqual(test_seq, received_seq)