├── README.md ├── pcie_7x ├── src ├── 75immt.xdc ├── pcileech_captain_75T.xdc ├── pcileech_com.sv ├── pcileech_com_e.v ├── pcileech_enigma_x1.xdc ├── pcileech_enigma_x1_top.sv ├── pcileech_fifo.sv ├── pcileech_ft601.sv ├── pcileech_header.svh ├── pcileech_mux.sv ├── pcileech_pcie_a7.sv ├── pcileech_pcie_a7x4.sv ├── pcileech_pcie_cfg_a7.sv ├── pcileech_pcie_cfgspace_shadow.sv ├── pcileech_pcie_tlp_a7.sv ├── pcileech_screamer_m2.xdc ├── pcileech_screamer_m2_top.sv ├── pcileech_squirrel.xdc ├── pcileech_squirrel_top.sv ├── pcileech_tbx4_100t.xdc ├── pcileech_tbx4_100t_top.sv ├── pcileech_tlps128_bar_controller.sv └── pcileech_tlps128_cfgspace_shadow.sv ├── vivado_build.tcl ├── vivado_build_100t.tcl ├── vivado_generate_project_100t.tcl ├── vivado_generate_project_captain_75T.tcl ├── vivado_generate_project_enigma_x1.tcl ├── vivado_generate_project_immortal_75T.tcl ├── vivado_generate_project_immortal_75Ts.tcl ├── vivado_generate_project_m2.tcl └── vivado_generate_project_squirrel.tcl /README.md: -------------------------------------------------------------------------------- 1 | ## **💡 Current Status** 2 | 3 | The **network card firmware** has been patched by **ACE** and is no longer functional in its original state. 4 | The purpose of open-sourcing this firmware is to **accelerate learning** and provide insights into this project. 5 | 6 | By sharing this resource, we aim to foster a deeper understanding and enable developers to explore and innovate further. 7 | Remember, this is for educational and research purposes—let's build a better community together! 8 | 9 | ## **🔧 Focus Areas** 10 | 11 | Our primary focus is on **media cards**, **sound cards**, and **hard drives**. 12 | Due to the nature of these devices, we have decided **not to open-source them**. 13 | 14 | If you are interested in discussing these technologies or joining our community, feel free to connect with us on **Discord**: 15 | 16 | 17 | ## ⚠️ About TLP Interrupts 18 | 19 | The TLP interrupt mechanism requires proper echoing with the computer motherboard. This project was developed specifically for **ASUS motherboards**, ensuring compatibility. However, many individuals who have **stolen this project** fail to adapt the kernel interrupts for other systems. As a result, users might experience issues such as **blue screens** or other errors due to these unaddressed compatibility problems. These individuals often mislead users into switching to specific motherboards instead of resolving the underlying issues, highlighting their lack of technical expertise. 20 | 21 | While **network card firmware technology is outdated**, some developers continue to sell it at **high prices**, exploiting users who may not know better. Our decision to open-source this technology has disrupted many fraudulent developers, leading to retaliation instead of constructive improvements on their part. We believe that true developers should focus on **learning, innovating**, and solving compatibility challenges rather than deceiving customers or charging unreasonable fees. 22 | 23 | ## ⚠️ Important Update on Network Card Firmware 24 | 25 | ACE has now marked all **Intel** and **Realtek** series network cards. In the future, **network card firmware** will be fully detected. Scammers who are exploiting our open-source technology will soon be exposed. 26 | 27 | ### Why We Open-Sourced This Project 28 | The primary purpose of open-sourcing this project was to **counter the exploitation of our work**. By making the technology publicly available, we ensure that **malicious users** cannot hide behind our creations and resell them unlawfully. 29 | 30 | We will continue to monitor and update the firmware to stay ahead of these attempts. 31 | 32 | Thank you for your continued support. 33 | 34 | **Purpose of Open Source**: Following a leak by a customer, the firmware became widely distributed and resold. To address this, it has been made public. 35 | 36 | Note that once exposed, anti-cheat systems will likely detect the firmware's space, which may limit its future usability. 37 | 38 | We are not working with any developers and any mention of us is false! 39 | 40 | ## Caution Against Scammers 41 | 42 | Currently, there are many fake users cloning this open-source library and using our information to deceive others. 43 | 44 | **Devices for Full Emulation**: Killer series network cards. 45 | 46 | **New Update**: We have modified a new IP core to support the detection of Delta games. 47 | 48 | **Want to share your insights or seek assistance?** 49 | 50 | > ⚠️ **Note to Malicious Attackers and Troublemakers** 51 | > Please refrain from joining our group. We do not welcome individuals who intend to misuse our free resources for resale purposes. Such members will be removed from the community 52 | 53 | ### Open Access to Network Card DMA Firmware 54 | ACE has recently restricted many RTL-type devices, including network card DMA firmware. Importantly, this technology has become **publicly accessible**, allowing anyone with basic technical knowledge to quickly learn and create it. As a result, prices for these firmware solutions remain relatively affordable, generally within the **100-180 USD** range. This applies to both Killer cards and other models, so prices should not vary significantly. 55 | 56 | ### Recognizing False Claims and High-Price Tactics 57 | Some individuals may attempt to mislead new players by claiming that open-source network card devices, often with additional modifications, are exclusive "internal" products. They may also assert that their versions are unique or private. 58 | 59 | - **Unique Firmware:** ACE is likely to soon gather data on all such devices. Each firmware version requires unique encoding, ensuring distinct versions for each user. 60 | - **Open and Accessible Technology:** With the right emulation skills, anyone can achieve stability and reliability in these devices. 61 | There is no "private" firmware—only **thousands of lines of code** accessible to those who seek it. 62 | 63 | 64 | ### Scam Alert 65 | If you’ve paid **300 USD** for network card emulation firmware, there’s a strong chance you’ve been overcharged, as this technology is now widely accessible. 66 | 67 | **Devices for Full Emulation**: Killer series network cards. 68 | 69 | -------------------------------------------------------------------------------- /pcie_7x: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/75immt.xdc: -------------------------------------------------------------------------------- 1 | set_property PACKAGE_PIN V20 [get_ports ft601_be[0]] 2 | set_property PACKAGE_PIN V19 [get_ports ft601_be[1]] 3 | set_property PACKAGE_PIN W20 [get_ports ft601_be[2]] 4 | set_property PACKAGE_PIN AB20 [get_ports ft601_be[3]] 5 | set_property PACKAGE_PIN H20 [get_ports ft601_data[0]] 6 | set_property PACKAGE_PIN H22 [get_ports ft601_data[1]] 7 | set_property PACKAGE_PIN J21 [get_ports ft601_data[2]] 8 | set_property PACKAGE_PIN J22 [get_ports ft601_data[3]] 9 | set_property PACKAGE_PIN K21 [get_ports ft601_data[4]] 10 | set_property PACKAGE_PIN K22 [get_ports ft601_data[5]] 11 | set_property PACKAGE_PIN L21 [get_ports ft601_data[6]] 12 | set_property PACKAGE_PIN N18 [get_ports ft601_data[7]] 13 | set_property PACKAGE_PIN M18 [get_ports ft601_data[8]] 14 | set_property PACKAGE_PIN L20 [get_ports ft601_data[9]] 15 | set_property PACKAGE_PIN L19 [get_ports ft601_data[10]] 16 | set_property PACKAGE_PIN M20 [get_ports ft601_data[11]] 17 | set_property PACKAGE_PIN M22 [get_ports ft601_data[12]] 18 | set_property PACKAGE_PIN M21 [get_ports ft601_data[13]] 19 | set_property PACKAGE_PIN N22 [get_ports ft601_data[14]] 20 | set_property PACKAGE_PIN N20 [get_ports ft601_data[15]] 21 | set_property PACKAGE_PIN P15 [get_ports ft601_data[16]] 22 | set_property PACKAGE_PIN T21 [get_ports ft601_data[17]] 23 | set_property PACKAGE_PIN R16 [get_ports ft601_data[18]] 24 | # OLD ft601_data[19] 25 | set_property PACKAGE_PIN T20 [get_ports ft601_data[19]] 26 | 27 | set_property PACKAGE_PIN U17 [get_ports ft601_data[20]] 28 | set_property PACKAGE_PIN U20 [get_ports ft601_data[21]] 29 | set_property PACKAGE_PIN U21 [get_ports ft601_data[22]] 30 | set_property PACKAGE_PIN V22 [get_ports ft601_data[23]] 31 | set_property PACKAGE_PIN W22 [get_ports ft601_data[24]] 32 | set_property PACKAGE_PIN W21 [get_ports ft601_data[25]] 33 | set_property PACKAGE_PIN Y22 [get_ports ft601_data[26]] 34 | set_property PACKAGE_PIN Y21 [get_ports ft601_data[27]] 35 | set_property PACKAGE_PIN AB22 [get_ports ft601_data[28]] 36 | set_property PACKAGE_PIN AA21 [get_ports ft601_data[29]] 37 | set_property PACKAGE_PIN AB21 [get_ports ft601_data[30]] 38 | set_property PACKAGE_PIN AA20 [get_ports ft601_data[31]] 39 | set_property PACKAGE_PIN W17 [get_ports ft601_oe_n] 40 | set_property PACKAGE_PIN P16 [get_ports ft601_rd_n] 41 | set_property PACKAGE_PIN AA18 [get_ports ft601_rxf_n] 42 | set_property PACKAGE_PIN AB18 [get_ports ft601_siwu_n] 43 | set_property PACKAGE_PIN AA19 [get_ports ft601_txe_n] 44 | set_property PACKAGE_PIN W19 [get_ports ft601_wr_n] 45 | set_property PACKAGE_PIN N13 [get_ports ft601_rst_n] 46 | set_property IOSTANDARD LVCMOS33 [get_ports {ft601_txe_n ft601_rxf_n}] 47 | set_property IOSTANDARD LVCMOS33 [get_ports {{ft601_be[*]} {ft601_data[*]}}] 48 | set_property IOSTANDARD LVCMOS33 [get_ports {ft601_wr_n ft601_rd_n ft601_oe_n ft601_siwu_n ft601_rst_n}] 49 | set_property SLEW FAST [get_ports {{ft601_be[*]} {ft601_data[*]}}] 50 | set_property SLEW FAST [get_ports {ft601_wr_n ft601_rd_n ft601_oe_n ft601_siwu_n ft601_rst_n}] 51 | 52 | set_property PACKAGE_PIN G21 [get_ports user_ld1_n] 53 | set_property PACKAGE_PIN G22 [get_ports user_ld2_n] 54 | set_property PACKAGE_PIN F19 [get_ports user_sw1_n] 55 | set_property PACKAGE_PIN F20 [get_ports user_sw2_n] 56 | set_property IOSTANDARD LVCMOS33 [get_ports {user_ld1_n user_ld2_n user_sw1_n user_sw2_n}] 57 | 58 | # SYSCLK 59 | set_property PACKAGE_PIN J19 [get_ports clk] 60 | set_property IOSTANDARD LVCMOS33 [get_ports clk] 61 | create_clock -period 10.000 -name net_clk -waveform {0.000 5.000} [get_ports clk] 62 | 63 | # FT601 CLK 64 | create_clock -period 10.000 -name net_ft601_clk -waveform {0.000 5.000} [get_ports ft601_clk] 65 | set_property IOSTANDARD LVCMOS33 [get_ports ft601_clk] 66 | set_property PACKAGE_PIN K18 [get_ports ft601_clk] 67 | 68 | set_input_delay -clock [get_clocks net_ft601_clk] -min 6.5 [get_ports {ft601_data[*]}] 69 | set_input_delay -clock [get_clocks net_ft601_clk] -max 7.0 [get_ports {ft601_data[*]}] 70 | set_input_delay -clock [get_clocks net_ft601_clk] -min 6.5 [get_ports ft601_rxf_n] 71 | set_input_delay -clock [get_clocks net_ft601_clk] -max 7.0 [get_ports ft601_rxf_n] 72 | set_input_delay -clock [get_clocks net_ft601_clk] -min 6.5 [get_ports ft601_txe_n] 73 | set_input_delay -clock [get_clocks net_ft601_clk] -max 7.0 [get_ports ft601_txe_n] 74 | 75 | set_output_delay -clock [get_clocks net_ft601_clk] -max 1.0 [get_ports {ft601_wr_n ft601_rd_n ft601_oe_n}] 76 | set_output_delay -clock [get_clocks net_ft601_clk] -min 4.8 [get_ports {ft601_wr_n ft601_rd_n ft601_oe_n}] 77 | set_output_delay -clock [get_clocks net_ft601_clk] -max 1.0 [get_ports {{ft601_be[*]} {ft601_data[*]}}] 78 | set_output_delay -clock [get_clocks net_ft601_clk] -min 4.8 [get_ports {{ft601_be[*]} {ft601_data[*]}}] 79 | 80 | set_property IOB TRUE [get_cells i_pcileech_com/i_pcileech_ft601/FT601_OE_N_reg] 81 | set_property IOB TRUE [get_cells i_pcileech_com/i_pcileech_ft601/FT601_RD_N_reg] 82 | set_property IOB TRUE [get_cells i_pcileech_com/i_pcileech_ft601/FT601_WR_N_reg] 83 | set_property IOB TRUE [get_cells i_pcileech_com/i_pcileech_ft601/txo_dout_reg[*]] 84 | 85 | set_multicycle_path 2 -from [get_pins i_pcileech_com/i_pcileech_ft601/oe_reg/C] -to [get_ports {{ft601_be[*]} {ft601_data[*]}}] 86 | set_false_path -from [get_pins {tickcount64_reg[*]/C}] 87 | set_false_path -from [get_pins {i_pcileech_fifo/_pcie_core_config_reg[*]/C}] 88 | 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}] 89 | set_false_path -from [get_pins i_pcileech_pcie_a7/i_pcie_7x_0/inst/inst/user_reset_out_reg/C] 90 | 91 | #PCIe signals 92 | set_property PACKAGE_PIN A13 [get_ports pcie_present] 93 | set_property PACKAGE_PIN C13 [get_ports pcie_perst_n] 94 | set_property PACKAGE_PIN B13 [get_ports pcie_wake_n] 95 | set_property IOSTANDARD LVCMOS33 [get_ports pcie_present] 96 | set_property IOSTANDARD LVCMOS33 [get_ports pcie_perst_n] 97 | set_property IOSTANDARD LVCMOS33 [get_ports pcie_wake_n] 98 | 99 | set_property PACKAGE_PIN C9 [get_ports {pcie_rx_n[0]}] 100 | set_property PACKAGE_PIN D9 [get_ports {pcie_rx_p[0]}] 101 | set_property PACKAGE_PIN C7 [get_ports {pcie_tx_n[0]}] 102 | set_property PACKAGE_PIN D7 [get_ports {pcie_tx_p[0]}] 103 | 104 | set_property PACKAGE_PIN E10 [get_ports pcie_clk_n] 105 | set_property PACKAGE_PIN F10 [get_ports pcie_clk_p] 106 | 107 | create_clock -name pcie_sys_clk_p -period 10.0 [get_nets pcie_clk_p] 108 | 109 | set_property CFGBVS Vcco [current_design] 110 | set_property CONFIG_VOLTAGE 3.3 [current_design] 111 | set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design] 112 | set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design] 113 | set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES [current_design] 114 | set_property BITSTREAM.CONFIG.CONFIGRATE 66 [current_design] -------------------------------------------------------------------------------- /src/pcileech_captain_75T.xdc: -------------------------------------------------------------------------------- 1 | set_property PACKAGE_PIN V20 [get_ports ft601_be[0]] 2 | set_property PACKAGE_PIN V19 [get_ports ft601_be[1]] 3 | set_property PACKAGE_PIN W20 [get_ports ft601_be[2]] 4 | set_property PACKAGE_PIN AB20 [get_ports ft601_be[3]] 5 | set_property PACKAGE_PIN H20 [get_ports ft601_data[0]] 6 | set_property PACKAGE_PIN H22 [get_ports ft601_data[1]] 7 | set_property PACKAGE_PIN J21 [get_ports ft601_data[2]] 8 | set_property PACKAGE_PIN J22 [get_ports ft601_data[3]] 9 | set_property PACKAGE_PIN K21 [get_ports ft601_data[4]] 10 | set_property PACKAGE_PIN K22 [get_ports ft601_data[5]] 11 | set_property PACKAGE_PIN L21 [get_ports ft601_data[6]] 12 | set_property PACKAGE_PIN N18 [get_ports ft601_data[7]] 13 | set_property PACKAGE_PIN M18 [get_ports ft601_data[8]] 14 | set_property PACKAGE_PIN L20 [get_ports ft601_data[9]] 15 | set_property PACKAGE_PIN L19 [get_ports ft601_data[10]] 16 | set_property PACKAGE_PIN M20 [get_ports ft601_data[11]] 17 | set_property PACKAGE_PIN M22 [get_ports ft601_data[12]] 18 | set_property PACKAGE_PIN M21 [get_ports ft601_data[13]] 19 | set_property PACKAGE_PIN N22 [get_ports ft601_data[14]] 20 | set_property PACKAGE_PIN N20 [get_ports ft601_data[15]] 21 | set_property PACKAGE_PIN P15 [get_ports ft601_data[16]] 22 | set_property PACKAGE_PIN T21 [get_ports ft601_data[17]] 23 | set_property PACKAGE_PIN R16 [get_ports ft601_data[18]] 24 | # OLD ft601_data[19] 25 | set_property PACKAGE_PIN T20 [get_ports ft601_data[19]] 26 | # NEW ft601_data[19] 27 | # set_property PACKAGE_PIN T18 [get_ports ft601_data[19]] 28 | set_property PACKAGE_PIN U17 [get_ports ft601_data[20]] 29 | set_property PACKAGE_PIN U20 [get_ports ft601_data[21]] 30 | set_property PACKAGE_PIN U21 [get_ports ft601_data[22]] 31 | set_property PACKAGE_PIN V22 [get_ports ft601_data[23]] 32 | set_property PACKAGE_PIN W22 [get_ports ft601_data[24]] 33 | set_property PACKAGE_PIN W21 [get_ports ft601_data[25]] 34 | set_property PACKAGE_PIN Y22 [get_ports ft601_data[26]] 35 | set_property PACKAGE_PIN Y21 [get_ports ft601_data[27]] 36 | set_property PACKAGE_PIN AB22 [get_ports ft601_data[28]] 37 | set_property PACKAGE_PIN AA21 [get_ports ft601_data[29]] 38 | set_property PACKAGE_PIN AB21 [get_ports ft601_data[30]] 39 | set_property PACKAGE_PIN AA20 [get_ports ft601_data[31]] 40 | set_property PACKAGE_PIN W17 [get_ports ft601_oe_n] 41 | set_property PACKAGE_PIN P16 [get_ports ft601_rd_n] 42 | set_property PACKAGE_PIN AA18 [get_ports ft601_rxf_n] 43 | set_property PACKAGE_PIN AB18 [get_ports ft601_siwu_n] 44 | set_property PACKAGE_PIN AA19 [get_ports ft601_txe_n] 45 | set_property PACKAGE_PIN W19 [get_ports ft601_wr_n] 46 | set_property PACKAGE_PIN N13 [get_ports ft601_rst_n] 47 | set_property IOSTANDARD LVCMOS33 [get_ports {ft601_txe_n ft601_rxf_n}] 48 | set_property IOSTANDARD LVCMOS33 [get_ports {{ft601_be[*]} {ft601_data[*]}}] 49 | set_property IOSTANDARD LVCMOS33 [get_ports {ft601_wr_n ft601_rd_n ft601_oe_n ft601_siwu_n ft601_rst_n}] 50 | set_property SLEW FAST [get_ports {{ft601_be[*]} {ft601_data[*]}}] 51 | set_property SLEW FAST [get_ports {ft601_wr_n ft601_rd_n ft601_oe_n ft601_siwu_n ft601_rst_n}] 52 | 53 | set_property PACKAGE_PIN G21 [get_ports user_ld1_n] 54 | set_property PACKAGE_PIN G22 [get_ports user_ld2_n] 55 | set_property PACKAGE_PIN F19 [get_ports user_sw1_n] 56 | set_property PACKAGE_PIN F20 [get_ports user_sw2_n] 57 | set_property IOSTANDARD LVCMOS33 [get_ports {user_ld1_n user_ld2_n user_sw1_n user_sw2_n}] 58 | 59 | # SYSCLK 60 | set_property PACKAGE_PIN J19 [get_ports clk] 61 | set_property IOSTANDARD LVCMOS33 [get_ports clk] 62 | create_clock -period 10.000 -name net_clk -waveform {0.000 5.000} [get_ports clk] 63 | 64 | # FT601 CLK 65 | create_clock -period 10.000 -name net_ft601_clk -waveform {0.000 5.000} [get_ports ft601_clk] 66 | set_property IOSTANDARD LVCMOS33 [get_ports ft601_clk] 67 | set_property PACKAGE_PIN K18 [get_ports ft601_clk] 68 | 69 | set_input_delay -clock [get_clocks net_ft601_clk] -min 6.5 [get_ports {ft601_data[*]}] 70 | set_input_delay -clock [get_clocks net_ft601_clk] -max 7.0 [get_ports {ft601_data[*]}] 71 | set_input_delay -clock [get_clocks net_ft601_clk] -min 6.5 [get_ports ft601_rxf_n] 72 | set_input_delay -clock [get_clocks net_ft601_clk] -max 7.0 [get_ports ft601_rxf_n] 73 | set_input_delay -clock [get_clocks net_ft601_clk] -min 6.5 [get_ports ft601_txe_n] 74 | set_input_delay -clock [get_clocks net_ft601_clk] -max 7.0 [get_ports ft601_txe_n] 75 | 76 | set_output_delay -clock [get_clocks net_ft601_clk] -max 1.0 [get_ports {ft601_wr_n ft601_rd_n ft601_oe_n}] 77 | set_output_delay -clock [get_clocks net_ft601_clk] -min 4.8 [get_ports {ft601_wr_n ft601_rd_n ft601_oe_n}] 78 | set_output_delay -clock [get_clocks net_ft601_clk] -max 1.0 [get_ports {{ft601_be[*]} {ft601_data[*]}}] 79 | set_output_delay -clock [get_clocks net_ft601_clk] -min 4.8 [get_ports {{ft601_be[*]} {ft601_data[*]}}] 80 | 81 | set_property IOB TRUE [get_cells i_pcileech_com/i_pcileech_ft601/FT601_OE_N_reg] 82 | set_property IOB TRUE [get_cells i_pcileech_com/i_pcileech_ft601/FT601_RD_N_reg] 83 | set_property IOB TRUE [get_cells i_pcileech_com/i_pcileech_ft601/FT601_WR_N_reg] 84 | set_property IOB TRUE [get_cells i_pcileech_com/i_pcileech_ft601/FT601_DATA_OUT_reg[0][*]] 85 | 86 | set_multicycle_path 2 -from [get_pins i_pcileech_com/i_pcileech_ft601/OE_reg/C] -to [get_ports {{ft601_be[*]} {ft601_data[*]}}] 87 | set_false_path -from [get_pins {tickcount64_reg[*]/C}] 88 | set_false_path -from [get_pins {i_pcileech_fifo/_pcie_core_config_reg[*]/C}] 89 | 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}] 90 | set_false_path -from [get_pins i_pcileech_pcie_a7/i_pcie_7x_0/inst/inst/user_reset_out_reg/C] 91 | 92 | #PCIe signals 93 | set_property PACKAGE_PIN A13 [get_ports pcie_present] 94 | set_property PACKAGE_PIN C13 [get_ports pcie_perst_n] 95 | set_property PACKAGE_PIN B13 [get_ports pcie_wake_n] 96 | set_property IOSTANDARD LVCMOS33 [get_ports pcie_present] 97 | set_property IOSTANDARD LVCMOS33 [get_ports pcie_perst_n] 98 | set_property IOSTANDARD LVCMOS33 [get_ports pcie_wake_n] 99 | 100 | set_property PACKAGE_PIN C9 [get_ports {pcie_rx_n[0]}] 101 | set_property PACKAGE_PIN D9 [get_ports {pcie_rx_p[0]}] 102 | set_property PACKAGE_PIN C7 [get_ports {pcie_tx_n[0]}] 103 | set_property PACKAGE_PIN D7 [get_ports {pcie_tx_p[0]}] 104 | 105 | set_property PACKAGE_PIN E10 [get_ports pcie_clk_n] 106 | set_property PACKAGE_PIN F10 [get_ports pcie_clk_p] 107 | 108 | create_clock -name pcie_sys_clk_p -period 10.0 [get_nets pcie_clk_p] 109 | 110 | set_property CFGBVS Vcco [current_design] 111 | set_property CONFIG_VOLTAGE 3.3 [current_design] 112 | set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design] 113 | set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design] 114 | set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES [current_design] 115 | set_property BITSTREAM.CONFIG.CONFIGRATE 66 [current_design] -------------------------------------------------------------------------------- /src/pcileech_com.sv: -------------------------------------------------------------------------------- 1 | // 2 | // PCILeech Buffered Communication Core for either: 3 | // - FT601 USB3. 4 | // - FPGA RMII ETHERNET. 5 | // 6 | // 7 | // (c) Ulf Frisk, 2019-2024 8 | // Author: Ulf Frisk, pcileech@frizk.net 9 | // 10 | 11 | `timescale 1ns / 1ps 12 | //`define ENABLE_ETH 13 | `define ENABLE_FT601 14 | 15 | module pcileech_com ( 16 | // SYS 17 | input clk, // 100MHz SYSTEM CLK 18 | input clk_com, // COMMUNICATION CORE CLK 19 | input rst, 20 | output led_state_txdata, 21 | input led_state_invert, 22 | 23 | // TO/FROM FIFO 24 | IfComToFifo.mp_com dfifo, 25 | 26 | `ifdef ENABLE_FT601 27 | // FT601 28 | inout [31:0] ft601_data, 29 | output [3:0] ft601_be, 30 | input ft601_rxf_n, 31 | input ft601_txe_n, 32 | output ft601_wr_n, 33 | output ft601_siwu_n, 34 | output ft601_rd_n, 35 | output ft601_oe_n 36 | `endif /* ENABLE_FT601 */ 37 | `ifdef ENABLE_ETH 38 | // ETH 39 | output eth_clk50, 40 | output eth_rst_n, 41 | input [1:0] eth_rx_data, 42 | input eth_crs_dv, 43 | output eth_tx_en, 44 | output [1:0] eth_tx_data, 45 | output eth_mdc, 46 | inout eth_mdio, 47 | input eth_rx_err, 48 | input [31:0] eth_cfg_static_addr, 49 | input eth_cfg_static_force, 50 | input [15:0] eth_cfg_port, 51 | output eth_led_state_red, 52 | output eth_led_state_green 53 | `endif /* ENABLE_ETH */ 54 | ); 55 | 56 | // ---------------------------------------------------------------------------- 57 | // COMMUNICATION CORE INITIAL ON-BOARD DEFAULT RX-DATA 58 | // Sometimes there is a need to perform actions - such as setting DRP-related 59 | // values before the PCIe core is brought online. This is possible by specify 60 | // "virtual" COM-core initial transmitted values below. 61 | // ---------------------------------------------------------------------------- 62 | 63 | bit [63:0] initial_rx [5] = '{ 64 | // Modify data below to set own actions - examples: 65 | // - send some initial TLP on core startup. 66 | // - set initial VID/PID if PCIe core has been modified. 67 | // - write to DRP memory space to alter the core. 68 | // replace / expand on dummy values below - for syntax of each 64-bit word 69 | // please consult sources and also device_fpga.c in the LeechCore project. 70 | 64'h00000000_00000000, 71 | 64'h00000000_00000000, 72 | 64'h00000000_00000000, 73 | 64'h00000000_00000000, 74 | 75 | // Bring the PCIe core online from initial hot-reset state. This is done by 76 | // setting control bit in PCIleech FIFO CMD register. This should ideally be 77 | // done after DRP&Config actions are completed - but before sending PCIe TLPs. 78 | 64'h00000003_80182377 79 | }; 80 | 81 | time tickcount64 = 0; 82 | always @ ( posedge clk ) 83 | tickcount64 <= rst ? 0 : tickcount64 + 1; 84 | 85 | time tickcount64_com = 0; 86 | always @ ( posedge clk_com ) 87 | tickcount64_com <= rst ? 0 : tickcount64_com + 1; 88 | 89 | wire initial_rx_valid = ~rst & (tickcount64 >= 16) & (tickcount64 < $size(initial_rx) + 16); 90 | wire [63:0] initial_rx_data = initial_rx_valid ? initial_rx[tickcount64 - 16] : 64'h0; 91 | 92 | // ---------------------------------------------------------------------------- 93 | // COMMUNICATION CORE RX DATA BELOW: 94 | // 1: convert 32-bit signal into 64-bit signal using logic. 95 | // 2: change clock domain from clk_com to clk using a very shallow fifo. 96 | // due to previous 32->64 conversion this will be fine if: 2*clk_com < clk. 97 | // ---------------------------------------------------------------------------- 98 | 99 | wire [31:0] com_rx_data32; 100 | wire com_rx_valid32; 101 | reg [63:0] com_rx_data64; 102 | reg [1:0] com_rx_valid64_dw; 103 | wire com_rx_valid64 = com_rx_valid64_dw[0] & com_rx_valid64_dw[1]; 104 | wire [63:0] com_rx_dout; 105 | wire com_rx_valid; 106 | 107 | always @ ( posedge clk_com ) 108 | if ( rst | (~com_rx_valid32 & com_rx_valid64_dw[0] & com_rx_valid64_dw[1]) ) 109 | com_rx_valid64_dw <= 2'b00; 110 | else if ( com_rx_valid32 && (com_rx_data32 == 32'h66665555) && (com_rx_data64[31:0] == 32'h66665555) ) 111 | // resync logic to allow the host to send resync data that will 112 | // allow bitstream to sync to proper 32->64-bit sequence in case 113 | // it should have happen to get out of sync at startup/shutdown. 114 | com_rx_valid64_dw <= 2'b00; 115 | else if ( com_rx_valid32 ) 116 | begin 117 | com_rx_data64 <= (com_rx_data64 << 32) | com_rx_data32; 118 | com_rx_valid64_dw <= (com_rx_valid64_dw == 2'b01) ? 2'b11 : 2'b01; 119 | end 120 | 121 | fifo_64_64_clk2_comrx i_fifo_64_64_clk2_comrx( 122 | .rst ( rst | (tickcount64_com<2) ), 123 | .wr_clk ( clk_com ), 124 | .rd_clk ( clk ), 125 | .din ( com_rx_data64 ), 126 | .wr_en ( com_rx_valid64 ), 127 | .rd_en ( 1'b1 ), 128 | .dout ( com_rx_dout ), 129 | .full ( ), 130 | .empty ( ), 131 | .valid ( com_rx_valid ) 132 | ); 133 | 134 | assign dfifo.com_dout = initial_rx_valid ? initial_rx_data : com_rx_dout; 135 | assign dfifo.com_dout_valid = initial_rx_valid | com_rx_valid; 136 | 137 | // ---------------------------------------------------------------------------- 138 | // COMMUNICATION CORE TX DATA BELOW: 139 | // ---------------------------------------------------------------------------- 140 | 141 | wire [31:0] core_din; 142 | wire core_din_empty; 143 | wire core_din_wr_en; 144 | wire core_din_ready; 145 | 146 | wire [31:0] com_tx_data; 147 | wire com_tx_wr_en; 148 | wire com_tx_almost_full; 149 | wire com_tx_prog_full; 150 | wire com_tx_prog_empty; 151 | 152 | wire out_buffer1_almost_full; 153 | 154 | assign dfifo.com_din_ready = ~out_buffer1_almost_full; 155 | assign led_state_txdata = com_tx_prog_full ^ led_state_invert; 156 | 157 | fifo_32_32_clk1_comtx i_fifo_32_32_clk2_comtx( 158 | .clk ( clk_com ), 159 | .srst ( rst ), 160 | .din ( com_tx_data ), 161 | .wr_en ( com_tx_wr_en ), 162 | .rd_en ( core_din_ready ), 163 | .dout ( core_din ), 164 | .full ( ), 165 | .almost_full ( com_tx_almost_full ), 166 | .empty ( core_din_empty ), 167 | .prog_empty ( com_tx_prog_empty ), // threshold = 3 168 | .prog_full ( com_tx_prog_full ), // threshold = 6 169 | .valid ( core_din_wr_en ) 170 | ); 171 | fifo_256_32_clk2_comtx i_fifo_256_32_clk2_comtx( 172 | .rd_clk ( clk_com ), 173 | .wr_clk ( clk ), 174 | .rst ( rst ), 175 | .din ( dfifo.com_din ), 176 | .wr_en ( dfifo.com_din_wr_en ), 177 | .rd_en ( ~com_tx_almost_full ), 178 | .dout ( com_tx_data ), 179 | .full ( ), 180 | .almost_full ( out_buffer1_almost_full ), 181 | .empty ( ), 182 | .valid ( com_tx_wr_en ) 183 | ); 184 | 185 | // ---------------------------------------------------- 186 | // FT601 USB3 BELOW: 187 | // ---------------------------------------------------- 188 | `ifdef ENABLE_FT601 189 | 190 | pcileech_ft601 i_pcileech_ft601( 191 | // SYS 192 | .clk ( clk_com ), 193 | .rst ( rst ), 194 | // TO/FROM FT601 PADS 195 | .FT601_DATA ( ft601_data ), 196 | .FT601_BE ( ft601_be ), 197 | .FT601_TXE_N ( ft601_txe_n ), 198 | .FT601_RXF_N ( ft601_rxf_n ), 199 | .FT601_SIWU_N ( ft601_siwu_n ), 200 | .FT601_WR_N ( ft601_wr_n ), 201 | .FT601_RD_N ( ft601_rd_n ), 202 | .FT601_OE_N ( ft601_oe_n ), 203 | // TO/FROM FIFO 204 | .dout ( com_rx_data32 ), // -> [31:0] 205 | .dout_valid ( com_rx_valid32 ), // -> 206 | .din ( core_din ), // <- [31:0] 207 | .din_wr_en ( core_din_wr_en ), // <- 208 | .din_req_data ( core_din_ready ) // -> 209 | ); 210 | `endif /* ENABLE_FT601 */ 211 | 212 | // ---------------------------------------------------- 213 | // UDP Ethernet Below: 214 | // ---------------------------------------------------- 215 | `ifdef ENABLE_ETH 216 | 217 | pcileech_eth i_pcileech_eth( 218 | // SYS 219 | .clk ( clk_com ), 220 | .rst ( rst ), 221 | // MAC/RMII 222 | .eth_clk50 ( eth_clk50 ), 223 | .eth_rst_n ( eth_rst_n ), 224 | .eth_crs_dv ( eth_crs_dv ), 225 | .eth_rx_data ( eth_rx_data ), 226 | .eth_rx_err ( eth_rx_err ), 227 | .eth_tx_en ( eth_tx_en ), 228 | .eth_tx_data ( eth_tx_data ), 229 | .eth_mdc ( eth_mdc ), 230 | .eth_mdio ( eth_mdio ), 231 | // CFG 232 | .cfg_static_addr ( eth_cfg_static_addr ), // <- [31:0] 233 | .cfg_static_force ( eth_cfg_static_force ), // <- 234 | .cfg_port ( eth_cfg_port ), // <- [15:0] 235 | // State and Activity LEDs 236 | .led_state_red ( eth_led_state_red ), // -> 237 | .led_state_green ( eth_led_state_green ), // -> 238 | // TO/FROM FIFO 239 | .dout ( com_rx_data32 ), // -> [31:0] 240 | .dout_valid ( com_rx_valid32 ), // -> 241 | .din ( core_din ), // <- [31:0] 242 | .din_empty ( core_din_empty ), // <- 243 | .din_wr_en ( core_din_wr_en ), // <- 244 | .din_ready ( core_din_ready ) // -> 245 | ); 246 | `endif /* ENABLE_ETH */ 247 | 248 | endmodule 249 | -------------------------------------------------------------------------------- /src/pcileech_enigma_x1.xdc: -------------------------------------------------------------------------------- 1 | set_property PACKAGE_PIN V20 [get_ports ft601_be[0]] 2 | set_property PACKAGE_PIN V19 [get_ports ft601_be[1]] 3 | set_property PACKAGE_PIN W20 [get_ports ft601_be[2]] 4 | set_property PACKAGE_PIN AB20 [get_ports ft601_be[3]] 5 | set_property PACKAGE_PIN H20 [get_ports ft601_data[0]] 6 | set_property PACKAGE_PIN H22 [get_ports ft601_data[1]] 7 | set_property PACKAGE_PIN J21 [get_ports ft601_data[2]] 8 | set_property PACKAGE_PIN J22 [get_ports ft601_data[3]] 9 | set_property PACKAGE_PIN K21 [get_ports ft601_data[4]] 10 | set_property PACKAGE_PIN K22 [get_ports ft601_data[5]] 11 | set_property PACKAGE_PIN L21 [get_ports ft601_data[6]] 12 | set_property PACKAGE_PIN N18 [get_ports ft601_data[7]] 13 | set_property PACKAGE_PIN M18 [get_ports ft601_data[8]] 14 | set_property PACKAGE_PIN L20 [get_ports ft601_data[9]] 15 | set_property PACKAGE_PIN L19 [get_ports ft601_data[10]] 16 | set_property PACKAGE_PIN M20 [get_ports ft601_data[11]] 17 | set_property PACKAGE_PIN M22 [get_ports ft601_data[12]] 18 | set_property PACKAGE_PIN M21 [get_ports ft601_data[13]] 19 | set_property PACKAGE_PIN N22 [get_ports ft601_data[14]] 20 | set_property PACKAGE_PIN N20 [get_ports ft601_data[15]] 21 | set_property PACKAGE_PIN P15 [get_ports ft601_data[16]] 22 | set_property PACKAGE_PIN T21 [get_ports ft601_data[17]] 23 | set_property PACKAGE_PIN R16 [get_ports ft601_data[18]] 24 | # OLD ft601_data[19] 25 | #set_property PACKAGE_PIN T20 [get_ports ft601_data[19]] 26 | # NEW ft601_data[19] 27 | set_property PACKAGE_PIN T18 [get_ports ft601_data[19]] 28 | set_property PACKAGE_PIN U17 [get_ports ft601_data[20]] 29 | set_property PACKAGE_PIN U20 [get_ports ft601_data[21]] 30 | set_property PACKAGE_PIN U21 [get_ports ft601_data[22]] 31 | set_property PACKAGE_PIN V22 [get_ports ft601_data[23]] 32 | set_property PACKAGE_PIN W22 [get_ports ft601_data[24]] 33 | set_property PACKAGE_PIN W21 [get_ports ft601_data[25]] 34 | set_property PACKAGE_PIN Y22 [get_ports ft601_data[26]] 35 | set_property PACKAGE_PIN Y21 [get_ports ft601_data[27]] 36 | set_property PACKAGE_PIN AB22 [get_ports ft601_data[28]] 37 | set_property PACKAGE_PIN AA21 [get_ports ft601_data[29]] 38 | set_property PACKAGE_PIN AB21 [get_ports ft601_data[30]] 39 | set_property PACKAGE_PIN AA20 [get_ports ft601_data[31]] 40 | set_property PACKAGE_PIN W17 [get_ports ft601_oe_n] 41 | set_property PACKAGE_PIN P16 [get_ports ft601_rd_n] 42 | set_property PACKAGE_PIN AA18 [get_ports ft601_rxf_n] 43 | set_property PACKAGE_PIN AB18 [get_ports ft601_siwu_n] 44 | set_property PACKAGE_PIN AA19 [get_ports ft601_txe_n] 45 | set_property PACKAGE_PIN W19 [get_ports ft601_wr_n] 46 | set_property PACKAGE_PIN N13 [get_ports ft601_rst_n] 47 | set_property IOSTANDARD LVCMOS33 [get_ports {ft601_txe_n ft601_rxf_n}] 48 | set_property IOSTANDARD LVCMOS33 [get_ports {{ft601_be[*]} {ft601_data[*]}}] 49 | set_property IOSTANDARD LVCMOS33 [get_ports {ft601_wr_n ft601_rd_n ft601_oe_n ft601_siwu_n ft601_rst_n}] 50 | set_property SLEW FAST [get_ports {{ft601_be[*]} {ft601_data[*]}}] 51 | set_property SLEW FAST [get_ports {ft601_wr_n ft601_rd_n ft601_oe_n ft601_siwu_n ft601_rst_n}] 52 | 53 | set_property PACKAGE_PIN G21 [get_ports user_ld1_n] 54 | set_property PACKAGE_PIN G22 [get_ports user_ld2_n] 55 | set_property PACKAGE_PIN F19 [get_ports user_sw1_n] 56 | set_property PACKAGE_PIN F20 [get_ports user_sw2_n] 57 | set_property IOSTANDARD LVCMOS33 [get_ports {user_ld1_n user_ld2_n user_sw1_n user_sw2_n}] 58 | 59 | # SYSCLK 60 | set_property PACKAGE_PIN J19 [get_ports clk] 61 | set_property IOSTANDARD LVCMOS33 [get_ports clk] 62 | create_clock -period 10.000 -name net_clk -waveform {0.000 5.000} [get_ports clk] 63 | 64 | # FT601 CLK 65 | create_clock -period 10.000 -name net_ft601_clk -waveform {0.000 5.000} [get_ports ft601_clk] 66 | set_property IOSTANDARD LVCMOS33 [get_ports ft601_clk] 67 | set_property PACKAGE_PIN K18 [get_ports ft601_clk] 68 | 69 | set_input_delay -clock [get_clocks net_ft601_clk] -min 6.5 [get_ports {ft601_data[*]}] 70 | set_input_delay -clock [get_clocks net_ft601_clk] -max 7.0 [get_ports {ft601_data[*]}] 71 | set_input_delay -clock [get_clocks net_ft601_clk] -min 6.5 [get_ports ft601_rxf_n] 72 | set_input_delay -clock [get_clocks net_ft601_clk] -max 7.0 [get_ports ft601_rxf_n] 73 | set_input_delay -clock [get_clocks net_ft601_clk] -min 6.5 [get_ports ft601_txe_n] 74 | set_input_delay -clock [get_clocks net_ft601_clk] -max 7.0 [get_ports ft601_txe_n] 75 | 76 | set_output_delay -clock [get_clocks net_ft601_clk] -max 1.0 [get_ports {ft601_wr_n ft601_rd_n ft601_oe_n}] 77 | set_output_delay -clock [get_clocks net_ft601_clk] -min 4.8 [get_ports {ft601_wr_n ft601_rd_n ft601_oe_n}] 78 | set_output_delay -clock [get_clocks net_ft601_clk] -max 1.0 [get_ports {{ft601_be[*]} {ft601_data[*]}}] 79 | set_output_delay -clock [get_clocks net_ft601_clk] -min 4.8 [get_ports {{ft601_be[*]} {ft601_data[*]}}] 80 | 81 | set_property IOB TRUE [get_cells i_pcileech_com/i_pcileech_ft601/FT601_OE_N_reg] 82 | set_property IOB TRUE [get_cells i_pcileech_com/i_pcileech_ft601/FT601_RD_N_reg] 83 | set_property IOB TRUE [get_cells i_pcileech_com/i_pcileech_ft601/FT601_WR_N_reg] 84 | set_property IOB TRUE [get_cells i_pcileech_com/i_pcileech_ft601/FT601_DATA_OUT_reg[0][*]] 85 | 86 | set_multicycle_path 2 -from [get_pins i_pcileech_com/i_pcileech_ft601/OE_reg/C] -to [get_ports {{ft601_be[*]} {ft601_data[*]}}] 87 | set_false_path -from [get_pins {tickcount64_reg[*]/C}] 88 | set_false_path -from [get_pins {i_pcileech_fifo/_pcie_core_config_reg[*]/C}] 89 | 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}] 90 | set_false_path -from [get_pins i_pcileech_pcie_a7/i_pcie_7x_0/inst/inst/user_reset_out_reg/C] 91 | 92 | #PCIe signals 93 | set_property PACKAGE_PIN A13 [get_ports pcie_present] 94 | set_property PACKAGE_PIN C13 [get_ports pcie_perst_n] 95 | set_property PACKAGE_PIN B13 [get_ports pcie_wake_n] 96 | set_property IOSTANDARD LVCMOS33 [get_ports pcie_present] 97 | set_property IOSTANDARD LVCMOS33 [get_ports pcie_perst_n] 98 | set_property IOSTANDARD LVCMOS33 [get_ports pcie_wake_n] 99 | 100 | set_property PACKAGE_PIN C9 [get_ports {pcie_rx_n[0]}] 101 | set_property PACKAGE_PIN D9 [get_ports {pcie_rx_p[0]}] 102 | set_property PACKAGE_PIN C7 [get_ports {pcie_tx_n[0]}] 103 | set_property PACKAGE_PIN D7 [get_ports {pcie_tx_p[0]}] 104 | 105 | set_property PACKAGE_PIN E10 [get_ports pcie_clk_n] 106 | set_property PACKAGE_PIN F10 [get_ports pcie_clk_p] 107 | 108 | create_clock -name pcie_sys_clk_p -period 10.0 [get_nets pcie_clk_p] 109 | 110 | set_property CFGBVS Vcco [current_design] 111 | set_property CONFIG_VOLTAGE 3.3 [current_design] 112 | set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design] 113 | set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design] 114 | set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES [current_design] 115 | set_property BITSTREAM.CONFIG.CONFIGRATE 66 [current_design] -------------------------------------------------------------------------------- /src/pcileech_enigma_x1_top.sv: -------------------------------------------------------------------------------- 1 | // 2 | // PCILeech FPGA. 3 | // 4 | // Top module for the Enigma X1 Artix-7 board. 5 | // 6 | // (c) Ulf Frisk, 2019-2024 7 | // Author: Ulf Frisk, pcileech@frizk.net 8 | // 9 | 10 | `timescale 1ns / 1ps 11 | `include "pcileech_header.svh" 12 | 13 | module pcileech_enigma_x1_top #( 14 | // DEVICE IDs as follows: 15 | // 0 = SP605, 1 = PCIeScreamer R1, 2 = AC701, 3 = PCIeScreamer R2, 4 = Screamer, 5 = NeTV2 16 | parameter PARAM_DEVICE_ID = 9, 17 | parameter PARAM_VERSION_NUMBER_MAJOR = 4, 18 | parameter PARAM_VERSION_NUMBER_MINOR = 13, 19 | parameter PARAM_CUSTOM_VALUE = 32'hffffffff 20 | ) ( 21 | // SYS 22 | input clk, 23 | input ft601_clk, 24 | 25 | // SYSTEM LEDs and BUTTONs 26 | output user_ld1_n, 27 | output user_ld2_n, 28 | input user_sw1_n, 29 | input user_sw2_n, 30 | 31 | // PCI-E FABRIC 32 | output [0:0] pcie_tx_p, 33 | output [0:0] pcie_tx_n, 34 | input [0:0] pcie_rx_p, 35 | input [0:0] pcie_rx_n, 36 | input pcie_clk_p, 37 | input pcie_clk_n, 38 | input pcie_present, 39 | input pcie_perst_n, 40 | output reg pcie_wake_n = 1'b1, 41 | 42 | // TO/FROM FT601 PADS 43 | output ft601_rst_n, 44 | 45 | inout [31:0] ft601_data, 46 | output [3:0] ft601_be, 47 | input ft601_rxf_n, 48 | input ft601_txe_n, 49 | output ft601_wr_n, 50 | output ft601_siwu_n, 51 | output ft601_rd_n, 52 | output ft601_oe_n 53 | ); 54 | 55 | // SYS 56 | wire rst; 57 | 58 | // FIFO CTL <--> COM CTL 59 | wire [63:0] com_dout; 60 | wire com_dout_valid; 61 | wire [255:0] com_din; 62 | wire com_din_wr_en; 63 | wire com_din_ready; 64 | wire led_com; 65 | wire led_pcie; 66 | 67 | // FIFO CTL <--> COM CTL 68 | IfComToFifo dcom_fifo(); 69 | 70 | // FIFO CTL <--> PCIe 71 | IfPCIeFifoCfg dcfg(); 72 | IfPCIeFifoTlp dtlp(); 73 | IfPCIeFifoCore dpcie(); 74 | IfShadow2Fifo dshadow2fifo(); 75 | 76 | // ---------------------------------------------------- 77 | // TickCount64 CLK 78 | // ---------------------------------------------------- 79 | 80 | time tickcount64 = 0; 81 | time tickcount64_reload = 0; 82 | always @ ( posedge clk ) begin 83 | tickcount64 <= user_sw2_n ? (tickcount64 + 1) : 0; 84 | tickcount64_reload <= user_sw2_n ? 0 : (tickcount64_reload + 1); 85 | end 86 | 87 | assign rst = ~user_sw2_n || ((tickcount64 < 64) ? 1'b1 : 1'b0); 88 | assign ft601_rst_n = ~rst; 89 | wire led_pwronblink = ~user_sw1_n ^ (tickcount64[24] & (tickcount64[63:27] == 0)); 90 | 91 | OBUF led_ld1_obuf(.O(user_ld1_n), .I(~led_pcie)); 92 | OBUF led_ld2_obuf(.O(user_ld2_n), .I(~led_com)); 93 | 94 | // ---------------------------------------------------- 95 | // BUFFERED COMMUNICATION DEVICE (FT601) 96 | // ---------------------------------------------------- 97 | 98 | pcileech_com i_pcileech_com ( 99 | // SYS 100 | .clk ( clk ), 101 | .clk_com ( ft601_clk ), 102 | .rst ( rst ), 103 | .led_state_txdata ( led_com ), // -> 104 | .led_state_invert ( led_pwronblink ), // <- 105 | // FIFO CTL <--> COM CTL 106 | .dfifo ( dcom_fifo.mp_com ), 107 | // TO/FROM FT601 PADS 108 | .ft601_data ( ft601_data ), // <> [31:0] 109 | .ft601_be ( ft601_be ), // -> [3:0] 110 | .ft601_txe_n ( ft601_txe_n ), // <- 111 | .ft601_rxf_n ( ft601_rxf_n ), // <- 112 | .ft601_siwu_n ( ft601_siwu_n ), // -> 113 | .ft601_wr_n ( ft601_wr_n ), // -> 114 | .ft601_rd_n ( ft601_rd_n ), // -> 115 | .ft601_oe_n ( ft601_oe_n ) // -> 116 | ); 117 | 118 | // ---------------------------------------------------- 119 | // FIFO CTL 120 | // ---------------------------------------------------- 121 | 122 | pcileech_fifo #( 123 | .PARAM_DEVICE_ID ( PARAM_DEVICE_ID ), 124 | .PARAM_VERSION_NUMBER_MAJOR ( PARAM_VERSION_NUMBER_MAJOR ), 125 | .PARAM_VERSION_NUMBER_MINOR ( PARAM_VERSION_NUMBER_MINOR ), 126 | .PARAM_CUSTOM_VALUE ( PARAM_CUSTOM_VALUE ) 127 | ) i_pcileech_fifo ( 128 | .clk ( clk ), 129 | .rst ( rst ), 130 | .rst_cfg_reload ( (tickcount64_reload > 500000000) ? 1'b1 : 1'b0 ), // config reload after 5s button press 131 | .pcie_present ( pcie_present ), 132 | .pcie_perst_n ( pcie_perst_n ), 133 | // FIFO CTL <--> COM CTL 134 | .dcom ( dcom_fifo.mp_fifo ), 135 | // FIFO CTL <--> PCIe 136 | .dcfg ( dcfg.mp_fifo ), 137 | .dtlp ( dtlp.mp_fifo ), 138 | .dpcie ( dpcie.mp_fifo ), 139 | .dshadow2fifo ( dshadow2fifo.fifo ) 140 | ); 141 | 142 | // ---------------------------------------------------- 143 | // PCIe 144 | // ---------------------------------------------------- 145 | 146 | pcileech_pcie_a7 i_pcileech_pcie_a7( 147 | .clk_sys ( clk ), 148 | .rst ( rst ), 149 | // PCIe fabric 150 | .pcie_tx_p ( pcie_tx_p ), 151 | .pcie_tx_n ( pcie_tx_n ), 152 | .pcie_rx_p ( pcie_rx_p ), 153 | .pcie_rx_n ( pcie_rx_n ), 154 | .pcie_clk_p ( pcie_clk_p ), 155 | .pcie_clk_n ( pcie_clk_n ), 156 | .pcie_perst_n ( pcie_perst_n ), 157 | // State and Activity LEDs 158 | .led_state ( led_pcie ), 159 | // FIFO CTL <--> PCIe 160 | .dfifo_cfg ( dcfg.mp_pcie ), 161 | .dfifo_tlp ( dtlp.mp_pcie ), 162 | .dfifo_pcie ( dpcie.mp_pcie ), 163 | .dshadow2fifo ( dshadow2fifo.shadow ) 164 | ); 165 | 166 | endmodule 167 | -------------------------------------------------------------------------------- /src/pcileech_fifo.sv: -------------------------------------------------------------------------------- 1 | // 2 | // PCILeech FPGA. 3 | // 4 | // FIFO network / control. 5 | // 6 | // (c) Ulf Frisk, 2017-2024 7 | // Author: Ulf Frisk, pcileech@frizk.net 8 | // Special thanks to: Dmytro Oleksiuk @d_olex 9 | // 10 | 11 | `timescale 1ns / 1ps 12 | `include "pcileech_header.svh" 13 | 14 | `define ENABLE_STARTUPE2 15 | 16 | module pcileech_fifo #( 17 | parameter PARAM_DEVICE_ID = 0, 18 | parameter PARAM_VERSION_NUMBER_MAJOR = 0, 19 | parameter PARAM_VERSION_NUMBER_MINOR = 0, 20 | parameter PARAM_CUSTOM_VALUE = 0 21 | ) ( 22 | input clk, 23 | input rst, 24 | input rst_cfg_reload, 25 | 26 | input pcie_present, 27 | input pcie_perst_n, 28 | 29 | IfComToFifo.mp_fifo dcom, 30 | 31 | IfPCIeFifoCfg.mp_fifo dcfg, 32 | IfPCIeFifoTlp.mp_fifo dtlp, 33 | IfPCIeFifoCore.mp_fifo dpcie, 34 | IfShadow2Fifo.fifo dshadow2fifo 35 | ); 36 | 37 | // ---------------------------------------------------- 38 | // TickCount64 39 | // ---------------------------------------------------- 40 | 41 | time tickcount64 = 0; 42 | always @ ( posedge clk ) 43 | tickcount64 <= tickcount64 + 1; 44 | 45 | // ---------------------------------------------------------------------------- 46 | // RX FROM USB/FT601/FT245 BELOW: 47 | // ---------------------------------------------------------------------------- 48 | // Incoming data received from FT601 is converted from 32-bit to 64-bit. 49 | // This always happen regardless whether receiving FIFOs are full or not. 50 | // The actual data contains a MAGIC which tells which receiving FIFO should 51 | // accept the data. Receiving TYPEs are: PCIe TLP, PCIe CFG, Loopback, Command. 52 | // 53 | // /--> PCIe TLP (32-bit) 54 | // | 55 | // FT601 --+--> PCIe CFG (64-bit) 56 | // | 57 | // +--> LOOPBACK (32-bit) 58 | // | 59 | // \--> COMMAND (64-bit) 60 | // 61 | 62 | // ---------------------------------------------------------- 63 | // Route 64-bit incoming FT601 data to correct receiver below: 64 | // ---------------------------------------------------------- 65 | `define CHECK_MAGIC (dcom.com_dout[7:0] == 8'h77) 66 | `define CHECK_TYPE_TLP (dcom.com_dout[9:8] == 2'b00) 67 | `define CHECK_TYPE_CFG (dcom.com_dout[9:8] == 2'b01) 68 | `define CHECK_TYPE_LOOP (dcom.com_dout[9:8] == 2'b10) 69 | `define CHECK_TYPE_CMD (dcom.com_dout[9:8] == 2'b11) 70 | 71 | assign dtlp.tx_valid = dcom.com_dout_valid & `CHECK_MAGIC & `CHECK_TYPE_TLP; 72 | assign dcfg.tx_valid = dcom.com_dout_valid & `CHECK_MAGIC & `CHECK_TYPE_CFG; 73 | wire _loop_rx_wren = dcom.com_dout_valid & `CHECK_MAGIC & `CHECK_TYPE_LOOP; 74 | wire _cmd_rx_wren = dcom.com_dout_valid & `CHECK_MAGIC & `CHECK_TYPE_CMD; 75 | 76 | // Incoming TLPs are forwarded to PCIe core logic. 77 | assign dtlp.tx_data = dcom.com_dout[63:32]; 78 | assign dtlp.tx_last = dcom.com_dout[10]; 79 | // Incoming CFGs are forwarded to PCIe core logic. 80 | assign dcfg.tx_data = dcom.com_dout; 81 | 82 | // ---------------------------------------------------------------------------- 83 | // TX TO USB/FT601/FT245 BELOW: 84 | // ---------------------------------------------------------------------------- 85 | // 86 | // MULTIPLEXER 87 | // =========== 88 | // 1st priority 89 | // PCIe TLP ->(32-bit) --------------------->--\ 90 | // 2nd | /-----------------------------------------\ 91 | // PCIe CFG ->(32-bit)---------------------->--+--> | 256-> BUFFER FIFO (NATIVE OR DRAM) ->32 | -> FT601 92 | // | \-----------------------------------------/ 93 | // /--------------------------\ 3rd | 94 | // FT601 -> | 34-> Loopback FIFO ->34 | ->--/ 95 | // \--------------------------/ | 96 | // | 97 | // /--------------------------\ 4th | 98 | // COMMAND -> | 34-> Command FIFO ->34 | ->--/ 99 | // \--------------------------/ 100 | // 101 | 102 | // ---------------------------------------------------------- 103 | // LOOPBACK FIFO: 104 | // ---------------------------------------------------------- 105 | wire [33:0] _loop_dout; 106 | wire _loop_valid; 107 | wire _loop_rd_en; 108 | fifo_34_34 i_fifo_loop_tx( 109 | .clk ( clk ), 110 | .srst ( rst ), 111 | .rd_en ( _loop_rd_en ), 112 | .dout ( _loop_dout ), 113 | .din ( {dcom.com_dout[11:10], dcom.com_dout[63:32]} ), 114 | .wr_en ( _loop_rx_wren ), 115 | .full ( ), 116 | .almost_full ( ), 117 | .empty ( ), 118 | .valid ( _loop_valid ) 119 | ); 120 | 121 | // ---------------------------------------------------------- 122 | // COMMAND FIFO: 123 | // ---------------------------------------------------------- 124 | wire [33:0] _cmd_tx_dout; 125 | wire _cmd_tx_valid; 126 | wire _cmd_tx_rd_en; 127 | wire _cmd_tx_almost_full; 128 | reg _cmd_tx_wr_en; 129 | reg [33:0] _cmd_tx_din; 130 | fifo_34_34 i_fifo_cmd_tx( 131 | .clk ( clk ), 132 | .srst ( rst ), 133 | .rd_en ( _cmd_tx_rd_en ), 134 | .dout ( _cmd_tx_dout ), 135 | .din ( _cmd_tx_din ), 136 | .wr_en ( _cmd_tx_wr_en ), 137 | .full ( ), 138 | .almost_full ( _cmd_tx_almost_full ), 139 | .empty ( ), 140 | .valid ( _cmd_tx_valid ) 141 | ); 142 | 143 | // ---------------------------------------------------------- 144 | // MULTIPLEXER 145 | // ---------------------------------------------------------- 146 | pcileech_mux i_pcileech_mux( 147 | .clk ( clk ), 148 | .rst ( rst ), 149 | // output 150 | .dout ( dcom.com_din ), 151 | .valid ( dcom.com_din_wr_en ), 152 | .rd_en ( dcom.com_din_ready ), 153 | // LOOPBACK: 154 | .p0_din ( _loop_dout[31:0] ), 155 | .p0_tag ( 2'b10 ), 156 | .p0_ctx ( _loop_dout[33:32] ), 157 | .p0_wr_en ( _loop_valid ), 158 | .p0_req_data ( _loop_rd_en ), 159 | // COMMAND: 160 | .p1_din ( _cmd_tx_dout[31:0] ), 161 | .p1_tag ( 2'b11 ), 162 | .p1_ctx ( _cmd_tx_dout[33:32] ), 163 | .p1_wr_en ( _cmd_tx_valid ), 164 | .p1_req_data ( _cmd_tx_rd_en ), 165 | // PCIe CFG 166 | .p2_din ( dcfg.rx_data ), 167 | .p2_tag ( 2'b01 ), 168 | .p2_ctx ( 2'b00 ), 169 | .p2_wr_en ( dcfg.rx_valid ), 170 | .p2_req_data ( dcfg.rx_rd_en ), 171 | // PCIe TLP #1 172 | .p3_din ( dtlp.rx_data[0] ), 173 | .p3_tag ( 2'b00 ), 174 | .p3_ctx ( {dtlp.rx_first[0], dtlp.rx_last[0]} ), 175 | .p3_wr_en ( dtlp.rx_valid[0] ), 176 | .p3_req_data ( dtlp.rx_rd_en ), 177 | // PCIe TLP #2 178 | .p4_din ( dtlp.rx_data[1] ), 179 | .p4_tag ( 2'b00 ), 180 | .p4_ctx ( {dtlp.rx_first[1], dtlp.rx_last[1]} ), 181 | .p4_wr_en ( dtlp.rx_valid[1] ), 182 | .p4_req_data ( ), 183 | // PCIe TLP #3 184 | .p5_din ( dtlp.rx_data[2] ), 185 | .p5_tag ( 2'b00 ), 186 | .p5_ctx ( {dtlp.rx_first[2], dtlp.rx_last[2]} ), 187 | .p5_wr_en ( dtlp.rx_valid[2] ), 188 | .p5_req_data ( dtlp.rx_rd_en ), 189 | // PCIe TLP #4 190 | .p6_din ( dtlp.rx_data[3] ), 191 | .p6_tag ( 2'b00 ), 192 | .p6_ctx ( {dtlp.rx_first[3], dtlp.rx_last[3]} ), 193 | .p6_wr_en ( dtlp.rx_valid[3] ), 194 | .p6_req_data ( ), 195 | // P7 196 | .p7_din ( 32'h00000000 ), 197 | .p7_tag ( 2'b11 ), 198 | .p7_ctx ( 2'b00 ), 199 | .p7_wr_en ( 1'b0 ), 200 | .p7_req_data ( ) 201 | ); 202 | 203 | // ------------------------------------------------------------------------ 204 | // COMMAND / CONTROL FIFO: REGISTER FILE: COMMON 205 | // ------------------------------------------------------------------------ 206 | 207 | localparam RWPOS_WAIT_COMPLETE = 18; // WAIT FOR DRP COMPLETION 208 | localparam RWPOS_DRP_RD_EN = 20; 209 | localparam RWPOS_DRP_WR_EN = 21; 210 | localparam RWPOS_GLOBAL_SYSTEM_RESET = 31; 211 | 212 | wire [319:0] ro; 213 | reg [239:0] rw; 214 | 215 | // special non-user accessible registers 216 | reg [79:0] _pcie_core_config = { 4'hf, 1'b1, 1'b1, 1'b0, 1'b0, 8'h02, 16'h0666, 16'h10EE, 16'h0007, 16'h10EE }; 217 | time _cmd_timer_inactivity_base; 218 | reg rwi_drp_rd_en; 219 | reg rwi_drp_wr_en; 220 | reg [15:0] rwi_drp_data; 221 | 222 | // ------------------------------------------------------------------------ 223 | // COMMAND / CONTROL FIFO: REGISTER FILE: READ-ONLY LAYOUT/SPECIFICATION 224 | // ------------------------------------------------------------------------ 225 | 226 | // MAGIC 227 | assign ro[15:0] = 16'hab89; // +000: MAGIC 228 | // SPECIAL 229 | assign ro[19:16] = 0; // +002: SPECIAL 230 | assign ro[20] = rwi_drp_rd_en; // 231 | assign ro[21] = rwi_drp_wr_en; // 232 | assign ro[31:22] = 0; // 233 | // SIZEOF / BYTECOUNT [little-endian] 234 | assign ro[63:32] = $bits(ro) >> 3; // +004: SIZEOF / BYTECOUNT [little-endian] 235 | // ID: VERSION & DEVICE 236 | assign ro[71:64] = PARAM_VERSION_NUMBER_MAJOR; // +008: VERSION MAJOR 237 | assign ro[79:72] = PARAM_VERSION_NUMBER_MINOR; // +009: VERSION MINOR 238 | assign ro[87:80] = PARAM_DEVICE_ID; // +00A: DEVICE ID 239 | assign ro[127:88] = 0; // +00B: SLACK 240 | // UPTIME (tickcount64*100MHz) 241 | assign ro[191:128] = tickcount64; // +010: UPTIME (tickcount64*100MHz) 242 | // INACTIVITY TIMER 243 | assign ro[255:192] = _cmd_timer_inactivity_base; // +018: INACTIVITY TIMER 244 | // PCIe DRP 245 | assign ro[271:256] = rwi_drp_data; // +020: DRP: pcie_drp_do 246 | // PCIe 247 | assign ro[272] = pcie_present; // +022: PCIe PRSNT# 248 | assign ro[273] = pcie_perst_n; // PCIe PERST# 249 | assign ro[287:274] = 0; // SLACK 250 | // CUSTOM_VALUE 251 | assign ro[319:288] = PARAM_CUSTOM_VALUE; // +024: CUSTOM VALUE 252 | // +028 253 | 254 | // ------------------------------------------------------------------------ 255 | // INITIALIZATION/RESET BLOCK _AND_ 256 | // COMMAND / CONTROL FIFO: REGISTER FILE: READ-WRITE LAYOUT/SPECIFICATION 257 | // ------------------------------------------------------------------------ 258 | 259 | task pcileech_fifo_ctl_initialvalues; // task is non automatic 260 | begin 261 | _cmd_tx_wr_en <= 1'b0; 262 | 263 | // MAGIC 264 | rw[15:0] <= 16'hefcd; // +000: MAGIC 265 | // SPECIAL 266 | rw[16] <= 0; // +002: enable inactivity timer 267 | rw[17] <= 0; // enable send count 268 | rw[18] <= 1; // WAIT FOR PCIe DRP RD/WR COMPLETION BEFORE ACCEPT NEW FIFO READ/WRITES 269 | rw[19] <= 0; // SLACK 270 | rw[20] <= 0; // DRP RD EN 271 | rw[21] <= 0; // DRP WR EN 272 | rw[30:22] <= 0; // RESERVED FUTURE 273 | rw[31] <= 0; // global system reset (GSR) via STARTUPE2 primitive 274 | // SIZEOF / BYTECOUNT [little-endian] 275 | rw[63:32] <= $bits(rw) >> 3; // +004: bytecount [little endian] 276 | // CMD INACTIVITY TIMER TRIGGER VALUE 277 | rw[95:64] <= 0; // +008: cmd_inactivity_timer (ticks) [little-endian] 278 | // CMD SEND COUNT 279 | rw[127:96] <= 0; // +00C: cmd_send_count [little-endian] 280 | // PCIE INITIAL CONFIG (SPECIAL BITSTREAM) 281 | // NB! "initial" CLK0 values may also be changed in: '_pcie_core_config = {...};' [important on PCIeScreamer]. 282 | rw[143:128] <= 16'h10EE; // +010: CFG_SUBSYS_VEND_ID (NOT IMPLEMENTED) 283 | rw[159:144] <= 16'h0007; // +012: CFG_SUBSYS_ID (NOT IMPLEMENTED) 284 | rw[175:160] <= 16'h10EE; // +014: CFG_VEND_ID (NOT IMPLEMENTED) 285 | rw[191:176] <= 16'h0666; // +016: CFG_DEV_ID (NOT IMPLEMENTED) 286 | rw[199:192] <= 8'h02; // +018: CFG_REV_ID (NOT IMPLEMENTED) 287 | rw[200] <= 1'b1; // +019: PCIE CORE RESET 288 | rw[201] <= 1'b0; // PCIE SUBSYSTEM RESET 289 | rw[202] <= 1'b1; // CFGTLP PROCESSING ENABLE 290 | rw[203] <= 1'b1; // CFGTLP ZERO DATA 291 | rw[204] <= 1'b1; // CFGTLP FILTER TLP FROM USER 292 | rw[205] <= 1'b1; // PCIE BAR PIO ON-BOARD PROCESSING ENABLE 293 | rw[206] <= 1'b0; // CFGTLP PCIE WRITE ENABLE 294 | rw[207] <= 1'b1; // TLP FILTER FROM USER: EXCEPT: Cpl,CplD and CfgRd/CfgWr (handled by rw[204]) 295 | // PCIe DRP, PRSNT#, PERST# 296 | rw[208+:16] <= 0; // +01A: DRP: pcie_drp_di 297 | rw[224+:9] <= 0; // +01C: DRP: pcie_drp_addr 298 | rw[233+:7] <= 0; // SLACK 299 | // 01E - 300 | 301 | end 302 | endtask 303 | 304 | wire _cmd_timer_inactivity_enable = rw[16]; 305 | wire [31:0] _cmd_timer_inactivity_ticks = rw[95:64]; 306 | wire [15:0] _cmd_send_count_dword = rw[63:32]; 307 | wire _cmd_send_count_enable = rw[17] & (_cmd_send_count_dword != 16'h0000); 308 | 309 | always @ ( posedge clk ) 310 | _pcie_core_config <= rw[207:128]; 311 | assign dpcie.pcie_rst_core = _pcie_core_config[72]; 312 | assign dpcie.pcie_rst_subsys = _pcie_core_config[73]; 313 | assign dshadow2fifo.cfgtlp_en = _pcie_core_config[74]; 314 | assign dshadow2fifo.cfgtlp_zero = _pcie_core_config[75]; 315 | assign dshadow2fifo.cfgtlp_filter = _pcie_core_config[76]; 316 | assign dshadow2fifo.bar_en = _pcie_core_config[77]; 317 | assign dshadow2fifo.cfgtlp_wren = _pcie_core_config[78]; 318 | assign dshadow2fifo.alltlp_filter = _pcie_core_config[79]; 319 | assign dpcie.drp_en = rw[RWPOS_DRP_WR_EN] | rw[RWPOS_DRP_RD_EN]; 320 | assign dpcie.drp_we = rw[RWPOS_DRP_WR_EN]; 321 | assign dpcie.drp_addr = rw[224+:9]; 322 | assign dpcie.drp_di = rw[208+:16]; 323 | 324 | // ------------------------------------------------------------------------ 325 | // COMMAND / CONTROL FIFO: STATE MACHINE / LOGIC FOR READ/WRITE AND OTHER HOUSEKEEPING TASKS 326 | // ------------------------------------------------------------------------ 327 | 328 | wire [63:0] cmd_rx_dout; 329 | wire cmd_rx_valid; 330 | wire cmd_rx_rd_en_drp = rwi_drp_rd_en | rwi_drp_wr_en | rw[RWPOS_DRP_RD_EN] | rw[RWPOS_DRP_WR_EN]; 331 | wire cmd_rx_rd_en = tickcount64[1] & ( ~rw[RWPOS_WAIT_COMPLETE] | ~cmd_rx_rd_en_drp); 332 | 333 | fifo_64_64_clk1_fifocmd i_fifo_cmd_rx( 334 | .clk ( clk ), 335 | .srst ( rst ), 336 | .rd_en ( cmd_rx_rd_en ), 337 | .dout ( cmd_rx_dout ), 338 | .din ( dcom.com_dout ), 339 | .wr_en ( _cmd_rx_wren ), 340 | .full ( ), 341 | .empty ( ), 342 | .valid ( cmd_rx_valid ) 343 | ); 344 | 345 | integer i_write; 346 | wire [15:0] in_cmd_address_byte = cmd_rx_dout[31:16]; 347 | wire [17:0] in_cmd_address_bit = {in_cmd_address_byte[14:0], 3'b000}; 348 | wire [15:0] in_cmd_value = {cmd_rx_dout[48+:8], cmd_rx_dout[56+:8]}; 349 | wire [15:0] in_cmd_mask = {cmd_rx_dout[32+:8], cmd_rx_dout[40+:8]}; 350 | wire f_rw = in_cmd_address_byte[15]; 351 | wire f_shadowcfgspace = in_cmd_address_byte[14]; 352 | wire [15:0] in_cmd_data_in = (in_cmd_address_bit < (f_rw ? $bits(rw) : $bits(ro))) ? (f_rw ? rw[in_cmd_address_bit+:16] : ro[in_cmd_address_bit+:16]) : 16'h0000; 353 | wire in_cmd_read = cmd_rx_valid & cmd_rx_dout[12] & ~f_shadowcfgspace; 354 | wire in_cmd_write = cmd_rx_valid & cmd_rx_dout[13] & ~f_shadowcfgspace & f_rw; 355 | assign dshadow2fifo.rx_rden = cmd_rx_valid & cmd_rx_dout[12] & f_shadowcfgspace; 356 | assign dshadow2fifo.rx_wren = cmd_rx_valid & cmd_rx_dout[13] & f_shadowcfgspace & f_rw; 357 | assign dshadow2fifo.rx_be = {(in_cmd_mask[7:0] > 0 ? ~in_cmd_address_byte[1] : 1'b0), (in_cmd_mask[15:8] > 0 ? ~in_cmd_address_byte[1] : 1'b0), (in_cmd_mask[7:0] > 0 ? in_cmd_address_byte[1] : 1'b0), (in_cmd_mask[15:8] > 0 ? in_cmd_address_byte[1] : 1'b0)}; 358 | assign dshadow2fifo.rx_addr = in_cmd_address_byte[11:2]; 359 | assign dshadow2fifo.rx_addr_lo = in_cmd_address_byte[1]; 360 | assign dshadow2fifo.rx_data = {in_cmd_value[7:0], in_cmd_value[15:8], in_cmd_value[7:0], in_cmd_value[15:8]}; 361 | 362 | initial pcileech_fifo_ctl_initialvalues(); 363 | 364 | always @ ( posedge clk ) 365 | if ( rst ) 366 | pcileech_fifo_ctl_initialvalues(); 367 | else 368 | begin 369 | // SHADOW CONFIG SPACE RESPONSE 370 | if ( dshadow2fifo.tx_valid ) 371 | begin 372 | _cmd_tx_wr_en <= 1'b1; 373 | _cmd_tx_din[31:16] <= {4'b1100, dshadow2fifo.tx_addr, dshadow2fifo.tx_addr_lo, 1'b0}; 374 | _cmd_tx_din[15:0] <= dshadow2fifo.tx_addr_lo ? dshadow2fifo.tx_data[15:0] : dshadow2fifo.tx_data[31:16]; 375 | end 376 | // READ config 377 | else if ( in_cmd_read ) 378 | begin 379 | _cmd_tx_wr_en <= 1'b1; 380 | _cmd_tx_din[31:16] <= in_cmd_address_byte; 381 | _cmd_tx_din[15:0] <= {in_cmd_data_in[7:0], in_cmd_data_in[15:8]}; 382 | end 383 | // SEND COUNT ACTION 384 | else if ( ~_cmd_tx_almost_full & ~in_cmd_write & _cmd_send_count_enable ) 385 | begin 386 | _cmd_tx_wr_en <= 1'b1; 387 | _cmd_tx_din[31:16] <= 16'hfffe; 388 | _cmd_tx_din[15:0] <= _cmd_send_count_dword; 389 | rw[63:32] <= _cmd_send_count_dword - 1; 390 | end 391 | // INACTIVITY TIMER ACTION 392 | else if ( ~_cmd_tx_almost_full & ~in_cmd_write & _cmd_timer_inactivity_enable & (_cmd_timer_inactivity_ticks + _cmd_timer_inactivity_base < tickcount64) ) 393 | begin 394 | _cmd_tx_wr_en <= 1'b1; 395 | _cmd_tx_din[31:16] <= 16'hffff; 396 | _cmd_tx_din[15:0] <= 16'hcede; 397 | rw[16] <= 1'b0; 398 | end 399 | else 400 | _cmd_tx_wr_en <= 1'b0; 401 | 402 | // WRITE config 403 | if ( tickcount64 < 8 ) 404 | pcileech_fifo_ctl_initialvalues(); 405 | else if ( in_cmd_write ) 406 | for ( i_write = 0; i_write < 16; i_write = i_write + 1 ) 407 | begin 408 | if ( in_cmd_mask[i_write] ) 409 | rw[in_cmd_address_bit+i_write] <= in_cmd_value[i_write]; 410 | end 411 | 412 | // UPDATE INACTIVITY TIMER BASE 413 | if ( dcom.com_din_wr_en | ~dcom.com_din_ready ) 414 | _cmd_timer_inactivity_base <= tickcount64; 415 | 416 | // DRP READ/WRITE 417 | if ( dpcie.drp_rdy ) 418 | begin 419 | rwi_drp_rd_en <= 1'b0; 420 | rwi_drp_wr_en <= 1'b0; 421 | rwi_drp_data <= dpcie.drp_do; 422 | end 423 | else if ( rw[RWPOS_DRP_RD_EN] | rw[RWPOS_DRP_WR_EN] ) 424 | begin 425 | rw[RWPOS_DRP_RD_EN] <= 1'b0; 426 | rw[RWPOS_DRP_WR_EN] <= 1'b0; 427 | rwi_drp_rd_en <= rwi_drp_rd_en | rw[RWPOS_DRP_RD_EN]; 428 | rwi_drp_wr_en <= rwi_drp_wr_en | rw[RWPOS_DRP_WR_EN]; 429 | end 430 | 431 | end 432 | 433 | // ---------------------------------------------------- 434 | // GLOBAL SYSTEM RESET: ( provided via STARTUPE2 primitive ) 435 | // ---------------------------------------------------- 436 | `ifdef ENABLE_STARTUPE2 437 | 438 | STARTUPE2 #( 439 | .PROG_USR ( "FALSE" ), 440 | .SIM_CCLK_FREQ ( 0.0 ) 441 | ) i_STARTUPE2 ( 442 | .CFGCLK ( ), // -> 443 | .CFGMCLK ( ), // -> 444 | .EOS ( ), // -> 445 | .PREQ ( ), // -> 446 | .CLK ( clk ), // <- 447 | .GSR ( rw[RWPOS_GLOBAL_SYSTEM_RESET] | rst_cfg_reload ), // <- GLOBAL SYSTEM RESET 448 | .GTS ( 1'b0 ), // <- 449 | .KEYCLEARB ( 1'b0 ), // <- 450 | .PACK ( 1'b0 ), // <- 451 | .USRCCLKO ( 1'b0 ), // <- 452 | .USRCCLKTS ( 1'b0 ), // <- 453 | .USRDONEO ( 1'b1 ), // <- 454 | .USRDONETS ( 1'b1 ) // <- 455 | ); 456 | `endif /* ENABLE_STARTUPE2 */ 457 | 458 | endmodule 459 | -------------------------------------------------------------------------------- /src/pcileech_ft601.sv: -------------------------------------------------------------------------------- 1 | // 2 | // PCILeech FPGA. 3 | // 4 | // FT601 / FT245 controller module (v4). 5 | // 6 | // (c) Ulf Frisk, 2017-2024 7 | // Author: Ulf Frisk, pcileech@frizk.net 8 | // 9 | 10 | `timescale 1ns / 1ps 11 | 12 | module pcileech_ft601( 13 | input clk, 14 | input rst, 15 | // TO/FROM PADS 16 | output [3:0] FT601_BE, 17 | inout [31:0] FT601_DATA, 18 | input FT601_RXF_N, 19 | input FT601_TXE_N, 20 | output bit FT601_OE_N, 21 | output bit FT601_RD_N, 22 | output bit FT601_WR_N, 23 | output bit FT601_SIWU_N, 24 | // TO/FROM FIFO 25 | output bit [31:0] dout, 26 | output bit dout_valid, 27 | input [31:0] din, 28 | input din_wr_en, 29 | output din_req_data 30 | ); 31 | 32 | initial begin 33 | FT601_OE_N <= 1'b1; 34 | FT601_RD_N <= 1'b1; 35 | FT601_WR_N <= 1'b1; 36 | FT601_SIWU_N <= 1'b1; 37 | dout_valid <= 1'b0; 38 | dout <= 32'h00000000; 39 | end 40 | 41 | `define S_FT601_IDLE 4'h0 42 | `define S_FT601_RX_WAIT1 4'h2 43 | `define S_FT601_RX_WAIT2 4'h3 44 | `define S_FT601_RX_WAIT3 4'h4 45 | `define S_FT601_RX_ACTIVE 4'h5 46 | `define S_FT601_RX_COOLDOWN1 4'h6 47 | `define S_FT601_RX_COOLDOWN2 4'h7 48 | `define S_FT601_TX_WAIT1 4'h8 49 | `define S_FT601_TX_WAIT2 4'h9 50 | `define S_FT601_TX_ACTIVE 4'ha 51 | `define S_FT601_TX_COOLDOWN1 4'hb 52 | `define S_FT601_TX_COOLDOWN2 4'hc 53 | 54 | bit [31:0] FT601_DATA_OUT[5]; 55 | (* KEEP = "TRUE" *) wire FWD; 56 | (* KEEP = "TRUE" *) bit OE = 1'b1; 57 | (* KEEP = "TRUE" *) bit [3:0] data_cooldown_count = 0; 58 | (* KEEP = "TRUE" *) bit [2:0] data_queue_count = 0; 59 | (* KEEP = "TRUE" *) bit [3:0] state = `S_FT601_IDLE; 60 | 61 | 62 | 63 | // ------------------------------------------------------------------------- 64 | // FT245 RX / DATA INPUT BELOW: 65 | // ------------------------------------------------------------------------- 66 | 67 | always @ ( posedge clk ) 68 | begin 69 | dout_valid <= !rst && !FT601_RXF_N && (state == `S_FT601_RX_ACTIVE); 70 | dout[7:0] <= FT601_DATA[31:24]; 71 | dout[15:8] <= FT601_DATA[23:16]; 72 | dout[23:16] <= FT601_DATA[15:8]; 73 | dout[31:24] <= FT601_DATA[7:0]; 74 | end 75 | 76 | 77 | 78 | // ------------------------------------------------------------------------- 79 | // FT245 TX / DATA OUTPUT BELOW: 80 | // ------------------------------------------------------------------------- 81 | 82 | assign FT601_BE = OE ? 4'b1111 : 4'bzzzz; 83 | assign FT601_DATA = OE ? {FT601_DATA_OUT[0][7:0], FT601_DATA_OUT[0][15:8], FT601_DATA_OUT[0][23:16], FT601_DATA_OUT[0][31:24]} : 32'hzzzzzzzz; 84 | assign din_req_data = !rst && (data_queue_count == 2) || (data_queue_count == 3); 85 | assign FWD = !rst && !FT601_TXE_N && (data_queue_count != 0) && (state == `S_FT601_TX_ACTIVE); 86 | 87 | always @ ( posedge clk ) begin 88 | if ( rst || (data_cooldown_count == 4'hf) ) begin 89 | data_cooldown_count <= 0; 90 | data_queue_count <= 5; 91 | FT601_DATA_OUT[0] <= 32'h66665555; 92 | FT601_DATA_OUT[1] <= 32'h66665555; 93 | FT601_DATA_OUT[2] <= 32'h66665555; 94 | FT601_DATA_OUT[3] <= 32'h66665555; 95 | FT601_DATA_OUT[4] <= 32'h66665555; 96 | end 97 | else begin 98 | data_cooldown_count <= (data_queue_count == 0) ? (data_cooldown_count + 1) : 0; 99 | data_queue_count <= data_queue_count + (din_wr_en ? 3'b001 : 3'b000) - (FWD ? 3'b001 : 3'b000); 100 | if ( FWD ) begin 101 | if ( data_queue_count > 1 ) begin 102 | FT601_DATA_OUT[0] <= FT601_DATA_OUT[1]; 103 | end 104 | if ( data_queue_count > 2 ) begin 105 | FT601_DATA_OUT[1] <= FT601_DATA_OUT[2]; 106 | end 107 | if ( data_queue_count > 3 ) begin 108 | FT601_DATA_OUT[2] <= FT601_DATA_OUT[3]; 109 | end 110 | if ( data_queue_count > 4 ) begin 111 | FT601_DATA_OUT[3] <= FT601_DATA_OUT[4]; 112 | end 113 | end 114 | if ( din_wr_en ) begin 115 | FT601_DATA_OUT[data_queue_count - (FWD ? 3'b001 : 3'b000)] <= din; 116 | end 117 | end 118 | end 119 | 120 | 121 | 122 | // ------------------------------------------------------------------------- 123 | // FT245 main control below: 124 | // ------------------------------------------------------------------------- 125 | 126 | always @ ( posedge clk ) 127 | begin 128 | OE <= (rst || FT601_RXF_N || ((state != `S_FT601_RX_ACTIVE) && (state != `S_FT601_RX_WAIT3) && (state != `S_FT601_RX_WAIT2) && (state != `S_FT601_RX_COOLDOWN1) && (state != `S_FT601_RX_COOLDOWN2))); 129 | FT601_OE_N <= (rst || FT601_RXF_N || ((state != `S_FT601_RX_ACTIVE) && (state != `S_FT601_RX_WAIT3) && (state != `S_FT601_RX_WAIT2))); 130 | FT601_RD_N <= (rst || FT601_RXF_N || ((state != `S_FT601_RX_ACTIVE) && (state != `S_FT601_RX_WAIT3))); 131 | FT601_WR_N <= !(!rst && !FT601_TXE_N && ((state == `S_FT601_TX_WAIT2) || ((state == `S_FT601_TX_ACTIVE) && (din_wr_en || (data_queue_count > 1))))); 132 | end 133 | 134 | always @ ( posedge clk ) 135 | if ( rst ) 136 | begin 137 | state <= `S_FT601_IDLE; 138 | end 139 | else case ( state ) 140 | // ---------------------------------------------------------------- 141 | // IDLE STATE: 142 | // RX are prioritized above TX in case both options are available. 143 | // ---------------------------------------------------------------- 144 | `S_FT601_IDLE: 145 | if ( !FT601_RXF_N ) 146 | state <= `S_FT601_RX_WAIT1; 147 | else if ( !FT601_TXE_N && (data_queue_count > 0) ) 148 | state <= `S_FT601_TX_WAIT1; 149 | // ---------------------------------------------------------------- 150 | // RX DATA FROM THE FT601: 151 | // The receiver FIFO is assumed to always be non-full. 152 | // If receiver FIFO is full data will still be received but lost. 153 | // ---------------------------------------------------------------- 154 | `S_FT601_RX_WAIT1: 155 | state <= FT601_RXF_N ? `S_FT601_RX_COOLDOWN1 : `S_FT601_RX_WAIT2; 156 | `S_FT601_RX_WAIT2: 157 | state <= FT601_RXF_N ? `S_FT601_RX_COOLDOWN1 : `S_FT601_RX_WAIT3; 158 | `S_FT601_RX_WAIT3: 159 | state <= FT601_RXF_N ? `S_FT601_RX_COOLDOWN1 : `S_FT601_RX_ACTIVE; 160 | `S_FT601_RX_ACTIVE: 161 | state <= FT601_RXF_N ? `S_FT601_RX_COOLDOWN1 : `S_FT601_RX_ACTIVE; 162 | `S_FT601_RX_COOLDOWN1: 163 | state <= `S_FT601_RX_COOLDOWN2; 164 | `S_FT601_RX_COOLDOWN2: 165 | state <= `S_FT601_IDLE; 166 | // ---------------------------------------------------------------- 167 | // TX DATA TO THE FT601: 168 | // ---------------------------------------------------------------- 169 | `S_FT601_TX_WAIT1: 170 | state <= FT601_TXE_N ? `S_FT601_TX_COOLDOWN1 : `S_FT601_TX_WAIT2; 171 | `S_FT601_TX_WAIT2: 172 | state <= FT601_TXE_N ? `S_FT601_TX_COOLDOWN1 : `S_FT601_TX_ACTIVE; 173 | `S_FT601_TX_ACTIVE: 174 | state <= (FT601_TXE_N || (!din_wr_en && (data_queue_count <= 1))) ? `S_FT601_TX_COOLDOWN1 : `S_FT601_TX_ACTIVE; 175 | `S_FT601_TX_COOLDOWN1: 176 | state <= `S_FT601_TX_COOLDOWN2; 177 | `S_FT601_TX_COOLDOWN2: 178 | state <= `S_FT601_IDLE; 179 | endcase 180 | 181 | endmodule 182 | -------------------------------------------------------------------------------- /src/pcileech_header.svh: -------------------------------------------------------------------------------- 1 | // 2 | // PCILeech FPGA. 3 | // 4 | // SystemVerilog Header File for PCILeech FPGA projects. 5 | // 6 | // (c) Ulf Frisk, 2019-2024 7 | // Author: Ulf Frisk, pcileech@frizk.net 8 | // 9 | 10 | `ifndef _pcileech_header_svh_ 11 | `define _pcileech_header_svh_ 12 | 13 | `define _bs16(v) {{v}[7:0], {v}[15:8]} 14 | `define _bs32(v) {{v}[7:0], {v}[15:8], {v}[23:16], {v}[31:24]} 15 | 16 | // ------------------------------------------------------------------------ 17 | // Interface connecting COM to FIFO module. 18 | // ------------------------------------------------------------------------ 19 | interface IfComToFifo; 20 | wire [63:0] com_dout; 21 | wire com_dout_valid; 22 | wire [255:0] com_din; 23 | wire com_din_wr_en; 24 | wire com_din_ready; 25 | 26 | modport mp_com ( 27 | output com_dout, com_dout_valid, com_din_ready, 28 | input com_din, com_din_wr_en 29 | ); 30 | 31 | modport mp_fifo ( 32 | input com_dout, com_dout_valid, com_din_ready, 33 | output com_din, com_din_wr_en 34 | ); 35 | endinterface 36 | 37 | // ------------------------------------------------------------------------ 38 | // Interface connecting PCIe to PCIe CFG module. 39 | // ------------------------------------------------------------------------ 40 | interface IfPCIeSignals; 41 | // ------------------------------------------------------------------------ 42 | // VALUES FROM PCIe TO module. 43 | // ------------------------------------------------------------------------ 44 | wire [7:0] cfg_bus_number; 45 | wire [4:0] cfg_device_number; 46 | wire [2:0] cfg_function_number; 47 | 48 | wire [15:0] cfg_command; 49 | wire [31:0] cfg_mgmt_do; 50 | wire cfg_mgmt_rd_wr_done; 51 | 52 | wire [2:0] pl_initial_link_width; 53 | wire pl_phy_lnk_up; 54 | wire [1:0] pl_lane_reversal_mode; 55 | wire pl_link_gen2_cap; 56 | wire pl_link_partner_gen2_supported; 57 | wire pl_link_upcfg_cap; 58 | wire pl_sel_lnk_rate; 59 | wire [1:0] pl_sel_lnk_width; 60 | wire [5:0] pl_ltssm_state; 61 | wire [1:0] pl_rx_pm_state; 62 | wire [2:0] pl_tx_pm_state; 63 | wire pl_directed_change_done; 64 | wire pl_received_hot_rst; 65 | 66 | wire cfg_aer_rooterr_corr_err_received; 67 | wire cfg_aer_rooterr_corr_err_reporting_en; 68 | wire cfg_aer_rooterr_fatal_err_received; 69 | wire cfg_aer_rooterr_fatal_err_reporting_en; 70 | wire cfg_aer_rooterr_non_fatal_err_received; 71 | wire cfg_aer_rooterr_non_fatal_err_reporting_en; 72 | wire cfg_bridge_serr_en; 73 | wire [15:0] cfg_dcommand; 74 | wire [15:0] cfg_dcommand2; 75 | wire [15:0] cfg_dstatus; 76 | wire [15:0] cfg_lcommand; 77 | wire [15:0] cfg_lstatus; 78 | wire [2:0] cfg_pcie_link_state; 79 | wire cfg_pmcsr_pme_en; 80 | wire cfg_pmcsr_pme_status; 81 | wire [1:0] cfg_pmcsr_powerstate; 82 | wire cfg_received_func_lvl_rst; 83 | wire cfg_root_control_pme_int_en; 84 | wire cfg_root_control_syserr_corr_err_en; 85 | wire cfg_root_control_syserr_fatal_err_en; 86 | wire cfg_root_control_syserr_non_fatal_err_en; 87 | wire cfg_slot_control_electromech_il_ctl_pulse; 88 | wire [15:0] cfg_status; 89 | wire cfg_to_turnoff; 90 | wire [5:0] tx_buf_av; 91 | wire tx_cfg_req; 92 | wire tx_err_drop; 93 | wire [6:0] cfg_vc_tcvc_map; 94 | 95 | wire [2:0] cfg_interrupt_mmenable; 96 | wire cfg_interrupt_msienable; 97 | wire cfg_interrupt_msixenable; 98 | wire cfg_interrupt_msixfm; 99 | wire cfg_interrupt_rdy; 100 | wire [7:0] cfg_interrupt_do; 101 | 102 | // ------------------------------------------------------------------------ 103 | // VALUES FROM module TO PCIe. 104 | // ------------------------------------------------------------------------ 105 | 106 | wire cfg_mgmt_rd_en; 107 | wire cfg_mgmt_wr_en; 108 | 109 | wire [63:0] cfg_dsn; 110 | wire [31:0] cfg_mgmt_di; 111 | wire [9:0] cfg_mgmt_dwaddr; 112 | wire [3:0] cfg_mgmt_byte_en; 113 | wire cfg_mgmt_wr_readonly; 114 | wire cfg_mgmt_wr_rw1c_as_rw; 115 | 116 | wire [1:0] pl_directed_link_change; 117 | wire [1:0] pl_directed_link_width; 118 | wire pl_directed_link_auton; 119 | wire pl_directed_link_speed; 120 | wire pl_upstream_prefer_deemph; 121 | wire pl_transmit_hot_rst; 122 | wire pl_downstream_deemph_source; 123 | 124 | wire [7:0] cfg_interrupt_di; 125 | wire [4:0] cfg_pciecap_interrupt_msgnum; 126 | wire cfg_interrupt_assert; 127 | wire cfg_interrupt; 128 | wire cfg_interrupt_stat; 129 | 130 | wire [1:0] cfg_pm_force_state; 131 | wire cfg_pm_force_state_en; 132 | wire cfg_pm_halt_aspm_l0s; 133 | wire cfg_pm_halt_aspm_l1; 134 | wire cfg_pm_send_pme_to; 135 | wire cfg_pm_wake; 136 | wire cfg_trn_pending; 137 | wire cfg_turnoff_ok; 138 | wire rx_np_ok; 139 | wire rx_np_req; 140 | wire tx_cfg_gnt; 141 | 142 | modport mpm ( 143 | input cfg_bus_number, cfg_device_number, cfg_function_number, cfg_command, cfg_mgmt_do, cfg_mgmt_rd_wr_done, 144 | pl_initial_link_width, pl_phy_lnk_up, pl_lane_reversal_mode, pl_link_gen2_cap, pl_link_partner_gen2_supported, 145 | pl_link_upcfg_cap, pl_sel_lnk_rate, pl_sel_lnk_width, pl_ltssm_state, pl_rx_pm_state, 146 | pl_tx_pm_state, pl_directed_change_done, pl_received_hot_rst, 147 | cfg_aer_rooterr_corr_err_received, cfg_aer_rooterr_corr_err_reporting_en, cfg_aer_rooterr_fatal_err_received, cfg_aer_rooterr_fatal_err_reporting_en, 148 | cfg_aer_rooterr_non_fatal_err_received, cfg_aer_rooterr_non_fatal_err_reporting_en, cfg_bridge_serr_en, cfg_dcommand, cfg_dcommand2, cfg_dstatus, 149 | cfg_lcommand, cfg_lstatus, cfg_pcie_link_state, cfg_pmcsr_pme_en, cfg_pmcsr_pme_status, cfg_pmcsr_powerstate, cfg_received_func_lvl_rst, cfg_root_control_pme_int_en, 150 | cfg_root_control_syserr_corr_err_en, cfg_root_control_syserr_fatal_err_en, cfg_root_control_syserr_non_fatal_err_en, cfg_slot_control_electromech_il_ctl_pulse, 151 | cfg_status, cfg_to_turnoff, tx_buf_av, tx_cfg_req, tx_err_drop, cfg_vc_tcvc_map, 152 | cfg_interrupt_mmenable, cfg_interrupt_msienable, cfg_interrupt_msixenable, cfg_interrupt_msixfm, cfg_interrupt_rdy, cfg_interrupt_do, 153 | 154 | output cfg_mgmt_rd_en, cfg_mgmt_wr_en, cfg_dsn, cfg_mgmt_di, cfg_mgmt_dwaddr, cfg_mgmt_wr_readonly, cfg_mgmt_wr_rw1c_as_rw, cfg_mgmt_byte_en, pl_directed_link_change, pl_directed_link_width, pl_directed_link_auton, 155 | pl_directed_link_speed, pl_upstream_prefer_deemph, pl_transmit_hot_rst, pl_downstream_deemph_source, 156 | cfg_interrupt_di, cfg_pciecap_interrupt_msgnum, cfg_interrupt_assert, cfg_interrupt, cfg_interrupt_stat, cfg_pm_force_state, cfg_pm_force_state_en, cfg_pm_halt_aspm_l0s, 157 | cfg_pm_halt_aspm_l1, cfg_pm_send_pme_to, cfg_pm_wake, cfg_trn_pending, cfg_turnoff_ok, rx_np_ok, rx_np_req, tx_cfg_gnt 158 | ); 159 | endinterface 160 | 161 | // ------------------------------------------------------------------------ 162 | // Interface PCIe 128-bit RX stream 163 | // ------------------------------------------------------------------------ 164 | 165 | interface IfAXIS128; 166 | wire [127:0] tdata; 167 | wire [3:0] tkeepdw; 168 | wire tvalid; 169 | wire tlast; 170 | wire [8:0] tuser; // [0] = first 171 | // [1] = last 172 | // [8:2] = BAR, 2=BAR0, 3=BAR1, .. 7=BAR5, 8=EXPROM 173 | 174 | wire tready; 175 | wire has_data; 176 | 177 | modport source( 178 | input tready, 179 | output tdata, tkeepdw, tvalid, tlast, tuser, has_data 180 | ); 181 | 182 | modport sink( 183 | output tready, 184 | input tdata, tkeepdw, tvalid, tlast, tuser, has_data 185 | ); 186 | 187 | modport source_lite( 188 | output tdata, tkeepdw, tvalid, tlast, tuser 189 | ); 190 | 191 | modport sink_lite( 192 | input tdata, tkeepdw, tvalid, tlast, tuser 193 | ); 194 | endinterface 195 | 196 | // ------------------------------------------------------------------------ 197 | // Interface connecting PCIe CFG to FIFO 198 | // ------------------------------------------------------------------------ 199 | interface IfPCIeFifoCfg; 200 | wire [63:0] tx_data; 201 | wire tx_valid; 202 | wire [31:0] rx_data; 203 | wire rx_valid; 204 | wire rx_rd_en; 205 | 206 | modport mp_fifo ( 207 | output tx_data, tx_valid, rx_rd_en, 208 | input rx_data, rx_valid 209 | ); 210 | 211 | modport mp_pcie ( 212 | input tx_data, tx_valid, rx_rd_en, 213 | output rx_data, rx_valid 214 | ); 215 | endinterface 216 | 217 | // ------------------------------------------------------------------------ 218 | // Interface connecting PCIe TLP to FIFO 219 | // ------------------------------------------------------------------------ 220 | interface IfPCIeFifoTlp; 221 | wire [31:0] tx_data; 222 | wire tx_last; 223 | wire tx_valid; 224 | wire [31:0] rx_data[4]; 225 | wire rx_first[4]; 226 | wire rx_last[4]; 227 | wire rx_valid[4]; 228 | wire rx_rd_en; 229 | 230 | modport mp_fifo ( 231 | output tx_data, tx_last, tx_valid, rx_rd_en, 232 | input rx_data, rx_first, rx_last, rx_valid 233 | ); 234 | 235 | modport mp_pcie ( 236 | input tx_data, tx_last, tx_valid, rx_rd_en, 237 | output rx_data, rx_first, rx_last, rx_valid 238 | ); 239 | endinterface 240 | 241 | // ------------------------------------------------------------------------ 242 | // Interface connecting PCIe CORE config to FIFO 243 | // ------------------------------------------------------------------------ 244 | interface IfPCIeFifoCore; 245 | // PCIe optional config 246 | wire pcie_rst_core; 247 | wire pcie_rst_subsys; 248 | // DRP config 249 | wire drp_rdy; 250 | wire [15:0] drp_do; 251 | wire drp_en; 252 | wire drp_we; 253 | wire [8:0] drp_addr; 254 | wire [15:0] drp_di; 255 | 256 | modport mp_fifo ( 257 | input drp_rdy, drp_do, 258 | output pcie_rst_core, pcie_rst_subsys, drp_en, drp_we, drp_addr, drp_di 259 | ); 260 | 261 | modport mp_pcie ( 262 | input pcie_rst_core, pcie_rst_subsys, drp_en, drp_we, drp_addr, drp_di, 263 | output drp_rdy, drp_do 264 | ); 265 | endinterface 266 | 267 | interface IfShadow2Fifo; 268 | // SHADOW CONFIGURATION SPACE TO FIFO 269 | wire rx_rden; 270 | wire rx_wren; 271 | wire [3:0] rx_be; 272 | wire [31:0] rx_data; 273 | wire [9:0] rx_addr; 274 | wire rx_addr_lo; 275 | wire tx_valid; 276 | wire [31:0] tx_data; 277 | wire [9:0] tx_addr; 278 | wire tx_addr_lo; 279 | wire cfgtlp_wren; 280 | wire cfgtlp_zero; 281 | wire cfgtlp_en; 282 | wire cfgtlp_filter; 283 | wire alltlp_filter; 284 | wire bar_en; 285 | 286 | modport fifo ( 287 | output cfgtlp_wren, cfgtlp_zero, rx_rden, rx_wren, rx_be, rx_addr, rx_addr_lo, rx_data, cfgtlp_en, cfgtlp_filter, alltlp_filter, bar_en, 288 | input tx_valid, tx_addr, tx_addr_lo, tx_data 289 | ); 290 | 291 | modport shadow ( 292 | input cfgtlp_wren, cfgtlp_zero, rx_rden, rx_wren, rx_be, rx_addr, rx_addr_lo, rx_data, cfgtlp_en, cfgtlp_filter, alltlp_filter, bar_en, 293 | output tx_valid, tx_addr, tx_addr_lo, tx_data 294 | ); 295 | endinterface 296 | 297 | // ------------------------------------------------------------------------ 298 | // Interface PCIe AXI RX / TX 299 | // ------------------------------------------------------------------------ 300 | interface IfPCIeTlpRxTx; 301 | wire [63:0] data; 302 | wire [7:0] keep; 303 | wire last; 304 | wire [21:0] user; 305 | wire valid; 306 | wire ready; 307 | 308 | modport source ( 309 | output data, keep, last, user, valid, 310 | input ready 311 | ); 312 | 313 | modport sink ( 314 | input data, keep, last, user, valid, 315 | output ready 316 | ); 317 | endinterface 318 | 319 | interface IfPCIeTlpRx128; 320 | wire [127:0] data; 321 | wire [21:0] user; 322 | wire valid; 323 | wire ready; 324 | 325 | modport source ( 326 | output data, user, valid, 327 | input ready 328 | ); 329 | 330 | modport sink ( 331 | input data, user, valid, 332 | output ready 333 | ); 334 | endinterface 335 | 336 | `endif 337 | -------------------------------------------------------------------------------- /src/pcileech_mux.sv: -------------------------------------------------------------------------------- 1 | // 2 | // PCILeech FPGA. 3 | // 4 | // Merge multiple 32-bit words into a 256-bit word consisting of one (1) 32-bit 5 | // status word and seven (7) data words. This is done to enable relatively 6 | // efficient transmission over the FT601 together with some additional info. 7 | // 8 | // (c) Ulf Frisk, 2017-2024 9 | // Author: Ulf Frisk, pcileech@frizk.net 10 | // 11 | 12 | `timescale 1ns / 1ps 13 | 14 | module pcileech_mux( 15 | input clk, 16 | input rst, 17 | // output 18 | output [255:0] dout, 19 | output valid, 20 | input rd_en, 21 | // port0: input highest priority 22 | input [31:0] p0_din, 23 | input [1:0] p0_tag, 24 | input [1:0] p0_ctx, 25 | input p0_wr_en, 26 | output p0_req_data, 27 | // port1: 28 | input [31:0] p1_din, 29 | input [1:0] p1_tag, 30 | input [1:0] p1_ctx, 31 | input p1_wr_en, 32 | output p1_req_data, 33 | // port2: 34 | input [31:0] p2_din, 35 | input [1:0] p2_tag, 36 | input [1:0] p2_ctx, 37 | input p2_wr_en, 38 | output p2_req_data, 39 | // port3: 40 | input [31:0] p3_din, 41 | input [1:0] p3_tag, 42 | input [1:0] p3_ctx, 43 | input p3_wr_en, 44 | output p3_req_data, 45 | // port4: 46 | input [31:0] p4_din, 47 | input [1:0] p4_tag, 48 | input [1:0] p4_ctx, 49 | input p4_wr_en, 50 | output p4_req_data, 51 | // port5: 52 | input [31:0] p5_din, 53 | input [1:0] p5_tag, 54 | input [1:0] p5_ctx, 55 | input p5_wr_en, 56 | output p5_req_data, 57 | // port6: 58 | input [31:0] p6_din, 59 | input [1:0] p6_tag, 60 | input [1:0] p6_ctx, 61 | input p6_wr_en, 62 | output p6_req_data, 63 | // port7: 64 | input [31:0] p7_din, 65 | input [1:0] p7_tag, 66 | input [1:0] p7_ctx, 67 | input p7_wr_en, 68 | output p7_req_data 69 | ); 70 | 71 | // 'en' is delayed 1CLK so it's in synch with inputs. 72 | // output integrity is handled by extra register. 73 | reg en; 74 | always @ ( posedge clk ) 75 | en <= rd_en && !rst; 76 | 77 | assign p0_req_data = rd_en; 78 | assign p1_req_data = rd_en; 79 | assign p2_req_data = rd_en; 80 | assign p3_req_data = rd_en; 81 | assign p4_req_data = rd_en; 82 | assign p5_req_data = rd_en; 83 | assign p6_req_data = rd_en; 84 | assign p7_req_data = rd_en; 85 | 86 | reg [31:0] data_reg[14]; 87 | reg [3:0] ctx_reg[14]; 88 | 89 | wire p8_wr_en; 90 | reg [3:0] idx_base; 91 | wire [3:0] p0_idx = idx_base; 92 | wire [3:0] p1_idx = p0_idx + p0_wr_en; 93 | wire [3:0] p2_idx = p1_idx + p1_wr_en; 94 | wire [3:0] p3_idx = p2_idx + p2_wr_en; 95 | wire [3:0] p4_idx = p3_idx + p3_wr_en; 96 | wire [3:0] p5_idx = p4_idx + p4_wr_en; 97 | wire [3:0] p6_idx = p5_idx + p5_wr_en; 98 | wire [3:0] p7_idx = p6_idx + p6_wr_en; 99 | wire [3:0] p8_idx = p7_idx + p7_wr_en; // idle port 100 | wire [3:0] idx_max = p8_idx + p8_wr_en; // max index 101 | 102 | // P8: INTERNAL "IDLE PORT" 103 | reg [3:0] idle_count; 104 | wire [31:0] p8_din = 32'hffffffff; 105 | wire [1:0] p8_tag = 2'b11; 106 | wire [1:0] p8_ctx = 2'b11; 107 | assign p8_wr_en = en && (idx_base > 0) && (idle_count > 7) && (idx_base == p8_idx); 108 | 109 | 110 | 111 | // output buffer logic, when rd_en is deasserted the output data must be 112 | // buffered not to cause data loss. 113 | reg dout_valid; 114 | wire [255:0] dout_data = { ctx_reg[1], ctx_reg[0], ctx_reg[3], ctx_reg[2], ctx_reg[5], ctx_reg[4], 4'hE, ctx_reg[6], data_reg[0], data_reg[1], data_reg[2], data_reg[3], data_reg[4], data_reg[5], data_reg[6] }; 115 | reg dout_buf_valid; 116 | reg [255:0] dout_buf_data; 117 | assign valid = rd_en && (dout_buf_valid || dout_valid); 118 | assign dout = dout_buf_valid ? dout_buf_data : dout_data; 119 | 120 | 121 | 122 | always @ ( posedge clk ) begin 123 | if( rst ) 124 | begin 125 | idx_base <= 0; 126 | idle_count <= 0; 127 | dout_valid <= 0; 128 | dout_buf_valid <= 0; 129 | end 130 | else 131 | begin 132 | // OUTPUT BUFFER LOGIC: 133 | 134 | if( en ) begin 135 | dout_buf_valid <= 0; 136 | end else if( dout_valid ) begin 137 | dout_buf_data <= dout_data; 138 | dout_buf_valid <= 1; 139 | end 140 | 141 | // OUTPUT VALID: 142 | dout_valid <= en && (idx_max >= 7); 143 | 144 | if( en ) begin 145 | // NEXT INDEX BASE: 146 | idx_base <= idx_max - ((idx_max >= 7) ? 7 : 0); 147 | // IDLE COUNT: 148 | idle_count <= ((idx_base > 0) && (idx_base == p8_idx)) ? (idle_count + 1) : 0; 149 | // DATA/CTX writes into index [0-8]: 150 | if( p0_wr_en ) begin data_reg[p0_idx] <= p0_din; ctx_reg[p0_idx] <= {p0_ctx, p0_tag}; end 151 | if( p1_wr_en ) begin data_reg[p1_idx] <= p1_din; ctx_reg[p1_idx] <= {p1_ctx, p1_tag}; end 152 | if( p2_wr_en ) begin data_reg[p2_idx] <= p2_din; ctx_reg[p2_idx] <= {p2_ctx, p2_tag}; end 153 | if( p3_wr_en ) begin data_reg[p3_idx] <= p3_din; ctx_reg[p3_idx] <= {p3_ctx, p3_tag}; end 154 | if( p4_wr_en ) begin data_reg[p4_idx] <= p4_din; ctx_reg[p4_idx] <= {p4_ctx, p4_tag}; end 155 | if( p5_wr_en ) begin data_reg[p5_idx] <= p5_din; ctx_reg[p5_idx] <= {p5_ctx, p5_tag}; end 156 | if( p6_wr_en ) begin data_reg[p6_idx] <= p6_din; ctx_reg[p6_idx] <= {p6_ctx, p6_tag}; end 157 | if( p7_wr_en ) begin data_reg[p7_idx] <= p7_din; ctx_reg[p7_idx] <= {p7_ctx, p7_tag}; end 158 | if( p8_wr_en ) begin data_reg[p8_idx] <= p8_din; ctx_reg[p8_idx] <= {p8_ctx, p8_tag}; end 159 | end 160 | 161 | if( dout_valid ) begin 162 | // DATA/CTX previous move: 163 | if( idx_base > 0) begin data_reg[0] <= data_reg[7+0]; ctx_reg[0] <= ctx_reg[7+0]; end 164 | if( idx_base > 1) begin data_reg[1] <= data_reg[7+1]; ctx_reg[1] <= ctx_reg[7+1]; end 165 | if( idx_base > 2) begin data_reg[2] <= data_reg[7+2]; ctx_reg[2] <= ctx_reg[7+2]; end 166 | if( idx_base > 3) begin data_reg[3] <= data_reg[7+3]; ctx_reg[3] <= ctx_reg[7+3]; end 167 | if( idx_base > 4) begin data_reg[4] <= data_reg[7+4]; ctx_reg[4] <= ctx_reg[7+4]; end 168 | if( idx_base > 5) begin data_reg[5] <= data_reg[7+5]; ctx_reg[5] <= ctx_reg[7+5]; end 169 | if( idx_base > 6) begin data_reg[6] <= data_reg[7+6]; ctx_reg[6] <= ctx_reg[7+6]; end 170 | end 171 | 172 | 173 | end 174 | end 175 | endmodule 176 | -------------------------------------------------------------------------------- /src/pcileech_pcie_a7.sv: -------------------------------------------------------------------------------- 1 | // 2 | // PCILeech FPGA. 3 | // 4 | // PCIe module for Artix-7. 5 | // 6 | // (c) Ulf Frisk, 2018-2024 7 | // Author: Ulf Frisk, pcileech@frizk.net 8 | // 9 | 10 | `timescale 1ns / 1ps 11 | `include "pcileech_header.svh" 12 | 13 | module pcileech_pcie_a7( 14 | input clk_sys, 15 | input rst, 16 | 17 | // PCIe fabric 18 | output [0:0] pcie_tx_p, 19 | output [0:0] pcie_tx_n, 20 | input [0:0] pcie_rx_p, 21 | input [0:0] pcie_rx_n, 22 | input pcie_clk_p, 23 | input pcie_clk_n, 24 | input pcie_perst_n, 25 | 26 | // State and Activity LEDs 27 | output led_state, 28 | 29 | // PCIe <--> FIFOs 30 | IfPCIeFifoCfg.mp_pcie dfifo_cfg, 31 | IfPCIeFifoTlp.mp_pcie dfifo_tlp, 32 | IfPCIeFifoCore.mp_pcie dfifo_pcie, 33 | IfShadow2Fifo.shadow dshadow2fifo 34 | ); 35 | 36 | // ---------------------------------------------------------------------------- 37 | // PCIe DEFINES AND WIRES 38 | // ---------------------------------------------------------------------------- 39 | 40 | IfPCIeSignals ctx(); 41 | IfPCIeTlpRxTx tlp_tx(); 42 | IfPCIeTlpRxTx tlp_rx(); 43 | IfAXIS128 tlps_tx(); 44 | IfAXIS128 tlps_rx(); 45 | 46 | IfAXIS128 tlps_static(); // static tlp transmit from cfg->tlp 47 | wire [15:0] pcie_id; 48 | wire user_lnk_up; 49 | 50 | // system interface 51 | wire pcie_clk_c; 52 | wire clk_pcie; 53 | wire rst_pcie_user; 54 | wire rst_subsys = rst || rst_pcie_user || dfifo_pcie.pcie_rst_subsys; 55 | wire rst_pcie = rst || ~pcie_perst_n || dfifo_pcie.pcie_rst_core; 56 | 57 | // Buffer for differential system clock 58 | IBUFDS_GTE2 refclk_ibuf (.O(pcie_clk_c), .ODIV2(), .I(pcie_clk_p), .CEB(1'b0), .IB(pcie_clk_n)); 59 | 60 | // ---------------------------------------------------- 61 | // TickCount64 PCIe REFCLK and LED OUTPUT 62 | // ---------------------------------------------------- 63 | 64 | time tickcount64_pcie_refclk = 0; 65 | always @ ( posedge pcie_clk_c ) 66 | tickcount64_pcie_refclk <= tickcount64_pcie_refclk + 1; 67 | assign led_state = user_lnk_up || tickcount64_pcie_refclk[25]; 68 | 69 | // ---------------------------------------------------------------------------- 70 | // PCIe CFG RX/TX <--> FIFO below 71 | // ---------------------------------------------------------------------------- 72 | wire [31:0] base_address_register; 73 | 74 | pcileech_pcie_cfg_a7 i_pcileech_pcie_cfg_a7( 75 | .rst ( rst_subsys ), 76 | .clk_sys ( clk_sys ), 77 | .clk_pcie ( clk_pcie ), 78 | .dfifo ( dfifo_cfg ), 79 | .ctx ( ctx ), 80 | .tlps_static ( tlps_static.source ), 81 | .pcie_id ( pcie_id ), // -> [15:0] 82 | .base_address_register ( base_address_register ) 83 | ); 84 | 85 | // ---------------------------------------------------------------------------- 86 | // PCIe TLP RX/TX <--> FIFO below 87 | // ---------------------------------------------------------------------------- 88 | 89 | pcileech_tlps128_src64 i_pcileech_tlps128_src64( 90 | .rst ( rst_subsys ), 91 | .clk_pcie ( clk_pcie ), 92 | .tlp_rx ( tlp_rx.sink ), 93 | .tlps_out ( tlps_rx.source_lite ) 94 | ); 95 | 96 | pcileech_pcie_tlp_a7 i_pcileech_pcie_tlp_a7( 97 | .rst ( rst_subsys ), 98 | .clk_pcie ( clk_pcie ), 99 | .clk_sys ( clk_sys ), 100 | .dfifo ( dfifo_tlp ), 101 | .tlps_tx ( tlps_tx.source ), 102 | .tlps_rx ( tlps_rx.sink_lite ), 103 | .tlps_static ( tlps_static.sink ), 104 | .dshadow2fifo ( dshadow2fifo ), 105 | .pcie_id ( pcie_id ), // <- [15:0] 106 | .base_address_register ( base_address_register ) 107 | ); 108 | 109 | pcileech_tlps128_dst64 i_pcileech_tlps128_dst64( 110 | .rst ( rst ), 111 | .clk_pcie ( clk_pcie ), 112 | .tlp_tx ( tlp_tx.source ), 113 | .tlps_in ( tlps_tx.sink ) 114 | ); 115 | 116 | // ---------------------------------------------------------------------------- 117 | // PCIe CORE BELOW 118 | // ---------------------------------------------------------------------------- 119 | 120 | pcie_7x_0 i_pcie_7x_0 ( 121 | // pcie_7x_mgt 122 | .pci_exp_txp ( pcie_tx_p ), // -> 123 | .pci_exp_txn ( pcie_tx_n ), // -> 124 | .pci_exp_rxp ( pcie_rx_p ), // <- 125 | .pci_exp_rxn ( pcie_rx_n ), // <- 126 | .sys_clk ( pcie_clk_c ), // <- 127 | .sys_rst_n ( ~rst_pcie ), // <- 128 | 129 | // s_axis_tx (transmit data) 130 | .s_axis_tx_tdata ( tlp_tx.data ), // <- [63:0] 131 | .s_axis_tx_tkeep ( tlp_tx.keep ), // <- [7:0] 132 | .s_axis_tx_tlast ( tlp_tx.last ), // <- 133 | .s_axis_tx_tready ( tlp_tx.ready ), // -> 134 | .s_axis_tx_tuser ( 4'b0 ), // <- [3:0] 135 | .s_axis_tx_tvalid ( tlp_tx.valid ), // <- 136 | 137 | // s_axis_rx (receive data) 138 | .m_axis_rx_tdata ( tlp_rx.data ), // -> [63:0] 139 | .m_axis_rx_tkeep ( tlp_rx.keep ), // -> [7:0] 140 | .m_axis_rx_tlast ( tlp_rx.last ), // -> 141 | .m_axis_rx_tready ( tlp_rx.ready ), // <- 142 | .m_axis_rx_tuser ( tlp_rx.user ), // -> [21:0] 143 | .m_axis_rx_tvalid ( tlp_rx.valid ), // -> 144 | 145 | // pcie_cfg_mgmt 146 | .cfg_mgmt_dwaddr ( ctx.cfg_mgmt_dwaddr ), // <- [9:0] 147 | .cfg_mgmt_byte_en ( ctx.cfg_mgmt_byte_en ), // <- [3:0] 148 | .cfg_mgmt_do ( ctx.cfg_mgmt_do ), // -> [31:0] 149 | .cfg_mgmt_rd_en ( ctx.cfg_mgmt_rd_en ), // <- 150 | .cfg_mgmt_rd_wr_done ( ctx.cfg_mgmt_rd_wr_done ), // -> 151 | .cfg_mgmt_wr_readonly ( ctx.cfg_mgmt_wr_readonly ), // <- 152 | .cfg_mgmt_wr_rw1c_as_rw ( ctx.cfg_mgmt_wr_rw1c_as_rw ), // <- 153 | .cfg_mgmt_di ( ctx.cfg_mgmt_di ), // <- [31:0] 154 | .cfg_mgmt_wr_en ( ctx.cfg_mgmt_wr_en ), // <- 155 | 156 | // special core config 157 | //.pcie_cfg_vend_id ( dfifo_pcie.pcie_cfg_vend_id ), // <- [15:0] 158 | //.pcie_cfg_dev_id ( dfifo_pcie.pcie_cfg_dev_id ), // <- [15:0] 159 | //.pcie_cfg_rev_id ( dfifo_pcie.pcie_cfg_rev_id ), // <- [7:0] 160 | //.pcie_cfg_subsys_vend_id ( dfifo_pcie.pcie_cfg_subsys_vend_id ), // <- [15:0] 161 | //.pcie_cfg_subsys_id ( dfifo_pcie.pcie_cfg_subsys_id ), // <- [15:0] 162 | 163 | // pcie2_cfg_interrupt 164 | .cfg_interrupt_assert ( ctx.cfg_interrupt_assert ), // <- 165 | .cfg_interrupt ( ctx.cfg_interrupt ), // <- 166 | .cfg_interrupt_mmenable ( ctx.cfg_interrupt_mmenable ), // -> [2:0] 167 | .cfg_interrupt_msienable ( ctx.cfg_interrupt_msienable ), // -> 168 | .cfg_interrupt_msixenable ( ctx.cfg_interrupt_msixenable ), // -> 169 | .cfg_interrupt_msixfm ( ctx.cfg_interrupt_msixfm ), // -> 170 | .cfg_pciecap_interrupt_msgnum ( ctx.cfg_pciecap_interrupt_msgnum ), // <- [4:0] 171 | .cfg_interrupt_rdy ( ctx.cfg_interrupt_rdy ), // -> 172 | .cfg_interrupt_do ( ctx.cfg_interrupt_do ), // -> [7:0] 173 | .cfg_interrupt_stat ( ctx.cfg_interrupt_stat ), // <- 174 | .cfg_interrupt_di ( ctx.cfg_interrupt_di ), // <- [7:0] 175 | 176 | // pcie2_cfg_control 177 | .cfg_ds_bus_number ( ctx.cfg_bus_number ), // <- [7:0] 178 | .cfg_ds_device_number ( ctx.cfg_device_number ), // <- [4:0] 179 | .cfg_ds_function_number ( ctx.cfg_function_number ), // <- [2:0] 180 | .cfg_dsn ( ctx.cfg_dsn ), // <- [63:0] 181 | .cfg_pm_force_state ( ctx.cfg_pm_force_state ), // <- [1:0] 182 | .cfg_pm_force_state_en ( ctx.cfg_pm_force_state_en ), // <- 183 | .cfg_pm_halt_aspm_l0s ( ctx.cfg_pm_halt_aspm_l0s ), // <- 184 | .cfg_pm_halt_aspm_l1 ( ctx.cfg_pm_halt_aspm_l1 ), // <- 185 | .cfg_pm_send_pme_to ( ctx.cfg_pm_send_pme_to ), // <- 186 | .cfg_pm_wake ( ctx.cfg_pm_wake ), // <- 187 | .rx_np_ok ( ctx.rx_np_ok ), // <- 188 | .rx_np_req ( ctx.rx_np_req ), // <- 189 | .cfg_trn_pending ( ctx.cfg_trn_pending ), // <- 190 | .cfg_turnoff_ok ( ctx.cfg_turnoff_ok ), // <- 191 | .tx_cfg_gnt ( ctx.tx_cfg_gnt ), // <- 192 | 193 | // pcie2_cfg_status 194 | .cfg_command ( ctx.cfg_command ), // -> [15:0] 195 | .cfg_bus_number ( ctx.cfg_bus_number ), // -> [7:0] 196 | .cfg_device_number ( ctx.cfg_device_number ), // -> [4:0] 197 | .cfg_function_number ( ctx.cfg_function_number ), // -> [2:0] 198 | .cfg_root_control_pme_int_en( ctx.cfg_root_control_pme_int_en ), // -> 199 | .cfg_bridge_serr_en ( ctx.cfg_bridge_serr_en ), // -> 200 | .cfg_dcommand ( ctx.cfg_dcommand ), // -> [15:0] 201 | .cfg_dcommand2 ( ctx.cfg_dcommand2 ), // -> [15:0] 202 | .cfg_dstatus ( ctx.cfg_dstatus ), // -> [15:0] 203 | .cfg_lcommand ( ctx.cfg_lcommand ), // -> [15:0] 204 | .cfg_lstatus ( ctx.cfg_lstatus ), // -> [15:0] 205 | .cfg_pcie_link_state ( ctx.cfg_pcie_link_state ), // -> [2:0] 206 | .cfg_pmcsr_pme_en ( ctx.cfg_pmcsr_pme_en ), // -> 207 | .cfg_pmcsr_pme_status ( ctx.cfg_pmcsr_pme_status ), // -> 208 | .cfg_pmcsr_powerstate ( ctx.cfg_pmcsr_powerstate ), // -> [1:0] 209 | .cfg_received_func_lvl_rst ( ctx.cfg_received_func_lvl_rst ), // -> 210 | .cfg_status ( ctx.cfg_status ), // -> [15:0] 211 | .cfg_to_turnoff ( ctx.cfg_to_turnoff ), // -> 212 | .tx_buf_av ( ctx.tx_buf_av ), // -> [5:0] 213 | .tx_cfg_req ( ctx.tx_cfg_req ), // -> 214 | .tx_err_drop ( ctx.tx_err_drop ), // -> 215 | .cfg_vc_tcvc_map ( ctx.cfg_vc_tcvc_map ), // -> [6:0] 216 | .cfg_aer_rooterr_corr_err_received ( ctx.cfg_aer_rooterr_corr_err_received ), // -> 217 | .cfg_aer_rooterr_corr_err_reporting_en ( ctx.cfg_aer_rooterr_corr_err_reporting_en ), // -> 218 | .cfg_aer_rooterr_fatal_err_received ( ctx.cfg_aer_rooterr_fatal_err_received ), // -> 219 | .cfg_aer_rooterr_fatal_err_reporting_en ( ctx.cfg_aer_rooterr_fatal_err_reporting_en ), // -> 220 | .cfg_aer_rooterr_non_fatal_err_received ( ctx.cfg_aer_rooterr_non_fatal_err_received ), // -> 221 | .cfg_aer_rooterr_non_fatal_err_reporting_en ( ctx.cfg_aer_rooterr_non_fatal_err_reporting_en ), // -> 222 | .cfg_root_control_syserr_corr_err_en ( ctx.cfg_root_control_syserr_corr_err_en ), // -> 223 | .cfg_root_control_syserr_fatal_err_en ( ctx.cfg_root_control_syserr_fatal_err_en ), // -> 224 | .cfg_root_control_syserr_non_fatal_err_en ( ctx.cfg_root_control_syserr_non_fatal_err_en ), // -> 225 | .cfg_slot_control_electromech_il_ctl_pulse ( ctx.cfg_slot_control_electromech_il_ctl_pulse ), // -> 226 | 227 | // PCIe core PHY 228 | .pl_initial_link_width ( ctx.pl_initial_link_width ), // -> [2:0] 229 | .pl_phy_lnk_up ( ctx.pl_phy_lnk_up ), // -> 230 | .pl_lane_reversal_mode ( ctx.pl_lane_reversal_mode ), // -> [1:0] 231 | .pl_link_gen2_cap ( ctx.pl_link_gen2_cap ), // -> 232 | .pl_link_partner_gen2_supported ( ctx.pl_link_partner_gen2_supported ), // -> 233 | .pl_link_upcfg_cap ( ctx.pl_link_upcfg_cap ), // -> 234 | .pl_sel_lnk_rate ( ctx.pl_sel_lnk_rate ), // -> 235 | .pl_sel_lnk_width ( ctx.pl_sel_lnk_width ), // -> [1:0] 236 | .pl_ltssm_state ( ctx.pl_ltssm_state ), // -> [5:0] 237 | .pl_rx_pm_state ( ctx.pl_rx_pm_state ), // -> [1:0] 238 | .pl_tx_pm_state ( ctx.pl_tx_pm_state ), // -> [2:0] 239 | .pl_directed_change_done ( ctx.pl_directed_change_done ), // -> 240 | .pl_received_hot_rst ( ctx.pl_received_hot_rst ), // -> 241 | .pl_directed_link_auton ( ctx.pl_directed_link_auton ), // <- 242 | .pl_directed_link_change ( ctx.pl_directed_link_change ), // <- [1:0] 243 | .pl_directed_link_speed ( ctx.pl_directed_link_speed ), // <- 244 | .pl_directed_link_width ( ctx.pl_directed_link_width ), // <- [1:0] 245 | .pl_upstream_prefer_deemph ( ctx.pl_upstream_prefer_deemph ), // <- 246 | .pl_transmit_hot_rst ( ctx.pl_transmit_hot_rst ), // <- 247 | .pl_downstream_deemph_source( ctx.pl_downstream_deemph_source ), // <- 248 | 249 | // DRP - clock domain clk_100 - write should only happen when core is in reset state ... 250 | .pcie_drp_clk ( clk_sys ), // <- 251 | .pcie_drp_en ( dfifo_pcie.drp_en ), // <- 252 | .pcie_drp_we ( dfifo_pcie.drp_we ), // <- 253 | .pcie_drp_addr ( dfifo_pcie.drp_addr ), // <- [8:0] 254 | .pcie_drp_di ( dfifo_pcie.drp_di ), // <- [15:0] 255 | .pcie_drp_rdy ( dfifo_pcie.drp_rdy ), // -> 256 | .pcie_drp_do ( dfifo_pcie.drp_do ), // -> [15:0] 257 | 258 | // user interface 259 | .user_clk_out ( clk_pcie ), // -> 260 | .user_reset_out ( rst_pcie_user ), // -> 261 | .user_lnk_up ( user_lnk_up ), // -> 262 | .user_app_rdy ( ) // -> 263 | ); 264 | 265 | endmodule 266 | 267 | 268 | // ------------------------------------------------------------------------ 269 | // TLP STREAM SINK: 270 | // Convert a 128-bit TLP-AXI-STREAM to a 64-bit PCIe core AXI-STREAM. 271 | // ------------------------------------------------------------------------ 272 | module pcileech_tlps128_dst64( 273 | input rst, 274 | input clk_pcie, 275 | IfPCIeTlpRxTx.source tlp_tx, 276 | IfAXIS128.sink tlps_in 277 | ); 278 | 279 | bit [63:0] d1_tdata; 280 | bit d1_tkeepdw2; 281 | bit d1_tlast; 282 | bit d1_tvalid = 0; 283 | 284 | assign tlps_in.tready = tlp_tx.ready && !(tlps_in.tvalid && tlps_in.tkeepdw[2]); 285 | 286 | wire tkeepdw2 = d1_tvalid ? d1_tkeepdw2 : tlps_in.tkeepdw[1]; 287 | assign tlp_tx.data = d1_tvalid ? d1_tdata : tlps_in.tdata[63:0]; 288 | assign tlp_tx.last = d1_tvalid ? d1_tlast : (tlps_in.tlast && !tlps_in.tkeepdw[2]); 289 | assign tlp_tx.keep = tkeepdw2 ? 8'hff : 8'h0f; 290 | assign tlp_tx.valid = d1_tvalid || tlps_in.tvalid; 291 | 292 | always @ ( posedge clk_pcie ) begin 293 | d1_tvalid <= !rst && tlps_in.tvalid && tlps_in.tkeepdw[2]; 294 | d1_tdata <= tlps_in.tdata[127:64]; 295 | d1_tlast <= tlps_in.tlast; 296 | d1_tkeepdw2 <= tlps_in.tkeepdw[3]; 297 | end 298 | 299 | endmodule 300 | 301 | 302 | // ------------------------------------------------------------------------ 303 | // TLP STREAM SOURCE: 304 | // Convert a 64-bit PCIe core AXIS to a 128-bit TLP-AXI-STREAM 305 | // ------------------------------------------------------------------------ 306 | module pcileech_tlps128_src64( 307 | input rst, 308 | input clk_pcie, 309 | IfPCIeTlpRxTx.sink tlp_rx, 310 | IfAXIS128.source_lite tlps_out 311 | ); 312 | 313 | bit [127:0] tdata; 314 | bit first = 1; 315 | bit tlast = 0; 316 | bit [3:0] len = 0; 317 | bit [6:0] bar_hit = 0; 318 | wire tvalid = tlast || (len>2); 319 | 320 | assign tlp_rx.ready = 1'b1; 321 | assign tlps_out.tdata = tdata; 322 | assign tlps_out.tkeepdw = {(len>3), (len>2), (len>1), 1'b1}; 323 | assign tlps_out.tlast = tlast; 324 | assign tlps_out.tvalid = tvalid; 325 | assign tlps_out.tuser[0] = first; 326 | assign tlps_out.tuser[1] = tlast; 327 | assign tlps_out.tuser[8:2] = bar_hit; 328 | 329 | wire [3:0] next_base = (tlast || tvalid) ? 0 : len; 330 | wire [3:0] next_len = next_base + 1 + tlp_rx.keep[4]; 331 | 332 | always @ ( posedge clk_pcie ) 333 | if ( rst ) begin 334 | first <= 1; 335 | tlast <= 0; 336 | len <= 0; 337 | bar_hit <= 0; 338 | end 339 | else if ( tlp_rx.valid ) begin 340 | tdata[(32*next_base)+:64] <= tlp_rx.data; 341 | first <= tvalid ? tlast : first; 342 | tlast <= tlp_rx.last; 343 | len <= next_len; 344 | bar_hit <= tlp_rx.user[8:2]; 345 | end 346 | else if ( tvalid ) begin 347 | first <= tlast; 348 | tlast <= 0; 349 | len <= 0; 350 | bar_hit <= 0; 351 | end 352 | 353 | endmodule 354 | -------------------------------------------------------------------------------- /src/pcileech_pcie_a7x4.sv: -------------------------------------------------------------------------------- 1 | // 2 | // PCILeech FPGA. 3 | // 4 | // PCIe module for Artix-7. 5 | // 6 | // (c) Ulf Frisk, 2018-2024 7 | // Author: Ulf Frisk, pcileech@frizk.net 8 | // 9 | 10 | `timescale 1ns / 1ps 11 | `include "pcileech_header.svh" 12 | 13 | module pcileech_pcie_a7x4( 14 | input clk_sys, 15 | input rst, 16 | 17 | // PCIe fabric 18 | output [3:0] pcie_tx_p, 19 | output [3:0] pcie_tx_n, 20 | input [3:0] pcie_rx_p, 21 | input [3:0] pcie_rx_n, 22 | input pcie_clk_p, 23 | input pcie_clk_n, 24 | input pcie_perst_n, 25 | 26 | // State and Activity LEDs 27 | output led_state, 28 | 29 | // PCIe <--> FIFOs 30 | IfPCIeFifoCfg.mp_pcie dfifo_cfg, 31 | IfPCIeFifoTlp.mp_pcie dfifo_tlp, 32 | IfPCIeFifoCore.mp_pcie dfifo_pcie, 33 | IfShadow2Fifo.shadow dshadow2fifo 34 | ); 35 | 36 | // ---------------------------------------------------------------------------- 37 | // PCIe DEFINES AND WIRES 38 | // ---------------------------------------------------------------------------- 39 | 40 | IfPCIeSignals ctx(); 41 | IfAXIS128 tlp_tx(); 42 | IfPCIeTlpRx128 tlp_rx(); 43 | IfAXIS128 tlps_tx(); 44 | IfAXIS128 tlps_rx(); 45 | 46 | IfAXIS128 tlps_static(); // static tlp transmit from cfg->tlp 47 | wire [15:0] pcie_id; 48 | wire user_lnk_up; 49 | 50 | // system interface 51 | wire pcie_clk_c; 52 | wire clk_pcie; 53 | wire rst_pcie_user; 54 | wire rst_subsys = rst || rst_pcie_user || dfifo_pcie.pcie_rst_subsys; 55 | wire rst_pcie = rst || ~pcie_perst_n || dfifo_pcie.pcie_rst_core; 56 | 57 | // Buffer for differential system clock 58 | IBUFDS_GTE2 refclk_ibuf (.O(pcie_clk_c), .ODIV2(), .I(pcie_clk_p), .CEB(1'b0), .IB(pcie_clk_n)); 59 | 60 | // ---------------------------------------------------- 61 | // TickCount64 PCIe REFCLK and LED OUTPUT 62 | // ---------------------------------------------------- 63 | 64 | time tickcount64_pcie_refclk = 0; 65 | always @ ( posedge pcie_clk_c ) 66 | tickcount64_pcie_refclk <= tickcount64_pcie_refclk + 1; 67 | assign led_state = user_lnk_up || tickcount64_pcie_refclk[25]; 68 | 69 | // ---------------------------------------------------------------------------- 70 | // PCIe CFG RX/TX <--> FIFO below 71 | // ---------------------------------------------------------------------------- 72 | wire [31:0] base_address_register; 73 | pcileech_pcie_cfg_a7 i_pcileech_pcie_cfg_a7( 74 | .rst ( rst_subsys ), 75 | .clk_sys ( clk_sys ), 76 | .clk_pcie ( clk_pcie ), 77 | .dfifo ( dfifo_cfg ), 78 | .ctx ( ctx ), 79 | .tlps_static ( tlps_static.source ), 80 | .pcie_id ( pcie_id ), // -> [15:0] 81 | .base_address_register ( base_address_register ) 82 | ); 83 | 84 | // ---------------------------------------------------------------------------- 85 | // PCIe TLP RX/TX <--> FIFO below 86 | // ---------------------------------------------------------------------------- 87 | 88 | pcileech_tlps128_src128 i_pcileech_tlps128_src128( 89 | .rst ( rst_subsys ), 90 | .clk_pcie ( clk_pcie ), 91 | .tlp_rx ( tlp_rx.sink ), 92 | .tlps_out ( tlps_rx.source_lite ) 93 | ); 94 | 95 | pcileech_pcie_tlp_a7 i_pcileech_pcie_tlp_a7( 96 | .rst ( rst_subsys ), 97 | .clk_pcie ( clk_pcie ), 98 | .clk_sys ( clk_sys ), 99 | .dfifo ( dfifo_tlp ), 100 | .tlps_tx ( tlps_tx.source ), 101 | .tlps_rx ( tlps_rx.sink_lite ), 102 | .tlps_static ( tlps_static.sink ), 103 | .dshadow2fifo ( dshadow2fifo ), 104 | .pcie_id ( pcie_id ), // <- [15:0] 105 | .base_address_register ( base_address_register ) 106 | ); 107 | 108 | pcileech_tlps128_dst128 i_pcileech_tlps128_dst128( 109 | .rst ( rst_subsys ), 110 | .clk_pcie ( clk_pcie ), 111 | .tlps_in ( tlps_tx.sink ), 112 | .tlps_out ( tlp_tx.source ) 113 | ); 114 | 115 | wire [15:0] tlp_tx_tkeep; 116 | assign tlp_tx_tkeep[3:0] = tlp_tx.tkeepdw[0] ? 4'hf : 4'h0; 117 | assign tlp_tx_tkeep[7:4] = tlp_tx.tkeepdw[1] ? 4'hf : 4'h0; 118 | assign tlp_tx_tkeep[11:8] = tlp_tx.tkeepdw[2] ? 4'hf : 4'h0; 119 | assign tlp_tx_tkeep[15:12] = tlp_tx.tkeepdw[3] ? 4'hf : 4'h0; 120 | 121 | // ---------------------------------------------------------------------------- 122 | // PCIe CORE BELOW 123 | // ---------------------------------------------------------------------------- 124 | 125 | pcie_7x_0 i_pcie_7x_0 ( 126 | // pcie_7x_mgt 127 | .pci_exp_txp ( pcie_tx_p ), // -> 128 | .pci_exp_txn ( pcie_tx_n ), // -> 129 | .pci_exp_rxp ( pcie_rx_p ), // <- 130 | .pci_exp_rxn ( pcie_rx_n ), // <- 131 | .sys_clk ( pcie_clk_c ), // <- 132 | .sys_rst_n ( ~rst_pcie ), // <- 133 | 134 | // s_axis_tx (transmit data) - 128-bit AXIS 135 | .s_axis_tx_tdata ( tlp_tx.tdata ), // <- [127:0] 136 | .s_axis_tx_tkeep ( tlp_tx_tkeep ), // <- [15:0] 137 | .s_axis_tx_tlast ( tlp_tx.tlast ), // <- 138 | .s_axis_tx_tready ( tlp_tx.tready ), // -> 139 | .s_axis_tx_tuser ( 4'b0000 ), // <- [3:0] 140 | .s_axis_tx_tvalid ( tlp_tx.tvalid ), // <- 141 | // s_axis_rx (receive data) - 128-bit AXIS 142 | .m_axis_rx_tdata ( tlp_rx.data ), // -> [127:0] 143 | .m_axis_rx_tkeep ( ), // -> [15:0] 144 | .m_axis_rx_tlast ( ), // -> 145 | .m_axis_rx_tready ( tlp_rx.ready ), // <- 146 | .m_axis_rx_tuser ( tlp_rx.user ), // -> [21:0] 147 | .m_axis_rx_tvalid ( tlp_rx.valid ), // -> 148 | 149 | // pcie_cfg_mgmt 150 | .cfg_mgmt_dwaddr ( ctx.cfg_mgmt_dwaddr ), // <- [9:0] 151 | .cfg_mgmt_byte_en ( ctx.cfg_mgmt_byte_en ), // <- [3:0] 152 | .cfg_mgmt_do ( ctx.cfg_mgmt_do ), // -> [31:0] 153 | .cfg_mgmt_rd_en ( ctx.cfg_mgmt_rd_en ), // <- 154 | .cfg_mgmt_rd_wr_done ( ctx.cfg_mgmt_rd_wr_done ), // -> 155 | .cfg_mgmt_wr_readonly ( ctx.cfg_mgmt_wr_readonly ), // <- 156 | .cfg_mgmt_wr_rw1c_as_rw ( ctx.cfg_mgmt_wr_rw1c_as_rw ), // <- 157 | .cfg_mgmt_di ( ctx.cfg_mgmt_di ), // <- [31:0] 158 | .cfg_mgmt_wr_en ( ctx.cfg_mgmt_wr_en ), // <- 159 | 160 | // special core config 161 | //.pcie_cfg_vend_id ( dfifo_pcie.pcie_cfg_vend_id ), // <- [15:0] 162 | //.pcie_cfg_dev_id ( dfifo_pcie.pcie_cfg_dev_id ), // <- [15:0] 163 | //.pcie_cfg_rev_id ( dfifo_pcie.pcie_cfg_rev_id ), // <- [7:0] 164 | //.pcie_cfg_subsys_vend_id ( dfifo_pcie.pcie_cfg_subsys_vend_id ), // <- [15:0] 165 | //.pcie_cfg_subsys_id ( dfifo_pcie.pcie_cfg_subsys_id ), // <- [15:0] 166 | 167 | // pcie2_cfg_interrupt 168 | .cfg_interrupt_assert ( ctx.cfg_interrupt_assert ), // <- 169 | .cfg_interrupt ( ctx.cfg_interrupt ), // <- 170 | .cfg_interrupt_mmenable ( ctx.cfg_interrupt_mmenable ), // -> [2:0] 171 | .cfg_interrupt_msienable ( ctx.cfg_interrupt_msienable ), // -> 172 | .cfg_interrupt_msixenable ( ctx.cfg_interrupt_msixenable ), // -> 173 | .cfg_interrupt_msixfm ( ctx.cfg_interrupt_msixfm ), // -> 174 | .cfg_pciecap_interrupt_msgnum ( ctx.cfg_pciecap_interrupt_msgnum ), // <- [4:0] 175 | .cfg_interrupt_rdy ( ctx.cfg_interrupt_rdy ), // -> 176 | .cfg_interrupt_do ( ctx.cfg_interrupt_do ), // -> [7:0] 177 | .cfg_interrupt_stat ( ctx.cfg_interrupt_stat ), // <- 178 | .cfg_interrupt_di ( ctx.cfg_interrupt_di ), // <- [7:0] 179 | 180 | // pcie2_cfg_control 181 | .cfg_ds_bus_number ( ctx.cfg_bus_number ), // <- [7:0] 182 | .cfg_ds_device_number ( ctx.cfg_device_number ), // <- [4:0] 183 | .cfg_ds_function_number ( ctx.cfg_function_number ), // <- [2:0] 184 | .cfg_dsn ( ctx.cfg_dsn ), // <- [63:0] 185 | .cfg_pm_force_state ( ctx.cfg_pm_force_state ), // <- [1:0] 186 | .cfg_pm_force_state_en ( ctx.cfg_pm_force_state_en ), // <- 187 | .cfg_pm_halt_aspm_l0s ( ctx.cfg_pm_halt_aspm_l0s ), // <- 188 | .cfg_pm_halt_aspm_l1 ( ctx.cfg_pm_halt_aspm_l1 ), // <- 189 | .cfg_pm_send_pme_to ( ctx.cfg_pm_send_pme_to ), // <- 190 | .cfg_pm_wake ( ctx.cfg_pm_wake ), // <- 191 | .rx_np_ok ( ctx.rx_np_ok ), // <- 192 | .rx_np_req ( ctx.rx_np_req ), // <- 193 | .cfg_trn_pending ( ctx.cfg_trn_pending ), // <- 194 | .cfg_turnoff_ok ( ctx.cfg_turnoff_ok ), // <- 195 | .tx_cfg_gnt ( ctx.tx_cfg_gnt ), // <- 196 | 197 | // pcie2_cfg_status 198 | .cfg_command ( ctx.cfg_command ), // -> [15:0] 199 | .cfg_bus_number ( ctx.cfg_bus_number ), // -> [7:0] 200 | .cfg_device_number ( ctx.cfg_device_number ), // -> [4:0] 201 | .cfg_function_number ( ctx.cfg_function_number ), // -> [2:0] 202 | .cfg_root_control_pme_int_en( ctx.cfg_root_control_pme_int_en ), // -> 203 | .cfg_bridge_serr_en ( ctx.cfg_bridge_serr_en ), // -> 204 | .cfg_dcommand ( ctx.cfg_dcommand ), // -> [15:0] 205 | .cfg_dcommand2 ( ctx.cfg_dcommand2 ), // -> [15:0] 206 | .cfg_dstatus ( ctx.cfg_dstatus ), // -> [15:0] 207 | .cfg_lcommand ( ctx.cfg_lcommand ), // -> [15:0] 208 | .cfg_lstatus ( ctx.cfg_lstatus ), // -> [15:0] 209 | .cfg_pcie_link_state ( ctx.cfg_pcie_link_state ), // -> [2:0] 210 | .cfg_pmcsr_pme_en ( ctx.cfg_pmcsr_pme_en ), // -> 211 | .cfg_pmcsr_pme_status ( ctx.cfg_pmcsr_pme_status ), // -> 212 | .cfg_pmcsr_powerstate ( ctx.cfg_pmcsr_powerstate ), // -> [1:0] 213 | .cfg_received_func_lvl_rst ( ctx.cfg_received_func_lvl_rst ), // -> 214 | .cfg_status ( ctx.cfg_status ), // -> [15:0] 215 | .cfg_to_turnoff ( ctx.cfg_to_turnoff ), // -> 216 | .tx_buf_av ( ctx.tx_buf_av ), // -> [5:0] 217 | .tx_cfg_req ( ctx.tx_cfg_req ), // -> 218 | .tx_err_drop ( ctx.tx_err_drop ), // -> 219 | .cfg_vc_tcvc_map ( ctx.cfg_vc_tcvc_map ), // -> [6:0] 220 | .cfg_aer_rooterr_corr_err_received ( ctx.cfg_aer_rooterr_corr_err_received ), // -> 221 | .cfg_aer_rooterr_corr_err_reporting_en ( ctx.cfg_aer_rooterr_corr_err_reporting_en ), // -> 222 | .cfg_aer_rooterr_fatal_err_received ( ctx.cfg_aer_rooterr_fatal_err_received ), // -> 223 | .cfg_aer_rooterr_fatal_err_reporting_en ( ctx.cfg_aer_rooterr_fatal_err_reporting_en ), // -> 224 | .cfg_aer_rooterr_non_fatal_err_received ( ctx.cfg_aer_rooterr_non_fatal_err_received ), // -> 225 | .cfg_aer_rooterr_non_fatal_err_reporting_en ( ctx.cfg_aer_rooterr_non_fatal_err_reporting_en ), // -> 226 | .cfg_root_control_syserr_corr_err_en ( ctx.cfg_root_control_syserr_corr_err_en ), // -> 227 | .cfg_root_control_syserr_fatal_err_en ( ctx.cfg_root_control_syserr_fatal_err_en ), // -> 228 | .cfg_root_control_syserr_non_fatal_err_en ( ctx.cfg_root_control_syserr_non_fatal_err_en ), // -> 229 | .cfg_slot_control_electromech_il_ctl_pulse ( ctx.cfg_slot_control_electromech_il_ctl_pulse ), // -> 230 | 231 | // PCIe core PHY 232 | .pl_initial_link_width ( ctx.pl_initial_link_width ), // -> [2:0] 233 | .pl_phy_lnk_up ( ctx.pl_phy_lnk_up ), // -> 234 | .pl_lane_reversal_mode ( ctx.pl_lane_reversal_mode ), // -> [1:0] 235 | .pl_link_gen2_cap ( ctx.pl_link_gen2_cap ), // -> 236 | .pl_link_partner_gen2_supported ( ctx.pl_link_partner_gen2_supported ), // -> 237 | .pl_link_upcfg_cap ( ctx.pl_link_upcfg_cap ), // -> 238 | .pl_sel_lnk_rate ( ctx.pl_sel_lnk_rate ), // -> 239 | .pl_sel_lnk_width ( ctx.pl_sel_lnk_width ), // -> [1:0] 240 | .pl_ltssm_state ( ctx.pl_ltssm_state ), // -> [5:0] 241 | .pl_rx_pm_state ( ctx.pl_rx_pm_state ), // -> [1:0] 242 | .pl_tx_pm_state ( ctx.pl_tx_pm_state ), // -> [2:0] 243 | .pl_directed_change_done ( ctx.pl_directed_change_done ), // -> 244 | .pl_received_hot_rst ( ctx.pl_received_hot_rst ), // -> 245 | .pl_directed_link_auton ( ctx.pl_directed_link_auton ), // <- 246 | .pl_directed_link_change ( ctx.pl_directed_link_change ), // <- [1:0] 247 | .pl_directed_link_speed ( ctx.pl_directed_link_speed ), // <- 248 | .pl_directed_link_width ( ctx.pl_directed_link_width ), // <- [1:0] 249 | .pl_upstream_prefer_deemph ( ctx.pl_upstream_prefer_deemph ), // <- 250 | .pl_transmit_hot_rst ( ctx.pl_transmit_hot_rst ), // <- 251 | .pl_downstream_deemph_source( ctx.pl_downstream_deemph_source ), // <- 252 | 253 | // DRP - clock domain clk - write should only happen when core is in reset state ... 254 | .pcie_drp_clk ( clk_sys ), // <- 255 | .pcie_drp_en ( dfifo_pcie.drp_en ), // <- 256 | .pcie_drp_we ( dfifo_pcie.drp_we ), // <- 257 | .pcie_drp_addr ( dfifo_pcie.drp_addr ), // <- [8:0] 258 | .pcie_drp_di ( dfifo_pcie.drp_di ), // <- [15:0] 259 | .pcie_drp_rdy ( dfifo_pcie.drp_rdy ), // -> 260 | .pcie_drp_do ( dfifo_pcie.drp_do ), // -> [15:0] 261 | 262 | // user interface 263 | .user_clk_out ( clk_pcie ), // -> 264 | .user_reset_out ( rst_pcie_user ), // -> 265 | .user_lnk_up ( user_lnk_up ), // -> 266 | .user_app_rdy ( ) // -> 267 | ); 268 | 269 | endmodule 270 | 271 | // ------------------------------------------------------------------------ 272 | // TLP STREAM SINK: 273 | // Convert a 128-bit TLP-AXI-STREAM to a 128-bit PCIe core AXI-STREAM. 274 | // ------------------------------------------------------------------------ 275 | module pcileech_tlps128_dst128( 276 | input rst, 277 | input clk_pcie, 278 | IfAXIS128.source tlps_out, 279 | IfAXIS128.sink tlps_in 280 | ); 281 | 282 | bit [127:0] d_tdata; 283 | bit [3:0] d_tkeepdw; 284 | bit d_tlast; 285 | bit d_tvalid; 286 | always @ ( posedge clk_pcie ) begin 287 | if ( rst ) begin 288 | d_tvalid <= 0; 289 | end 290 | else if ( tlps_in.tvalid ) begin 291 | d_tdata <= tlps_in.tdata; 292 | d_tkeepdw <= tlps_in.tkeepdw; 293 | d_tlast <= tlps_in.tlast; 294 | d_tvalid <= !tlps_out.tready; 295 | end 296 | else if ( tlps_out.tready ) begin 297 | d_tvalid <= 0; 298 | end 299 | end 300 | 301 | assign tlps_in.tready = tlps_out.tready && !d_tvalid; 302 | assign tlps_out.tdata = d_tvalid ? d_tdata : tlps_in.tdata; 303 | assign tlps_out.tkeepdw = d_tvalid ? d_tkeepdw : tlps_in.tkeepdw; 304 | assign tlps_out.tlast = d_tvalid ? d_tlast : tlps_in.tlast; 305 | assign tlps_out.tvalid = d_tvalid || tlps_in.tvalid; 306 | 307 | endmodule 308 | 309 | // ------------------------------------------------------------------------ 310 | // TLP STREAM SOURCE: 311 | // Convert a 128-bit PCIe core AXIS to a 128-bit TLP-AXI-STREAM 312 | // ------------------------------------------------------------------------ 313 | module pcileech_tlps128_src128( 314 | input rst, 315 | input clk_pcie, 316 | IfPCIeTlpRx128.sink tlp_rx, 317 | IfAXIS128.source_lite tlps_out 318 | ); 319 | 320 | bit rxd_ready; 321 | wire [127:0] rxf_data = tlp_rx.data; 322 | wire [21:0] rxf_user = tlp_rx.user; 323 | wire rxf_valid = tlp_rx.valid && rxd_ready; 324 | wire rxf_ready; 325 | assign tlp_rx.ready = rxf_ready; 326 | 327 | bit rxd_sof; 328 | bit rxd_eof; 329 | bit rxd_eof_dw; 330 | bit [6:0] rxd_bar_hit; 331 | bit [63:0] rxd_data_qw; 332 | bit rxd_valid; 333 | 334 | wire [63:0] rxf_data_qw0 = rxf_data[63:0]; 335 | wire [63:0] rxf_data_qw1 = rxf_data[127:64]; 336 | wire rxf_sof = rxf_user[14]; 337 | wire rxf_sof_qw = rxf_user[13]; 338 | wire rxf_eof = rxf_user[21]; 339 | wire [1:0] rxf_eof_dw = rxf_user[20:19]; 340 | wire [6:0] rxf_bar_hit = rxf_user[8:2]; 341 | 342 | wire [3:0] rx_keep_dw; 343 | 344 | assign rxf_ready = !(rxd_valid && rxf_eof && (rxf_eof_dw >= 2)) || !rxf_valid; 345 | 346 | assign tlps_out.tdata = rxd_valid ? {rxf_data_qw0, rxd_data_qw} : {rxf_data_qw1, rxf_data_qw0}; 347 | assign tlps_out.tuser[0] = rxd_valid ? rxd_sof : (rxf_sof && !rxf_sof_qw); // tfirst 348 | assign tlps_out.tuser[1] = rxd_valid ? (rxd_eof || (rxf_eof && (rxf_eof_dw <= 1))) : rxf_eof; // tlast 349 | assign tlps_out.tuser[8:2] = rxd_valid ? rxd_bar_hit : rxf_bar_hit; 350 | assign tlps_out.tlast = tlps_out.tuser[1]; 351 | assign tlps_out.tvalid = rxd_valid || (rxf_valid && rxf_eof) || (rxf_valid && !(rxf_sof && rxf_sof_qw)); 352 | 353 | assign tlps_out.tkeepdw[0] = rxd_valid || rxf_valid; 354 | assign tlps_out.tkeepdw[1] = rxd_valid ? (!rxd_eof || rxd_eof_dw) : 355 | (!rxf_eof || (rxf_eof_dw >= 1)); 356 | assign tlps_out.tkeepdw[2] = rxd_valid ? (!rxd_eof && rxf_valid) : 357 | (!rxf_eof || (rxf_eof_dw >= 2)); 358 | assign tlps_out.tkeepdw[3] = rxd_valid ? (!rxd_eof && rxf_valid && (!rxf_eof || (rxf_eof_dw >= 1))) : 359 | (!rxf_eof || (rxf_eof_dw >= 3)); 360 | 361 | wire rxf_rxd_valid_next = !rst && rxf_valid && (rxd_valid ? ((!rxf_sof && !rxf_eof) || (rxf_sof && rxf_sof_qw) || (rxf_eof && (rxf_eof_dw >= 2))) : 362 | (rxf_sof && rxf_sof_qw)); 363 | 364 | always @ ( posedge clk_pcie ) begin 365 | rxd_ready <= rxf_ready; 366 | rxd_bar_hit <= rxf_bar_hit; 367 | rxd_data_qw <= rxf_data_qw1; 368 | rxd_sof <= rxf_sof && rxf_sof_qw; 369 | rxd_eof <= rxf_eof && (rxf_eof_dw >= 2); 370 | rxd_eof_dw <= (rxf_eof_dw == 3); 371 | rxd_valid <= rxf_rxd_valid_next; 372 | end 373 | 374 | endmodule -------------------------------------------------------------------------------- /src/pcileech_pcie_cfgspace_shadow.sv: -------------------------------------------------------------------------------- 1 | // 2 | // PCILeech FPGA. 3 | // 4 | // PCIe custom shadow configuration space. 5 | // Xilinx PCIe core will take configuration space priority; if Xilinx PCIe core 6 | // is configured to forward configuration requests to user application such TLP 7 | // will end up being processed by this module. 8 | // 9 | // (c) Ulf Frisk, 2021-2022 10 | // Author: Ulf Frisk, pcileech@frizk.net 11 | // 12 | 13 | `timescale 1ns / 1ps 14 | 15 | module pcileech_pcie_cfgspace_shadow( 16 | input rst, 17 | input clk, 18 | IfShadow2Fifo.src dshadow2fifo, 19 | IfShadow2Tlp.shadow dshadow2tlp 20 | ); 21 | 22 | wire int_rden; 23 | wire int_wren; 24 | wire [9:0] int_wr_addr; 25 | wire [31:0] int_wr_data; 26 | wire [9:0] int_rd_addr; 27 | 28 | // ---------------------------------------------------------------------------- 29 | // WRITE multiplexor: simple naive multiplexor which will prioritize in order: 30 | // (1) PCIe (if enabled), (2) USB, (3) INTERNAL. 31 | // Collisions will be discarded (it's assumed that they'll be very rare) 32 | // ---------------------------------------------------------------------------- 33 | wire bram_wr_1_tlp = dshadow2tlp.rx_wren; 34 | wire bram_wr_2_usb = ~bram_wr_1_tlp & dshadow2fifo.rx_wren; 35 | wire bram_wr_3_int = ~bram_wr_1_tlp & ~bram_wr_2_usb & int_wren; 36 | wire [3:0] bram_wr_be = bram_wr_1_tlp ? (dshadow2fifo.cfgtlp_wren ? dshadow2tlp.rx_be : 4'b0000) : (bram_wr_2_usb ? dshadow2fifo.rx_be : (bram_wr_3_int ? 4'b1111 : 4'b0000)); 37 | wire [9:0] bram_wr_addr = bram_wr_1_tlp ? dshadow2tlp.rx_addr : (bram_wr_2_usb ? dshadow2fifo.rx_addr : int_wr_addr); 38 | wire [31:0] bram_wr_data = bram_wr_1_tlp ? dshadow2tlp.rx_data : (bram_wr_2_usb ? dshadow2fifo.rx_data : int_wr_data); 39 | 40 | // ---------------------------------------------------------------------------- 41 | // WRITE multiplexor and state machine: simple naive multiplexor which will prioritize in order: 42 | // (1) PCIe (if enabled), (2) USB, (3) INTERNAL. 43 | // Collisions will be discarded (it's assumed that they'll be very rare) 44 | // ---------------------------------------------------------------------------- 45 | `define S_SHADOW_CFGSPACE_IDLE 2'b00 46 | `define S_SHADOW_CFGSPACE_TLP 2'b01 47 | `define S_SHADOW_CFGSPACE_USB 2'b10 48 | `define S_SHADOW_CFGSPACE_INT 2'b11 49 | 50 | wire [31:0] bram_rd_data; 51 | wire bram_rd_1_tlp = dshadow2tlp.rx_rden; 52 | wire bram_rd_2_usb = ~bram_rd_1_tlp & dshadow2fifo.rx_rden; 53 | wire bram_rd_3_int = ~bram_rd_1_tlp & ~bram_rd_2_usb & int_rden; 54 | wire [1:0] bram_rd_tp_3 = bram_rd_1_tlp ? `S_SHADOW_CFGSPACE_TLP : ( 55 | bram_rd_2_usb ? `S_SHADOW_CFGSPACE_USB : ( 56 | bram_rd_3_int ? `S_SHADOW_CFGSPACE_INT : `S_SHADOW_CFGSPACE_IDLE)); 57 | wire [9:0] bram_rd_addr_3 = bram_rd_1_tlp ? dshadow2tlp.rx_addr : ( 58 | bram_rd_2_usb ? dshadow2fifo.rx_addr : int_rd_addr); 59 | wire [7:0] bram_rd_tag_3 = bram_rd_1_tlp ? dshadow2tlp.rx_tag : {7'h00, dshadow2fifo.rx_addr_lo}; 60 | bit [9:0] bram_rd_addr, bram_rd_addr_2; 61 | bit [7:0] bram_rd_tag, bram_rd_tag_2; 62 | bit [1:0] bram_rd_tp, bram_rd_tp_2; 63 | 64 | always @ ( posedge clk ) 65 | begin 66 | bram_rd_addr <= bram_rd_addr_2; 67 | bram_rd_tag <= bram_rd_tag_2; 68 | bram_rd_tp <= bram_rd_tp_2; 69 | bram_rd_addr_2 <= bram_rd_addr_3; 70 | bram_rd_tag_2 <= bram_rd_tag_3; 71 | bram_rd_tp_2 <= bram_rd_tp_3; 72 | end 73 | 74 | // BRAM MEMORY ACCESS for the 4kB / 0x1000 byte shadow configuration space. 75 | bram_pcie_cfgspace i_bram_pcie_cfgspace( 76 | .clka ( clk ), 77 | .clkb ( clk ), 78 | .wea ( bram_wr_be ), 79 | .addra ( bram_wr_addr ), 80 | .dina ( bram_wr_data ), 81 | .addrb ( bram_rd_addr_3 ), 82 | .doutb ( bram_rd_data ) 83 | ); 84 | 85 | assign dshadow2tlp.tx_valid = bram_wr_1_tlp | (bram_rd_tp == `S_SHADOW_CFGSPACE_TLP); 86 | assign dshadow2tlp.tx_tlprd = ~bram_wr_1_tlp; 87 | assign dshadow2tlp.tx_tag = bram_wr_1_tlp ? dshadow2tlp.rx_tag : bram_rd_tag; 88 | assign dshadow2tlp.tx_data = dshadow2fifo.cfgtlp_zero ? 32'h00000000 : bram_rd_data; 89 | 90 | assign dshadow2fifo.tx_valid = (bram_rd_tp == `S_SHADOW_CFGSPACE_USB); 91 | assign dshadow2fifo.tx_addr = bram_rd_addr; 92 | assign dshadow2fifo.tx_addr_lo = bram_rd_tag[0]; 93 | assign dshadow2fifo.tx_data = dshadow2fifo.cfgtlp_zero ? 32'h00000000 : bram_rd_data; 94 | 95 | // ---------------------------------------------------------------------------- 96 | // INTERNAL LOGIC BELOW: 97 | // ---------------------------------------------------------------------------- 98 | 99 | assign int_rden = 0; 100 | assign int_wren = 0; 101 | assign int_wr_addr = 0; 102 | assign int_wr_data = 0; 103 | assign int_rd_addr = 0; 104 | 105 | endmodule 106 | -------------------------------------------------------------------------------- /src/pcileech_pcie_tlp_a7.sv: -------------------------------------------------------------------------------- 1 | // 2 | // PCILeech FPGA. 3 | // 4 | // PCIe controller module - TLP handling for Artix-7. 5 | // 6 | // (c) Ulf Frisk, 2018-2024 7 | // Author: Ulf Frisk, pcileech@frizk.net 8 | // 9 | 10 | `timescale 1ns / 1ps 11 | `include "pcileech_header.svh" 12 | 13 | module pcileech_pcie_tlp_a7( 14 | input rst, 15 | input clk_pcie, 16 | input clk_sys, 17 | IfPCIeFifoTlp.mp_pcie dfifo, 18 | 19 | // PCIe core receive/transmit data 20 | IfAXIS128.source tlps_tx, 21 | IfAXIS128.sink_lite tlps_rx, 22 | IfAXIS128.sink tlps_static, 23 | IfShadow2Fifo.shadow dshadow2fifo, 24 | input [15:0] pcie_id, 25 | input [31:0] base_address_register 26 | ); 27 | 28 | IfAXIS128 tlps_bar_rsp(); 29 | IfAXIS128 tlps_cfg_rsp(); 30 | 31 | // ------------------------------------------------------------------------ 32 | // Convert received TLPs from PCIe core and transmit onwards: 33 | // ------------------------------------------------------------------------ 34 | IfAXIS128 tlps_filtered(); 35 | 36 | pcileech_tlps128_bar_controller i_pcileech_tlps128_bar_controller( 37 | .rst ( rst ), 38 | .clk ( clk_pcie ), 39 | .bar_en ( dshadow2fifo.bar_en ), 40 | .pcie_id ( pcie_id ), 41 | .base_address_register ( base_address_register ), 42 | .tlps_in ( tlps_rx ), 43 | .tlps_out ( tlps_bar_rsp.source ) 44 | ); 45 | 46 | pcileech_tlps128_cfgspace_shadow i_pcileech_tlps128_cfgspace_shadow( 47 | .rst ( rst ), 48 | .clk_pcie ( clk_pcie ), 49 | .clk_sys ( clk_sys ), 50 | .tlps_in ( tlps_rx ), 51 | .pcie_id ( pcie_id ), 52 | .dshadow2fifo ( dshadow2fifo ), 53 | .tlps_cfg_rsp ( tlps_cfg_rsp.source ) 54 | ); 55 | 56 | pcileech_tlps128_filter i_pcileech_tlps128_filter( 57 | .rst ( rst ), 58 | .clk_pcie ( clk_pcie ), 59 | .alltlp_filter ( dshadow2fifo.alltlp_filter ), 60 | .cfgtlp_filter ( dshadow2fifo.cfgtlp_filter ), 61 | .tlps_in ( tlps_rx ), 62 | .tlps_out ( tlps_filtered.source_lite ) 63 | ); 64 | 65 | pcileech_tlps128_dst_fifo i_pcileech_tlps128_dst_fifo( 66 | .rst ( rst ), 67 | .clk_pcie ( clk_pcie ), 68 | .clk_sys ( clk_sys ), 69 | .tlps_in ( tlps_filtered.sink_lite ), 70 | .dfifo ( dfifo ) 71 | ); 72 | 73 | // ------------------------------------------------------------------------ 74 | // TX data received from FIFO 75 | // ------------------------------------------------------------------------ 76 | IfAXIS128 tlps_rx_fifo(); 77 | 78 | pcileech_tlps128_src_fifo i_pcileech_tlps128_src_fifo( 79 | .rst ( rst ), 80 | .clk_pcie ( clk_pcie ), 81 | .clk_sys ( clk_sys ), 82 | .dfifo_tx_data ( dfifo.tx_data ), 83 | .dfifo_tx_last ( dfifo.tx_last ), 84 | .dfifo_tx_valid ( dfifo.tx_valid ), 85 | .tlps_out ( tlps_rx_fifo.source ) 86 | ); 87 | 88 | pcileech_tlps128_sink_mux1 i_pcileech_tlps128_sink_mux1( 89 | .rst ( rst ), 90 | .clk_pcie ( clk_pcie ), 91 | .tlps_out ( tlps_tx ), 92 | .tlps_in1 ( tlps_cfg_rsp.sink ), 93 | .tlps_in2 ( tlps_bar_rsp.sink ), 94 | .tlps_in3 ( tlps_rx_fifo.sink ), 95 | .tlps_in4 ( tlps_static ) 96 | ); 97 | 98 | endmodule 99 | 100 | 101 | 102 | // ------------------------------------------------------------------------ 103 | // TLP-AXI-STREAM destination: 104 | // Forward the data to output device (FT601, etc.). 105 | // ------------------------------------------------------------------------ 106 | module pcileech_tlps128_dst_fifo( 107 | input rst, 108 | input clk_pcie, 109 | input clk_sys, 110 | IfAXIS128.sink_lite tlps_in, 111 | IfPCIeFifoTlp.mp_pcie dfifo 112 | ); 113 | 114 | wire tvalid; 115 | wire [127:0] tdata; 116 | wire [3:0] tkeepdw; 117 | wire tlast; 118 | wire first; 119 | 120 | fifo_134_134_clk2 i_fifo_134_134_clk2 ( 121 | .rst ( rst ), 122 | .wr_clk ( clk_pcie ), 123 | .rd_clk ( clk_sys ), 124 | .din ( { tlps_in.tuser[0], tlps_in.tlast, tlps_in.tkeepdw, tlps_in.tdata } ), 125 | .wr_en ( tlps_in.tvalid ), 126 | .rd_en ( dfifo.rx_rd_en ), 127 | .dout ( { first, tlast, tkeepdw, tdata } ), 128 | .full ( ), 129 | .empty ( ), 130 | .valid ( tvalid ) 131 | ); 132 | 133 | assign dfifo.rx_data[0] = tdata[31:0]; 134 | assign dfifo.rx_data[1] = tdata[63:32]; 135 | assign dfifo.rx_data[2] = tdata[95:64]; 136 | assign dfifo.rx_data[3] = tdata[127:96]; 137 | assign dfifo.rx_first[0] = first; 138 | assign dfifo.rx_first[1] = 0; 139 | assign dfifo.rx_first[2] = 0; 140 | assign dfifo.rx_first[3] = 0; 141 | assign dfifo.rx_last[0] = tlast && (tkeepdw == 4'b0001); 142 | assign dfifo.rx_last[1] = tlast && (tkeepdw == 4'b0011); 143 | assign dfifo.rx_last[2] = tlast && (tkeepdw == 4'b0111); 144 | assign dfifo.rx_last[3] = tlast && (tkeepdw == 4'b1111); 145 | assign dfifo.rx_valid[0] = tvalid && tkeepdw[0]; 146 | assign dfifo.rx_valid[1] = tvalid && tkeepdw[1]; 147 | assign dfifo.rx_valid[2] = tvalid && tkeepdw[2]; 148 | assign dfifo.rx_valid[3] = tvalid && tkeepdw[3]; 149 | 150 | endmodule 151 | 152 | 153 | 154 | // ------------------------------------------------------------------------ 155 | // TLP-AXI-STREAM FILTER: 156 | // Filter away certain packet types such as CfgRd/CfgWr or non-Cpl/CplD 157 | // ------------------------------------------------------------------------ 158 | module pcileech_tlps128_filter( 159 | input rst, 160 | input clk_pcie, 161 | input alltlp_filter, 162 | input cfgtlp_filter, 163 | IfAXIS128.sink_lite tlps_in, 164 | IfAXIS128.source_lite tlps_out 165 | ); 166 | 167 | bit [127:0] tdata; 168 | bit [3:0] tkeepdw; 169 | bit tvalid = 0; 170 | bit [8:0] tuser; 171 | bit tlast; 172 | 173 | assign tlps_out.tdata = tdata; 174 | assign tlps_out.tkeepdw = tkeepdw; 175 | assign tlps_out.tvalid = tvalid; 176 | assign tlps_out.tuser = tuser; 177 | assign tlps_out.tlast = tlast; 178 | 179 | bit filter = 0; 180 | wire first = tlps_in.tuser[0]; 181 | wire is_tlphdr_cpl = first && ( 182 | (tlps_in.tdata[31:25] == 7'b0000101) || // Cpl: Fmt[2:0]=000b (3 DW header, no data), Cpl=0101xb 183 | (tlps_in.tdata[31:25] == 7'b0100101) // CplD: Fmt[2:0]=010b (3 DW header, data), CplD=0101xb 184 | ); 185 | wire is_tlphdr_cfg = first && ( 186 | (tlps_in.tdata[31:25] == 7'b0000010) || // CfgRd: Fmt[2:0]=000b (3 DW header, no data), CfgRd0/CfgRd1=0010xb 187 | (tlps_in.tdata[31:25] == 7'b0100010) // CfgWr: Fmt[2:0]=010b (3 DW header, data), CfgWr0/CfgWr1=0010xb 188 | ); 189 | wire filter_next = (filter && !first) || (cfgtlp_filter && first && is_tlphdr_cfg) || (alltlp_filter && first && !is_tlphdr_cpl && !is_tlphdr_cfg); 190 | 191 | always @ ( posedge clk_pcie ) begin 192 | tdata <= tlps_in.tdata; 193 | tkeepdw <= tlps_in.tkeepdw; 194 | tvalid <= tlps_in.tvalid && !filter_next && !rst; 195 | tuser <= tlps_in.tuser; 196 | tlast <= tlps_in.tlast; 197 | filter <= filter_next && !rst; 198 | end 199 | 200 | endmodule 201 | 202 | 203 | 204 | // ------------------------------------------------------------------------ 205 | // RX FROM FIFO - TLP-AXI-STREAM: 206 | // Convert 32-bit incoming data to 128-bit TLP-AXI-STREAM to be sent onwards to mux/pcie core. 207 | // ------------------------------------------------------------------------ 208 | module pcileech_tlps128_src_fifo ( 209 | input rst, 210 | input clk_pcie, 211 | input clk_sys, 212 | input [31:0] dfifo_tx_data, 213 | input dfifo_tx_last, 214 | input dfifo_tx_valid, 215 | IfAXIS128.source tlps_out 216 | ); 217 | 218 | // 1: 32-bit -> 128-bit state machine: 219 | bit [127:0] tdata; 220 | bit [3:0] tkeepdw = 0; 221 | bit tlast; 222 | bit first = 1; 223 | wire tvalid = tlast || tkeepdw[3]; 224 | 225 | always @ ( posedge clk_sys ) 226 | if ( rst ) begin 227 | tkeepdw <= 0; 228 | tlast <= 0; 229 | first <= 1; 230 | end 231 | else begin 232 | tlast <= dfifo_tx_valid && dfifo_tx_last; 233 | tkeepdw <= tvalid ? (dfifo_tx_valid ? 4'b0001 : 4'b0000) : (dfifo_tx_valid ? ((tkeepdw << 1) | 1'b1) : tkeepdw); 234 | first <= tvalid ? tlast : first; 235 | if ( dfifo_tx_valid ) begin 236 | if ( tvalid || !tkeepdw[0] ) 237 | tdata[31:0] <= dfifo_tx_data; 238 | if ( !tkeepdw[1] ) 239 | tdata[63:32] <= dfifo_tx_data; 240 | if ( !tkeepdw[2] ) 241 | tdata[95:64] <= dfifo_tx_data; 242 | if ( !tkeepdw[3] ) 243 | tdata[127:96] <= dfifo_tx_data; 244 | end 245 | end 246 | 247 | // 2.1 - packet count (w/ safe fifo clock-crossing). 248 | bit [10:0] pkt_count = 0; 249 | wire pkt_count_dec = tlps_out.tvalid && tlps_out.tlast; 250 | wire pkt_count_inc; 251 | wire [10:0] pkt_count_next = pkt_count + pkt_count_inc - pkt_count_dec; 252 | assign tlps_out.has_data = (pkt_count_next > 0); 253 | 254 | fifo_1_1_clk2 i_fifo_1_1_clk2( 255 | .rst ( rst ), 256 | .wr_clk ( clk_sys ), 257 | .rd_clk ( clk_pcie ), 258 | .din ( 1'b1 ), 259 | .wr_en ( tvalid && tlast ), 260 | .rd_en ( 1'b1 ), 261 | .dout ( ), 262 | .full ( ), 263 | .empty ( ), 264 | .valid ( pkt_count_inc ) 265 | ); 266 | 267 | always @ ( posedge clk_pcie ) begin 268 | pkt_count <= rst ? 0 : pkt_count_next; 269 | end 270 | 271 | // 2.2 - submit to output fifo - will feed into mux/pcie core. 272 | // together with 2.1 this will form a low-latency "packet fifo". 273 | fifo_134_134_clk2_rxfifo i_fifo_134_134_clk2_rxfifo( 274 | .rst ( rst ), 275 | .wr_clk ( clk_sys ), 276 | .rd_clk ( clk_pcie ), 277 | .din ( { first, tlast, tkeepdw, tdata } ), 278 | .wr_en ( tvalid ), 279 | .rd_en ( tlps_out.tready && (pkt_count_next > 0) ), 280 | .dout ( { tlps_out.tuser[0], tlps_out.tlast, tlps_out.tkeepdw, tlps_out.tdata } ), 281 | .full ( ), 282 | .empty ( ), 283 | .valid ( tlps_out.tvalid ) 284 | ); 285 | 286 | endmodule 287 | 288 | 289 | 290 | // ------------------------------------------------------------------------ 291 | // RX MUX - TLP-AXI-STREAM: 292 | // Select the TLP-AXI-STREAM with the highest priority (lowest number) and 293 | // let it transmit its full packet. 294 | // Each incoming stream must have latency of 1CLK. 295 | // ------------------------------------------------------------------------ 296 | module pcileech_tlps128_sink_mux1 ( 297 | input clk_pcie, 298 | input rst, 299 | IfAXIS128.source tlps_out, 300 | IfAXIS128.sink tlps_in1, 301 | IfAXIS128.sink tlps_in2, 302 | IfAXIS128.sink tlps_in3, 303 | IfAXIS128.sink tlps_in4 304 | ); 305 | bit [2:0] id = 0; 306 | 307 | assign tlps_out.has_data = tlps_in1.has_data || tlps_in2.has_data || tlps_in3.has_data || tlps_in4.has_data; 308 | 309 | assign tlps_out.tdata = (id==1) ? tlps_in1.tdata : 310 | (id==2) ? tlps_in2.tdata : 311 | (id==3) ? tlps_in3.tdata : 312 | (id==4) ? tlps_in4.tdata : 0; 313 | 314 | assign tlps_out.tkeepdw = (id==1) ? tlps_in1.tkeepdw : 315 | (id==2) ? tlps_in2.tkeepdw : 316 | (id==3) ? tlps_in3.tkeepdw : 317 | (id==4) ? tlps_in4.tkeepdw : 0; 318 | 319 | assign tlps_out.tlast = (id==1) ? tlps_in1.tlast : 320 | (id==2) ? tlps_in2.tlast : 321 | (id==3) ? tlps_in3.tlast : 322 | (id==4) ? tlps_in4.tlast : 0; 323 | 324 | assign tlps_out.tuser = (id==1) ? tlps_in1.tuser : 325 | (id==2) ? tlps_in2.tuser : 326 | (id==3) ? tlps_in3.tuser : 327 | (id==4) ? tlps_in4.tuser : 0; 328 | 329 | assign tlps_out.tvalid = (id==1) ? tlps_in1.tvalid : 330 | (id==2) ? tlps_in2.tvalid : 331 | (id==3) ? tlps_in3.tvalid : 332 | (id==4) ? tlps_in4.tvalid : 0; 333 | 334 | wire [2:0] id_next_newsel = tlps_in1.has_data ? 1 : 335 | tlps_in2.has_data ? 2 : 336 | tlps_in3.has_data ? 3 : 337 | tlps_in4.has_data ? 4 : 0; 338 | 339 | wire [2:0] id_next = ((id==0) || (tlps_out.tvalid && tlps_out.tlast)) ? id_next_newsel : id; 340 | 341 | assign tlps_in1.tready = tlps_out.tready && (id_next==1); 342 | assign tlps_in2.tready = tlps_out.tready && (id_next==2); 343 | assign tlps_in3.tready = tlps_out.tready && (id_next==3); 344 | assign tlps_in4.tready = tlps_out.tready && (id_next==4); 345 | 346 | always @ ( posedge clk_pcie ) begin 347 | id <= rst ? 0 : id_next; 348 | end 349 | 350 | endmodule 351 | -------------------------------------------------------------------------------- /src/pcileech_screamer_m2.xdc: -------------------------------------------------------------------------------- 1 | set_property PACKAGE_PIN L18 [get_ports {ft601_be[0]}] 2 | set_property PACKAGE_PIN M17 [get_ports {ft601_be[1]}] 3 | set_property PACKAGE_PIN N18 [get_ports {ft601_be[2]}] 4 | set_property PACKAGE_PIN N17 [get_ports {ft601_be[3]}] 5 | set_property PACKAGE_PIN B9 [get_ports {ft601_data[0]}] 6 | set_property PACKAGE_PIN A9 [get_ports {ft601_data[1]}] 7 | set_property PACKAGE_PIN C9 [get_ports {ft601_data[2]}] 8 | set_property PACKAGE_PIN A10 [get_ports {ft601_data[3]}] 9 | set_property PACKAGE_PIN B10 [get_ports {ft601_data[4]}] 10 | set_property PACKAGE_PIN B11 [get_ports {ft601_data[5]}] 11 | set_property PACKAGE_PIN A12 [get_ports {ft601_data[6]}] 12 | set_property PACKAGE_PIN B12 [get_ports {ft601_data[7]}] 13 | set_property PACKAGE_PIN A13 [get_ports {ft601_data[8]}] 14 | set_property PACKAGE_PIN A14 [get_ports {ft601_data[9]}] 15 | set_property PACKAGE_PIN B14 [get_ports {ft601_data[10]}] 16 | set_property PACKAGE_PIN A15 [get_ports {ft601_data[11]}] 17 | set_property PACKAGE_PIN B15 [get_ports {ft601_data[12]}] 18 | set_property PACKAGE_PIN B16 [get_ports {ft601_data[13]}] 19 | set_property PACKAGE_PIN A17 [get_ports {ft601_data[14]}] 20 | set_property PACKAGE_PIN B17 [get_ports {ft601_data[15]}] 21 | set_property PACKAGE_PIN C17 [get_ports {ft601_data[16]}] 22 | set_property PACKAGE_PIN C18 [get_ports {ft601_data[17]}] 23 | set_property PACKAGE_PIN D18 [get_ports {ft601_data[18]}] 24 | set_property PACKAGE_PIN E17 [get_ports {ft601_data[19]}] 25 | set_property PACKAGE_PIN E18 [get_ports {ft601_data[20]}] 26 | set_property PACKAGE_PIN E16 [get_ports {ft601_data[21]}] 27 | set_property PACKAGE_PIN F18 [get_ports {ft601_data[22]}] 28 | set_property PACKAGE_PIN F17 [get_ports {ft601_data[23]}] 29 | set_property PACKAGE_PIN G17 [get_ports {ft601_data[24]}] 30 | set_property PACKAGE_PIN H18 [get_ports {ft601_data[25]}] 31 | set_property PACKAGE_PIN D13 [get_ports {ft601_data[26]}] 32 | set_property PACKAGE_PIN C14 [get_ports {ft601_data[27]}] 33 | set_property PACKAGE_PIN D14 [get_ports {ft601_data[28]}] 34 | set_property PACKAGE_PIN D15 [get_ports {ft601_data[29]}] 35 | set_property PACKAGE_PIN C16 [get_ports {ft601_data[30]}] 36 | set_property PACKAGE_PIN D16 [get_ports {ft601_data[31]}] 37 | set_property PACKAGE_PIN T15 [get_ports ft601_oe_n] 38 | set_property PACKAGE_PIN R16 [get_ports ft601_rd_n] 39 | set_property PACKAGE_PIN R18 [get_ports ft601_rxf_n] 40 | set_property PACKAGE_PIN R17 [get_ports ft601_siwu_n] 41 | set_property PACKAGE_PIN P18 [get_ports ft601_txe_n] 42 | set_property PACKAGE_PIN T18 [get_ports ft601_wr_n] 43 | set_property PACKAGE_PIN U15 [get_ports ft601_rst_n] 44 | set_property IOSTANDARD LVCMOS33 [get_ports {ft601_txe_n ft601_rxf_n}] 45 | set_property IOSTANDARD LVCMOS33 [get_ports {{ft601_be[*]} {ft601_data[*]}}] 46 | set_property IOSTANDARD LVCMOS33 [get_ports {ft601_wr_n ft601_rd_n ft601_oe_n ft601_siwu_n ft601_rst_n}] 47 | set_property SLEW FAST [get_ports {{ft601_be[*]} {ft601_data[*]}}] 48 | set_property SLEW FAST [get_ports {ft601_wr_n ft601_rd_n ft601_oe_n ft601_siwu_n ft601_rst_n}] 49 | 50 | set_property PACKAGE_PIN V17 [get_ports user_ld1] 51 | set_property PACKAGE_PIN U17 [get_ports user_ld2] 52 | set_property IOSTANDARD LVCMOS33 [get_ports {user_ld1 user_ld2}] 53 | 54 | # SYSCLK 55 | set_property PACKAGE_PIN R2 [get_ports clk] 56 | set_property IOSTANDARD LVCMOS33 [get_ports clk] 57 | create_clock -period 10.000 -name net_clk -waveform {0.000 5.000} [get_ports clk] 58 | 59 | # FT601 CLK 60 | create_clock -period 10.000 -name net_ft601_clk -waveform {0.000 5.000} [get_ports ft601_clk] 61 | set_property IOSTANDARD LVCMOS33 [get_ports ft601_clk] 62 | set_property PACKAGE_PIN E13 [get_ports ft601_clk] 63 | 64 | set_input_delay -clock [get_clocks net_ft601_clk] -min 6.5 [get_ports {ft601_data[*]}] 65 | set_input_delay -clock [get_clocks net_ft601_clk] -max 7.0 [get_ports {ft601_data[*]}] 66 | set_input_delay -clock [get_clocks net_ft601_clk] -min 6.5 [get_ports ft601_rxf_n] 67 | set_input_delay -clock [get_clocks net_ft601_clk] -max 7.0 [get_ports ft601_rxf_n] 68 | set_input_delay -clock [get_clocks net_ft601_clk] -min 6.5 [get_ports ft601_txe_n] 69 | set_input_delay -clock [get_clocks net_ft601_clk] -max 7.0 [get_ports ft601_txe_n] 70 | 71 | set_output_delay -clock [get_clocks net_ft601_clk] -max 1.0 [get_ports {ft601_wr_n ft601_rd_n ft601_oe_n}] 72 | set_output_delay -clock [get_clocks net_ft601_clk] -min 4.8 [get_ports {ft601_wr_n ft601_rd_n ft601_oe_n}] 73 | set_output_delay -clock [get_clocks net_ft601_clk] -max 1.0 [get_ports {{ft601_be[*]} {ft601_data[*]}}] 74 | set_output_delay -clock [get_clocks net_ft601_clk] -min 4.8 [get_ports {{ft601_be[*]} {ft601_data[*]}}] 75 | 76 | set_property IOB TRUE [get_cells i_pcileech_com/i_pcileech_ft601/FT601_OE_N_reg] 77 | set_property IOB TRUE [get_cells i_pcileech_com/i_pcileech_ft601/FT601_RD_N_reg] 78 | set_property IOB TRUE [get_cells i_pcileech_com/i_pcileech_ft601/FT601_WR_N_reg] 79 | set_property IOB TRUE [get_cells i_pcileech_com/i_pcileech_ft601/FT601_DATA_OUT_reg[0][*]] 80 | 81 | set_multicycle_path 2 -from [get_pins i_pcileech_com/i_pcileech_ft601/OE_reg/C] -to [get_ports {{ft601_be[*]} {ft601_data[*]}}] 82 | set_false_path -from [get_pins {tickcount64_reg[*]/C}] 83 | set_false_path -from [get_pins {i_pcileech_fifo/_pcie_core_config_reg[*]/C}] 84 | 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}] 85 | set_false_path -from [get_pins i_pcileech_pcie_a7/i_pcie_7x_0/inst/inst/user_reset_out_reg/C] 86 | 87 | #PCIe signals 88 | set_property PACKAGE_PIN K1 [get_ports pcie_present] 89 | set_property PACKAGE_PIN M1 [get_ports pcie_perst_n] 90 | set_property PACKAGE_PIN L2 [get_ports pcie_wake_n] 91 | set_property IOSTANDARD LVCMOS33 [get_ports pcie_present] 92 | set_property IOSTANDARD LVCMOS33 [get_ports pcie_perst_n] 93 | set_property IOSTANDARD LVCMOS33 [get_ports pcie_wake_n] 94 | 95 | set_property LOC GTPE2_CHANNEL_X0Y2 [get_cells {i_pcileech_pcie_a7/i_pcie_7x_0/inst/inst/gt_top_i/pipe_wrapper_i/pipe_lane[0].gt_wrapper_i/gtp_channel.gtpe2_channel_i}] 96 | set_property PACKAGE_PIN E3 [get_ports pcie_rx_n[0]] 97 | set_property PACKAGE_PIN E4 [get_ports pcie_rx_p[0]] 98 | set_property PACKAGE_PIN H1 [get_ports pcie_tx_n[0]] 99 | set_property PACKAGE_PIN H2 [get_ports pcie_tx_p[0]] 100 | 101 | #set_property PACKAGE_PIN A3 [get_ports pcie_rx_n[1]] 102 | #set_property PACKAGE_PIN A4 [get_ports pcie_rx_p[1]] 103 | #set_property PACKAGE_PIN F1 [get_ports pcie_tx_n[1]] 104 | #set_property PACKAGE_PIN F2 [get_ports pcie_tx_p[1]] 105 | 106 | #set_property PACKAGE_PIN C3 [get_ports pcie_rx_n[2]] 107 | #set_property PACKAGE_PIN C4 [get_ports pcie_rx_p[2]] 108 | #set_property PACKAGE_PIN D1 [get_ports pcie_tx_n[2]] 109 | #set_property PACKAGE_PIN D2 [get_ports pcie_tx_p[2]] 110 | 111 | #set_property PACKAGE_PIN G3 [get_ports pcie_rx_n[3]] 112 | #set_property PACKAGE_PIN G4 [get_ports pcie_rx_p[3]] 113 | #set_property PACKAGE_PIN B1 [get_ports pcie_tx_n[3]] 114 | #set_property PACKAGE_PIN B2 [get_ports pcie_tx_p[3]] 115 | 116 | set_property PACKAGE_PIN D5 [get_ports pcie_clk_n] 117 | set_property PACKAGE_PIN D6 [get_ports pcie_clk_p] 118 | 119 | create_clock -name pcie_sys_clk_p -period 10.0 [get_nets pcie_clk_p] 120 | 121 | set_property CFGBVS Vcco [current_design] 122 | set_property CONFIG_VOLTAGE 3.3 [current_design] 123 | set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design] 124 | set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design] 125 | set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES [current_design] 126 | set_property BITSTREAM.CONFIG.CONFIGRATE 66 [current_design] 127 | -------------------------------------------------------------------------------- /src/pcileech_screamer_m2_top.sv: -------------------------------------------------------------------------------- 1 | // 2 | // PCILeech FPGA. 3 | // 4 | // Top module for various 35T-325 x1 Artix-7 boards. 5 | // 6 | // (c) Ulf Frisk, 2019-2024 7 | // Author: Ulf Frisk, pcileech@frizk.net 8 | // 9 | 10 | `timescale 1ns / 1ps 11 | `include "pcileech_header.svh" 12 | 13 | module pcileech_screamer_m2_top #( 14 | parameter PARAM_DEVICE_ID = 4, 15 | parameter PARAM_VERSION_NUMBER_MAJOR = 4, 16 | parameter PARAM_VERSION_NUMBER_MINOR = 13, 17 | parameter PARAM_CUSTOM_VALUE = 32'hffffffff 18 | ) ( 19 | // SYS 20 | input clk, 21 | input ft601_clk, 22 | 23 | // SYSTEM LEDs and BUTTONs 24 | output user_ld1, 25 | output user_ld2, 26 | 27 | // PCI-E FABRIC 28 | output [0:0] pcie_tx_p, 29 | output [0:0] pcie_tx_n, 30 | input [0:0] pcie_rx_p, 31 | input [0:0] pcie_rx_n, 32 | input pcie_clk_p, 33 | input pcie_clk_n, 34 | input pcie_present, 35 | input pcie_perst_n, 36 | output reg pcie_wake_n = 1'b1, 37 | 38 | // TO/FROM FT601 PADS 39 | output ft601_rst_n, 40 | 41 | inout [31:0] ft601_data, 42 | output [3:0] ft601_be, 43 | input ft601_rxf_n, 44 | input ft601_txe_n, 45 | output ft601_wr_n, 46 | output ft601_siwu_n, 47 | output ft601_rd_n, 48 | output ft601_oe_n 49 | ); 50 | 51 | // SYS 52 | wire rst; 53 | 54 | // FIFO CTL <--> COM CTL 55 | wire [63:0] com_dout; 56 | wire com_dout_valid; 57 | wire [255:0] com_din; 58 | wire com_din_wr_en; 59 | wire com_din_ready; 60 | wire led_com; 61 | wire led_pcie; 62 | 63 | // FIFO CTL <--> COM CTL 64 | IfComToFifo dcom_fifo(); 65 | 66 | // FIFO CTL <--> PCIe 67 | IfPCIeFifoCfg dcfg(); 68 | IfPCIeFifoTlp dtlp(); 69 | IfPCIeFifoCore dpcie(); 70 | IfShadow2Fifo dshadow2fifo(); 71 | 72 | // ---------------------------------------------------- 73 | // TickCount64 CLK 74 | // ---------------------------------------------------- 75 | 76 | time tickcount64 = 0; 77 | always @ ( posedge clk ) 78 | tickcount64 <= tickcount64 + 1; 79 | 80 | assign rst = (tickcount64 < 64) ? 1'b1 : 1'b0; 81 | assign ft601_rst_n = ~rst; 82 | wire led_pwronblink = tickcount64[24] & (tickcount64[63:27] == 0); 83 | 84 | OBUF led_ld1_obuf(.O(user_ld1), .I(led_pcie)); 85 | OBUF led_ld2_obuf(.O(user_ld2), .I(led_com)); 86 | 87 | // ---------------------------------------------------- 88 | // BUFFERED COMMUNICATION DEVICE (FT601) 89 | // ---------------------------------------------------- 90 | 91 | pcileech_com i_pcileech_com ( 92 | // SYS 93 | .clk ( clk ), 94 | .clk_com ( ft601_clk ), 95 | .rst ( rst ), 96 | .led_state_txdata ( led_com ), // -> 97 | .led_state_invert ( led_pwronblink ), // <- 98 | // FIFO CTL <--> COM CTL 99 | .dfifo ( dcom_fifo.mp_com ), 100 | // TO/FROM FT601 PADS 101 | .ft601_data ( ft601_data ), // <> [31:0] 102 | .ft601_be ( ft601_be ), // -> [3:0] 103 | .ft601_txe_n ( ft601_txe_n ), // <- 104 | .ft601_rxf_n ( ft601_rxf_n ), // <- 105 | .ft601_siwu_n ( ft601_siwu_n ), // -> 106 | .ft601_wr_n ( ft601_wr_n ), // -> 107 | .ft601_rd_n ( ft601_rd_n ), // -> 108 | .ft601_oe_n ( ft601_oe_n ) // -> 109 | ); 110 | 111 | // ---------------------------------------------------- 112 | // FIFO CTL 113 | // ---------------------------------------------------- 114 | 115 | pcileech_fifo #( 116 | .PARAM_DEVICE_ID ( PARAM_DEVICE_ID ), 117 | .PARAM_VERSION_NUMBER_MAJOR ( PARAM_VERSION_NUMBER_MAJOR ), 118 | .PARAM_VERSION_NUMBER_MINOR ( PARAM_VERSION_NUMBER_MINOR ), 119 | .PARAM_CUSTOM_VALUE ( PARAM_CUSTOM_VALUE ) 120 | ) i_pcileech_fifo ( 121 | .clk ( clk ), 122 | .rst ( rst ), 123 | .rst_cfg_reload ( 1'b0 ), 124 | .pcie_present ( pcie_present ), 125 | .pcie_perst_n ( pcie_perst_n ), 126 | // FIFO CTL <--> COM CTL 127 | .dcom ( dcom_fifo.mp_fifo ), 128 | // FIFO CTL <--> PCIe 129 | .dcfg ( dcfg.mp_fifo ), 130 | .dtlp ( dtlp.mp_fifo ), 131 | .dpcie ( dpcie.mp_fifo ), 132 | .dshadow2fifo ( dshadow2fifo.fifo ) 133 | ); 134 | 135 | // ---------------------------------------------------- 136 | // PCIe 137 | // ---------------------------------------------------- 138 | 139 | pcileech_pcie_a7 i_pcileech_pcie_a7( 140 | .clk_sys ( clk ), 141 | .rst ( rst ), 142 | // PCIe fabric 143 | .pcie_tx_p ( pcie_tx_p ), 144 | .pcie_tx_n ( pcie_tx_n ), 145 | .pcie_rx_p ( pcie_rx_p ), 146 | .pcie_rx_n ( pcie_rx_n ), 147 | .pcie_clk_p ( pcie_clk_p ), 148 | .pcie_clk_n ( pcie_clk_n ), 149 | .pcie_perst_n ( pcie_perst_n ), 150 | // State and Activity LEDs 151 | .led_state ( led_pcie ), 152 | // FIFO CTL <--> PCIe 153 | .dfifo_cfg ( dcfg.mp_pcie ), 154 | .dfifo_tlp ( dtlp.mp_pcie ), 155 | .dfifo_pcie ( dpcie.mp_pcie ), 156 | .dshadow2fifo ( dshadow2fifo.shadow ) 157 | ); 158 | 159 | endmodule 160 | -------------------------------------------------------------------------------- /src/pcileech_squirrel.xdc: -------------------------------------------------------------------------------- 1 | set_property PACKAGE_PIN Y18 [get_ports ft601_be[0]] 2 | set_property PACKAGE_PIN AA18 [get_ports ft601_be[1]] 3 | set_property PACKAGE_PIN AB18 [get_ports ft601_be[2]] 4 | set_property PACKAGE_PIN W17 [get_ports ft601_be[3]] 5 | set_property PACKAGE_PIN N13 [get_ports ft601_data[0]] 6 | set_property PACKAGE_PIN N14 [get_ports ft601_data[1]] 7 | set_property PACKAGE_PIN N15 [get_ports ft601_data[2]] 8 | set_property PACKAGE_PIN P15 [get_ports ft601_data[3]] 9 | set_property PACKAGE_PIN P16 [get_ports ft601_data[4]] 10 | set_property PACKAGE_PIN N17 [get_ports ft601_data[5]] 11 | set_property PACKAGE_PIN P17 [get_ports ft601_data[6]] 12 | set_property PACKAGE_PIN R17 [get_ports ft601_data[7]] 13 | set_property PACKAGE_PIN P19 [get_ports ft601_data[8]] 14 | set_property PACKAGE_PIN R18 [get_ports ft601_data[9]] 15 | set_property PACKAGE_PIN R19 [get_ports ft601_data[10]] 16 | set_property PACKAGE_PIN T18 [get_ports ft601_data[11]] 17 | set_property PACKAGE_PIN U18 [get_ports ft601_data[12]] 18 | set_property PACKAGE_PIN V18 [get_ports ft601_data[13]] 19 | set_property PACKAGE_PIN V19 [get_ports ft601_data[14]] 20 | set_property PACKAGE_PIN V17 [get_ports ft601_data[15]] 21 | set_property PACKAGE_PIN W20 [get_ports ft601_data[16]] 22 | set_property PACKAGE_PIN Y19 [get_ports ft601_data[17]] 23 | set_property PACKAGE_PIN T21 [get_ports ft601_data[18]] 24 | set_property PACKAGE_PIN T20 [get_ports ft601_data[19]] 25 | set_property PACKAGE_PIN U21 [get_ports ft601_data[20]] 26 | set_property PACKAGE_PIN V20 [get_ports ft601_data[21]] 27 | set_property PACKAGE_PIN W22 [get_ports ft601_data[22]] 28 | set_property PACKAGE_PIN W21 [get_ports ft601_data[23]] 29 | set_property PACKAGE_PIN Y22 [get_ports ft601_data[24]] 30 | set_property PACKAGE_PIN Y21 [get_ports ft601_data[25]] 31 | set_property PACKAGE_PIN AA21 [get_ports ft601_data[26]] 32 | set_property PACKAGE_PIN AB22 [get_ports ft601_data[27]] 33 | set_property PACKAGE_PIN AA20 [get_ports ft601_data[28]] 34 | set_property PACKAGE_PIN AB21 [get_ports ft601_data[29]] 35 | set_property PACKAGE_PIN AA19 [get_ports ft601_data[30]] 36 | set_property PACKAGE_PIN AB20 [get_ports ft601_data[31]] 37 | set_property PACKAGE_PIN AB6 [get_ports ft601_oe_n] 38 | set_property PACKAGE_PIN AA6 [get_ports ft601_rd_n] 39 | set_property PACKAGE_PIN AB8 [get_ports ft601_rxf_n] 40 | set_property PACKAGE_PIN Y8 [get_ports ft601_siwu_n] 41 | set_property PACKAGE_PIN AA8 [get_ports ft601_txe_n] 42 | set_property PACKAGE_PIN AB7 [get_ports ft601_wr_n] 43 | set_property PACKAGE_PIN Y9 [get_ports ft601_rst_n] 44 | set_property IOSTANDARD LVCMOS33 [get_ports {ft601_txe_n ft601_rxf_n}] 45 | set_property IOSTANDARD LVCMOS33 [get_ports {{ft601_be[*]} {ft601_data[*]}}] 46 | set_property IOSTANDARD LVCMOS33 [get_ports {ft601_wr_n ft601_rd_n ft601_oe_n ft601_siwu_n ft601_rst_n}] 47 | set_property SLEW FAST [get_ports {{ft601_be[*]} {ft601_data[*]}}] 48 | set_property SLEW FAST [get_ports {ft601_wr_n ft601_rd_n ft601_oe_n ft601_siwu_n ft601_rst_n}] 49 | 50 | set_property PACKAGE_PIN Y6 [get_ports user_ld1] 51 | set_property PACKAGE_PIN AB5 [get_ports user_ld2] 52 | set_property PACKAGE_PIN AB3 [get_ports user_sw1_n] 53 | set_property PACKAGE_PIN AA5 [get_ports user_sw2_n] 54 | set_property IOSTANDARD LVCMOS33 [get_ports {user_ld1 user_ld2 user_sw1_n user_sw2_n}] 55 | 56 | set_property PACKAGE_PIN F21 [get_ports ft2232_rst_n] 57 | set_property IOSTANDARD LVCMOS33 [get_ports ft2232_rst_n] 58 | 59 | # SYSCLK 60 | set_property PACKAGE_PIN H4 [get_ports clk] 61 | set_property IOSTANDARD LVCMOS33 [get_ports clk] 62 | create_clock -period 10.000 -name net_clk -waveform {0.000 5.000} [get_ports clk] 63 | 64 | # FT601 CLK 65 | create_clock -period 10.000 -name net_ft601_clk -waveform {0.000 5.000} [get_ports ft601_clk] 66 | set_property IOSTANDARD LVCMOS33 [get_ports ft601_clk] 67 | set_property PACKAGE_PIN W19 [get_ports ft601_clk] 68 | 69 | set_input_delay -clock [get_clocks net_ft601_clk] -min 6.5 [get_ports {ft601_data[*]}] 70 | set_input_delay -clock [get_clocks net_ft601_clk] -max 7.0 [get_ports {ft601_data[*]}] 71 | set_input_delay -clock [get_clocks net_ft601_clk] -min 6.5 [get_ports ft601_rxf_n] 72 | set_input_delay -clock [get_clocks net_ft601_clk] -max 7.0 [get_ports ft601_rxf_n] 73 | set_input_delay -clock [get_clocks net_ft601_clk] -min 6.5 [get_ports ft601_txe_n] 74 | set_input_delay -clock [get_clocks net_ft601_clk] -max 7.0 [get_ports ft601_txe_n] 75 | 76 | set_output_delay -clock [get_clocks net_ft601_clk] -max 1.0 [get_ports {ft601_wr_n ft601_rd_n ft601_oe_n}] 77 | set_output_delay -clock [get_clocks net_ft601_clk] -min 4.8 [get_ports {ft601_wr_n ft601_rd_n ft601_oe_n}] 78 | set_output_delay -clock [get_clocks net_ft601_clk] -max 1.0 [get_ports {{ft601_be[*]} {ft601_data[*]}}] 79 | set_output_delay -clock [get_clocks net_ft601_clk] -min 4.8 [get_ports {{ft601_be[*]} {ft601_data[*]}}] 80 | 81 | set_property IOB TRUE [get_cells i_pcileech_com/i_pcileech_ft601/FT601_OE_N_reg] 82 | set_property IOB TRUE [get_cells i_pcileech_com/i_pcileech_ft601/FT601_RD_N_reg] 83 | set_property IOB TRUE [get_cells i_pcileech_com/i_pcileech_ft601/FT601_WR_N_reg] 84 | set_property IOB TRUE [get_cells i_pcileech_com/i_pcileech_ft601/FT601_DATA_OUT_reg[0][*]] 85 | 86 | set_multicycle_path 2 -from [get_pins i_pcileech_com/i_pcileech_ft601/OE_reg/C] -to [get_ports {{ft601_be[*]} {ft601_data[*]}}] 87 | set_false_path -from [get_pins {tickcount64_reg[*]/C}] 88 | set_false_path -from [get_pins {i_pcileech_fifo/_pcie_core_config_reg[*]/C}] 89 | 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}] 90 | set_false_path -from [get_pins i_pcileech_pcie_a7/i_pcie_7x_0/inst/inst/user_reset_out_reg/C] 91 | 92 | #PCIe signals 93 | set_property LOC GTPE2_CHANNEL_X0Y2 [get_cells {i_pcileech_pcie_a7/i_pcie_7x_0/inst/inst/gt_top_i/pipe_wrapper_i/pipe_lane[0].gt_wrapper_i/gtp_channel.gtpe2_channel_i}] 94 | set_property PACKAGE_PIN A13 [get_ports pcie_present] 95 | set_property PACKAGE_PIN B13 [get_ports pcie_perst_n] 96 | set_property PACKAGE_PIN A14 [get_ports pcie_wake_n] 97 | set_property IOSTANDARD LVCMOS33 [get_ports pcie_present] 98 | set_property IOSTANDARD LVCMOS33 [get_ports pcie_perst_n] 99 | set_property IOSTANDARD LVCMOS33 [get_ports pcie_wake_n] 100 | 101 | set_property PACKAGE_PIN A10 [get_ports {pcie_rx_n[0]}] 102 | set_property PACKAGE_PIN B10 [get_ports {pcie_rx_p[0]}] 103 | set_property PACKAGE_PIN A6 [get_ports {pcie_tx_n[0]}] 104 | set_property PACKAGE_PIN B6 [get_ports {pcie_tx_p[0]}] 105 | 106 | set_property PACKAGE_PIN E6 [get_ports pcie_clk_n] 107 | set_property PACKAGE_PIN F6 [get_ports pcie_clk_p] 108 | 109 | create_clock -name pcie_sys_clk_p -period 10.0 [get_nets pcie_clk_p] 110 | 111 | set_property CFGBVS Vcco [current_design] 112 | set_property CONFIG_VOLTAGE 3.3 [current_design] 113 | set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design] 114 | set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design] 115 | set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES [current_design] 116 | set_property BITSTREAM.CONFIG.CONFIGRATE 66 [current_design] -------------------------------------------------------------------------------- /src/pcileech_squirrel_top.sv: -------------------------------------------------------------------------------- 1 | // 2 | // PCILeech FPGA. 3 | // 4 | // Top module for various 35T-484 x1 Artix-7 boards. 5 | // 6 | // (c) Ulf Frisk, 2019-2024 7 | // Author: Ulf Frisk, pcileech@frizk.net 8 | // 9 | 10 | `timescale 1ns / 1ps 11 | `include "pcileech_header.svh" 12 | 13 | module pcileech_squirrel_top #( 14 | parameter PARAM_DEVICE_ID = 4, 15 | parameter PARAM_VERSION_NUMBER_MAJOR = 4, 16 | parameter PARAM_VERSION_NUMBER_MINOR = 13, 17 | parameter PARAM_CUSTOM_VALUE = 32'hffffffff 18 | ) ( 19 | // SYS 20 | input clk, 21 | input ft601_clk, 22 | 23 | // SYSTEM LEDs and BUTTONs 24 | output user_ld1, 25 | output user_ld2, 26 | input user_sw1_n, 27 | input user_sw2_n, 28 | 29 | output ft2232_rst_n, 30 | 31 | // PCI-E FABRIC 32 | output [0:0] pcie_tx_p, 33 | output [0:0] pcie_tx_n, 34 | input [0:0] pcie_rx_p, 35 | input [0:0] pcie_rx_n, 36 | input pcie_clk_p, 37 | input pcie_clk_n, 38 | input pcie_present, 39 | input pcie_perst_n, 40 | output reg pcie_wake_n = 1'b1, 41 | 42 | // TO/FROM FT601 PADS 43 | output ft601_rst_n, 44 | inout [31:0] ft601_data, 45 | output [3:0] ft601_be, 46 | input ft601_rxf_n, 47 | input ft601_txe_n, 48 | output ft601_wr_n, 49 | output ft601_siwu_n, 50 | output ft601_rd_n, 51 | output ft601_oe_n 52 | ); 53 | 54 | // SYS 55 | wire rst; 56 | 57 | // FIFO CTL <--> COM CTL 58 | wire [63:0] com_dout; 59 | wire com_dout_valid; 60 | wire [255:0] com_din; 61 | wire com_din_wr_en; 62 | wire com_din_ready; 63 | wire led_com; 64 | wire led_pcie; 65 | 66 | // FIFO CTL <--> COM CTL 67 | IfComToFifo dcom_fifo(); 68 | 69 | // FIFO CTL <--> PCIe 70 | IfPCIeFifoCfg dcfg(); 71 | IfPCIeFifoTlp dtlp(); 72 | IfPCIeFifoCore dpcie(); 73 | IfShadow2Fifo dshadow2fifo(); 74 | 75 | // ---------------------------------------------------- 76 | // TickCount64 CLK 77 | // ---------------------------------------------------- 78 | 79 | time tickcount64 = 0; 80 | time tickcount64_reload = 0; 81 | always @ ( posedge clk ) begin 82 | tickcount64 <= user_sw2_n ? (tickcount64 + 1) : 0; 83 | tickcount64_reload <= user_sw2_n ? 0 : (tickcount64_reload + 1); 84 | end 85 | 86 | assign rst = ~user_sw2_n || ((tickcount64 < 64) ? 1'b1 : 1'b0); 87 | assign ft601_rst_n = ~rst; 88 | wire led_pwronblink = ~user_sw1_n ^ (tickcount64[24] & (tickcount64[63:27] == 0)); 89 | 90 | OBUF led_ld1_obuf(.O(user_ld1), .I(led_pcie)); 91 | OBUF led_ld2_obuf(.O(user_ld2), .I(led_com)); 92 | OBUF ft2232_rst_obuf(.O(ft2232_rst_n), .I(user_sw2_n)); 93 | 94 | // ---------------------------------------------------- 95 | // BUFFERED COMMUNICATION DEVICE (FT601) 96 | // ---------------------------------------------------- 97 | 98 | pcileech_com i_pcileech_com ( 99 | // SYS 100 | .clk ( clk ), 101 | .clk_com ( ft601_clk ), 102 | .rst ( rst ), 103 | .led_state_txdata ( led_com ), // -> 104 | .led_state_invert ( led_pwronblink ), // <- 105 | // FIFO CTL <--> COM CTL 106 | .dfifo ( dcom_fifo.mp_com ), 107 | // TO/FROM FT601 PADS 108 | .ft601_data ( ft601_data ), // <> [31:0] 109 | .ft601_be ( ft601_be ), // -> [3:0] 110 | .ft601_txe_n ( ft601_txe_n ), // <- 111 | .ft601_rxf_n ( ft601_rxf_n ), // <- 112 | .ft601_siwu_n ( ft601_siwu_n ), // -> 113 | .ft601_wr_n ( ft601_wr_n ), // -> 114 | .ft601_rd_n ( ft601_rd_n ), // -> 115 | .ft601_oe_n ( ft601_oe_n ) // -> 116 | ); 117 | 118 | // ---------------------------------------------------- 119 | // FIFO CTL 120 | // ---------------------------------------------------- 121 | 122 | pcileech_fifo #( 123 | .PARAM_DEVICE_ID ( PARAM_DEVICE_ID ), 124 | .PARAM_VERSION_NUMBER_MAJOR ( PARAM_VERSION_NUMBER_MAJOR ), 125 | .PARAM_VERSION_NUMBER_MINOR ( PARAM_VERSION_NUMBER_MINOR ), 126 | .PARAM_CUSTOM_VALUE ( PARAM_CUSTOM_VALUE ) 127 | ) i_pcileech_fifo ( 128 | .clk ( clk ), 129 | .rst ( rst ), 130 | .rst_cfg_reload ( (tickcount64_reload > 500000000) ? 1'b1 : 1'b0 ), // config reload after 5s button press 131 | .pcie_present ( pcie_present ), 132 | .pcie_perst_n ( pcie_perst_n ), 133 | // FIFO CTL <--> COM CTL 134 | .dcom ( dcom_fifo.mp_fifo ), 135 | // FIFO CTL <--> PCIe 136 | .dcfg ( dcfg.mp_fifo ), 137 | .dtlp ( dtlp.mp_fifo ), 138 | .dpcie ( dpcie.mp_fifo ), 139 | .dshadow2fifo ( dshadow2fifo.fifo ) 140 | ); 141 | 142 | // ---------------------------------------------------- 143 | // PCIe 144 | // ---------------------------------------------------- 145 | 146 | pcileech_pcie_a7 i_pcileech_pcie_a7( 147 | .clk_sys ( clk ), 148 | .rst ( rst ), 149 | // PCIe fabric 150 | .pcie_tx_p ( pcie_tx_p ), 151 | .pcie_tx_n ( pcie_tx_n ), 152 | .pcie_rx_p ( pcie_rx_p ), 153 | .pcie_rx_n ( pcie_rx_n ), 154 | .pcie_clk_p ( pcie_clk_p ), 155 | .pcie_clk_n ( pcie_clk_n ), 156 | .pcie_perst_n ( pcie_perst_n ), 157 | // State and Activity LEDs 158 | .led_state ( led_pcie ), 159 | // FIFO CTL <--> PCIe 160 | .dfifo_cfg ( dcfg.mp_pcie ), 161 | .dfifo_tlp ( dtlp.mp_pcie ), 162 | .dfifo_pcie ( dpcie.mp_pcie ), 163 | .dshadow2fifo ( dshadow2fifo.shadow ) 164 | ); 165 | 166 | endmodule 167 | -------------------------------------------------------------------------------- /src/pcileech_tbx4_100t.xdc: -------------------------------------------------------------------------------- 1 | # SW 2 | set_property PACKAGE_PIN F21 [get_ports power_sw] 3 | set_property IOSTANDARD LVCMOS18 [get_ports power_sw] 4 | set_property PULLTYPE PULLUP [get_ports power_sw] 5 | 6 | # LED 7 | set_property PACKAGE_PIN AA5 [get_ports pcie_led] 8 | set_property IOSTANDARD LVCMOS18 [get_ports pcie_led] 9 | 10 | # SYSCLK 11 | set_property PACKAGE_PIN J19 [get_ports clk_in] 12 | set_property IOSTANDARD LVCMOS33 [get_ports clk_in] 13 | create_clock -period 8.000 [get_nets clk] 14 | 15 | #BUS DO 16 | set_property PACKAGE_PIN A21 [get_ports {BUS_DO[0]}] 17 | set_property PACKAGE_PIN A20 [get_ports {BUS_DO[1]}] 18 | set_property PACKAGE_PIN A19 [get_ports {BUS_DO[2]}] 19 | set_property PACKAGE_PIN A18 [get_ports {BUS_DO[3]}] 20 | set_property PACKAGE_PIN A16 [get_ports {BUS_DO[4]}] 21 | set_property PACKAGE_PIN A15 [get_ports {BUS_DO[5]}] 22 | set_property PACKAGE_PIN A14 [get_ports {BUS_DO[6]}] 23 | set_property PACKAGE_PIN A13 [get_ports {BUS_DO[7]}] 24 | set_property PACKAGE_PIN B22 [get_ports {BUS_DO[8]}] 25 | set_property PACKAGE_PIN B21 [get_ports {BUS_DO[9]}] 26 | set_property PACKAGE_PIN B20 [get_ports {BUS_DO[10]}] 27 | set_property PACKAGE_PIN B18 [get_ports {BUS_DO[11]}] 28 | set_property PACKAGE_PIN B17 [get_ports {BUS_DO[12]}] 29 | set_property PACKAGE_PIN B16 [get_ports {BUS_DO[13]}] 30 | set_property PACKAGE_PIN B15 [get_ports {BUS_DO[14]}] 31 | set_property PACKAGE_PIN B13 [get_ports {BUS_DO[15]}] 32 | set_property PACKAGE_PIN C22 [get_ports {BUS_DO[16]}] 33 | set_property PACKAGE_PIN C20 [get_ports {BUS_DO[17]}] 34 | set_property PACKAGE_PIN C19 [get_ports {BUS_DO[18]}] 35 | set_property PACKAGE_PIN C18 [get_ports {BUS_DO[19]}] 36 | set_property PACKAGE_PIN V7 [get_ports {BUS_DO[20]}] 37 | set_property PACKAGE_PIN Y4 [get_ports {BUS_DO[21]}] 38 | set_property PACKAGE_PIN AA4 [get_ports {BUS_DO[22]}] 39 | set_property PACKAGE_PIN V4 [get_ports {BUS_DO[23]}] 40 | set_property PACKAGE_PIN W4 [get_ports {BUS_DO[24]}] 41 | set_property PACKAGE_PIN R4 [get_ports {BUS_DO[25]}] 42 | set_property PACKAGE_PIN T4 [get_ports {BUS_DO[26]}] 43 | set_property PACKAGE_PIN T5 [get_ports {BUS_DO[27]}] 44 | set_property PACKAGE_PIN U5 [get_ports {BUS_DO[28]}] 45 | set_property PACKAGE_PIN W6 [get_ports {BUS_DO[29]}] 46 | set_property PACKAGE_PIN W5 [get_ports {BUS_DO[30]}] 47 | set_property PACKAGE_PIN U6 [get_ports {BUS_DO[31]}] 48 | set_property PACKAGE_PIN V5 [get_ports {BUS_DO[32]}] 49 | set_property PACKAGE_PIN R6 [get_ports {BUS_DO[33]}] 50 | set_property PACKAGE_PIN T6 [get_ports {BUS_DO[34]}] 51 | set_property PACKAGE_PIN Y6 [get_ports {BUS_DO[35]}] 52 | set_property PACKAGE_PIN AA6 [get_ports {BUS_DO[36]}] 53 | set_property IOSTANDARD LVCMOS18 [get_ports {BUS_DO[*]}] 54 | 55 | #BUS DI 56 | set_property PACKAGE_PIN F4 [get_ports {BUS_DI[0]}] 57 | set_property PACKAGE_PIN B1 [get_ports {BUS_DI[1]}] 58 | set_property PACKAGE_PIN A1 [get_ports {BUS_DI[2]}] 59 | set_property PACKAGE_PIN C2 [get_ports {BUS_DI[3]}] 60 | set_property PACKAGE_PIN B2 [get_ports {BUS_DI[4]}] 61 | set_property PACKAGE_PIN E1 [get_ports {BUS_DI[5]}] 62 | set_property PACKAGE_PIN D1 [get_ports {BUS_DI[6]}] 63 | set_property PACKAGE_PIN E2 [get_ports {BUS_DI[7]}] 64 | set_property PACKAGE_PIN D2 [get_ports {BUS_DI[8]}] 65 | set_property PACKAGE_PIN G1 [get_ports {BUS_DI[9]}] 66 | set_property PACKAGE_PIN F1 [get_ports {BUS_DI[10]}] 67 | set_property PACKAGE_PIN F3 [get_ports {BUS_DI[11]}] 68 | set_property PACKAGE_PIN E3 [get_ports {BUS_DI[12]}] 69 | set_property PACKAGE_PIN K1 [get_ports {BUS_DI[13]}] 70 | set_property PACKAGE_PIN J1 [get_ports {BUS_DI[14]}] 71 | set_property PACKAGE_PIN H2 [get_ports {BUS_DI[15]}] 72 | set_property PACKAGE_PIN G2 [get_ports {BUS_DI[16]}] 73 | set_property PACKAGE_PIN K2 [get_ports {BUS_DI[17]}] 74 | set_property PACKAGE_PIN J2 [get_ports {BUS_DI[18]}] 75 | set_property PACKAGE_PIN J5 [get_ports {BUS_DI[19]}] 76 | set_property PACKAGE_PIN H5 [get_ports {BUS_DI[20]}] 77 | set_property PACKAGE_PIN H3 [get_ports {BUS_DI[21]}] 78 | set_property PACKAGE_PIN G3 [get_ports {BUS_DI[22]}] 79 | set_property PACKAGE_PIN H4 [get_ports {BUS_DI[23]}] 80 | set_property PACKAGE_PIN G4 [get_ports {BUS_DI[24]}] 81 | set_property PACKAGE_PIN K4 [get_ports {BUS_DI[25]}] 82 | set_property PACKAGE_PIN J4 [get_ports {BUS_DI[26]}] 83 | set_property PACKAGE_PIN L3 [get_ports {BUS_DI[27]}] 84 | set_property PACKAGE_PIN K3 [get_ports {BUS_DI[28]}] 85 | set_property PACKAGE_PIN M1 [get_ports {BUS_DI[29]}] 86 | set_property PACKAGE_PIN L1 [get_ports {BUS_DI[30]}] 87 | set_property PACKAGE_PIN M3 [get_ports {BUS_DI[31]}] 88 | set_property PACKAGE_PIN M2 [get_ports {BUS_DI[32]}] 89 | set_property PACKAGE_PIN K6 [get_ports {BUS_DI[33]}] 90 | set_property PACKAGE_PIN J6 [get_ports {BUS_DI[34]}] 91 | set_property PACKAGE_PIN L5 [get_ports {BUS_DI[35]}] 92 | set_property PACKAGE_PIN L4 [get_ports {BUS_DI[36]}] 93 | set_property PACKAGE_PIN N4 [get_ports {BUS_DI[37]}] 94 | set_property PACKAGE_PIN N3 [get_ports {BUS_DI[38]}] 95 | set_property PACKAGE_PIN R1 [get_ports {BUS_DI[39]}] 96 | set_property PACKAGE_PIN P1 [get_ports {BUS_DI[40]}] 97 | set_property PACKAGE_PIN P5 [get_ports {BUS_DI[41]}] 98 | set_property PACKAGE_PIN P4 [get_ports {BUS_DI[42]}] 99 | set_property PACKAGE_PIN P2 [get_ports {BUS_DI[43]}] 100 | set_property PACKAGE_PIN N2 [get_ports {BUS_DI[44]}] 101 | set_property PACKAGE_PIN M6 [get_ports {BUS_DI[45]}] 102 | set_property PACKAGE_PIN M5 [get_ports {BUS_DI[46]}] 103 | set_property PACKAGE_PIN P6 [get_ports {BUS_DI[47]}] 104 | set_property PACKAGE_PIN N5 [get_ports {BUS_DI[48]}] 105 | set_property PACKAGE_PIN L6 [get_ports {BUS_DI[49]}] 106 | set_property PACKAGE_PIN T3 [get_ports {BUS_DI[50]}] 107 | set_property PACKAGE_PIN T1 [get_ports {BUS_DI[51]}] 108 | set_property PACKAGE_PIN U1 [get_ports {BUS_DI[52]}] 109 | set_property PACKAGE_PIN U2 [get_ports {BUS_DI[53]}] 110 | set_property PACKAGE_PIN V2 [get_ports {BUS_DI[54]}] 111 | set_property PACKAGE_PIN R3 [get_ports {BUS_DI[55]}] 112 | set_property PACKAGE_PIN R2 [get_ports {BUS_DI[56]}] 113 | set_property PACKAGE_PIN W2 [get_ports {BUS_DI[57]}] 114 | set_property PACKAGE_PIN Y2 [get_ports {BUS_DI[58]}] 115 | set_property PACKAGE_PIN W1 [get_ports {BUS_DI[59]}] 116 | set_property PACKAGE_PIN Y1 [get_ports {BUS_DI[60]}] 117 | set_property PACKAGE_PIN U3 [get_ports {BUS_DI[61]}] 118 | set_property PACKAGE_PIN V3 [get_ports {BUS_DI[62]}] 119 | set_property PACKAGE_PIN AA1 [get_ports {BUS_DI[63]}] 120 | set_property PACKAGE_PIN AB1 [get_ports {BUS_DI[64]}] 121 | set_property PACKAGE_PIN AB3 [get_ports {BUS_DI[65]}] 122 | set_property PACKAGE_PIN AB2 [get_ports {BUS_DI[66]}] 123 | set_property PACKAGE_PIN Y3 [get_ports {BUS_DI[67]}] 124 | set_property PACKAGE_PIN AA3 [get_ports {BUS_DI[68]}] 125 | set_property IOSTANDARD LVCMOS18 [get_ports {BUS_DI[*]}] 126 | 127 | set_property PACKAGE_PIN AB6 [get_ports BUS_DI_PROG_FULL] 128 | set_property IOSTANDARD LVCMOS18 [get_ports BUS_DI_PROG_FULL] 129 | 130 | #TIMING FALSE PATHS 131 | set_false_path -from [get_pins {tickcount64_reg[*]/C}] 132 | set_false_path -from [get_pins {i_pcileech_fifo/_pcie_core_config_reg[*]/C}] 133 | set_false_path -from [get_pins i_pcileech_pcie_a7x4/i_pcie_7x_0/inst/inst/user_lnk_up_int_reg/C] -to [get_pins {i_pcileech_fifo/_cmd_tx_din_reg[16]/D}] 134 | set_false_path -from [get_pins i_pcileech_pcie_a7x4/i_pcie_7x_0/inst/inst/user_reset_out_reg/C] 135 | 136 | #PCIe signals 137 | set_property PACKAGE_PIN J14 [get_ports pcie_present1] 138 | set_property PACKAGE_PIN AB16 [get_ports pcie_present2] 139 | set_property PACKAGE_PIN J22 [get_ports pcie_perst1_n] 140 | set_property PACKAGE_PIN AB10 [get_ports pcie_perst2_n] 141 | set_property IOSTANDARD LVCMOS33 [get_ports {pcie_present1 pcie_present2 pcie_perst1_n pcie_perst2_n}] 142 | set_property PULLTYPE PULLUP [get_ports {pcie_present1 pcie_present2 pcie_perst1_n pcie_perst2_n}] 143 | 144 | set_property LOC GTPE2_CHANNEL_X0Y4 [get_cells {i_pcileech_pcie_a7x4/i_pcie_7x_0/inst/inst/gt_top_i/pipe_wrapper_i/pipe_lane[0].gt_wrapper_i/gtp_channel.gtpe2_channel_i}] 145 | set_property LOC GTPE2_CHANNEL_X0Y5 [get_cells {i_pcileech_pcie_a7x4/i_pcie_7x_0/inst/inst/gt_top_i/pipe_wrapper_i/pipe_lane[1].gt_wrapper_i/gtp_channel.gtpe2_channel_i}] 146 | set_property LOC GTPE2_CHANNEL_X0Y6 [get_cells {i_pcileech_pcie_a7x4/i_pcie_7x_0/inst/inst/gt_top_i/pipe_wrapper_i/pipe_lane[2].gt_wrapper_i/gtp_channel.gtpe2_channel_i}] 147 | set_property LOC GTPE2_CHANNEL_X0Y7 [get_cells {i_pcileech_pcie_a7x4/i_pcie_7x_0/inst/inst/gt_top_i/pipe_wrapper_i/pipe_lane[3].gt_wrapper_i/gtp_channel.gtpe2_channel_i}] 148 | 149 | set_property PACKAGE_PIN A8 [get_ports pcie_rx_n[0]] 150 | set_property PACKAGE_PIN B8 [get_ports pcie_rx_p[0]] 151 | set_property PACKAGE_PIN A4 [get_ports pcie_tx_n[0]] 152 | set_property PACKAGE_PIN B4 [get_ports pcie_tx_p[0]] 153 | 154 | set_property PACKAGE_PIN C11 [get_ports pcie_rx_n[1]] 155 | set_property PACKAGE_PIN D11 [get_ports pcie_rx_p[1]] 156 | set_property PACKAGE_PIN C5 [get_ports pcie_tx_n[1]] 157 | set_property PACKAGE_PIN D5 [get_ports pcie_tx_p[1]] 158 | 159 | set_property PACKAGE_PIN A10 [get_ports pcie_rx_n[2]] 160 | set_property PACKAGE_PIN B10 [get_ports pcie_rx_p[2]] 161 | set_property PACKAGE_PIN A6 [get_ports pcie_tx_n[2]] 162 | set_property PACKAGE_PIN B6 [get_ports pcie_tx_p[2]] 163 | 164 | set_property PACKAGE_PIN C9 [get_ports pcie_rx_n[3]] 165 | set_property PACKAGE_PIN D9 [get_ports pcie_rx_p[3]] 166 | set_property PACKAGE_PIN C7 [get_ports pcie_tx_n[3]] 167 | set_property PACKAGE_PIN D7 [get_ports pcie_tx_p[3]] 168 | 169 | set_property PACKAGE_PIN F10 [get_ports pcie_clk_p] 170 | set_property PACKAGE_PIN E10 [get_ports pcie_clk_n] 171 | create_clock -period 10.000 -name pcie_sys_clk_p [get_nets pcie_clk_p] 172 | 173 | #GENRAL CONFIG 174 | set_property CFGBVS Vcco [current_design] 175 | set_property CONFIG_VOLTAGE 3.3 [current_design] 176 | set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design] 177 | set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design] 178 | set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES [current_design] 179 | set_property BITSTREAM.CONFIG.CONFIGRATE 66 [current_design] 180 | -------------------------------------------------------------------------------- /src/pcileech_tbx4_100t_top.sv: -------------------------------------------------------------------------------- 1 | // 2 | // PCILeech FPGA. 3 | // 4 | // Top module for PCILeech TB x4 5 | // 6 | // (c) Ulf Frisk, 2019-2024 7 | // Author: Ulf Frisk, pcileech@frizk.net 8 | // 9 | 10 | `timescale 1ns / 1ps 11 | `include "pcileech_header.svh" 12 | 13 | module pcileech_tbx4_100t_top #( 14 | // DEVICE IDs as follows: 15 | parameter PARAM_DEVICE_ID = 17, 16 | parameter PARAM_VERSION_NUMBER_MAJOR = 4, 17 | parameter PARAM_VERSION_NUMBER_MINOR = 15, 18 | parameter PARAM_CUSTOM_VALUE = 32'hffffffff, 19 | parameter POWER_SW_MODE = 0, // disable_pcie_on_thunderbolt_noconnect_not_enabled(0), disable_pcie_on_thunderbolt_noconnect_enabled(1) 20 | parameter POWER_SW_TIME = 60*125_000_000 // detection sample time in ticks of 125MHz (125M=1s) 21 | ) ( 22 | // SYS 23 | input clk_in, 24 | 25 | // SYSTEM LEDs and BUTTONs 26 | output pcie_led, 27 | input power_sw, 28 | 29 | // TO/FROM FPGA IO BRIDGE 30 | input [36:0] BUS_DO, 31 | output [68:0] BUS_DI, 32 | input BUS_DI_PROG_FULL, 33 | 34 | // PCI-E FABRIC 35 | output [3:0] pcie_tx_p, 36 | output [3:0] pcie_tx_n, 37 | input [3:0] pcie_rx_p, 38 | input [3:0] pcie_rx_n, 39 | input pcie_clk_p, 40 | input pcie_clk_n, 41 | input pcie_present1, 42 | input pcie_present2, 43 | input pcie_perst1_n, 44 | input pcie_perst2_n 45 | ); 46 | 47 | // SYS 48 | wire rst; 49 | wire clk; 50 | wire clk_com; 51 | reg rst_sw = 0; 52 | 53 | // FIFO CTL <--> COM CTL 54 | wire [63:0] com_dout; 55 | wire com_dout_valid; 56 | wire [255:0] com_din; 57 | wire com_din_wr_en; 58 | wire com_din_ready; 59 | 60 | // FIFO CTL <--> COM CTL 61 | IfComToFifo dcom_fifo(); 62 | 63 | // FIFO CTL <--> PCIe 64 | IfPCIeFifoCfg dcfg(); 65 | IfPCIeFifoTlp dtlp(); 66 | IfPCIeFifoCore dpcie(); 67 | IfShadow2Fifo dshadow2fifo(); 68 | 69 | // PCIe 70 | wire pcie_present = pcie_present1 && pcie_present2; 71 | wire pcie_perst_n = pcie_perst1_n && pcie_perst2_n && ~rst_sw; 72 | 73 | // ---------------------------------------------------- 74 | // CLK: INPUT (clkin): 50MHz 75 | // COM (clk_com): 250MHz 76 | // SYS (clk): 125MHz 77 | // ---------------------------------------------------- 78 | 79 | wire clk_locked, clk_out1, clk_out2; 80 | clk_wiz_0 i_clk_wiz_0( 81 | .clk_in1 ( clk_in ), // <- 50MHz 82 | .clk_out1 ( clk_out1 ), // -> 250MHz 83 | .clk_out2 ( clk_out2 ), // -> 125MHz 84 | .locked ( clk_locked ) 85 | ); 86 | 87 | BUFG i_BUFG_1 ( .I( clk_locked ? clk_out1 : clk_in ), .O( clk_com ) ); 88 | BUFG i_BUFG_2 ( .I( clk_locked ? clk_out2 : clk_in ), .O( clk ) ); 89 | 90 | // ---------------------------------------------------- 91 | // TickCount64 CLK 92 | // ---------------------------------------------------- 93 | 94 | time tickcount64 = 0; 95 | always @ ( posedge clk ) 96 | tickcount64 <= tickcount64 + 1; 97 | assign rst = (tickcount64 < 64) ? 1'b1 : 1'b0; 98 | 99 | wire led_pcie; 100 | OBUF led_ld1_obuf(.O(pcie_led), .I(led_pcie)); 101 | 102 | // ---------------------------------------------------- 103 | // POWER SWITCH MODE (DISABLE PCIE WHEN THUNDERBOLT NOT CONNECTED) 104 | // ---------------------------------------------------- 105 | 106 | always @ ( posedge clk ) begin 107 | if ( rst ) begin 108 | rst_sw <= 0; 109 | end 110 | else if ( (POWER_SW_MODE == 1) && (tickcount64 == POWER_SW_TIME) ) begin 111 | rst_sw <= ~power_sw; 112 | end 113 | end 114 | 115 | // ---------------------------------------------------- 116 | // BUFFERED COMMUNICATION DEVICE (FPGA IO BRIDGE) 117 | // ---------------------------------------------------- 118 | 119 | pcileech_com i_pcileech_com ( 120 | // SYS 121 | .clk ( clk ), 122 | .clk_com ( clk_com ), 123 | .rst ( rst ), 124 | // TO/FROM FPGA IO BRIDGE 125 | .BUS_DO ( BUS_DO ), 126 | .BUS_DI ( BUS_DI ), 127 | .BUS_DI_PROG_FULL ( BUS_DI_PROG_FULL ), 128 | // FIFO CTL <--> COM CTL 129 | .com_dout ( dcom_fifo.com_dout ), 130 | .com_dout_valid ( dcom_fifo.com_dout_valid ), 131 | .com_din_ready ( dcom_fifo.com_din_ready ), 132 | .com_din ( dcom_fifo.com_din ), 133 | .com_din_wr_en ( dcom_fifo.com_din_wr_en ) 134 | ); 135 | 136 | // ---------------------------------------------------- 137 | // FIFO CTL 138 | // ---------------------------------------------------- 139 | 140 | pcileech_fifo #( 141 | .PARAM_DEVICE_ID ( PARAM_DEVICE_ID ), 142 | .PARAM_VERSION_NUMBER_MAJOR ( PARAM_VERSION_NUMBER_MAJOR ), 143 | .PARAM_VERSION_NUMBER_MINOR ( PARAM_VERSION_NUMBER_MINOR ), 144 | .PARAM_CUSTOM_VALUE ( PARAM_CUSTOM_VALUE ) 145 | ) i_pcileech_fifo ( 146 | .clk ( clk ), 147 | .rst ( rst ), 148 | .rst_cfg_reload ( 1'b0 ), 149 | .pcie_present ( pcie_present ), 150 | .pcie_perst_n ( pcie_perst_n ), 151 | // FIFO CTL <--> COM CTL 152 | .dcom ( dcom_fifo.mp_fifo ), 153 | // FIFO CTL <--> PCIe 154 | .dcfg ( dcfg.mp_fifo ), 155 | .dtlp ( dtlp.mp_fifo ), 156 | .dpcie ( dpcie.mp_fifo ), 157 | .dshadow2fifo ( dshadow2fifo.fifo ) 158 | ); 159 | 160 | // ---------------------------------------------------- 161 | // PCIe 162 | // ---------------------------------------------------- 163 | 164 | pcileech_pcie_a7x4 i_pcileech_pcie_a7x4( 165 | .clk_sys ( clk ), 166 | .rst ( rst ), 167 | // PCIe fabric 168 | .pcie_tx_p ( pcie_tx_p ), 169 | .pcie_tx_n ( pcie_tx_n ), 170 | .pcie_rx_p ( pcie_rx_p ), 171 | .pcie_rx_n ( pcie_rx_n ), 172 | .pcie_clk_p ( pcie_clk_p ), 173 | .pcie_clk_n ( pcie_clk_n ), 174 | .pcie_perst_n ( pcie_perst_n ), 175 | // State and Activity LEDs 176 | .led_state ( led_pcie ), 177 | // FIFO CTL <--> PCIe 178 | .dfifo_cfg ( dcfg.mp_pcie ), 179 | .dfifo_tlp ( dtlp.mp_pcie ), 180 | .dfifo_pcie ( dpcie.mp_pcie ), 181 | .dshadow2fifo ( dshadow2fifo.shadow ) 182 | ); 183 | 184 | endmodule -------------------------------------------------------------------------------- /src/pcileech_tlps128_cfgspace_shadow.sv: -------------------------------------------------------------------------------- 1 | // 2 | // PCILeech FPGA. 3 | // 4 | // PCIe custom shadow configuration space. 5 | // Xilinx PCIe core will take configuration space priority; if Xilinx PCIe core 6 | // is configured to forward configuration requests to user application such TLP 7 | // will end up being processed by this module. 8 | // 9 | // (c) Ulf Frisk, 2021-2024 10 | // Author: Ulf Frisk, pcileech@frizk.net 11 | // 12 | 13 | `timescale 1ns / 1ps 14 | 15 | module pcileech_tlps128_cfgspace_shadow( 16 | input rst, 17 | input clk_pcie, 18 | input clk_sys, 19 | IfAXIS128.sink_lite tlps_in, 20 | input [15:0] pcie_id, 21 | IfAXIS128.source tlps_cfg_rsp, 22 | IfShadow2Fifo.shadow dshadow2fifo 23 | ); 24 | // ---------------------------------------------------------------------------- 25 | // PCIe RECEIVE: 26 | // ---------------------------------------------------------------------------- 27 | wire pcie_rx_rden = tlps_in.tvalid && tlps_in.tuser[0] && (tlps_in.tdata[31:25] == 7'b0000010); // CfgRd: Fmt[2:0]=000b (3 DW header, no data), CfgRd0/CfgRd1=0010xb 28 | wire pcie_rx_wren = tlps_in.tvalid && tlps_in.tuser[0] && (tlps_in.tdata[31:25] == 7'b0100010); // CfgWr: Fmt[2:0]=010b (3 DW header, data), CfgWr0/CfgWr1=0010xb 29 | wire [9:0] pcie_rx_addr = tlps_in.tdata[75:66]; 30 | wire [31:0] pcie_rx_data = tlps_in.tdata[127:96]; 31 | wire [7:0] pcie_rx_tag = tlps_in.tdata[47:40]; 32 | wire [3:0] pcie_rx_be = {tlps_in.tdata[32], tlps_in.tdata[33], tlps_in.tdata[34], tlps_in.tdata[35]}; 33 | wire [15:0] pcie_rx_reqid = tlps_in.tdata[63:48]; 34 | 35 | // ---------------------------------------------------------------------------- 36 | // USB RECEIVE (clock domain crossing): 37 | // ---------------------------------------------------------------------------- 38 | wire usb_rx_rden_out; 39 | wire usb_rx_wren_out; 40 | wire usb_rx_valid; 41 | wire usb_rx_rden = usb_rx_valid && usb_rx_rden_out; 42 | wire usb_rx_wren = usb_rx_valid && usb_rx_wren_out; 43 | wire [3:0] usb_rx_be; 44 | wire [31:0] usb_rx_data; 45 | wire [9:0] usb_rx_addr; 46 | wire usb_rx_addr_lo; 47 | fifo_49_49_clk2 i_fifo_49_49_clk2( 48 | .rst ( rst ), 49 | .wr_clk ( clk_sys ), 50 | .rd_clk ( clk_pcie ), 51 | .wr_en ( dshadow2fifo.rx_rden || dshadow2fifo.rx_wren ), 52 | .din ( {dshadow2fifo.rx_rden, dshadow2fifo.rx_wren, dshadow2fifo.rx_addr_lo, dshadow2fifo.rx_addr, dshadow2fifo.rx_be, dshadow2fifo.rx_data} ), 53 | .full ( ), 54 | .rd_en ( 1'b1 ), 55 | .dout ( {usb_rx_rden_out, usb_rx_wren_out, usb_rx_addr_lo, usb_rx_addr, usb_rx_be, usb_rx_data} ), 56 | .empty ( ), 57 | .valid ( usb_rx_valid ) 58 | ); 59 | 60 | // ---------------------------------------------------------------------------- 61 | // WRITE multiplexor: simple naive multiplexor which will prioritize in order: 62 | // (1) PCIe (if enabled), (2) USB, (3) INTERNAL. 63 | // Collisions will be discarded (it's assumed that they'll be very rare) 64 | // ---------------------------------------------------------------------------- 65 | wire bram_wr_1_tlp = pcie_rx_wren & dshadow2fifo.cfgtlp_en; 66 | wire bram_wr_2_usb = ~bram_wr_1_tlp & usb_rx_wren; 67 | wire [3:0] bram_wr_be = bram_wr_1_tlp ? (dshadow2fifo.cfgtlp_wren ? pcie_rx_be : 4'b0000) : (bram_wr_2_usb ? usb_rx_be : 4'b0000); 68 | wire [31:0] bram_wr_data = bram_wr_1_tlp ? pcie_rx_data : (bram_wr_2_usb ? usb_rx_data : 32'h00000000); 69 | 70 | // ---------------------------------------------------------------------------- 71 | // WRITE multiplexor and state machine: simple naive multiplexor which will prioritize in order: 72 | // (1) PCIe (if enabled), (2) USB, (3) INTERNAL. 73 | // Collisions will be discarded (it's assumed that they'll be very rare) 74 | // ---------------------------------------------------------------------------- 75 | `define S_SHADOW_CFGSPACE_IDLE 2'b00 76 | `define S_SHADOW_CFGSPACE_TLP 2'b01 77 | `define S_SHADOW_CFGSPACE_USB 2'b10 78 | 79 | wire [15:0] bram_rd_reqid; 80 | wire [1:0] bram_rd_tp; 81 | wire [7:0] bram_rd_tag; 82 | wire [9:0] bram_rd_addr; 83 | wire [31:0] bram_rd_data; 84 | wire [31:0] bram_rd_data_z = dshadow2fifo.cfgtlp_zero ? 32'h00000000 : bram_rd_data; 85 | wire bram_rd_valid = (bram_rd_tp == `S_SHADOW_CFGSPACE_TLP); 86 | wire bram_rd_tlpwr; 87 | 88 | wire bram_rd_1_tlp = pcie_rx_rden & dshadow2fifo.cfgtlp_en; 89 | wire bram_tlp = bram_rd_1_tlp | bram_wr_1_tlp; 90 | wire bram_rd_2_usb = ~bram_tlp & usb_rx_rden; 91 | wire [1:0] bram_rdreq_tp = bram_tlp ? `S_SHADOW_CFGSPACE_TLP : (bram_rd_2_usb ? `S_SHADOW_CFGSPACE_USB : `S_SHADOW_CFGSPACE_IDLE); 92 | wire [9:0] bram_rdreq_addr = bram_tlp ? pcie_rx_addr : usb_rx_addr; 93 | wire [7:0] bram_rdreq_tag = bram_tlp ? pcie_rx_tag : {7'h00, usb_rx_addr_lo}; 94 | wire [15:0] bram_rdreq_reqid= bram_tlp ? pcie_rx_reqid : 16'h0000; 95 | 96 | // BRAM MEMORY ACCESS for the 4kB / 0x1000 byte shadow configuration space. 97 | pcileech_mem_wrap i_pcileech_mem_wrap( 98 | .clk_pcie ( clk_pcie ), // <- 99 | .rdwr_addr ( bram_rdreq_addr ), // <- 100 | .wr_be ( bram_wr_be ), // <- 101 | .wr_data ( bram_wr_data ), // <- 102 | .rdreq_tag ( bram_rdreq_tag ), // <- 103 | .rdreq_tp ( bram_rdreq_tp ), // <- 104 | .rdreq_reqid ( bram_rdreq_reqid ), // <- 105 | .rdreq_tlpwr ( bram_wr_1_tlp ), // <- 106 | .rd_data ( bram_rd_data ), // -> 107 | .rd_addr ( bram_rd_addr ), // -> 108 | .rd_tag ( bram_rd_tag ), // -> 109 | .rd_tp ( bram_rd_tp ), // -> 110 | .rd_reqid ( bram_rd_reqid ), // -> 111 | .rd_tlpwr ( bram_rd_tlpwr ) // -> 112 | ); 113 | 114 | // PCIe REPLY: 115 | pcileech_cfgspace_pcie_tx i_pcileech_cfgspace_pcie_tx( 116 | .rst ( rst ), // <- 117 | .clk_pcie ( clk_pcie ), // <- 118 | .pcie_id ( pcie_id ), // <- [15:0] 119 | .tlps_cfg_rsp ( tlps_cfg_rsp ), 120 | // cfgspace: 121 | .cfg_wren ( bram_rd_valid ), // <- 122 | .cfg_tlpwr ( bram_rd_tlpwr ), // <- 123 | .cfg_tag ( bram_rd_tag ), // <- [7:0] 124 | .cfg_data ( bram_rd_data_z ), // <- [32:0] 125 | .cfg_reqid ( bram_rd_reqid ) // <- [15:0] 126 | ); 127 | 128 | // USB REPLY: 129 | fifo_43_43_clk2 i_fifo_43_43_clk2( 130 | .rst ( rst ), 131 | .wr_clk ( clk_pcie ), 132 | .rd_clk ( clk_sys ), 133 | .wr_en ( (bram_rd_tp == `S_SHADOW_CFGSPACE_USB) ), 134 | .din ( {bram_rd_tag[0], bram_rd_addr, bram_rd_data_z} ), 135 | .full ( ), 136 | .rd_en ( 1'b1 ), 137 | .dout ( {dshadow2fifo.tx_addr_lo, dshadow2fifo.tx_addr, dshadow2fifo.tx_data} ), 138 | .empty ( ), 139 | .valid ( dshadow2fifo.tx_valid ) 140 | ); 141 | 142 | endmodule 143 | 144 | 145 | 146 | // PCIe TLP cfg reply module: 147 | module pcileech_cfgspace_pcie_tx( 148 | input rst, 149 | input clk_pcie, 150 | input [15:0] pcie_id, // PCIe id of this core 151 | IfAXIS128.source tlps_cfg_rsp, 152 | // cfgspace: 153 | input cfg_wren, 154 | input cfg_tlpwr, 155 | input [7:0] cfg_tag, 156 | input [31:0] cfg_data, 157 | input [15:0] cfg_reqid 158 | ); 159 | 160 | wire [31:0] cpl_tlp_data_dw0_rd = 32'b01001010000000000000000000000001; 161 | wire [31:0] cpl_tlp_data_dw0_wr = 32'b00001010000000000000000000000000; 162 | wire [31:0] cpl_tlp_data_dw1 = { `_bs16(pcie_id), 16'h0004 }; 163 | wire [31:0] cpl_tlp_data_dw2 = { cfg_reqid, cfg_tag, 8'h00 }; 164 | wire [31:0] cpl_tlp_data_dw3 = cfg_data; 165 | wire [127:0] cpl_tlp_rd = { cpl_tlp_data_dw3, cpl_tlp_data_dw2, cpl_tlp_data_dw1, cpl_tlp_data_dw0_rd }; 166 | wire [127:0] cpl_tlp_wr = { 32'h00000000, cpl_tlp_data_dw2, cpl_tlp_data_dw1, cpl_tlp_data_dw0_wr }; 167 | wire [128:0] cpl_tlps = cfg_tlpwr ? {1'b0, cpl_tlp_wr} : {1'b1, cpl_tlp_rd}; 168 | 169 | wire tx_tp; 170 | wire tx_empty; 171 | fifo_129_129_clk1 i_fifo_129_129_clk1 ( 172 | .srst ( rst ), 173 | .clk ( clk_pcie ), 174 | // data in 175 | .wr_en ( cfg_wren ), 176 | .din ( cpl_tlps ), 177 | .full ( ), 178 | // data out 179 | .rd_en ( tlps_cfg_rsp.tready ), 180 | .dout ( {tx_tp, tlps_cfg_rsp.tdata} ), 181 | .empty ( tx_empty ), 182 | .valid ( tlps_cfg_rsp.tvalid ) 183 | ); 184 | 185 | assign tlps_cfg_rsp.tkeepdw = (tx_tp ? 4'b1111 : 4'b0111); 186 | assign tlps_cfg_rsp.tlast = 1; 187 | assign tlps_cfg_rsp.tuser = 0; 188 | assign tlps_cfg_rsp.has_data = ~tx_empty; 189 | endmodule 190 | 191 | 192 | 193 | // Wrapper module for the BRAM-backed configuration space. 194 | module pcileech_mem_wrap( 195 | input clk_pcie, 196 | 197 | // Address common to Read/Write: 198 | input [9:0] rdwr_addr, 199 | 200 | // Write to 'configuration/action space': 201 | input [3:0] wr_be, 202 | input [31:0] wr_data, 203 | 204 | // Read from 'configuration space': 205 | input [7:0] rdreq_tag, 206 | input [1:0] rdreq_tp, 207 | input [15:0] rdreq_reqid, 208 | input rdreq_tlpwr, 209 | 210 | output bit [9:0] rd_addr, 211 | output [31:0] rd_data, 212 | output bit [7:0] rd_tag, 213 | output bit [1:0] rd_tp, 214 | output bit [15:0] rd_reqid, 215 | output bit rd_tlpwr 216 | ); 217 | 218 | bit [3:0] wr_be_d; 219 | bit [31:0] wr_data_d; 220 | 221 | wire [31:0] wr_mask; 222 | wire [31:0] wr_dina; 223 | 224 | // DELAY TO FOLLOW BRAM DELAY 225 | always @ ( posedge clk_pcie ) 226 | begin 227 | wr_be_d <= wr_be; 228 | wr_data_d <= wr_data; 229 | rd_addr <= rdwr_addr; 230 | rd_tag <= rdreq_tag; 231 | rd_tp <= rdreq_tp; 232 | rd_reqid <= rdreq_reqid; 233 | rd_tlpwr <= rdreq_tlpwr; 234 | end 235 | 236 | // BRAM: 'configuration space' - 4kB / 0x1000 bytes: 237 | bram_pcie_cfgspace i_bram_pcie_cfgspace( 238 | .clka ( clk_pcie ), 239 | .clkb ( clk_pcie ), 240 | .wea ( wr_be_d ), 241 | .addra ( rd_addr ), 242 | .dina ( wr_dina ), 243 | .addrb ( rdwr_addr ), 244 | .doutb ( rd_data ) 245 | ); 246 | 247 | // DROM: 'configuration space' - 4kB / 0x1000 bytes write mask: 248 | drom_pcie_cfgspace_writemask i_drom_pcie_cfgspace_writemask( 249 | .a ( rd_addr ), 250 | .spo ( wr_mask ) 251 | ); 252 | 253 | genvar i; 254 | generate 255 | for (i = 0; i < 32; i++) begin 256 | assign wr_dina[i] = wr_mask[i] ? wr_data_d[i] : rd_data[i]; 257 | end 258 | endgenerate 259 | 260 | endmodule 261 | -------------------------------------------------------------------------------- /vivado_build.tcl: -------------------------------------------------------------------------------- 1 | # 2 | # RUN FROM WITHIN "Vivado Tcl Shell" WITH COMMAND: 3 | # source vivado_build.tcl -notrace 4 | # 5 | puts "-------------------------------------------------------" 6 | puts " STARTING SYNTHESIS STEP. " 7 | puts "-------------------------------------------------------" 8 | launch_runs synth_1 9 | puts "-------------------------------------------------------" 10 | puts " WAITING FOR SYNTHESIS STEP TO FINISH ... " 11 | puts " THIS IS LIKELY TO TAKE A VERY LONG TIME. " 12 | puts "-------------------------------------------------------" 13 | wait_on_run synth_1 14 | puts "-------------------------------------------------------" 15 | puts " STARTING IMPLEMENTATION STEP. " 16 | puts "-------------------------------------------------------" 17 | launch_runs impl_1 -to_step write_bitstream 18 | puts "-------------------------------------------------------" 19 | puts " WAITING FOR IMPLEMENTATION STEP TO FINISH ... " 20 | puts " THIS IS LIKELY TO TAKE A VERY LONG TIME. " 21 | puts "-------------------------------------------------------" 22 | wait_on_run impl_1 23 | file copy -force ./pcileech_squirrel/pcileech_squirrel.runs/impl_1/pcileech_squirrel_top.bin pcileech_squirrel.bin 24 | puts "-------------------------------------------------------" 25 | puts " BUILD HOPEFULLY COMPLETED. " 26 | puts "-------------------------------------------------------" -------------------------------------------------------------------------------- /vivado_build_100t.tcl: -------------------------------------------------------------------------------- 1 | # 2 | # RUN FROM WITHIN "Vivado Tcl Shell" WITH COMMAND: 3 | # source vivado_build.tcl -notrace 4 | # 5 | puts "-------------------------------------------------------" 6 | puts " STARTING SYNTHESIS STEP. " 7 | puts "-------------------------------------------------------" 8 | launch_runs -jobs 6 synth_1 9 | puts "-------------------------------------------------------" 10 | puts " WAITING FOR SYNTHESIS STEP TO FINISH ... " 11 | puts " THIS IS LIKELY TO TAKE A VERY LONG TIME. " 12 | puts "-------------------------------------------------------" 13 | wait_on_run synth_1 14 | puts "-------------------------------------------------------" 15 | puts " STARTING IMPLEMENTATION STEP. " 16 | puts "-------------------------------------------------------" 17 | launch_runs -jobs 4 impl_1 -to_step write_bitstream 18 | puts "-------------------------------------------------------" 19 | puts " WAITING FOR IMPLEMENTATION STEP TO FINISH ... " 20 | puts " THIS IS LIKELY TO TAKE A VERY LONG TIME. " 21 | puts "-------------------------------------------------------" 22 | wait_on_run impl_1 23 | file copy -force ./pcileech_tbx4_100t/pcileech_tbx4_100t.runs/impl_1/pcileech_tbx4_100t_top.bin pcileech_zdma_100t_fpga0.bin 24 | puts "-------------------------------------------------------" 25 | puts " BUILD HOPEFULLY COMPLETED. " 26 | puts "-------------------------------------------------------" --------------------------------------------------------------------------------