├── .gitmodules ├── LICENSE ├── README.md ├── sw ├── bus_interface.py ├── dump.py ├── load_bin.py ├── peek.py ├── poke.py ├── socket_interface.py └── uart_bus_interface.py ├── usb_bridge └── src_v │ ├── usb_bridge.v │ └── usb_bridge_fifo.v └── usb_bridge_top.v /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "usb_fs_phy"] 2 | path = usb_fs_phy 3 | url = https://github.com/ultraembedded/core_usb_fs_phy 4 | [submodule "usb_cdc"] 5 | path = usb_cdc 6 | url = https://github.com/ultraembedded/core_usb_cdc 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 2.1, February 1999 3 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | [This is the first released version of the Lesser GPL. It also counts 10 | as the successor of the GNU Library Public License, version 2, hence 11 | the version number 2.1.] 12 | 13 | Preamble 14 | 15 | The licenses for most software are designed to take away your 16 | freedom to share and change it. By contrast, the GNU General Public 17 | Licenses are intended to guarantee your freedom to share and change 18 | free software--to make sure the software is free for all its users. 19 | 20 | This license, the Lesser General Public License, applies to some 21 | specially designated software packages--typically libraries--of the 22 | Free Software Foundation and other authors who decide to use it. You 23 | can use it too, but we suggest you first think carefully about whether 24 | this license or the ordinary General Public License is the better 25 | strategy to use in any particular case, based on the explanations below. 26 | 27 | When we speak of free software, we are referring to freedom of use, 28 | not price. Our General Public Licenses are designed to make sure that 29 | you have the freedom to distribute copies of free software (and charge 30 | for this service if you wish); that you receive source code or can get 31 | it if you want it; that you can change the software and use pieces of 32 | it in new free programs; and that you are informed that you can do 33 | these things. 34 | 35 | To protect your rights, we need to make restrictions that forbid 36 | distributors to deny you these rights or to ask you to surrender these 37 | rights. These restrictions translate to certain responsibilities for 38 | you if you distribute copies of the library or if you modify it. 39 | 40 | For example, if you distribute copies of the library, whether gratis 41 | or for a fee, you must give the recipients all the rights that we gave 42 | you. You must make sure that they, too, receive or can get the source 43 | code. If you link other code with the library, you must provide 44 | complete object files to the recipients, so that they can relink them 45 | with the library after making changes to the library and recompiling 46 | it. And you must show them these terms so they know their rights. 47 | 48 | We protect your rights with a two-step method: (1) we copyright the 49 | library, and (2) we offer you this license, which gives you legal 50 | permission to copy, distribute and/or modify the library. 51 | 52 | To protect each distributor, we want to make it very clear that 53 | there is no warranty for the free library. Also, if the library is 54 | modified by someone else and passed on, the recipients should know 55 | that what they have is not the original version, so that the original 56 | author's reputation will not be affected by problems that might be 57 | introduced by others. 58 | 59 | Finally, software patents pose a constant threat to the existence of 60 | any free program. We wish to make sure that a company cannot 61 | effectively restrict the users of a free program by obtaining a 62 | restrictive license from a patent holder. Therefore, we insist that 63 | any patent license obtained for a version of the library must be 64 | consistent with the full freedom of use specified in this license. 65 | 66 | Most GNU software, including some libraries, is covered by the 67 | ordinary GNU General Public License. This license, the GNU Lesser 68 | General Public License, applies to certain designated libraries, and 69 | is quite different from the ordinary General Public License. We use 70 | this license for certain libraries in order to permit linking those 71 | libraries into non-free programs. 72 | 73 | When a program is linked with a library, whether statically or using 74 | a shared library, the combination of the two is legally speaking a 75 | combined work, a derivative of the original library. The ordinary 76 | General Public License therefore permits such linking only if the 77 | entire combination fits its criteria of freedom. The Lesser General 78 | Public License permits more lax criteria for linking other code with 79 | the library. 80 | 81 | We call this license the "Lesser" General Public License because it 82 | does Less to protect the user's freedom than the ordinary General 83 | Public License. It also provides other free software developers Less 84 | of an advantage over competing non-free programs. These disadvantages 85 | are the reason we use the ordinary General Public License for many 86 | libraries. However, the Lesser license provides advantages in certain 87 | special circumstances. 88 | 89 | For example, on rare occasions, there may be a special need to 90 | encourage the widest possible use of a certain library, so that it becomes 91 | a de-facto standard. To achieve this, non-free programs must be 92 | allowed to use the library. A more frequent case is that a free 93 | library does the same job as widely used non-free libraries. In this 94 | case, there is little to gain by limiting the free library to free 95 | software only, so we use the Lesser General Public License. 96 | 97 | In other cases, permission to use a particular library in non-free 98 | programs enables a greater number of people to use a large body of 99 | free software. For example, permission to use the GNU C Library in 100 | non-free programs enables many more people to use the whole GNU 101 | operating system, as well as its variant, the GNU/Linux operating 102 | system. 103 | 104 | Although the Lesser General Public License is Less protective of the 105 | users' freedom, it does ensure that the user of a program that is 106 | linked with the Library has the freedom and the wherewithal to run 107 | that program using a modified version of the Library. 108 | 109 | The precise terms and conditions for copying, distribution and 110 | modification follow. Pay close attention to the difference between a 111 | "work based on the library" and a "work that uses the library". The 112 | former contains code derived from the library, whereas the latter must 113 | be combined with the library in order to run. 114 | 115 | GNU LESSER GENERAL PUBLIC LICENSE 116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 117 | 118 | 0. This License Agreement applies to any software library or other 119 | program which contains a notice placed by the copyright holder or 120 | other authorized party saying it may be distributed under the terms of 121 | this Lesser General Public License (also called "this License"). 122 | Each licensee is addressed as "you". 123 | 124 | A "library" means a collection of software functions and/or data 125 | prepared so as to be conveniently linked with application programs 126 | (which use some of those functions and data) to form executables. 127 | 128 | The "Library", below, refers to any such software library or work 129 | which has been distributed under these terms. A "work based on the 130 | Library" means either the Library or any derivative work under 131 | copyright law: that is to say, a work containing the Library or a 132 | portion of it, either verbatim or with modifications and/or translated 133 | straightforwardly into another language. (Hereinafter, translation is 134 | included without limitation in the term "modification".) 135 | 136 | "Source code" for a work means the preferred form of the work for 137 | making modifications to it. For a library, complete source code means 138 | all the source code for all modules it contains, plus any associated 139 | interface definition files, plus the scripts used to control compilation 140 | and installation of the library. 141 | 142 | Activities other than copying, distribution and modification are not 143 | covered by this License; they are outside its scope. The act of 144 | running a program using the Library is not restricted, and output from 145 | such a program is covered only if its contents constitute a work based 146 | on the Library (independent of the use of the Library in a tool for 147 | writing it). Whether that is true depends on what the Library does 148 | and what the program that uses the Library does. 149 | 150 | 1. You may copy and distribute verbatim copies of the Library's 151 | complete source code as you receive it, in any medium, provided that 152 | you conspicuously and appropriately publish on each copy an 153 | appropriate copyright notice and disclaimer of warranty; keep intact 154 | all the notices that refer to this License and to the absence of any 155 | warranty; and distribute a copy of this License along with the 156 | Library. 157 | 158 | You may charge a fee for the physical act of transferring a copy, 159 | and you may at your option offer warranty protection in exchange for a 160 | fee. 161 | 162 | 2. You may modify your copy or copies of the Library or any portion 163 | of it, thus forming a work based on the Library, and copy and 164 | distribute such modifications or work under the terms of Section 1 165 | above, provided that you also meet all of these conditions: 166 | 167 | a) The modified work must itself be a software library. 168 | 169 | b) You must cause the files modified to carry prominent notices 170 | stating that you changed the files and the date of any change. 171 | 172 | c) You must cause the whole of the work to be licensed at no 173 | charge to all third parties under the terms of this License. 174 | 175 | d) If a facility in the modified Library refers to a function or a 176 | table of data to be supplied by an application program that uses 177 | the facility, other than as an argument passed when the facility 178 | is invoked, then you must make a good faith effort to ensure that, 179 | in the event an application does not supply such function or 180 | table, the facility still operates, and performs whatever part of 181 | its purpose remains meaningful. 182 | 183 | (For example, a function in a library to compute square roots has 184 | a purpose that is entirely well-defined independent of the 185 | application. Therefore, Subsection 2d requires that any 186 | application-supplied function or table used by this function must 187 | be optional: if the application does not supply it, the square 188 | root function must still compute square roots.) 189 | 190 | These requirements apply to the modified work as a whole. If 191 | identifiable sections of that work are not derived from the Library, 192 | and can be reasonably considered independent and separate works in 193 | themselves, then this License, and its terms, do not apply to those 194 | sections when you distribute them as separate works. But when you 195 | distribute the same sections as part of a whole which is a work based 196 | on the Library, the distribution of the whole must be on the terms of 197 | this License, whose permissions for other licensees extend to the 198 | entire whole, and thus to each and every part regardless of who wrote 199 | it. 200 | 201 | Thus, it is not the intent of this section to claim rights or contest 202 | your rights to work written entirely by you; rather, the intent is to 203 | exercise the right to control the distribution of derivative or 204 | collective works based on the Library. 205 | 206 | In addition, mere aggregation of another work not based on the Library 207 | with the Library (or with a work based on the Library) on a volume of 208 | a storage or distribution medium does not bring the other work under 209 | the scope of this License. 210 | 211 | 3. You may opt to apply the terms of the ordinary GNU General Public 212 | License instead of this License to a given copy of the Library. To do 213 | this, you must alter all the notices that refer to this License, so 214 | that they refer to the ordinary GNU General Public License, version 2, 215 | instead of to this License. (If a newer version than version 2 of the 216 | ordinary GNU General Public License has appeared, then you can specify 217 | that version instead if you wish.) Do not make any other change in 218 | these notices. 219 | 220 | Once this change is made in a given copy, it is irreversible for 221 | that copy, so the ordinary GNU General Public License applies to all 222 | subsequent copies and derivative works made from that copy. 223 | 224 | This option is useful when you wish to copy part of the code of 225 | the Library into a program that is not a library. 226 | 227 | 4. You may copy and distribute the Library (or a portion or 228 | derivative of it, under Section 2) in object code or executable form 229 | under the terms of Sections 1 and 2 above provided that you accompany 230 | it with the complete corresponding machine-readable source code, which 231 | must be distributed under the terms of Sections 1 and 2 above on a 232 | medium customarily used for software interchange. 233 | 234 | If distribution of object code is made by offering access to copy 235 | from a designated place, then offering equivalent access to copy the 236 | source code from the same place satisfies the requirement to 237 | distribute the source code, even though third parties are not 238 | compelled to copy the source along with the object code. 239 | 240 | 5. A program that contains no derivative of any portion of the 241 | Library, but is designed to work with the Library by being compiled or 242 | linked with it, is called a "work that uses the Library". Such a 243 | work, in isolation, is not a derivative work of the Library, and 244 | therefore falls outside the scope of this License. 245 | 246 | However, linking a "work that uses the Library" with the Library 247 | creates an executable that is a derivative of the Library (because it 248 | contains portions of the Library), rather than a "work that uses the 249 | library". The executable is therefore covered by this License. 250 | Section 6 states terms for distribution of such executables. 251 | 252 | When a "work that uses the Library" uses material from a header file 253 | that is part of the Library, the object code for the work may be a 254 | derivative work of the Library even though the source code is not. 255 | Whether this is true is especially significant if the work can be 256 | linked without the Library, or if the work is itself a library. The 257 | threshold for this to be true is not precisely defined by law. 258 | 259 | If such an object file uses only numerical parameters, data 260 | structure layouts and accessors, and small macros and small inline 261 | functions (ten lines or less in length), then the use of the object 262 | file is unrestricted, regardless of whether it is legally a derivative 263 | work. (Executables containing this object code plus portions of the 264 | Library will still fall under Section 6.) 265 | 266 | Otherwise, if the work is a derivative of the Library, you may 267 | distribute the object code for the work under the terms of Section 6. 268 | Any executables containing that work also fall under Section 6, 269 | whether or not they are linked directly with the Library itself. 270 | 271 | 6. As an exception to the Sections above, you may also combine or 272 | link a "work that uses the Library" with the Library to produce a 273 | work containing portions of the Library, and distribute that work 274 | under terms of your choice, provided that the terms permit 275 | modification of the work for the customer's own use and reverse 276 | engineering for debugging such modifications. 277 | 278 | You must give prominent notice with each copy of the work that the 279 | Library is used in it and that the Library and its use are covered by 280 | this License. You must supply a copy of this License. If the work 281 | during execution displays copyright notices, you must include the 282 | copyright notice for the Library among them, as well as a reference 283 | directing the user to the copy of this License. Also, you must do one 284 | of these things: 285 | 286 | a) Accompany the work with the complete corresponding 287 | machine-readable source code for the Library including whatever 288 | changes were used in the work (which must be distributed under 289 | Sections 1 and 2 above); and, if the work is an executable linked 290 | with the Library, with the complete machine-readable "work that 291 | uses the Library", as object code and/or source code, so that the 292 | user can modify the Library and then relink to produce a modified 293 | executable containing the modified Library. (It is understood 294 | that the user who changes the contents of definitions files in the 295 | Library will not necessarily be able to recompile the application 296 | to use the modified definitions.) 297 | 298 | b) Use a suitable shared library mechanism for linking with the 299 | Library. A suitable mechanism is one that (1) uses at run time a 300 | copy of the library already present on the user's computer system, 301 | rather than copying library functions into the executable, and (2) 302 | will operate properly with a modified version of the library, if 303 | the user installs one, as long as the modified version is 304 | interface-compatible with the version that the work was made with. 305 | 306 | c) Accompany the work with a written offer, valid for at 307 | least three years, to give the same user the materials 308 | specified in Subsection 6a, above, for a charge no more 309 | than the cost of performing this distribution. 310 | 311 | d) If distribution of the work is made by offering access to copy 312 | from a designated place, offer equivalent access to copy the above 313 | specified materials from the same place. 314 | 315 | e) Verify that the user has already received a copy of these 316 | materials or that you have already sent this user a copy. 317 | 318 | For an executable, the required form of the "work that uses the 319 | Library" must include any data and utility programs needed for 320 | reproducing the executable from it. However, as a special exception, 321 | the materials to be distributed need not include anything that is 322 | normally distributed (in either source or binary form) with the major 323 | components (compiler, kernel, and so on) of the operating system on 324 | which the executable runs, unless that component itself accompanies 325 | the executable. 326 | 327 | It may happen that this requirement contradicts the license 328 | restrictions of other proprietary libraries that do not normally 329 | accompany the operating system. Such a contradiction means you cannot 330 | use both them and the Library together in an executable that you 331 | distribute. 332 | 333 | 7. You may place library facilities that are a work based on the 334 | Library side-by-side in a single library together with other library 335 | facilities not covered by this License, and distribute such a combined 336 | library, provided that the separate distribution of the work based on 337 | the Library and of the other library facilities is otherwise 338 | permitted, and provided that you do these two things: 339 | 340 | a) Accompany the combined library with a copy of the same work 341 | based on the Library, uncombined with any other library 342 | facilities. This must be distributed under the terms of the 343 | Sections above. 344 | 345 | b) Give prominent notice with the combined library of the fact 346 | that part of it is a work based on the Library, and explaining 347 | where to find the accompanying uncombined form of the same work. 348 | 349 | 8. You may not copy, modify, sublicense, link with, or distribute 350 | the Library except as expressly provided under this License. Any 351 | attempt otherwise to copy, modify, sublicense, link with, or 352 | distribute the Library is void, and will automatically terminate your 353 | rights under this License. However, parties who have received copies, 354 | or rights, from you under this License will not have their licenses 355 | terminated so long as such parties remain in full compliance. 356 | 357 | 9. You are not required to accept this License, since you have not 358 | signed it. However, nothing else grants you permission to modify or 359 | distribute the Library or its derivative works. These actions are 360 | prohibited by law if you do not accept this License. Therefore, by 361 | modifying or distributing the Library (or any work based on the 362 | Library), you indicate your acceptance of this License to do so, and 363 | all its terms and conditions for copying, distributing or modifying 364 | the Library or works based on it. 365 | 366 | 10. Each time you redistribute the Library (or any work based on the 367 | Library), the recipient automatically receives a license from the 368 | original licensor to copy, distribute, link with or modify the Library 369 | subject to these terms and conditions. You may not impose any further 370 | restrictions on the recipients' exercise of the rights granted herein. 371 | You are not responsible for enforcing compliance by third parties with 372 | this License. 373 | 374 | 11. If, as a consequence of a court judgment or allegation of patent 375 | infringement or for any other reason (not limited to patent issues), 376 | conditions are imposed on you (whether by court order, agreement or 377 | otherwise) that contradict the conditions of this License, they do not 378 | excuse you from the conditions of this License. If you cannot 379 | distribute so as to satisfy simultaneously your obligations under this 380 | License and any other pertinent obligations, then as a consequence you 381 | may not distribute the Library at all. For example, if a patent 382 | license would not permit royalty-free redistribution of the Library by 383 | all those who receive copies directly or indirectly through you, then 384 | the only way you could satisfy both it and this License would be to 385 | refrain entirely from distribution of the Library. 386 | 387 | If any portion of this section is held invalid or unenforceable under any 388 | particular circumstance, the balance of the section is intended to apply, 389 | and the section as a whole is intended to apply in other circumstances. 390 | 391 | It is not the purpose of this section to induce you to infringe any 392 | patents or other property right claims or to contest validity of any 393 | such claims; this section has the sole purpose of protecting the 394 | integrity of the free software distribution system which is 395 | implemented by public license practices. Many people have made 396 | generous contributions to the wide range of software distributed 397 | through that system in reliance on consistent application of that 398 | system; it is up to the author/donor to decide if he or she is willing 399 | to distribute software through any other system and a licensee cannot 400 | impose that choice. 401 | 402 | This section is intended to make thoroughly clear what is believed to 403 | be a consequence of the rest of this License. 404 | 405 | 12. If the distribution and/or use of the Library is restricted in 406 | certain countries either by patents or by copyrighted interfaces, the 407 | original copyright holder who places the Library under this License may add 408 | an explicit geographical distribution limitation excluding those countries, 409 | so that distribution is permitted only in or among countries not thus 410 | excluded. In such case, this License incorporates the limitation as if 411 | written in the body of this License. 412 | 413 | 13. The Free Software Foundation may publish revised and/or new 414 | versions of the Lesser General Public License from time to time. 415 | Such new versions will be similar in spirit to the present version, 416 | but may differ in detail to address new problems or concerns. 417 | 418 | Each version is given a distinguishing version number. If the Library 419 | specifies a version number of this License which applies to it and 420 | "any later version", you have the option of following the terms and 421 | conditions either of that version or of any later version published by 422 | the Free Software Foundation. If the Library does not specify a 423 | license version number, you may choose any version ever published by 424 | the Free Software Foundation. 425 | 426 | 14. If you wish to incorporate parts of the Library into other free 427 | programs whose distribution conditions are incompatible with these, 428 | write to the author to ask for permission. For software which is 429 | copyrighted by the Free Software Foundation, write to the Free 430 | Software Foundation; we sometimes make exceptions for this. Our 431 | decision will be guided by the two goals of preserving the free status 432 | of all derivatives of our free software and of promoting the sharing 433 | and reuse of software generally. 434 | 435 | NO WARRANTY 436 | 437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 446 | 447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 456 | DAMAGES. 457 | 458 | END OF TERMS AND CONDITIONS 459 | 460 | How to Apply These Terms to Your New Libraries 461 | 462 | If you develop a new library, and you want it to be of the greatest 463 | possible use to the public, we recommend making it free software that 464 | everyone can redistribute and change. You can do so by permitting 465 | redistribution under these terms (or, alternatively, under the terms of the 466 | ordinary General Public License). 467 | 468 | To apply these terms, attach the following notices to the library. It is 469 | safest to attach them to the start of each source file to most effectively 470 | convey the exclusion of warranty; and each file should have at least the 471 | "copyright" line and a pointer to where the full notice is found. 472 | 473 | 474 | Copyright (C) 475 | 476 | This library is free software; you can redistribute it and/or 477 | modify it under the terms of the GNU Lesser General Public 478 | License as published by the Free Software Foundation; either 479 | version 2.1 of the License, or (at your option) any later version. 480 | 481 | This library is distributed in the hope that it will be useful, 482 | but WITHOUT ANY WARRANTY; without even the implied warranty of 483 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 484 | Lesser General Public License for more details. 485 | 486 | You should have received a copy of the GNU Lesser General Public 487 | License along with this library; if not, write to the Free Software 488 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 489 | USA 490 | 491 | Also add information on how to contact you by electronic and paper mail. 492 | 493 | You should also get your employer (if you work as a programmer) or your 494 | school, if any, to sign a "copyright disclaimer" for the library, if 495 | necessary. Here is a sample; alter the names: 496 | 497 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 498 | library `Frob' (a library for tweaking knobs) written by James Random 499 | Hacker. 500 | 501 | , 1 April 1990 502 | Ty Coon, President of Vice 503 | 504 | That's all there is to it! 505 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### USB -> AXI Debug Bridge 2 | 3 | Github: [http://github.com/ultraembedded/core_usb_bridge](https://github.com/ultraembedded/core_usb_bridge) 4 | 5 | This component is a USB (CDC-ACM / USB Serial) to AXI4-Lite bus master bridge. 6 | This IP enumerates as a full speed (12Mbit/s) USB device which can then be used to read / write to memories / peripherals in your FPGA based SoC. 7 | 8 | The PHY / transceiver are built in requiring no additional external hardware other than a USB port connected to the FPGA I/Os. 9 | 10 | #### Cloning 11 | 12 | This repo contains submodules, and to clone them run the following command; 13 | 14 | ``` 15 | git clone --recursive https://github.com/ultraembedded/core_usb_bridge.git 16 | 17 | ``` 18 | 19 | #### Design Files 20 | ``` 21 | usb_bridge_top.v 22 | ├── usb_bridge 23 | │   └── src_v 24 | │   ├── usb_bridge_fifo.v 25 | │   └── usb_bridge.v 26 | ├── usb_cdc 27 | │   └── src_v 28 | │   ├── usb_cdc_core.v 29 | │   ├── usb_desc_rom.v 30 | │   ├── usbf_crc16.v 31 | │   ├── usbf_defs.v 32 | │   ├── usbf_device_core.v 33 | │   ├── usbf_sie_ep.v 34 | │   ├── usbf_sie_rx.v 35 | │   └── usbf_sie_tx.v 36 | └── usb_fs_phy 37 | └── src_v 38 | ├── usb_fs_phy.v 39 | └── usb_transceiver.v 40 | ``` 41 | 42 | #### Configuration / Requirements 43 | * Top: usb_bridge_top 44 | * Clock: clk_i - 48MHz 45 | * Reset: rst_i - Asynchronous, active high 46 | * VID/PID can be changed in usb_desc_rom.v 47 | 48 | #### Hardware 49 | 50 | Connection from your FPGA I/Os can be made simply using a breakout board; 51 | * [https://www.sparkfun.com/products/12035](https://www.sparkfun.com/products/12035) 52 | 53 | In order to enumerate as a USB FS device, there must be a pull-up on the D+ pin (but not on the D- pin). 54 | This can be achieved using the internal pull-ups on some FPGAs (though how reliable this is remains to be seen). 55 | 56 | Example constraints (Xilinx Vivado); 57 | ``` 58 | set_property -dict { PACKAGE_PIN N4 IOSTANDARD LVCMOS33 } [get_ports { usb_dp_io }]; # USB D+ 59 | set_property -dict { PACKAGE_PIN P3 IOSTANDARD LVCMOS33 } [get_ports { usb_dn_io }]; # USB D- 60 | set_property PULLUP TRUE [get_ports usb_dp_io] 61 | ``` 62 | 63 | For Xilinx FPGAs, pad pull-ups should be disabled before configuration is completed (PUDC_B). 64 | 65 | #### Software 66 | Included python based utils provide peek and poke access, plus binary load / dump support. 67 | 68 | Examples: 69 | ``` 70 | # Read a memory location (0x0) 71 | ./sw/peek.py -d /dev/ttyACM0 -a 0x0 72 | 73 | # Write a memory word (0x0 = 0x12345678) 74 | ./sw/poke.py -d /dev/ttyACM0 -a 0x0 -v 0x12345678 75 | ``` 76 | 77 | #### References 78 | * [USB Full Speed PHY](https://github.com/ultraembedded/core_usb_fs_phy) 79 | * [USB CDC Device](https://github.com/ultraembedded/core_usb_cdc) -------------------------------------------------------------------------------- /sw/bus_interface.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | from uart_bus_interface import * 4 | from socket_interface import * 5 | 6 | ################################################################## 7 | # BusInterface: Bus Interface Wrapper 8 | ################################################################## 9 | class BusInterface: 10 | ################################################################## 11 | # Construction 12 | ################################################################## 13 | def __init__(self, iface_type = 'uart', iface = '/dev/ttyUSB1', baud = 115200): 14 | if iface_type == "uart": 15 | self.bus = UartBusInterface(iface, baud) 16 | elif iface_type == "socket": 17 | self.bus = SocketInterface(iface) 18 | else: 19 | self.bus = None 20 | 21 | ################################################################## 22 | # set_progress_cb: Set progress callback 23 | ################################################################## 24 | def set_progress_cb(self, prog_cb): 25 | self.bus.set_progress_cb(prog_cb) 26 | 27 | ################################################################## 28 | # open: Open connection 29 | ################################################################## 30 | def open(self): 31 | pass 32 | 33 | ################################################################## 34 | # close: Close connection 35 | ################################################################## 36 | def close(self): 37 | pass 38 | 39 | ################################################################## 40 | # write: Write a block of data to a specified address 41 | ################################################################## 42 | def write(self, addr, data, length, addr_incr=True, max_block_size=-1): 43 | self.bus.write(addr, data, length, addr_incr, max_block_size) 44 | 45 | ################################################################## 46 | # read: Read a block of data from a specified address 47 | ################################################################## 48 | def read(self, addr, length, addr_incr=True, max_block_size=-1): 49 | return self.bus.read(addr, length, addr_incr, max_block_size) 50 | 51 | ################################################################## 52 | # read32: Read a word from a specified address 53 | ################################################################## 54 | def read32(self, addr): 55 | return self.bus.read32(addr) 56 | 57 | ################################################################## 58 | # write32: Write a word to a specified address 59 | ################################################################## 60 | def write32(self, addr, value): 61 | return self.bus.write32(addr, value) 62 | 63 | ################################################################## 64 | # read_gpio: Read GPIO bus 65 | ################################################################## 66 | def read_gpio(self): 67 | return self.bus.read_gpio() 68 | 69 | ################################################################## 70 | # write_gpio: Write a byte to GPIO 71 | ################################################################## 72 | def write_gpio(self, value): 73 | return self.bus.write_gpio(value) 74 | -------------------------------------------------------------------------------- /sw/dump.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import sys 3 | import argparse 4 | 5 | from bus_interface import * 6 | 7 | ################################################################## 8 | # Print iterations progress 9 | ################################################################## 10 | def print_progress(iteration, total, prefix='', suffix='', decimals=1, bar_length=50): 11 | str_format = "{0:." + str(decimals) + "f}" 12 | percents = str_format.format(100 * (iteration / float(total))) 13 | filled_length = int(round(bar_length * iteration / float(total))) 14 | bar = 'X' * filled_length + ' ' * (bar_length - filled_length) 15 | 16 | sys.stdout.write('\r%s |%s| %s%s %s' % (prefix, bar, percents, '%', suffix)), 17 | 18 | if iteration == total: 19 | sys.stdout.write('\n') 20 | sys.stdout.flush() 21 | 22 | ################################################################## 23 | # Main 24 | ################################################################## 25 | def main(argv): 26 | 27 | parser = argparse.ArgumentParser() 28 | parser.add_argument('-t', dest='type', default='uart', help='Device type (uart|socket)') 29 | parser.add_argument('-d', dest='device', default='/dev/ttyUSB1', help='Serial Device') 30 | parser.add_argument('-b', dest='baud', default=1000000, type=int, help='Baud rate') 31 | parser.add_argument('-o', dest='filename',required=True, help='Output filename') 32 | parser.add_argument('-a', dest='address', default="0", help='Address to dump from (default to 0x0)') 33 | parser.add_argument('-s', dest='size', required=True, type=int, help='Size to dump') 34 | args = parser.parse_args() 35 | 36 | bus_if = BusInterface(args.type, args.device, args.baud) 37 | bus_if.set_progress_cb(print_progress) 38 | 39 | addr = int(args.address, 0) 40 | print "Dump: %d bytes from 0x%08x" % (args.size, addr) 41 | 42 | # Read from target 43 | data = bus_if.read(addr, args.size) 44 | 45 | # Write to file 46 | file = open(args.filename, mode='wb') 47 | file.write(data) 48 | 49 | if __name__ == "__main__": 50 | main(sys.argv[1:]) -------------------------------------------------------------------------------- /sw/load_bin.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import sys 3 | import argparse 4 | 5 | from bus_interface import * 6 | 7 | ################################################################## 8 | # Print iterations progress 9 | ################################################################## 10 | def print_progress(iteration, total, prefix='', suffix='', decimals=1, bar_length=50): 11 | str_format = "{0:." + str(decimals) + "f}" 12 | percents = str_format.format(100 * (iteration / float(total))) 13 | filled_length = int(round(bar_length * iteration / float(total))) 14 | bar = 'X' * filled_length + ' ' * (bar_length - filled_length) 15 | 16 | sys.stdout.write('\r%s |%s| %s%s %s' % (prefix, bar, percents, '%', suffix)), 17 | 18 | if iteration == total: 19 | sys.stdout.write('\n') 20 | sys.stdout.flush() 21 | 22 | ################################################################## 23 | # Main 24 | ################################################################## 25 | def main(argv): 26 | 27 | parser = argparse.ArgumentParser() 28 | parser.add_argument('-t', dest='type', default='uart', help='Device type (uart|socket)') 29 | parser.add_argument('-d', dest='device', default='/dev/ttyUSB1', help='Serial Device') 30 | parser.add_argument('-b', dest='baud', default=1000000, type=int, help='Baud rate') 31 | parser.add_argument('-f', dest='filename',required=True, help='File to load') 32 | parser.add_argument('-a', dest='address', default="0", help='Address to write to (default to 0x0)') 33 | parser.add_argument('-s', dest='size', default=-1, type=int, help='Size override') 34 | parser.add_argument('-v', dest='verify', default=False, action='store_true', help='Verify write') 35 | args = parser.parse_args() 36 | 37 | bus_if = BusInterface(args.type, args.device, args.baud) 38 | bus_if.set_progress_cb(print_progress) 39 | 40 | # Open file 41 | file = open(args.filename, mode='rb') 42 | data = file.read() 43 | filesize = len(data) 44 | 45 | # Size override 46 | if args.size != -1 and filesize > args.size: 47 | filesize = args.size 48 | 49 | addr = int(args.address, 0) 50 | print("Load: %d bytes to 0x%08x" % (filesize, addr)) 51 | 52 | # Write to target 53 | bus_if.write(addr, data, filesize) 54 | 55 | # Verification 56 | if args.verify: 57 | print("Verify:") 58 | data_rb = bus_if.read(addr, filesize) 59 | 60 | for i in range(filesize): 61 | if sys.version_info[0] < 3: 62 | exp = ord(data[i]) & 0xFF 63 | else: 64 | exp = data[i] & 0xFF 65 | 66 | if data_rb[i] != exp: 67 | print("Data mismatches @ %d: %s != %d" % (addr + i, str(data_rb[i]), exp)) 68 | sys.exit(-1) 69 | 70 | print("Verify: Done") 71 | 72 | if __name__ == "__main__": 73 | main(sys.argv[1:]) 74 | 75 | -------------------------------------------------------------------------------- /sw/peek.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import sys 3 | import argparse 4 | 5 | from bus_interface import * 6 | 7 | ################################################################## 8 | # Main 9 | ################################################################## 10 | def main(argv): 11 | 12 | parser = argparse.ArgumentParser() 13 | parser.add_argument('-t', dest='type', default='uart', help='Device type (uart|socket)') 14 | parser.add_argument('-d', dest='device', default='/dev/ttyUSB1', help='Serial Device') 15 | parser.add_argument('-b', dest='baud', default=1000000, type=int, help='Baud rate') 16 | parser.add_argument('-a', dest='address',required=True, help='Address to read') 17 | parser.add_argument('-q', dest='quiet', action='store_true', default=False, help='Quiet mode - set exit code to read value') 18 | args = parser.parse_args() 19 | 20 | bus_if = BusInterface(args.type, args.device, args.baud) 21 | 22 | addr = int(args.address, 0) 23 | value = bus_if.read32(addr) 24 | 25 | if not args.quiet: 26 | print("%08x: 0x%08x (%d)" % (addr, value, value)) 27 | else: 28 | sys.exit(value) 29 | 30 | if __name__ == "__main__": 31 | main(sys.argv[1:]) -------------------------------------------------------------------------------- /sw/poke.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import sys 3 | import argparse 4 | 5 | from bus_interface import * 6 | 7 | ################################################################## 8 | # Main 9 | ################################################################## 10 | def main(argv): 11 | 12 | parser = argparse.ArgumentParser() 13 | parser.add_argument('-t', dest='type', default='uart', help='Device type (uart|socket)') 14 | parser.add_argument('-d', dest='device', default='/dev/ttyUSB1', help='Serial Device') 15 | parser.add_argument('-b', dest='baud', default=1000000, type=int, help='Baud rate') 16 | parser.add_argument('-a', dest='address',required=True, help='Address to write') 17 | parser.add_argument('-v', dest='value', required=True, help='Value to write') 18 | args = parser.parse_args() 19 | 20 | bus_if = BusInterface(args.type, args.device, args.baud) 21 | 22 | addr = int(args.address, 0) 23 | value = int(args.value, 0) 24 | 25 | bus_if.write32(addr, value) 26 | 27 | if __name__ == "__main__": 28 | main(sys.argv[1:]) 29 | -------------------------------------------------------------------------------- /sw/socket_interface.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import sys 3 | 4 | ################################################################## 5 | # SocketInterface: Socket -> Bus master 6 | ################################################################## 7 | class SocketInterface: 8 | ################################################################## 9 | # Construction 10 | ################################################################## 11 | def __init__(self, port_num = '2000'): 12 | self.server_addr = ('localhost', int(port_num)) 13 | self.sock = None 14 | self.prog_cb = None 15 | self.CMD_WRITE = 0x10 16 | self.CMD_READ = 0x11 17 | self.MAX_SIZE = 255 18 | self.BLOCK_SIZE = 128 19 | 20 | ################################################################## 21 | # set_progress_cb: Set progress callback 22 | ################################################################## 23 | def set_progress_cb(self, prog_cb): 24 | self.prog_cb = prog_cb 25 | 26 | ################################################################## 27 | # connect: Create socket 28 | ################################################################## 29 | def connect(self): 30 | self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 31 | 32 | ################################################################## 33 | # read32: Read a word from a specified address 34 | ################################################################## 35 | def read32(self, addr): 36 | # Connect if required 37 | if self.sock == None: 38 | self.connect() 39 | 40 | # Send read command 41 | cmd = bytearray([self.CMD_READ, 42 | 4, 43 | (addr >> 24) & 0xFF, 44 | (addr >> 16) & 0xFF, 45 | (addr >> 8) & 0xFF, 46 | (addr >> 0) & 0xFF]) 47 | self.sock.sendto(cmd, self.server_addr) 48 | 49 | value = 0 50 | idx = 0 51 | resp = self.sock.recv(4) 52 | for b in resp: 53 | value |= (ord(b) << (idx * 8)) 54 | idx += 1 55 | 56 | return value 57 | 58 | ################################################################## 59 | # write32: Write a word to a specified address 60 | ################################################################## 61 | def write32(self, addr, value): 62 | # Connect if required 63 | if self.sock == None: 64 | self.connect() 65 | 66 | # Send write command 67 | cmd = bytearray([self.CMD_WRITE, 68 | 4, 69 | (addr >> 24) & 0xFF, 70 | (addr >> 16) & 0xFF, 71 | (addr >> 8) & 0xFF, 72 | (addr >> 0) & 0xFF, 73 | (value >> 0) & 0xFF, 74 | (value >> 8) & 0xFF, 75 | (value >> 16) & 0xFF, 76 | (value >> 24) & 0xFF]) 77 | self.sock.sendto(cmd, self.server_addr) 78 | self.sock.recv(1) 79 | 80 | ################################################################## 81 | # write: Write a block of data to a specified address 82 | ################################################################## 83 | def write(self, addr, data, length, addr_incr=True, max_block_size=-1): 84 | # Connect if required 85 | if self.sock == None: 86 | self.connect() 87 | 88 | # Write blocks 89 | idx = 0 90 | remainder = length 91 | 92 | if self.prog_cb != None: 93 | self.prog_cb(0, length) 94 | 95 | if max_block_size == -1: 96 | max_block_size = self.BLOCK_SIZE 97 | 98 | while remainder > 0: 99 | l = max_block_size 100 | if l > remainder: 101 | l = remainder 102 | 103 | cmd = bytearray(2 + 4 + l) 104 | cmd[0] = self.CMD_WRITE 105 | cmd[1] = l & 0xFF 106 | cmd[2] = (addr >> 24) & 0xFF 107 | cmd[3] = (addr >> 16) & 0xFF 108 | cmd[4] = (addr >> 8) & 0xFF 109 | cmd[5] = (addr >> 0) & 0xFF 110 | 111 | for i in range(l): 112 | cmd[6+i] = data[idx] 113 | idx += 1 114 | 115 | # Write to serial port 116 | self.sock.sendto(cmd, self.server_addr) 117 | self.sock.recv(1) 118 | 119 | # Update display 120 | if self.prog_cb != None: 121 | self.prog_cb(idx, length) 122 | 123 | if addr_incr: 124 | addr += l 125 | remainder -= l 126 | 127 | ################################################################## 128 | # read: Read a block of data from a specified address 129 | ################################################################## 130 | def read(self, addr, length, addr_incr=True, max_block_size=-1): 131 | # Connect if required 132 | if self.sock == None: 133 | self.connect() 134 | 135 | idx = 0 136 | remainder = length 137 | data = bytearray(length) 138 | 139 | if self.prog_cb != None: 140 | self.prog_cb(0, length) 141 | 142 | if max_block_size == -1: 143 | max_block_size = self.BLOCK_SIZE 144 | 145 | while remainder > 0: 146 | l = max_block_size 147 | if l > remainder: 148 | l = remainder 149 | 150 | cmd = bytearray(2 + 4) 151 | cmd[0] = self.CMD_READ 152 | cmd[1] = l & 0xFF 153 | cmd[2] = (addr >> 24) & 0xFF 154 | cmd[3] = (addr >> 16) & 0xFF 155 | cmd[4] = (addr >> 8) & 0xFF 156 | cmd[5] = (addr >> 0) & 0xFF 157 | 158 | # Write to serial port 159 | self.sock.sendto(cmd, self.server_addr) 160 | 161 | # Read block response 162 | resp = self.sock.recv(l) 163 | for i in range(l): 164 | data[idx] = ord(resp[i]) & 0xFF 165 | idx += 1 166 | 167 | # Update display 168 | if self.prog_cb != None: 169 | self.prog_cb(idx, length) 170 | 171 | if addr_incr: 172 | addr += l 173 | remainder -= l 174 | 175 | return data 176 | 177 | ################################################################## 178 | # read_gpio: Read GPIO bus 179 | ################################################################## 180 | def read_gpio(self): 181 | return self.read32(0xF0000000) 182 | 183 | ################################################################## 184 | # write_gpio: Write a byte to GPIO 185 | ################################################################## 186 | def write_gpio(self, value): 187 | self.write32(0xF0000000, value) 188 | -------------------------------------------------------------------------------- /sw/uart_bus_interface.py: -------------------------------------------------------------------------------- 1 | import serial 2 | 3 | ################################################################## 4 | # UartBusInterface: UART -> Bus master interface 5 | ################################################################## 6 | class UartBusInterface: 7 | ################################################################## 8 | # Construction 9 | ################################################################## 10 | def __init__(self, iface = '/dev/ttyUSB1', baud = 115200): 11 | self.interface = iface 12 | self.baud = baud 13 | self.uart = None 14 | self.prog_cb = None 15 | self.CMD_WRITE = 0x10 16 | self.CMD_READ = 0x11 17 | self.MAX_SIZE = 255 18 | self.BLOCK_SIZE = 64-6 19 | self.GPIO_ADDR = 0xF0000000 20 | self.STS_ADDR = 0xF0000004 21 | 22 | ################################################################## 23 | # set_progress_cb: Set progress callback 24 | ################################################################## 25 | def set_progress_cb(self, prog_cb): 26 | self.prog_cb = prog_cb 27 | 28 | ################################################################## 29 | # connect: Open serial connection 30 | ################################################################## 31 | def connect(self): 32 | self.uart = serial.Serial( 33 | port=self.interface, 34 | baudrate=self.baud, 35 | parity=serial.PARITY_NONE, 36 | stopbits=serial.STOPBITS_ONE, 37 | bytesize=serial.EIGHTBITS 38 | ) 39 | self.uart.isOpen() 40 | 41 | ################################################################## 42 | # read32: Read a word from a specified address 43 | ################################################################## 44 | def read32(self, addr): 45 | # Connect if required 46 | if self.uart == None: 47 | self.connect() 48 | 49 | # Send read command 50 | cmd = bytearray([self.CMD_READ, 51 | 4, 52 | (addr >> 24) & 0xFF, 53 | (addr >> 16) & 0xFF, 54 | (addr >> 8) & 0xFF, 55 | (addr >> 0) & 0xFF]) 56 | self.uart.write(cmd) 57 | 58 | value = 0 59 | idx = 0 60 | while (idx < 4): 61 | b = self.uart.read(1) 62 | value |= (ord(b) << (idx * 8)) 63 | idx += 1 64 | 65 | return value 66 | 67 | ################################################################## 68 | # write32: Write a word to a specified address 69 | ################################################################## 70 | def write32(self, addr, value): 71 | # Connect if required 72 | if self.uart == None: 73 | self.connect() 74 | 75 | # Send write command 76 | cmd = bytearray([self.CMD_WRITE, 77 | 4, 78 | (addr >> 24) & 0xFF, 79 | (addr >> 16) & 0xFF, 80 | (addr >> 8) & 0xFF, 81 | (addr >> 0) & 0xFF, 82 | (value >> 0) & 0xFF, 83 | (value >> 8) & 0xFF, 84 | (value >> 16) & 0xFF, 85 | (value >> 24) & 0xFF]) 86 | self.uart.write(cmd) 87 | 88 | ################################################################## 89 | # write: Write a block of data to a specified address 90 | ################################################################## 91 | def write(self, addr, data, length, addr_incr=True, max_block_size=-1): 92 | # Connect if required 93 | if self.uart == None: 94 | self.connect() 95 | 96 | # Write blocks 97 | idx = 0 98 | remainder = length 99 | 100 | if self.prog_cb != None: 101 | self.prog_cb(0, length) 102 | 103 | if max_block_size == -1: 104 | max_block_size = self.BLOCK_SIZE 105 | 106 | while remainder > 0: 107 | l = max_block_size 108 | if l > remainder: 109 | l = remainder 110 | 111 | cmd = bytearray(2 + 4 + l) 112 | cmd[0] = self.CMD_WRITE 113 | cmd[1] = l & 0xFF 114 | cmd[2] = (addr >> 24) & 0xFF 115 | cmd[3] = (addr >> 16) & 0xFF 116 | cmd[4] = (addr >> 8) & 0xFF 117 | cmd[5] = (addr >> 0) & 0xFF 118 | 119 | for i in range(l): 120 | cmd[6+i] = data[idx] 121 | idx += 1 122 | 123 | # Write to serial port 124 | self.uart.write(cmd) 125 | 126 | # Update display 127 | if self.prog_cb != None: 128 | self.prog_cb(idx, length) 129 | 130 | if addr_incr: 131 | addr += l 132 | remainder -= l 133 | 134 | ################################################################## 135 | # read: Read a block of data from a specified address 136 | ################################################################## 137 | def read(self, addr, length, addr_incr=True, max_block_size=-1): 138 | # Connect if required 139 | if self.uart == None: 140 | self.connect() 141 | 142 | idx = 0 143 | remainder = length 144 | data = bytearray(length) 145 | 146 | if self.prog_cb != None: 147 | self.prog_cb(0, length) 148 | 149 | if max_block_size == -1: 150 | max_block_size = self.BLOCK_SIZE 151 | 152 | while remainder > 0: 153 | l = max_block_size 154 | if l > remainder: 155 | l = remainder 156 | 157 | cmd = bytearray(2 + 4) 158 | cmd[0] = self.CMD_READ 159 | cmd[1] = l & 0xFF 160 | cmd[2] = (addr >> 24) & 0xFF 161 | cmd[3] = (addr >> 16) & 0xFF 162 | cmd[4] = (addr >> 8) & 0xFF 163 | cmd[5] = (addr >> 0) & 0xFF 164 | 165 | # Write to serial port 166 | self.uart.write(cmd) 167 | 168 | # Read block response 169 | for i in range(l): 170 | data[idx] = ord(self.uart.read(1)) & 0xFF 171 | idx += 1 172 | 173 | # Update display 174 | if self.prog_cb != None: 175 | self.prog_cb(idx, length) 176 | 177 | if addr_incr: 178 | addr += l 179 | remainder -= l 180 | 181 | return data 182 | 183 | ################################################################## 184 | # read_gpio: Read GPIO bus 185 | ################################################################## 186 | def read_gpio(self): 187 | return self.read32(self.GPIO_ADDR) 188 | 189 | ################################################################## 190 | # write_gpio: Write a byte to GPIO 191 | ################################################################## 192 | def write_gpio(self, value): 193 | self.write32(self.GPIO_ADDR, value) 194 | -------------------------------------------------------------------------------- /usb_bridge/src_v/usb_bridge.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // USB to AXI Bridge 3 | // V0.1 4 | // Ultra-Embedded.com 5 | // Copyright 2019 6 | // 7 | // Email: admin@ultra-embedded.com 8 | // 9 | // License: LGPL 10 | //----------------------------------------------------------------- 11 | // 12 | // This source file may be used and distributed without 13 | // restriction provided that this copyright statement is not 14 | // removed from the file and that any derivative work contains 15 | // the original copyright notice and the associated disclaimer. 16 | // 17 | // This source file is free software; you can redistribute it 18 | // and/or modify it under the terms of the GNU Lesser General 19 | // Public License as published by the Free Software Foundation; 20 | // either version 2.1 of the License, or (at your option) any 21 | // later version. 22 | // 23 | // This source is distributed in the hope that it will be 24 | // useful, but WITHOUT ANY WARRANTY; without even the implied 25 | // warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 26 | // PURPOSE. See the GNU Lesser General Public License for more 27 | // details. 28 | // 29 | // You should have received a copy of the GNU Lesser General 30 | // Public License along with this source; if not, write to the 31 | // Free Software Foundation, Inc., 59 Temple Place, Suite 330, 32 | // Boston, MA 02111-1307 USA 33 | //----------------------------------------------------------------- 34 | 35 | //----------------------------------------------------------------- 36 | // Generated File 37 | //----------------------------------------------------------------- 38 | 39 | module usb_bridge 40 | ( 41 | // Inputs 42 | input clk_i 43 | ,input rst_i 44 | ,input [ 7:0] utmi_data_in_i 45 | ,input utmi_txready_i 46 | ,input utmi_rxvalid_i 47 | ,input utmi_rxactive_i 48 | ,input utmi_rxerror_i 49 | ,input [ 1:0] utmi_linestate_i 50 | ,input mem_awready_i 51 | ,input mem_wready_i 52 | ,input mem_bvalid_i 53 | ,input [ 1:0] mem_bresp_i 54 | ,input mem_arready_i 55 | ,input mem_rvalid_i 56 | ,input [ 31:0] mem_rdata_i 57 | ,input [ 1:0] mem_rresp_i 58 | 59 | // Outputs 60 | ,output [ 7:0] utmi_data_out_o 61 | ,output utmi_txvalid_o 62 | ,output [ 1:0] utmi_op_mode_o 63 | ,output [ 1:0] utmi_xcvrselect_o 64 | ,output utmi_termselect_o 65 | ,output utmi_dppulldown_o 66 | ,output utmi_dmpulldown_o 67 | ,output mem_awvalid_o 68 | ,output [ 31:0] mem_awaddr_o 69 | ,output mem_wvalid_o 70 | ,output [ 31:0] mem_wdata_o 71 | ,output [ 3:0] mem_wstrb_o 72 | ,output mem_bready_o 73 | ,output mem_arvalid_o 74 | ,output [ 31:0] mem_araddr_o 75 | ,output mem_rready_o 76 | ); 77 | 78 | 79 | 80 | //----------------------------------------------------------------- 81 | // Config 82 | //----------------------------------------------------------------- 83 | parameter CLK_FREQ = 48000000; 84 | parameter GPIO_ADDRESS = 32'hf0000000 + 32'h0; 85 | parameter STS_ADDRESS = 32'hf0000000 + 32'h4; 86 | parameter AXI_ID = 4'd0; 87 | 88 | //----------------------------------------------------------------- 89 | // Defines 90 | //----------------------------------------------------------------- 91 | localparam REQ_WRITE = 8'h10; 92 | localparam REQ_READ = 8'h11; 93 | 94 | `define STATE_W 4 95 | `define STATE_R 3:0 96 | localparam STATE_IDLE = 4'd0; 97 | localparam STATE_LEN = 4'd2; 98 | localparam STATE_ADDR0 = 4'd3; 99 | localparam STATE_ADDR1 = 4'd4; 100 | localparam STATE_ADDR2 = 4'd5; 101 | localparam STATE_ADDR3 = 4'd6; 102 | localparam STATE_WRITE = 4'd7; 103 | localparam STATE_READ = 4'd8; 104 | localparam STATE_DATA0 = 4'd9; 105 | localparam STATE_DATA1 = 4'd10; 106 | localparam STATE_DATA2 = 4'd11; 107 | localparam STATE_DATA3 = 4'd12; 108 | 109 | //----------------------------------------------------------------- 110 | // Wires / Regs 111 | //----------------------------------------------------------------- 112 | wire uart_wr_w; 113 | wire [7:0] uart_wr_data_w; 114 | wire uart_tx_pop_w; 115 | 116 | wire uart_rd_w; 117 | wire [7:0] uart_rd_data_w; 118 | wire uart_rd_valid_w; 119 | 120 | wire uart_rx_error_w; 121 | 122 | wire tx_valid_w; 123 | wire [7:0] tx_data_w; 124 | wire tx_accept_w; 125 | wire read_skip_w; 126 | 127 | wire rx_valid_w; 128 | wire [7:0] rx_data_w; 129 | wire rx_accept_w; 130 | 131 | reg [31:0] mem_addr_q; 132 | reg mem_busy_q; 133 | reg mem_wr_q; 134 | 135 | reg [7:0] len_q; 136 | 137 | // Byte Index 138 | reg [1:0] data_idx_q; 139 | 140 | // Word storage 141 | reg [31:0] data_q; 142 | 143 | wire magic_addr_w = (mem_addr_q == GPIO_ADDRESS || mem_addr_q == STS_ADDRESS); 144 | 145 | //----------------------------------------------------------------- 146 | // USB core 147 | //----------------------------------------------------------------- 148 | usb_cdc_core 149 | u_core 150 | ( 151 | .clk_i(clk_i), 152 | .rst_i(rst_i), 153 | 154 | .enable_i(1'b1), 155 | 156 | .utmi_data_in_i(utmi_data_in_i), 157 | .utmi_txready_i(utmi_txready_i), 158 | .utmi_rxvalid_i(utmi_rxvalid_i), 159 | .utmi_rxactive_i(utmi_rxactive_i), 160 | .utmi_rxerror_i(utmi_rxerror_i), 161 | .utmi_linestate_i(utmi_linestate_i), 162 | .utmi_data_out_o(utmi_data_out_o), 163 | .utmi_txvalid_o(utmi_txvalid_o), 164 | .utmi_op_mode_o(utmi_op_mode_o), 165 | .utmi_xcvrselect_o(utmi_xcvrselect_o), 166 | .utmi_termselect_o(utmi_termselect_o), 167 | .utmi_dppulldown_o(utmi_dppulldown_o), 168 | .utmi_dmpulldown_o(utmi_dmpulldown_o), 169 | 170 | // Device -> Host 171 | .inport_valid_i(uart_wr_w), 172 | .inport_data_i(uart_wr_data_w), 173 | .inport_accept_o(uart_tx_pop_w), 174 | 175 | // Host -> Device 176 | .outport_valid_o(uart_rd_valid_w), 177 | .outport_data_o(uart_rd_data_w), 178 | .outport_accept_i(uart_rd_w) 179 | ); 180 | 181 | 182 | //----------------------------------------------------------------- 183 | // Output FIFO 184 | //----------------------------------------------------------------- 185 | usb_bridge_fifo 186 | #( 187 | .WIDTH(8), 188 | .DEPTH(64), 189 | .ADDR_W(6) 190 | ) 191 | u_fifo_tx 192 | ( 193 | .clk_i(clk_i), 194 | .rst_i(rst_i), 195 | 196 | // In 197 | .push_i(tx_valid_w), 198 | .data_in_i(tx_data_w), 199 | .accept_o(tx_accept_w), 200 | 201 | // Out 202 | .pop_i(uart_tx_pop_w), 203 | .data_out_o(uart_wr_data_w), 204 | .valid_o(uart_wr_w) 205 | ); 206 | 207 | //----------------------------------------------------------------- 208 | // Input FIFO 209 | //----------------------------------------------------------------- 210 | usb_bridge_fifo 211 | #( 212 | .WIDTH(8), 213 | .DEPTH(64), 214 | .ADDR_W(6) 215 | ) 216 | u_fifo_rx 217 | ( 218 | .clk_i(clk_i), 219 | .rst_i(rst_i), 220 | 221 | // In 222 | .push_i(uart_rd_valid_w), 223 | .data_in_i(uart_rd_data_w), 224 | .accept_o(uart_rd_w), 225 | 226 | // Out 227 | .pop_i(rx_accept_w), 228 | .data_out_o(rx_data_w), 229 | .valid_o(rx_valid_w) 230 | ); 231 | 232 | //----------------------------------------------------------------- 233 | // States 234 | //----------------------------------------------------------------- 235 | reg [`STATE_R] state_q; 236 | reg [`STATE_R] next_state_r; 237 | 238 | always @ * 239 | begin 240 | next_state_r = state_q; 241 | 242 | case (next_state_r) 243 | //------------------------------------------------------------- 244 | // IDLE: 245 | //------------------------------------------------------------- 246 | STATE_IDLE: 247 | begin 248 | if (rx_valid_w) 249 | begin 250 | case (rx_data_w) 251 | REQ_WRITE, 252 | REQ_READ: 253 | next_state_r = STATE_LEN; 254 | default: 255 | ; 256 | endcase 257 | end 258 | end 259 | //----------------------------------------- 260 | // STATE_LEN 261 | //----------------------------------------- 262 | STATE_LEN : 263 | begin 264 | if (rx_valid_w) 265 | next_state_r = STATE_ADDR0; 266 | end 267 | //----------------------------------------- 268 | // STATE_ADDR 269 | //----------------------------------------- 270 | STATE_ADDR0 : if (rx_valid_w) next_state_r = STATE_ADDR1; 271 | STATE_ADDR1 : if (rx_valid_w) next_state_r = STATE_ADDR2; 272 | STATE_ADDR2 : if (rx_valid_w) next_state_r = STATE_ADDR3; 273 | STATE_ADDR3 : 274 | begin 275 | if (rx_valid_w && mem_wr_q) 276 | next_state_r = STATE_WRITE; 277 | else if (rx_valid_w) 278 | next_state_r = STATE_READ; 279 | end 280 | //----------------------------------------- 281 | // STATE_WRITE 282 | //----------------------------------------- 283 | STATE_WRITE : 284 | begin 285 | if (len_q == 8'b0 && (mem_bvalid_i || magic_addr_w)) 286 | next_state_r = STATE_IDLE; 287 | else 288 | next_state_r = STATE_WRITE; 289 | end 290 | //----------------------------------------- 291 | // STATE_READ 292 | //----------------------------------------- 293 | STATE_READ : 294 | begin 295 | // Data ready 296 | if (mem_rvalid_i || magic_addr_w) 297 | next_state_r = STATE_DATA0; 298 | end 299 | //----------------------------------------- 300 | // STATE_DATA 301 | //----------------------------------------- 302 | STATE_DATA0 : 303 | begin 304 | if (read_skip_w) 305 | next_state_r = STATE_DATA1; 306 | else if (tx_accept_w && (len_q == 8'b0)) 307 | next_state_r = STATE_IDLE; 308 | else if (tx_accept_w) 309 | next_state_r = STATE_DATA1; 310 | end 311 | STATE_DATA1 : 312 | begin 313 | if (read_skip_w) 314 | next_state_r = STATE_DATA2; 315 | else if (tx_accept_w && (len_q == 8'b0)) 316 | next_state_r = STATE_IDLE; 317 | else if (tx_accept_w) 318 | next_state_r = STATE_DATA2; 319 | end 320 | STATE_DATA2 : 321 | begin 322 | if (read_skip_w) 323 | next_state_r = STATE_DATA3; 324 | else if (tx_accept_w && (len_q == 8'b0)) 325 | next_state_r = STATE_IDLE; 326 | else if (tx_accept_w) 327 | next_state_r = STATE_DATA3; 328 | end 329 | STATE_DATA3 : 330 | begin 331 | if (tx_accept_w && (len_q != 8'b0)) 332 | next_state_r = STATE_READ; 333 | else if (tx_accept_w) 334 | next_state_r = STATE_IDLE; 335 | end 336 | default: 337 | ; 338 | endcase 339 | end 340 | 341 | // State storage 342 | always @ (posedge clk_i or posedge rst_i) 343 | if (rst_i) 344 | state_q <= STATE_IDLE; 345 | else 346 | state_q <= next_state_r; 347 | 348 | //----------------------------------------------------------------- 349 | // RD/WR to and from UART 350 | //----------------------------------------------------------------- 351 | 352 | // Write to UART Tx buffer in the following states 353 | assign tx_valid_w = ((state_q == STATE_DATA0) | 354 | (state_q == STATE_DATA1) | 355 | (state_q == STATE_DATA2) | 356 | (state_q == STATE_DATA3)) && !read_skip_w; 357 | 358 | // Accept data in the following states 359 | assign rx_accept_w = (state_q == STATE_IDLE) | 360 | (state_q == STATE_LEN) | 361 | (state_q == STATE_ADDR0) | 362 | (state_q == STATE_ADDR1) | 363 | (state_q == STATE_ADDR2) | 364 | (state_q == STATE_ADDR3) | 365 | (state_q == STATE_WRITE && !mem_busy_q); 366 | 367 | //----------------------------------------------------------------- 368 | // Capture length 369 | //----------------------------------------------------------------- 370 | always @ (posedge clk_i or posedge rst_i) 371 | if (rst_i) 372 | len_q <= 8'd0; 373 | else if (state_q == STATE_LEN && rx_valid_w) 374 | len_q[7:0] <= rx_data_w; 375 | else if (state_q == STATE_WRITE && rx_valid_w && !mem_busy_q) 376 | len_q <= len_q - 8'd1; 377 | else if (state_q == STATE_READ && ((mem_busy_q && mem_rvalid_i) || magic_addr_w)) 378 | len_q <= len_q - 8'd1; 379 | else if (((state_q == STATE_DATA0) || (state_q == STATE_DATA1) || (state_q == STATE_DATA2)) && (tx_accept_w && !read_skip_w)) 380 | len_q <= len_q - 8'd1; 381 | 382 | //----------------------------------------------------------------- 383 | // Capture addr 384 | //----------------------------------------------------------------- 385 | always @ (posedge clk_i or posedge rst_i) 386 | if (rst_i) 387 | mem_addr_q <= 'd0; 388 | else if (state_q == STATE_ADDR0 && rx_valid_w) 389 | mem_addr_q[31:24] <= rx_data_w; 390 | else if (state_q == STATE_ADDR1 && rx_valid_w) 391 | mem_addr_q[23:16] <= rx_data_w; 392 | else if (state_q == STATE_ADDR2 && rx_valid_w) 393 | mem_addr_q[15:8] <= rx_data_w; 394 | else if (state_q == STATE_ADDR3 && rx_valid_w) 395 | mem_addr_q[7:0] <= rx_data_w; 396 | // Address increment on every access issued 397 | else if (state_q == STATE_WRITE && (mem_busy_q && mem_bvalid_i)) 398 | mem_addr_q <= {mem_addr_q[31:2], 2'b0} + 'd4; 399 | else if (state_q == STATE_READ && (mem_busy_q && mem_rvalid_i)) 400 | mem_addr_q <= {mem_addr_q[31:2], 2'b0} + 'd4; 401 | 402 | //----------------------------------------------------------------- 403 | // Data Index 404 | //----------------------------------------------------------------- 405 | always @ (posedge clk_i or posedge rst_i) 406 | if (rst_i) 407 | data_idx_q <= 2'b0; 408 | else if (state_q == STATE_ADDR3) 409 | data_idx_q <= rx_data_w[1:0]; 410 | else if (state_q == STATE_WRITE && rx_valid_w && !mem_busy_q) 411 | data_idx_q <= data_idx_q + 2'd1; 412 | else if (((state_q == STATE_DATA0) || (state_q == STATE_DATA1) || (state_q == STATE_DATA2)) && tx_accept_w && (data_idx_q != 2'b0)) 413 | data_idx_q <= data_idx_q - 2'd1; 414 | 415 | assign read_skip_w = (data_idx_q != 2'b0); 416 | 417 | //----------------------------------------------------------------- 418 | // Data Sample 419 | //----------------------------------------------------------------- 420 | always @ (posedge clk_i or posedge rst_i) 421 | if (rst_i) 422 | data_q <= 32'b0; 423 | // Write to memory 424 | else if (state_q == STATE_WRITE && rx_valid_w && !mem_busy_q) 425 | begin 426 | case (data_idx_q) 427 | 2'd0: data_q[7:0] <= rx_data_w; 428 | 2'd1: data_q[15:8] <= rx_data_w; 429 | 2'd2: data_q[23:16] <= rx_data_w; 430 | 2'd3: data_q[31:24] <= rx_data_w; 431 | endcase 432 | end 433 | // Read from GPIO Input? 434 | else if (state_q == STATE_READ && mem_addr_q == GPIO_ADDRESS) 435 | begin 436 | data_q <= 32'b0; 437 | end 438 | // Read from status register? 439 | else if (state_q == STATE_READ && mem_addr_q == STS_ADDRESS) 440 | data_q <= {16'hcafe, 15'd0, mem_busy_q}; 441 | // Read from memory 442 | else if (state_q == STATE_READ && mem_rvalid_i) 443 | data_q <= mem_rdata_i; 444 | // Shift data out (read response -> UART) 445 | else if (((state_q == STATE_DATA0) || (state_q == STATE_DATA1) || (state_q == STATE_DATA2)) && (tx_accept_w || read_skip_w)) 446 | data_q <= {8'b0, data_q[31:8]}; 447 | 448 | assign tx_data_w = data_q[7:0]; 449 | 450 | assign mem_wdata_o = data_q; 451 | 452 | //----------------------------------------------------------------- 453 | // AXI: Write Request 454 | //----------------------------------------------------------------- 455 | reg mem_awvalid_q; 456 | reg mem_awvalid_r; 457 | 458 | reg mem_wvalid_q; 459 | reg mem_wvalid_r; 460 | 461 | always @ * 462 | begin 463 | mem_awvalid_r = 1'b0; 464 | mem_wvalid_r = 1'b0; 465 | 466 | // Hold 467 | if (mem_awvalid_o && !mem_awready_i) 468 | mem_awvalid_r = mem_awvalid_q; 469 | else if (mem_awvalid_o) 470 | mem_awvalid_r = 1'b0; 471 | // Every 4th byte, issue bus access 472 | else if (state_q == STATE_WRITE && rx_valid_w && (data_idx_q == 2'd3 || len_q == 1)) 473 | mem_awvalid_r = !magic_addr_w; 474 | 475 | // Hold 476 | if (mem_wvalid_o && !mem_wready_i) 477 | mem_wvalid_r = mem_wvalid_q; 478 | else if (mem_wvalid_o) 479 | mem_wvalid_r = 1'b0; 480 | // Every 4th byte, issue bus access 481 | else if (state_q == STATE_WRITE && rx_valid_w && (data_idx_q == 2'd3 || len_q == 1)) 482 | mem_wvalid_r = !magic_addr_w; 483 | end 484 | 485 | always @ (posedge clk_i or posedge rst_i) 486 | if (rst_i) 487 | begin 488 | mem_awvalid_q <= 1'b0; 489 | mem_wvalid_q <= 1'b0; 490 | end 491 | else 492 | begin 493 | mem_awvalid_q <= mem_awvalid_r; 494 | mem_wvalid_q <= mem_wvalid_r; 495 | end 496 | 497 | assign mem_awvalid_o = mem_awvalid_q; 498 | assign mem_wvalid_o = mem_wvalid_q; 499 | assign mem_awaddr_o = {mem_addr_q[31:2], 2'b0}; 500 | 501 | assign mem_bready_o = 1'b1; 502 | 503 | //----------------------------------------------------------------- 504 | // AXI: Read Request 505 | //----------------------------------------------------------------- 506 | reg mem_arvalid_q; 507 | reg mem_arvalid_r; 508 | 509 | always @ * 510 | begin 511 | mem_arvalid_r = 1'b0; 512 | 513 | // Hold 514 | if (mem_arvalid_o && !mem_arready_i) 515 | mem_arvalid_r = mem_arvalid_q; 516 | else if (mem_arvalid_o) 517 | mem_arvalid_r = 1'b0; 518 | else if (state_q == STATE_READ && !mem_busy_q) 519 | mem_arvalid_r = !magic_addr_w; 520 | end 521 | 522 | always @ (posedge clk_i or posedge rst_i) 523 | if (rst_i) 524 | mem_arvalid_q <= 1'b0; 525 | else 526 | mem_arvalid_q <= mem_arvalid_r; 527 | 528 | assign mem_arvalid_o = mem_arvalid_q; 529 | assign mem_araddr_o = {mem_addr_q[31:2], 2'b0}; 530 | 531 | assign mem_rready_o = 1'b1; 532 | 533 | //----------------------------------------------------------------- 534 | // Write mask 535 | //----------------------------------------------------------------- 536 | reg [3:0] mem_sel_q; 537 | reg [3:0] mem_sel_r; 538 | 539 | always @ * 540 | begin 541 | mem_sel_r = 4'b1111; 542 | 543 | case (data_idx_q) 544 | 2'd0: mem_sel_r = 4'b0001; 545 | 2'd1: mem_sel_r = 4'b0011; 546 | 2'd2: mem_sel_r = 4'b0111; 547 | 2'd3: mem_sel_r = 4'b1111; 548 | endcase 549 | 550 | case (mem_addr_q[1:0]) 551 | 2'd0: mem_sel_r = mem_sel_r & 4'b1111; 552 | 2'd1: mem_sel_r = mem_sel_r & 4'b1110; 553 | 2'd2: mem_sel_r = mem_sel_r & 4'b1100; 554 | 2'd3: mem_sel_r = mem_sel_r & 4'b1000; 555 | endcase 556 | end 557 | 558 | always @ (posedge clk_i or posedge rst_i) 559 | if (rst_i) 560 | mem_sel_q <= 4'b0; 561 | // Idle - reset for read requests 562 | else if (state_q == STATE_IDLE) 563 | mem_sel_q <= 4'b1111; 564 | // Every 4th byte, issue bus access 565 | else if (state_q == STATE_WRITE && rx_valid_w && (data_idx_q == 2'd3 || len_q == 8'd1)) 566 | mem_sel_q <= mem_sel_r; 567 | 568 | assign mem_wstrb_o = mem_sel_q; 569 | 570 | //----------------------------------------------------------------- 571 | // Write enable 572 | //----------------------------------------------------------------- 573 | always @ (posedge clk_i or posedge rst_i) 574 | if (rst_i) 575 | mem_wr_q <= 1'b0; 576 | else if (state_q == STATE_IDLE && rx_valid_w) 577 | mem_wr_q <= (rx_data_w == REQ_WRITE); 578 | 579 | //----------------------------------------------------------------- 580 | // Access in progress 581 | //----------------------------------------------------------------- 582 | always @ (posedge clk_i or posedge rst_i) 583 | if (rst_i == 1'b1) 584 | mem_busy_q <= 1'b0; 585 | else if (mem_arvalid_o || mem_awvalid_o) 586 | mem_busy_q <= 1'b1; 587 | else if (mem_bvalid_i || mem_rvalid_i) 588 | mem_busy_q <= 1'b0; 589 | 590 | 591 | 592 | endmodule 593 | -------------------------------------------------------------------------------- /usb_bridge/src_v/usb_bridge_fifo.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // USB to AXI Bridge 3 | // V0.1 4 | // Ultra-Embedded.com 5 | // Copyright 2019 6 | // 7 | // Email: admin@ultra-embedded.com 8 | // 9 | // License: LGPL 10 | //----------------------------------------------------------------- 11 | // 12 | // This source file may be used and distributed without 13 | // restriction provided that this copyright statement is not 14 | // removed from the file and that any derivative work contains 15 | // the original copyright notice and the associated disclaimer. 16 | // 17 | // This source file is free software; you can redistribute it 18 | // and/or modify it under the terms of the GNU Lesser General 19 | // Public License as published by the Free Software Foundation; 20 | // either version 2.1 of the License, or (at your option) any 21 | // later version. 22 | // 23 | // This source is distributed in the hope that it will be 24 | // useful, but WITHOUT ANY WARRANTY; without even the implied 25 | // warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 26 | // PURPOSE. See the GNU Lesser General Public License for more 27 | // details. 28 | // 29 | // You should have received a copy of the GNU Lesser General 30 | // Public License along with this source; if not, write to the 31 | // Free Software Foundation, Inc., 59 Temple Place, Suite 330, 32 | // Boston, MA 02111-1307 USA 33 | //----------------------------------------------------------------- 34 | 35 | //----------------------------------------------------------------- 36 | // Generated File 37 | //----------------------------------------------------------------- 38 | module usb_bridge_fifo 39 | //----------------------------------------------------------------- 40 | // Params 41 | //----------------------------------------------------------------- 42 | #( 43 | parameter WIDTH = 8, 44 | parameter DEPTH = 4, 45 | parameter ADDR_W = 2 46 | ) 47 | //----------------------------------------------------------------- 48 | // Ports 49 | //----------------------------------------------------------------- 50 | ( 51 | // Inputs 52 | input clk_i 53 | ,input rst_i 54 | ,input [WIDTH-1:0] data_in_i 55 | ,input push_i 56 | ,input pop_i 57 | 58 | // Outputs 59 | ,output [WIDTH-1:0] data_out_o 60 | ,output accept_o 61 | ,output valid_o 62 | ); 63 | 64 | //----------------------------------------------------------------- 65 | // Local Params 66 | //----------------------------------------------------------------- 67 | localparam COUNT_W = ADDR_W + 1; 68 | 69 | //----------------------------------------------------------------- 70 | // Registers 71 | //----------------------------------------------------------------- 72 | reg [WIDTH-1:0] ram_q[DEPTH-1:0]; 73 | reg [ADDR_W-1:0] rd_ptr_q; 74 | reg [ADDR_W-1:0] wr_ptr_q; 75 | reg [COUNT_W-1:0] count_q; 76 | 77 | //----------------------------------------------------------------- 78 | // Sequential 79 | //----------------------------------------------------------------- 80 | always @ (posedge clk_i or posedge rst_i) 81 | if (rst_i) 82 | begin 83 | count_q <= {(COUNT_W) {1'b0}}; 84 | rd_ptr_q <= {(ADDR_W) {1'b0}}; 85 | wr_ptr_q <= {(ADDR_W) {1'b0}}; 86 | end 87 | else 88 | begin 89 | // Push 90 | if (push_i & accept_o) 91 | begin 92 | ram_q[wr_ptr_q] <= data_in_i; 93 | wr_ptr_q <= wr_ptr_q + 1; 94 | end 95 | 96 | // Pop 97 | if (pop_i & valid_o) 98 | rd_ptr_q <= rd_ptr_q + 1; 99 | 100 | // Count up 101 | if ((push_i & accept_o) & ~(pop_i & valid_o)) 102 | count_q <= count_q + 1; 103 | // Count down 104 | else if (~(push_i & accept_o) & (pop_i & valid_o)) 105 | count_q <= count_q - 1; 106 | end 107 | 108 | //------------------------------------------------------------------- 109 | // Combinatorial 110 | //------------------------------------------------------------------- 111 | /* verilator lint_off WIDTH */ 112 | assign valid_o = (count_q != 0); 113 | assign accept_o = (count_q != DEPTH); 114 | /* verilator lint_on WIDTH */ 115 | 116 | assign data_out_o = ram_q[rd_ptr_q]; 117 | 118 | endmodule 119 | -------------------------------------------------------------------------------- /usb_bridge_top.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // USB to AXI Bridge 3 | // V0.1 4 | // Ultra-Embedded.com 5 | // Copyright 2019 6 | // 7 | // Email: admin@ultra-embedded.com 8 | // 9 | // License: LGPL 10 | //----------------------------------------------------------------- 11 | // 12 | // This source file may be used and distributed without 13 | // restriction provided that this copyright statement is not 14 | // removed from the file and that any derivative work contains 15 | // the original copyright notice and the associated disclaimer. 16 | // 17 | // This source file is free software; you can redistribute it 18 | // and/or modify it under the terms of the GNU Lesser General 19 | // Public License as published by the Free Software Foundation; 20 | // either version 2.1 of the License, or (at your option) any 21 | // later version. 22 | // 23 | // This source is distributed in the hope that it will be 24 | // useful, but WITHOUT ANY WARRANTY; without even the implied 25 | // warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 26 | // PURPOSE. See the GNU Lesser General Public License for more 27 | // details. 28 | // 29 | // You should have received a copy of the GNU Lesser General 30 | // Public License along with this source; if not, write to the 31 | // Free Software Foundation, Inc., 59 Temple Place, Suite 330, 32 | // Boston, MA 02111-1307 USA 33 | //----------------------------------------------------------------- 34 | module usb_bridge_top 35 | ( 36 | // Inputs 37 | input clk_i 38 | ,input rst_i 39 | ,input axi_awready_i 40 | ,input axi_wready_i 41 | ,input axi_bvalid_i 42 | ,input [ 1:0] axi_bresp_i 43 | ,input axi_arready_i 44 | ,input axi_rvalid_i 45 | ,input [ 31:0] axi_rdata_i 46 | ,input [ 1:0] axi_rresp_i 47 | 48 | // Outputs 49 | ,output axi_awvalid_o 50 | ,output [ 31:0] axi_awaddr_o 51 | ,output axi_wvalid_o 52 | ,output [ 31:0] axi_wdata_o 53 | ,output [ 3:0] axi_wstrb_o 54 | ,output axi_bready_o 55 | ,output axi_arvalid_o 56 | ,output [ 31:0] axi_araddr_o 57 | ,output axi_rready_o 58 | 59 | // USB D+/D- 60 | ,inout usb_dp_io 61 | ,inout usb_dn_io 62 | ); 63 | 64 | wire [ 7:0] utmi_data_out_w; 65 | wire utmi_rxvalid_w; 66 | wire [ 1:0] utmi_linestate_w; 67 | wire usb_pads_tx_dp_w; 68 | wire [ 1:0] utmi_xcvrselect_w; 69 | wire utmi_termselect_w; 70 | wire usb_pads_tx_oen_w; 71 | wire usb_pads_rx_dn_w; 72 | wire [ 1:0] utmi_op_mode_w; 73 | wire [ 7:0] utmi_data_in_w; 74 | wire usb_pads_tx_dn_w; 75 | wire utmi_rxerror_w; 76 | wire utmi_rxactive_w; 77 | wire usb_pads_rx_rcv_w; 78 | wire usb_pads_rx_dp_w; 79 | wire utmi_dppulldown_w; 80 | wire usb_xcvr_mode_w = 1'h1; 81 | wire utmi_txready_w; 82 | wire utmi_txvalid_w; 83 | wire utmi_dmpulldown_w; 84 | 85 | 86 | usb_bridge u_usb 87 | ( 88 | // Inputs 89 | .clk_i(clk_i) 90 | ,.rst_i(rst_i) 91 | ,.utmi_data_in_i(utmi_data_in_w) 92 | ,.utmi_txready_i(utmi_txready_w) 93 | ,.utmi_rxvalid_i(utmi_rxvalid_w) 94 | ,.utmi_rxactive_i(utmi_rxactive_w) 95 | ,.utmi_rxerror_i(utmi_rxerror_w) 96 | ,.utmi_linestate_i(utmi_linestate_w) 97 | ,.mem_awready_i(axi_awready_i) 98 | ,.mem_wready_i(axi_wready_i) 99 | ,.mem_bvalid_i(axi_bvalid_i) 100 | ,.mem_bresp_i(axi_bresp_i) 101 | ,.mem_arready_i(axi_arready_i) 102 | ,.mem_rvalid_i(axi_rvalid_i) 103 | ,.mem_rdata_i(axi_rdata_i) 104 | ,.mem_rresp_i(axi_rresp_i) 105 | 106 | // Outputs 107 | ,.utmi_data_out_o(utmi_data_out_w) 108 | ,.utmi_txvalid_o(utmi_txvalid_w) 109 | ,.utmi_op_mode_o(utmi_op_mode_w) 110 | ,.utmi_xcvrselect_o(utmi_xcvrselect_w) 111 | ,.utmi_termselect_o(utmi_termselect_w) 112 | ,.utmi_dppulldown_o(utmi_dppulldown_w) 113 | ,.utmi_dmpulldown_o(utmi_dmpulldown_w) 114 | ,.mem_awvalid_o(axi_awvalid_o) 115 | ,.mem_awaddr_o(axi_awaddr_o) 116 | ,.mem_wvalid_o(axi_wvalid_o) 117 | ,.mem_wdata_o(axi_wdata_o) 118 | ,.mem_wstrb_o(axi_wstrb_o) 119 | ,.mem_bready_o(axi_bready_o) 120 | ,.mem_arvalid_o(axi_arvalid_o) 121 | ,.mem_araddr_o(axi_araddr_o) 122 | ,.mem_rready_o(axi_rready_o) 123 | ); 124 | 125 | 126 | usb_transceiver u_usb_xcvr 127 | ( 128 | // Inputs 129 | .usb_phy_tx_dp_i(usb_pads_tx_dp_w) 130 | ,.usb_phy_tx_dn_i(usb_pads_tx_dn_w) 131 | ,.usb_phy_tx_oen_i(usb_pads_tx_oen_w) 132 | ,.mode_i(usb_xcvr_mode_w) 133 | 134 | // Outputs 135 | ,.usb_dp_io(usb_dp_io) 136 | ,.usb_dn_io(usb_dn_io) 137 | ,.usb_phy_rx_rcv_o(usb_pads_rx_rcv_w) 138 | ,.usb_phy_rx_dp_o(usb_pads_rx_dp_w) 139 | ,.usb_phy_rx_dn_o(usb_pads_rx_dn_w) 140 | ); 141 | 142 | 143 | usb_fs_phy u_usb_phy 144 | ( 145 | // Inputs 146 | .clk_i(clk_i) 147 | ,.rst_i(rst_i) 148 | ,.utmi_data_out_i(utmi_data_out_w) 149 | ,.utmi_txvalid_i(utmi_txvalid_w) 150 | ,.utmi_op_mode_i(utmi_op_mode_w) 151 | ,.utmi_xcvrselect_i(utmi_xcvrselect_w) 152 | ,.utmi_termselect_i(utmi_termselect_w) 153 | ,.utmi_dppulldown_i(utmi_dppulldown_w) 154 | ,.utmi_dmpulldown_i(utmi_dmpulldown_w) 155 | ,.usb_rx_rcv_i(usb_pads_rx_rcv_w) 156 | ,.usb_rx_dp_i(usb_pads_rx_dp_w) 157 | ,.usb_rx_dn_i(usb_pads_rx_dn_w) 158 | ,.usb_reset_assert_i(1'b0) 159 | 160 | // Outputs 161 | ,.utmi_data_in_o(utmi_data_in_w) 162 | ,.utmi_txready_o(utmi_txready_w) 163 | ,.utmi_rxvalid_o(utmi_rxvalid_w) 164 | ,.utmi_rxactive_o(utmi_rxactive_w) 165 | ,.utmi_rxerror_o(utmi_rxerror_w) 166 | ,.utmi_linestate_o(utmi_linestate_w) 167 | ,.usb_tx_dp_o(usb_pads_tx_dp_w) 168 | ,.usb_tx_dn_o(usb_pads_tx_dn_w) 169 | ,.usb_tx_oen_o(usb_pads_tx_oen_w) 170 | ,.usb_reset_detect_o() 171 | ,.usb_en_o() 172 | ); 173 | 174 | endmodule 175 | --------------------------------------------------------------------------------