├── .gitignore
├── LICENSE.md
├── Makefile
├── README.md
├── cfg
└── program_screamer.cfg
├── docs
└── system_design.md
├── ip
├── fifo_32_32_bram
│ └── fifo_32_32_bram.xci
├── fifo_36_36_prim
│ └── fifo_36_36_prim.xci
├── fifo_pcie_tlp_r32_w64_4096_bram
│ └── fifo_pcie_tlp_r32_w64_4096_bram.xci
├── fifo_pcie_tlp_r64_w32_4096_bram
│ └── fifo_pcie_tlp_r64_w32_4096_bram.xci
├── ila_0
│ └── ila_0.xci
├── pcie_7x_0
│ └── pcie_7x_0.xci
├── pcie_ila
│ └── pcie_ila.xci
└── pcie_tlp_ila
│ └── pcie_tlp_ila.xci
├── src
├── constrs
│ └── screamer_m2.xdc
├── design
│ ├── tlp_streamer_ft601.vhd
│ ├── tlp_streamer_loopback.vhd
│ ├── tlp_streamer_pcie.vhd
│ ├── tlp_streamer_pcie_cfg.vhd
│ ├── tlp_streamer_pcie_tlp.vhd
│ ├── tlp_streamer_records.vhd
│ ├── tlp_streamer_reset.vhd
│ ├── tlp_streamer_rx_dispatch.vhd
│ ├── tlp_streamer_top.vhd
│ └── tlp_streamer_tx_arbiter.vhd
└── sim
│ ├── tlp_streamer_usb_rx_sim.vhd
│ └── tlp_usb_rx_sim_behav.wcfg
├── vivado_build.tcl
└── vivado_generate_project.tcl
/.gitignore:
--------------------------------------------------------------------------------
1 | *.log
2 | *.jou
3 | *.str
4 | *.cache
5 | *.xpr
6 | *.hw
7 | tlp-streamer
8 | *.tmp
9 | .Xil
10 | ip/pcie*
11 | !ip/pcie*/*.xci
12 | *.ila
13 | *.diff
14 | *.old
15 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # License
2 |
3 | ## Xilinx IP
4 |
5 | The completed solution contains Xilinx proprietary IP cores licensed under the Xilinx CORE LICENSE AGREEMENT. This project as-is published on Github contains no Xilinx proprietary IP. The end user that have downloaded the no-charge Vivado WebPACK from Xilinx will have the proper licenses and will be able to re-generate Xilinx proprietary IP cores by running the build detailed above.
6 |
7 | ## src/constrs/screamer_m2.xdc
8 |
9 | Copyright 2021 Ulf Frisk
10 |
11 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
16 |
17 | ## All other published Source Files
18 |
19 | TLP Streamer - FPGA
20 | Copyright (C) 2021-2022 MikeM64
21 |
22 | This program is free software: you can redistribute it and/or modify
23 | it under the terms of the GNU General Public License as published by
24 | the Free Software Foundation, version 3.
25 |
26 | This program is distributed in the hope that it will be useful,
27 | but WITHOUT ANY WARRANTY; without even the implied warranty of
28 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 | GNU General Public License for more details.
30 |
31 | You should have received a copy of the GNU General Public License
32 | along with this program. If not, see .
33 |
34 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | tlp-streamer/tlp-streamer.runs/impl_1/tlp_streamer.bit:
2 | vivado -mode tcl -source vivado_build.tcl -notrace tlp-streamer/tlp-streamer.xpr
3 |
4 | install: tlp-streamer/tlp-streamer.runs/impl_1/tlp_streamer.bit
5 | openocd -f cfg/program_screamer.cfg
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # TLP Streamer
2 | ## Overview
3 | This project is a PCIe TLP Streamer intended to support device emulation from an attached host computer.
4 |
5 | Please refer to [system_design.md](docs/system_design.md) for details of the design.
6 |
7 | The current board target is the [Screamer M.2](https://shop.lambdaconcept.com/home/43-screamer-m2.html) from LambdaConcept.
8 |
9 | ## Progress
10 | - [x] - FT601 RX/TX Loopback
11 | - [x] - Host Packet RX Dispatch
12 | - [x] - FPGA Packet TX Arbitration
13 | - [x] - PCIe Link Up
14 | - [x] - PCIe configuration space R/W
15 | - [ ] - PCIe TLP Handling
16 | + [x] - TLP RX
17 | + [ ] - TLP TX (in progress)
18 | - [ ] - Host software
19 |
20 | # Thanks
21 |
22 | - [PCILeech](https://github.com/ufrisk/pcileech)
23 | - [NetTLP](https://github.com/nettlp)
24 |
25 |
--------------------------------------------------------------------------------
/cfg/program_screamer.cfg:
--------------------------------------------------------------------------------
1 | adapter driver ftdi
2 | transport select jtag
3 | ftdi vid_pid 0x0403 0x6011
4 | ftdi channel 0
5 | ftdi layout_init 0x0098 0x008b
6 | reset_config none
7 |
8 | source [find cpld/xilinx-xc7.cfg]
9 | source [find cpld/jtagspi.cfg]
10 | adapter speed 10000
11 |
12 | init
13 | xc7_program xc7.tap
14 | pld load 0 ./tlp-streamer/tlp-streamer.runs/impl_1/tlp_streamer.bit
15 | shutdown
16 |
--------------------------------------------------------------------------------
/docs/system_design.md:
--------------------------------------------------------------------------------
1 | # PCIe TLP Streamer
2 |
3 | ## Architecture
4 |
5 | ### HW:
6 | PCIe (Target) <=> FPGA <=> FT601 <= (USB3) => Host Computer
7 |
8 | ### SW:
9 | FT601 Driver <=> Server Process <= (UDP Socket) => Client
10 |
11 | ## Functionality
12 |
13 | Client could be any PCIe emulator:
14 | - NVMe
15 | - Ethernet
16 | - Etc...
17 |
18 | ## Requirements
19 | - MUST be able to handle both regular and config TLPs
20 | - MUST have counters available for debugging and statistics (USB Packet RX/TX, PCIe TLP RX/TX, etc...)
21 | - MAY be hot-restart capable to change VID/PID/device class from the client software (dependent on FPGA support)
22 |
23 | ## Design
24 | ### Clock Domains
25 | There are three clock domains for the design logic (except for the internals of Xilinx IP):
26 | 1) ft601_clk
27 | - This clock is driven by the FT601 and is used to clock incoming/outgoing data towards the host
28 | - Drives the RX/TX FIFOs
29 | 2) sys_clk
30 | - This is the external 100MHz clock
31 | - Drives the majority of the internal logic
32 | 3) pcie_user_clk
33 | - User clock output from the PCIe IP
34 | - Used to clock all data reads/writes related to the PCIe IP
35 |
36 | ### USB to FPGA Design
37 | The FT601 supports both synchronous single-channel and multi-channel operation. Maximum of 8 channels - 4 IN and 4 OUT.
38 |
39 | Does it make sense to use the multi-channel feature here? One per PCIe data, PCIe config, board config/mgmt.
40 |
41 | Pros:
42 | - Don't need to decode part of the user packet in HW to determine where the data is supposed to go
43 |
44 | Cons:
45 | - More complex software to manage where to send the packet
46 | - More complex bus interactions with the FT601
47 |
48 | Neutral:
49 | - More FIFO resources needed to buffer the three channels (turns out that an RX buffer for each channel is still needed to quickly drain the FT601 FIFO buffer)
50 |
51 | Questions:
52 | - Is the screamer wired up for multichannel FIFO?
53 | - Are the FT601 GPIOs writeable from the FPGA or are they hardwired to a specific config?
54 | - Is it cheaper to decode part of the user packet to determine where to send it or cheaper to implement multi-channel FIFOs?
55 |
56 | **It probably doesn't make sense when starting out to go multi-channel. The design should be modular enough to go multi-channel if required.**
57 |
58 | ### FPGA Design
59 | #### USB Loopback
60 | FT601 => FPGA => FT601 is implemented in order to verify the USB comms channel.
61 |
62 | ##### USB Packet RX
63 | The 245 bus mode on the FT601 has the following read state machine. All FT601 signals change on the negative clock edge and should be clocked on the positive edge.
64 |
65 | 1. `BUS_IDLE`
66 | - The default state of the bus
67 | - This will transition to either `RX_READY` or `TX_READY` depending on which signal is asserted by the FT601. `BUS_IDLE` will also check the state of the RX/TX FIFO to make sure there's either space to receive or data to transfer.
68 | 2. `RX_READY`
69 | - Wait state before asserting `FT601_OE`
70 | 3. `RX_START`
71 | - Asserts `FT601_OE`
72 | - Wait state before asserting `FT601_RD`
73 | 4. `RX_WORD_1`
74 | - Asserts `FT601_OE` and `FT601_RD`
75 | - Wait state before clocking valid data into the RX fifo
76 | 5. `RX_WORD_2`
77 | - Same as `RX_WORD_1`, but clocks valid data into the RX FIFO
78 | - Seems like the FT601 will keep valid data on the bus for an extra cycle, so we only want to clock one copy
79 | - Moves to `RX_COMPLETE` when either there is no more data from the FT601 or
80 | the RX FIFO is full
81 | 6. `RX_COMPLETE`
82 | - Delay state to de-assert `FT601_OE` and `FT601_RD` before going back to `BUS_IDLE`
83 |
84 | ##### USB Packet TX
85 | Similar to the USB Packet RX state machine, this control the TX process
86 |
87 | 1. `TX_READY`
88 | - Wait state before asserting `FT601_WR`
89 | 2. `TX_WORD`
90 | - Transmits a word on the FT601 bus
91 | 3. `TX_COMPLETE`
92 | - Wait state before going back to `BUS_IDLE`
93 |
94 | The controller for FT601 transfers is implemented in `tlp_streamer_ft601.vhd` and provides two FIFOs (one RX from host and one TX to host) as an interface to the rest of the FPGA design.
95 |
96 | #### Host-to-FPGA communications
97 | Packets sent/received by the FPGA are encoded in network order (Big-endian) for ease of communication with the PCIe core. The host is responsible for translating the packet before sending it.
98 |
99 | Each packet MUST have the following header prepended to any data:
100 |
101 | ```
102 | typedef enum tsh_msg_type_et {
103 | /** Loopback the packet back to the host */
104 | TSH_MSG_LOOPBACK = 0,
105 | /** PCIe Configuration Space packet */
106 | TSH_MSG_PCIE_CONFIG,
107 | } __attribute__ ((packed));
108 |
109 | /*
110 | * NOTE: The header must ALWAYS be size which is a multiple of a uint32_t to
111 | * allow for easy decoding on the FPGA.
112 | */
113 | struct tlp_streamer_header {
114 | /** @enum tsh_msg_type_et */
115 | uint8_t tsh_msg_type;
116 | /** Padding */
117 | uint8_t tsh_reserved_1;
118 | /** Number of DWORDs in the packet, including the header */
119 | uint16_t tsh_msg_len;
120 | /** Host-defined sequence number, for debugging */
121 | uint16_t tsh_seq_num;
122 | /** Padding */
123 | uint8_t tsh_reserved_2[2];
124 | } __attribute__((packed));
125 | ```
126 |
127 | #### Host Packet Processing
128 | 1) Parse header
129 | - Determine which component deals with the request
130 | 2) Dispatch request
131 | - Write header + packet into component FIFO
132 |
133 | #### PCIe Configuration Space Requests
134 | First step in bringing up a PCIe device is respnding to configuration space requests. Refer to "User-Implemented Configuration Space" on page 119 of PG054.
135 |
136 | Most of this is handled by the IP hard block in the FPGA. For NVMe emulation,
137 | BAR0 and BAR1 are of interest. BAR2 is an optional register for NVMe (see 2.1.12 in the NVMe 1.4c specification.) BAR0/1 need to be exposed to the host PC in order to generate TLP requests for the correct memory addresses.
138 |
139 | Per the 7-series FPGA documentation, only PCI config space addresses 0xA8 -> 0xFF are able to be handled by user logic. This means that the host software MUST request BAR addresses during its initialization process by querying the configuration interface.
140 |
141 | The following structure is used to contain configuration space requests from the host.
142 |
143 | ```
144 | enum tlp_streamer_write_options {
145 | /** PCIe config space read */
146 | TSWO_READ = (0 << 0),
147 | /** PCIe config space write */
148 | TSWO_WRITE = (1 << 0),
149 | /**
150 | * Write enable to treat any Read Only bit in the current write
151 | * as RW, not including bits set by attributes, reserved bits and
152 | * status bits.
153 | */
154 | TSWO_WRITE_READONLY = (1 << 1),
155 | /**
156 | * Indicates the current write operation should treat any RW1C bit as
157 | * RW. Normally a RW1C bit is cleared by writing 1 to it and can normally
158 | * only be set by internal core conditions. During a configuration write
159 | * with this flag set, for every bit in tspcc_cfg_reg_data that is 1, a
160 | * corresponding RW1C configuration register bit is set to 1. A value of
161 | * 0 during this operation has no effect and non-RW1C bits are
162 | * unaffected regardless of the data in tspcc_cfg_reg_data.
163 | */
164 | TSWO_WRITE_RW1C = (1 << 2),
165 | }
166 |
167 | struct tlp_streamer_pcie_cfg_cmd {
168 | /**
169 | * Configuration register to read from, see page 109+ from pg054.
170 | * Only 10 bits are used.
171 | */
172 | uint16_t tspcc_cfg_reg_addr;
173 | /** Read vs. write */
174 | uint8_t tspcc_cfg_write;
175 | /** Which bytes are valid during a cfg_reg write. 4-bits used. */
176 | uint8_t tspcc_cfg_reg_be;
177 | /** Data returned from the register, or data to write to the register */
178 | uint32_t tspcc_cfg_reg_data;
179 | };
180 | ```
181 |
182 | For example, a request to read BAR0 would be sent as:
183 | ```
184 | {
185 | .tspcc_cfg_reg_addr = 0x04,
186 | .tspcc_cfg_write = 0,
187 | /* tspcc_cfg_reg_data and tspcf_cfg_reg_be may be uninitialized */
188 | }
189 | ```
190 |
191 | And the FPGA would respond:
192 | ```
193 | {
194 | .tspcc_cfg_reg_addr = 0x4,
195 | .tspcc_cfg_write = 0,
196 | .tspcc_cfg_reg_data = 0xdeadbeef,
197 | .tspcc_cfg_reg_be = 0xf,
198 | }
199 | ```
200 |
201 | #### PCIe TLP Management
202 | This block manages regular TLP transfers to and from the PCIe IP. It needs to pull data and feed the FIFO in front of the FT601.
203 |
204 | #### FPGA Configuration Block
205 | This block manages configuration of the FPGA device. It manages the following features:
206 | - FPGA hot reset for PCIe reconfiguration
207 | - USB loopback enable/disable
208 | - PCIe attributes that may be changed dynamically
209 |
210 | Q: Should all other requests be stopped during a config change?
211 | Q: Should the in-flight requests be handled first without starting any new ones?
212 |
213 | # Notes on manual testing
214 | ## How to trigger rescan after upgrading the bitstream
215 | 0) Flash new bitstream to the card
216 |
217 | 1) Get the PCI slot from `lspci`:
218 | ```
219 | $ lspci -d 13a8:7021
220 | 0b:00.0 Serial controller: Exar Corp. Device 7021
221 | ```
222 |
223 | 2) Remove the device (as root):
224 | ```
225 | $ echo 1 > /sys/bus/pci/devices/0000\:0b\:00.0/remove
226 | ```
227 |
228 | 3) Re-scan the PCI bus (as root):
229 | ```
230 | $ echo 1 > /sys/bus/pci/rescan
231 | ```
232 |
233 | ## Enabling MMIO for MRd/MWr TLP Generation
234 | 0) Get the PCI slot from `lspci`:
235 | ```
236 | $ lspci -d 13a8:7021
237 | 0b:00.0 Serial controller: Exar Corp. Device 7021
238 | ```
239 |
240 | 1) Enable MMIO for the slot (as root):
241 | ```
242 | $ setpci -s 0b:00.0 COMMAND=0x2
243 | ```
244 |
245 | 2) Verify the `BAR` is enabled
246 | - There should not be `[virtual]` or `[disabled]` in the output of lspci
247 |
248 | Working output:
249 | ```
250 | $ lspci -d 13a8:7021 -v | grep "Memory at"
251 | Memory at fcc00000 (32-bit, non-prefetchable) [size=2K]
252 | ```
253 |
254 | Non-working output:
255 | ```
256 | $ lspci -d 13a8:7021 -v | grep "Memory at"
257 | Memory at fcc00000 (32-bit, non-prefetchable) [disabled] [size=2K]
258 | ```
259 |
260 | ## Trigger a MRd/MWr TLP
261 | 0) Get the PCI slot from `lspci`:
262 | ```
263 | $ lspci -d 13a8:7021
264 | 0b:00.0 Serial controller: Exar Corp. Device 7021
265 | ```
266 |
267 | 1) Find the sysfs path to the PCIe device
268 | ```
269 | $ find /sys/devices -name '0000:0b:00.0' | grep -v iommu
270 | /sys/devices/pci0000:00/0000:00:03.2/0000:0b:00.0
271 | ```
272 |
273 | 2) Trigger a MRd TLP (as root)
274 | - Requires pcimem - https://github.com/billfarrow/pcimem
275 | - If the kernel has loaded a driver for the PCIe device, it may need to be unloaded first
276 | - The `resource0` file corresponds to `BAR0`, adjust as necessary for the appropriate `BAR` address.
277 | ```
278 | $ ./pcimem /sys/devices/pci0000\:00/0000\:00\:03.2/0000\:0b\:00.0/resource0 0 w
279 | /sys/devices/pci0000:00/0000:00:03.2/0000:0b:00.0/resource0 opened.
280 | Target offset is 0x0, page size is 4096
281 | mmap(0, 4096, 0x3, 0x1, 3, 0x0)
282 | PCI Memory mapped to address 0x7fe58be8c000.
283 | 0x0000: 0xFFFFFFFF
284 | ```
285 |
--------------------------------------------------------------------------------
/src/constrs/screamer_m2.xdc:
--------------------------------------------------------------------------------
1 | set_property PACKAGE_PIN L18 [get_ports {ft601_be_io[0]}]
2 | set_property PACKAGE_PIN M17 [get_ports {ft601_be_io[1]}]
3 | set_property PACKAGE_PIN N18 [get_ports {ft601_be_io[2]}]
4 | set_property PACKAGE_PIN N17 [get_ports {ft601_be_io[3]}]
5 | set_property PACKAGE_PIN B9 [get_ports {ft601_data_io[0]}]
6 | set_property PACKAGE_PIN A9 [get_ports {ft601_data_io[1]}]
7 | set_property PACKAGE_PIN C9 [get_ports {ft601_data_io[2]}]
8 | set_property PACKAGE_PIN A10 [get_ports {ft601_data_io[3]}]
9 | set_property PACKAGE_PIN B10 [get_ports {ft601_data_io[4]}]
10 | set_property PACKAGE_PIN B11 [get_ports {ft601_data_io[5]}]
11 | set_property PACKAGE_PIN A12 [get_ports {ft601_data_io[6]}]
12 | set_property PACKAGE_PIN B12 [get_ports {ft601_data_io[7]}]
13 | set_property PACKAGE_PIN A13 [get_ports {ft601_data_io[8]}]
14 | set_property PACKAGE_PIN A14 [get_ports {ft601_data_io[9]}]
15 | set_property PACKAGE_PIN B14 [get_ports {ft601_data_io[10]}]
16 | set_property PACKAGE_PIN A15 [get_ports {ft601_data_io[11]}]
17 | set_property PACKAGE_PIN B15 [get_ports {ft601_data_io[12]}]
18 | set_property PACKAGE_PIN B16 [get_ports {ft601_data_io[13]}]
19 | set_property PACKAGE_PIN A17 [get_ports {ft601_data_io[14]}]
20 | set_property PACKAGE_PIN B17 [get_ports {ft601_data_io[15]}]
21 | set_property PACKAGE_PIN C17 [get_ports {ft601_data_io[16]}]
22 | set_property PACKAGE_PIN C18 [get_ports {ft601_data_io[17]}]
23 | set_property PACKAGE_PIN D18 [get_ports {ft601_data_io[18]}]
24 | set_property PACKAGE_PIN E17 [get_ports {ft601_data_io[19]}]
25 | set_property PACKAGE_PIN E18 [get_ports {ft601_data_io[20]}]
26 | set_property PACKAGE_PIN E16 [get_ports {ft601_data_io[21]}]
27 | set_property PACKAGE_PIN F18 [get_ports {ft601_data_io[22]}]
28 | set_property PACKAGE_PIN F17 [get_ports {ft601_data_io[23]}]
29 | set_property PACKAGE_PIN G17 [get_ports {ft601_data_io[24]}]
30 | set_property PACKAGE_PIN H18 [get_ports {ft601_data_io[25]}]
31 | set_property PACKAGE_PIN D13 [get_ports {ft601_data_io[26]}]
32 | set_property PACKAGE_PIN C14 [get_ports {ft601_data_io[27]}]
33 | set_property PACKAGE_PIN D14 [get_ports {ft601_data_io[28]}]
34 | set_property PACKAGE_PIN D15 [get_ports {ft601_data_io[29]}]
35 | set_property PACKAGE_PIN C16 [get_ports {ft601_data_io[30]}]
36 | set_property PACKAGE_PIN D16 [get_ports {ft601_data_io[31]}]
37 | set_property PACKAGE_PIN T15 [get_ports ft601_oe_n_o]
38 | set_property PACKAGE_PIN R16 [get_ports ft601_rd_n_o]
39 | set_property PACKAGE_PIN R18 [get_ports ft601_rxf_n_i]
40 | set_property PACKAGE_PIN R17 [get_ports ft601_siwu_n_o]
41 | set_property PACKAGE_PIN P18 [get_ports ft601_txe_n_i]
42 | set_property PACKAGE_PIN T18 [get_ports ft601_wr_n_o]
43 | set_property PACKAGE_PIN U15 [get_ports ft601_rst_n_o]
44 | set_property IOSTANDARD LVCMOS33 [get_ports ft601_rxf_n_i]
45 | set_property IOSTANDARD LVCMOS33 [get_ports ft601_txe_n_i]
46 | set_property IOSTANDARD LVCMOS33 [get_ports ft601_rst_n_o]
47 | set_property IOSTANDARD LVCMOS33 [get_ports ft601_oe_n_o]
48 | set_property IOSTANDARD LVCMOS33 [get_ports ft601_rd_n_o]
49 | set_property IOSTANDARD LVCMOS33 [get_ports ft601_wr_n_o]
50 | set_property IOSTANDARD LVCMOS33 [get_ports ft601_siwu_n_o]
51 | set_property IOSTANDARD LVCMOS33 [get_ports {{ft601_be_io[*]} {ft601_data_io[*]}}]
52 | set_property SLEW FAST [get_ports {{ft601_be_io[*]} {ft601_data_io[*]}}]
53 | set_property SLEW FAST [get_ports ft601_siwu_n_o]
54 | set_property SLEW FAST [get_ports ft601_wr_n_o]
55 | set_property SLEW FAST [get_ports ft601_rd_n_o]
56 | set_property SLEW FAST [get_ports ft601_oe_n_o]
57 | set_property SLEW FAST [get_ports ft601_rst_n_o]
58 |
59 | # LEDs are active high
60 | set_property PACKAGE_PIN V17 [get_ports user_led_ld1]
61 | set_property PACKAGE_PIN U17 [get_ports user_led_ld2]
62 | set_property IOSTANDARD LVCMOS33 [get_ports user_led_ld1]
63 | set_property IOSTANDARD LVCMOS33 [get_ports user_led_ld2]
64 |
65 | # SYSCLK
66 | set_property PACKAGE_PIN R2 [get_ports sys_clk]
67 | set_property IOSTANDARD LVCMOS33 [get_ports sys_clk]
68 | create_clock -period 10.000 -name net_clk -waveform {0.000 5.000} [get_ports sys_clk]
69 |
70 | # FT601 CLK
71 | set_property IOSTANDARD LVCMOS33 [get_ports ft601_clk_i]
72 | set_property PACKAGE_PIN E13 [get_ports ft601_clk_i]
73 | create_clock -period 10.000 -name net_ft601_clk_i -waveform {0.000 5.000} [get_ports ft601_clk_i]
74 |
75 | # Delay constraints are from FT601 Data sheet pg. 17
76 | set_input_delay -clock [get_clocks net_ft601_clk_i] -min 3.000 [get_ports {{ft601_data_io[*]} {ft601_be_io[*]}}]
77 | set_input_delay -clock [get_clocks net_ft601_clk_i] -max 3.500 [get_ports {{ft601_data_io[*]} {ft601_be_io[*]}}]
78 | set_output_delay -clock [get_clocks net_ft601_clk_i] -min 4.800 [get_ports {{ft601_data_io[*]} {ft601_be_io[*]}}]
79 | set_output_delay -clock [get_clocks net_ft601_clk_i] -max 1.000 [get_ports {{ft601_data_io[*]} {ft601_be_io[*]}}]
80 |
81 | set_input_delay -clock [get_clocks net_ft601_clk_i] -min 3.000 [get_ports {ft601_rxf_n_i ft601_txe_n_i}]
82 | set_input_delay -clock [get_clocks net_ft601_clk_i] -max 3.500 [get_ports {ft601_rxf_n_i ft601_txe_n_i}]
83 |
84 | set_output_delay -clock [get_clocks net_ft601_clk_i] -min 4.800 [get_ports {ft601_wr_n_o ft601_rd_n_o ft601_oe_n_o ft601_rst_n_o ft601_siwu_n_o}]
85 | set_output_delay -clock [get_clocks net_ft601_clk_i] -max 1.000 [get_ports {ft601_wr_n_o ft601_rd_n_o ft601_oe_n_o ft601_rst_n_o ft601_siwu_n_o}]
86 |
87 | # Constrain the LEDs to clean up the timing report
88 | set_output_delay -clock [get_clocks net_ft601_clk_i] -max 0.000 [get_ports {user_led_ld1 user_led_ld2}]
89 | set_output_delay -clock [get_clocks net_ft601_clk_i] -min 10.000 [get_ports {user_led_ld1 user_led_ld2}]
90 |
91 | # Exclude the reset hold counter from timing analysis as it only exists to
92 | # generate a reset signal during initial power-on.
93 | set_false_path -from [get_pins {comp_tlp_streamer_reset/reset_hold_count64_s_reg[*]/C}]
94 | set_false_path -to [get_ports {user_led_ld1 user_led_ld2}]
95 |
96 | # Force external signal registers to be in the IO Block for timing closure
97 | # Forcing the following three to IOB makes the design come within 1 net of timing closure
98 | set_property IOB TRUE [get_cells comp_tlp_streamer_ft601/ft601_rd_n_o_reg*]
99 | set_property IOB TRUE [get_cells comp_tlp_streamer_ft601/ft601_oe_n_o_reg*]
100 | set_property IOB TRUE [get_cells comp_tlp_streamer_ft601/ft601_wr_n_o_reg*]
101 | set_multicycle_path -from [get_pins comp_tlp_streamer_ft601/ft601_wr_n_s_2_reg*/C] -to [get_ports {{ft601_be_io[*]} {ft601_data_io[*]}}] 2
102 |
103 | #set_multicycle_path 2 -from [get_pins i_pcileech_com/i_pcileech_ft601/oe_reg/C] -to [get_ports {{ft601_be_io[*]} {ft601_data_io[*]}}]
104 | #set_multicycle_path 2 -from [get_clocks net_ft601_clk_i] -to [get_ports {{ft601_be_io[*]} {ft601_data_io[*]}}]
105 | #set_multicycle_path 2 -from [get_clocks net_ft601_clk_i] -to [get_ports ft601_oe_n_o]
106 | #set_multicycle_path 2 -from [get_clocks net_ft601_clk_i] -to [get_ports ft601_rd_n_o]
107 | #set_false_path -from [get_pins {i_pcileech_fifo/_pcie_core_config_reg[*]/C}]
108 | #set_false_path -from [get_pins i_pcileech_pcie_a7/i_pcie_7x_0/inst/inst/user_lnk_up_int_reg/C] -to [get_pins {i_pcileech_fifo/_cmd_tx_din_reg[16]/D}]
109 | #set_false_path -from [get_pins i_pcileech_pcie_a7/i_pcie_7x_0/inst/inst/user_reset_out_reg/C]
110 |
111 | #PCIe signals
112 | #set_property PACKAGE_PIN K1 [get_ports pcie_present]
113 | set_property PACKAGE_PIN M1 [get_ports pcie_perst_n_i]
114 | set_property PACKAGE_PIN L2 [get_ports pcie_wake_n_o]
115 | #set_property IOSTANDARD LVCMOS33 [get_ports pcie_present]
116 | set_property IOSTANDARD LVCMOS33 [get_ports pcie_perst_n_i]
117 | set_property IOSTANDARD LVCMOS33 [get_ports pcie_wake_n_o]
118 |
119 | #set_property LOC GTPE2_CHANNEL_X0Y2 [get_cells {comp_tlp_streamer_pcie/comp_pcie_7x_0/U0/inst/gt_top_i/pipe_wrapper_i/pipe_lane[0].gt_wrapper_i/gtp_channel.gtpe2_channel_i}]
120 | set_property LOC GTPE2_CHANNEL_X0Y0 [get_cells {comp_tlp_streamer_pcie/comp_pcie_7x_0/U0/inst/gt_top_i/pipe_wrapper_i/pipe_lane[0].gt_wrapper_i/gtp_channel.gtpe2_channel_i}]
121 | set_property PACKAGE_PIN E3 [get_ports {pcie_rxn_i[0]}]
122 | set_property PACKAGE_PIN E4 [get_ports {pcie_rxp_i[0]}]
123 | set_property PACKAGE_PIN H1 [get_ports {pcie_txn_o[0]}]
124 | set_property PACKAGE_PIN H2 [get_ports {pcie_txp_o[0]}]
125 |
126 | #set_property PACKAGE_PIN A3 [get_ports {pcie_rxn_i[1]}]
127 | #set_property PACKAGE_PIN A4 [get_ports {pcie_rxp_i[1]}]
128 | #set_property PACKAGE_PIN F1 [get_ports {pcie_txn_o[1]}]
129 | #set_property PACKAGE_PIN F2 [get_ports {pcie_txp_o[1]}]
130 |
131 | #set_property PACKAGE_PIN C3 [get_ports {pcie_rxn_i[2]}]
132 | #set_property PACKAGE_PIN C4 [get_ports {pcie_rxp_i[2]}]
133 | #set_property PACKAGE_PIN D1 [get_ports {pcie_txn_o[2]}]
134 | #set_property PACKAGE_PIN D2 [get_ports {pcie_txp_o[2]}]
135 |
136 | #set_property PACKAGE_PIN G3 [get_ports {pcie_rxn_i[3]}]
137 | #set_property PACKAGE_PIN G4 [get_ports {pcie_rxp_i[3]}]
138 | #set_property PACKAGE_PIN B1 [get_ports {pcie_txn_o[3]}]
139 | #set_property PACKAGE_PIN B2 [get_ports {pcie_txp_o[3]}]
140 |
141 | set_property PACKAGE_PIN D6 [get_ports pcie_clk_p_i]
142 | set_property PACKAGE_PIN D5 [get_ports pcie_clk_n_i]
143 |
144 | #set_property LOC GTPE2_COMMON_X0Y0 [get_cells {comp_tlp_streamer_pcie/ibufds_gte2_pcie_clk}]
145 | create_clock -period 10.000 -name pcie_ref_clk [get_nets pcie_clk_p_i]
146 |
147 | set_property CFGBVS Vcco [current_design]
148 | set_property CONFIG_VOLTAGE 3.3 [current_design]
149 | set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]
150 | set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]
151 | set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES [current_design]
152 | set_property BITSTREAM.CONFIG.CONFIGRATE 66 [current_design]
153 |
154 | set_operating_conditions -airflow 0
155 | set_operating_conditions -board_layers 4to7
156 | set_operating_conditions -board small
157 | set_operating_conditions -heatsink none
158 | set_property C_CLK_INPUT_FREQ_HZ 300000000 [get_debug_cores dbg_hub]
159 | set_property C_ENABLE_CLK_DIVIDER false [get_debug_cores dbg_hub]
160 | set_property C_USER_SCAN_CHAIN 1 [get_debug_cores dbg_hub]
161 | connect_debug_port dbg_hub/clk [get_nets ft601_clk_i_IBUF_BUFG]
162 |
--------------------------------------------------------------------------------
/src/design/tlp_streamer_ft601.vhd:
--------------------------------------------------------------------------------
1 | --
2 | -- TLP Streamer - FT601 Interface
3 | --
4 | -- (c) MikeM64 - 2021
5 | --
6 |
7 | library IEEE;
8 | use IEEE.std_logic_1164.all;
9 | use IEEE.numeric_std.all;
10 |
11 | entity tlp_streamer_ft601 is
12 | port (
13 | sys_clk_i : in std_logic;
14 | sys_reset_i : in std_logic;
15 | ft601_clk_i : in std_logic;
16 | ft601_be_io : inout std_logic_vector(3 downto 0);
17 | ft601_data_io : inout std_logic_vector(31 downto 0);
18 | ft601_oe_n_o : out std_logic;
19 | ft601_rxf_n_i : in std_logic;
20 | ft601_rd_n_o : out std_logic;
21 | ft601_rst_n_o : out std_logic;
22 | ft601_txe_n_i : in std_logic;
23 | ft601_wr_n_o : out std_logic;
24 | ft601_siwu_n_o : out std_logic;
25 | ft601_rx_fifo_rd_en_i : in std_logic;
26 | ft601_rx_fifo_rd_empty_o : out std_logic;
27 | ft601_rx_fifo_rd_valid_o : out std_logic;
28 | ft601_rx_fifo_rd_data_o : out std_logic_vector(35 downto 0);
29 | ft601_tx_fifo_wr_en_i : in std_logic;
30 | ft601_tx_fifo_wr_full_o : out std_logic;
31 | ft601_tx_fifo_wr_data_i : in std_logic_vector(35 downto 0));
32 | end entity tlp_streamer_ft601;
33 |
34 | architecture RTL of tlp_streamer_ft601 is
35 |
36 | component fifo_36_36_prim IS
37 | PORT (
38 | rst : IN STD_LOGIC;
39 | wr_clk : IN STD_LOGIC;
40 | rd_clk : IN STD_LOGIC;
41 | din : IN STD_LOGIC_VECTOR(35 DOWNTO 0);
42 | wr_en : IN STD_LOGIC;
43 | rd_en : IN STD_LOGIC;
44 | dout : OUT STD_LOGIC_VECTOR(35 DOWNTO 0);
45 | full : OUT STD_LOGIC;
46 | empty : OUT STD_LOGIC;
47 | valid : OUT STD_LOGIC);
48 | END component fifo_36_36_prim;
49 |
50 | --component ila_0 IS
51 | -- PORT (
52 | -- clk : IN STD_LOGIC;
53 | -- probe0 : IN STD_LOGIC_VECTOR(12 DOWNTO 0);
54 | -- probe1 : IN STD_LOGIC_VECTOR(12 DOWNTO 0);
55 | -- probe2 : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
56 | -- probe3 : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
57 | -- probe4 : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
58 | -- probe5 : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
59 | -- probe6 : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
60 | -- probe7 : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
61 | -- probe8 : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
62 | -- probe9 : IN STD_LOGIC_VECTOR(15 DOWNTO 0);
63 | -- probe10 : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
64 | -- probe11 : IN STD_LOGIC_VECTOR(9 DOWNTO 0);
65 | -- probe12 : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
66 | -- probe13 : IN STD_LOGIC_VECTOR(0 DOWNTO 0)
67 | --);
68 | --end component ila_0;
69 |
70 | type ft601_bus_state is (BUS_IDLE,
71 | RX_READY, RX_START, RX_WORD_1, RX_WORD_2, RX_COMPLETE,
72 | TX_READY, TX_WORD, TX_COMPLETE);
73 | signal current_bus_state, next_bus_state: ft601_bus_state;
74 |
75 | signal ft601_be_rd_i: std_logic_vector(3 downto 0);
76 | signal ft601_data_rd_i: std_logic_vector(31 downto 0);
77 |
78 | signal ft601_be_wr_o: std_logic_vector(3 downto 0);
79 | signal ft601_data_wr_o: std_logic_vector(31 downto 0);
80 |
81 | attribute IOB : string;
82 | attribute IOB of ft601_be_wr_o : signal is "TRUE";
83 | attribute IOB of ft601_data_wr_o : signal is "TRUE";
84 |
85 | signal ft601_oe_n_s: std_logic;
86 | signal ft601_rd_n_s: std_logic;
87 | signal ft601_wr_n_s_1: std_logic;
88 | signal ft601_wr_n_s_2: std_logic;
89 |
90 | signal fifo_rx_wr_data_s: std_logic_vector(35 downto 0);
91 | signal fifo_rx_wr_en_s: std_logic;
92 | signal fifo_rx_wr_full_s: std_logic;
93 |
94 | signal fifo_tx_rd_data_s: std_logic_vector(35 downto 0);
95 | signal fifo_tx_rd_en_s: std_logic;
96 | signal fifo_tx_rd_empty_s: std_logic;
97 | signal fifo_tx_rd_valid_s: std_logic;
98 |
99 | signal ft601_rx_fifo_rd_valid_s: std_logic;
100 |
101 | begin
102 |
103 | ft601_rx_usb_fifo: fifo_36_36_prim
104 | port map (
105 | rst => sys_reset_i,
106 | wr_clk => ft601_clk_i,
107 | rd_clk => sys_clk_i,
108 | din => fifo_rx_wr_data_s,
109 | wr_en => fifo_rx_wr_en_s,
110 | rd_en => ft601_rx_fifo_rd_en_i,
111 | dout => ft601_rx_fifo_rd_data_o,
112 | full => fifo_rx_wr_full_s,
113 | empty => ft601_rx_fifo_rd_empty_o,
114 | valid => ft601_rx_fifo_rd_valid_s);
115 |
116 | ft601_tx_usb_fifo: fifo_36_36_prim
117 | port map (
118 | rst => sys_reset_i,
119 | wr_clk => sys_clk_i,
120 | rd_clk => ft601_clk_i,
121 | din => ft601_tx_fifo_wr_data_i,
122 | wr_en => ft601_tx_fifo_wr_en_i,
123 | rd_en => fifo_tx_rd_en_s,
124 | dout => fifo_tx_rd_data_s,
125 | full => ft601_tx_fifo_wr_full_o,
126 | empty => fifo_tx_rd_empty_s,
127 | valid => fifo_tx_rd_valid_s);
128 |
129 | --comp_pcie_cfg_ila: ila_0
130 | -- PORT map (
131 | -- clk => ft601_clk_i,
132 | -- probe0 => (others => '0'),
133 | -- probe1 => (others => '0'),
134 | -- probe2 => fifo_tx_rd_data_s(31 downto 0),
135 | -- probe3 => fifo_rx_wr_data_s(31 downto 0),
136 | -- probe4(0) => fifo_tx_rd_en_s,
137 | -- probe5(0) => fifo_rx_wr_en_s,
138 | -- probe6(0) => ft601_txe_n_i,
139 | -- probe7(0) => fifo_tx_rd_empty_s,
140 | -- probe8 => (others => '0'),
141 | -- probe9 => (others => '0'),
142 | -- probe10 => (others => '0'),
143 | -- probe11 => (others => '0'),
144 | -- probe12 => (others => '0'),
145 | -- probe13(0) => ft601_rxf_n_i
146 | --);
147 |
148 |
149 | bus_read_write: process(ft601_wr_n_s_2, ft601_be_wr_o, ft601_data_wr_o,
150 | ft601_be_io, ft601_data_io)
151 | begin
152 |
153 | if (ft601_wr_n_s_2 = '1') then
154 | ft601_be_io <= "ZZZZ";
155 | ft601_data_io <= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
156 | else
157 | ft601_be_io <= ft601_be_wr_o;
158 | ft601_data_io <= ft601_data_wr_o;
159 | end if;
160 | ft601_be_rd_i <= ft601_be_io;
161 | ft601_data_rd_i <= ft601_data_io;
162 |
163 | end process bus_read_write;
164 |
165 | ft601_clock_process: process(ft601_clk_i, ft601_be_rd_i,
166 | ft601_data_rd_i, next_bus_state,
167 | ft601_oe_n_s, ft601_rx_fifo_rd_valid_s,
168 | ft601_rd_n_s, fifo_tx_rd_data_s,
169 | ft601_wr_n_s_1, ft601_wr_n_s_2)
170 | begin
171 |
172 | -- SIWU_N is listed as reserved in the FT601 datasheet.
173 | -- It *is* listed in the following datasheet:
174 | -- https://www.ftdichip.com/Support/Documents/AppNotes/AN_165_Establishing_Synchronous_245_FIFO_Communications_using_a_Morph-IC-II.pdf
175 | -- SI/WU == Send Immediate / Wake Up, assert this signal to send any TX data
176 | -- to the USB host immediately or to wake the host up from suspend.
177 | ft601_siwu_n_o <= '0';
178 | ft601_rx_fifo_rd_valid_o <= ft601_rx_fifo_rd_valid_s;
179 | fifo_rx_wr_data_s <= ft601_be_rd_i & ft601_data_rd_i;
180 |
181 | if (rising_edge(ft601_clk_i)) then
182 | ft601_oe_n_o <= ft601_oe_n_s;
183 | ft601_wr_n_s_2 <= ft601_wr_n_s_1;
184 | ft601_rd_n_o <= ft601_rd_n_s;
185 | ft601_wr_n_o <= ft601_wr_n_s_1;
186 | ft601_be_wr_o <= fifo_tx_rd_data_s(35 downto 32);
187 | ft601_data_wr_o <= fifo_tx_rd_data_s(31 downto 0);
188 | end if;
189 |
190 | end process ft601_clock_process;
191 |
192 | ft601_fsm_state_process: process(ft601_clk_i, next_bus_state, sys_reset_i)
193 | begin
194 |
195 | ft601_rst_n_o <= not sys_reset_i;
196 |
197 | if (sys_reset_i = '1') then
198 | current_bus_state <= BUS_IDLE;
199 | elsif (rising_edge(ft601_clk_i)) then
200 | current_bus_state <= next_bus_state;
201 | end if;
202 |
203 | end process ft601_fsm_state_process;
204 |
205 | ft601_fsm_data_output_process: process(current_bus_state, ft601_rxf_n_i,
206 | fifo_tx_rd_valid_s)
207 | begin
208 |
209 | -- Assume the FPGA is not taking control of the FT601 bus
210 | ft601_oe_n_s <= '1';
211 | ft601_rd_n_s <= '1';
212 | ft601_wr_n_s_1 <= '1';
213 | fifo_rx_wr_en_s <= '0';
214 | fifo_tx_rd_en_s <= '0';
215 |
216 | case current_bus_state is
217 | when RX_START =>
218 | ft601_oe_n_s <= '0';
219 | when RX_WORD_1 =>
220 | -- Insert a delay state to ensure the RX FIFO only
221 | -- starts clocking valid data
222 | ft601_oe_n_s <= '0';
223 | ft601_rd_n_s <= '0';
224 | when RX_WORD_2 =>
225 | -- Insert a delay state to ensure the RX FIFO only
226 | -- starts clocking valid data
227 | ft601_oe_n_s <= '0';
228 | ft601_rd_n_s <= '0';
229 | fifo_rx_wr_en_s <= not ft601_rxf_n_i;
230 | when RX_COMPLETE =>
231 | ft601_oe_n_s <= '1';
232 | ft601_rd_n_s <= '1';
233 | when TX_WORD =>
234 | fifo_tx_rd_en_s <= '1';
235 | ft601_wr_n_s_1 <= not fifo_tx_rd_valid_s;
236 | when others =>
237 | end case;
238 |
239 | end process ft601_fsm_data_output_process;
240 |
241 | ft601_fsm_state_select_process: process(current_bus_state, ft601_txe_n_i, ft601_rxf_n_i,
242 | fifo_rx_wr_full_s, fifo_tx_rd_empty_s, fifo_tx_rd_data_s)
243 |
244 | variable ft601_words_to_write_v: integer;
245 |
246 | begin
247 | -- Assume the state does not change by default
248 | next_bus_state <= current_bus_state;
249 | ft601_words_to_write_v := 0;
250 |
251 | case current_bus_state is
252 | when BUS_IDLE =>
253 | if (ft601_txe_n_i = '0' and fifo_tx_rd_empty_s = '0') then
254 | next_bus_state <= TX_READY;
255 | elsif (ft601_rxf_n_i = '0' and fifo_rx_wr_full_s = '0') then
256 | next_bus_state <= RX_READY;
257 | end if;
258 | when RX_READY =>
259 | next_bus_state <= RX_START;
260 | when RX_START =>
261 | next_bus_state <= RX_WORD_1;
262 | when RX_WORD_1 =>
263 | next_bus_state <= RX_WORD_2;
264 | when RX_WORD_2 =>
265 | if (ft601_rxf_n_i = '1') then
266 | next_bus_state <= RX_COMPLETE;
267 | end if;
268 | when RX_COMPLETE =>
269 | next_bus_state <= BUS_IDLE;
270 | when TX_READY =>
271 | next_bus_state <= TX_WORD;
272 | ft601_words_to_write_v := to_integer(unsigned(fifo_tx_rd_data_s(23 downto 16) & fifo_tx_rd_data_s(31 downto 24)));
273 | when TX_WORD =>
274 | ft601_words_to_write_v := ft601_words_to_write_v - 1;
275 | if (ft601_txe_n_i = '1' or fifo_tx_rd_empty_s = '1' or ft601_words_to_write_v = 0) then
276 | next_bus_state <= TX_COMPLETE;
277 | end if;
278 | when TX_COMPLETE =>
279 | next_bus_state <= BUS_IDLE;
280 | end case;
281 |
282 | end process ft601_fsm_state_select_process;
283 |
284 |
285 | end architecture RTL;
--------------------------------------------------------------------------------
/src/design/tlp_streamer_loopback.vhd:
--------------------------------------------------------------------------------
1 | --
2 | -- TLP Streamer - Host Packet Loopback Module
3 | --
4 | -- (c) MikeM64 - 2021
5 | --
6 |
7 | library IEEE;
8 | use IEEE.std_logic_1164.all;
9 | use IEEE.numeric_std.all;
10 |
11 | use work.tlp_streamer_records.all;
12 |
13 | entity tlp_streamer_loopback is
14 | port(
15 | sys_clk_i : in std_logic;
16 | sys_reset_i : in std_logic;
17 | -- Input from dispatch
18 | dispatch_i : in dispatch_producer_r;
19 | dispatch_o : out dispatch_consumer_r;
20 | -- Output to TX
21 | arbiter_i : in arbiter_producer_r;
22 | arbiter_o : out arbiter_consumer_r);
23 | end entity tlp_streamer_loopback;
24 |
25 | architecture RTL of tlp_streamer_loopback is
26 |
27 | component fifo_36_36_prim IS
28 | PORT (
29 | rst : IN STD_LOGIC;
30 | wr_clk : IN STD_LOGIC;
31 | rd_clk : IN STD_LOGIC;
32 | din : IN STD_LOGIC_VECTOR(35 DOWNTO 0);
33 | wr_en : IN STD_LOGIC;
34 | rd_en : IN STD_LOGIC;
35 | dout : OUT STD_LOGIC_VECTOR(35 DOWNTO 0);
36 | full : OUT STD_LOGIC;
37 | empty : OUT STD_LOGIC;
38 | valid : OUT STD_LOGIC);
39 | END component fifo_36_36_prim;
40 |
41 | signal loopback_wr_en_s: std_logic;
42 |
43 | begin
44 |
45 | loopback_fifo: fifo_36_36_prim
46 | port map (
47 | rst => sys_reset_i,
48 | wr_clk => sys_clk_i,
49 | rd_clk => sys_clk_i,
50 | din => dispatch_i.dispatch_wr_data,
51 | wr_en => loopback_wr_en_s,
52 | rd_en => arbiter_i.arbiter_rd_en,
53 | dout => arbiter_o.arbiter_rd_data,
54 | full => dispatch_o.dispatch_wr_full,
55 | empty => arbiter_o.arbiter_rd_empty,
56 | valid => arbiter_o.arbiter_rd_valid);
57 |
58 | loopback_wr_en_s <= dispatch_i.dispatch_wr_en and dispatch_i.dispatch_valid;
59 |
60 | end architecture RTL;
61 |
--------------------------------------------------------------------------------
/src/design/tlp_streamer_pcie.vhd:
--------------------------------------------------------------------------------
1 | --
2 | -- TLP Streamer - PCIe Interface
3 | --
4 | -- (c) MikeM64 - 2021
5 | --
6 |
7 | library IEEE;
8 | use IEEE.std_logic_1164.all;
9 | use IEEE.numeric_std.all;
10 |
11 | library UNISIM;
12 | use UNISIM.vcomponents.all;
13 |
14 | use work.tlp_streamer_records.all;
15 |
16 | entity tlp_streamer_pcie is
17 | port (
18 | user_led_ld2 : out std_logic;
19 | sys_clk_i : in std_logic;
20 | sys_reset_i : in std_logic;
21 | pcie_clk_p_i : in std_logic;
22 | pcie_clk_n_i : in std_logic;
23 | pcie_perst_n_i : in std_logic;
24 | pcie_wake_n_o : out std_logic;
25 | pcie_txp_o : out std_logic_vector(0 downto 0);
26 | pcie_txn_o : out std_logic_vector(0 downto 0);
27 | pcie_rxp_i : in std_logic_vector(0 downto 0);
28 | pcie_rxn_i : in std_logic_vector(0 downto 0);
29 | --pcie_usr_clk_o : out std_logic;
30 | --pcie_usr_rst_o : out std_logic;
31 | pcie_usr_link_up_o : out std_logic;
32 | -- Host Packet RX/TX management
33 | pcie_cfg_dispatch_i : in dispatch_producer_r;
34 | pcie_cfg_dispatch_o : out dispatch_consumer_r;
35 | pcie_cfg_arbiter_i : in arbiter_producer_r;
36 | pcie_cfg_arbiter_o : out arbiter_consumer_r;
37 | pcie_tlp_dispatch_i : in dispatch_producer_r;
38 | pcie_tlp_dispatch_o : out dispatch_consumer_r;
39 | pcie_tlp_arbiter_i : in arbiter_producer_r;
40 | pcie_tlp_arbiter_o : out arbiter_consumer_r);
41 | --pcie_usr_app_rdy : out std_logic;
42 | --pcie_s_axi_tx_tready_o : out std_logic;
43 | --pcie_s_axi_tx_tdata_i : in std_logic_vector(63 downto 0);
44 | --pcie_s_axi_tx_tkeep_i : in std_logic_vector(7 downto 0);
45 | --pcie_s_axi_tx_tlast_i : in std_logic;
46 | --pcie_s_axi_tx_tvalid_i : in std_logic;
47 | --pcie_s_axi_tx_tuser_i : in std_logic_vector(3 downto 0);
48 | --pcie_m_axi_rx_tdata_o : out std_logic_vector(63 downto 0);
49 | --pcie_m_axi_rx_tkeep_o : out std_logic_vector(7 downto 0);
50 | --pcie_m_axi_rx_tlast_o : out std_logic;
51 | --pcie_m_axi_rx_tvalid_o : out std_logic;
52 | --pcie_m_axi_rx_tready_i : in std_logic;
53 | --pcie_m_axi_rx_tuser_o : out std_logic_vector(21 downto 0);
54 | end entity tlp_streamer_pcie;
55 |
56 | architecture RTL of tlp_streamer_pcie is
57 |
58 | component pcie_7x_0 IS
59 | PORT (
60 | pci_exp_txp : OUT STD_LOGIC_VECTOR(0 DOWNTO 0);
61 | pci_exp_txn : OUT STD_LOGIC_VECTOR(0 DOWNTO 0);
62 | pci_exp_rxp : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
63 | pci_exp_rxn : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
64 | user_clk_out : OUT STD_LOGIC;
65 | user_reset_out : OUT STD_LOGIC;
66 | user_lnk_up : OUT STD_LOGIC;
67 | user_app_rdy : OUT STD_LOGIC;
68 | s_axis_tx_tready : OUT STD_LOGIC;
69 | s_axis_tx_tdata : IN STD_LOGIC_VECTOR(63 DOWNTO 0);
70 | s_axis_tx_tkeep : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
71 | s_axis_tx_tlast : IN STD_LOGIC;
72 | s_axis_tx_tvalid : IN STD_LOGIC;
73 | s_axis_tx_tuser : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
74 | m_axis_rx_tdata : OUT STD_LOGIC_VECTOR(63 DOWNTO 0);
75 | m_axis_rx_tkeep : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
76 | m_axis_rx_tlast : OUT STD_LOGIC;
77 | m_axis_rx_tvalid : OUT STD_LOGIC;
78 | m_axis_rx_tready : IN STD_LOGIC;
79 | m_axis_rx_tuser : OUT STD_LOGIC_VECTOR(21 DOWNTO 0);
80 | -- PCIe configuration management port
81 | cfg_mgmt_do : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);
82 | cfg_mgmt_rd_wr_done : OUT STD_LOGIC;
83 | cfg_mgmt_di : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
84 | cfg_mgmt_byte_en : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
85 | cfg_mgmt_dwaddr : IN STD_LOGIC_VECTOR(9 DOWNTO 0);
86 | cfg_mgmt_wr_en : IN STD_LOGIC;
87 | cfg_mgmt_rd_en : IN STD_LOGIC;
88 | cfg_mgmt_wr_readonly : IN STD_LOGIC;
89 | cfg_mgmt_wr_rw1c_as_rw : IN STD_LOGIC;
90 | cfg_interrupt : IN STD_LOGIC;
91 | cfg_interrupt_rdy : OUT STD_LOGIC;
92 | cfg_interrupt_assert : IN STD_LOGIC;
93 | cfg_interrupt_di : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
94 | cfg_interrupt_do : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
95 | cfg_interrupt_mmenable : OUT STD_LOGIC_VECTOR(2 DOWNTO 0);
96 | cfg_interrupt_msienable : OUT STD_LOGIC;
97 | cfg_interrupt_msixenable : OUT STD_LOGIC;
98 | cfg_interrupt_msixfm : OUT STD_LOGIC;
99 | cfg_interrupt_stat : IN STD_LOGIC;
100 | cfg_pciecap_interrupt_msgnum : IN STD_LOGIC_VECTOR(4 DOWNTO 0);
101 | pl_directed_link_change : IN STD_LOGIC_VECTOR(1 DOWNTO 0);
102 | pl_directed_link_width : IN STD_LOGIC_VECTOR(1 DOWNTO 0);
103 | pl_directed_link_speed : IN STD_LOGIC;
104 | pl_directed_link_auton : IN STD_LOGIC;
105 | pl_upstream_prefer_deemph : IN STD_LOGIC;
106 | pl_sel_lnk_rate : OUT STD_LOGIC; --
107 | pl_sel_lnk_width : OUT STD_LOGIC_VECTOR(1 DOWNTO 0);
108 | pl_ltssm_state : OUT STD_LOGIC_VECTOR(5 DOWNTO 0);
109 | pl_lane_reversal_mode : OUT STD_LOGIC_VECTOR(1 DOWNTO 0);
110 | pl_phy_lnk_up : OUT STD_LOGIC;
111 | pl_tx_pm_state : OUT STD_LOGIC_VECTOR(2 DOWNTO 0);
112 | pl_rx_pm_state : OUT STD_LOGIC_VECTOR(1 DOWNTO 0);
113 | pl_link_upcfg_cap : OUT STD_LOGIC;
114 | pl_link_gen2_cap : OUT STD_LOGIC;
115 | pl_link_partner_gen2_supported : OUT STD_LOGIC;
116 | pl_initial_link_width : OUT STD_LOGIC_VECTOR(2 DOWNTO 0); --
117 | pl_directed_change_done : OUT STD_LOGIC;
118 | pl_received_hot_rst : OUT STD_LOGIC;
119 | pl_transmit_hot_rst : IN STD_LOGIC;
120 | pl_downstream_deemph_source : IN STD_LOGIC;
121 | sys_clk : IN STD_LOGIC;
122 | sys_rst_n : IN STD_LOGIC
123 | );
124 | END component pcie_7x_0;
125 |
126 | component tlp_streamer_pcie_cfg is
127 | port (
128 | sys_clk_i : in std_logic;
129 | pcie_clk_i : in std_logic;
130 | sys_reset_i : in std_logic;
131 | -- PCIe Configuration Port from PCIe IP
132 | pcie_cfg_mgmt_producer_i : in pcie_cfg_mgmt_port_producer_r;
133 | pcie_cfg_mgmt_consumer_o : out pcie_cfg_mgmt_port_consumer_r;
134 | -- Input Requests from the host to handle
135 | dispatch_i : in dispatch_producer_r;
136 | dispatch_o : out dispatch_consumer_r;
137 | -- Output Packets towards the host
138 | arbiter_i : in arbiter_producer_r;
139 | arbiter_o : out arbiter_consumer_r);
140 | end component tlp_streamer_pcie_cfg;
141 |
142 | component tlp_streamer_pcie_tlp is
143 | port (
144 | sys_clk_i : in std_logic;
145 | pcie_clk_i : in std_logic;
146 | pcie_rst_i : in std_logic;
147 | -- Host Packet RX/TX management
148 | dispatch_i : in dispatch_producer_r;
149 | dispatch_o : out dispatch_consumer_r;
150 | arbiter_i : in arbiter_producer_r;
151 | arbiter_o : out arbiter_consumer_r;
152 | -- PCIe Core TLP Interface
153 | pcie_tlp_tx_producer_i : in pcie_tlp_tx_port_producer_r;
154 | pcie_tlp_tx_consumer_o : out pcie_tlp_tx_port_consumer_r;
155 | pcie_tlp_rx_producer_i : in pcie_tlp_rx_port_producer_r;
156 | pcie_tlp_rx_consumer_o : out pcie_tlp_rx_port_consumer_r);
157 | end component tlp_streamer_pcie_tlp;
158 |
159 | signal pcie_rst_n_s: std_logic;
160 | signal pcie_clk_s: std_logic;
161 |
162 | -- Temporary signal until more behaviour is implemented/exposed to other components.
163 | signal user_clk_s, user_lnk_up_s, user_reset_s, user_app_rdy_s: std_logic;
164 |
165 | signal cfg_interrupt_s, cfg_interrupt_rdy_s, cfg_interrupt_assert_s,
166 | cfg_interrupt_msienable_s, cfg_interrupt_msixenable_s,
167 | cfg_interrupt_msixfm_s, cfg_interrupt_stat_s: std_logic := '0';
168 | signal cfg_interrupt_di_s, cfg_interrupt_do_s: std_logic_vector(7 downto 0) := "00000000";
169 | signal cfg_interrupt_mmenable_s: std_logic_vector(2 downto 0) := "000";
170 | signal cfg_pciecap_interrupt_msgnum_s: std_logic_vector(4 downto 0) := "00000";
171 |
172 | signal pl_directed_link_change_s, pl_directed_link_width_s: std_logic_vector(1 downto 0) := "00";
173 | signal pl_directed_link_speed_s, pl_directed_link_auton_s, pl_upstream_prefer_deemph_s,
174 | pl_sel_lnk_rate_s, pl_phy_lnk_up_s, pl_link_upcfg_cap_s, pl_link_gen2_cap_s,
175 | pl_link_partner_gen2_supported_s, pl_directed_change_done_s, pl_received_hot_rst_s,
176 | pl_transmit_hot_rst_s, pl_downstream_deemph_source_s: std_logic := '0';
177 | signal pl_sel_lnk_width_s, pl_lane_reversal_mode_s, pl_rx_pm_state_s: std_logic_vector(1 downto 0) := "00";
178 | signal pl_ltssm_state_s: std_logic_vector(5 downto 0) := "000000";
179 | signal pl_tx_pm_state_s, pl_initial_link_width_s: std_logic_vector(2 downto 0) := "000";
180 |
181 | signal pcie_clk_blink_64_s: unsigned(63 downto 0) := (others => '0');
182 |
183 | -- Configuration management interface
184 | signal pcie_cfg_mgmt_producer_s: pcie_cfg_mgmt_port_producer_r;
185 | signal pcie_cfg_mgmt_consumer_s: pcie_cfg_mgmt_port_consumer_r;
186 |
187 | -- TLP RX/TX Interface
188 | signal pcie_tlp_tx_producer_s: pcie_tlp_tx_port_producer_r;
189 | signal pcie_tlp_tx_consumer_s: pcie_tlp_tx_port_consumer_r;
190 | signal pcie_tlp_rx_producer_s: pcie_tlp_rx_port_producer_r;
191 | signal pcie_tlp_rx_consumer_s: pcie_tlp_rx_port_consumer_r;
192 |
193 | begin
194 |
195 | -- Refer to https://www.xilinx.com/support/documentation/user_guides/ug482_7Series_GTP_Transceivers.pdf
196 | -- Page 24 for IBUFDS_GTE2 configuration options
197 | ibufds_gte2_pcie_clk : IBUFDS_GTE2
198 | generic map (
199 | CLKCM_CFG => TRUE,
200 | CLKRCV_TRST => TRUE,
201 | CLKSWING_CFG => "11"
202 | )
203 | port map (
204 | O => pcie_clk_s,
205 | ODIV2 => open,
206 | CEB => '0',
207 | I => pcie_clk_p_i,
208 | IB => pcie_clk_n_i
209 | );
210 |
211 | comp_tlp_streamer_pcie_cfg: tlp_streamer_pcie_cfg
212 | port map (
213 | sys_clk_i => sys_clk_i,
214 | pcie_clk_i => user_clk_s,
215 | sys_reset_i => user_reset_s,
216 | -- PCIe Configuration Port from PCIe IP
217 | pcie_cfg_mgmt_producer_i => pcie_cfg_mgmt_producer_s,
218 | pcie_cfg_mgmt_consumer_o => pcie_cfg_mgmt_consumer_s,
219 | -- Input Requests from the host to handle
220 | dispatch_i => pcie_cfg_dispatch_i,
221 | dispatch_o => pcie_cfg_dispatch_o,
222 | -- Output Packets towards the host
223 | arbiter_i => pcie_cfg_arbiter_i,
224 | arbiter_o => pcie_cfg_arbiter_o);
225 |
226 | comp_tlp_streamer_pcie_tlp: tlp_streamer_pcie_tlp
227 | port map(
228 | sys_clk_i => sys_clk_i,
229 | pcie_clk_i => user_clk_s,
230 | pcie_rst_i => user_reset_s,
231 | -- Host Packet RX/TX management
232 | dispatch_i => pcie_tlp_dispatch_i,
233 | dispatch_o => pcie_tlp_dispatch_o,
234 | arbiter_i => pcie_tlp_arbiter_i,
235 | arbiter_o => pcie_tlp_arbiter_o,
236 | -- PCIe Core TLP Interface
237 | pcie_tlp_tx_producer_i => pcie_tlp_tx_producer_s,
238 | pcie_tlp_tx_consumer_o => pcie_tlp_tx_consumer_s,
239 | pcie_tlp_rx_producer_i => pcie_tlp_rx_producer_s,
240 | pcie_tlp_rx_consumer_o => pcie_tlp_rx_consumer_s);
241 |
242 | comp_pcie_7x_0: pcie_7x_0
243 | port map(
244 | pci_exp_txp => pcie_txp_o,
245 | pci_exp_txn => pcie_txn_o,
246 | pci_exp_rxp => pcie_rxp_i,
247 | pci_exp_rxn => pcie_rxn_i,
248 | user_clk_out => user_clk_s,
249 | user_reset_out => user_reset_s,
250 | user_lnk_up => user_lnk_up_s,
251 | user_app_rdy => user_app_rdy_s,
252 | s_axis_tx_tready => pcie_tlp_tx_producer_s.tlp_axis_tx_tready,
253 | s_axis_tx_tdata => pcie_tlp_tx_consumer_s.tlp_axis_tx_tdata,
254 | s_axis_tx_tkeep => pcie_tlp_tx_consumer_s.tlp_axis_tx_tkeep,
255 | s_axis_tx_tlast => pcie_tlp_tx_consumer_s.tlp_axis_tx_tlast,
256 | s_axis_tx_tvalid => pcie_tlp_tx_consumer_s.tlp_axis_tx_tvalid,
257 | s_axis_tx_tuser => pcie_tlp_tx_consumer_s.tlp_axis_tx_tuser,
258 | m_axis_rx_tdata => pcie_tlp_rx_producer_s.tlp_axis_rx_tdata,
259 | m_axis_rx_tkeep => pcie_tlp_rx_producer_s.tlp_axis_rx_tkeep,
260 | m_axis_rx_tlast => pcie_tlp_rx_producer_s.tlp_axis_rx_tlast,
261 | m_axis_rx_tvalid => pcie_tlp_rx_producer_s.tlp_axis_rx_tvalid,
262 | m_axis_rx_tready => pcie_tlp_rx_consumer_s.tlp_axis_rx_tready,
263 | m_axis_rx_tuser => pcie_tlp_rx_producer_s.tlp_axis_rx_tuser,
264 | -- Configuration space management port
265 | cfg_mgmt_do => pcie_cfg_mgmt_producer_s.cfg_mgmt_do,
266 | cfg_mgmt_rd_wr_done => pcie_cfg_mgmt_producer_s.cfg_mgmt_rd_wr_done,
267 | cfg_mgmt_di => pcie_cfg_mgmt_consumer_s.cfg_mgmt_di,
268 | cfg_mgmt_byte_en => pcie_cfg_mgmt_consumer_s.cfg_mgmt_byte_en,
269 | cfg_mgmt_dwaddr => pcie_cfg_mgmt_consumer_s.cfg_mgmt_dwaddr,
270 | cfg_mgmt_wr_en => pcie_cfg_mgmt_consumer_s.cfg_mgmt_wr_en,
271 | cfg_mgmt_rd_en => pcie_cfg_mgmt_consumer_s.cfg_mgmt_rd_en,
272 | cfg_mgmt_wr_readonly => pcie_cfg_mgmt_consumer_s.cfg_mgmt_wr_readonly,
273 | cfg_mgmt_wr_rw1c_as_rw => pcie_cfg_mgmt_consumer_s.cfg_mgmt_wr_rw1c_as_rw,
274 | cfg_interrupt => cfg_interrupt_s,
275 | cfg_interrupt_rdy => cfg_interrupt_rdy_s,
276 | cfg_interrupt_assert => cfg_interrupt_assert_s,
277 | cfg_interrupt_di => cfg_interrupt_di_s,
278 | cfg_interrupt_do => cfg_interrupt_do_s,
279 | cfg_interrupt_mmenable => cfg_interrupt_mmenable_s,
280 | cfg_interrupt_msienable => cfg_interrupt_msienable_s,
281 | cfg_interrupt_msixenable => cfg_interrupt_msixenable_s,
282 | cfg_interrupt_msixfm => cfg_interrupt_msixfm_s,
283 | cfg_interrupt_stat => cfg_interrupt_stat_s,
284 | cfg_pciecap_interrupt_msgnum => cfg_pciecap_interrupt_msgnum_s,
285 | pl_directed_link_change => pl_directed_link_change_s,
286 | pl_directed_link_width => pl_directed_link_width_s,
287 | pl_directed_link_speed => pl_directed_link_speed_s,
288 | pl_directed_link_auton => pl_directed_link_auton_s,
289 | pl_upstream_prefer_deemph => pl_upstream_prefer_deemph_s,
290 | pl_sel_lnk_rate => pl_sel_lnk_rate_s,
291 | pl_sel_lnk_width => pl_sel_lnk_width_s,
292 | pl_ltssm_state => pl_ltssm_state_s,
293 | pl_lane_reversal_mode => pl_lane_reversal_mode_s,
294 | pl_phy_lnk_up => pl_phy_lnk_up_s,
295 | pl_tx_pm_state => pl_tx_pm_state_s,
296 | pl_rx_pm_state => pl_rx_pm_state_s,
297 | pl_link_upcfg_cap => pl_link_upcfg_cap_s,
298 | pl_link_gen2_cap => pl_link_gen2_cap_s,
299 | pl_link_partner_gen2_supported => pl_link_partner_gen2_supported_s,
300 | pl_initial_link_width => pl_initial_link_width_s,
301 | pl_directed_change_done => pl_directed_change_done_s,
302 | pl_received_hot_rst => pl_received_hot_rst_s,
303 | pl_transmit_hot_rst => pl_transmit_hot_rst_s,
304 | pl_downstream_deemph_source => pl_downstream_deemph_source_s,
305 | sys_clk => pcie_clk_s,
306 | sys_rst_n => pcie_rst_n_s
307 | );
308 |
309 | pcie_reset_process: process(sys_reset_i, pcie_perst_n_i, user_lnk_up_s)
310 | begin
311 |
312 | pcie_wake_n_o <= '1';
313 | pcie_rst_n_s <= not (sys_reset_i or not pcie_perst_n_i);
314 | pcie_usr_link_up_o <= user_lnk_up_s;
315 |
316 | end process pcie_reset_process;
317 |
318 | blink_debug_process: process(pcie_clk_s, pcie_clk_blink_64_s)
319 | begin
320 | user_led_ld2 <= pcie_clk_blink_64_s(25);
321 |
322 | if (rising_edge(pcie_clk_s)) then
323 | pcie_clk_blink_64_s <= pcie_clk_blink_64_s + 1;
324 | end if;
325 |
326 | end process blink_debug_process;
327 |
328 | end architecture RTL;
--------------------------------------------------------------------------------
/src/design/tlp_streamer_pcie_cfg.vhd:
--------------------------------------------------------------------------------
1 | --
2 | -- TLP Streamer - PCIe Configuration Space Request Management
3 | --
4 | -- (c) MikeM64 - 2021
5 | --
6 |
7 | library IEEE;
8 | use IEEE.std_logic_1164.all;
9 | use IEEE.numeric_std.all;
10 |
11 | use work.tlp_streamer_records.all;
12 |
13 | entity tlp_streamer_pcie_cfg is
14 | port (
15 | sys_clk_i : in std_logic;
16 | pcie_clk_i : in std_logic;
17 | sys_reset_i : in std_logic;
18 | -- PCIe Configuration Port from PCIe IP
19 | pcie_cfg_mgmt_producer_i : in pcie_cfg_mgmt_port_producer_r;
20 | pcie_cfg_mgmt_consumer_o : out pcie_cfg_mgmt_port_consumer_r;
21 | -- Input Requests from the host to handle
22 | dispatch_i : in dispatch_producer_r;
23 | dispatch_o : out dispatch_consumer_r;
24 | -- Output Packets towards the host
25 | arbiter_i : in arbiter_producer_r;
26 | arbiter_o : out arbiter_consumer_r);
27 | end entity tlp_streamer_pcie_cfg;
28 |
29 | architecture RTL of tlp_streamer_pcie_cfg is
30 |
31 | component fifo_32_32_bram IS
32 | port (
33 | rst : IN STD_LOGIC;
34 | wr_clk : IN STD_LOGIC;
35 | rd_clk : IN STD_LOGIC;
36 | din : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
37 | wr_en : IN STD_LOGIC;
38 | rd_en : IN STD_LOGIC;
39 | dout : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);
40 | full : OUT STD_LOGIC;
41 | empty : OUT STD_LOGIC;
42 | valid : OUT STD_LOGIC;
43 | wr_rst_busy : OUT STD_LOGIC;
44 | rd_rst_busy : OUT STD_LOGIC
45 | );
46 | end component fifo_32_32_bram;
47 |
48 | type pcie_cfg_req_state is (PCIE_CFG_IDLE, PCIE_CFG_AWAIT_HEADER, PCIE_CFG_PARSE_HEADER_1,
49 | PCIE_CFG_PARSE_HEADER_2, PCIE_CFG_PARSE_CMD_1, PCIE_CFG_PARSE_CMD_2,
50 | PCIE_CFG_READ_1, PCIE_CFG_READ_2, PCIE_CFG_WRITE_1, PCIE_CFG_WRITE_2,
51 | PCIE_CFG_TX_PACKET_1, PCIE_CFG_TX_PACKET_2, PCIE_CFG_TX_PACKET_3,
52 | PCIE_CFG_TX_PACKET_4, PCIE_CFG_COMPLETE);
53 |
54 | signal current_pcie_cfg_req_state, next_pcie_cfg_req_state: pcie_cfg_req_state;
55 |
56 | -- RX/TX FIFO Signals
57 | signal pcie_cfg_fifo_rx_wr_en_s: std_logic;
58 | signal pcie_cfg_fifo_rx_rd_en_s, pcie_cfg_fifo_rx_rd_empty_s, pcie_cfg_fifo_rx_rd_valid_s: std_logic;
59 | signal pcie_cfg_fifo_rx_rd_data_s: std_logic_vector(31 downto 0);
60 |
61 | signal pcie_cfg_fifo_tx_wr_en_s, next_pcie_cfg_fifo_tx_wr_en_s, pcie_cfg_fifo_tx_wr_full_s: std_logic;
62 | signal pcie_cfg_fifo_tx_wr_data_s, next_pcie_cfg_fifo_tx_wr_data_s, pcie_cfg_fifo_tx_rd_data_s: std_logic_vector(31 downto 0);
63 |
64 | -- Current packet signals
65 | signal pcie_cfg_req_seq_id_s, next_pcie_cfg_req_seq_id_s: std_logic_vector(15 downto 0);
66 | signal pcie_cfg_cmd_write_be_s, next_pcie_cfg_cmd_write_be_s: std_logic_vector(3 downto 0);
67 | signal pcie_cfg_cmd_write_s, next_pcie_cfg_cmd_write_s: std_logic;
68 | signal pcie_cfg_cmd_write_readonly_s, next_pcie_cfg_cmd_write_readonly_s: std_logic;
69 | signal pcie_cfg_cmd_write_rw1c_as_rw_s, next_pcie_cfg_cmd_write_rw1c_as_rw_s: std_logic;
70 | signal pcie_cfg_cmd_addr_s, next_pcie_cfg_cmd_addr_s: std_logic_vector(9 downto 0);
71 | signal pcie_cfg_cmd_data_s, next_pcie_cfg_cmd_data_s: std_logic_vector(31 downto 0);
72 |
73 | begin
74 |
75 | comp_pcie_cfg_rx_fifo: fifo_32_32_bram
76 | port map (
77 | rst => sys_reset_i,
78 | wr_clk => sys_clk_i,
79 | rd_clk => pcie_clk_i,
80 | din => dispatch_i.dispatch_wr_data(31 downto 0),
81 | wr_en => pcie_cfg_fifo_rx_wr_en_s,
82 | rd_en => pcie_cfg_fifo_rx_rd_en_s,
83 | dout => pcie_cfg_fifo_rx_rd_data_s,
84 | full => dispatch_o.dispatch_wr_full,
85 | empty => pcie_cfg_fifo_rx_rd_empty_s,
86 | valid => pcie_cfg_fifo_rx_rd_valid_s,
87 | wr_rst_busy => open,
88 | rd_rst_busy => open);
89 |
90 | comp_pcie_cfg_tx_fifo: fifo_32_32_bram
91 | port map (
92 | rst => sys_reset_i,
93 | wr_clk => pcie_clk_i,
94 | rd_clk => sys_clk_i,
95 | din => pcie_cfg_fifo_tx_wr_data_s,
96 | wr_en => pcie_cfg_fifo_tx_wr_en_s,
97 | rd_en => arbiter_i.arbiter_rd_en,
98 | dout => pcie_cfg_fifo_tx_rd_data_s,
99 | full => pcie_cfg_fifo_tx_wr_full_s,
100 | empty => arbiter_o.arbiter_rd_empty,
101 | valid => arbiter_o.arbiter_rd_valid,
102 | wr_rst_busy => open,
103 | rd_rst_busy => open);
104 |
105 | pcie_cfg_rx_tx_async_process: process(dispatch_i, pcie_cfg_fifo_tx_rd_data_s)
106 | begin
107 |
108 | pcie_cfg_fifo_rx_wr_en_s <= dispatch_i.dispatch_wr_en and
109 | dispatch_i.dispatch_valid;
110 | -- The extra 1's here correspond to the byte_enable portion of the
111 | -- data sent to the FT601
112 | arbiter_o.arbiter_rd_data <= "1111" & pcie_cfg_fifo_tx_rd_data_s;
113 |
114 | end process pcie_cfg_rx_tx_async_process;
115 |
116 | pcie_cfg_fsm_state_process: process(pcie_clk_i, sys_reset_i, next_pcie_cfg_req_state, current_pcie_cfg_req_state,
117 | next_pcie_cfg_req_seq_id_s, next_pcie_cfg_cmd_write_be_s,
118 | next_pcie_cfg_cmd_write_s, next_pcie_cfg_cmd_addr_s,
119 | next_pcie_cfg_cmd_data_s, next_pcie_cfg_fifo_tx_wr_data_s,
120 | next_pcie_cfg_cmd_write_readonly_s, next_pcie_cfg_cmd_write_rw1c_as_rw_s)
121 | begin
122 |
123 | if (sys_reset_i = '1') then
124 | current_pcie_cfg_req_state <= PCIE_CFG_IDLE;
125 | pcie_cfg_req_seq_id_s <= (others => '0');
126 | pcie_cfg_cmd_write_be_s <= (others => '0');
127 | pcie_cfg_cmd_write_s <= '0';
128 | pcie_cfg_cmd_addr_s <= (others => '0');
129 | pcie_cfg_cmd_data_s <= (others => '0');
130 | pcie_cfg_fifo_tx_wr_data_s <= (others => '0');
131 | pcie_cfg_fifo_tx_wr_en_s <= '0';
132 | elsif (rising_edge(pcie_clk_i)) then
133 | current_pcie_cfg_req_state <= next_pcie_cfg_req_state;
134 |
135 | pcie_cfg_req_seq_id_s <= next_pcie_cfg_req_seq_id_s;
136 | pcie_cfg_cmd_write_be_s <= next_pcie_cfg_cmd_write_be_s;
137 | pcie_cfg_cmd_write_s <= next_pcie_cfg_cmd_write_s;
138 | pcie_cfg_cmd_write_readonly_s <= next_pcie_cfg_cmd_write_readonly_s;
139 | pcie_cfg_cmd_write_rw1c_as_rw_s <= next_pcie_cfg_cmd_write_rw1c_as_rw_s;
140 | pcie_cfg_cmd_addr_s <= next_pcie_cfg_cmd_addr_s;
141 | pcie_cfg_cmd_data_s <= next_pcie_cfg_cmd_data_s;
142 |
143 | pcie_cfg_fifo_tx_wr_data_s <= next_pcie_cfg_fifo_tx_wr_data_s;
144 | pcie_cfg_fifo_tx_wr_en_s <= next_pcie_cfg_fifo_tx_wr_en_s;
145 | end if;
146 |
147 | end process pcie_cfg_fsm_state_process;
148 |
149 | pcie_cfg_fsm_data_output_process: process(current_pcie_cfg_req_state, pcie_cfg_req_seq_id_s,
150 | pcie_cfg_cmd_write_be_s, pcie_cfg_cmd_write_s,
151 | pcie_cfg_cmd_addr_s, pcie_cfg_cmd_data_s,
152 | pcie_cfg_fifo_rx_rd_data_s, pcie_cfg_mgmt_producer_i,
153 | pcie_cfg_fifo_tx_wr_data_s, pcie_cfg_cmd_write_readonly_s,
154 | pcie_cfg_cmd_write_rw1c_as_rw_s)
155 | begin
156 |
157 | pcie_cfg_fifo_rx_rd_en_s <= '0';
158 | next_pcie_cfg_fifo_tx_wr_en_s <= '0';
159 |
160 | next_pcie_cfg_req_seq_id_s <= pcie_cfg_req_seq_id_s;
161 | next_pcie_cfg_cmd_write_be_s <= pcie_cfg_cmd_write_be_s;
162 | next_pcie_cfg_cmd_write_s <= pcie_cfg_cmd_write_s;
163 | next_pcie_cfg_cmd_write_readonly_s <= pcie_cfg_cmd_write_readonly_s;
164 | next_pcie_cfg_cmd_write_rw1c_as_rw_s <= pcie_cfg_cmd_write_rw1c_as_rw_s;
165 | next_pcie_cfg_cmd_addr_s <= pcie_cfg_cmd_addr_s;
166 | next_pcie_cfg_cmd_data_s <= pcie_cfg_cmd_data_s;
167 | next_pcie_cfg_fifo_tx_wr_data_s <= pcie_cfg_fifo_tx_wr_data_s;
168 |
169 | pcie_cfg_mgmt_consumer_o.cfg_mgmt_di <= (others => '0');
170 | pcie_cfg_mgmt_consumer_o.cfg_mgmt_byte_en <= (others => '0');
171 | pcie_cfg_mgmt_consumer_o.cfg_mgmt_dwaddr <= (others => '0');
172 | pcie_cfg_mgmt_consumer_o.cfg_mgmt_wr_en <= '0';
173 | pcie_cfg_mgmt_consumer_o.cfg_mgmt_rd_en <= '0';
174 | pcie_cfg_mgmt_consumer_o.cfg_mgmt_wr_readonly <= '0';
175 | pcie_cfg_mgmt_consumer_o.cfg_mgmt_wr_rw1c_as_rw <= '0';
176 |
177 | case current_pcie_cfg_req_state is
178 | when PCIE_CFG_IDLE =>
179 | when PCIE_CFG_AWAIT_HEADER =>
180 | pcie_cfg_fifo_rx_rd_en_s <= '1';
181 | when PCIE_CFG_PARSE_HEADER_1 =>
182 | -- First valid header word will be here
183 | -- tsh_msg_type and tsh_msg_len are not used by this component and ignored.
184 | pcie_cfg_fifo_rx_rd_en_s <= '1';
185 | when PCIE_CFG_PARSE_HEADER_2 =>
186 | next_pcie_cfg_req_seq_id_s <= pcie_cfg_fifo_rx_rd_data_s(15 downto 0) ;
187 | pcie_cfg_fifo_rx_rd_en_s <= '1';
188 | when PCIE_CFG_PARSE_CMD_1 =>
189 | -- struct tlp_streamer_pcie_cfg_cmd is always fully
190 | -- parsed to simplify the decoding pipeline
191 | pcie_cfg_fifo_rx_rd_en_s <= '1';
192 | next_pcie_cfg_cmd_addr_s <= pcie_cfg_fifo_rx_rd_data_s(9 downto 0);
193 | next_pcie_cfg_cmd_write_s <= pcie_cfg_fifo_rx_rd_data_s(16);
194 | next_pcie_cfg_cmd_write_readonly_s <= pcie_cfg_fifo_rx_rd_data_s(17);
195 | next_pcie_cfg_cmd_write_rw1c_as_rw_s <= pcie_cfg_fifo_rx_rd_data_s(18);
196 | next_pcie_cfg_cmd_write_be_s <= pcie_cfg_fifo_rx_rd_data_s(27 downto 24);
197 | when PCIE_CFG_PARSE_CMD_2 =>
198 | next_pcie_cfg_cmd_data_s <= pcie_cfg_fifo_rx_rd_data_s;
199 | when PCIE_CFG_READ_1 =>
200 | pcie_cfg_mgmt_consumer_o.cfg_mgmt_rd_en <= '1';
201 | pcie_cfg_mgmt_consumer_o.cfg_mgmt_dwaddr <= pcie_cfg_cmd_addr_s;
202 | when PCIE_CFG_READ_2 =>
203 | pcie_cfg_mgmt_consumer_o.cfg_mgmt_rd_en <= '1';
204 | pcie_cfg_mgmt_consumer_o.cfg_mgmt_dwaddr <= pcie_cfg_cmd_addr_s;
205 | next_pcie_cfg_cmd_data_s <= pcie_cfg_mgmt_producer_i.cfg_mgmt_do;
206 | when PCIE_CFG_WRITE_1 =>
207 | pcie_cfg_mgmt_consumer_o.cfg_mgmt_wr_en <= '1';
208 | pcie_cfg_mgmt_consumer_o.cfg_mgmt_wr_readonly <= pcie_cfg_cmd_write_readonly_s;
209 | pcie_cfg_mgmt_consumer_o.cfg_mgmt_wr_rw1c_as_rw <= pcie_cfg_cmd_write_rw1c_as_rw_s;
210 | pcie_cfg_mgmt_consumer_o.cfg_mgmt_dwaddr <= pcie_cfg_cmd_addr_s;
211 | pcie_cfg_mgmt_consumer_o.cfg_mgmt_di <= pcie_cfg_cmd_data_s;
212 | pcie_cfg_mgmt_consumer_o.cfg_mgmt_byte_en <= pcie_cfg_cmd_write_be_s;
213 | when PCIE_CFG_WRITE_2 =>
214 | pcie_cfg_mgmt_consumer_o.cfg_mgmt_wr_en <= '1';
215 | pcie_cfg_mgmt_consumer_o.cfg_mgmt_wr_readonly <= pcie_cfg_cmd_write_readonly_s;
216 | pcie_cfg_mgmt_consumer_o.cfg_mgmt_wr_rw1c_as_rw <= pcie_cfg_cmd_write_rw1c_as_rw_s;
217 | pcie_cfg_mgmt_consumer_o.cfg_mgmt_dwaddr <= pcie_cfg_cmd_addr_s;
218 | pcie_cfg_mgmt_consumer_o.cfg_mgmt_di <= pcie_cfg_cmd_data_s;
219 | pcie_cfg_mgmt_consumer_o.cfg_mgmt_byte_en <= pcie_cfg_cmd_write_be_s;
220 | when PCIE_CFG_TX_PACKET_1 =>
221 | next_pcie_cfg_fifo_tx_wr_en_s <= '1';
222 | next_pcie_cfg_fifo_tx_wr_data_s <= "0000010000000000" & "00000000" & "00000001";
223 | when PCIE_CFG_TX_PACKET_2 =>
224 | next_pcie_cfg_fifo_tx_wr_en_s <= '1';
225 | next_pcie_cfg_fifo_tx_wr_data_s <= "0000000000000000" & pcie_cfg_req_seq_id_s;
226 | when PCIE_CFG_TX_PACKET_3 =>
227 | next_pcie_cfg_fifo_tx_wr_en_s <= '1';
228 | next_pcie_cfg_fifo_tx_wr_data_s <= "0000" & pcie_cfg_cmd_write_be_s & "00000" &
229 | pcie_cfg_cmd_write_rw1c_as_rw_s & pcie_cfg_cmd_write_readonly_s &
230 | pcie_cfg_cmd_write_s & "000000" & pcie_cfg_cmd_addr_s;
231 | when PCIE_CFG_TX_PACKET_4 =>
232 | next_pcie_cfg_fifo_tx_wr_en_s <= '1';
233 | next_pcie_cfg_fifo_tx_wr_data_s <= pcie_cfg_cmd_data_s;
234 | when PCIE_CFG_COMPLETE =>
235 | next_pcie_cfg_req_seq_id_s <= (others => '0');
236 | next_pcie_cfg_cmd_write_be_s <= (others => '0');
237 | next_pcie_cfg_cmd_write_s <= '0';
238 | next_pcie_cfg_cmd_write_readonly_s <= '0';
239 | next_pcie_cfg_cmd_write_rw1c_as_rw_s <= '0';
240 | next_pcie_cfg_cmd_addr_s <= (others => '0');
241 | next_pcie_cfg_cmd_data_s <= (others => '0');
242 | end case;
243 |
244 | end process pcie_cfg_fsm_data_output_process;
245 |
246 | pcie_cfg_fsm_state_select_process: process(current_pcie_cfg_req_state, pcie_cfg_fifo_rx_rd_empty_s,
247 | pcie_cfg_cmd_write_s, pcie_cfg_mgmt_producer_i)
248 | begin
249 |
250 | next_pcie_cfg_req_state <= current_pcie_cfg_req_state;
251 |
252 | case current_pcie_cfg_req_state is
253 | when PCIE_CFG_IDLE =>
254 | if (pcie_cfg_fifo_rx_rd_empty_s = '0') then
255 | next_pcie_cfg_req_state <= PCIE_CFG_AWAIT_HEADER;
256 | end if;
257 | when PCIE_CFG_AWAIT_HEADER =>
258 | next_pcie_cfg_req_state <= PCIE_CFG_PARSE_HEADER_1;
259 | when PCIE_CFG_PARSE_HEADER_1 =>
260 | next_pcie_cfg_req_state <= PCIE_CFG_PARSE_HEADER_2;
261 | when PCIE_CFG_PARSE_HEADER_2 =>
262 | next_pcie_cfg_req_state <= PCIE_CFG_PARSE_CMD_1;
263 | when PCIE_CFG_PARSE_CMD_1 =>
264 | next_pcie_cfg_req_state <= PCIE_CFG_PARSE_CMD_2;
265 | when PCIE_CFG_PARSE_CMD_2 =>
266 | if (pcie_cfg_cmd_write_s = '0') then
267 | next_pcie_cfg_req_state <= PCIE_CFG_READ_1;
268 | else
269 | next_pcie_cfg_req_state <= PCIE_CFG_WRITE_1;
270 | end if;
271 | when PCIE_CFG_READ_1 =>
272 | next_pcie_cfg_req_state <= PCIE_CFG_READ_2;
273 | when PCIE_CFG_READ_2 =>
274 | if (pcie_cfg_mgmt_producer_i.cfg_mgmt_rd_wr_done = '1') then
275 | next_pcie_cfg_req_state <= PCIE_CFG_TX_PACKET_1;
276 | end if;
277 | when PCIE_CFG_WRITE_1 =>
278 | next_pcie_cfg_req_state <= PCIE_CFG_WRITE_2;
279 | when PCIE_CFG_WRITE_2 =>
280 | if (pcie_cfg_mgmt_producer_i.cfg_mgmt_rd_wr_done = '1') then
281 | next_pcie_cfg_req_state <= PCIE_CFG_TX_PACKET_1;
282 | end if;
283 | when PCIE_CFG_TX_PACKET_1 =>
284 | next_pcie_cfg_req_state <= PCIE_CFG_TX_PACKET_2;
285 | when PCIE_CFG_TX_PACKET_2 =>
286 | next_pcie_cfg_req_state <= PCIE_CFG_TX_PACKET_3;
287 | when PCIE_CFG_TX_PACKET_3 =>
288 | next_pcie_cfg_req_state <= PCIE_CFG_TX_PACKET_4;
289 | when PCIE_CFG_TX_PACKET_4 =>
290 | next_pcie_cfg_req_state <= PCIE_CFG_COMPLETE;
291 | when PCIE_CFG_COMPLETE =>
292 | next_pcie_cfg_req_state <= PCIE_CFG_IDLE;
293 | end case;
294 |
295 | end process pcie_cfg_fsm_state_select_process;
296 |
297 | end architecture RTL;
--------------------------------------------------------------------------------
/src/design/tlp_streamer_pcie_tlp.vhd:
--------------------------------------------------------------------------------
1 | --
2 | -- TLP Streamer - PCIe TLP Interface
3 | --
4 | -- (c) MikeM64 - 2022
5 | --
6 |
7 | -- From this component's perspective, all references to TX are for Host -> PCIe direction
8 | -- and all RX references are PCIe -> Host
9 |
10 | library IEEE;
11 | use IEEE.std_logic_1164.all;
12 | use IEEE.numeric_std.all;
13 |
14 | use work.tlp_streamer_records.all;
15 |
16 | entity tlp_streamer_pcie_tlp is
17 | port (
18 | sys_clk_i : in std_logic;
19 | pcie_clk_i : in std_logic;
20 | pcie_rst_i : in std_logic;
21 | -- Host Packet RX/TX management
22 | dispatch_i : in dispatch_producer_r;
23 | dispatch_o : out dispatch_consumer_r;
24 | arbiter_i : in arbiter_producer_r;
25 | arbiter_o : out arbiter_consumer_r;
26 | -- PCIe Core TLP Interface
27 | pcie_tlp_tx_producer_i : in pcie_tlp_tx_port_producer_r;
28 | pcie_tlp_tx_consumer_o : out pcie_tlp_tx_port_consumer_r;
29 | pcie_tlp_rx_producer_i : in pcie_tlp_rx_port_producer_r;
30 | pcie_tlp_rx_consumer_o : out pcie_tlp_rx_port_consumer_r);
31 | end entity tlp_streamer_pcie_tlp;
32 |
33 | architecture RTL of tlp_streamer_pcie_tlp is
34 |
35 | component fifo_pcie_tlp_r64_w32_4096_bram IS
36 | port (
37 | rst : IN STD_LOGIC;
38 | wr_clk : IN STD_LOGIC;
39 | rd_clk : IN STD_LOGIC;
40 | din : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
41 | wr_en : IN STD_LOGIC;
42 | rd_en : IN STD_LOGIC;
43 | dout : OUT STD_LOGIC_VECTOR(63 DOWNTO 0);
44 | full : OUT STD_LOGIC;
45 | empty : OUT STD_LOGIC;
46 | valid : OUT STD_LOGIC;
47 | wr_rst_busy : OUT STD_LOGIC;
48 | rd_rst_busy : OUT STD_LOGIC
49 | );
50 | end component fifo_pcie_tlp_r64_w32_4096_bram;
51 |
52 | component fifo_pcie_tlp_r32_w64_4096_bram IS
53 | port (
54 | rst : IN STD_LOGIC;
55 | wr_clk : IN STD_LOGIC;
56 | rd_clk : IN STD_LOGIC;
57 | din : IN STD_LOGIC_VECTOR(63 DOWNTO 0);
58 | wr_en : IN STD_LOGIC;
59 | rd_en : IN STD_LOGIC;
60 | dout : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);
61 | full : OUT STD_LOGIC;
62 | empty : OUT STD_LOGIC;
63 | valid : OUT STD_LOGIC;
64 | wr_rst_busy : OUT STD_LOGIC;
65 | rd_rst_busy : OUT STD_LOGIC
66 | );
67 | end component fifo_pcie_tlp_r32_w64_4096_bram;
68 |
69 | component pcie_tlp_ila IS
70 | port (
71 | clk : IN STD_LOGIC;
72 | probe0 : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
73 | probe1 : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
74 | probe2 : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
75 | probe3 : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
76 | probe4 : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
77 | probe5 : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
78 | probe6 : IN STD_LOGIC_VECTOR(63 DOWNTO 0);
79 | probe7 : IN STD_LOGIC_VECTOR(63 DOWNTO 0);
80 | probe8 : IN STD_LOGIC_VECTOR(63 DOWNTO 0)
81 | );
82 | end component pcie_tlp_ila;
83 |
84 | -- TX FSM Signals and types
85 | type pcie_tlp_tx_req_state is (PCIE_TLP_TX_IDLE, PCIE_TLP_TX_PACKET_START, PCIE_TLP_TX_PACKET_PARSE_HEADER,
86 | PCIE_TLP_TX_PACKET);
87 |
88 | signal current_pcie_tlp_tx_req_state, next_pcie_tlp_tx_req_state: pcie_tlp_tx_req_state;
89 |
90 | signal pcie_tlp_fifo_tx_wr_en_s, next_pcie_tlp_fifo_tx_wr_en_s: std_logic;
91 | signal pcie_tlp_fifo_tx_rd_en_s: std_logic;
92 | signal pcie_tlp_fifo_tx_rd_data_s, ila_pcie_tlp_data: std_logic_vector(63 downto 0);
93 | signal pcie_tlp_fifo_tx_rd_empty_s: std_logic;
94 | signal pcie_tlp_fifo_tx_rd_valid_s: std_logic;
95 |
96 | -- This is the number of qwords to read from the TX FIFO when transmitting
97 | -- packets towards the PCIe core
98 | -- 514 is (1024 DW Max TLP Payload + 4 DW Max TLP Header == 1028 DW == 514 QW)
99 | signal pcie_tlp_tx_qwords_to_read, next_pcie_tlp_tx_qwords_to_read: integer range 0 to 514;
100 |
101 |
102 | -- RX FSM Signals and types
103 | type pcie_tlp_rx_req_state is (PCIE_TLP_AWAIT_RX, PCIE_TLP_RX_WRITE_HEADER, PCIE_TLP_RX_WRITE_TLP);
104 |
105 | signal current_pcie_tlp_rx_req_state, next_pcie_tlp_rx_req_state: pcie_tlp_rx_req_state;
106 | signal ila_current_tlp_state: std_logic_vector(2 downto 0);
107 | signal ila_current_tlp_tx_state: std_logic_vector(2 downto 0);
108 | signal ila_tx_tlast: std_logic;
109 |
110 | signal pcie_tlp_fifo_rx_wr_data_s, next_pcie_tlp_fifo_rx_wr_data_s: std_logic_vector(63 downto 0);
111 | -- Buffer to allow time for the header to be added to the RX FIFO ahead of the RXd TLP
112 | signal pcie_tlp_rx_buffer_s_1, pcie_tlp_rx_buffer_s_2: std_logic_vector(63 downto 0);
113 | signal pcie_tlp_rx_buffer_valid_s_1, pcie_tlp_rx_buffer_valid_s_2: std_logic;
114 | signal pcie_tlp_fifo_rx_wr_en_s, next_pcie_tlp_fifo_rx_wr_en_s: std_logic;
115 | signal pcie_tlp_fifo_rx_rd_data_s: std_logic_vector(31 downto 0);
116 | signal pcie_tlp_fifo_rx_rd_en_s, next_pcie_tlp_fifo_rx_rd_en_s: std_logic;
117 | signal pcie_tlp_fifo_rx_wr_full_s: std_logic;
118 |
119 | signal ila_tx_next_qwords_to_read: std_logic_vector(63 downto 0);
120 |
121 | begin
122 |
123 | comp_pcie_tlp_tx_fifo: fifo_pcie_tlp_r64_w32_4096_bram
124 | port map(
125 | rst => pcie_rst_i,
126 | wr_clk => sys_clk_i,
127 | rd_clk => pcie_clk_i,
128 | din => dispatch_i.dispatch_wr_data(31 downto 0),
129 | wr_en => pcie_tlp_fifo_tx_wr_en_s,
130 | rd_en => pcie_tlp_fifo_tx_rd_en_s,
131 | dout(63 downto 32) => pcie_tlp_fifo_tx_rd_data_s(31 downto 0),
132 | dout(31 downto 0) => pcie_tlp_fifo_tx_rd_data_s(63 downto 32),
133 | full => dispatch_o.dispatch_wr_full,
134 | empty => pcie_tlp_fifo_tx_rd_empty_s,
135 | valid => pcie_tlp_fifo_tx_rd_valid_s,
136 | wr_rst_busy => open,
137 | rd_rst_busy => open);
138 |
139 | comp_pcie_tlp_rx_fifo: fifo_pcie_tlp_r32_w64_4096_bram
140 | port map(
141 | rst => pcie_rst_i,
142 | wr_clk => pcie_clk_i,
143 | rd_clk => sys_clk_i,
144 | din => pcie_tlp_fifo_rx_wr_data_s,
145 | wr_en => pcie_tlp_fifo_rx_wr_en_s,
146 | rd_en => arbiter_i.arbiter_rd_en,
147 | dout(31 downto 24) => pcie_tlp_fifo_rx_rd_data_s(7 downto 0),
148 | dout(23 downto 16) => pcie_tlp_fifo_rx_rd_data_s(15 downto 8),
149 | dout(15 downto 8) => pcie_tlp_fifo_rx_rd_data_s(23 downto 16),
150 | dout(7 downto 0) => pcie_tlp_fifo_rx_rd_data_s(31 downto 24),
151 | full => pcie_tlp_fifo_rx_wr_full_s,
152 | empty => arbiter_o.arbiter_rd_empty,
153 | valid => arbiter_o.arbiter_rd_valid,
154 | wr_rst_busy => open,
155 | rd_rst_busy => open);
156 |
157 | --comp_pcie_tlp_rx_ila: pcie_tlp_ila
158 | -- port map(
159 | -- clk => pcie_clk_i,
160 | -- probe0(0) => pcie_tlp_rx_producer_i.tlp_axis_rx_tvalid,
161 | -- probe1(0) => pcie_tlp_rx_producer_i.tlp_axis_rx_tlast,
162 | -- probe2(0) => pcie_tlp_rx_buffer_valid_s_1,
163 | -- probe3(0) => pcie_tlp_rx_buffer_valid_s_2,
164 | -- probe4(0) => pcie_tlp_fifo_rx_wr_en_s,
165 | -- probe5 => ila_current_tlp_state,
166 | -- probe6 => pcie_tlp_rx_buffer_s_1,
167 | -- probe7 => pcie_tlp_rx_buffer_s_2,
168 | -- probe8 => pcie_tlp_fifo_rx_wr_data_s);
169 |
170 | comp_pcie_tlp_tx_ila: pcie_tlp_ila
171 | port map(
172 | clk => pcie_clk_i,
173 | probe0(0) => '0',
174 | probe1(0) => '0',
175 | probe2(0) => pcie_tlp_fifo_tx_rd_valid_s,
176 | probe3(0) => ila_tx_tlast,
177 | probe4(0) => pcie_tlp_fifo_tx_rd_en_s,
178 | probe5 => ila_current_tlp_tx_state,
179 | probe6 => ila_pcie_tlp_data,
180 | probe7 => ila_tx_next_qwords_to_read,
181 | probe8 => pcie_tlp_fifo_tx_rd_data_s);
182 |
183 | pcie_tlp_rx_tx_async_process: process(dispatch_i, pcie_tlp_fifo_rx_rd_data_s)
184 | begin
185 |
186 | pcie_tlp_fifo_tx_wr_en_s <= dispatch_i.dispatch_wr_en and
187 | dispatch_i.dispatch_valid;
188 | -- The extra 1's here correspond to the byte_enable portion of the
189 | -- data sent to the FT601
190 | arbiter_o.arbiter_rd_data <= "1111" & pcie_tlp_fifo_rx_rd_data_s;
191 |
192 | end process pcie_tlp_rx_tx_async_process;
193 |
194 | pcie_tlp_tx_fsm_clock_process: process(pcie_clk_i, pcie_rst_i, next_pcie_tlp_tx_req_state,
195 | next_pcie_tlp_tx_qwords_to_read)
196 | begin
197 |
198 | if (pcie_rst_i = '1') then
199 | current_pcie_tlp_tx_req_state <= PCIE_TLP_TX_IDLE;
200 | pcie_tlp_tx_qwords_to_read <= 0;
201 | ila_tx_next_qwords_to_read <= (others => '0');
202 | elsif (rising_edge(pcie_clk_i)) then
203 | current_pcie_tlp_tx_req_state <= next_pcie_tlp_tx_req_state;
204 | pcie_tlp_tx_qwords_to_read <= next_pcie_tlp_tx_qwords_to_read;
205 | ila_tx_next_qwords_to_read <= std_logic_vector(to_unsigned(next_pcie_tlp_tx_qwords_to_read, 64));
206 | ila_current_tlp_tx_state <= std_logic_vector(to_unsigned(pcie_tlp_tx_req_state'POS(next_pcie_tlp_tx_req_state), 3));
207 | end if;
208 |
209 | end process pcie_tlp_tx_fsm_clock_process;
210 |
211 | pcie_tlp_tx_fsm_data_output_process: process(current_pcie_tlp_tx_req_state,
212 | pcie_tlp_tx_qwords_to_read, pcie_tlp_fifo_tx_rd_data_s,
213 | pcie_tlp_fifo_tx_rd_valid_s)
214 | variable pcie_tlp_tx_packet_len_v: integer range 0 to 65535;
215 |
216 | begin
217 |
218 | pcie_tlp_fifo_tx_rd_en_s <= '0';
219 | next_pcie_tlp_tx_qwords_to_read <= pcie_tlp_tx_qwords_to_read;
220 | pcie_tlp_tx_consumer_o.tlp_axis_tx_tdata <= (others => '0');
221 | pcie_tlp_tx_consumer_o.tlp_axis_tx_tuser <= (others => '0');
222 | pcie_tlp_tx_consumer_o.tlp_axis_tx_tkeep <= (others => '0');
223 | pcie_tlp_tx_consumer_o.tlp_axis_tx_tlast <= '0';
224 | pcie_tlp_tx_consumer_o.tlp_axis_tx_tvalid <= '0';
225 | ila_pcie_tlp_data <= (others => '0');
226 | ila_tx_tlast <= '0';
227 |
228 | case current_pcie_tlp_tx_req_state is
229 | when PCIE_TLP_TX_IDLE =>
230 | next_pcie_tlp_tx_qwords_to_read <= 0;
231 | when PCIE_TLP_TX_PACKET_START =>
232 | pcie_tlp_fifo_tx_rd_en_s <= '1';
233 | next_pcie_tlp_tx_qwords_to_read <= 0;
234 | when PCIE_TLP_TX_PACKET_PARSE_HEADER =>
235 | -- The first double-word out of the FIFO is the tlp_streamer header.
236 | -- Use the length to know when to stop transmitting towards the
237 | -- PCIe core
238 | -- -2: -1 to not count the TLP streamer header,
239 | -- -1 as this read of the header also counts towards the data left
240 | next_pcie_tlp_tx_qwords_to_read <= (to_integer(unsigned(pcie_tlp_fifo_tx_rd_data_s(23 downto 16) &
241 | pcie_tlp_fifo_tx_rd_data_s(31 downto 24))) / 2) - 2;
242 | pcie_tlp_tx_packet_len_v := to_integer(unsigned(pcie_tlp_fifo_tx_rd_data_s(23 downto 16) &
243 | pcie_tlp_fifo_tx_rd_data_s(31 downto 24)));
244 | pcie_tlp_fifo_tx_rd_en_s <= '1';
245 | when PCIE_TLP_TX_PACKET =>
246 | pcie_tlp_fifo_tx_rd_en_s <= '1';
247 | -- Information from the host is transmitted in network-order, so swap
248 | -- it here to align with the PCIe IP.
249 | ila_pcie_tlp_data <= pcie_tlp_fifo_tx_rd_data_s(39 downto 32) &
250 | pcie_tlp_fifo_tx_rd_data_s(47 downto 40) &
251 | pcie_tlp_fifo_tx_rd_data_s(55 downto 48) &
252 | pcie_tlp_fifo_tx_rd_data_s(63 downto 56) &
253 | pcie_tlp_fifo_tx_rd_data_s(7 downto 0) &
254 | pcie_tlp_fifo_tx_rd_data_s(15 downto 8) &
255 | pcie_tlp_fifo_tx_rd_data_s(23 downto 16) &
256 | pcie_tlp_fifo_tx_rd_data_s(31 downto 24);
257 |
258 | pcie_tlp_tx_consumer_o.tlp_axis_tx_tdata <= pcie_tlp_fifo_tx_rd_data_s(39 downto 32) &
259 | pcie_tlp_fifo_tx_rd_data_s(47 downto 40) &
260 | pcie_tlp_fifo_tx_rd_data_s(55 downto 48) &
261 | pcie_tlp_fifo_tx_rd_data_s(63 downto 56) &
262 | pcie_tlp_fifo_tx_rd_data_s(7 downto 0) &
263 | pcie_tlp_fifo_tx_rd_data_s(15 downto 8) &
264 | pcie_tlp_fifo_tx_rd_data_s(23 downto 16) &
265 | pcie_tlp_fifo_tx_rd_data_s(31 downto 24);
266 | -- TODO: Fix this for return data that is not an odd DW count
267 | pcie_tlp_tx_consumer_o.tlp_axis_tx_tkeep <= (others => '1');
268 | if (pcie_tlp_tx_qwords_to_read = 0) then
269 | pcie_tlp_tx_consumer_o.tlp_axis_tx_tlast <= '1';
270 | ila_tx_tlast <= '1';
271 | end if;
272 | pcie_tlp_tx_consumer_o.tlp_axis_tx_tvalid <= pcie_tlp_fifo_tx_rd_valid_s;
273 | next_pcie_tlp_tx_qwords_to_read <= pcie_tlp_tx_qwords_to_read - 1;
274 | end case;
275 |
276 | end process pcie_tlp_tx_fsm_data_output_process;
277 |
278 | pcie_tlp_tx_fsm_state_select_process: process(current_pcie_tlp_tx_req_state, pcie_tlp_fifo_tx_rd_empty_s,
279 | pcie_tlp_tx_producer_i, pcie_tlp_tx_qwords_to_read)
280 | begin
281 |
282 | next_pcie_tlp_tx_req_state <= current_pcie_tlp_tx_req_state;
283 |
284 | case current_pcie_tlp_tx_req_state is
285 | when PCIE_TLP_TX_IDLE =>
286 | if (pcie_tlp_fifo_tx_rd_empty_s = '0' and
287 | pcie_tlp_tx_producer_i.tlp_axis_tx_tready = '1') then
288 | next_pcie_tlp_tx_req_state <= PCIE_TLP_TX_PACKET_START;
289 | end if;
290 | when PCIE_TLP_TX_PACKET_START =>
291 | next_pcie_tlp_tx_req_state <= PCIE_TLP_TX_PACKET_PARSE_HEADER;
292 | when PCIE_TLP_TX_PACKET_PARSE_HEADER =>
293 | next_pcie_tlp_tx_req_state <= PCIE_TLP_TX_PACKET;
294 | when PCIE_TLP_TX_PACKET =>
295 | if (pcie_tlp_tx_qwords_to_read = 0) then
296 | next_pcie_tlp_tx_req_state <= PCIE_TLP_TX_IDLE;
297 | end if;
298 | end case;
299 |
300 | end process pcie_tlp_tx_fsm_state_select_process;
301 |
302 | pcie_tlp_rx_clock_process: process(pcie_clk_i, pcie_rst_i, next_pcie_tlp_rx_req_state,
303 | next_pcie_tlp_fifo_rx_wr_data_s, next_pcie_tlp_fifo_rx_wr_en_s,
304 | pcie_tlp_rx_producer_i)
305 | begin
306 |
307 | if (pcie_rst_i = '1') then
308 | current_pcie_tlp_rx_req_state <= PCIE_TLP_AWAIT_RX;
309 | pcie_tlp_fifo_rx_wr_data_s <= (others => '0');
310 | pcie_tlp_fifo_rx_wr_en_s <= '0';
311 | elsif (rising_edge(pcie_clk_i)) then
312 | current_pcie_tlp_rx_req_state <= next_pcie_tlp_rx_req_state;
313 | ila_current_tlp_state <= std_logic_vector(to_unsigned(pcie_tlp_rx_req_state'POS(next_pcie_tlp_rx_req_state), 3));
314 | pcie_tlp_fifo_rx_wr_data_s <= next_pcie_tlp_fifo_rx_wr_data_s;
315 | pcie_tlp_fifo_rx_wr_en_s <= next_pcie_tlp_fifo_rx_wr_en_s;
316 |
317 | pcie_tlp_rx_buffer_s_1 <= pcie_tlp_rx_producer_i.tlp_axis_rx_tdata;
318 | pcie_tlp_rx_buffer_s_2 <= pcie_tlp_rx_buffer_s_1;
319 |
320 | pcie_tlp_rx_buffer_valid_s_1 <= pcie_tlp_rx_producer_i.tlp_axis_rx_tvalid;
321 | pcie_tlp_rx_buffer_valid_s_2 <= pcie_tlp_rx_buffer_valid_s_1;
322 | end if;
323 |
324 | end process pcie_tlp_rx_clock_process;
325 |
326 | pcie_tlp_rx_fsm_data_output_process: process(current_pcie_tlp_rx_req_state, pcie_tlp_fifo_rx_wr_full_s,
327 | pcie_tlp_rx_buffer_s_1, pcie_tlp_rx_buffer_s_2, pcie_tlp_rx_producer_i,
328 | pcie_tlp_rx_buffer_valid_s_2)
329 |
330 | variable pcie_tlp_rx_packet_len_v: integer range 0 to 65535;
331 | variable pcie_tlp_hdr_len_v: integer range 3 to 4;
332 |
333 | begin
334 |
335 | pcie_tlp_rx_consumer_o.tlp_axis_rx_tready <= not pcie_tlp_fifo_rx_wr_full_s;
336 | next_pcie_tlp_fifo_rx_wr_en_s <= '0';
337 | -- Need to word-swap the AXI interface so that the correct word is sent
338 | -- out on the wire first. Refer to page 47 of pg054.
339 | next_pcie_tlp_fifo_rx_wr_data_s <= pcie_tlp_rx_buffer_s_2(31 downto 0) &
340 | pcie_tlp_rx_buffer_s_2(63 downto 32);
341 |
342 | case current_pcie_tlp_rx_req_state is
343 | when PCIE_TLP_AWAIT_RX =>
344 | when PCIE_TLP_RX_WRITE_HEADER =>
345 | next_pcie_tlp_fifo_rx_wr_en_s <= '1';
346 | -- Setup the tlp_streamer header length based on the TLP
347 | -- format and length contained in the first QW read.
348 | if (pcie_tlp_rx_buffer_s_1(29) = '1') then
349 | pcie_tlp_hdr_len_v := 4;
350 | else
351 | pcie_tlp_hdr_len_v := 3;
352 | end if;
353 | if (pcie_tlp_rx_buffer_s_1(30) = '1') then
354 | -- This TLP has data attached to it
355 | if (pcie_tlp_rx_buffer_s_1(9 downto 0) = "0000000000") then
356 | pcie_tlp_rx_packet_len_v := 2 + 4 + 1024;
357 | else
358 | pcie_tlp_rx_packet_len_v := 2 + pcie_tlp_hdr_len_v + to_integer(unsigned(pcie_tlp_rx_buffer_s_1(9 downto 0)));
359 | if (pcie_tlp_rx_packet_len_v mod 2 = 1) then
360 | -- If it's an odd packet length overall, add one more DW to align
361 | -- the TXd packet with a QW natural boundary.
362 | pcie_tlp_rx_packet_len_v := pcie_tlp_rx_packet_len_v + 1;
363 | end if;
364 | end if;
365 | else
366 | -- TLPs are always assumed to have a 4-byte header in the FPGA
367 | -- to easily align with natural QW/FIFO write boundaries.
368 | -- The host will ignore the additional bytes when it processes the TLP.
369 | pcie_tlp_rx_packet_len_v := 2 + 4;
370 | end if;
371 | -- The length is stored in network-order when going over the wire
372 | next_pcie_tlp_fifo_rx_wr_data_s <= "0000000000000010" & -- tsh_msg_type == 2
373 | std_logic_vector(to_unsigned(pcie_tlp_rx_packet_len_v, 16)) &
374 | "0000000000000000" & -- tsh_rsvd_2 == 0
375 | "0000000000000000"; -- tsh_seq_id
376 | when PCIE_TLP_RX_WRITE_TLP =>
377 | next_pcie_tlp_fifo_rx_wr_en_s <= pcie_tlp_rx_buffer_valid_s_2;
378 | end case;
379 |
380 | end process pcie_tlp_rx_fsm_data_output_process;
381 |
382 | pcie_tlp_rx_fsm_state_select_process: process(current_pcie_tlp_rx_req_state, pcie_tlp_rx_producer_i,
383 | pcie_tlp_rx_buffer_valid_s_2)
384 | begin
385 |
386 | next_pcie_tlp_rx_req_state <= current_pcie_tlp_rx_req_state;
387 |
388 | case current_pcie_tlp_rx_req_state is
389 | when PCIE_TLP_AWAIT_RX =>
390 | if (pcie_tlp_rx_producer_i.tlp_axis_rx_tvalid = '1') then
391 | next_pcie_tlp_rx_req_state <= PCIE_TLP_RX_WRITE_HEADER;
392 | end if;
393 | when PCIE_TLP_RX_WRITE_HEADER =>
394 | next_pcie_tlp_rx_req_state <= PCIE_TLP_RX_WRITE_TLP;
395 | when PCIE_TLP_RX_WRITE_TLP =>
396 | if (pcie_tlp_rx_producer_i.tlp_axis_rx_tlast = '1' or
397 | (pcie_tlp_rx_producer_i.tlp_axis_rx_tvalid = '0' and pcie_tlp_rx_buffer_valid_s_2 = '0')) then
398 | next_pcie_tlp_rx_req_state <= PCIE_TLP_AWAIT_RX;
399 | end if;
400 | end case;
401 |
402 | end process pcie_tlp_rx_fsm_state_select_process;
403 |
404 |
405 | end architecture RTL;
406 |
--------------------------------------------------------------------------------
/src/design/tlp_streamer_records.vhd:
--------------------------------------------------------------------------------
1 | --
2 | -- TLP Streamer Records - Record Package
3 | --
4 | -- (c) MikeM64 - 2021
5 | --
6 |
7 | library IEEE;
8 | use IEEE.std_logic_1164.all;
9 |
10 | package tlp_streamer_records is
11 |
12 | --
13 | -- Signals produced by the dispatch queue
14 | --
15 | type dispatch_producer_r is record
16 | dispatch_wr_en : std_logic;
17 | dispatch_valid : std_logic;
18 | dispatch_empty : std_logic;
19 | dispatch_wr_data : std_logic_vector(35 downto 0);
20 | end record dispatch_producer_r;
21 |
22 | --
23 | -- Signals consumed by the dispatch queue
24 | --
25 | type dispatch_consumer_r is record
26 | dispatch_wr_full : std_logic;
27 | end record dispatch_consumer_r;
28 |
29 | -- Array versions of the above records
30 | type dispatch_producer_r_array is array (integer range <>) of dispatch_producer_r;
31 | type dispatch_consumer_r_array is array (integer range <>) of dispatch_consumer_r;
32 |
33 | --
34 | -- Signals produced by the TX arbitrator
35 | --
36 | type arbiter_producer_r is record
37 | arbiter_rd_en : std_logic;
38 | arbiter_wr_full : std_logic;
39 | end record arbiter_producer_r;
40 |
41 | --
42 | -- Signals consumed by the TX arbitrator
43 | --
44 | type arbiter_consumer_r is record
45 | arbiter_rd_data : std_logic_vector(35 downto 0);
46 | arbiter_rd_empty : std_logic;
47 | arbiter_rd_valid : std_logic;
48 | end record arbiter_consumer_r;
49 |
50 | type arbiter_producer_r_array is array (integer range <>) of arbiter_producer_r;
51 | type arbiter_consumer_r_array is array (integer range <>) of arbiter_consumer_r;
52 |
53 | type pcie_cfg_mgmt_port_producer_r is record
54 | cfg_mgmt_do : STD_LOGIC_VECTOR(31 DOWNTO 0);
55 | cfg_mgmt_rd_wr_done : STD_LOGIC;
56 | end record pcie_cfg_mgmt_port_producer_r;
57 |
58 | type pcie_cfg_mgmt_port_consumer_r is record
59 | cfg_mgmt_di : STD_LOGIC_VECTOR(31 DOWNTO 0);
60 | cfg_mgmt_byte_en : STD_LOGIC_VECTOR(3 DOWNTO 0);
61 | cfg_mgmt_dwaddr : STD_LOGIC_VECTOR(9 DOWNTO 0);
62 | cfg_mgmt_wr_en : STD_LOGIC;
63 | cfg_mgmt_rd_en : STD_LOGIC;
64 | cfg_mgmt_wr_readonly : STD_LOGIC;
65 | cfg_mgmt_wr_rw1c_as_rw : STD_LOGIC;
66 | end record pcie_cfg_mgmt_port_consumer_r;
67 |
68 | type pcie_tlp_tx_port_producer_r is record
69 | tlp_axis_tx_tready : std_logic;
70 | end record pcie_tlp_tx_port_producer_r;
71 |
72 | type pcie_tlp_tx_port_consumer_r is record
73 | tlp_axis_tx_tdata : std_logic_vector(63 downto 0);
74 | tlp_axis_tx_tkeep : std_logic_vector(7 downto 0);
75 | tlp_axis_tx_tlast : std_logic;
76 | tlp_axis_tx_tvalid : std_logic;
77 | tlp_axis_tx_tuser : std_logic_vector(3 downto 0);
78 | end record pcie_tlp_tx_port_consumer_r;
79 |
80 | type pcie_tlp_rx_port_producer_r is record
81 | tlp_axis_rx_tdata : std_logic_vector(63 downto 0);
82 | tlp_axis_rx_tkeep : std_logic_vector(7 downto 0);
83 | tlp_axis_rx_tlast : std_logic;
84 | tlp_axis_rx_tvalid : std_logic;
85 | tlp_axis_rx_tuser : std_logic_vector(21 downto 0);
86 | end record pcie_tlp_rx_port_producer_r;
87 |
88 | type pcie_tlp_rx_port_consumer_r is record
89 | tlp_axis_rx_tready : std_logic;
90 | end record pcie_tlp_rx_port_consumer_r;
91 |
92 | end package tlp_streamer_records;
93 |
--------------------------------------------------------------------------------
/src/design/tlp_streamer_reset.vhd:
--------------------------------------------------------------------------------
1 | --
2 | -- TLP Streamer - Reset generator
3 | --
4 | -- (c) MikeM64 - 2021
5 | --
6 |
7 | library IEEE;
8 | use IEEE.std_logic_1164.all;
9 | use IEEE.numeric_std.all;
10 |
11 | entity tlp_streamer_reset is
12 | port(
13 | sys_clk_i : in std_logic;
14 | sys_reset_o : out std_logic);
15 | end entity tlp_streamer_reset;
16 |
17 | architecture RTL of tlp_streamer_reset is
18 |
19 | signal reset_hold_count64_s: unsigned(63 downto 0) := (others => '0');
20 | signal reset_s: std_logic;
21 |
22 | begin
23 |
24 | reset_process: process(sys_clk_i, reset_hold_count64_s, reset_s)
25 | begin
26 | sys_reset_o <= reset_s;
27 |
28 | -- Self-generate a 1500ns reset pulse
29 | if (reset_hold_count64_s < to_unsigned(150, 64)) then
30 | reset_s <= '1';
31 | else
32 | reset_s <= '0';
33 | end if;
34 |
35 | if (rising_edge(sys_clk_i)) then
36 | reset_hold_count64_s <= reset_hold_count64_s + 1;
37 | end if;
38 |
39 | end process reset_process;
40 |
41 | end architecture RTL;
42 |
--------------------------------------------------------------------------------
/src/design/tlp_streamer_rx_dispatch.vhd:
--------------------------------------------------------------------------------
1 | --
2 | -- TLP Streamer - Host Packet RX Dispatch Module
3 | --
4 | -- (c) MikeM64 - 2021
5 | --
6 |
7 | library IEEE;
8 | use IEEE.std_logic_1164.all;
9 | use IEEE.numeric_std.all;
10 |
11 | use work.tlp_streamer_records.all;
12 |
13 | entity tlp_streamer_rx_dispatch is
14 | generic (NUM_OUTPUT_QUEUES : integer);
15 | port(
16 | sys_clk_i : in std_logic;
17 | sys_reset_i : in std_logic;
18 | -- Input FIFO to dispatch
19 | fifo_rd_en_o : out std_logic;
20 | fifo_rd_empty_i : in std_logic;
21 | fifo_rd_valid_i : in std_logic;
22 | fifo_rd_data_i : in std_logic_vector(35 downto 0);
23 | -- Output FIFOs to dispatch to
24 | dispatch_o_arr : out dispatch_producer_r_array(NUM_OUTPUT_QUEUES-1 downto 0);
25 | dispatch_i_arr : in dispatch_consumer_r_array(NUM_OUTPUT_QUEUES-1 downto 0));
26 |
27 | end entity tlp_streamer_rx_dispatch;
28 |
29 | architecture RTL of tlp_streamer_rx_dispatch is
30 |
31 | --component ila_0 IS
32 | --PORT (
33 | --clk : IN STD_LOGIC;
34 | --probe0 : IN STD_LOGIC_VECTOR(12 DOWNTO 0);
35 | -- probe1 : IN STD_LOGIC_VECTOR(12 DOWNTO 0);
36 | -- probe2 : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
37 | -- probe3 : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
38 | -- probe4 : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
39 | -- probe5 : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
40 | -- probe6 : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
41 | -- probe7 : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
42 | -- probe8 : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
43 | -- probe9 : IN STD_LOGIC_VECTOR(15 DOWNTO 0);
44 | -- probe10 : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
45 | -- probe11 : IN STD_LOGIC_VECTOR(9 DOWNTO 0);
46 | -- probe12 : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
47 | -- probe13 : IN STD_LOGIC_VECTOR(0 DOWNTO 0)
48 | --);
49 | --END component ila_0;
50 |
51 | type dispatch_state is (DISPATCH_IDLE, DISPATCH_AWAIT_HEADER, DISPATCH_READ_HEADER,
52 | DISPATCH_WRITE_HEADER, DISPATCH_WRITE_PACKET, DISPATCH_COMPLETE);
53 |
54 | signal current_dispatch_state_s, next_dispatch_state_s: dispatch_state;
55 | signal dispatch_words_to_write, next_dispatch_words_to_write: integer range 0 to 65535;
56 | signal dispatch_output_queue, next_dispatch_output_queue: integer range 0 to 255;
57 |
58 | -- A two-cycle delay for output data is required in order to first parse the
59 | -- packet header (which denotes the appropriate output queue) and then
60 | -- to continue writing the data to the output queue after it has been clocked
61 | signal dispatch_rd_en_s, dispatch_rd_empty_s, dispatch_rd_valid_s_1, dispatch_rd_valid_s_2, dispatch_wr_en_s: std_logic;
62 | signal dispatch_data_s_1, dispatch_data_s_2: std_logic_vector(35 downto 0);
63 |
64 | --signal ila_dispatch_state: std_logic_vector(5 downto 0);
65 | --signal ila_words_to_write: std_logic_vector(15 downto 0);
66 | --signal ila_dispatch_output_queue: std_logic_vector(7 downto 0);
67 |
68 | begin
69 |
70 | --comp_rx_dispatch_ila: ila_0
71 | --port map (
72 | -- clk => sys_clk_i,
73 | -- probe0(12 downto 6) => (others => '0'),
74 | -- probe0(5 downto 0) => ila_dispatch_state,
75 | -- probe1 => (others => '0'),
76 | -- probe2(31 downto 16) => (others => '0'),
77 | -- probe2(15 downto 0) => ila_words_to_write,
78 | -- probe3 => fifo_rd_data_i(31 downto 0),
79 | -- probe4(0) => dispatch_wr_en_s,
80 | -- probe5(0) => dispatch_rd_valid_s_2,
81 | -- probe6(0) => fifo_rd_valid_i,
82 | -- probe7(0) => '0',
83 | -- probe8(0) => '0',
84 | -- probe9 => (others => '0'),
85 | -- probe10 => (others => '0'),
86 | -- probe11(9 downto 8) => (others => '0'),
87 | -- probe11(7 downto 0) => ila_dispatch_output_queue,
88 | -- probe12 => dispatch_data_s_2(31 downto 0),
89 | -- probe13(0) => '0');
90 |
91 | dispatch_fsm_state_process: process(sys_clk_i, next_dispatch_state_s, sys_reset_i, dispatch_data_s_1,
92 | dispatch_rd_valid_s_1, dispatch_rd_empty_s, dispatch_wr_en_s,
93 | dispatch_data_s_2)
94 | begin
95 | if (sys_reset_i = '1') then
96 | current_dispatch_state_s <= DISPATCH_IDLE;
97 | for i in 0 to NUM_OUTPUT_QUEUES-1 loop
98 | dispatch_o_arr(i).dispatch_wr_data <= (others => '0');
99 | dispatch_o_arr(i).dispatch_valid <= '0';
100 | dispatch_o_arr(i).dispatch_empty <= '1';
101 | dispatch_o_arr(i).dispatch_wr_en <= '0';
102 | end loop;
103 | elsif (rising_edge(sys_clk_i)) then
104 | current_dispatch_state_s <= next_dispatch_state_s;
105 |
106 | -- ila_dispatch_state <= std_logic_vector(to_unsigned(dispatch_state'POS(next_dispatch_state_s), 6));
107 | -- ila_dispatch_output_queue <= std_logic_vector(to_unsigned(next_dispatch_output_queue, 8));
108 | -- ila_words_to_write <= std_logic_vector(to_unsigned(next_dispatch_words_to_write, 16));
109 |
110 | dispatch_output_queue <= next_dispatch_output_queue;
111 | dispatch_words_to_write <= next_dispatch_words_to_write;
112 |
113 | dispatch_rd_empty_s <= fifo_rd_empty_i;
114 | dispatch_rd_valid_s_1 <= fifo_rd_valid_i;
115 | dispatch_data_s_1 <= fifo_rd_data_i;
116 |
117 | dispatch_data_s_2 <= dispatch_data_s_1;
118 | dispatch_rd_valid_s_2 <= dispatch_rd_valid_s_1;
119 |
120 | fifo_rd_en_o <= dispatch_rd_en_s;
121 |
122 | for i in 0 to NUM_OUTPUT_QUEUES-1 loop
123 | if (i = next_dispatch_output_queue) then
124 | dispatch_o_arr(i).dispatch_wr_data <= dispatch_data_s_2;
125 | dispatch_o_arr(i).dispatch_valid <= dispatch_rd_valid_s_2;
126 | dispatch_o_arr(i).dispatch_empty <= dispatch_rd_empty_s;
127 | dispatch_o_arr(i).dispatch_wr_en <= dispatch_wr_en_s;
128 | else
129 | -- Only the selected output will receive valid data.
130 | -- All other outputs will receive placeholder data.
131 | dispatch_o_arr(i).dispatch_wr_data <= (others => '0');
132 | dispatch_o_arr(i).dispatch_valid <= '0';
133 | dispatch_o_arr(i).dispatch_empty <= '1';
134 | dispatch_o_arr(i).dispatch_wr_en <= '0';
135 | end if;
136 | end loop;
137 | end if;
138 |
139 | end process dispatch_fsm_state_process;
140 |
141 | dispatch_fsm_data_output_process: process(current_dispatch_state_s, dispatch_output_queue, dispatch_rd_valid_s_2,
142 | dispatch_data_s_2, dispatch_words_to_write)
143 | begin
144 | dispatch_rd_en_s <= '0';
145 | dispatch_wr_en_s <= '0';
146 | next_dispatch_output_queue <= dispatch_output_queue;
147 | next_dispatch_words_to_write <= dispatch_words_to_write;
148 |
149 | case current_dispatch_state_s is
150 | when DISPATCH_IDLE =>
151 | next_dispatch_output_queue <= 0;
152 | next_dispatch_words_to_write <= 0;
153 | when DISPATCH_AWAIT_HEADER =>
154 | dispatch_rd_en_s <= '1';
155 | next_dispatch_words_to_write <= 0;
156 | when DISPATCH_READ_HEADER =>
157 | dispatch_rd_en_s <= '1';
158 | -- Write signal started one cycle before the header write to align
159 | -- when the data is available on the output queue
160 | dispatch_wr_en_s <= '1';
161 | -- tsh_msg_type
162 | next_dispatch_output_queue <= to_integer(unsigned(dispatch_data_s_2(7 downto 0)));
163 | -- tsh_msg_len - Stored in network order
164 | next_dispatch_words_to_write <= to_integer(unsigned(dispatch_data_s_2(23 downto 16) & dispatch_data_s_2(31 downto 24)));
165 | when DISPATCH_WRITE_HEADER =>
166 | -- Now that the header is available, it can be written-through to the
167 | -- output component
168 | dispatch_rd_en_s <= '1';
169 | dispatch_wr_en_s <= '1';
170 | next_dispatch_words_to_write <= dispatch_words_to_write - 1;
171 | when DISPATCH_WRITE_PACKET =>
172 | dispatch_rd_en_s <= '1';
173 | dispatch_wr_en_s <= dispatch_rd_valid_s_2;
174 | next_dispatch_words_to_write <= dispatch_words_to_write - 1;
175 | when DISPATCH_COMPLETE =>
176 | next_dispatch_words_to_write <= 0;
177 | end case;
178 |
179 | end process dispatch_fsm_data_output_process;
180 |
181 | dispatch_fsm_state_select_process: process(current_dispatch_state_s, dispatch_rd_empty_s, dispatch_words_to_write,
182 | dispatch_rd_valid_s_1)
183 | begin
184 |
185 | -- Current state does not change by default
186 | next_dispatch_state_s <= current_dispatch_state_s;
187 |
188 | case current_dispatch_state_s is
189 | when DISPATCH_IDLE =>
190 | if (dispatch_rd_empty_s = '0') then
191 | next_dispatch_state_s <= DISPATCH_AWAIT_HEADER;
192 | end if;
193 | when DISPATCH_AWAIT_HEADER =>
194 | -- Wait for valid data to appear before continuing
195 | if (dispatch_rd_valid_s_1 = '1') then
196 | next_dispatch_state_s <= DISPATCH_READ_HEADER;
197 | end if;
198 | when DISPATCH_READ_HEADER =>
199 | next_dispatch_state_s <= DISPATCH_WRITE_HEADER;
200 | when DISPATCH_WRITE_HEADER =>
201 | next_dispatch_state_s <= DISPATCH_WRITE_PACKET;
202 | when DISPATCH_WRITE_PACKET =>
203 | -- Its possible that a received packet straddles two USB packets
204 | -- Trust the count in the packet for how many words to transfer
205 | if (dispatch_words_to_write = 0) then
206 | next_dispatch_state_s <= DISPATCH_COMPLETE;
207 | end if;
208 | when DISPATCH_COMPLETE =>
209 | next_dispatch_state_s <= DISPATCH_IDLE;
210 | end case;
211 |
212 | end process dispatch_fsm_state_select_process;
213 |
214 | end architecture RTL;
215 |
--------------------------------------------------------------------------------
/src/design/tlp_streamer_top.vhd:
--------------------------------------------------------------------------------
1 | --
2 | -- TLP Streamer - Top Module
3 | --
4 | -- (c) MikeM64 - 2021
5 | --
6 |
7 | library IEEE;
8 | use IEEE.std_logic_1164.all;
9 | use IEEE.numeric_std.all;
10 |
11 | use work.tlp_streamer_records.all;
12 |
13 | entity tlp_streamer is
14 | port (
15 | -- FT601 Pins
16 | ft601_clk_i : in std_logic;
17 | ft601_be_io : inout std_logic_vector(3 downto 0);
18 | ft601_data_io : inout std_logic_vector(31 downto 0);
19 | ft601_oe_n_o : out std_logic;
20 | ft601_rxf_n_i : in std_logic;
21 | ft601_rd_n_o : out std_logic;
22 | ft601_rst_n_o : out std_logic;
23 | ft601_txe_n_i : in std_logic;
24 | ft601_wr_n_o : out std_logic;
25 | ft601_siwu_n_o : out std_logic;
26 | -- PCIe Pins
27 | pcie_clk_p_i : in std_logic;
28 | pcie_clk_n_i : in std_logic;
29 | pcie_perst_n_i : in std_logic;
30 | pcie_wake_n_o : out std_logic;
31 | pcie_txp_o : out std_logic_vector(0 downto 0);
32 | pcie_txn_o : out std_logic_vector(0 downto 0);
33 | pcie_rxp_i : in std_logic_vector(0 downto 0);
34 | pcie_rxn_i : in std_logic_vector(0 downto 0);
35 | -- Others
36 | user_led_ld1 : out std_logic;
37 | user_led_ld2 : out std_logic;
38 | sys_clk : in std_logic);
39 | end entity tlp_streamer;
40 |
41 | architecture RTL of tlp_streamer is
42 |
43 | component tlp_streamer_reset is
44 | port(
45 | sys_clk_i : in std_logic;
46 | sys_reset_o : out std_logic);
47 | end component tlp_streamer_reset;
48 |
49 | component tlp_streamer_ft601 is
50 | port (
51 | sys_clk_i : in std_logic;
52 | sys_reset_i : in std_logic;
53 | ft601_clk_i : in std_logic;
54 | ft601_be_io : inout std_logic_vector(3 downto 0);
55 | ft601_data_io : inout std_logic_vector(31 downto 0);
56 | ft601_oe_n_o : out std_logic;
57 | ft601_rxf_n_i : in std_logic;
58 | ft601_rd_n_o : out std_logic;
59 | ft601_rst_n_o : out std_logic;
60 | ft601_txe_n_i : in std_logic;
61 | ft601_wr_n_o : out std_logic;
62 | ft601_siwu_n_o : out std_logic;
63 | ft601_rx_fifo_rd_en_i : in std_logic;
64 | ft601_rx_fifo_rd_empty_o : out std_logic;
65 | ft601_rx_fifo_rd_valid_o : out std_logic;
66 | ft601_rx_fifo_rd_data_o : out std_logic_vector(35 downto 0);
67 | ft601_tx_fifo_wr_en_i : in std_logic;
68 | ft601_tx_fifo_wr_full_o : out std_logic;
69 | ft601_tx_fifo_wr_data_i : in std_logic_vector(35 downto 0));
70 | end component tlp_streamer_ft601;
71 |
72 | component tlp_streamer_rx_dispatch is
73 | generic(NUM_OUTPUT_QUEUES : integer);
74 | port(
75 | sys_clk_i : in std_logic;
76 | sys_reset_i : in std_logic;
77 | -- Input FIFO to dispatch
78 | fifo_rd_en_o : out std_logic;
79 | fifo_rd_empty_i : in std_logic;
80 | fifo_rd_valid_i : in std_logic;
81 | fifo_rd_data_i : in std_logic_vector(35 downto 0);
82 | -- Output FIFOs to dispatch to
83 | dispatch_o_arr : out dispatch_producer_r_array(NUM_OUTPUT_QUEUES-1 downto 0);
84 | dispatch_i_arr : in dispatch_consumer_r_array(NUM_OUTPUT_QUEUES-1 downto 0));
85 | end component tlp_streamer_rx_dispatch;
86 |
87 | component tlp_streamer_tx_arbiter is
88 | generic (NUM_INPUT_QUEUES : integer);
89 | port (
90 | sys_clk_i : in std_logic;
91 | sys_reset_i : in std_logic;
92 | -- Input FIFOs to arbitrate
93 | arbiter_o_arr : out arbiter_producer_r_array(NUM_INPUT_QUEUES-1 downto 0);
94 | arbiter_i_arr : in arbiter_consumer_r_array(NUM_INPUT_QUEUES-1 downto 0);
95 | -- Output FIFO to feed
96 | arbiter_output_wr_en_o : out std_logic;
97 | arbiter_output_wr_full_i : in std_logic;
98 | arbiter_output_wr_data_o : out std_logic_vector(35 downto 0));
99 | end component tlp_streamer_tx_arbiter;
100 |
101 | component tlp_streamer_loopback is
102 | port(
103 | sys_clk_i : in std_logic;
104 | sys_reset_i : in std_logic;
105 | -- Input from dispatch
106 | dispatch_i : in dispatch_producer_r;
107 | dispatch_o : out dispatch_consumer_r;
108 | -- Output to TX
109 | arbiter_i : in arbiter_producer_r;
110 | arbiter_o : out arbiter_consumer_r);
111 | end component tlp_streamer_loopback;
112 |
113 | component tlp_streamer_pcie is
114 | port(
115 | user_led_ld2 : out std_logic;
116 | sys_clk_i : in std_logic;
117 | sys_reset_i : in std_logic;
118 | pcie_clk_p_i : in std_logic;
119 | pcie_clk_n_i : in std_logic;
120 | pcie_perst_n_i : in std_logic;
121 | pcie_wake_n_o : out std_logic;
122 | pcie_txp_o : out std_logic_vector(0 downto 0);
123 | pcie_txn_o : out std_logic_vector(0 downto 0);
124 | pcie_rxp_i : in std_logic_vector(0 downto 0);
125 | pcie_rxn_i : in std_logic_vector(0 downto 0);
126 | pcie_usr_link_up_o : out std_logic;
127 | pcie_cfg_dispatch_i : in dispatch_producer_r;
128 | pcie_cfg_dispatch_o : out dispatch_consumer_r;
129 | pcie_cfg_arbiter_i : in arbiter_producer_r;
130 | pcie_cfg_arbiter_o : out arbiter_consumer_r;
131 | pcie_tlp_dispatch_i : in dispatch_producer_r;
132 | pcie_tlp_dispatch_o : out dispatch_consumer_r;
133 | pcie_tlp_arbiter_i : in arbiter_producer_r;
134 | pcie_tlp_arbiter_o : out arbiter_consumer_r);
135 | end component tlp_streamer_pcie;
136 |
137 | -- Signals for FT601 RX/TX
138 | signal ft601_rx_fifo_data_s, ft601_wr_data_s: std_logic_vector(35 downto 0);
139 | signal ft601_rx_fifo_rd_en_s, ft601_rx_fifo_rd_empty_s, ft601_rx_fifo_rd_valid_s: std_logic;
140 | signal ft601_tx_wr_en_s, ft601_wr_full_s : std_logic;
141 |
142 | -- Signals for system reset
143 | signal tlp_streamer_reset_s: std_logic;
144 |
145 | -- Signals for RX dispatch queues
146 | signal loopback_queue_out: dispatch_producer_r;
147 | signal loopback_queue_in: dispatch_consumer_r;
148 | signal pcie_cfg_rx_dispatch_out: dispatch_producer_r;
149 | signal pcie_cfg_rx_dispatch_in: dispatch_consumer_r;
150 | signal pcie_tlp_rx_dispatch_out: dispatch_producer_r;
151 | signal pcie_tlp_rx_dispatch_in: dispatch_consumer_r;
152 |
153 | -- Signals for TX arbitration
154 | signal loopback_tx_out: arbiter_producer_r;
155 | signal loopback_tx_in: arbiter_consumer_r;
156 | signal pcie_cfg_tx_arbiter_out: arbiter_producer_r;
157 | signal pcie_cfg_tx_arbiter_in: arbiter_consumer_r;
158 | signal pcie_tlp_tx_arbiter_out: arbiter_producer_r;
159 | signal pcie_tlp_tx_arbiter_in: arbiter_consumer_r;
160 |
161 | begin
162 |
163 | comp_tlp_streamer_reset: tlp_streamer_reset
164 | port map(
165 | sys_clk_i => sys_clk,
166 | sys_reset_o => tlp_streamer_reset_s);
167 |
168 | comp_tlp_streamer_ft601: tlp_streamer_ft601
169 | port map (
170 | sys_clk_i => sys_clk,
171 | sys_reset_i => tlp_streamer_reset_s,
172 | ft601_clk_i => ft601_clk_i,
173 | ft601_be_io => ft601_be_io,
174 | ft601_data_io => ft601_data_io,
175 | ft601_oe_n_o => ft601_oe_n_o,
176 | ft601_rxf_n_i => ft601_rxf_n_i,
177 | ft601_rd_n_o => ft601_rd_n_o,
178 | ft601_rst_n_o => ft601_rst_n_o,
179 | ft601_txe_n_i => ft601_txe_n_i,
180 | ft601_wr_n_o => ft601_wr_n_o,
181 | ft601_siwu_n_o => ft601_siwu_n_o,
182 | ft601_rx_fifo_rd_en_i => ft601_rx_fifo_rd_en_s,
183 | ft601_rx_fifo_rd_empty_o => ft601_rx_fifo_rd_empty_s,
184 | ft601_rx_fifo_rd_valid_o => ft601_rx_fifo_rd_valid_s,
185 | ft601_rx_fifo_rd_data_o => ft601_rx_fifo_data_s,
186 | ft601_tx_fifo_wr_en_i => ft601_tx_wr_en_s,
187 | ft601_tx_fifo_wr_full_o => ft601_wr_full_s,
188 | ft601_tx_fifo_wr_data_i => ft601_wr_data_s);
189 |
190 | comp_tlp_streamer_pcie: tlp_streamer_pcie
191 | port map (
192 | user_led_ld2 => user_led_ld2,
193 | sys_clk_i => sys_clk,
194 | sys_reset_i => tlp_streamer_reset_s,
195 | pcie_clk_p_i => pcie_clk_p_i,
196 | pcie_clk_n_i => pcie_clk_n_i,
197 | pcie_perst_n_i => pcie_perst_n_i,
198 | pcie_wake_n_o => pcie_wake_n_o,
199 | pcie_txp_o => pcie_txp_o,
200 | pcie_txn_o => pcie_txn_o,
201 | pcie_rxp_i => pcie_rxp_i,
202 | pcie_rxn_i => pcie_rxn_i,
203 | pcie_usr_link_up_o => open,
204 | -- Conguration management port
205 | pcie_cfg_dispatch_i => pcie_cfg_rx_dispatch_out,
206 | pcie_cfg_dispatch_o => pcie_cfg_rx_dispatch_in,
207 | pcie_cfg_arbiter_i => pcie_cfg_tx_arbiter_out,
208 | pcie_cfg_arbiter_o => pcie_cfg_tx_arbiter_in,
209 | -- TLP Packet handling
210 | pcie_tlp_dispatch_i => pcie_tlp_rx_dispatch_out,
211 | pcie_tlp_dispatch_o => pcie_tlp_rx_dispatch_in,
212 | pcie_tlp_arbiter_i => pcie_tlp_tx_arbiter_out,
213 | pcie_tlp_arbiter_o => pcie_tlp_tx_arbiter_in);
214 |
215 | comp_tlp_streamer_rx_dispatch: tlp_streamer_rx_dispatch
216 | generic map (NUM_OUTPUT_QUEUES => 3)
217 | port map(
218 | sys_clk_i => sys_clk,
219 | sys_reset_i => tlp_streamer_reset_s,
220 | -- Input FIFO to dispatch
221 | fifo_rd_en_o => ft601_rx_fifo_rd_en_s,
222 | fifo_rd_empty_i => ft601_rx_fifo_rd_empty_s,
223 | fifo_rd_valid_i => ft601_rx_fifo_rd_valid_s,
224 | fifo_rd_data_i => ft601_rx_fifo_data_s,
225 | -- Output Components
226 | -- These MUST correspond to tsh_msg_type_et.
227 | dispatch_o_arr(0) => loopback_queue_out,
228 | dispatch_o_arr(1) => pcie_cfg_rx_dispatch_out,
229 | dispatch_o_arr(2) => pcie_tlp_rx_dispatch_out,
230 | dispatch_i_arr(0) => loopback_queue_in,
231 | dispatch_i_arr(1) => pcie_cfg_rx_dispatch_in,
232 | dispatch_i_arr(2) => pcie_tlp_rx_dispatch_in);
233 |
234 | comp_tlp_streamer_tx_arbiter: tlp_streamer_tx_arbiter
235 | generic map (NUM_INPUT_QUEUES => 3)
236 | port map (
237 | sys_clk_i => sys_clk,
238 | sys_reset_i => tlp_streamer_reset_s,
239 | -- Input FIFOs to arbitrate
240 | arbiter_o_arr(0) => loopback_tx_out,
241 | arbiter_o_arr(1) => pcie_cfg_tx_arbiter_out,
242 | arbiter_o_arr(2) => pcie_tlp_tx_arbiter_out,
243 | arbiter_i_arr(0) => loopback_tx_in,
244 | arbiter_i_arr(1) => pcie_cfg_tx_arbiter_in,
245 | arbiter_i_arr(2) => pcie_tlp_tx_arbiter_in,
246 | -- Output FIFO to feed
247 | arbiter_output_wr_en_o => ft601_tx_wr_en_s,
248 | arbiter_output_wr_full_i => ft601_wr_full_s,
249 | arbiter_output_wr_data_o => ft601_wr_data_s);
250 |
251 | comp_tlp_streamer_loopback: tlp_streamer_loopback
252 | port map(
253 | sys_clk_i => sys_clk,
254 | sys_reset_i => tlp_streamer_reset_s,
255 | -- Input from dispatch
256 | dispatch_i => loopback_queue_out,
257 | dispatch_o => loopback_queue_in,
258 | -- Output to TX
259 | arbiter_i => loopback_tx_out,
260 | arbiter_o => loopback_tx_in);
261 |
262 | user_led_ld1 <= tlp_streamer_reset_s;
263 |
264 | end architecture RTL;
265 |
--------------------------------------------------------------------------------
/src/design/tlp_streamer_tx_arbiter.vhd:
--------------------------------------------------------------------------------
1 | --
2 | -- TLP Streamer - FPGA Packet TX Arbiter
3 | --
4 | -- (c) MikeM64 - 2021
5 | --
6 |
7 | library IEEE;
8 | use IEEE.std_logic_1164.all;
9 | use IEEE.numeric_std.all;
10 |
11 | use work.tlp_streamer_records.all;
12 |
13 | entity tlp_streamer_tx_arbiter is
14 | generic (NUM_INPUT_QUEUES : integer);
15 | port (
16 | sys_clk_i : in std_logic;
17 | sys_reset_i : in std_logic;
18 | -- Input FIFOs to arbitrate
19 | arbiter_o_arr : out arbiter_producer_r_array(NUM_INPUT_QUEUES-1 downto 0);
20 | arbiter_i_arr : in arbiter_consumer_r_array(NUM_INPUT_QUEUES-1 downto 0);
21 | -- Output FIFO to feed
22 | arbiter_output_wr_en_o : out std_logic;
23 | arbiter_output_wr_full_i : in std_logic;
24 | arbiter_output_wr_data_o : out std_logic_vector(35 downto 0));
25 | end entity tlp_streamer_tx_arbiter;
26 |
27 | architecture RTL of tlp_streamer_tx_arbiter is
28 |
29 | type arbiter_state is (ARBITER_IDLE, ARBITER_AWAIT_HEADER, ARBITER_READ_HEADER,
30 | ARBITER_WRITE_PACKET, ARBITER_COMPLETE_1, ARBITER_COMPLETE_2);
31 |
32 | signal current_arbiter_state_s, next_arbiter_state_s: arbiter_state;
33 | signal arbiter_words_to_write, next_arbiter_words_to_write: integer range 0 to 65535;
34 | signal arbiter_input_queue, next_arbiter_input_queue: integer range 0 to NUM_INPUT_QUEUES;
35 |
36 | signal arbiter_rd_en_s, arbiter_rd_valid_s_1, arbiter_rd_valid_s_2, arbiter_rd_empty_s,
37 | arbiter_wr_en_s : std_logic;
38 | signal arbiter_rd_data_s_1, arbiter_rd_data_s_2, arbiter_rd_data_s_3 : std_logic_vector(35 downto 0);
39 |
40 | begin
41 |
42 | arbiter_fsm_state_process: process(sys_clk_i, sys_reset_i, next_arbiter_state_s,
43 | arbiter_rd_en_s, arbiter_output_wr_full_i,
44 | arbiter_wr_en_s, arbiter_rd_data_s_1,
45 | arbiter_i_arr, arbiter_rd_data_s_2,
46 | arbiter_words_to_write, arbiter_rd_valid_s_1,
47 | arbiter_rd_valid_s_2, next_arbiter_input_queue)
48 | begin
49 |
50 | if (sys_reset_i = '1') then
51 | current_arbiter_state_s <= ARBITER_IDLE;
52 | arbiter_output_wr_en_o <= '0';
53 | arbiter_rd_data_s_1 <= (others => '0');
54 | arbiter_rd_data_s_2 <= (others => '0');
55 | arbiter_rd_valid_s_1 <= '0';
56 | arbiter_rd_valid_s_2 <= '0';
57 | arbiter_rd_empty_s <= '1';
58 | arbiter_input_queue <= NUM_INPUT_QUEUES;
59 | for i in 0 to NUM_INPUT_QUEUES-1 loop
60 | arbiter_o_arr(i).arbiter_rd_en <= '0';
61 | arbiter_o_arr(i).arbiter_wr_full <= '0';
62 | end loop;
63 | elsif (rising_edge(sys_clk_i)) then
64 | current_arbiter_state_s <= next_arbiter_state_s;
65 |
66 | for i in 0 to NUM_INPUT_QUEUES-1 loop
67 | if (i = next_arbiter_input_queue) then
68 | arbiter_rd_data_s_1 <= arbiter_i_arr(i).arbiter_rd_data;
69 | arbiter_rd_valid_s_1 <= arbiter_i_arr(i).arbiter_rd_valid;
70 | arbiter_rd_empty_s <= arbiter_i_arr(i).arbiter_rd_empty;
71 | arbiter_o_arr(i).arbiter_rd_en <= arbiter_rd_en_s;
72 | arbiter_o_arr(i).arbiter_wr_full <= arbiter_output_wr_full_i;
73 | -- There used to be an else statement here in order to set the
74 | -- signals for the unselected inputs to a known default but
75 | -- that seemed to optimize out some of the signals from the
76 | -- selected inputs.
77 | end if;
78 | end loop;
79 |
80 | arbiter_rd_data_s_2 <= arbiter_rd_data_s_1;
81 | arbiter_rd_valid_s_2 <= arbiter_rd_valid_s_1;
82 |
83 | arbiter_output_wr_data_o <= arbiter_rd_data_s_2;
84 | arbiter_rd_data_s_3 <= arbiter_rd_data_s_2;
85 | arbiter_output_wr_en_o <= arbiter_wr_en_s;
86 |
87 | arbiter_input_queue <= next_arbiter_input_queue;
88 | arbiter_words_to_write <= next_arbiter_words_to_write;
89 | end if;
90 |
91 | end process arbiter_fsm_state_process;
92 |
93 | arbiter_fsm_data_output_process: process(current_arbiter_state_s, arbiter_i_arr, arbiter_input_queue,
94 | arbiter_words_to_write, arbiter_rd_valid_s_2, arbiter_rd_data_s_3)
95 | begin
96 |
97 | arbiter_rd_en_s <= '0';
98 | arbiter_wr_en_s <= '0';
99 | next_arbiter_input_queue <= arbiter_input_queue;
100 | next_arbiter_words_to_write <= arbiter_words_to_write;
101 |
102 | case current_arbiter_state_s is
103 | when ARBITER_IDLE =>
104 | for i in 0 to NUM_INPUT_QUEUES-1 loop
105 | if (arbiter_i_arr(i).arbiter_rd_empty = '0') then
106 | next_arbiter_input_queue <= i;
107 | end if;
108 | exit when arbiter_i_arr(i).arbiter_rd_empty = '0';
109 | end loop;
110 | next_arbiter_words_to_write <= 0;
111 | when ARBITER_AWAIT_HEADER =>
112 | arbiter_rd_en_s <= '1';
113 | arbiter_wr_en_s <= arbiter_rd_valid_s_2;
114 | next_arbiter_words_to_write <= 0;
115 | when ARBITER_READ_HEADER =>
116 | arbiter_rd_en_s <= '1';
117 | arbiter_wr_en_s <= arbiter_rd_valid_s_2;
118 | next_arbiter_words_to_write <= to_integer(unsigned(arbiter_rd_data_s_3(23 downto 16) & arbiter_rd_data_s_3(31 downto 24))) - 1;
119 | when ARBITER_WRITE_PACKET =>
120 | if (arbiter_words_to_write > 3) then
121 | arbiter_rd_en_s <= '1';
122 | else
123 | arbiter_rd_en_s <= '0';
124 | end if;
125 | arbiter_wr_en_s <= arbiter_rd_valid_s_2;
126 | next_arbiter_words_to_write <= arbiter_words_to_write - 1;
127 | when ARBITER_COMPLETE_1 =>
128 | next_arbiter_words_to_write <= 0;
129 | when ARBITER_COMPLETE_2 =>
130 | -- A second complete state is used to allow for the rd_en
131 | -- signal to be de-asserted for the selected input before
132 | -- resetting the input queue for the next TX packet
133 | next_arbiter_input_queue <= NUM_INPUT_QUEUES;
134 | next_arbiter_words_to_write <= 0;
135 | end case;
136 |
137 | end process arbiter_fsm_data_output_process;
138 |
139 | arbiter_fsm_state_select_process: process(current_arbiter_state_s, arbiter_i_arr,
140 | arbiter_words_to_write, arbiter_rd_valid_s_2,
141 | arbiter_input_queue)
142 | begin
143 |
144 | -- Current state does not change by default
145 | next_arbiter_state_s <= current_arbiter_state_s;
146 |
147 | case current_arbiter_state_s is
148 | when ARBITER_IDLE =>
149 | -- Once an input queue is available and there is space in the output queue
150 | -- move to ARBITER_INPUT_SELECTED
151 | if (arbiter_input_queue < NUM_INPUT_QUEUES) then
152 | next_arbiter_state_s <= ARBITER_AWAIT_HEADER;
153 | end if;
154 | when ARBITER_AWAIT_HEADER =>
155 | if (arbiter_rd_valid_s_2 = '1') then
156 | next_arbiter_state_s <= ARBITER_READ_HEADER;
157 | end if;
158 | when ARBITER_READ_HEADER =>
159 | next_arbiter_state_s <= ARBITER_WRITE_PACKET;
160 | when ARBITER_WRITE_PACKET =>
161 | if (arbiter_words_to_write = 0) then
162 | next_arbiter_state_s <= ARBITER_COMPLETE_1;
163 | end if;
164 | when ARBITER_COMPLETE_1 =>
165 | next_arbiter_state_s <= ARBITER_COMPLETE_2;
166 | when ARBITER_COMPLETE_2 =>
167 | next_arbiter_state_s <= ARBITER_IDLE;
168 | end case;
169 |
170 | end process arbiter_fsm_state_select_process;
171 |
172 | end architecture RTL;
173 |
--------------------------------------------------------------------------------
/src/sim/tlp_streamer_usb_rx_sim.vhd:
--------------------------------------------------------------------------------
1 | --
2 | -- TLP Streamer - USB RX Simulation
3 | --
4 | -- (c) MikeM64 - 2021
5 | --
6 |
7 | library IEEE;
8 | use IEEE.std_logic_1164.all;
9 | use IEEE.numeric_std.all;
10 |
11 | entity tlp_usb_rx_sim is end tlp_usb_rx_sim;
12 |
13 | architecture test of tlp_usb_rx_sim is
14 | component tlp_streamer
15 | port(
16 | -- FT601 Pins
17 | ft601_clk_i : in std_logic;
18 | ft601_be_io : inout std_logic_vector(3 downto 0);
19 | ft601_data_io : inout std_logic_vector(31 downto 0);
20 | ft601_oe_n_o : out std_logic;
21 | ft601_rxf_n_i : in std_logic;
22 | ft601_rd_n_o : out std_logic;
23 | ft601_rst_n_o : out std_logic;
24 | ft601_txe_n_i : in std_logic;
25 | ft601_wr_n_o : out std_logic;
26 | ft601_siwu_n_o : out std_logic;
27 | -- PCIe Pins
28 | pcie_clk_p_i : in std_logic;
29 | pcie_clk_n_i : in std_logic;
30 | pcie_perst_n_i : in std_logic;
31 | pcie_wake_n_o : out std_logic;
32 | pcie_txp_o : out std_logic_vector(0 downto 0);
33 | pcie_txn_o : out std_logic_vector(0 downto 0);
34 | pcie_rxp_i : in std_logic_vector(0 downto 0);
35 | pcie_rxn_i : in std_logic_vector(0 downto 0);
36 | -- Others
37 | user_led_ld1 : out std_logic;
38 | user_led_ld2 : out std_logic;
39 | sys_clk : in std_logic);
40 |
41 | end component;
42 |
43 | signal test_ft601_clk: std_logic := '1';
44 | signal test_sys_clk: std_logic := '1';
45 | signal test_ft601_be: std_logic_vector(3 downto 0) := "0000";
46 | signal test_ft601_data: std_logic_vector(31 downto 0) := "00000000000000000000000000000000";
47 |
48 | signal test_ft601_bus_wr_s: std_logic := '1';
49 | signal test_ft601_be_rd_i: std_logic_vector(3 downto 0);
50 | signal test_ft601_data_rd_i: std_logic_vector(31 downto 0);
51 | signal test_ft601_be_wr_o: std_logic_vector(3 downto 0);
52 | signal test_ft601_data_wr_o: std_logic_vector(31 downto 0);
53 |
54 | signal test_ft601_oe_n: std_logic := '1';
55 | signal test_ft601_rxf_n: std_logic := '1';
56 | signal test_ft601_rd_n: std_logic := '1';
57 | signal test_ft601_rst_n: std_logic := '1';
58 | signal test_ft601_txe_n: std_logic := '1';
59 | signal test_ft601_wr_n: std_logic := '1';
60 | signal test_ft601_siwu_n_o: std_logic := '0';
61 |
62 | signal pcie_clk_p_i : std_logic := '0';
63 | signal pcie_clk_n_i : std_logic := '0';
64 | signal pcie_perst_n_i : std_logic := '0';
65 | signal pcie_wake_n_o : std_logic := '0';
66 | signal pcie_txp_o : std_logic_vector(0 downto 0) := "0";
67 | signal pcie_txn_o : std_logic_vector(0 downto 0) := "0";
68 | signal pcie_rxp_i : std_logic_vector(0 downto 0) := "0";
69 | signal pcie_rxn_i : std_logic_vector(0 downto 0) := "0";
70 |
71 | signal test_user_led_ld1: std_logic := '0';
72 | signal test_user_led_ld2: std_logic := '0';
73 |
74 | begin
75 |
76 | UUT: tlp_streamer
77 | port map(
78 | ft601_clk_i => test_ft601_clk,
79 | ft601_be_io => test_ft601_be,
80 | ft601_data_io => test_ft601_data,
81 | ft601_oe_n_o => test_ft601_oe_n,
82 | ft601_rxf_n_i => test_ft601_rxf_n,
83 | ft601_rd_n_o => test_ft601_rd_n,
84 | ft601_rst_n_o => test_ft601_rst_n,
85 | ft601_txe_n_i => test_ft601_txe_n,
86 | ft601_wr_n_o => test_ft601_wr_n,
87 | ft601_siwu_n_o => test_ft601_siwu_n_o,
88 | -- PCIe Pins
89 | pcie_clk_p_i => pcie_clk_p_i,
90 | pcie_clk_n_i => pcie_clk_n_i,
91 | pcie_perst_n_i => pcie_perst_n_i,
92 | pcie_wake_n_o => pcie_wake_n_o,
93 | pcie_txp_o => pcie_txp_o,
94 | pcie_txn_o => pcie_txn_o,
95 | pcie_rxp_i => pcie_rxp_i,
96 | pcie_rxn_i => pcie_rxn_i,
97 |
98 | user_led_ld1 => test_user_led_ld1,
99 | user_led_ld2 => test_user_led_ld2,
100 | sys_clk => test_sys_clk);
101 |
102 | test_ft601_clk <= not test_ft601_clk after 5ns;
103 | test_sys_clk <= not test_sys_clk after 5ns;
104 |
105 | bus_write: process(test_ft601_clk) begin
106 |
107 | if (test_ft601_clk'EVENT and test_ft601_clk = '1') then
108 | if (test_ft601_bus_wr_s = '1') then
109 | test_ft601_be <= test_ft601_be_wr_o;
110 | test_ft601_data <= test_ft601_data_wr_o;
111 | else
112 | test_ft601_be <= "ZZZZ";
113 | test_ft601_data <= "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
114 | end if;
115 |
116 | test_ft601_be_rd_i <= test_ft601_be;
117 | test_ft601_data_rd_i <= test_ft601_data;
118 | end if;
119 |
120 | end process bus_write;
121 |
122 | tb: process begin
123 |
124 | test_ft601_bus_wr_s <= '1';
125 | test_ft601_be_wr_o <= "0000";
126 | test_ft601_data_wr_o <= "00000000000000000000000000000000";
127 |
128 | wait for 800ns;
129 | report "FPGA reset complete";
130 |
131 | -- Refer to pg. 17 of the FT601 datasheet for the
132 | -- controller read timing diagram. This is what is
133 | -- being verified here.
134 | test_ft601_rxf_n <= '0';
135 |
136 | wait for 30ns;
137 | test_ft601_be_wr_o <= "1111";
138 | test_ft601_data_wr_o <= "00000000000001101111111100000000";
139 |
140 | wait for 10ns;
141 | test_ft601_data_wr_o <= "00000000000000000000000000000000";
142 |
143 | wait for 10ns;
144 | test_ft601_data_wr_o <= "01010101010101010101010101010101";
145 |
146 | wait for 10ns;
147 | test_ft601_data_wr_o <= "10101010101010101010101010101010";
148 |
149 | wait for 10ns;
150 | test_ft601_data_wr_o <= "10101010101010101010101010101010";
151 |
152 | wait for 10ns;
153 | test_ft601_data_wr_o <= "10101010101010101010101010101010";
154 |
155 | wait for 10ns;
156 | --assert test_ft601_oe_n = '0' report "The core has not asserted OE_N, 3 cycles after RXF_N" severity failure;
157 | test_ft601_be_wr_o <= "0000";
158 | test_ft601_data_wr_o <= "00000000000000000000000000000000";
159 |
160 | wait for 10ns;
161 | test_ft601_bus_wr_s <= '0';
162 | test_ft601_rxf_n <= '1';
163 |
164 | --assert test_ft601_rd_n = '0' report "The core has not asserted RD_N, 1 cycle after OE_N" severity failure;
165 | wait for 100ns;
166 |
167 | --assert test_ft601_oe_n = '1' report "The core has not de-asserted OE_N, 1 cycle after RXF_N" severity failure;
168 | --assert test_ft601_rd_n = '1' report "The core has not de-asserted RD_N, 1 cycle after RXF_N" severity failure;
169 | test_ft601_txe_n <= '0';
170 |
171 | wait for 210ns;
172 | test_ft601_txe_n <= '1';
173 | wait for 50ns;
174 |
175 | report "Simulation complete!";
176 |
177 | end process tb;
178 |
179 | end architecture;
--------------------------------------------------------------------------------
/src/sim/tlp_usb_rx_sim_behav.wcfg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | Test Signals
27 | label
28 |
29 | test_sys_clk
30 | test_sys_clk
31 |
32 |
33 | test_ft601_clk
34 | test_ft601_clk
35 |
36 |
37 | test_ft601_be[3:0]
38 | test_ft601_be[3:0]
39 |
40 |
41 | test_ft601_data[31:0]
42 | test_ft601_data[31:0]
43 |
44 |
45 | test_ft601_oe_n
46 | test_ft601_oe_n
47 |
48 |
49 | test_ft601_rd_n
50 | test_ft601_rd_n
51 |
52 |
53 | test_ft601_wr_n
54 | test_ft601_wr_n
55 |
56 |
57 | test_ft601_rxf_n
58 | test_ft601_rxf_n
59 |
60 |
61 | test_ft601_txe_n
62 | test_ft601_txe_n
63 |
64 |
65 | test_ft601_rst_n
66 | test_ft601_rst_n
67 |
68 |
69 |
70 | ft601_be_io[3:0]
71 | ft601_be_io[3:0]
72 |
73 |
74 | ft601_data_io[31:0]
75 | ft601_data_io[31:0]
76 |
77 |
78 | Bus FSM
79 | label
80 |
81 |
82 |
83 | label
84 | ft601_txe_n_i
85 | ft601_txe_n_i
86 | /tlp_usb_rx_sim/UUT/ft601_txe_n_ift601_txe_n_i
87 |
88 |
89 | ft601_wr_n_o
90 | ft601_wr_n_o
91 |
92 |
93 | ft601_rst_n_o
94 | ft601_rst_n_o
95 |
96 |
97 | RX FIFO
98 | label
99 |
100 | ft601_data_rd_i[31:0]
101 | ft601_data_rd_i[31:0]
102 |
103 |
104 | fifo_rx_wr_data_s[35:0]
105 | fifo_rx_wr_data_s[35:0]
106 |
107 |
108 | current_bus_state
109 | current_bus_state
110 |
111 |
112 | next_bus_state
113 | next_bus_state
114 |
115 |
116 | ft601_rx_fifo_rd_data_o[35:0]
117 | ft601_rx_fifo_rd_data_o[35:0]
118 |
119 |
120 | fifo_rx_wr_en_s
121 | fifo_rx_wr_en_s
122 |
123 |
124 |
125 | TX FIFO
126 | label
127 |
128 | fifo_tx_rd_data_s[35:0]
129 | fifo_tx_rd_data_s[35:0]
130 |
131 |
132 | fifo_tx_rd_en_s
133 | fifo_tx_rd_en_s
134 |
135 |
136 | fifo_tx_rd_empty_s
137 | fifo_tx_rd_empty_s
138 |
139 |
140 | fifo_tx_rd_valid_s
141 | fifo_tx_rd_valid_s
142 |
143 |
144 | wr_en
145 | wr_en
146 |
147 |
148 | full
149 | full
150 |
151 |
152 | empty
153 | empty
154 |
155 |
156 | ft601_tx_fifo_wr_full_o
157 | ft601_tx_fifo_wr_full_o
158 |
159 |
160 | ft601_tx_fifo_wr_data_i[35:0]
161 | ft601_tx_fifo_wr_data_i[35:0]
162 |
163 |
164 | ft601_tx_fifo_wr_en_i
165 | ft601_tx_fifo_wr_en_i
166 |
167 |
168 |
169 | RX Dispatch
170 | label
171 |
172 |
173 | fifo_rd_data_i[35:0]
174 | fifo_rd_data_i[35:0]
175 |
176 |
177 | fifo_rd_valid_i
178 | fifo_rd_valid_i
179 |
180 |
181 | fifo_rd_empty_i
182 | fifo_rd_empty_i
183 |
184 |
185 | fifo_rd_en_o
186 | fifo_rd_en_o
187 |
188 |
189 | current_dispatch_state_s
190 | current_dispatch_state_s
191 |
192 |
193 | next_dispatch_state_s
194 | next_dispatch_state_s
195 |
196 |
197 | dispatch_output_queue
198 | dispatch_output_queue
199 |
200 |
201 | dispatch_words_to_write
202 | dispatch_words_to_write
203 |
204 |
205 | next_dispatch_words_to_write
206 | next_dispatch_words_to_write
207 |
208 |
209 | dispatch_data_s_1[35:0]
210 | dispatch_data_s_1[35:0]
211 |
212 |
213 | dispatch_data_s_2[35:0]
214 | dispatch_data_s_2[35:0]
215 |
216 |
217 | dispatch_o_arr[1:0]
218 | dispatch_o_arr[1:0]
219 |
220 |
221 | [1]
222 | [1]
223 |
224 |
225 | [0]
226 | [0]
227 |
228 |
229 |
230 |
231 | dispatch_i_arr[1:0]
232 | dispatch_i_arr[1:0]
233 |
234 |
235 |
236 | TX Arbiter
237 | label
238 |
239 |
240 | current_arbiter_state_s
241 | current_arbiter_state_s
242 |
243 |
244 | next_arbiter_state_s
245 | next_arbiter_state_s
246 |
247 |
248 | arbiter_words_to_write
249 | arbiter_words_to_write
250 |
251 |
252 | next_arbiter_words_to_write
253 | next_arbiter_words_to_write
254 |
255 |
256 | arbiter_input_queue
257 | arbiter_input_queue
258 |
259 |
260 | next_arbiter_input_queue
261 | next_arbiter_input_queue
262 |
263 |
264 | arbiter_output_wr_full_i
265 | arbiter_output_wr_full_i
266 |
267 |
268 | arbiter_wr_en_s
269 | arbiter_wr_en_s
270 |
271 |
272 | arbiter_output_wr_en_o
273 | arbiter_output_wr_en_o
274 |
275 |
276 | arbiter_rd_en_s
277 | arbiter_rd_en_s
278 |
279 |
280 | arbiter_rd_valid_s_1
281 | arbiter_rd_valid_s_1
282 |
283 |
284 | arbiter_rd_valid_s_2
285 | arbiter_rd_valid_s_2
286 |
287 |
288 | arbiter_rd_data_s_1[35:0]
289 | arbiter_rd_data_s_1[35:0]
290 |
291 |
292 | arbiter_rd_data_s_2[35:0]
293 | arbiter_rd_data_s_2[35:0]
294 |
295 |
296 | arbiter_output_wr_data_o[35:0]
297 | arbiter_output_wr_data_o[35:0]
298 |
299 |
300 | arbiter_rd_data_s_3[35:0]
301 | arbiter_rd_data_s_3[35:0]
302 |
303 |
304 | arbiter_i_arr[1:0]
305 | arbiter_i_arr[1:0]
306 |
307 |
308 | [1]
309 | [1]
310 |
311 |
312 |
313 | [0]
314 | [0]
315 |
316 |
317 |
318 |
319 | arbiter_o_arr[1:0]
320 | arbiter_o_arr[1:0]
321 |
322 |
323 | [1]
324 | [1]
325 |
326 |
327 |
328 | [0]
329 | [0]
330 |
331 |
332 |
333 |
334 |
335 | Loopback
336 | label
337 |
338 | wr_en
339 | wr_en
340 |
341 |
342 | dispatch_i
343 | dispatch_i
344 |
345 |
346 |
347 | dispatch_o
348 | dispatch_o
349 |
350 |
351 |
352 | arbiter_i
353 | arbiter_i
354 |
355 |
356 |
357 | rd_en
358 | rd_en
359 |
360 |
361 | arbiter_o
362 | arbiter_o
363 |
364 |
365 |
366 |
367 |
--------------------------------------------------------------------------------
/vivado_build.tcl:
--------------------------------------------------------------------------------
1 | #
2 | # RUN FROM WITHIN "Vivado Tcl Shell" WITH COMMAND:
3 | # source vivado_build.tcl -notrace
4 | #
5 | reset_run synth_1
6 | puts "-------------------------------------------------------"
7 | puts " STARTING SYNTHESIS STEP. "
8 | puts "-------------------------------------------------------"
9 | launch_runs synth_1
10 | puts "-------------------------------------------------------"
11 | puts " WAITING FOR SYNTHESIS STEP TO FINISH ... "
12 | puts " THIS IS LIKELY TO TAKE A VERY LONG TIME. "
13 | puts "-------------------------------------------------------"
14 | wait_on_run synth_1
15 | puts "-------------------------------------------------------"
16 | puts " STARTING IMPLEMENTATION STEP. "
17 | puts "-------------------------------------------------------"
18 | launch_runs impl_1 -to_step write_bitstream
19 | puts "-------------------------------------------------------"
20 | puts " WAITING FOR IMPLEMENTATION STEP TO FINISH ... "
21 | puts " THIS IS LIKELY TO TAKE A VERY LONG TIME. "
22 | puts "-------------------------------------------------------"
23 | wait_on_run impl_1
24 | puts "-------------------------------------------------------"
25 | puts " BUILD HOPEFULLY COMPLETED. "
26 | puts "-------------------------------------------------------"
27 | quit
28 |
--------------------------------------------------------------------------------
/vivado_generate_project.tcl:
--------------------------------------------------------------------------------
1 | #*****************************************************************************************
2 | # Vivado (TM) v2020.2 (64-bit)
3 | #
4 | # vivado_generate_project.tcl: Tcl script for re-creating project 'tlp-streamer'
5 | #
6 | # Generated by Vivado on Sun Jan 02 03:42:26 EST 2022
7 | # IP Build 3064653 on Wed Nov 18 14:17:31 MST 2020
8 | #
9 | # This file contains the Vivado Tcl commands for re-creating the project to the state*
10 | # when this script was generated. In order to re-create the project, please source this
11 | # file in the Vivado Tcl Shell.
12 | #
13 | # * Note that the runs in the created project will be configured the same way as the
14 | # original project, however they will not be launched automatically. To regenerate the
15 | # run results please launch the synthesis/implementation runs as needed.
16 | #
17 | #*****************************************************************************************
18 | # NOTE: In order to use this script for source control purposes, please make sure that the
19 | # following files are added to the source control system:-
20 | #
21 | # 1. This project restoration tcl script (vivado_generate_project.tcl) that was generated.
22 | #
23 | # 2. The following source(s) files that were local or imported into the original project.
24 | # (Please see the '$orig_proj_dir' and '$origin_dir' variable setting below at the start of the script)
25 | #
26 | #
27 | #
28 | # 3. The following remote source files that were added to the original project:-
29 | #
30 | # "./src/design/tlp_streamer_records.vhd"
31 | # "./src/design/tlp_streamer_top.vhd"
32 | # "./src/design/tlp_streamer_ft601.vhd"
33 | # "./src/design/tlp_streamer_pcie.vhd"
34 | # "./src/design/tlp_streamer_rx_dispatch.vhd"
35 | # "./src/design/tlp_streamer_loopback.vhd"
36 | # "./src/design/tlp_streamer_reset.vhd"
37 | # "./src/design/tlp_streamer_tx_arbiter.vhd"
38 | # "./src/design/tlp_streamer_pcie_tlp.vhd"
39 | # "./src/design/tlp_streamer_pcie_cfg.vhd"
40 | # "./ip/fifo_36_36_prim/fifo_36_36_prim.xci"
41 | # "./ip/fifo_32_32_bram/fifo_32_32_bram.xci"
42 | # "./ip/ila_0/ila_0.xci"
43 | # "./ip/fifo_pcie_tlp_r32_w64_4096_bram/fifo_pcie_tlp_r32_w64_4096_bram.xci"
44 | # "./ip/pcie_tlp_ila/pcie_tlp_ila.xci"
45 | # "./ip/fifo_pcie_tlp_r64_w32_4096_bram/fifo_pcie_tlp_r64_w32_4096_bram.xci"
46 | # "./ip/pcie_7x_0/pcie_7x_0.xci"
47 | # "./src/constrs/screamer_m2.xdc"
48 | # "./src/sim/tlp_streamer_usb_rx_sim.vhd"
49 | # "./src/sim/tlp_usb_rx_sim_behav.wcfg"
50 | #
51 | #*****************************************************************************************
52 |
53 | # Check file required for this script exists
54 | proc checkRequiredFiles { origin_dir} {
55 | set status true
56 | set files [list \
57 | "./src/design/tlp_streamer_records.vhd" \
58 | "./src/design/tlp_streamer_top.vhd" \
59 | "./src/design/tlp_streamer_ft601.vhd" \
60 | "./src/design/tlp_streamer_pcie.vhd" \
61 | "./src/design/tlp_streamer_rx_dispatch.vhd" \
62 | "./src/design/tlp_streamer_loopback.vhd" \
63 | "./src/design/tlp_streamer_reset.vhd" \
64 | "./src/design/tlp_streamer_tx_arbiter.vhd" \
65 | "./src/design/tlp_streamer_pcie_tlp.vhd" \
66 | "./src/design/tlp_streamer_pcie_cfg.vhd" \
67 | "./ip/fifo_36_36_prim/fifo_36_36_prim.xci" \
68 | "./ip/fifo_32_32_bram/fifo_32_32_bram.xci" \
69 | "./ip/ila_0/ila_0.xci" \
70 | "./ip/fifo_pcie_tlp_r32_w64_4096_bram/fifo_pcie_tlp_r32_w64_4096_bram.xci" \
71 | "./ip/pcie_tlp_ila/pcie_tlp_ila.xci" \
72 | "./ip/fifo_pcie_tlp_r64_w32_4096_bram/fifo_pcie_tlp_r64_w32_4096_bram.xci" \
73 | "./ip/pcie_7x_0/pcie_7x_0.xci" \
74 | "./src/constrs/screamer_m2.xdc" \
75 | "./src/sim/tlp_streamer_usb_rx_sim.vhd" \
76 | "./src/sim/tlp_usb_rx_sim_behav.wcfg" \
77 | ]
78 | foreach ifile $files {
79 | if { ![file isfile $ifile] } {
80 | puts " Could not find remote file $ifile "
81 | set status false
82 | }
83 | }
84 |
85 | return $status
86 | }
87 | # Set the reference directory for source file relative paths (by default the value is script directory path)
88 | set origin_dir "."
89 |
90 | # Use origin directory path location variable, if specified in the tcl shell
91 | if { [info exists ::origin_dir_loc] } {
92 | set origin_dir $::origin_dir_loc
93 | }
94 |
95 | # Set the project name
96 | set _xil_proj_name_ "tlp-streamer"
97 |
98 | # Use project name variable, if specified in the tcl shell
99 | if { [info exists ::user_project_name] } {
100 | set _xil_proj_name_ $::user_project_name
101 | }
102 |
103 | variable script_file
104 | set script_file "vivado_generate_project.tcl"
105 |
106 | # Help information for this script
107 | proc print_help {} {
108 | variable script_file
109 | puts "\nDescription:"
110 | puts "Recreate a Vivado project from this script. The created project will be"
111 | puts "functionally equivalent to the original project for which this script was"
112 | puts "generated. The script contains commands for creating a project, filesets,"
113 | puts "runs, adding/importing sources and setting properties on various objects.\n"
114 | puts "Syntax:"
115 | puts "$script_file"
116 | puts "$script_file -tclargs \[--origin_dir \]"
117 | puts "$script_file -tclargs \[--project_name \]"
118 | puts "$script_file -tclargs \[--help\]\n"
119 | puts "Usage:"
120 | puts "Name Description"
121 | puts "-------------------------------------------------------------------------"
122 | puts "\[--origin_dir \] Determine source file paths wrt this path. Default"
123 | puts " origin_dir path value is \".\", otherwise, the value"
124 | puts " that was set with the \"-paths_relative_to\" switch"
125 | puts " when this script was generated.\n"
126 | puts "\[--project_name \] Create project with the specified name. Default"
127 | puts " name is the name of the project from where this"
128 | puts " script was generated.\n"
129 | puts "\[--help\] Print help information for this script"
130 | puts "-------------------------------------------------------------------------\n"
131 | exit 0
132 | }
133 |
134 | if { $::argc > 0 } {
135 | for {set i 0} {$i < $::argc} {incr i} {
136 | set option [string trim [lindex $::argv $i]]
137 | switch -regexp -- $option {
138 | "--origin_dir" { incr i; set origin_dir [lindex $::argv $i] }
139 | "--project_name" { incr i; set _xil_proj_name_ [lindex $::argv $i] }
140 | "--help" { print_help }
141 | default {
142 | if { [regexp {^-} $option] } {
143 | puts "ERROR: Unknown option '$option' specified, please type '$script_file -tclargs --help' for usage info.\n"
144 | return 1
145 | }
146 | }
147 | }
148 | }
149 | }
150 |
151 | # Set the directory path for the original project from where this script was exported
152 | set orig_proj_dir "[file normalize "$origin_dir/tlp-streamer"]"
153 |
154 | # Check for paths and files needed for project creation
155 | set validate_required 0
156 | if { $validate_required } {
157 | if { [checkRequiredFiles $origin_dir] } {
158 | puts "Tcl file $script_file is valid. All files required for project creation is accesable. "
159 | } else {
160 | puts "Tcl file $script_file is not valid. Not all files required for project creation is accesable. "
161 | return
162 | }
163 | }
164 |
165 | # Create project
166 | create_project ${_xil_proj_name_} ./${_xil_proj_name_} -part xc7a35tcsg325-2
167 |
168 | # Set the directory path for the new project
169 | set proj_dir [get_property directory [current_project]]
170 |
171 | # Set project properties
172 | set obj [current_project]
173 | set_property -name "default_lib" -value "xil_defaultlib" -objects $obj
174 | set_property -name "enable_vhdl_2008" -value "1" -objects $obj
175 | set_property -name "ip_cache_permissions" -value "read write" -objects $obj
176 | set_property -name "ip_output_repo" -value "$proj_dir/${_xil_proj_name_}.cache/ip" -objects $obj
177 | set_property -name "mem.enable_memory_map_generation" -value "1" -objects $obj
178 | set_property -name "part" -value "xc7a35tcsg325-2" -objects $obj
179 | set_property -name "sim.central_dir" -value "$proj_dir/${_xil_proj_name_}.ip_user_files" -objects $obj
180 | set_property -name "sim.ip.auto_export_scripts" -value "1" -objects $obj
181 | set_property -name "simulator_language" -value "Mixed" -objects $obj
182 | set_property -name "source_mgmt_mode" -value "DisplayOnly" -objects $obj
183 | set_property -name "target_language" -value "VHDL" -objects $obj
184 | set_property -name "webtalk.activehdl_export_sim" -value "97" -objects $obj
185 | set_property -name "webtalk.ies_export_sim" -value "97" -objects $obj
186 | set_property -name "webtalk.modelsim_export_sim" -value "97" -objects $obj
187 | set_property -name "webtalk.questa_export_sim" -value "97" -objects $obj
188 | set_property -name "webtalk.riviera_export_sim" -value "97" -objects $obj
189 | set_property -name "webtalk.vcs_export_sim" -value "97" -objects $obj
190 | set_property -name "webtalk.xcelium_export_sim" -value "4" -objects $obj
191 | set_property -name "webtalk.xsim_export_sim" -value "97" -objects $obj
192 | set_property -name "webtalk.xsim_launch_sim" -value "507" -objects $obj
193 | set_property -name "xpm_libraries" -value "XPM_CDC XPM_MEMORY" -objects $obj
194 |
195 | # Create 'sources_1' fileset (if not found)
196 | if {[string equal [get_filesets -quiet sources_1] ""]} {
197 | create_fileset -srcset sources_1
198 | }
199 |
200 | # Set 'sources_1' fileset object
201 | set obj [get_filesets sources_1]
202 | set files [list \
203 | [file normalize "${origin_dir}/src/design/tlp_streamer_records.vhd"] \
204 | [file normalize "${origin_dir}/src/design/tlp_streamer_top.vhd"] \
205 | [file normalize "${origin_dir}/src/design/tlp_streamer_ft601.vhd"] \
206 | [file normalize "${origin_dir}/src/design/tlp_streamer_pcie.vhd"] \
207 | [file normalize "${origin_dir}/src/design/tlp_streamer_rx_dispatch.vhd"] \
208 | [file normalize "${origin_dir}/src/design/tlp_streamer_loopback.vhd"] \
209 | [file normalize "${origin_dir}/src/design/tlp_streamer_reset.vhd"] \
210 | [file normalize "${origin_dir}/src/design/tlp_streamer_tx_arbiter.vhd"] \
211 | [file normalize "${origin_dir}/src/design/tlp_streamer_pcie_tlp.vhd"] \
212 | [file normalize "${origin_dir}/src/design/tlp_streamer_pcie_cfg.vhd"] \
213 | [file normalize "${origin_dir}/ip/fifo_36_36_prim/fifo_36_36_prim.xci"] \
214 | [file normalize "${origin_dir}/ip/fifo_32_32_bram/fifo_32_32_bram.xci"] \
215 | [file normalize "${origin_dir}/ip/ila_0/ila_0.xci"] \
216 | [file normalize "${origin_dir}/ip/fifo_pcie_tlp_r32_w64_4096_bram/fifo_pcie_tlp_r32_w64_4096_bram.xci"] \
217 | [file normalize "${origin_dir}/ip/pcie_tlp_ila/pcie_tlp_ila.xci"] \
218 | [file normalize "${origin_dir}/ip/fifo_pcie_tlp_r64_w32_4096_bram/fifo_pcie_tlp_r64_w32_4096_bram.xci"] \
219 | ]
220 | add_files -norecurse -fileset $obj $files
221 |
222 | # Set 'sources_1' fileset file properties for remote files
223 | set file "$origin_dir/src/design/tlp_streamer_records.vhd"
224 | set file [file normalize $file]
225 | set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
226 | set_property -name "file_type" -value "VHDL" -objects $file_obj
227 |
228 | set file "$origin_dir/src/design/tlp_streamer_top.vhd"
229 | set file [file normalize $file]
230 | set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
231 | set_property -name "file_type" -value "VHDL" -objects $file_obj
232 |
233 | set file "$origin_dir/src/design/tlp_streamer_ft601.vhd"
234 | set file [file normalize $file]
235 | set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
236 | set_property -name "file_type" -value "VHDL" -objects $file_obj
237 |
238 | set file "$origin_dir/src/design/tlp_streamer_pcie.vhd"
239 | set file [file normalize $file]
240 | set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
241 | set_property -name "file_type" -value "VHDL" -objects $file_obj
242 |
243 | set file "$origin_dir/src/design/tlp_streamer_rx_dispatch.vhd"
244 | set file [file normalize $file]
245 | set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
246 | set_property -name "file_type" -value "VHDL" -objects $file_obj
247 |
248 | set file "$origin_dir/src/design/tlp_streamer_loopback.vhd"
249 | set file [file normalize $file]
250 | set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
251 | set_property -name "file_type" -value "VHDL" -objects $file_obj
252 |
253 | set file "$origin_dir/src/design/tlp_streamer_reset.vhd"
254 | set file [file normalize $file]
255 | set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
256 | set_property -name "file_type" -value "VHDL" -objects $file_obj
257 |
258 | set file "$origin_dir/src/design/tlp_streamer_tx_arbiter.vhd"
259 | set file [file normalize $file]
260 | set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
261 | set_property -name "file_type" -value "VHDL" -objects $file_obj
262 |
263 | set file "$origin_dir/src/design/tlp_streamer_pcie_tlp.vhd"
264 | set file [file normalize $file]
265 | set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
266 | set_property -name "file_type" -value "VHDL" -objects $file_obj
267 |
268 | set file "$origin_dir/src/design/tlp_streamer_pcie_cfg.vhd"
269 | set file [file normalize $file]
270 | set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
271 | set_property -name "file_type" -value "VHDL" -objects $file_obj
272 |
273 | set file "$origin_dir/ip/fifo_36_36_prim/fifo_36_36_prim.xci"
274 | set file [file normalize $file]
275 | set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
276 | set_property -name "generate_files_for_reference" -value "0" -objects $file_obj
277 | set_property -name "registered_with_manager" -value "1" -objects $file_obj
278 | if { ![get_property "is_locked" $file_obj] } {
279 | set_property -name "synth_checkpoint_mode" -value "Singular" -objects $file_obj
280 | }
281 |
282 | set file "$origin_dir/ip/fifo_32_32_bram/fifo_32_32_bram.xci"
283 | set file [file normalize $file]
284 | set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
285 | set_property -name "generate_files_for_reference" -value "0" -objects $file_obj
286 | set_property -name "registered_with_manager" -value "1" -objects $file_obj
287 | if { ![get_property "is_locked" $file_obj] } {
288 | set_property -name "synth_checkpoint_mode" -value "Singular" -objects $file_obj
289 | }
290 |
291 | set file "$origin_dir/ip/ila_0/ila_0.xci"
292 | set file [file normalize $file]
293 | set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
294 | set_property -name "generate_files_for_reference" -value "0" -objects $file_obj
295 | set_property -name "registered_with_manager" -value "1" -objects $file_obj
296 | if { ![get_property "is_locked" $file_obj] } {
297 | set_property -name "synth_checkpoint_mode" -value "Singular" -objects $file_obj
298 | }
299 |
300 | set file "$origin_dir/ip/fifo_pcie_tlp_r32_w64_4096_bram/fifo_pcie_tlp_r32_w64_4096_bram.xci"
301 | set file [file normalize $file]
302 | set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
303 | set_property -name "generate_files_for_reference" -value "0" -objects $file_obj
304 | set_property -name "registered_with_manager" -value "1" -objects $file_obj
305 | if { ![get_property "is_locked" $file_obj] } {
306 | set_property -name "synth_checkpoint_mode" -value "Singular" -objects $file_obj
307 | }
308 |
309 | set file "$origin_dir/ip/pcie_tlp_ila/pcie_tlp_ila.xci"
310 | set file [file normalize $file]
311 | set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
312 | set_property -name "generate_files_for_reference" -value "0" -objects $file_obj
313 | set_property -name "registered_with_manager" -value "1" -objects $file_obj
314 | if { ![get_property "is_locked" $file_obj] } {
315 | set_property -name "synth_checkpoint_mode" -value "Singular" -objects $file_obj
316 | }
317 |
318 | set file "$origin_dir/ip/fifo_pcie_tlp_r64_w32_4096_bram/fifo_pcie_tlp_r64_w32_4096_bram.xci"
319 | set file [file normalize $file]
320 | set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
321 | set_property -name "generate_files_for_reference" -value "0" -objects $file_obj
322 | set_property -name "registered_with_manager" -value "1" -objects $file_obj
323 | if { ![get_property "is_locked" $file_obj] } {
324 | set_property -name "synth_checkpoint_mode" -value "Singular" -objects $file_obj
325 | }
326 |
327 |
328 | # Set 'sources_1' fileset file properties for local files
329 | # None
330 |
331 | # Set 'sources_1' fileset properties
332 | set obj [get_filesets sources_1]
333 | set_property -name "top" -value "tlp_streamer" -objects $obj
334 | set_property -name "top_auto_set" -value "0" -objects $obj
335 |
336 | # Set 'sources_1' fileset object
337 | set obj [get_filesets sources_1]
338 | set files [list \
339 | [file normalize "${origin_dir}/ip/pcie_7x_0/pcie_7x_0.xci"] \
340 | ]
341 | add_files -norecurse -fileset $obj $files
342 |
343 | # Set 'sources_1' fileset file properties for remote files
344 | set file "$origin_dir/ip/pcie_7x_0/pcie_7x_0.xci"
345 | set file [file normalize $file]
346 | set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]
347 | set_property -name "generate_files_for_reference" -value "0" -objects $file_obj
348 | set_property -name "registered_with_manager" -value "1" -objects $file_obj
349 | if { ![get_property "is_locked" $file_obj] } {
350 | set_property -name "synth_checkpoint_mode" -value "Singular" -objects $file_obj
351 | }
352 |
353 |
354 | # Set 'sources_1' fileset file properties for local files
355 | # None
356 |
357 | # Create 'constrs_1' fileset (if not found)
358 | if {[string equal [get_filesets -quiet constrs_1] ""]} {
359 | create_fileset -constrset constrs_1
360 | }
361 |
362 | # Set 'constrs_1' fileset object
363 | set obj [get_filesets constrs_1]
364 |
365 | # Add/Import constrs file and set constrs file properties
366 | set file "[file normalize "$origin_dir/src/constrs/screamer_m2.xdc"]"
367 | set file_added [add_files -norecurse -fileset $obj [list $file]]
368 | set file "$origin_dir/src/constrs/screamer_m2.xdc"
369 | set file [file normalize $file]
370 | set file_obj [get_files -of_objects [get_filesets constrs_1] [list "*$file"]]
371 | set_property -name "file_type" -value "XDC" -objects $file_obj
372 |
373 | # Set 'constrs_1' fileset properties
374 | set obj [get_filesets constrs_1]
375 | set_property -name "target_constrs_file" -value "[file normalize "$origin_dir/src/constrs/screamer_m2.xdc"]" -objects $obj
376 | set_property -name "target_part" -value "xc7a35tcsg325-2" -objects $obj
377 | set_property -name "target_ucf" -value "[file normalize "$origin_dir/src/constrs/screamer_m2.xdc"]" -objects $obj
378 |
379 | # Create 'sim_1' fileset (if not found)
380 | if {[string equal [get_filesets -quiet sim_1] ""]} {
381 | create_fileset -simset sim_1
382 | }
383 |
384 | # Set 'sim_1' fileset object
385 | set obj [get_filesets sim_1]
386 | set files [list \
387 | [file normalize "${origin_dir}/src/sim/tlp_streamer_usb_rx_sim.vhd"] \
388 | [file normalize "${origin_dir}/src/sim/tlp_usb_rx_sim_behav.wcfg"] \
389 | ]
390 | add_files -norecurse -fileset $obj $files
391 |
392 | # Set 'sim_1' fileset file properties for remote files
393 | set file "$origin_dir/src/sim/tlp_streamer_usb_rx_sim.vhd"
394 | set file [file normalize $file]
395 | set file_obj [get_files -of_objects [get_filesets sim_1] [list "*$file"]]
396 | set_property -name "file_type" -value "VHDL" -objects $file_obj
397 |
398 |
399 | # Set 'sim_1' fileset file properties for local files
400 | # None
401 |
402 | # Set 'sim_1' fileset properties
403 | set obj [get_filesets sim_1]
404 | set_property -name "hbs.configure_design_for_hier_access" -value "1" -objects $obj
405 | set_property -name "top" -value "tlp_usb_rx_sim" -objects $obj
406 | set_property -name "top_auto_set" -value "0" -objects $obj
407 | set_property -name "top_lib" -value "xil_defaultlib" -objects $obj
408 | set_property -name "xsim.simulate.log_all_signals" -value "1" -objects $obj
409 | set_property -name "xsim.simulate.runtime" -value "1500" -objects $obj
410 |
411 | # Set 'utils_1' fileset object
412 | set obj [get_filesets utils_1]
413 | # Empty (no sources present)
414 |
415 | # Set 'utils_1' fileset properties
416 | set obj [get_filesets utils_1]
417 |
418 | # Create 'synth_1' run (if not found)
419 | if {[string equal [get_runs -quiet synth_1] ""]} {
420 | create_run -name synth_1 -part xc7a35tcsg325-2 -flow {Vivado Synthesis 2020} -strategy "Vivado Synthesis Defaults" -report_strategy {No Reports} -constrset constrs_1
421 | } else {
422 | set_property strategy "Vivado Synthesis Defaults" [get_runs synth_1]
423 | set_property flow "Vivado Synthesis 2020" [get_runs synth_1]
424 | }
425 | set obj [get_runs synth_1]
426 | set_property set_report_strategy_name 1 $obj
427 | set_property report_strategy {Vivado Synthesis Default Reports} $obj
428 | set_property set_report_strategy_name 0 $obj
429 | # Create 'synth_1_synth_report_utilization_0' report (if not found)
430 | if { [ string equal [get_report_configs -of_objects [get_runs synth_1] synth_1_synth_report_utilization_0] "" ] } {
431 | create_report_config -report_name synth_1_synth_report_utilization_0 -report_type report_utilization:1.0 -steps synth_design -runs synth_1
432 | }
433 | set obj [get_report_configs -of_objects [get_runs synth_1] synth_1_synth_report_utilization_0]
434 | if { $obj != "" } {
435 |
436 | }
437 | set obj [get_runs synth_1]
438 | set_property -name "needs_refresh" -value "1" -objects $obj
439 | set_property -name "part" -value "xc7a35tcsg325-2" -objects $obj
440 | set_property -name "strategy" -value "Vivado Synthesis Defaults" -objects $obj
441 | set_property -name "steps.synth_design.args.fsm_extraction" -value "one_hot" -objects $obj
442 | set_property -name "steps.synth_design.args.keep_equivalent_registers" -value "1" -objects $obj
443 |
444 | # set the current synth run
445 | current_run -synthesis [get_runs synth_1]
446 |
447 | # Create 'impl_1' run (if not found)
448 | if {[string equal [get_runs -quiet impl_1] ""]} {
449 | create_run -name impl_1 -part xc7a35tcsg325-2 -flow {Vivado Implementation 2020} -strategy "Vivado Implementation Defaults" -report_strategy {No Reports} -constrset constrs_1 -parent_run synth_1
450 | } else {
451 | set_property strategy "Vivado Implementation Defaults" [get_runs impl_1]
452 | set_property flow "Vivado Implementation 2020" [get_runs impl_1]
453 | }
454 | set obj [get_runs impl_1]
455 | set_property set_report_strategy_name 1 $obj
456 | set_property report_strategy {Vivado Implementation Default Reports} $obj
457 | set_property set_report_strategy_name 0 $obj
458 | # Create 'impl_1_init_report_timing_summary_0' report (if not found)
459 | if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_init_report_timing_summary_0] "" ] } {
460 | create_report_config -report_name impl_1_init_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps init_design -runs impl_1
461 | }
462 | set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_init_report_timing_summary_0]
463 | if { $obj != "" } {
464 | set_property -name "is_enabled" -value "0" -objects $obj
465 | set_property -name "options.max_paths" -value "10" -objects $obj
466 |
467 | }
468 | # Create 'impl_1_opt_report_drc_0' report (if not found)
469 | if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_opt_report_drc_0] "" ] } {
470 | create_report_config -report_name impl_1_opt_report_drc_0 -report_type report_drc:1.0 -steps opt_design -runs impl_1
471 | }
472 | set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_opt_report_drc_0]
473 | if { $obj != "" } {
474 |
475 | }
476 | # Create 'impl_1_opt_report_timing_summary_0' report (if not found)
477 | if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_opt_report_timing_summary_0] "" ] } {
478 | create_report_config -report_name impl_1_opt_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps opt_design -runs impl_1
479 | }
480 | set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_opt_report_timing_summary_0]
481 | if { $obj != "" } {
482 | set_property -name "is_enabled" -value "0" -objects $obj
483 | set_property -name "options.max_paths" -value "10" -objects $obj
484 |
485 | }
486 | # Create 'impl_1_power_opt_report_timing_summary_0' report (if not found)
487 | if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_power_opt_report_timing_summary_0] "" ] } {
488 | create_report_config -report_name impl_1_power_opt_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps power_opt_design -runs impl_1
489 | }
490 | set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_power_opt_report_timing_summary_0]
491 | if { $obj != "" } {
492 | set_property -name "is_enabled" -value "0" -objects $obj
493 | set_property -name "options.max_paths" -value "10" -objects $obj
494 |
495 | }
496 | # Create 'impl_1_place_report_io_0' report (if not found)
497 | if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_io_0] "" ] } {
498 | create_report_config -report_name impl_1_place_report_io_0 -report_type report_io:1.0 -steps place_design -runs impl_1
499 | }
500 | set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_io_0]
501 | if { $obj != "" } {
502 |
503 | }
504 | # Create 'impl_1_place_report_utilization_0' report (if not found)
505 | if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_utilization_0] "" ] } {
506 | create_report_config -report_name impl_1_place_report_utilization_0 -report_type report_utilization:1.0 -steps place_design -runs impl_1
507 | }
508 | set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_utilization_0]
509 | if { $obj != "" } {
510 |
511 | }
512 | # Create 'impl_1_place_report_control_sets_0' report (if not found)
513 | if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_control_sets_0] "" ] } {
514 | create_report_config -report_name impl_1_place_report_control_sets_0 -report_type report_control_sets:1.0 -steps place_design -runs impl_1
515 | }
516 | set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_control_sets_0]
517 | if { $obj != "" } {
518 | set_property -name "options.verbose" -value "1" -objects $obj
519 |
520 | }
521 | # Create 'impl_1_place_report_incremental_reuse_0' report (if not found)
522 | if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_incremental_reuse_0] "" ] } {
523 | create_report_config -report_name impl_1_place_report_incremental_reuse_0 -report_type report_incremental_reuse:1.0 -steps place_design -runs impl_1
524 | }
525 | set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_incremental_reuse_0]
526 | if { $obj != "" } {
527 | set_property -name "is_enabled" -value "0" -objects $obj
528 |
529 | }
530 | # Create 'impl_1_place_report_incremental_reuse_1' report (if not found)
531 | if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_incremental_reuse_1] "" ] } {
532 | create_report_config -report_name impl_1_place_report_incremental_reuse_1 -report_type report_incremental_reuse:1.0 -steps place_design -runs impl_1
533 | }
534 | set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_incremental_reuse_1]
535 | if { $obj != "" } {
536 | set_property -name "is_enabled" -value "0" -objects $obj
537 |
538 | }
539 | # Create 'impl_1_place_report_timing_summary_0' report (if not found)
540 | if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_timing_summary_0] "" ] } {
541 | create_report_config -report_name impl_1_place_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps place_design -runs impl_1
542 | }
543 | set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_place_report_timing_summary_0]
544 | if { $obj != "" } {
545 | set_property -name "is_enabled" -value "0" -objects $obj
546 | set_property -name "options.max_paths" -value "10" -objects $obj
547 |
548 | }
549 | # Create 'impl_1_post_place_power_opt_report_timing_summary_0' report (if not found)
550 | if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_post_place_power_opt_report_timing_summary_0] "" ] } {
551 | create_report_config -report_name impl_1_post_place_power_opt_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps post_place_power_opt_design -runs impl_1
552 | }
553 | set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_post_place_power_opt_report_timing_summary_0]
554 | if { $obj != "" } {
555 | set_property -name "is_enabled" -value "0" -objects $obj
556 | set_property -name "options.max_paths" -value "10" -objects $obj
557 |
558 | }
559 | # Create 'impl_1_phys_opt_report_timing_summary_0' report (if not found)
560 | if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_phys_opt_report_timing_summary_0] "" ] } {
561 | create_report_config -report_name impl_1_phys_opt_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps phys_opt_design -runs impl_1
562 | }
563 | set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_phys_opt_report_timing_summary_0]
564 | if { $obj != "" } {
565 | set_property -name "is_enabled" -value "0" -objects $obj
566 | set_property -name "options.max_paths" -value "10" -objects $obj
567 |
568 | }
569 | # Create 'impl_1_route_report_drc_0' report (if not found)
570 | if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_drc_0] "" ] } {
571 | create_report_config -report_name impl_1_route_report_drc_0 -report_type report_drc:1.0 -steps route_design -runs impl_1
572 | }
573 | set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_drc_0]
574 | if { $obj != "" } {
575 |
576 | }
577 | # Create 'impl_1_route_report_methodology_0' report (if not found)
578 | if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_methodology_0] "" ] } {
579 | create_report_config -report_name impl_1_route_report_methodology_0 -report_type report_methodology:1.0 -steps route_design -runs impl_1
580 | }
581 | set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_methodology_0]
582 | if { $obj != "" } {
583 |
584 | }
585 | # Create 'impl_1_route_report_power_0' report (if not found)
586 | if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_power_0] "" ] } {
587 | create_report_config -report_name impl_1_route_report_power_0 -report_type report_power:1.0 -steps route_design -runs impl_1
588 | }
589 | set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_power_0]
590 | if { $obj != "" } {
591 |
592 | }
593 | # Create 'impl_1_route_report_route_status_0' report (if not found)
594 | if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_route_status_0] "" ] } {
595 | create_report_config -report_name impl_1_route_report_route_status_0 -report_type report_route_status:1.0 -steps route_design -runs impl_1
596 | }
597 | set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_route_status_0]
598 | if { $obj != "" } {
599 |
600 | }
601 | # Create 'impl_1_route_report_timing_summary_0' report (if not found)
602 | if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_timing_summary_0] "" ] } {
603 | create_report_config -report_name impl_1_route_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps route_design -runs impl_1
604 | }
605 | set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_timing_summary_0]
606 | if { $obj != "" } {
607 | set_property -name "options.max_paths" -value "10" -objects $obj
608 |
609 | }
610 | # Create 'impl_1_route_report_incremental_reuse_0' report (if not found)
611 | if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_incremental_reuse_0] "" ] } {
612 | create_report_config -report_name impl_1_route_report_incremental_reuse_0 -report_type report_incremental_reuse:1.0 -steps route_design -runs impl_1
613 | }
614 | set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_incremental_reuse_0]
615 | if { $obj != "" } {
616 |
617 | }
618 | # Create 'impl_1_route_report_clock_utilization_0' report (if not found)
619 | if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_clock_utilization_0] "" ] } {
620 | create_report_config -report_name impl_1_route_report_clock_utilization_0 -report_type report_clock_utilization:1.0 -steps route_design -runs impl_1
621 | }
622 | set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_clock_utilization_0]
623 | if { $obj != "" } {
624 |
625 | }
626 | # Create 'impl_1_route_report_bus_skew_0' report (if not found)
627 | if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_bus_skew_0] "" ] } {
628 | create_report_config -report_name impl_1_route_report_bus_skew_0 -report_type report_bus_skew:1.1 -steps route_design -runs impl_1
629 | }
630 | set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_route_report_bus_skew_0]
631 | if { $obj != "" } {
632 | set_property -name "options.warn_on_violation" -value "1" -objects $obj
633 |
634 | }
635 | # Create 'impl_1_post_route_phys_opt_report_timing_summary_0' report (if not found)
636 | if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_post_route_phys_opt_report_timing_summary_0] "" ] } {
637 | create_report_config -report_name impl_1_post_route_phys_opt_report_timing_summary_0 -report_type report_timing_summary:1.0 -steps post_route_phys_opt_design -runs impl_1
638 | }
639 | set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_post_route_phys_opt_report_timing_summary_0]
640 | if { $obj != "" } {
641 | set_property -name "options.max_paths" -value "10" -objects $obj
642 | set_property -name "options.warn_on_violation" -value "1" -objects $obj
643 |
644 | }
645 | # Create 'impl_1_post_route_phys_opt_report_bus_skew_0' report (if not found)
646 | if { [ string equal [get_report_configs -of_objects [get_runs impl_1] impl_1_post_route_phys_opt_report_bus_skew_0] "" ] } {
647 | create_report_config -report_name impl_1_post_route_phys_opt_report_bus_skew_0 -report_type report_bus_skew:1.1 -steps post_route_phys_opt_design -runs impl_1
648 | }
649 | set obj [get_report_configs -of_objects [get_runs impl_1] impl_1_post_route_phys_opt_report_bus_skew_0]
650 | if { $obj != "" } {
651 | set_property -name "options.warn_on_violation" -value "1" -objects $obj
652 |
653 | }
654 | set obj [get_runs impl_1]
655 | set_property -name "needs_refresh" -value "1" -objects $obj
656 | set_property -name "part" -value "xc7a35tcsg325-2" -objects $obj
657 | set_property -name "strategy" -value "Vivado Implementation Defaults" -objects $obj
658 | set_property -name "steps.place_design.args.directive" -value "ExtraTimingOpt" -objects $obj
659 | set_property -name "steps.write_bitstream.args.bin_file" -value "1" -objects $obj
660 | set_property -name "steps.write_bitstream.args.readback_file" -value "0" -objects $obj
661 | set_property -name "steps.write_bitstream.args.verbose" -value "0" -objects $obj
662 |
663 | # set the current impl run
664 | current_run -implementation [get_runs impl_1]
665 |
666 | puts "INFO: Project created:${_xil_proj_name_}"
667 | # Create 'drc_1' gadget (if not found)
668 | if {[string equal [get_dashboard_gadgets [ list "drc_1" ] ] ""]} {
669 | create_dashboard_gadget -name {drc_1} -type drc
670 | }
671 | set obj [get_dashboard_gadgets [ list "drc_1" ] ]
672 | set_property -name "reports" -value "impl_1#impl_1_route_report_drc_0" -objects $obj
673 |
674 | # Create 'methodology_1' gadget (if not found)
675 | if {[string equal [get_dashboard_gadgets [ list "methodology_1" ] ] ""]} {
676 | create_dashboard_gadget -name {methodology_1} -type methodology
677 | }
678 | set obj [get_dashboard_gadgets [ list "methodology_1" ] ]
679 | set_property -name "reports" -value "impl_1#impl_1_route_report_methodology_0" -objects $obj
680 |
681 | # Create 'power_1' gadget (if not found)
682 | if {[string equal [get_dashboard_gadgets [ list "power_1" ] ] ""]} {
683 | create_dashboard_gadget -name {power_1} -type power
684 | }
685 | set obj [get_dashboard_gadgets [ list "power_1" ] ]
686 | set_property -name "reports" -value "impl_1#impl_1_route_report_power_0" -objects $obj
687 |
688 | # Create 'timing_1' gadget (if not found)
689 | if {[string equal [get_dashboard_gadgets [ list "timing_1" ] ] ""]} {
690 | create_dashboard_gadget -name {timing_1} -type timing
691 | }
692 | set obj [get_dashboard_gadgets [ list "timing_1" ] ]
693 | set_property -name "reports" -value "impl_1#impl_1_route_report_timing_summary_0" -objects $obj
694 |
695 | # Create 'utilization_1' gadget (if not found)
696 | if {[string equal [get_dashboard_gadgets [ list "utilization_1" ] ] ""]} {
697 | create_dashboard_gadget -name {utilization_1} -type utilization
698 | }
699 | set obj [get_dashboard_gadgets [ list "utilization_1" ] ]
700 | set_property -name "reports" -value "synth_1#synth_1_synth_report_utilization_0" -objects $obj
701 | set_property -name "run.step" -value "synth_design" -objects $obj
702 | set_property -name "run.type" -value "synthesis" -objects $obj
703 |
704 | # Create 'utilization_2' gadget (if not found)
705 | if {[string equal [get_dashboard_gadgets [ list "utilization_2" ] ] ""]} {
706 | create_dashboard_gadget -name {utilization_2} -type utilization
707 | }
708 | set obj [get_dashboard_gadgets [ list "utilization_2" ] ]
709 | set_property -name "reports" -value "impl_1#impl_1_place_report_utilization_0" -objects $obj
710 |
711 | move_dashboard_gadget -name {utilization_1} -row 0 -col 0
712 | move_dashboard_gadget -name {power_1} -row 1 -col 0
713 | move_dashboard_gadget -name {drc_1} -row 2 -col 0
714 | move_dashboard_gadget -name {timing_1} -row 0 -col 1
715 | move_dashboard_gadget -name {utilization_2} -row 1 -col 1
716 | move_dashboard_gadget -name {methodology_1} -row 2 -col 1
717 |
--------------------------------------------------------------------------------