diff --git a/examples/protocols/pcie/pcie-conn.stanza b/examples/protocols/pcie/pcie-conn.stanza new file mode 100644 index 00000000..e469a01e --- /dev/null +++ b/examples/protocols/pcie/pcie-conn.stanza @@ -0,0 +1,155 @@ +#use-added-syntax(jitx) +defpackage jsl/examples/protocols/pcie/pcie-conn : + import core + import jitx + import jitx/commands + + import jsl + +; This is primarily just a placeholder for a +; real PCIe connector. +val SSOP-pkg = SOP( + num-leads = 32, + lead-profile = Lead-Profile( + span = min-max(6.2, 6.6), + pitch = 0.65, + lead = SOP-Lead( + length = min-max(0.5, 0.75), + width = min-max(0.19, 0.3) + ) + ), + package-body = PackageBody( + width = min-max(4.3, 4.5) + length = min-max(4.9, 5.1) + height = min-max(1.0, 1.2) + ), + density-level = DensityLevelC + ) + + + +public pcb-component component : + reference-prefix = "J" + mpn = "JITX002" + description = "Dummy PCIe Connector with multiple PCIe supports" + + port REFCLK : diff-pair + port LANE : lane-pair[4] + + pin-properties : + [pin:Ref | pads:Int ... ] + + [REFCLK.N | 1 ] + [REFCLK.P | 2 ] + [GND[0] | 3 ] + + [LANE[0].TX.P | 4 ] + [LANE[0].TX.N | 5 ] + [GND[1] | 6 ] + [LANE[0].RX.P | 7 ] + [LANE[0].RX.N | 8 ] + [GND[2] | 9 ] + + [LANE[1].TX.P | 10 ] + [LANE[1].TX.N | 11 ] + [GND[3] | 12 ] + [LANE[1].RX.P | 13] + [LANE[1].RX.N | 14 ] + [GND[4] | 15 ] + [PRSNT# | 16 ] + + [GND[5] | 17 ] + [LANE[2].TX.P | 18 ] + [LANE[2].TX.N | 19 ] + [GND[6] | 20 ] + [LANE[2].RX.P | 21 ] + [LANE[2].RX.N | 22 ] + [GND[7] | 23 ] + + [LANE[3].TX.P | 24 ] + [LANE[3].TX.N | 25 ] + [GND[8] | 26 ] + [LANE[3].RX.P | 27 ] + [LANE[3].RX.N | 28 ] + [GND[9] | 29 ] + + [PERST# | 30 ] + [PEWAKE# | 31 ] + [CLKREQ# | 32 ] + + + + val box = BoxSymbol(self) + + set-side(Left, self.GND, self.PERST#, self.PEWAKE#, self.CLKREQ#, self.PRSNT#) + set-side(Right, self.LANE, self.REFCLK) + + assign-symbol $ create-symbol(box) + + val lp = create-landpattern(SSOP-pkg) + assign-landpattern(lp) + + + for i in 0 to 4 do : + diff-pin-model(self.LANE[i].TX.P, LANE[i].TX.N, delay = typ(10.0e-15) loss = typ(0.1)) + diff-pin-model(self.LANE[i].RX.P, LANE[i].RX.N, delay = typ(10.0e-15) loss = typ(0.1)) + + diff-pin-model(self.REFCLK.P, self.REFCLK.N, delay = typ(10.0e-15) loss = typ(0.1)) + + +doc: \ +Helper function for creating the necessary PCIe Supports Statements + +The user must pass a bundle type, such as `pcie-std()` and +this will construct a supports statement that will connect +the bundle ports to the predefined `self.sw` instance of the +`compponent` connector. + +defn connect_lanes (b:Bundle): + inside pcb-module: + supports b: + for i in indices(b.data.lane) do : + b.data.lane[i].RX.P => self.sw.LANE[i].RX.P + b.data.lane[i].RX.N => self.sw.LANE[i].RX.N + b.data.lane[i].TX.P => self.sw.LANE[i].TX.P + b.data.lane[i].TX.N => self.sw.LANE[i].TX.N + b.data.refclk.P => self.sw.REFCLK.P + b.data.refclk.N => self.sw.REFCLK.N + + b.control.PEWAKE# => self.sw.PEWAKE# + b.control.PERST# => self.sw.PERST# + b.control.CLKREQ# => self.sw.CLKREQ# + + if has-PRSNT#(b): + b.control.PRSNT# => self.sw.PRSNT# + + +doc: \ +PCIe Connector Module with Exposed Pin-Assigned PCIe ports + +User must use: + +``` +inst dut : jsl/examples/protocols/pcie/pcie-conn/module +require pcie-1x:pcie-std(1) from dut +``` + +To access one of the PCIe interface. + +public pcb-module module : + + public inst sw : component + + val bundle-types = [ + pcie-std(4), + pcie-std(2), + pcie-std(1), + pcie-with-hotplug(4), + pcie-with-hotplug(2), + pcie-with-hotplug(1), + ] + + for btype in bundle-types do: + connect_lanes(btype) + + diff --git a/examples/protocols/pcie/pcie-main.stanza b/examples/protocols/pcie/pcie-main.stanza index e2383558..cfa41732 100644 --- a/examples/protocols/pcie/pcie-main.stanza +++ b/examples/protocols/pcie/pcie-main.stanza @@ -24,53 +24,25 @@ pcb-module pcie-example : val b-cap = block-cap(220.0e-9) - ; Construct a typical passive connector setup - ; for a 2 lane configuration. This means a - ; straight through `tx => tx` and `rx => rx` - ; configuration. - - require src-ep : pcie(2) from dut1 - require dst-ep : pcie(2) from dut2 - - within [src, dst] = constrain-topology(src-ep, dst-ep, cst): - ; Here we construct the circuit topology for the link - ; Note that we don't need to worry about any of the constraint - ; application, as that is handled by the `PCIe-Constraint` type. - ; You can add other components in the topology as you wish - below - ; is a typical basic implementation. - for i in indices(src.data.lane) do: - inst tx-coupler : dp-coupler(b-cap) - topo-pair(src.data.lane[i].TX => tx-coupler => dst.data.lane[i].TX) - ; No Blocking Caps on the Receive side. - topo-net(src.data.lane[i].RX => dst.data.lane[i].RX) - - topo-net(src.data.refclk => dst.data.refclk) - ; The control signals do not demand a topology so - ; we just use a straight net connection. - net (src.control, dst.control) - ; Setup an example of an active to active connection between ; two ICs (ie not to a connector). In this case, we need ; a null-modem style connection and blocking caps on both rx and ; tx. - ; Notice that the `reverse-pcie-lane` function handles the null-modem - ; swap. We continue to use `tx => tx` and `rx => rx` inside for - ; consistency. - require src-IC : pcie(2, PCIe-PRSNT#) from dut1 - require dst-IC : pcie(2, PCIe-PRSNT#) from dut2 + require src-IC : pcie-with-hotplug(1) from dut1 + require dst-IC : pcie-with-hotplug(1) from dut2 ; TODO - the routing structure is not applying through the node here. - within [src, dst-straight] = constrain-topology(src-IC, dst-IC, cst): - ; Notice that the `reverse-pcie-lane` function handles the null-modem - ; swap. We continue to use `tx => tx` and `rx => rx` inside for - ; consistency. - val dst = reverse-pcie-lanes(dst-straight) + within [src, dst] = constrain-topology(src-IC, dst-IC, cst): for i in indices(src.data.lane) do: + ; We reverse the Tx/Rx in a null-modem style for active->active connection. + val lane-Rx = dst.data.lane[i].TX + val lane-Tx = dst.data.lane[i].RX + inst tx-coupler : dp-coupler(b-cap) - topo-pair(src.data.lane[i].TX => tx-coupler => dst.data.lane[i].TX) + topo-pair(src.data.lane[i].TX => tx-coupler => lane-Tx) inst rx-coupler : dp-coupler(b-cap) - topo-pair(src.data.lane[i].RX => rx-coupler => dst.data.lane[i].RX) + topo-pair(src.data.lane[i].RX => rx-coupler => lane-Rx) topo-net(src.data.refclk => dst.data.refclk) net (src.control, dst.control) diff --git a/examples/protocols/pcie/pcie-shared-wake.stanza b/examples/protocols/pcie/pcie-shared-wake.stanza new file mode 100644 index 00000000..48fb4d36 --- /dev/null +++ b/examples/protocols/pcie/pcie-shared-wake.stanza @@ -0,0 +1,79 @@ +#use-added-syntax(jitx) +defpackage jsl/examples/protocols/pcie/main: + import core + import collections + import jitx + import jitx/commands + + + import jsl + + import jsl/examples/protocols/common/example-board + import jsl/examples/protocols/common/example-components + import jsl/examples/protocols/pcie/pcie-src + + +pcb-module pcie-example : + + inst dut1 : jsl/examples/protocols/pcie/pcie-src/module + inst conns : jsl/examples/protocols/pcie/pcie-conn/module[2] + + val version = PCIE-V4 + val trace-imped = pcie-get-trace-impedance(version) + val cst = PCIe-Constraint(version, diff(trace-imped)) + + val b-cap = block-cap(220.0e-9) + + ; Construct a typical passive connector setup + ; for a 2 lane configuration. This means a + ; straight through `tx => tx` and `rx => rx` + ; configuration. + ; + ; The two connectors share the one wake pin from the IC source module + val pcie-btype = pcie-std(2) + for i in 0 to 2 do: + require dst-ep : pcie-btype from conns[i] + require src-ep : pcie-btype from dut1 + + within [src, dst] = constrain-topology(src-ep, dst-ep, cst): + ; Here we construct the circuit topology for the link + ; Note that we don't need to worry about any of the constraint + ; application, as that is handled by the `PCIe-Constraint` type. + ; You can add other components in the topology as you wish - below + ; is a typical basic implementation. + for i in indices(src.data.lane) do: + inst tx-coupler : dp-coupler(b-cap) + topo-pair(src.data.lane[i].TX => tx-coupler => dst.data.lane[i].TX) + ; No Blocking Caps on the Receive side. + topo-net(src.data.lane[i].RX => dst.data.lane[i].RX) + + topo-net(src.data.refclk => dst.data.refclk) + ; The control signals do not demand a topology so + ; we just use a straight net connection. + net (src.control.PERST#, dst.control.PERST#) + net (src.control.CLKREQ#, dst.control.CLKREQ#) + + ; Notice that this is a direct connection that doesn't use + ; the pin assigned bundles. This is how we make a shared + ; connection. It must be out of band from the pin assignment solution. + ; Note that this will not work for topologies with the `constrain-topology` + ; structure unless you make a custom `SI-Constraint` object that is aware + ; of the shared topology and then apply constraints from the top level. + net (dut1.shared_wake, dst.control.PEWAKE#) + + + + +set-current-design("pcie-example-2") +setup-board() +; Set the schematic sheet size +set-paper(ANSI-A) + +; Set the top level module (the module to be compile into a schematic and PCB) +set-main-module(pcie-example) + +; View the results +view-board() +view-schematic() +view-design-explorer() +; view-bom(BOM-STD) diff --git a/examples/protocols/pcie/pcie-src.stanza b/examples/protocols/pcie/pcie-src.stanza index 6efe1682..01daf983 100644 --- a/examples/protocols/pcie/pcie-src.stanza +++ b/examples/protocols/pcie/pcie-src.stanza @@ -26,17 +26,19 @@ public pcb-component component : mpn = "JITX001" description = "Dummy device with multiple PCIe supports" + port REFCLK : diff-pair[4] + pin-properties : [pin:Ref | pads:Ref ... ] - [REFCLKN[0] | A[1] ] - [REFCLKP[0] | A[2] ] - [REFCLKP[1] | D[4] ] - [REFCLKN[1] | D[3] ] - [REFCLKP[2] | D[2] ] - [REFCLKN[2] | D[1] ] - [REFCLKP[3] | C[7] ] - [REFCLKN[3] | C[6] ] + [REFCLK[0].N | A[1] ] + [REFCLK[0].P | A[2] ] + [REFCLK[1].P | D[4] ] + [REFCLK[1].N | D[3] ] + [REFCLK[2].P | D[2] ] + [REFCLK[2].N | D[1] ] + [REFCLK[3].P | C[7] ] + [REFCLK[3].N | C[6] ] [PTXP[0] | B[3] ] [PTXN[0] | B[2] ] @@ -104,7 +106,7 @@ public pcb-component component : set-side(Right, self.PTXP, self.PTXN, self.PRXP, self.PRXN) set-bank(ctl-r, self.GPIO, self.PERST#) - set-bank(ctl-r, self.REFCLKP, self.REFCLKN) + set-bank(ctl-r, self.REFCLK) set-group("reset-grp", self.PERST#) @@ -115,10 +117,10 @@ public pcb-component component : for i in 0 to 4 do: val name = to-string $ "ref-clk-%_" % [i] - set-group(name, self.REFCLKP[i], self.REFCLKN[i] ) + set-group(name, self.REFCLK[i].P, self.REFCLK[i].N ) set-head-margin(box, 0.5, name) - set-side(Right, self.REFCLKP, self.REFCLKN) + set-side(Right, self.REFCLK) assign-symbols( ctl-r => box, @@ -132,117 +134,100 @@ public pcb-component component : for i in 0 to 4 do : diff-pin-model(self.PRXP[i], self.PRXN[i], delay = typ(10.0e-15) loss = typ(0.1)) diff-pin-model(self.PTXP[i], self.PTXN[i], delay = typ(10.0e-15) loss = typ(0.1)) - diff-pin-model(self.REFCLKP[i], self.REFCLKN[i], delay = typ(10.0e-15) loss = typ(0.1)) + diff-pin-model(self.REFCLK[i].P, self.REFCLK[i].N, delay = typ(10.0e-15) loss = typ(0.1)) + + + +defn connect_lanes ( + b:Bundle, + ref_clk:JITXObject, + ctl_lines:[JITXObject, JITXObject, JITXObject], + present:JITXObject|False, + -- + ch-offset:Int = 0 + ): + val [wake, reset, clkreq] = ctl_lines + inside pcb-module: + supports b: + for i in indices(b.data.lane) do : + b.data.lane[i].RX.P => self.sw.PRXP[i + ch-offset] + b.data.lane[i].RX.N => self.sw.PRXN[i + ch-offset] + b.data.lane[i].TX.P => self.sw.PTXP[i + ch-offset] + b.data.lane[i].TX.N => self.sw.PTXN[i + ch-offset] + b.data.refclk.P => ref_clk.P + b.data.refclk.N => ref_clk.N + + if has-PEWAKE#(b): + b.control.PEWAKE# => wake + if has-PERST#(b): + b.control.PERST# => reset + if has-CLKREQ#(b): + b.control.CLKREQ# => clkreq + + if has-PRSNT#(b): + match(present): + (_:False): + throw $ ValueError("Missing Present Connection - Passed False") + (p:JITXObject): + b.control.PRSNT# => p public pcb-module module : public inst sw : component - val bd-4x = pcie(4) - supports bd-4x : - for i in 0 to 4 do : - bd-4x.data.lane[i].RX.P => sw.PRXP[i] - bd-4x.data.lane[i].RX.N => sw.PRXN[i] - bd-4x.data.lane[i].TX.P => sw.PTXP[i] - bd-4x.data.lane[i].TX.N => sw.PTXN[i] - bd-4x.data.refclk.P => sw.REFCLKP[0] - bd-4x.data.refclk.N => sw.REFCLKN[0] - - bd-4x.control.PEWAKE# => sw.GPIO[5] - bd-4x.control.PERST# => sw.PERST#[0] - bd-4x.control.CLKREQ# => sw.GPIO[1] - - val bd-4x-prsnt = pcie(4, PCIe-PRSNT#) - supports bd-4x-prsnt : - for i in 0 to 4 do : - bd-4x-prsnt.data.lane[i].RX.P => sw.PRXP[i] - bd-4x-prsnt.data.lane[i].RX.N => sw.PRXN[i] - bd-4x-prsnt.data.lane[i].TX.P => sw.PTXP[i] - bd-4x-prsnt.data.lane[i].TX.N => sw.PTXN[i] - bd-4x-prsnt.data.refclk.P => sw.REFCLKP[0] - bd-4x-prsnt.data.refclk.N => sw.REFCLKN[0] - - bd-4x-prsnt.control.PEWAKE# => sw.GPIO[5] - bd-4x-prsnt.control.PERST# => sw.PERST#[0] - bd-4x-prsnt.control.PRSNT# => sw.GPIO[12] - bd-4x-prsnt.control.CLKREQ# => sw.GPIO[1] + ; Optional Connection to demonstrate shared + ; pins across pin assigned bundles. + port shared_wake + + net (shared_wake, sw.GPIO[7]) + + ;;;;;;;;;;;;;;;;;;;;;;; + ; PCIe 4x + ;;;;;;;;;;;;;;;;;;;;;;; + + + val bd-4x = pcie-std(4) + connect_lanes(bd-4x, self.sw.REFCLK[0], [sw.GPIO[8], sw.PERST#[0], sw.GPIO[1]], false) + + val bd-4x-prsnt = pcie-with-hotplug(4) + connect_lanes(bd-4x-prsnt, self.sw.REFCLK[0], [sw.GPIO[8], sw.PERST#[0], sw.GPIO[1]], sw.GPIO[12]) + + ;;;;;;;;;;;;;;;;;;;;;;; + ; PCIe 1x + ;;;;;;;;;;;;;;;;;;;;;;; + + val bd-1x = pcie-std(1) + val bd-1x-prsnt = pcie-with-hotplug(1) - val ctls-2x = [ - [sw.GPIO[6], sw.GPIO[12], sw.GPIO[1]] - [sw.GPIO[7], sw.GPIO[13], sw.GPIO[2]] - ] - val bd-2x = pcie(2) - for j in 0 to 2 do: - supports bd-2x: - val ch-offset = (2 * j) - for i in 0 to 2 do : - bd-2x.data.lane[i].RX.P => sw.PRXP[i + ch-offset] - bd-2x.data.lane[i].RX.N => sw.PRXN[i + ch-offset] - bd-2x.data.lane[i].TX.P => sw.PTXP[i + ch-offset] - bd-2x.data.lane[i].TX.N => sw.PTXN[i + ch-offset] - bd-2x.data.refclk.P => sw.REFCLKP[ch-offset] - bd-2x.data.refclk.N => sw.REFCLKN[ch-offset] - - val [wake, present, clkreq] = ctls-2x[j] - - bd-2x.control.PEWAKE# => wake - bd-2x.control.PERST# => sw.PERST#[ch-offset] - bd-2x.control.CLKREQ# => clkreq - - val bd-2x-prsnt = pcie(2, PCIe-PRSNT#) - for j in 0 to 2 do: - supports bd-2x-prsnt: - val ch-offset = (2 * j) - for i in 0 to 2 do : - bd-2x-prsnt.data.lane[i].RX.P => sw.PRXP[i + ch-offset] - bd-2x-prsnt.data.lane[i].RX.N => sw.PRXN[i + ch-offset] - bd-2x-prsnt.data.lane[i].TX.P => sw.PTXP[i + ch-offset] - bd-2x-prsnt.data.lane[i].TX.N => sw.PTXN[i + ch-offset] - bd-2x-prsnt.data.refclk.P => sw.REFCLKP[ch-offset] - bd-2x-prsnt.data.refclk.N => sw.REFCLKN[ch-offset] - - val [wake, present, clkreq] = ctls-2x[j] - - bd-2x-prsnt.control.PEWAKE# => wake - bd-2x-prsnt.control.PERST# => sw.PERST#[ch-offset] - bd-2x-prsnt.control.PRSNT# => present - bd-2x-prsnt.control.CLKREQ# => clkreq - - val bd-1x = pcie(1) val ctls-1x = [ - [sw.GPIO[8], sw.GPIO[12], sw.GPIO[1]], - [sw.GPIO[9], sw.GPIO[14], sw.GPIO[3]], - [sw.GPIO[10], sw.GPIO[13], sw.GPIO[2]], - [sw.GPIO[11], sw.GPIO[15], sw.GPIO[4]], + [sw.GPIO[8], sw.PERST#[0], sw.GPIO[1]], + [sw.GPIO[9], sw.PERST#[1], sw.GPIO[3]], + [sw.GPIO[10], sw.PERST#[2], sw.GPIO[2]], + [sw.GPIO[11], sw.PERST#[3], sw.GPIO[4]], ] + for j in 0 to 4 do: - supports bd-1x: - bd-1x.data.lane[0].RX.P => sw.PRXP[j] - bd-1x.data.lane[0].RX.N => sw.PRXN[j] - bd-1x.data.lane[0].TX.P => sw.PTXP[j] - bd-1x.data.lane[0].TX.N => sw.PTXN[j] - bd-1x.data.refclk.P => sw.REFCLKP[j] - bd-1x.data.refclk.N => sw.REFCLKN[j] - - val [wake, present, clkreq] = ctls-1x[j] - bd-1x.control.PERST# => sw.PERST#[j] - bd-1x.control.PEWAKE# => wake - bd-1x.control.CLKREQ# => clkreq - - val bd-1x-prsnt = pcie(1, PCIe-PRSNT#) - for j in 0 to 4 do: - supports bd-1x-prsnt: - bd-1x-prsnt.data.lane[0].RX.P => sw.PRXP[j] - bd-1x-prsnt.data.lane[0].RX.N => sw.PRXN[j] - bd-1x-prsnt.data.lane[0].TX.P => sw.PTXP[j] - bd-1x-prsnt.data.lane[0].TX.N => sw.PTXN[j] - bd-1x-prsnt.data.refclk.P => sw.REFCLKP[j] - bd-1x-prsnt.data.refclk.N => sw.REFCLKN[j] - - val [wake, present, clkreq] = ctls-1x[j] - bd-1x-prsnt.control.PERST# => sw.PERST#[j] - bd-1x-prsnt.control.PEWAKE# => wake - bd-1x-prsnt.control.PRSNT# => present - bd-1x-prsnt.control.CLKREQ# => clkreq + connect_lanes(bd-1x, self.sw.REFCLK[j], ctls-1x[j], false, ch-offset = j) + connect_lanes(bd-1x-prsnt, self.sw.REFCLK[j], ctls-1x[j], sw.GPIO[12 + j], ch-offset = j) + + + ;;;;;;;;;;;;;;;;;;;;;;; + ; PCIe 2x + ;;;;;;;;;;;;;;;;;;;;;;; + + val pcie-2x-shared-wake = sw.GPIO[7] + val ctls-2x = [ + [sw.GPIO[8], sw.PERST#[0], sw.GPIO[1]] + [sw.GPIO[10], sw.PERST#[2], sw.GPIO[3]] + ] + ; The internal bundle contains reset, and clock request + ; but does not include the WAKE + val bd-2x = pcie-std(2) + val bd-2x-prsnt = pcie-with-hotplug(2) + + for j in 0 to 2 do: + connect_lanes(bd-2x, self.sw.REFCLK[j], ctls-2x[j], false, ch-offset = 2 * j) + connect_lanes(bd-2x-prsnt, self.sw.REFCLK[j], ctls-2x[j], sw.GPIO[12 + j], ch-offset = 2 * j) + diff --git a/src/protocols/pcie.stanza b/src/protocols/pcie.stanza index 998b9fba..3b586611 100644 --- a/src/protocols/pcie.stanza +++ b/src/protocols/pcie.stanza @@ -82,11 +82,19 @@ public defn PCIe-enum-to-int (en:PCIeWidth) -> Int: PCIe-x8 : 8 PCIe-x16 : 16 PCIe-x32 : 32 + doc: \ -@member PCIe-PRSNT# +Optional PCIe Control Pin Enum +@member PCIe-PRSNT# Hot-plug (Presences) detection +@member PCIe-WAKE# Device Wake +@member PCIe-PERST# Reset +@member PCIe-CLKREQ# Clock Request public pcb-enum jsl/bundles/pcie/PCIePins : PCIe-PRSNT# + PCIe-WAKE# + PCIe-PERST# + PCIe-CLKREQ# doc: \ @brief PCI-e Bundle @@ -106,6 +114,38 @@ and it also includes a refclk (100MHz) differential pair public defn pcie (lanes:Int, opt-pins:PCIePins ...) : pcie-b(lanes, opt-pins) +; Common Control signals - minus Presence. +val COMMON_CTL = [PCIe-WAKE#, PCIe-PERST#, PCIe-CLKREQ#] + +doc: \ +Construct an N-lane PCIe Bundle with Standard Control Signals + +The default control signal set is: + +* PCIe-WAKE# +* PCIe-PERST# +* PCIe-CLKREQ# + +But doesn't include presence / hotplug detection. See +{@link pcie-with-hotplug} + +@return PCIe `pcb-bundle` definition + +public defn pcie-std (lanes:Int): + pcie-b(lanes, COMMON_CTL) + +public defn pcie-with-hotplug (lanes:Int): + pcie-b(lanes, to-tuple $ cat(COMMON_CTL, [PCIe-PRSNT#])) + +doc: \ +Parametric PCIe Bundle Definition + +@param lanes Number of {@link lane-pair} sets for the `data` interface +@param opt-pins Set of optional control pins to construct. + +@member control PCIe Control bundle controlled by `opt-pins` +@member data PCIe Data bundle + public pcb-bundle pcie-b (lanes:Int, opt-pins:Collection) : name = "PCI-e" description = "PCI-e Serial Communications Link" @@ -117,34 +157,71 @@ doc: \ The Data bundle consists of a number (1 or more) of RX and TX pairs (1 RX/TX pair set = 1 lane) and it also includes a refclk (100MHz) differential pair. @param lanes The number of lanes in the bundle. -@member rx The receive diff-pair (# of lanes wide) -@member tx The transmit diff-pair (# of lanes wide) +@member lane An array of {@link lane-pair} ports +@member refclk Reference Clock, typically 100MHz - public pcb-bundle pcie-data (lanes:Int) : name = "PCI-e Data" description = "PCI-e Serial Communications Link Data" port lane : lane-pair[lanes] port refclk : diff-pair +doc: \ +PCIe Control Bundle + +Note that all pins are optional because there are common +cases where control pins are shared across bundles. By allowing +them to be configured - we can create sub-set bundles that +are often useful when doing pin assignment. + +@member PRSNT# HotPlug / Presence detection +@member PEWAKE# Wake signal +@member PERST# Reset signal +@member CLKREQ# Clock Request signal + pcb-bundle pcie-control-b (pins:Collection) : name = "PCI-e Control" description = "PCI-e Serial Communications Link Control" - port PEWAKE# - port PERST# ; PCI-E Reset signal - port CLKREQ# ; clock request for p in pins do : switch(p) : - PCIe-PRSNT# : make-port(`PRSNT#) ; hot plug detection + PCIe-PRSNT# : make-port(`PRSNT#) ; hot plug detection + PCIe-WAKE# : make-port(`PEWAKE#) + PCIe-PERST# : make-port(`PERST#) ; PCI-E Reset signal + PCIe-CLKREQ# : make-port(`CLKREQ#) ; clock request + + +public defn has-PEWAKE# (b:Bundle) -> True|False : + for p in pins(b) any? : + val refName = to-string $ ref(p) + suffix?(refName, "PEWAKE#") + +public defn has-PERST# (b:Bundle) -> True|False : + for p in pins(b) any? : + val refName = to-string $ ref(p) + suffix?(refName, "PERST#") + +public defn has-PRSNT# (b:Bundle) -> True|False : + for p in pins(b) any? : + val refName = to-string $ ref(p) + suffix?(refName, "PRSNT#") + +public defn has-CLKREQ# (b:Bundle) -> True|False : + for p in pins(b) any? : + val refName = to-string $ ref(p) + suffix?(refName, "CLKREQ#") doc: \ @brief PCI-e Control bundle PCI-e is a serial communication supporting high speed data links + +All signal pins of the control bundle are optional and controlled by +the `pins` set. + @param pins An optional set of pins to be implemented in the control bundle -@member PEWAKE# -@member PERST# -@member CLKREQ# -@member PRSNT# Optional signal +@member PRSNT# HotPlug / Presence detection +@member PEWAKE# Wake signal +@member PERST# Reset signal +@member CLKREQ# Clock Request signal public defn pcie-control (pins:Collection) :