├── LICENSE ├── README.md ├── src_c ├── gpio_defs.h ├── irq_ctrl_defs.h ├── spi_lite.c ├── spi_lite.h ├── spi_lite_defs.h ├── timer_defs.h ├── uart_lite.c ├── uart_lite.h └── uart_lite_defs.h └── src_v ├── axi4lite_dist.v ├── core_soc.v ├── gpio.v ├── gpio_defs.v ├── irq_ctrl.v ├── irq_ctrl_defs.v ├── spi_lite.v ├── spi_lite_defs.v ├── timer.v ├── timer_defs.v ├── uart_lite.v └── uart_lite_defs.v /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 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 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Basic Peripheral SoC 2 | 3 | Github: [http://github.com/ultraembedded/core_soc](http://github.com/ultraembedded/core_soc) 4 | 5 | A basic SoC with Timer, UART, SPI, GPIO and Interrupt Controller peripherals. 6 | 7 | ### Features 8 | * Multi-channel timer peripheral. 9 | * UART peripheral. 10 | * SPI (master mode) peripheral with 8 chip selects. 11 | * 32 I/O GPIO controller. 12 | * 3 external peripherals (AXI4-Lite interface). 13 | * Interrupt controller (combines peripheral IRQs into single IRQ). 14 | * AXI4-Lite slave interface. 15 | 16 | ### Configuration 17 | * Top: core_soc 18 | * Clock: clk_i 19 | * Reset: rst_i - Asynchronous, active high 20 | * parameter CLK_FREQ - Clock speed (in Hz) 21 | * parameter BAUDRATE - UART baud rate (e.g. 115200) 22 | * parameter C_SCK_RATIO - SPI clock divider ratio for clk_i -> spi_clk_o 23 | 24 | ### Memory Map 25 | 26 | | Range | Description | 27 | | ------------------------- | --------------------------------------------------- | 28 | | 0x0000_0000 - 0x00ff_ffff | Peripheral - IRQ controller | 29 | | 0x0100_0000 - 0x01ff_ffff | Peripheral - Timer | 30 | | 0x0200_0000 - 0x02ff_ffff | Peripheral - UART | 31 | | 0x0300_0000 - 0x03ff_ffff | Peripheral - SPI | 32 | | 0x0400_0000 - 0x04ff_ffff | Peripheral - GPIO | 33 | | 0x0500_0000 - 0x05ff_ffff | Peripheral - External 1 | 34 | | 0x0600_0000 - 0x06ff_ffff | Peripheral - External 2 | 35 | | 0x0700_0000 - 0x07ff_ffff | Peripheral - External 3 | 36 | 37 | ### Interrupt Sources 38 | 39 | | Index | Source | 40 | | -------| --------------------------- | 41 | | 0 | Peripheral - Timer | 42 | | 1 | Peripheral - UART | 43 | | 2 | Peripheral - SPI | 44 | | 3 | Peripheral - GPIO | 45 | | 4 | Peripheral - External 1 | 46 | | 5 | Peripheral - External 2 | 47 | | 6 | Peripheral - External 3 | 48 | 49 | ### Peripheral Register Map 50 | 51 | | Offset | Name | Description | 52 | | ------ | ---- | ------------- | 53 | | 0x0000_0000 | IRQ_ISR | [RW] Interrupt Status Register | 54 | | 0x0000_0004 | IRQ_IPR | [R] Interrupt Pending Register | 55 | | 0x0000_0008 | IRQ_IER | [RW] Interrupt Enable Register | 56 | | 0x0000_000c | IRQ_IAR | [W] Interrupt Acknowledge Register | 57 | | 0x0000_0010 | IRQ_SIE | [W] Set Interrupt Enable bits | 58 | | 0x0000_0014 | IRQ_CIE | [W] Clear Interrupt Enable bits | 59 | | 0x0000_0018 | IRQ_IVR | [RW] Interrupt Vector Register | 60 | | 0x0000_001c | IRQ_MER | [RW] Master Enable Register | 61 | | 0x0100_0008 | TIMER_CTRL0 | [RW] Control | 62 | | 0x0100_000c | TIMER_CMP0 | [RW] Compare value (interrupt on match) | 63 | | 0x0100_0010 | TIMER_VAL0 | [RW] Current Value | 64 | | 0x0100_0014 | TIMER_CTRL1 | [RW] Control | 65 | | 0x0100_0018 | TIMER_CMP1 | [RW] Compare value (interrupt on match) | 66 | | 0x0100_001c | TIMER_VAL1 | [RW] Current Value | 67 | | 0x0200_0000 | ULITE_RX | [R] UART Data Register | 68 | | 0x0200_0004 | ULITE_TX | [W] UART Data Register | 69 | | 0x0200_0008 | ULITE_STATUS | [R] UART Status Register | 70 | | 0x0200_000c | ULITE_CONTROL | [RW] UART Configuration Register | 71 | | 0x0300_001c | SPI_DGIER | [RW] Device Global Interrupt Enable Register | 72 | | 0x0300_0020 | SPI_IPISR | [RW] IP Interrupt Status Register | 73 | | 0x0300_0028 | SPI_IPIER | [RW] IP Interrupt Enable Register | 74 | | 0x0300_0040 | SPI_SRR | [RW] Software Reset Register | 75 | | 0x0300_0060 | SPI_CR | [RW] SPI Control Register | 76 | | 0x0300_0064 | SPI_SR | [R] SPI Status Register | 77 | | 0x0300_0068 | SPI_DTR | [W] SPI Data Transmit Register | 78 | | 0x0300_006c | SPI_DRR | [R] SPI Data Receive Register | 79 | | 0x0300_0070 | SPI_SSR | [RW] SPI Slave Select Register | 80 | | 0x0400_0000 | GPIO_DIRECTION | [RW] Configuration Register | 81 | | 0x0400_0004 | GPIO_INPUT | [R] GPIO Input Status | 82 | | 0x0400_0008 | GPIO_OUTPUT | [RW] GPIO Output Control | 83 | | 0x0400_000c | GPIO_OUTPUT_SET | [W] GPIO Output Control Set Alias | 84 | | 0x0400_0010 | GPIO_OUTPUT_CLR | [W] GPIO Output Control Clr Alias | 85 | | 0x0400_0014 | GPIO_INT_MASK | [RW] GPIO Interrupt Enable Mask | 86 | | 0x0400_0018 | GPIO_INT_SET | [W] GPIO Interrupt Set | 87 | | 0x0400_001c | GPIO_INT_CLR | [W] GPIO Interrupt Clear | 88 | | 0x0400_0020 | GPIO_INT_STATUS | [R] GPIO Interrupt Raw Status | 89 | | 0x0400_0024 | GPIO_INT_LEVEL | [RW] GPIO Interrupt Level | 90 | | 0x0400_0028 | GPIO_INT_MODE | [RW] GPIO Interrupt Mode | 91 | 92 | ### Peripheral Register Fields 93 | 94 | ##### IRQ Register: IRQ_ISR 95 | 96 | | Bits | Name | Description | 97 | | ---- | ---- | -------------- | 98 | | 7:0 | STATUS | Pending interrupt (unmasked) bitmap. | 99 | 100 | ##### IRQ Register: IRQ_IPR 101 | 102 | | Bits | Name | Description | 103 | | ---- | ---- | -------------- | 104 | | 7:0 | PENDING | Pending interrupts (masked) bitmap. | 105 | 106 | ##### IRQ Register: IRQ_IER 107 | 108 | | Bits | Name | Description | 109 | | ---- | ---- | -------------- | 110 | | 7:0 | ENABLE | Interrupt enable mask. | 111 | 112 | ##### IRQ Register: IRQ_IAR 113 | 114 | | Bits | Name | Description | 115 | | ---- | ---- | -------------- | 116 | | 7:0 | ACK | Bitmap of interrupts to acknowledge. | 117 | 118 | ##### IRQ Register: IRQ_SIE 119 | 120 | | Bits | Name | Description | 121 | | ---- | ---- | -------------- | 122 | | 7:0 | SET | Bitmap of interrupts to enable. | 123 | 124 | ##### IRQ Register: IRQ_CIE 125 | 126 | | Bits | Name | Description | 127 | | ---- | ---- | -------------- | 128 | | 7:0 | CLR | Bitmap of interrupts to disable. | 129 | 130 | ##### IRQ Register: IRQ_IVR 131 | 132 | | Bits | Name | Description | 133 | | ---- | ---- | -------------- | 134 | | 31:0 | VECTOR | Highest priority active interrupt number. | 135 | 136 | ##### IRQ Register: IRQ_MER 137 | 138 | | Bits | Name | Description | 139 | | ---- | ---- | -------------- | 140 | | 0 | ME | Master Enable | 141 | 142 | ##### Timer Register: TIMER_CTRLx 143 | 144 | | Bits | Name | Description | 145 | | ---- | ---- | -------------- | 146 | | 1 | INTERRUPT | Interrupt enable. | 147 | | 2 | ENABLE | Timer enable. | 148 | 149 | ##### Timer Register: TIMER_CMPx 150 | 151 | | Bits | Name | Description | 152 | | ---- | ---- | -------------- | 153 | | 31:0 | VALUE | Match value. | 154 | 155 | ##### Timer Register: TIMER_VALx 156 | 157 | | Bits | Name | Description | 158 | | ---- | ---- | -------------- | 159 | | 31:0 | CURRENT | Current timer value. | 160 | 161 | ##### UART Register: ULITE_RX 162 | 163 | | Bits | Name | Description | 164 | | ---- | ---- | -------------- | 165 | | 7:0 | DATA | Date byte | 166 | 167 | ##### UART Register: ULITE_TX 168 | 169 | | Bits | Name | Description | 170 | | ---- | ---- | -------------- | 171 | | 7:0 | DATA | Date byte | 172 | 173 | ##### UART Register: ULITE_STATUS 174 | 175 | | Bits | Name | Description | 176 | | ---- | ---- | -------------- | 177 | | 4 | IE | Interrupt enabled | 178 | | 3 | TXFULL | Transmit buffer full | 179 | | 2 | TXEMPTY | Transmit buffer empty | 180 | | 1 | RXFULL | Receive buffer full | 181 | | 0 | RXVALID | Receive buffer not empty | 182 | 183 | ##### UART Register: ULITE_CONTROL 184 | 185 | | Bits | Name | Description | 186 | | ---- | ---- | -------------- | 187 | | 4 | IE | Interrupt enable | 188 | | 1 | RST_RX | Flush Rx Buffer | 189 | | 0 | RST_TX | Flush Tx Buffer | 190 | 191 | ##### SPI Register: SPI_DGIER 192 | 193 | | Bits | Name | Description | 194 | | ---- | ---- | -------------- | 195 | | 31 | GIE | Global interrupt enable. | 196 | 197 | ##### SPI Register: SPI_IPISR 198 | 199 | | Bits | Name | Description | 200 | | ---- | ---- | -------------- | 201 | | 2 | TX_EMPTY | Tx FIFO empty interrupt status. | 202 | 203 | ##### SPI Register: SPI_IPIER 204 | 205 | | Bits | Name | Description | 206 | | ---- | ---- | -------------- | 207 | | 2 | TX_EMPTY | Tx FIFO interrupt enable. | 208 | 209 | ##### SPI Register: SPI_SRR 210 | 211 | | Bits | Name | Description | 212 | | ---- | ---- | -------------- | 213 | | 31:0 | RESET | Software FIFO reset. | 214 | 215 | ##### SPI Register: SPI_CR 216 | 217 | | Bits | Name | Description | 218 | | ---- | ---- | -------------- | 219 | | 0 | LOOP | Loopback enable (MOSI to MISO). | 220 | | 1 | SPE | SPI Enable. | 221 | | 2 | MASTER | Master mode (slave mode not currently supported). | 222 | | 3 | CPOL | Clock polarity. | 223 | | 4 | CPHA | Clock phase. | 224 | | 5 | TXFIFO_RST | Tx FIFO reset. | 225 | | 6 | RXFIFO_RST | Rx FIFO reset. | 226 | | 7 | MANUAL_SS | Manual chip select mode (auto mode not supported). | 227 | | 8 | TRANS_INHIBIT | Transfer inhibit. | 228 | | 9 | LSB_FIRST | Data LSB first (1) or MSB first (0). | 229 | 230 | ##### SPI Register: SPI_SR 231 | 232 | | Bits | Name | Description | 233 | | ---- | ---- | -------------- | 234 | | 0 | RX_EMPTY | Rx FIFO empty. | 235 | | 1 | RX_FULL | Rx FIFO full. | 236 | | 2 | TX_EMPTY | Tx FIFO empty. | 237 | | 3 | TX_FULL | Tx FIFO full. | 238 | 239 | ##### SPI Register: SPI_DTR 240 | 241 | | Bits | Name | Description | 242 | | ---- | ---- | -------------- | 243 | | 7:0 | DATA | Date byte | 244 | 245 | ##### SPI Register: SPI_DRR 246 | 247 | | Bits | Name | Description | 248 | | ---- | ---- | -------------- | 249 | | 7:0 | DATA | Date byte | 250 | 251 | ##### SPI Register: SPI_SSR 252 | 253 | | Bits | Name | Description | 254 | | ---- | ---- | -------------- | 255 | | 0 | VALUE | Chip select value | 256 | 257 | ##### GPIO Register: GPIO_DIRECTION 258 | 259 | | Bits | Name | Description | 260 | | ---- | ---- | -------------- | 261 | | 31:0 | OUTPUT | 0 = Input, 1 = Output | 262 | 263 | ##### GPIO Register: GPIO_INPUT 264 | 265 | | Bits | Name | Description | 266 | | ---- | ---- | -------------- | 267 | | 31:0 | VALUE | Raw input status | 268 | 269 | ##### GPIO Register: GPIO_OUTPUT 270 | 271 | | Bits | Name | Description | 272 | | ---- | ---- | -------------- | 273 | | 31:0 | DATA | GPIO output value | 274 | 275 | ##### GPIO Register: GPIO_OUTPUT_SET 276 | 277 | | Bits | Name | Description | 278 | | ---- | ---- | -------------- | 279 | | 31:0 | DATA | GPIO output mask - set for high | 280 | 281 | ##### GPIO Register: GPIO_OUTPUT_CLR 282 | 283 | | Bits | Name | Description | 284 | | ---- | ---- | -------------- | 285 | | 31:0 | DATA | GPIO output mask - set for low | 286 | 287 | ##### GPIO Register: GPIO_INT_MASK 288 | 289 | | Bits | Name | Description | 290 | | ---- | ---- | -------------- | 291 | | 31:0 | ENABLE | GPIO Interrupt Enable Mask | 292 | 293 | ##### GPIO Register: GPIO_INT_SET 294 | 295 | | Bits | Name | Description | 296 | | ---- | ---- | -------------- | 297 | | 31:0 | SW_IRQ | Write 1 to assert an interrupt | 298 | 299 | ##### GPIO Register: GPIO_INT_CLR 300 | 301 | | Bits | Name | Description | 302 | | ---- | ---- | -------------- | 303 | | 31:0 | ACK | Write 1 to clear an interrupt | 304 | 305 | ##### GPIO Register: GPIO_INT_STATUS 306 | 307 | | Bits | Name | Description | 308 | | ---- | ---- | -------------- | 309 | | 31:0 | RAW | Set if interrupt active (regardless of INT_MASK) | 310 | 311 | ##### GPIO Register: GPIO_INT_LEVEL 312 | 313 | | Bits | Name | Description | 314 | | ---- | ---- | -------------- | 315 | | 31:0 | ACTIVE_HIGH | GPIO Interrupt Level - 1 = active high / rising edge, 0 = active low / falling edge | 316 | 317 | ##### GPIO Register: GPIO_INT_MODE 318 | 319 | | Bits | Name | Description | 320 | | ---- | ---- | -------------- | 321 | | 31:0 | EDGE | GPIO Interrupt Mode - 1 = edge triggered, 0 = level | 322 | 323 | -------------------------------------------------------------------------------- /src_c/gpio_defs.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // Basic Peripheral SoC 3 | // V1.1 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2020 6 | // 7 | // Email: admin@ultra-embedded.com 8 | // 9 | // License: GPL 10 | // If you would like a version with a more permissive license for 11 | // use in closed source commercial applications please contact me 12 | // for details. 13 | //----------------------------------------------------------------- 14 | // 15 | // This file is open source HDL; you can redistribute it and/or 16 | // modify it under the terms of the GNU General Public License as 17 | // published by the Free Software Foundation; either version 2 of 18 | // the License, or (at your option) any later version. 19 | // 20 | // This file is distributed in the hope that it will be useful, 21 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | // GNU General Public License for more details. 24 | // 25 | // You should have received a copy of the GNU General Public 26 | // License along with this file; if not, write to the Free Software 27 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 28 | // USA 29 | //----------------------------------------------------------------- 30 | 31 | //----------------------------------------------------------------- 32 | // Generated File 33 | //----------------------------------------------------------------- 34 | 35 | #ifndef __GPIO_DEFS_H__ 36 | #define __GPIO_DEFS_H__ 37 | 38 | #define GPIO_DIRECTION 0x0 39 | #define GPIO_DIRECTION_OUTPUT_SHIFT 0 40 | #define GPIO_DIRECTION_OUTPUT_MASK 0xffffffff 41 | 42 | #define GPIO_INPUT 0x4 43 | #define GPIO_INPUT_VALUE_SHIFT 0 44 | #define GPIO_INPUT_VALUE_MASK 0xffffffff 45 | 46 | #define GPIO_OUTPUT 0x8 47 | #define GPIO_OUTPUT_DATA_SHIFT 0 48 | #define GPIO_OUTPUT_DATA_MASK 0xffffffff 49 | 50 | #define GPIO_OUTPUT_SET 0xc 51 | #define GPIO_OUTPUT_SET_DATA_SHIFT 0 52 | #define GPIO_OUTPUT_SET_DATA_MASK 0xffffffff 53 | 54 | #define GPIO_OUTPUT_CLR 0x10 55 | #define GPIO_OUTPUT_CLR_DATA_SHIFT 0 56 | #define GPIO_OUTPUT_CLR_DATA_MASK 0xffffffff 57 | 58 | #define GPIO_INT_MASK 0x14 59 | #define GPIO_INT_MASK_ENABLE_SHIFT 0 60 | #define GPIO_INT_MASK_ENABLE_MASK 0xffffffff 61 | 62 | #define GPIO_INT_SET 0x18 63 | #define GPIO_INT_SET_SW_IRQ_SHIFT 0 64 | #define GPIO_INT_SET_SW_IRQ_MASK 0xffffffff 65 | 66 | #define GPIO_INT_CLR 0x1c 67 | #define GPIO_INT_CLR_ACK_SHIFT 0 68 | #define GPIO_INT_CLR_ACK_MASK 0xffffffff 69 | 70 | #define GPIO_INT_STATUS 0x20 71 | #define GPIO_INT_STATUS_RAW_SHIFT 0 72 | #define GPIO_INT_STATUS_RAW_MASK 0xffffffff 73 | 74 | #define GPIO_INT_LEVEL 0x24 75 | #define GPIO_INT_LEVEL_ACTIVE_HIGH_SHIFT 0 76 | #define GPIO_INT_LEVEL_ACTIVE_HIGH_MASK 0xffffffff 77 | 78 | #define GPIO_INT_MODE 0x28 79 | #define GPIO_INT_MODE_EDGE_SHIFT 0 80 | #define GPIO_INT_MODE_EDGE_MASK 0xffffffff 81 | 82 | #endif -------------------------------------------------------------------------------- /src_c/irq_ctrl_defs.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // Basic Peripheral SoC 3 | // V1.1 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2020 6 | // 7 | // Email: admin@ultra-embedded.com 8 | // 9 | // License: GPL 10 | // If you would like a version with a more permissive license for 11 | // use in closed source commercial applications please contact me 12 | // for details. 13 | //----------------------------------------------------------------- 14 | // 15 | // This file is open source HDL; you can redistribute it and/or 16 | // modify it under the terms of the GNU General Public License as 17 | // published by the Free Software Foundation; either version 2 of 18 | // the License, or (at your option) any later version. 19 | // 20 | // This file is distributed in the hope that it will be useful, 21 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | // GNU General Public License for more details. 24 | // 25 | // You should have received a copy of the GNU General Public 26 | // License along with this file; if not, write to the Free Software 27 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 28 | // USA 29 | //----------------------------------------------------------------- 30 | 31 | //----------------------------------------------------------------- 32 | // Generated File 33 | //----------------------------------------------------------------- 34 | 35 | #ifndef __IRQ_CTRL_DEFS_H__ 36 | #define __IRQ_CTRL_DEFS_H__ 37 | 38 | #define IRQ_ISR 0x0 39 | #define IRQ_ISR_STATUS_SHIFT 0 40 | #define IRQ_ISR_STATUS_MASK 0x7f 41 | 42 | #define IRQ_IPR 0x4 43 | #define IRQ_IPR_PENDING_SHIFT 0 44 | #define IRQ_IPR_PENDING_MASK 0x7f 45 | 46 | #define IRQ_IER 0x8 47 | #define IRQ_IER_ENABLE_SHIFT 0 48 | #define IRQ_IER_ENABLE_MASK 0x7f 49 | 50 | #define IRQ_IAR 0xc 51 | #define IRQ_IAR_ACK_SHIFT 0 52 | #define IRQ_IAR_ACK_MASK 0x7f 53 | 54 | #define IRQ_SIE 0x10 55 | #define IRQ_SIE_SET_SHIFT 0 56 | #define IRQ_SIE_SET_MASK 0x7f 57 | 58 | #define IRQ_CIE 0x14 59 | #define IRQ_CIE_CLR_SHIFT 0 60 | #define IRQ_CIE_CLR_MASK 0x7f 61 | 62 | #define IRQ_IVR 0x18 63 | #define IRQ_IVR_VECTOR_SHIFT 0 64 | #define IRQ_IVR_VECTOR_MASK 0xffffffff 65 | 66 | #define IRQ_MER 0x1c 67 | #define IRQ_MER_ME 0 68 | #define IRQ_MER_ME_SHIFT 0 69 | #define IRQ_MER_ME_MASK 0x1 70 | 71 | #endif -------------------------------------------------------------------------------- /src_c/spi_lite.c: -------------------------------------------------------------------------------- 1 | #include "spi_lite.h" 2 | #include "spi_lite_defs.h" 3 | 4 | //----------------------------------------------------------------- 5 | // Locals 6 | //----------------------------------------------------------------- 7 | static volatile uint32_t *m_spi; 8 | 9 | //----------------------------------------------------------------- 10 | // spi_delay_ns: Simple delay loop 11 | //----------------------------------------------------------------- 12 | static void spi_delay_ns(int delay) 13 | { 14 | volatile uint32_t i=delay; 15 | while (i--) 16 | ; 17 | } 18 | //----------------------------------------------------------------- 19 | // spi_init: Initialise SPI master 20 | //----------------------------------------------------------------- 21 | void spi_init(uint32_t base_addr) 22 | { 23 | uint32_t cfg = 0; 24 | m_spi = (volatile uint32_t *)base_addr; 25 | 26 | cfg += (1 << SPI_CR_SPE_SHIFT); 27 | cfg += (1 << SPI_CR_MASTER_SHIFT); 28 | cfg += (0 << SPI_CR_CPOL_SHIFT); 29 | cfg += (0 << SPI_CR_CPHA_SHIFT); 30 | cfg += (1 << SPI_CR_MANUAL_SS_SHIFT); 31 | cfg += (0 << SPI_CR_LSB_FIRST_SHIFT); 32 | 33 | m_spi[SPI_CR/4] = cfg; 34 | m_spi[SPI_SSR/4] = ~0; 35 | 36 | // Soft reset 37 | m_spi[SPI_SRR/4] = 0x0000000A; 38 | } 39 | //----------------------------------------------------------------- 40 | // spi_cs: Set chip select 41 | //----------------------------------------------------------------- 42 | void spi_cs(uint32_t value) 43 | { 44 | spi_delay_ns(50); 45 | m_spi[SPI_SSR/4] = value; 46 | spi_delay_ns(50); 47 | } 48 | //----------------------------------------------------------------- 49 | // spi_sendrecv: Send or receive a character 50 | //----------------------------------------------------------------- 51 | uint8_t spi_sendrecv(uint8_t data) 52 | { 53 | m_spi[SPI_DTR/4] = data; 54 | 55 | while (!(m_spi[SPI_SR/4] & (1 << SPI_SR_TX_EMPTY_SHIFT))) 56 | ; 57 | 58 | return (uint8_t)m_spi[SPI_DRR/4]; 59 | } 60 | //----------------------------------------------------------------- 61 | // spi_readblock: Read a block of data from a device 62 | //----------------------------------------------------------------- 63 | void spi_readblock(uint8_t *ptr, int length) 64 | { 65 | int i; 66 | 67 | for (i=0;i 5 | 6 | //----------------------------------------------------------------- 7 | // Prototypes: 8 | //----------------------------------------------------------------- 9 | void spi_init(uint32_t base_addr); 10 | void spi_cs(uint32_t value); 11 | uint8_t spi_sendrecv(uint8_t ch); 12 | void spi_readblock(uint8_t *ptr, int length); 13 | void spi_writeblock(uint8_t *ptr, int length); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /src_c/spi_lite_defs.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // Basic Peripheral SoC 3 | // V1.1 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2020 6 | // 7 | // Email: admin@ultra-embedded.com 8 | // 9 | // License: GPL 10 | // If you would like a version with a more permissive license for 11 | // use in closed source commercial applications please contact me 12 | // for details. 13 | //----------------------------------------------------------------- 14 | // 15 | // This file is open source HDL; you can redistribute it and/or 16 | // modify it under the terms of the GNU General Public License as 17 | // published by the Free Software Foundation; either version 2 of 18 | // the License, or (at your option) any later version. 19 | // 20 | // This file is distributed in the hope that it will be useful, 21 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | // GNU General Public License for more details. 24 | // 25 | // You should have received a copy of the GNU General Public 26 | // License along with this file; if not, write to the Free Software 27 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 28 | // USA 29 | //----------------------------------------------------------------- 30 | 31 | //----------------------------------------------------------------- 32 | // Generated File 33 | //----------------------------------------------------------------- 34 | 35 | #ifndef __SPI_LITE_DEFS_H__ 36 | #define __SPI_LITE_DEFS_H__ 37 | 38 | #define SPI_DGIER 0x1c 39 | #define SPI_DGIER_GIE 31 40 | #define SPI_DGIER_GIE_SHIFT 31 41 | #define SPI_DGIER_GIE_MASK 0x1 42 | 43 | #define SPI_IPISR 0x20 44 | #define SPI_IPISR_TX_EMPTY 2 45 | #define SPI_IPISR_TX_EMPTY_SHIFT 2 46 | #define SPI_IPISR_TX_EMPTY_MASK 0x1 47 | 48 | #define SPI_IPIER 0x28 49 | #define SPI_IPIER_TX_EMPTY 2 50 | #define SPI_IPIER_TX_EMPTY_SHIFT 2 51 | #define SPI_IPIER_TX_EMPTY_MASK 0x1 52 | 53 | #define SPI_SRR 0x40 54 | #define SPI_SRR_RESET_SHIFT 0 55 | #define SPI_SRR_RESET_MASK 0xffffffff 56 | 57 | #define SPI_CR 0x60 58 | #define SPI_CR_LOOP 0 59 | #define SPI_CR_LOOP_SHIFT 0 60 | #define SPI_CR_LOOP_MASK 0x1 61 | 62 | #define SPI_CR_SPE 1 63 | #define SPI_CR_SPE_SHIFT 1 64 | #define SPI_CR_SPE_MASK 0x1 65 | 66 | #define SPI_CR_MASTER 2 67 | #define SPI_CR_MASTER_SHIFT 2 68 | #define SPI_CR_MASTER_MASK 0x1 69 | 70 | #define SPI_CR_CPOL 3 71 | #define SPI_CR_CPOL_SHIFT 3 72 | #define SPI_CR_CPOL_MASK 0x1 73 | 74 | #define SPI_CR_CPHA 4 75 | #define SPI_CR_CPHA_SHIFT 4 76 | #define SPI_CR_CPHA_MASK 0x1 77 | 78 | #define SPI_CR_TXFIFO_RST 5 79 | #define SPI_CR_TXFIFO_RST_SHIFT 5 80 | #define SPI_CR_TXFIFO_RST_MASK 0x1 81 | 82 | #define SPI_CR_RXFIFO_RST 6 83 | #define SPI_CR_RXFIFO_RST_SHIFT 6 84 | #define SPI_CR_RXFIFO_RST_MASK 0x1 85 | 86 | #define SPI_CR_MANUAL_SS 7 87 | #define SPI_CR_MANUAL_SS_SHIFT 7 88 | #define SPI_CR_MANUAL_SS_MASK 0x1 89 | 90 | #define SPI_CR_TRANS_INHIBIT 8 91 | #define SPI_CR_TRANS_INHIBIT_SHIFT 8 92 | #define SPI_CR_TRANS_INHIBIT_MASK 0x1 93 | 94 | #define SPI_CR_LSB_FIRST 9 95 | #define SPI_CR_LSB_FIRST_SHIFT 9 96 | #define SPI_CR_LSB_FIRST_MASK 0x1 97 | 98 | #define SPI_SR 0x64 99 | #define SPI_SR_RX_EMPTY 0 100 | #define SPI_SR_RX_EMPTY_SHIFT 0 101 | #define SPI_SR_RX_EMPTY_MASK 0x1 102 | 103 | #define SPI_SR_RX_FULL 1 104 | #define SPI_SR_RX_FULL_SHIFT 1 105 | #define SPI_SR_RX_FULL_MASK 0x1 106 | 107 | #define SPI_SR_TX_EMPTY 2 108 | #define SPI_SR_TX_EMPTY_SHIFT 2 109 | #define SPI_SR_TX_EMPTY_MASK 0x1 110 | 111 | #define SPI_SR_TX_FULL 3 112 | #define SPI_SR_TX_FULL_SHIFT 3 113 | #define SPI_SR_TX_FULL_MASK 0x1 114 | 115 | #define SPI_DTR 0x68 116 | #define SPI_DTR_DATA_SHIFT 0 117 | #define SPI_DTR_DATA_MASK 0xff 118 | 119 | #define SPI_DRR 0x6c 120 | #define SPI_DRR_DATA_SHIFT 0 121 | #define SPI_DRR_DATA_MASK 0xff 122 | 123 | #define SPI_SSR 0x70 124 | #define SPI_SSR_VALUE_SHIFT 0 125 | #define SPI_SSR_VALUE_MASK 0xff 126 | 127 | #endif -------------------------------------------------------------------------------- /src_c/timer_defs.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // Basic Peripheral SoC 3 | // V1.1 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2020 6 | // 7 | // Email: admin@ultra-embedded.com 8 | // 9 | // License: GPL 10 | // If you would like a version with a more permissive license for 11 | // use in closed source commercial applications please contact me 12 | // for details. 13 | //----------------------------------------------------------------- 14 | // 15 | // This file is open source HDL; you can redistribute it and/or 16 | // modify it under the terms of the GNU General Public License as 17 | // published by the Free Software Foundation; either version 2 of 18 | // the License, or (at your option) any later version. 19 | // 20 | // This file is distributed in the hope that it will be useful, 21 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | // GNU General Public License for more details. 24 | // 25 | // You should have received a copy of the GNU General Public 26 | // License along with this file; if not, write to the Free Software 27 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 28 | // USA 29 | //----------------------------------------------------------------- 30 | 31 | //----------------------------------------------------------------- 32 | // Generated File 33 | //----------------------------------------------------------------- 34 | 35 | #ifndef __TIMER_DEFS_H__ 36 | #define __TIMER_DEFS_H__ 37 | 38 | #define TIMER_CTRL0 0x8 39 | #define TIMER_CTRL0_INTERRUPT 1 40 | #define TIMER_CTRL0_INTERRUPT_SHIFT 1 41 | #define TIMER_CTRL0_INTERRUPT_MASK 0x1 42 | 43 | #define TIMER_CTRL0_ENABLE 2 44 | #define TIMER_CTRL0_ENABLE_SHIFT 2 45 | #define TIMER_CTRL0_ENABLE_MASK 0x1 46 | 47 | #define TIMER_CMP0 0xc 48 | #define TIMER_CMP0_VALUE_SHIFT 0 49 | #define TIMER_CMP0_VALUE_MASK 0xffffffff 50 | 51 | #define TIMER_VAL0 0x10 52 | #define TIMER_VAL0_CURRENT_SHIFT 0 53 | #define TIMER_VAL0_CURRENT_MASK 0xffffffff 54 | 55 | #define TIMER_CTRL1 0x14 56 | #define TIMER_CTRL1_INTERRUPT 1 57 | #define TIMER_CTRL1_INTERRUPT_SHIFT 1 58 | #define TIMER_CTRL1_INTERRUPT_MASK 0x1 59 | 60 | #define TIMER_CTRL1_ENABLE 2 61 | #define TIMER_CTRL1_ENABLE_SHIFT 2 62 | #define TIMER_CTRL1_ENABLE_MASK 0x1 63 | 64 | #define TIMER_CMP1 0x18 65 | #define TIMER_CMP1_VALUE_SHIFT 0 66 | #define TIMER_CMP1_VALUE_MASK 0xffffffff 67 | 68 | #define TIMER_VAL1 0x1c 69 | #define TIMER_VAL1_CURRENT_SHIFT 0 70 | #define TIMER_VAL1_CURRENT_MASK 0xffffffff 71 | 72 | #endif -------------------------------------------------------------------------------- /src_c/uart_lite.c: -------------------------------------------------------------------------------- 1 | #include "uart_lite.h" 2 | #include "uart_lite_defs.h" 3 | 4 | //----------------------------------------------------------------- 5 | // Locals 6 | //----------------------------------------------------------------- 7 | static volatile uint32_t *m_uart; 8 | 9 | //----------------------------------------------------------------- 10 | // uartlite_init: Initialise UART peripheral 11 | //----------------------------------------------------------------- 12 | void uartlite_init(uint32_t base_addr) 13 | { 14 | uint32_t cfg = 0; 15 | m_uart = (volatile uint32_t *)base_addr; 16 | 17 | // Soft reset 18 | cfg += (1 << ULITE_CONTROL_RST_RX_SHIFT); 19 | cfg += (1 << ULITE_CONTROL_RST_TX_SHIFT); 20 | cfg += (1 << ULITE_CONTROL_IE_SHIFT); 21 | 22 | m_uart[ULITE_CONTROL/4] = cfg; 23 | } 24 | //----------------------------------------------------------------- 25 | // uartlite_putc: Polled putchar 26 | //----------------------------------------------------------------- 27 | int uartlite_putc(char c) 28 | { 29 | // While TX FIFO full 30 | while (m_uart[ULITE_STATUS/4] & (1 << ULITE_STATUS_TXFULL_SHIFT)) 31 | ; 32 | 33 | m_uart[ULITE_TX/4] = c; 34 | 35 | return 0; 36 | } 37 | //----------------------------------------------------------------- 38 | // uartlite_haschar: 39 | //----------------------------------------------------------------- 40 | int uartlite_haschar(void) 41 | { 42 | return (m_uart[ULITE_STATUS/4] & (1 << ULITE_STATUS_RXVALID_SHIFT)) != 0; 43 | } 44 | //----------------------------------------------------------------- 45 | // uartlite_getchar: Read character from UART 46 | //----------------------------------------------------------------- 47 | int uartlite_getchar(void) 48 | { 49 | if (uartlite_haschar()) 50 | return (uint8_t)m_uart[ULITE_RX/4]; 51 | else 52 | return -1; 53 | } 54 | -------------------------------------------------------------------------------- /src_c/uart_lite.h: -------------------------------------------------------------------------------- 1 | #ifndef __UART_LITE_H__ 2 | #define __UART_LITE_H__ 3 | 4 | #include 5 | 6 | //----------------------------------------------------------------- 7 | // Prototypes 8 | //----------------------------------------------------------------- 9 | void uartlite_init(uint32_t base_addr); 10 | int uartlite_putc(char c); 11 | int uartlite_haschar(void); 12 | int uartlite_getchar(void); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src_c/uart_lite_defs.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // Basic Peripheral SoC 3 | // V1.1 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2020 6 | // 7 | // Email: admin@ultra-embedded.com 8 | // 9 | // License: GPL 10 | // If you would like a version with a more permissive license for 11 | // use in closed source commercial applications please contact me 12 | // for details. 13 | //----------------------------------------------------------------- 14 | // 15 | // This file is open source HDL; you can redistribute it and/or 16 | // modify it under the terms of the GNU General Public License as 17 | // published by the Free Software Foundation; either version 2 of 18 | // the License, or (at your option) any later version. 19 | // 20 | // This file is distributed in the hope that it will be useful, 21 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | // GNU General Public License for more details. 24 | // 25 | // You should have received a copy of the GNU General Public 26 | // License along with this file; if not, write to the Free Software 27 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 28 | // USA 29 | //----------------------------------------------------------------- 30 | 31 | //----------------------------------------------------------------- 32 | // Generated File 33 | //----------------------------------------------------------------- 34 | 35 | #ifndef __UART_LITE_DEFS_H__ 36 | #define __UART_LITE_DEFS_H__ 37 | 38 | #define ULITE_RX 0x0 39 | #define ULITE_RX_DATA_SHIFT 0 40 | #define ULITE_RX_DATA_MASK 0xff 41 | 42 | #define ULITE_TX 0x4 43 | #define ULITE_TX_DATA_SHIFT 0 44 | #define ULITE_TX_DATA_MASK 0xff 45 | 46 | #define ULITE_STATUS 0x8 47 | #define ULITE_STATUS_IE 4 48 | #define ULITE_STATUS_IE_SHIFT 4 49 | #define ULITE_STATUS_IE_MASK 0x1 50 | 51 | #define ULITE_STATUS_TXFULL 3 52 | #define ULITE_STATUS_TXFULL_SHIFT 3 53 | #define ULITE_STATUS_TXFULL_MASK 0x1 54 | 55 | #define ULITE_STATUS_TXEMPTY 2 56 | #define ULITE_STATUS_TXEMPTY_SHIFT 2 57 | #define ULITE_STATUS_TXEMPTY_MASK 0x1 58 | 59 | #define ULITE_STATUS_RXFULL 1 60 | #define ULITE_STATUS_RXFULL_SHIFT 1 61 | #define ULITE_STATUS_RXFULL_MASK 0x1 62 | 63 | #define ULITE_STATUS_RXVALID 0 64 | #define ULITE_STATUS_RXVALID_SHIFT 0 65 | #define ULITE_STATUS_RXVALID_MASK 0x1 66 | 67 | #define ULITE_CONTROL 0xc 68 | #define ULITE_CONTROL_IE 4 69 | #define ULITE_CONTROL_IE_SHIFT 4 70 | #define ULITE_CONTROL_IE_MASK 0x1 71 | 72 | #define ULITE_CONTROL_RST_RX 1 73 | #define ULITE_CONTROL_RST_RX_SHIFT 1 74 | #define ULITE_CONTROL_RST_RX_MASK 0x1 75 | 76 | #define ULITE_CONTROL_RST_TX 0 77 | #define ULITE_CONTROL_RST_TX_SHIFT 0 78 | #define ULITE_CONTROL_RST_TX_MASK 0x1 79 | 80 | #endif -------------------------------------------------------------------------------- /src_v/axi4lite_dist.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // Basic Peripheral SoC 3 | // V1.1 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2020 6 | // 7 | // Email: admin@ultra-embedded.com 8 | // 9 | // License: GPL 10 | // If you would like a version with a more permissive license for 11 | // use in closed source commercial applications please contact me 12 | // for details. 13 | //----------------------------------------------------------------- 14 | // 15 | // This file is open source HDL; you can redistribute it and/or 16 | // modify it under the terms of the GNU General Public License as 17 | // published by the Free Software Foundation; either version 2 of 18 | // the License, or (at your option) any later version. 19 | // 20 | // This file is distributed in the hope that it will be useful, 21 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | // GNU General Public License for more details. 24 | // 25 | // You should have received a copy of the GNU General Public 26 | // License along with this file; if not, write to the Free Software 27 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 28 | // USA 29 | //----------------------------------------------------------------- 30 | 31 | //----------------------------------------------------------------- 32 | // Generated File 33 | //----------------------------------------------------------------- 34 | 35 | module axi4lite_dist 36 | ( 37 | // Inputs 38 | input clk_i 39 | ,input rst_i 40 | ,input inport_awvalid_i 41 | ,input [ 31:0] inport_awaddr_i 42 | ,input inport_wvalid_i 43 | ,input [ 31:0] inport_wdata_i 44 | ,input [ 3:0] inport_wstrb_i 45 | ,input inport_bready_i 46 | ,input inport_arvalid_i 47 | ,input [ 31:0] inport_araddr_i 48 | ,input inport_rready_i 49 | ,input outport0_awready_i 50 | ,input outport0_wready_i 51 | ,input outport0_bvalid_i 52 | ,input [ 1:0] outport0_bresp_i 53 | ,input outport0_arready_i 54 | ,input outport0_rvalid_i 55 | ,input [ 31:0] outport0_rdata_i 56 | ,input [ 1:0] outport0_rresp_i 57 | ,input outport1_awready_i 58 | ,input outport1_wready_i 59 | ,input outport1_bvalid_i 60 | ,input [ 1:0] outport1_bresp_i 61 | ,input outport1_arready_i 62 | ,input outport1_rvalid_i 63 | ,input [ 31:0] outport1_rdata_i 64 | ,input [ 1:0] outport1_rresp_i 65 | ,input outport2_awready_i 66 | ,input outport2_wready_i 67 | ,input outport2_bvalid_i 68 | ,input [ 1:0] outport2_bresp_i 69 | ,input outport2_arready_i 70 | ,input outport2_rvalid_i 71 | ,input [ 31:0] outport2_rdata_i 72 | ,input [ 1:0] outport2_rresp_i 73 | ,input outport3_awready_i 74 | ,input outport3_wready_i 75 | ,input outport3_bvalid_i 76 | ,input [ 1:0] outport3_bresp_i 77 | ,input outport3_arready_i 78 | ,input outport3_rvalid_i 79 | ,input [ 31:0] outport3_rdata_i 80 | ,input [ 1:0] outport3_rresp_i 81 | ,input outport4_awready_i 82 | ,input outport4_wready_i 83 | ,input outport4_bvalid_i 84 | ,input [ 1:0] outport4_bresp_i 85 | ,input outport4_arready_i 86 | ,input outport4_rvalid_i 87 | ,input [ 31:0] outport4_rdata_i 88 | ,input [ 1:0] outport4_rresp_i 89 | ,input outport5_awready_i 90 | ,input outport5_wready_i 91 | ,input outport5_bvalid_i 92 | ,input [ 1:0] outport5_bresp_i 93 | ,input outport5_arready_i 94 | ,input outport5_rvalid_i 95 | ,input [ 31:0] outport5_rdata_i 96 | ,input [ 1:0] outport5_rresp_i 97 | ,input outport6_awready_i 98 | ,input outport6_wready_i 99 | ,input outport6_bvalid_i 100 | ,input [ 1:0] outport6_bresp_i 101 | ,input outport6_arready_i 102 | ,input outport6_rvalid_i 103 | ,input [ 31:0] outport6_rdata_i 104 | ,input [ 1:0] outport6_rresp_i 105 | ,input outport7_awready_i 106 | ,input outport7_wready_i 107 | ,input outport7_bvalid_i 108 | ,input [ 1:0] outport7_bresp_i 109 | ,input outport7_arready_i 110 | ,input outport7_rvalid_i 111 | ,input [ 31:0] outport7_rdata_i 112 | ,input [ 1:0] outport7_rresp_i 113 | 114 | // Outputs 115 | ,output inport_awready_o 116 | ,output inport_wready_o 117 | ,output inport_bvalid_o 118 | ,output [ 1:0] inport_bresp_o 119 | ,output inport_arready_o 120 | ,output inport_rvalid_o 121 | ,output [ 31:0] inport_rdata_o 122 | ,output [ 1:0] inport_rresp_o 123 | ,output outport0_awvalid_o 124 | ,output [ 31:0] outport0_awaddr_o 125 | ,output outport0_wvalid_o 126 | ,output [ 31:0] outport0_wdata_o 127 | ,output [ 3:0] outport0_wstrb_o 128 | ,output outport0_bready_o 129 | ,output outport0_arvalid_o 130 | ,output [ 31:0] outport0_araddr_o 131 | ,output outport0_rready_o 132 | ,output outport1_awvalid_o 133 | ,output [ 31:0] outport1_awaddr_o 134 | ,output outport1_wvalid_o 135 | ,output [ 31:0] outport1_wdata_o 136 | ,output [ 3:0] outport1_wstrb_o 137 | ,output outport1_bready_o 138 | ,output outport1_arvalid_o 139 | ,output [ 31:0] outport1_araddr_o 140 | ,output outport1_rready_o 141 | ,output outport2_awvalid_o 142 | ,output [ 31:0] outport2_awaddr_o 143 | ,output outport2_wvalid_o 144 | ,output [ 31:0] outport2_wdata_o 145 | ,output [ 3:0] outport2_wstrb_o 146 | ,output outport2_bready_o 147 | ,output outport2_arvalid_o 148 | ,output [ 31:0] outport2_araddr_o 149 | ,output outport2_rready_o 150 | ,output outport3_awvalid_o 151 | ,output [ 31:0] outport3_awaddr_o 152 | ,output outport3_wvalid_o 153 | ,output [ 31:0] outport3_wdata_o 154 | ,output [ 3:0] outport3_wstrb_o 155 | ,output outport3_bready_o 156 | ,output outport3_arvalid_o 157 | ,output [ 31:0] outport3_araddr_o 158 | ,output outport3_rready_o 159 | ,output outport4_awvalid_o 160 | ,output [ 31:0] outport4_awaddr_o 161 | ,output outport4_wvalid_o 162 | ,output [ 31:0] outport4_wdata_o 163 | ,output [ 3:0] outport4_wstrb_o 164 | ,output outport4_bready_o 165 | ,output outport4_arvalid_o 166 | ,output [ 31:0] outport4_araddr_o 167 | ,output outport4_rready_o 168 | ,output outport5_awvalid_o 169 | ,output [ 31:0] outport5_awaddr_o 170 | ,output outport5_wvalid_o 171 | ,output [ 31:0] outport5_wdata_o 172 | ,output [ 3:0] outport5_wstrb_o 173 | ,output outport5_bready_o 174 | ,output outport5_arvalid_o 175 | ,output [ 31:0] outport5_araddr_o 176 | ,output outport5_rready_o 177 | ,output outport6_awvalid_o 178 | ,output [ 31:0] outport6_awaddr_o 179 | ,output outport6_wvalid_o 180 | ,output [ 31:0] outport6_wdata_o 181 | ,output [ 3:0] outport6_wstrb_o 182 | ,output outport6_bready_o 183 | ,output outport6_arvalid_o 184 | ,output [ 31:0] outport6_araddr_o 185 | ,output outport6_rready_o 186 | ,output outport7_awvalid_o 187 | ,output [ 31:0] outport7_awaddr_o 188 | ,output outport7_wvalid_o 189 | ,output [ 31:0] outport7_wdata_o 190 | ,output [ 3:0] outport7_wstrb_o 191 | ,output outport7_bready_o 192 | ,output outport7_arvalid_o 193 | ,output [ 31:0] outport7_araddr_o 194 | ,output outport7_rready_o 195 | ); 196 | 197 | 198 | 199 | //----------------------------------------------------------------- 200 | // Read Dist 201 | //----------------------------------------------------------------- 202 | reg [2:0] read_sel_r; 203 | reg [2:0] read_sel_q; 204 | reg read_pending_q; 205 | reg read_pending_r; 206 | 207 | always @ * 208 | begin 209 | read_pending_r = read_pending_q; 210 | 211 | // Read response 212 | if (inport_rvalid_o && inport_rready_i) 213 | read_pending_r = 1'b0; 214 | // New request 215 | else if (!read_pending_r && inport_arvalid_i) 216 | read_pending_r = inport_arready_o; 217 | 218 | // Address to port selection 219 | if (!read_pending_q) 220 | read_sel_r = inport_araddr_i[26:24]; 221 | else 222 | read_sel_r = read_sel_q; 223 | end 224 | 225 | always @ (posedge clk_i or posedge rst_i) 226 | if (rst_i) 227 | begin 228 | read_sel_q <= 3'b0; 229 | read_pending_q <= 1'b0; 230 | end 231 | else 232 | begin 233 | read_sel_q <= read_sel_r; 234 | read_pending_q <= read_pending_r; 235 | end 236 | 237 | //----------------------------------------------------------------- 238 | // Read Request 239 | //----------------------------------------------------------------- 240 | assign outport0_arvalid_o = inport_arvalid_i && (read_sel_r == 3'd0) && !read_pending_q; 241 | assign outport0_araddr_o = inport_araddr_i; 242 | assign outport1_arvalid_o = inport_arvalid_i && (read_sel_r == 3'd1) && !read_pending_q; 243 | assign outport1_araddr_o = inport_araddr_i; 244 | assign outport2_arvalid_o = inport_arvalid_i && (read_sel_r == 3'd2) && !read_pending_q; 245 | assign outport2_araddr_o = inport_araddr_i; 246 | assign outport3_arvalid_o = inport_arvalid_i && (read_sel_r == 3'd3) && !read_pending_q; 247 | assign outport3_araddr_o = inport_araddr_i; 248 | assign outport4_arvalid_o = inport_arvalid_i && (read_sel_r == 3'd4) && !read_pending_q; 249 | assign outport4_araddr_o = inport_araddr_i; 250 | assign outport5_arvalid_o = inport_arvalid_i && (read_sel_r == 3'd5) && !read_pending_q; 251 | assign outport5_araddr_o = inport_araddr_i; 252 | assign outport6_arvalid_o = inport_arvalid_i && (read_sel_r == 3'd6) && !read_pending_q; 253 | assign outport6_araddr_o = inport_araddr_i; 254 | assign outport7_arvalid_o = inport_arvalid_i && (read_sel_r == 3'd7) && !read_pending_q; 255 | assign outport7_araddr_o = inport_araddr_i; 256 | 257 | //----------------------------------------------------------------- 258 | // Read Request Accept 259 | //----------------------------------------------------------------- 260 | reg inport_arready_r; 261 | 262 | always @ * 263 | begin 264 | inport_arready_r = 1'b0; 265 | 266 | case (read_sel_r) 267 | 3'd0: 268 | inport_arready_r = outport0_arready_i; 269 | 3'd1: 270 | inport_arready_r = outport1_arready_i; 271 | 3'd2: 272 | inport_arready_r = outport2_arready_i; 273 | 3'd3: 274 | inport_arready_r = outport3_arready_i; 275 | 3'd4: 276 | inport_arready_r = outport4_arready_i; 277 | 3'd5: 278 | inport_arready_r = outport5_arready_i; 279 | 3'd6: 280 | inport_arready_r = outport6_arready_i; 281 | 3'd7: 282 | inport_arready_r = outport7_arready_i; 283 | default : 284 | ; 285 | endcase 286 | end 287 | 288 | assign inport_arready_o = inport_arready_r && !read_pending_q; 289 | 290 | //----------------------------------------------------------------- 291 | // Read Response 292 | //----------------------------------------------------------------- 293 | reg inport_rvalid_r; 294 | reg [31:0] inport_rdata_r; 295 | reg [1:0] inport_rresp_r; 296 | 297 | always @ * 298 | begin 299 | inport_rvalid_r = 1'b0; 300 | inport_rdata_r = 32'b0; 301 | inport_rresp_r = 2'b0; 302 | 303 | case (read_sel_q) 304 | 3'd0: 305 | begin 306 | inport_rvalid_r = outport0_rvalid_i; 307 | inport_rdata_r = outport0_rdata_i; 308 | inport_rresp_r = outport0_rresp_i; 309 | end 310 | 3'd1: 311 | begin 312 | inport_rvalid_r = outport1_rvalid_i; 313 | inport_rdata_r = outport1_rdata_i; 314 | inport_rresp_r = outport1_rresp_i; 315 | end 316 | 3'd2: 317 | begin 318 | inport_rvalid_r = outport2_rvalid_i; 319 | inport_rdata_r = outport2_rdata_i; 320 | inport_rresp_r = outport2_rresp_i; 321 | end 322 | 3'd3: 323 | begin 324 | inport_rvalid_r = outport3_rvalid_i; 325 | inport_rdata_r = outport3_rdata_i; 326 | inport_rresp_r = outport3_rresp_i; 327 | end 328 | 3'd4: 329 | begin 330 | inport_rvalid_r = outport4_rvalid_i; 331 | inport_rdata_r = outport4_rdata_i; 332 | inport_rresp_r = outport4_rresp_i; 333 | end 334 | 3'd5: 335 | begin 336 | inport_rvalid_r = outport5_rvalid_i; 337 | inport_rdata_r = outport5_rdata_i; 338 | inport_rresp_r = outport5_rresp_i; 339 | end 340 | 3'd6: 341 | begin 342 | inport_rvalid_r = outport6_rvalid_i; 343 | inport_rdata_r = outport6_rdata_i; 344 | inport_rresp_r = outport6_rresp_i; 345 | end 346 | 3'd7: 347 | begin 348 | inport_rvalid_r = outport7_rvalid_i; 349 | inport_rdata_r = outport7_rdata_i; 350 | inport_rresp_r = outport7_rresp_i; 351 | end 352 | default : 353 | ; 354 | endcase 355 | end 356 | 357 | assign inport_rvalid_o = inport_rvalid_r; 358 | assign inport_rdata_o = inport_rdata_r; 359 | assign inport_rresp_o = inport_rresp_r; 360 | 361 | //----------------------------------------------------------------- 362 | // Read Response accept 363 | //----------------------------------------------------------------- 364 | assign outport0_rready_o = inport_rready_i && (read_sel_q == 3'd0); 365 | assign outport1_rready_o = inport_rready_i && (read_sel_q == 3'd1); 366 | assign outport2_rready_o = inport_rready_i && (read_sel_q == 3'd2); 367 | assign outport3_rready_o = inport_rready_i && (read_sel_q == 3'd3); 368 | assign outport4_rready_o = inport_rready_i && (read_sel_q == 3'd4); 369 | assign outport5_rready_o = inport_rready_i && (read_sel_q == 3'd5); 370 | assign outport6_rready_o = inport_rready_i && (read_sel_q == 3'd6); 371 | assign outport7_rready_o = inport_rready_i && (read_sel_q == 3'd7); 372 | 373 | //----------------------------------------------------------------- 374 | // Write command tracking 375 | //----------------------------------------------------------------- 376 | reg awvalid_q; 377 | reg wvalid_q; 378 | wire wr_cmd_accepted_w = (inport_awvalid_i && inport_awready_o) || awvalid_q; 379 | wire wr_data_accepted_w = (inport_wvalid_i && inport_wready_o) || wvalid_q; 380 | 381 | reg awvalid_r; 382 | 383 | always @ * 384 | begin 385 | awvalid_r = awvalid_q; 386 | 387 | // Address ready, data not ready 388 | if (inport_awvalid_i && inport_awready_o && !wr_data_accepted_w) 389 | awvalid_r = 1'b1; 390 | else if (wr_data_accepted_w) 391 | awvalid_r = 1'b0; 392 | end 393 | 394 | always @ (posedge clk_i or posedge rst_i) 395 | if (rst_i) 396 | awvalid_q <= 1'b0; 397 | else 398 | awvalid_q <= awvalid_r; 399 | 400 | //----------------------------------------------------------------- 401 | // Write data tracking 402 | //----------------------------------------------------------------- 403 | reg wvalid_r; 404 | 405 | always @ * 406 | begin 407 | wvalid_r = wvalid_q; 408 | 409 | // Data ready, address not ready 410 | if (inport_wvalid_i && inport_wready_o && !wr_cmd_accepted_w) 411 | wvalid_r = 1'b1; 412 | else if (wr_cmd_accepted_w) 413 | wvalid_r = 1'b0; 414 | end 415 | 416 | always @ (posedge clk_i or posedge rst_i) 417 | if (rst_i) 418 | wvalid_q <= 1'b0; 419 | else 420 | wvalid_q <= wvalid_r; 421 | 422 | //----------------------------------------------------------------- 423 | // Write Dist 424 | //----------------------------------------------------------------- 425 | reg [2:0] write_sel_r; 426 | reg [2:0] write_sel_q; 427 | reg write_pending_q; 428 | reg write_pending_r; 429 | 430 | always @ * 431 | begin 432 | write_pending_r = write_pending_q; 433 | write_sel_r = write_sel_q; 434 | 435 | // Write response 436 | if (inport_bvalid_o && inport_bready_i) 437 | write_pending_r = 1'b0; 438 | // New request - both command and data accepted 439 | else if (wr_cmd_accepted_w && wr_data_accepted_w) 440 | write_pending_r = 1'b1; 441 | 442 | // New request - latch address to port selection 443 | if (inport_awvalid_i && !awvalid_q && !write_pending_q) 444 | write_sel_r = inport_awaddr_i[26:24]; 445 | end 446 | 447 | always @ (posedge clk_i or posedge rst_i) 448 | if (rst_i) 449 | begin 450 | write_sel_q <= 3'b0; 451 | write_pending_q <= 1'b0; 452 | end 453 | else 454 | begin 455 | write_sel_q <= write_sel_r; 456 | write_pending_q <= write_pending_r; 457 | end 458 | 459 | //----------------------------------------------------------------- 460 | // Write Request 461 | //----------------------------------------------------------------- 462 | assign outport0_awvalid_o = inport_awvalid_i && (write_sel_r == 3'd0) && !awvalid_q && !write_pending_q; 463 | assign outport0_awaddr_o = inport_awaddr_i; 464 | assign outport0_wvalid_o = inport_wvalid_i && (inport_awvalid_i || awvalid_q) && (write_sel_r == 3'd0) && !wvalid_q && !write_pending_q; 465 | assign outport0_wdata_o = inport_wdata_i; 466 | assign outport0_wstrb_o = inport_wstrb_i; 467 | assign outport1_awvalid_o = inport_awvalid_i && (write_sel_r == 3'd1) && !awvalid_q && !write_pending_q; 468 | assign outport1_awaddr_o = inport_awaddr_i; 469 | assign outport1_wvalid_o = inport_wvalid_i && (inport_awvalid_i || awvalid_q) && (write_sel_r == 3'd1) && !wvalid_q && !write_pending_q; 470 | assign outport1_wdata_o = inport_wdata_i; 471 | assign outport1_wstrb_o = inport_wstrb_i; 472 | assign outport2_awvalid_o = inport_awvalid_i && (write_sel_r == 3'd2) && !awvalid_q && !write_pending_q; 473 | assign outport2_awaddr_o = inport_awaddr_i; 474 | assign outport2_wvalid_o = inport_wvalid_i && (inport_awvalid_i || awvalid_q) && (write_sel_r == 3'd2) && !wvalid_q && !write_pending_q; 475 | assign outport2_wdata_o = inport_wdata_i; 476 | assign outport2_wstrb_o = inport_wstrb_i; 477 | assign outport3_awvalid_o = inport_awvalid_i && (write_sel_r == 3'd3) && !awvalid_q && !write_pending_q; 478 | assign outport3_awaddr_o = inport_awaddr_i; 479 | assign outport3_wvalid_o = inport_wvalid_i && (inport_awvalid_i || awvalid_q) && (write_sel_r == 3'd3) && !wvalid_q && !write_pending_q; 480 | assign outport3_wdata_o = inport_wdata_i; 481 | assign outport3_wstrb_o = inport_wstrb_i; 482 | assign outport4_awvalid_o = inport_awvalid_i && (write_sel_r == 3'd4) && !awvalid_q && !write_pending_q; 483 | assign outport4_awaddr_o = inport_awaddr_i; 484 | assign outport4_wvalid_o = inport_wvalid_i && (inport_awvalid_i || awvalid_q) && (write_sel_r == 3'd4) && !wvalid_q && !write_pending_q; 485 | assign outport4_wdata_o = inport_wdata_i; 486 | assign outport4_wstrb_o = inport_wstrb_i; 487 | assign outport5_awvalid_o = inport_awvalid_i && (write_sel_r == 3'd5) && !awvalid_q && !write_pending_q; 488 | assign outport5_awaddr_o = inport_awaddr_i; 489 | assign outport5_wvalid_o = inport_wvalid_i && (inport_awvalid_i || awvalid_q) && (write_sel_r == 3'd5) && !wvalid_q && !write_pending_q; 490 | assign outport5_wdata_o = inport_wdata_i; 491 | assign outport5_wstrb_o = inport_wstrb_i; 492 | assign outport6_awvalid_o = inport_awvalid_i && (write_sel_r == 3'd6) && !awvalid_q && !write_pending_q; 493 | assign outport6_awaddr_o = inport_awaddr_i; 494 | assign outport6_wvalid_o = inport_wvalid_i && (inport_awvalid_i || awvalid_q) && (write_sel_r == 3'd6) && !wvalid_q && !write_pending_q; 495 | assign outport6_wdata_o = inport_wdata_i; 496 | assign outport6_wstrb_o = inport_wstrb_i; 497 | assign outport7_awvalid_o = inport_awvalid_i && (write_sel_r == 3'd7) && !awvalid_q && !write_pending_q; 498 | assign outport7_awaddr_o = inport_awaddr_i; 499 | assign outport7_wvalid_o = inport_wvalid_i && (inport_awvalid_i || awvalid_q) && (write_sel_r == 3'd7) && !wvalid_q && !write_pending_q; 500 | assign outport7_wdata_o = inport_wdata_i; 501 | assign outport7_wstrb_o = inport_wstrb_i; 502 | 503 | //----------------------------------------------------------------- 504 | // Write Request Accept 505 | //----------------------------------------------------------------- 506 | reg inport_awready_r; 507 | reg inport_wready_r; 508 | 509 | always @ * 510 | begin 511 | inport_awready_r = 1'b0; 512 | inport_wready_r = 1'b0; 513 | 514 | case (write_sel_r) 515 | 3'd0: 516 | begin 517 | inport_awready_r = outport0_awready_i; 518 | inport_wready_r = outport0_wready_i; 519 | end 520 | 3'd1: 521 | begin 522 | inport_awready_r = outport1_awready_i; 523 | inport_wready_r = outport1_wready_i; 524 | end 525 | 3'd2: 526 | begin 527 | inport_awready_r = outport2_awready_i; 528 | inport_wready_r = outport2_wready_i; 529 | end 530 | 3'd3: 531 | begin 532 | inport_awready_r = outport3_awready_i; 533 | inport_wready_r = outport3_wready_i; 534 | end 535 | 3'd4: 536 | begin 537 | inport_awready_r = outport4_awready_i; 538 | inport_wready_r = outport4_wready_i; 539 | end 540 | 3'd5: 541 | begin 542 | inport_awready_r = outport5_awready_i; 543 | inport_wready_r = outport5_wready_i; 544 | end 545 | 3'd6: 546 | begin 547 | inport_awready_r = outport6_awready_i; 548 | inport_wready_r = outport6_wready_i; 549 | end 550 | 3'd7: 551 | begin 552 | inport_awready_r = outport7_awready_i; 553 | inport_wready_r = outport7_wready_i; 554 | end 555 | default : 556 | ; 557 | endcase 558 | end 559 | 560 | assign inport_awready_o = inport_awready_r && !awvalid_q && !write_pending_q; 561 | assign inport_wready_o = inport_wready_r && !wvalid_q && !write_pending_q; 562 | 563 | //----------------------------------------------------------------- 564 | // Write Response 565 | //----------------------------------------------------------------- 566 | reg inport_bvalid_r; 567 | reg [1:0] inport_bresp_r; 568 | 569 | always @ * 570 | begin 571 | inport_bvalid_r = 1'b0; 572 | inport_bresp_r = 2'b0; 573 | 574 | case (write_sel_q) 575 | 3'd0: 576 | begin 577 | inport_bvalid_r = outport0_bvalid_i; 578 | inport_bresp_r = outport0_bresp_i; 579 | end 580 | 3'd1: 581 | begin 582 | inport_bvalid_r = outport1_bvalid_i; 583 | inport_bresp_r = outport1_bresp_i; 584 | end 585 | 3'd2: 586 | begin 587 | inport_bvalid_r = outport2_bvalid_i; 588 | inport_bresp_r = outport2_bresp_i; 589 | end 590 | 3'd3: 591 | begin 592 | inport_bvalid_r = outport3_bvalid_i; 593 | inport_bresp_r = outport3_bresp_i; 594 | end 595 | 3'd4: 596 | begin 597 | inport_bvalid_r = outport4_bvalid_i; 598 | inport_bresp_r = outport4_bresp_i; 599 | end 600 | 3'd5: 601 | begin 602 | inport_bvalid_r = outport5_bvalid_i; 603 | inport_bresp_r = outport5_bresp_i; 604 | end 605 | 3'd6: 606 | begin 607 | inport_bvalid_r = outport6_bvalid_i; 608 | inport_bresp_r = outport6_bresp_i; 609 | end 610 | 3'd7: 611 | begin 612 | inport_bvalid_r = outport7_bvalid_i; 613 | inport_bresp_r = outport7_bresp_i; 614 | end 615 | default : 616 | ; 617 | endcase 618 | end 619 | 620 | assign inport_bvalid_o = inport_bvalid_r; 621 | assign inport_bresp_o = inport_bresp_r; 622 | 623 | //----------------------------------------------------------------- 624 | // Write Response accept 625 | //----------------------------------------------------------------- 626 | assign outport0_bready_o = inport_bready_i && (write_sel_q == 3'd0); 627 | assign outport1_bready_o = inport_bready_i && (write_sel_q == 3'd1); 628 | assign outport2_bready_o = inport_bready_i && (write_sel_q == 3'd2); 629 | assign outport3_bready_o = inport_bready_i && (write_sel_q == 3'd3); 630 | assign outport4_bready_o = inport_bready_i && (write_sel_q == 3'd4); 631 | assign outport5_bready_o = inport_bready_i && (write_sel_q == 3'd5); 632 | assign outport6_bready_o = inport_bready_i && (write_sel_q == 3'd6); 633 | assign outport7_bready_o = inport_bready_i && (write_sel_q == 3'd7); 634 | 635 | 636 | 637 | endmodule 638 | -------------------------------------------------------------------------------- /src_v/core_soc.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // Basic Peripheral SoC 3 | // V1.1 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2020 6 | // 7 | // Email: admin@ultra-embedded.com 8 | // 9 | // License: GPL 10 | // If you would like a version with a more permissive license for 11 | // use in closed source commercial applications please contact me 12 | // for details. 13 | //----------------------------------------------------------------- 14 | // 15 | // This file is open source HDL; you can redistribute it and/or 16 | // modify it under the terms of the GNU General Public License as 17 | // published by the Free Software Foundation; either version 2 of 18 | // the License, or (at your option) any later version. 19 | // 20 | // This file is distributed in the hope that it will be useful, 21 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | // GNU General Public License for more details. 24 | // 25 | // You should have received a copy of the GNU General Public 26 | // License along with this file; if not, write to the Free Software 27 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 28 | // USA 29 | //----------------------------------------------------------------- 30 | 31 | //----------------------------------------------------------------- 32 | // Generated File 33 | //----------------------------------------------------------------- 34 | 35 | module core_soc 36 | //----------------------------------------------------------------- 37 | // Params 38 | //----------------------------------------------------------------- 39 | #( 40 | parameter CLK_FREQ = 50000000 41 | ,parameter BAUDRATE = 1000000 42 | ,parameter C_SCK_RATIO = 50 43 | ) 44 | //----------------------------------------------------------------- 45 | // Ports 46 | //----------------------------------------------------------------- 47 | ( 48 | // Inputs 49 | input clk_i 50 | ,input rst_i 51 | ,input inport_awvalid_i 52 | ,input [ 31:0] inport_awaddr_i 53 | ,input inport_wvalid_i 54 | ,input [ 31:0] inport_wdata_i 55 | ,input [ 3:0] inport_wstrb_i 56 | ,input inport_bready_i 57 | ,input inport_arvalid_i 58 | ,input [ 31:0] inport_araddr_i 59 | ,input inport_rready_i 60 | ,input spi_miso_i 61 | ,input uart_rx_i 62 | ,input [ 31:0] gpio_input_i 63 | ,input ext1_cfg_awready_i 64 | ,input ext1_cfg_wready_i 65 | ,input ext1_cfg_bvalid_i 66 | ,input [ 1:0] ext1_cfg_bresp_i 67 | ,input ext1_cfg_arready_i 68 | ,input ext1_cfg_rvalid_i 69 | ,input [ 31:0] ext1_cfg_rdata_i 70 | ,input [ 1:0] ext1_cfg_rresp_i 71 | ,input ext1_irq_i 72 | ,input ext2_cfg_awready_i 73 | ,input ext2_cfg_wready_i 74 | ,input ext2_cfg_bvalid_i 75 | ,input [ 1:0] ext2_cfg_bresp_i 76 | ,input ext2_cfg_arready_i 77 | ,input ext2_cfg_rvalid_i 78 | ,input [ 31:0] ext2_cfg_rdata_i 79 | ,input [ 1:0] ext2_cfg_rresp_i 80 | ,input ext2_irq_i 81 | ,input ext3_cfg_awready_i 82 | ,input ext3_cfg_wready_i 83 | ,input ext3_cfg_bvalid_i 84 | ,input [ 1:0] ext3_cfg_bresp_i 85 | ,input ext3_cfg_arready_i 86 | ,input ext3_cfg_rvalid_i 87 | ,input [ 31:0] ext3_cfg_rdata_i 88 | ,input [ 1:0] ext3_cfg_rresp_i 89 | ,input ext3_irq_i 90 | 91 | // Outputs 92 | ,output intr_o 93 | ,output inport_awready_o 94 | ,output inport_wready_o 95 | ,output inport_bvalid_o 96 | ,output [ 1:0] inport_bresp_o 97 | ,output inport_arready_o 98 | ,output inport_rvalid_o 99 | ,output [ 31:0] inport_rdata_o 100 | ,output [ 1:0] inport_rresp_o 101 | ,output spi_clk_o 102 | ,output spi_mosi_o 103 | ,output [ 7:0] spi_cs_o 104 | ,output uart_tx_o 105 | ,output [ 31:0] gpio_output_o 106 | ,output [ 31:0] gpio_output_enable_o 107 | ,output ext1_cfg_awvalid_o 108 | ,output [ 31:0] ext1_cfg_awaddr_o 109 | ,output ext1_cfg_wvalid_o 110 | ,output [ 31:0] ext1_cfg_wdata_o 111 | ,output [ 3:0] ext1_cfg_wstrb_o 112 | ,output ext1_cfg_bready_o 113 | ,output ext1_cfg_arvalid_o 114 | ,output [ 31:0] ext1_cfg_araddr_o 115 | ,output ext1_cfg_rready_o 116 | ,output ext2_cfg_awvalid_o 117 | ,output [ 31:0] ext2_cfg_awaddr_o 118 | ,output ext2_cfg_wvalid_o 119 | ,output [ 31:0] ext2_cfg_wdata_o 120 | ,output [ 3:0] ext2_cfg_wstrb_o 121 | ,output ext2_cfg_bready_o 122 | ,output ext2_cfg_arvalid_o 123 | ,output [ 31:0] ext2_cfg_araddr_o 124 | ,output ext2_cfg_rready_o 125 | ,output ext3_cfg_awvalid_o 126 | ,output [ 31:0] ext3_cfg_awaddr_o 127 | ,output ext3_cfg_wvalid_o 128 | ,output [ 31:0] ext3_cfg_wdata_o 129 | ,output [ 3:0] ext3_cfg_wstrb_o 130 | ,output ext3_cfg_bready_o 131 | ,output ext3_cfg_arvalid_o 132 | ,output [ 31:0] ext3_cfg_araddr_o 133 | ,output ext3_cfg_rready_o 134 | ); 135 | 136 | wire [ 31:0] periph1_rdata_w; 137 | wire [ 1:0] periph0_bresp_w; 138 | wire periph2_awvalid_w; 139 | wire [ 1:0] periph3_rresp_w; 140 | wire periph4_arready_w; 141 | wire periph1_bready_w; 142 | wire periph2_arready_w; 143 | wire periph3_arvalid_w; 144 | wire [ 31:0] periph4_rdata_w; 145 | wire periph3_bready_w; 146 | wire periph3_rvalid_w; 147 | wire periph4_bvalid_w; 148 | wire periph1_bvalid_w; 149 | wire periph4_arvalid_w; 150 | wire periph2_bready_w; 151 | wire periph0_rvalid_w; 152 | wire periph2_awready_w; 153 | wire periph2_arvalid_w; 154 | wire periph1_arvalid_w; 155 | wire [ 31:0] periph2_rdata_w; 156 | wire periph0_awvalid_w; 157 | wire [ 31:0] periph3_araddr_w; 158 | wire [ 1:0] periph1_rresp_w; 159 | wire [ 31:0] periph0_rdata_w; 160 | wire [ 3:0] periph4_wstrb_w; 161 | wire [ 31:0] periph2_awaddr_w; 162 | wire [ 1:0] periph4_bresp_w; 163 | wire periph1_arready_w; 164 | wire [ 31:0] periph3_rdata_w; 165 | wire periph4_rready_w; 166 | wire periph1_wvalid_w; 167 | wire [ 31:0] periph4_araddr_w; 168 | wire periph0_bvalid_w; 169 | wire periph0_rready_w; 170 | wire periph1_rready_w; 171 | wire periph4_rvalid_w; 172 | wire periph3_arready_w; 173 | wire [ 1:0] periph2_bresp_w; 174 | wire periph3_awvalid_w; 175 | wire periph4_wready_w; 176 | wire [ 31:0] periph3_awaddr_w; 177 | wire [ 3:0] periph1_wstrb_w; 178 | wire [ 1:0] periph0_rresp_w; 179 | wire [ 3:0] periph0_wstrb_w; 180 | wire [ 31:0] periph1_wdata_w; 181 | wire periph1_awready_w; 182 | wire interrupt1_w; 183 | wire interrupt0_w; 184 | wire interrupt3_w; 185 | wire interrupt2_w; 186 | wire [ 31:0] periph1_awaddr_w; 187 | wire periph4_awvalid_w; 188 | wire periph3_awready_w; 189 | wire periph1_awvalid_w; 190 | wire periph3_wready_w; 191 | wire periph0_wready_w; 192 | wire [ 31:0] periph0_awaddr_w; 193 | wire [ 1:0] periph3_bresp_w; 194 | wire periph0_arvalid_w; 195 | wire periph3_bvalid_w; 196 | wire periph0_bready_w; 197 | wire [ 31:0] periph2_wdata_w; 198 | wire periph4_wvalid_w; 199 | wire periph0_wvalid_w; 200 | wire [ 3:0] periph2_wstrb_w; 201 | wire periph2_rvalid_w; 202 | wire [ 31:0] periph4_awaddr_w; 203 | wire [ 1:0] periph4_rresp_w; 204 | wire [ 1:0] periph1_bresp_w; 205 | wire periph1_wready_w; 206 | wire periph2_rready_w; 207 | wire periph2_bvalid_w; 208 | wire periph2_wready_w; 209 | wire [ 31:0] periph0_wdata_w; 210 | wire [ 3:0] periph3_wstrb_w; 211 | wire [ 31:0] periph4_wdata_w; 212 | wire periph0_awready_w; 213 | wire periph1_rvalid_w; 214 | wire [ 31:0] periph1_araddr_w; 215 | wire periph4_awready_w; 216 | wire periph0_arready_w; 217 | wire [ 31:0] periph2_araddr_w; 218 | wire periph3_wvalid_w; 219 | wire [ 1:0] periph2_rresp_w; 220 | wire [ 31:0] periph0_araddr_w; 221 | wire periph4_bready_w; 222 | wire [ 31:0] periph3_wdata_w; 223 | wire periph3_rready_w; 224 | wire periph2_wvalid_w; 225 | 226 | 227 | irq_ctrl 228 | u_intc 229 | ( 230 | // Inputs 231 | .clk_i(clk_i) 232 | ,.rst_i(rst_i) 233 | ,.cfg_awvalid_i(periph0_awvalid_w) 234 | ,.cfg_awaddr_i(periph0_awaddr_w) 235 | ,.cfg_wvalid_i(periph0_wvalid_w) 236 | ,.cfg_wdata_i(periph0_wdata_w) 237 | ,.cfg_wstrb_i(periph0_wstrb_w) 238 | ,.cfg_bready_i(periph0_bready_w) 239 | ,.cfg_arvalid_i(periph0_arvalid_w) 240 | ,.cfg_araddr_i(periph0_araddr_w) 241 | ,.cfg_rready_i(periph0_rready_w) 242 | ,.interrupt0_i(interrupt0_w) 243 | ,.interrupt1_i(interrupt1_w) 244 | ,.interrupt2_i(interrupt2_w) 245 | ,.interrupt3_i(interrupt3_w) 246 | ,.interrupt4_i(ext1_irq_i) 247 | ,.interrupt5_i(ext2_irq_i) 248 | ,.interrupt6_i(ext3_irq_i) 249 | 250 | // Outputs 251 | ,.cfg_awready_o(periph0_awready_w) 252 | ,.cfg_wready_o(periph0_wready_w) 253 | ,.cfg_bvalid_o(periph0_bvalid_w) 254 | ,.cfg_bresp_o(periph0_bresp_w) 255 | ,.cfg_arready_o(periph0_arready_w) 256 | ,.cfg_rvalid_o(periph0_rvalid_w) 257 | ,.cfg_rdata_o(periph0_rdata_w) 258 | ,.cfg_rresp_o(periph0_rresp_w) 259 | ,.intr_o(intr_o) 260 | ); 261 | 262 | 263 | axi4lite_dist 264 | u_dist 265 | ( 266 | // Inputs 267 | .clk_i(clk_i) 268 | ,.rst_i(rst_i) 269 | ,.inport_awvalid_i(inport_awvalid_i) 270 | ,.inport_awaddr_i(inport_awaddr_i) 271 | ,.inport_wvalid_i(inport_wvalid_i) 272 | ,.inport_wdata_i(inport_wdata_i) 273 | ,.inport_wstrb_i(inport_wstrb_i) 274 | ,.inport_bready_i(inport_bready_i) 275 | ,.inport_arvalid_i(inport_arvalid_i) 276 | ,.inport_araddr_i(inport_araddr_i) 277 | ,.inport_rready_i(inport_rready_i) 278 | ,.outport0_awready_i(periph0_awready_w) 279 | ,.outport0_wready_i(periph0_wready_w) 280 | ,.outport0_bvalid_i(periph0_bvalid_w) 281 | ,.outport0_bresp_i(periph0_bresp_w) 282 | ,.outport0_arready_i(periph0_arready_w) 283 | ,.outport0_rvalid_i(periph0_rvalid_w) 284 | ,.outport0_rdata_i(periph0_rdata_w) 285 | ,.outport0_rresp_i(periph0_rresp_w) 286 | ,.outport1_awready_i(periph1_awready_w) 287 | ,.outport1_wready_i(periph1_wready_w) 288 | ,.outport1_bvalid_i(periph1_bvalid_w) 289 | ,.outport1_bresp_i(periph1_bresp_w) 290 | ,.outport1_arready_i(periph1_arready_w) 291 | ,.outport1_rvalid_i(periph1_rvalid_w) 292 | ,.outport1_rdata_i(periph1_rdata_w) 293 | ,.outport1_rresp_i(periph1_rresp_w) 294 | ,.outport2_awready_i(periph2_awready_w) 295 | ,.outport2_wready_i(periph2_wready_w) 296 | ,.outport2_bvalid_i(periph2_bvalid_w) 297 | ,.outport2_bresp_i(periph2_bresp_w) 298 | ,.outport2_arready_i(periph2_arready_w) 299 | ,.outport2_rvalid_i(periph2_rvalid_w) 300 | ,.outport2_rdata_i(periph2_rdata_w) 301 | ,.outport2_rresp_i(periph2_rresp_w) 302 | ,.outport3_awready_i(periph3_awready_w) 303 | ,.outport3_wready_i(periph3_wready_w) 304 | ,.outport3_bvalid_i(periph3_bvalid_w) 305 | ,.outport3_bresp_i(periph3_bresp_w) 306 | ,.outport3_arready_i(periph3_arready_w) 307 | ,.outport3_rvalid_i(periph3_rvalid_w) 308 | ,.outport3_rdata_i(periph3_rdata_w) 309 | ,.outport3_rresp_i(periph3_rresp_w) 310 | ,.outport4_awready_i(periph4_awready_w) 311 | ,.outport4_wready_i(periph4_wready_w) 312 | ,.outport4_bvalid_i(periph4_bvalid_w) 313 | ,.outport4_bresp_i(periph4_bresp_w) 314 | ,.outport4_arready_i(periph4_arready_w) 315 | ,.outport4_rvalid_i(periph4_rvalid_w) 316 | ,.outport4_rdata_i(periph4_rdata_w) 317 | ,.outport4_rresp_i(periph4_rresp_w) 318 | ,.outport5_awready_i(ext1_cfg_awready_i) 319 | ,.outport5_wready_i(ext1_cfg_wready_i) 320 | ,.outport5_bvalid_i(ext1_cfg_bvalid_i) 321 | ,.outport5_bresp_i(ext1_cfg_bresp_i) 322 | ,.outport5_arready_i(ext1_cfg_arready_i) 323 | ,.outport5_rvalid_i(ext1_cfg_rvalid_i) 324 | ,.outport5_rdata_i(ext1_cfg_rdata_i) 325 | ,.outport5_rresp_i(ext1_cfg_rresp_i) 326 | ,.outport6_awready_i(ext2_cfg_awready_i) 327 | ,.outport6_wready_i(ext2_cfg_wready_i) 328 | ,.outport6_bvalid_i(ext2_cfg_bvalid_i) 329 | ,.outport6_bresp_i(ext2_cfg_bresp_i) 330 | ,.outport6_arready_i(ext2_cfg_arready_i) 331 | ,.outport6_rvalid_i(ext2_cfg_rvalid_i) 332 | ,.outport6_rdata_i(ext2_cfg_rdata_i) 333 | ,.outport6_rresp_i(ext2_cfg_rresp_i) 334 | ,.outport7_awready_i(ext3_cfg_awready_i) 335 | ,.outport7_wready_i(ext3_cfg_wready_i) 336 | ,.outport7_bvalid_i(ext3_cfg_bvalid_i) 337 | ,.outport7_bresp_i(ext3_cfg_bresp_i) 338 | ,.outport7_arready_i(ext3_cfg_arready_i) 339 | ,.outport7_rvalid_i(ext3_cfg_rvalid_i) 340 | ,.outport7_rdata_i(ext3_cfg_rdata_i) 341 | ,.outport7_rresp_i(ext3_cfg_rresp_i) 342 | 343 | // Outputs 344 | ,.inport_awready_o(inport_awready_o) 345 | ,.inport_wready_o(inport_wready_o) 346 | ,.inport_bvalid_o(inport_bvalid_o) 347 | ,.inport_bresp_o(inport_bresp_o) 348 | ,.inport_arready_o(inport_arready_o) 349 | ,.inport_rvalid_o(inport_rvalid_o) 350 | ,.inport_rdata_o(inport_rdata_o) 351 | ,.inport_rresp_o(inport_rresp_o) 352 | ,.outport0_awvalid_o(periph0_awvalid_w) 353 | ,.outport0_awaddr_o(periph0_awaddr_w) 354 | ,.outport0_wvalid_o(periph0_wvalid_w) 355 | ,.outport0_wdata_o(periph0_wdata_w) 356 | ,.outport0_wstrb_o(periph0_wstrb_w) 357 | ,.outport0_bready_o(periph0_bready_w) 358 | ,.outport0_arvalid_o(periph0_arvalid_w) 359 | ,.outport0_araddr_o(periph0_araddr_w) 360 | ,.outport0_rready_o(periph0_rready_w) 361 | ,.outport1_awvalid_o(periph1_awvalid_w) 362 | ,.outport1_awaddr_o(periph1_awaddr_w) 363 | ,.outport1_wvalid_o(periph1_wvalid_w) 364 | ,.outport1_wdata_o(periph1_wdata_w) 365 | ,.outport1_wstrb_o(periph1_wstrb_w) 366 | ,.outport1_bready_o(periph1_bready_w) 367 | ,.outport1_arvalid_o(periph1_arvalid_w) 368 | ,.outport1_araddr_o(periph1_araddr_w) 369 | ,.outport1_rready_o(periph1_rready_w) 370 | ,.outport2_awvalid_o(periph2_awvalid_w) 371 | ,.outport2_awaddr_o(periph2_awaddr_w) 372 | ,.outport2_wvalid_o(periph2_wvalid_w) 373 | ,.outport2_wdata_o(periph2_wdata_w) 374 | ,.outport2_wstrb_o(periph2_wstrb_w) 375 | ,.outport2_bready_o(periph2_bready_w) 376 | ,.outport2_arvalid_o(periph2_arvalid_w) 377 | ,.outport2_araddr_o(periph2_araddr_w) 378 | ,.outport2_rready_o(periph2_rready_w) 379 | ,.outport3_awvalid_o(periph3_awvalid_w) 380 | ,.outport3_awaddr_o(periph3_awaddr_w) 381 | ,.outport3_wvalid_o(periph3_wvalid_w) 382 | ,.outport3_wdata_o(periph3_wdata_w) 383 | ,.outport3_wstrb_o(periph3_wstrb_w) 384 | ,.outport3_bready_o(periph3_bready_w) 385 | ,.outport3_arvalid_o(periph3_arvalid_w) 386 | ,.outport3_araddr_o(periph3_araddr_w) 387 | ,.outport3_rready_o(periph3_rready_w) 388 | ,.outport4_awvalid_o(periph4_awvalid_w) 389 | ,.outport4_awaddr_o(periph4_awaddr_w) 390 | ,.outport4_wvalid_o(periph4_wvalid_w) 391 | ,.outport4_wdata_o(periph4_wdata_w) 392 | ,.outport4_wstrb_o(periph4_wstrb_w) 393 | ,.outport4_bready_o(periph4_bready_w) 394 | ,.outport4_arvalid_o(periph4_arvalid_w) 395 | ,.outport4_araddr_o(periph4_araddr_w) 396 | ,.outport4_rready_o(periph4_rready_w) 397 | ,.outport5_awvalid_o(ext1_cfg_awvalid_o) 398 | ,.outport5_awaddr_o(ext1_cfg_awaddr_o) 399 | ,.outport5_wvalid_o(ext1_cfg_wvalid_o) 400 | ,.outport5_wdata_o(ext1_cfg_wdata_o) 401 | ,.outport5_wstrb_o(ext1_cfg_wstrb_o) 402 | ,.outport5_bready_o(ext1_cfg_bready_o) 403 | ,.outport5_arvalid_o(ext1_cfg_arvalid_o) 404 | ,.outport5_araddr_o(ext1_cfg_araddr_o) 405 | ,.outport5_rready_o(ext1_cfg_rready_o) 406 | ,.outport6_awvalid_o(ext2_cfg_awvalid_o) 407 | ,.outport6_awaddr_o(ext2_cfg_awaddr_o) 408 | ,.outport6_wvalid_o(ext2_cfg_wvalid_o) 409 | ,.outport6_wdata_o(ext2_cfg_wdata_o) 410 | ,.outport6_wstrb_o(ext2_cfg_wstrb_o) 411 | ,.outport6_bready_o(ext2_cfg_bready_o) 412 | ,.outport6_arvalid_o(ext2_cfg_arvalid_o) 413 | ,.outport6_araddr_o(ext2_cfg_araddr_o) 414 | ,.outport6_rready_o(ext2_cfg_rready_o) 415 | ,.outport7_awvalid_o(ext3_cfg_awvalid_o) 416 | ,.outport7_awaddr_o(ext3_cfg_awaddr_o) 417 | ,.outport7_wvalid_o(ext3_cfg_wvalid_o) 418 | ,.outport7_wdata_o(ext3_cfg_wdata_o) 419 | ,.outport7_wstrb_o(ext3_cfg_wstrb_o) 420 | ,.outport7_bready_o(ext3_cfg_bready_o) 421 | ,.outport7_arvalid_o(ext3_cfg_arvalid_o) 422 | ,.outport7_araddr_o(ext3_cfg_araddr_o) 423 | ,.outport7_rready_o(ext3_cfg_rready_o) 424 | ); 425 | 426 | 427 | uart_lite 428 | #( 429 | .CLK_FREQ(CLK_FREQ) 430 | ,.BAUDRATE(BAUDRATE) 431 | ) 432 | u_uart 433 | ( 434 | // Inputs 435 | .clk_i(clk_i) 436 | ,.rst_i(rst_i) 437 | ,.cfg_awvalid_i(periph2_awvalid_w) 438 | ,.cfg_awaddr_i(periph2_awaddr_w) 439 | ,.cfg_wvalid_i(periph2_wvalid_w) 440 | ,.cfg_wdata_i(periph2_wdata_w) 441 | ,.cfg_wstrb_i(periph2_wstrb_w) 442 | ,.cfg_bready_i(periph2_bready_w) 443 | ,.cfg_arvalid_i(periph2_arvalid_w) 444 | ,.cfg_araddr_i(periph2_araddr_w) 445 | ,.cfg_rready_i(periph2_rready_w) 446 | ,.rx_i(uart_rx_i) 447 | 448 | // Outputs 449 | ,.cfg_awready_o(periph2_awready_w) 450 | ,.cfg_wready_o(periph2_wready_w) 451 | ,.cfg_bvalid_o(periph2_bvalid_w) 452 | ,.cfg_bresp_o(periph2_bresp_w) 453 | ,.cfg_arready_o(periph2_arready_w) 454 | ,.cfg_rvalid_o(periph2_rvalid_w) 455 | ,.cfg_rdata_o(periph2_rdata_w) 456 | ,.cfg_rresp_o(periph2_rresp_w) 457 | ,.tx_o(uart_tx_o) 458 | ,.intr_o(interrupt1_w) 459 | ); 460 | 461 | 462 | timer 463 | u_timer 464 | ( 465 | // Inputs 466 | .clk_i(clk_i) 467 | ,.rst_i(rst_i) 468 | ,.cfg_awvalid_i(periph1_awvalid_w) 469 | ,.cfg_awaddr_i(periph1_awaddr_w) 470 | ,.cfg_wvalid_i(periph1_wvalid_w) 471 | ,.cfg_wdata_i(periph1_wdata_w) 472 | ,.cfg_wstrb_i(periph1_wstrb_w) 473 | ,.cfg_bready_i(periph1_bready_w) 474 | ,.cfg_arvalid_i(periph1_arvalid_w) 475 | ,.cfg_araddr_i(periph1_araddr_w) 476 | ,.cfg_rready_i(periph1_rready_w) 477 | 478 | // Outputs 479 | ,.cfg_awready_o(periph1_awready_w) 480 | ,.cfg_wready_o(periph1_wready_w) 481 | ,.cfg_bvalid_o(periph1_bvalid_w) 482 | ,.cfg_bresp_o(periph1_bresp_w) 483 | ,.cfg_arready_o(periph1_arready_w) 484 | ,.cfg_rvalid_o(periph1_rvalid_w) 485 | ,.cfg_rdata_o(periph1_rdata_w) 486 | ,.cfg_rresp_o(periph1_rresp_w) 487 | ,.intr_o(interrupt0_w) 488 | ); 489 | 490 | 491 | spi_lite 492 | #( 493 | .C_SCK_RATIO(C_SCK_RATIO) 494 | ) 495 | u_spi 496 | ( 497 | // Inputs 498 | .clk_i(clk_i) 499 | ,.rst_i(rst_i) 500 | ,.cfg_awvalid_i(periph3_awvalid_w) 501 | ,.cfg_awaddr_i(periph3_awaddr_w) 502 | ,.cfg_wvalid_i(periph3_wvalid_w) 503 | ,.cfg_wdata_i(periph3_wdata_w) 504 | ,.cfg_wstrb_i(periph3_wstrb_w) 505 | ,.cfg_bready_i(periph3_bready_w) 506 | ,.cfg_arvalid_i(periph3_arvalid_w) 507 | ,.cfg_araddr_i(periph3_araddr_w) 508 | ,.cfg_rready_i(periph3_rready_w) 509 | ,.spi_miso_i(spi_miso_i) 510 | 511 | // Outputs 512 | ,.cfg_awready_o(periph3_awready_w) 513 | ,.cfg_wready_o(periph3_wready_w) 514 | ,.cfg_bvalid_o(periph3_bvalid_w) 515 | ,.cfg_bresp_o(periph3_bresp_w) 516 | ,.cfg_arready_o(periph3_arready_w) 517 | ,.cfg_rvalid_o(periph3_rvalid_w) 518 | ,.cfg_rdata_o(periph3_rdata_w) 519 | ,.cfg_rresp_o(periph3_rresp_w) 520 | ,.spi_clk_o(spi_clk_o) 521 | ,.spi_mosi_o(spi_mosi_o) 522 | ,.spi_cs_o(spi_cs_o) 523 | ,.intr_o(interrupt2_w) 524 | ); 525 | 526 | 527 | gpio 528 | u_gpio 529 | ( 530 | // Inputs 531 | .clk_i(clk_i) 532 | ,.rst_i(rst_i) 533 | ,.cfg_awvalid_i(periph4_awvalid_w) 534 | ,.cfg_awaddr_i(periph4_awaddr_w) 535 | ,.cfg_wvalid_i(periph4_wvalid_w) 536 | ,.cfg_wdata_i(periph4_wdata_w) 537 | ,.cfg_wstrb_i(periph4_wstrb_w) 538 | ,.cfg_bready_i(periph4_bready_w) 539 | ,.cfg_arvalid_i(periph4_arvalid_w) 540 | ,.cfg_araddr_i(periph4_araddr_w) 541 | ,.cfg_rready_i(periph4_rready_w) 542 | ,.gpio_input_i(gpio_input_i) 543 | 544 | // Outputs 545 | ,.cfg_awready_o(periph4_awready_w) 546 | ,.cfg_wready_o(periph4_wready_w) 547 | ,.cfg_bvalid_o(periph4_bvalid_w) 548 | ,.cfg_bresp_o(periph4_bresp_w) 549 | ,.cfg_arready_o(periph4_arready_w) 550 | ,.cfg_rvalid_o(periph4_rvalid_w) 551 | ,.cfg_rdata_o(periph4_rdata_w) 552 | ,.cfg_rresp_o(periph4_rresp_w) 553 | ,.gpio_output_o(gpio_output_o) 554 | ,.gpio_output_enable_o(gpio_output_enable_o) 555 | ,.intr_o(interrupt3_w) 556 | ); 557 | 558 | 559 | 560 | endmodule 561 | -------------------------------------------------------------------------------- /src_v/gpio.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // Basic Peripheral SoC 3 | // V1.1 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2020 6 | // 7 | // Email: admin@ultra-embedded.com 8 | // 9 | // License: GPL 10 | // If you would like a version with a more permissive license for 11 | // use in closed source commercial applications please contact me 12 | // for details. 13 | //----------------------------------------------------------------- 14 | // 15 | // This file is open source HDL; you can redistribute it and/or 16 | // modify it under the terms of the GNU General Public License as 17 | // published by the Free Software Foundation; either version 2 of 18 | // the License, or (at your option) any later version. 19 | // 20 | // This file is distributed in the hope that it will be useful, 21 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | // GNU General Public License for more details. 24 | // 25 | // You should have received a copy of the GNU General Public 26 | // License along with this file; if not, write to the Free Software 27 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 28 | // USA 29 | //----------------------------------------------------------------- 30 | 31 | //----------------------------------------------------------------- 32 | // Generated File 33 | //----------------------------------------------------------------- 34 | 35 | `include "gpio_defs.v" 36 | 37 | //----------------------------------------------------------------- 38 | // Module: General Purpose IO Peripheral 39 | //----------------------------------------------------------------- 40 | module gpio 41 | ( 42 | // Inputs 43 | input clk_i 44 | ,input rst_i 45 | ,input cfg_awvalid_i 46 | ,input [31:0] cfg_awaddr_i 47 | ,input cfg_wvalid_i 48 | ,input [31:0] cfg_wdata_i 49 | ,input [3:0] cfg_wstrb_i 50 | ,input cfg_bready_i 51 | ,input cfg_arvalid_i 52 | ,input [31:0] cfg_araddr_i 53 | ,input cfg_rready_i 54 | ,input [31:0] gpio_input_i 55 | 56 | // Outputs 57 | ,output cfg_awready_o 58 | ,output cfg_wready_o 59 | ,output cfg_bvalid_o 60 | ,output [1:0] cfg_bresp_o 61 | ,output cfg_arready_o 62 | ,output cfg_rvalid_o 63 | ,output [31:0] cfg_rdata_o 64 | ,output [1:0] cfg_rresp_o 65 | ,output [31:0] gpio_output_o 66 | ,output [31:0] gpio_output_enable_o 67 | ,output intr_o 68 | ); 69 | 70 | //----------------------------------------------------------------- 71 | // Write address / data split 72 | //----------------------------------------------------------------- 73 | // Address but no data ready 74 | reg awvalid_q; 75 | 76 | // Data but no data ready 77 | reg wvalid_q; 78 | 79 | wire wr_cmd_accepted_w = (cfg_awvalid_i && cfg_awready_o) || awvalid_q; 80 | wire wr_data_accepted_w = (cfg_wvalid_i && cfg_wready_o) || wvalid_q; 81 | 82 | always @ (posedge clk_i or posedge rst_i) 83 | if (rst_i) 84 | awvalid_q <= 1'b0; 85 | else if (cfg_awvalid_i && cfg_awready_o && !wr_data_accepted_w) 86 | awvalid_q <= 1'b1; 87 | else if (wr_data_accepted_w) 88 | awvalid_q <= 1'b0; 89 | 90 | always @ (posedge clk_i or posedge rst_i) 91 | if (rst_i) 92 | wvalid_q <= 1'b0; 93 | else if (cfg_wvalid_i && cfg_wready_o && !wr_cmd_accepted_w) 94 | wvalid_q <= 1'b1; 95 | else if (wr_cmd_accepted_w) 96 | wvalid_q <= 1'b0; 97 | 98 | //----------------------------------------------------------------- 99 | // Capture address (for delayed data) 100 | //----------------------------------------------------------------- 101 | reg [7:0] wr_addr_q; 102 | 103 | always @ (posedge clk_i or posedge rst_i) 104 | if (rst_i) 105 | wr_addr_q <= 8'b0; 106 | else if (cfg_awvalid_i && cfg_awready_o) 107 | wr_addr_q <= cfg_awaddr_i[7:0]; 108 | 109 | wire [7:0] wr_addr_w = awvalid_q ? wr_addr_q : cfg_awaddr_i[7:0]; 110 | 111 | //----------------------------------------------------------------- 112 | // Retime write data 113 | //----------------------------------------------------------------- 114 | reg [31:0] wr_data_q; 115 | 116 | always @ (posedge clk_i or posedge rst_i) 117 | if (rst_i) 118 | wr_data_q <= 32'b0; 119 | else if (cfg_wvalid_i && cfg_wready_o) 120 | wr_data_q <= cfg_wdata_i; 121 | 122 | //----------------------------------------------------------------- 123 | // Request Logic 124 | //----------------------------------------------------------------- 125 | wire read_en_w = cfg_arvalid_i & cfg_arready_o; 126 | wire write_en_w = wr_cmd_accepted_w && wr_data_accepted_w; 127 | 128 | //----------------------------------------------------------------- 129 | // Accept Logic 130 | //----------------------------------------------------------------- 131 | assign cfg_arready_o = ~cfg_rvalid_o; 132 | assign cfg_awready_o = ~cfg_bvalid_o && ~cfg_arvalid_i && ~awvalid_q; 133 | assign cfg_wready_o = ~cfg_bvalid_o && ~cfg_arvalid_i && ~wvalid_q; 134 | 135 | 136 | //----------------------------------------------------------------- 137 | // Register gpio_direction 138 | //----------------------------------------------------------------- 139 | reg gpio_direction_wr_q; 140 | 141 | always @ (posedge clk_i or posedge rst_i) 142 | if (rst_i) 143 | gpio_direction_wr_q <= 1'b0; 144 | else if (write_en_w && (wr_addr_w[7:0] == `GPIO_DIRECTION)) 145 | gpio_direction_wr_q <= 1'b1; 146 | else 147 | gpio_direction_wr_q <= 1'b0; 148 | 149 | // gpio_direction_output [internal] 150 | reg [31:0] gpio_direction_output_q; 151 | 152 | always @ (posedge clk_i or posedge rst_i) 153 | if (rst_i) 154 | gpio_direction_output_q <= 32'd`GPIO_DIRECTION_OUTPUT_DEFAULT; 155 | else if (write_en_w && (wr_addr_w[7:0] == `GPIO_DIRECTION)) 156 | gpio_direction_output_q <= cfg_wdata_i[`GPIO_DIRECTION_OUTPUT_R]; 157 | 158 | wire [31:0] gpio_direction_output_out_w = gpio_direction_output_q; 159 | 160 | 161 | //----------------------------------------------------------------- 162 | // Register gpio_input 163 | //----------------------------------------------------------------- 164 | reg gpio_input_wr_q; 165 | 166 | always @ (posedge clk_i or posedge rst_i) 167 | if (rst_i) 168 | gpio_input_wr_q <= 1'b0; 169 | else if (write_en_w && (wr_addr_w[7:0] == `GPIO_INPUT)) 170 | gpio_input_wr_q <= 1'b1; 171 | else 172 | gpio_input_wr_q <= 1'b0; 173 | 174 | 175 | //----------------------------------------------------------------- 176 | // Register gpio_output 177 | //----------------------------------------------------------------- 178 | reg gpio_output_wr_q; 179 | 180 | always @ (posedge clk_i or posedge rst_i) 181 | if (rst_i) 182 | gpio_output_wr_q <= 1'b0; 183 | else if (write_en_w && (wr_addr_w[7:0] == `GPIO_OUTPUT)) 184 | gpio_output_wr_q <= 1'b1; 185 | else 186 | gpio_output_wr_q <= 1'b0; 187 | 188 | // gpio_output_data [external] 189 | wire [31:0] gpio_output_data_out_w = wr_data_q[`GPIO_OUTPUT_DATA_R]; 190 | 191 | 192 | //----------------------------------------------------------------- 193 | // Register gpio_output_set 194 | //----------------------------------------------------------------- 195 | reg gpio_output_set_wr_q; 196 | 197 | always @ (posedge clk_i or posedge rst_i) 198 | if (rst_i) 199 | gpio_output_set_wr_q <= 1'b0; 200 | else if (write_en_w && (wr_addr_w[7:0] == `GPIO_OUTPUT_SET)) 201 | gpio_output_set_wr_q <= 1'b1; 202 | else 203 | gpio_output_set_wr_q <= 1'b0; 204 | 205 | // gpio_output_set_data [external] 206 | wire [31:0] gpio_output_set_data_out_w = wr_data_q[`GPIO_OUTPUT_SET_DATA_R]; 207 | 208 | 209 | //----------------------------------------------------------------- 210 | // Register gpio_output_clr 211 | //----------------------------------------------------------------- 212 | reg gpio_output_clr_wr_q; 213 | 214 | always @ (posedge clk_i or posedge rst_i) 215 | if (rst_i) 216 | gpio_output_clr_wr_q <= 1'b0; 217 | else if (write_en_w && (wr_addr_w[7:0] == `GPIO_OUTPUT_CLR)) 218 | gpio_output_clr_wr_q <= 1'b1; 219 | else 220 | gpio_output_clr_wr_q <= 1'b0; 221 | 222 | // gpio_output_clr_data [external] 223 | wire [31:0] gpio_output_clr_data_out_w = wr_data_q[`GPIO_OUTPUT_CLR_DATA_R]; 224 | 225 | 226 | //----------------------------------------------------------------- 227 | // Register gpio_int_mask 228 | //----------------------------------------------------------------- 229 | reg gpio_int_mask_wr_q; 230 | 231 | always @ (posedge clk_i or posedge rst_i) 232 | if (rst_i) 233 | gpio_int_mask_wr_q <= 1'b0; 234 | else if (write_en_w && (wr_addr_w[7:0] == `GPIO_INT_MASK)) 235 | gpio_int_mask_wr_q <= 1'b1; 236 | else 237 | gpio_int_mask_wr_q <= 1'b0; 238 | 239 | // gpio_int_mask_enable [internal] 240 | reg [31:0] gpio_int_mask_enable_q; 241 | 242 | always @ (posedge clk_i or posedge rst_i) 243 | if (rst_i) 244 | gpio_int_mask_enable_q <= 32'd`GPIO_INT_MASK_ENABLE_DEFAULT; 245 | else if (write_en_w && (wr_addr_w[7:0] == `GPIO_INT_MASK)) 246 | gpio_int_mask_enable_q <= cfg_wdata_i[`GPIO_INT_MASK_ENABLE_R]; 247 | 248 | wire [31:0] gpio_int_mask_enable_out_w = gpio_int_mask_enable_q; 249 | 250 | 251 | //----------------------------------------------------------------- 252 | // Register gpio_int_set 253 | //----------------------------------------------------------------- 254 | reg gpio_int_set_wr_q; 255 | 256 | always @ (posedge clk_i or posedge rst_i) 257 | if (rst_i) 258 | gpio_int_set_wr_q <= 1'b0; 259 | else if (write_en_w && (wr_addr_w[7:0] == `GPIO_INT_SET)) 260 | gpio_int_set_wr_q <= 1'b1; 261 | else 262 | gpio_int_set_wr_q <= 1'b0; 263 | 264 | // gpio_int_set_sw_irq [external] 265 | wire [31:0] gpio_int_set_sw_irq_out_w = wr_data_q[`GPIO_INT_SET_SW_IRQ_R]; 266 | 267 | 268 | //----------------------------------------------------------------- 269 | // Register gpio_int_clr 270 | //----------------------------------------------------------------- 271 | reg gpio_int_clr_wr_q; 272 | 273 | always @ (posedge clk_i or posedge rst_i) 274 | if (rst_i) 275 | gpio_int_clr_wr_q <= 1'b0; 276 | else if (write_en_w && (wr_addr_w[7:0] == `GPIO_INT_CLR)) 277 | gpio_int_clr_wr_q <= 1'b1; 278 | else 279 | gpio_int_clr_wr_q <= 1'b0; 280 | 281 | // gpio_int_clr_ack [external] 282 | wire [31:0] gpio_int_clr_ack_out_w = wr_data_q[`GPIO_INT_CLR_ACK_R]; 283 | 284 | 285 | //----------------------------------------------------------------- 286 | // Register gpio_int_status 287 | //----------------------------------------------------------------- 288 | reg gpio_int_status_wr_q; 289 | 290 | always @ (posedge clk_i or posedge rst_i) 291 | if (rst_i) 292 | gpio_int_status_wr_q <= 1'b0; 293 | else if (write_en_w && (wr_addr_w[7:0] == `GPIO_INT_STATUS)) 294 | gpio_int_status_wr_q <= 1'b1; 295 | else 296 | gpio_int_status_wr_q <= 1'b0; 297 | 298 | 299 | //----------------------------------------------------------------- 300 | // Register gpio_int_level 301 | //----------------------------------------------------------------- 302 | reg gpio_int_level_wr_q; 303 | 304 | always @ (posedge clk_i or posedge rst_i) 305 | if (rst_i) 306 | gpio_int_level_wr_q <= 1'b0; 307 | else if (write_en_w && (wr_addr_w[7:0] == `GPIO_INT_LEVEL)) 308 | gpio_int_level_wr_q <= 1'b1; 309 | else 310 | gpio_int_level_wr_q <= 1'b0; 311 | 312 | // gpio_int_level_active_high [internal] 313 | reg [31:0] gpio_int_level_active_high_q; 314 | 315 | always @ (posedge clk_i or posedge rst_i) 316 | if (rst_i) 317 | gpio_int_level_active_high_q <= 32'd`GPIO_INT_LEVEL_ACTIVE_HIGH_DEFAULT; 318 | else if (write_en_w && (wr_addr_w[7:0] == `GPIO_INT_LEVEL)) 319 | gpio_int_level_active_high_q <= cfg_wdata_i[`GPIO_INT_LEVEL_ACTIVE_HIGH_R]; 320 | 321 | wire [31:0] gpio_int_level_active_high_out_w = gpio_int_level_active_high_q; 322 | 323 | 324 | //----------------------------------------------------------------- 325 | // Register gpio_int_mode 326 | //----------------------------------------------------------------- 327 | reg gpio_int_mode_wr_q; 328 | 329 | always @ (posedge clk_i or posedge rst_i) 330 | if (rst_i) 331 | gpio_int_mode_wr_q <= 1'b0; 332 | else if (write_en_w && (wr_addr_w[7:0] == `GPIO_INT_MODE)) 333 | gpio_int_mode_wr_q <= 1'b1; 334 | else 335 | gpio_int_mode_wr_q <= 1'b0; 336 | 337 | // gpio_int_mode_edge [internal] 338 | reg [31:0] gpio_int_mode_edge_q; 339 | 340 | always @ (posedge clk_i or posedge rst_i) 341 | if (rst_i) 342 | gpio_int_mode_edge_q <= 32'd`GPIO_INT_MODE_EDGE_DEFAULT; 343 | else if (write_en_w && (wr_addr_w[7:0] == `GPIO_INT_MODE)) 344 | gpio_int_mode_edge_q <= cfg_wdata_i[`GPIO_INT_MODE_EDGE_R]; 345 | 346 | wire [31:0] gpio_int_mode_edge_out_w = gpio_int_mode_edge_q; 347 | 348 | 349 | wire [31:0] gpio_input_value_in_w; 350 | wire [31:0] gpio_output_data_in_w; 351 | wire [31:0] gpio_int_status_raw_in_w; 352 | 353 | 354 | //----------------------------------------------------------------- 355 | // Read mux 356 | //----------------------------------------------------------------- 357 | reg [31:0] data_r; 358 | 359 | always @ * 360 | begin 361 | data_r = 32'b0; 362 | 363 | case (cfg_araddr_i[7:0]) 364 | 365 | `GPIO_DIRECTION: 366 | begin 367 | data_r[`GPIO_DIRECTION_OUTPUT_R] = gpio_direction_output_q; 368 | end 369 | `GPIO_INPUT: 370 | begin 371 | data_r[`GPIO_INPUT_VALUE_R] = gpio_input_value_in_w; 372 | end 373 | `GPIO_OUTPUT: 374 | begin 375 | data_r[`GPIO_OUTPUT_DATA_R] = gpio_output_data_in_w; 376 | end 377 | `GPIO_INT_MASK: 378 | begin 379 | data_r[`GPIO_INT_MASK_ENABLE_R] = gpio_int_mask_enable_q; 380 | end 381 | `GPIO_INT_STATUS: 382 | begin 383 | data_r[`GPIO_INT_STATUS_RAW_R] = gpio_int_status_raw_in_w; 384 | end 385 | `GPIO_INT_LEVEL: 386 | begin 387 | data_r[`GPIO_INT_LEVEL_ACTIVE_HIGH_R] = gpio_int_level_active_high_q; 388 | end 389 | `GPIO_INT_MODE: 390 | begin 391 | data_r[`GPIO_INT_MODE_EDGE_R] = gpio_int_mode_edge_q; 392 | end 393 | default : 394 | data_r = 32'b0; 395 | endcase 396 | end 397 | 398 | //----------------------------------------------------------------- 399 | // RVALID 400 | //----------------------------------------------------------------- 401 | reg rvalid_q; 402 | 403 | always @ (posedge clk_i or posedge rst_i) 404 | if (rst_i) 405 | rvalid_q <= 1'b0; 406 | else if (read_en_w) 407 | rvalid_q <= 1'b1; 408 | else if (cfg_rready_i) 409 | rvalid_q <= 1'b0; 410 | 411 | assign cfg_rvalid_o = rvalid_q; 412 | 413 | //----------------------------------------------------------------- 414 | // Retime read response 415 | //----------------------------------------------------------------- 416 | reg [31:0] rd_data_q; 417 | 418 | always @ (posedge clk_i or posedge rst_i) 419 | if (rst_i) 420 | rd_data_q <= 32'b0; 421 | else if (!cfg_rvalid_o || cfg_rready_i) 422 | rd_data_q <= data_r; 423 | 424 | assign cfg_rdata_o = rd_data_q; 425 | assign cfg_rresp_o = 2'b0; 426 | 427 | //----------------------------------------------------------------- 428 | // BVALID 429 | //----------------------------------------------------------------- 430 | reg bvalid_q; 431 | 432 | always @ (posedge clk_i or posedge rst_i) 433 | if (rst_i) 434 | bvalid_q <= 1'b0; 435 | else if (write_en_w) 436 | bvalid_q <= 1'b1; 437 | else if (cfg_bready_i) 438 | bvalid_q <= 1'b0; 439 | 440 | assign cfg_bvalid_o = bvalid_q; 441 | assign cfg_bresp_o = 2'b0; 442 | 443 | wire gpio_output_rd_req_w = read_en_w & (cfg_araddr_i[7:0] == `GPIO_OUTPUT); 444 | 445 | wire gpio_output_wr_req_w = gpio_output_wr_q; 446 | wire gpio_output_set_wr_req_w = gpio_output_set_wr_q; 447 | wire gpio_output_clr_wr_req_w = gpio_output_clr_wr_q; 448 | wire gpio_int_set_wr_req_w = gpio_int_set_wr_q; 449 | wire gpio_int_clr_wr_req_w = gpio_int_clr_wr_q; 450 | 451 | 452 | //----------------------------------------------------------------- 453 | // Inputs 454 | //----------------------------------------------------------------- 455 | // Resync inputs 456 | reg [31:0] input_ms; 457 | reg [31:0] input_q; 458 | 459 | always @ (posedge clk_i or posedge rst_i) 460 | if (rst_i) 461 | begin 462 | input_ms <= 32'b0; 463 | input_q <= 32'b0; 464 | end 465 | else 466 | begin 467 | input_q <= input_ms; 468 | input_ms <= gpio_input_i; 469 | end 470 | 471 | assign gpio_input_value_in_w = input_q; 472 | 473 | //----------------------------------------------------------------- 474 | // Outputs 475 | //----------------------------------------------------------------- 476 | reg [31:0] output_q; 477 | reg [31:0] output_next_r; 478 | 479 | always @ * 480 | begin 481 | output_next_r = output_q; 482 | 483 | if (gpio_output_set_wr_req_w) 484 | output_next_r = output_q | gpio_output_set_data_out_w; 485 | else if (gpio_output_clr_wr_req_w) 486 | output_next_r = output_q & ~gpio_output_clr_data_out_w; 487 | else if (gpio_output_wr_req_w) 488 | output_next_r = gpio_output_data_out_w; 489 | end 490 | 491 | always @ (posedge clk_i or posedge rst_i) 492 | if (rst_i) 493 | output_q <= 32'b0; 494 | else 495 | output_q <= output_next_r; 496 | 497 | assign gpio_output_data_in_w = output_q; 498 | assign gpio_output_o = output_q; 499 | 500 | //----------------------------------------------------------------- 501 | // Interrupts 502 | //----------------------------------------------------------------- 503 | reg intr_q; 504 | 505 | reg [31:0] interrupt_raw_q; 506 | reg [31:0] interrupt_raw_r; 507 | 508 | reg [31:0] input_last_q; 509 | 510 | always @ (posedge clk_i or posedge rst_i) 511 | if (rst_i) 512 | input_last_q <= 32'b0; 513 | else 514 | input_last_q <= gpio_input_value_in_w; 515 | 516 | wire [31:0] active_low_w = (~gpio_int_level_active_high_out_w); 517 | wire [31:0] falling_edge_w = (~gpio_int_level_active_high_out_w); 518 | wire [31:0] level_mask_w = (~gpio_int_mode_edge_out_w); 519 | wire [31:0] edge_mask_w = gpio_int_mode_edge_out_w; 520 | 521 | wire [31:0] level_active_w = (gpio_input_value_in_w ^ active_low_w) & level_mask_w; 522 | 523 | wire [31:0] edge_detect_w = (input_last_q ^ gpio_input_value_in_w); 524 | wire [31:0] edge_active_w = (edge_detect_w & (gpio_input_value_in_w ^ falling_edge_w)) & edge_mask_w; 525 | 526 | reg [31:0] interrupt_level_r; 527 | always @ * 528 | begin 529 | interrupt_raw_r = interrupt_raw_q; 530 | 531 | // Clear (ACK) 532 | if (gpio_int_clr_wr_req_w) 533 | interrupt_raw_r = interrupt_raw_r & ~gpio_int_clr_ack_out_w; 534 | 535 | // New interrupts 536 | interrupt_raw_r = interrupt_raw_r | level_active_w | edge_active_w; 537 | 538 | // Set (SW IRQ) 539 | if (gpio_int_set_wr_req_w) 540 | interrupt_raw_r = interrupt_raw_r | gpio_int_set_sw_irq_out_w; 541 | end 542 | 543 | always @ (posedge clk_i or posedge rst_i) 544 | if (rst_i) 545 | begin 546 | intr_q <= 1'b0; 547 | interrupt_raw_q <= 32'b0; 548 | end 549 | else 550 | begin 551 | intr_q <= |(interrupt_raw_q & gpio_int_mask_enable_out_w); 552 | interrupt_raw_q <= interrupt_raw_r; 553 | end 554 | 555 | assign gpio_int_status_raw_in_w = interrupt_raw_q; 556 | assign intr_o = intr_q; 557 | 558 | //----------------------------------------------------------------- 559 | // Assignments 560 | //----------------------------------------------------------------- 561 | assign gpio_output_enable_o = gpio_direction_output_out_w; 562 | 563 | 564 | endmodule 565 | -------------------------------------------------------------------------------- /src_v/gpio_defs.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // Basic Peripheral SoC 3 | // V1.1 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2020 6 | // 7 | // Email: admin@ultra-embedded.com 8 | // 9 | // License: GPL 10 | // If you would like a version with a more permissive license for 11 | // use in closed source commercial applications please contact me 12 | // for details. 13 | //----------------------------------------------------------------- 14 | // 15 | // This file is open source HDL; you can redistribute it and/or 16 | // modify it under the terms of the GNU General Public License as 17 | // published by the Free Software Foundation; either version 2 of 18 | // the License, or (at your option) any later version. 19 | // 20 | // This file is distributed in the hope that it will be useful, 21 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | // GNU General Public License for more details. 24 | // 25 | // You should have received a copy of the GNU General Public 26 | // License along with this file; if not, write to the Free Software 27 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 28 | // USA 29 | //----------------------------------------------------------------- 30 | 31 | //----------------------------------------------------------------- 32 | // Generated File 33 | //----------------------------------------------------------------- 34 | 35 | `define GPIO_DIRECTION 8'h0 36 | 37 | `define GPIO_DIRECTION_OUTPUT_DEFAULT 0 38 | `define GPIO_DIRECTION_OUTPUT_B 0 39 | `define GPIO_DIRECTION_OUTPUT_T 31 40 | `define GPIO_DIRECTION_OUTPUT_W 32 41 | `define GPIO_DIRECTION_OUTPUT_R 31:0 42 | 43 | `define GPIO_INPUT 8'h4 44 | 45 | `define GPIO_INPUT_VALUE_DEFAULT 0 46 | `define GPIO_INPUT_VALUE_B 0 47 | `define GPIO_INPUT_VALUE_T 31 48 | `define GPIO_INPUT_VALUE_W 32 49 | `define GPIO_INPUT_VALUE_R 31:0 50 | 51 | `define GPIO_OUTPUT 8'h8 52 | 53 | `define GPIO_OUTPUT_DATA_DEFAULT 0 54 | `define GPIO_OUTPUT_DATA_B 0 55 | `define GPIO_OUTPUT_DATA_T 31 56 | `define GPIO_OUTPUT_DATA_W 32 57 | `define GPIO_OUTPUT_DATA_R 31:0 58 | 59 | `define GPIO_OUTPUT_SET 8'hc 60 | 61 | `define GPIO_OUTPUT_SET_DATA_DEFAULT 0 62 | `define GPIO_OUTPUT_SET_DATA_B 0 63 | `define GPIO_OUTPUT_SET_DATA_T 31 64 | `define GPIO_OUTPUT_SET_DATA_W 32 65 | `define GPIO_OUTPUT_SET_DATA_R 31:0 66 | 67 | `define GPIO_OUTPUT_CLR 8'h10 68 | 69 | `define GPIO_OUTPUT_CLR_DATA_DEFAULT 0 70 | `define GPIO_OUTPUT_CLR_DATA_B 0 71 | `define GPIO_OUTPUT_CLR_DATA_T 31 72 | `define GPIO_OUTPUT_CLR_DATA_W 32 73 | `define GPIO_OUTPUT_CLR_DATA_R 31:0 74 | 75 | `define GPIO_INT_MASK 8'h14 76 | 77 | `define GPIO_INT_MASK_ENABLE_DEFAULT 0 78 | `define GPIO_INT_MASK_ENABLE_B 0 79 | `define GPIO_INT_MASK_ENABLE_T 31 80 | `define GPIO_INT_MASK_ENABLE_W 32 81 | `define GPIO_INT_MASK_ENABLE_R 31:0 82 | 83 | `define GPIO_INT_SET 8'h18 84 | 85 | `define GPIO_INT_SET_SW_IRQ_DEFAULT 0 86 | `define GPIO_INT_SET_SW_IRQ_B 0 87 | `define GPIO_INT_SET_SW_IRQ_T 31 88 | `define GPIO_INT_SET_SW_IRQ_W 32 89 | `define GPIO_INT_SET_SW_IRQ_R 31:0 90 | 91 | `define GPIO_INT_CLR 8'h1c 92 | 93 | `define GPIO_INT_CLR_ACK_DEFAULT 0 94 | `define GPIO_INT_CLR_ACK_B 0 95 | `define GPIO_INT_CLR_ACK_T 31 96 | `define GPIO_INT_CLR_ACK_W 32 97 | `define GPIO_INT_CLR_ACK_R 31:0 98 | 99 | `define GPIO_INT_STATUS 8'h20 100 | 101 | `define GPIO_INT_STATUS_RAW_DEFAULT 0 102 | `define GPIO_INT_STATUS_RAW_B 0 103 | `define GPIO_INT_STATUS_RAW_T 31 104 | `define GPIO_INT_STATUS_RAW_W 32 105 | `define GPIO_INT_STATUS_RAW_R 31:0 106 | 107 | `define GPIO_INT_LEVEL 8'h24 108 | 109 | `define GPIO_INT_LEVEL_ACTIVE_HIGH_DEFAULT 0 110 | `define GPIO_INT_LEVEL_ACTIVE_HIGH_B 0 111 | `define GPIO_INT_LEVEL_ACTIVE_HIGH_T 31 112 | `define GPIO_INT_LEVEL_ACTIVE_HIGH_W 32 113 | `define GPIO_INT_LEVEL_ACTIVE_HIGH_R 31:0 114 | 115 | `define GPIO_INT_MODE 8'h28 116 | 117 | `define GPIO_INT_MODE_EDGE_DEFAULT 0 118 | `define GPIO_INT_MODE_EDGE_B 0 119 | `define GPIO_INT_MODE_EDGE_T 31 120 | `define GPIO_INT_MODE_EDGE_W 32 121 | `define GPIO_INT_MODE_EDGE_R 31:0 122 | 123 | -------------------------------------------------------------------------------- /src_v/irq_ctrl.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // Basic Peripheral SoC 3 | // V1.1 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2020 6 | // 7 | // Email: admin@ultra-embedded.com 8 | // 9 | // License: GPL 10 | // If you would like a version with a more permissive license for 11 | // use in closed source commercial applications please contact me 12 | // for details. 13 | //----------------------------------------------------------------- 14 | // 15 | // This file is open source HDL; you can redistribute it and/or 16 | // modify it under the terms of the GNU General Public License as 17 | // published by the Free Software Foundation; either version 2 of 18 | // the License, or (at your option) any later version. 19 | // 20 | // This file is distributed in the hope that it will be useful, 21 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | // GNU General Public License for more details. 24 | // 25 | // You should have received a copy of the GNU General Public 26 | // License along with this file; if not, write to the Free Software 27 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 28 | // USA 29 | //----------------------------------------------------------------- 30 | 31 | //----------------------------------------------------------------- 32 | // Generated File 33 | //----------------------------------------------------------------- 34 | 35 | `include "irq_ctrl_defs.v" 36 | 37 | //----------------------------------------------------------------- 38 | // Module: IRQ Controller 39 | //----------------------------------------------------------------- 40 | module irq_ctrl 41 | ( 42 | // Inputs 43 | input clk_i 44 | ,input rst_i 45 | ,input cfg_awvalid_i 46 | ,input [31:0] cfg_awaddr_i 47 | ,input cfg_wvalid_i 48 | ,input [31:0] cfg_wdata_i 49 | ,input [3:0] cfg_wstrb_i 50 | ,input cfg_bready_i 51 | ,input cfg_arvalid_i 52 | ,input [31:0] cfg_araddr_i 53 | ,input cfg_rready_i 54 | ,input interrupt0_i 55 | ,input interrupt1_i 56 | ,input interrupt2_i 57 | ,input interrupt3_i 58 | ,input interrupt4_i 59 | ,input interrupt5_i 60 | ,input interrupt6_i 61 | 62 | // Outputs 63 | ,output cfg_awready_o 64 | ,output cfg_wready_o 65 | ,output cfg_bvalid_o 66 | ,output [1:0] cfg_bresp_o 67 | ,output cfg_arready_o 68 | ,output cfg_rvalid_o 69 | ,output [31:0] cfg_rdata_o 70 | ,output [1:0] cfg_rresp_o 71 | ,output intr_o 72 | ); 73 | 74 | //----------------------------------------------------------------- 75 | // Write address / data split 76 | //----------------------------------------------------------------- 77 | // Address but no data ready 78 | reg awvalid_q; 79 | 80 | // Data but no data ready 81 | reg wvalid_q; 82 | 83 | wire wr_cmd_accepted_w = (cfg_awvalid_i && cfg_awready_o) || awvalid_q; 84 | wire wr_data_accepted_w = (cfg_wvalid_i && cfg_wready_o) || wvalid_q; 85 | 86 | always @ (posedge clk_i or posedge rst_i) 87 | if (rst_i) 88 | awvalid_q <= 1'b0; 89 | else if (cfg_awvalid_i && cfg_awready_o && !wr_data_accepted_w) 90 | awvalid_q <= 1'b1; 91 | else if (wr_data_accepted_w) 92 | awvalid_q <= 1'b0; 93 | 94 | always @ (posedge clk_i or posedge rst_i) 95 | if (rst_i) 96 | wvalid_q <= 1'b0; 97 | else if (cfg_wvalid_i && cfg_wready_o && !wr_cmd_accepted_w) 98 | wvalid_q <= 1'b1; 99 | else if (wr_cmd_accepted_w) 100 | wvalid_q <= 1'b0; 101 | 102 | //----------------------------------------------------------------- 103 | // Capture address (for delayed data) 104 | //----------------------------------------------------------------- 105 | reg [7:0] wr_addr_q; 106 | 107 | always @ (posedge clk_i or posedge rst_i) 108 | if (rst_i) 109 | wr_addr_q <= 8'b0; 110 | else if (cfg_awvalid_i && cfg_awready_o) 111 | wr_addr_q <= cfg_awaddr_i[7:0]; 112 | 113 | wire [7:0] wr_addr_w = awvalid_q ? wr_addr_q : cfg_awaddr_i[7:0]; 114 | 115 | //----------------------------------------------------------------- 116 | // Retime write data 117 | //----------------------------------------------------------------- 118 | reg [31:0] wr_data_q; 119 | 120 | always @ (posedge clk_i or posedge rst_i) 121 | if (rst_i) 122 | wr_data_q <= 32'b0; 123 | else if (cfg_wvalid_i && cfg_wready_o) 124 | wr_data_q <= cfg_wdata_i; 125 | 126 | //----------------------------------------------------------------- 127 | // Request Logic 128 | //----------------------------------------------------------------- 129 | wire read_en_w = cfg_arvalid_i & cfg_arready_o; 130 | wire write_en_w = wr_cmd_accepted_w && wr_data_accepted_w; 131 | 132 | //----------------------------------------------------------------- 133 | // Accept Logic 134 | //----------------------------------------------------------------- 135 | assign cfg_arready_o = ~cfg_rvalid_o; 136 | assign cfg_awready_o = ~cfg_bvalid_o && ~cfg_arvalid_i && ~awvalid_q; 137 | assign cfg_wready_o = ~cfg_bvalid_o && ~cfg_arvalid_i && ~wvalid_q; 138 | 139 | 140 | //----------------------------------------------------------------- 141 | // Register irq_isr 142 | //----------------------------------------------------------------- 143 | reg irq_isr_wr_q; 144 | 145 | always @ (posedge clk_i or posedge rst_i) 146 | if (rst_i) 147 | irq_isr_wr_q <= 1'b0; 148 | else if (write_en_w && (wr_addr_w[7:0] == `IRQ_ISR)) 149 | irq_isr_wr_q <= 1'b1; 150 | else 151 | irq_isr_wr_q <= 1'b0; 152 | 153 | // irq_isr_status [external] 154 | wire [6:0] irq_isr_status_out_w = wr_data_q[`IRQ_ISR_STATUS_R]; 155 | 156 | 157 | //----------------------------------------------------------------- 158 | // Register irq_ipr 159 | //----------------------------------------------------------------- 160 | reg irq_ipr_wr_q; 161 | 162 | always @ (posedge clk_i or posedge rst_i) 163 | if (rst_i) 164 | irq_ipr_wr_q <= 1'b0; 165 | else if (write_en_w && (wr_addr_w[7:0] == `IRQ_IPR)) 166 | irq_ipr_wr_q <= 1'b1; 167 | else 168 | irq_ipr_wr_q <= 1'b0; 169 | 170 | 171 | //----------------------------------------------------------------- 172 | // Register irq_ier 173 | //----------------------------------------------------------------- 174 | reg irq_ier_wr_q; 175 | 176 | always @ (posedge clk_i or posedge rst_i) 177 | if (rst_i) 178 | irq_ier_wr_q <= 1'b0; 179 | else if (write_en_w && (wr_addr_w[7:0] == `IRQ_IER)) 180 | irq_ier_wr_q <= 1'b1; 181 | else 182 | irq_ier_wr_q <= 1'b0; 183 | 184 | // irq_ier_enable [external] 185 | wire [6:0] irq_ier_enable_out_w = wr_data_q[`IRQ_IER_ENABLE_R]; 186 | 187 | 188 | //----------------------------------------------------------------- 189 | // Register irq_iar 190 | //----------------------------------------------------------------- 191 | reg irq_iar_wr_q; 192 | 193 | always @ (posedge clk_i or posedge rst_i) 194 | if (rst_i) 195 | irq_iar_wr_q <= 1'b0; 196 | else if (write_en_w && (wr_addr_w[7:0] == `IRQ_IAR)) 197 | irq_iar_wr_q <= 1'b1; 198 | else 199 | irq_iar_wr_q <= 1'b0; 200 | 201 | // irq_iar_ack [auto_clr] 202 | reg [6:0] irq_iar_ack_q; 203 | 204 | always @ (posedge clk_i or posedge rst_i) 205 | if (rst_i) 206 | irq_iar_ack_q <= 7'd`IRQ_IAR_ACK_DEFAULT; 207 | else if (write_en_w && (wr_addr_w[7:0] == `IRQ_IAR)) 208 | irq_iar_ack_q <= cfg_wdata_i[`IRQ_IAR_ACK_R]; 209 | else 210 | irq_iar_ack_q <= 7'd`IRQ_IAR_ACK_DEFAULT; 211 | 212 | wire [6:0] irq_iar_ack_out_w = irq_iar_ack_q; 213 | 214 | 215 | //----------------------------------------------------------------- 216 | // Register irq_sie 217 | //----------------------------------------------------------------- 218 | reg irq_sie_wr_q; 219 | 220 | always @ (posedge clk_i or posedge rst_i) 221 | if (rst_i) 222 | irq_sie_wr_q <= 1'b0; 223 | else if (write_en_w && (wr_addr_w[7:0] == `IRQ_SIE)) 224 | irq_sie_wr_q <= 1'b1; 225 | else 226 | irq_sie_wr_q <= 1'b0; 227 | 228 | // irq_sie_set [external] 229 | wire [6:0] irq_sie_set_out_w = wr_data_q[`IRQ_SIE_SET_R]; 230 | 231 | 232 | //----------------------------------------------------------------- 233 | // Register irq_cie 234 | //----------------------------------------------------------------- 235 | reg irq_cie_wr_q; 236 | 237 | always @ (posedge clk_i or posedge rst_i) 238 | if (rst_i) 239 | irq_cie_wr_q <= 1'b0; 240 | else if (write_en_w && (wr_addr_w[7:0] == `IRQ_CIE)) 241 | irq_cie_wr_q <= 1'b1; 242 | else 243 | irq_cie_wr_q <= 1'b0; 244 | 245 | // irq_cie_clr [external] 246 | wire [6:0] irq_cie_clr_out_w = wr_data_q[`IRQ_CIE_CLR_R]; 247 | 248 | 249 | //----------------------------------------------------------------- 250 | // Register irq_ivr 251 | //----------------------------------------------------------------- 252 | reg irq_ivr_wr_q; 253 | 254 | always @ (posedge clk_i or posedge rst_i) 255 | if (rst_i) 256 | irq_ivr_wr_q <= 1'b0; 257 | else if (write_en_w && (wr_addr_w[7:0] == `IRQ_IVR)) 258 | irq_ivr_wr_q <= 1'b1; 259 | else 260 | irq_ivr_wr_q <= 1'b0; 261 | 262 | // irq_ivr_vector [external] 263 | wire [31:0] irq_ivr_vector_out_w = wr_data_q[`IRQ_IVR_VECTOR_R]; 264 | 265 | 266 | //----------------------------------------------------------------- 267 | // Register irq_mer 268 | //----------------------------------------------------------------- 269 | reg irq_mer_wr_q; 270 | 271 | always @ (posedge clk_i or posedge rst_i) 272 | if (rst_i) 273 | irq_mer_wr_q <= 1'b0; 274 | else if (write_en_w && (wr_addr_w[7:0] == `IRQ_MER)) 275 | irq_mer_wr_q <= 1'b1; 276 | else 277 | irq_mer_wr_q <= 1'b0; 278 | 279 | // irq_mer_me [internal] 280 | reg irq_mer_me_q; 281 | 282 | always @ (posedge clk_i or posedge rst_i) 283 | if (rst_i) 284 | irq_mer_me_q <= 1'd`IRQ_MER_ME_DEFAULT; 285 | else if (write_en_w && (wr_addr_w[7:0] == `IRQ_MER)) 286 | irq_mer_me_q <= cfg_wdata_i[`IRQ_MER_ME_R]; 287 | 288 | wire irq_mer_me_out_w = irq_mer_me_q; 289 | 290 | 291 | wire [6:0] irq_isr_status_in_w; 292 | wire [6:0] irq_ipr_pending_in_w; 293 | wire [6:0] irq_ier_enable_in_w; 294 | wire [31:0] irq_ivr_vector_in_w; 295 | 296 | 297 | //----------------------------------------------------------------- 298 | // Read mux 299 | //----------------------------------------------------------------- 300 | reg [31:0] data_r; 301 | 302 | always @ * 303 | begin 304 | data_r = 32'b0; 305 | 306 | case (cfg_araddr_i[7:0]) 307 | 308 | `IRQ_ISR: 309 | begin 310 | data_r[`IRQ_ISR_STATUS_R] = irq_isr_status_in_w; 311 | end 312 | `IRQ_IPR: 313 | begin 314 | data_r[`IRQ_IPR_PENDING_R] = irq_ipr_pending_in_w; 315 | end 316 | `IRQ_IER: 317 | begin 318 | data_r[`IRQ_IER_ENABLE_R] = irq_ier_enable_in_w; 319 | end 320 | `IRQ_IVR: 321 | begin 322 | data_r[`IRQ_IVR_VECTOR_R] = irq_ivr_vector_in_w; 323 | end 324 | `IRQ_MER: 325 | begin 326 | data_r[`IRQ_MER_ME_R] = irq_mer_me_q; 327 | end 328 | default : 329 | data_r = 32'b0; 330 | endcase 331 | end 332 | 333 | //----------------------------------------------------------------- 334 | // RVALID 335 | //----------------------------------------------------------------- 336 | reg rvalid_q; 337 | 338 | always @ (posedge clk_i or posedge rst_i) 339 | if (rst_i) 340 | rvalid_q <= 1'b0; 341 | else if (read_en_w) 342 | rvalid_q <= 1'b1; 343 | else if (cfg_rready_i) 344 | rvalid_q <= 1'b0; 345 | 346 | assign cfg_rvalid_o = rvalid_q; 347 | 348 | //----------------------------------------------------------------- 349 | // Retime read response 350 | //----------------------------------------------------------------- 351 | reg [31:0] rd_data_q; 352 | 353 | always @ (posedge clk_i or posedge rst_i) 354 | if (rst_i) 355 | rd_data_q <= 32'b0; 356 | else if (!cfg_rvalid_o || cfg_rready_i) 357 | rd_data_q <= data_r; 358 | 359 | assign cfg_rdata_o = rd_data_q; 360 | assign cfg_rresp_o = 2'b0; 361 | 362 | //----------------------------------------------------------------- 363 | // BVALID 364 | //----------------------------------------------------------------- 365 | reg bvalid_q; 366 | 367 | always @ (posedge clk_i or posedge rst_i) 368 | if (rst_i) 369 | bvalid_q <= 1'b0; 370 | else if (write_en_w) 371 | bvalid_q <= 1'b1; 372 | else if (cfg_bready_i) 373 | bvalid_q <= 1'b0; 374 | 375 | assign cfg_bvalid_o = bvalid_q; 376 | assign cfg_bresp_o = 2'b0; 377 | 378 | 379 | wire irq_isr_wr_req_w = irq_isr_wr_q; 380 | wire irq_ier_wr_req_w = irq_ier_wr_q; 381 | wire irq_sie_wr_req_w = irq_sie_wr_q; 382 | wire irq_cie_wr_req_w = irq_cie_wr_q; 383 | wire irq_ivr_wr_req_w = irq_ivr_wr_q; 384 | 385 | wire [6:0] irq_input_w; 386 | 387 | irq_ctrl_resync 388 | u_irq0_sync 389 | ( 390 | .clk_i(clk_i) 391 | ,.rst_i(rst_i) 392 | ,.async_i(interrupt0_i) 393 | ,.sync_o(irq_input_w[0]) 394 | ); 395 | 396 | irq_ctrl_resync 397 | u_irq1_sync 398 | ( 399 | .clk_i(clk_i) 400 | ,.rst_i(rst_i) 401 | ,.async_i(interrupt1_i) 402 | ,.sync_o(irq_input_w[1]) 403 | ); 404 | 405 | irq_ctrl_resync 406 | u_irq2_sync 407 | ( 408 | .clk_i(clk_i) 409 | ,.rst_i(rst_i) 410 | ,.async_i(interrupt2_i) 411 | ,.sync_o(irq_input_w[2]) 412 | ); 413 | 414 | irq_ctrl_resync 415 | u_irq3_sync 416 | ( 417 | .clk_i(clk_i) 418 | ,.rst_i(rst_i) 419 | ,.async_i(interrupt3_i) 420 | ,.sync_o(irq_input_w[3]) 421 | ); 422 | 423 | irq_ctrl_resync 424 | u_irq4_sync 425 | ( 426 | .clk_i(clk_i) 427 | ,.rst_i(rst_i) 428 | ,.async_i(interrupt4_i) 429 | ,.sync_o(irq_input_w[4]) 430 | ); 431 | 432 | irq_ctrl_resync 433 | u_irq5_sync 434 | ( 435 | .clk_i(clk_i) 436 | ,.rst_i(rst_i) 437 | ,.async_i(interrupt5_i) 438 | ,.sync_o(irq_input_w[5]) 439 | ); 440 | 441 | irq_ctrl_resync 442 | u_irq6_sync 443 | ( 444 | .clk_i(clk_i) 445 | ,.rst_i(rst_i) 446 | ,.async_i(interrupt6_i) 447 | ,.sync_o(irq_input_w[6]) 448 | ); 449 | 450 | 451 | //----------------------------------------------------------------- 452 | // IRQ Enable 453 | //----------------------------------------------------------------- 454 | reg [6:0] irq_enable_q; 455 | 456 | always @ (posedge clk_i or posedge rst_i) 457 | if (rst_i) 458 | irq_enable_q <= 7'b0; 459 | else if (irq_ier_wr_req_w) 460 | irq_enable_q <= irq_ier_enable_out_w; 461 | else if (irq_sie_wr_req_w) 462 | irq_enable_q <= irq_enable_q | irq_sie_set_out_w; 463 | else if (irq_cie_wr_req_w) 464 | irq_enable_q <= irq_enable_q & ~irq_cie_clr_out_w; 465 | 466 | assign irq_ier_enable_in_w = irq_enable_q; 467 | 468 | //----------------------------------------------------------------- 469 | // IRQ Pending 470 | //----------------------------------------------------------------- 471 | reg [6:0] irq_pending_q; 472 | 473 | wire [6:0] irq_sw_int_w = {7{irq_isr_wr_req_w}} & irq_isr_status_out_w; 474 | 475 | always @ (posedge clk_i or posedge rst_i) 476 | if (rst_i) 477 | irq_pending_q <= 7'b0; 478 | else 479 | irq_pending_q <= irq_input_w | irq_sw_int_w | (irq_pending_q & ~irq_iar_ack_out_w); 480 | 481 | assign irq_isr_status_in_w = irq_pending_q; 482 | assign irq_ipr_pending_in_w = irq_pending_q & irq_enable_q; 483 | 484 | //----------------------------------------------------------------- 485 | // IRQ Vector 486 | //----------------------------------------------------------------- 487 | reg [31:0] ivr_vector_r; 488 | always @ * 489 | begin 490 | ivr_vector_r = 32'hffffffff; 491 | 492 | if (irq_ipr_pending_in_w[0]) 493 | ivr_vector_r = 32'd0; 494 | else 495 | if (irq_ipr_pending_in_w[1]) 496 | ivr_vector_r = 32'd1; 497 | else 498 | if (irq_ipr_pending_in_w[2]) 499 | ivr_vector_r = 32'd2; 500 | else 501 | if (irq_ipr_pending_in_w[3]) 502 | ivr_vector_r = 32'd3; 503 | else 504 | if (irq_ipr_pending_in_w[4]) 505 | ivr_vector_r = 32'd4; 506 | else 507 | if (irq_ipr_pending_in_w[5]) 508 | ivr_vector_r = 32'd5; 509 | else 510 | if (irq_ipr_pending_in_w[6]) 511 | ivr_vector_r = 32'd6; 512 | else 513 | ivr_vector_r = 32'hffffffff; 514 | end 515 | 516 | assign irq_ivr_vector_in_w = ivr_vector_r; 517 | 518 | //----------------------------------------------------------------- 519 | // IRQ output 520 | //----------------------------------------------------------------- 521 | reg intr_q; 522 | 523 | always @ (posedge clk_i or posedge rst_i) 524 | if (rst_i) 525 | intr_q <= 1'b0; 526 | else 527 | intr_q <= irq_mer_me_out_w ? (|irq_ipr_pending_in_w) : 1'b0; 528 | 529 | //----------------------------------------------------------------- 530 | // Assignments 531 | //----------------------------------------------------------------- 532 | assign intr_o = intr_q; 533 | 534 | endmodule 535 | 536 | module irq_ctrl_resync 537 | //----------------------------------------------------------------- 538 | // Params 539 | //----------------------------------------------------------------- 540 | #( 541 | parameter RESET_VAL = 1'b0 542 | ) 543 | //----------------------------------------------------------------- 544 | // Ports 545 | //----------------------------------------------------------------- 546 | ( 547 | input clk_i, 548 | input rst_i, 549 | input async_i, 550 | output sync_o 551 | ); 552 | 553 | reg sync_ms; 554 | reg sync_q; 555 | 556 | always @ (posedge clk_i or posedge rst_i) 557 | if (rst_i) 558 | begin 559 | sync_ms <= RESET_VAL; 560 | sync_q <= RESET_VAL; 561 | end 562 | else 563 | begin 564 | sync_ms <= async_i; 565 | sync_q <= sync_ms; 566 | end 567 | 568 | assign sync_o = sync_q; 569 | 570 | 571 | 572 | endmodule 573 | -------------------------------------------------------------------------------- /src_v/irq_ctrl_defs.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // Basic Peripheral SoC 3 | // V1.1 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2020 6 | // 7 | // Email: admin@ultra-embedded.com 8 | // 9 | // License: GPL 10 | // If you would like a version with a more permissive license for 11 | // use in closed source commercial applications please contact me 12 | // for details. 13 | //----------------------------------------------------------------- 14 | // 15 | // This file is open source HDL; you can redistribute it and/or 16 | // modify it under the terms of the GNU General Public License as 17 | // published by the Free Software Foundation; either version 2 of 18 | // the License, or (at your option) any later version. 19 | // 20 | // This file is distributed in the hope that it will be useful, 21 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | // GNU General Public License for more details. 24 | // 25 | // You should have received a copy of the GNU General Public 26 | // License along with this file; if not, write to the Free Software 27 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 28 | // USA 29 | //----------------------------------------------------------------- 30 | 31 | //----------------------------------------------------------------- 32 | // Generated File 33 | //----------------------------------------------------------------- 34 | 35 | `define IRQ_ISR 8'h0 36 | 37 | `define IRQ_ISR_STATUS_DEFAULT 0 38 | `define IRQ_ISR_STATUS_B 0 39 | `define IRQ_ISR_STATUS_T 6 40 | `define IRQ_ISR_STATUS_W 7 41 | `define IRQ_ISR_STATUS_R 6:0 42 | 43 | `define IRQ_IPR 8'h4 44 | 45 | `define IRQ_IPR_PENDING_DEFAULT 0 46 | `define IRQ_IPR_PENDING_B 0 47 | `define IRQ_IPR_PENDING_T 6 48 | `define IRQ_IPR_PENDING_W 7 49 | `define IRQ_IPR_PENDING_R 6:0 50 | 51 | `define IRQ_IER 8'h8 52 | 53 | `define IRQ_IER_ENABLE_DEFAULT 0 54 | `define IRQ_IER_ENABLE_B 0 55 | `define IRQ_IER_ENABLE_T 6 56 | `define IRQ_IER_ENABLE_W 7 57 | `define IRQ_IER_ENABLE_R 6:0 58 | 59 | `define IRQ_IAR 8'hc 60 | 61 | `define IRQ_IAR_ACK_DEFAULT 0 62 | `define IRQ_IAR_ACK_B 0 63 | `define IRQ_IAR_ACK_T 6 64 | `define IRQ_IAR_ACK_W 7 65 | `define IRQ_IAR_ACK_R 6:0 66 | 67 | `define IRQ_SIE 8'h10 68 | 69 | `define IRQ_SIE_SET_DEFAULT 0 70 | `define IRQ_SIE_SET_B 0 71 | `define IRQ_SIE_SET_T 6 72 | `define IRQ_SIE_SET_W 7 73 | `define IRQ_SIE_SET_R 6:0 74 | 75 | `define IRQ_CIE 8'h14 76 | 77 | `define IRQ_CIE_CLR_DEFAULT 0 78 | `define IRQ_CIE_CLR_B 0 79 | `define IRQ_CIE_CLR_T 6 80 | `define IRQ_CIE_CLR_W 7 81 | `define IRQ_CIE_CLR_R 6:0 82 | 83 | `define IRQ_IVR 8'h18 84 | 85 | `define IRQ_IVR_VECTOR_DEFAULT 0 86 | `define IRQ_IVR_VECTOR_B 0 87 | `define IRQ_IVR_VECTOR_T 31 88 | `define IRQ_IVR_VECTOR_W 32 89 | `define IRQ_IVR_VECTOR_R 31:0 90 | 91 | `define IRQ_MER 8'h1c 92 | 93 | `define IRQ_MER_ME 0 94 | `define IRQ_MER_ME_DEFAULT 0 95 | `define IRQ_MER_ME_B 0 96 | `define IRQ_MER_ME_T 0 97 | `define IRQ_MER_ME_W 1 98 | `define IRQ_MER_ME_R 0:0 99 | 100 | -------------------------------------------------------------------------------- /src_v/spi_lite.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // Basic Peripheral SoC 3 | // V1.1 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2020 6 | // 7 | // Email: admin@ultra-embedded.com 8 | // 9 | // License: GPL 10 | // If you would like a version with a more permissive license for 11 | // use in closed source commercial applications please contact me 12 | // for details. 13 | //----------------------------------------------------------------- 14 | // 15 | // This file is open source HDL; you can redistribute it and/or 16 | // modify it under the terms of the GNU General Public License as 17 | // published by the Free Software Foundation; either version 2 of 18 | // the License, or (at your option) any later version. 19 | // 20 | // This file is distributed in the hope that it will be useful, 21 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | // GNU General Public License for more details. 24 | // 25 | // You should have received a copy of the GNU General Public 26 | // License along with this file; if not, write to the Free Software 27 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 28 | // USA 29 | //----------------------------------------------------------------- 30 | 31 | //----------------------------------------------------------------- 32 | // Generated File 33 | //----------------------------------------------------------------- 34 | 35 | `include "spi_lite_defs.v" 36 | 37 | //----------------------------------------------------------------- 38 | // Module: SPI-Lite Peripheral (Xilinx IP emulation) 39 | //----------------------------------------------------------------- 40 | module spi_lite 41 | //----------------------------------------------------------------- 42 | // Params 43 | //----------------------------------------------------------------- 44 | #( 45 | parameter C_SCK_RATIO = 32 46 | ) 47 | //----------------------------------------------------------------- 48 | // Ports 49 | //----------------------------------------------------------------- 50 | ( 51 | // Inputs 52 | input clk_i 53 | ,input rst_i 54 | ,input cfg_awvalid_i 55 | ,input [31:0] cfg_awaddr_i 56 | ,input cfg_wvalid_i 57 | ,input [31:0] cfg_wdata_i 58 | ,input [3:0] cfg_wstrb_i 59 | ,input cfg_bready_i 60 | ,input cfg_arvalid_i 61 | ,input [31:0] cfg_araddr_i 62 | ,input cfg_rready_i 63 | ,input spi_miso_i 64 | 65 | // Outputs 66 | ,output cfg_awready_o 67 | ,output cfg_wready_o 68 | ,output cfg_bvalid_o 69 | ,output [1:0] cfg_bresp_o 70 | ,output cfg_arready_o 71 | ,output cfg_rvalid_o 72 | ,output [31:0] cfg_rdata_o 73 | ,output [1:0] cfg_rresp_o 74 | ,output spi_clk_o 75 | ,output spi_mosi_o 76 | ,output [7:0] spi_cs_o 77 | ,output intr_o 78 | ); 79 | 80 | //----------------------------------------------------------------- 81 | // Write address / data split 82 | //----------------------------------------------------------------- 83 | // Address but no data ready 84 | reg awvalid_q; 85 | 86 | // Data but no data ready 87 | reg wvalid_q; 88 | 89 | wire wr_cmd_accepted_w = (cfg_awvalid_i && cfg_awready_o) || awvalid_q; 90 | wire wr_data_accepted_w = (cfg_wvalid_i && cfg_wready_o) || wvalid_q; 91 | 92 | always @ (posedge clk_i or posedge rst_i) 93 | if (rst_i) 94 | awvalid_q <= 1'b0; 95 | else if (cfg_awvalid_i && cfg_awready_o && !wr_data_accepted_w) 96 | awvalid_q <= 1'b1; 97 | else if (wr_data_accepted_w) 98 | awvalid_q <= 1'b0; 99 | 100 | always @ (posedge clk_i or posedge rst_i) 101 | if (rst_i) 102 | wvalid_q <= 1'b0; 103 | else if (cfg_wvalid_i && cfg_wready_o && !wr_cmd_accepted_w) 104 | wvalid_q <= 1'b1; 105 | else if (wr_cmd_accepted_w) 106 | wvalid_q <= 1'b0; 107 | 108 | //----------------------------------------------------------------- 109 | // Capture address (for delayed data) 110 | //----------------------------------------------------------------- 111 | reg [7:0] wr_addr_q; 112 | 113 | always @ (posedge clk_i or posedge rst_i) 114 | if (rst_i) 115 | wr_addr_q <= 8'b0; 116 | else if (cfg_awvalid_i && cfg_awready_o) 117 | wr_addr_q <= cfg_awaddr_i[7:0]; 118 | 119 | wire [7:0] wr_addr_w = awvalid_q ? wr_addr_q : cfg_awaddr_i[7:0]; 120 | 121 | //----------------------------------------------------------------- 122 | // Retime write data 123 | //----------------------------------------------------------------- 124 | reg [31:0] wr_data_q; 125 | 126 | always @ (posedge clk_i or posedge rst_i) 127 | if (rst_i) 128 | wr_data_q <= 32'b0; 129 | else if (cfg_wvalid_i && cfg_wready_o) 130 | wr_data_q <= cfg_wdata_i; 131 | 132 | //----------------------------------------------------------------- 133 | // Request Logic 134 | //----------------------------------------------------------------- 135 | wire read_en_w = cfg_arvalid_i & cfg_arready_o; 136 | wire write_en_w = wr_cmd_accepted_w && wr_data_accepted_w; 137 | 138 | //----------------------------------------------------------------- 139 | // Accept Logic 140 | //----------------------------------------------------------------- 141 | assign cfg_arready_o = ~cfg_rvalid_o; 142 | assign cfg_awready_o = ~cfg_bvalid_o && ~cfg_arvalid_i && ~awvalid_q; 143 | assign cfg_wready_o = ~cfg_bvalid_o && ~cfg_arvalid_i && ~wvalid_q; 144 | 145 | 146 | //----------------------------------------------------------------- 147 | // Register spi_dgier 148 | //----------------------------------------------------------------- 149 | reg spi_dgier_wr_q; 150 | 151 | always @ (posedge clk_i or posedge rst_i) 152 | if (rst_i) 153 | spi_dgier_wr_q <= 1'b0; 154 | else if (write_en_w && (wr_addr_w[7:0] == `SPI_DGIER)) 155 | spi_dgier_wr_q <= 1'b1; 156 | else 157 | spi_dgier_wr_q <= 1'b0; 158 | 159 | // spi_dgier_gie [internal] 160 | reg spi_dgier_gie_q; 161 | 162 | always @ (posedge clk_i or posedge rst_i) 163 | if (rst_i) 164 | spi_dgier_gie_q <= 1'd`SPI_DGIER_GIE_DEFAULT; 165 | else if (write_en_w && (wr_addr_w[7:0] == `SPI_DGIER)) 166 | spi_dgier_gie_q <= cfg_wdata_i[`SPI_DGIER_GIE_R]; 167 | 168 | wire spi_dgier_gie_out_w = spi_dgier_gie_q; 169 | 170 | 171 | //----------------------------------------------------------------- 172 | // Register spi_ipisr 173 | //----------------------------------------------------------------- 174 | reg spi_ipisr_wr_q; 175 | 176 | always @ (posedge clk_i or posedge rst_i) 177 | if (rst_i) 178 | spi_ipisr_wr_q <= 1'b0; 179 | else if (write_en_w && (wr_addr_w[7:0] == `SPI_IPISR)) 180 | spi_ipisr_wr_q <= 1'b1; 181 | else 182 | spi_ipisr_wr_q <= 1'b0; 183 | 184 | // spi_ipisr_tx_empty [external] 185 | wire spi_ipisr_tx_empty_out_w = wr_data_q[`SPI_IPISR_TX_EMPTY_R]; 186 | 187 | 188 | //----------------------------------------------------------------- 189 | // Register spi_ipier 190 | //----------------------------------------------------------------- 191 | reg spi_ipier_wr_q; 192 | 193 | always @ (posedge clk_i or posedge rst_i) 194 | if (rst_i) 195 | spi_ipier_wr_q <= 1'b0; 196 | else if (write_en_w && (wr_addr_w[7:0] == `SPI_IPIER)) 197 | spi_ipier_wr_q <= 1'b1; 198 | else 199 | spi_ipier_wr_q <= 1'b0; 200 | 201 | // spi_ipier_tx_empty [internal] 202 | reg spi_ipier_tx_empty_q; 203 | 204 | always @ (posedge clk_i or posedge rst_i) 205 | if (rst_i) 206 | spi_ipier_tx_empty_q <= 1'd`SPI_IPIER_TX_EMPTY_DEFAULT; 207 | else if (write_en_w && (wr_addr_w[7:0] == `SPI_IPIER)) 208 | spi_ipier_tx_empty_q <= cfg_wdata_i[`SPI_IPIER_TX_EMPTY_R]; 209 | 210 | wire spi_ipier_tx_empty_out_w = spi_ipier_tx_empty_q; 211 | 212 | 213 | //----------------------------------------------------------------- 214 | // Register spi_srr 215 | //----------------------------------------------------------------- 216 | reg spi_srr_wr_q; 217 | 218 | always @ (posedge clk_i or posedge rst_i) 219 | if (rst_i) 220 | spi_srr_wr_q <= 1'b0; 221 | else if (write_en_w && (wr_addr_w[7:0] == `SPI_SRR)) 222 | spi_srr_wr_q <= 1'b1; 223 | else 224 | spi_srr_wr_q <= 1'b0; 225 | 226 | // spi_srr_reset [auto_clr] 227 | reg [31:0] spi_srr_reset_q; 228 | 229 | always @ (posedge clk_i or posedge rst_i) 230 | if (rst_i) 231 | spi_srr_reset_q <= 32'd`SPI_SRR_RESET_DEFAULT; 232 | else if (write_en_w && (wr_addr_w[7:0] == `SPI_SRR)) 233 | spi_srr_reset_q <= cfg_wdata_i[`SPI_SRR_RESET_R]; 234 | else 235 | spi_srr_reset_q <= 32'd`SPI_SRR_RESET_DEFAULT; 236 | 237 | wire [31:0] spi_srr_reset_out_w = spi_srr_reset_q; 238 | 239 | 240 | //----------------------------------------------------------------- 241 | // Register spi_cr 242 | //----------------------------------------------------------------- 243 | reg spi_cr_wr_q; 244 | 245 | always @ (posedge clk_i or posedge rst_i) 246 | if (rst_i) 247 | spi_cr_wr_q <= 1'b0; 248 | else if (write_en_w && (wr_addr_w[7:0] == `SPI_CR)) 249 | spi_cr_wr_q <= 1'b1; 250 | else 251 | spi_cr_wr_q <= 1'b0; 252 | 253 | // spi_cr_loop [internal] 254 | reg spi_cr_loop_q; 255 | 256 | always @ (posedge clk_i or posedge rst_i) 257 | if (rst_i) 258 | spi_cr_loop_q <= 1'd`SPI_CR_LOOP_DEFAULT; 259 | else if (write_en_w && (wr_addr_w[7:0] == `SPI_CR)) 260 | spi_cr_loop_q <= cfg_wdata_i[`SPI_CR_LOOP_R]; 261 | 262 | wire spi_cr_loop_out_w = spi_cr_loop_q; 263 | 264 | 265 | // spi_cr_spe [internal] 266 | reg spi_cr_spe_q; 267 | 268 | always @ (posedge clk_i or posedge rst_i) 269 | if (rst_i) 270 | spi_cr_spe_q <= 1'd`SPI_CR_SPE_DEFAULT; 271 | else if (write_en_w && (wr_addr_w[7:0] == `SPI_CR)) 272 | spi_cr_spe_q <= cfg_wdata_i[`SPI_CR_SPE_R]; 273 | 274 | wire spi_cr_spe_out_w = spi_cr_spe_q; 275 | 276 | 277 | // spi_cr_master [internal] 278 | reg spi_cr_master_q; 279 | 280 | always @ (posedge clk_i or posedge rst_i) 281 | if (rst_i) 282 | spi_cr_master_q <= 1'd`SPI_CR_MASTER_DEFAULT; 283 | else if (write_en_w && (wr_addr_w[7:0] == `SPI_CR)) 284 | spi_cr_master_q <= cfg_wdata_i[`SPI_CR_MASTER_R]; 285 | 286 | wire spi_cr_master_out_w = spi_cr_master_q; 287 | 288 | 289 | // spi_cr_cpol [internal] 290 | reg spi_cr_cpol_q; 291 | 292 | always @ (posedge clk_i or posedge rst_i) 293 | if (rst_i) 294 | spi_cr_cpol_q <= 1'd`SPI_CR_CPOL_DEFAULT; 295 | else if (write_en_w && (wr_addr_w[7:0] == `SPI_CR)) 296 | spi_cr_cpol_q <= cfg_wdata_i[`SPI_CR_CPOL_R]; 297 | 298 | wire spi_cr_cpol_out_w = spi_cr_cpol_q; 299 | 300 | 301 | // spi_cr_cpha [internal] 302 | reg spi_cr_cpha_q; 303 | 304 | always @ (posedge clk_i or posedge rst_i) 305 | if (rst_i) 306 | spi_cr_cpha_q <= 1'd`SPI_CR_CPHA_DEFAULT; 307 | else if (write_en_w && (wr_addr_w[7:0] == `SPI_CR)) 308 | spi_cr_cpha_q <= cfg_wdata_i[`SPI_CR_CPHA_R]; 309 | 310 | wire spi_cr_cpha_out_w = spi_cr_cpha_q; 311 | 312 | 313 | // spi_cr_txfifo_rst [auto_clr] 314 | reg spi_cr_txfifo_rst_q; 315 | 316 | always @ (posedge clk_i or posedge rst_i) 317 | if (rst_i) 318 | spi_cr_txfifo_rst_q <= 1'd`SPI_CR_TXFIFO_RST_DEFAULT; 319 | else if (write_en_w && (wr_addr_w[7:0] == `SPI_CR)) 320 | spi_cr_txfifo_rst_q <= cfg_wdata_i[`SPI_CR_TXFIFO_RST_R]; 321 | else 322 | spi_cr_txfifo_rst_q <= 1'd`SPI_CR_TXFIFO_RST_DEFAULT; 323 | 324 | wire spi_cr_txfifo_rst_out_w = spi_cr_txfifo_rst_q; 325 | 326 | 327 | // spi_cr_rxfifo_rst [auto_clr] 328 | reg spi_cr_rxfifo_rst_q; 329 | 330 | always @ (posedge clk_i or posedge rst_i) 331 | if (rst_i) 332 | spi_cr_rxfifo_rst_q <= 1'd`SPI_CR_RXFIFO_RST_DEFAULT; 333 | else if (write_en_w && (wr_addr_w[7:0] == `SPI_CR)) 334 | spi_cr_rxfifo_rst_q <= cfg_wdata_i[`SPI_CR_RXFIFO_RST_R]; 335 | else 336 | spi_cr_rxfifo_rst_q <= 1'd`SPI_CR_RXFIFO_RST_DEFAULT; 337 | 338 | wire spi_cr_rxfifo_rst_out_w = spi_cr_rxfifo_rst_q; 339 | 340 | 341 | // spi_cr_manual_ss [internal] 342 | reg spi_cr_manual_ss_q; 343 | 344 | always @ (posedge clk_i or posedge rst_i) 345 | if (rst_i) 346 | spi_cr_manual_ss_q <= 1'd`SPI_CR_MANUAL_SS_DEFAULT; 347 | else if (write_en_w && (wr_addr_w[7:0] == `SPI_CR)) 348 | spi_cr_manual_ss_q <= cfg_wdata_i[`SPI_CR_MANUAL_SS_R]; 349 | 350 | wire spi_cr_manual_ss_out_w = spi_cr_manual_ss_q; 351 | 352 | 353 | // spi_cr_trans_inhibit [internal] 354 | reg spi_cr_trans_inhibit_q; 355 | 356 | always @ (posedge clk_i or posedge rst_i) 357 | if (rst_i) 358 | spi_cr_trans_inhibit_q <= 1'd`SPI_CR_TRANS_INHIBIT_DEFAULT; 359 | else if (write_en_w && (wr_addr_w[7:0] == `SPI_CR)) 360 | spi_cr_trans_inhibit_q <= cfg_wdata_i[`SPI_CR_TRANS_INHIBIT_R]; 361 | 362 | wire spi_cr_trans_inhibit_out_w = spi_cr_trans_inhibit_q; 363 | 364 | 365 | // spi_cr_lsb_first [internal] 366 | reg spi_cr_lsb_first_q; 367 | 368 | always @ (posedge clk_i or posedge rst_i) 369 | if (rst_i) 370 | spi_cr_lsb_first_q <= 1'd`SPI_CR_LSB_FIRST_DEFAULT; 371 | else if (write_en_w && (wr_addr_w[7:0] == `SPI_CR)) 372 | spi_cr_lsb_first_q <= cfg_wdata_i[`SPI_CR_LSB_FIRST_R]; 373 | 374 | wire spi_cr_lsb_first_out_w = spi_cr_lsb_first_q; 375 | 376 | 377 | //----------------------------------------------------------------- 378 | // Register spi_sr 379 | //----------------------------------------------------------------- 380 | reg spi_sr_wr_q; 381 | 382 | always @ (posedge clk_i or posedge rst_i) 383 | if (rst_i) 384 | spi_sr_wr_q <= 1'b0; 385 | else if (write_en_w && (wr_addr_w[7:0] == `SPI_SR)) 386 | spi_sr_wr_q <= 1'b1; 387 | else 388 | spi_sr_wr_q <= 1'b0; 389 | 390 | 391 | 392 | 393 | 394 | //----------------------------------------------------------------- 395 | // Register spi_dtr 396 | //----------------------------------------------------------------- 397 | reg spi_dtr_wr_q; 398 | 399 | always @ (posedge clk_i or posedge rst_i) 400 | if (rst_i) 401 | spi_dtr_wr_q <= 1'b0; 402 | else if (write_en_w && (wr_addr_w[7:0] == `SPI_DTR)) 403 | spi_dtr_wr_q <= 1'b1; 404 | else 405 | spi_dtr_wr_q <= 1'b0; 406 | 407 | // spi_dtr_data [external] 408 | wire [7:0] spi_dtr_data_out_w = wr_data_q[`SPI_DTR_DATA_R]; 409 | 410 | 411 | //----------------------------------------------------------------- 412 | // Register spi_drr 413 | //----------------------------------------------------------------- 414 | reg spi_drr_wr_q; 415 | 416 | always @ (posedge clk_i or posedge rst_i) 417 | if (rst_i) 418 | spi_drr_wr_q <= 1'b0; 419 | else if (write_en_w && (wr_addr_w[7:0] == `SPI_DRR)) 420 | spi_drr_wr_q <= 1'b1; 421 | else 422 | spi_drr_wr_q <= 1'b0; 423 | 424 | 425 | //----------------------------------------------------------------- 426 | // Register spi_ssr 427 | //----------------------------------------------------------------- 428 | reg spi_ssr_wr_q; 429 | 430 | always @ (posedge clk_i or posedge rst_i) 431 | if (rst_i) 432 | spi_ssr_wr_q <= 1'b0; 433 | else if (write_en_w && (wr_addr_w[7:0] == `SPI_SSR)) 434 | spi_ssr_wr_q <= 1'b1; 435 | else 436 | spi_ssr_wr_q <= 1'b0; 437 | 438 | // spi_ssr_value [internal] 439 | reg [7:0] spi_ssr_value_q; 440 | 441 | always @ (posedge clk_i or posedge rst_i) 442 | if (rst_i) 443 | spi_ssr_value_q <= 8'd`SPI_SSR_VALUE_DEFAULT; 444 | else if (write_en_w && (wr_addr_w[7:0] == `SPI_SSR)) 445 | spi_ssr_value_q <= cfg_wdata_i[`SPI_SSR_VALUE_R]; 446 | 447 | wire [7:0] spi_ssr_value_out_w = spi_ssr_value_q; 448 | 449 | 450 | wire spi_ipisr_tx_empty_in_w; 451 | wire spi_sr_rx_empty_in_w; 452 | wire spi_sr_rx_full_in_w; 453 | wire spi_sr_tx_empty_in_w; 454 | wire spi_sr_tx_full_in_w; 455 | wire [7:0] spi_drr_data_in_w; 456 | 457 | 458 | //----------------------------------------------------------------- 459 | // Read mux 460 | //----------------------------------------------------------------- 461 | reg [31:0] data_r; 462 | 463 | always @ * 464 | begin 465 | data_r = 32'b0; 466 | 467 | case (cfg_araddr_i[7:0]) 468 | 469 | `SPI_DGIER: 470 | begin 471 | data_r[`SPI_DGIER_GIE_R] = spi_dgier_gie_q; 472 | end 473 | `SPI_IPISR: 474 | begin 475 | data_r[`SPI_IPISR_TX_EMPTY_R] = spi_ipisr_tx_empty_in_w; 476 | end 477 | `SPI_IPIER: 478 | begin 479 | data_r[`SPI_IPIER_TX_EMPTY_R] = spi_ipier_tx_empty_q; 480 | end 481 | `SPI_SRR: 482 | begin 483 | end 484 | `SPI_CR: 485 | begin 486 | data_r[`SPI_CR_LOOP_R] = spi_cr_loop_q; 487 | data_r[`SPI_CR_SPE_R] = spi_cr_spe_q; 488 | data_r[`SPI_CR_MASTER_R] = spi_cr_master_q; 489 | data_r[`SPI_CR_CPOL_R] = spi_cr_cpol_q; 490 | data_r[`SPI_CR_CPHA_R] = spi_cr_cpha_q; 491 | data_r[`SPI_CR_MANUAL_SS_R] = spi_cr_manual_ss_q; 492 | data_r[`SPI_CR_TRANS_INHIBIT_R] = spi_cr_trans_inhibit_q; 493 | data_r[`SPI_CR_LSB_FIRST_R] = spi_cr_lsb_first_q; 494 | end 495 | `SPI_SR: 496 | begin 497 | data_r[`SPI_SR_RX_EMPTY_R] = spi_sr_rx_empty_in_w; 498 | data_r[`SPI_SR_RX_FULL_R] = spi_sr_rx_full_in_w; 499 | data_r[`SPI_SR_TX_EMPTY_R] = spi_sr_tx_empty_in_w; 500 | data_r[`SPI_SR_TX_FULL_R] = spi_sr_tx_full_in_w; 501 | end 502 | `SPI_DRR: 503 | begin 504 | data_r[`SPI_DRR_DATA_R] = spi_drr_data_in_w; 505 | end 506 | `SPI_SSR: 507 | begin 508 | data_r[`SPI_SSR_VALUE_R] = spi_ssr_value_q; 509 | end 510 | default : 511 | data_r = 32'b0; 512 | endcase 513 | end 514 | 515 | //----------------------------------------------------------------- 516 | // RVALID 517 | //----------------------------------------------------------------- 518 | reg rvalid_q; 519 | 520 | always @ (posedge clk_i or posedge rst_i) 521 | if (rst_i) 522 | rvalid_q <= 1'b0; 523 | else if (read_en_w) 524 | rvalid_q <= 1'b1; 525 | else if (cfg_rready_i) 526 | rvalid_q <= 1'b0; 527 | 528 | assign cfg_rvalid_o = rvalid_q; 529 | 530 | //----------------------------------------------------------------- 531 | // Retime read response 532 | //----------------------------------------------------------------- 533 | reg [31:0] rd_data_q; 534 | 535 | always @ (posedge clk_i or posedge rst_i) 536 | if (rst_i) 537 | rd_data_q <= 32'b0; 538 | else if (!cfg_rvalid_o || cfg_rready_i) 539 | rd_data_q <= data_r; 540 | 541 | assign cfg_rdata_o = rd_data_q; 542 | assign cfg_rresp_o = 2'b0; 543 | 544 | //----------------------------------------------------------------- 545 | // BVALID 546 | //----------------------------------------------------------------- 547 | reg bvalid_q; 548 | 549 | always @ (posedge clk_i or posedge rst_i) 550 | if (rst_i) 551 | bvalid_q <= 1'b0; 552 | else if (write_en_w) 553 | bvalid_q <= 1'b1; 554 | else if (cfg_bready_i) 555 | bvalid_q <= 1'b0; 556 | 557 | assign cfg_bvalid_o = bvalid_q; 558 | assign cfg_bresp_o = 2'b0; 559 | 560 | wire spi_cr_rd_req_w = read_en_w & (cfg_araddr_i[7:0] == `SPI_CR); 561 | wire spi_drr_rd_req_w = read_en_w & (cfg_araddr_i[7:0] == `SPI_DRR); 562 | 563 | wire spi_ipisr_wr_req_w = spi_ipisr_wr_q; 564 | wire spi_cr_wr_req_w = spi_cr_wr_q; 565 | wire spi_dtr_wr_req_w = spi_dtr_wr_q; 566 | wire spi_drr_wr_req_w = spi_drr_wr_q; 567 | 568 | 569 | //----------------------------------------------------------------- 570 | // TX FIFO 571 | //----------------------------------------------------------------- 572 | wire sw_reset_w = spi_srr_reset_out_w == 32'h0000000A; 573 | wire tx_fifo_flush_w = sw_reset_w | spi_cr_txfifo_rst_out_w; 574 | wire rx_fifo_flush_w = sw_reset_w | spi_cr_rxfifo_rst_out_w; 575 | 576 | wire tx_accept_w; 577 | wire tx_ready_w; 578 | wire [7:0] tx_data_raw_w; 579 | wire tx_pop_w; 580 | 581 | spi_lite_fifo 582 | #( 583 | .WIDTH(8), 584 | .DEPTH(4), 585 | .ADDR_W(2) 586 | ) 587 | u_tx_fifo 588 | ( 589 | .clk_i(clk_i), 590 | .rst_i(rst_i), 591 | 592 | .flush_i(tx_fifo_flush_w), 593 | 594 | .data_in_i(spi_dtr_data_out_w), 595 | .push_i(spi_dtr_wr_req_w), 596 | .accept_o(tx_accept_w), 597 | 598 | .pop_i(tx_pop_w), 599 | .data_out_o(tx_data_raw_w), 600 | .valid_o(tx_ready_w) 601 | ); 602 | 603 | assign spi_sr_tx_empty_in_w = ~tx_ready_w; 604 | assign spi_sr_tx_full_in_w = ~tx_accept_w; 605 | 606 | // Reverse order if LSB first 607 | wire [7:0] tx_data_w = spi_cr_lsb_first_out_w ? 608 | { 609 | tx_data_raw_w[0] 610 | , tx_data_raw_w[1] 611 | , tx_data_raw_w[2] 612 | , tx_data_raw_w[3] 613 | , tx_data_raw_w[4] 614 | , tx_data_raw_w[5] 615 | , tx_data_raw_w[6] 616 | , tx_data_raw_w[7] 617 | } : tx_data_raw_w; 618 | 619 | //----------------------------------------------------------------- 620 | // RX FIFO 621 | //----------------------------------------------------------------- 622 | wire rx_accept_w; 623 | wire rx_ready_w; 624 | wire [7:0] rx_data_w; 625 | wire rx_push_w; 626 | 627 | spi_lite_fifo 628 | #( 629 | .WIDTH(8), 630 | .DEPTH(4), 631 | .ADDR_W(2) 632 | ) 633 | u_rx_fifo 634 | ( 635 | .clk_i(clk_i), 636 | .rst_i(rst_i), 637 | 638 | .flush_i(rx_fifo_flush_w), 639 | 640 | .data_in_i(rx_data_w), 641 | .push_i(rx_push_w), 642 | .accept_o(rx_accept_w), 643 | 644 | .pop_i(spi_drr_rd_req_w), 645 | .data_out_o(spi_drr_data_in_w), 646 | .valid_o(rx_ready_w) 647 | ); 648 | 649 | 650 | assign spi_sr_rx_empty_in_w = ~rx_ready_w; 651 | assign spi_sr_rx_full_in_w = ~rx_accept_w; 652 | 653 | //----------------------------------------------------------------- 654 | // Configuration 655 | //----------------------------------------------------------------- 656 | wire [31:0] clk_div_w = C_SCK_RATIO; 657 | 658 | //----------------------------------------------------------------- 659 | // Registers 660 | //----------------------------------------------------------------- 661 | reg active_q; 662 | reg [5:0] bit_count_q; 663 | reg [7:0] shift_reg_q; 664 | reg [31:0] clk_div_q; 665 | reg done_q; 666 | 667 | // Xilinx placement pragmas: 668 | //synthesis attribute IOB of spi_clk_q is "TRUE" 669 | //synthesis attribute IOB of spi_mosi_q is "TRUE" 670 | //synthesis attribute IOB of spi_cs_o is "TRUE" 671 | reg spi_clk_q; 672 | reg spi_mosi_q; 673 | 674 | //----------------------------------------------------------------- 675 | // Implementation 676 | //----------------------------------------------------------------- 677 | wire enable_w = spi_cr_spe_out_w & spi_cr_master_out_w & ~spi_cr_trans_inhibit_out_w; 678 | 679 | // Something to do, SPI enabled... 680 | wire start_w = enable_w & ~active_q & ~done_q & tx_ready_w; 681 | 682 | // Loopback more or normal 683 | wire miso_w = spi_cr_loop_out_w ? spi_mosi_o : spi_miso_i; 684 | 685 | // SPI Clock Generator 686 | always @ (posedge clk_i or posedge rst_i) 687 | if (rst_i) 688 | clk_div_q <= 32'd0; 689 | else if (start_w || sw_reset_w || clk_div_q == 32'd0) 690 | clk_div_q <= clk_div_w; 691 | else 692 | clk_div_q <= clk_div_q - 32'd1; 693 | 694 | wire clk_en_w = (clk_div_q == 32'd0); 695 | 696 | //----------------------------------------------------------------- 697 | // Sample, Drive pulse generation 698 | //----------------------------------------------------------------- 699 | reg sample_r; 700 | reg drive_r; 701 | 702 | always @ * 703 | begin 704 | sample_r = 1'b0; 705 | drive_r = 1'b0; 706 | 707 | // SPI = IDLE 708 | if (start_w) 709 | drive_r = ~spi_cr_cpha_out_w; // Drive initial data (CPHA=0) 710 | // SPI = ACTIVE 711 | else if (active_q && clk_en_w) 712 | begin 713 | // Sample 714 | // CPHA=0, sample on the first edge 715 | // CPHA=1, sample on the second edge 716 | if (bit_count_q[0] == spi_cr_cpha_out_w) 717 | sample_r = 1'b1; 718 | // Drive (CPHA = 1) 719 | else if (spi_cr_cpha_out_w) 720 | drive_r = 1'b1; 721 | // Drive (CPHA = 0) 722 | else 723 | drive_r = (bit_count_q != 6'b0) && (bit_count_q != 6'd15); 724 | end 725 | end 726 | 727 | //----------------------------------------------------------------- 728 | // Shift register 729 | //----------------------------------------------------------------- 730 | always @ (posedge clk_i or posedge rst_i) 731 | if (rst_i) 732 | begin 733 | shift_reg_q <= 8'b0; 734 | spi_clk_q <= 1'b0; 735 | spi_mosi_q <= 1'b0; 736 | end 737 | else 738 | begin 739 | // SPI = RESET (or potentially update CPOL) 740 | if (sw_reset_w || (spi_cr_wr_req_w & !start_w)) 741 | begin 742 | shift_reg_q <= 8'b0; 743 | spi_clk_q <= spi_cr_cpol_out_w; 744 | end 745 | // SPI = IDLE 746 | else if (start_w) 747 | begin 748 | spi_clk_q <= spi_cr_cpol_out_w; 749 | 750 | // CPHA = 0 751 | if (drive_r) 752 | begin 753 | spi_mosi_q <= tx_data_w[7]; 754 | shift_reg_q <= {tx_data_w[6:0], 1'b0}; 755 | end 756 | // CPHA = 1 757 | else 758 | shift_reg_q <= tx_data_w; 759 | end 760 | // SPI = ACTIVE 761 | else if (active_q && clk_en_w) 762 | begin 763 | // Toggle SPI clock output 764 | if (!spi_cr_loop_out_w) 765 | spi_clk_q <= ~spi_clk_q; 766 | 767 | // Drive MOSI 768 | if (drive_r) 769 | begin 770 | spi_mosi_q <= shift_reg_q[7]; 771 | shift_reg_q <= {shift_reg_q[6:0],1'b0}; 772 | end 773 | // Sample MISO 774 | else if (sample_r) 775 | shift_reg_q[0] <= miso_w; 776 | end 777 | end 778 | 779 | //----------------------------------------------------------------- 780 | // Bit counter 781 | //----------------------------------------------------------------- 782 | always @ (posedge clk_i or posedge rst_i) 783 | if (rst_i) 784 | begin 785 | bit_count_q <= 6'b0; 786 | active_q <= 1'b0; 787 | done_q <= 1'b0; 788 | end 789 | else if (sw_reset_w) 790 | begin 791 | bit_count_q <= 6'b0; 792 | active_q <= 1'b0; 793 | done_q <= 1'b0; 794 | end 795 | else if (start_w) 796 | begin 797 | bit_count_q <= 6'b0; 798 | active_q <= 1'b1; 799 | done_q <= 1'b0; 800 | end 801 | else if (active_q && clk_en_w) 802 | begin 803 | // End of SPI transfer reached 804 | if (bit_count_q == 6'd15) 805 | begin 806 | // Go back to IDLE active_q 807 | active_q <= 1'b0; 808 | 809 | // Set transfer complete flags 810 | done_q <= 1'b1; 811 | end 812 | // Increment cycle counter 813 | else 814 | bit_count_q <= bit_count_q + 6'd1; 815 | end 816 | else 817 | done_q <= 1'b0; 818 | 819 | // Delayed done_q for FIFO level check 820 | reg check_tx_level_q; 821 | always @ (posedge clk_i or posedge rst_i) 822 | if (rst_i) 823 | check_tx_level_q <= 1'b0; 824 | else 825 | check_tx_level_q <= done_q; 826 | 827 | // Interrupt 828 | reg intr_q; 829 | 830 | always @ (posedge clk_i or posedge rst_i) 831 | if (rst_i) 832 | intr_q <= 1'b0; 833 | else if (check_tx_level_q && spi_ipier_tx_empty_out_w && spi_ipisr_tx_empty_in_w) 834 | intr_q <= 1'b1; 835 | else if (spi_ipisr_wr_req_w && spi_ipisr_tx_empty_out_w) 836 | intr_q <= 1'b0; 837 | 838 | assign spi_ipisr_tx_empty_in_w = spi_sr_tx_empty_in_w; 839 | 840 | //----------------------------------------------------------------- 841 | // Assignments 842 | //----------------------------------------------------------------- 843 | assign spi_clk_o = spi_clk_q; 844 | assign spi_mosi_o = spi_mosi_q; 845 | 846 | // Reverse order if LSB first 847 | assign rx_data_w = spi_cr_lsb_first_out_w ? 848 | { 849 | shift_reg_q[0] 850 | , shift_reg_q[1] 851 | , shift_reg_q[2] 852 | , shift_reg_q[3] 853 | , shift_reg_q[4] 854 | , shift_reg_q[5] 855 | , shift_reg_q[6] 856 | , shift_reg_q[7] 857 | } : shift_reg_q; 858 | 859 | 860 | assign rx_push_w = done_q; 861 | assign tx_pop_w = done_q; 862 | 863 | assign spi_cs_o = spi_ssr_value_out_w; 864 | assign intr_o = spi_dgier_gie_out_w & intr_q; 865 | 866 | endmodule 867 | 868 | //----------------------------------------------------------------- 869 | // Params 870 | //----------------------------------------------------------------- 871 | 872 | module spi_lite_fifo 873 | //----------------------------------------------------------------- 874 | // Params 875 | //----------------------------------------------------------------- 876 | #( 877 | parameter WIDTH = 8, 878 | parameter DEPTH = 4, 879 | parameter ADDR_W = 2 880 | ) 881 | //----------------------------------------------------------------- 882 | // Ports 883 | //----------------------------------------------------------------- 884 | ( 885 | // Inputs 886 | input clk_i 887 | ,input rst_i 888 | ,input [WIDTH-1:0] data_in_i 889 | ,input push_i 890 | ,input pop_i 891 | ,input flush_i 892 | 893 | // Outputs 894 | ,output [WIDTH-1:0] data_out_o 895 | ,output accept_o 896 | ,output valid_o 897 | ); 898 | 899 | //----------------------------------------------------------------- 900 | // Local Params 901 | //----------------------------------------------------------------- 902 | localparam COUNT_W = ADDR_W + 1; 903 | 904 | //----------------------------------------------------------------- 905 | // Registers 906 | //----------------------------------------------------------------- 907 | reg [WIDTH-1:0] ram_q[DEPTH-1:0]; 908 | reg [ADDR_W-1:0] rd_ptr_q; 909 | reg [ADDR_W-1:0] wr_ptr_q; 910 | reg [COUNT_W-1:0] count_q; 911 | 912 | //----------------------------------------------------------------- 913 | // Sequential 914 | //----------------------------------------------------------------- 915 | always @ (posedge clk_i or posedge rst_i) 916 | if (rst_i) 917 | begin 918 | count_q <= {(COUNT_W) {1'b0}}; 919 | rd_ptr_q <= {(ADDR_W) {1'b0}}; 920 | wr_ptr_q <= {(ADDR_W) {1'b0}}; 921 | end 922 | else if (flush_i) 923 | begin 924 | count_q <= {(COUNT_W) {1'b0}}; 925 | rd_ptr_q <= {(ADDR_W) {1'b0}}; 926 | wr_ptr_q <= {(ADDR_W) {1'b0}}; 927 | end 928 | else 929 | begin 930 | // Push 931 | if (push_i & accept_o) 932 | begin 933 | ram_q[wr_ptr_q] <= data_in_i; 934 | wr_ptr_q <= wr_ptr_q + 1; 935 | end 936 | 937 | // Pop 938 | if (pop_i & valid_o) 939 | rd_ptr_q <= rd_ptr_q + 1; 940 | 941 | // Count up 942 | if ((push_i & accept_o) & ~(pop_i & valid_o)) 943 | count_q <= count_q + 1; 944 | // Count down 945 | else if (~(push_i & accept_o) & (pop_i & valid_o)) 946 | count_q <= count_q - 1; 947 | end 948 | 949 | //------------------------------------------------------------------- 950 | // Combinatorial 951 | //------------------------------------------------------------------- 952 | /* verilator lint_off WIDTH */ 953 | assign valid_o = (count_q != 0); 954 | assign accept_o = (count_q != DEPTH); 955 | /* verilator lint_on WIDTH */ 956 | 957 | assign data_out_o = ram_q[rd_ptr_q]; 958 | 959 | 960 | 961 | endmodule 962 | -------------------------------------------------------------------------------- /src_v/spi_lite_defs.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // Basic Peripheral SoC 3 | // V1.1 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2020 6 | // 7 | // Email: admin@ultra-embedded.com 8 | // 9 | // License: GPL 10 | // If you would like a version with a more permissive license for 11 | // use in closed source commercial applications please contact me 12 | // for details. 13 | //----------------------------------------------------------------- 14 | // 15 | // This file is open source HDL; you can redistribute it and/or 16 | // modify it under the terms of the GNU General Public License as 17 | // published by the Free Software Foundation; either version 2 of 18 | // the License, or (at your option) any later version. 19 | // 20 | // This file is distributed in the hope that it will be useful, 21 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | // GNU General Public License for more details. 24 | // 25 | // You should have received a copy of the GNU General Public 26 | // License along with this file; if not, write to the Free Software 27 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 28 | // USA 29 | //----------------------------------------------------------------- 30 | 31 | //----------------------------------------------------------------- 32 | // Generated File 33 | //----------------------------------------------------------------- 34 | 35 | `define SPI_DGIER 8'h1c 36 | 37 | `define SPI_DGIER_GIE 31 38 | `define SPI_DGIER_GIE_DEFAULT 0 39 | `define SPI_DGIER_GIE_B 31 40 | `define SPI_DGIER_GIE_T 31 41 | `define SPI_DGIER_GIE_W 1 42 | `define SPI_DGIER_GIE_R 31:31 43 | 44 | `define SPI_IPISR 8'h20 45 | 46 | `define SPI_IPISR_TX_EMPTY 2 47 | `define SPI_IPISR_TX_EMPTY_DEFAULT 0 48 | `define SPI_IPISR_TX_EMPTY_B 2 49 | `define SPI_IPISR_TX_EMPTY_T 2 50 | `define SPI_IPISR_TX_EMPTY_W 1 51 | `define SPI_IPISR_TX_EMPTY_R 2:2 52 | 53 | `define SPI_IPIER 8'h28 54 | 55 | `define SPI_IPIER_TX_EMPTY 2 56 | `define SPI_IPIER_TX_EMPTY_DEFAULT 0 57 | `define SPI_IPIER_TX_EMPTY_B 2 58 | `define SPI_IPIER_TX_EMPTY_T 2 59 | `define SPI_IPIER_TX_EMPTY_W 1 60 | `define SPI_IPIER_TX_EMPTY_R 2:2 61 | 62 | `define SPI_SRR 8'h40 63 | 64 | `define SPI_SRR_RESET_DEFAULT 0 65 | `define SPI_SRR_RESET_B 0 66 | `define SPI_SRR_RESET_T 31 67 | `define SPI_SRR_RESET_W 32 68 | `define SPI_SRR_RESET_R 31:0 69 | 70 | `define SPI_CR 8'h60 71 | 72 | `define SPI_CR_LOOP 0 73 | `define SPI_CR_LOOP_DEFAULT 0 74 | `define SPI_CR_LOOP_B 0 75 | `define SPI_CR_LOOP_T 0 76 | `define SPI_CR_LOOP_W 1 77 | `define SPI_CR_LOOP_R 0:0 78 | 79 | `define SPI_CR_SPE 1 80 | `define SPI_CR_SPE_DEFAULT 0 81 | `define SPI_CR_SPE_B 1 82 | `define SPI_CR_SPE_T 1 83 | `define SPI_CR_SPE_W 1 84 | `define SPI_CR_SPE_R 1:1 85 | 86 | `define SPI_CR_MASTER 2 87 | `define SPI_CR_MASTER_DEFAULT 0 88 | `define SPI_CR_MASTER_B 2 89 | `define SPI_CR_MASTER_T 2 90 | `define SPI_CR_MASTER_W 1 91 | `define SPI_CR_MASTER_R 2:2 92 | 93 | `define SPI_CR_CPOL 3 94 | `define SPI_CR_CPOL_DEFAULT 0 95 | `define SPI_CR_CPOL_B 3 96 | `define SPI_CR_CPOL_T 3 97 | `define SPI_CR_CPOL_W 1 98 | `define SPI_CR_CPOL_R 3:3 99 | 100 | `define SPI_CR_CPHA 4 101 | `define SPI_CR_CPHA_DEFAULT 0 102 | `define SPI_CR_CPHA_B 4 103 | `define SPI_CR_CPHA_T 4 104 | `define SPI_CR_CPHA_W 1 105 | `define SPI_CR_CPHA_R 4:4 106 | 107 | `define SPI_CR_TXFIFO_RST 5 108 | `define SPI_CR_TXFIFO_RST_DEFAULT 0 109 | `define SPI_CR_TXFIFO_RST_B 5 110 | `define SPI_CR_TXFIFO_RST_T 5 111 | `define SPI_CR_TXFIFO_RST_W 1 112 | `define SPI_CR_TXFIFO_RST_R 5:5 113 | 114 | `define SPI_CR_RXFIFO_RST 6 115 | `define SPI_CR_RXFIFO_RST_DEFAULT 0 116 | `define SPI_CR_RXFIFO_RST_B 6 117 | `define SPI_CR_RXFIFO_RST_T 6 118 | `define SPI_CR_RXFIFO_RST_W 1 119 | `define SPI_CR_RXFIFO_RST_R 6:6 120 | 121 | `define SPI_CR_MANUAL_SS 7 122 | `define SPI_CR_MANUAL_SS_DEFAULT 0 123 | `define SPI_CR_MANUAL_SS_B 7 124 | `define SPI_CR_MANUAL_SS_T 7 125 | `define SPI_CR_MANUAL_SS_W 1 126 | `define SPI_CR_MANUAL_SS_R 7:7 127 | 128 | `define SPI_CR_TRANS_INHIBIT 8 129 | `define SPI_CR_TRANS_INHIBIT_DEFAULT 0 130 | `define SPI_CR_TRANS_INHIBIT_B 8 131 | `define SPI_CR_TRANS_INHIBIT_T 8 132 | `define SPI_CR_TRANS_INHIBIT_W 1 133 | `define SPI_CR_TRANS_INHIBIT_R 8:8 134 | 135 | `define SPI_CR_LSB_FIRST 9 136 | `define SPI_CR_LSB_FIRST_DEFAULT 0 137 | `define SPI_CR_LSB_FIRST_B 9 138 | `define SPI_CR_LSB_FIRST_T 9 139 | `define SPI_CR_LSB_FIRST_W 1 140 | `define SPI_CR_LSB_FIRST_R 9:9 141 | 142 | `define SPI_SR 8'h64 143 | 144 | `define SPI_SR_RX_EMPTY 0 145 | `define SPI_SR_RX_EMPTY_DEFAULT 0 146 | `define SPI_SR_RX_EMPTY_B 0 147 | `define SPI_SR_RX_EMPTY_T 0 148 | `define SPI_SR_RX_EMPTY_W 1 149 | `define SPI_SR_RX_EMPTY_R 0:0 150 | 151 | `define SPI_SR_RX_FULL 1 152 | `define SPI_SR_RX_FULL_DEFAULT 0 153 | `define SPI_SR_RX_FULL_B 1 154 | `define SPI_SR_RX_FULL_T 1 155 | `define SPI_SR_RX_FULL_W 1 156 | `define SPI_SR_RX_FULL_R 1:1 157 | 158 | `define SPI_SR_TX_EMPTY 2 159 | `define SPI_SR_TX_EMPTY_DEFAULT 0 160 | `define SPI_SR_TX_EMPTY_B 2 161 | `define SPI_SR_TX_EMPTY_T 2 162 | `define SPI_SR_TX_EMPTY_W 1 163 | `define SPI_SR_TX_EMPTY_R 2:2 164 | 165 | `define SPI_SR_TX_FULL 3 166 | `define SPI_SR_TX_FULL_DEFAULT 0 167 | `define SPI_SR_TX_FULL_B 3 168 | `define SPI_SR_TX_FULL_T 3 169 | `define SPI_SR_TX_FULL_W 1 170 | `define SPI_SR_TX_FULL_R 3:3 171 | 172 | `define SPI_DTR 8'h68 173 | 174 | `define SPI_DTR_DATA_DEFAULT 0 175 | `define SPI_DTR_DATA_B 0 176 | `define SPI_DTR_DATA_T 7 177 | `define SPI_DTR_DATA_W 8 178 | `define SPI_DTR_DATA_R 7:0 179 | 180 | `define SPI_DRR 8'h6c 181 | 182 | `define SPI_DRR_DATA_DEFAULT 0 183 | `define SPI_DRR_DATA_B 0 184 | `define SPI_DRR_DATA_T 7 185 | `define SPI_DRR_DATA_W 8 186 | `define SPI_DRR_DATA_R 7:0 187 | 188 | `define SPI_SSR 8'h70 189 | 190 | `define SPI_SSR_VALUE_DEFAULT 1 191 | `define SPI_SSR_VALUE_B 0 192 | `define SPI_SSR_VALUE_T 7 193 | `define SPI_SSR_VALUE_W 8 194 | `define SPI_SSR_VALUE_R 7:0 195 | 196 | -------------------------------------------------------------------------------- /src_v/timer.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // Basic Peripheral SoC 3 | // V1.1 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2020 6 | // 7 | // Email: admin@ultra-embedded.com 8 | // 9 | // License: GPL 10 | // If you would like a version with a more permissive license for 11 | // use in closed source commercial applications please contact me 12 | // for details. 13 | //----------------------------------------------------------------- 14 | // 15 | // This file is open source HDL; you can redistribute it and/or 16 | // modify it under the terms of the GNU General Public License as 17 | // published by the Free Software Foundation; either version 2 of 18 | // the License, or (at your option) any later version. 19 | // 20 | // This file is distributed in the hope that it will be useful, 21 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | // GNU General Public License for more details. 24 | // 25 | // You should have received a copy of the GNU General Public 26 | // License along with this file; if not, write to the Free Software 27 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 28 | // USA 29 | //----------------------------------------------------------------- 30 | 31 | //----------------------------------------------------------------- 32 | // Generated File 33 | //----------------------------------------------------------------- 34 | 35 | `include "timer_defs.v" 36 | 37 | //----------------------------------------------------------------- 38 | // Module: System Tick Timer 39 | //----------------------------------------------------------------- 40 | module timer 41 | ( 42 | // Inputs 43 | input clk_i 44 | ,input rst_i 45 | ,input cfg_awvalid_i 46 | ,input [31:0] cfg_awaddr_i 47 | ,input cfg_wvalid_i 48 | ,input [31:0] cfg_wdata_i 49 | ,input [3:0] cfg_wstrb_i 50 | ,input cfg_bready_i 51 | ,input cfg_arvalid_i 52 | ,input [31:0] cfg_araddr_i 53 | ,input cfg_rready_i 54 | 55 | // Outputs 56 | ,output cfg_awready_o 57 | ,output cfg_wready_o 58 | ,output cfg_bvalid_o 59 | ,output [1:0] cfg_bresp_o 60 | ,output cfg_arready_o 61 | ,output cfg_rvalid_o 62 | ,output [31:0] cfg_rdata_o 63 | ,output [1:0] cfg_rresp_o 64 | ,output intr_o 65 | ); 66 | 67 | //----------------------------------------------------------------- 68 | // Write address / data split 69 | //----------------------------------------------------------------- 70 | // Address but no data ready 71 | reg awvalid_q; 72 | 73 | // Data but no data ready 74 | reg wvalid_q; 75 | 76 | wire wr_cmd_accepted_w = (cfg_awvalid_i && cfg_awready_o) || awvalid_q; 77 | wire wr_data_accepted_w = (cfg_wvalid_i && cfg_wready_o) || wvalid_q; 78 | 79 | always @ (posedge clk_i or posedge rst_i) 80 | if (rst_i) 81 | awvalid_q <= 1'b0; 82 | else if (cfg_awvalid_i && cfg_awready_o && !wr_data_accepted_w) 83 | awvalid_q <= 1'b1; 84 | else if (wr_data_accepted_w) 85 | awvalid_q <= 1'b0; 86 | 87 | always @ (posedge clk_i or posedge rst_i) 88 | if (rst_i) 89 | wvalid_q <= 1'b0; 90 | else if (cfg_wvalid_i && cfg_wready_o && !wr_cmd_accepted_w) 91 | wvalid_q <= 1'b1; 92 | else if (wr_cmd_accepted_w) 93 | wvalid_q <= 1'b0; 94 | 95 | //----------------------------------------------------------------- 96 | // Capture address (for delayed data) 97 | //----------------------------------------------------------------- 98 | reg [7:0] wr_addr_q; 99 | 100 | always @ (posedge clk_i or posedge rst_i) 101 | if (rst_i) 102 | wr_addr_q <= 8'b0; 103 | else if (cfg_awvalid_i && cfg_awready_o) 104 | wr_addr_q <= cfg_awaddr_i[7:0]; 105 | 106 | wire [7:0] wr_addr_w = awvalid_q ? wr_addr_q : cfg_awaddr_i[7:0]; 107 | 108 | //----------------------------------------------------------------- 109 | // Retime write data 110 | //----------------------------------------------------------------- 111 | reg [31:0] wr_data_q; 112 | 113 | always @ (posedge clk_i or posedge rst_i) 114 | if (rst_i) 115 | wr_data_q <= 32'b0; 116 | else if (cfg_wvalid_i && cfg_wready_o) 117 | wr_data_q <= cfg_wdata_i; 118 | 119 | //----------------------------------------------------------------- 120 | // Request Logic 121 | //----------------------------------------------------------------- 122 | wire read_en_w = cfg_arvalid_i & cfg_arready_o; 123 | wire write_en_w = wr_cmd_accepted_w && wr_data_accepted_w; 124 | 125 | //----------------------------------------------------------------- 126 | // Accept Logic 127 | //----------------------------------------------------------------- 128 | assign cfg_arready_o = ~cfg_rvalid_o; 129 | assign cfg_awready_o = ~cfg_bvalid_o && ~cfg_arvalid_i && ~awvalid_q; 130 | assign cfg_wready_o = ~cfg_bvalid_o && ~cfg_arvalid_i && ~wvalid_q; 131 | 132 | 133 | //----------------------------------------------------------------- 134 | // Register timer_ctrl0 135 | //----------------------------------------------------------------- 136 | reg timer_ctrl0_wr_q; 137 | 138 | always @ (posedge clk_i or posedge rst_i) 139 | if (rst_i) 140 | timer_ctrl0_wr_q <= 1'b0; 141 | else if (write_en_w && (wr_addr_w[7:0] == `TIMER_CTRL0)) 142 | timer_ctrl0_wr_q <= 1'b1; 143 | else 144 | timer_ctrl0_wr_q <= 1'b0; 145 | 146 | // timer_ctrl0_interrupt [internal] 147 | reg timer_ctrl0_interrupt_q; 148 | 149 | always @ (posedge clk_i or posedge rst_i) 150 | if (rst_i) 151 | timer_ctrl0_interrupt_q <= 1'd`TIMER_CTRL0_INTERRUPT_DEFAULT; 152 | else if (write_en_w && (wr_addr_w[7:0] == `TIMER_CTRL0)) 153 | timer_ctrl0_interrupt_q <= cfg_wdata_i[`TIMER_CTRL0_INTERRUPT_R]; 154 | 155 | wire timer_ctrl0_interrupt_out_w = timer_ctrl0_interrupt_q; 156 | 157 | 158 | // timer_ctrl0_enable [internal] 159 | reg timer_ctrl0_enable_q; 160 | 161 | always @ (posedge clk_i or posedge rst_i) 162 | if (rst_i) 163 | timer_ctrl0_enable_q <= 1'd`TIMER_CTRL0_ENABLE_DEFAULT; 164 | else if (write_en_w && (wr_addr_w[7:0] == `TIMER_CTRL0)) 165 | timer_ctrl0_enable_q <= cfg_wdata_i[`TIMER_CTRL0_ENABLE_R]; 166 | 167 | wire timer_ctrl0_enable_out_w = timer_ctrl0_enable_q; 168 | 169 | 170 | //----------------------------------------------------------------- 171 | // Register timer_cmp0 172 | //----------------------------------------------------------------- 173 | reg timer_cmp0_wr_q; 174 | 175 | always @ (posedge clk_i or posedge rst_i) 176 | if (rst_i) 177 | timer_cmp0_wr_q <= 1'b0; 178 | else if (write_en_w && (wr_addr_w[7:0] == `TIMER_CMP0)) 179 | timer_cmp0_wr_q <= 1'b1; 180 | else 181 | timer_cmp0_wr_q <= 1'b0; 182 | 183 | // timer_cmp0_value [internal] 184 | reg [31:0] timer_cmp0_value_q; 185 | 186 | always @ (posedge clk_i or posedge rst_i) 187 | if (rst_i) 188 | timer_cmp0_value_q <= 32'd`TIMER_CMP0_VALUE_DEFAULT; 189 | else if (write_en_w && (wr_addr_w[7:0] == `TIMER_CMP0)) 190 | timer_cmp0_value_q <= cfg_wdata_i[`TIMER_CMP0_VALUE_R]; 191 | 192 | wire [31:0] timer_cmp0_value_out_w = timer_cmp0_value_q; 193 | 194 | 195 | //----------------------------------------------------------------- 196 | // Register timer_val0 197 | //----------------------------------------------------------------- 198 | reg timer_val0_wr_q; 199 | 200 | always @ (posedge clk_i or posedge rst_i) 201 | if (rst_i) 202 | timer_val0_wr_q <= 1'b0; 203 | else if (write_en_w && (wr_addr_w[7:0] == `TIMER_VAL0)) 204 | timer_val0_wr_q <= 1'b1; 205 | else 206 | timer_val0_wr_q <= 1'b0; 207 | 208 | // timer_val0_current [external] 209 | wire [31:0] timer_val0_current_out_w = wr_data_q[`TIMER_VAL0_CURRENT_R]; 210 | 211 | 212 | //----------------------------------------------------------------- 213 | // Register timer_ctrl1 214 | //----------------------------------------------------------------- 215 | reg timer_ctrl1_wr_q; 216 | 217 | always @ (posedge clk_i or posedge rst_i) 218 | if (rst_i) 219 | timer_ctrl1_wr_q <= 1'b0; 220 | else if (write_en_w && (wr_addr_w[7:0] == `TIMER_CTRL1)) 221 | timer_ctrl1_wr_q <= 1'b1; 222 | else 223 | timer_ctrl1_wr_q <= 1'b0; 224 | 225 | // timer_ctrl1_interrupt [internal] 226 | reg timer_ctrl1_interrupt_q; 227 | 228 | always @ (posedge clk_i or posedge rst_i) 229 | if (rst_i) 230 | timer_ctrl1_interrupt_q <= 1'd`TIMER_CTRL1_INTERRUPT_DEFAULT; 231 | else if (write_en_w && (wr_addr_w[7:0] == `TIMER_CTRL1)) 232 | timer_ctrl1_interrupt_q <= cfg_wdata_i[`TIMER_CTRL1_INTERRUPT_R]; 233 | 234 | wire timer_ctrl1_interrupt_out_w = timer_ctrl1_interrupt_q; 235 | 236 | 237 | // timer_ctrl1_enable [internal] 238 | reg timer_ctrl1_enable_q; 239 | 240 | always @ (posedge clk_i or posedge rst_i) 241 | if (rst_i) 242 | timer_ctrl1_enable_q <= 1'd`TIMER_CTRL1_ENABLE_DEFAULT; 243 | else if (write_en_w && (wr_addr_w[7:0] == `TIMER_CTRL1)) 244 | timer_ctrl1_enable_q <= cfg_wdata_i[`TIMER_CTRL1_ENABLE_R]; 245 | 246 | wire timer_ctrl1_enable_out_w = timer_ctrl1_enable_q; 247 | 248 | 249 | //----------------------------------------------------------------- 250 | // Register timer_cmp1 251 | //----------------------------------------------------------------- 252 | reg timer_cmp1_wr_q; 253 | 254 | always @ (posedge clk_i or posedge rst_i) 255 | if (rst_i) 256 | timer_cmp1_wr_q <= 1'b0; 257 | else if (write_en_w && (wr_addr_w[7:0] == `TIMER_CMP1)) 258 | timer_cmp1_wr_q <= 1'b1; 259 | else 260 | timer_cmp1_wr_q <= 1'b0; 261 | 262 | // timer_cmp1_value [internal] 263 | reg [31:0] timer_cmp1_value_q; 264 | 265 | always @ (posedge clk_i or posedge rst_i) 266 | if (rst_i) 267 | timer_cmp1_value_q <= 32'd`TIMER_CMP1_VALUE_DEFAULT; 268 | else if (write_en_w && (wr_addr_w[7:0] == `TIMER_CMP1)) 269 | timer_cmp1_value_q <= cfg_wdata_i[`TIMER_CMP1_VALUE_R]; 270 | 271 | wire [31:0] timer_cmp1_value_out_w = timer_cmp1_value_q; 272 | 273 | 274 | //----------------------------------------------------------------- 275 | // Register timer_val1 276 | //----------------------------------------------------------------- 277 | reg timer_val1_wr_q; 278 | 279 | always @ (posedge clk_i or posedge rst_i) 280 | if (rst_i) 281 | timer_val1_wr_q <= 1'b0; 282 | else if (write_en_w && (wr_addr_w[7:0] == `TIMER_VAL1)) 283 | timer_val1_wr_q <= 1'b1; 284 | else 285 | timer_val1_wr_q <= 1'b0; 286 | 287 | // timer_val1_current [external] 288 | wire [31:0] timer_val1_current_out_w = wr_data_q[`TIMER_VAL1_CURRENT_R]; 289 | 290 | 291 | wire [31:0] timer_val0_current_in_w; 292 | wire [31:0] timer_val1_current_in_w; 293 | 294 | 295 | //----------------------------------------------------------------- 296 | // Read mux 297 | //----------------------------------------------------------------- 298 | reg [31:0] data_r; 299 | 300 | always @ * 301 | begin 302 | data_r = 32'b0; 303 | 304 | case (cfg_araddr_i[7:0]) 305 | 306 | `TIMER_CTRL0: 307 | begin 308 | data_r[`TIMER_CTRL0_INTERRUPT_R] = timer_ctrl0_interrupt_q; 309 | data_r[`TIMER_CTRL0_ENABLE_R] = timer_ctrl0_enable_q; 310 | end 311 | `TIMER_CMP0: 312 | begin 313 | data_r[`TIMER_CMP0_VALUE_R] = timer_cmp0_value_q; 314 | end 315 | `TIMER_VAL0: 316 | begin 317 | data_r[`TIMER_VAL0_CURRENT_R] = timer_val0_current_in_w; 318 | end 319 | `TIMER_CTRL1: 320 | begin 321 | data_r[`TIMER_CTRL1_INTERRUPT_R] = timer_ctrl1_interrupt_q; 322 | data_r[`TIMER_CTRL1_ENABLE_R] = timer_ctrl1_enable_q; 323 | end 324 | `TIMER_CMP1: 325 | begin 326 | data_r[`TIMER_CMP1_VALUE_R] = timer_cmp1_value_q; 327 | end 328 | `TIMER_VAL1: 329 | begin 330 | data_r[`TIMER_VAL1_CURRENT_R] = timer_val1_current_in_w; 331 | end 332 | default : 333 | data_r = 32'b0; 334 | endcase 335 | end 336 | 337 | //----------------------------------------------------------------- 338 | // RVALID 339 | //----------------------------------------------------------------- 340 | reg rvalid_q; 341 | 342 | always @ (posedge clk_i or posedge rst_i) 343 | if (rst_i) 344 | rvalid_q <= 1'b0; 345 | else if (read_en_w) 346 | rvalid_q <= 1'b1; 347 | else if (cfg_rready_i) 348 | rvalid_q <= 1'b0; 349 | 350 | assign cfg_rvalid_o = rvalid_q; 351 | 352 | //----------------------------------------------------------------- 353 | // Retime read response 354 | //----------------------------------------------------------------- 355 | reg [31:0] rd_data_q; 356 | 357 | always @ (posedge clk_i or posedge rst_i) 358 | if (rst_i) 359 | rd_data_q <= 32'b0; 360 | else if (!cfg_rvalid_o || cfg_rready_i) 361 | rd_data_q <= data_r; 362 | 363 | assign cfg_rdata_o = rd_data_q; 364 | assign cfg_rresp_o = 2'b0; 365 | 366 | //----------------------------------------------------------------- 367 | // BVALID 368 | //----------------------------------------------------------------- 369 | reg bvalid_q; 370 | 371 | always @ (posedge clk_i or posedge rst_i) 372 | if (rst_i) 373 | bvalid_q <= 1'b0; 374 | else if (write_en_w) 375 | bvalid_q <= 1'b1; 376 | else if (cfg_bready_i) 377 | bvalid_q <= 1'b0; 378 | 379 | assign cfg_bvalid_o = bvalid_q; 380 | assign cfg_bresp_o = 2'b0; 381 | 382 | 383 | wire timer_val0_wr_req_w = timer_val0_wr_q; 384 | wire timer_val1_wr_req_w = timer_val1_wr_q; 385 | 386 | //----------------------------------------------------------------- 387 | // Timer0 388 | //----------------------------------------------------------------- 389 | reg [31:0] timer0_value_q; 390 | 391 | always @ (posedge clk_i or posedge rst_i) 392 | if (rst_i) 393 | timer0_value_q <= 32'b0; 394 | else if (timer_val0_wr_req_w) 395 | timer0_value_q <= timer_val0_current_out_w; 396 | else if (timer_ctrl0_enable_out_w) 397 | timer0_value_q <= timer0_value_q + 32'd1; 398 | 399 | assign timer_val0_current_in_w = timer0_value_q; 400 | 401 | wire timer0_irq_w = (timer_val0_current_in_w == timer_cmp0_value_out_w) && timer_ctrl0_interrupt_out_w && timer_ctrl0_enable_out_w; 402 | 403 | //----------------------------------------------------------------- 404 | // Timer1 405 | //----------------------------------------------------------------- 406 | reg [31:0] timer1_value_q; 407 | 408 | always @ (posedge clk_i or posedge rst_i) 409 | if (rst_i) 410 | timer1_value_q <= 32'b0; 411 | else if (timer_val1_wr_req_w) 412 | timer1_value_q <= timer_val1_current_out_w; 413 | else if (timer_ctrl1_enable_out_w) 414 | timer1_value_q <= timer1_value_q + 32'd1; 415 | 416 | assign timer_val1_current_in_w = timer1_value_q; 417 | 418 | wire timer1_irq_w = (timer_val1_current_in_w == timer_cmp1_value_out_w) && timer_ctrl1_interrupt_out_w && timer_ctrl1_enable_out_w; 419 | 420 | 421 | //----------------------------------------------------------------- 422 | // IRQ output 423 | //----------------------------------------------------------------- 424 | reg intr_q; 425 | 426 | always @ (posedge clk_i or posedge rst_i) 427 | if (rst_i) 428 | intr_q <= 1'b0; 429 | else if (1'b0 430 | | timer0_irq_w 431 | | timer1_irq_w 432 | ) 433 | intr_q <= 1'b1; 434 | else 435 | intr_q <= 1'b0; 436 | 437 | //----------------------------------------------------------------- 438 | // Assignments 439 | //----------------------------------------------------------------- 440 | assign intr_o = intr_q; 441 | 442 | 443 | 444 | endmodule 445 | -------------------------------------------------------------------------------- /src_v/timer_defs.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // Basic Peripheral SoC 3 | // V1.1 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2020 6 | // 7 | // Email: admin@ultra-embedded.com 8 | // 9 | // License: GPL 10 | // If you would like a version with a more permissive license for 11 | // use in closed source commercial applications please contact me 12 | // for details. 13 | //----------------------------------------------------------------- 14 | // 15 | // This file is open source HDL; you can redistribute it and/or 16 | // modify it under the terms of the GNU General Public License as 17 | // published by the Free Software Foundation; either version 2 of 18 | // the License, or (at your option) any later version. 19 | // 20 | // This file is distributed in the hope that it will be useful, 21 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | // GNU General Public License for more details. 24 | // 25 | // You should have received a copy of the GNU General Public 26 | // License along with this file; if not, write to the Free Software 27 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 28 | // USA 29 | //----------------------------------------------------------------- 30 | 31 | //----------------------------------------------------------------- 32 | // Generated File 33 | //----------------------------------------------------------------- 34 | 35 | `define TIMER_CTRL0 8'h8 36 | 37 | `define TIMER_CTRL0_INTERRUPT 1 38 | `define TIMER_CTRL0_INTERRUPT_DEFAULT 0 39 | `define TIMER_CTRL0_INTERRUPT_B 1 40 | `define TIMER_CTRL0_INTERRUPT_T 1 41 | `define TIMER_CTRL0_INTERRUPT_W 1 42 | `define TIMER_CTRL0_INTERRUPT_R 1:1 43 | 44 | `define TIMER_CTRL0_ENABLE 2 45 | `define TIMER_CTRL0_ENABLE_DEFAULT 0 46 | `define TIMER_CTRL0_ENABLE_B 2 47 | `define TIMER_CTRL0_ENABLE_T 2 48 | `define TIMER_CTRL0_ENABLE_W 1 49 | `define TIMER_CTRL0_ENABLE_R 2:2 50 | 51 | `define TIMER_CMP0 8'hc 52 | 53 | `define TIMER_CMP0_VALUE_DEFAULT 0 54 | `define TIMER_CMP0_VALUE_B 0 55 | `define TIMER_CMP0_VALUE_T 31 56 | `define TIMER_CMP0_VALUE_W 32 57 | `define TIMER_CMP0_VALUE_R 31:0 58 | 59 | `define TIMER_VAL0 8'h10 60 | 61 | `define TIMER_VAL0_CURRENT_DEFAULT 0 62 | `define TIMER_VAL0_CURRENT_B 0 63 | `define TIMER_VAL0_CURRENT_T 31 64 | `define TIMER_VAL0_CURRENT_W 32 65 | `define TIMER_VAL0_CURRENT_R 31:0 66 | 67 | `define TIMER_CTRL1 8'h14 68 | 69 | `define TIMER_CTRL1_INTERRUPT 1 70 | `define TIMER_CTRL1_INTERRUPT_DEFAULT 0 71 | `define TIMER_CTRL1_INTERRUPT_B 1 72 | `define TIMER_CTRL1_INTERRUPT_T 1 73 | `define TIMER_CTRL1_INTERRUPT_W 1 74 | `define TIMER_CTRL1_INTERRUPT_R 1:1 75 | 76 | `define TIMER_CTRL1_ENABLE 2 77 | `define TIMER_CTRL1_ENABLE_DEFAULT 0 78 | `define TIMER_CTRL1_ENABLE_B 2 79 | `define TIMER_CTRL1_ENABLE_T 2 80 | `define TIMER_CTRL1_ENABLE_W 1 81 | `define TIMER_CTRL1_ENABLE_R 2:2 82 | 83 | `define TIMER_CMP1 8'h18 84 | 85 | `define TIMER_CMP1_VALUE_DEFAULT 0 86 | `define TIMER_CMP1_VALUE_B 0 87 | `define TIMER_CMP1_VALUE_T 31 88 | `define TIMER_CMP1_VALUE_W 32 89 | `define TIMER_CMP1_VALUE_R 31:0 90 | 91 | `define TIMER_VAL1 8'h1c 92 | 93 | `define TIMER_VAL1_CURRENT_DEFAULT 0 94 | `define TIMER_VAL1_CURRENT_B 0 95 | `define TIMER_VAL1_CURRENT_T 31 96 | `define TIMER_VAL1_CURRENT_W 32 97 | `define TIMER_VAL1_CURRENT_R 31:0 98 | 99 | -------------------------------------------------------------------------------- /src_v/uart_lite.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // Basic Peripheral SoC 3 | // V1.1 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2020 6 | // 7 | // Email: admin@ultra-embedded.com 8 | // 9 | // License: GPL 10 | // If you would like a version with a more permissive license for 11 | // use in closed source commercial applications please contact me 12 | // for details. 13 | //----------------------------------------------------------------- 14 | // 15 | // This file is open source HDL; you can redistribute it and/or 16 | // modify it under the terms of the GNU General Public License as 17 | // published by the Free Software Foundation; either version 2 of 18 | // the License, or (at your option) any later version. 19 | // 20 | // This file is distributed in the hope that it will be useful, 21 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | // GNU General Public License for more details. 24 | // 25 | // You should have received a copy of the GNU General Public 26 | // License along with this file; if not, write to the Free Software 27 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 28 | // USA 29 | //----------------------------------------------------------------- 30 | 31 | //----------------------------------------------------------------- 32 | // Generated File 33 | //----------------------------------------------------------------- 34 | 35 | `include "uart_lite_defs.v" 36 | 37 | //----------------------------------------------------------------- 38 | // Module: UART (uartlite compatable) 39 | //----------------------------------------------------------------- 40 | module uart_lite 41 | //----------------------------------------------------------------- 42 | // Params 43 | //----------------------------------------------------------------- 44 | #( 45 | parameter CLK_FREQ = 1843200 46 | ,parameter BAUDRATE = 115200 47 | ) 48 | //----------------------------------------------------------------- 49 | // Ports 50 | //----------------------------------------------------------------- 51 | ( 52 | // Inputs 53 | input clk_i 54 | ,input rst_i 55 | ,input cfg_awvalid_i 56 | ,input [31:0] cfg_awaddr_i 57 | ,input cfg_wvalid_i 58 | ,input [31:0] cfg_wdata_i 59 | ,input [3:0] cfg_wstrb_i 60 | ,input cfg_bready_i 61 | ,input cfg_arvalid_i 62 | ,input [31:0] cfg_araddr_i 63 | ,input cfg_rready_i 64 | ,input rx_i 65 | 66 | // Outputs 67 | ,output cfg_awready_o 68 | ,output cfg_wready_o 69 | ,output cfg_bvalid_o 70 | ,output [1:0] cfg_bresp_o 71 | ,output cfg_arready_o 72 | ,output cfg_rvalid_o 73 | ,output [31:0] cfg_rdata_o 74 | ,output [1:0] cfg_rresp_o 75 | ,output tx_o 76 | ,output intr_o 77 | ); 78 | 79 | //----------------------------------------------------------------- 80 | // Write address / data split 81 | //----------------------------------------------------------------- 82 | // Address but no data ready 83 | reg awvalid_q; 84 | 85 | // Data but no data ready 86 | reg wvalid_q; 87 | 88 | wire wr_cmd_accepted_w = (cfg_awvalid_i && cfg_awready_o) || awvalid_q; 89 | wire wr_data_accepted_w = (cfg_wvalid_i && cfg_wready_o) || wvalid_q; 90 | 91 | always @ (posedge clk_i or posedge rst_i) 92 | if (rst_i) 93 | awvalid_q <= 1'b0; 94 | else if (cfg_awvalid_i && cfg_awready_o && !wr_data_accepted_w) 95 | awvalid_q <= 1'b1; 96 | else if (wr_data_accepted_w) 97 | awvalid_q <= 1'b0; 98 | 99 | always @ (posedge clk_i or posedge rst_i) 100 | if (rst_i) 101 | wvalid_q <= 1'b0; 102 | else if (cfg_wvalid_i && cfg_wready_o && !wr_cmd_accepted_w) 103 | wvalid_q <= 1'b1; 104 | else if (wr_cmd_accepted_w) 105 | wvalid_q <= 1'b0; 106 | 107 | //----------------------------------------------------------------- 108 | // Capture address (for delayed data) 109 | //----------------------------------------------------------------- 110 | reg [7:0] wr_addr_q; 111 | 112 | always @ (posedge clk_i or posedge rst_i) 113 | if (rst_i) 114 | wr_addr_q <= 8'b0; 115 | else if (cfg_awvalid_i && cfg_awready_o) 116 | wr_addr_q <= cfg_awaddr_i[7:0]; 117 | 118 | wire [7:0] wr_addr_w = awvalid_q ? wr_addr_q : cfg_awaddr_i[7:0]; 119 | 120 | //----------------------------------------------------------------- 121 | // Retime write data 122 | //----------------------------------------------------------------- 123 | reg [31:0] wr_data_q; 124 | 125 | always @ (posedge clk_i or posedge rst_i) 126 | if (rst_i) 127 | wr_data_q <= 32'b0; 128 | else if (cfg_wvalid_i && cfg_wready_o) 129 | wr_data_q <= cfg_wdata_i; 130 | 131 | //----------------------------------------------------------------- 132 | // Request Logic 133 | //----------------------------------------------------------------- 134 | wire read_en_w = cfg_arvalid_i & cfg_arready_o; 135 | wire write_en_w = wr_cmd_accepted_w && wr_data_accepted_w; 136 | 137 | //----------------------------------------------------------------- 138 | // Accept Logic 139 | //----------------------------------------------------------------- 140 | assign cfg_arready_o = ~cfg_rvalid_o; 141 | assign cfg_awready_o = ~cfg_bvalid_o && ~cfg_arvalid_i && ~awvalid_q; 142 | assign cfg_wready_o = ~cfg_bvalid_o && ~cfg_arvalid_i && ~wvalid_q; 143 | 144 | 145 | //----------------------------------------------------------------- 146 | // Register ulite_rx 147 | //----------------------------------------------------------------- 148 | reg ulite_rx_wr_q; 149 | 150 | always @ (posedge clk_i or posedge rst_i) 151 | if (rst_i) 152 | ulite_rx_wr_q <= 1'b0; 153 | else if (write_en_w && (wr_addr_w[7:0] == `ULITE_RX)) 154 | ulite_rx_wr_q <= 1'b1; 155 | else 156 | ulite_rx_wr_q <= 1'b0; 157 | 158 | 159 | //----------------------------------------------------------------- 160 | // Register ulite_tx 161 | //----------------------------------------------------------------- 162 | reg ulite_tx_wr_q; 163 | 164 | always @ (posedge clk_i or posedge rst_i) 165 | if (rst_i) 166 | ulite_tx_wr_q <= 1'b0; 167 | else if (write_en_w && (wr_addr_w[7:0] == `ULITE_TX)) 168 | ulite_tx_wr_q <= 1'b1; 169 | else 170 | ulite_tx_wr_q <= 1'b0; 171 | 172 | // ulite_tx_data [external] 173 | wire [7:0] ulite_tx_data_out_w = wr_data_q[`ULITE_TX_DATA_R]; 174 | 175 | 176 | //----------------------------------------------------------------- 177 | // Register ulite_status 178 | //----------------------------------------------------------------- 179 | reg ulite_status_wr_q; 180 | 181 | always @ (posedge clk_i or posedge rst_i) 182 | if (rst_i) 183 | ulite_status_wr_q <= 1'b0; 184 | else if (write_en_w && (wr_addr_w[7:0] == `ULITE_STATUS)) 185 | ulite_status_wr_q <= 1'b1; 186 | else 187 | ulite_status_wr_q <= 1'b0; 188 | 189 | 190 | 191 | 192 | 193 | 194 | //----------------------------------------------------------------- 195 | // Register ulite_control 196 | //----------------------------------------------------------------- 197 | reg ulite_control_wr_q; 198 | 199 | always @ (posedge clk_i or posedge rst_i) 200 | if (rst_i) 201 | ulite_control_wr_q <= 1'b0; 202 | else if (write_en_w && (wr_addr_w[7:0] == `ULITE_CONTROL)) 203 | ulite_control_wr_q <= 1'b1; 204 | else 205 | ulite_control_wr_q <= 1'b0; 206 | 207 | // ulite_control_ie [internal] 208 | reg ulite_control_ie_q; 209 | 210 | always @ (posedge clk_i or posedge rst_i) 211 | if (rst_i) 212 | ulite_control_ie_q <= 1'd`ULITE_CONTROL_IE_DEFAULT; 213 | else if (write_en_w && (wr_addr_w[7:0] == `ULITE_CONTROL)) 214 | ulite_control_ie_q <= cfg_wdata_i[`ULITE_CONTROL_IE_R]; 215 | 216 | wire ulite_control_ie_out_w = ulite_control_ie_q; 217 | 218 | 219 | // ulite_control_rst_rx [auto_clr] 220 | reg ulite_control_rst_rx_q; 221 | 222 | always @ (posedge clk_i or posedge rst_i) 223 | if (rst_i) 224 | ulite_control_rst_rx_q <= 1'd`ULITE_CONTROL_RST_RX_DEFAULT; 225 | else if (write_en_w && (wr_addr_w[7:0] == `ULITE_CONTROL)) 226 | ulite_control_rst_rx_q <= cfg_wdata_i[`ULITE_CONTROL_RST_RX_R]; 227 | else 228 | ulite_control_rst_rx_q <= 1'd`ULITE_CONTROL_RST_RX_DEFAULT; 229 | 230 | wire ulite_control_rst_rx_out_w = ulite_control_rst_rx_q; 231 | 232 | 233 | // ulite_control_rst_tx [auto_clr] 234 | reg ulite_control_rst_tx_q; 235 | 236 | always @ (posedge clk_i or posedge rst_i) 237 | if (rst_i) 238 | ulite_control_rst_tx_q <= 1'd`ULITE_CONTROL_RST_TX_DEFAULT; 239 | else if (write_en_w && (wr_addr_w[7:0] == `ULITE_CONTROL)) 240 | ulite_control_rst_tx_q <= cfg_wdata_i[`ULITE_CONTROL_RST_TX_R]; 241 | else 242 | ulite_control_rst_tx_q <= 1'd`ULITE_CONTROL_RST_TX_DEFAULT; 243 | 244 | wire ulite_control_rst_tx_out_w = ulite_control_rst_tx_q; 245 | 246 | 247 | wire [7:0] ulite_rx_data_in_w; 248 | wire ulite_status_ie_in_w; 249 | wire ulite_status_txfull_in_w; 250 | wire ulite_status_txempty_in_w; 251 | wire ulite_status_rxfull_in_w; 252 | wire ulite_status_rxvalid_in_w; 253 | 254 | 255 | //----------------------------------------------------------------- 256 | // Read mux 257 | //----------------------------------------------------------------- 258 | reg [31:0] data_r; 259 | 260 | always @ * 261 | begin 262 | data_r = 32'b0; 263 | 264 | case (cfg_araddr_i[7:0]) 265 | 266 | `ULITE_RX: 267 | begin 268 | data_r[`ULITE_RX_DATA_R] = ulite_rx_data_in_w; 269 | end 270 | `ULITE_STATUS: 271 | begin 272 | data_r[`ULITE_STATUS_IE_R] = ulite_status_ie_in_w; 273 | data_r[`ULITE_STATUS_TXFULL_R] = ulite_status_txfull_in_w; 274 | data_r[`ULITE_STATUS_TXEMPTY_R] = ulite_status_txempty_in_w; 275 | data_r[`ULITE_STATUS_RXFULL_R] = ulite_status_rxfull_in_w; 276 | data_r[`ULITE_STATUS_RXVALID_R] = ulite_status_rxvalid_in_w; 277 | end 278 | `ULITE_CONTROL: 279 | begin 280 | data_r[`ULITE_CONTROL_IE_R] = ulite_control_ie_q; 281 | end 282 | default : 283 | data_r = 32'b0; 284 | endcase 285 | end 286 | 287 | //----------------------------------------------------------------- 288 | // RVALID 289 | //----------------------------------------------------------------- 290 | reg rvalid_q; 291 | 292 | always @ (posedge clk_i or posedge rst_i) 293 | if (rst_i) 294 | rvalid_q <= 1'b0; 295 | else if (read_en_w) 296 | rvalid_q <= 1'b1; 297 | else if (cfg_rready_i) 298 | rvalid_q <= 1'b0; 299 | 300 | assign cfg_rvalid_o = rvalid_q; 301 | 302 | //----------------------------------------------------------------- 303 | // Retime read response 304 | //----------------------------------------------------------------- 305 | reg [31:0] rd_data_q; 306 | 307 | always @ (posedge clk_i or posedge rst_i) 308 | if (rst_i) 309 | rd_data_q <= 32'b0; 310 | else if (!cfg_rvalid_o || cfg_rready_i) 311 | rd_data_q <= data_r; 312 | 313 | assign cfg_rdata_o = rd_data_q; 314 | assign cfg_rresp_o = 2'b0; 315 | 316 | //----------------------------------------------------------------- 317 | // BVALID 318 | //----------------------------------------------------------------- 319 | reg bvalid_q; 320 | 321 | always @ (posedge clk_i or posedge rst_i) 322 | if (rst_i) 323 | bvalid_q <= 1'b0; 324 | else if (write_en_w) 325 | bvalid_q <= 1'b1; 326 | else if (cfg_bready_i) 327 | bvalid_q <= 1'b0; 328 | 329 | assign cfg_bvalid_o = bvalid_q; 330 | assign cfg_bresp_o = 2'b0; 331 | 332 | wire ulite_rx_rd_req_w = read_en_w & (cfg_araddr_i[7:0] == `ULITE_RX); 333 | 334 | wire ulite_rx_wr_req_w = ulite_rx_wr_q; 335 | wire ulite_tx_wr_req_w = ulite_tx_wr_q; 336 | 337 | //----------------------------------------------------------------- 338 | // Registers 339 | //----------------------------------------------------------------- 340 | 341 | // Configuration 342 | localparam STOP_BITS = 1'b0; // 0 = 1, 1 = 2 343 | localparam BIT_DIV = (CLK_FREQ / BAUDRATE) - 1; 344 | 345 | localparam START_BIT = 4'd0; 346 | localparam STOP_BIT0 = 4'd9; 347 | localparam STOP_BIT1 = 4'd10; 348 | 349 | // Xilinx placement pragmas: 350 | //synthesis attribute IOB of txd_q is "TRUE" 351 | 352 | // TX Signals 353 | reg tx_busy_q; 354 | reg [3:0] tx_bits_q; 355 | reg [31:0] tx_count_q; 356 | reg [7:0] tx_shift_reg_q; 357 | reg txd_q; 358 | 359 | // RX Signals 360 | reg rxd_q; 361 | reg [7:0] rx_data_q; 362 | reg [3:0] rx_bits_q; 363 | reg [31:0] rx_count_q; 364 | reg [7:0] rx_shift_reg_q; 365 | reg rx_ready_q; 366 | reg rx_busy_q; 367 | 368 | reg rx_err_q; 369 | 370 | //----------------------------------------------------------------- 371 | // Re-sync RXD 372 | //----------------------------------------------------------------- 373 | reg rxd_ms_q; 374 | 375 | always @ (posedge clk_i or posedge rst_i) 376 | if (rst_i) 377 | begin 378 | rxd_ms_q <= 1'b1; 379 | rxd_q <= 1'b1; 380 | end 381 | else 382 | begin 383 | rxd_ms_q <= rx_i; 384 | rxd_q <= rxd_ms_q; 385 | end 386 | 387 | //----------------------------------------------------------------- 388 | // RX Clock Divider 389 | //----------------------------------------------------------------- 390 | wire rx_sample_w = (rx_count_q == 32'b0); 391 | 392 | always @ (posedge clk_i or posedge rst_i) 393 | if (rst_i) 394 | rx_count_q <= 32'b0; 395 | else 396 | begin 397 | // Inactive 398 | if (!rx_busy_q) 399 | rx_count_q <= {1'b0, BIT_DIV[31:1]}; 400 | // Rx bit timer 401 | else if (rx_count_q != 0) 402 | rx_count_q <= (rx_count_q - 1); 403 | // Active 404 | else if (rx_sample_w) 405 | begin 406 | // Last bit? 407 | if ((rx_bits_q == STOP_BIT0 && !STOP_BITS) || (rx_bits_q == STOP_BIT1 && STOP_BITS)) 408 | rx_count_q <= 32'b0; 409 | else 410 | rx_count_q <= BIT_DIV; 411 | end 412 | end 413 | 414 | //----------------------------------------------------------------- 415 | // RX Shift Register 416 | //----------------------------------------------------------------- 417 | always @ (posedge clk_i or posedge rst_i) 418 | if (rst_i) 419 | begin 420 | rx_shift_reg_q <= 8'h00; 421 | rx_busy_q <= 1'b0; 422 | end 423 | // Rx busy 424 | else if (rx_busy_q && rx_sample_w) 425 | begin 426 | // Last bit? 427 | if (rx_bits_q == STOP_BIT0 && !STOP_BITS) 428 | rx_busy_q <= 1'b0; 429 | else if (rx_bits_q == STOP_BIT1 && STOP_BITS) 430 | rx_busy_q <= 1'b0; 431 | else if (rx_bits_q == START_BIT) 432 | begin 433 | // Start bit should still be low as sampling mid 434 | // way through start bit, so if high, error! 435 | if (rxd_q) 436 | rx_busy_q <= 1'b0; 437 | end 438 | // Rx shift register 439 | else 440 | rx_shift_reg_q <= {rxd_q, rx_shift_reg_q[7:1]}; 441 | end 442 | // Start bit? 443 | else if (!rx_busy_q && rxd_q == 1'b0) 444 | begin 445 | rx_shift_reg_q <= 8'h00; 446 | rx_busy_q <= 1'b1; 447 | end 448 | 449 | always @ (posedge clk_i or posedge rst_i) 450 | if (rst_i) 451 | rx_bits_q <= START_BIT; 452 | else if (rx_sample_w && rx_busy_q) 453 | begin 454 | if ((rx_bits_q == STOP_BIT1 && STOP_BITS) || (rx_bits_q == STOP_BIT0 && !STOP_BITS)) 455 | rx_bits_q <= START_BIT; 456 | else 457 | rx_bits_q <= rx_bits_q + 4'd1; 458 | end 459 | else if (!rx_busy_q && (BIT_DIV == 32'b0)) 460 | rx_bits_q <= START_BIT + 4'd1; 461 | else if (!rx_busy_q) 462 | rx_bits_q <= START_BIT; 463 | 464 | //----------------------------------------------------------------- 465 | // RX Data 466 | //----------------------------------------------------------------- 467 | always @ (posedge clk_i or posedge rst_i) 468 | if (rst_i) 469 | begin 470 | rx_ready_q <= 1'b0; 471 | rx_data_q <= 8'h00; 472 | rx_err_q <= 1'b0; 473 | end 474 | else 475 | begin 476 | // If reading data, reset data state 477 | if (ulite_rx_rd_req_w || ulite_control_rst_rx_out_w) 478 | begin 479 | rx_ready_q <= 1'b0; 480 | rx_err_q <= 1'b0; 481 | end 482 | 483 | if (rx_busy_q && rx_sample_w) 484 | begin 485 | // Stop bit 486 | if ((rx_bits_q == STOP_BIT1 && STOP_BITS) || (rx_bits_q == STOP_BIT0 && !STOP_BITS)) 487 | begin 488 | // RXD should be still high 489 | if (rxd_q) 490 | begin 491 | rx_data_q <= rx_shift_reg_q; 492 | rx_ready_q <= 1'b1; 493 | end 494 | // Bad Stop bit - wait for a full bit period 495 | // before allowing start bit detection again 496 | else 497 | begin 498 | rx_ready_q <= 1'b0; 499 | rx_data_q <= 8'h00; 500 | rx_err_q <= 1'b1; 501 | end 502 | end 503 | // Mid start bit sample - if high then error 504 | else if (rx_bits_q == START_BIT && rxd_q) 505 | rx_err_q <= 1'b1; 506 | end 507 | end 508 | 509 | assign ulite_rx_data_in_w = rx_data_q; 510 | assign ulite_status_rxvalid_in_w = rx_ready_q; 511 | assign ulite_status_rxfull_in_w = rx_ready_q; 512 | 513 | //----------------------------------------------------------------- 514 | // TX Clock Divider 515 | //----------------------------------------------------------------- 516 | wire tx_sample_w = (tx_count_q == 32'b0); 517 | 518 | always @ (posedge clk_i or posedge rst_i) 519 | if (rst_i) 520 | tx_count_q <= 32'b0; 521 | else 522 | begin 523 | // Idle 524 | if (!tx_busy_q) 525 | tx_count_q <= BIT_DIV; 526 | // Tx bit timer 527 | else if (tx_count_q != 0) 528 | tx_count_q <= (tx_count_q - 1); 529 | else if (tx_sample_w) 530 | tx_count_q <= BIT_DIV; 531 | end 532 | 533 | //----------------------------------------------------------------- 534 | // TX Shift Register 535 | //----------------------------------------------------------------- 536 | reg tx_complete_q; 537 | 538 | always @ (posedge clk_i or posedge rst_i) 539 | if (rst_i) 540 | begin 541 | tx_shift_reg_q <= 8'h00; 542 | tx_busy_q <= 1'b0; 543 | tx_complete_q <= 1'b0; 544 | end 545 | // Tx busy 546 | else if (tx_busy_q) 547 | begin 548 | // Shift tx data 549 | if (tx_bits_q != START_BIT && tx_sample_w) 550 | tx_shift_reg_q <= {1'b0, tx_shift_reg_q[7:1]}; 551 | 552 | // Last bit? 553 | if (tx_bits_q == STOP_BIT0 && tx_sample_w && !STOP_BITS) 554 | begin 555 | tx_busy_q <= 1'b0; 556 | tx_complete_q <= 1'b1; 557 | end 558 | else if (tx_bits_q == STOP_BIT1 && tx_sample_w && STOP_BITS) 559 | begin 560 | tx_busy_q <= 1'b0; 561 | tx_complete_q <= 1'b1; 562 | end 563 | end 564 | // Buffer data to transmit 565 | else if (ulite_tx_wr_req_w) 566 | begin 567 | tx_shift_reg_q <= ulite_tx_data_out_w; 568 | tx_busy_q <= 1'b1; 569 | tx_complete_q <= 1'b0; 570 | end 571 | else 572 | tx_complete_q <= 1'b0; 573 | 574 | assign ulite_status_txfull_in_w = tx_busy_q; 575 | assign ulite_status_txempty_in_w = ~tx_busy_q; 576 | 577 | always @ (posedge clk_i or posedge rst_i) 578 | if (rst_i) 579 | tx_bits_q <= 4'd0; 580 | else if (tx_sample_w && tx_busy_q) 581 | begin 582 | if ((tx_bits_q == STOP_BIT1 && STOP_BITS) || (tx_bits_q == STOP_BIT0 && !STOP_BITS)) 583 | tx_bits_q <= START_BIT; 584 | else 585 | tx_bits_q <= tx_bits_q + 4'd1; 586 | end 587 | 588 | //----------------------------------------------------------------- 589 | // UART Tx Pin 590 | //----------------------------------------------------------------- 591 | reg txd_r; 592 | 593 | always @ * 594 | begin 595 | txd_r = 1'b1; 596 | 597 | if (tx_busy_q) 598 | begin 599 | // Start bit (TXD = L) 600 | if (tx_bits_q == START_BIT) 601 | txd_r = 1'b0; 602 | // Stop bits (TXD = H) 603 | else if (tx_bits_q == STOP_BIT0 || tx_bits_q == STOP_BIT1) 604 | txd_r = 1'b1; 605 | // Data bits 606 | else 607 | txd_r = tx_shift_reg_q[0]; 608 | end 609 | end 610 | 611 | always @ (posedge clk_i or posedge rst_i) 612 | if (rst_i) 613 | txd_q <= 1'b1; 614 | else 615 | txd_q <= txd_r; 616 | 617 | assign tx_o = txd_q; 618 | 619 | //----------------------------------------------------------------- 620 | // Interrupt 621 | //----------------------------------------------------------------- 622 | reg intr_q; 623 | 624 | always @ (posedge clk_i or posedge rst_i) 625 | if (rst_i) 626 | intr_q <= 1'b0; 627 | else if (tx_complete_q) 628 | intr_q <= 1'b1; 629 | else if (ulite_status_rxvalid_in_w) 630 | intr_q <= 1'b1; 631 | else 632 | intr_q <= 1'b0; 633 | 634 | assign ulite_status_ie_in_w = ulite_control_ie_out_w; 635 | 636 | //----------------------------------------------------------------- 637 | // Assignments 638 | //----------------------------------------------------------------- 639 | assign intr_o = intr_q; 640 | 641 | 642 | endmodule 643 | -------------------------------------------------------------------------------- /src_v/uart_lite_defs.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // Basic Peripheral SoC 3 | // V1.1 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2020 6 | // 7 | // Email: admin@ultra-embedded.com 8 | // 9 | // License: GPL 10 | // If you would like a version with a more permissive license for 11 | // use in closed source commercial applications please contact me 12 | // for details. 13 | //----------------------------------------------------------------- 14 | // 15 | // This file is open source HDL; you can redistribute it and/or 16 | // modify it under the terms of the GNU General Public License as 17 | // published by the Free Software Foundation; either version 2 of 18 | // the License, or (at your option) any later version. 19 | // 20 | // This file is distributed in the hope that it will be useful, 21 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | // GNU General Public License for more details. 24 | // 25 | // You should have received a copy of the GNU General Public 26 | // License along with this file; if not, write to the Free Software 27 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 28 | // USA 29 | //----------------------------------------------------------------- 30 | 31 | //----------------------------------------------------------------- 32 | // Generated File 33 | //----------------------------------------------------------------- 34 | 35 | `define ULITE_RX 8'h0 36 | 37 | `define ULITE_RX_DATA_DEFAULT 0 38 | `define ULITE_RX_DATA_B 0 39 | `define ULITE_RX_DATA_T 7 40 | `define ULITE_RX_DATA_W 8 41 | `define ULITE_RX_DATA_R 7:0 42 | 43 | `define ULITE_TX 8'h4 44 | 45 | `define ULITE_TX_DATA_DEFAULT 0 46 | `define ULITE_TX_DATA_B 0 47 | `define ULITE_TX_DATA_T 7 48 | `define ULITE_TX_DATA_W 8 49 | `define ULITE_TX_DATA_R 7:0 50 | 51 | `define ULITE_STATUS 8'h8 52 | 53 | `define ULITE_STATUS_IE 4 54 | `define ULITE_STATUS_IE_DEFAULT 0 55 | `define ULITE_STATUS_IE_B 4 56 | `define ULITE_STATUS_IE_T 4 57 | `define ULITE_STATUS_IE_W 1 58 | `define ULITE_STATUS_IE_R 4:4 59 | 60 | `define ULITE_STATUS_TXFULL 3 61 | `define ULITE_STATUS_TXFULL_DEFAULT 0 62 | `define ULITE_STATUS_TXFULL_B 3 63 | `define ULITE_STATUS_TXFULL_T 3 64 | `define ULITE_STATUS_TXFULL_W 1 65 | `define ULITE_STATUS_TXFULL_R 3:3 66 | 67 | `define ULITE_STATUS_TXEMPTY 2 68 | `define ULITE_STATUS_TXEMPTY_DEFAULT 0 69 | `define ULITE_STATUS_TXEMPTY_B 2 70 | `define ULITE_STATUS_TXEMPTY_T 2 71 | `define ULITE_STATUS_TXEMPTY_W 1 72 | `define ULITE_STATUS_TXEMPTY_R 2:2 73 | 74 | `define ULITE_STATUS_RXFULL 1 75 | `define ULITE_STATUS_RXFULL_DEFAULT 0 76 | `define ULITE_STATUS_RXFULL_B 1 77 | `define ULITE_STATUS_RXFULL_T 1 78 | `define ULITE_STATUS_RXFULL_W 1 79 | `define ULITE_STATUS_RXFULL_R 1:1 80 | 81 | `define ULITE_STATUS_RXVALID 0 82 | `define ULITE_STATUS_RXVALID_DEFAULT 0 83 | `define ULITE_STATUS_RXVALID_B 0 84 | `define ULITE_STATUS_RXVALID_T 0 85 | `define ULITE_STATUS_RXVALID_W 1 86 | `define ULITE_STATUS_RXVALID_R 0:0 87 | 88 | `define ULITE_CONTROL 8'hc 89 | 90 | `define ULITE_CONTROL_IE 4 91 | `define ULITE_CONTROL_IE_DEFAULT 0 92 | `define ULITE_CONTROL_IE_B 4 93 | `define ULITE_CONTROL_IE_T 4 94 | `define ULITE_CONTROL_IE_W 1 95 | `define ULITE_CONTROL_IE_R 4:4 96 | 97 | `define ULITE_CONTROL_RST_RX 1 98 | `define ULITE_CONTROL_RST_RX_DEFAULT 0 99 | `define ULITE_CONTROL_RST_RX_B 1 100 | `define ULITE_CONTROL_RST_RX_T 1 101 | `define ULITE_CONTROL_RST_RX_W 1 102 | `define ULITE_CONTROL_RST_RX_R 1:1 103 | 104 | `define ULITE_CONTROL_RST_TX 0 105 | `define ULITE_CONTROL_RST_TX_DEFAULT 0 106 | `define ULITE_CONTROL_RST_TX_B 0 107 | `define ULITE_CONTROL_RST_TX_T 0 108 | `define ULITE_CONTROL_RST_TX_W 1 109 | `define ULITE_CONTROL_RST_TX_R 0:0 110 | 111 | --------------------------------------------------------------------------------