├── .gitignore ├── LICENSE ├── Setup.hs ├── Shakefile.hs ├── cabal.project ├── constraints.xdc ├── default.nix ├── ip └── pcie_7xi │ ├── doc │ └── pcie_7x_v3_3_changelog.txt │ ├── pcie_7xi.dcp │ ├── pcie_7xi.veo │ ├── pcie_7xi.vho │ ├── pcie_7xi.xci │ ├── pcie_7xi.xml │ ├── pcie_7xi_sim_netlist.v │ ├── pcie_7xi_sim_netlist.vhdl │ ├── pcie_7xi_stub.v │ ├── pcie_7xi_stub.vhdl │ ├── sim │ └── pcie_7xi.v │ ├── source │ ├── pcie_7xi-PCIE_X0Y0.xdc │ ├── pcie_7xi_axi_basic_rx.v │ ├── pcie_7xi_axi_basic_rx_null_gen.v │ ├── pcie_7xi_axi_basic_rx_pipeline.v │ ├── pcie_7xi_axi_basic_top.v │ ├── pcie_7xi_axi_basic_tx.v │ ├── pcie_7xi_axi_basic_tx_pipeline.v │ ├── pcie_7xi_axi_basic_tx_thrtl_ctl.v │ ├── pcie_7xi_core_top.v │ ├── pcie_7xi_gt_common.v │ ├── pcie_7xi_gt_rx_valid_filter_7x.v │ ├── pcie_7xi_gt_top.v │ ├── pcie_7xi_gt_wrapper.v │ ├── pcie_7xi_gtp_cpllpd_ovrd.v │ ├── pcie_7xi_gtp_pipe_drp.v │ ├── pcie_7xi_gtp_pipe_rate.v │ ├── pcie_7xi_gtp_pipe_reset.v │ ├── pcie_7xi_gtx_cpllpd_ovrd.v │ ├── pcie_7xi_pcie2_top.v │ ├── pcie_7xi_pcie_7x.v │ ├── pcie_7xi_pcie_bram_7x.v │ ├── pcie_7xi_pcie_bram_top_7x.v │ ├── pcie_7xi_pcie_brams_7x.v │ ├── pcie_7xi_pcie_pipe_lane.v │ ├── pcie_7xi_pcie_pipe_misc.v │ ├── pcie_7xi_pcie_pipe_pipeline.v │ ├── pcie_7xi_pcie_top.v │ ├── pcie_7xi_pipe_clock.v │ ├── pcie_7xi_pipe_drp.v │ ├── pcie_7xi_pipe_eq.v │ ├── pcie_7xi_pipe_rate.v │ ├── pcie_7xi_pipe_reset.v │ ├── pcie_7xi_pipe_sync.v │ ├── pcie_7xi_pipe_user.v │ ├── pcie_7xi_pipe_wrapper.v │ ├── pcie_7xi_qpll_drp.v │ ├── pcie_7xi_qpll_reset.v │ ├── pcie_7xi_qpll_wrapper.v │ └── pcie_7xi_rxeq_scan.v │ ├── synth │ ├── pcie_7xi.v │ └── pcie_7xi_ooc.xdc │ └── sys_clk_gen_ps_v.txt ├── nix ├── default.nix ├── sources.json └── sources.nix ├── picodma-fpga.cabal ├── readme.md ├── shell.nix ├── src ├── Axi.hs ├── Blackboxes.hs ├── Clash │ └── Minilude.hs ├── Dma │ └── Prelude.hs ├── Pcie.hs ├── Probe.hs ├── Register.hs ├── Search.hs ├── SpiSlave.hs ├── StreamReassembly.hs ├── Tlp.hs └── Top.hs └── tests ├── Test ├── DmaCore.hs └── Test.hs └── tests.hs /.gitignore: -------------------------------------------------------------------------------- 1 | trash/ 2 | .shake/ 3 | result/ 4 | .envrc 5 | .git-old/ 6 | micropython-setup.py 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2019 PicoDMA Team 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -------------------------------------------------------------------------------- /Shakefile.hs: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env runhaskell 2 | 3 | {-# LANGUAGE RecordWildCards #-} 4 | {-# LANGUAGE ScopedTypeVariables #-} 5 | {-# LANGUAGE QuasiQuotes #-} 6 | 7 | import Development.Shake hiding ((~>)) 8 | import Development.Shake.Command 9 | import Development.Shake.FilePath 10 | import Development.Shake.Config 11 | import Development.Shake.Util 12 | 13 | import System.Directory (copyFile) 14 | 15 | import Data.String.Interpolate 16 | import Data.String.Interpolate.Util 17 | 18 | import Data.ByteString (ByteString) 19 | import qualified Data.ByteString as B hiding (unpack, putStrLn) 20 | import qualified Data.ByteString.Char8 as B (unpack, putStrLn) 21 | 22 | import Text.Regex.TDFA 23 | import qualified Data.Text as T 24 | 25 | import Data.String (fromString) 26 | 27 | import Clash.Driver.Types 28 | 29 | topModule = "Top" 30 | topName = "board" 31 | 32 | artifactDir = ".shake" 33 | hdl = "verilog" 34 | envDir = artifactDir hdl topModule topName 35 | manifest = envDir topName <.> "manifest" 36 | 37 | copyTo dir n = copyFile' n (dir takeFileName n) 38 | 39 | readManifest content = [ envDir f <.> "v" | f <- files ] 40 | where 41 | files = map T.unpack (componentNames $ read content) 42 | 43 | getManifestOutputs = do 44 | need [manifest] 45 | readManifest <$> readFile' manifest 46 | 47 | testReport = artifactDir "test-report.txt" 48 | 49 | main :: IO () 50 | main = shakeArgs shakeOptions 51 | { shakeThreads = 0 52 | , shakeColor = True 53 | -- , shakeLint = Just LintFSATrace 54 | } $ do 55 | want [testReport] 56 | 57 | phony "clean" $ do 58 | putNormal "Removing build files and generated HDL" 59 | removeFilesAfter artifactDir ["//*"] 60 | 61 | testReport %> \o -> do 62 | getDirectoryFiles "" ["src//*.hs"] >>= need 63 | getDirectoryFiles "" ["tests//*.hs"] >>= need 64 | 65 | need ["picodma-fpga.cabal"] 66 | 67 | Stdout (out :: ByteString) <- cmd "cabal run tests" 68 | let s = out =~ "Expected successes(\n*.*)*" 69 | liftIO $ B.writeFile o s 70 | putNormal (B.unpack s) 71 | 72 | phony "test" $ do 73 | need [testReport] 74 | readFile' testReport >>= putNormal 75 | 76 | manifest %> \o -> do 77 | need [testReport] 78 | 79 | getDirectoryFiles "" ["src//*.hs"] >>= need 80 | 81 | withTempDir $ \trash -> do 82 | let odir = trash "odir" 83 | let hidir = trash "hidir" 84 | let top = "src/Top.hs" 85 | let opts = 86 | ["--verilog", "-isrc" 87 | , "-odir", odir 88 | , "-hidir", hidir 89 | , "-fclash-inline-limit=200" 90 | , "-fclash-hdldir", artifactDir 91 | , "-fclash-hdlsyn", "Xilinx" 92 | ] 93 | ++ [top] 94 | cmd_ "clash" opts 95 | 96 | hdl <- readManifest <$> liftIO (readFile manifest) 97 | produces hdl 98 | 99 | phony "clash" $ need [manifest] 100 | 101 | phony "yosys" $ do 102 | need [manifest] 103 | stubs <- getDirectoryFiles "" ["ip//*.v"] 104 | need stubs 105 | 106 | source <- getManifestOutputs 107 | 108 | (Stdout (out :: ByteString), Stderr (err :: ByteString)) 109 | <- cmd "yosys -p synth_xilinx" stubs source 110 | 111 | liftIO $ B.putStrLn $ out =~ "=== design hierarchy ===(\n*.*)*Number of cells.*(\n.+)*" 112 | liftIO $ B.writeFile "hdl/.yosys" $ out =~ "Printing statistics(\n*.*)*" 113 | 114 | "picodma.bit" %> \o -> do 115 | let mcs = takeDirectory o "picodma.mcs" 116 | 117 | need [manifest] 118 | 119 | source <- getManifestOutputs 120 | 121 | ip <- getDirectoryFiles "" ["ip//*.xci"] 122 | constraints <- getDirectoryFiles "" ["constraints.xdc"] 123 | need (ip <> constraints) 124 | 125 | withTempFile $ \tclFile -> do 126 | writeFile' tclFile 127 | $ vivadoTcl 128 | source 129 | ip 130 | constraints 131 | 132 | vivadoCmd tclFile 133 | 134 | produces [takeDirectory o "picodma.mcs"] 135 | 136 | phony "vivado" $ need ["picodma.bit"] 137 | 138 | phony "programFpga" $ do 139 | alwaysRerun 140 | 141 | need ["picodma.bit"] 142 | 143 | withTempFile $ \tclFile -> do 144 | writeFile' tclFile programFpgaTcl 145 | 146 | vivadoCmd tclFile 147 | 148 | phony "flashFpga" $ do 149 | alwaysRerun 150 | 151 | need ["picodma.mcs"] 152 | 153 | withTempFile $ \tclFile -> do 154 | writeFile' tclFile flashFpgaTcl 155 | 156 | vivadoCmd tclFile 157 | 158 | --- * Vivado scripts 159 | 160 | vivadoCmd tclFile = cmd_ [i|vivado -nolog -nojournal -mode batch -source #{tclFile}|] 161 | 162 | vivadoTcl source ip constraints = unindent [i| 163 | set_part xc7a50tcsg325-2 164 | 165 | read_verilog #{unwords source} 166 | read_ip #{unwords ip} 167 | read_xdc #{unwords constraints} 168 | 169 | synth_ip [get_ips] 170 | 171 | synth_design -top board 172 | 173 | opt_design -sweep -retarget -propconst -bram_power_opt -remap 174 | opt_design -directive Explore 175 | 176 | place_design 177 | 178 | # phys_opt_design -directive Explore 179 | route_design -directive Explore 180 | 181 | # phys_opt_design -directive Explore 182 | 183 | report_utilization 184 | report_timing 185 | 186 | write_bitstream -force picodma.bit 187 | 188 | write_cfgmem -force -format mcs -size 4 -interface SPIx4 -loadbit {up 0x00000000 "picodma.bit" } -file "picodma.mcs" 189 | |] 190 | 191 | connectHw = unindent [i| 192 | open_hw_manager 193 | 194 | connect_hw_server 195 | 196 | # fpga connection errors - vivado bug? 197 | set i 0 198 | while {[catch {open_hw_target -xvc_url localhost:2542} issue] && $i < 5} { 199 | puts "Failed to connect to FPGA : $issue" 200 | after 500 201 | incr i 202 | } 203 | 204 | set i 0 205 | while {[catch {refresh_hw_target} issue] && $i < 5} { 206 | puts "Failed to connect to FPGA : $issue" 207 | after 500 208 | incr i 209 | } 210 | 211 | set i 0 212 | while {[catch {get_hw_devices} issue] && $i < 5} { 213 | puts "Failed to connect to FPGA : $issue" 214 | after 500 215 | incr i 216 | } 217 | |] 218 | 219 | 220 | 221 | programFpgaTcl = connectHw <> unindent [i| 222 | create_hw_bitstream -hw_device [lindex [get_hw_devices xc7a50t_0] 0] "picodma.bit" 223 | program_hw_devices [get_hw_devices xc7a50t_0] 224 | |] 225 | 226 | flashFpgaTcl = connectHw <> unindent [i| 227 | # from https://github.com/RHSResearchLLC/PicoEVB/blob/master/Sample-Projects/Project-0/FPGA/tcl/prog-flash.tcl 228 | 229 | # Add flash part, s25fl132k; default to erase and program (no verify) 230 | create_hw_cfgmem -hw_device [lindex [get_hw_devices xc7a50t_0] 0] [lindex [get_cfgmem_parts {s25fl132k-spi-x1_x2_x4}] 0] 231 | set_property PROGRAM.BLANK_CHECK 0 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a50t_0] 0]] 232 | set_property PROGRAM.ERASE 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a50t_0] 0]] 233 | set_property PROGRAM.CFG_PROGRAM 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a50t_0] 0]] 234 | set_property PROGRAM.VERIFY 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a50t_0] 0]] 235 | set_property PROGRAM.CHECKSUM 0 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a50t_0] 0]] 236 | refresh_hw_device [lindex [get_hw_devices xc7a50t_0] 0] 237 | set_property PROGRAM.ADDRESS_RANGE {use_file} [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a50t_0] 0]] 238 | set_property PROGRAM.FILES [list "picodma.mcs" ] [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a50t_0] 0]] 239 | set_property PROGRAM.PRM_FILE {} [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a50t_0] 0]] 240 | set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a50t_0] 0]] 241 | 242 | # Program the fabric with the flash loader 243 | startgroup 244 | if {![string equal [get_property PROGRAM.HW_CFGMEM_TYPE [lindex [get_hw_devices xc7a50t_0] 0]] [get_property MEM_TYPE [get_property CFGMEM_PART [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a50t_0] 0]]]]] } { create_hw_bitstream -hw_device [lindex [get_hw_devices xc7a50t_0] 0] [get_property PROGRAM.HW_CFGMEM_BITFILE [ lindex [get_hw_devices xc7a50t_0] 0]]; program_hw_devices [lindex [get_hw_devices xc7a50t_0] 0]; }; 245 | 246 | # Finally, program the flash 247 | program_hw_cfgmem -hw_cfgmem [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices xc7a50t_0] 0]] 248 | 249 | |] 250 | 251 | -------------------------------------------------------------------------------- /cabal.project: -------------------------------------------------------------------------------- 1 | packages: . 2 | -------------------------------------------------------------------------------- /constraints.xdc: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Pinout and Related I/O Constraints 3 | ############################################################################### 4 | # SYS reset (input) signal. The sys_reset_n signal is generated 5 | # by the PCI Express interface (PERST#). 6 | set_property PACKAGE_PIN A10 [get_ports sys_rst_n] 7 | set_property IOSTANDARD LVCMOS33 [get_ports sys_rst_n] 8 | set_property PULLDOWN true [get_ports sys_rst_n] 9 | 10 | # SYS clock 100 MHz (input) signal. The sys_clk_p and sys_clk_n 11 | # signals are the PCI Express reference clock. 12 | set_property PACKAGE_PIN B6 [get_ports sys_clk_p] 13 | set_property PACKAGE_PIN B5 [get_ports sys_clk_n] 14 | 15 | # PCIe x1 link 16 | # set_property LOC GTPE2_CHANNEL_X0Y3 [get_cells {pcie_7x_0/U0/inst/gt_top_i/pipe_wrapper_i/pipe_lane[0].gt_wrapper_i/gtp_channel.gtpe2_channel_i}] 17 | # 18 | set_property LOC GTPE2_CHANNEL_X0Y3 [get_cells {*/pcie_7xi_inst/inst/inst/gt_top_i/pipe_wrapper_i/pipe_lane[0].gt_wrapper_i/gtp_channel.gtpe2_channel_i}] 19 | # set_property LOC GTPE2_CHANNEL_X0Y3 [get_cells {*/pcie_7x_0_inst/inst/inst/gt_top_i/pipe_wrapper_i/pipe_lane[0].gt_wrapper_i/gtp_channel.gtpe2_channel_i}] 20 | # set_property LOC GTPE2_CHANNEL_X0Y3 [get_cells {*/pcie_7x_0_inst/inst/inst/gt_top_i/pipe_wrapper_i/pipe_lane[0].gt_wrapper_i/gtp_channel.gtpe2_channel_i}] 21 | # set_property PACKAGE_PIN G3 [get_ports {pcie_mgt_rx[0]}] 22 | # set_property PACKAGE_PIN G4 [get_ports {pcie_mgt_rx[1]}] 23 | # set_property PACKAGE_PIN B1 [get_ports {pcie_mgt_tx[0]}] 24 | # set_property PACKAGE_PIN B2 [get_ports {pcie_mgt_tx[1]}] 25 | set_property PACKAGE_PIN G3 [get_ports pcie_mgt_rx_n] 26 | set_property PACKAGE_PIN G4 [get_ports pcie_mgt_rx_p] 27 | set_property PACKAGE_PIN B1 [get_ports pcie_mgt_tx_n] 28 | set_property PACKAGE_PIN B2 [get_ports pcie_mgt_tx_p] 29 | 30 | # MGT Loopback 31 | #set_property PACKAGE_PIN C4 [get_ports loop_mgt_rxp] 32 | #set_property PACKAGE_PIN C3 [get_ports loop_mgt_rxn] 33 | #set_property PACKAGE_PIN D2 [get_ports loop_mgt_txp] 34 | #set_property PACKAGE_PIN D1 [get_ports loop_mgt_txn] 35 | 36 | ############################################################################### 37 | # Timing Constraints 38 | ############################################################################### 39 | 40 | create_clock -period 10.000 -name sys_clk [get_ports sys_clk_p] 41 | 42 | ############################################################################### 43 | # Physical Constraints 44 | ############################################################################### 45 | 46 | # Input reset is resynchronized within FPGA design as necessary 47 | set_false_path -from [get_ports sys_rst_n] 48 | #eh 49 | #set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets sys_rst_n_IBUF] 50 | 51 | ######################################################################################################################### 52 | # End PCIe Core Constraints 53 | ######################################################################################################################### 54 | 55 | 56 | ############################################################################### 57 | # NanoEVB, PicoEVB common I/O 58 | ############################################################################### 59 | 60 | set_property PACKAGE_PIN V14 [get_ports {status_leds[2]}] 61 | set_property PACKAGE_PIN V13 [get_ports {status_leds[1]}] 62 | set_property PACKAGE_PIN V12 [get_ports {status_leds[0]}] 63 | set_property IOSTANDARD LVCMOS33 [get_ports {status_leds[2]}] 64 | set_property IOSTANDARD LVCMOS33 [get_ports {status_leds[1]}] 65 | set_property IOSTANDARD LVCMOS33 [get_ports {status_leds[0]}] 66 | set_property PULLUP true [get_ports {status_leds[2]}] 67 | set_property PULLUP true [get_ports {status_leds[1]}] 68 | set_property PULLUP true [get_ports {status_leds[0]}] 69 | set_property DRIVE 8 [get_ports {status_leds[2]}] 70 | set_property DRIVE 8 [get_ports {status_leds[1]}] 71 | set_property DRIVE 8 [get_ports {status_leds[0]}] 72 | 73 | # clkreq_l is active low clock request for M.2 card to 74 | # request PCI Express reference clock 75 | set_property PACKAGE_PIN A9 [get_ports clkreq_l] 76 | set_property IOSTANDARD LVCMOS33 [get_ports clkreq_l] 77 | set_property PULLDOWN true [get_ports clkreq_l] 78 | 79 | # Auxillary I/O Connector 80 | # auxio[0] - conn pin 1 81 | # auxio[1] - conn pin 2 82 | # auxio[2] - conn pin 4 83 | # auxio[3] - conn pin 5 84 | # Note: These I/O may be re-purposed to use with XADC as analog inputs 85 | 86 | set_property PACKAGE_PIN A14 [get_ports spi_select] 87 | set_property PACKAGE_PIN A13 [get_ports spi_mosi] 88 | set_property PACKAGE_PIN B12 [get_ports spi_miso] 89 | set_property PACKAGE_PIN A12 [get_ports spi_clock] 90 | set_property IOSTANDARD LVCMOS33 [get_ports spi_select] 91 | set_property IOSTANDARD LVCMOS33 [get_ports spi_mosi] 92 | set_property IOSTANDARD LVCMOS33 [get_ports spi_miso] 93 | set_property IOSTANDARD LVCMOS33 [get_ports spi_clock] 94 | 95 | #set_property PULLDOWN true [get_ports spi_select] 96 | #set_property PULLUP true [get_ports spi_clock] 97 | 98 | 99 | ############################################################################### 100 | # PicoEVB-specific I/O 101 | # Digital IO on PCIe edge connector (PicoEVB Rev.D and newer) 102 | ############################################################################### 103 | # set_property PACKAGE_PIN K2 [get_ports {di_edge[0]}] 104 | # set_property PACKAGE_PIN K1 [get_ports {di_edge[1]}] 105 | # set_property PACKAGE_PIN V2 [get_ports {do_edge[0]}] 106 | # set_property PACKAGE_PIN V3 [get_ports {do_edge[1]}] 107 | # set_property IOSTANDARD LVCMOS33 [get_ports {di_edge[0]}] 108 | # set_property IOSTANDARD LVCMOS33 [get_ports {di_edge[1]}] 109 | # set_property IOSTANDARD LVCMOS33 [get_ports {do_edge[0]}] 110 | # set_property IOSTANDARD LVCMOS33 [get_ports {do_edge[1]}] 111 | 112 | 113 | 114 | # High-speed configuration so FPGA is up in time to negotiate with PCIe root complex 115 | set_property BITSTREAM.CONFIG.CONFIGRATE 66 [current_design] 116 | set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design] 117 | set_property CONFIG_MODE SPIx4 [current_design] 118 | set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES [current_design] 119 | set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design] 120 | 121 | set_property CONFIG_VOLTAGE 3.3 [current_design] 122 | set_property CFGBVS VCCO [current_design] 123 | 124 | # set_property OFFCHIP_TERM NONE [get_ports TxD] 125 | 126 | # set_input_delay -clock pcie_7x_0_user_clk_out -min 2 -max 2 [get_ports spi_select] 127 | # set_input_delay -clock pcie_7x_0_user_clk_out -min 2 -max 2 [get_ports spi_mosi] 128 | # set_input_delay -clock pcie_7x_0_user_clk_out -min 2 -max 2 [get_ports spi_miso] 129 | # set_input_delay -clock pcie_7x_0_user_clk_out -min 2 -max 2 [get_ports spi_clock] 130 | -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | let sources = import ./nix/sources.nix; 2 | pkgs = import ./nix { inherit sources; }; 3 | haskellPackages = pkgs.haskell.packages.ghc865; 4 | 5 | in haskellPackages.callCabal2nix "picodma-fpga" ./. { } 6 | # picodma-fpga = haskellPackages.developPackage { 7 | # root = (pkgs.gitignore.gitignoreSource ./.); 8 | # name = "picodma-fpga"; 9 | 10 | # overrides = (self: super: 11 | # { ghc = super.ghc // { withPackages = super.ghc.withHoogle; }; 12 | # ghcWithPackages = self.ghc.withPackages; 13 | # }); 14 | 15 | # modifier = drv: pkgs.haskell.lib.overrideCabal drv (attrs: { 16 | # buildTools = (attrs.buildTools or []) 17 | # ++ [ 18 | # pkgs.niv 19 | # pkgs.yosys 20 | # ] 21 | # ++ (with haskellPackages; [ 22 | # cabal-install 23 | # clash-ghc 24 | # clash-lib 25 | # clash-ghc 26 | 27 | # shake 28 | # interpolate 29 | # bytestring 30 | # regex-tdfa 31 | # influxdb 32 | # ]); 33 | 34 | # buildDepends = (attrs.buildDepends or []) ++ [ haskellPackages.shake ]; 35 | # }); 36 | # returnShellEnv = true; 37 | # }; 38 | # in { inherit pkgs picodma-fpga; } 39 | -------------------------------------------------------------------------------- /ip/pcie_7xi/pcie_7xi.dcp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picodma/picodma-fpga/32005b72bbfd0cb2d8564db769655fe04a76fe35/ip/pcie_7xi/pcie_7xi.dcp -------------------------------------------------------------------------------- /ip/pcie_7xi/pcie_7xi_stub.v: -------------------------------------------------------------------------------- 1 | // Copyright 1986-2019 Xilinx, Inc. All Rights Reserved. 2 | // -------------------------------------------------------------------------------- 3 | // Tool Version: Vivado v.2019.2 (lin64) Build 2708876 Wed Nov 6 21:39:14 MST 2019 4 | // Date : Sat Nov 23 05:37:06 2019 5 | // Host : e200 running 64-bit unknown 6 | // Command : write_verilog -force -mode synth_stub /home/ben/clash-dma/ip/pcie_7xi/pcie_7xi_stub.v 7 | // Design : pcie_7xi 8 | // Purpose : Stub declaration of top-level module interface 9 | // Device : xc7a50tcsg325-2 10 | // -------------------------------------------------------------------------------- 11 | 12 | // This empty module with port declaration file causes synthesis tools to infer a black box for IP. 13 | // The synthesis directives are for Synopsys Synplify support to prevent IO buffer insertion. 14 | // Please paste the declaration into a Verilog source file or add the file as an additional source. 15 | (* X_CORE_INFO = "pcie_7xi_pcie2_top,Vivado 2019.2" *) 16 | module pcie_7xi(pci_exp_txp, pci_exp_txn, pci_exp_rxp, 17 | pci_exp_rxn, user_clk_out, user_reset_out, user_lnk_up, user_app_rdy, tx_buf_av, tx_cfg_req, 18 | tx_err_drop, s_axis_tx_tready, s_axis_tx_tdata, s_axis_tx_tkeep, s_axis_tx_tlast, 19 | s_axis_tx_tvalid, s_axis_tx_tuser, tx_cfg_gnt, m_axis_rx_tdata, m_axis_rx_tkeep, 20 | m_axis_rx_tlast, m_axis_rx_tvalid, m_axis_rx_tready, m_axis_rx_tuser, rx_np_ok, rx_np_req, 21 | cfg_mgmt_do, cfg_mgmt_rd_wr_done, cfg_status, cfg_command, cfg_dstatus, cfg_dcommand, 22 | cfg_lstatus, cfg_lcommand, cfg_dcommand2, cfg_pcie_link_state, cfg_pmcsr_pme_en, 23 | cfg_pmcsr_powerstate, cfg_pmcsr_pme_status, cfg_received_func_lvl_rst, cfg_mgmt_di, 24 | cfg_mgmt_byte_en, cfg_mgmt_dwaddr, cfg_mgmt_wr_en, cfg_mgmt_rd_en, cfg_mgmt_wr_readonly, 25 | cfg_trn_pending, cfg_pm_halt_aspm_l0s, cfg_pm_halt_aspm_l1, cfg_pm_force_state_en, 26 | cfg_pm_force_state, cfg_dsn, cfg_interrupt, cfg_interrupt_rdy, cfg_interrupt_assert, 27 | cfg_interrupt_di, cfg_interrupt_do, cfg_interrupt_mmenable, cfg_interrupt_msienable, 28 | cfg_interrupt_msixenable, cfg_interrupt_msixfm, cfg_interrupt_stat, 29 | cfg_pciecap_interrupt_msgnum, cfg_to_turnoff, cfg_turnoff_ok, cfg_bus_number, 30 | cfg_device_number, cfg_function_number, cfg_pm_wake, cfg_pm_send_pme_to, 31 | cfg_ds_bus_number, cfg_ds_device_number, cfg_ds_function_number, 32 | cfg_mgmt_wr_rw1c_as_rw, cfg_bridge_serr_en, 33 | cfg_slot_control_electromech_il_ctl_pulse, cfg_root_control_syserr_corr_err_en, 34 | cfg_root_control_syserr_non_fatal_err_en, cfg_root_control_syserr_fatal_err_en, 35 | cfg_root_control_pme_int_en, cfg_aer_rooterr_corr_err_reporting_en, 36 | cfg_aer_rooterr_non_fatal_err_reporting_en, cfg_aer_rooterr_fatal_err_reporting_en, 37 | cfg_aer_rooterr_corr_err_received, cfg_aer_rooterr_non_fatal_err_received, 38 | cfg_aer_rooterr_fatal_err_received, cfg_vc_tcvc_map, sys_clk, sys_rst_n) 39 | /* synthesis syn_black_box black_box_pad_pin="pci_exp_txp[0:0],pci_exp_txn[0:0],pci_exp_rxp[0:0],pci_exp_rxn[0:0],user_clk_out,user_reset_out,user_lnk_up,user_app_rdy,tx_buf_av[5:0],tx_cfg_req,tx_err_drop,s_axis_tx_tready,s_axis_tx_tdata[63:0],s_axis_tx_tkeep[7:0],s_axis_tx_tlast,s_axis_tx_tvalid,s_axis_tx_tuser[3:0],tx_cfg_gnt,m_axis_rx_tdata[63:0],m_axis_rx_tkeep[7:0],m_axis_rx_tlast,m_axis_rx_tvalid,m_axis_rx_tready,m_axis_rx_tuser[21:0],rx_np_ok,rx_np_req,cfg_mgmt_do[31:0],cfg_mgmt_rd_wr_done,cfg_status[15:0],cfg_command[15:0],cfg_dstatus[15:0],cfg_dcommand[15:0],cfg_lstatus[15:0],cfg_lcommand[15:0],cfg_dcommand2[15:0],cfg_pcie_link_state[2:0],cfg_pmcsr_pme_en,cfg_pmcsr_powerstate[1:0],cfg_pmcsr_pme_status,cfg_received_func_lvl_rst,cfg_mgmt_di[31:0],cfg_mgmt_byte_en[3:0],cfg_mgmt_dwaddr[9:0],cfg_mgmt_wr_en,cfg_mgmt_rd_en,cfg_mgmt_wr_readonly,cfg_trn_pending,cfg_pm_halt_aspm_l0s,cfg_pm_halt_aspm_l1,cfg_pm_force_state_en,cfg_pm_force_state[1:0],cfg_dsn[63:0],cfg_interrupt,cfg_interrupt_rdy,cfg_interrupt_assert,cfg_interrupt_di[7:0],cfg_interrupt_do[7:0],cfg_interrupt_mmenable[2:0],cfg_interrupt_msienable,cfg_interrupt_msixenable,cfg_interrupt_msixfm,cfg_interrupt_stat,cfg_pciecap_interrupt_msgnum[4:0],cfg_to_turnoff,cfg_turnoff_ok,cfg_bus_number[7:0],cfg_device_number[4:0],cfg_function_number[2:0],cfg_pm_wake,cfg_pm_send_pme_to,cfg_ds_bus_number[7:0],cfg_ds_device_number[4:0],cfg_ds_function_number[2:0],cfg_mgmt_wr_rw1c_as_rw,cfg_bridge_serr_en,cfg_slot_control_electromech_il_ctl_pulse,cfg_root_control_syserr_corr_err_en,cfg_root_control_syserr_non_fatal_err_en,cfg_root_control_syserr_fatal_err_en,cfg_root_control_pme_int_en,cfg_aer_rooterr_corr_err_reporting_en,cfg_aer_rooterr_non_fatal_err_reporting_en,cfg_aer_rooterr_fatal_err_reporting_en,cfg_aer_rooterr_corr_err_received,cfg_aer_rooterr_non_fatal_err_received,cfg_aer_rooterr_fatal_err_received,cfg_vc_tcvc_map[6:0],sys_clk,sys_rst_n" */; 40 | output [0:0]pci_exp_txp; 41 | output [0:0]pci_exp_txn; 42 | input [0:0]pci_exp_rxp; 43 | input [0:0]pci_exp_rxn; 44 | output user_clk_out; 45 | output user_reset_out; 46 | output user_lnk_up; 47 | output user_app_rdy; 48 | output [5:0]tx_buf_av; 49 | output tx_cfg_req; 50 | output tx_err_drop; 51 | output s_axis_tx_tready; 52 | input [63:0]s_axis_tx_tdata; 53 | input [7:0]s_axis_tx_tkeep; 54 | input s_axis_tx_tlast; 55 | input s_axis_tx_tvalid; 56 | input [3:0]s_axis_tx_tuser; 57 | input tx_cfg_gnt; 58 | output [63:0]m_axis_rx_tdata; 59 | output [7:0]m_axis_rx_tkeep; 60 | output m_axis_rx_tlast; 61 | output m_axis_rx_tvalid; 62 | input m_axis_rx_tready; 63 | output [21:0]m_axis_rx_tuser; 64 | input rx_np_ok; 65 | input rx_np_req; 66 | output [31:0]cfg_mgmt_do; 67 | output cfg_mgmt_rd_wr_done; 68 | output [15:0]cfg_status; 69 | output [15:0]cfg_command; 70 | output [15:0]cfg_dstatus; 71 | output [15:0]cfg_dcommand; 72 | output [15:0]cfg_lstatus; 73 | output [15:0]cfg_lcommand; 74 | output [15:0]cfg_dcommand2; 75 | output [2:0]cfg_pcie_link_state; 76 | output cfg_pmcsr_pme_en; 77 | output [1:0]cfg_pmcsr_powerstate; 78 | output cfg_pmcsr_pme_status; 79 | output cfg_received_func_lvl_rst; 80 | input [31:0]cfg_mgmt_di; 81 | input [3:0]cfg_mgmt_byte_en; 82 | input [9:0]cfg_mgmt_dwaddr; 83 | input cfg_mgmt_wr_en; 84 | input cfg_mgmt_rd_en; 85 | input cfg_mgmt_wr_readonly; 86 | input cfg_trn_pending; 87 | input cfg_pm_halt_aspm_l0s; 88 | input cfg_pm_halt_aspm_l1; 89 | input cfg_pm_force_state_en; 90 | input [1:0]cfg_pm_force_state; 91 | input [63:0]cfg_dsn; 92 | input cfg_interrupt; 93 | output cfg_interrupt_rdy; 94 | input cfg_interrupt_assert; 95 | input [7:0]cfg_interrupt_di; 96 | output [7:0]cfg_interrupt_do; 97 | output [2:0]cfg_interrupt_mmenable; 98 | output cfg_interrupt_msienable; 99 | output cfg_interrupt_msixenable; 100 | output cfg_interrupt_msixfm; 101 | input cfg_interrupt_stat; 102 | input [4:0]cfg_pciecap_interrupt_msgnum; 103 | output cfg_to_turnoff; 104 | input cfg_turnoff_ok; 105 | output [7:0]cfg_bus_number; 106 | output [4:0]cfg_device_number; 107 | output [2:0]cfg_function_number; 108 | input cfg_pm_wake; 109 | input cfg_pm_send_pme_to; 110 | input [7:0]cfg_ds_bus_number; 111 | input [4:0]cfg_ds_device_number; 112 | input [2:0]cfg_ds_function_number; 113 | input cfg_mgmt_wr_rw1c_as_rw; 114 | output cfg_bridge_serr_en; 115 | output cfg_slot_control_electromech_il_ctl_pulse; 116 | output cfg_root_control_syserr_corr_err_en; 117 | output cfg_root_control_syserr_non_fatal_err_en; 118 | output cfg_root_control_syserr_fatal_err_en; 119 | output cfg_root_control_pme_int_en; 120 | output cfg_aer_rooterr_corr_err_reporting_en; 121 | output cfg_aer_rooterr_non_fatal_err_reporting_en; 122 | output cfg_aer_rooterr_fatal_err_reporting_en; 123 | output cfg_aer_rooterr_corr_err_received; 124 | output cfg_aer_rooterr_non_fatal_err_received; 125 | output cfg_aer_rooterr_fatal_err_received; 126 | output [6:0]cfg_vc_tcvc_map; 127 | input sys_clk; 128 | input sys_rst_n; 129 | endmodule 130 | -------------------------------------------------------------------------------- /ip/pcie_7xi/pcie_7xi_stub.vhdl: -------------------------------------------------------------------------------- 1 | -- Copyright 1986-2019 Xilinx, Inc. All Rights Reserved. 2 | -- -------------------------------------------------------------------------------- 3 | -- Tool Version: Vivado v.2019.2 (lin64) Build 2708876 Wed Nov 6 21:39:14 MST 2019 4 | -- Date : Sat Nov 23 05:37:06 2019 5 | -- Host : e200 running 64-bit unknown 6 | -- Command : write_vhdl -force -mode synth_stub /home/ben/clash-dma/ip/pcie_7xi/pcie_7xi_stub.vhdl 7 | -- Design : pcie_7xi 8 | -- Purpose : Stub declaration of top-level module interface 9 | -- Device : xc7a50tcsg325-2 10 | -- -------------------------------------------------------------------------------- 11 | library IEEE; 12 | use IEEE.STD_LOGIC_1164.ALL; 13 | 14 | entity pcie_7xi is 15 | Port ( 16 | pci_exp_txp : out STD_LOGIC_VECTOR ( 0 to 0 ); 17 | pci_exp_txn : out STD_LOGIC_VECTOR ( 0 to 0 ); 18 | pci_exp_rxp : in STD_LOGIC_VECTOR ( 0 to 0 ); 19 | pci_exp_rxn : in STD_LOGIC_VECTOR ( 0 to 0 ); 20 | user_clk_out : out STD_LOGIC; 21 | user_reset_out : out STD_LOGIC; 22 | user_lnk_up : out STD_LOGIC; 23 | user_app_rdy : out STD_LOGIC; 24 | tx_buf_av : out STD_LOGIC_VECTOR ( 5 downto 0 ); 25 | tx_cfg_req : out STD_LOGIC; 26 | tx_err_drop : out STD_LOGIC; 27 | s_axis_tx_tready : out STD_LOGIC; 28 | s_axis_tx_tdata : in STD_LOGIC_VECTOR ( 63 downto 0 ); 29 | s_axis_tx_tkeep : in STD_LOGIC_VECTOR ( 7 downto 0 ); 30 | s_axis_tx_tlast : in STD_LOGIC; 31 | s_axis_tx_tvalid : in STD_LOGIC; 32 | s_axis_tx_tuser : in STD_LOGIC_VECTOR ( 3 downto 0 ); 33 | tx_cfg_gnt : in STD_LOGIC; 34 | m_axis_rx_tdata : out STD_LOGIC_VECTOR ( 63 downto 0 ); 35 | m_axis_rx_tkeep : out STD_LOGIC_VECTOR ( 7 downto 0 ); 36 | m_axis_rx_tlast : out STD_LOGIC; 37 | m_axis_rx_tvalid : out STD_LOGIC; 38 | m_axis_rx_tready : in STD_LOGIC; 39 | m_axis_rx_tuser : out STD_LOGIC_VECTOR ( 21 downto 0 ); 40 | rx_np_ok : in STD_LOGIC; 41 | rx_np_req : in STD_LOGIC; 42 | cfg_mgmt_do : out STD_LOGIC_VECTOR ( 31 downto 0 ); 43 | cfg_mgmt_rd_wr_done : out STD_LOGIC; 44 | cfg_status : out STD_LOGIC_VECTOR ( 15 downto 0 ); 45 | cfg_command : out STD_LOGIC_VECTOR ( 15 downto 0 ); 46 | cfg_dstatus : out STD_LOGIC_VECTOR ( 15 downto 0 ); 47 | cfg_dcommand : out STD_LOGIC_VECTOR ( 15 downto 0 ); 48 | cfg_lstatus : out STD_LOGIC_VECTOR ( 15 downto 0 ); 49 | cfg_lcommand : out STD_LOGIC_VECTOR ( 15 downto 0 ); 50 | cfg_dcommand2 : out STD_LOGIC_VECTOR ( 15 downto 0 ); 51 | cfg_pcie_link_state : out STD_LOGIC_VECTOR ( 2 downto 0 ); 52 | cfg_pmcsr_pme_en : out STD_LOGIC; 53 | cfg_pmcsr_powerstate : out STD_LOGIC_VECTOR ( 1 downto 0 ); 54 | cfg_pmcsr_pme_status : out STD_LOGIC; 55 | cfg_received_func_lvl_rst : out STD_LOGIC; 56 | cfg_mgmt_di : in STD_LOGIC_VECTOR ( 31 downto 0 ); 57 | cfg_mgmt_byte_en : in STD_LOGIC_VECTOR ( 3 downto 0 ); 58 | cfg_mgmt_dwaddr : in STD_LOGIC_VECTOR ( 9 downto 0 ); 59 | cfg_mgmt_wr_en : in STD_LOGIC; 60 | cfg_mgmt_rd_en : in STD_LOGIC; 61 | cfg_mgmt_wr_readonly : in STD_LOGIC; 62 | cfg_trn_pending : in STD_LOGIC; 63 | cfg_pm_halt_aspm_l0s : in STD_LOGIC; 64 | cfg_pm_halt_aspm_l1 : in STD_LOGIC; 65 | cfg_pm_force_state_en : in STD_LOGIC; 66 | cfg_pm_force_state : in STD_LOGIC_VECTOR ( 1 downto 0 ); 67 | cfg_dsn : in STD_LOGIC_VECTOR ( 63 downto 0 ); 68 | cfg_interrupt : in STD_LOGIC; 69 | cfg_interrupt_rdy : out STD_LOGIC; 70 | cfg_interrupt_assert : in STD_LOGIC; 71 | cfg_interrupt_di : in STD_LOGIC_VECTOR ( 7 downto 0 ); 72 | cfg_interrupt_do : out STD_LOGIC_VECTOR ( 7 downto 0 ); 73 | cfg_interrupt_mmenable : out STD_LOGIC_VECTOR ( 2 downto 0 ); 74 | cfg_interrupt_msienable : out STD_LOGIC; 75 | cfg_interrupt_msixenable : out STD_LOGIC; 76 | cfg_interrupt_msixfm : out STD_LOGIC; 77 | cfg_interrupt_stat : in STD_LOGIC; 78 | cfg_pciecap_interrupt_msgnum : in STD_LOGIC_VECTOR ( 4 downto 0 ); 79 | cfg_to_turnoff : out STD_LOGIC; 80 | cfg_turnoff_ok : in STD_LOGIC; 81 | cfg_bus_number : out STD_LOGIC_VECTOR ( 7 downto 0 ); 82 | cfg_device_number : out STD_LOGIC_VECTOR ( 4 downto 0 ); 83 | cfg_function_number : out STD_LOGIC_VECTOR ( 2 downto 0 ); 84 | cfg_pm_wake : in STD_LOGIC; 85 | cfg_pm_send_pme_to : in STD_LOGIC; 86 | cfg_ds_bus_number : in STD_LOGIC_VECTOR ( 7 downto 0 ); 87 | cfg_ds_device_number : in STD_LOGIC_VECTOR ( 4 downto 0 ); 88 | cfg_ds_function_number : in STD_LOGIC_VECTOR ( 2 downto 0 ); 89 | cfg_mgmt_wr_rw1c_as_rw : in STD_LOGIC; 90 | cfg_bridge_serr_en : out STD_LOGIC; 91 | cfg_slot_control_electromech_il_ctl_pulse : out STD_LOGIC; 92 | cfg_root_control_syserr_corr_err_en : out STD_LOGIC; 93 | cfg_root_control_syserr_non_fatal_err_en : out STD_LOGIC; 94 | cfg_root_control_syserr_fatal_err_en : out STD_LOGIC; 95 | cfg_root_control_pme_int_en : out STD_LOGIC; 96 | cfg_aer_rooterr_corr_err_reporting_en : out STD_LOGIC; 97 | cfg_aer_rooterr_non_fatal_err_reporting_en : out STD_LOGIC; 98 | cfg_aer_rooterr_fatal_err_reporting_en : out STD_LOGIC; 99 | cfg_aer_rooterr_corr_err_received : out STD_LOGIC; 100 | cfg_aer_rooterr_non_fatal_err_received : out STD_LOGIC; 101 | cfg_aer_rooterr_fatal_err_received : out STD_LOGIC; 102 | cfg_vc_tcvc_map : out STD_LOGIC_VECTOR ( 6 downto 0 ); 103 | sys_clk : in STD_LOGIC; 104 | sys_rst_n : in STD_LOGIC 105 | ); 106 | 107 | end pcie_7xi; 108 | 109 | architecture stub of pcie_7xi is 110 | attribute syn_black_box : boolean; 111 | attribute black_box_pad_pin : string; 112 | attribute syn_black_box of stub : architecture is true; 113 | attribute black_box_pad_pin of stub : architecture is "pci_exp_txp[0:0],pci_exp_txn[0:0],pci_exp_rxp[0:0],pci_exp_rxn[0:0],user_clk_out,user_reset_out,user_lnk_up,user_app_rdy,tx_buf_av[5:0],tx_cfg_req,tx_err_drop,s_axis_tx_tready,s_axis_tx_tdata[63:0],s_axis_tx_tkeep[7:0],s_axis_tx_tlast,s_axis_tx_tvalid,s_axis_tx_tuser[3:0],tx_cfg_gnt,m_axis_rx_tdata[63:0],m_axis_rx_tkeep[7:0],m_axis_rx_tlast,m_axis_rx_tvalid,m_axis_rx_tready,m_axis_rx_tuser[21:0],rx_np_ok,rx_np_req,cfg_mgmt_do[31:0],cfg_mgmt_rd_wr_done,cfg_status[15:0],cfg_command[15:0],cfg_dstatus[15:0],cfg_dcommand[15:0],cfg_lstatus[15:0],cfg_lcommand[15:0],cfg_dcommand2[15:0],cfg_pcie_link_state[2:0],cfg_pmcsr_pme_en,cfg_pmcsr_powerstate[1:0],cfg_pmcsr_pme_status,cfg_received_func_lvl_rst,cfg_mgmt_di[31:0],cfg_mgmt_byte_en[3:0],cfg_mgmt_dwaddr[9:0],cfg_mgmt_wr_en,cfg_mgmt_rd_en,cfg_mgmt_wr_readonly,cfg_trn_pending,cfg_pm_halt_aspm_l0s,cfg_pm_halt_aspm_l1,cfg_pm_force_state_en,cfg_pm_force_state[1:0],cfg_dsn[63:0],cfg_interrupt,cfg_interrupt_rdy,cfg_interrupt_assert,cfg_interrupt_di[7:0],cfg_interrupt_do[7:0],cfg_interrupt_mmenable[2:0],cfg_interrupt_msienable,cfg_interrupt_msixenable,cfg_interrupt_msixfm,cfg_interrupt_stat,cfg_pciecap_interrupt_msgnum[4:0],cfg_to_turnoff,cfg_turnoff_ok,cfg_bus_number[7:0],cfg_device_number[4:0],cfg_function_number[2:0],cfg_pm_wake,cfg_pm_send_pme_to,cfg_ds_bus_number[7:0],cfg_ds_device_number[4:0],cfg_ds_function_number[2:0],cfg_mgmt_wr_rw1c_as_rw,cfg_bridge_serr_en,cfg_slot_control_electromech_il_ctl_pulse,cfg_root_control_syserr_corr_err_en,cfg_root_control_syserr_non_fatal_err_en,cfg_root_control_syserr_fatal_err_en,cfg_root_control_pme_int_en,cfg_aer_rooterr_corr_err_reporting_en,cfg_aer_rooterr_non_fatal_err_reporting_en,cfg_aer_rooterr_fatal_err_reporting_en,cfg_aer_rooterr_corr_err_received,cfg_aer_rooterr_non_fatal_err_received,cfg_aer_rooterr_fatal_err_received,cfg_vc_tcvc_map[6:0],sys_clk,sys_rst_n"; 114 | attribute X_CORE_INFO : string; 115 | attribute X_CORE_INFO of stub : architecture is "pcie_7xi_pcie2_top,Vivado 2019.2"; 116 | begin 117 | end; 118 | -------------------------------------------------------------------------------- /ip/pcie_7xi/source/pcie_7xi-PCIE_X0Y0.xdc: -------------------------------------------------------------------------------- 1 | ##----------------------------------------------------------------------------- 2 | ## 3 | ## (c) Copyright 2010-2011 Xilinx, Inc. All rights reserved. 4 | ## 5 | ## This file contains confidential and proprietary information 6 | ## of Xilinx, Inc. and is protected under U.S. and 7 | ## international copyright and other intellectual property 8 | ## laws. 9 | ## 10 | ## DISCLAIMER 11 | ## This disclaimer is not a license and does not grant any 12 | ## rights to the materials distributed herewith. Except as 13 | ## otherwise provided in a valid license issued to you by 14 | ## Xilinx, and to the maximum extent permitted by applicable 15 | ## law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND 16 | ## WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES 17 | ## AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING 18 | ## BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- 19 | ## INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and 20 | ## (2) Xilinx shall not be liable (whether in contract or tort, 21 | ## including negligence, or under any other theory of 22 | ## liability) for any loss or damage of any kind or nature 23 | ## related to, arising under or in connection with these 24 | ## materials, including for any direct, or any indirect, 25 | ## special, incidental, or consequential loss or damage 26 | ## (including loss of data, profits, goodwill, or any type of 27 | ## loss or damage suffered as a result of any action brought 28 | ## by a third party) even if such damage or loss was 29 | ## reasonably foreseeable or Xilinx had been advised of the 30 | ## possibility of the same. 31 | ## 32 | ## CRITICAL APPLICATIONS 33 | ## Xilinx products are not designed or intended to be fail- 34 | ## safe, or for use in any application requiring fail-safe 35 | ## performance, such as life-support or safety devices or 36 | ## systems, Class III medical devices, nuclear facilities, 37 | ## applications related to the deployment of airbags, or any 38 | ## other applications that could lead to death, personal 39 | ## injury, or severe property or environmental damage 40 | ## (individually and collectively, "Critical 41 | ## Applications"). Customer assumes the sole risk and 42 | ## liability of any use of Xilinx products in Critical 43 | ## Applications, subject only to applicable laws and 44 | ## regulations governing limitations on product liability. 45 | ## 46 | ## THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS 47 | ## PART OF THIS FILE AT ALL TIMES. 48 | ## 49 | ##----------------------------------------------------------------------------- 50 | ## Project : Series-7 Integrated Block for PCI Express 51 | ## File : pcie_7xi-PCIE_X0Y0.xdc 52 | ## Version : 3.3 53 | # 54 | ############################################################################### 55 | # Vivado - PCIe GUI / User Configuration 56 | ############################################################################### 57 | # 58 | # Family - artix7 59 | # Part - xc7a50t 60 | # Package - csg325 61 | # Speed grade - -2 62 | # PCIe Block - PCIE_X0Y0 63 | # 64 | # Link Speed - 2 65 | # Link Width - X1 66 | # AXIST Width - 64-bit 67 | # AXIST Frequ - 2 68 | # 69 | ############################################################################### 70 | # User Time Names / User Time Groups / Time Specs 71 | ############################################################################### 72 | 73 | ############################################################################### 74 | # User Physical Constraints 75 | ############################################################################### 76 | 77 | 78 | ############################################################################### 79 | # Pinout and Related I/O Constraints 80 | ############################################################################### 81 | 82 | 83 | ############################################################################### 84 | # Physical Constraints 85 | ############################################################################### 86 | # 87 | # Transceiver instance placement. This constraint selects the 88 | # transceivers to be used, which also dictates the pinout for the 89 | # transmit and receive differential pairs. Please refer to the 90 | # Virtex-7 GT Transceiver User Guide (UG) for more information. 91 | # 92 | 93 | # PCIe Lane 0 94 | set_property LOC GTPE2_CHANNEL_X0Y3 [get_cells {inst/gt_top_i/pipe_wrapper_i/pipe_lane[0].gt_wrapper_i/gtp_channel.gtpe2_channel_i}] 95 | 96 | # GTP Common Placement 97 | set_property LOC GTPE2_COMMON_X0Y0 [get_cells {inst/gt_top_i/pipe_wrapper_i/pipe_lane[0].pipe_quad.gt_common_enabled.gt_common_int.gt_common_i/qpll_wrapper_i/gtp_common.gtpe2_common_i}] 98 | 99 | # 100 | # PCI Express Block placement. This constraint selects the PCI Express 101 | # Block to be used. 102 | # 103 | 104 | set_property LOC PCIE_X0Y0 [get_cells inst/pcie_top_i/pcie_7x_i/pcie_block_i] 105 | 106 | # 107 | # BlockRAM placement 108 | # 109 | set_property LOC RAMB36_X0Y24 [get_cells {inst/pcie_top_i/pcie_7x_i/pcie_bram_top/pcie_brams_rx/brams[0].ram/use_tdp.ramb36/genblk*.bram36_tdp_bl.bram36_tdp_bl}] 110 | set_property LOC RAMB36_X0Y23 [get_cells {inst/pcie_top_i/pcie_7x_i/pcie_bram_top/pcie_brams_rx/brams[1].ram/use_tdp.ramb36/genblk*.bram36_tdp_bl.bram36_tdp_bl}] 111 | set_property LOC RAMB36_X0Y21 [get_cells {inst/pcie_top_i/pcie_7x_i/pcie_bram_top/pcie_brams_tx/brams[0].ram/use_tdp.ramb36/genblk*.bram36_tdp_bl.bram36_tdp_bl}] 112 | set_property LOC RAMB36_X0Y20 [get_cells {inst/pcie_top_i/pcie_7x_i/pcie_bram_top/pcie_brams_tx/brams[1].ram/use_tdp.ramb36/genblk*.bram36_tdp_bl.bram36_tdp_bl}] 113 | 114 | ############################################################################### 115 | # Timing Constraints 116 | ############################################################################### 117 | # 118 | create_clock -name txoutclk_x0y0 -period 10 [get_pins {inst/gt_top_i/pipe_wrapper_i/pipe_lane[0].gt_wrapper_i/gtp_channel.gtpe2_channel_i/TXOUTCLK}] 119 | # 120 | # 121 | set_false_path -to [get_pins {inst/gt_top_i/pipe_wrapper_i/pipe_clock_int.pipe_clock_i/pclk_i1_bufgctrl.pclk_i1/S0}] 122 | set_false_path -to [get_pins {inst/gt_top_i/pipe_wrapper_i/pipe_clock_int.pipe_clock_i/pclk_i1_bufgctrl.pclk_i1/S1}] 123 | 124 | 125 | 126 | 127 | # 128 | create_generated_clock -name clk_125mhz_x0y0 [get_pins inst/gt_top_i/pipe_wrapper_i/pipe_clock_int.pipe_clock_i/mmcm_i/CLKOUT0] 129 | create_generated_clock -name clk_250mhz_x0y0 [get_pins inst/gt_top_i/pipe_wrapper_i/pipe_clock_int.pipe_clock_i/mmcm_i/CLKOUT1] 130 | create_generated_clock -name clk_125mhz_mux_x0y0 \ 131 | -source [get_pins inst/gt_top_i/pipe_wrapper_i/pipe_clock_int.pipe_clock_i/pclk_i1_bufgctrl.pclk_i1/I0] \ 132 | -divide_by 1 \ 133 | [get_pins inst/gt_top_i/pipe_wrapper_i/pipe_clock_int.pipe_clock_i/pclk_i1_bufgctrl.pclk_i1/O] 134 | # 135 | create_generated_clock -name clk_250mhz_mux_x0y0 \ 136 | -source [get_pins inst/gt_top_i/pipe_wrapper_i/pipe_clock_int.pipe_clock_i/pclk_i1_bufgctrl.pclk_i1/I1] \ 137 | -divide_by 1 -add -master_clock [get_clocks -of [get_pins inst/gt_top_i/pipe_wrapper_i/pipe_clock_int.pipe_clock_i/pclk_i1_bufgctrl.pclk_i1/I1]] \ 138 | [get_pins inst/gt_top_i/pipe_wrapper_i/pipe_clock_int.pipe_clock_i/pclk_i1_bufgctrl.pclk_i1/O] 139 | # 140 | set_clock_groups -name pcieclkmux -physically_exclusive -group clk_125mhz_mux_x0y0 -group clk_250mhz_mux_x0y0 141 | # 142 | # 143 | # Timing ignoring the below pins to avoid CDC analysis, but care has been taken in RTL to sync properly to other clock domain. 144 | # 145 | # 146 | set_false_path -through [get_pins -filter {REF_PIN_NAME=~PLPHYLNKUPN} -of_objects [get_cells -hierarchical -filter { PRIMITIVE_TYPE =~ * }]] 147 | set_false_path -through [get_pins -filter {REF_PIN_NAME=~PLRECEIVEDHOTRST} -of_objects [get_cells -hierarchical -filter { PRIMITIVE_TYPE =~ * }]] 148 | 149 | #------------------------------------------------------------------------------ 150 | # Asynchronous Paths 151 | #------------------------------------------------------------------------------ 152 | set_false_path -through [get_pins -filter {REF_PIN_NAME=~RXELECIDLE} -of_objects [get_cells -hierarchical -filter { PRIMITIVE_TYPE =~ IO.gt.* }]] 153 | set_false_path -through [get_pins -filter {REF_PIN_NAME=~TXPHINITDONE} -of_objects [get_cells -hierarchical -filter { PRIMITIVE_TYPE =~ IO.gt.* }]] 154 | set_false_path -through [get_pins -filter {REF_PIN_NAME=~TXPHALIGNDONE} -of_objects [get_cells -hierarchical -filter { PRIMITIVE_TYPE =~ IO.gt.* }]] 155 | set_false_path -through [get_pins -filter {REF_PIN_NAME=~TXDLYSRESETDONE} -of_objects [get_cells -hierarchical -filter { PRIMITIVE_TYPE =~ IO.gt.* }]] 156 | set_false_path -through [get_pins -filter {REF_PIN_NAME=~RXDLYSRESETDONE} -of_objects [get_cells -hierarchical -filter { PRIMITIVE_TYPE =~ IO.gt.* }]] 157 | set_false_path -through [get_pins -filter {REF_PIN_NAME=~RXPHALIGNDONE} -of_objects [get_cells -hierarchical -filter { PRIMITIVE_TYPE =~ IO.gt.* }]] 158 | set_false_path -through [get_pins -filter {REF_PIN_NAME=~RXCDRLOCK} -of_objects [get_cells -hierarchical -filter { PRIMITIVE_TYPE =~ IO.gt.* }]] 159 | set_false_path -through [get_pins -filter {REF_PIN_NAME=~CFGMSGRECEIVEDPMETO} -of_objects [get_cells -hierarchical -filter { PRIMITIVE_TYPE =~ * }]] 160 | set_false_path -through [get_pins -filter {REF_PIN_NAME=~PLL0LOCK} -of_objects [get_cells -hierarchical -filter { PRIMITIVE_TYPE =~ IO.gt.* }]] 161 | set_false_path -through [get_pins -filter {REF_PIN_NAME=~RXPMARESETDONE} -of_objects [get_cells -hierarchical -filter { PRIMITIVE_TYPE =~ IO.gt.* }]] 162 | set_false_path -through [get_pins -filter {REF_PIN_NAME=~RXSYNCDONE} -of_objects [get_cells -hierarchical -filter { PRIMITIVE_TYPE =~ IO.gt.* }]] 163 | set_false_path -through [get_pins -filter {REF_PIN_NAME=~TXSYNCDONE} -of_objects [get_cells -hierarchical -filter { PRIMITIVE_TYPE =~ IO.gt.* }]] 164 | 165 | ############################################################################### 166 | # End 167 | ############################################################################### 168 | -------------------------------------------------------------------------------- /ip/pcie_7xi/source/pcie_7xi_axi_basic_rx.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // (c) Copyright 2010-2011 Xilinx, Inc. All rights reserved. 4 | // 5 | // This file contains confidential and proprietary information 6 | // of Xilinx, Inc. and is protected under U.S. and 7 | // international copyright and other intellectual property 8 | // laws. 9 | // 10 | // DISCLAIMER 11 | // This disclaimer is not a license and does not grant any 12 | // rights to the materials distributed herewith. Except as 13 | // otherwise provided in a valid license issued to you by 14 | // Xilinx, and to the maximum extent permitted by applicable 15 | // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND 16 | // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES 17 | // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING 18 | // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- 19 | // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and 20 | // (2) Xilinx shall not be liable (whether in contract or tort, 21 | // including negligence, or under any other theory of 22 | // liability) for any loss or damage of any kind or nature 23 | // related to, arising under or in connection with these 24 | // materials, including for any direct, or any indirect, 25 | // special, incidental, or consequential loss or damage 26 | // (including loss of data, profits, goodwill, or any type of 27 | // loss or damage suffered as a result of any action brought 28 | // by a third party) even if such damage or loss was 29 | // reasonably foreseeable or Xilinx had been advised of the 30 | // possibility of the same. 31 | // 32 | // CRITICAL APPLICATIONS 33 | // Xilinx products are not designed or intended to be fail- 34 | // safe, or for use in any application requiring fail-safe 35 | // performance, such as life-support or safety devices or 36 | // systems, Class III medical devices, nuclear facilities, 37 | // applications related to the deployment of airbags, or any 38 | // other applications that could lead to death, personal 39 | // injury, or severe property or environmental damage 40 | // (individually and collectively, "Critical 41 | // Applications"). Customer assumes the sole risk and 42 | // liability of any use of Xilinx products in Critical 43 | // Applications, subject only to applicable laws and 44 | // regulations governing limitations on product liability. 45 | // 46 | // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS 47 | // PART OF THIS FILE AT ALL TIMES. 48 | // 49 | //----------------------------------------------------------------------------- 50 | // Project : Series-7 Integrated Block for PCI Express 51 | // File : pcie_7xi_axi_basic_rx.v 52 | // Version : 3.3 53 | // // 54 | // Description: // 55 | // TRN to AXI RX module. Instantiates pipeline and null generator RX // 56 | // submodules. // 57 | // // 58 | // Notes: // 59 | // Optional notes section. // 60 | // // 61 | // Hierarchical: // 62 | // axi_basic_top // 63 | // axi_basic_rx // 64 | // // 65 | //----------------------------------------------------------------------------// 66 | 67 | `timescale 1ps/1ps 68 | 69 | (* DowngradeIPIdentifiedWarnings = "yes" *) 70 | module pcie_7xi_axi_basic_rx #( 71 | parameter C_DATA_WIDTH = 128, // RX/TX interface data width 72 | parameter C_FAMILY = "X7", // Targeted FPGA family 73 | parameter C_ROOT_PORT = "FALSE", // PCIe block is in root port mode 74 | parameter C_PM_PRIORITY = "FALSE", // Disable TX packet boundary thrtl 75 | parameter TCQ = 1, // Clock to Q time 76 | 77 | // Do not override parameters below this line 78 | parameter REM_WIDTH = (C_DATA_WIDTH == 128) ? 2 : 1, // trem/rrem width 79 | parameter KEEP_WIDTH = C_DATA_WIDTH / 8 // KEEP width 80 | ) ( 81 | //---------------------------------------------// 82 | // User Design I/O // 83 | //---------------------------------------------// 84 | 85 | // AXI RX 86 | //----------- 87 | output [C_DATA_WIDTH-1:0] m_axis_rx_tdata, // RX data to user 88 | output m_axis_rx_tvalid, // RX data is valid 89 | input m_axis_rx_tready, // RX ready for data 90 | output [KEEP_WIDTH-1:0] m_axis_rx_tkeep, // RX strobe byte enables 91 | output m_axis_rx_tlast, // RX data is last 92 | output [21:0] m_axis_rx_tuser, // RX user signals 93 | 94 | //---------------------------------------------// 95 | // PCIe Block I/O // 96 | //---------------------------------------------// 97 | 98 | // TRN RX 99 | //----------- 100 | input [C_DATA_WIDTH-1:0] trn_rd, // RX data from block 101 | input trn_rsof, // RX start of packet 102 | input trn_reof, // RX end of packet 103 | input trn_rsrc_rdy, // RX source ready 104 | output trn_rdst_rdy, // RX destination ready 105 | input trn_rsrc_dsc, // RX source discontinue 106 | input [REM_WIDTH-1:0] trn_rrem, // RX remainder 107 | input trn_rerrfwd, // RX error forward 108 | input [6:0] trn_rbar_hit, // RX BAR hit 109 | input trn_recrc_err, // RX ECRC error 110 | 111 | // System 112 | //----------- 113 | output [2:0] np_counter, // Non-posted counter 114 | input user_clk, // user clock from block 115 | input user_rst // user reset from block 116 | ); 117 | 118 | 119 | // Wires 120 | wire null_rx_tvalid; 121 | wire null_rx_tlast; 122 | wire [KEEP_WIDTH-1:0] null_rx_tkeep; 123 | wire null_rdst_rdy; 124 | wire [4:0] null_is_eof; 125 | 126 | //---------------------------------------------// 127 | // RX Data Pipeline // 128 | //---------------------------------------------// 129 | 130 | pcie_7xi_axi_basic_rx_pipeline #( 131 | .C_DATA_WIDTH( C_DATA_WIDTH ), 132 | .C_FAMILY( C_FAMILY ), 133 | .TCQ( TCQ ), 134 | 135 | .REM_WIDTH( REM_WIDTH ), 136 | .KEEP_WIDTH( KEEP_WIDTH ) 137 | 138 | ) rx_pipeline_inst ( 139 | 140 | // Outgoing AXI TX 141 | //----------- 142 | .m_axis_rx_tdata( m_axis_rx_tdata ), 143 | .m_axis_rx_tvalid( m_axis_rx_tvalid ), 144 | .m_axis_rx_tready( m_axis_rx_tready ), 145 | .m_axis_rx_tkeep( m_axis_rx_tkeep ), 146 | .m_axis_rx_tlast( m_axis_rx_tlast ), 147 | .m_axis_rx_tuser( m_axis_rx_tuser ), 148 | 149 | // Incoming TRN RX 150 | //----------- 151 | .trn_rd( trn_rd ), 152 | .trn_rsof( trn_rsof ), 153 | .trn_reof( trn_reof ), 154 | .trn_rsrc_rdy( trn_rsrc_rdy ), 155 | .trn_rdst_rdy( trn_rdst_rdy ), 156 | .trn_rsrc_dsc( trn_rsrc_dsc ), 157 | .trn_rrem( trn_rrem ), 158 | .trn_rerrfwd( trn_rerrfwd ), 159 | .trn_rbar_hit( trn_rbar_hit ), 160 | .trn_recrc_err( trn_recrc_err ), 161 | 162 | // Null Inputs 163 | //----------- 164 | .null_rx_tvalid( null_rx_tvalid ), 165 | .null_rx_tlast( null_rx_tlast ), 166 | .null_rx_tkeep( null_rx_tkeep ), 167 | .null_rdst_rdy( null_rdst_rdy ), 168 | .null_is_eof( null_is_eof ), 169 | 170 | // System 171 | //----------- 172 | .np_counter( np_counter ), 173 | .user_clk( user_clk ), 174 | .user_rst( user_rst ) 175 | ); 176 | 177 | 178 | //---------------------------------------------// 179 | // RX Null Packet Generator // 180 | //---------------------------------------------// 181 | 182 | pcie_7xi_axi_basic_rx_null_gen #( 183 | .C_DATA_WIDTH( C_DATA_WIDTH ), 184 | .TCQ( TCQ ), 185 | 186 | .KEEP_WIDTH( KEEP_WIDTH ) 187 | 188 | ) rx_null_gen_inst ( 189 | 190 | // Inputs 191 | //----------- 192 | .m_axis_rx_tdata( m_axis_rx_tdata ), 193 | .m_axis_rx_tvalid( m_axis_rx_tvalid ), 194 | .m_axis_rx_tready( m_axis_rx_tready ), 195 | .m_axis_rx_tlast( m_axis_rx_tlast ), 196 | .m_axis_rx_tuser( m_axis_rx_tuser ), 197 | 198 | // Null Outputs 199 | //----------- 200 | .null_rx_tvalid( null_rx_tvalid ), 201 | .null_rx_tlast( null_rx_tlast ), 202 | .null_rx_tkeep( null_rx_tkeep ), 203 | .null_rdst_rdy( null_rdst_rdy ), 204 | .null_is_eof( null_is_eof ), 205 | 206 | // System 207 | //----------- 208 | .user_clk( user_clk ), 209 | .user_rst( user_rst ) 210 | ); 211 | 212 | endmodule 213 | -------------------------------------------------------------------------------- /ip/pcie_7xi/source/pcie_7xi_axi_basic_top.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // (c) Copyright 2010-2011 Xilinx, Inc. All rights reserved. 4 | // 5 | // This file contains confidential and proprietary information 6 | // of Xilinx, Inc. and is protected under U.S. and 7 | // international copyright and other intellectual property 8 | // laws. 9 | // 10 | // DISCLAIMER 11 | // This disclaimer is not a license and does not grant any 12 | // rights to the materials distributed herewith. Except as 13 | // otherwise provided in a valid license issued to you by 14 | // Xilinx, and to the maximum extent permitted by applicable 15 | // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND 16 | // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES 17 | // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING 18 | // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- 19 | // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and 20 | // (2) Xilinx shall not be liable (whether in contract or tort, 21 | // including negligence, or under any other theory of 22 | // liability) for any loss or damage of any kind or nature 23 | // related to, arising under or in connection with these 24 | // materials, including for any direct, or any indirect, 25 | // special, incidental, or consequential loss or damage 26 | // (including loss of data, profits, goodwill, or any type of 27 | // loss or damage suffered as a result of any action brought 28 | // by a third party) even if such damage or loss was 29 | // reasonably foreseeable or Xilinx had been advised of the 30 | // possibility of the same. 31 | // 32 | // CRITICAL APPLICATIONS 33 | // Xilinx products are not designed or intended to be fail- 34 | // safe, or for use in any application requiring fail-safe 35 | // performance, such as life-support or safety devices or 36 | // systems, Class III medical devices, nuclear facilities, 37 | // applications related to the deployment of airbags, or any 38 | // other applications that could lead to death, personal 39 | // injury, or severe property or environmental damage 40 | // (individually and collectively, "Critical 41 | // Applications"). Customer assumes the sole risk and 42 | // liability of any use of Xilinx products in Critical 43 | // Applications, subject only to applicable laws and 44 | // regulations governing limitations on product liability. 45 | // 46 | // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS 47 | // PART OF THIS FILE AT ALL TIMES. 48 | // 49 | //----------------------------------------------------------------------------- 50 | // Project : Series-7 Integrated Block for PCI Express 51 | // File : pcie_7xi_axi_basic_top.v 52 | // Version : 3.3 53 | // // 54 | // Description: // 55 | // TRN/AXI4-S Bridge top level module. Instantiates RX and TX modules. // 56 | // // 57 | // Notes: // 58 | // Optional notes section. // 59 | // // 60 | // Hierarchical: // 61 | // axi_basic_top // 62 | // // 63 | //----------------------------------------------------------------------------// 64 | 65 | `timescale 1ps/1ps 66 | 67 | (* DowngradeIPIdentifiedWarnings = "yes" *) 68 | module pcie_7xi_axi_basic_top #( 69 | parameter C_DATA_WIDTH = 128, // RX/TX interface data width 70 | parameter C_FAMILY = "X7", // Targeted FPGA family 71 | parameter C_ROOT_PORT = "FALSE", // PCIe block is in root port mode 72 | parameter C_PM_PRIORITY = "FALSE", // Disable TX packet boundary thrtl 73 | parameter TCQ = 1, // Clock to Q time 74 | 75 | // Do not override parameters below this line 76 | parameter REM_WIDTH = (C_DATA_WIDTH == 128) ? 2 : 1, // trem/rrem width 77 | parameter KEEP_WIDTH = C_DATA_WIDTH / 8 // KEEP width 78 | ) ( 79 | //---------------------------------------------// 80 | // User Design I/O // 81 | //---------------------------------------------// 82 | 83 | // AXI TX 84 | //----------- 85 | input [C_DATA_WIDTH-1:0] s_axis_tx_tdata, // TX data from user 86 | input s_axis_tx_tvalid, // TX data is valid 87 | output s_axis_tx_tready, // TX ready for data 88 | input [KEEP_WIDTH-1:0] s_axis_tx_tkeep, // TX strobe byte enables 89 | input s_axis_tx_tlast, // TX data is last 90 | input [3:0] s_axis_tx_tuser, // TX user signals 91 | 92 | // AXI RX 93 | //----------- 94 | output [C_DATA_WIDTH-1:0] m_axis_rx_tdata, // RX data to user 95 | output m_axis_rx_tvalid, // RX data is valid 96 | input m_axis_rx_tready, // RX ready for data 97 | output [KEEP_WIDTH-1:0] m_axis_rx_tkeep, // RX strobe byte enables 98 | output m_axis_rx_tlast, // RX data is last 99 | output [21:0] m_axis_rx_tuser, // RX user signals 100 | 101 | // User Misc. 102 | //----------- 103 | input user_turnoff_ok, // Turnoff OK from user 104 | input user_tcfg_gnt, // Send cfg OK from user 105 | 106 | //---------------------------------------------// 107 | // PCIe Block I/O // 108 | //---------------------------------------------// 109 | 110 | // TRN TX 111 | //----------- 112 | output [C_DATA_WIDTH-1:0] trn_td, // TX data from block 113 | output trn_tsof, // TX start of packet 114 | output trn_teof, // TX end of packet 115 | output trn_tsrc_rdy, // TX source ready 116 | input trn_tdst_rdy, // TX destination ready 117 | output trn_tsrc_dsc, // TX source discontinue 118 | output [REM_WIDTH-1:0] trn_trem, // TX remainder 119 | output trn_terrfwd, // TX error forward 120 | output trn_tstr, // TX streaming enable 121 | input [5:0] trn_tbuf_av, // TX buffers available 122 | output trn_tecrc_gen, // TX ECRC generate 123 | 124 | // TRN RX 125 | //----------- 126 | input [127:0] trn_rd, // RX data from block 127 | input trn_rsof, // RX start of packet 128 | input trn_reof, // RX end of packet 129 | input trn_rsrc_rdy, // RX source ready 130 | output trn_rdst_rdy, // RX destination ready 131 | input trn_rsrc_dsc, // RX source discontinue 132 | input [1:0] trn_rrem, // RX remainder 133 | input trn_rerrfwd, // RX error forward 134 | input [6:0] trn_rbar_hit, // RX BAR hit 135 | input trn_recrc_err, // RX ECRC error 136 | 137 | // TRN Misc. 138 | //----------- 139 | input trn_tcfg_req, // TX config request 140 | output trn_tcfg_gnt, // RX config grant 141 | input trn_lnk_up, // PCIe link up 142 | 143 | // 7 Series/Virtex6 PM 144 | //----------- 145 | input [2:0] cfg_pcie_link_state, // Encoded PCIe link state 146 | 147 | // Virtex6 PM 148 | //----------- 149 | input cfg_pm_send_pme_to, // PM send PME turnoff msg 150 | input [1:0] cfg_pmcsr_powerstate, // PMCSR power state 151 | input [31:0] trn_rdllp_data, // RX DLLP data 152 | input trn_rdllp_src_rdy, // RX DLLP source ready 153 | 154 | // Virtex6/Spartan6 PM 155 | //----------- 156 | input cfg_to_turnoff, // Turnoff request 157 | output cfg_turnoff_ok, // Turnoff grant 158 | 159 | // System 160 | //----------- 161 | output [2:0] np_counter, // Non-posted counter 162 | input user_clk, // user clock from block 163 | input user_rst // user reset from block 164 | ); 165 | 166 | 167 | //---------------------------------------------// 168 | // RX Data Pipeline // 169 | //---------------------------------------------// 170 | 171 | pcie_7xi_axi_basic_rx #( 172 | .C_DATA_WIDTH( C_DATA_WIDTH ), 173 | .C_FAMILY( C_FAMILY ), 174 | 175 | .TCQ( TCQ ), 176 | .REM_WIDTH( REM_WIDTH ), 177 | .KEEP_WIDTH( KEEP_WIDTH ) 178 | ) rx_inst ( 179 | 180 | // Outgoing AXI TX 181 | //----------- 182 | .m_axis_rx_tdata( m_axis_rx_tdata ), 183 | .m_axis_rx_tvalid( m_axis_rx_tvalid ), 184 | .m_axis_rx_tready( m_axis_rx_tready ), 185 | .m_axis_rx_tkeep( m_axis_rx_tkeep ), 186 | .m_axis_rx_tlast( m_axis_rx_tlast ), 187 | .m_axis_rx_tuser( m_axis_rx_tuser ), 188 | 189 | // Incoming TRN RX 190 | //----------- 191 | .trn_rd( trn_rd[C_DATA_WIDTH-1:0] ), 192 | .trn_rsof( trn_rsof ), 193 | .trn_reof( trn_reof ), 194 | .trn_rsrc_rdy( trn_rsrc_rdy ), 195 | .trn_rdst_rdy( trn_rdst_rdy ), 196 | .trn_rsrc_dsc( trn_rsrc_dsc ), 197 | .trn_rrem( trn_rrem[REM_WIDTH-1:0] ), 198 | .trn_rerrfwd( trn_rerrfwd ), 199 | .trn_rbar_hit( trn_rbar_hit ), 200 | .trn_recrc_err( trn_recrc_err ), 201 | 202 | // System 203 | //----------- 204 | .np_counter( np_counter ), 205 | .user_clk( user_clk ), 206 | .user_rst( user_rst ) 207 | ); 208 | 209 | 210 | 211 | //---------------------------------------------// 212 | // TX Data Pipeline // 213 | //---------------------------------------------// 214 | 215 | pcie_7xi_axi_basic_tx #( 216 | .C_DATA_WIDTH( C_DATA_WIDTH ), 217 | .C_FAMILY( C_FAMILY ), 218 | .C_ROOT_PORT( C_ROOT_PORT ), 219 | .C_PM_PRIORITY( C_PM_PRIORITY ), 220 | 221 | .TCQ( TCQ ), 222 | .REM_WIDTH( REM_WIDTH ), 223 | .KEEP_WIDTH( KEEP_WIDTH ) 224 | ) tx_inst ( 225 | 226 | // Incoming AXI RX 227 | //----------- 228 | .s_axis_tx_tdata( s_axis_tx_tdata ), 229 | .s_axis_tx_tvalid( s_axis_tx_tvalid ), 230 | .s_axis_tx_tready( s_axis_tx_tready ), 231 | .s_axis_tx_tkeep( s_axis_tx_tkeep ), 232 | .s_axis_tx_tlast( s_axis_tx_tlast ), 233 | .s_axis_tx_tuser( s_axis_tx_tuser ), 234 | 235 | // User Misc. 236 | //----------- 237 | .user_turnoff_ok( user_turnoff_ok ), 238 | .user_tcfg_gnt( user_tcfg_gnt ), 239 | 240 | // Outgoing TRN TX 241 | //----------- 242 | .trn_td( trn_td ), 243 | .trn_tsof( trn_tsof ), 244 | .trn_teof( trn_teof ), 245 | .trn_tsrc_rdy( trn_tsrc_rdy ), 246 | .trn_tdst_rdy( trn_tdst_rdy ), 247 | .trn_tsrc_dsc( trn_tsrc_dsc ), 248 | .trn_trem( trn_trem ), 249 | .trn_terrfwd( trn_terrfwd ), 250 | .trn_tstr( trn_tstr ), 251 | .trn_tbuf_av( trn_tbuf_av ), 252 | .trn_tecrc_gen( trn_tecrc_gen ), 253 | 254 | // TRN Misc. 255 | //----------- 256 | .trn_tcfg_req( trn_tcfg_req ), 257 | .trn_tcfg_gnt( trn_tcfg_gnt ), 258 | .trn_lnk_up( trn_lnk_up ), 259 | 260 | // 7 Series/Virtex6 PM 261 | //----------- 262 | .cfg_pcie_link_state( cfg_pcie_link_state ), 263 | 264 | // Virtex6 PM 265 | //----------- 266 | .cfg_pm_send_pme_to( cfg_pm_send_pme_to ), 267 | .cfg_pmcsr_powerstate( cfg_pmcsr_powerstate ), 268 | .trn_rdllp_data( trn_rdllp_data ), 269 | .trn_rdllp_src_rdy( trn_rdllp_src_rdy ), 270 | 271 | // Spartan6 PM 272 | //----------- 273 | .cfg_to_turnoff( cfg_to_turnoff ), 274 | .cfg_turnoff_ok( cfg_turnoff_ok ), 275 | 276 | // System 277 | //----------- 278 | .user_clk( user_clk ), 279 | .user_rst( user_rst ) 280 | ); 281 | 282 | endmodule 283 | -------------------------------------------------------------------------------- /ip/pcie_7xi/source/pcie_7xi_axi_basic_tx.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // (c) Copyright 2010-2011 Xilinx, Inc. All rights reserved. 4 | // 5 | // This file contains confidential and proprietary information 6 | // of Xilinx, Inc. and is protected under U.S. and 7 | // international copyright and other intellectual property 8 | // laws. 9 | // 10 | // DISCLAIMER 11 | // This disclaimer is not a license and does not grant any 12 | // rights to the materials distributed herewith. Except as 13 | // otherwise provided in a valid license issued to you by 14 | // Xilinx, and to the maximum extent permitted by applicable 15 | // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND 16 | // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES 17 | // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING 18 | // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- 19 | // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and 20 | // (2) Xilinx shall not be liable (whether in contract or tort, 21 | // including negligence, or under any other theory of 22 | // liability) for any loss or damage of any kind or nature 23 | // related to, arising under or in connection with these 24 | // materials, including for any direct, or any indirect, 25 | // special, incidental, or consequential loss or damage 26 | // (including loss of data, profits, goodwill, or any type of 27 | // loss or damage suffered as a result of any action brought 28 | // by a third party) even if such damage or loss was 29 | // reasonably foreseeable or Xilinx had been advised of the 30 | // possibility of the same. 31 | // 32 | // CRITICAL APPLICATIONS 33 | // Xilinx products are not designed or intended to be fail- 34 | // safe, or for use in any application requiring fail-safe 35 | // performance, such as life-support or safety devices or 36 | // systems, Class III medical devices, nuclear facilities, 37 | // applications related to the deployment of airbags, or any 38 | // other applications that could lead to death, personal 39 | // injury, or severe property or environmental damage 40 | // (individually and collectively, "Critical 41 | // Applications"). Customer assumes the sole risk and 42 | // liability of any use of Xilinx products in Critical 43 | // Applications, subject only to applicable laws and 44 | // regulations governing limitations on product liability. 45 | // 46 | // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS 47 | // PART OF THIS FILE AT ALL TIMES. 48 | // 49 | //----------------------------------------------------------------------------- 50 | // Project : Series-7 Integrated Block for PCI Express 51 | // File : pcie_7xi_axi_basic_tx.v 52 | // Version : 3.3 53 | // // 54 | // Description: // 55 | // AXI to TRN TX module. Instantiates pipeline and throttle control TX // 56 | // submodules. // 57 | // // 58 | // Notes: // 59 | // Optional notes section. // 60 | // // 61 | // Hierarchical: // 62 | // axi_basic_top // 63 | // axi_basic_tx // 64 | // // 65 | //----------------------------------------------------------------------------// 66 | 67 | `timescale 1ps/1ps 68 | 69 | (* DowngradeIPIdentifiedWarnings = "yes" *) 70 | module pcie_7xi_axi_basic_tx #( 71 | parameter C_DATA_WIDTH = 128, // RX/TX interface data width 72 | parameter C_FAMILY = "X7", // Targeted FPGA family 73 | parameter C_ROOT_PORT = "FALSE", // PCIe block is in root port mode 74 | parameter C_PM_PRIORITY = "FALSE", // Disable TX packet boundary thrtl 75 | parameter TCQ = 1, // Clock to Q time 76 | 77 | // Do not override parameters below this line 78 | parameter REM_WIDTH = (C_DATA_WIDTH == 128) ? 2 : 1, // trem/rrem width 79 | parameter KEEP_WIDTH = C_DATA_WIDTH / 8 // KEEP width 80 | ) ( 81 | //---------------------------------------------// 82 | // User Design I/O // 83 | //---------------------------------------------// 84 | 85 | // AXI TX 86 | //----------- 87 | input [C_DATA_WIDTH-1:0] s_axis_tx_tdata, // TX data from user 88 | input s_axis_tx_tvalid, // TX data is valid 89 | output s_axis_tx_tready, // TX ready for data 90 | input [KEEP_WIDTH-1:0] s_axis_tx_tkeep, // TX strobe byte enables 91 | input s_axis_tx_tlast, // TX data is last 92 | input [3:0] s_axis_tx_tuser, // TX user signals 93 | 94 | // User Misc. 95 | //----------- 96 | input user_turnoff_ok, // Turnoff OK from user 97 | input user_tcfg_gnt, // Send cfg OK from user 98 | 99 | //---------------------------------------------// 100 | // PCIe Block I/O // 101 | //---------------------------------------------// 102 | 103 | // TRN TX 104 | //----------- 105 | output [C_DATA_WIDTH-1:0] trn_td, // TX data from block 106 | output trn_tsof, // TX start of packet 107 | output trn_teof, // TX end of packet 108 | output trn_tsrc_rdy, // TX source ready 109 | input trn_tdst_rdy, // TX destination ready 110 | output trn_tsrc_dsc, // TX source discontinue 111 | output [REM_WIDTH-1:0] trn_trem, // TX remainder 112 | output trn_terrfwd, // TX error forward 113 | output trn_tstr, // TX streaming enable 114 | input [5:0] trn_tbuf_av, // TX buffers available 115 | output trn_tecrc_gen, // TX ECRC generate 116 | 117 | // TRN Misc. 118 | //----------- 119 | input trn_tcfg_req, // TX config request 120 | output trn_tcfg_gnt, // RX config grant 121 | input trn_lnk_up, // PCIe link up 122 | 123 | // 7 Series/Virtex6 PM 124 | //----------- 125 | input [2:0] cfg_pcie_link_state, // Encoded PCIe link state 126 | 127 | // Virtex6 PM 128 | //----------- 129 | input cfg_pm_send_pme_to, // PM send PME turnoff msg 130 | input [1:0] cfg_pmcsr_powerstate, // PMCSR power state 131 | input [31:0] trn_rdllp_data, // RX DLLP data 132 | input trn_rdllp_src_rdy, // RX DLLP source ready 133 | 134 | // Virtex6/Spartan6 PM 135 | //----------- 136 | input cfg_to_turnoff, // Turnoff request 137 | output cfg_turnoff_ok, // Turnoff grant 138 | 139 | // System 140 | //----------- 141 | input user_clk, // user clock from block 142 | input user_rst // user reset from block 143 | ); 144 | 145 | 146 | wire tready_thrtl; 147 | 148 | //---------------------------------------------// 149 | // TX Data Pipeline // 150 | //---------------------------------------------// 151 | 152 | pcie_7xi_axi_basic_tx_pipeline #( 153 | .C_DATA_WIDTH( C_DATA_WIDTH ), 154 | .C_PM_PRIORITY( C_PM_PRIORITY ), 155 | .TCQ( TCQ ), 156 | 157 | .REM_WIDTH( REM_WIDTH ), 158 | .KEEP_WIDTH( KEEP_WIDTH ) 159 | ) tx_pipeline_inst ( 160 | 161 | // Incoming AXI RX 162 | //----------- 163 | .s_axis_tx_tdata( s_axis_tx_tdata ), 164 | .s_axis_tx_tready( s_axis_tx_tready ), 165 | .s_axis_tx_tvalid( s_axis_tx_tvalid ), 166 | .s_axis_tx_tkeep( s_axis_tx_tkeep ), 167 | .s_axis_tx_tlast( s_axis_tx_tlast ), 168 | .s_axis_tx_tuser( s_axis_tx_tuser ), 169 | 170 | // Outgoing TRN TX 171 | //----------- 172 | .trn_td( trn_td ), 173 | .trn_tsof( trn_tsof ), 174 | .trn_teof( trn_teof ), 175 | .trn_tsrc_rdy( trn_tsrc_rdy ), 176 | .trn_tdst_rdy( trn_tdst_rdy ), 177 | .trn_tsrc_dsc( trn_tsrc_dsc ), 178 | .trn_trem( trn_trem ), 179 | .trn_terrfwd( trn_terrfwd ), 180 | .trn_tstr( trn_tstr ), 181 | .trn_tecrc_gen( trn_tecrc_gen ), 182 | .trn_lnk_up( trn_lnk_up ), 183 | 184 | // System 185 | //----------- 186 | .tready_thrtl( tready_thrtl ), 187 | .user_clk( user_clk ), 188 | .user_rst( user_rst ) 189 | ); 190 | 191 | 192 | //---------------------------------------------// 193 | // TX Throttle Controller // 194 | //---------------------------------------------// 195 | 196 | generate 197 | if(C_PM_PRIORITY == "FALSE") begin : thrtl_ctl_enabled 198 | pcie_7xi_axi_basic_tx_thrtl_ctl #( 199 | .C_DATA_WIDTH( C_DATA_WIDTH ), 200 | .C_FAMILY( C_FAMILY ), 201 | .C_ROOT_PORT( C_ROOT_PORT ), 202 | .TCQ( TCQ ) 203 | 204 | ) tx_thrl_ctl_inst ( 205 | 206 | // Outgoing AXI TX 207 | //----------- 208 | .s_axis_tx_tdata( s_axis_tx_tdata ), 209 | .s_axis_tx_tvalid( s_axis_tx_tvalid ), 210 | .s_axis_tx_tuser( s_axis_tx_tuser ), 211 | .s_axis_tx_tlast( s_axis_tx_tlast ), 212 | 213 | // User Misc. 214 | //----------- 215 | .user_turnoff_ok( user_turnoff_ok ), 216 | .user_tcfg_gnt( user_tcfg_gnt ), 217 | 218 | // Incoming TRN RX 219 | //----------- 220 | .trn_tbuf_av( trn_tbuf_av ), 221 | .trn_tdst_rdy( trn_tdst_rdy ), 222 | 223 | // TRN Misc. 224 | //----------- 225 | .trn_tcfg_req( trn_tcfg_req ), 226 | .trn_tcfg_gnt( trn_tcfg_gnt ), 227 | .trn_lnk_up( trn_lnk_up ), 228 | 229 | // 7 Seriesq/Virtex6 PM 230 | //----------- 231 | .cfg_pcie_link_state( cfg_pcie_link_state ), 232 | 233 | // Virtex6 PM 234 | //----------- 235 | .cfg_pm_send_pme_to( cfg_pm_send_pme_to ), 236 | .cfg_pmcsr_powerstate( cfg_pmcsr_powerstate ), 237 | .trn_rdllp_data( trn_rdllp_data ), 238 | .trn_rdllp_src_rdy( trn_rdllp_src_rdy ), 239 | 240 | // Spartan6 PM 241 | //----------- 242 | .cfg_to_turnoff( cfg_to_turnoff ), 243 | .cfg_turnoff_ok( cfg_turnoff_ok ), 244 | 245 | // System 246 | //----------- 247 | .tready_thrtl( tready_thrtl ), 248 | .user_clk( user_clk ), 249 | .user_rst( user_rst ) 250 | ); 251 | end 252 | else begin : thrtl_ctl_disabled 253 | assign tready_thrtl = 1'b0; 254 | 255 | assign cfg_turnoff_ok = user_turnoff_ok; 256 | assign trn_tcfg_gnt = user_tcfg_gnt; 257 | end 258 | endgenerate 259 | 260 | endmodule 261 | -------------------------------------------------------------------------------- /ip/pcie_7xi/source/pcie_7xi_gt_common.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // (c) Copyright 2010-2011 Xilinx, Inc. All rights reserved. 4 | // 5 | // This file contains confidential and proprietary information 6 | // of Xilinx, Inc. and is protected under U.S. and 7 | // international copyright and other intellectual property 8 | // laws. 9 | // 10 | // DISCLAIMER 11 | // This disclaimer is not a license and does not grant any 12 | // rights to the materials distributed herewith. Except as 13 | // otherwise provided in a valid license issued to you by 14 | // Xilinx, and to the maximum extent permitted by applicable 15 | // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND 16 | // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES 17 | // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING 18 | // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- 19 | // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and 20 | // (2) Xilinx shall not be liable (whether in contract or tort, 21 | // including negligence, or under any other theory of 22 | // liability) for any loss or damage of any kind or nature 23 | // related to, arising under or in connection with these 24 | // materials, including for any direct, or any indirect, 25 | // special, incidental, or consequential loss or damage 26 | // (including loss of data, profits, goodwill, or any type of 27 | // loss or damage suffered as a result of any action brought 28 | // by a third party) even if such damage or loss was 29 | // reasonably foreseeable or Xilinx had been advised of the 30 | // possibility of the same. 31 | // 32 | // CRITICAL APPLICATIONS 33 | // Xilinx products are not designed or intended to be fail- 34 | // safe, or for use in any application requiring fail-safe 35 | // performance, such as life-support or safety devices or 36 | // systems, Class III medical devices, nuclear facilities, 37 | // applications related to the deployment of airbags, or any 38 | // other applications that could lead to death, personal 39 | // injury, or severe property or environmental damage 40 | // (individually and collectively, "Critical 41 | // Applications"). Customer assumes the sole risk and 42 | // liability of any use of Xilinx products in Critical 43 | // Applications, subject only to applicable laws and 44 | // regulations governing limitations on product liability. 45 | // 46 | // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS 47 | // PART OF THIS FILE AT ALL TIMES. 48 | // 49 | //----------------------------------------------------------------------------- 50 | // Project : Series-7 Integrated Block for PCI Express 51 | // File : pcie_7xi_gt_common.v 52 | // Version : 3.3 53 | `timescale 1ns / 1ps 54 | 55 | (* DowngradeIPIdentifiedWarnings = "yes" *) 56 | module pcie_7xi_gt_common #( 57 | 58 | parameter PCIE_SIM_MODE = "FALSE", // PCIe sim mode 59 | parameter PCIE_GT_DEVICE = "GTX", // PCIe GT device 60 | parameter PCIE_USE_MODE = "2.1", // PCIe use mode 61 | parameter PCIE_PLL_SEL = "CPLL", // PCIe PLL select for Gen1/Gen2 only 62 | parameter PCIE_REFCLK_FREQ = 0 // PCIe reference clock frequency 63 | ) 64 | 65 | ( 66 | input CPLLPDREFCLK, 67 | input PIPE_CLK, 68 | input QPLL_QPLLPD, 69 | input QPLL_QPLLRESET, 70 | input QPLL_DRP_CLK, 71 | input QPLL_DRP_RST_N, 72 | input QPLL_DRP_OVRD, 73 | input QPLL_DRP_GEN3, 74 | input QPLL_DRP_START, 75 | output [5:0] QPLL_DRP_CRSCODE, 76 | output [8:0] QPLL_DRP_FSM, 77 | output QPLL_DRP_DONE, 78 | output QPLL_DRP_RESET, 79 | output QPLL_QPLLLOCK, 80 | output QPLL_QPLLOUTCLK, 81 | output QPLL_QPLLOUTREFCLK 82 | ); 83 | 84 | //---------- QPLL DRP Module Output -------------------- 85 | 86 | wire [7:0] qpll_drp_addr; 87 | wire qpll_drp_en; 88 | wire [15:0] qpll_drp_di; 89 | wire qpll_drp_we; 90 | 91 | //---------- QPLL Wrapper Output ----------------------- 92 | 93 | wire [15:0] qpll_drp_do; 94 | wire qpll_drp_rdy; 95 | 96 | //---------- QPLL Resets ----------------------- 97 | 98 | 99 | //---------- QPLL DRP Module --------------------------------------- 100 | 101 | pcie_7xi_qpll_drp # 102 | ( 103 | 104 | .PCIE_GT_DEVICE (PCIE_GT_DEVICE), // PCIe GT device 105 | .PCIE_USE_MODE (PCIE_USE_MODE), // PCIe use mode 106 | .PCIE_PLL_SEL (PCIE_PLL_SEL), // PCIe PLL select for Gen1/Gen2 only 107 | .PCIE_REFCLK_FREQ (PCIE_REFCLK_FREQ) // PCIe reference clock frequency 108 | 109 | ) 110 | qpll_drp_i 111 | ( 112 | 113 | //---------- Input ------------------------- 114 | .DRP_CLK (QPLL_DRP_CLK), 115 | .DRP_RST_N (!QPLL_DRP_RST_N), 116 | .DRP_OVRD (QPLL_DRP_OVRD), 117 | .DRP_GEN3 (&QPLL_DRP_GEN3), 118 | .DRP_QPLLLOCK (QPLL_QPLLLOCK), 119 | .DRP_START (QPLL_DRP_START), 120 | .DRP_DO (qpll_drp_do), 121 | .DRP_RDY (qpll_drp_rdy), 122 | 123 | //---------- Output ------------------------ 124 | .DRP_ADDR (qpll_drp_addr), 125 | .DRP_EN (qpll_drp_en), 126 | .DRP_DI (qpll_drp_di), 127 | .DRP_WE (qpll_drp_we), 128 | .DRP_DONE (QPLL_DRP_DONE), 129 | .DRP_QPLLRESET (QPLL_DRP_RESET), 130 | .DRP_CRSCODE (QPLL_DRP_CRSCODE), 131 | .DRP_FSM (QPLL_DRP_FSM) 132 | ); 133 | 134 | 135 | //---------- QPLL Wrapper ------------------------------------------ 136 | pcie_7xi_qpll_wrapper # 137 | ( 138 | .PCIE_SIM_MODE (PCIE_SIM_MODE), // PCIe sim mode 139 | .PCIE_GT_DEVICE (PCIE_GT_DEVICE), // PCIe GT device 140 | .PCIE_USE_MODE (PCIE_USE_MODE), // PCIe use mode 141 | .PCIE_PLL_SEL (PCIE_PLL_SEL), // PCIe PLL select for Gen1/Gen2 only 142 | .PCIE_REFCLK_FREQ (PCIE_REFCLK_FREQ) // PCIe reference clock frequency 143 | ) 144 | qpll_wrapper_i 145 | ( 146 | //---------- QPLL Clock Ports -------------- 147 | .QPLL_CPLLPDREFCLK (CPLLPDREFCLK), 148 | .QPLL_GTGREFCLK (PIPE_CLK), 149 | .QPLL_QPLLLOCKDETCLK (1'd0), 150 | .QPLL_QPLLOUTCLK (QPLL_QPLLOUTCLK), 151 | .QPLL_QPLLOUTREFCLK (QPLL_QPLLOUTREFCLK), 152 | .QPLL_QPLLLOCK (QPLL_QPLLLOCK), 153 | //---------- QPLL Reset Ports -------------- 154 | .QPLL_QPLLPD (QPLL_QPLLPD), 155 | .QPLL_QPLLRESET (QPLL_QPLLRESET), 156 | //---------- QPLL DRP Ports ---------------- 157 | .QPLL_DRPCLK (QPLL_DRP_CLK), 158 | .QPLL_DRPADDR (qpll_drp_addr), 159 | .QPLL_DRPEN (qpll_drp_en), 160 | .QPLL_DRPDI (qpll_drp_di), 161 | .QPLL_DRPWE (qpll_drp_we), 162 | .QPLL_DRPDO (qpll_drp_do), 163 | .QPLL_DRPRDY (qpll_drp_rdy) 164 | ); 165 | 166 | endmodule 167 | -------------------------------------------------------------------------------- /ip/pcie_7xi/source/pcie_7xi_gt_rx_valid_filter_7x.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // (c) Copyright 2010-2011 Xilinx, Inc. All rights reserved. 4 | // 5 | // This file contains confidential and proprietary information 6 | // of Xilinx, Inc. and is protected under U.S. and 7 | // international copyright and other intellectual property 8 | // laws. 9 | // 10 | // DISCLAIMER 11 | // This disclaimer is not a license and does not grant any 12 | // rights to the materials distributed herewith. Except as 13 | // otherwise provided in a valid license issued to you by 14 | // Xilinx, and to the maximum extent permitted by applicable 15 | // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND 16 | // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES 17 | // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING 18 | // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- 19 | // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and 20 | // (2) Xilinx shall not be liable (whether in contract or tort, 21 | // including negligence, or under any other theory of 22 | // liability) for any loss or damage of any kind or nature 23 | // related to, arising under or in connection with these 24 | // materials, including for any direct, or any indirect, 25 | // special, incidental, or consequential loss or damage 26 | // (including loss of data, profits, goodwill, or any type of 27 | // loss or damage suffered as a result of any action brought 28 | // by a third party) even if such damage or loss was 29 | // reasonably foreseeable or Xilinx had been advised of the 30 | // possibility of the same. 31 | // 32 | // CRITICAL APPLICATIONS 33 | // Xilinx products are not designed or intended to be fail- 34 | // safe, or for use in any application requiring fail-safe 35 | // performance, such as life-support or safety devices or 36 | // systems, Class III medical devices, nuclear facilities, 37 | // applications related to the deployment of airbags, or any 38 | // other applications that could lead to death, personal 39 | // injury, or severe property or environmental damage 40 | // (individually and collectively, "Critical 41 | // Applications"). Customer assumes the sole risk and 42 | // liability of any use of Xilinx products in Critical 43 | // Applications, subject only to applicable laws and 44 | // regulations governing limitations on product liability. 45 | // 46 | // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS 47 | // PART OF THIS FILE AT ALL TIMES. 48 | // 49 | //----------------------------------------------------------------------------- 50 | // Project : Series-7 Integrated Block for PCI Express 51 | // File : pcie_7xi_gt_rx_valid_filter_7x.v 52 | // Version : 3.3 53 | //-- Description: GTX module for 7-series Integrated PCIe Block 54 | //-- 55 | //-- 56 | //-- 57 | //-------------------------------------------------------------------------------- 58 | 59 | `timescale 1ns / 1ns 60 | 61 | (* DowngradeIPIdentifiedWarnings = "yes" *) 62 | module pcie_7xi_gt_rx_valid_filter_7x #( 63 | 64 | parameter CLK_COR_MIN_LAT = 28, 65 | parameter TCQ = 1 66 | 67 | ) 68 | ( 69 | output [1:0] USER_RXCHARISK, 70 | output [15:0] USER_RXDATA, 71 | output USER_RXVALID, 72 | output USER_RXELECIDLE, 73 | output [ 2:0] USER_RX_STATUS, 74 | output USER_RX_PHY_STATUS, 75 | input [1:0] GT_RXCHARISK, 76 | input [15:0] GT_RXDATA, 77 | input GT_RXVALID, 78 | input GT_RXELECIDLE, 79 | input [ 2:0] GT_RX_STATUS, 80 | input GT_RX_PHY_STATUS, 81 | 82 | input PLM_IN_L0, 83 | input PLM_IN_RS, 84 | 85 | input USER_CLK, 86 | input RESET 87 | 88 | ); 89 | 90 | 91 | 92 | localparam EIOS_DET_IDL = 5'b00001; 93 | localparam EIOS_DET_NO_STR0 = 5'b00010; 94 | localparam EIOS_DET_STR0 = 5'b00100; 95 | localparam EIOS_DET_STR1 = 5'b01000; 96 | localparam EIOS_DET_DONE = 5'b10000; 97 | 98 | localparam EIOS_COM = 8'hBC; 99 | localparam EIOS_IDL = 8'h7C; 100 | localparam FTSOS_COM = 8'hBC; 101 | localparam FTSOS_FTS = 8'h3C; 102 | 103 | reg [4:0] reg_state_eios_det; 104 | wire [4:0] state_eios_det; 105 | 106 | reg reg_eios_detected; 107 | wire eios_detected; 108 | 109 | reg reg_symbol_after_eios; 110 | wire symbol_after_eios; 111 | 112 | localparam USER_RXVLD_IDL = 4'b0001; 113 | localparam USER_RXVLD_EI = 4'b0010; 114 | localparam USER_RXVLD_EI_DB0 = 4'b0100; 115 | localparam USER_RXVLD_EI_DB1 = 4'b1000; 116 | 117 | 118 | reg [1:0] gt_rxcharisk_q; 119 | reg [15:0] gt_rxdata_q; 120 | reg gt_rxvalid_q; 121 | reg gt_rxelecidle_q; 122 | 123 | reg [ 2:0] gt_rx_status_q; 124 | reg gt_rx_phy_status_q; 125 | reg gt_rx_is_skp0_q; 126 | reg gt_rx_is_skp1_q; 127 | 128 | // EIOS detector 129 | 130 | always @(posedge USER_CLK) begin 131 | 132 | if (RESET) begin 133 | 134 | reg_eios_detected <= #TCQ 1'b0; 135 | reg_state_eios_det <= #TCQ EIOS_DET_IDL; 136 | reg_symbol_after_eios <= #TCQ 1'b0; 137 | gt_rxcharisk_q <= #TCQ 2'b00; 138 | gt_rxdata_q <= #TCQ 16'h0; 139 | gt_rxvalid_q <= #TCQ 1'b0; 140 | gt_rxelecidle_q <= #TCQ 1'b0; 141 | gt_rx_status_q <= #TCQ 3'b000; 142 | gt_rx_phy_status_q <= #TCQ 1'b0; 143 | gt_rx_is_skp0_q <= #TCQ 1'b0; 144 | gt_rx_is_skp1_q <= #TCQ 1'b0; 145 | 146 | end else begin 147 | reg_eios_detected <= #TCQ 1'b0; 148 | reg_symbol_after_eios <= #TCQ 1'b0; 149 | gt_rxcharisk_q <= #TCQ GT_RXCHARISK; 150 | gt_rxelecidle_q <= #TCQ GT_RXELECIDLE; 151 | gt_rxdata_q <= #TCQ GT_RXDATA; 152 | gt_rx_phy_status_q <= #TCQ GT_RX_PHY_STATUS; 153 | 154 | //De-assert rx_valid signal when EIOS is detected on RXDATA 155 | if(((reg_state_eios_det == 5'b10000)) && (PLM_IN_L0) 156 | ) begin 157 | 158 | gt_rxvalid_q <= #TCQ 1'b0; 159 | end 160 | else if (GT_RXELECIDLE && !gt_rxvalid_q) begin 161 | gt_rxvalid_q <= #TCQ 1'b0; 162 | end 163 | else begin 164 | gt_rxvalid_q <= GT_RXVALID; 165 | end 166 | 167 | if (gt_rxvalid_q) begin 168 | gt_rx_status_q <= #TCQ GT_RX_STATUS; 169 | 170 | end 171 | else if (!gt_rxvalid_q && PLM_IN_L0) begin 172 | gt_rx_status_q <= #TCQ 3'b0; 173 | end 174 | else begin 175 | gt_rx_status_q <= #TCQ GT_RX_STATUS; 176 | end 177 | 178 | 179 | 180 | if (GT_RXCHARISK[0] && GT_RXDATA[7:0] == FTSOS_FTS) 181 | gt_rx_is_skp0_q <= #TCQ 1'b1; 182 | else 183 | gt_rx_is_skp0_q <= #TCQ 1'b0; 184 | 185 | if (GT_RXCHARISK[1] && GT_RXDATA[15:8] == FTSOS_FTS) 186 | gt_rx_is_skp1_q <= #TCQ 1'b1; 187 | else 188 | gt_rx_is_skp1_q <= #TCQ 1'b0; 189 | 190 | case ( state_eios_det ) 191 | 192 | EIOS_DET_IDL : begin 193 | 194 | if ((gt_rxcharisk_q[0]) && (gt_rxdata_q[7:0] == EIOS_COM) && 195 | (gt_rxcharisk_q[1]) && (gt_rxdata_q[15:8] == EIOS_IDL)) begin 196 | 197 | reg_state_eios_det <= #TCQ EIOS_DET_NO_STR0; 198 | reg_eios_detected <= #TCQ 1'b1; 199 | // gt_rxvalid_q <= #TCQ 1'b0; 200 | 201 | end else if ((gt_rxcharisk_q[1]) && (gt_rxdata_q[15:8] == EIOS_COM)) 202 | reg_state_eios_det <= #TCQ EIOS_DET_STR0; 203 | else 204 | reg_state_eios_det <= #TCQ EIOS_DET_IDL; 205 | 206 | end 207 | 208 | EIOS_DET_NO_STR0 : begin 209 | 210 | if ((gt_rxcharisk_q[0] && (gt_rxdata_q[7:0] == EIOS_IDL)) && 211 | (gt_rxcharisk_q[1] && (gt_rxdata_q[15:8] == EIOS_IDL))) 212 | begin 213 | reg_state_eios_det <= #TCQ EIOS_DET_DONE; 214 | gt_rxvalid_q <= #TCQ 1'b0; 215 | end 216 | else if (gt_rxcharisk_q[0] && (gt_rxdata_q[7:0] == EIOS_IDL)) begin 217 | 218 | reg_state_eios_det <= #TCQ EIOS_DET_DONE; 219 | gt_rxvalid_q <= #TCQ 1'b0; 220 | end 221 | else 222 | reg_state_eios_det <= #TCQ EIOS_DET_IDL; 223 | 224 | end 225 | 226 | EIOS_DET_STR0 : begin 227 | 228 | if ((gt_rxcharisk_q[0] && (gt_rxdata_q[7:0] == EIOS_IDL)) && 229 | (gt_rxcharisk_q[1] && (gt_rxdata_q[15:8] == EIOS_IDL))) begin 230 | 231 | reg_state_eios_det <= #TCQ EIOS_DET_STR1; 232 | reg_eios_detected <= #TCQ 1'b1; 233 | gt_rxvalid_q <= #TCQ 1'b0; 234 | reg_symbol_after_eios <= #TCQ 1'b1; 235 | 236 | end else 237 | reg_state_eios_det <= #TCQ EIOS_DET_IDL; 238 | 239 | end 240 | 241 | EIOS_DET_STR1 : begin 242 | 243 | if ((gt_rxcharisk_q[0]) && (gt_rxdata_q[7:0] == EIOS_IDL)) 244 | begin 245 | reg_state_eios_det <= #TCQ EIOS_DET_DONE; 246 | gt_rxvalid_q <= #TCQ 1'b0; 247 | end 248 | else 249 | reg_state_eios_det <= #TCQ EIOS_DET_IDL; 250 | 251 | end 252 | 253 | EIOS_DET_DONE : begin 254 | 255 | reg_state_eios_det <= #TCQ EIOS_DET_IDL; 256 | 257 | end 258 | 259 | endcase 260 | 261 | end 262 | 263 | end 264 | assign state_eios_det = reg_state_eios_det; 265 | assign eios_detected = reg_eios_detected; 266 | assign symbol_after_eios = reg_symbol_after_eios; 267 | /*SRL16E #(.INIT(0)) rx_elec_idle_delay (.Q(USER_RXELECIDLE), 268 | .D(gt_rxelecidle_q), 269 | .CLK(USER_CLK), 270 | .CE(1'b1), .A3(1'b1),.A2(1'b1),.A1(1'b1),.A0(1'b1)); 271 | */ 272 | wire rst_l = ~RESET; 273 | 274 | 275 | assign USER_RXVALID = gt_rxvalid_q; 276 | assign USER_RXCHARISK[0] = gt_rxvalid_q ? gt_rxcharisk_q[0] : 1'b0; 277 | assign USER_RXCHARISK[1] = (gt_rxvalid_q && !symbol_after_eios) ? gt_rxcharisk_q[1] : 1'b0; 278 | assign USER_RXDATA[7:0] = gt_rxdata_q[7:0]; 279 | assign USER_RXDATA[15:8] = gt_rxdata_q[15:8]; 280 | assign USER_RX_STATUS = gt_rx_status_q; 281 | assign USER_RX_PHY_STATUS = gt_rx_phy_status_q; 282 | assign USER_RXELECIDLE = gt_rxelecidle_q; 283 | 284 | 285 | endmodule 286 | -------------------------------------------------------------------------------- /ip/pcie_7xi/source/pcie_7xi_gtp_cpllpd_ovrd.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // (c) Copyright 2010-2011 Xilinx, Inc. All rights reserved. 4 | // 5 | // This file contains confidential and proprietary information 6 | // of Xilinx, Inc. and is protected under U.S. and 7 | // international copyright and other intellectual property 8 | // laws. 9 | // 10 | // DISCLAIMER 11 | // This disclaimer is not a license and does not grant any 12 | // rights to the materials distributed herewith. Except as 13 | // otherwise provided in a valid license issued to you by 14 | // Xilinx, and to the maximum extent permitted by applicable 15 | // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND 16 | // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES 17 | // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING 18 | // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- 19 | // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and 20 | // (2) Xilinx shall not be liable (whether in contract or tort, 21 | // including negligence, or under any other theory of 22 | // liability) for any loss or damage of any kind or nature 23 | // related to, arising under or in connection with these 24 | // materials, including for any direct, or any indirect, 25 | // special, incidental, or consequential loss or damage 26 | // (including loss of data, profits, goodwill, or any type of 27 | // loss or damage suffered as a result of any action brought 28 | // by a third party) even if such damage or loss was 29 | // reasonably foreseeable or Xilinx had been advised of the 30 | // possibility of the same. 31 | // 32 | // CRITICAL APPLICATIONS 33 | // Xilinx products are not designed or intended to be fail- 34 | // safe, or for use in any application requiring fail-safe 35 | // performance, such as life-support or safety devices or 36 | // systems, Class III medical devices, nuclear facilities, 37 | // applications related to the deployment of airbags, or any 38 | // other applications that could lead to death, personal 39 | // injury, or severe property or environmental damage 40 | // (individually and collectively, "Critical 41 | // Applications"). Customer assumes the sole risk and 42 | // liability of any use of Xilinx products in Critical 43 | // Applications, subject only to applicable laws and 44 | // regulations governing limitations on product liability. 45 | // 46 | // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS 47 | // PART OF THIS FILE AT ALL TIMES. 48 | // 49 | //----------------------------------------------------------------------------- 50 | // Project : Series-7 Integrated Block for PCI Express 51 | // File : pcie_7xi_gtp_cpllpd_ovrd.v 52 | // Version : 3.3 53 | `timescale 1ns / 1ps 54 | module pcie_7xi_gtp_cpllpd_ovrd ( 55 | input i_ibufds_gte2, 56 | output o_cpllpd_ovrd, 57 | output o_cpllreset_ovrd 58 | ); 59 | (* equivalent_register_removal="no" *) reg [95:0] cpllpd_wait = 96'hFFFFFFFFFFFFFFFFFFFFFFFF; 60 | (* equivalent_register_removal="no" *) reg [127:0] cpllreset_wait = 128'h000000000000000000000000000000FF; 61 | always @(posedge i_ibufds_gte2) 62 | begin 63 | cpllpd_wait <= {cpllpd_wait[94:0], 1'b0}; 64 | cpllreset_wait <= {cpllreset_wait[126:0], 1'b0}; 65 | end 66 | assign o_cpllpd_ovrd = cpllpd_wait[95]; 67 | assign o_cpllreset_ovrd = cpllreset_wait[127]; 68 | endmodule 69 | -------------------------------------------------------------------------------- /ip/pcie_7xi/source/pcie_7xi_gtx_cpllpd_ovrd.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // (c) Copyright 2010-2011 Xilinx, Inc. All rights reserved. 4 | // 5 | // This file contains confidential and proprietary information 6 | // of Xilinx, Inc. and is protected under U.S. and 7 | // international copyright and other intellectual property 8 | // laws. 9 | // 10 | // DISCLAIMER 11 | // This disclaimer is not a license and does not grant any 12 | // rights to the materials distributed herewith. Except as 13 | // otherwise provided in a valid license issued to you by 14 | // Xilinx, and to the maximum extent permitted by applicable 15 | // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND 16 | // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES 17 | // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING 18 | // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- 19 | // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and 20 | // (2) Xilinx shall not be liable (whether in contract or tort, 21 | // including negligence, or under any other theory of 22 | // liability) for any loss or damage of any kind or nature 23 | // related to, arising under or in connection with these 24 | // materials, including for any direct, or any indirect, 25 | // special, incidental, or consequential loss or damage 26 | // (including loss of data, profits, goodwill, or any type of 27 | // loss or damage suffered as a result of any action brought 28 | // by a third party) even if such damage or loss was 29 | // reasonably foreseeable or Xilinx had been advised of the 30 | // possibility of the same. 31 | // 32 | // CRITICAL APPLICATIONS 33 | // Xilinx products are not designed or intended to be fail- 34 | // safe, or for use in any application requiring fail-safe 35 | // performance, such as life-support or safety devices or 36 | // systems, Class III medical devices, nuclear facilities, 37 | // applications related to the deployment of airbags, or any 38 | // other applications that could lead to death, personal 39 | // injury, or severe property or environmental damage 40 | // (individually and collectively, "Critical 41 | // Applications"). Customer assumes the sole risk and 42 | // liability of any use of Xilinx products in Critical 43 | // Applications, subject only to applicable laws and 44 | // regulations governing limitations on product liability. 45 | // 46 | // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS 47 | // PART OF THIS FILE AT ALL TIMES. 48 | // 49 | //----------------------------------------------------------------------------- 50 | // Project : Series-7 Integrated Block for PCI Express 51 | // File : pcie_7xi_gtx_cpllpd_ovrd.v 52 | // Version : 3.3 53 | `timescale 1ns / 1ps 54 | module pcie_7xi_gtx_cpllpd_ovrd ( 55 | input i_ibufds_gte2, 56 | output o_cpllpd_ovrd, 57 | output o_cpllreset_ovrd 58 | ); 59 | (* equivalent_register_removal="no" *) reg [95:0] cpllpd_wait = 96'hFFFFFFFFFFFFFFFFFFFFFFFF; 60 | (* equivalent_register_removal="no" *) reg [127:0] cpllreset_wait = 128'h000000000000000000000000000000FF; 61 | always @(posedge i_ibufds_gte2) 62 | begin 63 | cpllpd_wait <= {cpllpd_wait[94:0], 1'b0}; 64 | cpllreset_wait <= {cpllreset_wait[126:0], 1'b0}; 65 | end 66 | assign o_cpllpd_ovrd = cpllpd_wait[95]; 67 | assign o_cpllreset_ovrd = cpllreset_wait[127]; 68 | endmodule 69 | -------------------------------------------------------------------------------- /ip/pcie_7xi/source/pcie_7xi_pcie_bram_7x.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // (c) Copyright 2010-2011 Xilinx, Inc. All rights reserved. 4 | // 5 | // This file contains confidential and proprietary information 6 | // of Xilinx, Inc. and is protected under U.S. and 7 | // international copyright and other intellectual property 8 | // laws. 9 | // 10 | // DISCLAIMER 11 | // This disclaimer is not a license and does not grant any 12 | // rights to the materials distributed herewith. Except as 13 | // otherwise provided in a valid license issued to you by 14 | // Xilinx, and to the maximum extent permitted by applicable 15 | // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND 16 | // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES 17 | // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING 18 | // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- 19 | // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and 20 | // (2) Xilinx shall not be liable (whether in contract or tort, 21 | // including negligence, or under any other theory of 22 | // liability) for any loss or damage of any kind or nature 23 | // related to, arising under or in connection with these 24 | // materials, including for any direct, or any indirect, 25 | // special, incidental, or consequential loss or damage 26 | // (including loss of data, profits, goodwill, or any type of 27 | // loss or damage suffered as a result of any action brought 28 | // by a third party) even if such damage or loss was 29 | // reasonably foreseeable or Xilinx had been advised of the 30 | // possibility of the same. 31 | // 32 | // CRITICAL APPLICATIONS 33 | // Xilinx products are not designed or intended to be fail- 34 | // safe, or for use in any application requiring fail-safe 35 | // performance, such as life-support or safety devices or 36 | // systems, Class III medical devices, nuclear facilities, 37 | // applications related to the deployment of airbags, or any 38 | // other applications that could lead to death, personal 39 | // injury, or severe property or environmental damage 40 | // (individually and collectively, "Critical 41 | // Applications"). Customer assumes the sole risk and 42 | // liability of any use of Xilinx products in Critical 43 | // Applications, subject only to applicable laws and 44 | // regulations governing limitations on product liability. 45 | // 46 | // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS 47 | // PART OF THIS FILE AT ALL TIMES. 48 | // 49 | //----------------------------------------------------------------------------- 50 | // Project : Series-7 Integrated Block for PCI Express 51 | // File : pcie_7xi_pcie_bram_7x.v 52 | // Version : 3.3 53 | // Description : single bram wrapper for the mb pcie block 54 | // The bram A port is the write port 55 | // the B port is the read port 56 | // 57 | // 58 | //-----------------------------------------------------------------------------// 59 | 60 | `timescale 1ps/1ps 61 | 62 | (* DowngradeIPIdentifiedWarnings = "yes" *) 63 | module pcie_7xi_pcie_bram_7x 64 | #( 65 | parameter [3:0] LINK_CAP_MAX_LINK_SPEED = 4'h1, // PCIe Link Speed : 1 - 2.5 GT/s; 2 - 5.0 GT/s 66 | parameter [5:0] LINK_CAP_MAX_LINK_WIDTH = 6'h08, // PCIe Link Width : 1 / 2 / 4 / 8 67 | parameter IMPL_TARGET = "HARD", // the implementation target : HARD, SOFT 68 | parameter DOB_REG = 0, // 1 - use the output register; 69 | // 0 - don't use the output register 70 | parameter WIDTH = 0 // supported WIDTH's : 4, 9, 18, 36 - uses RAMB36 71 | // 72 - uses RAMB36SDP 72 | ) 73 | ( 74 | input user_clk_i,// user clock 75 | input reset_i, // bram reset 76 | 77 | input wen_i, // write enable 78 | input [12:0] waddr_i, // write address 79 | input [WIDTH - 1:0] wdata_i, // write data 80 | 81 | input ren_i, // read enable 82 | input rce_i, // output register clock enable 83 | input [12:0] raddr_i, // read address 84 | 85 | output [WIDTH - 1:0] rdata_o // read data 86 | ); 87 | 88 | // map the address bits 89 | localparam ADDR_MSB = ((WIDTH == 4) ? 12 : 90 | (WIDTH == 9) ? 11 : 91 | (WIDTH == 18) ? 10 : 92 | (WIDTH == 36) ? 9 : 93 | 8 94 | ); 95 | 96 | // set the width of the tied off low address bits 97 | localparam ADDR_LO_BITS = ((WIDTH == 4) ? 2 : 98 | (WIDTH == 9) ? 3 : 99 | (WIDTH == 18) ? 4 : 100 | (WIDTH == 36) ? 5 : 101 | 0 // for WIDTH 72 use RAMB36SDP 102 | ); 103 | 104 | // map the data bits 105 | localparam D_MSB = ((WIDTH == 4) ? 3 : 106 | (WIDTH == 9) ? 7 : 107 | (WIDTH == 18) ? 15 : 108 | (WIDTH == 36) ? 31 : 109 | 63 110 | ); 111 | 112 | // map the data parity bits 113 | localparam DP_LSB = D_MSB + 1; 114 | 115 | localparam DP_MSB = ((WIDTH == 4) ? 4 : 116 | (WIDTH == 9) ? 8 : 117 | (WIDTH == 18) ? 17 : 118 | (WIDTH == 36) ? 35 : 119 | 71 120 | ); 121 | 122 | localparam DPW = DP_MSB - DP_LSB + 1; 123 | localparam WRITE_MODE = ((WIDTH == 72) && (!((LINK_CAP_MAX_LINK_SPEED == 4'h2) && (LINK_CAP_MAX_LINK_WIDTH == 6'h08)))) ? "WRITE_FIRST" : 124 | ((LINK_CAP_MAX_LINK_SPEED == 4'h2) && (LINK_CAP_MAX_LINK_WIDTH == 6'h08)) ? "WRITE_FIRST" : "NO_CHANGE"; 125 | 126 | localparam DEVICE = (IMPL_TARGET == "HARD") ? "7SERIES" : "VIRTEX6"; 127 | localparam BRAM_SIZE = "36Kb"; 128 | 129 | localparam WE_WIDTH =(DEVICE == "VIRTEX5" || DEVICE == "VIRTEX6" || DEVICE == "7SERIES") ? 130 | ((WIDTH <= 9) ? 1 : 131 | (WIDTH > 9 && WIDTH <= 18) ? 2 : 132 | (WIDTH > 18 && WIDTH <= 36) ? 4 : 133 | (WIDTH > 36 && WIDTH <= 72) ? 8 : 134 | (BRAM_SIZE == "18Kb") ? 4 : 8 ) : 8; 135 | 136 | //synthesis translate_off 137 | initial begin 138 | //$display("[%t] %m DOB_REG %0d WIDTH %0d ADDR_MSB %0d ADDR_LO_BITS %0d DP_MSB %0d DP_LSB %0d D_MSB %0d", 139 | // $time, DOB_REG, WIDTH, ADDR_MSB, ADDR_LO_BITS, DP_MSB, DP_LSB, D_MSB); 140 | 141 | case (WIDTH) 142 | 4,9,18,36,72:; 143 | default: 144 | begin 145 | $display("[%t] %m Error WIDTH %0d not supported", $time, WIDTH); 146 | $finish; 147 | end 148 | endcase // case (WIDTH) 149 | end 150 | //synthesis translate_on 151 | 152 | generate 153 | if ((LINK_CAP_MAX_LINK_WIDTH == 6'h08 && LINK_CAP_MAX_LINK_SPEED == 4'h2) || (WIDTH == 72)) begin : use_sdp 154 | BRAM_SDP_MACRO #( 155 | .DEVICE (DEVICE), 156 | .BRAM_SIZE (BRAM_SIZE), 157 | .DO_REG (DOB_REG), 158 | .READ_WIDTH (WIDTH), 159 | .WRITE_WIDTH (WIDTH), 160 | .WRITE_MODE (WRITE_MODE) 161 | ) 162 | ramb36sdp( 163 | .DO (rdata_o[WIDTH-1:0]), 164 | .DI (wdata_i[WIDTH-1:0]), 165 | .RDADDR (raddr_i[ADDR_MSB:0]), 166 | .RDCLK (user_clk_i), 167 | .RDEN (ren_i), 168 | .REGCE (rce_i), 169 | .RST (reset_i), 170 | .WE ({WE_WIDTH{1'b1}}), 171 | .WRADDR (waddr_i[ADDR_MSB:0]), 172 | .WRCLK (user_clk_i), 173 | .WREN (wen_i) 174 | ); 175 | 176 | end // block: use_sdp 177 | else if (WIDTH <= 36) begin : use_tdp 178 | // use RAMB36's if the width is 4, 9, 18, or 36 179 | BRAM_TDP_MACRO #( 180 | .DEVICE (DEVICE), 181 | .BRAM_SIZE (BRAM_SIZE), 182 | .DOA_REG (0), 183 | .DOB_REG (DOB_REG), 184 | .READ_WIDTH_A (WIDTH), 185 | .READ_WIDTH_B (WIDTH), 186 | .WRITE_WIDTH_A (WIDTH), 187 | .WRITE_WIDTH_B (WIDTH), 188 | .WRITE_MODE_A (WRITE_MODE) 189 | ) 190 | ramb36( 191 | .DOA (), 192 | .DOB (rdata_o[WIDTH-1:0]), 193 | .ADDRA (waddr_i[ADDR_MSB:0]), 194 | .ADDRB (raddr_i[ADDR_MSB:0]), 195 | .CLKA (user_clk_i), 196 | .CLKB (user_clk_i), 197 | .DIA (wdata_i[WIDTH-1:0]), 198 | .DIB ({WIDTH{1'b0}}), 199 | .ENA (wen_i), 200 | .ENB (ren_i), 201 | .REGCEA (1'b0), 202 | .REGCEB (rce_i), 203 | .RSTA (reset_i), 204 | .RSTB (reset_i), 205 | .WEA ({WE_WIDTH{1'b1}}), 206 | .WEB ({WE_WIDTH{1'b0}}) 207 | ); 208 | end // block: use_tdp 209 | endgenerate 210 | 211 | endmodule // pcie_bram_7x 212 | 213 | -------------------------------------------------------------------------------- /ip/pcie_7xi/source/pcie_7xi_pcie_bram_top_7x.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // (c) Copyright 2010-2011 Xilinx, Inc. All rights reserved. 4 | // 5 | // This file contains confidential and proprietary information 6 | // of Xilinx, Inc. and is protected under U.S. and 7 | // international copyright and other intellectual property 8 | // laws. 9 | // 10 | // DISCLAIMER 11 | // This disclaimer is not a license and does not grant any 12 | // rights to the materials distributed herewith. Except as 13 | // otherwise provided in a valid license issued to you by 14 | // Xilinx, and to the maximum extent permitted by applicable 15 | // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND 16 | // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES 17 | // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING 18 | // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- 19 | // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and 20 | // (2) Xilinx shall not be liable (whether in contract or tort, 21 | // including negligence, or under any other theory of 22 | // liability) for any loss or damage of any kind or nature 23 | // related to, arising under or in connection with these 24 | // materials, including for any direct, or any indirect, 25 | // special, incidental, or consequential loss or damage 26 | // (including loss of data, profits, goodwill, or any type of 27 | // loss or damage suffered as a result of any action brought 28 | // by a third party) even if such damage or loss was 29 | // reasonably foreseeable or Xilinx had been advised of the 30 | // possibility of the same. 31 | // 32 | // CRITICAL APPLICATIONS 33 | // Xilinx products are not designed or intended to be fail- 34 | // safe, or for use in any application requiring fail-safe 35 | // performance, such as life-support or safety devices or 36 | // systems, Class III medical devices, nuclear facilities, 37 | // applications related to the deployment of airbags, or any 38 | // other applications that could lead to death, personal 39 | // injury, or severe property or environmental damage 40 | // (individually and collectively, "Critical 41 | // Applications"). Customer assumes the sole risk and 42 | // liability of any use of Xilinx products in Critical 43 | // Applications, subject only to applicable laws and 44 | // regulations governing limitations on product liability. 45 | // 46 | // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS 47 | // PART OF THIS FILE AT ALL TIMES. 48 | // 49 | //----------------------------------------------------------------------------- 50 | // Project : Series-7 Integrated Block for PCI Express 51 | // File : pcie_7xi_pcie_bram_top_7x.v 52 | // Version : 3.3 53 | // Description : bram wrapper for Tx and Rx 54 | // given the pcie block attributes calculate the number of brams 55 | // and pipeline stages and instantiate the brams 56 | // 57 | // Hierarchy: 58 | // pcie_bram_top top level 59 | // pcie_brams pcie_bram instantiations, 60 | // pipeline stages (if any), 61 | // address decode logic (if any), 62 | // datapath muxing (if any) 63 | // pcie_bram bram library cell wrapper 64 | // the pcie_bram module can have a paramter that 65 | // specifies the family (V6, V5, V4) 66 | // 67 | //----------------------------------------------------------------------------- 68 | 69 | `timescale 1ps/1ps 70 | 71 | (* DowngradeIPIdentifiedWarnings = "yes" *) 72 | module pcie_7xi_pcie_bram_top_7x 73 | #( 74 | parameter IMPL_TARGET = "HARD", // the implementation target : HARD, SOFT 75 | parameter DEV_CAP_MAX_PAYLOAD_SUPPORTED = 0, // MPS Supported : 0 - 128 B, 1 - 256 B, 2 - 512 B, 3 - 1024 B 76 | parameter [3:0] LINK_CAP_MAX_LINK_SPEED = 4'h1, // PCIe Link Speed : 1 - 2.5 GT/s; 2 - 5.0 GT/s 77 | parameter [5:0] LINK_CAP_MAX_LINK_WIDTH = 6'h08, // PCIe Link Width : 1 / 2 / 4 / 8 78 | 79 | parameter VC0_TX_LASTPACKET = 31, // Number of Packets in Transmit 80 | parameter TLM_TX_OVERHEAD = 24, // Overhead Bytes for Packets (Transmit) 81 | parameter TL_TX_RAM_RADDR_LATENCY = 1, // BRAM Read Address Latency (Transmit) 82 | parameter TL_TX_RAM_RDATA_LATENCY = 2, // BRAM Read Data Latency (Transmit) 83 | parameter TL_TX_RAM_WRITE_LATENCY = 1, // BRAM Write Latency (Transmit) 84 | 85 | parameter VC0_RX_RAM_LIMIT = 'h1FFF, // RAM Size (Receive) 86 | parameter TL_RX_RAM_RADDR_LATENCY = 1, // BRAM Read Address Latency (Receive) 87 | parameter TL_RX_RAM_RDATA_LATENCY = 2, // BRAM Read Data Latency (Receive) 88 | parameter TL_RX_RAM_WRITE_LATENCY = 1 // BRAM Write Latency (Receive) 89 | ) 90 | ( 91 | input user_clk_i, // Clock input 92 | input reset_i, // Reset input 93 | 94 | input mim_tx_wen, // Write Enable for Transmit path BRAM 95 | input [12:0] mim_tx_waddr, // Write Address for Transmit path BRAM 96 | input [71:0] mim_tx_wdata, // Write Data for Transmit path BRAM 97 | input mim_tx_ren, // Read Enable for Transmit path BRAM 98 | input mim_tx_rce, // Read Output Register Clock Enable for Transmit path BRAM 99 | input [12:0] mim_tx_raddr, // Read Address for Transmit path BRAM 100 | output [71:0] mim_tx_rdata, // Read Data for Transmit path BRAM 101 | 102 | input mim_rx_wen, // Write Enable for Receive path BRAM 103 | input [12:0] mim_rx_waddr, // Write Enable for Receive path BRAM 104 | input [71:0] mim_rx_wdata, // Write Enable for Receive path BRAM 105 | input mim_rx_ren, // Read Enable for Receive path BRAM 106 | input mim_rx_rce, // Read Output Register Clock Enable for Receive path BRAM 107 | input [12:0] mim_rx_raddr, // Read Address for Receive path BRAM 108 | output [71:0] mim_rx_rdata // Read Data for Receive path BRAM 109 | ); 110 | 111 | // TX calculations 112 | localparam MPS_BYTES = ((DEV_CAP_MAX_PAYLOAD_SUPPORTED == 0) ? 128 : 113 | (DEV_CAP_MAX_PAYLOAD_SUPPORTED == 1) ? 256 : 114 | (DEV_CAP_MAX_PAYLOAD_SUPPORTED == 2) ? 512 : 115 | 1024 ); 116 | 117 | localparam BYTES_TX = (VC0_TX_LASTPACKET + 1) * (MPS_BYTES + TLM_TX_OVERHEAD); 118 | 119 | localparam ROWS_TX = 1; 120 | localparam COLS_TX = ((BYTES_TX <= 4096) ? 1 : 121 | (BYTES_TX <= 8192) ? 2 : 122 | (BYTES_TX <= 16384) ? 4 : 123 | (BYTES_TX <= 32768) ? 8 : 124 | 18 125 | ); 126 | 127 | // RX calculations 128 | localparam ROWS_RX = 1; 129 | 130 | localparam COLS_RX = ((VC0_RX_RAM_LIMIT < 'h0200) ? 1 : 131 | (VC0_RX_RAM_LIMIT < 'h0400) ? 2 : 132 | (VC0_RX_RAM_LIMIT < 'h0800) ? 4 : 133 | (VC0_RX_RAM_LIMIT < 'h1000) ? 8 : 134 | 18 135 | ); 136 | 137 | initial begin 138 | $display("[%t] %m ROWS_TX %0d COLS_TX %0d", $time, ROWS_TX, COLS_TX); 139 | $display("[%t] %m ROWS_RX %0d COLS_RX %0d", $time, ROWS_RX, COLS_RX); 140 | end 141 | 142 | pcie_7xi_pcie_brams_7x #( 143 | .LINK_CAP_MAX_LINK_WIDTH ( LINK_CAP_MAX_LINK_WIDTH ), 144 | .LINK_CAP_MAX_LINK_SPEED ( LINK_CAP_MAX_LINK_SPEED ), 145 | .IMPL_TARGET ( IMPL_TARGET ), 146 | .NUM_BRAMS ( COLS_TX ), 147 | .RAM_RADDR_LATENCY ( TL_TX_RAM_RADDR_LATENCY ), 148 | .RAM_RDATA_LATENCY ( TL_TX_RAM_RDATA_LATENCY ), 149 | .RAM_WRITE_LATENCY ( TL_TX_RAM_WRITE_LATENCY ) 150 | ) 151 | pcie_brams_tx ( 152 | .user_clk_i ( user_clk_i ), 153 | .reset_i ( reset_i ), 154 | .waddr ( mim_tx_waddr ), 155 | .wen ( mim_tx_wen ), 156 | .ren ( mim_tx_ren ), 157 | .rce ( mim_tx_rce ), 158 | .wdata ( mim_tx_wdata ), 159 | .raddr ( mim_tx_raddr ), 160 | .rdata ( mim_tx_rdata ) 161 | ); 162 | 163 | pcie_7xi_pcie_brams_7x #( 164 | .LINK_CAP_MAX_LINK_WIDTH ( LINK_CAP_MAX_LINK_WIDTH ), 165 | .LINK_CAP_MAX_LINK_SPEED ( LINK_CAP_MAX_LINK_SPEED ), 166 | .IMPL_TARGET ( IMPL_TARGET ), 167 | .NUM_BRAMS ( COLS_RX ), 168 | .RAM_RADDR_LATENCY ( TL_RX_RAM_RADDR_LATENCY ), 169 | .RAM_RDATA_LATENCY ( TL_RX_RAM_RDATA_LATENCY ), 170 | .RAM_WRITE_LATENCY ( TL_RX_RAM_WRITE_LATENCY ) 171 | ) pcie_brams_rx ( 172 | .user_clk_i ( user_clk_i ), 173 | .reset_i ( reset_i ), 174 | .waddr ( mim_rx_waddr ), 175 | .wen ( mim_rx_wen ), 176 | .ren ( mim_rx_ren ), 177 | .rce ( mim_rx_rce ), 178 | .wdata ( mim_rx_wdata ), 179 | .raddr ( mim_rx_raddr ), 180 | .rdata ( mim_rx_rdata ) 181 | ); 182 | 183 | endmodule // pcie_bram_top 184 | 185 | -------------------------------------------------------------------------------- /ip/pcie_7xi/source/pcie_7xi_pcie_brams_7x.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // (c) Copyright 2010-2011 Xilinx, Inc. All rights reserved. 4 | // 5 | // This file contains confidential and proprietary information 6 | // of Xilinx, Inc. and is protected under U.S. and 7 | // international copyright and other intellectual property 8 | // laws. 9 | // 10 | // DISCLAIMER 11 | // This disclaimer is not a license and does not grant any 12 | // rights to the materials distributed herewith. Except as 13 | // otherwise provided in a valid license issued to you by 14 | // Xilinx, and to the maximum extent permitted by applicable 15 | // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND 16 | // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES 17 | // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING 18 | // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- 19 | // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and 20 | // (2) Xilinx shall not be liable (whether in contract or tort, 21 | // including negligence, or under any other theory of 22 | // liability) for any loss or damage of any kind or nature 23 | // related to, arising under or in connection with these 24 | // materials, including for any direct, or any indirect, 25 | // special, incidental, or consequential loss or damage 26 | // (including loss of data, profits, goodwill, or any type of 27 | // loss or damage suffered as a result of any action brought 28 | // by a third party) even if such damage or loss was 29 | // reasonably foreseeable or Xilinx had been advised of the 30 | // possibility of the same. 31 | // 32 | // CRITICAL APPLICATIONS 33 | // Xilinx products are not designed or intended to be fail- 34 | // safe, or for use in any application requiring fail-safe 35 | // performance, such as life-support or safety devices or 36 | // systems, Class III medical devices, nuclear facilities, 37 | // applications related to the deployment of airbags, or any 38 | // other applications that could lead to death, personal 39 | // injury, or severe property or environmental damage 40 | // (individually and collectively, "Critical 41 | // Applications"). Customer assumes the sole risk and 42 | // liability of any use of Xilinx products in Critical 43 | // Applications, subject only to applicable laws and 44 | // regulations governing limitations on product liability. 45 | // 46 | // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS 47 | // PART OF THIS FILE AT ALL TIMES. 48 | // 49 | //----------------------------------------------------------------------------- 50 | // Project : Series-7 Integrated Block for PCI Express 51 | // File : pcie_7xi_pcie_brams_7x.v 52 | // Version : 3.3 53 | // Description : pcie bram wrapper 54 | // arrange and connect brams 55 | // implement address decoding, datapath muxing and pipeline stages 56 | // 57 | // banks of brams are used for 1,2,4,8,18 brams 58 | // brams are stacked for other values of NUM_BRAMS 59 | // 60 | //----------------------------------------------------------------------------- 61 | 62 | `timescale 1ps/1ps 63 | 64 | (* DowngradeIPIdentifiedWarnings = "yes" *) 65 | module pcie_7xi_pcie_brams_7x 66 | #( 67 | parameter [3:0] LINK_CAP_MAX_LINK_SPEED = 4'h1, // PCIe Link Speed : 1 - 2.5 GT/s; 2 - 5.0 GT/s 68 | parameter [5:0] LINK_CAP_MAX_LINK_WIDTH = 6'h08, // PCIe Link Width : 1 / 2 / 4 / 8 69 | parameter IMPL_TARGET = "HARD", // the implementation target : HARD, SOFT 70 | 71 | // the number of BRAMs to use 72 | // supported values are: 73 | // 1,2,4,8,18 74 | parameter NUM_BRAMS = 0, 75 | 76 | // BRAM read address latency 77 | // 78 | // value meaning 79 | // ==================================================== 80 | // 0 BRAM read address port sample 81 | // 1 BRAM read address port sample and a pipeline stage on the address port 82 | parameter RAM_RADDR_LATENCY = 1, 83 | 84 | // BRAM read data latency 85 | // 86 | // value meaning 87 | // ==================================================== 88 | // 1 no BRAM OREG 89 | // 2 use BRAM OREG 90 | // 3 use BRAM OREG and a pipeline stage on the data port 91 | parameter RAM_RDATA_LATENCY = 1, 92 | 93 | // BRAM write latency 94 | // The BRAM write port is synchronous 95 | // 96 | // value meaning 97 | // ==================================================== 98 | // 0 BRAM write port sample 99 | // 1 BRAM write port sample plus pipeline stage 100 | parameter RAM_WRITE_LATENCY = 1, 101 | parameter TCQ = 1 // synthesis warning removed: parameter declaration becomes local 102 | ) 103 | ( 104 | input user_clk_i, 105 | input reset_i, 106 | 107 | input wen, 108 | input [12:0] waddr, 109 | input [71:0] wdata, 110 | input ren, 111 | input rce, 112 | input [12:0] raddr, 113 | output [71:0] rdata 114 | ); 115 | 116 | // turn on the bram output register 117 | localparam DOB_REG = (RAM_RDATA_LATENCY > 1) ? 1 : 0; 118 | 119 | // calculate the data width of the individual brams 120 | localparam [6:0] WIDTH = ((NUM_BRAMS == 1) ? 72 : 121 | (NUM_BRAMS == 2) ? 36 : 122 | (NUM_BRAMS == 4) ? 18 : 123 | (NUM_BRAMS == 8) ? 9 : 124 | 4 125 | ); 126 | 127 | // parameter TCQ = 1; 128 | 129 | wire wen_int; 130 | wire [12:0] waddr_int; 131 | wire [71:0] wdata_int; 132 | 133 | wire ren_int; 134 | wire [12:0] raddr_int; 135 | wire [71:0] rdata_int; 136 | 137 | //synthesis translate_off 138 | initial 139 | begin 140 | $display("[%t] %m NUM_BRAMS %0d DOB_REG %0d WIDTH %0d RAM_WRITE_LATENCY %0d RAM_RADDR_LATENCY %0d RAM_RDATA_LATENCY %0d", 141 | $time, NUM_BRAMS, DOB_REG, WIDTH, RAM_WRITE_LATENCY, RAM_RADDR_LATENCY, RAM_RDATA_LATENCY); 142 | 143 | case (NUM_BRAMS) 144 | 1,2,4,8,18:; 145 | default: 146 | begin 147 | $display("[%t] %m Error NUM_BRAMS %0d not supported", $time, NUM_BRAMS); 148 | $finish; 149 | end 150 | endcase // case(NUM_BRAMS) 151 | 152 | case (RAM_RADDR_LATENCY) 153 | 0,1:; 154 | default: 155 | begin 156 | $display("[%t] %m Error RAM_READ_LATENCY %0d not supported", $time, RAM_RADDR_LATENCY); 157 | $finish; 158 | end 159 | endcase // case (RAM_RADDR_LATENCY) 160 | 161 | case (RAM_RDATA_LATENCY) 162 | 1,2,3:; 163 | default: 164 | begin 165 | $display("[%t] %m Error RAM_READ_LATENCY %0d not supported", $time, RAM_RDATA_LATENCY); 166 | $finish; 167 | end 168 | endcase // case (RAM_RDATA_LATENCY) 169 | 170 | case (RAM_WRITE_LATENCY) 171 | 0,1:; 172 | default: 173 | begin 174 | $display("[%t] %m Error RAM_WRITE_LATENCY %0d not supported", $time, RAM_WRITE_LATENCY); 175 | $finish; 176 | end 177 | endcase // case(RAM_WRITE_LATENCY) 178 | 179 | end 180 | //synthesis translate_on 181 | 182 | // model the delays for ram write latency 183 | 184 | generate if (RAM_WRITE_LATENCY == 1) begin : wr_lat_2 185 | reg wen_q; 186 | reg [12:0] waddr_q; 187 | reg [71:0] wdata_q; 188 | 189 | always @(posedge user_clk_i) begin 190 | if (reset_i) 191 | begin 192 | wen_q <= #TCQ 1'b0; 193 | waddr_q <= #TCQ 13'b0; 194 | // Disable Reset on Data Path @ BRAM i/f as I/O come from PCIe HB. 195 | // wdata_q <= #TCQ 72'b0; 196 | end 197 | else 198 | begin 199 | wen_q <= #TCQ wen; 200 | waddr_q <= #TCQ waddr; 201 | wdata_q <= #TCQ wdata; 202 | end 203 | end 204 | 205 | assign wen_int = wen_q; 206 | assign waddr_int = waddr_q; 207 | assign wdata_int = wdata_q; 208 | end // if (RAM_WRITE_LATENCY == 1) 209 | 210 | else if (RAM_WRITE_LATENCY == 0) begin : wr_lat_1 211 | assign wen_int = wen; 212 | assign waddr_int = waddr; 213 | assign wdata_int = wdata; 214 | end 215 | endgenerate 216 | 217 | // model the delays for ram read latency 218 | 219 | generate if (RAM_RADDR_LATENCY == 1) begin : raddr_lat_2 220 | reg ren_q; 221 | reg [12:0] raddr_q; 222 | 223 | always @(posedge user_clk_i) begin 224 | if (reset_i) 225 | begin 226 | ren_q <= #TCQ 1'b0; 227 | raddr_q <= #TCQ 13'b0; 228 | end 229 | else 230 | begin 231 | ren_q <= #TCQ ren; 232 | raddr_q <= #TCQ raddr; 233 | end // else: !if(reset_i) 234 | end 235 | 236 | assign ren_int = ren_q; 237 | assign raddr_int = raddr_q; 238 | end // block: rd_lat_addr_2 239 | 240 | else begin : raddr_lat_1 241 | assign ren_int = ren; 242 | assign raddr_int = raddr; 243 | end 244 | endgenerate 245 | 246 | generate if (RAM_RDATA_LATENCY == 3) begin : rdata_lat_3 247 | reg [71:0] rdata_q; 248 | 249 | always @(posedge user_clk_i) begin 250 | // Disable Reset on Data Path @ BRAM i/f as I/O come from PCIe HB. 251 | //if (reset_i) 252 | //begin 253 | // rdata_q <= #TCQ 72'b0; 254 | //end 255 | //else 256 | //begin 257 | rdata_q <= #TCQ rdata_int; 258 | //end // else: !if(reset_i) 259 | end 260 | 261 | assign rdata = rdata_q; 262 | 263 | end // block: rd_lat_data_3 264 | 265 | else begin : rdata_lat_1_2 266 | assign rdata = rdata_int; 267 | end 268 | endgenerate 269 | 270 | // instantiate the brams 271 | generate 272 | genvar ii; 273 | for (ii = 0; ii < NUM_BRAMS; ii = ii + 1) begin : brams 274 | pcie_7xi_pcie_bram_7x #( 275 | .LINK_CAP_MAX_LINK_WIDTH(LINK_CAP_MAX_LINK_WIDTH), 276 | .LINK_CAP_MAX_LINK_SPEED(LINK_CAP_MAX_LINK_SPEED), 277 | .IMPL_TARGET (IMPL_TARGET), 278 | .DOB_REG (DOB_REG), 279 | .WIDTH (WIDTH) 280 | ) 281 | ram ( 282 | .user_clk_i(user_clk_i), 283 | .reset_i(reset_i), 284 | .wen_i(wen_int), 285 | .waddr_i(waddr_int), 286 | .wdata_i(wdata_int[(((ii + 1) * WIDTH) - 1): (ii * WIDTH)]), 287 | .ren_i(ren_int), 288 | .raddr_i(raddr_int), 289 | .rdata_o(rdata_int[(((ii + 1) * WIDTH) - 1): (ii * WIDTH)]), 290 | .rce_i(rce) 291 | ); 292 | end 293 | endgenerate 294 | 295 | endmodule // pcie_brams_7x 296 | 297 | -------------------------------------------------------------------------------- /ip/pcie_7xi/source/pcie_7xi_pcie_pipe_misc.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 3 | // (c) Copyright 2010-2011 Xilinx, Inc. All rights reserved. 4 | // 5 | // This file contains confidential and proprietary information 6 | // of Xilinx, Inc. and is protected under U.S. and 7 | // international copyright and other intellectual property 8 | // laws. 9 | // 10 | // DISCLAIMER 11 | // This disclaimer is not a license and does not grant any 12 | // rights to the materials distributed herewith. Except as 13 | // otherwise provided in a valid license issued to you by 14 | // Xilinx, and to the maximum extent permitted by applicable 15 | // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND 16 | // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES 17 | // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING 18 | // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- 19 | // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and 20 | // (2) Xilinx shall not be liable (whether in contract or tort, 21 | // including negligence, or under any other theory of 22 | // liability) for any loss or damage of any kind or nature 23 | // related to, arising under or in connection with these 24 | // materials, including for any direct, or any indirect, 25 | // special, incidental, or consequential loss or damage 26 | // (including loss of data, profits, goodwill, or any type of 27 | // loss or damage suffered as a result of any action brought 28 | // by a third party) even if such damage or loss was 29 | // reasonably foreseeable or Xilinx had been advised of the 30 | // possibility of the same. 31 | // 32 | // CRITICAL APPLICATIONS 33 | // Xilinx products are not designed or intended to be fail- 34 | // safe, or for use in any application requiring fail-safe 35 | // performance, such as life-support or safety devices or 36 | // systems, Class III medical devices, nuclear facilities, 37 | // applications related to the deployment of airbags, or any 38 | // other applications that could lead to death, personal 39 | // injury, or severe property or environmental damage 40 | // (individually and collectively, "Critical 41 | // Applications"). Customer assumes the sole risk and 42 | // liability of any use of Xilinx products in Critical 43 | // Applications, subject only to applicable laws and 44 | // regulations governing limitations on product liability. 45 | // 46 | // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS 47 | // PART OF THIS FILE AT ALL TIMES. 48 | // 49 | //----------------------------------------------------------------------------- 50 | // Project : Series-7 Integrated Block for PCI Express 51 | // File : pcie_7xi_pcie_pipe_misc.v 52 | // Version : 3.3 53 | // 54 | // Description: Misc PIPE module for 7-Series PCIe Block 55 | // 56 | // 57 | // 58 | //-------------------------------------------------------------------------------- 59 | 60 | `timescale 1ps/1ps 61 | 62 | (* DowngradeIPIdentifiedWarnings = "yes" *) 63 | module pcie_7xi_pcie_pipe_misc # 64 | ( 65 | parameter PIPE_PIPELINE_STAGES = 0, // 0 - 0 stages, 1 - 1 stage, 2 - 2 stages 66 | parameter TCQ = 1 // synthesis warning solved: parameter declaration becomes local 67 | ) 68 | ( 69 | 70 | input wire pipe_tx_rcvr_det_i , // PIPE Tx Receiver Detect 71 | input wire pipe_tx_reset_i , // PIPE Tx Reset 72 | input wire pipe_tx_rate_i , // PIPE Tx Rate 73 | input wire pipe_tx_deemph_i , // PIPE Tx Deemphasis 74 | input wire [2:0] pipe_tx_margin_i , // PIPE Tx Margin 75 | input wire pipe_tx_swing_i , // PIPE Tx Swing 76 | 77 | output wire pipe_tx_rcvr_det_o , // Pipelined PIPE Tx Receiver Detect 78 | output wire pipe_tx_reset_o , // Pipelined PIPE Tx Reset 79 | output wire pipe_tx_rate_o , // Pipelined PIPE Tx Rate 80 | output wire pipe_tx_deemph_o , // Pipelined PIPE Tx Deemphasis 81 | output wire [2:0] pipe_tx_margin_o , // Pipelined PIPE Tx Margin 82 | output wire pipe_tx_swing_o , // Pipelined PIPE Tx Swing 83 | 84 | input wire pipe_clk , // PIPE Clock 85 | input wire rst_n // Reset 86 | ); 87 | 88 | //******************************************************************// 89 | // Reality check. // 90 | //******************************************************************// 91 | 92 | // parameter TCQ = 1; // clock to out delay model 93 | 94 | generate 95 | 96 | if (PIPE_PIPELINE_STAGES == 0) begin : pipe_stages_0 97 | 98 | assign pipe_tx_rcvr_det_o = pipe_tx_rcvr_det_i; 99 | assign pipe_tx_reset_o = pipe_tx_reset_i; 100 | assign pipe_tx_rate_o = pipe_tx_rate_i; 101 | assign pipe_tx_deemph_o = pipe_tx_deemph_i; 102 | assign pipe_tx_margin_o = pipe_tx_margin_i; 103 | assign pipe_tx_swing_o = pipe_tx_swing_i; 104 | 105 | end // if (PIPE_PIPELINE_STAGES == 0) 106 | else if (PIPE_PIPELINE_STAGES == 1) begin : pipe_stages_1 107 | 108 | reg pipe_tx_rcvr_det_q ; 109 | reg pipe_tx_reset_q ; 110 | reg pipe_tx_rate_q ; 111 | reg pipe_tx_deemph_q ; 112 | reg [2:0] pipe_tx_margin_q ; 113 | reg pipe_tx_swing_q ; 114 | 115 | always @(posedge pipe_clk) begin 116 | 117 | if (rst_n) 118 | begin 119 | 120 | pipe_tx_rcvr_det_q <= #TCQ 0; 121 | pipe_tx_reset_q <= #TCQ 1'b1; 122 | pipe_tx_rate_q <= #TCQ 0; 123 | pipe_tx_deemph_q <= #TCQ 1'b1; 124 | pipe_tx_margin_q <= #TCQ 0; 125 | pipe_tx_swing_q <= #TCQ 0; 126 | 127 | end 128 | else 129 | begin 130 | 131 | pipe_tx_rcvr_det_q <= #TCQ pipe_tx_rcvr_det_i; 132 | pipe_tx_reset_q <= #TCQ pipe_tx_reset_i; 133 | pipe_tx_rate_q <= #TCQ pipe_tx_rate_i; 134 | pipe_tx_deemph_q <= #TCQ pipe_tx_deemph_i; 135 | pipe_tx_margin_q <= #TCQ pipe_tx_margin_i; 136 | pipe_tx_swing_q <= #TCQ pipe_tx_swing_i; 137 | 138 | end 139 | 140 | end 141 | 142 | assign pipe_tx_rcvr_det_o = pipe_tx_rcvr_det_q; 143 | assign pipe_tx_reset_o = pipe_tx_reset_q; 144 | assign pipe_tx_rate_o = pipe_tx_rate_q; 145 | assign pipe_tx_deemph_o = pipe_tx_deemph_q; 146 | assign pipe_tx_margin_o = pipe_tx_margin_q; 147 | assign pipe_tx_swing_o = pipe_tx_swing_q; 148 | 149 | end // if (PIPE_PIPELINE_STAGES == 1) 150 | else if (PIPE_PIPELINE_STAGES == 2) begin : pipe_stages_2 151 | 152 | reg pipe_tx_rcvr_det_q ; 153 | reg pipe_tx_reset_q ; 154 | reg pipe_tx_rate_q ; 155 | reg pipe_tx_deemph_q ; 156 | reg [2:0] pipe_tx_margin_q ; 157 | reg pipe_tx_swing_q ; 158 | 159 | reg pipe_tx_rcvr_det_qq ; 160 | reg pipe_tx_reset_qq ; 161 | reg pipe_tx_rate_qq ; 162 | reg pipe_tx_deemph_qq ; 163 | reg [2:0] pipe_tx_margin_qq ; 164 | reg pipe_tx_swing_qq ; 165 | 166 | always @(posedge pipe_clk) begin 167 | 168 | if (rst_n) 169 | begin 170 | 171 | pipe_tx_rcvr_det_q <= #TCQ 0; 172 | pipe_tx_reset_q <= #TCQ 1'b1; 173 | pipe_tx_rate_q <= #TCQ 0; 174 | pipe_tx_deemph_q <= #TCQ 1'b1; 175 | pipe_tx_margin_q <= #TCQ 0; 176 | pipe_tx_swing_q <= #TCQ 0; 177 | 178 | pipe_tx_rcvr_det_qq <= #TCQ 0; 179 | pipe_tx_reset_qq <= #TCQ 1'b1; 180 | pipe_tx_rate_qq <= #TCQ 0; 181 | pipe_tx_deemph_qq <= #TCQ 1'b1; 182 | pipe_tx_margin_qq <= #TCQ 0; 183 | pipe_tx_swing_qq <= #TCQ 0; 184 | 185 | end 186 | else 187 | begin 188 | 189 | pipe_tx_rcvr_det_q <= #TCQ pipe_tx_rcvr_det_i; 190 | pipe_tx_reset_q <= #TCQ pipe_tx_reset_i; 191 | pipe_tx_rate_q <= #TCQ pipe_tx_rate_i; 192 | pipe_tx_deemph_q <= #TCQ pipe_tx_deemph_i; 193 | pipe_tx_margin_q <= #TCQ pipe_tx_margin_i; 194 | pipe_tx_swing_q <= #TCQ pipe_tx_swing_i; 195 | 196 | pipe_tx_rcvr_det_qq <= #TCQ pipe_tx_rcvr_det_q; 197 | pipe_tx_reset_qq <= #TCQ pipe_tx_reset_q; 198 | pipe_tx_rate_qq <= #TCQ pipe_tx_rate_q; 199 | pipe_tx_deemph_qq <= #TCQ pipe_tx_deemph_q; 200 | pipe_tx_margin_qq <= #TCQ pipe_tx_margin_q; 201 | pipe_tx_swing_qq <= #TCQ pipe_tx_swing_q; 202 | 203 | end 204 | 205 | end 206 | 207 | assign pipe_tx_rcvr_det_o = pipe_tx_rcvr_det_qq; 208 | assign pipe_tx_reset_o = pipe_tx_reset_qq; 209 | assign pipe_tx_rate_o = pipe_tx_rate_qq; 210 | assign pipe_tx_deemph_o = pipe_tx_deemph_qq; 211 | assign pipe_tx_margin_o = pipe_tx_margin_qq; 212 | assign pipe_tx_swing_o = pipe_tx_swing_qq; 213 | 214 | end // if (PIPE_PIPELINE_STAGES == 2) 215 | 216 | endgenerate 217 | 218 | endmodule 219 | 220 | -------------------------------------------------------------------------------- /ip/pcie_7xi/synth/pcie_7xi_ooc.xdc: -------------------------------------------------------------------------------- 1 | ##----------------------------------------------------------------------------- 2 | ## 3 | ## (c) Copyright 2010-2011 Xilinx, Inc. All rights reserved. 4 | ## 5 | ## This file contains confidential and proprietary information 6 | ## of Xilinx, Inc. and is protected under U.S. and 7 | ## international copyright and other intellectual property 8 | ## laws. 9 | ## 10 | ## DISCLAIMER 11 | ## This disclaimer is not a license and does not grant any 12 | ## rights to the materials distributed herewith. Except as 13 | ## otherwise provided in a valid license issued to you by 14 | ## Xilinx, and to the maximum extent permitted by applicable 15 | ## law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND 16 | ## WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES 17 | ## AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING 18 | ## BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- 19 | ## INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and 20 | ## (2) Xilinx shall not be liable (whether in contract or tort, 21 | ## including negligence, or under any other theory of 22 | ## liability) for any loss or damage of any kind or nature 23 | ## related to, arising under or in connection with these 24 | ## materials, including for any direct, or any indirect, 25 | ## special, incidental, or consequential loss or damage 26 | ## (including loss of data, profits, goodwill, or any type of 27 | ## loss or damage suffered as a result of any action brought 28 | ## by a third party) even if such damage or loss was 29 | ## reasonably foreseeable or Xilinx had been advised of the 30 | ## possibility of the same. 31 | ## 32 | ## CRITICAL APPLICATIONS 33 | ## Xilinx products are not designed or intended to be fail- 34 | ## safe, or for use in any application requiring fail-safe 35 | ## performance, such as life-support or safety devices or 36 | ## systems, Class III medical devices, nuclear facilities, 37 | ## applications related to the deployment of airbags, or any 38 | ## other applications that could lead to death, personal 39 | ## injury, or severe property or environmental damage 40 | ## (individually and collectively, "Critical 41 | ## Applications"). Customer assumes the sole risk and 42 | ## liability of any use of Xilinx products in Critical 43 | ## Applications, subject only to applicable laws and 44 | ## regulations governing limitations on product liability. 45 | ## 46 | ## THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS 47 | ## PART OF THIS FILE AT ALL TIMES. 48 | ## 49 | ##----------------------------------------------------------------------------- 50 | ## Project : Series-7 Integrated Block for PCI Express 51 | ## File : pcie_7xi_ooc.xdc 52 | ## Version : 3.3 53 | # 54 | # This constraints file contains default clock frequencies to be used during out-of-context flows such as 55 | # OOC Synthesis and Hierarchical Designs. For best results the frequencies should be modified 56 | # to match the target frequencies. 57 | # This constraints file is not used in normal top-down synthesis (the default flow of Vivado) 58 | 59 | # 60 | create_clock -name pcie_7xi_sys_clk -period 10 [get_ports sys_clk] 61 | # 100/125/250 MHz 62 | 63 | -------------------------------------------------------------------------------- /ip/pcie_7xi/sys_clk_gen_ps_v.txt: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------------------- 2 | -------------------------------------------------------------------------------- /nix/default.nix: -------------------------------------------------------------------------------- 1 | { sources ? import ./sources.nix }: 2 | 3 | let 4 | overlay = super: pkgs: { 5 | # Nix tooling 6 | niv = (import sources.niv {}).niv; 7 | gitignore = import sources.gitignore {}; 8 | 9 | # haskellPackages = pkgs.haskellPackages.override { 10 | # overrides = self: super: { 11 | # Haskell overrides 12 | haskell = pkgs.haskell // { 13 | packageOverrides = self: super: { 14 | 15 | clash-prelude = 16 | pkgs.haskell.lib.dontCheck 17 | # (pkgs.haskell.lib.dontHaddock 18 | (self.callCabal2nix "clash-prelude" (sources.clash-compiler + "/clash-prelude") {}); 19 | clash-lib = 20 | pkgs.haskell.lib.dontCheck 21 | (pkgs.haskell.lib.dontHaddock 22 | (self.callCabal2nix "clash-lib" (sources.clash-compiler + "/clash-lib") {})); 23 | clash-ghc = 24 | pkgs.haskell.lib.dontCheck 25 | (pkgs.haskell.lib.dontHaddock 26 | (self.callCabal2nix "clash-ghc" (sources.clash-compiler + "/clash-ghc") {})); 27 | # External overrides 28 | ghc-typelits-extra = 29 | self.callCabal2nix "ghc-typelits-extra" sources.ghc-typelits-extra {}; 30 | ghc-typelits-knownnat = 31 | self.callCabal2nix "ghc-typelits-knownnat" sources.ghc-typelits-knownnat {}; 32 | 33 | higgledy = 34 | self.callCabal2nix "higgledy" sources.higgledy {}; 35 | 36 | type-errors = 37 | self.callCabal2nix "type-errors" sources.type-errors {}; 38 | 39 | first-class-families = 40 | self.callCabal2nix "first-class-families" sources.first-class-families {}; 41 | # }); 42 | }; 43 | }; 44 | } // import sources.clash-compiler {}; 45 | 46 | in import sources.nixpkgs { overlays = [ overlay ]; } 47 | -------------------------------------------------------------------------------- /nix/sources.json: -------------------------------------------------------------------------------- 1 | { 2 | "clash-compiler": { 3 | "branch": "blackboxscaffold", 4 | "description": "Haskell to VHDL/Verilog/SystemVerilog compiler", 5 | "homepage": "https://www.clash-lang.org/", 6 | "owner": "clash-lang", 7 | "repo": "clash-compiler", 8 | "rev": "1701a6feec09748c4e639cfa51a541c3a54bff88", 9 | "sha256": "0cswf68v6nhdpfdfyvhil7vgmv5z3rsdiap9d1sh4mxrdar4r23q", 10 | "type": "tarball", 11 | "url": "https://github.com/clash-lang/clash-compiler/archive/1701a6feec09748c4e639cfa51a541c3a54bff88.tar.gz", 12 | "url_template": "https://github.com///archive/.tar.gz" 13 | }, 14 | "first-class-families": { 15 | "branch": "master", 16 | "description": "First-class type families", 17 | "homepage": null, 18 | "owner": "Lysxia", 19 | "repo": "first-class-families", 20 | "rev": "bb6487804594c6d6cdc383011d81dc425e5a456c", 21 | "sha256": "1y1a6fi2307z04bzl5jw38zqrzzhjfb59kp47xj0ibnmqqr7xyka", 22 | "type": "tarball", 23 | "url": "https://github.com/Lysxia/first-class-families/archive/bb6487804594c6d6cdc383011d81dc425e5a456c.tar.gz", 24 | "url_template": "https://github.com///archive/.tar.gz" 25 | }, 26 | "ghc-typelits-extra": { 27 | "branch": "master", 28 | "description": "Extra type-level operations on GHC.TypeLits.Nat and a custom solver", 29 | "homepage": null, 30 | "owner": "clash-lang", 31 | "repo": "ghc-typelits-extra", 32 | "rev": "14b52940d30172aee1c315dbc9868c0314017e99", 33 | "sha256": "181m8nvac5px94spqy5hir0pnv67hnq8skcv46ji0dmb274c4zk9", 34 | "type": "tarball", 35 | "url": "https://github.com/clash-lang/ghc-typelits-extra/archive/14b52940d30172aee1c315dbc9868c0314017e99.tar.gz", 36 | "url_template": "https://github.com///archive/.tar.gz", 37 | "version": "a8de0b68b8216411cb862195354f251cd41bae50" 38 | }, 39 | "ghc-typelits-knownnat": { 40 | "branch": "master", 41 | "description": "Derive KnownNat constraints from other KnownNat constraints", 42 | "homepage": null, 43 | "owner": "clash-lang", 44 | "repo": "ghc-typelits-knownnat", 45 | "rev": "d2f0851b23cae51fc6e87a7d6e98998cfa20ea56", 46 | "sha256": "0khkpb6phqlk5z62frnamf0s35aqdddhz5v2li57m99k48vlkv2h", 47 | "type": "tarball", 48 | "url": "https://github.com/clash-lang/ghc-typelits-knownnat/archive/d2f0851b23cae51fc6e87a7d6e98998cfa20ea56.tar.gz", 49 | "url_template": "https://github.com///archive/.tar.gz" 50 | }, 51 | "gitignore": { 52 | "branch": "master", 53 | "description": "Nix function for filtering local git sources", 54 | "homepage": "", 55 | "owner": "hercules-ci", 56 | "repo": "gitignore", 57 | "rev": "ec4a0039152655b6c919d289dafd7ba32206ea1f", 58 | "sha256": "13qxqbs8jg2mz2fm2cs63czv30gxi39ws5qzf9j8mczqpdj6g3im", 59 | "type": "tarball", 60 | "url": "https://github.com/hercules-ci/gitignore/archive/ec4a0039152655b6c919d289dafd7ba32206ea1f.tar.gz", 61 | "url_template": "https://github.com///archive/.tar.gz" 62 | }, 63 | "higgledy": { 64 | "branch": "master", 65 | "description": "Higher-kinded data via generics", 66 | "homepage": "", 67 | "owner": "i-am-tom", 68 | "repo": "higgledy", 69 | "rev": "476d73a92e3ef6e1dc879555d751f877b0f91de8", 70 | "sha256": "1vg9ha3knggyh5a76678y808c29v9p1mai9bq355q7amy0icy46j", 71 | "type": "tarball", 72 | "url": "https://github.com/i-am-tom/higgledy/archive/476d73a92e3ef6e1dc879555d751f877b0f91de8.tar.gz", 73 | "url_template": "https://github.com///archive/.tar.gz" 74 | }, 75 | "niv": { 76 | "branch": "master", 77 | "description": "Easy dependency management for Nix projects", 78 | "homepage": "https://github.com/nmattia/niv", 79 | "owner": "nmattia", 80 | "repo": "niv", 81 | "rev": "88d6f20882b0422470acbcbf2d1b5f07e1d436f0", 82 | "sha256": "0wkvz4drnglmmdrz8q1i1yr2fqizpf96k1wq2rlhd8l8x1522izq", 83 | "type": "tarball", 84 | "url": "https://github.com/nmattia/niv/archive/88d6f20882b0422470acbcbf2d1b5f07e1d436f0.tar.gz", 85 | "url_template": "https://github.com///archive/.tar.gz" 86 | }, 87 | "nixpkgs": { 88 | "branch": "nixpkgs-unstable", 89 | "description": "Nixpkgs/NixOS branches that track the Nixpkgs/NixOS channels", 90 | "homepage": null, 91 | "owner": "NixOS", 92 | "repo": "nixpkgs-channels", 93 | "rev": "b425012fdf450e7b3397d5a3d28d6091de24546f", 94 | "sha256": "14zg1m59788j37qnylnsad09al9kzcq0mqsfr0pa4zd4r7rfc4ny", 95 | "type": "tarball", 96 | "url": "https://github.com/NixOS/nixpkgs-channels/archive/b425012fdf450e7b3397d5a3d28d6091de24546f.tar.gz", 97 | "url_template": "https://github.com///archive/.tar.gz" 98 | }, 99 | "type-errors": { 100 | "branch": "master", 101 | "description": "tools for writing better type errors ", 102 | "homepage": null, 103 | "owner": "isovector", 104 | "repo": "type-errors", 105 | "rev": "f171628f607d83de18bd96c1d4247674fece6b15", 106 | "sha256": "1pkrns559mh1psp2ic4dybk8x91vcx04xpjx7m7msqx7xypfz2il", 107 | "type": "tarball", 108 | "url": "https://github.com/isovector/type-errors/archive/f171628f607d83de18bd96c1d4247674fece6b15.tar.gz", 109 | "url_template": "https://github.com///archive/.tar.gz" 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /nix/sources.nix: -------------------------------------------------------------------------------- 1 | # This file has been generated by Niv. 2 | 3 | # A record, from name to path, of the third-party packages 4 | with rec 5 | { 6 | pkgs = 7 | if hasNixpkgsPath 8 | then 9 | if hasThisAsNixpkgsPath 10 | then import (builtins_fetchTarball { inherit (sources_nixpkgs) url sha256; }) {} 11 | else import {} 12 | else 13 | import (builtins_fetchTarball { inherit (sources_nixpkgs) url sha256; }) {}; 14 | 15 | sources_nixpkgs = 16 | if builtins.hasAttr "nixpkgs" sources 17 | then sources.nixpkgs 18 | else abort 19 | '' 20 | Please specify either (through -I or NIX_PATH=nixpkgs=...) or 21 | add a package called "nixpkgs" to your sources.json. 22 | ''; 23 | 24 | # fetchTarball version that is compatible between all the versions of Nix 25 | builtins_fetchTarball = 26 | { url, sha256 }@attrs: 27 | let 28 | inherit (builtins) lessThan nixVersion fetchTarball; 29 | in 30 | if lessThan nixVersion "1.12" then 31 | fetchTarball { inherit url; } 32 | else 33 | fetchTarball attrs; 34 | 35 | # fetchurl version that is compatible between all the versions of Nix 36 | builtins_fetchurl = 37 | { url, sha256 }@attrs: 38 | let 39 | inherit (builtins) lessThan nixVersion fetchurl; 40 | in 41 | if lessThan nixVersion "1.12" then 42 | fetchurl { inherit url; } 43 | else 44 | fetchurl attrs; 45 | 46 | # A wrapper around pkgs.fetchzip that has inspectable arguments, 47 | # annoyingly this means we have to specify them 48 | fetchzip = { url, sha256 }@attrs: pkgs.fetchzip attrs; 49 | 50 | # A wrapper around pkgs.fetchurl that has inspectable arguments, 51 | # annoyingly this means we have to specify them 52 | fetchurl = { url, sha256 }@attrs: pkgs.fetchurl attrs; 53 | 54 | hasNixpkgsPath = (builtins.tryEval ).success; 55 | hasThisAsNixpkgsPath = 56 | (builtins.tryEval ).success && == ./.; 57 | 58 | sources = builtins.fromJSON (builtins.readFile ./sources.json); 59 | 60 | mapAttrs = builtins.mapAttrs or 61 | (f: set: with builtins; 62 | listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set))); 63 | 64 | # borrowed from nixpkgs 65 | functionArgs = f: f.__functionArgs or (builtins.functionArgs f); 66 | callFunctionWith = autoArgs: f: args: 67 | let auto = builtins.intersectAttrs (functionArgs f) autoArgs; 68 | in f (auto // args); 69 | 70 | getFetcher = spec: 71 | let fetcherName = 72 | if builtins.hasAttr "type" spec 73 | then builtins.getAttr "type" spec 74 | else "builtin-tarball"; 75 | in builtins.getAttr fetcherName { 76 | "tarball" = fetchzip; 77 | "builtin-tarball" = builtins_fetchTarball; 78 | "file" = fetchurl; 79 | "builtin-url" = builtins_fetchurl; 80 | }; 81 | }; 82 | # NOTE: spec must _not_ have an "outPath" attribute 83 | mapAttrs (_: spec: 84 | if builtins.hasAttr "outPath" spec 85 | then abort 86 | "The values in sources.json should not have an 'outPath' attribute" 87 | else 88 | if builtins.hasAttr "url" spec && builtins.hasAttr "sha256" spec 89 | then 90 | spec // 91 | { outPath = callFunctionWith spec (getFetcher spec) { }; } 92 | else spec 93 | ) sources 94 | -------------------------------------------------------------------------------- /picodma-fpga.cabal: -------------------------------------------------------------------------------- 1 | cabal-version: 2.2 2 | 3 | name: picodma-fpga 4 | version: 0.1.0.0 5 | 6 | -- synopsis: 7 | -- description: 8 | -- bug-reports: 9 | license: MIT 10 | license-file: LICENSE 11 | author: Ben Blaxill 12 | maintainer: ben.blaxill@gmail.com 13 | 14 | -- copyright: 15 | -- category: 16 | build-type: Simple 17 | 18 | library 19 | exposed-modules: 20 | Clash.Minilude 21 | Dma.Prelude 22 | Pcie 23 | 24 | Axi 25 | Blackboxes 26 | Register 27 | Search 28 | SpiSlave 29 | StreamReassembly 30 | Tlp 31 | Top 32 | 33 | build-depends: 34 | , base >=4.11 && <4.13 35 | -- , base-noprelude >=4.11 && <4.13 36 | , clash-lib 37 | , clash-prelude >=1.1.0 38 | , deepseq 39 | , free 40 | , ghc-typelits-extra >=0.3.1 41 | , ghc-typelits-knownnat >=0.7.1 42 | , ghc-typelits-natnormalise 43 | , lens 44 | , mtl 45 | , template-haskell 46 | , data-default-class 47 | -- , protolude 48 | 49 | default-extensions: 50 | NoImplicitPrelude 51 | BinaryLiterals 52 | ConstraintKinds 53 | DataKinds 54 | DeriveAnyClass 55 | DeriveGeneric 56 | DeriveLift 57 | DerivingStrategies 58 | ExplicitForAll 59 | ExplicitNamespaces 60 | FlexibleContexts 61 | FlexibleInstances 62 | KindSignatures 63 | MagicHash 64 | MonoLocalBinds 65 | QuasiQuotes 66 | ScopedTypeVariables 67 | TemplateHaskell 68 | TemplateHaskellQuotes 69 | TypeApplications 70 | TypeFamilies 71 | TypeOperators 72 | 73 | hs-source-dirs: src 74 | default-language: Haskell2010 75 | ghc-options: 76 | -- -Wmissing-local-signatures -fwarn-missing-signatures 77 | -fwarn-name-shadowing 78 | -fwarn-unused-binds -fwarn-unused-imports 79 | -fwarn-unused-matches -fwarn-empty-enumerations 80 | -fwarn-overflowed-literals 81 | 82 | test-suite test 83 | type: exitcode-stdio-1.0 84 | main-is: tests.hs 85 | hs-source-dirs: tests 86 | other-modules: Test.Test, Test.DmaCore 87 | build-depends: 88 | , base >=4.11 && <4.13 89 | , picodma-fpga 90 | , clash-prelude >=1.1.0 91 | , deepseq 92 | , free 93 | , ghc-typelits-extra 94 | , ghc-typelits-knownnat 95 | , ghc-typelits-natnormalise 96 | , interpolate 97 | , lens 98 | , mtl 99 | , recursion-schemes 100 | , tasty ^>=1.2 101 | , tasty-hunit 102 | , transformers 103 | , text 104 | 105 | default-extensions: 106 | NoImplicitPrelude 107 | BinaryLiterals 108 | ConstraintKinds 109 | DataKinds 110 | DeriveAnyClass 111 | DeriveGeneric 112 | DeriveLift 113 | DerivingStrategies 114 | ExplicitForAll 115 | ExplicitNamespaces 116 | FlexibleContexts 117 | FlexibleInstances 118 | KindSignatures 119 | MagicHash 120 | MonoLocalBinds 121 | QuasiQuotes 122 | ScopedTypeVariables 123 | TemplateHaskell 124 | TemplateHaskellQuotes 125 | TypeApplications 126 | TypeFamilies 127 | TypeOperators 128 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | #### Prerequisites 2 | 3 | 4 | 1. Install Vivado 2019.2 5 | 1. Install the Nix package manager . It's not required to build, but handles non-Xilinx dependencies and is the only supported method. 6 | 1. For programming/flashing FPGA, make sure 7 | [xvcd](https://github.com/RHSResearchLLC/xvcd) is running on port 2542. 8 | 9 | #### Flashing `picodma.bit` to FPGA flash memory 10 | 11 | 1. Run `nix-shell --command './Shakefile.hs flashFpga'` 12 | 2. Requires FPGA to be power cycled to load design, or: 13 | 14 | #### Reprogramming running FPGA with `picodma.bit` 15 | 16 | 1. Run `nix-shell --command './Shakefile.hs programFpga'` 17 | 2. Doesn't require FPGA to be flashed first 18 | 19 | #### Building `picodma.bit` without programming/flashing FPGA 20 | 21 | 1. Run `nix-shell --command './Shakefile.hs vivado'` 22 | 23 | SPI op codes (defined in src/Top.hs) 24 | === 25 | 26 | r/w | byte code | description 27 | --- | --- | --- 28 | rw | 0 | address low 29 | rw | 1 | address high 30 | rw | 2 | PCIe write trigger 31 | rw | 3 | search length, num 32bit chunks 32 | rw | 4 | value low 33 | rw | 5 | value high 34 | rw | 6 | buffer select 35 | r | 7 | buffer value 36 | r | 8 | buffer offset 37 | r | 9 | PCIe read busy 38 | w | 10 | PCIe read trigger 39 | r | 11 | PCIe read status 40 | r | 12 | PCIe read stat length = number of 64bit chunks 41 | r | 13 | debug index 42 | r | 14 | PCIe search busy 43 | w | 15 | PCIe search trigger 44 | r | 16 | PCIe search done 45 | r | 17 | PCIe search length = number of 64bit addresses 46 | rw | 18 | search type, 0=none,1=16bit,2=32bit 47 | rw | 19 | search value 48 | r | 20 | debug requester 49 | r | 21 | debug pci tx buffers count 50 | r | 22 | debug transaction writer ready 51 | r | 23 | debug transaction error drop 52 | r | 24 | debug transaction sent count 53 | r | 25 | debug tx has been ready since last message 54 | r | 26 | debug read trigger count 55 | r | 27 | debug search trigger count 56 | r | 28 | debug transaction received count 57 | 58 | ### PicoEVB pins for reference 59 | 60 | ~~~ 61 | # Auxillary I/O Connector 62 | # auxio[0] - conn pin 1 63 | # auxio[1] - conn pin 2 64 | # auxio[2] - conn pin 4 65 | # auxio[3] - conn pin 5 66 | set_property PACKAGE_PIN A14 [get_ports auxio_tri_io[0]] 67 | set_property PACKAGE_PIN A13 [get_ports auxio_tri_io[1]] 68 | set_property PACKAGE_PIN B12 [get_ports auxio_tri_io[2]] 69 | set_property PACKAGE_PIN A12 [get_ports auxio_tri_io[3]] 70 | 71 | set_property PACKAGE_PIN A14 [get_ports sel] 72 | set_property PACKAGE_PIN A13 [get_ports mosi] 73 | set_property PACKAGE_PIN B12 [get_ports miso] 74 | set_property PACKAGE_PIN A12 [get_ports sclk] 75 | set_property IOSTANDARD LVCMOS33 [get_ports sel] 76 | set_property IOSTANDARD LVCMOS33 [get_ports mosi] 77 | set_property IOSTANDARD LVCMOS33 [get_ports miso] 78 | set_property IOSTANDARD LVCMOS33 [get_ports sclk] 79 | ~~~ 80 | -------------------------------------------------------------------------------- /shell.nix: -------------------------------------------------------------------------------- 1 | let sources = import ./nix/sources.nix; 2 | pkgs = import ./nix/default.nix { inherit sources; }; 3 | haskellPackages = pkgs.haskell.packages.ghc865; 4 | 5 | in haskellPackages.developPackage { 6 | root = pkgs.nix-gitignore.gitignoreSource [] ./.; 7 | name = "picodma-fpga"; 8 | 9 | overrides = (self: super: 10 | { ghc = super.ghc // { withPackages = super.ghc.withHoogle; }; 11 | ghcWithPackages = self.ghc.withPackages; 12 | }); 13 | 14 | modifier = drv: pkgs.haskell.lib.overrideCabal drv (attrs: { 15 | buildTools = (attrs.buildTools or []) 16 | ++ [ 17 | pkgs.niv 18 | pkgs.yosys 19 | ] 20 | ++ (with haskellPackages; [ 21 | cabal-install 22 | clash-ghc 23 | clash-lib 24 | clash-ghc 25 | 26 | shake 27 | interpolate 28 | bytestring 29 | regex-tdfa 30 | influxdb 31 | ]); 32 | }); 33 | 34 | returnShellEnv = true; 35 | } 36 | -------------------------------------------------------------------------------- /src/Axi.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.Normalise #-} 2 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-} 3 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.Extra.Solver #-} 4 | 5 | {-# LANGUAGE ApplicativeDo #-} 6 | {-# LANGUAGE BinaryLiterals #-} 7 | {-# LANGUAGE BlockArguments #-} 8 | {-# LANGUAGE ConstraintKinds #-} 9 | {-# LANGUAGE DataKinds #-} 10 | {-# LANGUAGE DeriveAnyClass #-} 11 | {-# LANGUAGE DeriveFunctor #-} 12 | {-# LANGUAGE DeriveGeneric #-} 13 | {-# LANGUAGE DeriveLift #-} 14 | {-# LANGUAGE DerivingStrategies #-} 15 | {-# LANGUAGE FlexibleContexts #-} 16 | {-# LANGUAGE FlexibleInstances #-} 17 | {-# LANGUAGE GADTs #-} 18 | {-# LANGUAGE LambdaCase #-} 19 | {-# LANGUAGE MagicHash #-} 20 | {-# LANGUAGE NoImplicitPrelude #-} 21 | {-# LANGUAGE NoStarIsType #-} 22 | {-# LANGUAGE NumericUnderscores #-} 23 | {-# LANGUAGE QuasiQuotes #-} 24 | {-# LANGUAGE RankNTypes #-} 25 | {-# LANGUAGE RecordWildCards #-} 26 | {-# LANGUAGE ScopedTypeVariables #-} 27 | {-# LANGUAGE StandaloneDeriving #-} 28 | {-# LANGUAGE TemplateHaskell #-} 29 | {-# LANGUAGE TemplateHaskellQuotes #-} 30 | {-# LANGUAGE TypeApplications #-} 31 | {-# LANGUAGE TypeFamilies #-} 32 | {-# LANGUAGE TypeOperators #-} 33 | 34 | module Axi where 35 | 36 | import Dma.Prelude 37 | 38 | data AxiSimpleStream n m 39 | = AxiSimpleStream 40 | { _axis_valid :: "tvalid" ::: Bool 41 | , _axis_data :: "tdata" ::: BitVector (8*n) 42 | , _axis_last :: "tlast" ::: Bool 43 | , _axis_keep :: "tkeep" ::: BitVector n 44 | , _axis_user :: "tuser" ::: BitVector m 45 | } deriving (Generic, NFDataX, ShowX, Eq) 46 | 47 | makeLenses ''AxiSimpleStream 48 | 49 | instance (KnownNat n, KnownNat m) => Default (AxiSimpleStream n m) where 50 | def = AxiSimpleStream False 0 False 0 0 51 | 52 | mkAxisWrite :: (KnownNat n, KnownNat m) => BitVector (8*n) -> AxiSimpleStream n m 53 | mkAxisWrite data_ = def 54 | & axis_valid .~ True 55 | & axis_keep .~ complement 0 56 | & axis_data .~ data_ 57 | 58 | realignAxis 59 | :: (HiddenClockResetEnable domain) 60 | => Unbundled domain (Bool, AxiSimpleStream 8 m) 61 | -> Signal domain (Stream () (Maybe U64)) 62 | realignAxis (flush,stream) = realignWords $ mkStream <$> flush <*> stream 63 | where 64 | mkStream True _ = Done () 65 | mkStream False a | not (_axis_valid a) = Item Zero 66 | mkStream False a = Item 67 | $ uncurry (case _axis_keep a of 68 | 0xFF -> Two 69 | 0xF -> const One 70 | ) $ split $ _axis_data a 71 | 72 | -------------------------------------------------------------------------------- /src/Blackboxes.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.Normalise #-} 2 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-} 3 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.Extra.Solver #-} 4 | 5 | {-# OPTIONS_GHC -Wno-partial-type-signatures #-} 6 | 7 | {-# LANGUAGE BangPatterns #-} 8 | {-# LANGUAGE BinaryLiterals #-} 9 | {-# LANGUAGE ConstraintKinds #-} 10 | {-# LANGUAGE DataKinds #-} 11 | {-# LANGUAGE DeriveGeneric #-} 12 | {-# LANGUAGE FlexibleContexts #-} 13 | {-# LANGUAGE FlexibleInstances #-} 14 | {-# LANGUAGE GADTs #-} 15 | {-# LANGUAGE KindSignatures #-} 16 | {-# LANGUAGE LambdaCase #-} 17 | {-# LANGUAGE MagicHash #-} 18 | {-# LANGUAGE NoImplicitPrelude #-} 19 | {-# LANGUAGE NoStarIsType #-} 20 | {-# LANGUAGE NumericUnderscores #-} 21 | {-# LANGUAGE ScopedTypeVariables #-} 22 | {-# LANGUAGE TemplateHaskell #-} 23 | {-# LANGUAGE TypeApplications #-} 24 | 25 | module Blackboxes where 26 | 27 | import Clash.Primitives.Scaffold 28 | 29 | makeScaffold "xilinxDiff" "IBUFDS_GTE2" [] 30 | [ [ ClkOut "O" 31 | , ClkIn "I" 32 | , ClkIn "IB" 33 | ] 34 | ] 35 | 36 | makeScaffold "xilinxPcie" "pcie_7xi" [] 37 | 38 | [ [ ClkIn "sys_clk" 39 | , In "sys_rst_n" 1 40 | , In "pci_exp_rxp" 1 41 | , In "pci_exp_rxn" 1 42 | 43 | , Out "pci_exp_txp" 1 44 | , Out "pci_exp_txn" 1 45 | ] 46 | 47 | , [ In "s_axis_tx_tdata" 64 48 | , In "s_axis_tx_tkeep" 8 49 | , In "s_axis_tx_tlast" 1 50 | , In "s_axis_tx_tuser" 4 51 | , In "s_axis_tx_tvalid" 1 52 | , In "m_axis_rx_tready" 1 53 | , In "cfg_mgmt_dwaddr" 10 54 | , In "cfg_mgmt_byte_en" 4 55 | , In "cfg_mgmt_rd_en" 1 56 | , In "cfg_mgmt_wr_readonly" 1 57 | , In "cfg_mgmt_wr_rw1c_as_rw" 1 58 | , In "cfg_mgmt_di" 32 59 | , In "cfg_mgmt_wr_en" 1 60 | , In "cfg_dsn" 64 61 | , In "cfg_pm_force_state" 2 62 | , In "cfg_pm_force_state_en" 1 63 | , In "cfg_pm_halt_aspm_l0s" 1 64 | , In "cfg_pm_halt_aspm_l1" 1 65 | , In "cfg_pm_send_pme_to" 1 66 | , In "cfg_pm_wake" 1 67 | , In "rx_np_ok" 1 68 | , In "rx_np_req" 1 69 | , In "cfg_trn_pending" 1 70 | , In "cfg_turnoff_ok" 1 71 | , In "tx_cfg_gnt" 1 72 | 73 | , In "cfg_interrupt_assert" 1 74 | , In "cfg_interrupt" 1 75 | , In "cfg_interrupt_stat" 1 76 | , In "cfg_interrupt_di" 8 77 | , In "cfg_pciecap_interrupt_msgnum" 5 78 | 79 | , Out "s_axis_tx_tready" 1 80 | , Out "m_axis_rx_tdata" 64 81 | , Out "m_axis_rx_tkeep" 8 82 | , Out "m_axis_rx_tlast" 1 83 | , Out "m_axis_rx_tuser" 22 84 | , Out "m_axis_rx_tvalid" 1 85 | , Out "cfg_mgmt_do" 32 86 | , Out "cfg_mgmt_rd_wr_done" 1 87 | , Out "cfg_command" 16 88 | , Out "cfg_bus_number" 8 89 | , Out "cfg_device_number" 5 90 | , Out "cfg_function_number" 3 91 | , Out "cfg_bridge_serr_en" 1 92 | , Out "cfg_dcommand" 16 93 | , Out "cfg_dcommand2" 16 94 | , Out "cfg_dstatus" 16 95 | , Out "cfg_lcommand" 16 96 | , Out "cfg_lstatus" 16 97 | , Out "cfg_pcie_link_state" 3 98 | , Out "cfg_pmcsr_pme_en" 1 99 | , Out "cfg_pmcsr_pme_status" 1 100 | , Out "cfg_pmcsr_powerstate" 2 101 | , Out "cfg_received_func_lvl_rst" 1 102 | , Out "cfg_slot_control_electromech_il_ctl_pulse" 1 103 | , Out "cfg_status" 16 104 | , Out "cfg_to_turnoff" 1 105 | , Out "tx_buf_av" 6 106 | , Out "tx_cfg_req" 1 107 | , Out "tx_err_drop" 1 108 | , Out "cfg_vc_tcvc_map" 7 109 | 110 | , ClkOut "user_clk_out" 111 | 112 | , Out "user_reset_out" 1 113 | , Out "user_lnk_up" 1 114 | , Out "user_app_rdy" 1 115 | ] 116 | ] 117 | -------------------------------------------------------------------------------- /src/Clash/Minilude.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.Normalise #-} 2 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-} 3 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.Extra.Solver #-} 4 | 5 | {-# LANGUAGE ApplicativeDo #-} 6 | {-# LANGUAGE BinaryLiterals #-} 7 | {-# LANGUAGE BlockArguments #-} 8 | {-# LANGUAGE ConstraintKinds #-} 9 | {-# LANGUAGE DataKinds #-} 10 | {-# LANGUAGE DerivingStrategies #-} 11 | {-# LANGUAGE FlexibleContexts #-} 12 | {-# LANGUAGE FlexibleInstances #-} 13 | {-# LANGUAGE GADTs #-} 14 | {-# LANGUAGE NoImplicitPrelude #-} 15 | {-# LANGUAGE NoStarIsType #-} 16 | {-# LANGUAGE NumericUnderscores #-} 17 | {-# LANGUAGE RankNTypes #-} 18 | {-# LANGUAGE ScopedTypeVariables #-} 19 | {-# LANGUAGE TemplateHaskellQuotes #-} 20 | {-# LANGUAGE TypeFamilies #-} 21 | {-# LANGUAGE TypeOperators #-} 22 | 23 | module Clash.Minilude 24 | ( -- * Creating synchronous sequential circuits 25 | mealy 26 | , mealyB 27 | , mealyState 28 | , mealyStateB 29 | , (<^>) 30 | , registerB 31 | , module Clash.Signal 32 | , module Clash.Signal.Delayed 33 | -- ** Datatypes 34 | -- *** Bit vectors 35 | , module Clash.Sized.BitVector 36 | , module Clash.Prelude.BitIndex 37 | , module Clash.Prelude.BitReduction 38 | -- *** Arbitrary-width numbers 39 | , module Clash.Sized.Signed 40 | , module Clash.Sized.Unsigned 41 | , module Clash.Sized.Index 42 | -- *** Fixed size vectors 43 | , module Clash.Sized.Vector 44 | -- ** Type-level natural numbers 45 | , module GHC.TypeLits 46 | , module GHC.TypeLits.Extra 47 | , module Clash.Promoted.Nat 48 | , module Clash.Promoted.Nat.Literals 49 | , module Clash.Promoted.Nat.TH 50 | -- ** Type-level strings 51 | , module Clash.Promoted.Symbol 52 | -- ** Type classes 53 | -- *** Clash 54 | -- , module Clash.Class.AutoReg 55 | , autoReg, deriveAutoReg 56 | , module Clash.Class.BitPack 57 | , module Clash.Class.Exp 58 | , module Clash.Class.Num 59 | , module Clash.Class.Resize 60 | -- ** Exceptions 61 | , module Clash.XException 62 | -- ** Named types 63 | , module Clash.NamedTypes 64 | , undefined 65 | ) 66 | where 67 | 68 | import Clash.Class.BitPack 69 | import Clash.Class.Exp 70 | import Clash.Class.Num 71 | import Clash.Class.Resize 72 | import Clash.NamedTypes 73 | import Clash.Prelude.BitIndex 74 | import Clash.Prelude.BitReduction 75 | import Clash.Prelude.Safe 76 | import Clash.Promoted.Nat 77 | import Clash.Promoted.Nat.TH 78 | import Clash.Promoted.Nat.Literals 79 | import Clash.Promoted.Symbol 80 | import Clash.Sized.BitVector 81 | import Clash.Sized.Index 82 | import Clash.Sized.Signed 83 | import Clash.Sized.Unsigned 84 | import Clash.Sized.Vector 85 | import Clash.Signal 86 | import Clash.Signal.Delayed 87 | import Clash.XException 88 | 89 | import Clash.Prelude 90 | import GHC.TypeLits 91 | import GHC.TypeLits.Extra 92 | 93 | import Control.Monad.State 94 | import Data.Tuple ( swap ) 95 | 96 | mealyState 97 | :: (HiddenClockResetEnable domain, NFDataX s) 98 | => (i -> State s o) 99 | -> s 100 | -> (Signal domain i -> Signal domain o) 101 | mealyState f = mealy step 102 | where 103 | step s x = swap $ runState (f x) s 104 | 105 | mealyStateB 106 | :: (HiddenClockResetEnable domain, NFDataX s, Bundle i, Bundle o) 107 | => (i -> State s o) 108 | -> s 109 | -> Unbundled domain i 110 | -> Unbundled domain o 111 | mealyStateB f initial = step <^> initial 112 | where 113 | step s x = swap $ runState (f x) s 114 | 115 | -------------------------------------------------------------------------------- /src/Dma/Prelude.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.Normalise #-} 2 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-} 3 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.Extra.Solver #-} 4 | 5 | {-# LANGUAGE ApplicativeDo #-} 6 | {-# LANGUAGE BinaryLiterals #-} 7 | {-# LANGUAGE BlockArguments #-} 8 | {-# LANGUAGE ConstraintKinds #-} 9 | {-# LANGUAGE DataKinds #-} 10 | {-# LANGUAGE DeriveAnyClass #-} 11 | {-# LANGUAGE DeriveFunctor #-} 12 | {-# LANGUAGE DeriveGeneric #-} 13 | {-# LANGUAGE DerivingStrategies #-} 14 | {-# LANGUAGE FlexibleContexts #-} 15 | {-# LANGUAGE FlexibleInstances #-} 16 | {-# LANGUAGE GADTs #-} 17 | {-# LANGUAGE NoImplicitPrelude #-} 18 | {-# LANGUAGE NoStarIsType #-} 19 | {-# LANGUAGE NumericUnderscores #-} 20 | {-# LANGUAGE RankNTypes #-} 21 | {-# LANGUAGE ScopedTypeVariables #-} 22 | {-# LANGUAGE TemplateHaskellQuotes #-} 23 | {-# LANGUAGE TypeApplications #-} 24 | {-# LANGUAGE TypeFamilies #-} 25 | {-# LANGUAGE TypeOperators #-} 26 | 27 | module Dma.Prelude 28 | ( 29 | module Clash.Minilude 30 | , module Control.Applicative 31 | , module Data.Bifunctor 32 | , module Data.Maybe 33 | , module Data.Bits 34 | , module Control.Lens 35 | , module Clash.Prelude 36 | 37 | , module Control.Monad.State 38 | 39 | , U8, U16, U32 ,U64 40 | , Diff 41 | , (<$$>) 42 | , (.++#.) 43 | , (#<<+) 44 | , ite 45 | , bool 46 | , toMaybe 47 | , unpackMaybe 48 | , reduce 49 | , DoublePort(..) 50 | , portCount 51 | , Stream (..) 52 | , unstream 53 | , undone 54 | , streamCount 55 | , realignWordsT 56 | , realignWords 57 | 58 | -- , String, Show (show) 59 | ) 60 | where 61 | 62 | import Prelude 63 | import Clash.Minilude 64 | import Clash.Prelude hiding (String, Show, read) 65 | 66 | import Control.Applicative 67 | import Data.Bifunctor 68 | import Control.Monad.State hiding (lift) 69 | import Data.Bits 70 | import Data.Maybe 71 | import Control.Lens ( makeLenses 72 | , makePrisms 73 | , (^.) 74 | , (^?) 75 | , (^?!) 76 | , (.~) 77 | , (%~) 78 | , (.=) 79 | , (+=) 80 | , (%=) 81 | , _1, _2, _3, _4 82 | , _Just 83 | , (&) 84 | , (<&>) 85 | , ix 86 | , mapped 87 | , use, uses 88 | , zoom 89 | , view 90 | ) 91 | 92 | import Clash.Sized.Internal.Index ( fromSNat ) 93 | 94 | type U8 = BitVector 8 95 | type U16 = BitVector 16 96 | type U32 = BitVector 32 97 | type U64 = BitVector 64 98 | 99 | type Diff a = ("p" ::: a, "n" ::: a) 100 | 101 | infixl 4 <$$> 102 | 103 | (<$$>) :: (Functor f, Functor g) => (a -> b) -> f (g a) -> f (g b) 104 | (<$$>) = fmap . fmap 105 | 106 | (.++#.) 107 | :: (KnownNat n, KnownNat m, Applicative f) 108 | => f (BitVector n) 109 | -> f (BitVector m) 110 | -> f (BitVector (n+m)) 111 | (.++#.) = liftA2 (++#) 112 | 113 | ite i t e = if i then t else e 114 | bool f t x = ite x t f 115 | 116 | toMaybe :: Bool -> a -> Maybe a 117 | toMaybe False _ = Nothing 118 | toMaybe True x = Just x 119 | 120 | unpackMaybe :: (NFDataX a) => Maybe a -> (Bool, a) 121 | unpackMaybe (Just a) = (True, a) 122 | unpackMaybe _ = (False, deepErrorX "NFDataX unpackMaybe!") 123 | 124 | infixl 4 #<<+ 125 | (#<<+) :: (KnownNat n) => BitVector n -> Bit -> BitVector n 126 | xs #<<+ b = v2bv . flip (<<+) b $ bv2v xs 127 | {-# INLINE (#<<+) #-} 128 | 129 | reduce 130 | :: forall n m i. (KnownNat n, KnownNat m) 131 | => BitVector (n+m+1) -> BitVector (n+1) 132 | reduce v = 133 | let lo = slice (SNat @n) d0 v :: BitVector (n+1) 134 | hi = slice (SNat @(m+n)) (SNat @(n+1)) v :: BitVector m 135 | in if reduceOr hi == high then maxBound else lo 136 | 137 | data DoublePort a 138 | = Zero 139 | | One a 140 | | Two a a 141 | deriving (Eq, Generic, ShowX, NFDataX) 142 | 143 | portCount :: Num b => DoublePort a -> b 144 | portCount Zero = 0 145 | portCount One{} = 1 146 | portCount Two{} = 2 147 | 148 | data Stream r a 149 | = Done r 150 | | Item a 151 | deriving (Eq, Functor, Generic, ShowX, NFDataX) 152 | 153 | unstream :: b -> (a -> b) -> Stream r a -> b 154 | unstream b _ (Done _) = b 155 | unstream _ f (Item a) = f a 156 | 157 | undone :: b -> (a -> b) -> Stream a x -> b 158 | undone _ f (Done r) = f r 159 | undone b _ (Item _) = b 160 | 161 | streamCount :: (Num a) => a -> Stream r (Maybe b) -> a 162 | streamCount v = maybe v (const $ v + 1) . unstream Nothing id 163 | 164 | realignWordsT 165 | :: Maybe U32 166 | -> Stream r (DoublePort U32) 167 | -> (Maybe U32, Stream r (Maybe U64)) 168 | 169 | realignWordsT Nothing (Done r) = (Nothing, Done r) 170 | realignWordsT a (Done _) = (Nothing, Item $ fmap resize a) 171 | realignWordsT (Just a) (Item (Two b c)) = (Just c, Item $ Just $ b ++# a) 172 | realignWordsT Nothing (Item (Two b c)) = (Nothing, Item $ Just $ c ++# b) 173 | realignWordsT (Just a) (Item (One b )) = (Nothing, Item $ Just $ b ++# a) 174 | realignWordsT Nothing (Item (One b )) = (Just b, Item Nothing) 175 | realignWordsT a (Item Zero ) = (a, Item Nothing) 176 | 177 | realignWords 178 | :: (HiddenClockResetEnable domain) 179 | => Signal domain (Stream r (DoublePort U32)) 180 | -> Signal domain (Stream r (Maybe U64)) 181 | realignWords = mealy realignWordsT def 182 | -------------------------------------------------------------------------------- /src/Pcie.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.Normalise #-} 2 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-} 3 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.Extra.Solver #-} 4 | 5 | {-# LANGUAGE DeriveFunctor #-} 6 | {-# LANGUAGE TypeApplications #-} 7 | 8 | module Pcie where 9 | 10 | import Dma.Prelude 11 | 12 | newtype Address (alignment :: Nat) 13 | = Address (BitVector (64 - alignment)) 14 | 15 | data Addressable (alignment :: Nat) a 16 | = Addressable (Address alignment) a 17 | deriving Functor 18 | 19 | address 20 | :: forall align1 align2 . 21 | ( KnownNat align1 22 | , KnownNat align2 23 | , align1 <= 64 24 | ) 25 | => Address align1 26 | -> Address align2 27 | address (Address a) = Address $ slice d63 (SNat @align2) full 28 | where 29 | full = a ++# 0 :: BitVector 64 30 | 31 | -- addressable :: f (Addressable a) -> Addressable (f a) 32 | 33 | -------------------------------------------------------------------------------- /src/Probe.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.Normalise #-} 2 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-} 3 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.Extra.Solver #-} 4 | 5 | {-# LANGUAGE TypeApplications #-} 6 | {-# LANGUAGE ApplicativeDo #-} 7 | {-# LANGUAGE BlockArguments #-} 8 | {-# LANGUAGE GADTs #-} 9 | {-# LANGUAGE LambdaCase #-} 10 | {-# LANGUAGE NoStarIsType #-} 11 | {-# LANGUAGE NumericUnderscores #-} 12 | {-# LANGUAGE RankNTypes #-} 13 | {-# LANGUAGE RecordWildCards #-} 14 | {-# LANGUAGE TupleSections #-} 15 | {-# LANGUAGE ViewPatterns #-} 16 | 17 | module Probe 18 | ( 19 | ) 20 | where 21 | 22 | import Prelude 23 | import Data.Default.Class 24 | import Control.Lens ( view 25 | , _3 26 | ) 27 | 28 | import Tlp 29 | 30 | 31 | -- (Addr, stride) 32 | type ProbeRequest = (BitVector 64, BitVector 40) 33 | 34 | -- type Failed = Bool 35 | 36 | -- data ReassemblyState 37 | -- = ReassemblyState 38 | -- { _address :: BitVector 62 39 | -- , _remaining :: BitVector 28 40 | -- , _timer :: BitVector 20 41 | -- , _bufferedTx :: Maybe Tx 42 | -- , _failed :: Bool 43 | -- } deriving (Eq, ShowX, Generic, NFDataX) 44 | 45 | -- instance Default ReassemblyState where 46 | -- def = ReassemblyState 0 0 0 Nothing False 47 | 48 | -- reassemblyState (addr, len) tx = ReassemblyState addr len 0 tx False 49 | -- done (_, len) = len == 0 50 | 51 | -- nextRequest :: ReassemblyState -> BitVector 2 -> StreamRequest 52 | -- nextRequest (ReassemblyState addr rem _ _ _) l = 53 | -- ( truncateB $ add addr l 54 | -- , truncateB $ sub rem l ) 55 | 56 | -- mkTlp tag (addr,len) = ReadTx (addr ++# 0) (nextLength addr len) tag 57 | 58 | -- nextLength :: BitVector 62 -> BitVector 28 -> BitVector 10 59 | -- nextLength addr l = 60 | -- let loaddr = resize addr :: BitVector 10 61 | -- pageBound = 1 + complement loaddr 62 | -- in if loaddr == 0 63 | -- then reduce l 64 | -- else minimum (reduce l :> pageBound :> Nil) 65 | 66 | -- filterTagT 67 | -- :: Tag 68 | -- -> ReassemblyState 69 | -- -> (Maybe (TlpHeader, DoublePort U32), Maybe StreamRequest, Bool) 70 | -- -> (ReassemblyState, (Stream Failed (DoublePort U32), Maybe Tx)) 71 | 72 | -- -- Start a new transaction 73 | -- filterTagT tag _ (_, Just r, _) = 74 | -- let tx = mkTlp tag r 75 | -- in ( reassemblyState r (Just tx) 76 | -- , (Item Zero, Nothing) 77 | -- ) 78 | 79 | -- filterTagT _ s@(_remaining -> r) _ | r == 0 = (s, (Done False, Nothing)) 80 | -- filterTagT _ s@(_failed -> f) _ | f = (s, (Done True, Nothing)) 81 | -- filterTagT _ (_timer -> t) _ | t == 500_000 = (def { _failed = True }, (Done True, Nothing)) 82 | 83 | -- -- Relevant packet received 84 | -- filterTagT tag s (Just t, _, _) 85 | -- | t ^. _1 . tlpTag == tag && not (_failed s) 86 | -- = let sanity 87 | -- | t ^. _1 . tlpHeaderPulse 88 | -- = slice d4 d0 (_address s) == slice d6 d2 (t ^. _1 . tlpLowerAddress) 89 | -- | otherwise = True 90 | 91 | -- r = nextRequest s (portCount $ t ^. _2) 92 | 93 | -- tx 94 | -- | done r = Nothing 95 | -- | t ^. _1 . tlpBytesRemaining == 0 = Just (mkTlp tag r) 96 | -- | otherwise = Nothing 97 | 98 | -- in if sanity 99 | -- then (reassemblyState r tx, (Item $ t ^. _2, Nothing)) 100 | -- else (def {_failed = True}, (Done True, Nothing)) 101 | 102 | -- filterTagT _ (ReassemblyState addr len t tx False) (view _3 -> txReady) = 103 | -- ( ReassemblyState addr len (t + 1) (tx <* guard (not txReady)) False 104 | -- , (Item Zero, tx) 105 | -- ) 106 | 107 | -- filterTag 108 | -- :: HiddenClockResetEnable domain 109 | -- => Tag 110 | -- -> Unbundled domain (Maybe (TlpHeader, DoublePort U32), Maybe StreamRequest, Bool) 111 | -- -> Unbundled domain (Stream Failed (DoublePort U32), Maybe Tx) 112 | -- filterTag tag = filterTagT tag <^> def 113 | -------------------------------------------------------------------------------- /src/Register.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.Normalise #-} 2 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-} 3 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.Extra.Solver #-} 4 | 5 | {-# LANGUAGE DeriveFunctor #-} 6 | {-# LANGUAGE GADTs #-} 7 | {-# LANGUAGE LambdaCase #-} 8 | {-# LANGUAGE NoStarIsType #-} 9 | {-# LANGUAGE NumericUnderscores #-} 10 | {-# LANGUAGE RankNTypes #-} 11 | {-# LANGUAGE StandaloneDeriving #-} 12 | {-# LANGUAGE TupleSections #-} 13 | {-# LANGUAGE ViewPatterns #-} 14 | 15 | module Register 16 | ( 17 | RegisterHandler 18 | , RegisterHandler' 19 | , deviceRegisters 20 | , Permission(..) 21 | , PermissionMap 22 | , RegisterSlot(..) 23 | ) where 24 | 25 | import Dma.Prelude 26 | 27 | data Permission 28 | = Permission 29 | { canWrite :: Bool 30 | , canRead :: Bool 31 | } deriving (Generic, ShowX, NFDataX) 32 | 33 | instance Default Permission where 34 | def = Permission False False 35 | 36 | type PermissionMap n = Vec n Permission 37 | 38 | checkWriteRead :: MonadPlus m => Bool -> Permission -> m () 39 | checkWriteRead True (Permission True _ ) = return () 40 | checkWriteRead False (Permission _ True) = return () 41 | checkWriteRead _ (Permission _ _ ) = mzero 42 | 43 | data RegisterSlot n a 44 | = RegisterSlot (Index n) a 45 | deriving (Functor, Generic, NFDataX, ShowX) 46 | 47 | byteToRegisterSlot 48 | :: forall n a 49 | . (KnownNat n, n <= 127, 1 <= n) 50 | => PermissionMap n 51 | -> U8 52 | -> (Bool -> a) 53 | -> Maybe (RegisterSlot n a) 54 | byteToRegisterSlot perms b f = 55 | let isWrite = bitToBool (msb b) 56 | check = checkWriteRead isWrite 57 | idx = unpack (resize $ slice d6 d0 b) 58 | in RegisterSlot idx (f isWrite) <$ (perms ^? ix idx >>= check) 59 | 60 | type Indexer = Index (2^16) 61 | data Stage = InitRead | InitWrite | Read Indexer | Write Indexer U8 62 | deriving (Generic, NFDataX, ShowX) 63 | 64 | makePrisms ''Stage 65 | 66 | type Decoded n = Maybe (RegisterSlot n (Indexer, Maybe U8)) 67 | type XS n = Maybe (RegisterSlot n Stage) 68 | 69 | toDecoded :: XS n -> Decoded n 70 | toDecoded Nothing = Nothing 71 | toDecoded (Just (RegisterSlot n InitRead)) = Just (RegisterSlot n (0, Nothing)) 72 | toDecoded (Just (RegisterSlot _ InitWrite)) = Nothing 73 | toDecoded (Just (RegisterSlot n (Read i))) = Just (RegisterSlot n (i, Nothing)) 74 | toDecoded (Just (RegisterSlot n (Write i w))) = Just (RegisterSlot n (i, Just w)) 75 | 76 | decoderT 77 | :: forall n 78 | . (KnownNat n, n <= 127, 1 <= n) 79 | => PermissionMap n 80 | -> XS n 81 | -> (Bool, Maybe U8) 82 | -> (XS n, Decoded n) 83 | decoderT _ _ (False, _ ) = (def, def) 84 | decoderT _ s (True , Nothing) = (s, toDecoded s) 85 | 86 | decoderT m Nothing (True, Just b) = (byteToRegisterSlot m b build, def) 87 | where 88 | build :: Bool -> Stage 89 | build True = InitWrite 90 | build False = InitRead 91 | 92 | decoderT _ (Just c) (True, Just b) = 93 | ( Just 94 | $ c 95 | & mapped . _Read %~ satAdd SatBound 1 96 | & mapped . _Write %~ (\(i,_) -> (satAdd SatBound 1 i, b)) 97 | & mapped %~ \case 98 | InitRead -> Read 1 99 | InitWrite -> Write 0 b 100 | x -> x 101 | , toDecoded $ Just c) 102 | 103 | decoder 104 | :: forall domain n 105 | . (HiddenClockResetEnable domain, KnownNat n, n <= 127, 1 <= n) 106 | => PermissionMap n 107 | -> Signal domain (Bool, Maybe U8) 108 | -> Signal domain (Decoded n) 109 | decoder m = mealy (decoderT m) def 110 | 111 | readDeviceRegistersT 112 | :: forall n 113 | . ( KnownNat n) 114 | => Decoded n 115 | -> Vec n U32 116 | -> U8 117 | readDeviceRegistersT Nothing _ = 0 118 | readDeviceRegistersT (Just (RegisterSlot i (idx, _))) vs = 119 | let el = vs ^?! ix i 120 | lo = slice d1 d0 (pack idx :: BitVector 16) 121 | in flip (!!) lo . reverse . bitCoerce @_ @(Vec 4 U8) $ el 122 | 123 | writeDeviceRegistersT 124 | :: forall n i i1 125 | . ( KnownNat n) 126 | => Decoded n 127 | -> Vec n U32 128 | -> Vec n U32 129 | writeDeviceRegistersT Nothing = id 130 | writeDeviceRegistersT (Just command) = imap (write command) 131 | where 132 | write :: RegisterSlot n (Indexer, Maybe U8) -> Index n -> U32 -> U32 133 | write (RegisterSlot i (idx, Just x)) j y | i==j = 134 | let lo = slice d1 d0 (pack idx :: BitVector 16) 135 | in bitCoerceMap @(Vec 4 U8) (reverse . replace' lo x . reverse) y 136 | write _ _ x = x 137 | 138 | replace' :: BitVector 2 -> U8 -> Vec 4 U8 -> Vec 4 U8 139 | replace' 0 x (_:>b:>c:>d:>Nil) = (x:>b:>c:>d:>Nil) 140 | replace' 1 x (a:>_:>c:>d:>Nil) = (a:>x:>c:>d:>Nil) 141 | replace' 2 x (a:>b:>_:>d:>Nil) = (a:>b:>x:>d:>Nil) 142 | replace' 3 x (a:>b:>c:>_:>Nil) = (a:>b:>c:>x:>Nil) 143 | 144 | type RegisterHandler domain n 145 | = Signal domain (Maybe (RegisterSlot n (Indexer))) 146 | -> Signal domain (Vec n U32) 147 | -> Signal domain (Vec n U32) 148 | 149 | type RegisterHandler' n 150 | = Maybe (RegisterSlot n (Indexer)) 151 | -> Vec n U32 152 | -> Vec n U32 153 | 154 | deviceRegisters 155 | :: forall domain n 156 | . ( KnownNat n 157 | , n <= 127, 1 <= n 158 | , HiddenClockResetEnable domain) 159 | => (Signal domain Bool, Signal domain (Maybe U8)) 160 | -> RegisterHandler domain n 161 | -> Vec n Permission 162 | -> (Vec n (Signal domain U32), Signal domain U8) 163 | deviceRegisters spi update permissions = (unbundle registers, read) 164 | where 165 | cmd = decoder permissions $ bundle spi 166 | cmd' = cmd <&> _Just . mapped %~ fst 167 | registers = register (repeat 0) write 168 | read = readDeviceRegistersT <$> cmd <*> registers 169 | write = writeDeviceRegistersT <$> cmd <*> update cmd' registers 170 | -------------------------------------------------------------------------------- /src/Search.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.Normalise #-} 2 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-} 3 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.Extra.Solver #-} 4 | 5 | {-# LANGUAGE TypeApplications #-} 6 | {-# LANGUAGE ViewPatterns #-} 7 | {-# LANGUAGE ApplicativeDo #-} 8 | {-# LANGUAGE BlockArguments #-} 9 | {-# LANGUAGE GADTs #-} 10 | {-# LANGUAGE NumericUnderscores #-} 11 | {-# LANGUAGE RankNTypes #-} 12 | 13 | module Search where 14 | 15 | import Dma.Prelude 16 | 17 | data SearchTarget = None | S16 U16 | S32 U32 18 | deriving (Generic, Eq, ShowX, NFDataX) 19 | type SearchState = (SearchTarget, BitVector 24, BitVector 32, Bool) 20 | type SearchResult = BitVector 32 21 | 22 | toSearch :: U32 -> U32 -> SearchTarget 23 | toSearch 0 _ = None 24 | toSearch 1 v = S16 (resize v) 25 | toSearch 2 v = S32 v 26 | toSearch _ _ = None 27 | 28 | searchT 29 | :: SearchState 30 | -> (Maybe SearchTarget, Stream r (Maybe U64)) 31 | -> (SearchState, Stream r (Maybe SearchResult)) 32 | searchT _ (Just i@S32{}, _) = ((i, 0, -3, True), Item Nothing) 33 | searchT _ (Just i@S16{}, _) = ((i, 0, -1, True), Item Nothing) 34 | 35 | searchT s (Nothing, Done r) = (s, Done r) 36 | 37 | searchT s (Nothing, Item Nothing) = (s, Item Nothing) 38 | searchT s (Nothing, _) | (None, _, _, _) <- s = (s, Item Nothing) 39 | 40 | searchT (target, buff, offset, isFirst) (Nothing, Item (Just x)) 41 | = ((target,slice d63 d40 x,offset+8,False), Item m) 42 | where 43 | m = collate 44 | $ imap (\i -> match target i . pack) 45 | $ reverse 46 | $ windows1d d4 $ bitCoerce @_ @(Vec _ U8) $ x ++# buff 47 | match (S32 t) i v | t == v && not (isFirst && i < 3) = Just i 48 | match (S16 t) i (slice d31 d16 -> v) | t == v && not (isFirst && i == 0) = Just i 49 | match _ _ _ = Nothing 50 | collate = fmap ((+) offset . resize . pack) . fold (<|>) 51 | 52 | search 53 | :: (HiddenClockResetEnable domain) 54 | => Unbundled domain (Maybe SearchTarget, Stream r (Maybe U64)) 55 | -> Signal domain (Stream r (Maybe SearchResult)) 56 | search = mealy searchT (None, 0, 0, False) . bundle 57 | -------------------------------------------------------------------------------- /src/SpiSlave.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE LambdaCase #-} 2 | 3 | module SpiSlave 4 | ( spiSlave 5 | , SpiI 6 | ) 7 | where 8 | 9 | import Dma.Prelude 10 | import Control.Lens 11 | 12 | type SpiI = ("clock" ::: Bit, "select" ::: Bool, "mosi" ::: Bit) 13 | 14 | data SpiState 15 | = SpiState 16 | { _recv :: U8 17 | , _recvIdx :: BitVector 3 18 | , _sendIdx :: BitVector 3 19 | , _clkBuf :: BitVector 2 20 | , _miso :: Bit 21 | , _rxValid :: Bool 22 | } deriving (ShowX, Eq, Generic, NFDataX) 23 | 24 | instance Bundle SpiState 25 | 26 | makeLenses ''SpiState 27 | 28 | receiveByte :: SpiState -> Maybe U8 29 | receiveByte s = toMaybe (s ^. rxValid) (s ^. recv) 30 | 31 | spiSlaveT :: ((Bit, Bool, Bit), U8) 32 | -> State SpiState (Bool, Maybe U8, Bit) 33 | spiSlaveT ((clock, slaveSelect, mosi), next) = do 34 | (rising, falling) <- uses clkBuf $ \case 35 | 0b01 -> (True, False) 36 | 0b10 -> (False, True) 37 | _ -> (False, False) 38 | clkBuf %= (#<<+ clock) 39 | 40 | rxValid .= False 41 | 42 | if not slaveSelect then do 43 | recvIdx .= 0 44 | sendIdx .= 0 45 | recv .= 0 46 | clkBuf .= 0 47 | miso <~ boolToBit . testBit next . (7 - ) . fromEnum <$> use sendIdx 48 | else do 49 | when falling $ do 50 | sendIdx += 1 51 | miso <~ boolToBit . testBit next . (7 - ) . fromEnum <$> use sendIdx 52 | when rising $ do 53 | recv %= (#<<+ mosi) 54 | recvIdx' <- recvIdx <+= 1 55 | when (recvIdx' == 0) (rxValid .= True) 56 | 57 | get >>= \s -> return (slaveSelect, receiveByte s, _miso s) 58 | 59 | {-# NOINLINE spiSlave #-} 60 | spiSlave :: (HiddenClockResetEnable sys) 61 | => Unbundled sys ((Bit, Bool, Bit), U8) 62 | -> Unbundled sys (Bool, Maybe U8, Bit) 63 | spiSlave 64 | = mealyStateB spiSlaveT (SpiState 0 0 0 0 0b11 False) 65 | -------------------------------------------------------------------------------- /src/StreamReassembly.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.Normalise #-} 2 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-} 3 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.Extra.Solver #-} 4 | 5 | {-# LANGUAGE ApplicativeDo #-} 6 | {-# LANGUAGE BlockArguments #-} 7 | {-# LANGUAGE GADTs #-} 8 | {-# LANGUAGE NoStarIsType #-} 9 | {-# LANGUAGE NumericUnderscores #-} 10 | {-# LANGUAGE RankNTypes #-} 11 | {-# LANGUAGE ViewPatterns #-} 12 | 13 | module StreamReassembly 14 | ( 15 | StreamRequest 16 | , Failed 17 | , filterTag 18 | ) 19 | where 20 | 21 | import Dma.Prelude 22 | 23 | import Tlp 24 | 25 | -- * Byte stream reassembly 26 | 27 | -- 62 bit address of word, 28bit length of words 28 | type StreamRequest = (BitVector 62, BitVector 28) 29 | type Failed = Bool 30 | 31 | data ReassemblyState 32 | = ReassemblyState 33 | { _address :: BitVector 62 34 | , _remaining :: BitVector 28 35 | , _timer :: BitVector 20 36 | , _bufferedTx :: Maybe Tx 37 | , _failed :: Bool 38 | } deriving (Eq, ShowX, Generic, NFDataX) 39 | 40 | instance Default ReassemblyState where 41 | def = ReassemblyState 0 0 0 Nothing False 42 | 43 | reassemblyState (addr, len) tx = ReassemblyState addr len 0 tx False 44 | done (_, len) = len == 0 45 | 46 | nextRequest :: ReassemblyState -> BitVector 2 -> StreamRequest 47 | nextRequest (ReassemblyState addr r _ _ _) l = 48 | ( truncateB $ add addr l 49 | , truncateB $ sub r l ) 50 | 51 | mkTlp tag (addr,len) = ReadTx (addr ++# 0) (nextLength addr len) tag 52 | 53 | nextLength :: BitVector 62 -> BitVector 28 -> BitVector 10 54 | nextLength addr l = 55 | let loaddr = resize addr :: BitVector 10 56 | pageBound = 1 + complement loaddr 57 | in if loaddr == 0 58 | then reduce l 59 | else minimum (reduce l :> pageBound :> Nil) 60 | 61 | filterTagT 62 | :: Tag 63 | -> ReassemblyState 64 | -> (Maybe (TlpHeader, DoublePort U32), Maybe StreamRequest, Bool) 65 | -> (ReassemblyState, (Stream Failed (DoublePort U32), Maybe Tx)) 66 | 67 | -- Start a new transaction 68 | filterTagT tag _ (_, Just r, _) = 69 | let tx = mkTlp tag r 70 | in ( reassemblyState r (Just tx) 71 | , (Item Zero, Nothing) 72 | ) 73 | 74 | filterTagT _ s@(_remaining -> r) _ | r == 0 = (s, (Done False, Nothing)) 75 | filterTagT _ s@(_failed -> f) _ | f = (s, (Done True, Nothing)) 76 | filterTagT _ (_timer -> t) _ | t == 500_000 = (def { _failed = True }, (Done True, Nothing)) 77 | 78 | -- Relevant packet received 79 | filterTagT tag s (Just t, _, _) 80 | | t ^. _1 . tlpTag == tag && not (_failed s) 81 | = let sanity 82 | | t ^. _1 . tlpHeaderPulse 83 | = slice d4 d0 (_address s) == slice d6 d2 (t ^. _1 . tlpLowerAddress) 84 | | otherwise = True 85 | 86 | r = nextRequest s (portCount $ t ^. _2) 87 | 88 | tx 89 | | done r = Nothing 90 | | t ^. _1 . tlpBytesRemaining == 0 = Just (mkTlp tag r) 91 | | otherwise = Nothing 92 | 93 | in if sanity 94 | then (reassemblyState r tx, (Item $ t ^. _2, Nothing)) 95 | else (def {_failed = True}, (Done True, Nothing)) 96 | 97 | filterTagT _ (ReassemblyState addr len t tx False) (view _3 -> txReady) = 98 | ( ReassemblyState addr len (t + 1) (tx <* guard (not txReady)) False 99 | , (Item Zero, tx) 100 | ) 101 | 102 | filterTag 103 | :: HiddenClockResetEnable domain 104 | => Tag 105 | -> Unbundled domain (Maybe (TlpHeader, DoublePort U32), Maybe StreamRequest, Bool) 106 | -> Unbundled domain (Stream Failed (DoublePort U32), Maybe Tx) 107 | filterTag tag = filterTagT tag <^> def 108 | -------------------------------------------------------------------------------- /src/Tlp.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.Normalise #-} 2 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-} 3 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.Extra.Solver #-} 4 | 5 | {-# LANGUAGE ApplicativeDo #-} 6 | {-# LANGUAGE BlockArguments #-} 7 | {-# LANGUAGE GADTs #-} 8 | {-# LANGUAGE LambdaCase #-} 9 | {-# LANGUAGE TypeApplications #-} 10 | {-# LANGUAGE NoStarIsType #-} 11 | {-# LANGUAGE NumericUnderscores #-} 12 | {-# LANGUAGE RankNTypes #-} 13 | {-# LANGUAGE RecordWildCards #-} 14 | {-# LANGUAGE TupleSections #-} 15 | {-# LANGUAGE ViewPatterns #-} 16 | 17 | module Tlp 18 | ( 19 | Tag 20 | , Tx(..) 21 | 22 | , TlpHeader(..) 23 | , tlpTag 24 | , tlpLowerAddress 25 | , tlpBytesRemaining 26 | , tlpDone 27 | , tlpStatus 28 | , tlpHeaderPulse 29 | 30 | , completionStream 31 | , transactionWriter 32 | 33 | ) where 34 | 35 | import Dma.Prelude 36 | 37 | import Axi 38 | 39 | type Tag = BitVector 8 40 | data Tx = ReadTx U64 (BitVector 10) Tag | WriteTx U64 U64 Tag 41 | deriving (Eq, ShowX, Generic, NFDataX) 42 | 43 | -- * Tlp parsing 44 | 45 | data TlpHeader 46 | = TlpHeader 47 | { _tlpTag :: Tag 48 | , _tlpLowerAddress :: BitVector 7 49 | , _tlpBytesRemaining :: BitVector 12 50 | , _tlpDone :: Bool 51 | , _tlpStatus :: BitVector 3 52 | , _tlpHeaderPulse :: Bool 53 | } deriving (Generic, NFDataX, ShowX, Eq, BitPack) 54 | 55 | data CompletionStreamState 56 | = CompletionStreamState 57 | { _packetIndex :: Index 4 58 | , _packetHeader :: TlpHeader 59 | , _packetFlush :: Bool 60 | } deriving (Generic, NFDataX) 61 | 62 | makeLenses ''TlpHeader 63 | makeLenses ''CompletionStreamState 64 | 65 | instance Default TlpHeader where 66 | def = TlpHeader 0 0 0 False 0 False 67 | instance Default CompletionStreamState where 68 | def = CompletionStreamState 0 def False 69 | 70 | data ParseTlpU32 = Flush | Consumed | IsData U32 71 | deriving (Eq, ShowX, Generic, NFDataX) 72 | 73 | getData :: ParseTlpU32 -> Maybe U32 74 | getData (IsData x) = Just x 75 | getData _ = Nothing 76 | 77 | parseTlpU32 :: Bool -> U32 -> State CompletionStreamState ParseTlpU32 78 | parseTlpU32 False _ = return Consumed 79 | parseTlpU32 True data_ = do 80 | index <- use packetIndex 81 | packetIndex .= satAdd SatBound index 1 82 | zoom packetHeader $ case index of 83 | 0 -> do 84 | let _length = slice d9 d0 data_ 85 | type_ = slice d28 d24 data_ 86 | 87 | if type_ /= 0xa then return Flush else return Consumed 88 | 89 | 1 -> do 90 | let byteCount = slice d11 d0 data_ 91 | status_ = slice d15 d13 data_ 92 | 93 | tlpBytesRemaining .= byteCount 94 | 95 | tlpStatus .= status_ 96 | if status_ /= 0 then return Flush else return Consumed 97 | 98 | 2 -> do 99 | let tag = slice d15 d8 data_ 100 | let lowAddr = slice d6 d0 data_ 101 | 102 | tlpLowerAddress .= lowAddr 103 | tlpTag .= tag 104 | tlpHeaderPulse .= True 105 | 106 | return Consumed 107 | _ -> do 108 | tlpLowerAddress += 4 109 | tlpBytesRemaining %= flip (satSub SatBound) 4 110 | return $ IsData (bitCoerceMap @(Vec 4 U8) reverse data_) 111 | 112 | completionStreamT 113 | :: AxiSimpleStream 8 n 114 | -> State CompletionStreamState (Maybe (TlpHeader, DoublePort U32)) 115 | completionStreamT (_axis_valid -> False) = return Nothing 116 | completionStreamT rx = do 117 | let data2En = case rx ^. axis_keep of 118 | 0x0F -> False 119 | 0xFF -> True 120 | _ -> errorX "Xilinx PCIe core violation" 121 | let (data2, data1) = split $ rx ^. axis_data 122 | 123 | p1 <- parseTlpU32 True data1 124 | p2 <- parseTlpU32 data2En data2 125 | 126 | when (p1 == Flush || p2 == Flush) (packetFlush .= True) 127 | zoom packetHeader $ tlpHeaderPulse .= False 128 | flushing <- use packetFlush 129 | index <- use packetIndex 130 | 131 | if rx ^. axis_last 132 | then do 133 | packetFlush .= False 134 | zoom packetHeader $ tlpDone .= True 135 | packetIndex .= 0 136 | else zoom packetHeader $ tlpDone .= False 137 | 138 | if flushing 139 | then return Nothing 140 | else do 141 | header' <- use packetHeader 142 | let data_ = case (getData p1, getData p2) of 143 | (Just x1, Just x2) -> Two x1 x2 144 | (Nothing, Just x2) -> One x2 145 | (Just x1, Nothing) -> One x1 146 | (_ , _ ) -> Zero 147 | return $ if index == 3 then Just (header', data_) else Nothing 148 | 149 | -- {-# NOINLINE completionStream #-} 150 | completionStream 151 | :: (HiddenClockResetEnable dom) 152 | => Signal dom (AxiSimpleStream 8 n) 153 | -> Signal dom (Maybe (TlpHeader, DoublePort U32)) 154 | completionStream = mealyState completionStreamT def 155 | 156 | --- * Transaction writer 157 | 158 | type TransactionWriterState = (Index 4, Maybe Tx) 159 | 160 | txLen :: Tx -> BitVector 10 161 | txLen (ReadTx _ len _) = len 162 | txLen WriteTx {} = 2 163 | 164 | txFlag :: Tx -> BitVector 2 165 | txFlag ReadTx {} = 0b00 166 | txFlag WriteTx {} = 0b01 167 | 168 | txAddr :: Tx -> BitVector 64 169 | txAddr (ReadTx x _ _) = x 170 | txAddr (WriteTx x _ _) = x 171 | 172 | tx32Bit :: Tx -> Bool 173 | tx32Bit x = 0x1_0000_0000 > txAddr x 174 | 175 | txType :: Tx -> BitVector 3 176 | txType t | tx32Bit t = txFlag t ++# 0b0 177 | | otherwise = txFlag t ++# 0b1 178 | 179 | txTag :: Tx -> Tag 180 | txTag (ReadTx _ _ tag) = tag 181 | txTag (WriteTx _ _ tag) = tag 182 | 183 | transactionWriterT 184 | :: KnownNat n 185 | => TransactionWriterState 186 | -> (BitVector 16, Maybe Tx, Bool, BitVector 6) 187 | -> (TransactionWriterState, (AxiSimpleStream 8 n, Bool, Bool)) 188 | 189 | transactionWriterT (0, tx) (_, _, _, downStreamBuffers) 190 | | downStreamBuffers < 3 = ((0,tx), (def, not (isJust tx), False)) 191 | transactionWriterT (i, Just tx) (requester, nxTx, pciReady, _buffers) 192 | | i == fromSNat d0 193 | = let w1 :: BitVector 32 = txType tx ++# 0 ++# txLen tx 194 | w2 :: BitVector 32 = requester ++# txTag tx ++# (if txLen tx > 1 then 0xFF else 0x0F) 195 | in (s', (mkAxisWrite (w2 ++# w1), False, pciReady)) 196 | | i == fromSNat d1 197 | = case tx of 198 | ReadTx {} -> 199 | let w | tx32Bit tx = mkAxisWrite (0 ++# lo) & axis_keep .~ 0xF 200 | | otherwise = mkAxisWrite (lo ++# hi) 201 | in (z, (w & axis_last .~ True, pciReady, False)) 202 | WriteTx _ v _ -> 203 | let (_, vlo) = split v 204 | w | tx32Bit tx = rev vlo ++# lo 205 | | otherwise = lo ++# hi 206 | in (s', (mkAxisWrite w, False, False)) 207 | | i == fromSNat d2 208 | = case tx of 209 | ReadTx {} -> errorX "Reached invalid state for read transaction!" 210 | WriteTx _ v _ -> 211 | let (vhi, vlo) = split v 212 | w | tx32Bit tx = mkAxisWrite (0 ++# rev vhi) & axis_keep .~ 0xF 213 | | otherwise = mkAxisWrite (rev vhi ++# rev vlo) 214 | in (z, (w & axis_last .~ True, pciReady, False)) 215 | where 216 | z = if pciReady then (0, nxTx) else (i, Just tx) 217 | s' = if pciReady then (i + 1, Just tx) else (i, Just tx) 218 | 219 | mask = 0xFFFF_FFFC 220 | (hi :: BitVector 32, lo) = second (mask .&.) $ split (txAddr tx) 221 | rev = pack . reverse @4 @U8 . unpack :: U32 -> U32 222 | 223 | transactionWriterT (_, _) (_, nxTx, _, _) = ((0, nxTx), (def, True, False)) 224 | 225 | -- {-# NOINLINE transactionWriter #-} 226 | transactionWriter 227 | :: (KnownNat n, HiddenClockResetEnable dom) 228 | => Unbundled dom (BitVector 16, Maybe Tx, Bool, BitVector 6) 229 | -> Unbundled dom (AxiSimpleStream 8 n, Bool, Bool) 230 | transactionWriter = transactionWriterT <^> def 231 | -------------------------------------------------------------------------------- /tests/Test/DmaCore.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.Normalise #-} 2 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-} 3 | {-# OPTIONS_GHC -fplugin GHC.TypeLits.Extra.Solver #-} 4 | 5 | {-# LANGUAGE ApplicativeDo #-} 6 | {-# LANGUAGE BlockArguments #-} 7 | {-# LANGUAGE DerivingVia #-} 8 | {-# LANGUAGE GADTs #-} 9 | {-# LANGUAGE LambdaCase #-} 10 | {-# LANGUAGE NumericUnderscores #-} 11 | {-# LANGUAGE PartialTypeSignatures #-} 12 | {-# LANGUAGE PolyKinds #-} 13 | {-# LANGUAGE RankNTypes #-} 14 | {-# LANGUAGE RecursiveDo #-} 15 | {-# LANGUAGE TupleSections #-} 16 | {-# LANGUAGE ViewPatterns #-} 17 | 18 | {-# LANGUAGE AllowAmbiguousTypes #-} 19 | {-# LANGUAGE UndecidableInstances #-} 20 | 21 | module Test.DmaCore where 22 | 23 | import Dma.Prelude 24 | import qualified Data.Foldable as P 25 | import qualified Data.List as P 26 | import Clash.Prelude hiding ( fifoDF ) 27 | import qualified Clash.Prelude.Testbench as TB 28 | import qualified Clash.Explicit.Testbench as TBE 29 | import Control.Lens hiding ( index 30 | , Index 31 | , (:>) 32 | , (:<) 33 | , elements 34 | , at 35 | ) 36 | import Control.Monad 37 | import Clash.Annotations.TH 38 | 39 | import Axi 40 | import SpiSlave 41 | import Tlp 42 | import Register 43 | import Top 44 | 45 | import Test.Test 46 | import Test.Tasty hiding ( assertEqual 47 | , assert 48 | ) 49 | import Test.Tasty.HUnit hiding ( assertEqual 50 | , assert 51 | ) 52 | 53 | type DmaCoreI = 54 | ((Bit, Bool, Bit), AxiSimpleStream 8 22, (U8, BitVector 5, BitVector 3), Bool, BitVector 6) 55 | type DmaCoreO = (Bit, Bool, AxiSimpleStream 8 4, Bool) 56 | type DmaCoreTestM a 57 | = TestM 58 | DmaCoreI 59 | DmaCoreO 60 | a 61 | 62 | onlySpi :: (Bit, Bool, Bit) -> DmaCoreI 63 | onlySpi x = (x, def, (0xFF,0,0), True, complement 0) 64 | 65 | onlyAxi :: AxiSimpleStream 8 22 -> DmaCoreI 66 | onlyAxi x = ((0,False,0), x, (0xFF,0,0), True, complement 0) 67 | 68 | silent = onlySpi (0, False, 0) 69 | 70 | writeSpiBit :: Bit -> DmaCoreTestM DmaCoreO 71 | writeSpiBit b = do 72 | tick $ onlySpi (0, True, b) 73 | tick $ onlySpi (0, True, b) 74 | tick $ onlySpi (0, True, b) 75 | o <- tick $ onlySpi (1, True, b) 76 | tick $ onlySpi (1, True, b) 77 | tick $ onlySpi (1, True, b) 78 | return o 79 | 80 | writeSpiByte :: U8 -> DmaCoreTestM (Vec 8 DmaCoreO) 81 | writeSpiByte b = traverse writeSpiBit (bv2v b) 82 | 83 | writeSpiV :: (KnownNat n, 1 <= n) => Vec n U8 -> DmaCoreTestM (Vec n (Vec 8 DmaCoreO)) 84 | writeSpiV = traverse writeSpiByte 85 | 86 | rwSpi :: (KnownNat n, 1 <= n) => U8 -> Vec n U8 -> DmaCoreTestM (Vec n U8) 87 | rwSpi c v = do 88 | tick silent 89 | tick silent 90 | tick silent 91 | writeSpiByte c 92 | r <- writeSpiV v 93 | tick silent 94 | return $ fmap (v2bv . fmap (view _1)) r 95 | 96 | testIdx :: DmaCoreTestM () 97 | testIdx = 98 | rwSpi 13 (replicate d8 0) 99 | >>= assertEqual "idx" $(listToVecTH [0,1::U8,2,3,4,5,6,7]) 100 | 101 | testWrite :: DmaCoreTestM () 102 | testWrite = do 103 | rwSpi 0 (replicate d4 0) 104 | >>= assertEqual "read #0 empty" $(listToVecTH [0::U8,0,0,0]) 105 | rwSpi 1 (replicate d4 0) 106 | >>= assertEqual "read #1 empty" $(listToVecTH [0::U8,0,0,0]) 107 | rwSpi 3 (replicate d4 0) 108 | >>= assertEqual "read #3 empty" $(listToVecTH [0::U8,0,0,0]) 109 | rwSpi 128 $(listToVecTH [1::U8,0,2,0]) 110 | >>= assertEqual "" $(listToVecTH [0::U8,1,0,2]) 111 | rwSpi 129 $(listToVecTH [1::U8,9,8,7]) 112 | >>= assertEqual "" $(listToVecTH [0::U8,1,9,8]) 113 | rwSpi 131 $(listToVecTH [9::U8,10,11,12]) 114 | >>= assertEqual "" $(listToVecTH [0::U8,9,10,11]) 115 | rwSpi 0 (replicate d4 0) 116 | >>= assertEqual "read back #0" $(listToVecTH [1::U8,0,2,0]) 117 | rwSpi 1 (replicate d4 0) 118 | >>= assertEqual "read back #1" $(listToVecTH [1::U8,9,8,7]) 119 | rwSpi 3 (replicate d4 0) 120 | >>= assertEqual "read back #3" $(listToVecTH [9::U8,10,11,12]) 121 | -- 122 | return () 123 | 124 | testPcieReadStatus :: DmaCoreTestM () 125 | testPcieReadStatus = do 126 | rwSpi 138 (0:>0:>0:>1:>Nil) 127 | findAxiWrite >>= trace . showX 128 | findFailed 129 | where 130 | findAxiWrite = mdo 131 | x <- tick silent 132 | if x ^. _3 . axis_valid 133 | then return x 134 | else findAxiWrite 135 | alwaysFailed = mdo 136 | x :: U8 <- head <$> rwSpi 12 (replicate d4 0) 137 | assert (x == 1) $ "busy or failed: " <> showX x 138 | findFailed 139 | 140 | findFailed = mdo 141 | x :: U8 <- head <$> rwSpi 12 (replicate d4 0) 142 | assert (x == 2 || x == 1) $ "busy or failed: " <> showX x 143 | if x == 1 144 | then alwaysFailed 145 | else findFailed 146 | 147 | testPcieRead :: DmaCoreTestM () 148 | testPcieRead = do 149 | rwSpi 11 (replicate d4 0) 150 | >>= assertEqual "read is done" 151 | $(listToVecTH [0,0,0,0 ::U8]) 152 | 153 | rwSpi 138 (1:>0:>0:>0:>Nil) 154 | 155 | tick silent 156 | 157 | rwSpi 9 (replicate d4 0) 158 | >>= assertEqual "read is busy" 159 | $(listToVecTH [1,0,0,0 ::U8]) 160 | rwSpi 11 (replicate d4 0) 161 | >>= assertEqual "read is not failed" 162 | $(listToVecTH [0,0,0,0 ::U8]) 163 | 164 | rwSpi 26 (replicate d4 0) 165 | >>= assertEqual "read trigger count is 1" 166 | $(listToVecTH [1,0,0,0 ::U8]) 167 | 168 | tick silent 169 | tick silent 170 | 171 | rwSpi 24 (replicate d4 0) 172 | >>= assertEqual "tx sent count is 1" 173 | $(listToVecTH [1,0,0,0 ::U8]) 174 | 175 | -- tick $ onlyAxi $ mkAxisWrite 0x00000018_4a000006 176 | -- tick $ onlyAxi $ mkAxisWrite 0x12345678_00001f00 177 | -- tick $ onlyAxi $ mkAxisWrite 0x33333333_abcdef00 178 | -- tick $ onlyAxi $ mkAxisWrite 0x55555555_44444444 179 | -- tick $ onlyAxi $ mkAxisWrite 0x00000000_66666666 & axis_last .~ True & axis_keep .~ 0xF 180 | 181 | tick $ onlyAxi $ mkAxisWrite 0x00000018_4a000006 & axis_keep .~ 0xF 182 | tick $ onlyAxi $ mkAxisWrite 0x00000000_00000018 & axis_keep .~ 0xF 183 | tick $ onlyAxi $ mkAxisWrite 0x00000000_00000000 & axis_valid .~ False 184 | tick $ onlyAxi $ mkAxisWrite 0x12345678_00001f00 & axis_keep .~ 0xF 185 | tick $ onlyAxi $ mkAxisWrite 0x12345678_12345678 & axis_keep .~ 0xF 186 | tick $ onlyAxi $ mkAxisWrite 0x33333333_abcdef00 187 | tick $ onlyAxi $ mkAxisWrite 0x55555555_44444444 188 | tick $ onlyAxi $ mkAxisWrite 0x00000000_66666666 & axis_last .~ True & axis_keep .~ 0xF 189 | tick silent 190 | tick silent 191 | 192 | rwSpi 9 (replicate d4 0) 193 | >>= assertEqual "read is still busy" 194 | $(listToVecTH [1,0,0,0 ::U8]) 195 | 196 | rwSpi 26 (replicate d4 0) 197 | >>= assertEqual "read trigger count is 1" 198 | $(listToVecTH [1,0,0,0 ::U8]) 199 | 200 | rwSpi 7 (replicate d24 0) 201 | >>= assertEqual "ram val" 202 | $(listToVecTH 203 | [ 0x12, 0x34, 0x56, 0x78 204 | , 0xab, 0xcd, 0xef, 0x00 205 | , 0x33, 0x33, 0x33, 0x33 206 | , 0x44, 0x44, 0x44, 0x44 207 | , 0x55, 0x55, 0x55, 0x55 208 | , 0x66, 0x66, 0x66, 0x66 209 | :: U8]) 210 | 211 | rwSpi 134 (2:>0:>0:>0:>Nil) 212 | 213 | rwSpi 7 (replicate d16 0) 214 | >>= assertEqual "raw tlp val" 215 | $(listToVecTH 216 | [ 0x06, 0x00, 0x00, 0x4a 217 | , 0x18, 0x00, 0x00, 0x00 218 | , 0x00, 0x1f, 0x00, 0x00 219 | , 0x78, 0x56, 0x34, 0x12 220 | :: U8]) 221 | 222 | testPcieSearch :: DmaCoreTestM () 223 | testPcieSearch = do 224 | rwSpi 134 (1:>0:>0:>0:>Nil) -- Select search 225 | 226 | rwSpi 14 (replicate d4 0) 227 | >>= assertEqual "search is done" 228 | $(listToVecTH [0,0,0,0 ::U8]) 229 | rwSpi 16 (replicate d4 0) 230 | >>= assertEqual "search is not failed" 231 | $(listToVecTH [0,0,0,0 ::U8]) 232 | 233 | rwSpi 131 (100:>0:>0:>0:>Nil) -- Search length 234 | rwSpi 146 ( 1:>0:>0:>0:>Nil) -- Search type 235 | -- rwSpi 147 (0x00:>0x33:>0x0:>0x0:>Nil) -- Search val 236 | -- rwSpi 147 (0x12:>0x34:>0x0:>0x0:>Nil) -- Search val 237 | -- rwSpi 147 (0xab:>0xcd:>0x0:>0x0:>Nil) -- Search val 238 | rwSpi 147 (0x55:>0x55:>0x55:>0x55:>Nil) -- Search val 239 | rwSpi 143 ( 1:>0:>0:>0:>Nil) -- Trigger search 240 | 241 | tick silent 242 | 243 | rwSpi 14 (replicate d4 0) 244 | >>= assertEqual "search is busy" 245 | $(listToVecTH [1,0,0,0 ::U8]) 246 | 247 | tick silent 248 | tick silent 249 | 250 | tick $ onlyAxi $ mkAxisWrite 0x00000018_4a000006 251 | tick $ onlyAxi $ mkAxisWrite 0x12345678_00000100 252 | tick $ onlyAxi $ mkAxisWrite 0x33333333_abcdef00 253 | tick $ onlyAxi $ mkAxisWrite 0x55555555_44444444 254 | tick $ onlyAxi $ mkAxisWrite 0x00000000_66666666 & axis_last .~ True & axis_keep .~ 0xF 255 | 256 | tick silent 257 | tick silent 258 | 259 | rwSpi 14 (replicate d4 0) 260 | >>= assertEqual "search is busy" 261 | $(listToVecTH [1,0,0,0 ::U8]) 262 | rwSpi 16 (replicate d4 0) 263 | >>= assertEqual "search is not failed" 264 | $(listToVecTH [0,0,0,0 ::U8]) 265 | 266 | rwSpi 17 (replicate d4 0) 267 | >>= assertEqual "search found" 268 | $(listToVecTH [1,0,0,0 ::U8]) 269 | 270 | 271 | rwSpi 7 (replicate d8 0) 272 | >>= assertEqual "ram val" 273 | $(listToVecTH 274 | [ 0x10, 0x00, 0x00, 0x00 275 | , 0x00, 0x00, 0x00, 0x00 276 | :: U8]) 277 | 278 | dut :: DmaCoreTestM () -> TestLog DmaCoreI DmaCoreO () 279 | dut = runTestM dut 280 | where 281 | dut = withClockResetEnable systemClockGen systemResetGen enableGen $ 282 | \(unbundle -> (a, b, unbundle -> c,d,e)) -> 283 | bundle $ dmaCore a b c d e 0 284 | 285 | tests :: TestTree 286 | tests = testGroup "DmaCore tests" 287 | [ testCase "idx" $ testForError (dut testIdx) 288 | , testCase "write register" $ testForError (dut testWrite) 289 | , testCase "pcie tx" $ testForError (truncateLog 10000 (dut testPcieReadStatus)) 290 | , testCase "pcie read" $ testForError (truncateLog 10000 (dut testPcieRead)) 291 | , testCase "pcie search" $ testForError (truncateLog 10000 (dut testPcieSearch )) 292 | ] 293 | -------------------------------------------------------------------------------- /tests/Test/Test.hs: -------------------------------------------------------------------------------- 1 | -- | This file is is a modified version of 2 | -- https://git.smart-cactus.org/ben/clash-testbench (BSD 3-clause "New" or "Revised" License) 3 | -- 4 | -- Copyright (c) 2017, Ben Gamari 5 | 6 | -- All rights reserved. 7 | 8 | -- Redistribution and use in source and binary forms, with or without 9 | -- modification, are permitted provided that the following conditions are met: 10 | 11 | -- * Redistributions of source code must retain the above copyright 12 | -- notice, this list of conditions and the following disclaimer. 13 | 14 | -- * Redistributions in binary form must reproduce the above 15 | -- copyright notice, this list of conditions and the following 16 | -- disclaimer in the documentation and/or other materials provided 17 | -- with the distribution. 18 | 19 | -- * Neither the name of Ben Gamari nor the names of other 20 | -- contributors may be used to endorse or promote products derived 21 | -- from this software without specific prior written permission. 22 | 23 | -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 | -- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 | -- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26 | -- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 | -- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 | -- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 29 | -- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 | -- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31 | -- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 | -- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 | -- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | 35 | {-# LANGUAGE RecursiveDo #-} 36 | {-# LANGUAGE BangPatterns #-} 37 | {-# LANGUAGE DeriveFunctor #-} 38 | {-# LANGUAGE GeneralizedNewtypeDeriving #-} 39 | {-# LANGUAGE GADTs #-} 40 | 41 | module Test.Test 42 | where 43 | 44 | import GHC.Generics 45 | import Control.DeepSeq 46 | import Control.Monad.Free 47 | import Control.Monad.Fail 48 | import Control.Monad hiding (fail) 49 | import Data.Semigroup 50 | import Clash.Prelude hiding (fail) 51 | import Clash.Signal.Internal (Signal(..)) 52 | import System.IO.Unsafe 53 | import Data.IORef 54 | import Data.List (foldr) 55 | 56 | import Test.Tasty.HUnit (assertFailure) 57 | 58 | data Stream i o = Stream o (i -> Stream i o) 59 | 60 | -- | Convert a 'Signal' to a 'Stream', where the input to each timestep can be 61 | -- computed as a function of previous outputs. 62 | -- 63 | -- Note that the 'Stream' must be consumed linearly; that is, you can apply 64 | -- the continuation associated with a particular stream element only once. 65 | streamSignal :: forall clk i o. KnownDomain clk => (Signal clk i -> Signal clk o) -> i -> Stream i o 66 | streamSignal dut input0 = unsafePerformIO $ mdo 67 | -- oh the horror... 68 | inputRefs <- infiniteRefList Nothing 69 | let goOut :: Int -> [IORef (Maybe i)] -> [o] -> IO (Stream i o) 70 | goOut !n (inRef:inRefs) (out:rest) = do 71 | let next :: i -> Stream i o 72 | next i = unsafePerformIO $ do 73 | old <- atomicModifyIORef inRef (\old -> (Just i, old)) 74 | case old of 75 | Nothing -> return () 76 | Just _ -> fail "streamIt: non-linear usage" 77 | unsafeInterleaveIO $ goOut (n+1) inRefs rest 78 | return $ Stream out next 79 | goOut _ _ [] = fail "reached end of Signal" 80 | goOut _ [] _ = fail "impossible" 81 | 82 | let inputs = input0 : fmap readInput inputRefs 83 | readInput ref = unsafePerformIO $ do 84 | val <- readIORef ref 85 | case val of 86 | Nothing -> fail "bad news bears" 87 | Just x -> return x 88 | goOut 0 inputRefs $ simulate_lazy dut inputs 89 | {-# NOINLINE streamSignal #-} 90 | 91 | infiniteRefList :: a -> IO [IORef a] 92 | infiniteRefList val = go 93 | where 94 | go = do 95 | rest <- unsafeInterleaveIO go 96 | ref <- newIORef val 97 | return (ref : rest) 98 | 99 | type DUT clk i o = Signal clk i -> Signal clk o 100 | 101 | data TestF i o next 102 | = Tick i (o -> next) 103 | | Trace String next 104 | | Fail String 105 | deriving (Functor) 106 | 107 | newtype TestM i o a = TestM (Free (TestF i o) a) 108 | deriving stock (Functor) 109 | deriving newtype (Applicative, Monad) 110 | 111 | instance MonadFail (TestM i o) where 112 | fail = TestM . liftF . Fail 113 | 114 | tick :: i -> TestM i o o 115 | tick i = TestM $ liftF (Tick i id) 116 | 117 | tick_ :: i -> TestM i o () 118 | tick_ = void . tick 119 | 120 | tickUntil :: (NFData i) 121 | => i -> (o -> Bool) -> TestM i o o 122 | tickUntil i cond = do 123 | o <- tick i 124 | if cond o 125 | then return o 126 | else tickUntil i cond 127 | 128 | tickUntilJust :: (NFData i) 129 | => i -> (o -> Maybe a) -> TestM i o a 130 | tickUntilJust i f = do 131 | o <- tick i 132 | case f o of 133 | Just o' -> return o' 134 | Nothing -> tickUntilJust i f 135 | 136 | trace :: String -> TestM i o () 137 | trace msg = TestM $ liftF (Trace msg ()) 138 | 139 | assert :: Bool -> String -> TestM i o () 140 | assert cond msg 141 | | not cond = fail msg 142 | | otherwise = return () 143 | 144 | assertEqual :: (ShowX a, Eq a) => String -> a -> a -> TestM i o () 145 | assertEqual msg expected actual 146 | | expected == actual = return () 147 | | otherwise = fail $ unlines [ msg 148 | , "Expected: " <> showX expected 149 | , "Actual: " <> showX actual 150 | ] 151 | 152 | data TestLog i o a = Ticked i o (TestLog i o a) 153 | | TraceMsg String (TestLog i o a) 154 | | Finished a 155 | | Failed String 156 | deriving stock (Show, Functor, Generic) 157 | deriving anyclass (ShowX) 158 | 159 | toTickList :: TestLog i o a -> [(i,o)] 160 | toTickList (Ticked i o rest) = (i,o) : toTickList rest 161 | toTickList (TraceMsg _ rest) = toTickList rest 162 | toTickList (Failed s) = error $ "Failed "<>s 163 | toTickList (Finished _) = [] 164 | 165 | 166 | runTestM :: forall clk i o a. KnownDomain clk => DUT clk i o -> TestM i o a -> TestLog i o a 167 | runTestM dut (TestM m) = 168 | let f :: (i -> Stream i o) -> Free (TestF i o) a -> TestLog i o a 169 | f k (Free (Tick i k')) = let Stream o rest = k i 170 | in Ticked i o (f rest (k' o)) 171 | f k (Free (Trace s k')) = TraceMsg s (f k k') 172 | f _ (Free (Fail s)) = Failed s 173 | f _ (Pure x) = Finished x 174 | in f (streamSignal dut) m 175 | 176 | 177 | toTraceList :: TestLog i o a -> [String] 178 | toTraceList (Ticked _ _ rest) = toTraceList rest 179 | toTraceList (TraceMsg s rest) = s : toTraceList rest 180 | toTraceList (Failed s) = error $ "Failed "<>s 181 | toTraceList (Finished _) = [] 182 | 183 | testForError :: TestLog i o a -> IO () 184 | testForError (Ticked _ _ rest) = testForError rest 185 | testForError (TraceMsg s rest) = testForError rest 186 | testForError (Failed s) = assertFailure $ "Failed "<>s 187 | testForError (Finished _) = pure () 188 | 189 | prepend :: (Eq a) => a -> [a] -> [a] 190 | prepend x [] = [x] 191 | prepend x (y:ys) | x == y = y:ys 192 | | otherwise = x : y:ys 193 | uniq :: Eq a => [a] -> [a] 194 | uniq = Data.List.foldr prepend [] 195 | 196 | -- | Split a log at step @n@. 197 | splitLog :: Int -> TestLog i o a -> TestLog i o (Either (TestLog i o a) a) 198 | splitLog 0 x = Finished $ Left x 199 | splitLog n (Ticked i o rest) = Ticked i o (splitLog (n-1) rest) 200 | splitLog n (TraceMsg s rest) = TraceMsg s (splitLog (n-1) rest) 201 | splitLog _ (Finished x) = Finished (Right x) 202 | splitLog _ (Failed x) = Failed x 203 | 204 | data Truncated a = Truncated 205 | -- ^ it was truncated before producing a result 206 | | NotTruncated a 207 | -- ^ it finished with a result 208 | deriving (Show) 209 | 210 | truncateLog :: Int -> TestLog i o a -> TestLog i o (Truncated a) 211 | truncateLog n = fmap (either (const Truncated) NotTruncated) . splitLog n 212 | -------------------------------------------------------------------------------- /tests/tests.hs: -------------------------------------------------------------------------------- 1 | module Main where 2 | 3 | import Prelude 4 | 5 | import Test.Tasty hiding ( assertEqual 6 | , assert 7 | ) 8 | import Test.Tasty.HUnit hiding ( assertEqual 9 | , assert 10 | ) 11 | 12 | import qualified Test.DmaCore as DmaCore 13 | -- import qualified Test.Tlp as Tlp 14 | -- import qualified Test.Reassembly as Reassembly 15 | 16 | main :: IO () 17 | main = defaultMain $ 18 | testGroup "Expected successes" 19 | -- [ Tlp.tests 20 | -- , Reassembly.tests 21 | [ DmaCore.tests 22 | ] 23 | --------------------------------------------------------------------------------