├── LICENSE ├── README.md ├── src_v ├── dbg_bridge.v ├── dbg_bridge_fifo.v └── dbg_bridge_uart.v └── sw ├── bus_interface.py ├── dump.py ├── load_bin.py ├── peek.py ├── poke.py ├── socket_interface.py └── uart_bus_interface.py /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 | ### UART -> AXI Debug Bridge 2 | 3 | Github: [http://github.com/ultraembedded/cores](https://github.com/ultraembedded/cores/tree/master/dbg_bridge) 4 | 5 | This component provides a bridge from a standard UART interface (8N1) to a AXI4 bus master & GPIO interface. 6 | This can be very useful for FPGA dev boards featuring a FTDI UART interface where loading memories, peeking, poking SoC state is required. 7 | 8 | ##### Testing 9 | 10 | Used extensively on various Xilinx FPGAs over the years. 11 | 12 | ##### Configuration 13 | * CLK_FREQ - Clock (clk_i) frequency (in Hz). 14 | * UART_SPEED - UART baud rate (bps) 15 | * AXI_ID - AXI ID to be used for transactions 16 | 17 | ##### Software 18 | Included python based utils provide peek and poke access, plus binary load / dump support. 19 | 20 | Examples: 21 | ``` 22 | # Read a memory location (0x0) 23 | ./sw/peek.py -d /dev/ttyUSB1 -b 115200 -a 0x0 24 | 25 | # Write a memory word (0x0 = 0x12345678) 26 | ./sw/poke.py -d /dev/ttyUSB1 -b 115200 -a 0x0 -v 0x12345678 27 | ``` -------------------------------------------------------------------------------- /src_v/dbg_bridge.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // UART -> AXI Debug Bridge 3 | // V1.0 4 | // Ultra-Embedded.com 5 | // Copyright 2017-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 dbg_bridge 40 | //----------------------------------------------------------------- 41 | // Params 42 | //----------------------------------------------------------------- 43 | #( 44 | parameter CLK_FREQ = 14745600 45 | ,parameter UART_SPEED = 115200 46 | ,parameter AXI_ID = 4'd0 47 | ,parameter GPIO_ADDRESS = 32'hf0000000 48 | ,parameter STS_ADDRESS = 32'hf0000004 49 | ) 50 | //----------------------------------------------------------------- 51 | // Ports 52 | //----------------------------------------------------------------- 53 | ( 54 | // Inputs 55 | input clk_i 56 | ,input rst_i 57 | ,input uart_rxd_i 58 | ,input mem_awready_i 59 | ,input mem_wready_i 60 | ,input mem_bvalid_i 61 | ,input [ 1:0] mem_bresp_i 62 | ,input [ 3:0] mem_bid_i 63 | ,input mem_arready_i 64 | ,input mem_rvalid_i 65 | ,input [ 31:0] mem_rdata_i 66 | ,input [ 1:0] mem_rresp_i 67 | ,input [ 3:0] mem_rid_i 68 | ,input mem_rlast_i 69 | ,input [ 31:0] gpio_inputs_i 70 | 71 | // Outputs 72 | ,output uart_txd_o 73 | ,output mem_awvalid_o 74 | ,output [ 31:0] mem_awaddr_o 75 | ,output [ 3:0] mem_awid_o 76 | ,output [ 7:0] mem_awlen_o 77 | ,output [ 1:0] mem_awburst_o 78 | ,output mem_wvalid_o 79 | ,output [ 31:0] mem_wdata_o 80 | ,output [ 3:0] mem_wstrb_o 81 | ,output mem_wlast_o 82 | ,output mem_bready_o 83 | ,output mem_arvalid_o 84 | ,output [ 31:0] mem_araddr_o 85 | ,output [ 3:0] mem_arid_o 86 | ,output [ 7:0] mem_arlen_o 87 | ,output [ 1:0] mem_arburst_o 88 | ,output mem_rready_o 89 | ,output [ 31:0] gpio_outputs_o 90 | ); 91 | 92 | 93 | 94 | //----------------------------------------------------------------- 95 | // Defines 96 | //----------------------------------------------------------------- 97 | localparam REQ_WRITE = 8'h10; 98 | localparam REQ_READ = 8'h11; 99 | 100 | `define STATE_W 4 101 | `define STATE_R 3:0 102 | localparam STATE_IDLE = 4'd0; 103 | localparam STATE_LEN = 4'd2; 104 | localparam STATE_ADDR0 = 4'd3; 105 | localparam STATE_ADDR1 = 4'd4; 106 | localparam STATE_ADDR2 = 4'd5; 107 | localparam STATE_ADDR3 = 4'd6; 108 | localparam STATE_WRITE = 4'd7; 109 | localparam STATE_READ = 4'd8; 110 | localparam STATE_DATA0 = 4'd9; 111 | localparam STATE_DATA1 = 4'd10; 112 | localparam STATE_DATA2 = 4'd11; 113 | localparam STATE_DATA3 = 4'd12; 114 | 115 | //----------------------------------------------------------------- 116 | // Wires / Regs 117 | //----------------------------------------------------------------- 118 | wire uart_wr_w; 119 | wire [7:0] uart_wr_data_w; 120 | wire uart_wr_busy_w; 121 | 122 | wire uart_rd_w; 123 | wire [7:0] uart_rd_data_w; 124 | wire uart_rd_valid_w; 125 | 126 | wire uart_rx_error_w; 127 | 128 | wire tx_valid_w; 129 | wire [7:0] tx_data_w; 130 | wire tx_accept_w; 131 | wire read_skip_w; 132 | 133 | wire rx_valid_w; 134 | wire [7:0] rx_data_w; 135 | wire rx_accept_w; 136 | 137 | reg [31:0] mem_addr_q; 138 | reg mem_busy_q; 139 | reg mem_wr_q; 140 | 141 | reg [7:0] len_q; 142 | 143 | // Byte Index 144 | reg [1:0] data_idx_q; 145 | 146 | // Word storage 147 | reg [31:0] data_q; 148 | 149 | wire magic_addr_w = (mem_addr_q == GPIO_ADDRESS || mem_addr_q == STS_ADDRESS); 150 | 151 | //----------------------------------------------------------------- 152 | // UART core 153 | //----------------------------------------------------------------- 154 | dbg_bridge_uart 155 | #( .UART_DIVISOR_W(32) ) 156 | u_uart 157 | ( 158 | .clk_i(clk_i), 159 | .rst_i(rst_i), 160 | 161 | // Control 162 | .bit_div_i((CLK_FREQ / UART_SPEED) - 1), 163 | .stop_bits_i(1'b0), // 0 = 1, 1 = 2 164 | 165 | // Transmit 166 | .wr_i(uart_wr_w), 167 | .data_i(uart_wr_data_w), 168 | .tx_busy_o(uart_wr_busy_w), 169 | 170 | // Receive 171 | .rd_i(uart_rd_w), 172 | .data_o(uart_rd_data_w), 173 | .rx_ready_o(uart_rd_valid_w), 174 | 175 | .rx_err_o(uart_rx_error_w), 176 | 177 | // UART pins 178 | .rxd_i(uart_rxd_i), 179 | .txd_o(uart_txd_o) 180 | ); 181 | 182 | //----------------------------------------------------------------- 183 | // Output FIFO 184 | //----------------------------------------------------------------- 185 | wire uart_tx_pop_w = ~uart_wr_busy_w; 186 | 187 | dbg_bridge_fifo 188 | #( 189 | .WIDTH(8), 190 | .DEPTH(8), 191 | .ADDR_W(3) 192 | ) 193 | u_fifo_tx 194 | ( 195 | .clk_i(clk_i), 196 | .rst_i(rst_i), 197 | 198 | // In 199 | .push_i(tx_valid_w), 200 | .data_in_i(tx_data_w), 201 | .accept_o(tx_accept_w), 202 | 203 | // Out 204 | .pop_i(uart_tx_pop_w), 205 | .data_out_o(uart_wr_data_w), 206 | .valid_o(uart_wr_w) 207 | ); 208 | 209 | //----------------------------------------------------------------- 210 | // Input FIFO 211 | //----------------------------------------------------------------- 212 | dbg_bridge_fifo 213 | #( 214 | .WIDTH(8), 215 | .DEPTH(8), 216 | .ADDR_W(3) 217 | ) 218 | u_fifo_rx 219 | ( 220 | .clk_i(clk_i), 221 | .rst_i(rst_i), 222 | 223 | // In 224 | .push_i(uart_rd_valid_w), 225 | .data_in_i(uart_rd_data_w), 226 | .accept_o(uart_rd_w), 227 | 228 | // Out 229 | .pop_i(rx_accept_w), 230 | .data_out_o(rx_data_w), 231 | .valid_o(rx_valid_w) 232 | ); 233 | 234 | //----------------------------------------------------------------- 235 | // States 236 | //----------------------------------------------------------------- 237 | reg [`STATE_R] state_q; 238 | reg [`STATE_R] next_state_r; 239 | 240 | always @ * 241 | begin 242 | next_state_r = state_q; 243 | 244 | case (next_state_r) 245 | //------------------------------------------------------------- 246 | // IDLE: 247 | //------------------------------------------------------------- 248 | STATE_IDLE: 249 | begin 250 | if (rx_valid_w) 251 | begin 252 | case (rx_data_w) 253 | REQ_WRITE, 254 | REQ_READ: 255 | next_state_r = STATE_LEN; 256 | default: 257 | ; 258 | endcase 259 | end 260 | end 261 | //----------------------------------------- 262 | // STATE_LEN 263 | //----------------------------------------- 264 | STATE_LEN : 265 | begin 266 | if (rx_valid_w) 267 | next_state_r = STATE_ADDR0; 268 | end 269 | //----------------------------------------- 270 | // STATE_ADDR 271 | //----------------------------------------- 272 | STATE_ADDR0 : if (rx_valid_w) next_state_r = STATE_ADDR1; 273 | STATE_ADDR1 : if (rx_valid_w) next_state_r = STATE_ADDR2; 274 | STATE_ADDR2 : if (rx_valid_w) next_state_r = STATE_ADDR3; 275 | STATE_ADDR3 : 276 | begin 277 | if (rx_valid_w && mem_wr_q) 278 | next_state_r = STATE_WRITE; 279 | else if (rx_valid_w) 280 | next_state_r = STATE_READ; 281 | end 282 | //----------------------------------------- 283 | // STATE_WRITE 284 | //----------------------------------------- 285 | STATE_WRITE : 286 | begin 287 | if (len_q == 8'b0 && (mem_bvalid_i || magic_addr_w)) 288 | next_state_r = STATE_IDLE; 289 | else 290 | next_state_r = STATE_WRITE; 291 | end 292 | //----------------------------------------- 293 | // STATE_READ 294 | //----------------------------------------- 295 | STATE_READ : 296 | begin 297 | // Data ready 298 | if (mem_rvalid_i || magic_addr_w) 299 | next_state_r = STATE_DATA0; 300 | end 301 | //----------------------------------------- 302 | // STATE_DATA 303 | //----------------------------------------- 304 | STATE_DATA0 : 305 | begin 306 | if (read_skip_w) 307 | next_state_r = STATE_DATA1; 308 | else if (tx_accept_w && (len_q == 8'b0)) 309 | next_state_r = STATE_IDLE; 310 | else if (tx_accept_w) 311 | next_state_r = STATE_DATA1; 312 | end 313 | STATE_DATA1 : 314 | begin 315 | if (read_skip_w) 316 | next_state_r = STATE_DATA2; 317 | else if (tx_accept_w && (len_q == 8'b0)) 318 | next_state_r = STATE_IDLE; 319 | else if (tx_accept_w) 320 | next_state_r = STATE_DATA2; 321 | end 322 | STATE_DATA2 : 323 | begin 324 | if (read_skip_w) 325 | next_state_r = STATE_DATA3; 326 | else if (tx_accept_w && (len_q == 8'b0)) 327 | next_state_r = STATE_IDLE; 328 | else if (tx_accept_w) 329 | next_state_r = STATE_DATA3; 330 | end 331 | STATE_DATA3 : 332 | begin 333 | if (tx_accept_w && (len_q != 8'b0)) 334 | next_state_r = STATE_READ; 335 | else if (tx_accept_w) 336 | next_state_r = STATE_IDLE; 337 | end 338 | default: 339 | ; 340 | endcase 341 | end 342 | 343 | // State storage 344 | always @ (posedge clk_i or posedge rst_i) 345 | if (rst_i) 346 | state_q <= STATE_IDLE; 347 | else 348 | state_q <= next_state_r; 349 | 350 | //----------------------------------------------------------------- 351 | // RD/WR to and from UART 352 | //----------------------------------------------------------------- 353 | 354 | // Write to UART Tx buffer in the following states 355 | assign tx_valid_w = ((state_q == STATE_DATA0) | 356 | (state_q == STATE_DATA1) | 357 | (state_q == STATE_DATA2) | 358 | (state_q == STATE_DATA3)) && !read_skip_w; 359 | 360 | // Accept data in the following states 361 | assign rx_accept_w = (state_q == STATE_IDLE) | 362 | (state_q == STATE_LEN) | 363 | (state_q == STATE_ADDR0) | 364 | (state_q == STATE_ADDR1) | 365 | (state_q == STATE_ADDR2) | 366 | (state_q == STATE_ADDR3) | 367 | (state_q == STATE_WRITE && !mem_busy_q); 368 | 369 | //----------------------------------------------------------------- 370 | // Capture length 371 | //----------------------------------------------------------------- 372 | always @ (posedge clk_i or posedge rst_i) 373 | if (rst_i) 374 | len_q <= 8'd0; 375 | else if (state_q == STATE_LEN && rx_valid_w) 376 | len_q[7:0] <= rx_data_w; 377 | else if (state_q == STATE_WRITE && rx_valid_w && !mem_busy_q) 378 | len_q <= len_q - 8'd1; 379 | else if (state_q == STATE_READ && ((mem_busy_q && mem_rvalid_i) || magic_addr_w)) 380 | len_q <= len_q - 8'd1; 381 | else if (((state_q == STATE_DATA0) || (state_q == STATE_DATA1) || (state_q == STATE_DATA2)) && (tx_accept_w && !read_skip_w)) 382 | len_q <= len_q - 8'd1; 383 | 384 | //----------------------------------------------------------------- 385 | // Capture addr 386 | //----------------------------------------------------------------- 387 | always @ (posedge clk_i or posedge rst_i) 388 | if (rst_i) 389 | mem_addr_q <= 'd0; 390 | else if (state_q == STATE_ADDR0 && rx_valid_w) 391 | mem_addr_q[31:24] <= rx_data_w; 392 | else if (state_q == STATE_ADDR1 && rx_valid_w) 393 | mem_addr_q[23:16] <= rx_data_w; 394 | else if (state_q == STATE_ADDR2 && rx_valid_w) 395 | mem_addr_q[15:8] <= rx_data_w; 396 | else if (state_q == STATE_ADDR3 && rx_valid_w) 397 | mem_addr_q[7:0] <= rx_data_w; 398 | // Address increment on every access issued 399 | else if (state_q == STATE_WRITE && (mem_busy_q && mem_bvalid_i)) 400 | mem_addr_q <= {mem_addr_q[31:2], 2'b0} + 'd4; 401 | else if (state_q == STATE_READ && (mem_busy_q && mem_rvalid_i)) 402 | mem_addr_q <= {mem_addr_q[31:2], 2'b0} + 'd4; 403 | 404 | //----------------------------------------------------------------- 405 | // Data Index 406 | //----------------------------------------------------------------- 407 | always @ (posedge clk_i or posedge rst_i) 408 | if (rst_i) 409 | data_idx_q <= 2'b0; 410 | else if (state_q == STATE_ADDR3) 411 | data_idx_q <= rx_data_w[1:0]; 412 | else if (state_q == STATE_WRITE && rx_valid_w && !mem_busy_q) 413 | data_idx_q <= data_idx_q + 2'd1; 414 | else if (((state_q == STATE_DATA0) || (state_q == STATE_DATA1) || (state_q == STATE_DATA2)) && tx_accept_w && (data_idx_q != 2'b0)) 415 | data_idx_q <= data_idx_q - 2'd1; 416 | 417 | assign read_skip_w = (data_idx_q != 2'b0); 418 | 419 | //----------------------------------------------------------------- 420 | // Data Sample 421 | //----------------------------------------------------------------- 422 | always @ (posedge clk_i or posedge rst_i) 423 | if (rst_i) 424 | data_q <= 32'b0; 425 | // Write to memory 426 | else if (state_q == STATE_WRITE && rx_valid_w && !mem_busy_q) 427 | begin 428 | case (data_idx_q) 429 | 2'd0: data_q[7:0] <= rx_data_w; 430 | 2'd1: data_q[15:8] <= rx_data_w; 431 | 2'd2: data_q[23:16] <= rx_data_w; 432 | 2'd3: data_q[31:24] <= rx_data_w; 433 | endcase 434 | end 435 | // Read from GPIO Input? 436 | else if (state_q == STATE_READ && mem_addr_q == GPIO_ADDRESS) 437 | begin 438 | data_q <= {{(32-32){1'b0}}, gpio_inputs_i}; 439 | end 440 | // Read from status register? 441 | else if (state_q == STATE_READ && mem_addr_q == STS_ADDRESS) 442 | data_q <= {16'hcafe, 15'd0, mem_busy_q}; 443 | // Read from memory 444 | else if (state_q == STATE_READ && mem_rvalid_i) 445 | data_q <= mem_rdata_i; 446 | // Shift data out (read response -> UART) 447 | else if (((state_q == STATE_DATA0) || (state_q == STATE_DATA1) || (state_q == STATE_DATA2)) && (tx_accept_w || read_skip_w)) 448 | data_q <= {8'b0, data_q[31:8]}; 449 | 450 | assign tx_data_w = data_q[7:0]; 451 | 452 | assign mem_wdata_o = data_q; 453 | 454 | //----------------------------------------------------------------- 455 | // AXI: Write Request 456 | //----------------------------------------------------------------- 457 | reg mem_awvalid_q; 458 | reg mem_awvalid_r; 459 | 460 | reg mem_wvalid_q; 461 | reg mem_wvalid_r; 462 | 463 | always @ * 464 | begin 465 | mem_awvalid_r = 1'b0; 466 | mem_wvalid_r = 1'b0; 467 | 468 | // Hold 469 | if (mem_awvalid_o && !mem_awready_i) 470 | mem_awvalid_r = mem_awvalid_q; 471 | else if (mem_awvalid_o) 472 | mem_awvalid_r = 1'b0; 473 | // Every 4th byte, issue bus access 474 | else if (state_q == STATE_WRITE && rx_valid_w && (data_idx_q == 2'd3 || len_q == 1)) 475 | mem_awvalid_r = !magic_addr_w; 476 | 477 | // Hold 478 | if (mem_wvalid_o && !mem_wready_i) 479 | mem_wvalid_r = mem_wvalid_q; 480 | else if (mem_wvalid_o) 481 | mem_wvalid_r = 1'b0; 482 | // Every 4th byte, issue bus access 483 | else if (state_q == STATE_WRITE && rx_valid_w && (data_idx_q == 2'd3 || len_q == 1)) 484 | mem_wvalid_r = !magic_addr_w; 485 | end 486 | 487 | always @ (posedge clk_i or posedge rst_i) 488 | if (rst_i) 489 | begin 490 | mem_awvalid_q <= 1'b0; 491 | mem_wvalid_q <= 1'b0; 492 | end 493 | else 494 | begin 495 | mem_awvalid_q <= mem_awvalid_r; 496 | mem_wvalid_q <= mem_wvalid_r; 497 | end 498 | 499 | assign mem_awvalid_o = mem_awvalid_q; 500 | assign mem_wvalid_o = mem_wvalid_q; 501 | assign mem_awaddr_o = {mem_addr_q[31:2], 2'b0}; 502 | assign mem_awid_o = AXI_ID; 503 | assign mem_awlen_o = 8'b0; 504 | assign mem_awburst_o = 2'b01; 505 | assign mem_wlast_o = 1'b1; 506 | 507 | assign mem_bready_o = 1'b1; 508 | 509 | //----------------------------------------------------------------- 510 | // AXI: Read Request 511 | //----------------------------------------------------------------- 512 | reg mem_arvalid_q; 513 | reg mem_arvalid_r; 514 | 515 | always @ * 516 | begin 517 | mem_arvalid_r = 1'b0; 518 | 519 | // Hold 520 | if (mem_arvalid_o && !mem_arready_i) 521 | mem_arvalid_r = mem_arvalid_q; 522 | else if (mem_arvalid_o) 523 | mem_arvalid_r = 1'b0; 524 | else if (state_q == STATE_READ && !mem_busy_q) 525 | mem_arvalid_r = !magic_addr_w; 526 | end 527 | 528 | always @ (posedge clk_i or posedge rst_i) 529 | if (rst_i) 530 | mem_arvalid_q <= 1'b0; 531 | else 532 | mem_arvalid_q <= mem_arvalid_r; 533 | 534 | assign mem_arvalid_o = mem_arvalid_q; 535 | assign mem_araddr_o = {mem_addr_q[31:2], 2'b0}; 536 | assign mem_arid_o = AXI_ID; 537 | assign mem_arlen_o = 8'b0; 538 | assign mem_arburst_o = 2'b01; 539 | 540 | assign mem_rready_o = 1'b1; 541 | 542 | //----------------------------------------------------------------- 543 | // Write mask 544 | //----------------------------------------------------------------- 545 | reg [3:0] mem_sel_q; 546 | reg [3:0] mem_sel_r; 547 | 548 | always @ * 549 | begin 550 | mem_sel_r = 4'b1111; 551 | 552 | case (data_idx_q) 553 | 2'd0: mem_sel_r = 4'b0001; 554 | 2'd1: mem_sel_r = 4'b0011; 555 | 2'd2: mem_sel_r = 4'b0111; 556 | 2'd3: mem_sel_r = 4'b1111; 557 | endcase 558 | 559 | case (mem_addr_q[1:0]) 560 | 2'd0: mem_sel_r = mem_sel_r & 4'b1111; 561 | 2'd1: mem_sel_r = mem_sel_r & 4'b1110; 562 | 2'd2: mem_sel_r = mem_sel_r & 4'b1100; 563 | 2'd3: mem_sel_r = mem_sel_r & 4'b1000; 564 | endcase 565 | end 566 | 567 | always @ (posedge clk_i or posedge rst_i) 568 | if (rst_i) 569 | mem_sel_q <= 4'b0; 570 | // Idle - reset for read requests 571 | else if (state_q == STATE_IDLE) 572 | mem_sel_q <= 4'b1111; 573 | // Every 4th byte, issue bus access 574 | else if (state_q == STATE_WRITE && rx_valid_w && (data_idx_q == 2'd3 || len_q == 8'd1)) 575 | mem_sel_q <= mem_sel_r; 576 | 577 | assign mem_wstrb_o = mem_sel_q; 578 | 579 | //----------------------------------------------------------------- 580 | // Write enable 581 | //----------------------------------------------------------------- 582 | always @ (posedge clk_i or posedge rst_i) 583 | if (rst_i) 584 | mem_wr_q <= 1'b0; 585 | else if (state_q == STATE_IDLE && rx_valid_w) 586 | mem_wr_q <= (rx_data_w == REQ_WRITE); 587 | 588 | //----------------------------------------------------------------- 589 | // Access in progress 590 | //----------------------------------------------------------------- 591 | always @ (posedge clk_i or posedge rst_i) 592 | if (rst_i == 1'b1) 593 | mem_busy_q <= 1'b0; 594 | else if (mem_arvalid_o || mem_awvalid_o) 595 | mem_busy_q <= 1'b1; 596 | else if (mem_bvalid_i || mem_rvalid_i) 597 | mem_busy_q <= 1'b0; 598 | 599 | //----------------------------------------------------------------- 600 | // GPIO Outputs 601 | //----------------------------------------------------------------- 602 | reg gpio_wr_q; 603 | reg [31:0] gpio_output_q; 604 | 605 | always @ (posedge clk_i or posedge rst_i) 606 | if (rst_i) 607 | gpio_wr_q <= 1'b0; 608 | else if (mem_addr_q == GPIO_ADDRESS && state_q == STATE_WRITE && rx_valid_w && (data_idx_q == 2'd3 || len_q == 1)) 609 | gpio_wr_q <= 1'b1; 610 | else 611 | gpio_wr_q <= 1'b0; 612 | 613 | always @ (posedge clk_i or posedge rst_i) 614 | if (rst_i) 615 | gpio_output_q <= 32'h0; 616 | else if (gpio_wr_q) 617 | gpio_output_q <= data_q[31:0]; 618 | 619 | assign gpio_outputs_o = gpio_output_q; 620 | 621 | 622 | 623 | endmodule 624 | -------------------------------------------------------------------------------- /src_v/dbg_bridge_fifo.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // UART -> AXI Debug Bridge 3 | // V1.0 4 | // Ultra-Embedded.com 5 | // Copyright 2017-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 dbg_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 | -------------------------------------------------------------------------------- /src_v/dbg_bridge_uart.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // UART -> AXI Debug Bridge 3 | // V1.0 4 | // Ultra-Embedded.com 5 | // Copyright 2017-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 dbg_bridge_uart 39 | 40 | //----------------------------------------------------------------- 41 | // Params 42 | //----------------------------------------------------------------- 43 | #( 44 | parameter UART_DIVISOR_W = 9 45 | ) 46 | 47 | //----------------------------------------------------------------- 48 | // Ports 49 | //----------------------------------------------------------------- 50 | ( 51 | // Clock & Reset 52 | input clk_i, 53 | input rst_i, 54 | 55 | // Control 56 | input [UART_DIVISOR_W-1:0] bit_div_i, 57 | input stop_bits_i, // 0 = 1, 1 = 2 58 | 59 | // Transmit 60 | input wr_i, 61 | input [7:0] data_i, 62 | output tx_busy_o, 63 | 64 | // Receive 65 | input rd_i, 66 | output [7:0] data_o, 67 | output rx_ready_o, 68 | 69 | output rx_err_o, 70 | 71 | // UART pins 72 | input rxd_i, 73 | output txd_o 74 | ); 75 | 76 | //----------------------------------------------------------------- 77 | // Registers 78 | //----------------------------------------------------------------- 79 | localparam START_BIT = 4'd0; 80 | localparam STOP_BIT0 = 4'd9; 81 | localparam STOP_BIT1 = 4'd10; 82 | 83 | // Xilinx placement pragmas: 84 | //synthesis attribute IOB of txd_q is "TRUE" 85 | 86 | // TX Signals 87 | reg tx_busy_q; 88 | reg [3:0] tx_bits_q; 89 | reg [UART_DIVISOR_W-1:0] tx_count_q; 90 | reg [7:0] tx_shift_reg_q; 91 | reg txd_q; 92 | 93 | // RX Signals 94 | reg rxd_q; 95 | reg [7:0] rx_data_q; 96 | reg [3:0] rx_bits_q; 97 | reg [UART_DIVISOR_W-1:0] rx_count_q; 98 | reg [7:0] rx_shift_reg_q; 99 | reg rx_ready_q; 100 | reg rx_busy_q; 101 | 102 | reg rx_err_q; 103 | 104 | //----------------------------------------------------------------- 105 | // Re-sync RXD 106 | //----------------------------------------------------------------- 107 | reg rxd_ms_q; 108 | 109 | always @ (posedge clk_i or posedge rst_i) 110 | if (rst_i) 111 | begin 112 | rxd_ms_q <= 1'b1; 113 | rxd_q <= 1'b1; 114 | end 115 | else 116 | begin 117 | rxd_ms_q <= rxd_i; 118 | rxd_q <= rxd_ms_q; 119 | end 120 | 121 | //----------------------------------------------------------------- 122 | // RX Clock Divider 123 | //----------------------------------------------------------------- 124 | wire rx_sample_w = (rx_count_q == {(UART_DIVISOR_W){1'b0}}); 125 | 126 | always @ (posedge clk_i or posedge rst_i) 127 | if (rst_i) 128 | rx_count_q <= {(UART_DIVISOR_W){1'b0}}; 129 | else 130 | begin 131 | // Inactive 132 | if (!rx_busy_q) 133 | rx_count_q <= {1'b0, bit_div_i[UART_DIVISOR_W-1:1]}; 134 | // Rx bit timer 135 | else if (rx_count_q != 0) 136 | rx_count_q <= (rx_count_q - 1); 137 | // Active 138 | else if (rx_sample_w) 139 | begin 140 | // Last bit? 141 | if ((rx_bits_q == STOP_BIT0 && !stop_bits_i) || (rx_bits_q == STOP_BIT1 && stop_bits_i)) 142 | rx_count_q <= {(UART_DIVISOR_W){1'b0}}; 143 | else 144 | rx_count_q <= bit_div_i; 145 | end 146 | end 147 | 148 | //----------------------------------------------------------------- 149 | // RX Shift Register 150 | //----------------------------------------------------------------- 151 | always @ (posedge clk_i or posedge rst_i) 152 | if (rst_i) 153 | begin 154 | rx_shift_reg_q <= 8'h00; 155 | rx_busy_q <= 1'b0; 156 | end 157 | // Rx busy 158 | else if (rx_busy_q && rx_sample_w) 159 | begin 160 | // Last bit? 161 | if (rx_bits_q == STOP_BIT0 && !stop_bits_i) 162 | rx_busy_q <= 1'b0; 163 | else if (rx_bits_q == STOP_BIT1 && stop_bits_i) 164 | rx_busy_q <= 1'b0; 165 | else if (rx_bits_q == START_BIT) 166 | begin 167 | // Start bit should still be low as sampling mid 168 | // way through start bit, so if high, error! 169 | if (rxd_q) 170 | rx_busy_q <= 1'b0; 171 | end 172 | // Rx shift register 173 | else 174 | rx_shift_reg_q <= {rxd_q, rx_shift_reg_q[7:1]}; 175 | end 176 | // Start bit? 177 | else if (!rx_busy_q && rxd_q == 1'b0) 178 | begin 179 | rx_shift_reg_q <= 8'h00; 180 | rx_busy_q <= 1'b1; 181 | end 182 | 183 | always @ (posedge clk_i or posedge rst_i) 184 | if (rst_i) 185 | rx_bits_q <= START_BIT; 186 | else if (rx_sample_w && rx_busy_q) 187 | begin 188 | if ((rx_bits_q == STOP_BIT1 && stop_bits_i) || (rx_bits_q == STOP_BIT0 && !stop_bits_i)) 189 | rx_bits_q <= START_BIT; 190 | else 191 | rx_bits_q <= rx_bits_q + 4'd1; 192 | end 193 | else if (!rx_busy_q && (bit_div_i == {(UART_DIVISOR_W){1'b0}})) 194 | rx_bits_q <= START_BIT + 4'd1; 195 | else if (!rx_busy_q) 196 | rx_bits_q <= START_BIT; 197 | 198 | //----------------------------------------------------------------- 199 | // RX Data 200 | //----------------------------------------------------------------- 201 | always @ (posedge clk_i or posedge rst_i) 202 | if (rst_i) 203 | begin 204 | rx_ready_q <= 1'b0; 205 | rx_data_q <= 8'h00; 206 | rx_err_q <= 1'b0; 207 | end 208 | else 209 | begin 210 | // If reading data, reset data state 211 | if (rd_i == 1'b1) 212 | begin 213 | rx_ready_q <= 1'b0; 214 | rx_err_q <= 1'b0; 215 | end 216 | 217 | if (rx_busy_q && rx_sample_w) 218 | begin 219 | // Stop bit 220 | if ((rx_bits_q == STOP_BIT1 && stop_bits_i) || (rx_bits_q == STOP_BIT0 && !stop_bits_i)) 221 | begin 222 | // RXD should be still high 223 | if (rxd_q) 224 | begin 225 | rx_data_q <= rx_shift_reg_q; 226 | rx_ready_q <= 1'b1; 227 | end 228 | // Bad Stop bit - wait for a full bit period 229 | // before allowing start bit detection again 230 | else 231 | begin 232 | rx_ready_q <= 1'b0; 233 | rx_data_q <= 8'h00; 234 | rx_err_q <= 1'b1; 235 | end 236 | end 237 | // Mid start bit sample - if high then error 238 | else if (rx_bits_q == START_BIT && rxd_q) 239 | rx_err_q <= 1'b1; 240 | end 241 | end 242 | 243 | //----------------------------------------------------------------- 244 | // TX Clock Divider 245 | //----------------------------------------------------------------- 246 | wire tx_sample_w = (tx_count_q == {(UART_DIVISOR_W){1'b0}}); 247 | 248 | always @ (posedge clk_i or posedge rst_i) 249 | if (rst_i) 250 | tx_count_q <= {(UART_DIVISOR_W){1'b0}}; 251 | else 252 | begin 253 | // Idle 254 | if (!tx_busy_q) 255 | tx_count_q <= bit_div_i; 256 | // Tx bit timer 257 | else if (tx_count_q != 0) 258 | tx_count_q <= (tx_count_q - 1); 259 | else if (tx_sample_w) 260 | tx_count_q <= bit_div_i; 261 | end 262 | 263 | //----------------------------------------------------------------- 264 | // TX Shift Register 265 | //----------------------------------------------------------------- 266 | always @ (posedge clk_i or posedge rst_i) 267 | if (rst_i) 268 | begin 269 | tx_shift_reg_q <= 8'h00; 270 | tx_busy_q <= 1'b0; 271 | end 272 | // Tx busy 273 | else if (tx_busy_q) 274 | begin 275 | // Shift tx data 276 | if (tx_bits_q != START_BIT && tx_sample_w) 277 | tx_shift_reg_q <= {1'b0, tx_shift_reg_q[7:1]}; 278 | 279 | // Last bit? 280 | if (tx_bits_q == STOP_BIT0 && tx_sample_w && !stop_bits_i) 281 | tx_busy_q <= 1'b0; 282 | else if (tx_bits_q == STOP_BIT1 && tx_sample_w && stop_bits_i) 283 | tx_busy_q <= 1'b0; 284 | end 285 | // Buffer data to transmit 286 | else if (wr_i) 287 | begin 288 | tx_shift_reg_q <= data_i; 289 | tx_busy_q <= 1'b1; 290 | end 291 | 292 | always @ (posedge clk_i or posedge rst_i ) 293 | if (rst_i) 294 | tx_bits_q <= 4'd0; 295 | else if (tx_sample_w && tx_busy_q) 296 | begin 297 | if ((tx_bits_q == STOP_BIT1 && stop_bits_i) || (tx_bits_q == STOP_BIT0 && !stop_bits_i)) 298 | tx_bits_q <= START_BIT; 299 | else 300 | tx_bits_q <= tx_bits_q + 4'd1; 301 | end 302 | 303 | //----------------------------------------------------------------- 304 | // UART Tx Pin 305 | //----------------------------------------------------------------- 306 | reg txd_r; 307 | 308 | always @ * 309 | begin 310 | txd_r = 1'b1; 311 | 312 | if (tx_busy_q) 313 | begin 314 | // Start bit (TXD = L) 315 | if (tx_bits_q == START_BIT) 316 | txd_r = 1'b0; 317 | // Stop bits (TXD = H) 318 | else if (tx_bits_q == STOP_BIT0 || tx_bits_q == STOP_BIT1) 319 | txd_r = 1'b1; 320 | // Data bits 321 | else 322 | txd_r = tx_shift_reg_q[0]; 323 | end 324 | end 325 | 326 | always @ (posedge clk_i or posedge rst_i) 327 | if (rst_i) 328 | txd_q <= 1'b1; 329 | else 330 | txd_q <= txd_r; 331 | 332 | //----------------------------------------------------------------- 333 | // Outputs 334 | //----------------------------------------------------------------- 335 | assign tx_busy_o = tx_busy_q; 336 | assign rx_ready_o = rx_ready_q; 337 | assign txd_o = txd_q; 338 | assign data_o = rx_data_q; 339 | assign rx_err_o = rx_err_q; 340 | 341 | endmodule 342 | -------------------------------------------------------------------------------- /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 = 128 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 | # Check status register 42 | value = self.read32(self.STS_ADDR) 43 | if ((value & 0xFFFF0000) != 0xcafe0000): 44 | raise Exception("Target not responding correctly, check interface / baud rate...") 45 | 46 | ################################################################## 47 | # read32: Read a word from a specified address 48 | ################################################################## 49 | def read32(self, addr): 50 | # Connect if required 51 | if self.uart == None: 52 | self.connect() 53 | 54 | # Send read command 55 | cmd = bytearray([self.CMD_READ, 56 | 4, 57 | (addr >> 24) & 0xFF, 58 | (addr >> 16) & 0xFF, 59 | (addr >> 8) & 0xFF, 60 | (addr >> 0) & 0xFF]) 61 | self.uart.write(cmd) 62 | 63 | value = 0 64 | idx = 0 65 | while (idx < 4): 66 | b = self.uart.read(1) 67 | value |= (ord(b) << (idx * 8)) 68 | idx += 1 69 | 70 | return value 71 | 72 | ################################################################## 73 | # write32: Write a word to a specified address 74 | ################################################################## 75 | def write32(self, addr, value): 76 | # Connect if required 77 | if self.uart == None: 78 | self.connect() 79 | 80 | # Send write command 81 | cmd = bytearray([self.CMD_WRITE, 82 | 4, 83 | (addr >> 24) & 0xFF, 84 | (addr >> 16) & 0xFF, 85 | (addr >> 8) & 0xFF, 86 | (addr >> 0) & 0xFF, 87 | (value >> 0) & 0xFF, 88 | (value >> 8) & 0xFF, 89 | (value >> 16) & 0xFF, 90 | (value >> 24) & 0xFF]) 91 | self.uart.write(cmd) 92 | 93 | ################################################################## 94 | # write: Write a block of data to a specified address 95 | ################################################################## 96 | def write(self, addr, data, length, addr_incr=True, max_block_size=-1): 97 | # Connect if required 98 | if self.uart == None: 99 | self.connect() 100 | 101 | # Write blocks 102 | idx = 0 103 | remainder = length 104 | 105 | if self.prog_cb != None: 106 | self.prog_cb(0, length) 107 | 108 | if max_block_size == -1: 109 | max_block_size = self.BLOCK_SIZE 110 | 111 | while remainder > 0: 112 | l = max_block_size 113 | if l > remainder: 114 | l = remainder 115 | 116 | cmd = bytearray(2 + 4 + l) 117 | cmd[0] = self.CMD_WRITE 118 | cmd[1] = l & 0xFF 119 | cmd[2] = (addr >> 24) & 0xFF 120 | cmd[3] = (addr >> 16) & 0xFF 121 | cmd[4] = (addr >> 8) & 0xFF 122 | cmd[5] = (addr >> 0) & 0xFF 123 | 124 | for i in range(l): 125 | cmd[6+i] = data[idx] 126 | idx += 1 127 | 128 | # Write to serial port 129 | self.uart.write(cmd) 130 | 131 | # Update display 132 | if self.prog_cb != None: 133 | self.prog_cb(idx, length) 134 | 135 | if addr_incr: 136 | addr += l 137 | remainder -= l 138 | 139 | ################################################################## 140 | # read: Read a block of data from a specified address 141 | ################################################################## 142 | def read(self, addr, length, addr_incr=True, max_block_size=-1): 143 | # Connect if required 144 | if self.uart == None: 145 | self.connect() 146 | 147 | idx = 0 148 | remainder = length 149 | data = bytearray(length) 150 | 151 | if self.prog_cb != None: 152 | self.prog_cb(0, length) 153 | 154 | if max_block_size == -1: 155 | max_block_size = self.BLOCK_SIZE 156 | 157 | while remainder > 0: 158 | l = max_block_size 159 | if l > remainder: 160 | l = remainder 161 | 162 | cmd = bytearray(2 + 4) 163 | cmd[0] = self.CMD_READ 164 | cmd[1] = l & 0xFF 165 | cmd[2] = (addr >> 24) & 0xFF 166 | cmd[3] = (addr >> 16) & 0xFF 167 | cmd[4] = (addr >> 8) & 0xFF 168 | cmd[5] = (addr >> 0) & 0xFF 169 | 170 | # Write to serial port 171 | self.uart.write(cmd) 172 | 173 | # Read block response 174 | for i in range(l): 175 | data[idx] = ord(self.uart.read(1)) & 0xFF 176 | idx += 1 177 | 178 | # Update display 179 | if self.prog_cb != None: 180 | self.prog_cb(idx, length) 181 | 182 | if addr_incr: 183 | addr += l 184 | remainder -= l 185 | 186 | return data 187 | 188 | ################################################################## 189 | # read_gpio: Read GPIO bus 190 | ################################################################## 191 | def read_gpio(self): 192 | return self.read32(self.GPIO_ADDR) 193 | 194 | ################################################################## 195 | # write_gpio: Write a byte to GPIO 196 | ################################################################## 197 | def write_gpio(self, value): 198 | self.write32(self.GPIO_ADDR, value) 199 | --------------------------------------------------------------------------------