188 lines
5.9 KiB
Python
188 lines
5.9 KiB
Python
from migen.fhdl.std import *
|
|
from migen.actorlib.structuring import *
|
|
from migen.genlib.fsm import FSM, NextState
|
|
from migen.genlib.misc import chooser
|
|
|
|
from misoclib.com.litepcie.core.packet.common import *
|
|
|
|
|
|
class HeaderInserter(Module):
|
|
def __init__(self, dw):
|
|
self.sink = sink = Sink(tlp_raw_layout(dw))
|
|
self.source = source = Source(phy_layout(dw))
|
|
|
|
###
|
|
|
|
fsm = FSM(reset_state="HEADER1")
|
|
self.submodules += fsm
|
|
|
|
sink_dat_r = Signal(dw)
|
|
sink_eop_r = Signal()
|
|
self.sync += \
|
|
If(sink.stb & sink.ack,
|
|
sink_dat_r.eq(sink.dat),
|
|
sink_eop_r.eq(sink.eop)
|
|
)
|
|
|
|
fsm.act("HEADER1",
|
|
sink.ack.eq(1),
|
|
If(sink.stb & sink.sop,
|
|
sink.ack.eq(0),
|
|
source.stb.eq(1),
|
|
source.sop.eq(1),
|
|
source.eop.eq(0),
|
|
source.dat.eq(sink.header[:64]),
|
|
source.be.eq(0xff),
|
|
If(source.stb & source.ack,
|
|
NextState("HEADER2"),
|
|
)
|
|
)
|
|
)
|
|
fsm.act("HEADER2",
|
|
source.stb.eq(1),
|
|
source.sop.eq(0),
|
|
source.eop.eq(sink.eop),
|
|
source.dat.eq(Cat(sink.header[64:96], reverse_bytes(sink.dat[:32]))),
|
|
source.be.eq(Cat(Signal(4, reset=0xf), freversed(sink.be[:4]))),
|
|
If(source.stb & source.ack,
|
|
sink.ack.eq(1),
|
|
If(source.eop,
|
|
NextState("HEADER1")
|
|
).Else(
|
|
NextState("COPY")
|
|
)
|
|
)
|
|
)
|
|
fsm.act("COPY",
|
|
source.stb.eq(sink.stb | sink_eop_r),
|
|
source.sop.eq(0),
|
|
source.eop.eq(sink_eop_r),
|
|
source.dat.eq(Cat(reverse_bytes(sink_dat_r[32:64]), reverse_bytes(sink.dat[:32]))),
|
|
If(sink_eop_r,
|
|
source.be.eq(0x0f)
|
|
).Else(
|
|
source.be.eq(0xff)
|
|
),
|
|
If(source.stb & source.ack,
|
|
sink.ack.eq(~sink_eop_r),
|
|
If(source.eop,
|
|
NextState("HEADER1")
|
|
)
|
|
)
|
|
)
|
|
|
|
|
|
class Packetizer(Module):
|
|
def __init__(self, dw):
|
|
self.req_sink = req_sink = Sink(request_layout(dw))
|
|
self.cmp_sink = cmp_sink = Sink(completion_layout(dw))
|
|
|
|
self.source = Source(phy_layout(dw))
|
|
|
|
###
|
|
|
|
# format TLP request and encode it
|
|
tlp_req = Sink(tlp_request_layout(dw))
|
|
self.comb += [
|
|
tlp_req.stb.eq(req_sink.stb),
|
|
req_sink.ack.eq(tlp_req.ack),
|
|
tlp_req.sop.eq(req_sink.sop),
|
|
tlp_req.eop.eq(req_sink.eop),
|
|
|
|
If(req_sink.we,
|
|
Cat(tlp_req.type, tlp_req.fmt).eq(fmt_type_dict["mem_wr32"])
|
|
).Else(
|
|
Cat(tlp_req.type, tlp_req.fmt).eq(fmt_type_dict["mem_rd32"])
|
|
),
|
|
|
|
tlp_req.tc.eq(0),
|
|
tlp_req.td.eq(0),
|
|
tlp_req.ep.eq(0),
|
|
tlp_req.attr.eq(0),
|
|
tlp_req.length.eq(req_sink.len),
|
|
|
|
tlp_req.requester_id.eq(req_sink.req_id),
|
|
tlp_req.tag.eq(req_sink.tag),
|
|
If(req_sink.len > 1,
|
|
tlp_req.last_be.eq(0xf)
|
|
).Else(
|
|
tlp_req.last_be.eq(0x0)
|
|
),
|
|
tlp_req.first_be.eq(0xf),
|
|
tlp_req.address.eq(req_sink.adr[2:]),
|
|
|
|
tlp_req.dat.eq(req_sink.dat),
|
|
If(req_sink.we,
|
|
tlp_req.be.eq(0xff)
|
|
).Else(
|
|
tlp_req.be.eq(0x00)
|
|
),
|
|
]
|
|
|
|
tlp_raw_req = Sink(tlp_raw_layout(dw))
|
|
self.comb += [
|
|
tlp_raw_req.stb.eq(tlp_req.stb),
|
|
tlp_req.ack.eq(tlp_raw_req.ack),
|
|
tlp_raw_req.sop.eq(tlp_req.sop),
|
|
tlp_raw_req.eop.eq(tlp_req.eop),
|
|
tlp_request_header.encode(tlp_req, tlp_raw_req.header),
|
|
tlp_raw_req.dat.eq(tlp_req.dat),
|
|
tlp_raw_req.be.eq(tlp_req.be),
|
|
]
|
|
|
|
# format TLP completion and encode it
|
|
tlp_cmp = Sink(tlp_completion_layout(dw))
|
|
self.comb += [
|
|
tlp_cmp.stb.eq(cmp_sink.stb),
|
|
cmp_sink.ack.eq(tlp_cmp.ack),
|
|
tlp_cmp.sop.eq(cmp_sink.sop),
|
|
tlp_cmp.eop.eq(cmp_sink.eop),
|
|
|
|
tlp_cmp.tc.eq(0),
|
|
tlp_cmp.td.eq(0),
|
|
tlp_cmp.ep.eq(0),
|
|
tlp_cmp.attr.eq(0),
|
|
tlp_cmp.length.eq(cmp_sink.len),
|
|
|
|
tlp_cmp.completer_id.eq(cmp_sink.cmp_id),
|
|
If(cmp_sink.err,
|
|
Cat(tlp_cmp.type, tlp_cmp.fmt).eq(fmt_type_dict["cpl"]),
|
|
tlp_cmp.status.eq(cpl_dict["ur"])
|
|
).Else(
|
|
Cat(tlp_cmp.type, tlp_cmp.fmt).eq(fmt_type_dict["cpld"]),
|
|
tlp_cmp.status.eq(cpl_dict["sc"])
|
|
),
|
|
tlp_cmp.bcm.eq(0),
|
|
tlp_cmp.byte_count.eq(cmp_sink.len*4),
|
|
|
|
tlp_cmp.requester_id.eq(cmp_sink.req_id),
|
|
tlp_cmp.tag.eq(cmp_sink.tag),
|
|
tlp_cmp.lower_address.eq(cmp_sink.adr),
|
|
|
|
tlp_cmp.dat.eq(cmp_sink.dat),
|
|
tlp_cmp.be.eq(0xff)
|
|
]
|
|
|
|
tlp_raw_cmp = Sink(tlp_raw_layout(dw))
|
|
self.comb += [
|
|
tlp_raw_cmp.stb.eq(tlp_cmp.stb),
|
|
tlp_cmp.ack.eq(tlp_raw_cmp.ack),
|
|
tlp_raw_cmp.sop.eq(tlp_cmp.sop),
|
|
tlp_raw_cmp.eop.eq(tlp_cmp.eop),
|
|
tlp_completion_header.encode(tlp_cmp, tlp_raw_cmp.header),
|
|
tlp_raw_cmp.dat.eq(tlp_cmp.dat),
|
|
tlp_raw_cmp.be.eq(tlp_cmp.be),
|
|
]
|
|
|
|
# arbitrate
|
|
tlp_raw = Sink(tlp_raw_layout(dw))
|
|
self.submodules.arbitrer = Arbiter([tlp_raw_req, tlp_raw_cmp], tlp_raw)
|
|
|
|
# insert header
|
|
header_inserter = HeaderInserter(dw)
|
|
self.submodules += header_inserter
|
|
self.comb += [
|
|
Record.connect(tlp_raw, header_inserter.sink),
|
|
Record.connect(header_inserter.source, self.source)
|
|
]
|