├── LICENSE ├── README.md ├── crc.v ├── ethernet.v ├── ethernet_top.v ├── hdl ├── crc.v ├── ethernet.v ├── ethernet_top.v ├── udp_receive.v └── udp_send.v ├── udp_receive.v └── udp_send.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 | 千兆以太网芯片RTL8211Verilog程序 2 | ======== 3 | 4 | 本程序由多个verilog文件组成,包括了hdl文件夹里所有的相关文件以及一些必要的IP核。\ 5 | 文件功能介绍\ 6 | `crc.v`:主要在udp发送时使用,计算udp的包的CRC数值。\ 7 | `ethernet.v`:对udp_send.v和udp_receive.v文件的封装。\ 8 | `ethernet_top.v`:整个工程的示例顶层文件,只是展示如何调用文件和其他相关的ip核文件。\ 9 | `udp_receive.v`:负责udp的接收处理过程。\ 10 | `udp_send.v`:负责udp的发送处理过程。 11 | 12 | 文件讲解 13 | ===== 14 | udp_receive.v\ 15 | 端口: 16 | ------ 17 | `clk `:接收模块的主时钟。\ 18 | `rst_n `:接收模块的全局复位信号。\ 19 | `rx_data_len `:接收数据的udp数据包长度,是udp报头的参数。\ 20 | `rx_total_len `:接收数据的ip数据包长度,是ip数据报头的参数。\ 21 | `update `:当接收到新的udp数据包时,该值会拉高一周期。\ 22 | `ip_header `:接收的整个IP数据包头,仅支持160位的IP数据报头。\ 23 | `udp_header `:接收的整个UDP数据报头,仅支持64位的UDP数据报头。\ 24 | `mac `: 接收的整个MAC数据包,包括目的MAC,源MAC和IP包类型标识。\ 25 | `data_o `:接收的有效数据。\ 26 | `src_mac `:数据包的源MAC地址。\ 27 | `src_addr `:数据包的源IP地址。\ 28 | `src_port `:数据包的源端口地址。\ 29 | `DF `:IP数据包的参数,为0代表数据包可分片,为1代表不可分片。\ 30 | `MF `:IP数据包的参数,为1代表还有分片,为0代表这是最后一片。\ 31 | `e_rxdv `:RTL8211的控制IO,当为高时代表接收数据有效。\ 32 | `rxd `:RTL8211的接收数据IO。 33 | 34 | 常数定义: 35 | ------- 36 | `CAN_RECEIVE_BROADCAST`:是否支持接收广播数据包,也就是MAC地址为FFFFFFFFFFFF的数据包。\ 37 | `DST_ADDR`:设置目的地址的IP地址,也就是RTL8211的网卡地址。\ 38 | `DST_PORT`:设置目的地址的端口地址,也就是RTL8211的端口。\ 39 | `DST_MAC`:设置目的地址的MAC地址,也就是RTL8211的MAC地址。 40 | 41 | 状态机状态跳转设置: 42 | -------- 43 | `IDLE`:空闲状态,只要接收到前导码,就进入R_PRE状态。\ 44 | `R_PRE`:接收前导码,接收到7个前导码和一个开始位数据后,进入R_MAC状态。\ 45 | `R_MAC`:接收MAC数据状态,接收完毕后进入R_HEADER状态。\ 46 | `R_HEADER`:接收IP数据报头和UDP数据报头,接收完毕进入R_DATA状态。\ 47 | `R_DATA`:接收UDP有效数据,接收完毕后进入R_FINISH。\ 48 | `R_FINISH`:返回IDLE状态。 49 | 50 | udp_send.v\ 51 | 端口: 52 | ------ 53 | `clk`,`rst_n`信号如上;\ 54 | `data_i`:需要发送出去的数据,在tx_dv为高时将需要发送的数据通过该端口传输到UDP数据包。\ 55 | `tx_data_len`:发送的数据长度,UDP数据包的参数。\ 56 | `crc`:整个以太网数据包的CRC校验码,留作数据校验使用。\ 57 | `crcen`:crc模块的使能信号,为高crc校验模块才可以计算。\ 58 | `crcrst`:crc模块的复位信号,为高crc检验模块复位。\ 59 | `start`:UDP发送模块的开始信号,为高驱动模块开始组帧发送。\ 60 | `busy`:UDP发送模块的忙碌信号,当模块正在组帧发送的过程中时该信号拉高。\ 61 | `tx_dv`:UDP发送模块的指示信号,告知当前UDP模块已经可以将数据发送出去,请将需要发送的数据发过来。\ 62 | `dst_mac`:目的地址的MAC地址。\ 63 | `dst_addr`:目的地址的IP地址。\ 64 | `dst_port`:目的地址的端口地址。\ 65 | `DF`,`MF`如上所述。\ 66 | `tx_en`:RTL8211的发送使能信号,为高发送数据有效。\ 67 | `txer`:RTL8211的发送错误信号。\ 68 | `txd`:RTL8211的发送数据IO。 69 | 70 | 常数定义: 71 | ------ 72 | `IP_HEADER_LEN`:ip数据包的长度,默认就好,不需要改。\ 73 | `TTL`:IP数据包的参数,生存时间。\ 74 | `SRC_ADDR`:源地址的IP地址。\ 75 | `SRC_PORT`:源地址的端口。\ 76 | `SRC_MAC`:源地址的MAC地址。 77 | 78 | 状态机状态跳转设置: 79 | -------- 80 | `IDLE`:空闲状态,start为高进入MAKE_IP状态。\ 81 | `MAKE_IP`:生成IP数据包,进入MAKE_SUM状态。\ 82 | `MAKE_SUM`:计算IP数据包的首部校验和,计算完毕进入SEND_PRE状态。\ 83 | `SEND_PRE`:发送7个前导码和1个开始码。然后进入SEND_MAC状态。\ 84 | `SEND_MAC`:发送目的MAC,源MAC和IP数据包类型,然后进入SEND_HEADER状态。\ 85 | `SEND_HEADER`:发送IP数据报头和UDP数据报头,然后进入SEND_DATA状态。\ 86 | `SEND_DATA`:发送有效数据,发送完毕进入SEND_CRC状态。\ 87 | `SEND_CRC`:发送CRC数据,发送完毕进入IDLE_CODE状态。\ 88 | `IDLE_CODE`:发送12个空闲码,以太网数据包的要求。发送完毕回到IDLE状态 89 | 90 | 91 | 为了满足125Mhz的时序要求,这两个核心部分的代码尽力做了一些修改,比如udp_send中,发送如MAC,数据报头时,都采用了状态机根据计数器的值发送对应位的数据, 92 | 之前曾经试过直接发高八位,然后通过不断地移位将没有发送过得数据移到高八位,但这个方法无法满足125Mhz的时序要求,所以改成了现在这个方式。又比如计算首部检验和, 93 | 将计算的过程分成了几步来计算,也有效的减少了时序违例的总数。\ 94 | 但是即使如此,仍有部分信号不满足时序要求,时序报告会产生负1ns左右的时序路径。 95 | 96 | 97 | 未完待续,等着填坑。。。\ 98 | 填坑文章 \ 99 | [(探索千兆网)1. 认识以太网帧的整个结构](https://zhuanlan.zhihu.com/p/73727894) \ 100 | [(探索千兆网)2. 为保证数字电路时序裕量所做的努力](https://zhuanlan.zhihu.com/p/74874368) 101 | 102 | -------------------------------------------------------------------------------- /crc.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maxs-well/Ethernet-design-verilog/add94655f1cb9a9ee0c1192a19ac425d2ed01c8e/crc.v -------------------------------------------------------------------------------- /ethernet.v: -------------------------------------------------------------------------------- 1 | /** 2 | * @Function: Ethernet Driver Wrapper 3 | * @Date : 2019/07/23 4 | * @Vision : v1.2 5 | * @Note : 6 | * @Author : WoodFan 7 | * @param clk : fpga main clock 8 | * @param rst_n : active low reset signal 9 | * @param e_rxc: receiver clock 10 | * @param e_rxdv: receiver already signal 11 | * @param e_rxer: receiver error signal 12 | * @param e_rxd: receiver data signal 13 | * @param e_txc: transfer clock (100M ethernet) 14 | * @param e_gtxc: transfer clock (1000M ethernet) 15 | * @param e_txen : transfer data enable signal 16 | * @param e_txer : transfer error signal 17 | * @param e_txd: transfer data siganl 18 | * @param e_reset: phy reset signal 19 | * @param e_mdc : phy register clock 20 | * @param e_mdio : phy register IO 21 | * @param data_tx : data need to be sent 22 | * @param data_len_tx: amount of data need to be sent 23 | * @param cvt_tx : active high start transfer work 24 | * @param busy_tx : active high transfer working 25 | * @param dv_tx : active high enter data to be sent in turn 26 | * @param dst_mac : mac address of destination 27 | * @param dst_addr: ip address of destination 28 | * @param dst_port: port of destination 29 | * @param DF_rx : ip packet parameter 30 | * @param MF_tx : ip packet parameter 31 | * @param rx_data_len: amount of receive data 32 | * @param rx_total_len: amount of IP packet 33 | * @param update_rx: active high data update 34 | * @param data_rx: receive data 35 | * @param src_mac : source mac addr 36 | * @param src_addr: source ip addr 37 | * @param src_port: source port addr 38 | * @param DF_rx : ip packet parameter 39 | * @param MF_tx : ip packet parameter 40 | * @param r_ip : total receive IP packet header 41 | * @param r_udp : total receive UDP packet header 42 | * @param r_mac : total receive mac packet 43 | */ 44 | 45 | module ethernet 46 | # 47 | ( 48 | parameter UDP_SEND_OPEN = 1, 49 | parameter UDP_RECEIVE_OPEN = 1, 50 | parameter TTL = 8'd128, 51 | /* 192.168.0.3*/ 52 | parameter TX_SRC_ADDR = 32'hc0a80002, 53 | parameter TX_SRC_PORT = 16'd8000, 54 | parameter TX_SRC_MAC = 48'h000a3501fec0, 55 | 56 | /* 192.168.0.2*/ 57 | parameter RX_CAN_RECEIVE_BROADCAST = 1, 58 | parameter RX_DST_ADDR = 32'hc0a80002, 59 | parameter RX_DST_PORT = 16'd8000, 60 | parameter RX_DST_MAC = 48'h000a3501fec0 61 | ) 62 | ( 63 | /* system signal*/ 64 | input clk , 65 | input rst_n , 66 | /* rx interface */ 67 | input e_rxc , //125Mhz 68 | input e_rxdv , 69 | input e_rxer , 70 | input [7:0] e_rxd , 71 | /* tx interface */ 72 | input e_txc , 73 | output e_gtxc , 74 | output e_txen , 75 | output e_txer , 76 | output [7:0] e_txd , 77 | /* PHY setting interface */ 78 | output e_reset , 79 | output e_mdc , 80 | inout e_mdio , 81 | /* Control signal*/ 82 | /* tx */ 83 | input [7:0] data_tx , 84 | input [15:0] data_len_tx, 85 | input cvt_tx , 86 | output busy_tx , 87 | output dv_tx , 88 | input [47:0] dst_mac , 89 | input [31:0] dst_addr, 90 | input [15:0] dst_port, 91 | input DF_tx , 92 | input MF_tx , 93 | /* rx */ 94 | output [15:0] rx_data_len, 95 | output [15:0] rx_total_len, 96 | output update_rx, 97 | output [7:0] data_rx , 98 | output [47:0] src_mac , 99 | output [31:0] src_addr, 100 | output [15:0] src_port, 101 | output DF_rx , 102 | output MF_rx , 103 | output [159:0] r_ip , 104 | output [63:0] r_udp , 105 | output [111:0] r_mac 106 | ); 107 | 108 | assign e_gtxc = e_rxc; 109 | 110 | //assign e_gtxc = e_rxc; //125Mhz 111 | assign e_reset = 1'b1; 112 | assign e_mdio = 1'bz; 113 | 114 | wire [31:0] crc; 115 | wire crcen; 116 | wire crcrst; 117 | 118 | wire [7:0] txd_r; 119 | 120 | //增大扇出能力 increase fan_out 121 | io_buf io_inst 122 | ( 123 | .datain(txd_r), 124 | .dataout(e_txd) 125 | ); 126 | 127 | generate if (UDP_SEND_OPEN == 1) 128 | begin 129 | udp_send 130 | # 131 | ( 132 | .TTL (TTL) , 133 | .SRC_ADDR (TX_SRC_ADDR) , 134 | .SRC_PORT (TX_SRC_PORT) , 135 | .SRC_MAC (TX_SRC_MAC) 136 | ) 137 | udp_s_inst( 138 | /* system signal*/ 139 | .clk (e_gtxc), 140 | .rst_n (rst_n), 141 | /* user control*/ 142 | .data_i (data_tx), 143 | .tx_data_len(data_len_tx), 144 | .crc (crc), 145 | .crcen (crcen), 146 | .crcrst (crcrst), 147 | 148 | .start (cvt_tx), 149 | .busy (busy_tx), 150 | .tx_dv (dv_tx), 151 | .dst_mac (dst_mac), 152 | .dst_addr (dst_addr), 153 | .dst_port (dst_port), 154 | .DF (DF_tx), 155 | .MF (MF_tx), 156 | /* PHY interface*/ 157 | .tx_en (e_txen), 158 | .txer (e_txer), 159 | //.txd (e_txd) 160 | .txd (txd_r) 161 | ); 162 | 163 | crc crc_inst 164 | ( 165 | .Clk (e_gtxc), 166 | .Reset (crcrst), 167 | .Data_in(e_txd), 168 | .Enable (crcen), 169 | .Crc (crc), 170 | .CrcNext() 171 | ); 172 | end 173 | else 174 | begin 175 | assign e_gtxc = 1'b0; 176 | assign e_txen = 1'b0; 177 | assign e_txer = 1'b0; 178 | assign e_txd = 8'd0; 179 | end 180 | endgenerate 181 | 182 | generate if (UDP_RECEIVE_OPEN == 1) 183 | begin 184 | udp_receive 185 | # 186 | ( 187 | .CAN_RECEIVE_BROADCAST (RX_CAN_RECEIVE_BROADCAST), 188 | .DST_ADDR (RX_DST_ADDR) , 189 | .DST_PORT (RX_DST_PORT) , 190 | .DST_MAC (RX_DST_MAC) 191 | ) 192 | udp_r_inst( 193 | /* system signal*/ 194 | .clk (e_rxc), 195 | .rst_n (rst_n), 196 | /* user control*/ 197 | .rx_data_len(rx_data_len), 198 | .rx_total_len(rx_total_len), 199 | .update (update_rx), 200 | .ip_header (r_ip), 201 | .udp_header (r_udp), 202 | .mac (r_mac), 203 | .data_o (data_rx), 204 | .src_mac (src_mac), 205 | .src_addr (src_addr), 206 | .src_port (src_port), 207 | .DF (DF_rx), 208 | .MF (MF_rx), 209 | /* PHY interface*/ 210 | .e_rxdv (e_rxdv), 211 | .rxd (e_rxd) 212 | ); 213 | end 214 | else 215 | begin 216 | assign rx_data_len = 0; 217 | assign rx_total_len = 0; 218 | assign data_rx = 0; 219 | assign src_mac = 0; 220 | assign src_addr = 0; 221 | assign src_port = 0; 222 | assign r_ip = 0; 223 | assign r_udp = 0; 224 | assign update_rx = 0; 225 | assign DF_rx = 0; 226 | assign MF_rx = 0; 227 | assign r_mac = 0; 228 | end 229 | endgenerate 230 | 231 | 232 | endmodule -------------------------------------------------------------------------------- /ethernet_top.v: -------------------------------------------------------------------------------- 1 | module ethernet_top 2 | ( 3 | /* system signal*/ 4 | input clk , 5 | input rst_n , 6 | /* rx interface */ 7 | input e_rxc , //125Mhz 8 | input e_rxdv , 9 | input e_rxer , 10 | input [7:0] e_rxd , 11 | /* tx interface */ 12 | input e_txc , 13 | output e_gtxc , 14 | output e_txen , 15 | output e_txer , 16 | output [7:0] e_txd , 17 | /* PHY setting interface */ 18 | output e_reset , 19 | output e_mdc , 20 | inout e_mdio 21 | ); 22 | 23 | ethernet 24 | e_inst 25 | ( 26 | /* system signal*/ 27 | .clk (e_rxc), 28 | .rst_n (rst_n), 29 | /* rx interface */ 30 | .e_rxc (e_rxc ), //125Mhz 31 | .e_rxdv (e_rxdv ), 32 | .e_rxer (e_rxer ), 33 | .e_rxd (e_rxd ), 34 | /* tx interface */ 35 | .e_txc (e_txc ), 36 | .e_gtxc (e_gtxc ), 37 | .e_txen (e_txen ), 38 | .e_txer (e_txer ), 39 | .e_txd (e_txd ), 40 | /* PHY setting interface */ 41 | .e_reset(e_reset), 42 | .e_mdc (e_mdc ), 43 | .e_mdio (e_mdio ), 44 | /* Control signal*/ 45 | /* tx */ 46 | .data_tx (8'h66), 47 | .data_len_tx(16'd1000), 48 | .cvt_tx (1'b1), 49 | .busy_tx (), 50 | .dv_tx (), 51 | .dst_mac (48'h305a3aea6538), 52 | .dst_addr (32'hc0a80003), 53 | .dst_port (16'd8080), 54 | .DF_tx (1'b1), 55 | .MF_tx (1'b0), 56 | /* rx */ 57 | .rx_data_len(), 58 | .rx_total_len(), 59 | .update_rx (), 60 | .data_rx (), 61 | .src_mac (), 62 | .src_addr (), 63 | .src_port (), 64 | .DF_rx (), 65 | .MF_rx (), 66 | .r_ip (), 67 | .r_udp (), 68 | .r_mac () 69 | ); 70 | 71 | endmodule -------------------------------------------------------------------------------- /hdl/crc.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maxs-well/Ethernet-design-verilog/add94655f1cb9a9ee0c1192a19ac425d2ed01c8e/hdl/crc.v -------------------------------------------------------------------------------- /hdl/ethernet.v: -------------------------------------------------------------------------------- 1 | /** 2 | * @Function: Ethernet Driver Wrapper 3 | * @Date : 2019/05/28 4 | * @Vision : v1.0 5 | * @Note : 6 | * @Author : WoodFan 7 | * @param clk : fpga main clock 8 | * @param rst_n : active low reset signal 9 | * @param e_rxc: receiver clock 10 | * @param e_rxdv: receiver already signal 11 | * @param e_rxer: receiver error signal 12 | * @param e_rxd: receiver data signal 13 | * @param e_txc: transfer clock (100M ethernet) 14 | * @param e_gtxc: transfer clock (1000M ethernet) 15 | * @param e_txen : transfer data enable signal 16 | * @param e_txer : transfer error signal 17 | * @param e_txd: transfer data siganl 18 | * @param e_reset: phy reset signal 19 | * @param e_mdc : phy register clock 20 | * @param e_mdio : phy register IO 21 | * @param data_tx : data need to be sent 22 | * @param data_len_tx: amount of data need to be sent 23 | * @param cvt_tx : active high start transfer work 24 | * @param busy_tx : active high transfer working 25 | * @param dv_tx : active high enter data to be sent in turn 26 | * @param dst_mac : mac address of destination 27 | * @param dst_addr: ip address of destination 28 | * @param dst_port: port of destination 29 | * @param DF_rx : ip packet parameter 30 | * @param MF_tx : ip packet parameter 31 | * @param rx_data_len: amount of receive data 32 | * @param rx_total_len: amount of IP packet 33 | * @param update_rx: active high data update 34 | * @param data_rx: receive data 35 | * @param src_mac : source mac addr 36 | * @param src_addr: source ip addr 37 | * @param src_port: source port addr 38 | * @param DF_rx : ip packet parameter 39 | * @param MF_tx : ip packet parameter 40 | * @param r_ip : total receive IP packet header 41 | * @param r_udp : total receive UDP packet header 42 | * @param r_mac : total receive mac packet 43 | */ 44 | 45 | module ethernet 46 | # 47 | ( 48 | parameter TTL = 8'd128, 49 | /* 192.168.0.3*/ 50 | parameter TX_SRC_ADDR = 32'hc0a80002, 51 | parameter TX_SRC_PORT = 16'd8000, 52 | parameter TX_SRC_MAC = 48'h000a3501fec0, 53 | 54 | /* 192.168.0.2*/ 55 | parameter RX_CAN_RECEIVE_BROADCAST = 1, 56 | parameter RX_DST_ADDR = 32'hc0a80002, 57 | parameter RX_DST_PORT = 16'd8000, 58 | parameter RX_DST_MAC = 48'h000a3501fec0 59 | ) 60 | ( 61 | /* system signal*/ 62 | input clk , 63 | input rst_n , 64 | /* rx interface */ 65 | input e_rxc , //125Mhz 66 | input e_rxdv , 67 | input e_rxer , 68 | input [7:0] e_rxd , 69 | /* tx interface */ 70 | input e_txc , 71 | output e_gtxc , 72 | output e_txen , 73 | output e_txer , 74 | output [7:0] e_txd , 75 | /* PHY setting interface */ 76 | output e_reset , 77 | output e_mdc , 78 | inout e_mdio , 79 | /* Control signal*/ 80 | /* tx */ 81 | input [7:0] data_tx , 82 | input [15:0] data_len_tx, 83 | input cvt_tx , 84 | output busy_tx , 85 | output dv_tx , 86 | input [47:0] dst_mac , 87 | input [31:0] dst_addr, 88 | input [15:0] dst_port, 89 | input DF_tx , 90 | input MF_tx , 91 | /* rx */ 92 | output [15:0] rx_data_len, 93 | output [15:0] rx_total_len, 94 | output update_rx, 95 | output [7:0] data_rx , 96 | output [47:0] src_mac , 97 | output [31:0] src_addr, 98 | output [15:0] src_port, 99 | output DF_rx , 100 | output MF_rx , 101 | output [159:0] r_ip , 102 | output [63:0] r_udp , 103 | output [111:0] r_mac 104 | ); 105 | 106 | global g_inst( 107 | .in(e_rxc), 108 | .out(e_gtxc) 109 | ); 110 | 111 | //assign e_gtxc = e_rxc; //125Mhz 112 | assign e_reset = 1'b1; 113 | assign e_mdio = 1'bz; 114 | 115 | wire [31:0] crc; 116 | wire crcen; 117 | wire crcrst; 118 | 119 | wire [7:0] txd_r; 120 | 121 | //genvar j; 122 | //generate for (j = 0; j <= 7; j = j + 1) 123 | //begin: buf_inst 124 | io_buf_iobuf_out_b0t io_inst 125 | ( 126 | .datain(txd_r), 127 | .dataout(e_txd) 128 | ) ; 129 | //end 130 | //endgenerate 131 | 132 | 133 | udp_send 134 | # 135 | ( 136 | .TTL (TTL) , 137 | .SRC_ADDR (TX_SRC_ADDR) , 138 | .SRC_PORT (TX_SRC_PORT) , 139 | .SRC_MAC (TX_SRC_MAC) 140 | ) 141 | udp_s_inst( 142 | /* system signal*/ 143 | .clk (e_gtxc), 144 | .rst_n (rst_n), 145 | /* user control*/ 146 | .data_i (data_tx), 147 | .tx_data_len(data_len_tx), 148 | .crc (crc), 149 | .crcen (crcen), 150 | .crcrst (crcrst), 151 | 152 | .start (cvt_tx), 153 | .busy (busy_tx), 154 | .tx_dv (dv_tx), 155 | .dst_mac (dst_mac), 156 | .dst_addr (dst_addr), 157 | .dst_port (dst_port), 158 | .DF (DF_tx), 159 | .MF (MF_tx), 160 | /* PHY interface*/ 161 | .tx_en (e_txen), 162 | .txer (e_txer), 163 | //.txd (e_txd) 164 | .txd (txd_r) 165 | ); 166 | 167 | crc crc_inst 168 | ( 169 | .Clk (e_gtxc), 170 | .Reset (crcrst), 171 | .Data_in(e_txd), 172 | .Enable (crcen), 173 | .Crc (crc), 174 | .CrcNext() 175 | ); 176 | 177 | 178 | udp_receive 179 | # 180 | ( 181 | .CAN_RECEIVE_BROADCAST (RX_CAN_RECEIVE_BROADCAST), 182 | .DST_ADDR (RX_DST_ADDR) , 183 | .DST_PORT (RX_DST_PORT) , 184 | .DST_MAC (RX_DST_MAC) 185 | ) 186 | udp_r_inst( 187 | /* system signal*/ 188 | .clk (e_rxc), 189 | .rst_n (rst_n), 190 | /* user control*/ 191 | .rx_data_len(rx_data_len), 192 | .rx_total_len(rx_total_len), 193 | .update (update_rx), 194 | .ip_header (r_ip), 195 | .udp_header (r_udp), 196 | .mac (r_mac), 197 | .data_o (data_rx), 198 | .src_mac (src_mac), 199 | .src_addr (src_addr), 200 | .src_port (src_port), 201 | .DF (DF_rx), 202 | .MF (MF_rx), 203 | /* PHY interface*/ 204 | .e_rxdv (e_rxdv), 205 | .rxd (e_rxd) 206 | ); 207 | 208 | endmodule -------------------------------------------------------------------------------- /hdl/ethernet_top.v: -------------------------------------------------------------------------------- 1 | module ethernet_top 2 | ( 3 | /* system signal*/ 4 | input clk , 5 | input rst_n , 6 | /* rx interface */ 7 | input e_rxc , //125Mhz 8 | input e_rxdv , 9 | input e_rxer , 10 | input [7:0] e_rxd , 11 | /* tx interface */ 12 | input e_txc , 13 | output e_gtxc , 14 | output e_txen , 15 | output e_txer , 16 | output [7:0] e_txd , 17 | /* PHY setting interface */ 18 | output e_reset , 19 | output e_mdc , 20 | inout e_mdio 21 | ); 22 | 23 | ethernet 24 | e_inst 25 | ( 26 | /* system signal*/ 27 | .clk (e_rxc), 28 | .rst_n (rst_n), 29 | /* rx interface */ 30 | .e_rxc (e_rxc ), //125Mhz 31 | .e_rxdv (e_rxdv ), 32 | .e_rxer (e_rxer ), 33 | .e_rxd (e_rxd ), 34 | /* tx interface */ 35 | .e_txc (e_txc ), 36 | .e_gtxc (e_gtxc ), 37 | .e_txen (e_txen ), 38 | .e_txer (e_txer ), 39 | .e_txd (e_txd ), 40 | /* PHY setting interface */ 41 | .e_reset(e_reset), 42 | .e_mdc (e_mdc ), 43 | .e_mdio (e_mdio ), 44 | /* Control signal*/ 45 | /* tx */ 46 | .data_tx (8'h66), 47 | .data_len_tx(16'h50), 48 | .cvt_tx (1'b1), 49 | .busy_tx (), 50 | .dv_tx (), 51 | .dst_mac (48'h305a3aea6538), 52 | .dst_addr (32'hc0a80003), 53 | .dst_port (16'd8080), 54 | .DF_tx (1'b1), 55 | .MF_tx (1'b0), 56 | /* rx */ 57 | .rx_data_len(), 58 | .rx_total_len(), 59 | .update_rx (), 60 | .data_rx (), 61 | .src_mac (), 62 | .src_addr (), 63 | .src_port (), 64 | .DF_rx (), 65 | .MF_rx (), 66 | .r_ip (), 67 | .r_udp (), 68 | .r_mac () 69 | ); 70 | 71 | endmodule -------------------------------------------------------------------------------- /hdl/udp_receive.v: -------------------------------------------------------------------------------- 1 | /** 2 | * @Function: Ethernet Send UDP 3 | * @Date : 2019/05/26 4 | * @Vision : v1.0 5 | * @Note : 6 | * @Author : WoodFan 7 | * @param clk : fpga main clock 8 | * @param rst_n : active low reset signal 9 | * @param rx_data_len: rx udp data length parameter 10 | * @param rx_total_len: rx ip data length parameter 11 | * @param update : rx data update 12 | * @param ip_header: ip packet header 13 | * @param udp_header:udp packet header 14 | * @param mac : dst mac, src mac, ip type 15 | * @param data_o : data output 16 | * @param src_mac : source mac addr 17 | * @param src_addr: source ip addr 18 | * @param src_port: source port addr 19 | * @param DF : ip packet parameter 20 | * @param MF : ip packet parameter 21 | * @param e_rxdv : rx already signal 22 | * @param rxd : rxd data 23 | 24 | */ 25 | module udp_receive 26 | # 27 | ( 28 | /* 192.168.0.2*/ 29 | parameter CAN_RECEIVE_BROADCAST = 1, 30 | parameter DST_ADDR = 32'hc0a80002, 31 | parameter DST_PORT = 16'd8000, 32 | parameter DST_MAC = 48'h000a3501fec0 33 | ) 34 | ( 35 | /* system signal*/ 36 | input clk , 37 | input rst_n , 38 | /* user control*/ 39 | output [15:0] rx_data_len, 40 | output [15:0] rx_total_len, 41 | output reg update , 42 | output reg [159:0] ip_header, 43 | output reg [63:0] udp_header, 44 | output reg [111:0] mac , 45 | output reg [7:0] data_o , 46 | output [48:0] src_mac , 47 | output [31:0] src_addr, 48 | output [16:0] src_port, 49 | output DF , 50 | output MF , 51 | /* PHY interface*/ 52 | input e_rxdv , 53 | input [7:0] rxd 54 | ); 55 | 56 | localparam PRESEMBLE = 8'h55 ; 57 | localparam PRESTART = 8'hd5 ; 58 | localparam IP_TYPE = 16'h0800 ; 59 | localparam UDP_TYPE = 8'h11 ; 60 | localparam BROAD_MAC = CAN_RECEIVE_BROADCAST ? 48'hffffffffffff : DST_MAC; 61 | 62 | localparam PRE_CNT = 7 , 63 | MAC_CNT = 14 , 64 | HRD_CNT = 28 , 65 | CRC_CNT = 4 , 66 | CODE_CNT = 12 ; 67 | 68 | localparam IDLE = 4'b0000 , 69 | R_PRE = 4'b0010 , 70 | R_MAC = 4'b0110 , 71 | R_HEADER = 4'b0111 , 72 | R_DATA= 4'b0101 , 73 | R_FIHISH = 4'b0100 ; 74 | 75 | reg [3:0] state /*synthesis preserve*/; 76 | reg [3:0] nxt_state /*synthesis preserve*/; 77 | reg [15:0] cnt ; 78 | reg [15:0] rdata_len ; 79 | reg rxer ; 80 | 81 | wire [47:0] dst_mac_w ; 82 | wire [31:0] dst_addr_w ; 83 | wire [15:0] dst_port_w ; 84 | wire [7:0] ip_type ; 85 | wire [15:0] ethernet_type ; 86 | 87 | assign src_mac = mac[63:16] ; 88 | assign dst_mac_w = mac[111:64] ; 89 | assign src_addr= ip_header[63:32] ; 90 | assign dst_addr_w = ip_header[31:0]; 91 | assign src_port= udp_header[63:48] ; 92 | assign dst_port_w= udp_header[47:32]; 93 | assign ip_type = ip_header[87:80] ; 94 | assign ethernet_type = mac[15:0] ; 95 | 96 | assign rx_total_len = ip_header[31:16] ; 97 | assign rx_data_len = udp_header[47:32] ; 98 | assign DF = ip_header[33] ; 99 | assign MF = ip_header[34] ; 100 | 101 | always @ (posedge clk or negedge rst_n) 102 | begin 103 | if (!rst_n) 104 | state <= 'd0; 105 | else 106 | state <= nxt_state; 107 | end 108 | 109 | always @ (*) 110 | begin 111 | nxt_state = state; 112 | 113 | if (rxer) 114 | nxt_state = IDLE; 115 | else 116 | begin 117 | case (state) 118 | IDLE: 119 | if (e_rxdv && rxd == PRESEMBLE) 120 | nxt_state = R_PRE; 121 | 122 | R_PRE: 123 | if (cnt >= PRE_CNT - 16'd1) 124 | nxt_state = R_MAC; 125 | 126 | R_MAC: 127 | if (cnt >= MAC_CNT - 16'd1) 128 | nxt_state = R_HEADER; 129 | 130 | R_HEADER: 131 | if (dst_mac_w != DST_MAC && dst_mac_w != BROAD_MAC) 132 | nxt_state = IDLE; 133 | else if (cnt >= HRD_CNT - 16'd1) 134 | nxt_state = R_DATA; 135 | 136 | R_DATA: 137 | if (dst_port_w != DST_PORT || dst_addr_w != DST_ADDR || ip_type != UDP_TYPE) 138 | nxt_state = IDLE; 139 | else if (rdata_len <= 16'd9) 140 | nxt_state = R_FIHISH; 141 | 142 | R_FIHISH: nxt_state = IDLE; 143 | 144 | default: nxt_state = IDLE; 145 | endcase 146 | end 147 | end 148 | 149 | //cnt 150 | always @ (posedge clk) 151 | begin 152 | case (state) 153 | R_PRE: 154 | begin 155 | if (nxt_state != state) 156 | cnt <= 16'd0; 157 | else if ((rxd == PRESEMBLE) && e_rxdv && cnt < PRE_CNT - 16'd1) 158 | cnt <= cnt + 16'd1; 159 | else if ((rxd == PRESTART) && e_rxdv) 160 | cnt <= cnt + 16'd1; 161 | end 162 | 163 | R_MAC, R_HEADER: 164 | begin 165 | if (nxt_state != state) 166 | cnt <= 'd0; 167 | else if (e_rxdv) 168 | cnt <= cnt + 16'd1; 169 | end 170 | 171 | default: cnt <= 16'd0; 172 | endcase 173 | end 174 | 175 | //ip_header, udp_header, mac 176 | always @ (posedge clk) 177 | begin 178 | case (state) 179 | IDLE: 180 | begin 181 | ip_header <= 160'd0; 182 | udp_header <= 64'd0; 183 | mac <= 112'd0; 184 | end 185 | 186 | R_MAC: 187 | if (e_rxdv) 188 | case (cnt) 189 | 16'd0: mac[111:104] <= rxd; 190 | 16'd1: mac[103:96] <= rxd; 191 | 16'd2: mac[95:88] <= rxd; 192 | 16'd3: mac[87:80] <= rxd; 193 | 16'd4: mac[79:72] <= rxd; 194 | 16'd5: mac[71:64] <= rxd; 195 | 16'd6: mac[63:56] <= rxd; 196 | 16'd7: mac[55:48] <= rxd; 197 | 16'd8: mac[47:40] <= rxd; 198 | 16'd9: mac[39:32] <= rxd; 199 | 16'd10: mac[31:24] <= rxd; 200 | 16'd11: mac[23:16] <= rxd; 201 | 16'd12: mac[15:8] <= rxd; 202 | 16'd13: mac[7:0] <= rxd; 203 | default:; 204 | endcase 205 | 206 | R_HEADER: 207 | if (e_rxdv) 208 | begin 209 | case (cnt) 210 | 16'd0: ip_header[159:152] <= rxd; 211 | 16'd1: ip_header[151:144] <= rxd; 212 | 16'd2: ip_header[143:136] <= rxd; 213 | 16'd3: ip_header[135:128] <= rxd; 214 | 16'd4: ip_header[127:120] <= rxd; 215 | 16'd5: ip_header[119:112] <= rxd; 216 | 16'd6: ip_header[111:104] <= rxd; 217 | 16'd7: ip_header[103:96] <= rxd; 218 | 16'd8: ip_header[95:88] <= rxd; 219 | 16'd9: ip_header[87:80] <= rxd; 220 | 16'd10: ip_header[79:72] <= rxd; 221 | 16'd11: ip_header[71:64] <= rxd; 222 | 16'd12: ip_header[63:56] <= rxd; 223 | 16'd13: ip_header[55:48] <= rxd; 224 | 16'd14: ip_header[47:40] <= rxd; 225 | 16'd15: ip_header[39:32] <= rxd; 226 | 16'd16: ip_header[31:24] <= rxd; 227 | 16'd17: ip_header[23:16] <= rxd; 228 | 16'd18: ip_header[15:8] <= rxd; 229 | 16'd19: ip_header[7:0] <= rxd; 230 | 16'd20: udp_header[63:56] <= rxd; 231 | 16'd21: udp_header[55:48] <= rxd; 232 | 16'd22: udp_header[47:40] <= rxd; 233 | 16'd23: udp_header[39:32] <= rxd; 234 | 16'd24: udp_header[31:24] <= rxd; 235 | 16'd25: udp_header[23:16] <= rxd; 236 | 16'd26: udp_header[15:8] <= rxd; 237 | 16'd27: udp_header[7:0] <= rxd; 238 | default: ; 239 | endcase 240 | end 241 | default: ; 242 | endcase 243 | end 244 | 245 | //rdata_len, update, data_o 246 | always @ (posedge clk) 247 | begin 248 | if (state == R_HEADER) 249 | begin 250 | rdata_len <= udp_header[31:16]; 251 | end 252 | if (state == R_DATA) 253 | begin 254 | if (e_rxdv) 255 | begin 256 | rdata_len <= rdata_len - 16'd1; 257 | update <= 1'b1; 258 | data_o <= rxd; 259 | end 260 | else 261 | update <= 1'b0; 262 | end 263 | else 264 | update <= 1'b0; 265 | end 266 | endmodule -------------------------------------------------------------------------------- /hdl/udp_send.v: -------------------------------------------------------------------------------- 1 | /** 2 | * @Function: Ethernet Send UDP 3 | * @Date : 2019/05/25 4 | * @Vision : v1.0 5 | * @Note : 6 | * @Author : WoodFan 7 | * @param clk : fpga main clock 8 | * @param rst_n : active low reset signal 9 | * @param data_i : data need to be transformed 10 | * @param tx_data_len: amount of data need to be transformed 11 | * @param crc : crc code 12 | * @param crcen : crc enable signal 13 | * @param crcrst : crc reset signal 14 | * @param start : active high transform 15 | * @param busy : indicate the module has worked 16 | * @param tx_dv : High level means data will be sent 17 | * @param dst_mac : mac address of destination 18 | * @param dst_addr: ip address of destination 19 | * @param dst_port: port of destination 20 | * @param DF : ip packet parameter 21 | * @param MF : ip packet parameter 22 | * @param tx_en : active high when transform 23 | * @param txer : transform error 24 | * @param txd : transform data busy 25 | */ 26 | module udp_send 27 | # 28 | ( 29 | parameter IP_HEADER_LEN = 4'd5, 30 | parameter TTL = 8'd128, 31 | /* 192.168.0.3*/ 32 | parameter SRC_ADDR = 32'hc0a80002, 33 | parameter SRC_PORT = 16'd8000, 34 | parameter SRC_MAC = 48'h000a3501fec0 35 | ) 36 | ( 37 | /* system signal*/ 38 | input clk , 39 | input rst_n , 40 | /* user control*/ 41 | input [7:0] data_i , 42 | input [15:0] tx_data_len, 43 | input [31:0] crc , 44 | output reg crcen , 45 | output reg crcrst , 46 | 47 | input start , 48 | output reg busy , 49 | output reg tx_dv , 50 | input [47:0] dst_mac , 51 | input [31:0] dst_addr, 52 | input [15:0] dst_port, 53 | 54 | input DF , 55 | input MF , 56 | /* PHY interface*/ 57 | output reg tx_en , 58 | output reg txer , 59 | output reg [7:0] txd 60 | ); 61 | 62 | localparam PRESEMBLE = 8'h55 ; 63 | localparam PRESTART = 8'hd5 ; 64 | localparam IP_TYPE = 16'h0800; 65 | 66 | //counter 67 | localparam SUM_CNT = 5, 68 | PRE_CNT = 8, 69 | MAC_CNT = 14, 70 | HRD_CNT = 28, 71 | CRC_CNT = 4, 72 | CODE_CNT = 12; 73 | 74 | //FSM state 75 | localparam IDLE = 4'b0000, 76 | MAKE_IP = 4'b0001, 77 | MAKE_SUM = 4'b0011, 78 | SEND_PRE = 4'b0010, 79 | SEND_MAC = 4'b0110, 80 | SEND_HEADER = 4'b0111, 81 | SEND_DATA= 4'b0101, 82 | SEND_CRC = 4'b0100, 83 | IDLE_CODE = 4'b1100, 84 | T_AGAIN = 4'b1000 85 | ; 86 | 87 | reg [159:0] ip_header ; 88 | reg [63:0] udp_header ; 89 | reg [3:0] state /*synthesis preserve*/; 90 | reg [3:0] nxt_state /*synthesis preserve*/; 91 | reg [15:0] cnt ; 92 | reg [15:0] tdata_len ; 93 | reg [31:0] checksum_r ; 94 | reg [31:0] checksum_r1 ; 95 | reg [31:0] checksum_r2 ; 96 | reg [31:0] checksum_r3 ; 97 | reg [31:0] checksum_r4 ; 98 | reg [31:0] checksum_r5 ; 99 | reg [111:0] mac ; 100 | reg [15:0] ip_cnt ; 101 | reg [12:0] fragment_cnt ; 102 | 103 | wire [15:0] total_len; 104 | assign total_len = (IP_HEADER_LEN << 2) + tdata_len; 105 | 106 | always @ (posedge clk or negedge rst_n) 107 | begin 108 | if (!rst_n) 109 | state <= 'd0; 110 | else 111 | state <= nxt_state; 112 | end 113 | 114 | always @ (*) 115 | begin 116 | nxt_state = state; 117 | case (state) 118 | IDLE: 119 | if (start) 120 | nxt_state = MAKE_IP; 121 | 122 | MAKE_IP: nxt_state = MAKE_SUM; 123 | 124 | MAKE_SUM: 125 | if (cnt >= SUM_CNT - 16'd1) 126 | nxt_state = SEND_PRE; 127 | 128 | SEND_PRE: 129 | if (cnt >= PRE_CNT - 16'd1) 130 | nxt_state = SEND_MAC; 131 | 132 | SEND_MAC: 133 | if (cnt >= MAC_CNT - 16'd1) 134 | nxt_state = SEND_HEADER; 135 | 136 | SEND_HEADER: 137 | if (cnt >= HRD_CNT - 16'd1) 138 | nxt_state = SEND_DATA; 139 | 140 | SEND_DATA: 141 | if (tdata_len <= 16'd9) 142 | nxt_state = SEND_CRC; 143 | 144 | SEND_CRC: 145 | if (cnt >= CRC_CNT - 16'd1) 146 | nxt_state = IDLE_CODE; 147 | 148 | IDLE_CODE: 149 | if (cnt >= CODE_CNT && start) 150 | nxt_state = T_AGAIN ; 151 | else if (cnt >= CODE_CNT) 152 | nxt_state = IDLE ; 153 | 154 | T_AGAIN: nxt_state = MAKE_IP; 155 | 156 | default: nxt_state = IDLE; 157 | endcase 158 | end 159 | 160 | //counter 161 | //cnt 162 | //ip_cnt 163 | //fragment_cnt 164 | //tdata_len 165 | always @ (posedge clk) 166 | begin 167 | case (state) 168 | IDLE: 169 | begin 170 | cnt <= 16'd0; 171 | ip_cnt<=16'd0; 172 | fragment_cnt<=13'd0; 173 | tdata_len <= tx_data_len + 16'd8; 174 | end 175 | 176 | MAKE_IP: 177 | begin 178 | ip_cnt<= ip_cnt + 16'd1; 179 | if ({DF, MF} == 2'b01) 180 | fragment_cnt <= fragment_cnt + 13'd1; 181 | else 182 | fragment_cnt <= 13'd0; 183 | end 184 | 185 | MAKE_SUM, SEND_PRE, SEND_MAC, SEND_HEADER, SEND_CRC, IDLE_CODE: 186 | begin 187 | if (nxt_state == state) 188 | cnt <= cnt + 16'd1; 189 | else 190 | cnt <= 16'd0; 191 | end 192 | 193 | SEND_DATA: tdata_len <= tdata_len - 16'd1; 194 | 195 | T_AGAIN: 196 | begin 197 | cnt <= 16'd0; 198 | tdata_len <= tx_data_len + 16'd8; 199 | end 200 | default: ; 201 | endcase 202 | end 203 | 204 | //crc 205 | always @ (posedge clk) 206 | begin 207 | case (state) 208 | IDLE: 209 | begin 210 | crcen <= 1'b0; 211 | crcrst <= 1'b1; 212 | end 213 | 214 | SEND_MAC: 215 | begin 216 | crcen <= 1'b1; 217 | crcrst <= 1'b0; 218 | end 219 | 220 | SEND_DATA: 221 | begin 222 | if (state != nxt_state) 223 | begin 224 | crcen <= 1'b0; 225 | end 226 | end 227 | 228 | IDLE_CODE: crcrst<=1'b1; 229 | 230 | default: ; 231 | endcase 232 | end 233 | 234 | //txd 235 | always @ (posedge clk) 236 | begin 237 | case (state) 238 | IDLE: 239 | begin 240 | ip_header <= 160'd0; 241 | udp_header <= 64'd0; 242 | 243 | tx_en <= 1'b0 ; 244 | txer <= 1'b0 ; 245 | txd <= 8'd0 ; 246 | mac <= 96'd0; 247 | end 248 | 249 | MAKE_IP: 250 | begin 251 | /*ipv4 5 total_len*/ 252 | ip_header[159:128] <= {4'h4, IP_HEADER_LEN,8'b00,total_len }; 253 | /* counter */ 254 | ip_header[127:112]<= ip_cnt; 255 | /* fragment offset*/ 256 | ip_header[111:96]<= {1'b0, DF, MF, fragment_cnt}; 257 | /* TTL protype checksum*/ 258 | ip_header[95:64]<= {TTL, 8'h11, 16'd0}; 259 | ip_header[63:32]<= SRC_ADDR; 260 | ip_header[31:0]<=dst_addr; 261 | 262 | udp_header[63:32] <= {SRC_PORT, dst_port}; 263 | udp_header[31:0]<= {tdata_len, 16'h0000}; 264 | 265 | mac <= {dst_mac, SRC_MAC, IP_TYPE}; 266 | end 267 | 268 | MAKE_SUM: 269 | begin 270 | case (cnt) 271 | 16'd0: 272 | begin 273 | checksum_r1 <= ip_header[15:0] + ip_header[31:16]; 274 | checksum_r2 <= ip_header[47:32] + ip_header[63:48]; 275 | checksum_r3 <= ip_header[79:64] + ip_header[95:80]; 276 | checksum_r4 <= ip_header[111:96] + ip_header[127:112]; 277 | checksum_r5 <= ip_header[143:128] + ip_header[159:144]; 278 | end 279 | 280 | 16'd1: 281 | begin 282 | checksum_r1 <= checksum_r1 + checksum_r2 + checksum_r3; 283 | checksum_r4 <= checksum_r4 + checksum_r5; 284 | end 285 | 286 | 16'd2: checksum_r <= checksum_r1 + checksum_r4; 287 | 288 | 16'd3: checksum_r[15:0] <= checksum_r[31:16] + checksum_r[15:0]; 289 | 290 | 16'd4: ip_header[79:64] <= ~checksum_r[15:0]; 291 | default: ; 292 | endcase 293 | end 294 | 295 | SEND_PRE: 296 | begin 297 | if (cnt >= PRE_CNT - 16'd1) 298 | txd <= PRESTART; 299 | else 300 | txd <= PRESEMBLE; 301 | tx_en <= 1'b1; 302 | end 303 | 304 | SEND_MAC: 305 | begin 306 | case (cnt) 307 | 16'd0: txd <= mac[111:104]; 308 | 16'd1: txd <= mac[103:96] ; 309 | 16'd2: txd <= mac[95:88] ; 310 | 16'd3: txd <= mac[87:80] ; 311 | 16'd4: txd <= mac[79:72] ; 312 | 16'd5: txd <= mac[71:64] ; 313 | 16'd6: txd <= mac[63:56] ; 314 | 16'd7: txd <= mac[55:48] ; 315 | 16'd8: txd <= mac[47:40] ; 316 | 16'd9: txd <= mac[39:32] ; 317 | 16'd10: txd <= mac[31:24] ; 318 | 16'd11: txd <= mac[23:16] ; 319 | 16'd12: txd <= mac[15:8] ; 320 | 16'd13: txd <= mac[7:0] ; 321 | default:; 322 | endcase 323 | end 324 | 325 | SEND_HEADER: 326 | begin 327 | case (cnt) 328 | 16'd0: txd <= ip_header[159:152]; 329 | 16'd1: txd <= ip_header[151:144]; 330 | 16'd2: txd <= ip_header[143:136]; 331 | 16'd3: txd <= ip_header[135:128]; 332 | 16'd4: txd <= ip_header[127:120]; 333 | 16'd5: txd <= ip_header[119:112]; 334 | 16'd6: txd <= ip_header[111:104]; 335 | 16'd7: txd <= ip_header[103:96]; 336 | 16'd8: txd <= ip_header[95:88]; 337 | 16'd9: txd <= ip_header[87:80]; 338 | 16'd10: txd <= ip_header[79:72]; 339 | 16'd11: txd <= ip_header[71:64]; 340 | 16'd12: txd <= ip_header[63:56]; 341 | 16'd13: txd <= ip_header[55:48]; 342 | 16'd14: txd <= ip_header[47:40]; 343 | 16'd15: txd <= ip_header[39:32]; 344 | 16'd16: txd <= ip_header[31:24]; 345 | 16'd17: txd <= ip_header[23:16]; 346 | 16'd18: txd <= ip_header[15:8]; 347 | 16'd19: txd <= ip_header[7:0]; 348 | 16'd20: txd <= udp_header[63:56]; 349 | 16'd21: txd <= udp_header[55:48]; 350 | 16'd22: txd <= udp_header[47:40]; 351 | 16'd23: txd <= udp_header[39:32]; 352 | 16'd24: txd <= udp_header[31:24]; 353 | 16'd25: txd <= udp_header[23:16]; 354 | 16'd26: txd <= udp_header[15:8]; 355 | 16'd27: txd <= udp_header[7:0]; 356 | default: ; 357 | endcase 358 | end 359 | 360 | SEND_DATA: txd <= data_i; 361 | 362 | SEND_CRC: 363 | begin 364 | case (cnt) 365 | 16'd0: txd <= ~{crc[24], crc[25], crc[26], crc[27], crc[28], crc[29], crc[30], crc[31]}; 366 | 16'd1: txd <= ~{crc[16], crc[17], crc[18], crc[19], crc[20], crc[21], crc[22], crc[23]}; 367 | 16'd2: txd <= ~{crc[8], crc[9], crc[10], crc[11], crc[12], crc[13], crc[14], crc[15]}; 368 | 16'd3: txd <= ~{crc[0], crc[1], crc[1], crc[3], crc[4], crc[5], crc[6], crc[7]}; 369 | default: ; 370 | endcase 371 | end 372 | 373 | IDLE_CODE: 374 | begin 375 | tx_en<= 1'b0; 376 | txd <= 8'd0; 377 | end 378 | default:; 379 | endcase 380 | end 381 | 382 | //interface signal 383 | always @ (posedge clk) 384 | begin 385 | case (state) 386 | IDLE: 387 | busy <= 1'b0; 388 | 389 | MAKE_IP: 390 | busy <= 1'b1; 391 | 392 | T_AGAIN: 393 | busy <= 1'b0; 394 | default: ; 395 | endcase 396 | end 397 | 398 | always @ (posedge clk) 399 | begin 400 | if ((state == SEND_HEADER && (state != nxt_state)) || state == SEND_DATA) 401 | tx_dv <= 1'b1; 402 | else 403 | tx_dv <= 1'b0; 404 | end 405 | 406 | endmodule -------------------------------------------------------------------------------- /udp_receive.v: -------------------------------------------------------------------------------- 1 | /** 2 | * @Function: Ethernet Send UDP 3 | * @Date : 2019/07/23 4 | * @Vision : v1.2 5 | * @Note : 6 | * @Author : WoodFan 7 | * @param clk : fpga main clock 8 | * @param rst_n : active low reset signal 9 | * @param rx_data_len: rx udp data length parameter 10 | * @param rx_total_len: rx ip data length parameter 11 | * @param update : rx data update 12 | * @param ip_header: ip packet header 13 | * @param udp_header:udp packet header 14 | * @param mac : dst mac, src mac, ip type 15 | * @param data_o : data output 16 | * @param src_mac : source mac addr 17 | * @param src_addr: source ip addr 18 | * @param src_port: source port addr 19 | * @param DF : ip packet parameter 20 | * @param MF : ip packet parameter 21 | * @param e_rxdv : rx already signal 22 | * @param rxd : rxd data 23 | 24 | */ 25 | module udp_receive 26 | # 27 | ( 28 | /* 192.168.0.2*/ 29 | parameter CAN_RECEIVE_BROADCAST = 1, 30 | parameter DST_ADDR = 32'hc0a80002, 31 | parameter DST_PORT = 16'd8000, 32 | parameter DST_MAC = 48'h000a3501fec0 33 | ) 34 | ( 35 | /* system signal*/ 36 | input clk , 37 | input rst_n , 38 | /* user control*/ 39 | output [15:0] rx_data_len, 40 | output [15:0] rx_total_len, 41 | output reg update , 42 | output reg [159:0] ip_header, 43 | output reg [63:0] udp_header, 44 | output reg [111:0] mac , 45 | output reg [7:0] data_o , 46 | output [48:0] src_mac , 47 | output [31:0] src_addr, 48 | output [16:0] src_port, 49 | output DF , 50 | output MF , 51 | /* PHY interface*/ 52 | input e_rxdv , 53 | input [7:0] rxd 54 | ); 55 | 56 | localparam PRESEMBLE = 8'h55 ; 57 | localparam PRESTART = 8'hd5 ; 58 | localparam IP_TYPE = 16'h0800 ; 59 | localparam UDP_TYPE = 8'h11 ; 60 | localparam BROAD_MAC = CAN_RECEIVE_BROADCAST ? 48'hffffffffffff : DST_MAC; 61 | 62 | localparam PRE_CNT = 7 , 63 | MAC_CNT = 14 , 64 | HRD_CNT = 28 , 65 | CRC_CNT = 4 , 66 | CODE_CNT = 12 ; 67 | 68 | localparam IDLE = 4'b0000 , 69 | R_PRE = 4'b0010 , 70 | R_MAC = 4'b0110 , 71 | R_HEADER = 4'b0111 , 72 | R_DATA= 4'b0101 , 73 | R_FIHISH = 4'b0100 ; 74 | 75 | reg [3:0] state /*synthesis preserve*/; 76 | reg [3:0] nxt_state /*synthesis preserve*/; 77 | reg [15:0] cnt ; 78 | reg [15:0] rdata_len ; 79 | reg rxer ; 80 | 81 | wire [47:0] dst_mac_w ; 82 | wire [31:0] dst_addr_w ; 83 | wire [15:0] dst_port_w ; 84 | wire [7:0] ip_type ; 85 | wire [15:0] ethernet_type ; 86 | 87 | assign src_mac = mac[63:16] ; 88 | assign dst_mac_w = mac[111:64] ; 89 | assign src_addr= ip_header[63:32] ; 90 | assign dst_addr_w = ip_header[31:0]; 91 | assign src_port= udp_header[63:48] ; 92 | assign dst_port_w= udp_header[47:32]; 93 | assign ip_type = ip_header[87:80] ; 94 | assign ethernet_type = mac[15:0] ; 95 | 96 | assign rx_total_len = ip_header[31:16] ; 97 | assign rx_data_len = udp_header[47:32] ; 98 | assign DF = ip_header[33] ; 99 | assign MF = ip_header[34] ; 100 | 101 | wire is_rxd_PRE; 102 | wire is_cur_state_n; 103 | wire is_prestart ; 104 | wire is_hrd_state ; 105 | wire is_dat_state ; 106 | wire flag_pre_cnt ; 107 | wire flag_pre_over; 108 | wire flag_mac_over; 109 | wire flag_hrd_idle; 110 | wire flag_hrd_over; 111 | wire flag_dat_idle; 112 | wire flag_dat_over; 113 | 114 | //是否接收到PRESEMBLE 115 | assign is_rxd_PRE = (e_rxdv && rxd == PRESEMBLE) ? 1'b1: 1'b0; 116 | //当前状态不是next_state为1 117 | assign is_cur_state_n= (nxt_state != state) ? 1'b1 : 1'b0; 118 | //R_PRESEMBLE has been over 119 | assign flag_pre_over = (cnt >= PRE_CNT - 16'd1) ? 1'b1 : 1'b0; 120 | //R_MAC has been over 121 | assign flag_mac_over = (cnt >= MAC_CNT - 16'd1) ? 1'b1 : 1'b0; 122 | //R_HEADER to IDLE when signal active high 123 | assign flag_hrd_idle = (dst_mac_w != DST_MAC && dst_mac_w != BROAD_MAC) ? 1'b1 : 1'b0;\ 124 | //R_HEADER has been over 125 | assign flag_hrd_over = (cnt >= HRD_CNT - 16'd1) ? 1'b1 : 1'b0; 126 | //R_DATA to IDLE when signal active high 127 | assign flag_dat_idle = (dst_port_w != DST_PORT || dst_addr_w != DST_ADDR || ip_type != UDP_TYPE) ? 1'b1 : 1'b0; 128 | //R_DATA has been OVER 129 | assign flag_dat_over = (rdata_len <= 16'd9) ? 1'b1 : 1'b0; 130 | // 131 | assign flag_pre_cnt = ((rxd == PRESEMBLE) && e_rxdv && cnt < PRE_CNT - 16'd1) ? 1'b1 : 1'b0; 132 | //是否接收的数据时PRESTART 133 | assign is_prestart = ((rxd == PRESTART) && e_rxdv) ? 1'b1 : 1'b0; 134 | //when state in R_HEADER the signal active high 135 | assign is_hrd_state = (state == R_HEADER) ? 1'b1 : 1'b0; 136 | //when state in R_DATA the signal active high 137 | assign is_dat_state = (state == R_DATA) ? 1'b1 : 1'b0 ; 138 | 139 | always @ (posedge clk or negedge rst_n) 140 | begin 141 | if (!rst_n) 142 | state <= 'd0; 143 | else 144 | state <= nxt_state; 145 | end 146 | 147 | always @ (*) 148 | begin 149 | nxt_state = state; 150 | 151 | if (rxer) 152 | nxt_state = IDLE; 153 | else 154 | begin 155 | case (state) 156 | IDLE: 157 | if (is_rxd_PRE) 158 | nxt_state = R_PRE; 159 | 160 | R_PRE: 161 | if (flag_pre_over) 162 | nxt_state = R_MAC; 163 | 164 | R_MAC: 165 | if (flag_mac_over) 166 | nxt_state = R_HEADER; 167 | 168 | R_HEADER: 169 | if (flag_hrd_idle) 170 | nxt_state = IDLE; 171 | else if (flag_hrd_over) 172 | nxt_state = R_DATA; 173 | 174 | R_DATA: 175 | if (flag_dat_idle) 176 | nxt_state = IDLE; 177 | else if (flag_dat_over) 178 | nxt_state = R_FIHISH; 179 | 180 | R_FIHISH: nxt_state = IDLE; 181 | 182 | default: nxt_state = IDLE; 183 | endcase 184 | end 185 | end 186 | 187 | //cnt 188 | always @ (posedge clk) 189 | begin 190 | case (state) 191 | R_PRE: 192 | begin 193 | if (is_cur_state_n) 194 | cnt <= 16'd0; 195 | else if (flag_pre_cnt) 196 | cnt <= cnt + 16'd1; 197 | else if (is_prestart) 198 | cnt <= cnt + 16'd1; 199 | end 200 | 201 | R_MAC, R_HEADER: 202 | begin 203 | if (is_cur_state_n) 204 | cnt <= 'd0; 205 | else if (e_rxdv) 206 | cnt <= cnt + 16'd1; 207 | end 208 | 209 | default: cnt <= 16'd0; 210 | endcase 211 | end 212 | 213 | //ip_header, udp_header, mac 214 | always @ (posedge clk) 215 | begin 216 | case (state) 217 | IDLE: 218 | begin 219 | ip_header <= 160'd0; 220 | udp_header <= 64'd0; 221 | mac <= 112'd0; 222 | end 223 | 224 | R_MAC: 225 | if (e_rxdv) 226 | case (cnt) 227 | 16'd0: mac[111:104] <= rxd; 228 | 16'd1: mac[103:96] <= rxd; 229 | 16'd2: mac[95:88] <= rxd; 230 | 16'd3: mac[87:80] <= rxd; 231 | 16'd4: mac[79:72] <= rxd; 232 | 16'd5: mac[71:64] <= rxd; 233 | 16'd6: mac[63:56] <= rxd; 234 | 16'd7: mac[55:48] <= rxd; 235 | 16'd8: mac[47:40] <= rxd; 236 | 16'd9: mac[39:32] <= rxd; 237 | 16'd10: mac[31:24] <= rxd; 238 | 16'd11: mac[23:16] <= rxd; 239 | 16'd12: mac[15:8] <= rxd; 240 | 16'd13: mac[7:0] <= rxd; 241 | default:; 242 | endcase 243 | 244 | R_HEADER: 245 | if (e_rxdv) 246 | begin 247 | case (cnt) 248 | 16'd0: ip_header[159:152] <= rxd; 249 | 16'd1: ip_header[151:144] <= rxd; 250 | 16'd2: ip_header[143:136] <= rxd; 251 | 16'd3: ip_header[135:128] <= rxd; 252 | 16'd4: ip_header[127:120] <= rxd; 253 | 16'd5: ip_header[119:112] <= rxd; 254 | 16'd6: ip_header[111:104] <= rxd; 255 | 16'd7: ip_header[103:96] <= rxd; 256 | 16'd8: ip_header[95:88] <= rxd; 257 | 16'd9: ip_header[87:80] <= rxd; 258 | 16'd10: ip_header[79:72] <= rxd; 259 | 16'd11: ip_header[71:64] <= rxd; 260 | 16'd12: ip_header[63:56] <= rxd; 261 | 16'd13: ip_header[55:48] <= rxd; 262 | 16'd14: ip_header[47:40] <= rxd; 263 | 16'd15: ip_header[39:32] <= rxd; 264 | 16'd16: ip_header[31:24] <= rxd; 265 | 16'd17: ip_header[23:16] <= rxd; 266 | 16'd18: ip_header[15:8] <= rxd; 267 | 16'd19: ip_header[7:0] <= rxd; 268 | 16'd20: udp_header[63:56] <= rxd; 269 | 16'd21: udp_header[55:48] <= rxd; 270 | 16'd22: udp_header[47:40] <= rxd; 271 | 16'd23: udp_header[39:32] <= rxd; 272 | 16'd24: udp_header[31:24] <= rxd; 273 | 16'd25: udp_header[23:16] <= rxd; 274 | 16'd26: udp_header[15:8] <= rxd; 275 | 16'd27: udp_header[7:0] <= rxd; 276 | default: ; 277 | endcase 278 | end 279 | default: ; 280 | endcase 281 | end 282 | 283 | //rdata_len, update, data_o 284 | always @ (posedge clk) 285 | begin 286 | if (is_hrd_state) 287 | begin 288 | rdata_len <= udp_header[31:16]; 289 | end 290 | if (is_dat_state) 291 | begin 292 | if (e_rxdv) 293 | begin 294 | rdata_len <= rdata_len - 16'd1; 295 | update <= 1'b1; 296 | data_o <= rxd; 297 | end 298 | else 299 | update <= 1'b0; 300 | end 301 | else 302 | update <= 1'b0; 303 | end 304 | endmodule -------------------------------------------------------------------------------- /udp_send.v: -------------------------------------------------------------------------------- 1 | /** 2 | * @Function: Ethernet Send UDP 3 | * @Date : 2019/07/23 4 | * @Vision : v1.2 5 | * @Note : 6 | * @Author : WoodFan 7 | * @param clk : fpga main clock 8 | * @param rst_n : active low reset signal 9 | * @param data_i : data need to be transformed 10 | * @param tx_data_len: amount of data need to be transformed 11 | * @param crc : crc code 12 | * @param crcen : crc enable signal 13 | * @param crcrst : crc reset signal 14 | * @param start : active high transform 15 | * @param busy : indicate the module has worked 16 | * @param tx_dv : High level means data will be sent 17 | * @param dst_mac : mac address of destination 18 | * @param dst_addr: ip address of destination 19 | * @param dst_port: port of destination 20 | * @param DF : ip packet parameter 21 | * @param MF : ip packet parameter 22 | * @param tx_en : active high when transform 23 | * @param txer : transform error 24 | * @param txd : transform data busy 25 | */ 26 | module udp_send 27 | # 28 | ( 29 | parameter IP_HEADER_LEN = 4'd5, 30 | parameter TTL = 8'd128, 31 | /* 192.168.0.3*/ 32 | parameter SRC_ADDR = 32'hc0a80002, 33 | parameter SRC_PORT = 16'd8000, 34 | parameter SRC_MAC = 48'h000a3501fec0 35 | ) 36 | ( 37 | /* system signal*/ 38 | input clk , 39 | input rst_n , 40 | /* user control*/ 41 | input [7:0] data_i , 42 | input [15:0] tx_data_len, 43 | input [31:0] crc , 44 | output reg crcen , 45 | output reg crcrst , 46 | 47 | input start , 48 | output reg busy , 49 | output reg tx_dv , 50 | input [47:0] dst_mac , 51 | input [31:0] dst_addr, 52 | input [15:0] dst_port, 53 | 54 | input DF , 55 | input MF , 56 | /* PHY interface*/ 57 | output reg tx_en , 58 | output reg txer , 59 | output reg [7:0] txd 60 | ); 61 | 62 | localparam PRESEMBLE = 8'h55 ; 63 | localparam PRESTART = 8'hd5 ; 64 | localparam IP_TYPE = 16'h0800; 65 | 66 | //counter 67 | localparam SUM_CNT = 5, 68 | PRE_CNT = 8, 69 | MAC_CNT = 14, 70 | HRD_CNT = 28, 71 | CRC_CNT = 4, 72 | CODE_CNT = 12; 73 | 74 | //FSM state 75 | localparam IDLE = 4'b0000, 76 | MAKE_IP = 4'b0001, 77 | MAKE_SUM = 4'b0011, 78 | SEND_PRE = 4'b0010, 79 | SEND_MAC = 4'b0110, 80 | SEND_HEADER = 4'b0111, 81 | SEND_DATA= 4'b0101, 82 | SEND_CRC = 4'b0100, 83 | IDLE_CODE = 4'b1100, 84 | T_AGAIN = 4'b1000 85 | ; 86 | 87 | reg [159:0] ip_header ; 88 | reg [63:0] udp_header ; 89 | reg [3:0] state /*synthesis preserve*/; 90 | reg [3:0] nxt_state /*synthesis preserve*/; 91 | reg [15:0] cnt ; 92 | reg [15:0] tdata_len ; 93 | reg [31:0] checksum_r ; 94 | reg [31:0] checksum_r1 ; 95 | reg [31:0] checksum_r2 ; 96 | reg [31:0] checksum_r3 ; 97 | reg [31:0] checksum_r4 ; 98 | reg [31:0] checksum_r5 ; 99 | reg [111:0] mac ; 100 | reg [15:0] ip_cnt ; 101 | reg [12:0] fragment_cnt ; 102 | 103 | wire [15:0] total_len; 104 | wire flag_pre_over ; 105 | wire flag_mac_over ; 106 | wire flag_hrd_over ; 107 | wire flag_dat_over ; 108 | wire flag_crc_over ; 109 | wire flag_agn_over ; 110 | wire flag_ide_over ; 111 | 112 | assign total_len = (IP_HEADER_LEN << 2) + tdata_len; 113 | //PRESEMBLE has been over 114 | assign flag_pre_over = (cnt >= PRE_CNT - 16'd1) ? 1'b1 : 1'b0; 115 | //HEADER has been over 116 | assign flag_mac_over = (cnt >= MAC_CNT - 16'd1) ? 1'b1 : 1'b0; 117 | assign flag_hrd_over = (cnt >= HRD_CNT - 16'd1) ? 1'b1 : 1'b0; 118 | assign flag_dat_over = (tdata_len <= 16'd9) ? 1'b1 : 1'b0 ; 119 | assign flag_crc_over = (cnt >= CRC_CNT - 16'd1) ? 1'b1 : 1'b0; 120 | assign flag_agn_over = (flag_ide_over && start) ? 1'b1 : 1'b0; 121 | assign flag_ide_over = (cnt >= CODE_CNT) ? 1'b1 : 1'b0 ; 122 | 123 | always @ (posedge clk or negedge rst_n) 124 | begin 125 | if (!rst_n) 126 | state <= 'd0; 127 | else 128 | state <= nxt_state; 129 | end 130 | 131 | always @ (*) 132 | begin 133 | nxt_state = state; 134 | case (state) 135 | IDLE: 136 | if (start) 137 | nxt_state = SEND_PRE; 138 | 139 | SEND_PRE: 140 | if (flag_pre_over) 141 | nxt_state = SEND_MAC; 142 | 143 | SEND_MAC: 144 | if (flag_mac_over) 145 | nxt_state = SEND_HEADER; 146 | 147 | SEND_HEADER: 148 | if (flag_hrd_over) 149 | nxt_state = SEND_DATA; 150 | 151 | SEND_DATA: 152 | if (flag_dat_over) 153 | nxt_state = SEND_CRC; 154 | 155 | SEND_CRC: 156 | if (flag_crc_over) 157 | nxt_state = IDLE_CODE; 158 | 159 | IDLE_CODE: 160 | if (flag_agn_over) 161 | nxt_state = T_AGAIN ; 162 | else if (flag_ide_over) 163 | nxt_state = IDLE ; 164 | 165 | T_AGAIN: nxt_state = MAKE_IP; 166 | 167 | default: nxt_state = IDLE; 168 | endcase 169 | end 170 | 171 | //counter 172 | //cnt 173 | //ip_cnt 174 | //fragment_cnt 175 | //tdata_len 176 | always @ (posedge clk) 177 | begin 178 | case (state) 179 | IDLE: 180 | begin 181 | cnt <= 16'd0; 182 | ip_cnt<=16'd0; 183 | fragment_cnt<=13'd0; 184 | tdata_len <= tx_data_len + 16'd8; 185 | end 186 | 187 | SEND_PRE: 188 | begin 189 | if (nxt_state == state) 190 | cnt <= cnt + 16'd1; 191 | else 192 | cnt <= 16'd0; 193 | if (cnt == 0) 194 | begin 195 | ip_cnt<= ip_cnt + 16'd1; 196 | if ({DF, MF} == 2'b01) 197 | fragment_cnt <= fragment_cnt + 13'd1; 198 | else 199 | fragment_cnt <= 13'd0; 200 | end 201 | end 202 | 203 | SEND_MAC, SEND_HEADER, SEND_CRC, IDLE_CODE: 204 | begin 205 | if (nxt_state == state) 206 | cnt <= cnt + 16'd1; 207 | else 208 | cnt <= 16'd0; 209 | end 210 | 211 | SEND_DATA: tdata_len <= tdata_len - 16'd1; 212 | 213 | T_AGAIN: 214 | begin 215 | cnt <= 16'd0; 216 | tdata_len <= tx_data_len + 16'd8; 217 | end 218 | default: ; 219 | endcase 220 | end 221 | 222 | //crc 223 | always @ (posedge clk) 224 | begin 225 | case (state) 226 | IDLE: 227 | begin 228 | crcen <= 1'b0; 229 | crcrst <= 1'b1; 230 | end 231 | 232 | SEND_MAC: 233 | begin 234 | crcen <= 1'b1; 235 | crcrst <= 1'b0; 236 | end 237 | 238 | SEND_DATA: 239 | begin 240 | if (state != nxt_state) 241 | begin 242 | crcen <= 1'b0; 243 | end 244 | end 245 | 246 | IDLE_CODE: crcrst<=1'b1; 247 | 248 | default: ; 249 | endcase 250 | end 251 | 252 | //txd 253 | always @ (posedge clk) 254 | begin 255 | case (state) 256 | IDLE: 257 | begin 258 | tx_en <= 1'b0 ; 259 | txer <= 1'b0 ; 260 | txd <= 8'd0 ; 261 | end 262 | 263 | SEND_PRE: 264 | begin 265 | if (flag_pre_over) 266 | txd <= PRESTART; 267 | else 268 | txd <= PRESEMBLE; 269 | tx_en <= 1'b1; 270 | end 271 | 272 | SEND_MAC: 273 | begin 274 | case (cnt) 275 | 16'd0: txd <= mac[111:104]; 276 | 16'd1: txd <= mac[103:96] ; 277 | 16'd2: txd <= mac[95:88] ; 278 | 16'd3: txd <= mac[87:80] ; 279 | 16'd4: txd <= mac[79:72] ; 280 | 16'd5: txd <= mac[71:64] ; 281 | 16'd6: txd <= mac[63:56] ; 282 | 16'd7: txd <= mac[55:48] ; 283 | 16'd8: txd <= mac[47:40] ; 284 | 16'd9: txd <= mac[39:32] ; 285 | 16'd10: txd <= mac[31:24] ; 286 | 16'd11: txd <= mac[23:16] ; 287 | 16'd12: txd <= mac[15:8] ; 288 | 16'd13: txd <= mac[7:0] ; 289 | default:; 290 | endcase 291 | end 292 | 293 | SEND_HEADER: 294 | begin 295 | case (cnt) 296 | 16'd0: txd <= ip_header[159:152]; 297 | 16'd1: txd <= ip_header[151:144]; 298 | 16'd2: txd <= ip_header[143:136]; 299 | 16'd3: txd <= ip_header[135:128]; 300 | 16'd4: txd <= ip_header[127:120]; 301 | 16'd5: txd <= ip_header[119:112]; 302 | 16'd6: txd <= ip_header[111:104]; 303 | 16'd7: txd <= ip_header[103:96]; 304 | 16'd8: txd <= ip_header[95:88]; 305 | 16'd9: txd <= ip_header[87:80]; 306 | 16'd10: txd <= ip_header[79:72]; 307 | 16'd11: txd <= ip_header[71:64]; 308 | 16'd12: txd <= ip_header[63:56]; 309 | 16'd13: txd <= ip_header[55:48]; 310 | 16'd14: txd <= ip_header[47:40]; 311 | 16'd15: txd <= ip_header[39:32]; 312 | 16'd16: txd <= ip_header[31:24]; 313 | 16'd17: txd <= ip_header[23:16]; 314 | 16'd18: txd <= ip_header[15:8]; 315 | 16'd19: txd <= ip_header[7:0]; 316 | 16'd20: txd <= udp_header[63:56]; 317 | 16'd21: txd <= udp_header[55:48]; 318 | 16'd22: txd <= udp_header[47:40]; 319 | 16'd23: txd <= udp_header[39:32]; 320 | 16'd24: txd <= udp_header[31:24]; 321 | 16'd25: txd <= udp_header[23:16]; 322 | 16'd26: txd <= udp_header[15:8]; 323 | 16'd27: txd <= udp_header[7:0]; 324 | default: ; 325 | endcase 326 | end 327 | 328 | SEND_DATA: txd <= data_i; 329 | 330 | SEND_CRC: 331 | begin 332 | case (cnt) 333 | 16'd0: txd <= ~{crc[24], crc[25], crc[26], crc[27], crc[28], crc[29], crc[30], crc[31]}; 334 | 16'd1: txd <= ~{crc[16], crc[17], crc[18], crc[19], crc[20], crc[21], crc[22], crc[23]}; 335 | 16'd2: txd <= ~{crc[8], crc[9], crc[10], crc[11], crc[12], crc[13], crc[14], crc[15]}; 336 | 16'd3: txd <= ~{crc[0], crc[1], crc[1], crc[3], crc[4], crc[5], crc[6], crc[7]}; 337 | default: ; 338 | endcase 339 | end 340 | 341 | IDLE_CODE: 342 | begin 343 | tx_en<= 1'b0; 344 | txd <= 8'd0; 345 | end 346 | default:; 347 | endcase 348 | end 349 | 350 | //interface signal 351 | always @ (posedge clk) 352 | begin 353 | case (state) 354 | IDLE: 355 | busy <= 1'b0; 356 | 357 | MAKE_IP: 358 | busy <= 1'b1; 359 | 360 | T_AGAIN: 361 | busy <= 1'b0; 362 | default: ; 363 | endcase 364 | end 365 | 366 | //告诉上级模块准备发数据 367 | //indicate udp already for transforming data 368 | always @ (posedge clk) 369 | begin 370 | if ((state == SEND_HEADER && (state != nxt_state)) || state == SEND_DATA) 371 | tx_dv <= 1'b1; 372 | else 373 | tx_dv <= 1'b0; 374 | end 375 | 376 | //ip_header 377 | //udp_header 378 | //mac 379 | always @ (posedge clk) 380 | begin 381 | if (state == SEND_PRE) 382 | begin 383 | case (cnt) 384 | 4'd0: 385 | begin 386 | /*ipv4 5 total_len*/ 387 | ip_header[159:128] <= {4'h4, IP_HEADER_LEN,8'b00,total_len }; 388 | /* counter */ 389 | ip_header[127:112]<= ip_cnt; 390 | /* fragment offset*/ 391 | ip_header[111:96]<= {1'b0, DF, MF, fragment_cnt}; 392 | /* TTL protype checksum*/ 393 | ip_header[95:64]<= {TTL, 8'h11, 16'd0}; 394 | ip_header[63:32]<= SRC_ADDR; 395 | ip_header[31:0]<=dst_addr; 396 | 397 | udp_header[63:32] <= {SRC_PORT, dst_port}; 398 | udp_header[31:0]<= {tdata_len, 16'h0000}; 399 | 400 | mac <= {dst_mac, SRC_MAC, IP_TYPE}; 401 | end 402 | 403 | 4'd1: 404 | begin 405 | checksum_r1 <= ip_header[15:0] + ip_header[31:16]; 406 | checksum_r2 <= ip_header[47:32] + ip_header[63:48]; 407 | checksum_r3 <= ip_header[79:64] + ip_header[95:80]; 408 | checksum_r4 <= ip_header[111:96] + ip_header[127:112]; 409 | checksum_r5 <= ip_header[143:128] + ip_header[159:144]; 410 | end 411 | 412 | 4'd2: 413 | begin 414 | checksum_r1 <= checksum_r1 + checksum_r2 + checksum_r3; 415 | checksum_r4 <= checksum_r4 + checksum_r5; 416 | end 417 | 418 | 4'd3: checksum_r <= checksum_r1 + checksum_r4; 419 | 420 | 4'd4: checksum_r[15:0] <= checksum_r[31:16] + checksum_r[15:0]; 421 | 422 | 4'd5: ip_header[79:64] <= ~checksum_r[15:0]; 423 | default: ; 424 | endcase 425 | end 426 | else if (state == IDLE) 427 | begin 428 | ip_header <= 160'd0; 429 | udp_header <= 64'd0; 430 | mac <= 96'd0; 431 | end 432 | end 433 | 434 | endmodule --------------------------------------------------------------------------------