diff --git a/litepcie/common.py b/litepcie/common.py index 9190cd2..74db62a 100644 --- a/litepcie/common.py +++ b/litepcie/common.py @@ -9,6 +9,8 @@ from litex.soc.interconnect.stream import * from litex.soc.interconnect.stream_packet import * +# Constants/Helpers -------------------------------------------------------------------------------- + KB = 1024 MB = 1024*KB GB = 1024*MB @@ -24,6 +26,8 @@ def get_bar_mask(size): size = size >> 1 return mask +# Layouts ------------------------------------------------------------------------------------------ + def phy_layout(data_width): layout = [ ("dat", data_width), @@ -39,8 +43,8 @@ def request_layout(data_width): ("req_id", 16), ("tag", 8), ("dat", data_width), - ("channel", 8), # for routing - ("user_id", 8) # for packet identification + ("channel", 8), # for routing + ("user_id", 8) # for packet identification ] return EndpointDescription(layout) @@ -54,15 +58,14 @@ def completion_layout(data_width): ("err", 1), ("tag", 8), ("dat", data_width), - ("channel", 8), # for routing - ("user_id", 8) # for packet identification + ("channel", 8), # for routing + ("user_id", 8) # for packet identification ] return EndpointDescription(layout) def msi_layout(): return [("dat", 8)] - def dma_layout(data_width): layout = [("data", data_width)] return EndpointDescription(layout) diff --git a/litepcie/core/common.py b/litepcie/core/common.py index dc13c83..5585c11 100644 --- a/litepcie/core/common.py +++ b/litepcie/core/common.py @@ -9,28 +9,28 @@ class LitePCIeSlaveInternalPort: def __init__(self, data_width, address_decoder=None): self.address_decoder = address_decoder - self.sink = stream.Endpoint(completion_layout(data_width)) + self.sink = stream.Endpoint(completion_layout(data_width)) self.source = stream.Endpoint(request_layout(data_width)) class LitePCIeMasterInternalPort: def __init__(self, data_width, channel=None, write_only=False, read_only=False): - self.channel = channel + self.channel = channel self.write_only = write_only - self.read_only = read_only - self.sink = stream.Endpoint(request_layout(data_width)) + self.read_only = read_only + self.sink = stream.Endpoint(request_layout(data_width)) self.source = stream.Endpoint(completion_layout(data_width)) class LitePCIeSlavePort: def __init__(self, port): self.address_decoder = port.address_decoder - self.sink = port.source + self.sink = port.source self.source = port.sink class LitePCIeMasterPort: def __init__(self, port): self.channel = port.channel - self.sink = port.source - self.source = port.sink + self.sink = port.source + self.source = port.sink diff --git a/litepcie/core/crossbar.py b/litepcie/core/crossbar.py index c4d2710..cb4a4e6 100644 --- a/litepcie/core/crossbar.py +++ b/litepcie/core/crossbar.py @@ -7,29 +7,35 @@ from litepcie.core.common import * from litepcie.tlp.controller import LitePCIeTLPController +# -------------------------------------------------------------------------------------------------- class LitePCIeCrossbar(Module): def __init__(self, data_width, max_pending_requests): - self.data_width = data_width + self.data_width = data_width self.max_pending_requests = max_pending_requests - self.master = LitePCIeMasterInternalPort(data_width) - self.slave = LitePCIeSlaveInternalPort(data_width) + self.master = LitePCIeMasterInternalPort(data_width) + self.slave = LitePCIeSlaveInternalPort(data_width) self.phy_master = LitePCIeMasterPort(self.master) - self.phy_slave = LitePCIeSlavePort(self.slave) + self.phy_slave = LitePCIeSlavePort(self.slave) - self.user_masters = [] + self.user_masters = [] self.user_masters_channel = 0 - self.user_slaves = [] + self.user_slaves = [] def get_slave_port(self, address_decoder): - s = LitePCIeSlaveInternalPort(self.data_width, address_decoder) + s = LitePCIeSlaveInternalPort( + data_width = self.data_width, + address_decoder = address_decoder) self.user_slaves.append(s) return LitePCIeSlavePort(s) def get_master_port(self, write_only=False, read_only=False): - m = LitePCIeMasterInternalPort(self.data_width, self.user_masters_channel, - write_only, read_only) + m = LitePCIeMasterInternalPort( + data_width = self.data_width, + channel = self.user_masters_channel, + write_only = write_only, + read_only = read_only) self.user_masters_channel += 1 self.user_masters.append(m) return LitePCIeMasterPort(m) @@ -42,25 +48,25 @@ def filter_masters(self, write_only, read_only): return masters def slave_dispatch_arbitrate(self, slaves, slave): - # dispatch + # Dispatch --------------------------------------------------------------------------------- s_sources = [s.source for s in slaves] s_dispatcher = Dispatcher(slave.source, s_sources, one_hot=True) self.submodules += s_dispatcher for i, s in enumerate(slaves): self.comb += s_dispatcher.sel[i].eq(s.address_decoder(slave.source.adr)) - # arbitrate + # Arbitrate -------------------------------------------------------------------------------- s_sinks = [s.sink for s in slaves] s_arbiter = Arbiter(s_sinks, slave.sink) self.submodules += s_arbiter def master_arbitrate_dispatch(self, masters, master, dispatch=True): - # arbitrate + # Arbitrate -------------------------------------------------------------------------------- m_sinks = [m.sink for m in masters] m_arbiter = Arbiter(m_sinks, master.sink) self.submodules += m_arbiter - # dispatch + # Dispatch --------------------------------------------------------------------------------- if dispatch: m_sources = [m.source for m in masters] m_dispatcher = Dispatcher(master.source, m_sources, one_hot=True) @@ -69,17 +75,17 @@ def master_arbitrate_dispatch(self, masters, master, dispatch=True): if m.channel is not None: self.comb += m_dispatcher.sel[i].eq(master.source.channel == m.channel) else: - # connect to first master + # Connect to first master self.comb += master.source.connect(masters[0].source) def do_finalize(self): - # Slave path + # Slave path ------------------------------------------------------------------------------- # Dispatch request to user sources (according to address decoder) # Arbitrate completion from user sinks if self.user_slaves != []: self.slave_dispatch_arbitrate(self.user_slaves, self.slave) - # Master path + # Master path ------------------------------------------------------------------------------ # Abritrate requests from user sinks # Dispatch completion to user sources (according to channel) @@ -106,7 +112,7 @@ def do_finalize(self): if self.user_masters != []: masters = [] - # Arbitrate / dispatch read_only / read_write ports + # Arbitrate / dispatch read_only / read_write ports ------------------------------------ # and insert controller rd_rw_masters = self.filter_masters(False, True) rd_rw_masters += self.filter_masters(False, False) @@ -118,12 +124,12 @@ def do_finalize(self): self.master_arbitrate_dispatch(rd_rw_masters, controller.master_in) masters.append(controller.master_out) - # Arbitrate / dispatch write_only ports + # Arbitrate / dispatch write_only ports ------------------------------------------------ wr_masters = self.filter_masters(True, False) if wr_masters != []: wr_master = LitePCIeMasterInternalPort(self.data_width) self.master_arbitrate_dispatch(wr_masters, wr_master) masters.append(wr_master) - # Final Arbitrate / dispatch stage + # Final Arbitrate / dispatch stage ----------------------------------------------------- self.master_arbitrate_dispatch(masters, self.master, False) diff --git a/litepcie/core/endpoint.py b/litepcie/core/endpoint.py index 97d30dd..4811be2 100644 --- a/litepcie/core/endpoint.py +++ b/litepcie/core/endpoint.py @@ -9,35 +9,36 @@ from litepcie.tlp.packetizer import LitePCIeTLPPacketizer from litepcie.core.crossbar import LitePCIeCrossbar +# -------------------------------------------------------------------------------------------------- class LitePCIeEndpoint(Module): def __init__(self, phy, max_pending_requests=4, endianness="big"): - self.phy = phy + self.phy = phy self.max_pending_requests = max_pending_requests # # # - # TLP Packetizer / Depacketizer + # TLP Packetizer / Depacketizer ------------------------------------------------------------ depacketizer = LitePCIeTLPDepacketizer(phy.data_width, endianness, phy.bar0_mask) - packetizer = LitePCIeTLPPacketizer(phy.data_width, endianness) + packetizer = LitePCIeTLPPacketizer(phy.data_width, endianness) self.submodules.depacketizer = depacketizer - self.submodules.packetizer = packetizer + self.submodules.packetizer = packetizer self.comb += [ phy.source.connect(depacketizer.sink), packetizer.source.connect(phy.sink) ] - # Crossbar + # Crossbar --------------------------------------------------------------------------------- crossbar = LitePCIeCrossbar(phy.data_width, max_pending_requests) self.submodules.crossbar = crossbar - # (Slave) HOST initiates the transactions + # Slave: HOST initiates the transactions --------------------------------------------------- self.comb += [ depacketizer.req_source.connect(crossbar.phy_slave.sink), crossbar.phy_slave.source.connect(packetizer.cmp_sink) ] - # (Master) FPGA initiates the transactions + # Master: FPGA initiates the transactions -------------------------------------------------- self.comb += [ crossbar.phy_master.source.connect(packetizer.req_sink), depacketizer.cmp_source.connect(crossbar.phy_master.sink) diff --git a/litepcie/core/msi.py b/litepcie/core/msi.py index fa2aeed..f77e1a1 100644 --- a/litepcie/core/msi.py +++ b/litepcie/core/msi.py @@ -4,6 +4,7 @@ from litepcie.common import * +# -------------------------------------------------------------------------------------------------- class LitePCIeMSI(Module, AutoCSR): def __init__(self, width=32): diff --git a/litepcie/frontend/wishbone.py b/litepcie/frontend/wishbone.py index c7f44c4..824a749 100644 --- a/litepcie/frontend/wishbone.py +++ b/litepcie/frontend/wishbone.py @@ -70,7 +70,7 @@ def __init__(self, endpoint, address_decoder, shadow_base=0x00000000, qword_alig port.source.cmp_id.eq(endpoint.phy.id), port.source.req_id.eq(port.sink.req_id), If(update_dat, - port.source.dat.eq(self.wishbone.dat_r), + port.source.dat.eq(self.wishbone.dat_r) ) ] fsm.act("COMPLETION", diff --git a/litepcie/phy/c5pciephy.py b/litepcie/phy/c5pciephy.py index 07d7591..20403c5 100644 --- a/litepcie/phy/c5pciephy.py +++ b/litepcie/phy/c5pciephy.py @@ -128,13 +128,12 @@ def convert_size(command, size): self.id.eq(Cat(function_number, device_number, bus_number)) ] - # To capture configuration space Register - # register LSB bit of tl_cfg_add + # To capture configuration space Register, register LSB bit of tl_cfg_add self.sync.pcie += [ tl_cfg_add_reg_lsb.eq(pcie_config_tl_tl_cfg_add[0]), tl_cfg_add_reg2_lsb.eq(tl_cfg_add_reg_lsb) ] - # detect the address change to generate a strobe to sample the input 32-bit data + # Detect the address change to generate a strobe to sample the input 32-bit data self.sync.pcie += [ cfgctl_addr_change.eq(tl_cfg_add_reg_lsb != tl_cfg_add_reg2_lsb), cfgctl_addr_change2.eq(cfgctl_addr_change), @@ -159,9 +158,9 @@ def convert_size(command, size): ) ] - # tl_cfg_add[6:4] should represent function number whose information is - # being presented on tl_cfg_ctl, but only one function is enabled on IP core - # in this case function_number is always 0 + # tl_cfg_add[6:4] should represent function number whose information is being presented on + # tl_cfg_ctl, but only one function is enabled on IP core in this case function_number is + # always 0 self.comb += function_number.eq(0) # Native stream <--> AvalonST -------------------------------------------------------------- diff --git a/litepcie/tlp/common.py b/litepcie/tlp/common.py index 5b4ecd7..a5f0511 100644 --- a/litepcie/tlp/common.py +++ b/litepcie/tlp/common.py @@ -5,7 +5,8 @@ from litepcie.common import * -# constants +# Constants ---------------------------------------------------------------------------------------- + fmt_type_dict = { "mem_rd32": 0b0000000, "mem_wr32": 0b1000000, @@ -26,7 +27,8 @@ max_payload_size = 512 max_request_size = 512 -# headers +# Headers ------------------------------------------------------------------------------------------ + tlp_common_header_length = 16 tlp_common_header_fields = { "fmt": HeaderField(0*4, 29, 2), @@ -82,14 +84,14 @@ tlp_completion_header_length, swap_field_bytes=False) -# helpers +# Helpers ------------------------------------------------------------------------------------------ def convert_bytes(s, endianness="big"): return reverse_bytes(s) if endianness == "big" else s def convert_bits(s, endianness="big"): return reverse_bits(s) if endianness == "big" else s -# layouts +# Layouts ------------------------------------------------------------------------------------------ def tlp_raw_layout(data_width): layout = [ ("header", 4*32), diff --git a/litepcie/tlp/depacketizer.py b/litepcie/tlp/depacketizer.py index 3d39ac5..96aa024 100644 --- a/litepcie/tlp/depacketizer.py +++ b/litepcie/tlp/depacketizer.py @@ -5,20 +5,20 @@ from litepcie.tlp.common import * +# LitePCIeTLPHeaderExtracter64b -------------------------------------------------------------------- class LitePCIeTLPHeaderExtracter64b(Module): def __init__(self, endianness): - self.sink = sink = stream.Endpoint(phy_layout(64)) + self.sink = sink = stream.Endpoint(phy_layout(64)) self.source = source = stream.Endpoint(tlp_raw_layout(64)) # # # first = Signal() - last = Signal() + last = Signal() count = Signal() - - dat = Signal(64, reset_less=True) - be = Signal(64//8, reset_less=True) + dat = Signal(64, reset_less=True) + be = Signal(64//8, reset_less=True) self.sync += \ If(sink.valid & sink.ready, dat.eq(sink.dat), @@ -36,10 +36,10 @@ def __init__(self, endianness): sink.ready.eq(1), If(sink.valid, NextValue(count, count + 1), - NextValue(self.source.header[32*0:32*1], self.source.header[32*2:32*3]), - NextValue(self.source.header[32*1:32*2], self.source.header[32*3:32*4]), - NextValue(self.source.header[32*2:32*3], sink.dat[32*0:32*1]), - NextValue(self.source.header[32*3:32*4], sink.dat[32*1:32*2]), + NextValue(source.header[32*0:32*1], source.header[32*2:32*3]), + NextValue(source.header[32*1:32*2], source.header[32*3:32*4]), + NextValue(source.header[32*2:32*3], sink.dat[32*0:32*1]), + NextValue(source.header[32*3:32*4], sink.dat[32*1:32*2]), If(count, If(sink.last, NextValue(last, 1)), NextState("COPY") @@ -63,19 +63,19 @@ def __init__(self, endianness): source.be[4*1:4*2].eq(convert_bits(sink.be[4*0:4*1], endianness)) ] +# LitePCIeTLPHeaderExtracter128b ------------------------------------------------------------------- class LitePCIeTLPHeaderExtracter128b(Module): def __init__(self, endianness): - self.sink = sink = stream.Endpoint(phy_layout(128)) + self.sink = sink = stream.Endpoint(phy_layout(128)) self.source = source = stream.Endpoint(tlp_raw_layout(128)) # # # first = Signal() - last = Signal() - - dat = Signal(128, reset_less=True) - be = Signal(128//8, reset_less=True) + last = Signal() + dat = Signal(128, reset_less=True) + be = Signal(128//8, reset_less=True) self.sync += \ If(sink.valid & sink.ready, dat.eq(sink.dat), @@ -93,11 +93,13 @@ def __init__(self, endianness): fsm.act("HEADER", sink.ready.eq(1), If(sink.valid, - NextValue(self.source.header[32*0:32*1], sink.dat[32*0:32*1]), - NextValue(self.source.header[32*1:32*2], sink.dat[32*1:32*2]), - NextValue(self.source.header[32*2:32*3], sink.dat[32*2:32*3]), - NextValue(self.source.header[32*3:32*4], sink.dat[32*3:32*4]), - If(sink.last, NextValue(last, 1)), + NextValue(source.header[32*0:32*1], sink.dat[32*0:32*1]), + NextValue(source.header[32*1:32*2], sink.dat[32*1:32*2]), + NextValue(source.header[32*2:32*3], sink.dat[32*2:32*3]), + NextValue(source.header[32*3:32*4], sink.dat[32*3:32*4]), + If(sink.last, + NextValue(last, 1) + ), NextState("COPY") ) ) @@ -124,17 +126,17 @@ def __init__(self, endianness): source.be[4*1:4*2].eq(convert_bits(sink.be[4*2:4*3], endianness)) ] +# LitePCIeTLPDepacketizer -------------------------------------------------------------------------- class LitePCIeTLPDepacketizer(Module): def __init__(self, data_width, endianness, address_mask=0): - self.sink = stream.Endpoint(phy_layout(data_width)) - + self.sink = stream.Endpoint(phy_layout(data_width)) self.req_source = stream.Endpoint(request_layout(data_width)) self.cmp_source = stream.Endpoint(completion_layout(data_width)) # # # - # extract raw header + # Extract raw header ----------------------------------------------------------------------- header_extracter_cls = { 64 : LitePCIeTLPHeaderExtracter64b, 128 : LitePCIeTLPHeaderExtracter128b, @@ -144,10 +146,9 @@ def __init__(self, data_width, endianness, address_mask=0): self.comb += self.sink.connect(header_extracter.sink) header = header_extracter.source.header - - # dispatch data according to fmt/type + # Dispatch data according to fmt/type ------------------------------------------------------ dispatch_source = stream.Endpoint(tlp_common_layout(data_width)) - dispatch_sinks = [stream.Endpoint(tlp_common_layout(data_width)) for i in range(2)] + dispatch_sinks = [stream.Endpoint(tlp_common_layout(data_width)) for i in range(2)] self.comb += [ dispatch_source.valid.eq(header_extracter.source.valid), @@ -162,16 +163,15 @@ def __init__(self, data_width, endianness, address_mask=0): self.submodules.dispatcher = Dispatcher(dispatch_source, dispatch_sinks) fmt_type = Cat(dispatch_source.type, dispatch_source.fmt) - self.comb += \ - If((fmt_type == fmt_type_dict["mem_rd32"]) | - (fmt_type == fmt_type_dict["mem_wr32"]), + self.comb += [ + If((fmt_type == fmt_type_dict["mem_rd32"]) | (fmt_type == fmt_type_dict["mem_wr32"]), self.dispatcher.sel.eq(0), - ).Elif((fmt_type == fmt_type_dict["cpld"]) | - (fmt_type == fmt_type_dict["cpl"]), - self.dispatcher.sel.eq(1), + ).Elif((fmt_type == fmt_type_dict["cpld"]) | (fmt_type == fmt_type_dict["cpl"]), + self.dispatcher.sel.eq(1) ) + ] - # decode TLP request and format local request + # Decode TLP request and format local request ---------------------------------------------- self.tlp_req = tlp_req = stream.Endpoint(tlp_request_layout(data_width)) self.comb += dispatch_sinks[0].connect(tlp_req) self.comb += tlp_request_header.decode(header, tlp_req) @@ -179,8 +179,8 @@ def __init__(self, data_width, endianness, address_mask=0): req_source = self.req_source self.comb += [ req_source.valid.eq(tlp_req.valid), - req_source.we.eq(tlp_req.valid & (Cat(tlp_req.type, tlp_req.fmt) == - fmt_type_dict["mem_wr32"])), + req_source.we.eq(tlp_req.valid & + (Cat(tlp_req.type, tlp_req.fmt) == fmt_type_dict["mem_wr32"])), tlp_req.ready.eq(req_source.ready), req_source.first.eq(tlp_req.first), req_source.last.eq(tlp_req.last), @@ -188,10 +188,10 @@ def __init__(self, data_width, endianness, address_mask=0): req_source.len.eq(tlp_req.length), req_source.req_id.eq(tlp_req.requester_id), req_source.tag.eq(tlp_req.tag), - req_source.dat.eq(tlp_req.dat), + req_source.dat.eq(tlp_req.dat) ] - # decode TLP completion and format local completion + # Decode TLP completion and format local completion ---------------------------------------- self.tlp_cmp = tlp_cmp = stream.Endpoint(tlp_completion_layout(data_width)) self.comb += dispatch_sinks[1].connect(tlp_cmp) self.comb += tlp_completion_header.decode(header, tlp_cmp) diff --git a/litepcie/tlp/packetizer.py b/litepcie/tlp/packetizer.py index 10ce6d6..0b550c4 100644 --- a/litepcie/tlp/packetizer.py +++ b/litepcie/tlp/packetizer.py @@ -6,15 +6,16 @@ from litepcie.tlp.common import * +# LitePCIeTLPHeaderInserter64b --------------------------------------------------------------------- class LitePCIeTLPHeaderInserter64b(Module): def __init__(self, endianness): - self.sink = sink = stream.Endpoint(tlp_raw_layout(64)) + self.sink = sink = stream.Endpoint(tlp_raw_layout(64)) self.source = source = stream.Endpoint(phy_layout(64)) # # # - dat = Signal(64, reset_less=True) + dat = Signal(64, reset_less=True) last = Signal(reset_less=True) self.sync += \ If(sink.valid & sink.ready, @@ -80,15 +81,16 @@ def __init__(self, endianness): ) ) +# LitePCIeTLPHeaderInserter128b -------------------------------------------------------------------- class LitePCIeTLPHeaderInserter128b(Module): def __init__(self, endianness): - self.sink = sink = stream.Endpoint(tlp_raw_layout(128)) + self.sink = sink = stream.Endpoint(tlp_raw_layout(128)) self.source = source = stream.Endpoint(phy_layout(128)) # # # - dat = Signal(128, reset_less=True) + dat = Signal(128, reset_less=True) last = Signal(reset_less=True) self.sync += \ If(sink.valid & sink.ready, @@ -151,17 +153,17 @@ def __init__(self, endianness): ) ) +# LitePCIeTLPPacketizer ---------------------------------------------------------------------------- class LitePCIeTLPPacketizer(Module): def __init__(self, data_width, endianness): self.req_sink = req_sink = stream.Endpoint(request_layout(data_width)) self.cmp_sink = cmp_sink = stream.Endpoint(completion_layout(data_width)) - - self.source = stream.Endpoint(phy_layout(data_width)) + self.source = stream.Endpoint(phy_layout(data_width)) # # # - # format TLP request and encode it + # Format TLP request and encode it --------------------------------------------------------- self.tlp_req = tlp_req = stream.Endpoint(tlp_request_layout(data_width)) self.comb += [ tlp_req.valid.eq(req_sink.valid), @@ -196,7 +198,7 @@ def __init__(self, data_width, endianness): tlp_req.be.eq(0xff) ).Else( tlp_req.be.eq(0x00) - ), + ) ] tlp_raw_req = stream.Endpoint(tlp_raw_layout(data_width)) @@ -207,10 +209,10 @@ def __init__(self, data_width, endianness): tlp_raw_req.last.eq(tlp_req.last), 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), + tlp_raw_req.be.eq(tlp_req.be) ] - # format TLP completion and encode it + # Format TLP completion and encode it ------------------------------------------------------ self.tlp_cmp = tlp_cmp = stream.Endpoint(tlp_completion_layout(data_width)) self.comb += [ tlp_cmp.valid.eq(cmp_sink.valid), @@ -251,14 +253,14 @@ def __init__(self, data_width, endianness): tlp_raw_cmp.last.eq(tlp_cmp.last), 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), + tlp_raw_cmp.be.eq(tlp_cmp.be) ] - # arbitrate + # Arbitrate -------------------------------------------------------------------------------- tlp_raw = stream.Endpoint(tlp_raw_layout(data_width)) self.submodules.arbitrer = Arbiter([tlp_raw_req, tlp_raw_cmp], tlp_raw) - # insert header + # Insert header ---------------------------------------------------------------------------- header_inserter_cls = { 64 : LitePCIeTLPHeaderInserter64b, 128 : LitePCIeTLPHeaderInserter128b